QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4398|回复: 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预测时间序列数据$ F- y7 S' y8 x5 j+ g
    1 G% Y4 e0 e0 }
    4 Q4 a- q# p  A, X
    文章目录5 H& e# g  n7 O+ O
    背景5 S( {& t) m- `6 F1 G
    结论
    6 k1 B1 `+ r* z, G3 }; E代码
    " k: F$ {* q3 w( _# `实验结果
    3 |4 u9 u) Z0 hRNN和DNN的区别! H/ C1 M$ Q7 N( g$ _  s5 t: N
    RNN和LSTM的区别
    & h7 k2 u/ V/ b, r& C9 l背景
    & ?: y, |# I. P* H复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验, U) W0 n1 G! }9 N7 r
    熟悉用LSTM模型训练% n; R# A5 }/ L. E
    验证将时序数据 转化为分类问题后,预测是否有效果
    3 z+ r  o. {0 v7 H! @, p3 x对比SimpleRNN与LSTM模型 哪个效果最好?
    ! H# @$ y9 V7 |: K% E验证LSTM相比于Dense()模型 是否有提升?
    8 p4 x7 Z7 M3 p+ U对比使用前3天的数据 和使用前1天的数据 哪个效果最好?1 j, q" c, C8 \) F7 b! O4 i% g
    结论) e$ R0 w3 E- h0 Y+ D
    使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好1 m. V) }$ S$ h1 G4 A+ n, H" j4 W5 _
    使用LSTM的效果优于SimpleRNN
    + U' l8 o0 d$ w( `8 }4 |1 y代码
    ' f2 ]1 B2 U1 E3 }8 |from pandas import read_csv
    , r! s& ^$ \9 X+ R7 r; d& Mfrom datetime import datetime) ^; s8 z# W) \& E- `: o+ F
    import pandas as pd. o3 q5 s" z0 {+ L$ z( p' c( Z! ?
    from pandas import DataFrame
    9 A( r9 l. I/ a1 b' `+ y+ Pfrom sklearn.preprocessing import LabelEncoder,MinMaxScaler2 ^, D3 a2 {. f' _
    from sklearn.metrics import mean_squared_error% A0 M4 i' v# j) c6 {
    from keras.models import Sequential7 |$ k: H4 X" p3 @% |$ ~+ x& q
    from keras.layers import Dense, Dropout- o& P9 }4 O: @" ^) {/ s6 u
    from keras.layers import LSTM
    - Q4 S; ~' ?4 a% ufrom keras.layers.recurrent import SimpleRNN! B1 @& U: r0 g* J
    from numpy import concatenate/ B& \9 ?: x9 K/ u
    from math import sqrt" {1 A' c6 I1 l; ?4 L# P5 p& w

    " A4 a, e% i) o
    ' o( O8 J) }9 W
    % h, h& |- O7 X; j2 P9 f! v
    6 r0 n: n  ~& I4 T
    # load data
    $ h- i) Z: u8 C( y/ M7 Ydef parse(x):& L8 c; w! |/ g. @; q& u
            return datetime.strptime(x, '%Y %m %d %H')& V( G8 R+ j% p5 P9 i) T8 O4 Y+ m

    $ J5 j6 j: `1 ], qdef read_raw():9 U2 k  C+ O% |" d/ p
        dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
    ; l  [* X' R4 v9 K! [3 M5 c& \* Q    dataset.drop('No', axis=1, inplace=True)2 f, Z1 {& ^7 H
        # manually specify column names
    4 M' t, h. `7 D( d9 J$ f) Z    dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
    1 G1 I: `: p1 C# z    dataset.index.name = 'date'0 a! c- O0 i  n: `$ }7 a4 O' ~
        # mark all NA values with 0
    * F+ `5 H& K/ `$ K9 o1 C+ Q% Z    dataset['pollution'].fillna(0, inplace=True). F# g6 ?) V- F- A0 l
        # drop the first 24 hours6 I' r& e! E# @
        dataset = dataset[24:]
    0 D3 ~+ v( c+ w# h    # summarize first 5 rows
    8 z( ^9 |  y7 t4 b1 ~% {, ^    print(dataset.head(5))+ X- h* [, U: I! G& S
        # save to file# W, O, \. \' G9 a6 ^/ h+ q8 L
        dataset.to_csv('pollution.csv')% q/ o9 X  c0 D( S
    7 Z- Q6 g5 n0 G  w
    ) ^+ ?7 D- h3 o* g

    7 @4 y  p. l% k
    $ U6 h8 z- P. L. _" s, z; N- h
    # convert series to supervised learning
    ( `) w3 K: [) S' @1 Rdef series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
    5 N; z! y: {  F8 c' ~* K    n_vars = 1 if type(data) is list else data.shape[1]0 P* k* t2 A% m" u* G4 \; F
        df = DataFrame(data)# `, L3 Q& p) ?$ W+ y6 o: F: N
        cols, names = list(), list()
    $ G+ C) n+ V* _# q; ^    # input sequence (t-n, ... t-1)
    : A- a; I5 d" F- n% S; N% b) c- d    for i in range(n_in, 0, -1):6 P/ M. p/ m9 [( `
            cols.append(df.shift(i))* M4 F0 U5 F2 T8 ]8 d$ B- p
            names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
    9 i9 J: o  p, C. H( H# |& L    # forecast sequence (t, t+1, ... t+n)( c# e* F. Y7 @) b! T# \% b
        for i in range(0, n_out):
    " V, v7 R8 c4 s# `$ L        cols.append(df.shift(-i))
    * ~" @8 g9 o3 U' l0 {* K        if i == 0:/ \2 p3 _, _; g; |/ Y
                names += [('var%d(t)' % (j+1)) for j in range(n_vars)]3 C" x8 x+ E3 h: q
            else:, N+ q! U- c' N( f" \: l
                names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]: G  R1 A' d% A6 L7 k; v
        # put it all together+ _9 q. a4 D: ?$ O  l4 {+ e
        agg = pd.concat(cols, axis=1)
    4 H8 M7 Y! A6 v* t" w) a& r7 p$ G    agg.columns = names- {3 C3 l6 ~) I( _, o' h4 ^
        # drop rows with NaN values
    # J  H1 [& Y; p1 q) m    if dropnan:
    * h  o( b8 K, N# A  s2 L        agg.dropna(inplace=True)
    8 O& g/ u& c  v: U5 s! R5 Z: a    return agg
    : {1 N5 O' X: B5 O, l- a' Y
    ' x: R) g$ @. G& A# I* U; _8 u& Q# load dataset
    + o# r( O! O* Y; ?( M9 Udataset = read_csv('pollution.csv', header=0, index_col=0)2 a% ]" i6 K& y: C' b) ~2 a
    values = dataset.values9 {$ T& W$ [1 y; {$ p/ s

    % u1 n4 c, p" }1 v. x- k
    3 d0 `% ^9 \1 ~% P9 I7 p0 f* y( a
    # integer encode direction
      L. F. ~$ f( X' Q- k! [7 [encoder = LabelEncoder()1 w8 `; {3 s& g0 a# }* ^
    print(values[:,4])
    - Y% R8 z, }9 s" V& M1 Zvalues[:,4] = encoder.fit_transform(values[:,4])
    1 Y: v  L* |( C& n3 _  v& j3 k# ensure all data is float6 c) M" O9 e/ c! j" P; h) w
    values = values.astype('float32')
    8 Z" r* Q' Q6 ]# b" o. F) y. d# normalize features0 M5 A( A* Y* g7 R: s
    scaler = MinMaxScaler(feature_range=(0, 1))
    * `. `4 q! O4 R) Z2 vscaled = scaler.fit_transform(values). B) J5 u; B) o, ^& i# H
    # frame as supervised learning$ O$ G! P  _; B* ^" ?3 c
    reframed = series_to_supervised(scaled, 1, 1)
    * N" `; E. g! T/ D#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
    3 ~. R: G; |7 z5 e% Z# t1 Vprint("columns:", reframed.columns)
    0 L# Y& @" p# W" Q. d% A* T# drop columns we don't want to predict
      Z. O6 A! [: k& Breframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
    $ E" v3 l3 g2 f, W. ?% P5 {#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据  d, S# [# b0 S5 M' k5 z% X
    print(reframed.head())
    4 q% r5 S6 X6 ^! z9 V4 aprint("new columns:", reframed.columns)
    6 X3 }$ g( ^9 m& M5 N8 c/ M# split into train and test sets
    $ |  g8 V9 U) b+ H+ Jvalues = reframed.values
    0 F* G0 q1 }. O% N" V6 c) F; g" ~  Zn_train_hours = 365 * 24( H$ G7 Q6 X/ K4 k/ X
    train = values[:n_train_hours, :]
    9 T2 Y, o8 l. Vtest = values[n_train_hours:, :]
    ! l: Q- \8 G( [% H! W! l/ W' C# split into input and outputs
    6 i. E) a* Z5 Ztrain_X, train_y = train[:, :-1], train[:, -1]1 C$ u4 O# J8 P+ H" _/ G
    test_X, test_y = test[:, :-1], test[:, -1]
    0 X/ ?. u6 N" |" p% a+ t% _7 ]9 T# reshape input to be 3D [samples, timesteps, features]; [7 l3 \7 L: W6 B# m7 \: z/ r
    #使用Dense()模型时不用变换
    4 o2 z' p$ C  R+ a: N( Ktrain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
      a! t8 D8 T0 C- X- o' D2 F5 Qtest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))$ [6 X5 a8 P/ `( O
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
    , J5 X5 g$ _) E# design network. F# }( H; N& K. T; V# P- a; O* g
    model = Sequential()
    + ?3 {: z- U5 [& m( F, w: a7 e#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    $ C3 m- L; h6 @0 X0 R#model.add(Dense(50, activation='relu', input_dim = 8))
    % M8 ]* p  A2 x! ^$ l4 Jmodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    - h. M$ H4 V- @7 W3 D6 U/ S0 bmodel.add(Dense(1))
    4 Y3 z; F( A) C" t/ E0 Z) w" \, i* Wmodel.compile(loss='mae', optimizer='adam'), T, h5 b# A. Y- _5 [, H+ K
    # fit network6 E0 g: B4 }+ l
    history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
    # Z) h, m: ?3 ^6 H# make a prediction7 A: C3 _0 M0 y
    yhat = model.predict(test_X)
    " ]& j. a! I) }print("yhat shape:", yhat.shape)
      m. n+ R; M+ |; e- d'''
    : b2 x- I5 R! C3 a  {计算在测试集上的均方差: L- M3 _9 ~) ~
    test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
    : Q) ]2 R; D) z8 }% u. L- ^print("test_X shape:", test_X.shape)9 a7 _; J. k0 e! i# x% n$ `
    ! {- h3 `1 v4 g. X3 {! q" S# `. P

    5 v$ {* [% V" A- X- \+ m# invert scaling for forecast
    , B$ J1 C5 P1 }3 O3 H' v4 minv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
    3 K9 |4 U( n  ^# ^inv_yhat = scaler.inverse_transform(inv_yhat)9 u- @! @4 O, M
    inv_yhat = inv_yhat[:,0]
    - g/ t7 I. L( L* r8 U1 X" [- `# invert scaling for actual
    , Z4 v, h4 R( L. a+ q& C) [' btest_y = test_y.reshape((len(test_y), 1))
    - u* }8 O4 j: A/ P7 q) l! U8 pinv_y = concatenate((test_y, test_X[:, 1:]), axis=1)* i1 S9 p. j' L8 E
    print("inv_y:", inv_y[:10])
    $ l" Y4 N  u* zprint("inv_y shape:", inv_y.shape)
    & x4 E& J$ h+ v4 J- ^) {; B9 D- o; ^- d% \6 }
    4 ^; d' O8 n5 L, q
    inv_y = scaler.inverse_transform(inv_y)
    1 H" H! d# a5 X! s, Z2 b! }5 @print(inv_y, "*"*30)
    ' R% U7 U, T& i0 F) Z$ }0 Y! y" [% t( h8 G, b  Z( T

    ; g) Q9 `8 B6 j1 \+ v9 @inv_y = inv_y[:,0]
    2 H6 E$ a( ~# f2 o6 j2 J. w6 k# calculate RMSE0 }2 B0 z1 i6 d' s& f
    rmse = sqrt(mean_squared_error(inv_y, inv_yhat)): S/ |# {3 k; D! y- C; \
    print(inv_y[:100], inv_yhat[:100])7 N) m$ e* k3 J/ _! e: w4 c" P  M, {
    print('Test RMSE: %.3f' % rmse)  L2 K# h4 Z' d& \. ~) j2 r
    ( }% s: c  H/ F; J
    7 D1 Z. \- f0 T% Y8 Y7 L
    '''
    ; Q) d$ F& C7 k8 B. k  C实验结果! ]" Q& i% m* ]3 q
    实验1:用前一天的天气数据,预测某一天的空气质量
    6 Y# r. I& C; b- @$ j' ^使用LSTM模型
    8 K& |" g3 R5 A8 n结果:1 B' G' }- L' A
    Epoch 49/50. ~. n( f% p5 e) K. P0 o
    0s - loss: 0.0144 - val_loss: 0.0133) |1 ~, J) L" B1 `, q
    Epoch 50/508 @5 |& V! K8 Z8 i! W1 U' o6 b
    0s - loss: 0.0144 - val_loss: 0.0133
    9 ^( s: k0 G4 q1 Z2 q( }1 j) a0 |9 ?9 f7 d9 F1 @

    2 X; N5 N2 Z; a实验2:用前3天的天气数据,预测某一天的空气质量
    8 N+ c/ C# C1 v2 D8 w* u& B使用LSTM模型& R* U1 ~. i" o% ?2 N, U1 V

    9 C* f: l  ]9 i0 ~& V

    1 j# D) p) H0 D2 Z; h结果:
      K* b6 u2 w) C: j7 \# lEpoch 49/50" ^1 l0 {: a1 m! g! x# Z
    0s - loss: 0.0147 - val_loss: 0.0149
    9 F" |0 v6 y& KEpoch 50/508 C) |. F! l, |6 B- B" W% R
    0s - loss: 0.0147 - val_loss: 0.0150
    ' r% Q* U! A; R1 b& p  K. M% V0 h' [' Z/ T

    / O: b% P& A8 r实验3:用前一天的天气数据,预测某一天的空气质量
    & o, A) t) K+ s使用普通的全连接模型 Dense()$ k, w% M6 F0 f% m% {7 i  B. T8 D
    结果:
    2 G5 h9 z( H1 P3 o1 b6 t, \Epoch 49/504 D: t) k6 H: g
    0s - loss: 0.0144 - val_loss: 0.0146
    . k  T+ n9 C# E" V( i. Y! ZEpoch 50/50% X1 I! E6 ?4 ~9 f7 E: v4 e# D
    0s - loss: 0.0148 - val_loss: 0.0151) T- J9 J, o* K& `5 T
    9 }/ v: J$ T. q3 t
    + G1 T4 l" r+ g& e0 o3 s4 b1 d
    实验4:用前三天的天气数据,预测某一天的空气质量- Q! o7 y( D1 s" ^4 k
    使用普通的全连接模型 Dense()' d2 W; z8 ?! I
    结果:
    $ I2 y0 t) e" @. p2 s* o9 s1 qEpoch 49/500 r' j; ]0 I6 d+ r
    0s - loss: 0.0150 - val_loss: 0.0165) z( p7 {$ a' S4 ?2 @- m9 @
    Epoch 50/50; n/ b; X- G$ K4 Q) W/ ~
    0s - loss: 0.0148 - val_loss: 0.0141
    * O1 O, l5 B8 p' Y7 b0 K9 g3 _/ t, ?# R  g" t

    " i& s2 E3 K7 e: \3 r4 M- k9 _实验5:用前一天的天气数据,预测某一天的空气质量
    + s  @1 G" j7 d+ b使用SimpleRNN
    0 }- m# \: v7 a( ^$ e+ \+ A3 HEpoch 49/50
    3 }5 A0 A+ x: f  \! O0s - loss: 0.0160 - val_loss: 0.0140. D7 N% |& r' k. H2 Z# J# H
    Epoch 50/50
    " g9 _2 {, `1 [' |9 Y0s - loss: 0.0147 - val_loss: 0.0150( A% G  d  n4 J: c; d

    ( `3 l$ C) }9 _$ G1 V8 I4 d

      z5 n0 [! [3 m实验6:用前三天的天气数据,预测某一天的空气质量
    7 [4 a0 c+ s; V使用SimpleRNN7 ]7 M( B' h! d. z! f
    Epoch 49/50
    , X3 R. u7 Q/ O% u# b( F0s - loss: 0.0164 - val_loss: 0.0233. @1 ^2 [" r6 z( F8 ~" c* I$ F
    Epoch 50/504 H; ]% K4 [: V7 G* Q; D! z
    0s - loss: 0.0166 - val_loss: 0.0227- m, _3 f* F1 t9 u
    RNN和DNN的区别

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


    3 s4 C2 M" Z5 O& K

    - x& U* A5 l* v- l  }% t' s1 k0 t, Y3 E: P6 F3 [- r, f
    RNN和LSTM的区别5 E0 e' |' O) U$ U$ A' `$ c# h3 d% N( V) s
    LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。7 o; @: y/ q( T& v- s! |5 G

    6 Y7 H+ M  ?1 n5 K* j

    6 }9 O" b7 f5 G但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。9 w$ D; T3 P: Y! s
    : H5 T3 M+ J( {+ |: Z% Q: j+ `
    , f5 o% e) h7 P& o7 B& F' p- ?
    请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
    ! A& y1 ~8 v1 B2 O/ x$ W! ^8 V
    ) ]/ I& D- i9 v# R+ D- F
    8 G$ ~0 P/ i$ h; j3 u
    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-29 07:46 , Processed in 0.398116 second(s), 56 queries .

    回顶部