- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40300 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12801
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1419
- 主题
- 1178
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
|---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
 |
使用LSTM预测时间序列数据
# Y) x: g/ b& a2 A' W/ m& T( q7 I1 G
. k8 v B6 K! C c B文章目录
" m8 q; T, |4 i0 l背景
7 @; E+ {& F5 l G结论4 K% V& I6 l. l
代码2 k0 H5 K+ Y' R3 X! F1 t- ]: N r4 J
实验结果7 E V' D* P. _$ ^( z
RNN和DNN的区别
' a& j0 I* T, @. IRNN和LSTM的区别
. Y8 V3 @3 N; V* O背景
4 X: P2 G4 R: j复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验/ B5 t# Y6 ]" V4 L& b
熟悉用LSTM模型训练8 y+ H/ ^5 S. o' S8 X+ T
验证将时序数据 转化为分类问题后,预测是否有效果
8 F! @8 q6 D3 d' T对比SimpleRNN与LSTM模型 哪个效果最好?' ]: |7 r* D2 [: ~1 R4 h1 t
验证LSTM相比于Dense()模型 是否有提升?
( O- ]! A5 Z3 i" O对比使用前3天的数据 和使用前1天的数据 哪个效果最好?
& f: R* K& r5 M结论6 S- o/ R: a) o: [7 E d: _
使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好1 L1 y6 S7 K5 S* Y
使用LSTM的效果优于SimpleRNN8 }/ I! R/ U$ v$ @' A; c6 J
代码
& l1 V. {) @9 b4 J6 t8 A6 lfrom pandas import read_csv+ J) k+ q, f @, v7 ^" \
from datetime import datetime5 L w: C, D6 [' X
import pandas as pd
2 s# U" q: I% U6 V+ A qfrom pandas import DataFrame, Q5 K: \6 r; H6 F) P! I
from sklearn.preprocessing import LabelEncoder,MinMaxScaler
0 p3 y& L6 g4 G$ ^$ Nfrom sklearn.metrics import mean_squared_error. F/ ^7 m0 W1 c+ Y
from keras.models import Sequential' `% S; P X2 M7 W! D/ W$ {3 b' ~4 o B
from keras.layers import Dense, Dropout; F' C7 K. i1 }4 U1 t) |
from keras.layers import LSTM
& @. j3 _* w; T% A) Ofrom keras.layers.recurrent import SimpleRNN
& o3 C# c4 ]' l+ M6 n) L8 a% bfrom numpy import concatenate
( W* N+ I+ K. O$ o9 y1 }from math import sqrt+ a1 K5 h% |! ]* O4 W
: B. X" G$ C; d+ ^
9 t0 @( i, L; G5 b. t& L6 x. f( c O
3 [2 u, d! N1 U5 S/ h# load data
7 ~( k& f8 Y! Ndef parse(x):
; R% `$ B! l. `# o return datetime.strptime(x, '%Y %m %d %H')' b9 y! _7 P) q e. h# O
' w% v; n/ C. F: @) w# gdef read_raw():" J1 b8 ?' L. F% v
dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
! t$ e, e/ L' j. k0 }3 r* g. \! P dataset.drop('No', axis=1, inplace=True)) v( `$ S3 y/ D G: q
# manually specify column names
f! H) b3 U, ]( W1 b7 \) l' g6 f$ @ dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
3 E3 x! u% J3 k1 `9 ~% b dataset.index.name = 'date'
1 v# L( Z; _+ a; g! i k # mark all NA values with 06 z2 f' Z( j: {$ u1 L
dataset['pollution'].fillna(0, inplace=True): a |& I E0 e+ t1 i9 X
# drop the first 24 hours4 g8 ^$ r/ @% F/ J: W# u7 l
dataset = dataset[24:]+ q8 ?. M$ N! I+ Y3 R9 n
# summarize first 5 rows
* r, L; F9 r+ g; ? print(dataset.head(5))
. M/ d/ V; L+ G0 m # save to file: |7 N, N- |7 w' v) K# t+ {$ k
dataset.to_csv('pollution.csv')
: G4 E3 |1 |7 K T' q
) k1 W! F2 z- ?) y2 _ g& y. U) z% ~5 d# p/ k% {' t6 H* S
! P) _. T H) \: u/ o" X* \! B- q3 f0 g0 w4 U8 z8 A, P: ?
# convert series to supervised learning1 s' r0 ~; L& U4 S# z; e$ q$ x
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
; f/ H( _5 c* v1 c% } n_vars = 1 if type(data) is list else data.shape[1], S3 ]7 p- n. J8 T' [ a5 a1 P1 @; h9 Y
df = DataFrame(data)6 |. d; n+ E( C7 P! v8 _& f& c8 m5 o
cols, names = list(), list()
+ M$ h$ z5 L% ~ # input sequence (t-n, ... t-1)
/ `, M& T! U, f/ z for i in range(n_in, 0, -1):8 p+ a4 g+ l& a7 Q, Y4 p
cols.append(df.shift(i))
$ x- o2 u: `; {7 r- ]6 F names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]0 }0 _6 k o+ q' q2 p
# forecast sequence (t, t+1, ... t+n)9 F. P+ L/ M1 v# N! S( W! M
for i in range(0, n_out):( {. N, m9 m& w
cols.append(df.shift(-i))
* P( _& |7 e* ~9 ^ if i == 0:# J9 H$ n4 F& O$ h. e6 X: ~& H1 p
names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
) |" l$ J* D2 n, W8 e7 o else:) F7 n/ K6 G& r4 t
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]3 H: @- k8 Q+ D) c& ?' u
# put it all together" M. ], v5 }/ N& Y, P5 R7 e# K1 Y
agg = pd.concat(cols, axis=1)% ^# L$ A d9 q! j M" J
agg.columns = names
! E3 C: k- V% R# f6 F) s6 B! k # drop rows with NaN values" U9 R. Y$ c$ X: c% T
if dropnan:
9 e' G; V( s' f agg.dropna(inplace=True)% ~) t; K2 n" A) T+ B( f
return agg! ?0 w- @$ E( M* M, {
, T: @6 _: x9 O8 ?# m# [, s: B/ ~# load dataset# S' E& c: S0 f5 d" A) b
dataset = read_csv('pollution.csv', header=0, index_col=0): p/ S: w1 s" M; _$ Z
values = dataset.values
4 [3 f! G( v. _; G; p& `# l6 r6 F" y
8 W6 Z% E8 t e
# integer encode direction9 S. |) P- _1 T7 H
encoder = LabelEncoder()9 X9 [, F, e3 U$ @7 n3 I) H* @, O O# X- h
print(values[:,4])
. i5 n3 D6 B' mvalues[:,4] = encoder.fit_transform(values[:,4])/ i/ R& e9 z7 ?& d$ O
# ensure all data is float$ i- f5 Q7 x) v7 C
values = values.astype('float32')0 T$ t3 ^& G" G7 l6 f5 o/ c& W) C
# normalize features
# w0 l% _" F3 O oscaler = MinMaxScaler(feature_range=(0, 1))
# B% _+ b$ \+ q* yscaled = scaler.fit_transform(values)
8 T P- O% d @* j) ~* p' j( b# frame as supervised learning
& j) o* T( q( t$ M0 z/ A6 Sreframed = series_to_supervised(scaled, 1, 1) . Z; K! x! ^" ?
#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据1 m# J+ Y% O! p' d- T
print("columns:", reframed.columns)
W ~& Y& J" A" g# drop columns we don't want to predict
' p G6 ~& r+ e% e6 l! [& ]4 W; G z! Ireframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据" V5 p+ W8 A; ]6 S" C( F
#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据! i( b9 A Q" y" q- }
print(reframed.head())* r1 ]3 e, N; e
print("new columns:", reframed.columns)% b2 w- _! s+ u" G5 Z9 s
# split into train and test sets1 [$ o) K" h, {; y$ B, K. Y) d
values = reframed.values
8 f/ o6 c7 R( t. c! s# r5 r+ d; en_train_hours = 365 * 24
8 b# N& }/ i* e2 Htrain = values[:n_train_hours, :]+ I4 p% D; S/ Y; F8 N. ?
test = values[n_train_hours:, :]- m+ V8 V4 h+ [: t( t. k
# split into input and outputs
O6 `! ?0 o. h& o& E: Otrain_X, train_y = train[:, :-1], train[:, -1]' l8 g& j) O7 V' n2 }' Q, j
test_X, test_y = test[:, :-1], test[:, -1]+ P" j. [- p+ |
# reshape input to be 3D [samples, timesteps, features]
: }/ d% K. H3 e7 I W#使用Dense()模型时不用变换
j* v% v+ b+ strain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
1 ^8 A( n1 }% htest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))* b9 N& c0 ~6 n6 \4 Y
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
8 F( g, O0 ?; n/ O; l1 Q5 p- j& [/ o# design network
1 K T- Z O/ h- i2 N2 \0 K# cmodel = Sequential()
8 A b. S6 B* \) w) R& X#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))' k. g1 e( ~, c3 o' g, M5 D$ _$ H
#model.add(Dense(50, activation='relu', input_dim = 8))
4 U- D0 H; I) B" L9 Z! F( R' Smodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
0 F o- @7 X( |( Jmodel.add(Dense(1))
& _% F. r4 i% Rmodel.compile(loss='mae', optimizer='adam')# A2 ~1 `) ~9 t2 @6 F4 w
# fit network) y8 z0 Y: N8 B% w2 H5 _* {
history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False). {1 _) M0 s- O/ P$ V* z5 h# {+ n
# make a prediction
' c; \ b- X; r' t, c* M3 [yhat = model.predict(test_X)' h# n1 y' {% p; w8 E' p8 V
print("yhat shape:", yhat.shape)- |3 A9 X( l# u
'''
- Z5 T, ~# G, P) Z; ~. F* {9 i" a. {计算在测试集上的均方差
: Q' d7 [' S1 d6 ] D" w. rtest_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))6 \4 i' L# J* s E ]
print("test_X shape:", test_X.shape)
3 y+ X' m( l5 h- v
# H5 j7 _# \: `3 M% @. {9 f
" S" s# M# }8 ]' F# invert scaling for forecast: r2 c3 J: Z( d1 S; L
inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
# x4 a6 W4 ^: kinv_yhat = scaler.inverse_transform(inv_yhat)8 ]( o9 F8 `& Z
inv_yhat = inv_yhat[:,0]
& ?5 l; G: V: C9 @2 U0 o+ N# invert scaling for actual- M: I; p E* Q& b2 U* _9 m l
test_y = test_y.reshape((len(test_y), 1))
; }: }8 Y6 h2 E2 ainv_y = concatenate((test_y, test_X[:, 1:]), axis=1)' V+ b! Q8 b' h" V
print("inv_y:", inv_y[:10])
" n; O, G) ~* T% D$ e+ D. bprint("inv_y shape:", inv_y.shape)
. B+ g1 n& c4 R8 [+ O$ N
; z$ L6 N8 k( l8 A* K, b" h5 A( J% z& b( g
inv_y = scaler.inverse_transform(inv_y)
) ?7 s$ G; N+ cprint(inv_y, "*"*30)1 G2 K @. m- Z8 h
4 v4 N+ R6 s1 [9 u( Q2 F( L
& A" n2 M8 O2 p! I. N9 s4 G5 j: Cinv_y = inv_y[:,0] B" r' I8 ]' `+ F4 Z. T; C: @
# calculate RMSE
$ O' g$ c( ^7 Drmse = sqrt(mean_squared_error(inv_y, inv_yhat))
* w" @) k8 [# Lprint(inv_y[:100], inv_yhat[:100])
* v7 U6 A2 {) P& Y: z& Yprint('Test RMSE: %.3f' % rmse)
O6 c O" ~& R( D% r, D) p0 l1 g( b" o( _9 ]& U
3 F3 c8 H& g5 U- j; ]; L2 g2 J9 r0 ?'''
& g) Y5 r" j M实验结果% P& S) t# Q$ g3 H8 P1 k6 n. a2 M
实验1:用前一天的天气数据,预测某一天的空气质量
' Z' h3 V5 u5 z3 F+ e: b9 J/ V) d# _3 }使用LSTM模型' F5 j- N' C4 W0 U v4 v8 T
结果:3 c+ v! A/ l) h% d6 r5 B
Epoch 49/50/ }9 m. ?$ P: d. i4 ^8 Y: L
0s - loss: 0.0144 - val_loss: 0.0133* x( i/ \( s7 V9 Q5 L: S
Epoch 50/50
7 N9 u6 u$ N f. W0s - loss: 0.0144 - val_loss: 0.01332 N% p, [2 S( ?
$ W4 i9 V( c& |; v: y* z) B* s+ ?3 f+ A
实验2:用前3天的天气数据,预测某一天的空气质量
0 s" X+ {9 e1 {! l使用LSTM模型8 B! H9 H% y5 K% _
+ K3 z/ o/ q! z% ?6 S- ^( E' v0 Q e! m- A/ H2 E
结果:2 j1 ?) ^9 p- v+ r) ]) _9 V
Epoch 49/50
7 O5 w8 V$ A! T5 |4 z5 u4 D7 D0s - loss: 0.0147 - val_loss: 0.01491 {; D% U8 K( U J1 i
Epoch 50/50
& P! Y* u+ N6 z7 W# M* [0s - loss: 0.0147 - val_loss: 0.0150
+ y' ]. F, B4 J
y' r% \9 W0 r2 D( T) @( S1 U2 K- j. q) k
实验3:用前一天的天气数据,预测某一天的空气质量/ H, @7 \! r$ d% ~9 p& _1 n
使用普通的全连接模型 Dense()( q+ W3 j1 ]3 X! X6 t
结果:' l: |3 C! Z+ ^3 D, V' `
Epoch 49/50
7 _! E7 r+ b; A% g: ?- B0s - loss: 0.0144 - val_loss: 0.0146, T9 b$ d% _- {( s9 }" L
Epoch 50/50' K7 u5 e( w3 O, J5 V
0s - loss: 0.0148 - val_loss: 0.0151
9 \5 A0 c: e- @/ \0 K& a% P* d( o" o, W
4 t- }6 D! J$ |/ S
) }: H G3 p* v6 K" \5 C! @/ b实验4:用前三天的天气数据,预测某一天的空气质量7 ~4 C; n: m1 C# \3 c2 V) d
使用普通的全连接模型 Dense()4 X+ {" g, y' ~+ j/ ^2 f! x
结果:9 d/ D& o. N6 B' p. a5 ]$ g% \
Epoch 49/50# r( y1 F" x7 d! [5 l& A! V" {
0s - loss: 0.0150 - val_loss: 0.01650 F l$ E3 D* }: C* S
Epoch 50/50
9 Y1 g0 X! Z, C+ W& h- z4 n0s - loss: 0.0148 - val_loss: 0.0141
( N' b& O5 Q+ Q2 V
m4 x( A7 C3 F+ q x+ Z: V2 d' @, Y( i+ O: T9 R9 y
实验5:用前一天的天气数据,预测某一天的空气质量
! \1 X1 ~- i% [4 {0 G% i V) ~使用SimpleRNN
* }# [: ]3 r; l: f& uEpoch 49/50
# ] t8 W& c. a0 l, j8 g# e4 M0s - loss: 0.0160 - val_loss: 0.0140
/ z* U/ P. f' U/ B) X0 Y! x+ vEpoch 50/50% k% C3 y% |5 C/ \& x
0s - loss: 0.0147 - val_loss: 0.01500 O* S! \. }6 [8 l; e$ }$ P c
$ H) ^0 \7 g; l( z" _" Q
5 t9 y* Z- `* {8 d6 O2 `实验6:用前三天的天气数据,预测某一天的空气质量
8 L4 Z" _5 R" b使用SimpleRNN: d2 o. |7 k: n6 J
Epoch 49/50
' X# o7 @1 f" U0s - loss: 0.0164 - val_loss: 0.0233
7 Y. N" E% }. H4 [9 ]9 ^Epoch 50/50
) P9 h/ r1 H4 @3 j3 @0s - loss: 0.0166 - val_loss: 0.0227/ R- H' a( C( i2 q/ n5 C
RNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。 ) \' F/ w7 `7 M8 D' q$ ?! q) b
![]()
+ o4 m/ F4 B5 V. r& M2 T/ p4 G+ J/ @. S$ y
RNN和LSTM的区别' Y( s% V8 k k0 D- G6 ]: M& ~
LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。% {1 `' l3 H5 ]) H# h2 {
% N2 P2 _% P: \; G5 v, r3 ^
2 B0 p/ D% t( r3 h9 L7 b但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。1 \! j. c, b" l$ M9 a
![]()
! m1 K2 v" g7 i$ M
7 q+ b- Y+ N; C请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
% w; i4 Q3 o4 S$ d" f
, N7 ]' U4 G- b+ V) c2 v) q! h. {! d- ?9 u
|
zan
|