QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4386|回复: 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预测时间序列数据
    5 o# H6 S( R# C! }+ \- m% p' F/ e' T
    # D6 _, V$ L: [2 Y7 X3 g
      L/ h' Y0 d8 D: i! [
    文章目录
    / F7 r0 `- Q+ s8 q7 [背景9 Z6 I4 Q+ S% s2 h- g7 ]/ n8 y
    结论
    - @8 R/ d" m! \. i代码
    , O2 P+ ?( u& O0 |实验结果# |& b7 k, Z# K' B
    RNN和DNN的区别( f' c( s; i. g5 c9 I! _2 \
    RNN和LSTM的区别6 l6 c/ i6 w% Y% r; a* _3 Z
    背景
    0 r$ H- E8 o  r- q2 }6 i& H复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验
    9 \' k" ~7 C% u# C5 E) T熟悉用LSTM模型训练
    6 m) W/ `2 F0 p; X验证将时序数据 转化为分类问题后,预测是否有效果* m" Q: C& d; ?* ?
    对比SimpleRNN与LSTM模型 哪个效果最好?
    # A6 j" z/ e. K7 ^验证LSTM相比于Dense()模型 是否有提升?
    - z7 R$ d* X+ B7 w7 p7 B9 L7 K  E对比使用前3天的数据 和使用前1天的数据 哪个效果最好?+ t' D/ z8 m/ d) ~1 K7 s' w/ ~
    结论
    " I. x! W  w* h使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好
    6 b4 f$ {  ]7 ]9 d( `4 K+ |& K使用LSTM的效果优于SimpleRNN
    ( G4 e( m* H% V5 q" _代码
    3 e9 J( h8 T0 T" U$ ^from pandas import read_csv
    * |0 @5 k1 R5 \7 y0 N- Rfrom datetime import datetime$ J8 m) k9 K- N, ^8 W  ^
    import pandas as pd6 M% ~+ k* ^' ^, H, A- ]$ e
    from pandas import DataFrame6 D, _+ [9 V- W5 Z& P* Z
    from sklearn.preprocessing import LabelEncoder,MinMaxScaler4 Z$ x; i6 u5 [% W  Y  H! H
    from sklearn.metrics import mean_squared_error
    & g: r7 N: ^' i/ B) Sfrom keras.models import Sequential) e7 b+ H% M9 Z& P+ M" q
    from keras.layers import Dense, Dropout
    . j  X; m5 W. a. t2 Wfrom keras.layers import LSTM. I7 ^; k7 O7 u% K6 X2 ]
    from keras.layers.recurrent import SimpleRNN
    ; F: h  E: P- W  Y: {" m( }from numpy import concatenate
    5 F4 l/ r4 u$ Y1 V$ Nfrom math import sqrt
    ; l$ K/ D2 c0 |
    * @) M  J3 X' g1 Z& }
    + I8 W4 D; a( H9 c, i- B+ U* d

    6 e$ Y7 o' V) V, ~5 @
    : @6 a! \4 A, c: B* ]
    # load data( J* a6 p6 @# v7 _1 @. h& o
    def parse(x):
    # D, B( |  B& w- E        return datetime.strptime(x, '%Y %m %d %H')
    1 `. |: M& f! T, @, O
    5 W0 f3 {" [  ?8 S! xdef read_raw():1 o3 x' I# |  s+ K4 R
        dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)+ r) r( m7 S0 a% c5 [2 i) a8 g
        dataset.drop('No', axis=1, inplace=True)
    / [- g6 i3 _$ V& K* V6 A/ M5 z    # manually specify column names1 n- P+ d$ X3 I* x' w
        dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']1 R, Q! B# D: g7 f% N2 B, J
        dataset.index.name = 'date'
    + ^1 f! n% Y, W- l- m2 |9 x    # mark all NA values with 0! P, b) [7 J2 a
        dataset['pollution'].fillna(0, inplace=True)
    # a3 ~' n/ W: R" c$ `  U    # drop the first 24 hours
    - d  g) E7 C7 `+ K    dataset = dataset[24:]1 i. ^5 g0 j% e1 `9 C" y2 A
        # summarize first 5 rows
    8 t( q+ L) p9 p, N* u2 J    print(dataset.head(5))3 F* t0 P/ H* u* K
        # save to file9 f9 X; \! }, f/ O- N* t
        dataset.to_csv('pollution.csv')
    3 v! e, l4 n1 T  c5 C/ M
    ' N. ~0 u, Y5 U1 U% I3 S# o2 B% u; X/ w

    - e# y7 c- D; q5 m* G; j4 b% {7 P! `5 y/ t8 `1 p9 j' t

    : k  u, k% m* j( f. B) W8 H# convert series to supervised learning
    2 q! v  j/ E  `3 C* u2 {. f6 hdef series_to_supervised(data, n_in=1, n_out=1, dropnan=True):9 E1 ?3 o  m! ^6 l1 o$ Q
        n_vars = 1 if type(data) is list else data.shape[1]
    % K  J5 f& I7 A0 k( ?: k    df = DataFrame(data)
    . r& t7 v# |/ [& E- H. s! w! X/ A    cols, names = list(), list()
    6 Y! h9 K& m' P  {) C: R    # input sequence (t-n, ... t-1)( n% C4 S; h: w" j( m! G
        for i in range(n_in, 0, -1):
    $ |9 L6 Z7 P! D: m2 O  w( Q        cols.append(df.shift(i))6 c; |0 K0 L% w, m3 m
            names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
    ; ]% x( c5 ?! e; N1 v+ C    # forecast sequence (t, t+1, ... t+n)  X* j1 |! z0 q$ |! x& s9 u/ J
        for i in range(0, n_out):7 D( R! y& g( m/ `$ r: ~, l+ T
            cols.append(df.shift(-i))
    2 a  \1 T0 }6 Y  Z* {/ v2 Q; o  y        if i == 0:! ]- ]( }/ ?) n7 L' s. _0 ^# ^
                names += [('var%d(t)' % (j+1)) for j in range(n_vars)]8 A: S, G5 \5 |4 B2 h8 ]7 @7 {  Z
            else:
    / x) v' }4 }: O0 ?8 A            names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]9 i' e  p8 z& r- U; z' k
        # put it all together
    ' h/ @4 Q/ U% a) J7 K    agg = pd.concat(cols, axis=1)* b" [' \% {; ]* }+ i
        agg.columns = names
    9 `+ f- [- b8 w3 q, G3 D2 D6 {    # drop rows with NaN values( C% l  T1 _( j: a; H$ b3 d: W1 n0 Z
        if dropnan:
    . \; d$ e- F$ ^& q- O% [- T1 }- \        agg.dropna(inplace=True)
    $ k- A. ^4 W& u% c; ~    return agg
    $ n6 l' M! X6 c ! l; c- m+ _1 [! t
    # load dataset
    2 i4 d% k) ?5 C- v& w/ _: x% ndataset = read_csv('pollution.csv', header=0, index_col=0)
    " u+ |! M$ w& g4 A6 a0 Lvalues = dataset.values
    2 k$ w- I& b7 `1 X
    ) I( j$ I( W7 n
    0 }/ \6 I  H% {/ {. K) r: W4 p5 n
    # integer encode direction4 A1 m: A' o3 g( E8 ]* b1 s
    encoder = LabelEncoder()
    ; g  M" |4 H. V6 sprint(values[:,4])5 @- y1 K$ N4 N& R, }
    values[:,4] = encoder.fit_transform(values[:,4])
    8 O8 E2 y! E, G; L" ^1 q# ensure all data is float" {. U9 M& F" q( M% i7 m
    values = values.astype('float32')
    % @0 l3 M0 M8 F+ k# normalize features
      u' |% j- b; o) y! m9 }/ }, `' Escaler = MinMaxScaler(feature_range=(0, 1))* x: S* o/ P, i( j
    scaled = scaler.fit_transform(values)
    ; V" C; L/ C% r8 ^5 [% J1 q. v3 Z4 G# frame as supervised learning! h' p7 k  S9 W
    reframed = series_to_supervised(scaled, 1, 1) , X; A( {' w1 T9 e- R7 W4 x
    #reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
    1 p" b* J  Q% z$ `, }) Q8 W1 v- Hprint("columns:", reframed.columns); z. e" s0 t, j) V8 A9 c2 n# V- z
    # drop columns we don't want to predict% l& H$ x3 o! J( S% L, J( h* D
    reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据! X2 @: M  S! h( [4 l* n
    #reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
    ' e# M; o, f. @2 w7 Jprint(reframed.head()); ]! A$ K6 q) }% x7 ~+ S0 }6 W2 m
    print("new columns:", reframed.columns)
    5 |& Q: o' R0 s2 L3 Z. S- L9 X6 r# split into train and test sets
    2 O" h, f- {: h4 s, G1 W1 @- J$ E! {, Pvalues = reframed.values& s7 b  \1 l# C/ u' L& Y% J7 ?
    n_train_hours = 365 * 24( N- q5 {8 n5 v; B% L: ?5 m  u
    train = values[:n_train_hours, :]' p; P/ m4 G4 v& M( @) \9 r
    test = values[n_train_hours:, :]
    ! Q$ m* n; m9 m/ S4 c' u1 Z# split into input and outputs' E" Q: V1 _- b* ~8 L
    train_X, train_y = train[:, :-1], train[:, -1]' n  J7 I" y  u. q9 a; r
    test_X, test_y = test[:, :-1], test[:, -1]
    . ^7 F4 l1 z6 p" F# reshape input to be 3D [samples, timesteps, features]% @# f1 ?- o2 j  |. g
    #使用Dense()模型时不用变换' O6 {2 t* @) b, _4 [$ y( V2 l+ O
    train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
    . v, M3 H. v1 o8 p1 btest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))! f' ]! a2 o! f- M; U
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)# O1 c/ ~( T0 [9 u
    # design network
    ! D8 L% H) v0 l  x4 }model = Sequential()
    # t2 ?* K! D6 ?( l# f#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))0 e* Y) e) M4 H# G
    #model.add(Dense(50, activation='relu', input_dim = 8))
    5 _1 a6 E# N$ zmodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    % `% A( b/ `& ^# o7 E* n# jmodel.add(Dense(1))) E" q# b+ h' n( h1 o3 Y" C
    model.compile(loss='mae', optimizer='adam')* P7 O1 T! f& {, I
    # fit network
    8 r* o1 j* E, c) ?: ~history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
    0 ~. w# W$ R% W# make a prediction! N; v1 P/ n2 [  L# G% Z( Z; B$ Z
    yhat = model.predict(test_X)
    0 @  E$ g( d9 W7 cprint("yhat shape:", yhat.shape)
    : c- {* n  d) }'''$ s* U. W) m; Q: K( j
    计算在测试集上的均方差5 m* w- `+ K* u/ ?, z
    test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
    % o0 V- R% ^* m* S6 w+ `' bprint("test_X shape:", test_X.shape)
    - K* I. a. ?4 y5 s9 ]0 V$ |6 h1 N( B  {6 a8 i

    3 f; f$ O1 G% c. P8 ]# }# invert scaling for forecast
    . Y& B" k/ y1 [1 kinv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
    ) ]6 h" C" U. r4 w. W# @inv_yhat = scaler.inverse_transform(inv_yhat)
    - {2 u" F3 T0 ?- J; I1 Hinv_yhat = inv_yhat[:,0]
    ; |! i. ~: i$ B* }& V) g: p6 E# invert scaling for actual1 n/ A! E' }7 e
    test_y = test_y.reshape((len(test_y), 1))0 H; Z1 X- w/ A5 ]! D0 N
    inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)
    : x8 \5 k, @0 o- P5 Z2 eprint("inv_y:", inv_y[:10])
    : C" s9 C1 P9 u$ S3 Jprint("inv_y shape:", inv_y.shape)5 H6 n6 j  u$ M' Z9 k' e
    ' F; d& ^5 E$ s8 z" s
    # ?8 w& z. }6 U+ |
    inv_y = scaler.inverse_transform(inv_y)# X4 e) r* F) Q/ E# g
    print(inv_y, "*"*30)
    ) o6 @, p& H. @
    7 Q+ i% S( T8 a0 L8 A* S

    ( [; C8 e% c1 ^8 ]9 s5 K, G4 ]5 winv_y = inv_y[:,0], n$ Y) y3 p7 {# k; g
    # calculate RMSE2 N5 }+ Y* a) v, ~; X, v
    rmse = sqrt(mean_squared_error(inv_y, inv_yhat))3 e1 ^+ C* |# ^' X2 y
    print(inv_y[:100], inv_yhat[:100])- {, T( u% n" T0 }9 _# j# ]
    print('Test RMSE: %.3f' % rmse). Q) X; o3 e# N) C- u
    5 E7 F! T+ k7 \/ u9 }

    ! d- J# [* g0 L% W2 q/ N# H8 R'''
    # \; O# X: A$ y' D& r0 ^5 }实验结果
    3 V4 k! P) H3 O8 [, I. x
    实验1:用前一天的天气数据,预测某一天的空气质量8 m9 R  J. h  k5 o1 V
    使用LSTM模型/ c5 O7 M0 h0 c/ D9 I: f2 }7 a
    结果:/ m: K8 ?1 c  z4 A1 |
    Epoch 49/505 u, @( y1 N/ q! g6 Q
    0s - loss: 0.0144 - val_loss: 0.0133
      O2 }. |' V, \4 ?4 v6 m" b2 o9 CEpoch 50/50
    3 O: `8 ?8 O% D" t5 m  d% t0s - loss: 0.0144 - val_loss: 0.0133
    ( g+ G5 W0 U* e4 W5 C: @% n& S; j3 {- m2 O  @2 U' w
    6 S8 T3 m) \+ F9 p# k( p) z! \
    实验2:用前3天的天气数据,预测某一天的空气质量
    1 Z  d# M8 n9 w7 a7 F使用LSTM模型* m% Y, C9 X5 \$ M/ G( g3 B
    . ]3 R8 K5 I" K  Q+ N+ n5 q' K
    1 U( _5 X, x) a2 a
    结果:+ h6 B3 }% _. v) t
    Epoch 49/50
    : J. p; ?, D& ^% g, }" Z+ p0s - loss: 0.0147 - val_loss: 0.0149
    ' u' Y6 N& J3 O0 [4 eEpoch 50/50
    ; |2 C7 E8 r- Q, o0s - loss: 0.0147 - val_loss: 0.01504 k2 Z* W1 [. D

    , v5 S7 ?. {9 `# H/ f2 b
    ; [6 E4 [  R+ |$ J1 M6 [
    实验3:用前一天的天气数据,预测某一天的空气质量+ }5 f3 C% L7 H+ d
    使用普通的全连接模型 Dense()
    * T6 f0 E9 K3 D结果:
    . z* Y2 A. `5 v  f" E/ ?! }1 |0 AEpoch 49/50
    , H5 e( P' {" j0s - loss: 0.0144 - val_loss: 0.0146
    : X1 r' A2 C6 @' D* T, dEpoch 50/50
    ! [6 U1 v: Z' _6 s' |& N0 K0s - loss: 0.0148 - val_loss: 0.0151
    " ]' Y' H( N/ n+ i7 ]% \9 d6 ?' l& Q- z$ v# I1 t8 X; `: r. ?
    # {( }' Z' V3 h) w; c4 [: s+ i  k
    实验4:用前三天的天气数据,预测某一天的空气质量% R$ [8 e" G1 g, P' @
    使用普通的全连接模型 Dense()6 m8 Z$ N  R$ M% z
    结果:
    5 k8 U/ X4 F9 p' {) zEpoch 49/50' E1 \, r/ B! g' Z5 v/ U7 E
    0s - loss: 0.0150 - val_loss: 0.0165
    ) B' _7 _. W- gEpoch 50/50
    8 N# n3 x; q$ ]- F# j3 O1 c: p; K0s - loss: 0.0148 - val_loss: 0.01419 k+ i- O3 X* n

    : e7 l& s3 P+ B& z
    . R- N1 ]1 Y% W9 K, A8 g
    实验5:用前一天的天气数据,预测某一天的空气质量
    / |4 P4 L- _6 ~$ ^9 [使用SimpleRNN
    0 ~, {* F! B5 h  s! qEpoch 49/50" `: d% n, k- g, ^" T
    0s - loss: 0.0160 - val_loss: 0.0140
    ' \) m7 l( ~) F$ m) ?$ @. [Epoch 50/500 p/ |6 O6 J7 j! ^  z
    0s - loss: 0.0147 - val_loss: 0.0150' |) O. ~: `: o$ I0 T" u
    8 d" ^3 ]& h- C5 N: E

    5 X5 l5 N' ]$ n2 l! U. `5 b实验6:用前三天的天气数据,预测某一天的空气质量
    & h$ c& {* V% K3 X使用SimpleRNN5 q& U- c- r- R  ?  \4 z; y  I* L  N
    Epoch 49/502 ]# ~* U& l5 ?/ S
    0s - loss: 0.0164 - val_loss: 0.0233" k: w& M' j0 ]
    Epoch 50/50; e8 c# }; \1 X. E  |
    0s - loss: 0.0166 - val_loss: 0.0227
    2 Y% `  h  f" N# y# g! rRNN和DNN的区别

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


    3 e0 X- w7 A( y. L
    4 q/ k3 ^  C! h1 X0 b5 b% {
    " z2 I' C4 q( I0 [" f
    RNN和LSTM的区别1 @- D, q  O8 z( e1 y* ]. u
    LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
    0 Q) `# ~! F4 d8 x% d1 g5 `. ^
    * ?; O$ n8 R0 }0 v6 j
    & D3 k. g( t. t% t" b9 \$ R" \
    但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。
    . ]( R' m! }  Q0 w# Z5 Q5 ]* y
    + C8 ^3 Q8 m  z
    ; X: [; R# j! x; _1 {0 R) n4 h' d请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员

    ; ?0 m& q* `' {7 P1 w
    ; B- P+ q, O6 \% V6 t/ _( p4 K: @) }
    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-7-10 00:02 , Processed in 0.441631 second(s), 56 queries .

    回顶部