QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4328|回复: 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预测时间序列数据
    3 z$ |) k5 c. y8 C' a
    & h/ j  A4 M' Q! j8 E% y
    # f) e* D7 m$ }# W
    文章目录
    3 j0 f5 w. e; S0 h* B/ ~* s& F* s9 O背景
    6 W! G1 g+ O, e6 `8 d, O3 q结论
    & o: ]: j) g9 H- c代码* U9 E( ?) `9 G6 x, ]
    实验结果
    ) q' c6 r1 |' vRNN和DNN的区别6 r4 V/ }& ~9 F" p- ^' b0 b
    RNN和LSTM的区别
    ) T$ h) u+ X. s, V% [' V背景
    : z: v$ Z9 L2 e1 q7 Q( I0 y复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验9 y9 W- K1 Y0 W( l! P9 J( d
    熟悉用LSTM模型训练
    - ~) F) b7 `" p; X验证将时序数据 转化为分类问题后,预测是否有效果
    / A3 u" P1 M6 g" l; E对比SimpleRNN与LSTM模型 哪个效果最好?5 j0 y6 E! r4 w- q) R' |* o* S
    验证LSTM相比于Dense()模型 是否有提升?( g, ?5 c$ A5 P1 l. q
    对比使用前3天的数据 和使用前1天的数据 哪个效果最好?  s" t/ z& a9 I- J; P
    结论
    % C7 a9 k0 g7 W7 e5 j使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好8 Z8 f! F# ~' |' c  W) t5 T- o4 D( P4 X
    使用LSTM的效果优于SimpleRNN
    , Z8 j. |' J) k! }1 |/ [代码& U3 _( C8 s3 M' Y4 s
    from pandas import read_csv* e) ~. C" w% K2 T
    from datetime import datetime
    6 p- d+ g% |3 d# \& ~1 w) [7 wimport pandas as pd* j( M( q: ?; C6 W5 n, D
    from pandas import DataFrame
    2 W/ U7 D! c# i7 Y9 A1 G  Ifrom sklearn.preprocessing import LabelEncoder,MinMaxScaler
    $ B9 I4 I1 H7 I9 Gfrom sklearn.metrics import mean_squared_error8 Z1 M8 }7 f) u3 u! I
    from keras.models import Sequential
    + C* {- O+ y7 X% d2 g, Dfrom keras.layers import Dense, Dropout
    3 O0 L" ~, `% V* I) e/ bfrom keras.layers import LSTM
    ; @8 F+ V2 l/ ]1 ufrom keras.layers.recurrent import SimpleRNN% e2 z- R5 E4 ^
    from numpy import concatenate
    9 ?% `/ i2 X, f% C4 m: Dfrom math import sqrt
    7 k/ [8 j- N) [4 j* q$ w2 l; v* @9 o1 k( P1 @

    & v# b& e4 b; S/ o3 N* H
    ! j- x% I" J+ y

    6 u/ `$ f/ D1 E8 F8 X7 ]# load data6 w$ U; P7 k9 ], G
    def parse(x):
    0 ~5 w' k2 O* D* r( U        return datetime.strptime(x, '%Y %m %d %H')
    0 r, ~/ g& ~, ]; V$ F0 p" W 8 e/ r5 M: C% D- @2 x
    def read_raw():
    3 x4 L: p2 P& F5 T( C: I    dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
    9 }- v7 L$ Y$ B9 d8 {  `- S9 k    dataset.drop('No', axis=1, inplace=True)
    # i% N- E: V9 B8 C' _* X    # manually specify column names
    : g* O6 l% B9 K0 ~) d    dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']$ a+ s, ?3 ^5 {5 ]1 N
        dataset.index.name = 'date'
    : z5 `# k4 O! |$ k# ~# H% O) \    # mark all NA values with 0
    , d5 L. p! H7 Y! S" N    dataset['pollution'].fillna(0, inplace=True)# C6 E8 s8 x* m; ]# z3 I! i% d
        # drop the first 24 hours- k2 `9 {- D; H8 W
        dataset = dataset[24:]
    ! g* Y! M2 O) _5 S0 v/ \    # summarize first 5 rows* e( V1 T. ~2 S* f
        print(dataset.head(5))
    5 [/ a! f4 P4 a0 R4 F" u' J3 c1 J    # save to file1 J0 h2 f. `+ n
        dataset.to_csv('pollution.csv')5 X* d& B  V( a, `5 ~
      m$ d& y3 w7 K3 ^/ B5 h
      Y( E6 r; Z3 w4 X

    : Q* q( Y, V! Q- n
    % _' w' W2 B  Y& {- I3 {/ y& G
    # convert series to supervised learning# b! t* X5 a- o4 w" P
    def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
    + D7 `' k; C4 X+ x" u+ y    n_vars = 1 if type(data) is list else data.shape[1]
    ( [! |1 k; |7 O  K    df = DataFrame(data)
    8 P- m# y. B2 j- ]    cols, names = list(), list()
    2 k( C6 y/ e) G$ p" C: ?    # input sequence (t-n, ... t-1)
    , r- F" l( a# W: p9 h& [' ]; Q    for i in range(n_in, 0, -1):
    - l0 {' \7 u" N! W- _' x2 M! T        cols.append(df.shift(i))
    ( E9 K1 \; K5 E. L# h' \* L        names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]5 w0 n4 k+ S& m6 T( c4 O
        # forecast sequence (t, t+1, ... t+n)# D- W2 d) q: }' \
        for i in range(0, n_out):
    ( U$ S0 i' i, N* Z        cols.append(df.shift(-i))
    ! J! W  B0 b2 H# Y! d/ @        if i == 0:
    2 @' J9 j- s+ s$ I% a* `$ p0 x+ i            names += [('var%d(t)' % (j+1)) for j in range(n_vars)]: p  g. ~" C: |0 m" a
            else:
    2 @& h& J: V) e            names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]8 P* Y* F3 i/ X- @( @$ M4 w
        # put it all together
    . ?0 f' A6 Z+ h- w    agg = pd.concat(cols, axis=1)
    - L8 `9 q3 P. U1 ]* c2 @5 D6 o    agg.columns = names: R7 b- B' r4 S* Q7 W
        # drop rows with NaN values
    - o2 W$ e1 T1 D0 k7 u: D5 i    if dropnan:$ a  p5 H$ P. d. y. y( }0 k# _
            agg.dropna(inplace=True)/ t- u* _) g9 p1 Q1 E
        return agg
    ' s* K# I! A$ {$ @7 Z 5 t9 p1 ^2 y& o1 [
    # load dataset0 D6 @# R" h7 Y" X0 N( @+ r2 z8 q
    dataset = read_csv('pollution.csv', header=0, index_col=0)
    9 N7 b0 ?9 Q  T, `2 W4 D; Xvalues = dataset.values* m' l% D! C0 w1 K

    $ @* `! ~( P! j1 ?- _

    ! ?. ~5 s7 i; w: N( [) ]# integer encode direction" h2 F# `4 o  W- B7 i. i- J( d
    encoder = LabelEncoder()
    - C7 D0 W2 B6 J: u4 H, s, t5 k- [print(values[:,4])
    4 t5 c" p# }, Q0 |values[:,4] = encoder.fit_transform(values[:,4])& c) T$ U! N4 }1 S
    # ensure all data is float2 E+ B  }1 K1 D+ M. z$ t# k" i
    values = values.astype('float32')
    , k; |0 b( n% H) n, M5 `, q2 N4 T# normalize features
    / O$ \8 E- d, U9 [scaler = MinMaxScaler(feature_range=(0, 1))0 z! v$ t. j* R- v, p  R
    scaled = scaler.fit_transform(values)
    5 w7 ~; W( x! t% ?1 ^' D( f# frame as supervised learning
    , c$ `3 Z2 \1 N% g; H. l7 S5 G, P& areframed = series_to_supervised(scaled, 1, 1) , A1 f( T, k3 {+ ~" a
    #reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据1 n" x; Q, d9 T5 X4 q3 F
    print("columns:", reframed.columns). K2 L4 j' p. I8 S. J, n" s- `
    # drop columns we don't want to predict5 o; E: ~: ~3 B4 ~' Z4 b& S
    reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
    / n# S  h8 \0 g5 r6 h! o#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据  r. w; ~3 G: d* p8 \8 x
    print(reframed.head())1 w4 T1 A2 X5 y0 b' G& r
    print("new columns:", reframed.columns)
    " m, q. }( D% ^6 p# split into train and test sets
    0 p% q8 S/ C4 r# Y, {3 }7 N3 U5 hvalues = reframed.values4 ?; k3 Z' @, s7 d6 p
    n_train_hours = 365 * 24# G. P6 c- Z# P7 O
    train = values[:n_train_hours, :]
      l+ Y& M  l. q9 V. ?" v6 Otest = values[n_train_hours:, :]: |  h$ T. @8 M! ]
    # split into input and outputs
    ; O! E/ Y9 Z) H# Ftrain_X, train_y = train[:, :-1], train[:, -1]
    - {+ p/ b; ?6 r3 t+ stest_X, test_y = test[:, :-1], test[:, -1]
    & R, H0 z! f1 C) H& h  D. T4 e# reshape input to be 3D [samples, timesteps, features]
    " |! Q4 J2 _$ J% \#使用Dense()模型时不用变换- j9 _* g; J3 w0 N
    train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
    $ X8 Q$ A: X/ X2 D: x% mtest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
    6 C) o' C) V' s  [* Gprint(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
    9 p7 w+ }$ a3 c" K6 V4 x+ s# design network
    ; C3 C% s* j" e9 l6 zmodel = Sequential()
    + V) `. i; k; s  t& s#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))6 z5 R6 m/ F! N
    #model.add(Dense(50, activation='relu', input_dim = 8))$ ]' i: q! j+ Q0 b' I
    model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    6 G6 H: F! @9 e7 j/ r' Imodel.add(Dense(1))8 Y0 A/ ~* L5 Q( t& y
    model.compile(loss='mae', optimizer='adam')
    # w7 ]4 E' @" a# fit network" J) q" q/ h, i$ J
    history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
    8 U: y+ f) ?* a$ `4 Z# make a prediction% x% P' N- G" K/ C. S" e
    yhat = model.predict(test_X)6 `. n3 Y2 k  D7 o0 r* I1 J5 {
    print("yhat shape:", yhat.shape)& Q5 w( s. S" S* Q
    '''
    ( B9 P" E" @  p0 K) L计算在测试集上的均方差
    . ~* u8 h/ v0 z, m' j* w# gtest_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
    7 w) g6 I; ^5 z3 s) o# oprint("test_X shape:", test_X.shape)
    " H5 g5 F4 s$ _% x* b8 r
    # A2 A. o, ~; C5 T, q0 N9 U

    , v2 X% |  y  G, Z0 K: v4 Q7 f3 q* \; |# invert scaling for forecast* f, e% z9 u/ w- R! y2 H
    inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)5 M- V3 k6 r8 d1 F; m
    inv_yhat = scaler.inverse_transform(inv_yhat)
    ; B2 t: z3 l: ^7 Z1 Jinv_yhat = inv_yhat[:,0]
    9 D, I* V7 m, s# invert scaling for actual
    . P8 l$ X" n0 ]/ g& O' Q  Rtest_y = test_y.reshape((len(test_y), 1))
    - S. v! j2 V* _* m& W8 I$ Winv_y = concatenate((test_y, test_X[:, 1:]), axis=1)" w/ V% L1 j# i9 K
    print("inv_y:", inv_y[:10])& n3 e  p0 ]9 O/ C
    print("inv_y shape:", inv_y.shape)9 J/ J4 ?  C; K+ v' c2 N2 I, g9 G

    : _! Y' F% ]% N* N, x6 C# A, x
    9 M, p9 {4 c5 k1 J
    inv_y = scaler.inverse_transform(inv_y)% ?- y5 p8 d1 |  x
    print(inv_y, "*"*30)- z' R% s1 J( B0 t7 w  T7 Y* i: C6 S

    5 h* ?  W' C6 f6 k

    7 ~( T+ l3 a/ _. Z% Q6 Oinv_y = inv_y[:,0]  u1 z/ q: I7 Q. s1 @
    # calculate RMSE
    6 r" ^$ E- [( U9 x+ |( grmse = sqrt(mean_squared_error(inv_y, inv_yhat))
    2 k( K7 N- H( V$ B% r& {& l: nprint(inv_y[:100], inv_yhat[:100])+ D% Y3 Z2 X- a# B( \
    print('Test RMSE: %.3f' % rmse)
    0 Z) }7 R9 f, B7 H( S0 W# L! `( z* C

    1 U9 G2 |" N& E' f% u( y'''
    # |' ]& a0 E! p6 O$ v, `实验结果
    # m  q: k2 c9 M) T  _# `
    实验1:用前一天的天气数据,预测某一天的空气质量0 I% T9 U( C2 m# g
    使用LSTM模型0 d9 |$ [% ]+ K& j! `
    结果:- l' ^: x0 l! Z3 m6 g- r* b2 o" R
    Epoch 49/50% B; K0 B, M3 j5 H6 n, q
    0s - loss: 0.0144 - val_loss: 0.0133
    1 R# y  v7 d& n, REpoch 50/50& M+ ^4 i, z2 z* O8 I1 q
    0s - loss: 0.0144 - val_loss: 0.0133
    7 F2 t9 H1 X! u/ P+ b* Z, j/ p% ?+ R* W, F
    1 w3 Q, N; K0 f
    实验2:用前3天的天气数据,预测某一天的空气质量
    1 P5 X) w& A! K  _使用LSTM模型! ^. y3 P7 R$ Q& B  C0 a. S

    + e" k% F4 w$ e) w7 s; `4 O
    # f( d, n) c, q6 G% F% O6 ]
    结果:
    / f* {$ z6 m( o9 \' Y  Z: gEpoch 49/508 `- O0 O* O8 o' L8 H( W( G
    0s - loss: 0.0147 - val_loss: 0.01493 I$ f" a" y$ X) X
    Epoch 50/50
    ) f, y9 B' k  {* K0 ~2 V0s - loss: 0.0147 - val_loss: 0.0150
    0 |0 }% Y& s' _2 C0 \# `, T  v
    & i1 U! ~2 U! p! I5 ^5 _8 T; P+ g
    实验3:用前一天的天气数据,预测某一天的空气质量" F6 R, Z" h# Z0 R
    使用普通的全连接模型 Dense()
      g8 M5 S9 ^% Z" f+ ^4 C" E, N, G0 P结果:: ?$ @2 P6 x' j* |2 f
    Epoch 49/50
    6 u" C4 f' L' N/ g5 \# ~0 b1 D) f0s - loss: 0.0144 - val_loss: 0.0146
    , E  s% z4 _. vEpoch 50/508 `: d! P  M6 a2 u5 [
    0s - loss: 0.0148 - val_loss: 0.01519 k$ a# M" J! O6 O9 P8 |7 Y
    + y) g6 h5 H+ E" d' a( P

      _- I0 U( x1 K0 }& D实验4:用前三天的天气数据,预测某一天的空气质量0 P8 O1 z& O- I  e& G
    使用普通的全连接模型 Dense()
    8 s8 k& r% c0 j5 W; L结果:( E( c+ _6 Q/ l6 {0 M9 r
    Epoch 49/50
    ' C; Z: o6 {5 t: H: w6 M/ t! B0s - loss: 0.0150 - val_loss: 0.0165: E: ?4 f; J. S! ]; h% H4 H
    Epoch 50/50
      W- q4 ]% U' D9 d6 D7 ~0s - loss: 0.0148 - val_loss: 0.0141
    * ~- [  S1 {  B* n- P4 t( r, V/ y; V, }/ c. r% B3 h* n
    ) I( L' H) X& d" w, L
    实验5:用前一天的天气数据,预测某一天的空气质量
    # B4 c3 z0 O6 c6 E3 E' X使用SimpleRNN% q" d; r% O1 S) d1 [
    Epoch 49/50- z% B) |. x, @% c
    0s - loss: 0.0160 - val_loss: 0.0140# v- z1 p8 [( h3 I
    Epoch 50/50
    $ N, @1 p. y0 g  ~0s - loss: 0.0147 - val_loss: 0.0150
      v$ ~! h  l- Z, [5 V% s! A- a* p/ l6 h6 `& {6 n4 f3 q& _/ u# V$ Z$ o: g
    / j/ B" I) F) b: k7 t$ W2 ?! f
    实验6:用前三天的天气数据,预测某一天的空气质量9 P1 g7 h' {: y7 b$ K& L
    使用SimpleRNN
    # w5 G; P& l- ^7 v' d& hEpoch 49/50% M/ R4 L' F: w
    0s - loss: 0.0164 - val_loss: 0.0233  V( @' S8 D( v
    Epoch 50/50* j/ A  c; \& l  B
    0s - loss: 0.0166 - val_loss: 0.0227
    9 G+ [1 [4 r& \5 b6 {4 t6 MRNN和DNN的区别

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


    4 D7 s- ?- w0 a! N8 k7 e
    , c1 ?, B! @* U7 U, U

    9 X! b" W# c  ], J7 p# a
    RNN和LSTM的区别
    - s" [$ V. r  N/ y+ KLSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。* _* \! d8 ~4 _# U+ _9 G
    % c" V$ H; }( y* X$ z8 P

    8 K6 E* Q/ h( y/ Y& O但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。! [* J; H( L1 b; O, I& E9 x* D( d
    4 _/ ^, O" S3 f5 Q2 a/ u
    6 y& i- {! f0 T8 a; e$ T+ V" m
    请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
    6 F" i  O/ G9 [

    , d- y6 I6 I" z) T3 G# _) e  e1 g7 ?: K' b
    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-4-21 00:30 , Processed in 0.510125 second(s), 55 queries .

    回顶部