- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40278 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12794
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1419
- 主题
- 1178
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
|---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
 |
使用LSTM预测时间序列数据
5 o# H6 S( R# C! }+ \- m% p' F/ e' T
# D6 _, V$ L: [2 Y7 X3 g L/ h' Y0 d8 D: i! [
文章目录
/ F7 r0 `- Q+ s8 q7 [背景9 Z6 I4 Q+ S% s2 h- g7 ]/ n8 y
结论
- @8 R/ d" m! \. i代码
, O2 P+ ?( u& O0 |实验结果# |& b7 k, Z# K' B
RNN和DNN的区别( f' c( s; i. g5 c9 I! _2 \
RNN和LSTM的区别6 l6 c/ i6 w% Y% r; a* _3 Z
背景
0 r$ H- E8 o r- q2 }6 i& H复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验
9 \' k" ~7 C% u# C5 E) T熟悉用LSTM模型训练
6 m) W/ `2 F0 p; X验证将时序数据 转化为分类问题后,预测是否有效果* m" Q: C& d; ?* ?
对比SimpleRNN与LSTM模型 哪个效果最好?
# A6 j" z/ e. K7 ^验证LSTM相比于Dense()模型 是否有提升?
- z7 R$ d* X+ B7 w7 p7 B9 L7 K E对比使用前3天的数据 和使用前1天的数据 哪个效果最好?+ t' D/ z8 m/ d) ~1 K7 s' w/ ~
结论
" I. x! W w* h使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好
6 b4 f$ { ]7 ]9 d( `4 K+ |& K使用LSTM的效果优于SimpleRNN
( G4 e( m* H% V5 q" _代码
3 e9 J( h8 T0 T" U$ ^from pandas import read_csv
* |0 @5 k1 R5 \7 y0 N- Rfrom datetime import datetime$ J8 m) k9 K- N, ^8 W ^
import pandas as pd6 M% ~+ k* ^' ^, H, A- ]$ e
from pandas import DataFrame6 D, _+ [9 V- W5 Z& P* Z
from sklearn.preprocessing import LabelEncoder,MinMaxScaler4 Z$ x; i6 u5 [% W Y H! H
from sklearn.metrics import mean_squared_error
& g: r7 N: ^' i/ B) Sfrom keras.models import Sequential) e7 b+ H% M9 Z& P+ M" q
from keras.layers import Dense, Dropout
. j X; m5 W. a. t2 Wfrom keras.layers import LSTM. I7 ^; k7 O7 u% K6 X2 ]
from keras.layers.recurrent import SimpleRNN
; F: h E: P- W Y: {" m( }from numpy import concatenate
5 F4 l/ r4 u$ Y1 V$ Nfrom math import sqrt
; l$ K/ D2 c0 |
* @) M J3 X' g1 Z& }+ I8 W4 D; a( H9 c, i- B+ U* d
6 e$ Y7 o' V) V, ~5 @: @6 a! \4 A, c: B* ]
# load data( J* a6 p6 @# v7 _1 @. h& o
def parse(x):
# D, B( | B& w- E return datetime.strptime(x, '%Y %m %d %H')
1 `. |: M& f! T, @, O
5 W0 f3 {" [ ?8 S! xdef read_raw():1 o3 x' I# | s+ K4 R
dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)+ r) r( m7 S0 a% c5 [2 i) a8 g
dataset.drop('No', axis=1, inplace=True)
/ [- g6 i3 _$ V& K* V6 A/ M5 z # manually specify column names1 n- P+ d$ X3 I* x' w
dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']1 R, Q! B# D: g7 f% N2 B, J
dataset.index.name = 'date'
+ ^1 f! n% Y, W- l- m2 |9 x # mark all NA values with 0! P, b) [7 J2 a
dataset['pollution'].fillna(0, inplace=True)
# a3 ~' n/ W: R" c$ ` U # drop the first 24 hours
- d g) E7 C7 `+ K dataset = dataset[24:]1 i. ^5 g0 j% e1 `9 C" y2 A
# summarize first 5 rows
8 t( q+ L) p9 p, N* u2 J print(dataset.head(5))3 F* t0 P/ H* u* K
# save to file9 f9 X; \! }, f/ O- N* t
dataset.to_csv('pollution.csv')
3 v! e, l4 n1 T c5 C/ M
' N. ~0 u, Y5 U1 U% I3 S# o2 B% u; X/ w
- e# y7 c- D; q5 m* G; j4 b% {7 P! `5 y/ t8 `1 p9 j' t
: k u, k% m* j( f. B) W8 H# convert series to supervised learning
2 q! v j/ E `3 C* u2 {. f6 hdef series_to_supervised(data, n_in=1, n_out=1, dropnan=True):9 E1 ?3 o m! ^6 l1 o$ Q
n_vars = 1 if type(data) is list else data.shape[1]
% K J5 f& I7 A0 k( ?: k df = DataFrame(data)
. r& t7 v# |/ [& E- H. s! w! X/ A cols, names = list(), list()
6 Y! h9 K& m' P {) C: R # input sequence (t-n, ... t-1)( n% C4 S; h: w" j( m! G
for i in range(n_in, 0, -1):
$ |9 L6 Z7 P! D: m2 O w( Q cols.append(df.shift(i))6 c; |0 K0 L% w, m3 m
names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
; ]% x( c5 ?! e; N1 v+ C # forecast sequence (t, t+1, ... t+n) X* j1 |! z0 q$ |! x& s9 u/ J
for i in range(0, n_out):7 D( R! y& g( m/ `$ r: ~, l+ T
cols.append(df.shift(-i))
2 a \1 T0 }6 Y Z* {/ v2 Q; o y if i == 0:! ]- ]( }/ ?) n7 L' s. _0 ^# ^
names += [('var%d(t)' % (j+1)) for j in range(n_vars)]8 A: S, G5 \5 |4 B2 h8 ]7 @7 { Z
else:
/ x) v' }4 }: O0 ?8 A names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]9 i' e p8 z& r- U; z' k
# put it all together
' h/ @4 Q/ U% a) J7 K agg = pd.concat(cols, axis=1)* b" [' \% {; ]* }+ i
agg.columns = names
9 `+ f- [- b8 w3 q, G3 D2 D6 { # drop rows with NaN values( C% l T1 _( j: a; H$ b3 d: W1 n0 Z
if dropnan:
. \; d$ e- F$ ^& q- O% [- T1 }- \ agg.dropna(inplace=True)
$ k- A. ^4 W& u% c; ~ return agg
$ n6 l' M! X6 c ! l; c- m+ _1 [! t
# load dataset
2 i4 d% k) ?5 C- v& w/ _: x% ndataset = read_csv('pollution.csv', header=0, index_col=0)
" u+ |! M$ w& g4 A6 a0 Lvalues = dataset.values
2 k$ w- I& b7 `1 X
) I( j$ I( W7 n0 }/ \6 I H% {/ {. K) r: W4 p5 n
# integer encode direction4 A1 m: A' o3 g( E8 ]* b1 s
encoder = LabelEncoder()
; g M" |4 H. V6 sprint(values[:,4])5 @- y1 K$ N4 N& R, }
values[:,4] = encoder.fit_transform(values[:,4])
8 O8 E2 y! E, G; L" ^1 q# ensure all data is float" {. U9 M& F" q( M% i7 m
values = values.astype('float32')
% @0 l3 M0 M8 F+ k# normalize features
u' |% j- b; o) y! m9 }/ }, `' Escaler = MinMaxScaler(feature_range=(0, 1))* x: S* o/ P, i( j
scaled = scaler.fit_transform(values)
; V" C; L/ C% r8 ^5 [% J1 q. v3 Z4 G# frame as supervised learning! h' p7 k S9 W
reframed = series_to_supervised(scaled, 1, 1) , X; A( {' w1 T9 e- R7 W4 x
#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
1 p" b* J Q% z$ `, }) Q8 W1 v- Hprint("columns:", reframed.columns); z. e" s0 t, j) V8 A9 c2 n# V- z
# drop columns we don't want to predict% l& H$ x3 o! J( S% L, J( h* D
reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据! X2 @: M S! h( [4 l* n
#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
' e# M; o, f. @2 w7 Jprint(reframed.head()); ]! A$ K6 q) }% x7 ~+ S0 }6 W2 m
print("new columns:", reframed.columns)
5 |& Q: o' R0 s2 L3 Z. S- L9 X6 r# split into train and test sets
2 O" h, f- {: h4 s, G1 W1 @- J$ E! {, Pvalues = reframed.values& s7 b \1 l# C/ u' L& Y% J7 ?
n_train_hours = 365 * 24( N- q5 {8 n5 v; B% L: ?5 m u
train = values[:n_train_hours, :]' p; P/ m4 G4 v& M( @) \9 r
test = values[n_train_hours:, :]
! Q$ m* n; m9 m/ S4 c' u1 Z# split into input and outputs' E" Q: V1 _- b* ~8 L
train_X, train_y = train[:, :-1], train[:, -1]' n J7 I" y u. q9 a; r
test_X, test_y = test[:, :-1], test[:, -1]
. ^7 F4 l1 z6 p" F# reshape input to be 3D [samples, timesteps, features]% @# f1 ?- o2 j |. g
#使用Dense()模型时不用变换' O6 {2 t* @) b, _4 [$ y( V2 l+ O
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
. v, M3 H. v1 o8 p1 btest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))! f' ]! a2 o! f- M; U
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)# O1 c/ ~( T0 [9 u
# design network
! D8 L% H) v0 l x4 }model = Sequential()
# t2 ?* K! D6 ?( l# f#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))0 e* Y) e) M4 H# G
#model.add(Dense(50, activation='relu', input_dim = 8))
5 _1 a6 E# N$ zmodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
% `% A( b/ `& ^# o7 E* n# jmodel.add(Dense(1))) E" q# b+ h' n( h1 o3 Y" C
model.compile(loss='mae', optimizer='adam')* P7 O1 T! f& {, I
# fit network
8 r* o1 j* E, c) ?: ~history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
0 ~. w# W$ R% W# make a prediction! N; v1 P/ n2 [ L# G% Z( Z; B$ Z
yhat = model.predict(test_X)
0 @ E$ g( d9 W7 cprint("yhat shape:", yhat.shape)
: c- {* n d) }'''$ s* U. W) m; Q: K( j
计算在测试集上的均方差5 m* w- `+ K* u/ ?, z
test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
% o0 V- R% ^* m* S6 w+ `' bprint("test_X shape:", test_X.shape)
- K* I. a. ?4 y5 s9 ]0 V$ |6 h1 N( B {6 a8 i
3 f; f$ O1 G% c. P8 ]# }# invert scaling for forecast
. Y& B" k/ y1 [1 kinv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
) ]6 h" C" U. r4 w. W# @inv_yhat = scaler.inverse_transform(inv_yhat)
- {2 u" F3 T0 ?- J; I1 Hinv_yhat = inv_yhat[:,0]
; |! i. ~: i$ B* }& V) g: p6 E# invert scaling for actual1 n/ A! E' }7 e
test_y = test_y.reshape((len(test_y), 1))0 H; Z1 X- w/ A5 ]! D0 N
inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)
: x8 \5 k, @0 o- P5 Z2 eprint("inv_y:", inv_y[:10])
: C" s9 C1 P9 u$ S3 Jprint("inv_y shape:", inv_y.shape)5 H6 n6 j u$ M' Z9 k' e
' F; d& ^5 E$ s8 z" s
# ?8 w& z. }6 U+ |
inv_y = scaler.inverse_transform(inv_y)# X4 e) r* F) Q/ E# g
print(inv_y, "*"*30)
) o6 @, p& H. @
7 Q+ i% S( T8 a0 L8 A* S
( [; C8 e% c1 ^8 ]9 s5 K, G4 ]5 winv_y = inv_y[:,0], n$ Y) y3 p7 {# k; g
# calculate RMSE2 N5 }+ Y* a) v, ~; X, v
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))3 e1 ^+ C* |# ^' X2 y
print(inv_y[:100], inv_yhat[:100])- {, T( u% n" T0 }9 _# j# ]
print('Test RMSE: %.3f' % rmse). Q) X; o3 e# N) C- u
5 E7 F! T+ k7 \/ u9 }
! d- J# [* g0 L% W2 q/ N# H8 R'''
# \; O# X: A$ y' D& r0 ^5 }实验结果
3 V4 k! P) H3 O8 [, I. x实验1:用前一天的天气数据,预测某一天的空气质量8 m9 R J. h k5 o1 V
使用LSTM模型/ c5 O7 M0 h0 c/ D9 I: f2 }7 a
结果:/ m: K8 ?1 c z4 A1 |
Epoch 49/505 u, @( y1 N/ q! g6 Q
0s - loss: 0.0144 - val_loss: 0.0133
O2 }. |' V, \4 ?4 v6 m" b2 o9 CEpoch 50/50
3 O: `8 ?8 O% D" t5 m d% t0s - loss: 0.0144 - val_loss: 0.0133
( g+ G5 W0 U* e4 W5 C: @% n& S; j3 {- m2 O @2 U' w
6 S8 T3 m) \+ F9 p# k( p) z! \
实验2:用前3天的天气数据,预测某一天的空气质量
1 Z d# M8 n9 w7 a7 F使用LSTM模型* m% Y, C9 X5 \$ M/ G( g3 B
. ]3 R8 K5 I" K Q+ N+ n5 q' K
1 U( _5 X, x) a2 a
结果:+ h6 B3 }% _. v) t
Epoch 49/50
: J. p; ?, D& ^% g, }" Z+ p0s - loss: 0.0147 - val_loss: 0.0149
' u' Y6 N& J3 O0 [4 eEpoch 50/50
; |2 C7 E8 r- Q, o0s - loss: 0.0147 - val_loss: 0.01504 k2 Z* W1 [. D
, v5 S7 ?. {9 `# H/ f2 b; [6 E4 [ R+ |$ J1 M6 [
实验3:用前一天的天气数据,预测某一天的空气质量+ }5 f3 C% L7 H+ d
使用普通的全连接模型 Dense()
* T6 f0 E9 K3 D结果:
. z* Y2 A. `5 v f" E/ ?! }1 |0 AEpoch 49/50
, H5 e( P' {" j0s - loss: 0.0144 - val_loss: 0.0146
: X1 r' A2 C6 @' D* T, dEpoch 50/50
! [6 U1 v: Z' _6 s' |& N0 K0s - loss: 0.0148 - val_loss: 0.0151
" ]' Y' H( N/ n+ i7 ]% \9 d6 ?' l& Q- z$ v# I1 t8 X; `: r. ?
# {( }' Z' V3 h) w; c4 [: s+ i k
实验4:用前三天的天气数据,预测某一天的空气质量% R$ [8 e" G1 g, P' @
使用普通的全连接模型 Dense()6 m8 Z$ N R$ M% z
结果:
5 k8 U/ X4 F9 p' {) zEpoch 49/50' E1 \, r/ B! g' Z5 v/ U7 E
0s - loss: 0.0150 - val_loss: 0.0165
) B' _7 _. W- gEpoch 50/50
8 N# n3 x; q$ ]- F# j3 O1 c: p; K0s - loss: 0.0148 - val_loss: 0.01419 k+ i- O3 X* n
: e7 l& s3 P+ B& z. R- N1 ]1 Y% W9 K, A8 g
实验5:用前一天的天气数据,预测某一天的空气质量
/ |4 P4 L- _6 ~$ ^9 [使用SimpleRNN
0 ~, {* F! B5 h s! qEpoch 49/50" `: d% n, k- g, ^" T
0s - loss: 0.0160 - val_loss: 0.0140
' \) m7 l( ~) F$ m) ?$ @. [Epoch 50/500 p/ |6 O6 J7 j! ^ z
0s - loss: 0.0147 - val_loss: 0.0150' |) O. ~: `: o$ I0 T" u
8 d" ^3 ]& h- C5 N: E
5 X5 l5 N' ]$ n2 l! U. `5 b实验6:用前三天的天气数据,预测某一天的空气质量
& h$ c& {* V% K3 X使用SimpleRNN5 q& U- c- r- R ? \4 z; y I* L N
Epoch 49/502 ]# ~* U& l5 ?/ S
0s - loss: 0.0164 - val_loss: 0.0233" k: w& M' j0 ]
Epoch 50/50; e8 c# }; \1 X. E |
0s - loss: 0.0166 - val_loss: 0.0227
2 Y% ` h f" N# y# g! rRNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。
3 e0 X- w7 A( y. L 4 q/ k3 ^ C! h1 X0 b5 b% {
" z2 I' C4 q( I0 [" f
RNN和LSTM的区别1 @- D, q O8 z( e1 y* ]. u
LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
0 Q) `# ~! F4 d8 x% d1 g5 `. ^
* ?; O$ n8 R0 }0 v6 j& D3 k. g( t. t% t" b9 \$ R" \
但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。
. ]( R' m! } Q0 w# Z5 Q5 ]* y![]()
+ C8 ^3 Q8 m z
; X: [; R# j! x; _1 {0 R) n4 h' d请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
; ?0 m& q* `' {7 P1 w
; B- P+ q, O6 \% V6 t/ _( p4 K: @) }
|
zan
|