- 在线时间
- 514 小时
- 最后登录
- 2023-12-1
- 注册时间
- 2018-7-17
- 听众数
- 15
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40255 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 12788
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1419
- 主题
- 1178
- 精华
- 0
- 分享
- 0
- 好友
- 15
TA的每日心情 | 开心 2023-7-31 10:17 |
|---|
签到天数: 198 天 [LV.7]常住居民III
- 自我介绍
- 数学中国浅夏
 |
使用LSTM预测时间序列数据
9 L9 u( u; {4 [
: z7 Q) w" j% L( l6 d0 ?' S8 Z9 c( j
文章目录
/ S" L/ X9 z0 ]4 I- j背景
& m$ M( r& j; p; s结论
}' z7 j- z$ \. U4 Y! A* u代码
: o2 j3 @9 {/ e3 P1 k( P4 M实验结果
4 R" y1 [1 O# V9 ?% B* ARNN和DNN的区别! x* k& x- q9 I5 p
RNN和LSTM的区别
+ G6 V/ V: A* F$ Y. T背景2 p5 I, D1 x7 u/ d3 v
复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验5 H1 j8 p' S2 ~+ \1 y7 `) D
熟悉用LSTM模型训练7 E; }/ N, i: \3 h7 R0 Z) o7 e% k7 F
验证将时序数据 转化为分类问题后,预测是否有效果
/ l8 [7 J+ R/ |9 N4 h% J对比SimpleRNN与LSTM模型 哪个效果最好?
M2 i0 v) @2 ?( B4 Y验证LSTM相比于Dense()模型 是否有提升?
* ]; \) j3 v" I3 `' u/ X对比使用前3天的数据 和使用前1天的数据 哪个效果最好?
6 k$ V3 u' k% K7 r结论: J! {8 L! U* S% g0 C6 q( l; D
使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好: F' v B% u- q' U; P
使用LSTM的效果优于SimpleRNN" [' R0 g6 _0 A! y
代码6 i4 X. H6 u4 u6 Y3 B( b
from pandas import read_csv
9 x8 B8 e, N6 ]7 Y5 O5 Z# ~from datetime import datetime& B0 D# f7 z2 x0 `) L- \
import pandas as pd8 y/ d( c, r/ R# o, i2 s
from pandas import DataFrame
% K1 J, P' _7 z( y6 ?- pfrom sklearn.preprocessing import LabelEncoder,MinMaxScaler8 J9 I- H- X6 m+ `0 a: C
from sklearn.metrics import mean_squared_error" [3 \- h* s M
from keras.models import Sequential
# E r9 X$ z3 k hfrom keras.layers import Dense, Dropout
* O" U& Z8 |$ c! I9 ^* \7 [from keras.layers import LSTM, s( ^8 L! Z. y5 O7 x6 t; E
from keras.layers.recurrent import SimpleRNN
$ Y8 M2 i' Y# efrom numpy import concatenate9 n+ w7 b7 Z& X4 P
from math import sqrt) T- @$ F0 c; q, {1 Z
' G8 ^, |/ d6 ?% l: o
) Y1 d' O1 U% l0 b& u2 ^- B/ h* d, T6 J) D2 ]0 O1 f- ^; k
; r }* l* q2 F# load data: I# R! I( X9 l5 ^! y
def parse(x):+ ?' F) u6 A: m1 s/ i
return datetime.strptime(x, '%Y %m %d %H')
4 v( H$ f. S# N9 N, E |
- h2 P' o/ N3 e+ Q8 vdef read_raw():/ Q0 f. E3 _$ p8 C. U, C
dataset = pd.read_csv('raw.csv', parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
7 u( E3 z* Y" c# o0 N6 { w1 X0 C" W" b dataset.drop('No', axis=1, inplace=True)) B" q0 j8 @" L3 R
# manually specify column names% @ V# N) P8 {% r2 B( A
dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain'] s3 {+ t) s+ Y& p7 ^
dataset.index.name = 'date'
7 ^7 F$ O1 N g: A2 k # mark all NA values with 04 H$ L7 }- C e7 g4 [
dataset['pollution'].fillna(0, inplace=True) ^4 N0 X# q/ [0 [
# drop the first 24 hours
' i9 P6 H Y9 o" x; q dataset = dataset[24:]/ u" P& e% ~" [* n& C) k7 u
# summarize first 5 rows
7 Z, ] ] G2 [8 W R: f5 ^ print(dataset.head(5))+ V) c2 u) J, _- i7 A1 O2 p
# save to file8 E( c) `; n) _; l5 ^- |% L1 l
dataset.to_csv('pollution.csv')
3 N& k; z" k4 V& m
+ H0 F3 \$ L3 @) M' T4 c. h1 y$ S
2 A% Y( d. }2 u7 M" q- }" o3 m. ?) g9 l$ _* B: i( \
8 i+ Y4 _0 T: P# convert series to supervised learning
4 V$ R. c2 N' B3 `2 Wdef series_to_supervised(data, n_in=1, n_out=1, dropnan=True):# y8 s0 c% }% |6 i
n_vars = 1 if type(data) is list else data.shape[1]8 O( T7 z( _3 B9 ]2 i' } n7 T
df = DataFrame(data)
8 o& B5 j8 B* I" N; k2 M" b cols, names = list(), list()
: j1 U& `) a( D0 P. J5 d) }% | # input sequence (t-n, ... t-1)% Z P1 x# a# _( o, T# L! j% ^" o0 a
for i in range(n_in, 0, -1):* `( X" m! R) P: X% _+ A
cols.append(df.shift(i))0 v4 e; P% E/ T. y" C
names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]; t: C! D- A& }2 G9 \; t0 B" E
# forecast sequence (t, t+1, ... t+n)6 q7 I2 B0 @9 C# c
for i in range(0, n_out):
% d. m% i6 _* u cols.append(df.shift(-i))+ O% v1 E; i: F6 G; P
if i == 0:
2 {1 I! A3 J2 ^/ Z" m names += [('var%d(t)' % (j+1)) for j in range(n_vars)]- y2 I- G8 L5 B" b" r2 d
else:9 V: N. d' t4 N
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]; B3 S% w0 V' V5 e! m
# put it all together
4 [' s* y/ n8 z. \4 S/ k agg = pd.concat(cols, axis=1)
+ R9 ^- Y* Y+ G- e r [ agg.columns = names
+ X" W$ G$ z6 a% t5 l # drop rows with NaN values
; c" \7 [% ^3 C/ z6 U& ?' p if dropnan: D* e u" v/ _
agg.dropna(inplace=True)0 l0 f% f6 j0 \3 J# p4 ], ?
return agg
! t. a3 L& N8 t& r : \* L4 A3 k' K" d/ R
# load dataset
) u" E) H2 K2 x, t( Z% q: }7 U6 jdataset = read_csv('pollution.csv', header=0, index_col=0)
, [9 R9 `9 C/ q& _: |) Z" ?values = dataset.values1 r6 n' ?1 r/ v& ]- v
0 C* u: ]/ L, D, c9 {, U* ~3 D; n
/ }! X' W$ {! L. z
# integer encode direction
5 y+ D% G! J2 U7 l0 x! F9 cencoder = LabelEncoder(), E9 ?& S8 ? R" T; r
print(values[:,4])
6 |. G# X/ p7 ?1 a' l7 p1 evalues[:,4] = encoder.fit_transform(values[:,4])
7 ?* {; Z3 Q6 a; p* _9 X" `# ensure all data is float
- X5 j. u8 m: e$ w" m r4 ^5 ^# wvalues = values.astype('float32')
# j0 K. u- m8 ]" ?% y8 L# normalize features
8 j3 J, J. ]) O u% @, U: Q* v5 o2 pscaler = MinMaxScaler(feature_range=(0, 1))
# {: l% }* H% _6 P7 n; z4 |scaled = scaler.fit_transform(values)
- ]! y& h! y+ n+ `# frame as supervised learning
% d* o7 T. ^" ?' V6 f- H1 M9 A0 ]reframed = series_to_supervised(scaled, 1, 1) ' R( Q* w; C5 n$ d9 R
#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据% L/ p# q' j* ^3 Q" o- m1 \& j+ C! _
print("columns:", reframed.columns)6 B2 C& |- C% |9 P" f3 u
# drop columns we don't want to predict
5 R- z" M" `7 r2 ureframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
2 `& z: E" {. J) t5 Z8 u#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
: r9 e) Q4 S5 _8 J& v( sprint(reframed.head())
& @3 _$ `7 f# O# Zprint("new columns:", reframed.columns)
. q& B: T9 z9 B o; W# split into train and test sets; D- i( p, k! D- q' N- s6 B- _
values = reframed.values% N* @' d. _" p3 M4 x# T: u$ R
n_train_hours = 365 * 24) U; _* I5 N& r& {# U6 R* A
train = values[:n_train_hours, :]+ {, c. j! }, N
test = values[n_train_hours:, :]
) ~( s3 q1 R7 }" Z, E# split into input and outputs
6 o. q6 c5 A+ L8 gtrain_X, train_y = train[:, :-1], train[:, -1]" {+ w/ m/ S* ~* g
test_X, test_y = test[:, :-1], test[:, -1]
) g8 @1 Q# K( _5 f+ G, L# reshape input to be 3D [samples, timesteps, features]
/ O3 |, d+ L+ {( A% Y) T$ M#使用Dense()模型时不用变换
4 O6 P/ G' q7 htrain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
8 v" G* ?0 [# j; Q$ Ctest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
- h2 i( _: S8 o% @$ Qprint(train_X.shape, train_y.shape, test_X.shape, test_y.shape); o* g& | s, n0 y; o. T, T
# design network* z6 x( d! h2 c( ~' \3 f
model = Sequential()
0 A7 @/ e9 z/ O! u$ R+ c# `* [# Y+ D7 Q% s#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))2 Q' R( W( A B
#model.add(Dense(50, activation='relu', input_dim = 8))( `1 I# W5 z6 k4 P- F0 a6 J7 G0 _
model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
2 U/ p4 o! _% h r cmodel.add(Dense(1))
) F% b2 U& [: k4 R' ]: Wmodel.compile(loss='mae', optimizer='adam')/ ?# ?: u$ P4 ~2 U& T# C
# fit network2 x2 }: N% Q% ]" }
history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
1 v2 z3 J9 E) z# G' x# make a prediction- F$ r8 X5 l) X0 t. h) _( f
yhat = model.predict(test_X)
' |0 Y) S; d3 Q: V( rprint("yhat shape:", yhat.shape)8 `, P$ m$ c& ^
'''
4 C/ [' w: N0 ~& `0 w/ T- V' D计算在测试集上的均方差
W, F$ ~7 b7 Z' {7 o7 H$ M! Ztest_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
1 }6 f4 k) u; a( O3 iprint("test_X shape:", test_X.shape)# a, ^% t1 T, r, I# l3 H, {
1 ~" a3 o2 H6 e$ E" d! v8 {% {) E
9 H0 {1 I8 [' F- e7 l- v, ?) e
# invert scaling for forecast5 |4 \" Z, B" {* A
inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
/ @' j: `. N$ ?6 ]5 L8 {- Z1 [inv_yhat = scaler.inverse_transform(inv_yhat): o, x" Y7 m+ t- U* _( y
inv_yhat = inv_yhat[:,0]1 R+ U, _( x) x$ Z& |* Y+ p
# invert scaling for actual
5 e" e+ I0 d$ Z6 R6 y0 wtest_y = test_y.reshape((len(test_y), 1))5 _; S6 E: [) ?- D( r1 I- u; m* _
inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)
/ Z+ n7 C2 t$ zprint("inv_y:", inv_y[:10])( Z8 w# K$ U7 D8 e9 N/ c) R
print("inv_y shape:", inv_y.shape)
7 `# S) P* S x* O- [, ?/ g" I( I f* Q: {
$ G5 h- v. ~# G6 z, Y f
inv_y = scaler.inverse_transform(inv_y)
. \) }3 K; }7 J6 n5 W a+ nprint(inv_y, "*"*30)0 Y/ V! n$ G4 z* G& z0 z0 t4 z& s
+ m9 l( p4 o3 Z9 k C
$ t$ D, P9 q( Y! W) A3 p* V% k
inv_y = inv_y[:,0]# }7 g+ i5 v: x3 K, N
# calculate RMSE
2 @; J7 I4 ~! Nrmse = sqrt(mean_squared_error(inv_y, inv_yhat))
! ?) t# g6 }) Zprint(inv_y[:100], inv_yhat[:100])3 P5 i" W' j9 |( R+ w* m4 J% \
print('Test RMSE: %.3f' % rmse)
' H A7 P( v- T; U4 J4 P4 B1 H' i# v. ?- b) A. t& P `) y
9 u% |( @2 g+ ?7 W
'''
: m( C0 d$ ]: O6 i# K3 s实验结果
4 E5 p/ D+ r8 Y2 G; C% G实验1:用前一天的天气数据,预测某一天的空气质量
; |- j* \& D/ a4 h$ C9 X使用LSTM模型
! d$ a+ u, [2 h8 V结果:" ^2 P5 e+ b1 S% S% D, L7 ^2 L
Epoch 49/50; S+ Q1 F+ q6 F% Q$ [3 Y. m
0s - loss: 0.0144 - val_loss: 0.0133
& Q* h6 d" V2 G1 LEpoch 50/502 O1 z% s& V* S5 @! J6 d
0s - loss: 0.0144 - val_loss: 0.0133
$ s0 A$ ^' _% u4 l( u! U
( U2 @& U( z6 B0 L& z
: s. C" a6 T0 ]: U( }实验2:用前3天的天气数据,预测某一天的空气质量
0 Z: a5 I7 U" a" b3 W使用LSTM模型
: H$ b, G6 B8 Z3 \
. o1 n5 n4 s6 O3 s3 ?" a- u I; k2 Z$ b
结果:. z i4 \0 ~& B D3 }
Epoch 49/50
3 U% h5 u* N1 ^3 e4 T0s - loss: 0.0147 - val_loss: 0.01497 F8 K; L$ }; W7 e7 N3 k
Epoch 50/50
! K. G, R% y: B- o0s - loss: 0.0147 - val_loss: 0.0150
3 F9 [* D' C& P K4 O4 H7 `+ T$ K6 K% K7 O9 c+ T- j
2 M& {8 Q; B( D I
实验3:用前一天的天气数据,预测某一天的空气质量- f; y, r1 y8 g
使用普通的全连接模型 Dense()+ ?- g' Z" P5 K; Q, y& D- a
结果:
3 T( y) b6 ~/ _Epoch 49/50
9 K& y4 B/ D% H0s - loss: 0.0144 - val_loss: 0.0146, `4 S% x& X+ n$ b; O9 ~
Epoch 50/50
' G% f8 ^1 G2 H! q c; X% h& m9 a0s - loss: 0.0148 - val_loss: 0.0151
; R* K7 [" g7 f) d* J
, H% Z1 r, p n: j- s: D& U6 B6 a0 A* C( R# i7 a
实验4:用前三天的天气数据,预测某一天的空气质量
4 J. H! F+ b" w! A/ {2 D使用普通的全连接模型 Dense()
9 G& A2 b# F' a6 I$ ~9 B结果:
/ j5 n6 q" Z+ J& |Epoch 49/50" X$ @. f& u" g @* @
0s - loss: 0.0150 - val_loss: 0.0165' g' J$ s1 T! S- s, J1 }6 ]& i5 b
Epoch 50/50' ^6 B( f1 _% R+ X1 T" ~1 `
0s - loss: 0.0148 - val_loss: 0.0141/ R/ l+ m8 K. O/ S$ O, t/ A" M
( ^! l# o( x1 `8 J( ~7 ]) R d8 {6 c6 u7 ^
# F( p2 \8 r0 P实验5:用前一天的天气数据,预测某一天的空气质量
0 }+ y' Y9 l2 x& n9 Q0 ]使用SimpleRNN
1 O, r. Y& r* a5 A+ `% y* qEpoch 49/50( x& ?9 K2 s0 ?6 [& S, t
0s - loss: 0.0160 - val_loss: 0.0140! f* ~) u$ ^- S R' X* W6 H
Epoch 50/50
: _7 m: r3 U! A0 x8 o6 g, u9 k1 `7 L0s - loss: 0.0147 - val_loss: 0.0150
% v6 Y5 ~: s9 ], g. U# [' @. j' g. Q
- d% W% x* H' m8 Y* C* f- R实验6:用前三天的天气数据,预测某一天的空气质量
; L. g8 ?# H! L9 C+ u使用SimpleRNN$ f8 i: A2 L' O; ^- \5 x' P
Epoch 49/508 n4 _* O& a- j/ M. j% c3 _! T
0s - loss: 0.0164 - val_loss: 0.0233/ c* U# m9 ]) S* Y( y& V8 L$ O
Epoch 50/500 ]" U: k2 }) g8 J" `3 G' G# _
0s - loss: 0.0166 - val_loss: 0.0227
# e" f$ O9 _8 _2 N7 ^, S3 vRNN和DNN的区别RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。
, a- a7 Z( z2 Y, q8 p9 V : b3 y5 c, w3 K; L# w. w7 l( A3 J
) p, I T$ `( u+ A% S" u8 r, m/ {" ^+ KRNN和LSTM的区别: @, E. Y4 H2 [4 n+ r3 ^
LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。9 Z" l) U5 x( r
- R! w* k0 n/ l" ~
/ `7 C% y2 @" N- [ P# F3 X4 w但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。' Z3 T7 ]3 s" t" Y- Y7 n
![]()
$ M1 t+ ]: G9 i( }4 a. S
8 Z0 F) p5 G8 _6 J8 S. y5 `请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员3 b+ b% h& \( c, ~& J
' V- Y4 w( D1 |& v5 c# \- [- ~+ g3 j8 g5 G! Q8 T$ p6 E
|
zan
|