QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4369|回复: 1
打印 上一主题 下一主题

使用LSTM预测空气质量pm2.5

[复制链接]
字体大小: 正常 放大

1178

主题

15

听众

1万

积分

  • TA的每日心情
    开心
    2023-7-31 10:17
  • 签到天数: 198 天

    [LV.7]常住居民III

    自我介绍
    数学中国浅夏
    跳转到指定楼层
    1#
    发表于 2021-10-15 10:53 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    使用LSTM预测时间序列数据
    ' f8 i% G' y1 z9 L/ w& F' x
    ' D- M; e& Z+ Y: E% v" F1 B
    + M0 O) P) x3 ~7 G7 f: s% n
    文章目录2 \# Z6 k* ^$ O1 S8 f3 e
    背景6 N+ \! j" T$ }% R; ~
    结论) L3 \- @- t- O+ z* i( ^
    代码; U' G( w1 v  }; L
    实验结果
    : G2 G: r3 k- ]5 B; I- d0 ~RNN和DNN的区别
    , l- O( i# X7 D& _, p0 HRNN和LSTM的区别
    $ D  T+ g& T+ x: J) m+ z背景9 R1 X* o2 h5 x# I: t
    复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验' |2 Q- ], s9 ]
    熟悉用LSTM模型训练5 B  n, ^+ c3 ]) z/ I) ?
    验证将时序数据 转化为分类问题后,预测是否有效果
    8 W2 ~0 N9 u" H. g对比SimpleRNN与LSTM模型 哪个效果最好?
    ( Q$ h$ `) e4 I2 g% O& V) V验证LSTM相比于Dense()模型 是否有提升?
    6 m' [1 D: C# p6 h对比使用前3天的数据 和使用前1天的数据 哪个效果最好?# K. G3 U" ?7 \( J7 p! a
    结论6 p8 T) b, k. Y5 L
    使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好
    4 z$ e; Q9 l( i) P4 Q使用LSTM的效果优于SimpleRNN- U- T4 d* J& ~  n7 n" [2 O
    代码& u5 z/ O& a6 G5 `* ~& N; Q
    from pandas import read_csv
    * g6 x0 D) _# T$ O. {" }from datetime import datetime
    % W3 O) E3 |. {( u9 K! i' b8 rimport pandas as pd5 V1 I" Y4 @/ Z, ?
    from pandas import DataFrame  r, Z1 b0 k% J% i# {. R
    from sklearn.preprocessing import LabelEncoder,MinMaxScaler* n- w" o+ J' Y& F1 y) s
    from sklearn.metrics import mean_squared_error7 R$ H! X$ A5 n6 L% ]% E+ M
    from keras.models import Sequential! U! i6 _( v2 M! R- e$ Q: w" F7 _- a) [
    from keras.layers import Dense, Dropout; U! g6 U/ V; n5 v( e! X
    from keras.layers import LSTM
    1 l) C% L. B. T) T, dfrom keras.layers.recurrent import SimpleRNN
    ! N/ X) ]& D- C5 w' b) pfrom numpy import concatenate
    8 g4 c, U" i5 }; D2 D+ zfrom math import sqrt
    : K- t1 N8 _( ~  Z( e- w! g
    , A0 o  i) x- `$ z

    , p  p* ^$ x4 S9 f2 I! p
    $ d+ u2 v/ E! [' I4 Q

    / m# c0 f( I$ [' B! Z# load data
    ; z$ \) m* ?+ i: ^0 N+ u, Fdef parse(x):
    $ R  a1 W. a7 j1 V( Y5 Q        return datetime.strptime(x, '%Y %m %d %H')3 ]: D( k8 F- h6 C4 Z
    ( L0 s5 K4 q  q2 n  [$ a
    def read_raw():
    1 {2 T  K# `- p, i! L0 P( ?    dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
    * p3 ~; y  a3 V3 Y" j2 W; L. w    dataset.drop('No', axis=1, inplace=True)
    & U; Q/ k. c1 R/ Z    # manually specify column names
    , E8 Z  Y0 k) ^  O    dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']' k* Z" U9 G0 \' R  j3 o3 }
        dataset.index.name = 'date'
    / o8 M" A0 b/ L2 l. H, f    # mark all NA values with 0
    % _8 x. o1 E" ]$ q3 D$ M; c( [# K    dataset['pollution'].fillna(0, inplace=True)" j8 P" ]3 f" j
        # drop the first 24 hours1 |: b! B+ `# u
        dataset = dataset[24:]% E( j: M) b0 j' e& \: [: R
        # summarize first 5 rows
    . X, H; e! c6 ?( y! j    print(dataset.head(5))+ a8 M; _, e8 p! H& C, @0 _
        # save to file
    - B! }! }$ O$ ~3 v6 i) N    dataset.to_csv('pollution.csv')  d+ ?6 O" s/ o3 V7 j; y

    : {6 W, G- [9 J* b0 O( e# x

    * ^: J* t$ T. C& J$ O# m8 Z3 n; k/ `

    % [" S& Z! f- P2 x# convert series to supervised learning9 |$ J% B) i/ D. c' Z' N
    def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):: s. T0 [* |$ D9 y
        n_vars = 1 if type(data) is list else data.shape[1]
    / z1 ?6 }7 A2 z/ W  J( i& g    df = DataFrame(data)
    2 F& G& S, G7 |    cols, names = list(), list()( g* N0 |( j9 P  h( K4 e
        # input sequence (t-n, ... t-1)
    , Z$ O; i" Z# w# t    for i in range(n_in, 0, -1):
    8 [5 O" i1 |  P' z2 O% ^/ J7 W, N        cols.append(df.shift(i))
    ( m/ @! S# i, M1 w( `/ n5 G        names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
    ' W7 h  m; z3 Y6 k    # forecast sequence (t, t+1, ... t+n)3 s( w) e- h9 g" @' b
        for i in range(0, n_out):
    0 q3 x5 y5 s' |8 W9 U        cols.append(df.shift(-i))
    % m3 B: c9 N9 S5 x. ?1 M: h! F2 }/ f        if i == 0:% y. C: r' ]3 D
                names += [('var%d(t)' % (j+1)) for j in range(n_vars)]- E1 p$ p' R8 f' Z
            else:5 E' V, s4 g2 f4 J6 Q- P0 [" U
                names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
    9 Y) a  S9 o! E3 L* b    # put it all together
    ( a6 H0 z/ @) B    agg = pd.concat(cols, axis=1)9 P6 o8 l) u, G$ ?6 M! M+ H
        agg.columns = names/ n! A" ]0 i% M. V( ?% H" @% g
        # drop rows with NaN values" o; N! T4 Z+ D1 O  Z
        if dropnan:2 H" G: d* \: C7 t: h2 O
            agg.dropna(inplace=True)
    0 K7 f% `. p7 w- Q: u0 `0 w    return agg6 H$ h6 D' q) ?: h5 O+ F1 A

    ; d9 i: g: I! ~3 t; s# load dataset
    $ i% ^; E* d% s  ]6 o! n3 e2 Fdataset = read_csv('pollution.csv', header=0, index_col=0)3 P7 k# ^; z% u. o* a
    values = dataset.values+ P6 L" \. d4 @9 n( r& v

    $ O1 i7 q2 [  D' p9 m) I! X. L

    / W1 R! l7 ~& C# integer encode direction: `5 x7 }, R  H& q! u! y
    encoder = LabelEncoder()
    6 R8 t/ \  n! N& f# j' kprint(values[:,4])" b" k: ]6 y2 ]
    values[:,4] = encoder.fit_transform(values[:,4])  k3 Z+ T! j. w% \6 X
    # ensure all data is float
    - Y4 a: j4 T. J) vvalues = values.astype('float32')2 T- N- W! g" R
    # normalize features
    " d% d9 `1 f2 E  gscaler = MinMaxScaler(feature_range=(0, 1))/ C' T+ {4 P4 n. @0 J
    scaled = scaler.fit_transform(values)
    7 x7 M3 ?7 r, w' ?# frame as supervised learning8 z! }2 O- u/ b% m3 C$ W+ M
    reframed = series_to_supervised(scaled, 1, 1)
    ( v; b" |+ J% t; \5 N# U7 O#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
    6 i3 E. @, v" j$ w; j2 ^print("columns:", reframed.columns)/ h% V9 A- v! C5 I
    # drop columns we don't want to predict
    ' ], K5 f( H% D- A2 _reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据. C, J/ p- @  F% F
    #reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据! [. _# t/ H2 ^2 |' ~& P: L- h
    print(reframed.head())! W' h; j' q. F7 _4 ?* [+ @& Y) i* a
    print("new columns:", reframed.columns)
    ( W$ q4 [9 ?, J2 b# split into train and test sets  ]3 M5 M0 B( c4 M
    values = reframed.values7 r1 t$ U, ^$ d" H7 g& N7 x
    n_train_hours = 365 * 24
    , Q( ~2 x; n4 [1 J( a5 Ctrain = values[:n_train_hours, :]
    + ^: y0 _8 L6 Utest = values[n_train_hours:, :]) X2 P0 u4 b! ?+ a/ J) O
    # split into input and outputs! ?  V% N) d' Z7 S
    train_X, train_y = train[:, :-1], train[:, -1]8 T, n# g  l* I/ x' W5 R. ^3 |( \) d5 {
    test_X, test_y = test[:, :-1], test[:, -1]4 ~0 l' g* U! Y! S6 g+ ]
    # reshape input to be 3D [samples, timesteps, features]
    " Y' B' m# t2 ]: ]: ~#使用Dense()模型时不用变换
    ' G( b/ X6 x; _) R, r9 c5 Ftrain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))- n$ r- I& ~$ y! G
    test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))1 A3 g8 V. Z& n1 p8 N
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)! a7 a/ L" J7 K' y
    # design network0 L1 c1 F( a5 O* G! X3 w5 f/ N+ i
    model = Sequential()' i2 M' V' ^9 D' F3 v6 y& N" v
    #model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    9 b/ V$ C+ X4 Y% s# v#model.add(Dense(50, activation='relu', input_dim = 8))
    ( _: H) q8 f8 |, I+ zmodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))" {5 h4 v! T- e' a7 U% A$ U
    model.add(Dense(1))( w0 f' C# e4 |/ ?! F6 k) s
    model.compile(loss='mae', optimizer='adam')
    " c' R) x2 N% X3 P5 O  r/ }# fit network( Y7 z% a, q$ x# F% z* R
    history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)* @8 V5 I1 K) H  Q6 n+ Y2 J
    # make a prediction
    3 U2 }; ]" J% i9 oyhat = model.predict(test_X)
    9 L4 ]; v5 ?4 h/ D9 h5 n" Y7 mprint("yhat shape:", yhat.shape)( w. G" y" o1 a: C) L* q
    '''
    1 e9 J+ R1 b6 b/ Z7 k6 G- @3 p& e3 v计算在测试集上的均方差7 s) B3 e# E) G; l7 u
    test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
    , Q# }0 H( b/ z* w+ H. vprint("test_X shape:", test_X.shape)9 h2 t, k1 U6 h- {9 p# E
    , f! L/ L. {7 R
    9 `0 W" H+ o& G. f
    # invert scaling for forecast/ z8 o: J8 {8 C* H* s" Z! |
    inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)6 S( y5 X) D- h! V% T; _* \
    inv_yhat = scaler.inverse_transform(inv_yhat)
    5 i# G7 n4 T( L, U' Kinv_yhat = inv_yhat[:,0]
    & z2 F! h: d% n3 `* l0 q# invert scaling for actual0 L) {7 {' T; W: p
    test_y = test_y.reshape((len(test_y), 1))9 w; I% A# _% `% _5 O! {  ^: l
    inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)  @! g& `8 O  D) }3 [, t! i  ~& f
    print("inv_y:", inv_y[:10]); h6 c" [% @$ [! h3 X1 Z
    print("inv_y shape:", inv_y.shape)( n. O; \4 X7 |

    ( z8 z$ I5 ?1 X5 T$ o3 C

    0 F# I/ |4 J) P; W$ V- S. I7 Rinv_y = scaler.inverse_transform(inv_y)% e( Y" s! r, N0 [: X
    print(inv_y, "*"*30). o; G5 V2 _+ w7 i' R6 R
    / J% V1 M; U: l4 Z

    . W, Q% v, u6 [inv_y = inv_y[:,0]
    8 R1 N  J. ?! W3 f- g# calculate RMSE
    ( Q, U* T6 j- p2 f/ jrmse = sqrt(mean_squared_error(inv_y, inv_yhat))
    7 M/ o) n# u0 z* k7 ?9 }print(inv_y[:100], inv_yhat[:100])0 n' }' i% X) D5 X; s, |+ ^- Q
    print('Test RMSE: %.3f' % rmse)
    7 X6 l/ a1 `# t1 U/ w* b- s, v% p" x  W; _' n5 B! ~, E% j
    8 N7 [  g8 @& x( ]6 }. n( _
    '''
    5 G0 C7 f2 h. z实验结果7 R0 G4 K- H8 ?
    实验1:用前一天的天气数据,预测某一天的空气质量
    : M5 L1 ?6 m- h& ?使用LSTM模型& i2 I7 s8 o% q6 r; b3 C
    结果:
    7 L  ?! u) j' z5 p* [Epoch 49/50
    + T. S) i! H0 A7 d0s - loss: 0.0144 - val_loss: 0.01332 F+ K% r/ M- Q
    Epoch 50/50
    ! o- C3 O8 d, T6 [# P3 g7 t0s - loss: 0.0144 - val_loss: 0.0133
    5 f% ?9 E( D6 G" e8 u7 A; c
    ; C. Q4 B  c9 @' z9 b

    4 o5 ?- O+ Z0 M7 ?实验2:用前3天的天气数据,预测某一天的空气质量
    ! @" x% O6 e9 c& e/ B, @# Q! ]  G使用LSTM模型2 _6 M% o. }# H( V% q) @

    , ~. t6 h: n5 n# `' V" O5 y

    + a% S6 O  y5 R7 y) G, \结果:
    8 n( m8 ~7 M* |2 {( O5 u" yEpoch 49/50
    5 u& ]; O/ J1 {0s - loss: 0.0147 - val_loss: 0.0149
    4 ?6 P. [: w+ Z+ X& e$ z5 [( [+ I7 OEpoch 50/50  J. R3 E7 s: a) _
    0s - loss: 0.0147 - val_loss: 0.01501 f: V7 j0 {4 M/ i# P" k
    / h0 x# i$ R" p- X! {& u9 M4 Z
    9 T" {+ d, b; H$ N' `0 p+ Q/ R
    实验3:用前一天的天气数据,预测某一天的空气质量# ]8 \" I; o( ]1 x
    使用普通的全连接模型 Dense()/ V5 N1 R( Y, G& Z' N" ^7 M' Z: I
    结果:! h- |. Q, [7 B/ u
    Epoch 49/50
    5 c9 g3 f' f. C- C' [  d+ h0s - loss: 0.0144 - val_loss: 0.0146
    $ s5 Q' Y  U0 c0 b4 K+ DEpoch 50/508 u$ Q1 G3 M7 m. ]& Z5 D# q
    0s - loss: 0.0148 - val_loss: 0.0151
    0 r' s, K: N. k7 h* Q1 X, d* a" A* B
    / Y; r3 v: ]$ [1 n% a' \  d3 K
    实验4:用前三天的天气数据,预测某一天的空气质量1 P4 R0 x: l+ X! K5 E7 g
    使用普通的全连接模型 Dense()
    * _  `* ~9 L6 Q结果:6 n$ l( a$ J; `  V6 O0 o# J
    Epoch 49/50+ s+ ?% ^& v$ A2 W' ~$ ^& s! R
    0s - loss: 0.0150 - val_loss: 0.01651 t2 W0 e, H, F+ P6 D' r5 N
    Epoch 50/50; H) U4 ~3 @. V0 _$ `0 ]& j7 _# E
    0s - loss: 0.0148 - val_loss: 0.0141
    3 |: W$ `. h  p- e  B
    ' \- A7 u# d0 v8 N2 P
    : n. Q! l5 x1 t9 K5 i
    实验5:用前一天的天气数据,预测某一天的空气质量
    ; g  X% b% F# A% v0 A$ F使用SimpleRNN
    ( Q. ]- w2 g+ [  G" @Epoch 49/504 l0 I4 ~6 M' D
    0s - loss: 0.0160 - val_loss: 0.0140
    ' h6 N: r& U: e# l) L' G; QEpoch 50/508 A* J6 ^- z8 q) f9 J4 H
    0s - loss: 0.0147 - val_loss: 0.0150. }, ?$ e- D1 m. _) S. B

    1 I# P# Q: f: j5 J$ |- T
    4 I2 Q7 _  B3 H3 N2 {) W
    实验6:用前三天的天气数据,预测某一天的空气质量) @0 V) Y' r2 L7 Y: a
    使用SimpleRNN
    & J- ?# {' b5 z& I/ nEpoch 49/50
    % _- [$ e9 N* R3 [( \( l9 c# M0s - loss: 0.0164 - val_loss: 0.0233: w8 M1 S! y7 i6 Q, C' U' _
    Epoch 50/509 J' R+ a5 ?0 t! v5 c
    0s - loss: 0.0166 - val_loss: 0.02273 y/ P% V0 y6 }9 W+ k
    RNN和DNN的区别

    RNN中的循环是指一个序列当前的输出与前面的输出也有关系。也就是说,网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐层之间的节点不再是无连接的而是有连接的,并且隐层的输入不仅包括输入层的输出还包括上一时刻隐层的输出。

    8 Y- J. q- U6 S

    7 a4 C) s+ D: Q$ m! F7 K+ d  n9 P3 C8 n. b" f5 S( b
    RNN和LSTM的区别
    # m8 g5 w3 e% `8 O, @3 tLSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。8 e# Z6 K8 \* T& `9 ]

    0 A* [1 b& L- i3 n7 D' q
    $ Q8 i5 ^5 I* ~- A- B
    但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。
    2 \+ i! P  R' O4 y
    / G) D# L9 U& Y- b. [; T( U
    * Q8 D& e+ |' d: e1 V9 A0 v7 w请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
    / k0 m  y5 p" q# Z5 [
    5 [! S5 ^8 F+ R2 o' F

    - w/ }2 t, J5 Z0 v. }
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    sjlxdn        

    1

    主题

    2

    听众

    155

    积分

    升级  27.5%

  • TA的每日心情
    无聊
    2022-2-19 17:40
  • 签到天数: 30 天

    [LV.5]常住居民I

    国际赛参赛者

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-6-12 11:36 , Processed in 0.361383 second(s), 55 queries .

    回顶部