diff --git a/.gitignore b/.gitignore index 4b6eff3..b19cdc0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ result/ /lag-llama dataset/_test.py .venv -configs \ No newline at end of file +configs +chronospack \ No newline at end of file diff --git a/dataset/data_loader.py b/dataset/data_loader.py index 95c0db2..cf2eb0c 100644 --- a/dataset/data_loader.py +++ b/dataset/data_loader.py @@ -19,12 +19,8 @@ def __init__( df: pd.DataFrame, prediction_length: int = 24, context_length: int = 72, - # num_houses: int, - # num_pairs: int = 60, total_pairs: int = 1800, random_state: int = 0000, - # window_length: int, - # window_split_ratio: float, ): pair_maker = dp.PairMaker( window_length=prediction_length+context_length, diff --git a/dataset/data_process.py b/dataset/data_process.py index 82da46e..55bfe0c 100644 --- a/dataset/data_process.py +++ b/dataset/data_process.py @@ -329,7 +329,7 @@ def make_pairs(self, load = LoadDataset( resolution='60m', country='nl', - split_ratio=0.6 + split_ratio=0.3 ) train, test = load.load_dataset_agg(num_agg=2, num_houses=3) @@ -343,10 +343,10 @@ def make_pairs(self, random_state=42 ) - # # Select one group of data - # train = train[train['id'] == train['id'].unique()[0]] - # X, Y = pair_maker.make_pairs(train, type_of_split='overlap') - # print(X.shape, Y.shape) + # Select one group of data + train = train[train['id'] == train['id'].unique()[0]] + X, Y = pair_maker.make_pairs(train, type_of_split='overlap') + print(X.shape, Y.shape) # import matplotlib.pyplot as plt # _num = 20 diff --git a/exp/chronos_exp/chronos_predictor.py b/exp/chronos_exp/chronos_predictor.py index b6850f6..ac4098f 100644 --- a/exp/chronos_exp/chronos_predictor.py +++ b/exp/chronos_exp/chronos_predictor.py @@ -6,20 +6,20 @@ from typing import Union -from chronos import ChronosPipeline +from chronospack.src.chronos import ChronosPipeline # git clone the repo and add the path to the local repo import matplotlib.pyplot as plt import numpy as np import torch from tqdm import tqdm -from chronos import ChronosPipeline import dataset.data_loader as dl import exp.eva_metrics as evm import utility.configuration as cf +import exp.plot_tool as pt def chronos_prediction( device_map: Union[str, torch.device] = "cpu", - model_type: str = "amazon/chronos-t5-large", + model_type: str = "amazon/chronos-t5-tiny", torch_dtype: torch.dtype = torch.float32): # Define the pipeline @@ -68,7 +68,7 @@ def chronos_prediction( prediction_length=num_steps_day, ) # pair_iterable.total_pairs = 10 # NOTE only for debug - batch_size = 128 + batch_size = 48 pair_it = dl.collate_numpy(pair_iterable, batch_size) data_config = cf.DataConfig( @@ -78,7 +78,7 @@ def chronos_prediction( ) foo = next(iter(pair_iterable)) model_config = cf.ModelConfig( - model_name="chronos-t5-large", + model_name="chronos-t5-small", lookback_window=foo[0].shape[-1], prediction_length=foo[1].shape[-1], ) @@ -115,61 +115,65 @@ def chronos_prediction( print('target, forecast shape', _target.shape, forecast.shape) - eval_metrics = evm.EvaluationMetrics( - quantile_loss={ - '0.1': _q_10, - '0.5': _q_50, - '0.9': _q_90, - }, - mae=_mae, - rmse=_rmse, - ) - - print(f"reso: {reso}, country: {country}, type: {_type}") - print(f"q_10_loss: {_q_10}") - print(f"q_50_loss: {_q_50}") - print(f"q_90_loss: {_q_90}") - print(f"mae_loss: {_mae}") - print(f"rmse_loss: {_rmse}") - - exp_config = cf.ExperimentConfig( - exp_id=exp_id, - data=data_config, - model=model_config, - result=eval_metrics, - ) - exp_config.append_csv(f'/home/wxia/tsfm/TSFM-RLP-Forecast/exp/chronos_exp/result/{exp_id}.csv') + # eval_metrics = evm.EvaluationMetrics( + # quantile_loss={ + # '0.1': _q_10, + # '0.5': _q_50, + # '0.9': _q_90, + # }, + # mae=_mae, + # rmse=_rmse, + # ) + + # print(f"reso: {reso}, country: {country}, type: {_type}") + # print(f"q_10_loss: {_q_10}") + # print(f"q_50_loss: {_q_50}") + # print(f"q_90_loss: {_q_90}") + # print(f"mae_loss: {_mae}") + # print(f"rmse_loss: {_rmse}") + + # exp_config = cf.ExperimentConfig( + # exp_id=exp_id, + # data=data_config, + # model=model_config, + # result=eval_metrics, + # ) + # exp_config.append_csv(f'/home/wxia/tsfm/TSFM-RLP-Forecast/exp/chronos_exp/result/{exp_id}.csv') # ----------------- Experiment----------------- - # ----------------- Plot the Results----------- - plt.plot(_input[0, :], label='Input', color='b') + # # # ----------------- Plot the Results----------- + # plt.plot(_input[0, :], label='Input', color='b') - # Create the range for the target and predicted values - target_range = range(len(_input[0, :]), len(_input[0, :]) + len(_target[0, :])) + # # Create the range for the target and predicted values + # target_range = range(len(_input[0, :]), len(_input[0, :]) + len(_target[0, :])) - # Plot the target sequence - plt.plot(target_range, _target[0, :], c='r', label='Target') + # # Plot the target sequence + # plt.plot(target_range, _target[0, :], c='r', label='Target') - # Plot the median prediction - plt.plot(target_range, median[0, :], c='g', label='Median') + # # Plot the median prediction + # plt.plot(target_range, median[0, :], c='g', label='Median') - # Fill the area between low and high predictions - plt.fill_between(target_range, low[0, :], high[0, :], color='gray', alpha=0.3, label='Uncertainty') + # # Fill the area between low and high predictions + # plt.fill_between(target_range, low[0, :], high[0, :], color='gray', alpha=0.3, label='Uncertainty') - # Set plot labels and title - plt.xlabel('Time') - plt.ylabel('Value') - plt.title(f'Chronos Predictions for {country.capitalize()} ({_type.capitalize()})') + # # Set plot labels and title + # plt.xlabel('Time') + # plt.ylabel('Value') + # plt.title(f'Chronos Predictions for {country.capitalize()} ({_type.capitalize()})') - # Add a legend - # plt.legend() + # # Add a legend + # # plt.legend() + + # # Save the plot + # _path = 'exp/chronos_exp/result/' + # plt.savefig(_path + f'chronos_{country}_{reso}_{_type}.png') + # plt.close() + + # ----------------- Plot the Results----------- + # _path = 'exp/chronos_exp/result/' + pt.plot_chronos_predictions(_input, _target, median, low, high, country, reso, _type, _path = 'exp/chronos_exp/result/') - # Save the plot - _path = 'exp/chronos_exp/result/' - plt.savefig(_path + f'chronos_{country}_{reso}_{_type}.png') - plt.close() - diff --git a/exp/eva_metrics.py b/exp/eva_metrics.py index c00113a..9374b37 100644 --- a/exp/eva_metrics.py +++ b/exp/eva_metrics.py @@ -40,6 +40,8 @@ def mae(real_values, pre_values): def rmse(real_values, pre_values): """ give the real values and the predicted values to calculate the root mean squared error + + y shape: (batch_dim_0, batch_dim_1, ..., batch_dim_N, seq_len) or (batch_size, seq_len) or (seq_len,) """ - rmse = np.sqrt(np.power(real_values - pre_values, 2).mean()) - return rmse.mean() \ No newline at end of file + rmse = np.sqrt(np.power(real_values - pre_values, 2).mean(axis=-1)) # (batch_size,) + return rmse.mean() # scalar \ No newline at end of file diff --git a/exp/gp/__init__.py b/exp/gp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/exp/gp/gp_predictor.py b/exp/gp/gp_predictor.py new file mode 100644 index 0000000..8cf8d5f --- /dev/null +++ b/exp/gp/gp_predictor.py @@ -0,0 +1,168 @@ +import os +import sys +parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +# dataset_path = os.path.join(parent_dir, 'dataset') +sys.path.append(parent_dir) + +import matplotlib.pyplot as plt +import numpy as np +from sklearn.gaussian_process import GaussianProcessRegressor +from sklearn.gaussian_process.kernels import RBF, ConstantKernel as C +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import StandardScaler +import numpy as np +from tqdm import tqdm + +import dataset.data_loader as dl +import exp.eva_metrics as evm +import utility.configuration as cf +import exp.plot_tool as pt + +import numpy as np +from sklearn.gaussian_process import GaussianProcessRegressor +from sklearn.gaussian_process.kernels import RBF, ConstantKernel as C + +def train_gp_models(X, y): + models = [] + for i in range(y.shape[1]): + # Define the kernel for the Gaussian Process + kernel = C(1.0, (1e-3, 1e3)) * RBF(length_scale=1.0, length_scale_bounds=(1e-2, 1e2)) + # Initialize and train the Gaussian Process model + gp = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=10) + gp.fit(X, y[:, i]) + models.append(gp) + return models + +def gp_predict_quantiles(models, X_test): + means = np.zeros((X_test.shape[0], len(models))) + stds = np.zeros((X_test.shape[0], len(models))) + + # Obtain mean and standard deviation predictions for each output dimension + for i, model in enumerate(models): + mean, std = model.predict(X_test, return_std=True) + means[:, i] = mean + stds[:, i] = std + + # Calculate 10% and 90% quantiles using the mean and standard deviation + # quantiles = { + # '10%': means - 1.28 * stds, # 10% quantile = mean - 1.28 * std (for 10% quantile) + # 'mean': means, + # '90%': means + 1.28 * stds # 90% quantile = mean + 1.28 * std (for 90% quantile) + # } + + return means - 1.28 * stds, means, means + 1.28 * stds + + +if __name__ == "__main__": + # ----------------- Experiment Configuration ----------------- + reso_country = [ + ('60m', 'nl'), + ('60m', 'ge'), + ('30m', 'ge'), + ('15m', 'ge'), + ('30m', 'uk'), + ('60m', 'uk'), + ] + + + exp_id = cf.generate_time_id() + split_ratio = 0.6 + + for reso, country in reso_country: + if reso == '60m': + num_steps_day = 24 + elif reso == '30m': + num_steps_day = 48 + elif reso == '15m': + num_steps_day = 96 + + for _type in ['ind','agg']: # 'agg', , 'ind' + print('--------------------------------------------------') + print(f"reso: {reso}, country: {country}, type: {_type}") + print('--------------------------------------------------') + # load datastet + pair_iterable = dl.data_for_exp( + resolution = reso, + country = country, + data_type = _type, + context_length=num_steps_day*3, + prediction_length=num_steps_day, + ) + + # pair_iterable.total_pairs = 10 # NOTE only for debug + batch_size = 128*2 + pair_it = dl.collate_numpy(pair_iterable, batch_size) + + data_config = cf.DataConfig( + country=country, + resolution=reso, + aggregation_type=_type, + ) + foo = next(iter(pair_iterable)) + model_config = cf.ModelConfig( + model_name="GP", + lookback_window=foo[0].shape[-1], + prediction_length=foo[1].shape[-1], + ) + + # ----------------- Experiment Configuration ----------------- + + # ----------------- Experiment ----------------- + _q_10, _q_50, _q_90, _mae, _rmse = [], [], [], [], [] + + for x , y in tqdm(pair_it, total = len(pair_iterable)//batch_size): + x = x.reshape(x.shape[0],-1) + y = y.reshape(y.shape[0],-1) + + # fig regressor + regrs = train_gp_models(x[:int(split_ratio*x.shape[0]),:], y[:int(split_ratio*x.shape[0]),:]) + + # make predction + x = x[int(split_ratio*x.shape[0]):,:] + y = y[int(split_ratio*y.shape[0]):,:] + low, mean, high = gp_predict_quantiles(regrs, x) + ow = np.nan_to_num(low, nan=0) + mean = np.nan_to_num(mean, nan=0) + high = np.nan_to_num(high, nan=0) + + _q_10.append(evm.quantile_loss(low, y, 0.1).mean()) + _q_50.append(evm.quantile_loss(mean, y, 0.5).mean()) + _q_90.append(evm.quantile_loss(high, y, 0.9).mean()) + _mae.append(evm.mae(mean, y)) + _rmse.append(evm.rmse(mean, y)) + + _q_10, _q_50, _q_90, _mae, _rmse = np.mean(_q_10), np.mean(_q_50), np.mean(_q_90), np.mean(_mae), np.mean(_rmse) + + print('low, median, high shape', low.shape, mean.shape, high.shape) + print('input shape', x.shape) + print('target, forecast shape', y.shape, mean.shape) + + + eval_metrics = evm.EvaluationMetrics( + quantile_loss={ + '0.1': _q_10, + '0.5': _q_50, + '0.9': _q_90, + }, + mae=_mae, + rmse=_rmse, + ) + + print(f"reso: {reso}, country: {country}, type: {_type}") + print(f"q_10_loss: {_q_10}") + print(f"q_50_loss: {_q_50}") + print(f"q_90_loss: {_q_90}") + print(f"mae_loss: {_mae}") + print(f"rmse_loss: {_rmse}") + + exp_config = cf.ExperimentConfig( + exp_id=exp_id, + data=data_config, + model=model_config, + result=eval_metrics, + ) + exp_config.append_csv(f'exp/gp/result/{exp_id}.csv') + # ----------------- Experiment ----------------- + + # ----------------- Plot the Results----------- + pt.plot_gp_predictions(x, y, mean, low, high, country, reso, _type, _path = 'exp/gp/result/') diff --git a/exp/gp/test.py b/exp/gp/test.py new file mode 100644 index 0000000..f4a3d40 --- /dev/null +++ b/exp/gp/test.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +from sklearn.datasets import make_friedman2 +from sklearn.gaussian_process import GaussianProcessRegressor +from sklearn.gaussian_process.kernels import DotProduct, WhiteKernel + +# Generate multi-dimensional output data (e.g., modify the dataset as needed) +# Here, using make_friedman2 and repeating y to simulate multi-dimensional output +X, y_single = make_friedman2(n_samples=500, noise=0, random_state=0) +y = np.stack([y_single, y_single * 1.5 + 10], axis=1) # Example multi-dimensional output (shape: (500, 2)) + +# Define kernel and prepare the list for storing models +kernel = DotProduct() + WhiteKernel() +models = [] + +# Fit a separate GPR model for each output dimension +for i in range(y.shape[1]): + gpr = GaussianProcessRegressor(kernel=kernel, random_state=0).fit(X, y[:, i]) + models.append(gpr) + +# Make predictions and plot for the first dimension +X_test = X[:100, :] # Using 100 samples from X for demonstration +mean_preds = [] +std_preds = [] + +# Generate predictions for each output dimension +for model in models: + mean_pred, std_pred = model.predict(X_test, return_std=True) + mean_preds.append(mean_pred) + std_preds.append(std_pred) + +# Plot for the first dimension (y[:, 0]) +plt.figure(figsize=(12, 6)) + +# Sort data to create a smooth curve +sorted_idx = np.argsort(X_test[:, 0]) # Sorting by the first feature for visualization +X_sorted = X_test[sorted_idx] +mean_sorted = mean_preds[0][sorted_idx] +std_sorted = std_preds[0][sorted_idx] + +# Mean prediction for the first dimension +plt.plot(X_sorted[:, 0], mean_sorted, 'r-', label="Mean Prediction (Dim 1)") + +# 95% Confidence interval for the first dimension +plt.fill_between(X_sorted[:, 0], + mean_sorted - 1.96 * std_sorted, + mean_sorted + 1.96 * std_sorted, + alpha=0.2, color='gray', label="95% Confidence Interval (Dim 1)") + +# Scatter plot of actual values for comparison (first dimension) +plt.scatter(X_sorted[:, 0], y[:100, 0][sorted_idx], s=10, color='blue', label="Actual Values (Dim 1)", alpha=0.6) + +# Labels and title +plt.xlabel("Feature 0") +plt.ylabel("Target (Dim 1)") +plt.title("Gaussian Process Regression with Probabilistic Predictions (Dimension 1)") +plt.legend() +plt.show() diff --git a/exp/moment/moment_predictor.py b/exp/moment/moment_predictor.py index 4e66bdd..7e3db33 100644 --- a/exp/moment/moment_predictor.py +++ b/exp/moment/moment_predictor.py @@ -16,6 +16,7 @@ import utility.configuration as cf from momentfm import MOMENTPipeline +import exp.plot_tool as pt if __name__ == "__main__": reso_country = [ @@ -38,7 +39,7 @@ elif reso == '15m': num_steps_day = 96 - for _type in ['ind','agg']: # 'agg', , 'ind' + for _type in ['ind', 'agg']: # 'agg', , 'ind' print('--------------------------------------------------') print(f"reso: {reso}, country: {country}, type: {_type}") print('--------------------------------------------------') @@ -120,16 +121,26 @@ exp_config.append_csv(f'exp/moment/result/{exp_id}.csv') # ----------------- Plot the Results----------- - print(x.shape, _target[0, :].shape, out[0, 0, :].detach().numpy().shape) - plt.plot(range(x.shape[2]), x[0, 0, :], label='Input', color='b') - target_range = range(x.shape[2], x.shape[2] + len(_target[0, :])) - plt.plot(target_range, _target[0, :], c='r', label='Target') - plt.plot(target_range, out[0, 0, :].detach().numpy(), c='g', label='Median') - plt.xlabel('Time') - plt.ylabel('Value') - plt.title(f'Chronos Predictions for {country.capitalize()} ({_type.capitalize()})') - _path = 'exp/moment/result/' - plt.savefig(_path + f'moment_{country}_{reso}_{_type}.png') - plt.close() + # print(x.shape, _target[0, :].shape, out[0, 0, :].detach().numpy().shape) + # plt.plot(range(x.shape[2]), x[0, 0, :], label='Input', color='b') + # target_range = range(x.shape[2], x.shape[2] + len(_target[0, :])) + # plt.plot(target_range, _target[0, :], c='r', label='Target') + # plt.plot(target_range, out[0, 0, :].detach().numpy(), c='g', label='Median') + # plt.xlabel('Time') + # plt.ylabel('Value') + # plt.title(f'Chronos Predictions for {country.capitalize()} ({_type.capitalize()})') + # _path = 'exp/moment/result/' + # plt.savefig(_path + f'moment_{country}_{reso}_{_type}.png') + # plt.close() + + _path = 'exp/moment/result' + print(x.shape, y.shape) + x = x[:, 0, :] + y = _target + y_hat = out[:, 0, :].detach().numpy() + print(x.shape, y.shape, y_hat.shape) + pt.plot_predictions_point(x, y, y_hat, country, reso, _type, 'moment', num_steps_day, _path) + + \ No newline at end of file diff --git a/exp/plot_tool.py b/exp/plot_tool.py new file mode 100644 index 0000000..1db7bc7 --- /dev/null +++ b/exp/plot_tool.py @@ -0,0 +1,93 @@ +import matplotlib.pyplot as plt +import os + +def plot_predictions_point(x, y, y_hat, country, reso, _type, model_name, num_steps_day, _path): + x = x.reshape(-1, num_steps_day * 3) + target_range = range(num_steps_day * 3, num_steps_day * 4) + + plt.figure(figsize=(6, 4)) + plt.plot(range(num_steps_day * 3), x[-1, :], label='Input', color='b', linewidth=1.5) + plt.plot(target_range, y[-1, :], label='Target', color='r', linewidth=1.5) + plt.plot(target_range, y_hat[-1, :], label='Prediction (Mean)', color='g', linewidth=1.5) + + plt.xlabel('Time [Hour]', fontsize=14) + plt.ylabel('Electricity Consunption [kWh]', fontsize=14) + plt.title(f'{model_name} predictions for {country.capitalize()}-{_type.capitalize()}-{reso}', fontsize=16) + + plt.xticks(fontsize=12) + plt.yticks(fontsize=12) + plt.grid(True, linestyle='--', alpha=0.7) + + plt.legend(fontsize=12, loc='upper left') + + # Saving the plot + os.makedirs(_path, exist_ok=True) + plt.savefig(f'{_path}/{model_name}_{country}_{reso}_{_type}.png', bbox_inches='tight') + plt.close() + + +def plot_gp_predictions(x, y, mean, low, high, country, reso, _type, _path = 'exp/gp/result/'): + plt.figure(figsize=(6, 4)) + + # Plot the input sequence + plt.plot(x[-1, :], label='Input', color='b') + + # Create the range for the target and predicted values + target_range = range(len(x[-1, :]), len(x[-1, :]) + len(y[0, :])) + + # Plot the target sequence + plt.plot(target_range, y[-1, :], color='r', label='Target') + + # Plot the median prediction + plt.plot(target_range, mean[-1, :], color='g', label='Prediction (Mean)') + + # Fill the area between low and high predictions to show uncertainty + plt.fill_between(target_range, low[-1, :], high[-1, :], color='gray', alpha=0.3, label='Uncertainty') + + # Set plot labels and title + plt.xlabel('Time [Hour]', fontsize=14) + plt.ylabel('Electricity Consunption [kWh]', fontsize=14) + plt.title(f'GP Predictions for {country.capitalize()}-{_type.capitalize()}-{reso}', fontsize=16) + + # Add grid and legend + plt.grid(True, linestyle='--', alpha=0.7) + plt.legend(fontsize=12, loc='upper left') + + # Save the plot + os.makedirs(_path, exist_ok=True) + plt.savefig(os.path.join(_path, f'gp_{country}_{reso}_{_type}.png'), bbox_inches='tight') + plt.close() + + + +def plot_chronos_predictions(_input, _target, median, low, high, country, reso, _type, _path = 'exp/chronos_exp/result/'): + plt.figure(figsize=(6, 4)) + + # Plot the input sequence + plt.plot(_input[0, :], label='Input', color='b') + + # Create the range for the target and predicted values + target_range = range(len(_input[0, :]), len(_input[0, :]) + len(_target[0, :])) + + # Plot the target sequence + plt.plot(target_range, _target[0, :], color='r', label='Target') + + # Plot the median prediction + plt.plot(target_range, median[0, :], color='g', label='Prediction (Mean)') + + # Fill the area between low and high predictions to show uncertainty + plt.fill_between(target_range, low[0, :], high[0, :], color='gray', alpha=0.3, label='Uncertainty') + + # Set plot labels and title + plt.xlabel('Time [Hour]', fontsize=14) + plt.ylabel('Electricity Consunption [kWh]', fontsize=14) + plt.title(f'Chronos Predictions for {country.capitalize()}-{_type.capitalize()}-{reso}', fontsize=16) + + # Add grid and legend + plt.grid(True, linestyle='--', alpha=0.7) + plt.legend(fontsize=12, loc='upper left') + + # Save the plot + os.makedirs(_path, exist_ok=True) + plt.savefig(os.path.join(_path, f'chronos_{country}_{reso}_{_type}.png'), bbox_inches='tight') + plt.close() diff --git a/exp/svr/__init__.py b/exp/svr/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/exp/svr/figure_merge.py b/exp/svr/figure_merge.py new file mode 100644 index 0000000..0fad733 --- /dev/null +++ b/exp/svr/figure_merge.py @@ -0,0 +1,44 @@ +import os +from PIL import Image +import matplotlib.pyplot as plt + +# Path where images are stored +img_dir = 'exp/svr/result' + +# List of image filenames (adjust if necessary) +img_files = [ + "svr_ge_15m_agg.png", "svr_ge_15m_ind.png", + "svr_ge_30m_agg.png", "svr_ge_30m_ind.png", + "svr_ge_60m_agg.png", "svr_ge_60m_ind.png", + "svr_nl_60m_agg.png", "svr_nl_60m_ind.png", + "svr_uk_30m_agg.png", "svr_uk_30m_ind.png", + "svr_uk_60m_agg.png", "svr_uk_60m_ind.png" +] + +# Load images +images = [Image.open(os.path.join(img_dir, img)) for img in img_files] + +# Define grid layout (e.g., 4 rows x 3 columns) +rows, cols = 4, 3 +img_width, img_height = images[0].size +grid_width = cols * img_width +grid_height = rows * img_height + +# Create a new blank image with a white background +grid_image = Image.new('RGB', (grid_width, grid_height), 'white') + +# Paste images into grid +for index, img in enumerate(images): + x = (index % cols) * img_width+1 + y = (index // cols) * img_height+1 + grid_image.paste(img, (x, y)) + +# Save the grid image +output_path = 'exp/svr/result/combined_grid.png' +grid_image.save(output_path) + +# Display the combined image +plt.figure(figsize=(20, 8)) +plt.imshow(grid_image) +plt.axis('off') +plt.show() diff --git a/exp/svr/svr_predictor.py b/exp/svr/svr_predictor.py new file mode 100644 index 0000000..70227b0 --- /dev/null +++ b/exp/svr/svr_predictor.py @@ -0,0 +1,135 @@ +import os +import sys +parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +# dataset_path = os.path.join(parent_dir, 'dataset') +sys.path.append(parent_dir) + +# import matplotlib.pyplot as plt +import numpy as np +from sklearn.svm import SVR +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import StandardScaler +import numpy as np +from tqdm import tqdm + +import dataset.data_loader as dl +import exp.eva_metrics as evm +import utility.configuration as cf +import exp.plot_tool as pt + +def svr_fit(input, target): + regrs = [] + for _col in range(target.shape[1]): + regr = make_pipeline(StandardScaler(), SVR(C=1.0, epsilon=0.2)) + regr.fit(input, target[:, _col]) + regrs.append(regr) + return regrs + +def svr_pred(input, regrs): + # Prepare the output array with zeros, matching the shape (n, d) + predictions = np.zeros((input.shape[0], len(regrs))) + + # Use each trained model to predict its corresponding column + for i, regr in enumerate(regrs): + predictions[:, i] = regr.predict(input) + + return predictions + +if __name__ == "__main__": + # ----------------- Experiment Configuration ----------------- + reso_country = [ + ('60m', 'nl'), + ('60m', 'ge'), + ('30m', 'ge'), + ('15m', 'ge'), + ('30m', 'uk'), + ('60m', 'uk'), + ] + + + exp_id = cf.generate_time_id() + split_ratio = 0.6 + + for reso, country in reso_country: + if reso == '60m': + num_steps_day = 24 + elif reso == '30m': + num_steps_day = 48 + elif reso == '15m': + num_steps_day = 96 + + for _type in ['ind','agg']: # 'agg', , 'ind' + print('--------------------------------------------------') + print(f"reso: {reso}, country: {country}, type: {_type}") + print('--------------------------------------------------') + # load datastet + pair_iterable = dl.data_for_exp( + resolution = reso, + country = country, + data_type = _type, + context_length=num_steps_day*3, + prediction_length=num_steps_day, + ) + + # pair_iterable.total_pairs = 10 # NOTE only for debug + batch_size = 128*2 + pair_it = dl.collate_numpy(pair_iterable, batch_size) + + data_config = cf.DataConfig( + country=country, + resolution=reso, + aggregation_type=_type, + ) + foo = next(iter(pair_iterable)) + model_config = cf.ModelConfig( + model_name="SVR", + lookback_window=foo[0].shape[-1], + prediction_length=foo[1].shape[-1], + ) + + # ----------------- Experiment Configuration ----------------- + + # ----------------- Experiment ----------------- + _mae, _rmse = [], [] + + for x , y in tqdm(pair_it, total = len(pair_iterable)//batch_size): + x = x.reshape(x.shape[0],-1) + y = y.reshape(y.shape[0],-1) + + # fig regressor + regrs = svr_fit(x[:int(split_ratio*x.shape[0]),:], y[:int(split_ratio*x.shape[0]),:]) + + # make predction + x = x[int(split_ratio*x.shape[0]):,:] + y = y[int(split_ratio*y.shape[0]):,:] + y_hat = svr_pred(x, regrs) + print(x.shape, y.shape, y_hat.shape) + + _mae.append(evm.mae(y_hat, y)) + _rmse.append(evm.rmse(y_hat, y)) + + _mae, _rmse = np.mean(_mae), np.mean(_rmse) + # Output the experiment result + eval_metrics = evm.EvaluationMetrics( + quantile_loss={ + '0.1': -1, + '0.5': -1, + '0.9': -1, + }, + mae=_mae, + rmse=_rmse, + ) + + exp_config = cf.ExperimentConfig( + exp_id=exp_id, + data=data_config, + model=model_config, + result=eval_metrics, + ) + exp_config.append_csv(f'exp/svr/result/{exp_id}.csv') + # ----------------- Experiment ----------------- + + # ----------------- Plot the Results----------- + _path = 'exp/svr/result' + pt.plot_predictions_point(x, y, y_hat, country, reso, _type, 'SVR', num_steps_day, _path) + \ No newline at end of file diff --git a/exp/timegpt/timegpt_predictor.py b/exp/timegpt/timegpt_predictor.py index 76d2f06..c26d3e6 100644 --- a/exp/timegpt/timegpt_predictor.py +++ b/exp/timegpt/timegpt_predictor.py @@ -14,6 +14,7 @@ import dataset.data_loader as dl import exp.eva_metrics as evm import utility.configuration as cf +import exp.plot_tool as pt def numpy_to_dataframe(x, freq='15T'): @@ -53,7 +54,7 @@ def numpy_to_dataframe(x, freq='15T'): elif reso == '15m': num_steps_day = 96 - for _type in ['ind', 'agg']: # 'agg', , 'ind' + for _type in ['ind','agg']: # 'agg', , 'ind' print('--------------------------------------------------') print(f"reso: {reso}, country: {country}, type: {_type}") print('--------------------------------------------------') @@ -135,16 +136,6 @@ def numpy_to_dataframe(x, freq='15T'): # ----------------- Experiment ----------------- # ----------------- Plot the Results----------- - x = x.reshape(-1, num_steps_day*3) - plt.plot(range(num_steps_day*3), x[0, :], label='Input', color='b') - target_range = range(num_steps_day*3, num_steps_day*4) - plt.plot(target_range, y[0, :], c='r', label='Target') - plt.plot(target_range, y_hat[0, :], c='g', label='Median') - plt.xlabel('Time') - plt.ylabel('Value') - plt.title(f'Chronos Predictions for {country.capitalize()} ({_type.capitalize()})') _path = 'exp/timegpt/result' - plt.legend() - plt.savefig(_path + f'/timegpt_{country}_{reso}_{_type}.png') - - plt.close() + pt.plot_predictions_point(x, y, y_hat, country, reso, _type, 'timegpt', num_steps_day, _path) + diff --git a/exp/timesfm_exp/timesfm_predictor.py b/exp/timesfm_exp/timesfm_predictor.py index ef2c8fd..827e651 100644 --- a/exp/timesfm_exp/timesfm_predictor.py +++ b/exp/timesfm_exp/timesfm_predictor.py @@ -14,6 +14,7 @@ import dataset.data_loader as dl import exp.eva_metrics as evm import utility.configuration as cf +import exp.plot_tool as pt def pad_sequence( sequence: List, @@ -122,7 +123,7 @@ def get_timesfm_predictor( if forecast is None: forecast = y_pred else: - forecast = np.concatenate([forecast, y], axis=0) + forecast = np.concatenate([forecast, y_pred], axis=0) target = np.array(_target) @@ -157,4 +158,10 @@ def get_timesfm_predictor( ) exp_config.append_csv(f'result/{exp_id}.csv') + _path = 'exp/timesfm_exp/result' + pt.plot_predictions_point( + np.array(x), + np.array(y), + y_pred, country, reso, _type, 'TimesFM', num_steps_day, _path) + print('complete.') \ No newline at end of file diff --git a/sklearn-env/bin/python b/sklearn-env/bin/python new file mode 120000 index 0000000..b8a0adb --- /dev/null +++ b/sklearn-env/bin/python @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/sklearn-env/bin/python3 b/sklearn-env/bin/python3 new file mode 120000 index 0000000..0c54919 --- /dev/null +++ b/sklearn-env/bin/python3 @@ -0,0 +1 @@ +/home/wxia/tsfm/TSFM-RLP-Forecast/.venv/bin/python3 \ No newline at end of file diff --git a/sklearn-env/bin/python3.10 b/sklearn-env/bin/python3.10 new file mode 120000 index 0000000..b8a0adb --- /dev/null +++ b/sklearn-env/bin/python3.10 @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/sklearn-env/lib64 b/sklearn-env/lib64 new file mode 120000 index 0000000..7951405 --- /dev/null +++ b/sklearn-env/lib64 @@ -0,0 +1 @@ +lib \ No newline at end of file diff --git a/sklearn-env/pyvenv.cfg b/sklearn-env/pyvenv.cfg new file mode 100644 index 0000000..f77ed01 --- /dev/null +++ b/sklearn-env/pyvenv.cfg @@ -0,0 +1,3 @@ +home = /home/wxia/tsfm/TSFM-RLP-Forecast/.venv/bin +include-system-site-packages = false +version = 3.10.12