#https://blog.csdn.net/weixin_35757704/article/details/115910672 #https://www.bilibili.com/video/BV1hE411t7RN?p=27 #https://www.zhihu.com/question/39792141 import numpy as np from typing import Union import pandas as pd from itertools import product import torch from torch import nn from torch.utils.data import DataLoader import torchvision from sklearn.model_selection import train_test_split from sklearn.utils.validation import check_X_y import joblib from catboost import CatBoostRegressor from lightgbm import LGBMRegressor from xgboost import XGBRegressor from sklearn.metrics import r2_score from CNN_architecture import CNN_architecture from sklearn.utils import shuffle def get_state_vect_cols(prefix=''): if prefix: prefix += '_' vectors = ['r', 'v'] components = ['x', 'y', 'z'] col_names = [f'{prefix}{v}_{c}' for v, c in product(vectors, components)] return col_names pd.set_option('display.max_rows', None) pd.set_option('display.max_columns', None) pd.set_option('display.width', 1000) # %% df = pd.read_parquet("traindata/physics_preds.parquet") test_set = df[df['aso_id'] == "05277"] train_set = df.groupby('aso_id').apply(lambda x: x.head(x.count()[0] - 3)) print(df.count()[0], train_set.count()[0], test_set.count()[0]) data_count = df.count()[0] # print(train_set) # %% feature_cols = [ 'elapsed_seconds' ] + get_state_vect_cols('physics_pred') + get_state_vect_cols('start') print(feature_cols) # The target values are the errors between the physical model predictions # and the ground truth observations target_cols = get_state_vect_cols('physics_err') print(target_cols) print("样本统一归一化处理") all_cols = feature_cols + target_cols df = df[all_cols] df = shuffle(df) df = (df - df.mean(axis=0)) / df.std(axis=0) # Create feature and target matrices feature_cols = ['physics_err_v_x'] + feature_cols X = df[feature_cols] y = df[target_cols] # data_keys = ['X_train', 'X_test', 'y_train', 'y_test'] # data_vals = train_test_split(X, y, test_size=0.2) # train_test_data = dict(zip(data_keys, data_vals)) # train_test_data['X_test'] = test_set[feature_cols] # train_test_data['y_test'] = test_set[target_cols] # train_test_data = { # 'X_train': train_set[feature_cols], # 'y_train': train_set[target_cols], # 'X_test': test_set[feature_cols], # 'y_test': test_set[target_cols], # } # %% import numpy as np import torch from torch import nn import matplotlib.pyplot as plt """ Github: Yonv1943 Zen4 Jia1 hao2 https://github.com/Yonv1943/DL_RL_Zoo/blob/master/RNN The source of training data https://github.com/L1aoXingyu/ code-of-learn-deep-learning-with-pytorch/blob/master/ chapter5_RNN/time-series/lstm-time-series.ipynb """ import os os.environ["CUDA_VISIBLE_DEVICES"] = "0" def run_train_lstm(X): inp_dim = 14 out_dim = 1 mid_dim = 15 mid_layers = 2 batch_size = 12 * 4 mod_dir = '.' '''load data''' data = X.values pd.set_option('display.max_rows', None) pd.set_option('display.max_columns', None) pd.set_option('display.width', 1000) # np.set_printoptions(threshold='nan') # print(data) data_x = data[:-1, :] data_y = data[+1:, 0] # print(data_y) assert data_x.shape[1] == inp_dim train_size = int(data_count * 0.80) train_x = data_x[:train_size] train_y = data_y[:train_size] train_x = train_x.reshape((train_size, inp_dim)) train_y = train_y.reshape((train_size, out_dim)) # print(train_y) # X, ys = train_test_data['X_train'], train_test_data['y_train'] # # check_X_y(X, ys, multi_output=True) # # train_x = X.values # train_y = ys['physics_err_r_x'].values # train_y = ys.reshape(ys.shape[0], 1) '''build model''' # device = torch.device("cuda" if torch.cuda.is_available() else "cpu") device = torch.device("cuda") net = RegLSTM(inp_dim, out_dim, mid_dim, mid_layers).to(device) criterion = nn.MSELoss() optimizer = torch.optim.Adam(net.parameters(), lr=1e-2) '''train''' var_x = torch.tensor(train_x, dtype=torch.float32, device=device) var_y = torch.tensor(train_y, dtype=torch.float32, device=device) batch_var_x = list() batch_var_y = list() for i in range(batch_size): j = batch_size - i batch_var_x.append(var_x[j:]) batch_var_y.append(var_y[j:]) from torch.nn.utils.rnn import pad_sequence batch_var_x = pad_sequence(batch_var_x) batch_var_y = pad_sequence(batch_var_y) with torch.no_grad(): weights = np.tanh(np.arange(len(train_y)) * (np.e / len(train_y))) weights = torch.tensor(weights, dtype=torch.float32, device=device) print("Training Start") for e in range(10): out = net(batch_var_x) # loss = criterion(out, batch_var_y) loss = (out - batch_var_y) ** 2 * weights loss = loss.mean() optimizer.zero_grad() loss.backward() optimizer.step() if e % 64 == 0: print('Epoch: {:4}, Loss: {:.5f}'.format(e, loss.item())) torch.save(net.state_dict(), '{}/net.pth'.format(mod_dir)) print("Save in:", '{}/net.pth'.format(mod_dir)) '''eval''' net.load_state_dict(torch.load('{}/net.pth'.format(mod_dir), map_location=lambda storage, loc: storage)) net = net.eval() # X1, ys1 = train_test_data['X_test'], train_test_data['y_test'] # check_X_y(X1, ys1, multi_output=True) # test_x = X1.values # test_y = ys1['physics_err_r_x'].values # test_y = ys1.reshape(ys.shape[0], 1) # test_x = test_x = data_x.copy() test_x[train_size:, 0] = 0 # print(test_x) test_x = test_x[:, np.newaxis, :] test_x = torch.tensor(test_x, dtype=torch.float32, device=device) '''simple way but no elegant''' for i in range(train_size, len(data) - 2): test_y = net(test_x[:i]) test_x[i, 0, 0] = test_y[-1] '''elegant way but slightly complicated''' # eval_size = 1 # zero_ten = torch.zeros((mid_layers, eval_size, mid_dim), dtype=torch.float32, device=device) # test_y, hc = net.output_y_hc(test_x[:train_size], (zero_ten, zero_ten)) # test_x[train_size + 1, 0, 0] = test_y[-1] # for i in range(train_size + 1, len(data) - 2): # test_y, hc = net.output_y_hc(test_x[i:i + 1], hc) # test_x[i + 1, 0, 0] = test_y[-1] pred_y = test_x[1:, 0, 0] pred_y = pred_y.cpu().data.numpy() print("`````````````````````````") print(pred_y.shape) diff_y = pred_y[train_size:] - data_y[train_size:-1] print("------") # print(pred_y[train_size:]) print("------") # print(data_y[train_size:-1]) r2 = r2_score(data_y[train_size:-1], pred_y[train_size:], multioutput= 'uniform_average') evals = [] eval_dict = {'Error': 'physics_err_v_x', 'R^2': r2} evals.append(eval_dict) print(pd.DataFrame(evals)) l1_loss = np.mean(np.abs(diff_y)) l2_loss = np.mean(diff_y ** 2) print("L1: {:.3f} L2: {:.3f}".format(l1_loss, l2_loss)) plt.plot(pred_y, 'r', label='pred') plt.plot(data_y, 'b', label='real', alpha=0.3) plt.plot([train_size, train_size], [-1, 2], color='k', label='train | pred') plt.legend(loc='best') plt.savefig('lstm_reg.png') plt.pause(4) def run_origin(): inp_dim = 2 out_dim = 1 mod_dir = '.' '''load data''' data = load_data() # axis1: number, year, month data_x = np.concatenate((data[:-2, 0:1], data[+1:-1, 0:1]), axis=1) data_y = data[2:, 0] train_size = int(len(data_x) * 0.75) train_x = data_x[:train_size] train_y = data_y[:train_size] train_x = train_x.reshape((-1, 1, inp_dim)) train_y = train_y.reshape((-1, 1, out_dim)) '''build model''' device = torch.device("cuda" if torch.cuda.is_available() else "cpu") net = RegLSTM(inp_dim, out_dim, mid_dim=4, mid_layers=2).to(device) criterion = nn.SmoothL1Loss() optimizer = torch.optim.Adam(net.parameters(), lr=1e-2) '''train''' var_x = torch.tensor(train_x, dtype=torch.float32, device=device) var_y = torch.tensor(train_y, dtype=torch.float32, device=device) print('var_x.size():', var_x.size()) print('var_y.size():', var_y.size()) for e in range(512): out = net(var_x) loss = criterion(out, var_y) optimizer.zero_grad() loss.backward() optimizer.step() if (e + 1) % 100 == 0: # 每 100 次输出结果 print('Epoch: {}, Loss: {:.5f}'.format(e + 1, loss.item())) torch.save(net.state_dict(), '{}/net.pth'.format(mod_dir)) '''eval''' # net.load_state_dict(torch.load('{}/net.pth'.format(mod_dir), map_location=lambda storage, loc: storage)) net = net.eval() # 转换成测试模式 """ inappropriate way of seq prediction: use all real data to predict the number of next month """ test_x = data_x.reshape((-1, 1, inp_dim)) var_data = torch.tensor(test_x, dtype=torch.float32, device=device) eval_y = net(var_data) # 测试集的预测结果 pred_y = eval_y.view(-1).cpu().data.numpy() plt.plot(pred_y[1:], 'r', label='pred inappr', alpha=0.3) plt.plot(data_y, 'b', label='real', alpha=0.3) plt.plot([train_size, train_size], [-1, 2], label='train | pred') """ appropriate way of seq prediction: use real+pred data to predict the number of next 3 years. """ test_x = data_x.reshape((-1, 1, inp_dim)) test_x[train_size:] = 0 # delete the data of next 3 years. test_x = torch.tensor(test_x, dtype=torch.float32, device=device) for i in range(train_size, len(data) - 2): test_y = net(test_x[:i]) test_x[i, 0, 0] = test_x[i - 1, 0, 1] test_x[i, 0, 1] = test_y[-1, 0] pred_y = test_x.cpu().data.numpy() pred_y = pred_y[:, 0, 0] plt.plot(pred_y[2:], 'g', label='pred appr') plt.legend(loc='best') plt.savefig('lstm_origin.png') plt.pause(4) class RegLSTM(nn.Module): def __init__(self, inp_dim, out_dim, mid_dim, mid_layers): super(RegLSTM, self).__init__() self.rnn = nn.LSTM(inp_dim, mid_dim, mid_layers) # rnn self.reg = nn.Sequential( nn.Linear(mid_dim, mid_dim), nn.Tanh(), nn.Linear(mid_dim, out_dim), ) # regression def forward(self, x): y = self.rnn(x)[0] # y, (h, c) = self.rnn(x) seq_len, batch_size, hid_dim = y.shape y = y.view(-1, hid_dim) y = self.reg(y) y = y.view(seq_len, batch_size, -1) return y """ PyCharm Crtl+click nn.LSTM() jump to code of PyTorch: Examples:: >>> rnn = nn.LSTM(10, 20, 2) >>> input = torch.randn(5, 3, 10) >>> h0 = torch.randn(2, 3, 20) >>> c0 = torch.randn(2, 3, 20) >>> output, (hn, cn) = rnn(input, (h0, c0)) """ def output_y_hc(self, x, hc): y, hc = self.rnn(x, hc) # y, (h, c) = self.rnn(x) seq_len, batch_size, hid_dim = y.size() y = y.view(-1, hid_dim) y = self.reg(y) y = y.view(seq_len, batch_size, -1) return y, hc class RegGRU(nn.Module): def __init__(self, inp_dim, out_dim, mod_dim, mid_layers): super(RegGRU, self).__init__() self.rnn = nn.GRU(inp_dim, mod_dim, mid_layers) self.reg = nn.Linear(mod_dim, out_dim) def forward(self, x): x, h = self.rnn(x) # (seq, batch, hidden) seq_len, batch_size, hid_dim = x.shape x = x.view(-1, hid_dim) x = self.reg(x) x = x.view(seq_len, batch_size, -1) return x def output_y_h(self, x, h): y, h = self.rnn(x, h) seq_len, batch_size, hid_dim = y.size() y = y.view(-1, hid_dim) y = self.reg(y) y = y.view(seq_len, batch_size, -1) return y, h def load_data(): # passengers number of international airline , 1949-01 ~ 1960-12 per month seq_number = np.array( [112., 118., 132., 129., 121., 135., 148., 148., 136., 119., 104., 118., 115., 126., 141., 135., 125., 149., 170., 170., 158., 133., 114., 140., 145., 150., 178., 163., 172., 178., 199., 199., 184., 162., 146., 166., 171., 180., 193., 181., 183., 218., 230., 242., 209., 191., 172., 194., 196., 196., 236., 235., 229., 243., 264., 272., 237., 211., 180., 201., 204., 188., 235., 227., 234., 264., 302., 293., 259., 229., 203., 229., 242., 233., 267., 269., 270., 315., 364., 347., 312., 274., 237., 278., 284., 277., 317., 313., 318., 374., 413., 405., 355., 306., 271., 306., 315., 301., 356., 348., 355., 422., 465., 467., 404., 347., 305., 336., 340., 318., 362., 348., 363., 435., 491., 505., 404., 359., 310., 337., 360., 342., 406., 396., 420., 472., 548., 559., 463., 407., 362., 405., 417., 391., 419., 461., 472., 535., 622., 606., 508., 461., 390., 432.], dtype=np.float32) # assert seq_number.shape == (144, ) # plt.plot(seq_number) # plt.ion() # plt.pause(1) seq_number = seq_number[:, np.newaxis] # print(repr(seq)) # 1949~1960, 12 years, 12*12==144 month seq_year = np.arange(12) seq_month = np.arange(12) seq_year_month = np.transpose( [np.repeat(seq_year, len(seq_month)), np.tile(seq_month, len(seq_year))], ) # Cartesian Product seq = np.concatenate((seq_number, seq_year_month), axis=1) # normalization seq = (seq - seq.mean(axis=0)) / seq.std(axis=0) return seq if __name__ == '__main__': run_train_lstm(X) # run_train_gru() # run_origin()