- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40301 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12801
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1419
- 主题
- 1178
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
|---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
 |
使用LSTM预测时间序列数据
% B; l4 J& p* E% n
' T8 V( {, g G- I
9 j% n% T- D% h! _. X) p6 c. k文章目录
$ E7 i& w2 C' H6 T! j背景. C! X: F. `2 Y( [+ m: I% W8 {
结论9 m* {3 b' G9 r! {( y7 @
代码
) w, l8 v2 e- F; Y- m实验结果
: [! D! j3 S y1 M! PRNN和DNN的区别, Q" x& Y9 x" ?) v! n7 ^+ R
RNN和LSTM的区别
& Q7 o# K9 ?7 v0 [4 ~背景/ j# s9 a u W: s" N K
复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验
( A( R9 E0 h5 Y7 S4 g0 F9 i, c熟悉用LSTM模型训练. J: P& D; ^, o, u+ q+ o
验证将时序数据 转化为分类问题后,预测是否有效果
2 l; _+ S* X6 g+ q: x3 R5 b对比SimpleRNN与LSTM模型 哪个效果最好?
: m/ j, I Z" ?8 G& L8 f9 e$ H验证LSTM相比于Dense()模型 是否有提升?
' L. ], b) F5 S# y3 E; A7 q( V对比使用前3天的数据 和使用前1天的数据 哪个效果最好?
E2 t5 a. J% p! _结论
5 T. y- C7 ]. }: S( d7 d3 j使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好6 G- e3 ~7 i5 }( D- g/ x; Z Q Q
使用LSTM的效果优于SimpleRNN
. F5 m( W: P$ S& X6 m* w5 y代码: ?: I W( K3 q1 _- A+ O; \
from pandas import read_csv
) n. g# ^& R# Y% dfrom datetime import datetime7 C- _$ `/ W4 R+ M$ c D6 m+ A
import pandas as pd
H l9 L- o8 Jfrom pandas import DataFrame
! U7 j- R0 [' F7 N' rfrom sklearn.preprocessing import LabelEncoder,MinMaxScaler
; j3 ?3 U- S' R; j7 X- _9 ~; xfrom sklearn.metrics import mean_squared_error2 M8 D9 L/ C/ b2 e+ D
from keras.models import Sequential7 H6 V1 \8 y* J: a) m5 N A
from keras.layers import Dense, Dropout) d) ~) l7 [1 R" z, h
from keras.layers import LSTM
# h; m8 m7 ~+ Sfrom keras.layers.recurrent import SimpleRNN
- F. V) F7 y. L" ?2 Q! a m1 i9 U7 Yfrom numpy import concatenate
. x. E8 i- n/ m5 @+ {from math import sqrt$ w3 |1 n% v! q; ] e
) z0 `7 t4 m& R# `9 m0 P
/ Q" g9 I8 Q+ X+ b) r+ r! ~7 h
: T! e1 L9 k9 _( F) Y% u8 N; k' p }) f% Z8 Z
# load data+ q6 V* v' L! W/ D1 i
def parse(x):- t1 N6 b6 ^4 W% L. d- {' l0 z
return datetime.strptime(x, '%Y %m %d %H')
6 O! p, `$ \! H0 |+ a0 a $ H, N* f2 `" I1 u% j! ^; `
def read_raw():! H; \+ J/ x( L7 |
dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse), T+ E( q% F; O7 |3 j
dataset.drop('No', axis=1, inplace=True)
: c3 J1 S& k! N # manually specify column names
# \# _! J8 O4 w3 K7 \: P9 R4 ~3 i dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
* F! k2 v |: d U* ^+ y: \6 o1 u& f0 g dataset.index.name = 'date'' ?, n4 R$ m+ a: F t' x
# mark all NA values with 0( J/ O8 d4 @: M
dataset['pollution'].fillna(0, inplace=True)
3 g) V F8 N$ w* [( e0 t7 A6 f c # drop the first 24 hours
5 y( L- Y, E, x$ f$ |8 [ dataset = dataset[24:]& L. @# y3 V! h. m: x
# summarize first 5 rows
1 B2 n: e4 i" G X i print(dataset.head(5)) ^) Z0 E! j- X- v) u$ n3 l
# save to file# K0 x, V8 |5 P7 Y% y7 G
dataset.to_csv('pollution.csv')- n: G$ p# h0 x1 z3 _5 J: t1 w
9 P0 z- h: s1 S
; i% C0 f9 P2 S, u+ W( `
; q" C8 ?! Z e7 G1 c P& E' h# Q! N( p: _5 A
# convert series to supervised learning
4 F: x1 o& _3 F& Fdef series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
$ i7 m, B' ~9 Y n_vars = 1 if type(data) is list else data.shape[1]
* @) x Q2 P _: ~( O df = DataFrame(data)
1 W5 G2 y. z4 n/ \. a5 B cols, names = list(), list()1 k# |: r* I- @# }9 m' Y
# input sequence (t-n, ... t-1)
5 y6 o" N3 G1 \! _6 K+ H: A for i in range(n_in, 0, -1):8 U# ]' O2 H: U
cols.append(df.shift(i))
5 `. d( y# G9 M5 c0 v names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
% Q6 M% I* l3 p& Y' n! A2 u( L # forecast sequence (t, t+1, ... t+n)
6 S; r4 r" P5 }4 R- n3 h for i in range(0, n_out):
1 A/ t; r2 t6 ~3 z" O0 }$ b; o" P cols.append(df.shift(-i))/ K- C! ?5 n4 K
if i == 0:/ e$ T' v' Y; v# i6 I1 m) N
names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
' P' e% D( v1 }% e ` else:
! c! o- a0 Z: z, O e+ w) j# d2 L names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]' p0 @( W3 o0 E: S' Z
# put it all together
! Y/ |5 ^2 k9 O m8 J agg = pd.concat(cols, axis=1)
) f4 d$ `) G% }6 f& s2 A2 h agg.columns = names1 k% i( w* `0 k1 [" P* P2 ?
# drop rows with NaN values% G# w1 \# g$ }9 u
if dropnan:
; r+ X0 \1 e& f) G agg.dropna(inplace=True)) d( U7 P+ E1 F( V' t; b, p) ~
return agg7 s" X# s6 V2 Y
5 q" ]% w0 X y8 k! w! C# load dataset/ r6 P5 L* x9 s4 D; H, Q( } E8 I
dataset = read_csv('pollution.csv', header=0, index_col=0)
" C" Z4 v) H5 `1 w/ H% y/ Xvalues = dataset.values
* r4 n C: D( [3 r# B
; e$ v9 F' t4 w6 K% r
{) v+ M6 S0 E, p- F1 b# integer encode direction
8 J9 a1 z$ x. \0 Aencoder = LabelEncoder()
1 l4 E8 {# o4 H7 p5 p) q( ^' S# rprint(values[:,4])0 F6 D+ d" W- C9 T
values[:,4] = encoder.fit_transform(values[:,4])) p) G8 w6 U1 q1 l6 `( [
# ensure all data is float
% O' x4 @4 ^# K0 y2 E1 h1 gvalues = values.astype('float32')
4 \- H% R% H: E5 q. a8 }3 E# normalize features: v, Y' ~1 q9 u) q0 W) \/ \
scaler = MinMaxScaler(feature_range=(0, 1))- }! v" m _1 H
scaled = scaler.fit_transform(values)
/ ]- a/ |' g# `: B6 l2 P' C M# frame as supervised learning% J" Q- g$ }- P& V0 B
reframed = series_to_supervised(scaled, 1, 1) * E6 ?( {' g7 e1 c2 m
#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
8 s$ R; Q: [4 a6 D5 w" g7 Qprint("columns:", reframed.columns)+ k `9 K; E: G$ y- z4 A0 y
# drop columns we don't want to predict
p: O# D# V! G1 _- preframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
$ m- u' l" `$ K#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
) p8 Y) E7 h% e, o$ M2 s) ^$ p. \print(reframed.head())
1 x! J" B- X/ b- k6 r; uprint("new columns:", reframed.columns)
1 q# _5 W# c- S: h( r+ C# split into train and test sets! H2 C/ O- p$ ^
values = reframed.values
/ f* c1 T- R) y! K3 Wn_train_hours = 365 * 242 @# e) [" ]' ~6 g# Q- V& P# W
train = values[:n_train_hours, :]" `/ P) e; C1 r( q
test = values[n_train_hours:, :] l* v6 Q: G' y7 X y
# split into input and outputs# p/ G, C8 w! y/ ]5 Z( h
train_X, train_y = train[:, :-1], train[:, -1]
% @# w) W7 \& Mtest_X, test_y = test[:, :-1], test[:, -1]
% w; @( e# D m' }# reshape input to be 3D [samples, timesteps, features]& q0 O' f- A( `# Q% [
#使用Dense()模型时不用变换9 }9 F) U" h' I I5 c; T1 I
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))4 W4 [, n) u. O/ n" c3 U
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))" z9 X+ a9 T$ {, H8 {) f$ I {5 z
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)4 H( r5 o- y! @
# design network
. h9 c) q \1 P& G- Mmodel = Sequential()+ m' j& g: I2 ~# F Q% I6 }' k% u
#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
6 k5 k% G6 Z; o' T( B3 v+ a. _#model.add(Dense(50, activation='relu', input_dim = 8))& z0 F2 t1 h- q, N: i
model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
' G+ X u' J' q: ?model.add(Dense(1))
4 `* |3 i7 U- e# Wmodel.compile(loss='mae', optimizer='adam')
. Y$ g9 r6 j/ j1 A3 @2 Q" n# [# fit network& j9 r: X* n4 ~
history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
( _% a0 [3 _. Q! m' b' ]8 P# make a prediction
" P }$ S/ G9 Tyhat = model.predict(test_X)
: D' y, E( e4 ^# ?/ Lprint("yhat shape:", yhat.shape)
- a/ J9 L6 o! v: m% S( T% {'''# i& L0 x" A# G
计算在测试集上的均方差, C+ O7 O: t# D) H! A* o- w( J# }% ]
test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))6 Q* M$ v7 n2 }: h+ q- }9 a
print("test_X shape:", test_X.shape)
# _; t) u( v6 D/ A% `% O, ?" Y2 ]
9 M4 p' D; L. }3 D5 V& a
# invert scaling for forecast& p% y# P) d% n& S$ _6 v( n8 `
inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
' F$ ~6 y% V3 w4 W ^4 g# p) e8 Ginv_yhat = scaler.inverse_transform(inv_yhat)
0 \1 M' S8 _1 r& C$ Y& _inv_yhat = inv_yhat[:,0]0 }: G- F7 `) X! J. x) W! T
# invert scaling for actual
+ ^9 h7 H1 k+ ?4 w; \test_y = test_y.reshape((len(test_y), 1)): ]! A% ]7 Q1 W
inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)
# M; P W9 a- L+ ~print("inv_y:", inv_y[:10])8 Y# _/ r9 X8 h+ T& y$ M
print("inv_y shape:", inv_y.shape)
4 [; d1 b$ h t/ }% R0 k6 Q
5 b, z" W; L% @( R9 i
3 o! q7 X3 o; B, l. C4 L7 `4 oinv_y = scaler.inverse_transform(inv_y) q5 K# k6 F6 ~9 W4 c# T
print(inv_y, "*"*30)
8 P* z" \0 y: B s- w# f' u4 T8 M: v
: C0 I/ W9 g- ?0 z( d( zinv_y = inv_y[:,0]) A' v% A, ^; j- A' d$ a1 r! S/ k6 |
# calculate RMSE$ Y: L3 f1 z+ e) K9 q
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))( J; Q* z$ n5 m" ?& a3 M) P( J
print(inv_y[:100], inv_yhat[:100])
, o4 T) J% n* `# c" k! L' t" Bprint('Test RMSE: %.3f' % rmse)! V& d! v" o* o7 u$ q6 i; c
8 r3 J8 _: @2 H ~3 s6 R1 y3 {2 y) G
) v! [' S! z1 P# t8 w$ O" c'''
! n6 u" d$ G, E% @/ s( X实验结果+ v. r5 T0 a) G
实验1:用前一天的天气数据,预测某一天的空气质量
; I; v6 K4 a' Z" p使用LSTM模型
) J. T5 \3 l3 V& I/ L m结果:
9 _' t% p5 f% l2 b) X3 r% c5 }* EEpoch 49/50( t# D' n. D# g
0s - loss: 0.0144 - val_loss: 0.0133
( ~# b H9 k* N) ^- B6 GEpoch 50/50
. y& |0 E/ s% f2 w( Y$ [0s - loss: 0.0144 - val_loss: 0.0133
9 R& `' W- T8 U9 ^' ~1 X$ T: n3 Y4 k' A3 d
' `8 h7 g* `6 @- C$ j* B实验2:用前3天的天气数据,预测某一天的空气质量7 Z' H& e) T& o# n' m/ U
使用LSTM模型" @/ Q- F- f( r! G
$ A7 X" ?+ o+ l) P: y6 n- c K
9 j& C/ _0 @8 \" G" F4 v结果:
: {2 Y( A2 v LEpoch 49/50' a. N& {* m; O2 z
0s - loss: 0.0147 - val_loss: 0.0149
' n& z" ]( i s4 \' eEpoch 50/502 v& G- W9 v; A6 k: s* v: X
0s - loss: 0.0147 - val_loss: 0.0150
( s, y; x3 U& u' h* T( {) a' K* b& ?" P! U' t
- h) h6 J1 u% T/ M实验3:用前一天的天气数据,预测某一天的空气质量+ `2 N$ t& W" S6 }: s
使用普通的全连接模型 Dense(), a& }2 g+ D i0 e, p+ X
结果:
. o) E0 [; H* m$ _1 f' hEpoch 49/50, N" \8 s* d3 Y8 `+ C( k9 [4 R6 M
0s - loss: 0.0144 - val_loss: 0.01462 K, F/ V" B5 G' d* E
Epoch 50/50. I& M. k8 K2 g8 s e, C! e" w- k
0s - loss: 0.0148 - val_loss: 0.0151( z4 o/ q* \! f4 { Z7 o
, R- e4 @$ |" C& y H4 e% B
( w7 F8 k9 l5 Q6 w+ ]' n* ?实验4:用前三天的天气数据,预测某一天的空气质量
8 f! E. v; X/ e使用普通的全连接模型 Dense()+ D! K7 T% }2 ~9 M# ^. |, q
结果: i& X6 g+ a' @" O
Epoch 49/50/ X9 q& K* T+ K' @
0s - loss: 0.0150 - val_loss: 0.0165
' t; o1 T# x1 A3 \' O7 IEpoch 50/50# e5 S* g6 \3 V Y+ }- ^
0s - loss: 0.0148 - val_loss: 0.0141( a' X$ r/ D4 U3 C) R$ l' }2 J
& D' R* F; V# u% c4 r3 w X
2 [; V# z' @ U9 z5 P实验5:用前一天的天气数据,预测某一天的空气质量1 q; {8 U& O1 N
使用SimpleRNN" \7 \# y' q6 z. D! c
Epoch 49/50" C* j8 T; N+ R/ w, q5 |
0s - loss: 0.0160 - val_loss: 0.0140' i: g8 L; H: P5 a& F! S
Epoch 50/50
3 `+ H- d& b) h0s - loss: 0.0147 - val_loss: 0.0150
" O. O: p4 [; U3 ?% f h9 s9 I; M+ h7 v6 [% Y7 [3 y/ g
5 E0 R4 m9 @8 Q& B0 S5 D1 V实验6:用前三天的天气数据,预测某一天的空气质量
4 @3 ]1 h- ~ f5 k: m+ h使用SimpleRNN$ c$ V# \4 m n2 `# y0 e
Epoch 49/50
! @! C, }9 s W4 _. s! y0s - loss: 0.0164 - val_loss: 0.0233
$ Q# b9 ]% r7 z/ TEpoch 50/504 l4 f% u3 F! J& A
0s - loss: 0.0166 - val_loss: 0.0227/ F' f. v+ [1 r4 k
RNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。
( T+ M, R/ u& U6 _' N$ j5 C 1 g: g/ u, ]+ {" R, e% E
' n+ \6 s" U! qRNN和LSTM的区别" t% d3 u# @, d4 Z; d4 Z6 a% b
LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
2 r" j- C8 k& k" L2 i; `
# q d0 L0 f) t, }& {3 \/ ~
* l7 t4 _8 C- s但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。
8 u/ s! k( _6 b* g0 p+ {![]()
$ J$ M8 U9 f0 b, a7 a2 B
M5 Q: w3 [9 A9 | r; w请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员1 x7 s2 a5 z$ f$ \0 e
3 s. w( Z- {- @3 q3 s& z0 V
( U1 j6 E [1 B% P+ C8 I/ r
|
zan
|