QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4397|回复: 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预测时间序列数据/ u5 M4 E' t& _; e$ _6 e+ I
    1 e+ U& h1 S* z/ K! h3 Z
    * u% h& J1 D: t: Q+ D
    文章目录' T  ?& Z$ {% A) [; |$ g; o# m" [
    背景
    $ R% c+ U8 x1 T* w" l! ~6 J9 k+ |" |) t结论) G7 l7 R0 K' i
    代码
    3 p( z' E* Z+ P& f" A3 a0 D& i$ @实验结果: y: `6 H4 i) g) f1 |6 n
    RNN和DNN的区别
    " z  l4 i( W" @$ R; ERNN和LSTM的区别8 `; G' a/ a3 @0 Q  u! r1 f0 Y4 [
    背景( l2 b8 j2 p3 ^$ p8 H" @' j
    复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验
    8 ]) B% V- E4 w$ a熟悉用LSTM模型训练- o# q7 j& E- B. l7 \( L& y( ]
    验证将时序数据 转化为分类问题后,预测是否有效果
    # X4 ?! w) t3 G1 m对比SimpleRNN与LSTM模型 哪个效果最好?
    . O/ B# r$ ^$ n4 w) V8 l( O  a0 R# ^验证LSTM相比于Dense()模型 是否有提升?
    * ^* ]. B' s4 t对比使用前3天的数据 和使用前1天的数据 哪个效果最好?( r0 x, i+ U4 h- V
    结论; o3 Q1 t& o5 e' m6 C3 m7 p
    使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好
    - d$ S, O" N3 e1 G( k3 O7 j使用LSTM的效果优于SimpleRNN* ~4 v: d/ j% `9 S
    代码* B2 [- O- f+ N' B
    from pandas import read_csv
    3 X% e) k% N" h7 R8 N/ ofrom datetime import datetime- {$ W0 {" g2 t
    import pandas as pd
    ' {  D0 E- \7 k. Zfrom pandas import DataFrame
    + i  d- i" X9 k& R: n' D0 afrom sklearn.preprocessing import LabelEncoder,MinMaxScaler
    % {. v& G8 k' x8 \. ~! ~  ifrom sklearn.metrics import mean_squared_error
    7 x1 Q! U& v  t( M; f+ W# ^( \2 Wfrom keras.models import Sequential
    / C' H  X+ R5 tfrom keras.layers import Dense, Dropout5 r" [  \0 T" e! W* z# k' D; G8 M0 ]
    from keras.layers import LSTM
    1 h! W( K% W, N) \( Vfrom keras.layers.recurrent import SimpleRNN. y; B6 ]  _3 S+ h6 i3 l5 G
    from numpy import concatenate
    / Z, w& M. H; M; C, D7 k. v- ufrom math import sqrt4 f3 v$ B$ c$ z7 F2 O9 n, O
    ; f- |7 C& |0 g" j/ N4 i
      K5 L* I* A9 c2 l1 G

    # K% q  B! M  S) u8 G3 ~

    2 D3 Y6 |$ E6 L  A2 D. w* W: ~7 q9 H# load data
    2 B4 v3 v& ~. c) \" O4 Udef parse(x):, J2 N* N  H* q0 i+ q$ J  v# f
            return datetime.strptime(x, '%Y %m %d %H'), S" l* h) a7 `4 r
    0 o4 C7 J$ C0 c' h$ w+ S8 L5 p
    def read_raw():) e% t. J2 i; L# r; |7 L2 L/ |
        dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
    4 [9 n; i4 V7 s# H8 r    dataset.drop('No', axis=1, inplace=True)( j5 ^& f/ n3 a% H' E9 j
        # manually specify column names3 R8 x) R1 H* y! b2 R3 ^' n
        dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
    " i$ R: V) i- n    dataset.index.name = 'date'5 ^4 d* R5 T+ F- s
        # mark all NA values with 02 E; S  e7 x3 L6 f1 Z& }
        dataset['pollution'].fillna(0, inplace=True)  `9 d7 r) ?) R+ Y1 o5 z4 O& }/ v
        # drop the first 24 hours: \$ L. @3 [# |8 m
        dataset = dataset[24:]
    / K% y' ], o# u3 }/ }    # summarize first 5 rows0 M9 z* Y6 q9 ^/ ~4 d
        print(dataset.head(5))
    . X1 C' L0 A6 H* k    # save to file% w! Z; T6 C" A7 L5 i; `+ g, \
        dataset.to_csv('pollution.csv')
    ! @* b* N2 i6 M/ x' d2 {9 Z, _$ v; e! l/ z

    - C$ J" a( f* c) ?. L' q
    2 I$ C- X6 @1 B
    ! @) r9 I0 ^0 Y+ e" |9 y6 y+ \
    # convert series to supervised learning' V/ Q3 P' S+ L8 I2 W: ~0 C& _
    def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
    ' j* a* v/ w" ^) _    n_vars = 1 if type(data) is list else data.shape[1]
    7 k/ J2 c( \7 X$ i1 h! Q    df = DataFrame(data)
    0 I7 e, D+ W* r' G3 E9 l" _$ z    cols, names = list(), list()
    3 i7 b3 x+ W( [0 d8 Y    # input sequence (t-n, ... t-1)2 }( S1 k) T- \! k( [
        for i in range(n_in, 0, -1):
    + T/ T& j& R5 e+ b+ U1 H+ E        cols.append(df.shift(i))
    ) a! ?- I# Z6 o/ v5 z. G- q% Y        names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]: l* Q3 s0 L. u, D" J' b
        # forecast sequence (t, t+1, ... t+n)3 q3 E- E$ i+ L; |  v0 F
        for i in range(0, n_out):" J; @; y3 H- _/ O
            cols.append(df.shift(-i))6 {# O1 r. c) U$ }+ ]! l! _# @
            if i == 0:# x; `3 q7 n9 Z
                names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
    , D3 T. E1 p8 ?- v6 E        else:& B8 D9 H9 l0 F$ o% B  E) W% K' k
                names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
    - ^0 F  {; y' q; e' K    # put it all together
    5 y5 `. ?0 }1 u" K    agg = pd.concat(cols, axis=1)
    8 h; W% ^* H5 g1 w9 k+ _    agg.columns = names
    4 Y6 h" Q. f0 B& _+ s    # drop rows with NaN values6 R( b( M2 i+ r4 l* Q% T
        if dropnan:
    . E8 O' E3 R( w" V* s1 H        agg.dropna(inplace=True)6 c; d9 I$ a+ H6 @7 o
        return agg4 P4 f" ^/ z1 z+ p1 L% m- L
    ; m1 U- {# B& a' Z
    # load dataset
    8 h; F- T2 d- G# L. G3 a! K9 ddataset = read_csv('pollution.csv', header=0, index_col=0)
    9 p, X0 N! l, \8 wvalues = dataset.values
    8 A9 T$ s8 }9 u- v" c: R* u
    ( V6 W( N* f! Y4 E& d

    & }9 k9 L; |- o) u- z# i+ n# integer encode direction
    1 o6 f5 K) @! N$ t1 p! kencoder = LabelEncoder()& d& ~2 f+ _8 I9 b! `
    print(values[:,4])  g+ c1 r, `" T3 f( b
    values[:,4] = encoder.fit_transform(values[:,4])+ m* ?  @' e" F* ^) n; F( g, g/ ]
    # ensure all data is float
    ! U2 m, A* @: g4 \5 A- Q* x+ |values = values.astype('float32')
    ; e. ~# l: r/ N6 {- ~: Q# normalize features
    ( W# m1 d7 G9 \1 C) L: jscaler = MinMaxScaler(feature_range=(0, 1))9 a3 S5 W3 e9 _0 e* c
    scaled = scaler.fit_transform(values)
    2 B, F& b5 L% D# frame as supervised learning& |4 o- \; i9 h8 t0 m8 z- W6 ]) y
    reframed = series_to_supervised(scaled, 1, 1) ; k- h2 Q8 b) S' L
    #reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
    8 H4 o* `; d9 O# f' vprint("columns:", reframed.columns)
    1 D! b& }  W3 `9 J2 g( a# drop columns we don't want to predict$ v6 Q+ H+ S. [* v5 T% k8 b: m+ z
    reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
    $ I3 z$ k7 u  `( P' s  m* h#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据' s5 ~2 G* {0 }* q' L3 b- |6 m
    print(reframed.head()): l  P9 ?' Q1 L" \
    print("new columns:", reframed.columns)- D1 o8 C5 n8 Q& S
    # split into train and test sets8 A( Z/ v7 a+ F7 d5 d/ g& w
    values = reframed.values# W" [1 ]: A; E1 B" W
    n_train_hours = 365 * 24$ r7 N0 W. E, D1 G6 `; {1 |
    train = values[:n_train_hours, :]. k0 t! t4 @& D, d- x
    test = values[n_train_hours:, :]3 \* o& C5 ?# `" r' K% O# U
    # split into input and outputs
    ; O7 D7 E+ }$ M! ytrain_X, train_y = train[:, :-1], train[:, -1]
    7 z- O( J# x6 Atest_X, test_y = test[:, :-1], test[:, -1]" L; ]/ D% \4 e7 @3 N
    # reshape input to be 3D [samples, timesteps, features]
    # o$ }) f7 |( O+ c: B8 o* n" O#使用Dense()模型时不用变换
    7 }. h! j: P; mtrain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))/ w- x; P0 A! |( v3 L
    test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1])), J7 Y1 w( V# }. t6 g5 }7 J
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
    + |2 b4 Q# s1 `- c, z0 A, s! _# design network6 U6 M  x+ z' z3 q
    model = Sequential()2 c, L5 k/ x6 \; {
    #model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    , Z! m& A7 k$ F/ d, X#model.add(Dense(50, activation='relu', input_dim = 8))0 s/ F$ m: }; U/ w7 p5 f
    model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))# I, I" ~8 `2 C; o4 ]; [+ H
    model.add(Dense(1))
    4 k5 X$ l8 R8 A  C$ W+ p! Y7 x0 Dmodel.compile(loss='mae', optimizer='adam')
    # h/ l0 L9 R7 s, G4 d& h2 `. m# fit network
    4 F; L* C3 D+ ohistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
      _" c4 c# v8 r' G5 u! N# make a prediction
    ) G" [4 W" k* r- byhat = model.predict(test_X)
    8 ~8 [2 T9 f2 _& F; Y$ I% H# O1 nprint("yhat shape:", yhat.shape)
    8 ?( C2 K. q" h/ C2 {* i: ^'''3 t8 O" K. r( v9 V3 t! ]. H
    计算在测试集上的均方差) T( s" F! z% u; k4 k* |1 n
    test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))1 w* \2 w- y8 o' g
    print("test_X shape:", test_X.shape)& w( V# [( D( Y# D9 J% X- ^
    % s3 e& R. d5 E3 j1 n& N) D

    ' z; s% g' F, H0 T8 E8 y/ a' M# invert scaling for forecast$ i% {1 D; r, T
    inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
    4 [- ^: D* _. c% U- t! o6 Rinv_yhat = scaler.inverse_transform(inv_yhat)
    - m8 s5 H# O4 C- R3 U- S4 T" |: jinv_yhat = inv_yhat[:,0]
    # V/ F- \# q3 D# invert scaling for actual
    $ Z# f0 k' j2 x; v* x; T- Wtest_y = test_y.reshape((len(test_y), 1))+ b5 f* W9 C! h6 `' v  R. a6 Q
    inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)
    / V$ z+ I) x2 [, L+ t+ F* `print("inv_y:", inv_y[:10])
    4 l" s+ G, A. L+ oprint("inv_y shape:", inv_y.shape)
    9 o3 D8 {; k, n: {1 X
    * Y# c8 y* m8 U! `! t

    4 N& ~/ z# O' }inv_y = scaler.inverse_transform(inv_y)
    & x4 @" W2 A. o. u6 Z1 h( qprint(inv_y, "*"*30)
    5 v$ C' K5 D2 w5 r# C' ?  g# K* A9 b( ?
      _; {/ c* L& |4 C% _
    inv_y = inv_y[:,0]9 w$ d; a; {9 ~9 E3 ], [! V
    # calculate RMSE
    ' j/ `3 {/ @# Armse = sqrt(mean_squared_error(inv_y, inv_yhat))
      K2 ?, `5 U8 W+ Q3 ~% u1 X$ {' G- ^print(inv_y[:100], inv_yhat[:100])7 y6 o, t) {3 O7 t4 C, E
    print('Test RMSE: %.3f' % rmse)
    : D2 f( E+ K1 Z  s6 a# V  N7 P# d/ z# ?0 T
    % Q( i  v* D( |0 j( t2 s
    '''
    1 ?1 j/ \+ s& i- w0 W实验结果; Y9 u$ U7 {$ S
    实验1:用前一天的天气数据,预测某一天的空气质量5 Q2 f. n. W  S
    使用LSTM模型0 E7 v8 ?2 ?8 d1 i
    结果:8 H+ K% \7 f0 {3 `% g# V+ h1 ]
    Epoch 49/50
    $ g6 t) v  T% Q; C2 ~: m" B( C& S0s - loss: 0.0144 - val_loss: 0.0133
    $ J% ^2 C+ k5 v5 v4 D. pEpoch 50/50
    . y6 u. @  \0 O! ~5 i+ H; {3 }0s - loss: 0.0144 - val_loss: 0.0133/ ^8 {+ B. }" P- f: F) z

    + ]$ }5 b) Y% ?* n7 R. z5 }& N
    / N, ?  a/ S. N/ P& e& V) g" f
    实验2:用前3天的天气数据,预测某一天的空气质量
    . ~( H; _+ b9 ?3 |; u3 ^+ B$ W% V& J3 ~  ^使用LSTM模型
    . y& q  ^5 Y  V2 E% e) T9 M5 R( m5 E9 P$ u; k' N: l
    ' n( x- d! M, [. @4 ]. U8 c
    结果:
    / V! b1 g- W7 H% E, N& {& FEpoch 49/50, Y& z8 J7 X  m" d! K8 ^
    0s - loss: 0.0147 - val_loss: 0.0149
    5 t% A+ K0 G; o* e1 Y+ @Epoch 50/50
    * {$ ~# C. w- I5 [- s- `1 S0s - loss: 0.0147 - val_loss: 0.0150
    # K$ q( y2 _8 n; l! f9 z  D
    1 @+ f4 y* u6 {) f. P& u" U; C
    0 ^# E( P5 X+ V1 ^4 ?0 I+ [9 t
    实验3:用前一天的天气数据,预测某一天的空气质量
    + y* I) p$ ~& n& V! Y使用普通的全连接模型 Dense()
    * v; L) d" D3 x: W+ R5 k& b; d6 ~结果:
      b+ w3 g7 ^, ?+ s/ y- XEpoch 49/509 b1 y! V* ^8 q4 h# `- D9 y6 k
    0s - loss: 0.0144 - val_loss: 0.0146
    : q  [: `' a# K0 ?4 nEpoch 50/50' W' T; B% Q) ?, M3 }' f) y/ ?
    0s - loss: 0.0148 - val_loss: 0.0151* X3 i* Q9 }# {) u2 @5 ^( B2 y

      `  g( G% n2 U
    * H8 Q9 F6 w! D( b8 H: s; F& A
    实验4:用前三天的天气数据,预测某一天的空气质量
    7 T; y; p6 S' Q0 a使用普通的全连接模型 Dense()
    ; m0 O2 K. O& ^5 Z- U  q结果:
      W5 z+ r. {  U- @) [* u$ [4 e. sEpoch 49/50
    9 z& s% b9 f$ r) \) b: q0s - loss: 0.0150 - val_loss: 0.0165# W- W5 ?- m6 D2 `7 F; F+ g
    Epoch 50/500 E% n7 t4 \4 L8 F- A5 e1 l
    0s - loss: 0.0148 - val_loss: 0.0141
    ) _& T* c; V, D* d4 _1 ^* }, Q' c: h, U( j6 ?! I, G

    : ?: W- ~; O) _2 ]9 n( L实验5:用前一天的天气数据,预测某一天的空气质量
    # F/ L1 H+ R% i; D% `2 E' k使用SimpleRNN
    ) ~$ B9 z. C; T7 m7 eEpoch 49/50" A: k- l& ]& D9 S; w
    0s - loss: 0.0160 - val_loss: 0.0140
      i2 L; O7 r: Z+ v' [! @2 b; J1 zEpoch 50/50# y) d' u  b' t7 T+ ~" R
    0s - loss: 0.0147 - val_loss: 0.0150
    7 v1 `# E0 `' Y8 m3 }9 T2 ]; \1 \0 \" Y; k; ^7 j" a

    . }# c; i2 j8 Q" p( k实验6:用前三天的天气数据,预测某一天的空气质量9 w7 k7 H, u. P5 V
    使用SimpleRNN
    7 K% K" x  v; G2 y$ ^0 dEpoch 49/50
    7 ~! A" E% K4 |$ u' Q- s' [: D0 y0s - loss: 0.0164 - val_loss: 0.0233
    6 n2 d% [, n: z1 M8 UEpoch 50/50& k' p0 T) p1 M8 p+ ~% {% n, Q, [
    0s - loss: 0.0166 - val_loss: 0.0227
    . M5 ]& S8 P" r1 BRNN和DNN的区别

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

    ) t3 b' v- |/ `% c$ Z* {
    3 @( h; R3 U* `& V

    1 ~' q9 f5 j$ Y; w1 \
    RNN和LSTM的区别
    + G) B$ G0 ~6 m" _, s3 ELSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。3 L! u8 ~+ R2 J! ~5 |; @
    ; m$ |9 O, U, M" g8 ~5 ~

    4 H1 e7 M9 W4 o9 H8 i1 B但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。7 |* E' h" T, Z) g1 `' F7 T& ?

    + ]5 K8 N6 W) K3 D
    ! X9 W4 _, Q2 o- {4 T请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员

    7 D! K; T8 E6 ^* M* x
    : w0 U; _& q* l! `7 i- I4 V- m
    ; z5 i2 `& y& c3 B* 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 04:14 , Processed in 0.336082 second(s), 55 queries .

    回顶部