├── LSTM_Load_Forecasting ├── .idea │ ├── LSTM-Load-Forecasting.iml │ ├── dictionaries │ │ ├── Administrator.xml │ │ └── KI.xml │ ├── inspectionProfiles │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ ├── other.xml │ ├── vcs.xml │ └── workspace.xml ├── LSTMs │ ├── multivariate_multi_step.py │ ├── multivariate_single_step.py │ └── univariate_single_step.py ├── __pycache__ │ ├── args.cpython-37.pyc │ ├── args.cpython-38.pyc │ ├── data_process.cpython-37.pyc │ ├── data_process.cpython-38.pyc │ ├── models.cpython-37.pyc │ ├── models.cpython-38.pyc │ ├── util.cpython-37.pyc │ └── util.cpython-38.pyc ├── args.py ├── data │ ├── data.csv │ ├── predict_df.xlsx │ └── shengzhu.xlsx ├── data_process.py ├── models.py ├── models │ ├── multivariate_multi_step.pkl │ ├── multivariate_single_step.pkl │ └── univariate_single_step.pkl ├── tree.txt ├── util.py └── 时间序列预测项目.md ├── README.md ├── fbprophet.py ├── keras_model.py ├── tree.txt └── 广东地区企业报价.xlsx /LSTM_Load_Forecasting/.idea/LSTM-Load-Forecasting.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/.idea/dictionaries/Administrator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mape 5 | 6 | 7 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/.idea/dictionaries/KI.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | anqiudata 5 | pythonhashseed 6 | univariate 7 | 8 | 9 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/.idea/other.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 18 | 19 | 20 | 22 | 23 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 71 | 72 | 73 | 93 | 94 | 95 | 115 | 116 | 117 | 137 | 138 | 139 | 159 | 160 | 161 | 181 | 182 | 183 | 203 | 204 | 205 | 225 | 226 | 227 | 247 | 248 | 249 | 269 | 270 | 271 | 291 | 292 | 293 | 313 | 314 | 315 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 1646136315444 361 | 420 | 421 | 422 | 423 | 425 | 426 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/LSTMs/multivariate_multi_step.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | """ 3 | Author:LIAO XUECHUN 4 | Data:2023/1/12 5 | Describe:multivariate_multi_step 6 | """ 7 | import os 8 | import sys 9 | import pandas as pd 10 | 11 | curPath = os.path.abspath(os.path.dirname(__file__)) 12 | rootPath = os.path.split(curPath)[0] 13 | sys.path.append(rootPath) 14 | 15 | from args import mm_args_parser 16 | from util import train, test_m, load_data_m,forecast_m 17 | 18 | path = os.path.abspath(os.path.dirname(os.getcwd())) 19 | LSTM_PATH = path + '/models/multivariate_multi_step.pkl' 20 | 21 | 22 | if __name__ == '__main__': 23 | args = mm_args_parser() 24 | flag = 'mm' 25 | Dtr, Val, Dte, scaler = load_data_m(args, flag) 26 | train(args, Dtr, Val, LSTM_PATH) 27 | mape,test=test_m(args, Dte, LSTM_PATH,scaler,flag) 28 | forecast=forecast_m(args, LSTM_PATH,scaler) 29 | forecast_result=pd.concat([test,forecast]) 30 | def result(): 31 | if args.method =='yuce': 32 | result_print=forecast_result 33 | else: 34 | result_print = mape 35 | return result_print 36 | print(result()) -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/LSTMs/multivariate_single_step.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | """ 3 | Author:LIAO XUECHUN 4 | Data:2023/1/12 5 | Describe:multivariate_single_step 6 | """ 7 | import os 8 | import sys 9 | 10 | curPath = os.path.abspath(os.path.dirname(__file__)) 11 | rootPath = os.path.split(curPath)[0] 12 | sys.path.append(rootPath) 13 | 14 | from args import ms_args_parser 15 | from util import train, test_m, load_data_m,forecast_m 16 | import pandas as pd 17 | 18 | path = os.path.abspath(os.path.dirname(os.getcwd())) 19 | LSTM_PATH = path + '/models/multivariate_single_step.pkl' 20 | 21 | 22 | if __name__ == '__main__': 23 | args = ms_args_parser() 24 | flag = 'ms' 25 | Dtr, Val, Dte,scaler = load_data_m(args, flag) 26 | train(args, Dtr, Val, LSTM_PATH) 27 | mape,test=test_m(args, Dte, LSTM_PATH,scaler) 28 | forecast=forecast_m(args, LSTM_PATH,scaler) 29 | forecast_result=pd.concat([test,forecast]) 30 | def result(): 31 | if args.method =='yuce': 32 | result_print=forecast_result 33 | else: 34 | result_print = mape 35 | return result_print 36 | result() 37 | 38 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/LSTMs/univariate_single_step.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Author:LIAO XUECHUN 4 | Data:2023/1/12 5 | Describe:univariate_single_step 6 | """ 7 | import os 8 | import sys 9 | os.environ['KMP_DUPLICATE_LIB_OK'] = 'True' 10 | curPath = os.path.abspath(os.path.dirname(__file__)) 11 | rootPath = os.path.split(curPath)[0] 12 | sys.path.append(rootPath) 13 | 14 | from util import train, test, load_data_u,forecast,forecast_m 15 | from args import us_args_parser 16 | from data_process import setup_seed 17 | import pandas as pd 18 | 19 | setup_seed(20) 20 | path = os.path.abspath(os.path.dirname(os.getcwd()))#当前大文件夹目录 21 | LSTM_PATH = path + '/models/univariate_single_step.pkl' 22 | 23 | 24 | if __name__ == '__main__': 25 | args = us_args_parser() 26 | flag = 'us' 27 | Dtr, Val, Dte, m, n = load_data_u(args, flag) 28 | train(args, Dtr, Val, LSTM_PATH) 29 | mape,test=test(args, Dte, LSTM_PATH, m, n) 30 | forecast_result=forecast(args, LSTM_PATH) 31 | forecast_result=pd.concat([test,forecast_result]) 32 | def result(): 33 | if args.method =='yuce': 34 | result_print=forecast_result 35 | else: 36 | result_print = mape 37 | return result_print 38 | result() 39 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/__pycache__/args.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/__pycache__/args.cpython-37.pyc -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/__pycache__/args.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/__pycache__/args.cpython-38.pyc -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/__pycache__/data_process.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/__pycache__/data_process.cpython-37.pyc -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/__pycache__/data_process.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/__pycache__/data_process.cpython-38.pyc -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/__pycache__/models.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/__pycache__/models.cpython-37.pyc -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/__pycache__/models.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/__pycache__/models.cpython-38.pyc -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/__pycache__/util.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/__pycache__/util.cpython-37.pyc -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/__pycache__/util.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/__pycache__/util.cpython-38.pyc -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/args.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import argparse, torch 3 | 4 | def mm_args_parser(): 5 | parser = argparse.ArgumentParser() 6 | parser.add_argument('--epochs', type=int, default=50, help='input dimension') 7 | parser.add_argument('--input_size', type=int, default=3, help='input dimension') 8 | parser.add_argument('--seq_len', type=int, default=30, help='seq len') 9 | parser.add_argument('--output_size', type=int, default=3, help='output dimension') 10 | parser.add_argument('--hidden_size', type=int, default=32, help='hidden size') 11 | parser.add_argument('--num_layers', type=int, default=2, help='num layers') 12 | parser.add_argument('--lr', type=float, default=0.005, help='learning rate') 13 | parser.add_argument('--batch_size', type=int, default=30, help='batch size') 14 | parser.add_argument('--optimizer', type=str, default='adam', help='type of optimizer') 15 | parser.add_argument('--device', default=(torch.device('cuda' if torch.cuda.is_available() else 'cpu'))) 16 | parser.add_argument('--weight_decay', type=float, default=0.0001, help='weight decay') 17 | parser.add_argument('--bidirectional', type=bool, default=False, help='LSTM direction') 18 | parser.add_argument('--step_size', type=int, default=4, help='step size') 19 | parser.add_argument('--gamma', type=float, default=0.5, help='gamma') 20 | parser.add_argument('--yucestart',type=int,default=5,help='forecasting start') 21 | parser.add_argument('--yuceend',type=int,default=7,help='forecasting end') 22 | parser.add_argument('--train_split',type=int,default=0.6,help='train split') 23 | parser.add_argument('--test_split',type=int,default=0.8,help='test split ') 24 | parser.add_argument('--predict_df',type=str,default='F:/E/BaiduSyncdisk/lxc/tsf/tsf_finally/LSTM_Load_Forecasting/data/predict_df.xlsx',help='predict df ') 25 | parser.add_argument('--df',type=str,default='F:/E/BaiduSyncdisk/lxc/tsf/tsf_finally/LSTM_Load_Forecasting/data/shengzhu.xlsx',help='df ') 26 | parser.add_argument('--day', type=int, default=30, 27 | help='yuce day ') 28 | parser.add_argument('--method', type=str, default='yuce', 29 | help='is predict of mape ') 30 | args = parser.parse_args() 31 | return args 32 | 33 | 34 | def ms_args_parser(): 35 | parser = argparse.ArgumentParser() 36 | parser.add_argument('--epochs', type=int, default=30, help='input dimension') 37 | parser.add_argument('--input_size', type=int, default=3, help='input dimension') 38 | parser.add_argument('--seq_len', type=int, default=30, help='seq len') 39 | parser.add_argument('--output_size', type=int, default=1, help='output dimension') 40 | parser.add_argument('--hidden_size', type=int, default=32, help='hidden size') 41 | parser.add_argument('--num_layers', type=int, default=2, help='num layers') 42 | parser.add_argument('--lr', type=float, default=0.001, help='learning rate') 43 | parser.add_argument('--batch_size', type=int, default=30, help='batch size') 44 | parser.add_argument('--optimizer', type=str, default='adam', help='type of optimizer') 45 | parser.add_argument('--device', default=(torch.device('cuda' if torch.cuda.is_available() else 'cpu'))) 46 | parser.add_argument('--weight_decay', type=float, default=0.0001, help='weight decay') 47 | parser.add_argument('--bidirectional', type=bool, default=True, help='LSTM direction') 48 | parser.add_argument('--step_size', type=int, default=10, help='step size') 49 | parser.add_argument('--gamma', type=float, default=0.5, help='gamma') 50 | parser.add_argument('--yucestart',type=int,default=5,help='forecasting start') 51 | parser.add_argument('--yuceend',type=int,default=7,help='forecasting end') 52 | parser.add_argument('--train_split',type=int,default=0.6,help='train split') 53 | parser.add_argument('--test_split',type=int,default=0.8,help='test split ') 54 | parser.add_argument('--predict_df',type=str,default='F:/E/BaiduSyncdisk/lxc/tsf/tsf_finally/LSTM_Load_Forecasting/data/predict_df.xlsx',help='predict df ') 55 | parser.add_argument('--df',type=str,default='F:/E/BaiduSyncdisk/lxc/tsf/tsf_finally/LSTM_Load_Forecasting/data/shengzhu.xlsx',help='df ') 56 | parser.add_argument('--day', type=int, default=30, 57 | help='yuce day ') 58 | parser.add_argument('--method', type=str, default='yuce', 59 | help='is predict of mape ') 60 | args = parser.parse_args() 61 | return args 62 | 63 | 64 | def us_args_parser(): 65 | parser = argparse.ArgumentParser() 66 | parser.add_argument('--epochs', type=int, default=30, help='diedai num') 67 | parser.add_argument('--input_size', type=int, default=1, help='input dimension') 68 | parser.add_argument('--seq_len', type=int, default=30, help='seq len') 69 | parser.add_argument('--output_size', type=int, default=1, help='output dimension') 70 | parser.add_argument('--hidden_size', type=int, default=32, help='hidden size') 71 | parser.add_argument('--num_layers', type=int, default=2, help='num layers') 72 | parser.add_argument('--lr', type=float, default=0.001, help='learning rate') 73 | parser.add_argument('--batch_size', type=int, default=10, help='batch size') 74 | parser.add_argument('--optimizer', type=str, default='adam', help='type of optimizer') 75 | parser.add_argument('--device', default=(torch.device('cuda' if torch.cuda.is_available() else 'cpu'))) 76 | parser.add_argument('--weight_decay', type=float, default=0.0001, help='weight decay') 77 | parser.add_argument('--bidirectional', type=bool, default=False, help='LSTM direction')#是否是双向LSTM 78 | parser.add_argument('--step_size', type=int, default=10, help='step size') 79 | parser.add_argument('--gamma', type=float, default=0.5, help='gamma') 80 | parser.add_argument('--yucel',type=int,default=7,help='forecasting ') 81 | parser.add_argument('--train_split',type=int,default=0.6,help='train split') 82 | parser.add_argument('--test_split',type=int,default=0.8,help='test split ') 83 | parser.add_argument('--df',type=str,default='F:/E/BaiduSyncdisk/lxc/tsf/tsf_finally/LSTM_Load_Forecasting/data/shengzhu.xlsx',help='df ') 84 | parser.add_argument('--day', type=int, default=30, 85 | help='yuce day ') 86 | parser.add_argument('--method', type=str, default='yuce', 87 | help='is predict of mape ') 88 | args = parser.parse_args() 89 | return args 90 | # okay decompiling args.cpython-37.pyc 91 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/data/predict_df.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/data/predict_df.xlsx -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/data/shengzhu.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/data/shengzhu.xlsx -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/data_process.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import os, random, numpy as np, pandas as pd, torch 3 | from torch.utils.data import Dataset, DataLoader 4 | from args import us_args_parser,ms_args_parser,mm_args_parser 5 | from sklearn.preprocessing import MinMaxScaler 6 | device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 7 | 8 | def setup_seed(seed): 9 | os.environ['PYTHONHASHSEED'] = str(seed) 10 | torch.manual_seed(seed) 11 | torch.cuda.manual_seed_all(seed) 12 | np.random.seed(seed) 13 | random.seed(seed) 14 | torch.backends.cudnn.deterministic = True 15 | 16 | 17 | def load_datas(df): 18 | """ 19 | :return: 20 | """ 21 | #path = os.path.dirname(os.path.realpath(__file__)) + '/data/shengzhu.xlsx' 22 | df = pd.read_excel(df) 23 | df = df.set_index('date') 24 | return df 25 | 26 | 27 | class MyDataset(Dataset): 28 | 29 | def __init__(self, data): 30 | self.data = data 31 | 32 | def __getitem__(self, item): 33 | return self.data[item] 34 | 35 | def __len__(self): 36 | return len(self.data) 37 | 38 | 39 | def nn_seq_mm(args,seq_len, B, num,train_split,test_split): 40 | print('data processing...') 41 | args=mm_args_parser() 42 | dataset = load_datas(args.df).iloc[:,int(args.yucestart):int(args.yuceend)+1] 43 | #数据切分 44 | train_data = dataset[:int(len(dataset) * args.train_split)] 45 | val_data = dataset[int(len(dataset) * args.train_split):int(len(dataset) * args.test_split)] 46 | test_data = dataset[int(len(dataset) * args.test_split):len(dataset)]#shape 为(391, 3) 47 | global scaler 48 | #归一化,shape不变,但类型为numpy.ndarray 49 | scaler = MinMaxScaler(feature_range=(0, 1)) 50 | train = scaler.fit_transform(train_data) 51 | val = scaler.transform(val_data) 52 | test = scaler.transform(test_data)#shape 为(391, 3) 53 | def process(data, batch_size,step_size): 54 | #load = data.iloc[:,int(args.yucestart):int(args.yuceend)+1] 55 | #load1= scaler.fit_transform(load)#load.values的shape是(1172,int(args.yuceend)-int(args.yucestart)) 56 | seq = [] 57 | for i in range(0,len(data) - seq_len-num,num): 58 | train_seq = [] 59 | train_label = [] 60 | for j in range(i, i + seq_len): 61 | x=data[j,0:int(args.input_size)]#一个冒号的shape为(int(args.yuceend)+1-int(args.yucestart),) 62 | train_seq.append(x)#仍是列表 63 | #print(np.array(train_seq).shape)#(args.seq_len,int(args.yuceend)+1-int(args.yucestart)) 64 | for b in range(i + seq_len, i + seq_len + num): 65 | train_label.append(data[b,int(args.yuceend)-int(args.yucestart)]) 66 | #print(np.array(train_label).shape)#(num,) 67 | train_seq = torch.FloatTensor(train_seq) 68 | train_label = torch.FloatTensor(train_label).view(-1)#shape为([4])#确保为一维 69 | seq.append((train_seq, train_label)) 70 | #print(len(seq)) 例如这里test的shape为(391,3)所以seq的长度为(391-seq_len)//num,即为90 71 | 72 | seq = MyDataset(seq) 73 | seq = DataLoader(dataset=seq, batch_size=batch_size, shuffle=False, num_workers=0, drop_last=False) 74 | return seq 75 | 76 | Dtr = process(train, B, step_size=num) 77 | Val = process(val, B, step_size=num) 78 | Dte = process(test, B, step_size=num) 79 | return ( 80 | Dtr, Val, Dte, scaler) 81 | 82 | 83 | def nn_seq_ms(args,seq_len, B,train_split,test_split): 84 | ''' 85 | data.iloc[:,int(args.yucestart):int(args.yuceend)+1] 这里的维度就会为2维,shape为(len(data),int(args.yuceend)+1-int(args.yucestart)) 86 | minmaxscaler的使用方式:scaler.fit_transform(data.iloc[]) 87 | :param seq_len: 预测步长 88 | :param B: batch size 89 | :param train_split: 训练集切分比例 90 | :param test_split: 测试集切分比例 91 | :return:train_seq 的shape为(30,1)(seq_len,input_size) train_label的shape为(1)(output_size) 92 | ''' 93 | print('data processing...') 94 | args=ms_args_parser() 95 | dataset = load_datas(args.df).iloc[:,int(args.yucestart):int(args.yuceend)+1] 96 | #数据切分 97 | train_data = dataset[:int(len(dataset) * args.train_split)] 98 | val_data = dataset[int(len(dataset) * args.train_split):int(len(dataset) * args.test_split)] 99 | test_data = dataset[int(len(dataset) * args.test_split):len(dataset)]#shape 为(391, 3) 100 | global scaler 101 | #归一化,shape不变,但类型为numpy.ndarray 102 | scaler = MinMaxScaler(feature_range=(0, 1)) 103 | train = scaler.fit_transform(train_data) 104 | val = scaler.transform(val_data) 105 | test = scaler.transform(test_data)#shape 为(391, 3) 106 | 107 | def process(data, batch_size): 108 | #load = data.iloc[:,int(args.yucestart):int(args.yuceend)+1] 109 | #load1= scaler.fit_transform(load)#load.values的shape是(1172,int(args.yuceend)-int(args.yucestart)) 110 | seq = [] 111 | for i in range(len(data) - seq_len): 112 | train_seq = [] 113 | train_label = [] 114 | for j in range(i, i + seq_len): 115 | x=data[j,0:int(args.input_size)]#一个冒号的shape为(int(args.yuceend)+1-int(args.yucestart),) 116 | train_seq.append(x)#仍是列表 117 | #print(np.array(train_seq).shape)#(args.seq_len,int(args.yuceend)+1-int(args.yucestart)) 118 | 119 | train_label.append(data[(i + seq_len),int(args.yuceend)-int(args.yucestart)]) 120 | train_seq = torch.FloatTensor(train_seq)#可将list转化成tensor,np.array(train_seq)后的shape就为torch.Size([seq_len,int(args.yuceend)+1-int(args.yucestart)]) 121 | train_label = torch.FloatTensor(train_label).view(-1)#shape为torch.Size([1]) 122 | seq.append((train_seq, train_label)) 123 | print(len(seq)) 124 | seq = MyDataset(seq) 125 | seq = DataLoader(dataset=seq, batch_size=batch_size, shuffle=False, num_workers=0, drop_last=False) 126 | return seq 127 | 128 | Dtr = process(train, B) 129 | Val = process(val, B) 130 | Dte = process(test, B) 131 | return ( 132 | Dtr, Val, Dte,scaler) 133 | 134 | 135 | def nn_seq_us(args,seq_len, B,train_split,test_split): 136 | ''' 137 | 这里[:int(len(dataset) * train_split)][data.columns[args.yucel]的values因为是单变量,所以shape为(len(dataset) * train_split,),如需fit_transform需要 pd.DataFrame()扩展维度 138 | label这里因为view(-1)是确保为1维,例如如果使用minmaxscaler后增加的维度在label这里需要删除 139 | minmaxscaler的单变量使用方式:scaler.fit_transform(pd.DataFrame(data.iloc[].values)) 140 | :param seq_len: 预测步长 141 | :param B: batch size 142 | :param train_split: 训练集切分比例 143 | :param test_split: 测试集切分比例 144 | :return:train_seq 的shape为(30,1)(seq_len,input_size) train_label的shape为(1)(output_size) 145 | ''' 146 | print('data processing...') 147 | args=us_args_parser() 148 | dataset = load_datas(args.df) 149 | train = dataset[:int(len(dataset) * train_split)] 150 | val = dataset[int(len(dataset) * train_split):int(len(dataset) * test_split)] 151 | test = dataset[int(len(dataset) * test_split):len(dataset)] 152 | m, n = np.max(train[train.columns[args.yucel]]), np.min(train[train.columns[args.yucel]])#第一列的最大最小值 153 | #dataset.iloc[:, args.yucestart:args.yuceend] 154 | 155 | def process(data,batch_size): 156 | #load = data[data.columns[args.yucel]]#预测列 157 | load = data.iloc[:, int(args.yucel)] 158 | #方法一:如果选择平均化方式,因为这里是单变量,values的shape为(长度,)所以在创建数据时需要扩展维度x=[load[j]]为2维 159 | load0 = (load- n) / (m - n) #load.shape为(1178,) 160 | load0 = load0.tolist() # 对于单变量预测来说,是否tolist取数并无关系,可注释掉 161 | #方法二:如果选择minmaxscaler方式,注意这里必须要pd.DataFrame()增加维度,而load1的shpae为(长度,1),所以在创建数据时不需要扩展维度直接为x=load[j] 162 | #scaler = MinMaxScaler(feature_range=(0, 1)) 163 | #load1= scaler.fit_transform(pd.DataFrame(load.values)) 164 | #load1 = load1.tolist()#第一列数据归一化,是否tolist取数并无关系,可注释掉 165 | seq = [] 166 | for i in range(len(load) - seq_len): 167 | train_seq = [] 168 | train_label = [] 169 | for j in range(i, i + seq_len): 170 | #x=load1[j] 171 | x=[load0[j]] 172 | train_seq.append(x) 173 | #print(np.array(train_seq).shape)#shape为(30,1) 174 | train_label.append(load0[(i + seq_len)])#前24个数预测第25个 175 | train_seq = torch.FloatTensor(train_seq)#torch.FloatTensor(train_seq)类型转换, 将list ,numpy转化为tensor;等价于torch.from_numpy(np.array(train_seq)) 176 | train_label = torch.FloatTensor(train_label).view(-1)#确保为一维 177 | seq.append((train_seq, train_label))#seq[0]代表第一个预测的x和y 178 | seq = MyDataset(seq) 179 | seq = DataLoader(dataset=seq, batch_size=batch_size, shuffle=False, num_workers=0, drop_last=False)#torch格式的数据加载 180 | return seq 181 | 182 | 183 | Dtr = process(train, B) 184 | Val = process(val, B) 185 | Dte = process(test, B) 186 | return ( 187 | Dtr, Val, Dte,m,n) 188 | 189 | def data_gy(data): 190 | m, n = np.max(data), np.min(data) 191 | data=(data-n)/(m-n) 192 | return data 193 | def insertscaler(data,args): 194 | ''' 195 | :param data: np.array后的,np。reshape可改变列表维度 196 | :return: 逆变化后的预测列,因为我的预测列是最后一列,所以这里是-1 197 | ''' 198 | data_array=np.repeat(data,int(args.yuceend)+1-int(args.yucestart),axis=-1)#必须要改变形状才能inverse_transform 199 | data_ = scaler.inverse_transform(np.reshape(data_array,(len(data),int(args.yuceend)+1-int(args.yucestart))))[:,-1]#逆变化的第一列 200 | return data_ 201 | def get_mape(x, y): 202 | """ 203 | :param x: true value 204 | :param y: pred value 205 | :return: mape 206 | """ 207 | return np.mean(np.abs((x - y) / x)) 208 | # okay decompiling data_process.cpython-37.pyc 209 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/models.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: UTF-8 -*- 3 | from torch import nn 4 | import torch 5 | device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 6 | 7 | class LSTM(nn.Module): 8 | 9 | def __init__(self, input_size, hidden_size, num_layers, output_size, batch_size): 10 | super().__init__() 11 | self.input_size = input_size#单变量还是多变量 12 | self.hidden_size = hidden_size#隐藏层节点个数 13 | self.num_layers = num_layers#层数 14 | self.output_size = output_size 15 | self.num_directions = 1#单向 16 | self.batch_size = batch_size 17 | self.lstm = nn.LSTM((self.input_size), (self.hidden_size), (self.num_layers), batch_first=True)#将batch_size提前 18 | self.fc = nn.Linear(self.hidden_size, self.output_size) 19 | 20 | def forward(self, input_seq): 21 | batch_size, seq_len = input_seq.shape[0], input_seq.shape[1]#输入到lstm中的input的shape应该 input(batch_size,seq_len,input_size) 22 | h_0 = torch.randn(self.num_directions * self.num_layers, batch_size, self.hidden_size).to(device) 23 | c_0 = torch.randn(self.num_directions * self.num_layers, batch_size, self.hidden_size).to(device) 24 | output, _ = self.lstm(input_seq, (h_0, c_0))#(隐状态h_n,单元状态c_n) 25 | pred = self.fc(output) 26 | pred = pred[:, -1, :] 27 | return pred 28 | 29 | 30 | class BiLSTM(nn.Module): 31 | 32 | def __init__(self, input_size, hidden_size, num_layers, output_size, batch_size): 33 | super().__init__() 34 | self.input_size = input_size 35 | self.hidden_size = hidden_size 36 | self.num_layers = num_layers 37 | self.output_size = output_size 38 | self.num_directions = 2 39 | self.batch_size = batch_size 40 | self.lstm = nn.LSTM((self.input_size), (self.hidden_size), (self.num_layers), batch_first=True, bidirectional=True) 41 | self.linear = nn.Linear(self.hidden_size, self.output_size)#全连接层 42 | 43 | def forward(self, input_seq): 44 | batch_size, seq_len = input_seq.shape[0], input_seq.shape[1]#用pytorch输入进去本身是(seq_len,batch_size,input_size) 45 | h_0 = torch.randn(self.num_directions * self.num_layers, batch_size, self.hidden_size).to(device) 46 | c_0 = torch.randn(self.num_directions * self.num_layers, batch_size, self.hidden_size).to(device) 47 | output, _ = self.lstm(input_seq, (h_0, c_0)) 48 | output = output.contiguous().view(batch_size, seq_len, self.num_directions, self.hidden_size) 49 | output = torch.mean(output, dim=2) 50 | pred = self.linear(output) 51 | pred = pred[:, -1, :]#pred的shape为(batch_size, seq_len, output_size)。假设我们用前24个小时(1~24)预测后2个小时的负荷(25~26),那么seq_len=24, output_size=2。根据LSTM的原理,最终的输出中包含了所有位置的预测值,也就是((2 3), (3 4), (4 5)...(25 26))。很显然我们只需要最后一个预测值,即pred[:, -1, :]。 52 | return pred 53 | # okay decompiling models.cpython-37.pyc 54 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/models/multivariate_multi_step.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/models/multivariate_multi_step.pkl -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/models/multivariate_single_step.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/models/multivariate_single_step.pkl -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/models/univariate_single_step.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/models/univariate_single_step.pkl -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/tree.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/LSTM_Load_Forecasting/tree.txt -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/util.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import copy 3 | import os 4 | import sys 5 | 6 | import pandas as pd 7 | 8 | curPath = os.path.abspath(os.path.dirname(__file__)) 9 | rootPath = os.path.split(curPath)[0] 10 | sys.path.append(rootPath) 11 | from itertools import chain 12 | import torch 13 | from scipy.interpolate import make_interp_spline 14 | from torch import nn 15 | import numpy as np 16 | import matplotlib.pyplot as plt 17 | from torch.utils.data import DataLoader 18 | from models import LSTM, BiLSTM 19 | from data_process import nn_seq_us, nn_seq_ms, nn_seq_mm, device, get_mape, setup_seed, MyDataset,load_datas,data_gy,insertscaler 20 | from tqdm import tqdm 21 | from torch.optim.lr_scheduler import StepLR 22 | from datetime import timedelta 23 | import datetime 24 | from sklearn.preprocessing import MinMaxScaler 25 | setup_seed(20) 26 | 27 | def load_data_m(args, flag): 28 | if flag == 'ms': 29 | Dtr, Val, Dte,scaler = nn_seq_ms(args=args,seq_len=(args.seq_len), B=(args.batch_size),train_split=args.train_split,test_split=args.test_split) 30 | else: 31 | Dtr, Val, Dte,scaler = nn_seq_mm(args=args,seq_len=(args.seq_len), B=(args.batch_size), num=(args.output_size),train_split=args.train_split,test_split=args.test_split) 32 | return ( 33 | Dtr, Val, Dte,scaler) 34 | def load_data_u(args, flag): 35 | if flag == 'us': 36 | Dtr, Val, Dte, m, n = nn_seq_us(args=args,seq_len=(args.seq_len), B=(args.batch_size),train_split=args.train_split,test_split=args.test_split) 37 | return ( 38 | Dtr, Val, Dte, m, n) 39 | 40 | def get_val_loss(args, model, Val): 41 | model.eval() 42 | loss_function = nn.MSELoss().to(args.device)# 定义误差函数 43 | val_loss = [] 44 | for seq, label in Val: 45 | with torch.no_grad(): 46 | seq = seq.to(args.device) 47 | label = label.to(args.device) 48 | y_pred = model(seq) 49 | loss = loss_function(y_pred, label) 50 | val_loss.append(loss.item()) 51 | 52 | return np.mean(val_loss) 53 | 54 | 55 | def train(args, Dtr, Val, path): 56 | input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers 57 | output_size = args.output_size 58 | if args.bidirectional: 59 | model = BiLSTM(input_size, hidden_size, num_layers, output_size, batch_size=(args.batch_size)).to(device) 60 | else: 61 | model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=(args.batch_size)).to(device) 62 | loss_function = nn.MSELoss().to(device) 63 | if args.optimizer == 'adam': 64 | optimizer = torch.optim.Adam((model.parameters()), lr=(args.lr), weight_decay=(args.weight_decay)) 65 | else: 66 | optimizer = torch.optim.SGD((model.parameters()), lr=(args.lr), momentum=0.9, 67 | weight_decay=(args.weight_decay)) 68 | scheduler = StepLR(optimizer, step_size=(args.step_size), gamma=(args.gamma)) 69 | min_epochs = 10 70 | best_model = None 71 | min_val_loss = 5 72 | for epoch in tqdm(range(args.epochs)): 73 | train_loss = [] 74 | for seq, label in Dtr: 75 | seq = seq.to(device)#因为前期处理进行了torch.FloatTensor,这里直接to(device)。shape为(batch_size,seq_len,int(args.yuceend)+1-int(args.yucestart)) 76 | label = label.to(device)#shape为(batch_size,int(args.yuceend)+1-int(args.yucestart)) 77 | optimizer.zero_grad() 78 | y_pred = model(seq)#前向传播 79 | loss = loss_function(y_pred, label)#计算损失 80 | loss.backward()# 误差反向传播 81 | optimizer.step()# 梯度更新 82 | train_loss.append(loss.item()) # 损失记录 83 | scheduler.step() 84 | val_loss = get_val_loss(args, model, Val) 85 | if epoch + 1 >= min_epochs: 86 | if val_loss < min_val_loss: 87 | min_val_loss = val_loss 88 | best_model = copy.deepcopy(model) 89 | print('epoch {:03d} train_loss {:.8f} val_loss {:.8f}'.format(epoch, np.mean(train_loss), val_loss)) 90 | model.train() 91 | 92 | state = {'models': best_model.state_dict()} 93 | torch.save(state, path) 94 | 95 | def test_m(args, Dte, path,scaler,flag): 96 | ''' 97 | with torch.no_grad() 是创建了一张图,所以在这张图中,所有的计算都不会进入梯度计算;detach()将一个变量从图中剥离出来进而使得此变量的计算不会进入到梯度计算中 98 | :param args: 参数 99 | :param Dte: 测试集 100 | :param path: 加载模型 101 | :param scaler: 标准化 102 | :param flag: 模型代称 103 | :return: 评估结果和测试集原始预测 104 | ''' 105 | pred = [] 106 | y = [] 107 | print('loading models...') 108 | input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers 109 | output_size = args.output_size 110 | if args.bidirectional: 111 | model = BiLSTM(input_size, hidden_size, num_layers, output_size, batch_size=(args.batch_size)).to(device) 112 | else: 113 | model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=(args.batch_size)).to(device) 114 | model.load_state_dict(torch.load(path)['models']) 115 | model.eval() 116 | print('testing...') 117 | for seq, target in tqdm(Dte): 118 | target = list(chain.from_iterable(target.data.tolist()))#target.data.tolist()tensor数据转化成列表,再迭代成列表[[1,2],[3,4]]=>[1,2,3,4] 119 | y.extend(target)#数据扩展,在已存在的列表中添加新的列表内容 120 | seq = seq.to(device)#shape是(batch_size,seq_len,dim) 121 | #print(seq.shape)#torch.Size([30, 30, 1])...torch.Size([1, 30, 1]),一共361个 122 | with torch.no_grad(): 123 | y_pred = model(seq) 124 | y_pred = list(chain.from_iterable(y_pred.data.tolist())) 125 | pred.extend(y_pred) 126 | y, pred = np.array(y), np.array(pred)#注意这里的y和pred是列表 127 | #逆变化 128 | y=insertscaler(y,args) 129 | pred=insertscaler(pred,args) 130 | if flag=='ms': 131 | pred_result=pd.DataFrame({'original':y,'pred':pred},index = load_datas(args.df)[int(len(load_datas(args.df)) * args.test_split)+int(args.seq_len):len(load_datas(args.df))].index) 132 | if flag=='mm': 133 | pred_result = pd.DataFrame({'original': y, 'pred': pred}, index=load_datas(args.df)[int(len( 134 | load_datas(args.df)) * args.test_split) + int(args.seq_len):int(len( 135 | load_datas(args.df)) * args.test_split) + int(args.seq_len)+len(y)].index) 136 | # 评估 137 | print('mape:', get_mape(y, pred)) 138 | return pd.DataFrame([get_mape(y, pred)],columns=['mape']),pred_result 139 | def test(args, Dte, path, m, n): 140 | pred = [] 141 | y = [] 142 | print('loading models...') 143 | input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers 144 | output_size = args.output_size 145 | if args.bidirectional: 146 | model = BiLSTM(input_size, hidden_size, num_layers, output_size, batch_size=(args.batch_size)).to(device) 147 | else: 148 | model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=(args.batch_size)).to(device) 149 | model.load_state_dict(torch.load(path)['models']) 150 | model.eval() 151 | print('testing...') 152 | for seq, target in tqdm(Dte): 153 | target = list(chain.from_iterable(target.data.tolist())) 154 | y.extend(target) 155 | seq = seq.to(device)#shape是(batch_size,seq_len,dim) 156 | #print(seq.shape)#torch.Size([30, 30, 1])...torch.Size([1, 30, 1]),一共361个 157 | with torch.no_grad(): 158 | y_pred = model(seq) 159 | y_pred = list(chain.from_iterable(y_pred.data.tolist())) 160 | pred.extend(y_pred) 161 | y, pred = np.array(y), np.array(pred) 162 | #归一化处理 163 | y = (m - n) * y + n 164 | pred = (m - n) * pred + n 165 | pred_result = pd.DataFrame({'original': y, 'pred': pred}, index=load_datas(args.df)[int(len(load_datas(args.df)) * args.test_split) + int(args.seq_len):len(load_datas(args.df))].index) 166 | # 评估 167 | print('mape:', get_mape(y, pred)) 168 | return pd.DataFrame([get_mape(y, pred)],columns=['mape']),pred_result 169 | #x = [i for i in range(1, 151)] 170 | #x_smooth = np.linspace(np.min(x), np.max(x), 900)#在最大值和最小值之间生成900个数 171 | #y_smooth = make_interp_spline(x, y[150:300])(x_smooth)#使之平滑 172 | #plt.plot(y) 173 | #plt.plot(pred) 174 | #plt.plot(x_smooth, y_smooth, c='green', marker='*', ms=1, alpha=0.75, label='true') 175 | #y_smooth = make_interp_spline(x, pred[150:300])(x_smooth) 176 | #plt.plot(x_smooth, y_smooth, c='red', marker='o', ms=1, alpha=0.75, label='pred') 177 | #plt.grid(axis='y') 178 | #plt.legend() 179 | #plt.show() 180 | def forecast(args, path): 181 | print('forecasting') 182 | input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers 183 | output_size = args.output_size 184 | if args.bidirectional: 185 | model = BiLSTM(input_size, hidden_size, num_layers, output_size, batch_size=(args.batch_size)).to(device) 186 | else: 187 | model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=(args.batch_size)).to(device) 188 | model.load_state_dict(torch.load(path)['models']) 189 | #原始值 190 | df_day_past=load_datas(args.df)[-args.seq_len:] 191 | df_day_past=df_day_past.iloc[:,int(args.yucel)]#shape为(len(df_day_past),)可以np.array(df_day_past.iloc[:,int(args.yucel)]).reshape(-1,1)变为二维(len(df_day_past),1) 192 | past_array = data_gy(df_day_past).tolist() # 归一 193 | #未来值 194 | new_array=[0]*args.day 195 | past_array.extend(new_array) 196 | a1=datetime.datetime.strptime(str(df_day_past.index[-1]),'%Y-%m-%d')+timedelta(days=1) 197 | a2=a1+timedelta(days=args.day-1) 198 | 199 | for x in range(0,len(past_array)-args.seq_len): 200 | data_x=[] 201 | for j in range(x,x+args.seq_len): 202 | i=[past_array[j]] 203 | data_x.append(i) 204 | data_x = torch.FloatTensor([data_x])#增加维度 205 | #data_x = MyDataset(data_x) 206 | #data_x = DataLoader(dataset=data_x, batch_size=args.batch_size, shuffle=False, num_workers=0) 207 | #data_x = [x for x in iter(data_x)][0] 208 | data_x = data_x.to(device) 209 | with torch.no_grad(): 210 | x_pred = model(data_x) 211 | x_pred = list(chain.from_iterable(x_pred.data.tolist())) 212 | past_array[x+args.seq_len]=x_pred[0] 213 | yucel = [round(x * (np.max(df_day_past) - np.min(df_day_past)) + np.min(df_day_past),2) for x in past_array] 214 | yucel_data=pd.DataFrame({'pred':yucel[args.seq_len:]},index=pd.date_range(a1,a2)) 215 | return yucel_data 216 | def forecast_m(args, path,scaler): 217 | print('forecasting') 218 | input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers 219 | output_size = args.output_size 220 | if args.bidirectional: 221 | model = BiLSTM(input_size, hidden_size, num_layers, output_size, batch_size=(args.batch_size)).to(device) 222 | else: 223 | model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=(args.batch_size)).to(device) 224 | model.load_state_dict(torch.load(path)['models']) 225 | #原始值 226 | if args.method =='ms': 227 | df_day_past=load_datas(args.df)[-args.seq_len:] 228 | else: 229 | df_day_past = load_datas(args.df)[-(args.seq_len+args.day-args.output_size):] 230 | df_day_past=df_day_past.iloc[:,int(args.yucestart):int(args.yuceend)+1]#shape为(len(df_day_past),int(args.yuceend)-int(args.yucestart)) 231 | df_day_past_array=scaler.transform(df_day_past) 232 | #未来值 233 | a0=datetime.datetime.strptime(str(df_day_past.index[0]),'%Y-%m-%d') 234 | a1=datetime.datetime.strptime(str(df_day_past.index[-1]),'%Y-%m-%d')+timedelta(days=1) 235 | a2=a1+timedelta(days=args.day-1) 236 | df_day_future=load_datas(args.predict_df) 237 | df_day_future.index=pd.date_range(a1,a2) 238 | df_day_future[str(df_day_past.columns[-1])]=0 239 | df_day_future.columns = df_day_past.columns 240 | df_day_future_array=scaler.transform(df_day_future)#变成了array 241 | new_array=pd.DataFrame(df_day_future_array) 242 | new_array.iloc[:,int(args.yuceend)-int(args.yucestart)]=np.nan#缩放后将未来预测列替换成“nan" 243 | full_df=pd.concat([pd.DataFrame(df_day_past_array),new_array]) 244 | full_df_array=full_df.values#对于dataframe需要先取values,shape为(60,int(args.yuceend)+1-int(args.yucestart)) 245 | if args.method =='ms': 246 | for x in range(0,args.day): 247 | data_x=[] 248 | data_x.append(full_df_array[x:x+args.seq_len,0:int(args.input_size)]) 249 | data_x = torch.FloatTensor(data_x)#shape为(1,args.seq_len,int(args.yuceend)+1-int(args.yucestart)) 250 | data_x = data_x.to(device) 251 | with torch.no_grad(): 252 | x_pred = model(data_x) 253 | x_pred = list(chain.from_iterable(x_pred.data.tolist())) 254 | full_df.iloc[x+args.seq_len,int(args.yuceend)-int(args.yucestart)]=x_pred[0] 255 | else: 256 | for x in range(0,args.day,args.output_size): 257 | data_x=[] 258 | data_x.append(full_df_array[x:x+args.seq_len,0:int(args.input_size)]) 259 | data_x = torch.FloatTensor(data_x)#shape为(1,args.seq_len,int(args.yuceend)+1-int(args.yucestart)) 260 | data_x = data_x.to(device) 261 | with torch.no_grad(): 262 | x_pred = model(data_x) 263 | x_pred = list(chain.from_iterable(x_pred.data.tolist())) 264 | for y in range(0,args.output_size): 265 | full_df.iloc[x+(args.seq_len+args.day-args.output_size)+y,int(args.yuceend)-int(args.yucestart)]=x_pred[y] 266 | #逆变化 267 | yucel=np.array(full_df.iloc[:,int(args.yuceend)-int(args.yucestart)]).reshape(-1,1)#改变shape为(len(full_df),1) 268 | yucel=insertscaler(yucel,args) 269 | yucel_data=pd.DataFrame({'pred':yucel[(args.seq_len+args.day-args.output_size):]},index=pd.date_range(a1,a2)) 270 | return yucel_data 271 | 272 | 273 | -------------------------------------------------------------------------------- /LSTM_Load_Forecasting/时间序列预测项目.md: -------------------------------------------------------------------------------- 1 | @[TOC](目录索引) 2 | # 项目说明 3 | 本项目为时间序列预测项目,主要重点在于对预测项目整体流程的梳理总结,不同框架下如何进行简单数据处理和模型搭建。因此项目中搭建的主要为一些常用模型(后续会不断修改完善)。模型包含了prophet模型、keras库的bp神经网络和lstm网络模型、pytorch 框架下的lstm相关模型。由于prophet模型和keras库的bp神经网络和lstm网络模型的构建、训练、测试整体代码量较少,将直接各自在一个脚本中完成。而pytorch框架下的模型将对代码块进行拆解。 4 | # 项目代码树结构 5 | 6 | 7 | # 项目模型介绍 8 | ## prophet模型 9 | prophet模型是facebook开源的一个时间序列预测算法,适用于具有明显内在规律的时间序列数据,如:季节性趋势明显,有事先知道的重要节假日,有历史趋势变化。此处只为单变量时间序列预测,即选择需要的某一个变量。 10 | 11 | #### 模型说明 12 | prophet模型主要包含以下可调参数: 13 | day:预测天数,默认值为30 14 | ycl:预测列名,即需要预测的变量列名 15 | 本项目中prophet模型构建了**预测**和**误差评估**两个主要方法。 16 | #### 模型运行 17 | 直接运行 prophet.py脚本,d0和d1分别为**预测**和**误差评估**两个主要方法的结果: 18 | 调用预测方法结果: 19 | ![在 这里插入图片描述](https://img-blog.csdnimg.cn/191f1ce1f99a4e9fb94775650397a427.png) 20 | 调用误差评估方法: 21 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/3efcfef791594e20b70d79f6968477f2.png) 22 | ## keras库 23 | keras库的计算依托于tensorflow框架,由于封装得较好,对于快速构建神经网络模型相较友好,本项目中主要借助keras库构建了基础的bp神经网络和lstm神经网络模型。 24 | ### bpkeras模型 25 | BP神经网络为最基础的神经网络模型,主要包括前向运算和反向传播。此处指的是keras库下的BP神经网络模型,可方便快速构建神经网路模型,模型结构默认为输入层、中间层和输出层。可实现单变量和多变量时间序列预测。 26 | #### 模型说明 27 | BP模型主要包含以下可调参数: 28 | ycls:预测开始列,正整数,非时间列后,从0开始数 29 | ycle:预测结束列,正整数,非时间列后,从1开始 30 | ycl:目标预测列差,整数。若预测结束列-预测开始列为0,为单变量预测,大于0为多变量预测 31 | cut:训练集比例(数字范围:1-10) 32 | day:预测下一个目标值将在过去查看的步骤数,默认值为30 33 | srn:输入层单元数 34 | zjn:中间层单元数 35 | 本项目中bpkeras模型构建了**预测**和**误差评估**两个主要方法。 36 | #### 模型运行 37 | 直接运行keras_model.py脚本,其中result1得到的便是bpkeras模型的预测结果和评估结果 38 | 39 | ### lstmkeras模型 40 | LSTM模型在BP神经网络的基础上主要提出了门结构,通过忘记门,输入门,输出门来控制什么样的信息将被遗忘,保存和输出。为了控制一个存储单元,我们需要一些门。其中一个门需要从单元中读出条目(相对于读取任何其他单元而言)。我们将把它称为输出门。第二个门需要决定何时将数据读入单元。我们把它称为输入门。最后,我们需要一个机制来重置单元的内容,由一个遗忘门来管理。这样设计的动机和以前一样,即能够通过一个专门的机制来决定何时记住和何时忽略进入潜伏状态的输入。 41 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/1e7f1cecf33c4f56b4ce4d7a9d21a64e.png) 42 | 首先,忽略其内部细节,单看输入与输出可以发现,每个神经元都有三个输入与三个输出。根据上文,不难想到,X t 是该时刻新加入的信息,a t − 1与C t − 1 是上文信息的表示。 43 | 其次,在该神经元内部: 44 | 黄色的部分表示“逐元素运算”,一共有两种,分别是乘运算和加运算。也就是说,两个相同维度的向量经过黄色运算框之后对应元素进行相乘或相加。 45 | 棕色部分表示“激活运算”,也有两种,分别是σ函数和tanh函数。 46 | 两条线按箭头方向融合,则是上文说的简单堆叠;一条线分成两条,则是复制为相同的两份。 47 | 假设没有三个门函数,不难发现,a t − 1与X t 堆叠之后乘以权重W然后经过tanh激活函数后输出,这与RNN的运算是一模一样的。现在,a t − 1与X t 堆叠之后的值被复制成了四份: 48 | 第一份乘以遗忘门的权重W f然后用σ激活,得到的值可以称之为“遗忘权重”。 49 | 第二份乘以输入门的权重W i 然后用σ激活,得到的值可以称之为“输入权重”。 50 | 第三份则是进行了RNN中的运算。 51 | 第四份乘以输出门的权重W o 然后用σ激活,得到的值可以称之为“输出权重”。 52 | 应该时刻注意的是,上述“某某权重”其实是一个与a t − 1 与X t 堆叠后的向量同维度的向量,向量中所有的值都在( 0 , 1 ) (0,1)(0,1)之间,而且大部分都是非常接近0或者1的。 53 | 接下来看神经元内最上方的C t − 1。与a t − 1 类似,C t − 1也携带着上文的信息。进入神经元后,C t − 1首先会与遗忘权重逐元素相乘,可以想见,由于遗忘权重中值的特点,因此与该权重相乘之后C t − 1 中绝大部分的值会变的非常接近0或者非常接近该位置上原来的值。这非常像一扇门,它会决定让哪些C t − 1 的元素通过以及通过的比例有多大。反映到实际中,就是对C t − 1中携带的信息进行选择性的遗忘(乘以非常接近0的数)和通过(乘以非常接近1的数),亦即乘以一个权重。理解了遗忘门的作用之后,其他两个门也就比较好理解了。输入门则是对输入信息进行限制,而输入信息就是RNN中的前向运算的结果。经过输入门处理后的信息就可以添加到经过遗忘门处理的上文信息中去,这就是神经元内唯一一个逐元素相加的工作。 54 | 按照一般的理解,上文的信息根据当前的输入遗忘了旧的信息,并添加了新的信息,那么整体的更新操作就已经完成,即C t 已经生成。但是C t 实际扮演的角色是携带上文的信息,因此,如果当前神经元要输出内容,那么还要有一个输出门进行限制。C t 再乘以一个tanh激活函数之后,与输出权重逐元素相乘,就得到了当前神经元的输出和a t。 55 | 可以这样认为:C t 携带的信息经过由当前时刻的输入构成的输出门限制之后,含有更多的当前时刻的信息,因此得到的a t 与C t 相比可以说是具有短期记忆的,而C t 则是具有长期记忆的。因此,将它们统称为长短记忆网络。 56 | 57 | 58 | #### 模型说明 59 | lstmkeras模型主要包含以下可调参数: 60 | ycls:预测开始列,正整数,非时间列后,从0开始 61 | ycle:预测结束列,正整数,非时间列后,从1开始 62 | ycl:目标预测列差,整数。若预测结束列-预测开始列为0,为单变量预测,大于0为多变量预测 63 | cut:训练集比例(数字范围:1-10) 64 | day:预测下一个目标值将在过去查看的步骤数,默认值为30 65 | srn:输入层单元数 66 | zjn:中间层单元数 67 | dropout:正则化,随即丢弃一些神经元,防止过拟合(数字范围在0-1) 68 | 本项目中lstmkeras模型主要构建了**预测**和**误差**两个方法。 69 | #### 模型运行 70 | 直接运行keras_model.py脚本,其中result2得到的便是lstmkeras模型的预测结果和评估结果 71 | 72 | ## pytorch框架 73 | 本项目中在pytorch框架下主要搭建了LSTM和BILSTM两个模型,并分别实现了单变量单步预测、多变量单步预测和多变量多步预测三种模式。 74 | ### BILSTM模型 75 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/d9f50ddd73a4484a80d9a6e7f020722a.png) 76 | BILSTM模型在LSTM基础上添加了反向的运算,可以理解为把输入的序列反转重新计算一遍。 77 | 78 | ### 单变量单步预测 79 | 单变量单步预测顾名思义是指对单变量的前n个值滚动预测第n+1的值。由于是单变量,在对数据进行归一化操作时,直接采取的平均化方式。 80 | #### 参数说明 81 | 在单变量单步预测中主要包含以下可调参数: 82 | epochs:模型训练迭代次数,正整数,默认为30 83 | input_size:在时间序列预测中,此处其实是指传入模型中的变量数,正整数,此处为单变量,故默认为1 84 | seq_len:在时间序列预测中,此处其实是指预测值长度,正整数,即上述所提到的n值,默认为30 85 | output_size:在时间序列预测中,此处其实是指待预测值的变量数,此处为单变量,故默认为1 86 | hidden_size:模型隐藏层,正整数,默认为32 87 | num_layers:默认为2 88 | lr:学习率,默认为0.001 89 | optimizer:模型优化器,默认为adam 90 | device:此处选择GPU 91 | weight_decay:为防止模型过拟合的权重衰减,默认为0.0001 92 | bidirectional:是否选择双向LSTM 93 | step_size:调整学习率间隔,间隔单位是epoch。等间隔调整学习率 StepLR, 将学习率调整为 lr*gamma 94 | gamma:学习率调整倍数,默认为 0.1 倍,即下降 10 倍 95 | yucel:预测列,正整数,从0开始 96 | train_split:训练集切分比例,0-1间的小数 97 | test_split:测试集开始切分的比例,0-1间的小数 98 | df:数据位置 99 | day:预测天数 100 | method:方法,输入'yuce'表示预测方法,输入’es‘表示评估方法。 101 | 102 | #### 补充说明 103 | 1、先得到已转化成Dataloader格式的训练测试验证集数据,传入前的seq中train_seq的shape为(seq_len,input_size),train_label的shape为(output_size) 104 | 2、在本项目中,由于默认了batch_fist=True,故传入lstm模型中的x的shape为(batch_size,seq_len, 105 | batch_size,seq_len,input_size) 106 | #### 模型运行 107 | 直接运行univariate_single_step.py脚本文件,输出结果根据预测方法可以输出预测结果和评估参数。如需修改参数在args.py里us_args_parser函数里修改。 108 | 109 | ### 多变量单步预测 110 | 单变量单步预测是指对多变量(包括预测列)的前n个值滚动预测 预测列第n+1的值。此处使用的数据归一方式为MinMaxScaler。需要注意是预测数据应为连续列,且最后一列为预测列。 111 | #### 参数说明 112 | 在单变量单步预测中主要包含以下可调参数: 113 | epochs:模型训练迭代次数,正整数,默认为30 114 | input_size:在时间序列预测中,此处其实是指传入模型中的变量数,正整数,此处为多变量,故默认为3 115 | seq_len:在时间序列预测中,此处其实是指预测值长度,正整数,即上述所提到的n值,默认为30 116 | output_size:在时间序列预测中,此处其实是指待预测值的变量数,此处为单变量,故默认为1 117 | hidden_size:模型隐藏层,正整数,默认为32 118 | num_layers:默认为2 119 | lr:学习率,默认为0.001 120 | optimizer:模型优化器,默认为adam 121 | device:此处选择GPU 122 | weight_decay:为防止模型过拟合的权重衰减,默认为0.0001 123 | bidirectional:是否选择双向LSTM 124 | step_size:调整学习率间隔,间隔单位是epoch。等间隔调整学习率 StepLR, 将学习率调整为 lr*gamma 125 | gamma:学习率调整倍数,默认为 0.1 倍,即下降 10 倍 126 | yucestart:预测开始列,正整数,从0开始 127 | yuceend:预测结束列,正整数,从0开始,默认结束列为需预测列 128 | train_split:训练集切分比例,0-1间的小数 129 | test_split:测试集开始切分的比例,0-1间的小数 130 | df:数据位置 131 | predict_df:待预测数据配置 132 | day:预测天数 133 | method:方法,输入'yuce'表示预测方法,输入’es‘表示评估方法。 134 | #### 补充说明 135 | 1、先得到已转化成Dataloader格式的训练测试验证集数据,传入前的seq中train_seq的shape为(seq_len,input_size),train_label的shape为(output_size) 136 | 2、在本项目中,由于默认了batch_fist=True,故传入lstm模型中的x的shape为(batch_size,seq_len, 137 | batch_size,seq_len,input_size) 138 | 3、在预测时,需要将预测结果先进行维度扩充再进行逆变化,同时注意对应关系。 139 | #### 模型运行 140 | 直接运行multivariate_single_step.py脚本文件,输出结果根据预测方法可以输出预测结果和评估参数。如需修改参数在args.py里ms_args_parser函数里修改。 141 | 142 | ### 多变量多步预测 143 | 多变量多步预测是指对多变量(包括预测列)的前n个值滚动预测 预测列第(n+1)至(n+num)的值。此处使用的数据归一方式为MinMaxScaler。需要注意是预测数据应为连续列,且最后一列为预测列。 144 | #### 参数说明 145 | 在单变量单步预测中主要包含以下可调参数: 146 | epochs:模型训练迭代次数,正整数,默认为30 147 | input_size:在时间序列预测中,此处其实是指传入模型中的变量数,正整数,此处为多变量,故默认为3 148 | seq_len:在时间序列预测中,此处其实是指预测值长度,正整数,即上述所提到的n值,默认为30 149 | output_size:在时间序列预测中,此处其实是指待预测值的变量数,此处为单变量,故默认为3 150 | hidden_size:模型隐藏层,正整数,默认为32 151 | num_layers:默认为2 152 | lr:学习率,默认为0.001 153 | optimizer:模型优化器,默认为adam 154 | device:此处选择GPU 155 | weight_decay:为防止模型过拟合的权重衰减,默认为0.0001 156 | bidirectional:是否选择双向LSTM 157 | step_size:调整学习率间隔,间隔单位是epoch。等间隔调整学习率 StepLR, 将学习率调整为 lr*gamma 158 | gamma:学习率调整倍数,默认为 0.1 倍,即下降 10 倍 159 | yucestart:预测开始列,正整数,从0开始 160 | yuceend:预测结束列,正整数,从0开始,默认结束列为需预测列 161 | train_split:训练集切分比例,0-1间的小数 162 | test_split:测试集开始切分的比例,0-1间的小数 163 | df:数据位置 164 | predict_df:待预测数据配置 165 | day:预测天数 166 | method:方法,输入'yuce'表示预测方法,输入’es‘表示评估方法。 167 | #### 补充说明 168 | 1、先得到已转化成Dataloader格式的训练测试验证集数据,传入前的seq中train_seq的shape为(seq_len,input_size),train_label的shape为(output_size) 169 | 2、在本项目中,由于默认了batch_fist=True,故传入lstm模型中的x的shape为(batch_size,seq_len, 170 | batch_size,seq_len,input_size) 171 | 3、在预测时,需要将预测结果先进行维度扩充再进行逆变化,同时注意对应关系. 172 | #### 模型运行 173 | 直接运行multivariate_multi_step.py脚本文件,输出结果根据预测方法可以输出预测结果和评估参数。如需修改参数在args.py里ms_args_parser函数里修改。 174 | 175 | ## 参考说明 176 | 本项目中的pytorch模型部分代码参考: 177 | https://github.com/ki-ljl/LSTM-Load-Forecasting 178 | 基于此,主要对train_seq相关数据处理方式进行了修改,并在此基础上增加了三种模型的未来值预测实现。 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | @[TOC](目录索引) 2 | # 项目说明 3 | 本项目为时间序列预测项目,主要重点在于对预测项目整体流程的梳理总结,不同框架下如何进行简单数据处理和模型搭建。因此项目中搭建的主要为一些常用模型(后续会不断修改完善)。模型包含了prophet模型、keras库的bp神经网络和lstm网络模型、pytorch 框架下的lstm相关模型。由于prophet模型和keras库的bp神经网络和lstm网络模型的构建、训练、测试整体代码量较少,将直接各自在一个脚本中完成。而pytorch框架下的模型将对代码块进行拆解。 4 | # 项目主要环境 5 | prophet模型环境: 6 | python=3.6 7 | 安装fbprophet 8 | keras模型环境: 9 | tensorflow=2.9 10 | keras=2.0 11 | pytorch模型环境: 12 | python=3.8 13 | torch=1.9.1 14 | cuda=11.1 15 | cudnn=8.6 16 | 17 | 18 | # 项目模型介绍 19 | ## prophet模型 20 | prophet模型是facebook开源的一个时间序列预测算法,适用于具有明显内在规律的时间序列数据,如:季节性趋势明显,有事先知道的重要节假日,有历史趋势变化。此处只为单变量时间序列预测,即选择需要的某一个变量。 21 | 22 | #### 模型说明 23 | prophet模型主要包含以下可调参数: 24 | day:预测天数,默认值为30 25 | ycl:预测列名,即需要预测的变量列名 26 | 本项目中prophet模型构建了**预测**和**误差评估**两个主要方法。 27 | #### 模型运行 28 | 直接运行 prophet.py脚本,d0和d1分别为**预测**和**误差评估**两个主要方法的结果: 29 | 调用预测方法结果: 30 | ![在 这里插入图片描述](https://img-blog.csdnimg.cn/191f1ce1f99a4e9fb94775650397a427.png) 31 | 调用误差评估方法: 32 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/3efcfef791594e20b70d79f6968477f2.png) 33 | ## keras库 34 | keras库的计算依托于tensorflow框架,由于封装得较好,对于快速构建神经网络模型相较友好,本项目中主要借助keras库构建了基础的bp神经网络和lstm神经网络模型。 35 | ### bpkeras模型 36 | BP神经网络为最基础的神经网络模型,主要包括前向运算和反向传播。此处指的是keras库下的BP神经网络模型,可方便快速构建神经网路模型,模型结构默认为输入层、中间层和输出层。可实现单变量和多变量时间序列预测。 37 | #### 模型说明 38 | BP模型主要包含以下可调参数: 39 | ycls:预测开始列,正整数,非时间列后,从0开始数 40 | ycle:预测结束列,正整数,非时间列后,从1开始 41 | ycl:目标预测列差,整数。若预测结束列-预测开始列为0,为单变量预测,大于0为多变量预测 42 | cut:训练集比例(数字范围:1-10) 43 | day:预测下一个目标值将在过去查看的步骤数,默认值为30 44 | srn:输入层单元数 45 | zjn:中间层单元数 46 | 本项目中bpkeras模型构建了**预测**和**误差评估**两个主要方法。 47 | #### 模型运行 48 | 直接运行keras_model.py脚本,其中result1得到的便是bpkeras模型的预测结果和评估结果 49 | 50 | ### lstmkeras模型 51 | LSTM模型在BP神经网络的基础上主要提出了门结构,通过忘记门,输入门,输出门来控制什么样的信息将被遗忘,保存和输出。为了控制一个存储单元,我们需要一些门。其中一个门需要从单元中读出条目(相对于读取任何其他单元而言)。我们将把它称为输出门。第二个门需要决定何时将数据读入单元。我们把它称为输入门。最后,我们需要一个机制来重置单元的内容,由一个遗忘门来管理。这样设计的动机和以前一样,即能够通过一个专门的机制来决定何时记住和何时忽略进入潜伏状态的输入。 52 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/1e7f1cecf33c4f56b4ce4d7a9d21a64e.png) 53 | 首先,忽略其内部细节,单看输入与输出可以发现,每个神经元都有三个输入与三个输出。根据上文,不难想到,X t 是该时刻新加入的信息,a t − 1与C t − 1 是上文信息的表示。 54 | 其次,在该神经元内部: 55 | 黄色的部分表示“逐元素运算”,一共有两种,分别是乘运算和加运算。也就是说,两个相同维度的向量经过黄色运算框之后对应元素进行相乘或相加。 56 | 棕色部分表示“激活运算”,也有两种,分别是σ函数和tanh函数。 57 | 两条线按箭头方向融合,则是上文说的简单堆叠;一条线分成两条,则是复制为相同的两份。 58 | 假设没有三个门函数,不难发现,a t − 1与X t 堆叠之后乘以权重W然后经过tanh激活函数后输出,这与RNN的运算是一模一样的。现在,a t − 1与X t 堆叠之后的值被复制成了四份: 59 | 第一份乘以遗忘门的权重W f然后用σ激活,得到的值可以称之为“遗忘权重”。 60 | 第二份乘以输入门的权重W i 然后用σ激活,得到的值可以称之为“输入权重”。 61 | 第三份则是进行了RNN中的运算。 62 | 第四份乘以输出门的权重W o 然后用σ激活,得到的值可以称之为“输出权重”。 63 | 应该时刻注意的是,上述“某某权重”其实是一个与a t − 1 与X t 堆叠后的向量同维度的向量,向量中所有的值都在( 0 , 1 ) (0,1)(0,1)之间,而且大部分都是非常接近0或者1的。 64 | 接下来看神经元内最上方的C t − 1。与a t − 1 类似,C t − 1也携带着上文的信息。进入神经元后,C t − 1首先会与遗忘权重逐元素相乘,可以想见,由于遗忘权重中值的特点,因此与该权重相乘之后C t − 1 中绝大部分的值会变的非常接近0或者非常接近该位置上原来的值。这非常像一扇门,它会决定让哪些C t − 1 的元素通过以及通过的比例有多大。反映到实际中,就是对C t − 1中携带的信息进行选择性的遗忘(乘以非常接近0的数)和通过(乘以非常接近1的数),亦即乘以一个权重。理解了遗忘门的作用之后,其他两个门也就比较好理解了。输入门则是对输入信息进行限制,而输入信息就是RNN中的前向运算的结果。经过输入门处理后的信息就可以添加到经过遗忘门处理的上文信息中去,这就是神经元内唯一一个逐元素相加的工作。 65 | 按照一般的理解,上文的信息根据当前的输入遗忘了旧的信息,并添加了新的信息,那么整体的更新操作就已经完成,即C t 已经生成。但是C t 实际扮演的角色是携带上文的信息,因此,如果当前神经元要输出内容,那么还要有一个输出门进行限制。C t 再乘以一个tanh激活函数之后,与输出权重逐元素相乘,就得到了当前神经元的输出和a t。 66 | 可以这样认为:C t 携带的信息经过由当前时刻的输入构成的输出门限制之后,含有更多的当前时刻的信息,因此得到的a t 与C t 相比可以说是具有短期记忆的,而C t 则是具有长期记忆的。因此,将它们统称为长短记忆网络。 67 | 68 | 69 | #### 模型说明 70 | lstmkeras模型主要包含以下可调参数: 71 | ycls:预测开始列,正整数,非时间列后,从0开始 72 | ycle:预测结束列,正整数,非时间列后,从1开始 73 | ycl:目标预测列差,整数。若预测结束列-预测开始列为0,为单变量预测,大于0为多变量预测 74 | cut:训练集比例(数字范围:1-10) 75 | day:预测下一个目标值将在过去查看的步骤数,默认值为30 76 | srn:输入层单元数 77 | zjn:中间层单元数 78 | dropout:正则化,随即丢弃一些神经元,防止过拟合(数字范围在0-1) 79 | 本项目中lstmkeras模型主要构建了**预测**和**误差**两个方法。 80 | #### 模型运行 81 | 直接运行keras_model.py脚本,其中result2得到的便是lstmkeras模型的预测结果和评估结果 82 | 83 | ## pytorch框架 84 | 本项目中在pytorch框架下主要搭建了LSTM和BILSTM两个模型,并分别实现了单变量单步预测、多变量单步预测和多变量多步预测三种模式。 85 | ### BILSTM模型 86 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/d9f50ddd73a4484a80d9a6e7f020722a.png) 87 | BILSTM模型在LSTM基础上添加了反向的运算,可以理解为把输入的序列反转重新计算一遍。 88 | 89 | ### 单变量单步预测 90 | 单变量单步预测顾名思义是指对单变量的前n个值滚动预测第n+1的值。由于是单变量,在对数据进行归一化操作时,直接采取的平均化方式。 91 | #### 参数说明 92 | 在单变量单步预测中主要包含以下可调参数: 93 | epochs:模型训练迭代次数,正整数,默认为30 94 | input_size:在时间序列预测中,此处其实是指传入模型中的变量数,正整数,此处为单变量,故默认为1 95 | seq_len:在时间序列预测中,此处其实是指预测值长度,正整数,即上述所提到的n值,默认为30 96 | output_size:在时间序列预测中,此处其实是指待预测值的变量数,此处为单变量,故默认为1 97 | hidden_size:模型隐藏层,正整数,默认为32 98 | num_layers:默认为2 99 | lr:学习率,默认为0.001 100 | optimizer:模型优化器,默认为adam 101 | device:此处选择GPU 102 | weight_decay:为防止模型过拟合的权重衰减,默认为0.0001 103 | bidirectional:是否选择双向LSTM 104 | step_size:调整学习率间隔,间隔单位是epoch。等间隔调整学习率 StepLR, 将学习率调整为 lr*gamma 105 | gamma:学习率调整倍数,默认为 0.1 倍,即下降 10 倍 106 | yucel:预测列,正整数,从0开始 107 | train_split:训练集切分比例,0-1间的小数 108 | test_split:测试集开始切分的比例,0-1间的小数 109 | df:数据位置 110 | day:预测天数 111 | method:方法,输入'yuce'表示预测方法,输入’es‘表示评估方法。 112 | 113 | #### 补充说明 114 | 1、先得到已转化成Dataloader格式的训练测试验证集数据,传入前的seq中train_seq的shape为(seq_len,input_size),train_label的shape为(output_size) 115 | 2、在本项目中,由于默认了batch_fist=True,故传入lstm模型中的x的shape为(batch_size,seq_len,input_size) 116 | #### 模型运行 117 | 直接运行univariate_single_step.py脚本文件,输出结果根据预测方法可以输出预测结果和评估参数。如需修改参数在args.py里us_args_parser函数里修改。 118 | 119 | ### 多变量单步预测 120 | 单变量单步预测是指对多变量(包括预测列)的前n个值滚动预测 预测列第n+1的值。此处使用的数据归一方式为MinMaxScaler。需要注意是预测数据应为连续列,且最后一列为预测列。 121 | #### 参数说明 122 | 在单变量单步预测中主要包含以下可调参数: 123 | epochs:模型训练迭代次数,正整数,默认为30 124 | input_size:在时间序列预测中,此处其实是指传入模型中的变量数,正整数,此处为多变量,故默认为3 125 | seq_len:在时间序列预测中,此处其实是指预测值长度,正整数,即上述所提到的n值,默认为30 126 | output_size:在时间序列预测中,此处其实是指待预测值的变量数,此处为单变量,故默认为1 127 | hidden_size:模型隐藏层,正整数,默认为32 128 | num_layers:默认为2 129 | lr:学习率,默认为0.001 130 | optimizer:模型优化器,默认为adam 131 | device:此处选择GPU 132 | weight_decay:为防止模型过拟合的权重衰减,默认为0.0001 133 | bidirectional:是否选择双向LSTM 134 | step_size:调整学习率间隔,间隔单位是epoch。等间隔调整学习率 StepLR, 将学习率调整为 lr*gamma 135 | gamma:学习率调整倍数,默认为 0.1 倍,即下降 10 倍 136 | yucestart:预测开始列,正整数,从0开始 137 | yuceend:预测结束列,正整数,从0开始,默认结束列为需预测列 138 | train_split:训练集切分比例,0-1间的小数 139 | test_split:测试集开始切分的比例,0-1间的小数 140 | df:数据位置 141 | predict_df:待预测数据配置 142 | day:预测天数 143 | method:方法,输入'yuce'表示预测方法,输入’es‘表示评估方法。 144 | #### 补充说明 145 | 1、先得到已转化成Dataloader格式的训练测试验证集数据,传入前的seq中train_seq的shape为(seq_len,input_size),train_label的shape为(output_size) 146 | 2、在本项目中,由于默认了batch_fist=True,故传入lstm模型中的x的shape为(batch_size,seq_len, 147 | batch_size,seq_len,input_size) 148 | 3、在预测时,需要将预测结果先进行维度扩充再进行逆变化,同时注意对应关系。 149 | #### 模型运行 150 | 直接运行multivariate_single_step.py脚本文件,输出结果根据预测方法可以输出预测结果和评估参数。如需修改参数在args.py里ms_args_parser函数里修改。 151 | 152 | ### 多变量多步预测 153 | 多变量多步预测是指对多变量(包括预测列)的前n个值滚动预测 预测列第(n+1)至(n+num)的值。此处使用的数据归一方式为MinMaxScaler。需要注意是预测数据应为连续列,且最后一列为预测列。 154 | #### 参数说明 155 | 在单变量单步预测中主要包含以下可调参数: 156 | epochs:模型训练迭代次数,正整数,默认为30 157 | input_size:在时间序列预测中,此处其实是指传入模型中的变量数,正整数,此处为多变量,故默认为3 158 | seq_len:在时间序列预测中,此处其实是指预测值长度,正整数,即上述所提到的n值,默认为30 159 | output_size:在时间序列预测中,此处其实是指待预测值的变量数,此处为单变量,故默认为3 160 | hidden_size:模型隐藏层,正整数,默认为32 161 | num_layers:默认为2 162 | lr:学习率,默认为0.001 163 | optimizer:模型优化器,默认为adam 164 | device:此处选择GPU 165 | weight_decay:为防止模型过拟合的权重衰减,默认为0.0001 166 | bidirectional:是否选择双向LSTM 167 | step_size:调整学习率间隔,间隔单位是epoch。等间隔调整学习率 StepLR, 将学习率调整为 lr*gamma 168 | gamma:学习率调整倍数,默认为 0.1 倍,即下降 10 倍 169 | yucestart:预测开始列,正整数,从0开始 170 | yuceend:预测结束列,正整数,从0开始,默认结束列为需预测列 171 | train_split:训练集切分比例,0-1间的小数 172 | test_split:测试集开始切分的比例,0-1间的小数 173 | df:数据位置 174 | predict_df:待预测数据配置 175 | day:预测天数 176 | method:方法,输入'yuce'表示预测方法,输入’es‘表示评估方法。 177 | #### 补充说明 178 | 1、先得到已转化成Dataloader格式的训练测试验证集数据,传入前的seq中train_seq的shape为(seq_len,input_size),train_label的shape为(output_size) 179 | 2、在本项目中,由于默认了batch_fist=True,故传入lstm模型中的x的shape为(batch_size,seq_len, 180 | batch_size,seq_len,input_size) 181 | 3、在预测时,需要将预测结果先进行维度扩充再进行逆变化,同时注意对应关系. 182 | #### 模型运行 183 | 直接运行multivariate_multi_step.py脚本文件,输出结果根据预测方法可以输出预测结果和评估参数。如需修改参数在args.py里ms_args_parser函数里修改。 184 | 185 | ## 参考说明 186 | 本项目中的pytorch模型部分代码参考: 187 | https://github.com/ki-ljl/LSTM-Load-Forecasting 188 | 基于此,主要对train_seq相关数据处理方式进行了修改,并在此基础上增加了三种模型的未来值预测实现。 189 | -------------------------------------------------------------------------------- /fbprophet.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 2 | """ 3 | author:Liao Xuechun 4 | date:2022-07-12 5 | describe:prophet time series forecasting 6 | """ 7 | import warnings 8 | warnings.filterwarnings("ignore") 9 | import pandas as pd 10 | import numpy as np 11 | from fbprophet import Prophet 12 | from pandas import read_excel 13 | import holidays 14 | import datetime 15 | from sklearn.metrics import mean_absolute_error 16 | from sklearn.metrics import mean_squared_error 17 | from sklearn.metrics import r2_score 18 | 19 | data=pd.read_excel('广东地区企业报价.xlsx') 20 | data.columns=['date','ws','zb'] 21 | day=30 22 | ycl='ws' 23 | #数据输入 24 | class fbpredict: 25 | def __init__(self,day,ycl,datapath): 26 | self.day=day#预测天数 27 | self.ycl=ycl#预测列 28 | self.datapath=pd.DataFrame(datapath)#数据路径 29 | def fbdata(self): 30 | data=self.datapath 31 | data=data[['date',self.ycl]] 32 | data.columns=['ds','y'] 33 | data['y']=data['y'].apply(lambda x:float(x)) 34 | data['ds']=pd.to_datetime(data['ds']) 35 | return data 36 | def fit(self,fbdata): 37 | m = Prophet(yearly_seasonality=True, weekly_seasonality=True, daily_seasonality=True,changepoints=None) 38 | m.add_country_holidays(country_name="CN") 39 | mfit=m.fit(fbpredict.fbdata(self)) 40 | return m 41 | def predict(self,fit,fbdata): 42 | future=fbpredict.fit(self,fbpredict.fbdata(self)).make_future_dataframe(periods=int(self.day)) 43 | forecast = fbpredict.fit(self,fbpredict.fbdata(self)).predict(future) 44 | forecast_jg=pd.merge(forecast,fbpredict.fbdata(self),on='ds',how='left')#模型评估#模型保存 45 | forecast_jg=forecast_jg.set_index('ds') 46 | forecast_jg=forecast_jg.astype('float') 47 | forecast_jg['e']=forecast_jg['y']-forecast_jg['yhat'] 48 | forecast_jg_=forecast_jg[['y','yhat']] 49 | forecast_jg_['yhat']=forecast_jg_['yhat'].apply(lambda x:round(x,2)) 50 | train_len=len(fbpredict.fbdata(self)['y']) 51 | rmse = np.sqrt(np.mean(np.power(fbpredict.fbdata(self)["y"] - forecast["yhat"].head(train_len),2))) 52 | mae=mean_absolute_error(fbpredict.fbdata(self)["y"],forecast["yhat"]).head(train_len) 53 | mse=mean_squared_error(fbpredict.fbdata(self)["y"],forecast["yhat"]).head(train_len) 54 | r2=r2_score(fbpredict.fbdata(self)["y"],forecast["yhat"]).head(train_len) 55 | model_estimate=pd.DataFrame({'prophet':[rmse,mae,mse,r2]},index=['rmse','mae','mse','r2']) 56 | return forecast_jg_,model_estimate 57 | d=fbpredict(day,ycl,data)#初始化 58 | ddata=d.fbdata() 59 | d0=d.predict(d.fit(ddata),ddata) 60 | result=d0 -------------------------------------------------------------------------------- /keras_model.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 2 | """ 3 | author:Liao Xuechun 4 | date:2022-07-13 5 | describe:keras_model time series forecasting 6 | """ 7 | import numpy as np 8 | import pandas as pd 9 | from matplotlib import pyplot as plt 10 | from keras.models import Sequential 11 | from keras.layers import LSTM 12 | from keras.layers import Dense, Dropout 13 | from sklearn.preprocessing import MinMaxScaler 14 | from keras.wrappers.scikit_learn import KerasRegressor 15 | from sklearn.model_selection import GridSearchCV 16 | from sklearn.metrics import mean_absolute_error 17 | from sklearn.metrics import mean_squared_error 18 | from sklearn.metrics import r2_score 19 | from sklearn.metrics import mean_absolute_percentage_error 20 | from keras.models import Sequential 21 | from keras.layers.core import Dense, Activation 22 | from keras.optimizers import Adam 23 | from datetime import timedelta 24 | import datetime 25 | import openpyxl 26 | 27 | data=pd.read_excel('广东地区企业报价.xlsx') 28 | data.columns=['date','ws','zb'] 29 | ycls = 1 30 | ycle = 2 31 | ycl = 0 32 | cut = 9 33 | day = 30 34 | srn = 16 35 | zjn =6 36 | dropout=0.2 37 | #dataset 38 | class keras: 39 | def __init__(self,ycls,ycle,ycl,cut,day,datapath): 40 | self.ycls=int(ycls)#预测开始列 41 | self.ycle=int(ycle)#预测结束列 42 | self.ycl=int(ycl)#目标预测列差 43 | self.cut=int(cut)#训练集比例划分,取1-10之间的整数 44 | self.day=int(day)#预测下一个目标值将在过去查看的步骤数 45 | self.datapath=pd.DataFrame(datapath) 46 | def kerasdata(self): 47 | global data 48 | data=self.datapath 49 | data['date']=pd.to_datetime(data['date']) 50 | data=data.set_index('date') 51 | global data_ 52 | data_=pd.DataFrame(data.iloc[:,int(self.ycls):int(self.ycle)]) 53 | data_=data_.astype('float') 54 | global dataset 55 | dataset = data_.values#单变量必须要pd.Dataframe后变成二维 56 | global cut_ 57 | cut_=len(dataset)*int(self.cut)//10 58 | train,valid=dataset[:cut_],dataset[cut_:] 59 | global scaler 60 | scaler = MinMaxScaler(feature_range=(0, 1)) 61 | global scaled_data,scaled_train,scaled_valid 62 | scaled_data,scaled_train,scaled_valid= scaler.fit_transform(dataset),scaler.fit_transform(train),scaler.fit_transform(valid) 63 | return scaled_data,scaled_train,scaled_valid 64 | def creatXY(self,kerasdata): 65 | traindataX,traindataY,testdataX,testdataY,datadataX,datadataY=[],[],[],[],[],[] 66 | for i in range(self.day,len(keras.kerasdata(self)[1])): 67 | traindataX.append(keras.kerasdata(self)[1][i-self.day:i,0:keras.kerasdata(self)[1].shape[1]]) 68 | traindataY.append(keras.kerasdata(self)[1][i,int(self.ycl)]) 69 | trainX,trainY=np.array(traindataX),np.array(traindataY) 70 | for i in range(self.day,len(keras.kerasdata(self)[2])): 71 | testdataX.append(keras.kerasdata(self)[2][i-self.day:i,0:keras.kerasdata(self)[2].shape[1]]) 72 | testdataY.append(keras.kerasdata(self)[2][i,int(self.ycl)]) 73 | testX,testY=np.array(testdataX),np.array(testdataY) 74 | for i in range(self.day,len(keras.kerasdata(self)[0])): 75 | datadataX.append(keras.kerasdata(self)[0][i-self.day:i,0:keras.kerasdata(self)[0].shape[1]]) 76 | datadataY.append(keras.kerasdata(self)[0][i,int(self.ycl)]) 77 | dataX,dataY=np.array(datadataX),np.array(datadataY) 78 | trainX,trainY,testX,testY,dataX,dataY=trainX.reshape(len(keras.kerasdata(self)[1])-int(self.day),int(self.day)),trainY.reshape(len(keras.kerasdata(self)[1])-int(self.day),1),testX.reshape(len(keras.kerasdata(self)[2])-int(self.day),int(self.day)),testY.reshape(len(keras.kerasdata(self)[2])-int(self.day),1),dataX.reshape(len(keras.kerasdata(self)[0])-int(self.day),int(self.day)),dataY.reshape(len(keras.kerasdata(self)[0])-int(self.day),1) 79 | return trainX,trainY,testX,testY,dataX,dataY 80 | c=keras(ycls,ycle,ycl,cut,day,data) 81 | c1=c.kerasdata() 82 | c2=c.creatXY(c1) 83 | #net 84 | def build_model_bp(optimizer): 85 | grid_model = Sequential() 86 | #第一层 87 | grid_model.add(Dense(int(srn),input_dim=int(day),kernel_initializer='uniform')) #输入层,Dense表示BP层 88 | grid_model.add(Activation('relu')) #添加激活函数 89 | grid_model.add(Dense(int(zjn),kernel_initializer='uniform')) #中间层 90 | grid_model.add(Activation('sigmoid')) #添加激活函数 91 | grid_model.add(Dense(1)) #输出层 92 | grid_model.compile(loss='mean_squared_error', optimizer=optimizer) #编译模型 93 | return grid_model 94 | grid_model_bp = KerasRegressor(build_fn=build_model_bp,verbose=1) 95 | parameters_bp = {'batch_size':[16,20],'epochs':[8,10],'optimizer':['adam','Adadelta'] } 96 | grid_search_bp = GridSearchCV(estimator = grid_model_bp, 97 | param_grid = parameters_bp) 98 | grid_search_bp = grid_search_bp.fit(c2[0],c2[1],validation_data=(c2[2],c2[3]))#防止过拟合 99 | my_model_bp=grid_search_bp.best_estimator_.model 100 | def build_model_lstm(optimizer): 101 | grid_model = Sequential() 102 | grid_model.add(LSTM(int(srn),return_sequences=True,input_shape=(int(day),int(ycle)-int(ycls))))#输入层 103 | grid_model.add(LSTM(int(zjn)))#中间层 104 | grid_model.add(Dropout(float(dropout))) 105 | grid_model.add(Dense(1)) 106 | grid_model.compile(loss = 'mse',optimizer = optimizer) 107 | return grid_model 108 | grid_model_lstm = KerasRegressor(build_fn=build_model_lstm,verbose=1) 109 | parameters_lstm = {'batch_size':[16,20],'epochs':[8,10],'optimizer':['adam','Adadelta'] } 110 | grid_search_lstm = GridSearchCV(estimator = grid_model_lstm, 111 | param_grid = parameters_lstm, 112 | cv = 2) 113 | grid_search_lstm = grid_search_lstm.fit(c2[0],c2[1],validation_data=(c2[2],c2[3]))#防止过拟合 114 | my_model_lstm=grid_search_lstm.best_estimator_.model 115 | #predict and estimate 116 | def bpkeras_pe(data_,model,model_name,model_names): 117 | prediction_=model.predict(c2[2])#test 118 | pred=scaler.inverse_transform(prediction_)[:,int(ycl)] 119 | original=scaler.inverse_transform(c2[3]) 120 | df__days_past=data_.iloc[-int(day):,:] 121 | a1 = pd.to_datetime(data_.index[-1])+timedelta(days=1) 122 | a2=a1+timedelta(days=int(day)-1) 123 | df__days_future=pd.DataFrame(np.random.randn(int(day),int(ycle)-int(ycls)),index=pd.date_range(a1,a2),columns=data_.columns) 124 | df__days_future.iloc[:,int(ycl)]=0 125 | old_scaled_array=scaler.transform(df__days_past) 126 | new_scaled_array=scaler.transform(df__days_future)#缩放前变成0 127 | new_scaled_df=pd.DataFrame(new_scaled_array) 128 | new_scaled_df.iloc[:,int(ycl)]=np.nan 129 | full_df=pd.concat([pd.DataFrame(old_scaled_array),new_scaled_df]).reset_index().drop(["index"],axis=1)#拼在一起 130 | full_df_scaled_array=full_df.values 131 | all_data=[] 132 | time_step=int(day) 133 | for i in range(time_step,len(full_df_scaled_array)): 134 | data_x=[] 135 | data_x.append(full_df_scaled_array[i-time_step:i,0:full_df_scaled_array.shape[1]]) 136 | data_x0=np.array(data_x).reshape(1,int(day)) 137 | prediction=model.predict(data_x0) 138 | all_data.append(prediction) 139 | full_df.iloc[i,0]=prediction 140 | new_array=np.array(all_data)#一维 141 | new_array=new_array.reshape(-1,1)#变成两维 142 | y_pred_future__days = scaler.inverse_transform(new_array)[:,0]#变回去 143 | y_pred_future=pd.DataFrame(y_pred_future__days,index=pd.date_range(a1,a2),columns=[model_name]) 144 | #整理成预测和未来的 145 | y_pred=pd.DataFrame(original,pred).reset_index() 146 | y_pred.index=data.index[cut_+(int(day)):] 147 | y_pred=y_pred.astype('float') 148 | y_pred.columns=[model_name,'original'] 149 | y_pred=y_pred.append(y_pred_future,sort=True) 150 | y_pred=y_pred.apply(lambda x:round(x,2)) 151 | rmse = np.sqrt(np.mean(np.power(y_pred["original"][:-int(day)] - y_pred[model_name][:-int(day)],2))) 152 | mae=mean_absolute_error(y_pred["original"][:-int(day)],y_pred[model_name][:-int(day)]) 153 | mse=mean_squared_error(y_pred["original"][:-int(day)],y_pred[model_name][:-int(day)]) 154 | r2=r2_score(y_pred["original"][:-int(day)],y_pred[model_name][:-int(day)]) 155 | mape=mean_absolute_percentage_error(y_pred["original"][:-int(day)],y_pred[model_name][:-int(day)]) 156 | model_estimate=pd.DataFrame({model_names:[rmse,mae,mse,r2,,mape]},index=['rmse','mae','mse','r2','mape']) 157 | return y_pred,model_estimate 158 | result1=bpkeras_pe(data_,my_model_bp,'bp_pred','kerasbp') 159 | 160 | def lstmkeras_pe(data_,model,model_name,model_names): 161 | prediction=model.predict(c2[2]) 162 | prediction_copies_array = np.repeat(prediction,dataset.shape[1], axis=-1) 163 | pred=scaler.inverse_transform(np.reshape(prediction_copies_array,(len(prediction),dataset.shape[1])))[:,int(ycl)]#目标 164 | original_copies_array = np.repeat(c2[3],dataset.shape[1], axis=-1) 165 | original=scaler.inverse_transform(np.reshape(original_copies_array,(len(c2[3]),dataset.shape[1])))[:,int(ycl)]#第一列 166 | df__days_past=data_.iloc[-int(day):,:] 167 | a1 = data_.index[-1]+timedelta(days=1) 168 | a2=a1+timedelta(days=int(day)-1) 169 | df__days_future=pd.DataFrame(np.random.randn(int(day),int(ycle)-int(ycls)),index=pd.date_range(a1,a2),columns=data_.columns) 170 | df__days_future.iloc[:,int(ycl)]=0 171 | old_scaled_array=scaler.transform(df__days_past) 172 | new_scaled_array=scaler.transform(df__days_future)#缩放前变成0 173 | new_scaled_df=pd.DataFrame(new_scaled_array) 174 | new_scaled_df.iloc[:,0]=np.nan 175 | full_df=pd.concat([pd.DataFrame(old_scaled_array),new_scaled_df]).reset_index().drop(["index"],axis=1)#拼在一起 176 | full_df_scaled_array=full_df.values 177 | all_data=[] 178 | time_step=int(day) 179 | for i in range(time_step,len(full_df_scaled_array)): 180 | data_x=[] 181 | data_x.append(full_df_scaled_array[i-time_step:i,0:full_df_scaled_array.shape[1]]) 182 | data_x=np.array(data_x) 183 | prediction=model.predict(data_x) 184 | all_data.append(prediction) 185 | full_df.iloc[i,0]=prediction 186 | new_array=np.array(all_data)#一维 187 | new_array=new_array.reshape(-1,1)#变成两维 188 | prediction_copies_array = np.repeat(new_array,dataset.shape[1], axis=-1) 189 | y_pred_future__days = scaler.inverse_transform(np.reshape(prediction_copies_array,(len(new_array),dataset.shape[1])))[:,int(ycl)]#变回去 190 | y_pred_future=pd.DataFrame(y_pred_future__days,index=pd.date_range(a1,a2),columns=[model_name]) 191 | #整理成预测和未来的 192 | y_pred=pd.DataFrame(original,pred).reset_index() 193 | y_pred.index=data.index[cut_+(int(day)):] 194 | y_pred.columns=[model_name,'original'] 195 | y_pred=y_pred.append(y_pred_future,sort=True) 196 | result=y_pred 197 | y_pred=y_pred.apply(lambda x:round(x,2)) 198 | rmse = np.sqrt(np.mean(np.power(y_pred["original"][:-int(day)] - y_pred[model_name][:-int(day)],2))) 199 | mae=mean_absolute_error(y_pred["original"][:-int(day)],y_pred[model_name][:-int(day)]) 200 | mse=mean_squared_error(y_pred["original"][:-int(day)],y_pred[model_name][:-int(day)]) 201 | r2=r2_score(y_pred["original"][:-int(day)],y_pred[model_name][:-int(day)]) 202 | mape=mean_absolute_percentage_error(y_pred["original"][:-int(day)],y_pred[model_name][:-int(day)]) 203 | model_estimate=pd.DataFrame({model_names:[rmse,mae,mse,r2,mape]},index=['rmse','mae','mse','r2','mape']) 204 | return y_pred,model_estimate 205 | result2=lstmkeras_pe(data_,my_model_lstm,'lstm_pred','kreaslstm') -------------------------------------------------------------------------------- /tree.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/tree.txt -------------------------------------------------------------------------------- /广东地区企业报价.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loveseola/time-series-forecasting/f6c19a34a7027f9a7041258efa034508fc678e3d/广东地区企业报价.xlsx --------------------------------------------------------------------------------