You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

426 lines
14 KiB
Python

#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()