- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40219 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12777
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1419
- 主题
- 1178
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
|---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
 |
使用LSTM预测时间序列数据/ m% n3 t* U1 m% C' t
+ ^+ s. m& @. S+ O, y, u
% n- u7 N! c% W. N/ Z- t: a' d
文章目录2 b7 g1 ~3 ]5 p E" P
背景' B; u% e+ ~ c* [
结论
$ L; `9 E$ w/ J7 L& O# W6 R代码7 o; t, E9 C# `: c
实验结果
) e4 [- k7 C$ i1 H$ xRNN和DNN的区别$ q5 b2 j' G/ r2 F% T
RNN和LSTM的区别% [6 {! B" i6 D
背景
& K" H0 S2 t$ e9 x复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验) K& x4 U, Q- D$ ?- B
熟悉用LSTM模型训练
+ _- W( \8 ]5 Z) @ a. R2 |验证将时序数据 转化为分类问题后,预测是否有效果
z" q0 B5 A& c* o/ Y" b* t: ?对比SimpleRNN与LSTM模型 哪个效果最好?: S: I) N; S$ {+ U$ K, E- e
验证LSTM相比于Dense()模型 是否有提升?
, ?" b$ B c' W& Z7 o' C对比使用前3天的数据 和使用前1天的数据 哪个效果最好?+ C$ T' m, d1 \& _4 C/ _0 p
结论
0 a$ A- [7 i& M8 L" O- x使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好! U6 Z/ n% u& Z* A1 V7 s
使用LSTM的效果优于SimpleRNN e, O$ E3 \! [1 L* M" o5 k- }
代码
9 {9 J$ O2 i O6 @from pandas import read_csv
# L& f8 R% z! ]% `9 r1 P" ?+ E Ufrom datetime import datetime) w# Z' L. ~* Y6 g
import pandas as pd" n/ S" l8 x% j# e8 o" a# n
from pandas import DataFrame& e6 J2 n. ~% M5 ]6 i) ^; `1 h E
from sklearn.preprocessing import LabelEncoder,MinMaxScaler7 U+ Q% X7 T0 b* _- F
from sklearn.metrics import mean_squared_error
2 v' f, L' B( dfrom keras.models import Sequential
& S d- a1 [1 a* |5 o7 Nfrom keras.layers import Dense, Dropout. j( I, Z, Z; X. J5 o6 a
from keras.layers import LSTM( `+ H2 L% y e1 m
from keras.layers.recurrent import SimpleRNN
6 _4 I+ c; z& p$ ^4 }% Jfrom numpy import concatenate# p9 Z2 A; t' |0 k8 s7 f
from math import sqrt$ X& }8 U6 ^* K3 M% r$ D& S
+ @' @, L5 ?* l# A2 ]
" o; n6 R8 U" T) L& I, q0 P
5 @, n# T1 e9 ]# e7 }9 R
9 e m/ H( b# o, H9 U8 e1 \# load data
4 m6 G* V% F. s, W# A9 y0 ^def parse(x):* e, ]$ H j7 W U8 M* b0 S
return datetime.strptime(x, '%Y %m %d %H')8 G3 X1 f4 X7 H7 ~3 y" P
R7 J7 ` ?& f, u9 y
def read_raw():
1 j$ S4 s1 R& r6 F W8 I9 \ dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)% f% O5 G- p! K, m/ _; L1 y2 V
dataset.drop('No', axis=1, inplace=True)
p$ g6 _& E% @6 q # manually specify column names
# T: s# a8 I6 |5 e# P/ @ dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']% G, s& g& s& R/ z( u1 E& i5 \! O
dataset.index.name = 'date'
5 _$ V( o& L# ` # mark all NA values with 0
. R% b7 M* F7 {2 y/ b dataset['pollution'].fillna(0, inplace=True)) m7 q1 @6 J/ B
# drop the first 24 hours
; T6 j5 Y+ m1 D# D* x dataset = dataset[24:]
: X x/ i* t S5 d9 `% } # summarize first 5 rows9 e; s* Y" P8 B: E( m% T4 p
print(dataset.head(5))
8 E9 [/ g- n. B5 a( N% c9 v # save to file0 k/ k5 `/ d) { ]
dataset.to_csv('pollution.csv')
# t5 L0 h+ D& }* @0 i- H( ~2 C
$ r4 ^2 d7 c+ q O) ^2 T, C
% y7 `, B; y# b6 B5 L2 r
1 R- W" `" W1 L: m3 g
" {& T, [; A; R8 Z, p( m$ \' C8 T# convert series to supervised learning
4 P; d! e/ G+ ^: h* Fdef series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
2 K( @" I3 }5 Z) c k9 ^ n_vars = 1 if type(data) is list else data.shape[1]/ {8 O. G- B, Y$ w8 G- _/ {8 n8 t
df = DataFrame(data)
+ j3 i5 y( m1 Q% J cols, names = list(), list()
8 H. e% T9 W# n% A9 ~2 p # input sequence (t-n, ... t-1)2 v" E$ N4 B3 x# C8 c% |
for i in range(n_in, 0, -1):8 J, \3 D( X) ^* G+ B f, o
cols.append(df.shift(i))
+ S |- ?0 ?8 H0 J9 i% a4 L names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
' u, g2 V/ H4 i+ K/ Y. Y # forecast sequence (t, t+1, ... t+n)4 g" k) S# z9 Q0 k$ S
for i in range(0, n_out): R% e! t3 h' o
cols.append(df.shift(-i))! s4 B8 \8 F+ O+ _1 Z$ }
if i == 0:
- d% I6 }. z9 x7 j u9 k! H names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
6 V3 m( C+ ^9 |* h+ l else:- V5 X8 s; N6 E: k( J. v
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
1 [2 `' ^3 l- o4 p, s8 k # put it all together& ~- e: w, H2 E2 K" ?) ?$ ]4 @# f/ w
agg = pd.concat(cols, axis=1)9 p# E4 ^, h6 x' W( E4 S
agg.columns = names
6 ]* O4 Y1 z: V3 l4 W5 |' h1 ?: Y # drop rows with NaN values
( M. B/ P+ R) A" @ ^ if dropnan:# Q; j- e/ k8 y9 v
agg.dropna(inplace=True)' |5 d1 O) z1 I' [; f" C
return agg
2 a$ Q& U0 d, M/ _4 [" a . X5 f( v8 V4 v/ J) ^0 l# S
# load dataset. Y$ P3 ]8 O( s+ [2 o) w0 {6 B
dataset = read_csv('pollution.csv', header=0, index_col=0). o) h% F" L% n( s. X/ ]7 l) y
values = dataset.values
+ [2 C" q a1 K- Z _; G9 q7 x1 Y. s) Z% W* v' |4 e
: I e! ? I. V5 x1 Q# integer encode direction2 D) w0 K( {& @; {. A+ b, c
encoder = LabelEncoder(): m$ ~% `! y/ K) _+ ~& @
print(values[:,4])
9 _: p: }1 E1 o% rvalues[:,4] = encoder.fit_transform(values[:,4])4 P3 G, [' n/ o# d1 l6 V7 `
# ensure all data is float
3 s6 K& M1 L/ z: e! Jvalues = values.astype('float32')" P1 f/ m: b( b: A! F
# normalize features
6 ?5 I+ a( c, Y( b. l! v7 hscaler = MinMaxScaler(feature_range=(0, 1))) T+ w# `7 K# j; Z/ S9 b7 M
scaled = scaler.fit_transform(values)& E- X1 F/ ~7 O2 d* x! O
# frame as supervised learning+ e& a3 g7 P* W& b/ m! C/ g! \: O
reframed = series_to_supervised(scaled, 1, 1) 1 ^( h* E5 z9 c. t
#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
' Q) @( {4 D/ g$ bprint("columns:", reframed.columns)
1 r5 ^0 p6 Y$ [+ O& j+ A( I# drop columns we don't want to predict$ Z6 _" f6 S$ W6 G
reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据" J2 ]- D6 }. {5 f1 n* A6 y; x
#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据5 e3 ]+ P0 o- S3 q8 n
print(reframed.head()) N7 P& g9 h# d: {8 B5 q$ P: t; Q
print("new columns:", reframed.columns)
& a" _: _* L+ B( f) f# split into train and test sets
; H; K" ]/ h( l8 Y# a5 ?values = reframed.values6 e- a9 i5 o# C5 m! f
n_train_hours = 365 * 243 T6 c5 S; [+ Y" b, p% u
train = values[:n_train_hours, :]
0 @) Z: I B" t1 G: wtest = values[n_train_hours:, :]+ F; Y6 @& e$ o. h" ^; _
# split into input and outputs+ ]9 e; w* S; D }6 T1 L
train_X, train_y = train[:, :-1], train[:, -1]
! I8 C$ u( J, G( |1 Y9 ?test_X, test_y = test[:, :-1], test[:, -1]
2 Z% \ M# E1 O8 _# reshape input to be 3D [samples, timesteps, features]) W4 C4 K" {$ H7 q. @ T
#使用Dense()模型时不用变换
' H! m2 T8 y6 ytrain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))9 e5 r( g" J3 }3 \' c7 G/ f
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
, D0 D& E ~1 s8 r! B( }* eprint(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
( H3 Y* q2 Q8 b6 n9 E* _# design network
4 o; |" I$ T" v& J7 y- ymodel = Sequential()
7 _2 M) \: b1 P/ V' [#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))4 `( _+ T9 x' }. p) U7 H
#model.add(Dense(50, activation='relu', input_dim = 8))
& r: {* M- V* Y0 }: o Y. V3 _ pmodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
9 z9 G0 }1 K' @5 l, j. k+ [model.add(Dense(1))2 c; T1 w' F1 j; m8 @6 d# M- B
model.compile(loss='mae', optimizer='adam'); D+ V$ Z! A+ _5 R/ @
# fit network
; t5 ?7 |- X a2 n- V$ ?! p) xhistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)% ^0 n( d/ @ A! X) `- c# {4 `
# make a prediction7 Q7 X, W0 ~+ [+ l
yhat = model.predict(test_X)
" I9 L Z8 C- f+ Tprint("yhat shape:", yhat.shape)
% i* h, X% {: k% R'''! Q. l& y |9 {, z( t8 h
计算在测试集上的均方差
1 R% x+ j( ]. m2 S2 i1 jtest_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
& s9 K) l. Q: _! }& R) }print("test_X shape:", test_X.shape)+ M8 Q u; Z$ M
# c& t8 W5 O& \; E% F; H5 W' ]0 v0 E C9 C3 o: x
# invert scaling for forecast' _% V& `2 F/ p! k4 A4 `( `
inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)4 {2 A. b) S) e- d- d4 @1 q
inv_yhat = scaler.inverse_transform(inv_yhat)$ G! a' ~, l( x* ~/ B/ p
inv_yhat = inv_yhat[:,0]7 t5 R, ^' c! W1 p6 W+ m% }1 _
# invert scaling for actual
6 C) b1 e1 l; m9 o0 ?, ktest_y = test_y.reshape((len(test_y), 1))
* m0 x4 n" C4 ?inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)
' |4 x! i# `6 _3 l- d2 m, Qprint("inv_y:", inv_y[:10])" ?& e4 a7 y1 V) T% W5 O% F7 x+ q3 ?
print("inv_y shape:", inv_y.shape)) d! |6 O9 V8 g8 B% W+ u- Z5 M
1 c' M1 f* B- ?9 r" N' R- Z
9 ^- t8 l8 i* v! a( ]% ~! s& d$ p
inv_y = scaler.inverse_transform(inv_y)0 {4 i3 i$ g" D+ h
print(inv_y, "*"*30)
/ j. }( }6 Y) k8 T- o) t' k" ^3 u0 x" ^3 |# E( T
$ n7 P+ I7 q$ finv_y = inv_y[:,0]
1 }$ t* N( c3 K# calculate RMSE# R, ~7 p4 R# n) d
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
3 L7 m/ I2 e% L Q# O" C) E4 T6 rprint(inv_y[:100], inv_yhat[:100])$ l; s- o J" u: n4 n
print('Test RMSE: %.3f' % rmse)$ S! X( G8 x( G9 @* v
D6 }1 a. y% K' p/ t" n+ s& W4 H& M {+ M6 z' A+ F/ l: K$ z
'''
9 Z1 E8 o3 ?; \" P, }+ j/ h实验结果
* j2 @/ `& a: r# U+ L0 W( X实验1:用前一天的天气数据,预测某一天的空气质量
9 c8 B+ b* G7 S: C6 |. g' _使用LSTM模型
# D5 U5 T; `: [结果:1 r- `' L4 g& |0 ~) H, R$ ?
Epoch 49/50$ |5 f1 N1 X5 y
0s - loss: 0.0144 - val_loss: 0.0133
6 a0 O" ?; E8 o' x4 LEpoch 50/50
1 V3 H: Q" c. d; G$ a" k0s - loss: 0.0144 - val_loss: 0.01331 \+ D( H1 \1 k( L7 D5 p
( g/ r( I2 R- s) n+ A
6 U9 M5 ^/ j4 s' L2 a$ U$ \ W实验2:用前3天的天气数据,预测某一天的空气质量
/ y* |) x( L4 d* P使用LSTM模型( L. D5 @" l6 q Z
4 r3 J- ~! v5 W; O) r
9 O7 G1 X4 ~9 V) t结果:0 ]; m* k! J2 u
Epoch 49/50# @( a" N9 ]" O) A0 }
0s - loss: 0.0147 - val_loss: 0.0149
b( X& J* c" t6 h% sEpoch 50/50; X$ Z% O0 i7 Y4 s2 e% d9 N
0s - loss: 0.0147 - val_loss: 0.0150
; F2 \# d Q" g. y
% U/ \/ L6 c( Q. o9 } k, M% _" T. }) S/ ^+ e) ?
实验3:用前一天的天气数据,预测某一天的空气质量/ P7 O# k6 v0 [+ b
使用普通的全连接模型 Dense()
# I$ c$ n" g5 K% j0 f7 F: L结果:
3 q4 M: P: H3 p; [8 ]2 {$ uEpoch 49/50, i2 s# A! x" j- _0 R
0s - loss: 0.0144 - val_loss: 0.01460 o( X3 ], U! b
Epoch 50/50
" z3 S) A# N2 ?2 `4 `0s - loss: 0.0148 - val_loss: 0.0151
; K* B5 c/ m" y
: h% T* J/ I/ I9 Z( o/ m1 ]
5 B! C9 }6 `2 s" E实验4:用前三天的天气数据,预测某一天的空气质量0 q, z4 | \, G! x
使用普通的全连接模型 Dense()
& x! i: ]" G' E+ j: a: A9 e2 ~结果:
8 M! [% m" u, t M) u% |. _0 JEpoch 49/50
/ x7 S8 F, A, k2 S: ?- F" L0s - loss: 0.0150 - val_loss: 0.0165
& p0 {1 O) X, j( J$ C7 iEpoch 50/50- J+ [" k( P+ G3 H* J& k2 ?$ S
0s - loss: 0.0148 - val_loss: 0.0141) U* Y5 q/ y8 z1 X+ A, l Y
; I+ [' Q+ O, x$ I) Z
. s7 J5 R) |4 b8 e: W实验5:用前一天的天气数据,预测某一天的空气质量
, }" t1 t. l; ~+ n; R6 F! J0 Z使用SimpleRNN3 S% X3 m9 |, S0 \, g
Epoch 49/50
; y: W# U4 y% x' \/ E1 B0s - loss: 0.0160 - val_loss: 0.0140
( e5 w2 {8 l% W( m8 ~Epoch 50/50
2 g# _# S% |4 G% }0 x7 O0s - loss: 0.0147 - val_loss: 0.0150
& g7 @" w7 [- ~7 F- w8 @6 r, s
6 }9 q$ e z) w" u# y0 d* m5 T+ i8 @4 r7 u& U0 |5 k e$ ~3 s1 j, k V+ d
实验6:用前三天的天气数据,预测某一天的空气质量
! \$ _4 v. I! Z* z" |+ D0 f. v* C使用SimpleRNN' H( V( a6 S1 j
Epoch 49/500 K- ?9 f/ ?" k3 y9 N1 P! F/ Q
0s - loss: 0.0164 - val_loss: 0.0233
. n, m# C0 N' M6 c; I) \* o! S3 n8 o$ UEpoch 50/50
" W C( W# e* e! p$ k+ e0s - loss: 0.0166 - val_loss: 0.0227( f% r# Q- `6 d: l/ h
RNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。
( I: ]+ [) M9 ~ ' J& w' y& q- m- C( @
$ _/ ^0 G3 S+ S
RNN和LSTM的区别
( Y$ g' b7 ]. G- ~: Y7 w4 aLSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
& t% c1 g! i& a+ y% p$ s+ {, D3 \
% v/ N. G4 l/ R' X5 X9 f; {6 y- c/ u+ ^3 [ T5 f. k% q [
但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。* x/ a b+ [6 v U$ ~
![]()
5 K( X2 o+ Y# j4 x% q4 x# T
, x5 S% K9 `1 M请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员0 r# }6 A2 G; s2 { [" i! s
( {7 V$ k, W" P; \7 \5 b; L
p; R, f) L! P, @
|
zan
|