- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40243 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12784
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1419
- 主题
- 1178
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
|---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
 |
使用LSTM预测时间序列数据" @! {8 g3 X, O
5 |+ I2 I1 }( p3 p7 |
; E, a1 N- O1 w1 @文章目录
1 V# Q5 u7 E5 k& _背景
/ C5 Z6 F* P/ w7 g& B! E结论
+ f( C, O& B- L: k: e. x. c% ?( K/ k! P代码
0 L& a' @ L2 ^( t( u实验结果
; _8 D N5 \- QRNN和DNN的区别
) a* B+ S/ a: wRNN和LSTM的区别7 S9 t) U' |" ^$ P
背景
/ m2 J6 a2 u" b M5 W复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验
& x' I, l6 D( m; Q/ B7 A熟悉用LSTM模型训练
& p0 K9 F: w0 i验证将时序数据 转化为分类问题后,预测是否有效果6 ^# T8 { O1 B C- Q+ N) a4 A+ H$ P
对比SimpleRNN与LSTM模型 哪个效果最好?
0 N7 Q% J# d; e) C, p! K验证LSTM相比于Dense()模型 是否有提升?- |5 T$ k7 ]0 Z7 e
对比使用前3天的数据 和使用前1天的数据 哪个效果最好?6 l) b/ \2 t/ I+ W( i- S/ \
结论
1 v6 w; n7 s: K使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好
3 j4 a& O2 d3 \/ Y5 X6 v/ U2 `使用LSTM的效果优于SimpleRNN) m9 l. q( i8 D5 }; g& c
代码6 J q. D5 q* j r9 }
from pandas import read_csv+ c" f- p1 i( [9 H2 {, w" b# j
from datetime import datetime
+ o* O$ C6 d$ A5 V$ L. k3 t% Uimport pandas as pd
' L& C$ L3 J. _ Efrom pandas import DataFrame9 g0 O8 N9 ], w5 e
from sklearn.preprocessing import LabelEncoder,MinMaxScaler7 u4 t2 {2 I% h+ p( x$ ^
from sklearn.metrics import mean_squared_error4 y5 i+ ?/ e% e3 W0 ]( y: }
from keras.models import Sequential6 X; g7 e: h9 A# `- S1 L& [
from keras.layers import Dense, Dropout
1 s7 \0 F& [, u3 pfrom keras.layers import LSTM3 R& o0 P: {. y3 h! E+ {, O( u) x: i
from keras.layers.recurrent import SimpleRNN
5 F& Q" u0 J+ b3 P6 y8 k* N* Q! Mfrom numpy import concatenate
& b/ j! Z: M/ }% jfrom math import sqrt k9 I0 X3 i& i e8 W& J
6 G6 k' l5 S# y& {: ? q) f
' k9 A* t5 J/ a7 W- _1 o
+ A8 h' n# a7 c& q2 G7 p
+ q4 y; Q2 ^2 J5 M4 j# load data
e" x; f3 D6 E/ o6 L! x4 ydef parse(x):. c5 b$ [, G. X# I; ?
return datetime.strptime(x, '%Y %m %d %H')
+ Q6 }9 s( W Y2 R " C5 m3 ?8 I, K1 f9 K# q. y/ l0 E
def read_raw():* f' P" e: I5 T' V" H
dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
9 z3 Z2 ] |$ Y @4 b dataset.drop('No', axis=1, inplace=True)
1 ]( C3 K) I1 K # manually specify column names) o# J. l4 b9 ^
dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
! V! x0 Y) p8 N: P; g1 n dataset.index.name = 'date'
' O7 v0 k1 l1 e$ J # mark all NA values with 0
. @/ n0 G) v x3 M dataset['pollution'].fillna(0, inplace=True)/ Z: T+ @2 K5 L, a
# drop the first 24 hours
; k7 b% s1 Q. r; J+ k* x5 G dataset = dataset[24:]; S* M2 Y! L) `3 f. c: T4 Y# T9 U, }' f
# summarize first 5 rows
9 C; r( P7 g1 X+ P) }4 z! Y print(dataset.head(5))& a! ?7 r2 i+ U* `8 ~1 D: M
# save to file
9 c3 p& a5 O$ X: e* D4 g dataset.to_csv('pollution.csv')" X% m' o$ W; Q s* n) | z2 ?1 a
$ \2 @) o% X+ ~2 k. j: h. E
& u: I& T! G" N- A) O N1 T8 U: j) I+ Q9 M* {. D1 m2 P
! Y, u) z8 |( }3 K4 x* m# convert series to supervised learning
- v5 @1 g z- [) v7 d* _# _def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):' f9 b( _# m; O2 l, C+ C$ M K
n_vars = 1 if type(data) is list else data.shape[1]6 C" g3 B' B5 D0 J$ A2 m3 A2 V
df = DataFrame(data)
: w( B7 s7 v8 T3 _+ B1 J cols, names = list(), list()
( j/ A& T# g3 s/ ~/ F # input sequence (t-n, ... t-1)
* z* X. D6 `6 a7 ~ for i in range(n_in, 0, -1): n" P8 E! J1 L: G* g7 P. I
cols.append(df.shift(i)) y3 [- x7 c; E1 j4 _6 H4 z
names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]3 z. M+ z W# i( W T) t' Z4 i* s5 u
# forecast sequence (t, t+1, ... t+n)
- Y) B! `! x! c- f5 v! b0 H% x for i in range(0, n_out):; d: P4 T+ b" k3 S
cols.append(df.shift(-i))+ M8 Q: `% {6 c3 C) Z" `& X
if i == 0:% L9 v4 C9 B" h, R! x$ g3 d% {) h# Z- n
names += [('var%d(t)' % (j+1)) for j in range(n_vars)]$ P' o2 k8 Y0 y" ?
else:
9 p3 f% k# v" s# R names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
4 Y8 W/ z+ Q6 B6 O6 G # put it all together
2 ~' X; M, W% N8 H agg = pd.concat(cols, axis=1); i5 j3 q4 u) ]: P L
agg.columns = names l; @& p. Z9 R, A
# drop rows with NaN values# j( C3 M5 o5 R# H4 Q6 m
if dropnan:
+ i" \5 ]3 e: j+ M" f agg.dropna(inplace=True)
6 D v) v1 y% H( h6 Y return agg) k& d! A& E4 V; W- s4 L& e! h
s) w$ j0 g- I/ Z5 b. K# load dataset
& I( ^5 p& @2 Udataset = read_csv('pollution.csv', header=0, index_col=0)! A4 D6 Y6 W* d. g! t: Y
values = dataset.values
# M; N' B/ H9 A9 x' L7 J0 m' O
2 h! k. S8 K; ^, P1 r# integer encode direction3 ?0 ?/ |- u* ~( D+ ^" O
encoder = LabelEncoder()9 ^% H+ l T8 v) d, V
print(values[:,4]) m4 T$ G% q0 J# J$ y1 ]
values[:,4] = encoder.fit_transform(values[:,4])% G& S0 B' |" i7 h/ @9 ~
# ensure all data is float" r2 @* u3 X- B
values = values.astype('float32')9 @: ?8 o3 a8 Q7 B6 V, N4 h
# normalize features2 N* C4 Z. b0 ^
scaler = MinMaxScaler(feature_range=(0, 1))
; S2 _ m, y( [+ a- i' X+ V( sscaled = scaler.fit_transform(values)
: v E; Q- v, M3 n# frame as supervised learning8 S9 `& x% r; V' V: b
reframed = series_to_supervised(scaled, 1, 1)
o% j' g; R4 p/ f! E2 @. z#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据4 z4 y2 o9 k% g; O6 Y
print("columns:", reframed.columns). D) ^) o) p1 B) T! n! |( ~
# drop columns we don't want to predict
/ m. r3 C- S$ Zreframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据/ Z* A7 F5 y8 h/ t; e% K- i `
#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据0 p5 t5 u; t6 g, V) j
print(reframed.head())- o3 u0 A4 P _3 ?/ U; G) S
print("new columns:", reframed.columns)0 R7 B, G* |1 t: Y
# split into train and test sets
, A2 L" a* d7 svalues = reframed.values, M6 w; ]# n: @3 ?$ Z2 a7 F
n_train_hours = 365 * 24& e3 j4 e, _ d }
train = values[:n_train_hours, :]
3 T) U) w7 G4 ~4 ]% vtest = values[n_train_hours:, :]! V; ~: p5 T! }& s Q
# split into input and outputs) w' a" L9 Y e; k& ]8 I; v
train_X, train_y = train[:, :-1], train[:, -1]
- k2 H l. O# i. Vtest_X, test_y = test[:, :-1], test[:, -1]( Y6 C; d; M6 B
# reshape input to be 3D [samples, timesteps, features]: _0 ^ b( S& t6 n7 a5 `1 z
#使用Dense()模型时不用变换
4 }: o, a9 }( G& l( \& Strain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))( ~4 _+ a$ r7 Y9 a) \2 m, ^
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))& W, c- y# j1 M. k/ z, |# x6 ]; I, a
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape): s: r5 \# |, k! {6 [2 C1 ~
# design network
' R( u5 R0 C" a" e- ^/ _model = Sequential()" t8 {+ L; T; P
#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2]))): t; _* P* G0 d/ l# j
#model.add(Dense(50, activation='relu', input_dim = 8))
- A4 Q4 D& [9 ]; R( B! M3 amodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
1 w1 S8 X* ^6 X0 r9 pmodel.add(Dense(1))' t+ [/ G, _! [4 f+ t" @ v/ D
model.compile(loss='mae', optimizer='adam')
3 a1 ~; u( X% o# fit network
$ y9 ]* T% B. Ahistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
) A' v" ~" D0 H2 ]6 q- I# make a prediction
/ T+ r7 c/ v8 W8 Qyhat = model.predict(test_X)' c4 O0 _5 L2 B) m. r/ V2 |
print("yhat shape:", yhat.shape)
5 i; g9 q5 B6 c5 o, q" c' f( I''': h' f5 @! \4 S2 @; R! \0 G
计算在测试集上的均方差
/ t, J6 ]) t8 d4 |4 j' htest_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
& V, ]: F* N4 |5 o3 L; `. ~print("test_X shape:", test_X.shape)
4 A/ b: ^3 l6 E% t* N- S4 P3 e ]/ }0 o; _+ P# U
* H) \2 ^9 [6 d- B1 w# invert scaling for forecast
7 ^( s" }. h/ J5 T; S5 @inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)% H% ^1 s9 K7 z9 e
inv_yhat = scaler.inverse_transform(inv_yhat)
; l7 e4 s* ^9 K$ }4 y# ninv_yhat = inv_yhat[:,0]2 O+ g1 @" c) {6 @- ]
# invert scaling for actual, Y" g, W/ N5 y2 p8 l8 x
test_y = test_y.reshape((len(test_y), 1))" B) m+ v1 f, t# A! p
inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)0 I9 H/ P3 B9 P8 p; Q1 P1 y2 @( M1 X
print("inv_y:", inv_y[:10])7 c2 D+ n9 p l; g
print("inv_y shape:", inv_y.shape)5 h n+ A7 }0 `4 ]- d/ T
! l8 h" t5 H+ I6 G( j3 h( T; D+ A0 _
inv_y = scaler.inverse_transform(inv_y), J7 K4 H6 p, k
print(inv_y, "*"*30)
' U; T9 r" v# M; X9 `
: H! Q" B5 q% V4 M: j" Q. l% Q1 g: w/ P9 [7 k
inv_y = inv_y[:,0]" y7 v- v) y( h& Y2 F% J3 b
# calculate RMSE8 ?' }. T$ b5 h2 T* A
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))' K/ ^3 }0 r3 {7 s* W e e
print(inv_y[:100], inv_yhat[:100])
4 C# a& F* N$ J4 o$ qprint('Test RMSE: %.3f' % rmse)
9 ]9 _2 S% q6 Y( q- P1 k# g* Z2 J' K3 ~& i7 \2 U4 m% O
6 Y7 g4 a# l& b
'''
5 B; j& F: L5 \% l0 K实验结果
& A" n/ ^# x3 j) C) M0 _$ J: M实验1:用前一天的天气数据,预测某一天的空气质量0 b* f' W3 ?) }( ?
使用LSTM模型! V0 K7 D; y3 b' U7 a+ ?4 L9 L) {
结果:, _2 B4 y9 z3 [$ W5 N# s. w
Epoch 49/50
( U# l) V! H- n0s - loss: 0.0144 - val_loss: 0.0133
4 H3 b, F4 X, F+ _Epoch 50/50
- B+ ~7 F# D& Y' h* p9 q' M0s - loss: 0.0144 - val_loss: 0.0133
) h6 b2 [ {1 c+ u5 _
3 ~( [4 O$ a# E) O* g- {' N+ h; K( p& R! v* N' I+ n
实验2:用前3天的天气数据,预测某一天的空气质量
6 l( e+ J& i8 F- V0 {4 N7 y9 a0 ?使用LSTM模型
+ @" ^4 n) \6 ]# V
- W+ b( W% z' Y) ?% @
, p. S/ U3 s" Y0 K结果:) N% O* x! }2 o/ [- V
Epoch 49/50/ F. U! |( @) G/ [. ]
0s - loss: 0.0147 - val_loss: 0.0149
" v7 R( A7 L3 i* kEpoch 50/50
7 P, k% \) V- ?2 [6 l, n0s - loss: 0.0147 - val_loss: 0.0150
1 E, [0 j' g8 Z6 Q. w- {" L1 r" F
9 f* C! Z E: t# @; a( L+ C: s7 E& i
实验3:用前一天的天气数据,预测某一天的空气质量
5 _" }7 {8 u: L0 j& k使用普通的全连接模型 Dense()
$ K+ k' x) o0 \: R5 c结果:1 D6 N8 {- u8 f7 b7 J1 h
Epoch 49/501 n4 Y) o+ V8 D' z" g6 B8 h5 H
0s - loss: 0.0144 - val_loss: 0.0146" D! k7 R5 y$ v
Epoch 50/50
! K; n5 d. \* S0s - loss: 0.0148 - val_loss: 0.0151
. R/ T9 B' K; w. @/ {- e
0 o- p0 i, B6 X1 l8 u
( k2 ]' P, h4 f8 p C3 j实验4:用前三天的天气数据,预测某一天的空气质量% w7 W4 |5 \; g! W+ j& k* C* b
使用普通的全连接模型 Dense(); C: V" }; `' k# X0 b
结果:
. V _9 i+ @9 B0 \% `/ b% AEpoch 49/50
% O5 P7 [4 S. L0s - loss: 0.0150 - val_loss: 0.0165
( `, z6 t1 m8 v7 MEpoch 50/50
; S7 u$ ^# ^ D$ C1 z! w0s - loss: 0.0148 - val_loss: 0.01413 T5 z6 k$ Y. M, y
8 ~5 x' t( y) ^3 z# P0 j4 p: U3 @" M+ K/ W7 P
实验5:用前一天的天气数据,预测某一天的空气质量 g5 j9 h9 q" q1 E' o
使用SimpleRNN
. c6 f8 `" Q8 I/ PEpoch 49/50
2 z" x! g/ C3 y1 P; ^0s - loss: 0.0160 - val_loss: 0.0140
- v9 u+ ^% A4 yEpoch 50/50* f6 w. m0 R6 ]. a4 s" R' x
0s - loss: 0.0147 - val_loss: 0.0150$ E2 s: ]- {) b! O: S. j7 [* y. E7 @
( ` W/ H8 ]$ t2 V) S5 N
3 b" I2 ? q- ?实验6:用前三天的天气数据,预测某一天的空气质量
7 X, n. Q# i1 N( {使用SimpleRNN
2 p. e3 ]& D& s3 H4 uEpoch 49/50
1 q% i! }/ ^! Q/ [' y0 r) m$ M. {0s - loss: 0.0164 - val_loss: 0.0233
5 X$ p/ y. O6 L- cEpoch 50/50
; D! \) ^! `& j& h+ t8 i) U0s - loss: 0.0166 - val_loss: 0.0227
8 M% k( p L" K3 c& lRNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。
9 t: X/ K5 W: q6 I( n* `4 z. p![]()
7 E6 f# j2 t. o; u/ K9 g/ m. H' J/ l' x8 d2 J' s" y
RNN和LSTM的区别2 C& m; b7 E& u3 A7 _* D
LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
/ h" c+ p- a A: R, o; B& X4 e" d3 ]1 s
+ {0 x% N& ^# p
但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。1 i4 P: _3 n% } S- s9 G
* k: X) g) |) r; t/ |" h+ J7 s
* V3 ~. u4 \+ r3 s5 X5 x& f# @* ]9 @请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员4 ]" i9 ?5 `& e4 u: ~( j Z5 p) _% d
. r! b- e0 Z" e4 i/ y: O( h& ^
+ Y; g; O+ H. ?8 A
|
zan
|