- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40200 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12771
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1419
- 主题
- 1178
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
|---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
 |
使用LSTM预测时间序列数据
; Z% {7 a; F! j3 m1 z4 v$ `4 r
5 [* k3 L+ a5 T z1 S
# c/ ~0 a; _! q* X' @, `文章目录7 y# ]" t1 k5 g* b. m
背景6 F2 X3 v5 Z' v
结论
% T; A; F& Z* }+ Y9 L6 f代码+ Z# H$ q# y! z% }0 d0 A! `1 s
实验结果- ^, K; Y3 q' E3 M4 ^
RNN和DNN的区别
3 d/ D6 E: H, |5 E$ B# L5 xRNN和LSTM的区别 b# l. V& t4 t, g% M9 b: c: V
背景
K& Q5 R) @% K0 |复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验
5 A+ L4 Y- g! A9 J4 M. Q熟悉用LSTM模型训练0 X% e% L+ O. q! |1 `( o, h
验证将时序数据 转化为分类问题后,预测是否有效果; k/ a- T1 Y5 [
对比SimpleRNN与LSTM模型 哪个效果最好?; F0 M6 A" |$ {4 J7 e7 q, U
验证LSTM相比于Dense()模型 是否有提升?
. [9 P, d7 C) D2 v7 T4 ~" B- M对比使用前3天的数据 和使用前1天的数据 哪个效果最好?7 U [* W! x2 U
结论
. d& V/ K3 J; ]! M4 M1 ? q使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好+ N+ I! d/ P, Q: V3 \
使用LSTM的效果优于SimpleRNN2 U- i# \: l* N0 _
代码
3 I6 y/ c2 }0 |: h8 u+ |! dfrom pandas import read_csv
, r2 _- \' T$ h9 pfrom datetime import datetime
5 y+ i! {: P0 J x- jimport pandas as pd0 O2 t$ L1 m" d7 n r- K& J9 a
from pandas import DataFrame
$ i7 E0 z% T! p$ Pfrom sklearn.preprocessing import LabelEncoder,MinMaxScaler
5 J1 T8 W( ~! q, w' x; A* n9 hfrom sklearn.metrics import mean_squared_error
6 \/ M: `7 A* U- o* ~2 Qfrom keras.models import Sequential4 I# | \$ M7 c- v' p2 q
from keras.layers import Dense, Dropout) m, t+ |: d9 s, O# i" N/ W( I, q
from keras.layers import LSTM9 V6 i5 l, n' s- Z5 |0 q1 V
from keras.layers.recurrent import SimpleRNN
7 b4 i- ]) B4 L- o, f# mfrom numpy import concatenate6 T" G1 d" s# T5 \# j
from math import sqrt
) B& L3 G; T2 j5 ~) S$ B3 ?3 K6 B5 O2 H* p
; P# y, ?+ ~1 w
4 \( f! |) ~0 I/ V& Z' u f
3 \9 G( M( A8 I2 J& d* q0 m+ J# load data$ W" L8 t) t1 W/ ]: u
def parse(x):2 |. w: V5 X4 v- B' r
return datetime.strptime(x, '%Y %m %d %H')
6 w$ ]: c3 a) G& I 9 n" [! W+ I4 l1 Y( K- K
def read_raw():
# b4 T: n) o ], r5 a7 m: e+ Z dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)2 t/ C. L5 D5 Q
dataset.drop('No', axis=1, inplace=True)9 f) y0 j) _0 _! P3 k
# manually specify column names4 u+ `; h8 t& K, ?; w
dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
# |# ?& V' c N8 k J( P2 F dataset.index.name = 'date' z4 r' S! u. g2 f* c* `0 @$ X3 h
# mark all NA values with 0
. _" F: s/ Y: |, M, _ dataset['pollution'].fillna(0, inplace=True)
% F' z# u3 A8 j# x* T # drop the first 24 hours
. K! j! A9 c, Y! ^6 c) u) t, @! O dataset = dataset[24:]' f% R4 A& b6 o5 ]1 Y% T
# summarize first 5 rows, d8 m- P. F( a8 O
print(dataset.head(5))
# g6 Z! l! m+ Y' c/ k) d # save to file& j+ e" n- u# K8 e ?
dataset.to_csv('pollution.csv')
3 g" u) ]& K/ q. u l( I5 g6 J( B7 x d
+ K; ?% J4 v3 Z
& e" v3 u1 C9 D' D8 z0 E) E8 ^
) ]; V5 ^. a) J, v! K- _# convert series to supervised learning
" m$ Z7 Q# s" R5 E. R/ m% ^def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
# s1 y, L- p# |+ @ n_vars = 1 if type(data) is list else data.shape[1]1 ?' |) F# C2 n# s& b
df = DataFrame(data)$ L( H3 f! r7 a' d. u
cols, names = list(), list()0 q6 S% t2 c( P; @; I$ r. `
# input sequence (t-n, ... t-1)
- O* X% I( A4 B! k for i in range(n_in, 0, -1):9 w @& L/ l( w" o& R5 e
cols.append(df.shift(i))
8 y# i( z/ E q, ?. E6 F names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]7 L! ?+ e! F2 `& I
# forecast sequence (t, t+1, ... t+n)
$ g5 g8 i8 M+ F. ^ for i in range(0, n_out):
: Z( n9 j. d- y. n cols.append(df.shift(-i))* q8 W" P: H/ [/ w1 H3 F' g
if i == 0:
% |# `. q3 N! L" R5 B* ^ names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
9 ]+ P9 Z' [$ t6 e else:8 L. Z& t& o3 L- a- W* @0 X
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]3 x5 N/ F3 M6 o8 ~) M, B% [
# put it all together" g) r" {$ T' |* q
agg = pd.concat(cols, axis=1)
* ?; Y8 n2 E# w, Z agg.columns = names7 W& Y" G+ D, x$ ^* U7 m( N
# drop rows with NaN values3 K l5 t; q: b" L
if dropnan:9 w J, {0 H* `, f" x2 Q
agg.dropna(inplace=True) t: h2 k/ F8 h. U, ]) C0 q. N3 M) r
return agg/ I. }3 l3 ]* V. x3 P- b C* ]
. m* t( B R# p- [5 M% C
# load dataset
6 Z! H/ U' A3 J) f- k3 k$ ldataset = read_csv('pollution.csv', header=0, index_col=0)
" ?. I. g4 Y/ Jvalues = dataset.values. g ~$ f) W0 h, @" u
( c" k4 H/ V, a {' ?: D1 w
9 n# c* q: c. c1 | z6 l. F( {# integer encode direction
2 q+ `8 t. Z4 y: _8 d# h3 }encoder = LabelEncoder()( d& V( U" ?# b8 g; w7 k: D
print(values[:,4])
: @; X6 @2 n Avalues[:,4] = encoder.fit_transform(values[:,4])
+ k- h6 |8 S2 F( x$ \* R$ z3 l# ensure all data is float' r }9 h y" t( ^" A/ i8 B
values = values.astype('float32')( {! y2 L" o N
# normalize features
( b$ ?' ] f5 f& Mscaler = MinMaxScaler(feature_range=(0, 1))
$ ?5 {- d) N7 k) zscaled = scaler.fit_transform(values)& Z4 [" o, i' Z; w
# frame as supervised learning( w6 ~6 z; s6 q7 w E4 l
reframed = series_to_supervised(scaled, 1, 1)
6 [( E0 N) f7 O6 _6 r5 O4 T$ F#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
# {! i' ]- t) ^! t Uprint("columns:", reframed.columns)
6 m. V! ^, t* [+ R# drop columns we don't want to predict3 r* Z( S8 i/ C/ p/ V
reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据# G9 @$ F: Y' L
#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
: y8 J7 @! [ \% [print(reframed.head())% X8 z9 E5 A8 m9 h
print("new columns:", reframed.columns)" Y1 H3 w' q3 T; K
# split into train and test sets3 {1 k) I/ |6 b6 V7 p
values = reframed.values
, [% H+ @- o( V9 xn_train_hours = 365 * 24! [* S$ P7 b9 W* f3 f# J/ O
train = values[:n_train_hours, :]
7 j" s0 U3 s4 \1 v9 a! A/ Btest = values[n_train_hours:, :]$ p. g: v: p6 f5 v' Q
# split into input and outputs/ {% |' ~, } Y, Y0 Q
train_X, train_y = train[:, :-1], train[:, -1]6 z/ a* z1 r" O6 H' o) U
test_X, test_y = test[:, :-1], test[:, -1], W U+ q- P) n; Q1 F
# reshape input to be 3D [samples, timesteps, features], a) n# ?# w8 m+ t T8 O
#使用Dense()模型时不用变换& z; f0 ^! [' z+ f V$ n& h" o
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))" q6 D( t. z1 a( s. I
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
3 v& ^4 E3 A; v8 N+ ^3 e9 J+ T. rprint(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
- f& p8 F# [# ]+ r. o. z3 Z# design network) W* `- _0 k" X% i9 T/ G
model = Sequential()+ K* x5 |) T n& P- r9 [+ a/ `: r
#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2]))) p" {6 {/ W* z b# R/ Z. r
#model.add(Dense(50, activation='relu', input_dim = 8))% |8 _# Z! h. V( P
model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))" a0 k8 L* b! l: {2 K u
model.add(Dense(1))# r! _5 y8 A. _0 C4 `
model.compile(loss='mae', optimizer='adam')
# ~7 f8 ~3 D8 i) x' L% G/ p# fit network
8 I% ?0 y. G# Q) p' k& Hhistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)% G. J. i4 G! ^' `
# make a prediction
$ z1 h4 o% |: K2 u; p5 c+ B; J8 @yhat = model.predict(test_X)
9 [6 K- M' [' m" vprint("yhat shape:", yhat.shape); l4 y1 y1 b4 H$ G9 |. i- x
'''* X2 ~% ], G: l* n+ T
计算在测试集上的均方差
; ~9 Y& j) p1 y! s* [8 Xtest_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
. p+ [/ O# q6 \$ X# T" @print("test_X shape:", test_X.shape)0 Q' x ?, X: E( M
: N: ]7 @ x* x- g
6 U' l; H/ i1 b& w# F3 M( }8 t# invert scaling for forecast5 y; ]! N [% X$ b
inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
9 T& m( L' ?4 Xinv_yhat = scaler.inverse_transform(inv_yhat)8 ~2 I' m* x J, V8 N1 a m r* P* C
inv_yhat = inv_yhat[:,0]
/ p$ p- ~0 R4 V n) D" N3 F. p# invert scaling for actual
. L; C& E+ f, @! W4 ltest_y = test_y.reshape((len(test_y), 1))
8 i9 \ C' y! V. k9 b& Z3 d8 Ninv_y = concatenate((test_y, test_X[:, 1:]), axis=1)) n' \$ `- A# l4 a- \* R
print("inv_y:", inv_y[:10])) K4 Q9 L. l1 s; W
print("inv_y shape:", inv_y.shape)/ {) {/ Q- n/ \+ S0 c' |, z9 L1 U; ?
, K) U. u% B( d0 c3 }' q
1 e+ S$ S, K( W( a1 V, minv_y = scaler.inverse_transform(inv_y)
1 }7 u- @/ Z9 H( v- K, L& bprint(inv_y, "*"*30); e" R! }& s0 A
% ^. Q5 Z0 u/ s* r9 [* z; d
; n9 ?4 H& \" Q3 V. O: Jinv_y = inv_y[:,0]6 h; Y8 M3 P- }, M9 `: V7 N
# calculate RMSE5 T0 s7 r! d' U
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))& x& @! b& N' f! S
print(inv_y[:100], inv_yhat[:100])% T) {1 L- i! L0 X
print('Test RMSE: %.3f' % rmse). R! {/ k8 a6 I* Y5 j. v+ T
7 Q. o4 d2 _, b+ _" _% K# e& r( p5 d* R0 X
'''
4 O, k9 W9 w! E3 a& O/ x1 r# l实验结果
) C" L9 Y2 c$ h. N实验1:用前一天的天气数据,预测某一天的空气质量$ n! U# H* q ?0 V' u7 R+ c* U
使用LSTM模型
6 C$ g+ x! D) s1 l结果:7 y/ u) O _4 a2 k
Epoch 49/502 q0 S" R( _. }8 K" P
0s - loss: 0.0144 - val_loss: 0.0133
$ p4 ?* W1 v; V* X' U( `Epoch 50/50
" A" l3 m+ h( S0s - loss: 0.0144 - val_loss: 0.0133
O, p5 x7 R/ {1 {: W
1 L5 _) K; W1 W) }4 ]$ d. J+ p7 H
8 b* s( L+ O: l& d. t) i7 e* k+ A实验2:用前3天的天气数据,预测某一天的空气质量
+ W( b7 ^2 d6 m4 j使用LSTM模型" z7 n: ]% }; U' m5 ^) d+ T4 N: q
~8 m% L& t. N' j( j2 y
0 c# ^. P/ x! F1 e& }( i0 |; Y Y
结果: j" S8 w! u @9 s" B
Epoch 49/50
; E# h; s4 \2 Z, a) o) }/ C0s - loss: 0.0147 - val_loss: 0.01493 r$ E+ L; f) X, w* Q* b. U
Epoch 50/50
& C9 q1 `: T/ ?; k) T; A) p: T# @0s - loss: 0.0147 - val_loss: 0.0150. M) p0 _. D5 y
3 @# Z/ e2 O1 @
3 S# d3 {! w, P; [2 e3 U
实验3:用前一天的天气数据,预测某一天的空气质量
: w& \" u' A6 i) \8 c, y使用普通的全连接模型 Dense()3 W" q' }, U5 B, V' U7 c& x
结果:: T+ S& Z9 _" Z# m4 B
Epoch 49/500 g2 P" l3 |7 p: v% `# x7 B
0s - loss: 0.0144 - val_loss: 0.01460 t0 @% p# l' | _$ |4 p
Epoch 50/50
( Z; {) X2 L: y0s - loss: 0.0148 - val_loss: 0.01514 }" m# G" |5 }* J2 e Q4 p
3 J9 x- @$ w7 u B- I
g2 @) o4 O0 ]9 |9 m
实验4:用前三天的天气数据,预测某一天的空气质量
% H+ N+ r9 B0 s% c6 H使用普通的全连接模型 Dense()
% U* ?) F; H2 y& X( l结果:( G- s9 N; h! v' C0 D2 g8 E2 P
Epoch 49/50
1 C5 T C1 L+ R* W/ m: e0s - loss: 0.0150 - val_loss: 0.0165
: J7 D: b9 v% l# k8 S9 V. N+ eEpoch 50/50: r( {5 t- \1 t
0s - loss: 0.0148 - val_loss: 0.0141
6 Q; `# P' H9 R* c4 M+ b$ k' C( w" `% q6 u+ p3 g" ~* J) W; j
$ h9 I/ B$ E+ C3 D' v X
实验5:用前一天的天气数据,预测某一天的空气质量
7 @ f% n0 M( A8 {- {- D使用SimpleRNN; ]5 h5 x/ U% p9 b- O7 b" L! s
Epoch 49/50
& w4 J- ]; b; O) {, C0 O0s - loss: 0.0160 - val_loss: 0.0140( _, m( J- Y7 X- E+ U5 r
Epoch 50/500 p3 r! M: n; d, U E" R4 d. x! F
0s - loss: 0.0147 - val_loss: 0.0150- h) ^' ~; ~9 X
* R5 I0 Z4 n) R5 X
g( g% p; N. L2 w
实验6:用前三天的天气数据,预测某一天的空气质量
c) n/ Q7 X" j4 L0 @) }+ g使用SimpleRNN% l4 V" U$ P* G8 Y, W
Epoch 49/50
' a7 X/ _% c# |# G" i( ?2 y+ O+ E0s - loss: 0.0164 - val_loss: 0.0233; p! d8 K$ a7 T- x
Epoch 50/508 z O0 r+ n/ `0 F3 ^; v. d, {0 b; K
0s - loss: 0.0166 - val_loss: 0.02277 h4 y# Y8 W4 S$ ~$ Z( t" {2 p' ]
RNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。
0 B8 c* Z6 V9 ~1 `4 `( s![]()
+ e( h9 b+ G4 c2 H0 d, ]' m/ E% d% X
RNN和LSTM的区别) w7 }4 z X' }* c2 R
LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。5 e/ N/ ]% @- d2 L4 T8 @" S$ e( @
. f4 }! r' B4 h& Q8 m5 r
1 ]2 E' v2 m& A' F2 s
但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。9 r! n4 w2 m! v
0 M0 e) ]" ~. \6 K" K$ C
& _! J7 Y- A0 X4 h1 `
请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
0 H, Z9 s8 X4 v' V
; A6 j& ]* \7 w4 O$ H# Q! Z& J. l+ ]: v$ K9 K" ]! T4 \
|
zan
|