- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40222 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12778
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1419
- 主题
- 1178
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
|---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
 |
使用LSTM预测时间序列数据
3 z$ |) k5 c. y8 C' a
& h/ j A4 M' Q! j8 E% y# f) e* D7 m$ }# W
文章目录
3 j0 f5 w. e; S0 h* B/ ~* s& F* s9 O背景
6 W! G1 g+ O, e6 `8 d, O3 q结论
& o: ]: j) g9 H- c代码* U9 E( ?) `9 G6 x, ]
实验结果
) q' c6 r1 |' vRNN和DNN的区别6 r4 V/ }& ~9 F" p- ^' b0 b
RNN和LSTM的区别
) T$ h) u+ X. s, V% [' V背景
: z: v$ Z9 L2 e1 q7 Q( I0 y复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验9 y9 W- K1 Y0 W( l! P9 J( d
熟悉用LSTM模型训练
- ~) F) b7 `" p; X验证将时序数据 转化为分类问题后,预测是否有效果
/ A3 u" P1 M6 g" l; E对比SimpleRNN与LSTM模型 哪个效果最好?5 j0 y6 E! r4 w- q) R' |* o* S
验证LSTM相比于Dense()模型 是否有提升?( g, ?5 c$ A5 P1 l. q
对比使用前3天的数据 和使用前1天的数据 哪个效果最好? s" t/ z& a9 I- J; P
结论
% C7 a9 k0 g7 W7 e5 j使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好8 Z8 f! F# ~' |' c W) t5 T- o4 D( P4 X
使用LSTM的效果优于SimpleRNN
, Z8 j. |' J) k! }1 |/ [代码& U3 _( C8 s3 M' Y4 s
from pandas import read_csv* e) ~. C" w% K2 T
from datetime import datetime
6 p- d+ g% |3 d# \& ~1 w) [7 wimport pandas as pd* j( M( q: ?; C6 W5 n, D
from pandas import DataFrame
2 W/ U7 D! c# i7 Y9 A1 G Ifrom sklearn.preprocessing import LabelEncoder,MinMaxScaler
$ B9 I4 I1 H7 I9 Gfrom sklearn.metrics import mean_squared_error8 Z1 M8 }7 f) u3 u! I
from keras.models import Sequential
+ C* {- O+ y7 X% d2 g, Dfrom keras.layers import Dense, Dropout
3 O0 L" ~, `% V* I) e/ bfrom keras.layers import LSTM
; @8 F+ V2 l/ ]1 ufrom keras.layers.recurrent import SimpleRNN% e2 z- R5 E4 ^
from numpy import concatenate
9 ?% `/ i2 X, f% C4 m: Dfrom math import sqrt
7 k/ [8 j- N) [4 j* q$ w2 l; v* @9 o1 k( P1 @
& v# b& e4 b; S/ o3 N* H
! j- x% I" J+ y
6 u/ `$ f/ D1 E8 F8 X7 ]# load data6 w$ U; P7 k9 ], G
def parse(x):
0 ~5 w' k2 O* D* r( U return datetime.strptime(x, '%Y %m %d %H')
0 r, ~/ g& ~, ]; V$ F0 p" W 8 e/ r5 M: C% D- @2 x
def read_raw():
3 x4 L: p2 P& F5 T( C: I dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
9 }- v7 L$ Y$ B9 d8 { `- S9 k dataset.drop('No', axis=1, inplace=True)
# i% N- E: V9 B8 C' _* X # manually specify column names
: g* O6 l% B9 K0 ~) d dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']$ a+ s, ?3 ^5 {5 ]1 N
dataset.index.name = 'date'
: z5 `# k4 O! |$ k# ~# H% O) \ # mark all NA values with 0
, d5 L. p! H7 Y! S" N dataset['pollution'].fillna(0, inplace=True)# C6 E8 s8 x* m; ]# z3 I! i% d
# drop the first 24 hours- k2 `9 {- D; H8 W
dataset = dataset[24:]
! g* Y! M2 O) _5 S0 v/ \ # summarize first 5 rows* e( V1 T. ~2 S* f
print(dataset.head(5))
5 [/ a! f4 P4 a0 R4 F" u' J3 c1 J # save to file1 J0 h2 f. `+ n
dataset.to_csv('pollution.csv')5 X* d& B V( a, `5 ~
m$ d& y3 w7 K3 ^/ B5 h
Y( E6 r; Z3 w4 X
: Q* q( Y, V! Q- n% _' w' W2 B Y& {- I3 {/ y& G
# convert series to supervised learning# b! t* X5 a- o4 w" P
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
+ D7 `' k; C4 X+ x" u+ y n_vars = 1 if type(data) is list else data.shape[1]
( [! |1 k; |7 O K df = DataFrame(data)
8 P- m# y. B2 j- ] cols, names = list(), list()
2 k( C6 y/ e) G$ p" C: ? # input sequence (t-n, ... t-1)
, r- F" l( a# W: p9 h& [' ]; Q for i in range(n_in, 0, -1):
- l0 {' \7 u" N! W- _' x2 M! T cols.append(df.shift(i))
( E9 K1 \; K5 E. L# h' \* L names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]5 w0 n4 k+ S& m6 T( c4 O
# forecast sequence (t, t+1, ... t+n)# D- W2 d) q: }' \
for i in range(0, n_out):
( U$ S0 i' i, N* Z cols.append(df.shift(-i))
! J! W B0 b2 H# Y! d/ @ if i == 0:
2 @' J9 j- s+ s$ I% a* `$ p0 x+ i names += [('var%d(t)' % (j+1)) for j in range(n_vars)]: p g. ~" C: |0 m" a
else:
2 @& h& J: V) e names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]8 P* Y* F3 i/ X- @( @$ M4 w
# put it all together
. ?0 f' A6 Z+ h- w agg = pd.concat(cols, axis=1)
- L8 `9 q3 P. U1 ]* c2 @5 D6 o agg.columns = names: R7 b- B' r4 S* Q7 W
# drop rows with NaN values
- o2 W$ e1 T1 D0 k7 u: D5 i if dropnan:$ a p5 H$ P. d. y. y( }0 k# _
agg.dropna(inplace=True)/ t- u* _) g9 p1 Q1 E
return agg
' s* K# I! A$ {$ @7 Z 5 t9 p1 ^2 y& o1 [
# load dataset0 D6 @# R" h7 Y" X0 N( @+ r2 z8 q
dataset = read_csv('pollution.csv', header=0, index_col=0)
9 N7 b0 ?9 Q T, `2 W4 D; Xvalues = dataset.values* m' l% D! C0 w1 K
$ @* `! ~( P! j1 ?- _
! ?. ~5 s7 i; w: N( [) ]# integer encode direction" h2 F# `4 o W- B7 i. i- J( d
encoder = LabelEncoder()
- C7 D0 W2 B6 J: u4 H, s, t5 k- [print(values[:,4])
4 t5 c" p# }, Q0 |values[:,4] = encoder.fit_transform(values[:,4])& c) T$ U! N4 }1 S
# ensure all data is float2 E+ B }1 K1 D+ M. z$ t# k" i
values = values.astype('float32')
, k; |0 b( n% H) n, M5 `, q2 N4 T# normalize features
/ O$ \8 E- d, U9 [scaler = MinMaxScaler(feature_range=(0, 1))0 z! v$ t. j* R- v, p R
scaled = scaler.fit_transform(values)
5 w7 ~; W( x! t% ?1 ^' D( f# frame as supervised learning
, c$ `3 Z2 \1 N% g; H. l7 S5 G, P& areframed = series_to_supervised(scaled, 1, 1) , A1 f( T, k3 {+ ~" a
#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据1 n" x; Q, d9 T5 X4 q3 F
print("columns:", reframed.columns). K2 L4 j' p. I8 S. J, n" s- `
# drop columns we don't want to predict5 o; E: ~: ~3 B4 ~' Z4 b& S
reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
/ n# S h8 \0 g5 r6 h! o#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据 r. w; ~3 G: d* p8 \8 x
print(reframed.head())1 w4 T1 A2 X5 y0 b' G& r
print("new columns:", reframed.columns)
" m, q. }( D% ^6 p# split into train and test sets
0 p% q8 S/ C4 r# Y, {3 }7 N3 U5 hvalues = reframed.values4 ?; k3 Z' @, s7 d6 p
n_train_hours = 365 * 24# G. P6 c- Z# P7 O
train = values[:n_train_hours, :]
l+ Y& M l. q9 V. ?" v6 Otest = values[n_train_hours:, :]: | h$ T. @8 M! ]
# split into input and outputs
; O! E/ Y9 Z) H# Ftrain_X, train_y = train[:, :-1], train[:, -1]
- {+ p/ b; ?6 r3 t+ stest_X, test_y = test[:, :-1], test[:, -1]
& R, H0 z! f1 C) H& h D. T4 e# reshape input to be 3D [samples, timesteps, features]
" |! Q4 J2 _$ J% \#使用Dense()模型时不用变换- j9 _* g; J3 w0 N
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
$ X8 Q$ A: X/ X2 D: x% mtest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
6 C) o' C) V' s [* Gprint(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
9 p7 w+ }$ a3 c" K6 V4 x+ s# design network
; C3 C% s* j" e9 l6 zmodel = Sequential()
+ V) `. i; k; s t& s#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))6 z5 R6 m/ F! N
#model.add(Dense(50, activation='relu', input_dim = 8))$ ]' i: q! j+ Q0 b' I
model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
6 G6 H: F! @9 e7 j/ r' Imodel.add(Dense(1))8 Y0 A/ ~* L5 Q( t& y
model.compile(loss='mae', optimizer='adam')
# w7 ]4 E' @" a# fit network" J) q" q/ h, i$ J
history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
8 U: y+ f) ?* a$ `4 Z# make a prediction% x% P' N- G" K/ C. S" e
yhat = model.predict(test_X)6 `. n3 Y2 k D7 o0 r* I1 J5 {
print("yhat shape:", yhat.shape)& Q5 w( s. S" S* Q
'''
( B9 P" E" @ p0 K) L计算在测试集上的均方差
. ~* u8 h/ v0 z, m' j* w# gtest_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
7 w) g6 I; ^5 z3 s) o# oprint("test_X shape:", test_X.shape)
" H5 g5 F4 s$ _% x* b8 r
# A2 A. o, ~; C5 T, q0 N9 U
, v2 X% | y G, Z0 K: v4 Q7 f3 q* \; |# invert scaling for forecast* f, e% z9 u/ w- R! y2 H
inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)5 M- V3 k6 r8 d1 F; m
inv_yhat = scaler.inverse_transform(inv_yhat)
; B2 t: z3 l: ^7 Z1 Jinv_yhat = inv_yhat[:,0]
9 D, I* V7 m, s# invert scaling for actual
. P8 l$ X" n0 ]/ g& O' Q Rtest_y = test_y.reshape((len(test_y), 1))
- S. v! j2 V* _* m& W8 I$ Winv_y = concatenate((test_y, test_X[:, 1:]), axis=1)" w/ V% L1 j# i9 K
print("inv_y:", inv_y[:10])& n3 e p0 ]9 O/ C
print("inv_y shape:", inv_y.shape)9 J/ J4 ? C; K+ v' c2 N2 I, g9 G
: _! Y' F% ]% N* N, x6 C# A, x9 M, p9 {4 c5 k1 J
inv_y = scaler.inverse_transform(inv_y)% ?- y5 p8 d1 | x
print(inv_y, "*"*30)- z' R% s1 J( B0 t7 w T7 Y* i: C6 S
5 h* ? W' C6 f6 k
7 ~( T+ l3 a/ _. Z% Q6 Oinv_y = inv_y[:,0] u1 z/ q: I7 Q. s1 @
# calculate RMSE
6 r" ^$ E- [( U9 x+ |( grmse = sqrt(mean_squared_error(inv_y, inv_yhat))
2 k( K7 N- H( V$ B% r& {& l: nprint(inv_y[:100], inv_yhat[:100])+ D% Y3 Z2 X- a# B( \
print('Test RMSE: %.3f' % rmse)
0 Z) }7 R9 f, B7 H( S0 W# L! `( z* C
1 U9 G2 |" N& E' f% u( y'''
# |' ]& a0 E! p6 O$ v, `实验结果
# m q: k2 c9 M) T _# `实验1:用前一天的天气数据,预测某一天的空气质量0 I% T9 U( C2 m# g
使用LSTM模型0 d9 |$ [% ]+ K& j! `
结果:- l' ^: x0 l! Z3 m6 g- r* b2 o" R
Epoch 49/50% B; K0 B, M3 j5 H6 n, q
0s - loss: 0.0144 - val_loss: 0.0133
1 R# y v7 d& n, REpoch 50/50& M+ ^4 i, z2 z* O8 I1 q
0s - loss: 0.0144 - val_loss: 0.0133
7 F2 t9 H1 X! u/ P+ b* Z, j/ p% ?+ R* W, F
1 w3 Q, N; K0 f
实验2:用前3天的天气数据,预测某一天的空气质量
1 P5 X) w& A! K _使用LSTM模型! ^. y3 P7 R$ Q& B C0 a. S
+ e" k% F4 w$ e) w7 s; `4 O# f( d, n) c, q6 G% F% O6 ]
结果:
/ f* {$ z6 m( o9 \' Y Z: gEpoch 49/508 `- O0 O* O8 o' L8 H( W( G
0s - loss: 0.0147 - val_loss: 0.01493 I$ f" a" y$ X) X
Epoch 50/50
) f, y9 B' k {* K0 ~2 V0s - loss: 0.0147 - val_loss: 0.0150
0 |0 }% Y& s' _2 C0 \# `, T v
& i1 U! ~2 U! p! I5 ^5 _8 T; P+ g
实验3:用前一天的天气数据,预测某一天的空气质量" F6 R, Z" h# Z0 R
使用普通的全连接模型 Dense()
g8 M5 S9 ^% Z" f+ ^4 C" E, N, G0 P结果:: ?$ @2 P6 x' j* |2 f
Epoch 49/50
6 u" C4 f' L' N/ g5 \# ~0 b1 D) f0s - loss: 0.0144 - val_loss: 0.0146
, E s% z4 _. vEpoch 50/508 `: d! P M6 a2 u5 [
0s - loss: 0.0148 - val_loss: 0.01519 k$ a# M" J! O6 O9 P8 |7 Y
+ y) g6 h5 H+ E" d' a( P
_- I0 U( x1 K0 }& D实验4:用前三天的天气数据,预测某一天的空气质量0 P8 O1 z& O- I e& G
使用普通的全连接模型 Dense()
8 s8 k& r% c0 j5 W; L结果:( E( c+ _6 Q/ l6 {0 M9 r
Epoch 49/50
' C; Z: o6 {5 t: H: w6 M/ t! B0s - loss: 0.0150 - val_loss: 0.0165: E: ?4 f; J. S! ]; h% H4 H
Epoch 50/50
W- q4 ]% U' D9 d6 D7 ~0s - loss: 0.0148 - val_loss: 0.0141
* ~- [ S1 { B* n- P4 t( r, V/ y; V, }/ c. r% B3 h* n
) I( L' H) X& d" w, L
实验5:用前一天的天气数据,预测某一天的空气质量
# B4 c3 z0 O6 c6 E3 E' X使用SimpleRNN% q" d; r% O1 S) d1 [
Epoch 49/50- z% B) |. x, @% c
0s - loss: 0.0160 - val_loss: 0.0140# v- z1 p8 [( h3 I
Epoch 50/50
$ N, @1 p. y0 g ~0s - loss: 0.0147 - val_loss: 0.0150
v$ ~! h l- Z, [5 V% s! A- a* p/ l6 h6 `& {6 n4 f3 q& _/ u# V$ Z$ o: g
/ j/ B" I) F) b: k7 t$ W2 ?! f
实验6:用前三天的天气数据,预测某一天的空气质量9 P1 g7 h' {: y7 b$ K& L
使用SimpleRNN
# w5 G; P& l- ^7 v' d& hEpoch 49/50% M/ R4 L' F: w
0s - loss: 0.0164 - val_loss: 0.0233 V( @' S8 D( v
Epoch 50/50* j/ A c; \& l B
0s - loss: 0.0166 - val_loss: 0.0227
9 G+ [1 [4 r& \5 b6 {4 t6 MRNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。
4 D7 s- ?- w0 a! N8 k7 e , c1 ?, B! @* U7 U, U
9 X! b" W# c ], J7 p# aRNN和LSTM的区别
- s" [$ V. r N/ y+ KLSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。* _* \! d8 ~4 _# U+ _9 G
% c" V$ H; }( y* X$ z8 P
8 K6 E* Q/ h( y/ Y& O但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。! [* J; H( L1 b; O, I& E9 x* D( d
4 _/ ^, O" S3 f5 Q2 a/ u
6 y& i- {! f0 T8 a; e$ T+ V" m
请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员6 F" i O/ G9 [
, d- y6 I6 I" z) T3 G# _) e e1 g7 ?: K' b
|
zan
|