- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40343 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12814
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1419
- 主题
- 1178
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
|---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
 |
使用LSTM预测时间序列数据
m5 q8 s; x7 v2 q
1 M5 ~ Q* l# s; Y; j* G9 N
7 M. ?* j. E0 L% K文章目录 ^8 n( {* Z/ \
背景8 T1 j5 f! Y& H4 w" D- Z+ y/ R6 C7 ^
结论
4 t! R) j f) H- Y代码# u1 }+ K. y5 x4 q, i0 d; }% a5 v
实验结果
1 m# N8 Y% y5 Q+ D dRNN和DNN的区别
6 ]5 Y5 s5 r) X; p1 k3 \" mRNN和LSTM的区别 D% `8 A$ X, C4 }
背景' l) o0 B3 |( a1 e6 V% x
复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验4 X8 }3 k" [& t9 ?7 A8 ~" L+ v [
熟悉用LSTM模型训练
$ M" T5 v7 P" a/ ]0 g8 x! t验证将时序数据 转化为分类问题后,预测是否有效果# ~7 H& P) T1 d* d
对比SimpleRNN与LSTM模型 哪个效果最好?% I5 C+ U/ Q2 D% F
验证LSTM相比于Dense()模型 是否有提升?* Y+ k7 U& o2 B3 @; O! A3 z
对比使用前3天的数据 和使用前1天的数据 哪个效果最好?/ c6 N; s' F4 s: n1 A1 i
结论
* ~7 b& ?" W& ~使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好
+ W, e$ u l2 ]/ x使用LSTM的效果优于SimpleRNN! ?$ f0 E( ]" r+ B+ K& H s
代码
/ H4 h3 A, Y" \" K" i( W4 f8 x& Ufrom pandas import read_csv
3 q. f# Q. ?, T {9 ~/ `from datetime import datetime B2 v: {9 C- E1 X3 D0 B
import pandas as pd7 a8 n0 a8 h! C. \- X9 C
from pandas import DataFrame0 P/ A, _, N9 i& [! G
from sklearn.preprocessing import LabelEncoder,MinMaxScaler* x) z# ~; j2 W6 N
from sklearn.metrics import mean_squared_error5 d" C5 h( p9 B* t+ w: V" H
from keras.models import Sequential
# l* t% W. Y" _1 _, F8 jfrom keras.layers import Dense, Dropout# T9 p" N0 E6 k& B7 r* w; @
from keras.layers import LSTM
; h" M' |: Q& q& V4 M6 Cfrom keras.layers.recurrent import SimpleRNN
" L1 ?* }; i0 ~% h$ Cfrom numpy import concatenate; W. Y. J. N2 ]2 B! `1 E! C0 b
from math import sqrt
6 T' R5 j9 s- u3 H( U- W( k) w0 h7 M; P8 q4 O3 j
* k% t3 o" {# n! ^5 [# ?: j R1 v
8 M2 e1 x ~- l$ X
# load data( R4 w7 b& X' D, G5 `( G/ n! f. o
def parse(x):
6 Q! E- O+ B# I+ u return datetime.strptime(x, '%Y %m %d %H')
! u- n: ]; j- k w ( X/ C8 _) Q5 k
def read_raw():) c X R; n& K+ D
dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)) t9 P% N1 d5 u* O4 b
dataset.drop('No', axis=1, inplace=True)
5 M3 q1 y. J( {6 M& N # manually specify column names' x5 N) W6 r. u$ I( x
dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']; d1 [9 y x. b5 O6 E; ]8 k
dataset.index.name = 'date'. }! O0 M3 O& [; w3 M* l# G3 k# {
# mark all NA values with 0! H9 o# x, T* @" ~3 N" V
dataset['pollution'].fillna(0, inplace=True)
5 b4 w! x2 x! m. P% M # drop the first 24 hours
. @' ^: t" P: l. f dataset = dataset[24:]
D A, ]. L: a4 N # summarize first 5 rows
; M, t; T4 b* a: g print(dataset.head(5))
4 @- d2 B5 B0 w. Q # save to file, m9 u: N% b) Q' d
dataset.to_csv('pollution.csv')
. l; \, K# s' }& _ X: }! a. Y/ B
, c! O% n, Q6 M' ~; J ` `
z: I4 F+ w; i5 c3 `
2 y$ l& e# X+ \! M v6 J3 x
7 ]% n, [$ P! P* ]- k8 }9 \+ Q3 J3 Y# convert series to supervised learning+ B9 J- q) q" U! z! ]/ Y
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):( R* Y9 d; L: P6 Z4 `$ \3 }( g, Y
n_vars = 1 if type(data) is list else data.shape[1]% T. v$ y* h9 b- B$ S
df = DataFrame(data)6 h7 M) z) p% y. h) Y9 E0 T
cols, names = list(), list()' h6 t( X9 r" L( i0 K
# input sequence (t-n, ... t-1)
) t7 s; {) T2 u; X for i in range(n_in, 0, -1):- E6 |; a4 x9 U4 q( Z, W% S% {
cols.append(df.shift(i))
! _' I7 y. g* W( i0 [1 ^ names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
8 Q/ N/ Z& W! C0 B- b # forecast sequence (t, t+1, ... t+n); Q. W) P6 i$ Y" ~5 L! L9 Z' f1 }/ V
for i in range(0, n_out):" N; N3 O8 T! P7 v
cols.append(df.shift(-i))
/ G) f( U2 w3 ~0 x' d if i == 0:5 b1 w8 b; q: |: X5 m: n
names += [('var%d(t)' % (j+1)) for j in range(n_vars)]+ ?0 g7 q( K3 d: e3 o: d: K5 m
else:
. H) }9 R' Z' d4 V9 J names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
+ Q0 S# ~& U5 v. f9 l# D2 ^ # put it all together
( j2 u; x/ m' R2 f agg = pd.concat(cols, axis=1)
F1 W6 X* o( N$ o1 ]: ]# {+ k agg.columns = names
6 ~ \- X! T3 s* @+ d # drop rows with NaN values
- c3 I, o& T9 u3 ]& y if dropnan:# T: }: `7 W7 a$ P
agg.dropna(inplace=True)
, J5 i/ E+ S6 C) O9 h" O return agg
. Q) @$ Q7 t& o" @3 h
; v" F) C/ u7 I# load dataset
: i" c O: [7 R" W% q- idataset = read_csv('pollution.csv', header=0, index_col=0)
" l, u( @$ O0 i l, F; xvalues = dataset.values
/ `3 y" @! l) P% _
& h( _5 J- R. N9 o i) `4 B! w0 l/ K. W6 n3 Q& F6 U" x
# integer encode direction; |$ g2 ~1 _' v- R, t
encoder = LabelEncoder(); ]; B" `* K/ }4 g$ T/ k
print(values[:,4])
. N2 }: B n! H: Z+ dvalues[:,4] = encoder.fit_transform(values[:,4])/ d6 G7 P; ]% X$ }, c& t
# ensure all data is float
* S+ w* V* Z- E$ {, c2 x+ R2 kvalues = values.astype('float32')
% f/ |! N3 l$ C; C+ a D" v# normalize features
$ R" h `" o9 a& Zscaler = MinMaxScaler(feature_range=(0, 1))8 D' Z# N, j% J8 o4 h& y9 X
scaled = scaler.fit_transform(values)
7 {. k+ O1 c/ D. ]# o# frame as supervised learning* Z. Q6 T3 E- z4 w
reframed = series_to_supervised(scaled, 1, 1)
J* n4 U. j( H#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据9 W3 _# Q( O1 ]. V
print("columns:", reframed.columns)
?) ^2 H6 D( p# drop columns we don't want to predict
" R5 R$ e& y6 O8 c9 G/ Q+ X0 mreframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据/ y9 S F( d* r4 A V$ q4 c
#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
6 x7 M' q# T# f- U% D1 w9 A+ O! ]print(reframed.head())- _6 o/ Q& G( {$ B; w( N
print("new columns:", reframed.columns)! I! ]3 `$ l$ Y, P
# split into train and test sets, h. M0 ?# X3 }9 g
values = reframed.values8 o5 s7 K( d" |( m7 A
n_train_hours = 365 * 24( e- _1 A$ ?1 R
train = values[:n_train_hours, :]
( U9 s, B& _7 M# r% ptest = values[n_train_hours:, :]
H& U$ R. b1 {, a0 }) M. }" f# split into input and outputs
O( C- C! t: O2 Y% f7 [+ jtrain_X, train_y = train[:, :-1], train[:, -1]* Y; ?8 S; T P4 a) M2 K0 V! |8 l
test_X, test_y = test[:, :-1], test[:, -1], S+ L! g* s3 p4 W
# reshape input to be 3D [samples, timesteps, features]- f S* B& m5 V7 W# G5 R8 @
#使用Dense()模型时不用变换
2 Z# M% H5 b- K" }$ ]+ l [train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))0 w0 `2 j& \6 h6 E1 |
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1])): M. G9 L7 o+ C0 u0 b
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
9 |% V$ k& G# d1 H$ K' H) P3 F" s# design network* L3 j3 j; h% U8 p }. ^
model = Sequential()
6 I$ Q) d6 }$ ?2 ^5 ^( K( n9 @#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))* x( w, }6 D+ _( C( H7 B
#model.add(Dense(50, activation='relu', input_dim = 8))
4 S; u# D6 K: dmodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))$ k) o6 \0 p) j
model.add(Dense(1))+ v1 A9 O8 ~! W6 R# j) o/ ~
model.compile(loss='mae', optimizer='adam')3 t3 I1 P! O9 M& O
# fit network3 K N0 b! r& c: n# t
history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
) z& @5 b! r# ?* _) W# make a prediction
8 v5 b1 m, U+ X& m, G; fyhat = model.predict(test_X): }9 X: \# x. Y0 L, E" t1 B+ V
print("yhat shape:", yhat.shape)& Y& o8 H4 o9 c
'''" u0 C5 c- a5 L$ p9 O0 f$ u4 d
计算在测试集上的均方差6 P0 L" z5 ~- z" ^" {4 G7 D5 H
test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))4 y% i% f" n( @
print("test_X shape:", test_X.shape)
# k/ R! S3 r2 O, f
0 `$ l- T8 G, ^# x
; X/ e, p( o! _; G0 t3 I# Z# invert scaling for forecast
5 m. ~7 W. s D$ R! Y- g8 y& y8 dinv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
* H) p. U8 L/ hinv_yhat = scaler.inverse_transform(inv_yhat)/ s6 p0 n8 T2 Y1 W0 Z% c
inv_yhat = inv_yhat[:,0]
; p# J; h j+ c8 j, z, b; V- a# invert scaling for actual1 s8 V+ m3 `$ x/ D* B
test_y = test_y.reshape((len(test_y), 1))) |+ {1 `: Z* E) w% k$ ^) H
inv_y = concatenate((test_y, test_X[:, 1:]), axis=1). a5 }8 b3 T* ^# e) S
print("inv_y:", inv_y[:10])" N! t& w8 a1 _# G/ {
print("inv_y shape:", inv_y.shape)
# E% i0 s! e$ l; d+ R
2 l) \8 I: i! @, z2 k" Q
* R" P3 F/ a6 x2 r# rinv_y = scaler.inverse_transform(inv_y): ~9 Y" r2 G7 `" f
print(inv_y, "*"*30)) ?- s& q# {! H) s/ s9 s
# E$ z% C, u \! i8 b8 x% D
1 X. f: L; E3 D% Finv_y = inv_y[:,0]
# v* Y1 E: T! G+ l/ [# calculate RMSE' r+ k" {1 w0 G9 {" {
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
: o2 R9 z! f R+ P2 Fprint(inv_y[:100], inv_yhat[:100])
P7 E: G4 d* C* C2 \ r: Q% F" cprint('Test RMSE: %.3f' % rmse)
! H8 n' F7 [% u
+ u: E- \" G- ~( s2 g
/ C" ?8 h6 w1 {3 J# X2 f'''
+ D* }2 W( _4 z7 o) Y9 s实验结果
! p3 \! a6 U& s. D实验1:用前一天的天气数据,预测某一天的空气质量$ E8 l0 C: ]8 D: [" ]
使用LSTM模型
6 G8 f4 ]' C+ W* N- W9 r% d结果:
0 z* ~: }9 N; ]# j1 }Epoch 49/506 H7 J3 G1 k' `( C
0s - loss: 0.0144 - val_loss: 0.0133. }) z: {, U* d; L
Epoch 50/50
3 [* U7 M$ ` G/ L0 _) S. m0s - loss: 0.0144 - val_loss: 0.0133
7 h; d3 ]' f) q" s
3 ^: h1 s% u$ g4 u3 e4 o1 _( ]: K1 ]; K3 D
实验2:用前3天的天气数据,预测某一天的空气质量) m, w v1 I& }2 }& u3 U- Q
使用LSTM模型
4 D! f" t5 b8 Q0 E+ \4 Z, C3 x
0 C6 V& W! B8 X& R' C9 H' R
& U. X9 M" L1 r, t5 D* X结果:
2 ^3 A! J, {: @; s" MEpoch 49/50% K- a( H: P2 R; W/ H" L" {: y2 Q" n
0s - loss: 0.0147 - val_loss: 0.0149, I. h: X7 q) w+ Z
Epoch 50/50
7 D( t M' z( [! o6 g0s - loss: 0.0147 - val_loss: 0.0150# o/ |2 F/ V& K% K u" J
9 h! u+ q1 F* Q) P5 c. f
" A& j- I$ t" D. m! ]2 ^3 r6 J5 F实验3:用前一天的天气数据,预测某一天的空气质量
5 g6 W1 b7 X4 o使用普通的全连接模型 Dense()
' [, C5 {9 n* X# I$ q/ ~0 ]: c结果:
/ ^2 ?# \ @+ xEpoch 49/50
3 Y/ r( `- x; V" L0s - loss: 0.0144 - val_loss: 0.0146
0 k; z/ B( ^2 n- F" r( `6 U( XEpoch 50/50
- C/ ?* r3 w; n. F5 v; S" B- J) h0s - loss: 0.0148 - val_loss: 0.0151
4 F. z6 z/ U' |5 s" p/ C' r- \
' j I( J" u" k" u9 A
2 ?* u9 _( c( a- f$ Z" I实验4:用前三天的天气数据,预测某一天的空气质量
F0 k1 ?# V9 @使用普通的全连接模型 Dense()* [2 ^" A# }$ A; |- ^
结果:
; d+ g3 I, V% s d- UEpoch 49/50; l& R" b9 } y4 Y2 V# L- e
0s - loss: 0.0150 - val_loss: 0.0165, ]# m2 @2 ^, [
Epoch 50/50" [+ g, }1 i% J# R; A
0s - loss: 0.0148 - val_loss: 0.0141 X; @; W& I9 x2 O6 U8 W+ D4 n
( K: T$ R& [! }6 T
" v7 ?. Y4 Y9 G6 F1 W& z3 k! p1 P实验5:用前一天的天气数据,预测某一天的空气质量
# a. d- ?. E6 J! b) s Y5 j使用SimpleRNN! L9 V( x$ _# X
Epoch 49/50$ {) k4 [5 p' v! K
0s - loss: 0.0160 - val_loss: 0.0140
6 O5 ]. z: f2 _& E, gEpoch 50/50
. I' J9 ~! S5 a7 S+ z: v2 Y" G0s - loss: 0.0147 - val_loss: 0.0150
% s8 y# y: o; q y: s7 M) T1 q5 ~- ~- n. r
. p2 P" e/ b) l0 ] Y! N
实验6:用前三天的天气数据,预测某一天的空气质量
- p5 ]8 J- B B# h3 f+ }$ s使用SimpleRNN4 ~ ^1 T k% P
Epoch 49/50% \0 f( L/ `6 |' ~# r2 m
0s - loss: 0.0164 - val_loss: 0.0233
+ x* ^" S: [! {! }Epoch 50/50: u- n- {$ t# C8 c0 o$ ]4 e
0s - loss: 0.0166 - val_loss: 0.0227
3 n; I, g' e4 F/ d% d% X/ e$ gRNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。
0 n- ~! D3 }* L5 \1 k4 y 0 @* C& n; Q, ^# `$ O
/ x( {% u* U1 Q% ?
RNN和LSTM的区别
" ?9 C, L1 J* |: p; T/ I4 m2 QLSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
5 M4 w$ c1 j3 d! m! l1 \4 l2 ~" Z( ~) k8 c r4 o1 ~8 Z
% r' }3 V" P* e+ s7 u/ Q4 s但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。9 z7 U, b% u0 ?3 l
![]()
- q2 G/ h' Q: i' C4 b- e/ [
$ O6 m( d8 G6 }1 U" K/ m y请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员! M7 t4 n8 r4 ~% L0 a W
( b9 P! |0 _( u: X l$ o" X
7 a- x: g. V' [. k# \" t, W
|
zan
|