- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 39393 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12513
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1388
- 主题
- 1158
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
|
使用LSTM预测时间序列数据
S& T0 {1 `4 f7 v/ Q9 D+ t$ r. r3 q C4 s }
. N- _* I6 k( \: X0 t文章目录" ~0 C6 e9 z! c. ?# u' Z+ |
背景: b. k" c! M1 M- X7 s) [: x9 W' B
结论
; Z2 O' A; K0 I+ ~) v7 t代码
& C4 y+ y" ? F9 k& j0 v1 R实验结果+ `9 m, H" S8 {- h* ^
RNN和DNN的区别
7 U* g! J' z" ]) e, _2 z& b. FRNN和LSTM的区别
; F$ W8 i& B' W) c2 V背景
$ m1 j% \7 {$ X) b6 S6 F复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验. g- ^( Y, c$ v$ J$ G/ N
熟悉用LSTM模型训练
+ S$ C- C' F6 Y验证将时序数据 转化为分类问题后,预测是否有效果
* L- T: t) B; }+ W对比SimpleRNN与LSTM模型 哪个效果最好?& N! e$ ^& i. A! E2 m, n: g* H) y) `
验证LSTM相比于Dense()模型 是否有提升?
, f: J- C7 c' S+ I* Y! r) ?- M1 i对比使用前3天的数据 和使用前1天的数据 哪个效果最好?$ \) Y) ?% Y$ e( M. Q! N7 T+ O @
结论, i B3 t' L7 k8 W9 c1 f6 F9 @
使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好0 |+ \1 x2 r6 D' v' y! q
使用LSTM的效果优于SimpleRNN0 b$ Y! }2 A) t6 b
代码
( b6 U4 i$ y# Dfrom pandas import read_csv7 p$ @' ]* i6 P$ I" z
from datetime import datetime
+ h3 X4 E. Q Ximport pandas as pd
; r; v- K4 N" }; Rfrom pandas import DataFrame
; i: \7 f) `; L' ofrom sklearn.preprocessing import LabelEncoder,MinMaxScaler: }3 M3 a# i/ M+ b
from sklearn.metrics import mean_squared_error. W5 l- X) ]- Z3 e, ?( k
from keras.models import Sequential& } Z) v4 @& l5 Z' \5 G
from keras.layers import Dense, Dropout3 o: l3 n4 j {0 b
from keras.layers import LSTM
: ]+ v/ S, O7 m! w; z4 Ofrom keras.layers.recurrent import SimpleRNN
4 F! P: M5 ^6 I$ m* A: Z8 `. Pfrom numpy import concatenate! u9 s2 K3 u3 y0 p) N3 b$ K& }
from math import sqrt8 L ~" i/ ?* `* E& c9 v+ L4 e9 [
5 ~4 ?! \" \6 x R$ o! ?
& G, r+ {1 J% X5 _/ C) B. v: z% Z0 s( m1 A/ X0 X
# U" ]% E; |8 [) ]3 T% x
# load data
$ B4 l( Q, l+ _def parse(x):1 ^ e6 Z8 A1 Q, [5 O! d9 P
return datetime.strptime(x, '%Y %m %d %H')7 T9 i6 e( ^6 z0 V% v
% ?; z3 T0 Q: v' f. c+ p
def read_raw():
1 {& m: H8 w2 f2 N dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)5 q g5 h _3 D. R* b+ B* C
dataset.drop('No', axis=1, inplace=True)
, F: d0 \ q& h9 O3 I1 o # manually specify column names
+ l! D0 J$ b0 |# T* A4 a dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
6 `, _1 Q1 n, }; T) i dataset.index.name = 'date'1 N4 E h3 }, u; q" I2 N3 |
# mark all NA values with 0- S( }5 f+ {' R! m! r; L8 F
dataset['pollution'].fillna(0, inplace=True)% H0 t( j! b0 x2 p5 w/ }) _. u
# drop the first 24 hours' r' O* y, J P$ t/ q
dataset = dataset[24:]( X5 a$ g, Q) i' G6 S: P" ^* F
# summarize first 5 rows8 D' ?3 G" H$ C; G# @! W7 s/ l
print(dataset.head(5))% e1 ^0 y: E7 u. A
# save to file. L# M/ f7 C* F
dataset.to_csv('pollution.csv')
+ g; q' n# T2 y8 \. |5 e- P
- Q" g, c1 \7 ]& `. }7 r' y1 ] U$ C7 @+ p; u, F
$ e5 J! T" {' K2 k( e
) C8 u; ^2 H' j% G- r6 Z( h# convert series to supervised learning5 U9 ^* R8 y* N# s0 F8 o. V
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):% w% k7 r6 ]6 P- u3 o7 {
n_vars = 1 if type(data) is list else data.shape[1]
* D6 Z0 y7 }; X5 x df = DataFrame(data)6 v0 { s" m" S* ~7 T- C# |) D
cols, names = list(), list()
9 B, H. F B+ j7 v/ E # input sequence (t-n, ... t-1)
0 x+ r# u$ {; _6 V- y# n6 O for i in range(n_in, 0, -1):
8 ?% y5 T- x- {: o7 |% ~ cols.append(df.shift(i))
. O) l N3 y: t names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
+ l, T; b% ~, i. w7 X # forecast sequence (t, t+1, ... t+n)9 m: w& `- d# A+ X9 w% Y, ?
for i in range(0, n_out):5 s" a# w: C/ h" A! k% s
cols.append(df.shift(-i))
9 b: J9 g! _8 \4 [+ } if i == 0:
( B& [3 N2 E, g. l q3 D names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
0 F) \6 `! F2 s0 ?) @+ o4 |- | else:( @, ^' M3 A9 ?: q% u( H9 K6 q+ S
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]7 l& Q: r# a3 j1 m8 s2 |
# put it all together, h5 C5 u& M/ w8 V% ~3 b
agg = pd.concat(cols, axis=1)
. @; b- A! R6 B. u8 S1 A) y9 j9 [ agg.columns = names. D" d. K) P6 i6 J W$ K( V( s+ t
# drop rows with NaN values
! z" g$ _+ d7 t1 J if dropnan:0 s0 H' M0 E6 C, ^8 }
agg.dropna(inplace=True)+ P; l7 p# T5 O( Q( |
return agg7 T0 K+ [- i7 ^" R' }; W
2 _1 I' r3 V" n2 m
# load dataset
9 X5 d- ?# a5 e) g3 h. P+ Zdataset = read_csv('pollution.csv', header=0, index_col=0)4 F5 J6 f! P1 y2 d$ z& P! S
values = dataset.values, |7 b7 O; M" D
" e: t7 _5 T+ I4 k/ ]$ x% p/ y
' j, u* R) ~) [4 d3 h$ x# integer encode direction0 x* Y% J9 a$ ~& e
encoder = LabelEncoder(); v$ Q6 F+ K. M: h
print(values[:,4])4 W5 {( p- }- y6 H) Z
values[:,4] = encoder.fit_transform(values[:,4])7 M+ Q- M9 G# ^4 `4 C) v1 o
# ensure all data is float) b% P2 f: Q: g
values = values.astype('float32')
0 h& Z! ~: J2 l1 i- _8 v. Z$ l# normalize features
# p- ]. A5 X( Y- [3 d- V, q9 lscaler = MinMaxScaler(feature_range=(0, 1))
4 b u' ^% v& w8 p: }scaled = scaler.fit_transform(values)
2 L. ?0 T1 Y8 l) X' @# frame as supervised learning, A8 o( @2 a5 G7 l2 d- s. T
reframed = series_to_supervised(scaled, 1, 1) * K0 p. {- ]1 M4 d6 Q
#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
0 l- Q$ N* f8 n, ?, W9 oprint("columns:", reframed.columns)& b. O+ r" |$ i( T. k7 \
# drop columns we don't want to predict
' s1 l2 P) E( ~+ c$ z9 hreframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
$ `- `4 ~- l3 s( A( X# j ^#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
' L/ `6 v; H4 \- [7 sprint(reframed.head())
$ X' A+ o1 u& V$ hprint("new columns:", reframed.columns)& ^( _ L; E H- G0 r
# split into train and test sets
8 s7 u, |4 ~9 {* a" a: f, fvalues = reframed.values
) g6 R+ a9 k8 d5 k: cn_train_hours = 365 * 24
. T7 C) ?3 @$ j! e i" otrain = values[:n_train_hours, :]/ |% z0 q! x' V; g) Y
test = values[n_train_hours:, :]& q! L( W+ f9 c: d" W3 c+ ? o) ^
# split into input and outputs4 o& K( _ U* R9 T6 d2 R! g
train_X, train_y = train[:, :-1], train[:, -1]8 e$ t# \5 l# q* B
test_X, test_y = test[:, :-1], test[:, -1]
, e8 S% u n" ?# reshape input to be 3D [samples, timesteps, features]8 t) o5 U! k& H, V( Q
#使用Dense()模型时不用变换
8 B9 T& q- K, C; Ctrain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
; {/ o! D8 H/ C; gtest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))4 T4 ?2 }8 L! ^; k* y/ l1 t
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
/ ]# X1 k$ }' _3 n1 e# design network- G6 }1 }/ v) ]7 M4 w
model = Sequential()
5 M0 ~1 j. g; t a#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))5 |- m% U# e& P
#model.add(Dense(50, activation='relu', input_dim = 8))
) |, S& L9 R5 H. I8 y) C. zmodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))1 T7 c+ O# g3 f1 C! @) y
model.add(Dense(1))3 O2 B7 q$ \2 x. z& W: b
model.compile(loss='mae', optimizer='adam')
2 t/ S& n* | n! x8 `* d( C9 P/ Q# fit network
% s* u9 K" i4 }" k; C2 O/ Dhistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)& f i6 o% `# |" M* j8 a
# make a prediction I$ x, y* x, ^& a
yhat = model.predict(test_X)
+ h7 C& l' Y7 o% Q) M; zprint("yhat shape:", yhat.shape)
5 h+ ^9 }) n) I: M; M( r'''
. m1 C9 r6 W% S+ k! c计算在测试集上的均方差$ D N0 T6 i# c! _' r+ i
test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
9 {% M" f( o" Q3 @print("test_X shape:", test_X.shape)
* n" a" Z$ z+ ~
/ i. |4 m9 R+ r3 u" B: |
. c. \% n! M) o! h5 a; p# invert scaling for forecast/ [% f/ r; O' D" h
inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
! I) t5 H. H3 V& Q/ Z: `4 m& o. vinv_yhat = scaler.inverse_transform(inv_yhat)
8 D8 x2 X' E5 i* Tinv_yhat = inv_yhat[:,0]
# O' H& U x2 l4 n8 k& p' Z$ h# invert scaling for actual% @$ Q/ c7 [- f% I9 R
test_y = test_y.reshape((len(test_y), 1)): X' D1 [3 U$ l
inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)* g, s! H/ Y! U1 k* T
print("inv_y:", inv_y[:10])" ^4 u' |- y1 [. T; L; ~1 i$ k
print("inv_y shape:", inv_y.shape)
/ n( u& E2 I, O: z( J
; @: b9 s9 Y" O, ^
( `6 G) e$ p( finv_y = scaler.inverse_transform(inv_y)8 }: p/ C$ H4 ~' J
print(inv_y, "*"*30)
, s9 L! \/ ?" _$ d* i7 w$ o2 b% N$ @! y, |
1 p( c7 Y8 N% n) ~. ]4 E
inv_y = inv_y[:,0]
: P- V0 c" Z V) g ] d8 p' ]# calculate RMSE1 `0 s' J2 ]$ y. Y5 V3 m. }
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
8 Z' S/ |! p( L; G; Yprint(inv_y[:100], inv_yhat[:100])
; m- r7 f) D: K/ T: zprint('Test RMSE: %.3f' % rmse)/ y8 i7 S) P. ]- l4 R" H% A
* T' W, E) N' Z1 G3 B1 K
, m6 ?' R- w( p6 C# E( x# B''') w. |' T4 B6 r% D6 |! a
实验结果
- Z0 o, Q& q% j7 f/ b0 D, T* c实验1:用前一天的天气数据,预测某一天的空气质量2 D% Q# v1 R4 `* B, B# i' N+ f4 G
使用LSTM模型
) j0 s( A" ^1 o2 g3 g结果:
7 d! v0 ^3 C/ T7 ~( f/ nEpoch 49/50$ }( {! v3 j$ P. v( Z, Q. c# ]
0s - loss: 0.0144 - val_loss: 0.01339 y3 @: y+ r/ _
Epoch 50/50
8 ^! n5 o9 q1 o T1 E0s - loss: 0.0144 - val_loss: 0.01337 }, u( E8 V% K; M5 d/ U/ Q
2 V8 Q" k: P9 K2 H) T6 \/ E" K; E. P. B* b+ W. R5 \4 M- I. d
实验2:用前3天的天气数据,预测某一天的空气质量
, m# Z) W3 V8 |$ E& {1 t使用LSTM模型; u" l& d$ ]* c0 F
* `1 ]0 S, @8 h9 [9 Q" u. R$ C! O; _
l+ p+ }# E/ W* V. p+ \结果:
* |/ a4 ~% m3 N, |/ e5 G- j. GEpoch 49/509 Q4 o, T. g( _5 {! z2 K4 }
0s - loss: 0.0147 - val_loss: 0.01497 G3 y/ R8 d1 o3 ~) Q5 n1 T
Epoch 50/50
8 v" {% U& [( n1 M7 T& ^" h1 g. D& M. d0s - loss: 0.0147 - val_loss: 0.0150/ B- R1 a) [' i
0 d6 f. n1 I8 _' U
" e1 S, P: W2 ^2 O. t
实验3:用前一天的天气数据,预测某一天的空气质量6 U6 d* x/ J6 V/ G. O' P# y
使用普通的全连接模型 Dense(), g: Y6 S; g5 J7 i3 g# n" {4 U$ X
结果:# J# D# G( e; e
Epoch 49/50: K' R, i* w% k% N" z
0s - loss: 0.0144 - val_loss: 0.0146
$ q- g, ?! \6 B; t7 w0 y6 BEpoch 50/50. d- x6 i3 N+ n, q
0s - loss: 0.0148 - val_loss: 0.0151) g& o7 Z. \+ n- _2 V3 I0 Q0 n
. ?( V- c. g N# R0 a" L: Z- z
* F0 a0 Y; s6 S) |实验4:用前三天的天气数据,预测某一天的空气质量
% Y% K% Q% _& \" ]: ?" z1 f% l使用普通的全连接模型 Dense()
- u$ c* d( d5 p8 q结果:
& i5 ]' N. [6 r+ F6 J3 VEpoch 49/50; [8 z/ g6 V6 J0 U- G T- q6 g
0s - loss: 0.0150 - val_loss: 0.01652 o( l6 t G: r
Epoch 50/50
' N8 M2 v; R+ l" \. h; c0s - loss: 0.0148 - val_loss: 0.0141) g4 N# d7 B$ j) S: m% ^& I
: e$ X4 |3 e, n+ }- I0 H
. G' ~( Y+ C" Z4 B: b实验5:用前一天的天气数据,预测某一天的空气质量
4 N0 s+ v2 Q7 {; B: P使用SimpleRNN- D1 O2 C8 ]1 Z5 C @: K' l
Epoch 49/503 |* `8 L+ x1 {
0s - loss: 0.0160 - val_loss: 0.0140
; {5 p+ N4 [( _5 K( dEpoch 50/50- t$ {# I$ q H, {0 J) S
0s - loss: 0.0147 - val_loss: 0.01506 x4 P& ~; w, F! M
0 K- J* q- t: G9 {# t; W# t2 L' {* N5 E2 {2 i' v
实验6:用前三天的天气数据,预测某一天的空气质量3 S8 z8 A f& K8 B" H
使用SimpleRNN
- L9 O& m" Z' S: O7 X1 {* gEpoch 49/50
$ B7 t' W' l& F# g( e6 p* I5 Z; B$ O0s - loss: 0.0164 - val_loss: 0.0233+ Q; m% y. V. S8 k: v* ?8 S2 I/ W( \
Epoch 50/50
}! U( P* H# U4 U' f D0s - loss: 0.0166 - val_loss: 0.0227
, ]( C3 B' _4 u; n3 }( rRNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。 $ E- o& I `; H, G7 B% M
. i% T' q/ J1 {; W
# \; t' @/ z$ D; sRNN和LSTM的区别" r' B9 S. q, g* O4 R) U1 u, i
LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。$ q" i, o( {+ a6 X
$ o4 e2 |& e, L$ t0 y [) l
7 V6 D( \; D" x3 X0 J; K
但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。) U& Z! A( V$ @7 y( q$ M: {5 r) r
$ y* n" R0 z' S
( E0 r) L6 j* K; w& y# [# \请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
9 ?: `+ T8 b/ u6 c7 h2 T* X; Z3 W# X" u4 v1 K3 \4 _) [
D, Y) \) Y" H1 q4 Z! G' s
|
zan
|