在线时间 514 小时 最后登录 2023-12-1 注册时间 2018-7-17 听众数 15 收听数 0 能力 0 分 体力 40255 点 威望 0 点 阅读权限 255 积分 12788 相册 0 日志 0 记录 0 帖子 1419 主题 1178 精华 0 分享 0 好友 15
TA的每日心情 开心 2023-7-31 10:17
签到天数: 198 天
[LV.7]常住居民III
自我介绍 数学中国浅夏
使用LSTM预测时间序列数据
' f8 i% G' y1 z9 L/ w& F' x
' D- M; e& Z+ Y: E% v" F1 B + M0 O) P) x3 ~7 G7 f: s% n
文章目录 2 \# Z6 k* ^$ O1 S8 f3 e
背景 6 N+ \! j" T$ }% R; ~
结论 ) L3 \- @- t- O+ z* i( ^
代码 ; U' G( w1 v }; L
实验结果
: G2 G: r3 k- ]5 B; I- d0 ~ RNN和DNN的区别
, l- O( i# X7 D& _, p0 H RNN和LSTM的区别
$ D T+ g& T+ x: J) m+ z 背景 9 R1 X* o2 h5 x# I: t
复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验 ' |2 Q- ], s9 ]
熟悉用LSTM模型训练 5 B n, ^+ c3 ]) z/ I) ?
验证将时序数据 转化为分类问题后,预测是否有效果
8 W2 ~0 N9 u" H. g 对比SimpleRNN与LSTM模型 哪个效果最好?
( Q$ h$ `) e4 I2 g% O& V) V 验证LSTM相比于Dense()模型 是否有提升?
6 m' [1 D: C# p6 h 对比使用前3天的数据 和使用前1天的数据 哪个效果最好? # K. G3 U" ?7 \( J7 p! a
结论 6 p8 T) b, k. Y5 L
使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好
4 z$ e; Q9 l( i) P4 Q 使用LSTM的效果优于SimpleRNN - U- T4 d* J& ~ n7 n" [2 O
代码 & u5 z/ O& a6 G5 `* ~& N; Q
from pandas import read_csv
* g6 x0 D) _# T$ O. {" } from datetime import datetime
% W3 O) E3 |. {( u9 K! i' b8 r import pandas as pd 5 V1 I" Y4 @/ Z, ?
from pandas import DataFrame r, Z1 b0 k% J% i# {. R
from sklearn.preprocessing import LabelEncoder,MinMaxScaler * n- w" o+ J' Y& F1 y) s
from sklearn.metrics import mean_squared_error 7 R$ H! X$ A5 n6 L% ]% E+ M
from keras.models import Sequential ! U! i6 _( v2 M! R- e$ Q: w" F7 _- a) [
from keras.layers import Dense, Dropout ; U! g6 U/ V; n5 v( e! X
from keras.layers import LSTM
1 l) C% L. B. T) T, d from keras.layers.recurrent import SimpleRNN
! N/ X) ]& D- C5 w' b) p from numpy import concatenate
8 g4 c, U" i5 }; D2 D+ z from math import sqrt
: K- t1 N8 _( ~ Z( e- w! g
, A0 o i) x- `$ z
, p p* ^$ x4 S9 f2 I! p
$ d+ u2 v/ E! [' I4 Q
/ m# c0 f( I$ [' B! Z # load data
; z$ \) m* ?+ i: ^0 N+ u, F def parse(x):
$ R a1 W. a7 j1 V( Y5 Q return datetime.strptime(x, '%Y %m %d %H') 3 ]: D( k8 F- h6 C4 Z
( L0 s5 K4 q q2 n [$ a
def read_raw():
1 {2 T K# `- p, i! L0 P( ? dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
* p3 ~; y a3 V3 Y" j2 W; L. w dataset.drop('No', axis=1, inplace=True)
& U; Q/ k. c1 R/ Z # manually specify column names
, E8 Z Y0 k) ^ O dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain'] ' k* Z" U9 G0 \' R j3 o3 }
dataset.index.name = 'date'
/ o8 M" A0 b/ L2 l. H, f # mark all NA values with 0
% _8 x. o1 E" ]$ q3 D$ M; c( [# K dataset['pollution'].fillna(0, inplace=True) " j8 P" ]3 f" j
# drop the first 24 hours 1 |: b! B+ `# u
dataset = dataset[24:] % E( j: M) b0 j' e& \: [: R
# summarize first 5 rows
. X, H; e! c6 ?( y! j print(dataset.head(5)) + a8 M; _, e8 p! H& C, @0 _
# save to file
- B! }! }$ O$ ~3 v6 i) N dataset.to_csv('pollution.csv') d+ ?6 O" s/ o3 V7 j; y
: {6 W, G- [9 J* b0 O( e# x
* ^: J* t$ T. C& J $ O# m8 Z3 n; k/ `
% [" S& Z! f- P2 x # convert series to supervised learning 9 |$ J% B) i/ D. c' Z' N
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True): : s. T0 [* |$ D9 y
n_vars = 1 if type(data) is list else data.shape[1]
/ z1 ?6 }7 A2 z/ W J( i& g df = DataFrame(data)
2 F& G& S, G7 | cols, names = list(), list() ( g* N0 |( j9 P h( K4 e
# input sequence (t-n, ... t-1)
, Z$ O; i" Z# w# t for i in range(n_in, 0, -1):
8 [5 O" i1 | P' z2 O% ^/ J7 W, N cols.append(df.shift(i))
( m/ @! S# i, M1 w( `/ n5 G names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
' W7 h m; z3 Y6 k # forecast sequence (t, t+1, ... t+n) 3 s( w) e- h9 g" @' b
for i in range(0, n_out):
0 q3 x5 y5 s' |8 W9 U cols.append(df.shift(-i))
% m3 B: c9 N9 S5 x. ?1 M: h! F2 }/ f if i == 0: % y. C: r' ]3 D
names += [('var%d(t)' % (j+1)) for j in range(n_vars)] - E1 p$ p' R8 f' Z
else: 5 E' V, s4 g2 f4 J6 Q- P0 [" U
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
9 Y) a S9 o! E3 L* b # put it all together
( a6 H0 z/ @) B agg = pd.concat(cols, axis=1) 9 P6 o8 l) u, G$ ?6 M! M+ H
agg.columns = names / n! A" ]0 i% M. V( ?% H" @% g
# drop rows with NaN values " o; N! T4 Z+ D1 O Z
if dropnan: 2 H" G: d* \: C7 t: h2 O
agg.dropna(inplace=True)
0 K7 f% `. p7 w- Q: u0 `0 w return agg 6 H$ h6 D' q) ?: h5 O+ F1 A
; d9 i: g: I! ~3 t; s # load dataset
$ i% ^; E* d% s ]6 o! n3 e2 F dataset = read_csv('pollution.csv', header=0, index_col=0) 3 P7 k# ^; z% u. o* a
values = dataset.values + P6 L" \. d4 @9 n( r& v
$ O1 i7 q2 [ D' p9 m) I! X. L
/ W1 R! l7 ~& C # integer encode direction : `5 x7 }, R H& q! u! y
encoder = LabelEncoder()
6 R8 t/ \ n! N& f# j' k print(values[:,4]) " b" k: ]6 y2 ]
values[:,4] = encoder.fit_transform(values[:,4]) k3 Z+ T! j. w% \6 X
# ensure all data is float
- Y4 a: j4 T. J) v values = values.astype('float32') 2 T- N- W! g" R
# normalize features
" d% d9 `1 f2 E g scaler = MinMaxScaler(feature_range=(0, 1)) / C' T+ {4 P4 n. @0 J
scaled = scaler.fit_transform(values)
7 x7 M3 ?7 r, w' ? # frame as supervised learning 8 z! }2 O- u/ b% m3 C$ W+ M
reframed = series_to_supervised(scaled, 1, 1)
( v; b" |+ J% t; \5 N# U7 O #reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
6 i3 E. @, v" j$ w; j2 ^ print("columns:", reframed.columns) / h% V9 A- v! C5 I
# drop columns we don't want to predict
' ], K5 f( H% D- A2 _ reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据 . C, J/ p- @ F% F
#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据 ! [. _# t/ H2 ^2 |' ~& P: L- h
print(reframed.head()) ! W' h; j' q. F7 _4 ?* [+ @& Y) i* a
print("new columns:", reframed.columns)
( W$ q4 [9 ?, J2 b # split into train and test sets ]3 M5 M0 B( c4 M
values = reframed.values 7 r1 t$ U, ^$ d" H7 g& N7 x
n_train_hours = 365 * 24
, Q( ~2 x; n4 [1 J( a5 C train = values[:n_train_hours, :]
+ ^: y0 _8 L6 U test = values[n_train_hours:, :] ) X2 P0 u4 b! ?+ a/ J) O
# split into input and outputs ! ? V% N) d' Z7 S
train_X, train_y = train[:, :-1], train[:, -1] 8 T, n# g l* I/ x' W5 R. ^3 |( \) d5 {
test_X, test_y = test[:, :-1], test[:, -1] 4 ~0 l' g* U! Y! S6 g+ ]
# reshape input to be 3D [samples, timesteps, features]
" Y' B' m# t2 ]: ]: ~ #使用Dense()模型时不用变换
' G( b/ X6 x; _) R, r9 c5 F train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1])) - n$ r- I& ~$ y! G
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1])) 1 A3 g8 V. Z& n1 p8 N
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape) ! a7 a/ L" J7 K' y
# design network 0 L1 c1 F( a5 O* G! X3 w5 f/ N+ i
model = Sequential() ' i2 M' V' ^9 D' F3 v6 y& N" v
#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
9 b/ V$ C+ X4 Y% s# v #model.add(Dense(50, activation='relu', input_dim = 8))
( _: H) q8 f8 |, I+ z model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2]))) " {5 h4 v! T- e' a7 U% A$ U
model.add(Dense(1)) ( w0 f' C# e4 |/ ?! F6 k) s
model.compile(loss='mae', optimizer='adam')
" c' R) x2 N% X3 P5 O r/ } # fit network ( Y7 z% a, q$ x# F% z* R
history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False) * @8 V5 I1 K) H Q6 n+ Y2 J
# make a prediction
3 U2 }; ]" J% i9 o yhat = model.predict(test_X)
9 L4 ]; v5 ?4 h/ D9 h5 n" Y7 m print("yhat shape:", yhat.shape) ( w. G" y" o1 a: C) L* q
'''
1 e9 J+ R1 b6 b/ Z7 k6 G- @3 p& e3 v 计算在测试集上的均方差 7 s) B3 e# E) G; l7 u
test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
, Q# }0 H( b/ z* w+ H. v print("test_X shape:", test_X.shape) 9 h2 t, k1 U6 h- {9 p# E
, f! L/ L. {7 R
9 `0 W" H+ o& G. f
# invert scaling for forecast / z8 o: J8 {8 C* H* s" Z! |
inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1) 6 S( y5 X) D- h! V% T; _* \
inv_yhat = scaler.inverse_transform(inv_yhat)
5 i# G7 n4 T( L, U' K inv_yhat = inv_yhat[:,0]
& z2 F! h: d% n3 `* l0 q # invert scaling for actual 0 L) {7 {' T; W: p
test_y = test_y.reshape((len(test_y), 1)) 9 w; I% A# _% `% _5 O! { ^: l
inv_y = concatenate((test_y, test_X[:, 1:]), axis=1) @! g& `8 O D) }3 [, t! i ~& f
print("inv_y:", inv_y[:10]) ; h6 c" [% @$ [! h3 X1 Z
print("inv_y shape:", inv_y.shape) ( n. O; \4 X7 |
( z8 z$ I5 ?1 X5 T$ o3 C
0 F# I/ |4 J) P; W$ V- S. I7 R inv_y = scaler.inverse_transform(inv_y) % e( Y" s! r, N0 [: X
print(inv_y, "*"*30) . o; G5 V2 _+ w7 i' R6 R
/ J% V1 M; U: l4 Z
. W, Q% v, u6 [ inv_y = inv_y[:,0]
8 R1 N J. ?! W3 f- g # calculate RMSE
( Q, U* T6 j- p2 f/ j rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
7 M/ o) n# u0 z* k7 ?9 } print(inv_y[:100], inv_yhat[:100]) 0 n' }' i% X) D5 X; s, |+ ^- Q
print('Test RMSE: %.3f' % rmse)
7 X6 l/ a1 `# t1 U/ w* b - s, v% p" x W; _' n5 B! ~, E% j
8 N7 [ g8 @& x( ]6 }. n( _
'''
5 G0 C7 f2 h. z 实验结果 7 R0 G4 K- H8 ?
实验1:用前一天的天气数据,预测某一天的空气质量
: M5 L1 ?6 m- h& ? 使用LSTM模型 & i2 I7 s8 o% q6 r; b3 C
结果:
7 L ?! u) j' z5 p* [ Epoch 49/50
+ T. S) i! H0 A7 d 0s - loss: 0.0144 - val_loss: 0.0133 2 F+ K% r/ M- Q
Epoch 50/50
! o- C3 O8 d, T6 [# P3 g7 t 0s - loss: 0.0144 - val_loss: 0.0133
5 f% ?9 E( D6 G" e8 u7 A; c
; C. Q4 B c9 @' z9 b
4 o5 ?- O+ Z0 M7 ? 实验2:用前3天的天气数据,预测某一天的空气质量
! @" x% O6 e9 c& e/ B, @# Q! ] G 使用LSTM模型 2 _6 M% o. }# H( V% q) @
, ~. t6 h: n5 n# `' V" O5 y
+ a% S6 O y5 R7 y) G, \ 结果:
8 n( m8 ~7 M* |2 {( O5 u" y Epoch 49/50
5 u& ]; O/ J1 { 0s - loss: 0.0147 - val_loss: 0.0149
4 ?6 P. [: w+ Z+ X& e$ z5 [( [+ I7 O Epoch 50/50 J. R3 E7 s: a) _
0s - loss: 0.0147 - val_loss: 0.0150 1 f: V7 j0 {4 M/ i# P" k
/ h0 x# i$ R" p- X! {& u9 M4 Z
9 T" {+ d, b; H$ N' `0 p+ Q/ R
实验3:用前一天的天气数据,预测某一天的空气质量 # ]8 \" I; o( ]1 x
使用普通的全连接模型 Dense() / V5 N1 R( Y, G& Z' N" ^7 M' Z: I
结果: ! h- |. Q, [7 B/ u
Epoch 49/50
5 c9 g3 f' f. C- C' [ d+ h 0s - loss: 0.0144 - val_loss: 0.0146
$ s5 Q' Y U0 c0 b4 K+ D Epoch 50/50 8 u$ Q1 G3 M7 m. ]& Z5 D# q
0s - loss: 0.0148 - val_loss: 0.0151
0 r' s, K: N. k7 h * Q1 X, d* a" A* B
/ Y; r3 v: ]$ [1 n% a' \ d3 K
实验4:用前三天的天气数据,预测某一天的空气质量 1 P4 R0 x: l+ X! K5 E7 g
使用普通的全连接模型 Dense()
* _ `* ~9 L6 Q 结果: 6 n$ l( a$ J; ` V6 O0 o# J
Epoch 49/50 + s+ ?% ^& v$ A2 W' ~$ ^& s! R
0s - loss: 0.0150 - val_loss: 0.0165 1 t2 W0 e, H, F+ P6 D' r5 N
Epoch 50/50 ; H) U4 ~3 @. V0 _$ `0 ]& j7 _# E
0s - loss: 0.0148 - val_loss: 0.0141
3 |: W$ `. h p- e B
' \- A7 u# d0 v8 N2 P : n. Q! l5 x1 t9 K5 i
实验5:用前一天的天气数据,预测某一天的空气质量
; g X% b% F# A% v0 A$ F 使用SimpleRNN
( Q. ]- w2 g+ [ G" @ Epoch 49/50 4 l0 I4 ~6 M' D
0s - loss: 0.0160 - val_loss: 0.0140
' h6 N: r& U: e# l) L' G; Q Epoch 50/50 8 A* J6 ^- z8 q) f9 J4 H
0s - loss: 0.0147 - val_loss: 0.0150 . }, ?$ e- D1 m. _) S. B
1 I# P# Q: f: j5 J$ |- T 4 I2 Q7 _ B3 H3 N2 {) W
实验6:用前三天的天气数据,预测某一天的空气质量 ) @0 V) Y' r2 L7 Y: a
使用SimpleRNN
& J- ?# {' b5 z& I/ n Epoch 49/50
% _- [$ e9 N* R3 [( \( l9 c# M 0s - loss: 0.0164 - val_loss: 0.0233 : w8 M1 S! y7 i6 Q, C' U' _
Epoch 50/50 9 J' R+ a5 ?0 t! v5 c
0s - loss: 0.0166 - val_loss: 0.0227 3 y/ P% V0 y6 }9 W+ k
RNN和DNN的区别 RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。
8 Y- J. q- U6 S
7 a4 C) s+ D: Q$ m ! F7 K+ d n9 P3 C8 n. b" f5 S( b
RNN和LSTM的区别
# m8 g5 w3 e% `8 O, @3 t LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。 8 e# Z6 K8 \* T& `9 ]
0 A* [1 b& L- i3 n7 D' q $ Q8 i5 ^5 I* ~- A- B
但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。
2 \+ i! P R' O4 y
/ G) D# L9 U& Y- b. [; T( U
* Q8 D& e+ |' d: e1 V9 A0 v7 w 请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员/ k0 m y5 p" q# Z5 [
5 [! S5 ^8 F+ R2 o' F
- w/ }2 t, J5 Z0 v. }
zan