- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40344 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12814
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1419
- 主题
- 1178
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
|---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
 |
使用LSTM预测时间序列数据
* v9 Z/ `; ] T o x- Y2 Z# C. |" i: c/ _
9 j' P; o$ Y& {5 M e: ]
文章目录2 p. w+ B& P( z( F7 @( Q1 a
背景5 J& z9 }! `7 |6 n# _
结论 G. ?3 T* h2 y0 B( n
代码9 @3 s& [, L8 E* d# [% U' s
实验结果
: h3 F. a5 r8 A. ]% |& URNN和DNN的区别
8 {7 S# E/ p1 ^3 z4 L9 XRNN和LSTM的区别2 `8 D- P# v* F. x# S
背景
, p' F4 N/ f4 q1 ?2 j复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验& M6 y" y, f$ X. }
熟悉用LSTM模型训练
+ n' T1 ~' _" s. Z) g! Y验证将时序数据 转化为分类问题后,预测是否有效果
: G" M, b& s5 e: K. p* X8 B; k对比SimpleRNN与LSTM模型 哪个效果最好?' m- |$ g' Q* k! p
验证LSTM相比于Dense()模型 是否有提升?
! L8 f& i" ~6 C$ @% k对比使用前3天的数据 和使用前1天的数据 哪个效果最好?8 x# h. D/ e! d* A1 b. l$ k- x! D; D
结论4 j, [, T4 C& q0 c. V8 q
使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好. M, d- ]1 l, ]% o
使用LSTM的效果优于SimpleRNN2 }8 Q6 {: U. l+ X1 X5 W( Y# o6 D9 b
代码0 M0 j* u" Q( G. d
from pandas import read_csv4 U3 g, i. C! l9 J9 h
from datetime import datetime
" _( n. b3 I" P+ P8 C5 n$ J& Z; eimport pandas as pd5 ]) z' u! t& r. h
from pandas import DataFrame4 R% L6 f+ W# Q' o0 n# Z
from sklearn.preprocessing import LabelEncoder,MinMaxScaler! |. g( L# i5 K* A4 L# P
from sklearn.metrics import mean_squared_error0 x* B& S. l5 s
from keras.models import Sequential# G/ F. S7 Y/ q/ P- s( L
from keras.layers import Dense, Dropout
8 M2 z- y: L+ f4 m' o& zfrom keras.layers import LSTM
|: n; I$ s+ u& Xfrom keras.layers.recurrent import SimpleRNN: F1 L, Q1 K5 t9 ?! _
from numpy import concatenate
% `2 V% ?9 u, x0 A/ _from math import sqrt
- r- P6 Q( V% T) ]
/ u* {0 y# g) z8 K) D& k3 z( I# ]# N( r t+ P$ u
7 \7 b* z2 }! N0 c7 W
/ V7 z1 C$ N0 n5 ~0 Z. Z" ?/ V# load data( u% ~+ d8 a. J- P! O6 w" e
def parse(x):" ?$ u7 V- s# G* \
return datetime.strptime(x, '%Y %m %d %H')
7 ?* }- V9 f0 a9 X * Z6 \8 z1 W3 p) Z- x
def read_raw():
' f, r. N4 v% u" ~, I dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
" U1 F0 B7 J* `; d' @2 Y+ R dataset.drop('No', axis=1, inplace=True)7 w+ }( F( ~& ?, v
# manually specify column names2 V7 z4 o9 R9 w
dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
- J$ I s- V% y5 t$ p; T' z8 g dataset.index.name = 'date'
, a2 v+ b8 G2 H4 H: Q1 M6 K; z # mark all NA values with 0
; O x2 r5 \; A dataset['pollution'].fillna(0, inplace=True)$ _& n; c& B9 p# s! Z# @9 j: {
# drop the first 24 hours; D) h: ?- L! F8 R9 N3 \( b2 P
dataset = dataset[24:]
( O/ T3 i" c- a% e/ r! }: j # summarize first 5 rows) T( u0 K" A' Z3 ?# z
print(dataset.head(5))
; T+ b4 ^ ^8 ~4 ~9 ^. y # save to file: u \, D+ f2 y: {% t
dataset.to_csv('pollution.csv')+ B* Y4 M7 W5 a, N$ h S( C
0 S5 M, g1 V( s+ I2 Y* {; W1 G/ `) i9 j
- t7 B8 l& |# t; J/ J
: ]/ \4 b6 D; y4 _% G5 j) H# convert series to supervised learning: y* n! B6 r$ _* v0 i
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):8 _9 d% S( ~+ ?) M N/ i- Z
n_vars = 1 if type(data) is list else data.shape[1]
! @3 N h. X8 }+ H; a/ Z3 o# A. t df = DataFrame(data)2 |, a, v" h- R" Z2 X# K
cols, names = list(), list()/ Q9 Q& b; I3 `" L/ h# o7 i
# input sequence (t-n, ... t-1)$ @2 r' d6 Z1 Y2 |/ ]9 z6 m! V
for i in range(n_in, 0, -1):
9 E6 s s/ O3 L3 h& J, T2 U; d cols.append(df.shift(i))0 U6 ?5 \" R% w9 W" m7 C
names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
+ V" @% r6 t6 v: ^/ w # forecast sequence (t, t+1, ... t+n)% j9 i7 ?+ T, u* Y/ f! T9 F
for i in range(0, n_out):" T! [, S8 t/ J1 ~
cols.append(df.shift(-i)), \; s4 A) \' G2 B+ N* F
if i == 0:
( e( b* L3 j. L) a4 ^! O+ F4 r/ f names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
8 Z1 p: B; ]6 R: W else: Y4 l" s1 X7 W# o
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
8 Q; Z$ k* \) o) W # put it all together; ^8 P9 r# K5 H3 i/ f
agg = pd.concat(cols, axis=1)
+ B. ?8 W: C) T" J! e) W agg.columns = names
9 {/ t4 x' @2 @4 e" @ # drop rows with NaN values
2 D, d$ H- R+ t if dropnan:% e/ l( y, e! B; p+ C
agg.dropna(inplace=True)& W' \6 `; _ Y( H* f
return agg6 E. U$ ~2 P( m5 ]' n
2 i; z% }" H2 k9 x( U
# load dataset
2 s7 ^# ~3 s% t( E7 p$ z- d7 {" d+ Kdataset = read_csv('pollution.csv', header=0, index_col=0)2 o8 O& E. R# `$ p& o: h3 Q. s
values = dataset.values
$ H7 }' Z a: K: o5 y3 ?0 ~& [2 f, V, T+ c6 ~
2 n7 g) }1 o& H6 F# integer encode direction
" x/ `$ |. w/ Aencoder = LabelEncoder()
' n: W, F) H4 ?5 X& G! B& Sprint(values[:,4]); T Z$ J4 g* d% |2 }
values[:,4] = encoder.fit_transform(values[:,4])
; s- R# S- A! R3 {# ensure all data is float
, G% c4 C/ W% _6 u8 G2 Bvalues = values.astype('float32') m8 `4 X, ^9 ^8 W; g
# normalize features# k- b, x# [5 ?% j
scaler = MinMaxScaler(feature_range=(0, 1))
. ]. u1 m# x/ ~7 x0 k5 V' Dscaled = scaler.fit_transform(values), W- b; _& c; h/ q
# frame as supervised learning
% U* y. ` W. T' C y% |reframed = series_to_supervised(scaled, 1, 1) & D) W( r9 z: q- d( c/ `
#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
. W$ b! I7 _$ n L' ~- ~print("columns:", reframed.columns) a ^) Q9 D! x5 j
# drop columns we don't want to predict) }9 ?; m( j. |/ k' T* w
reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据5 D `! H9 O3 b S+ R2 P: c' i
#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
" T2 y& F' E( a7 Eprint(reframed.head())
: }" b6 }2 O( B. c! n Vprint("new columns:", reframed.columns) [/ Z' V6 \' h% Q [, D* _
# split into train and test sets
' W1 ^# C/ V" |: l _values = reframed.values2 w' x& I* W/ A, l2 Z Y
n_train_hours = 365 * 24
# q, F+ r; e. n! f& e" G3 h! G# ptrain = values[:n_train_hours, :]
3 h3 w0 j8 H- n* n; x& m0 ?test = values[n_train_hours:, :]
5 L" b4 G0 r$ Q* q3 f3 [9 `# split into input and outputs
) r$ y4 x+ @% C+ t) [$ I* I( mtrain_X, train_y = train[:, :-1], train[:, -1]
* ?: H, M1 K/ I6 X- jtest_X, test_y = test[:, :-1], test[:, -1]6 l( P2 u% l, l5 [/ z
# reshape input to be 3D [samples, timesteps, features]# K, O- d% n# \- e
#使用Dense()模型时不用变换, O7 K; G, C( ^0 N% y% I( M
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
$ M' x% O/ E, W! \ p/ }9 V/ D ktest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))# q8 m! j# q& [) F; x
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
; V, V% W# ~: Y: p" x/ ^# design network3 s, s; [- m* x4 v7 [2 d
model = Sequential()% T& x+ w" V) E G8 \
#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))) A1 t7 P/ c! V$ p$ z
#model.add(Dense(50, activation='relu', input_dim = 8))" P2 x& l1 b8 M3 ]2 S. `
model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
# S6 W* l+ @' l$ N( e4 u( Umodel.add(Dense(1))9 o4 J; w8 [; f( g; p% H2 }
model.compile(loss='mae', optimizer='adam')
" t- h/ N7 M8 B# fit network: P% v9 d! b: o+ w) f3 n }
history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)& H: B+ f: ^; y9 c: R' c
# make a prediction" l& z8 h9 c' H* p
yhat = model.predict(test_X)( i+ B- s; L& f1 X
print("yhat shape:", yhat.shape)
4 T7 F: [! W* l'''
" g/ ~: G! w% E& ~7 t* Z计算在测试集上的均方差; L. w8 M, C2 I+ w- O8 |& l
test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))* f% [/ ]9 m' X2 u% ~- U! b
print("test_X shape:", test_X.shape)! U; ]8 B4 j9 ~- k7 _) D, F2 r
7 B6 R1 Z% D" _$ {3 C
! e( O) h" r7 k( ?" e9 m- O
# invert scaling for forecast
# h% \5 J8 g2 B- @2 |inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)# i1 l5 c; ^8 [; H& K
inv_yhat = scaler.inverse_transform(inv_yhat)
# ^# U2 p. n! W/ d" t, \inv_yhat = inv_yhat[:,0]4 }- E8 t. u! F
# invert scaling for actual
# i4 y* s# ` u4 v* }test_y = test_y.reshape((len(test_y), 1))# x- s9 n! V/ l
inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)( T9 a* I, u, v; T8 R0 y" Y1 Y
print("inv_y:", inv_y[:10])
+ J0 E/ }, V- pprint("inv_y shape:", inv_y.shape)) m8 s& Q) N" S9 k7 k/ [
; s5 ]/ e3 w# I" m1 s- o
4 c9 x; u- A3 ]: S
inv_y = scaler.inverse_transform(inv_y): ~( c6 l: G) P% {
print(inv_y, "*"*30)
% d- y1 H" \ e# M2 |) N) ~/ Y3 x$ b! I
) m# E. u2 V$ M
inv_y = inv_y[:,0]2 D( B* r2 N) z @9 D3 s3 J) P
# calculate RMSE" d+ w ]" `' Y! O; l
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
* D% E3 N# p9 Iprint(inv_y[:100], inv_yhat[:100])
! ~) ?: z2 N; u1 {+ Qprint('Test RMSE: %.3f' % rmse); v7 E% f" B. p0 m9 r
) s. ~$ F, I/ U; z# i
% x7 O) }. D8 W. s9 W2 ~( Y1 R k2 `
'''- t9 l6 \) A; @; Q F& b% z
实验结果
* q# r2 n9 ^8 ~4 Y6 [实验1:用前一天的天气数据,预测某一天的空气质量0 y4 y7 O7 r0 f' K5 o4 X
使用LSTM模型 W# l3 ` W6 j' U# f' m* @8 N
结果:* i$ a2 R, Q+ @+ E b( A S7 Q% {4 ]
Epoch 49/50
8 T0 ]1 _. V% D( X( ?# a0s - loss: 0.0144 - val_loss: 0.0133
7 W( @; M+ e4 yEpoch 50/50
; D: G( `/ Q- F9 K& l" Y0s - loss: 0.0144 - val_loss: 0.0133
$ f2 w( V* G$ S1 ^
; w" Y9 k7 E+ {: `% O5 U0 D
4 w/ M( x5 I0 Q3 M( _' d实验2:用前3天的天气数据,预测某一天的空气质量: A/ O9 r2 P9 C$ t' T7 M, b, d
使用LSTM模型
3 g- P, {) J5 x( B% [! T
: G* p3 w5 K( P5 i. n
8 |/ R( p% q* p8 I% A结果: Q" r9 K# j% |' E5 N
Epoch 49/507 d' M6 N7 u* Y7 l5 k
0s - loss: 0.0147 - val_loss: 0.0149( R, ?0 q7 Z' b& e+ f6 k
Epoch 50/50
! K" D: _$ }- I% e0s - loss: 0.0147 - val_loss: 0.0150. r6 R2 f# S0 m
m5 a) V: u$ y/ ?
0 ^ D, |+ k8 d N0 M6 l* Y实验3:用前一天的天气数据,预测某一天的空气质量7 A: c# S1 {, n+ j' `3 |$ E
使用普通的全连接模型 Dense()
, E8 t" H( ]& V8 [7 C" d结果:1 f2 k; E7 i: V8 F& @- D
Epoch 49/506 Y9 \$ E9 G1 a: D; ]5 }$ T- L" h
0s - loss: 0.0144 - val_loss: 0.01465 ^) t" P( ~8 d( u2 U1 S
Epoch 50/504 q; `$ h q: T! i9 V
0s - loss: 0.0148 - val_loss: 0.0151
1 `2 ~6 F2 U) m7 s0 m" X: s& c
1 \9 q" b5 q' C) a) m& d$ u% |6 j& [0 V F" [
实验4:用前三天的天气数据,预测某一天的空气质量5 Z4 J3 ]: Y' ?$ Z
使用普通的全连接模型 Dense()
( b" B- r0 W6 x& c7 P结果:
/ Y) z4 f0 a3 N" S% M. m, w% e9 B/ dEpoch 49/50
5 @' }0 z/ h( E2 z2 K+ I0s - loss: 0.0150 - val_loss: 0.01651 U4 j0 v, I6 m
Epoch 50/50
9 n z8 j6 p+ K0 q% s+ e! W0s - loss: 0.0148 - val_loss: 0.0141- b/ n0 L: q" u! C; z- H% t
: `+ B7 Y1 Y9 B) {/ @; K
2 @2 [) o/ v% Q' _
实验5:用前一天的天气数据,预测某一天的空气质量& D I- h K0 l. S
使用SimpleRNN
! o' o+ `3 R) Y0 kEpoch 49/50! B9 E: x, t+ f, q! O& V
0s - loss: 0.0160 - val_loss: 0.0140' U& m% }9 J) |6 }/ b
Epoch 50/50
: Z+ }: u7 D# Z0s - loss: 0.0147 - val_loss: 0.0150 P* n- T- Z9 H( K
, ^3 W. N- ^6 C! k* d2 y% M7 ~
2 x! c! N* t& g8 b8 f4 z实验6:用前三天的天气数据,预测某一天的空气质量* v% W! l- ^! U8 I
使用SimpleRNN
/ ^7 Q1 w/ u! H9 |* b" p' yEpoch 49/50; A- D" ~- L9 M0 v
0s - loss: 0.0164 - val_loss: 0.0233
0 g+ |" \) ~* u& Z q. c* A' _9 uEpoch 50/50
# C& N3 X5 v0 b' w$ @0s - loss: 0.0166 - val_loss: 0.02277 o+ d6 j, B. B: c6 |
RNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。 5 v0 G6 P9 g+ b4 Y4 W$ d
![]()
# P9 L1 L; ?6 F- s
* h5 ]3 {# O. e) d3 n1 QRNN和LSTM的区别
; ^9 w1 e- _2 Q9 c0 d* MLSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
9 X) c; T- d' G a' ~9 ^ O+ O I: _ }4 ?
( x6 D% H1 s0 d: l但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。
# F& k/ B% {# ?. k![]()
3 ?* j% e$ u2 q9 x( e8 w7 A: {1 e; h' L/ I1 i" C9 \
请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
) Q1 ^1 L1 }1 F% q+ G3 J0 Z' M) C
+ M' A \' C' a6 k. A7 Q0 }8 p' I* U/ O( I# L% g
|
zan
|