├── 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 |
10 |
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 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LSTM_Load_Forecasting/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
5 |
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 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
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 |
362 |
363 | 1646136315444
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
434 |
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 | 
20 | 调用误差评估方法:
21 | 
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 | 
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 | 
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 | 
31 | 调用误差评估方法:
32 | 
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 | 
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 | 
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
--------------------------------------------------------------------------------