QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4460|回复: 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预测时间序列数据
    * v9 Z/ `; ]  T  o  x- Y2 Z# C. |" i: c/ _
    9 j' P; o$ Y& {5 M  e: ]
    文章目录2 p. w+ B& P( z( F7 @( Q1 a
    背景5 J& z9 }! `7 |6 n# _
    结论  G. ?3 T* h2 y0 B( n
    代码9 @3 s& [, L8 E* d# [% U' s
    实验结果
    : h3 F. a5 r8 A. ]% |& URNN和DNN的区别
    8 {7 S# E/ p1 ^3 z4 L9 XRNN和LSTM的区别2 `8 D- P# v* F. x# S
    背景
    , p' F4 N/ f4 q1 ?2 j复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验& M6 y" y, f$ X. }
    熟悉用LSTM模型训练
    + n' T1 ~' _" s. Z) g! Y验证将时序数据 转化为分类问题后,预测是否有效果
    : G" M, b& s5 e: K. p* X8 B; k对比SimpleRNN与LSTM模型 哪个效果最好?' m- |$ g' Q* k! p
    验证LSTM相比于Dense()模型 是否有提升?
    ! L8 f& i" ~6 C$ @% k对比使用前3天的数据 和使用前1天的数据 哪个效果最好?8 x# h. D/ e! d* A1 b. l$ k- x! D; D
    结论4 j, [, T4 C& q0 c. V8 q
    使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好. M, d- ]1 l, ]% o
    使用LSTM的效果优于SimpleRNN2 }8 Q6 {: U. l+ X1 X5 W( Y# o6 D9 b
    代码0 M0 j* u" Q( G. d
    from pandas import read_csv4 U3 g, i. C! l9 J9 h
    from datetime import datetime
    " _( n. b3 I" P+ P8 C5 n$ J& Z; eimport pandas as pd5 ]) z' u! t& r. h
    from pandas import DataFrame4 R% L6 f+ W# Q' o0 n# Z
    from sklearn.preprocessing import LabelEncoder,MinMaxScaler! |. g( L# i5 K* A4 L# P
    from sklearn.metrics import mean_squared_error0 x* B& S. l5 s
    from keras.models import Sequential# G/ F. S7 Y/ q/ P- s( L
    from keras.layers import Dense, Dropout
    8 M2 z- y: L+ f4 m' o& zfrom keras.layers import LSTM
      |: n; I$ s+ u& Xfrom keras.layers.recurrent import SimpleRNN: F1 L, Q1 K5 t9 ?! _
    from numpy import concatenate
    % `2 V% ?9 u, x0 A/ _from math import sqrt
    - r- P6 Q( V% T) ]
    / u* {0 y# g) z8 K) D
    & k3 z( I# ]# N( r  t+ P$ u
    7 \7 b* z2 }! N0 c7 W

    / V7 z1 C$ N0 n5 ~0 Z. Z" ?/ V# load data( u% ~+ d8 a. J- P! O6 w" e
    def parse(x):" ?$ u7 V- s# G* \
            return datetime.strptime(x, '%Y %m %d %H')
    7 ?* }- V9 f0 a9 X * Z6 \8 z1 W3 p) Z- x
    def read_raw():
    ' f, r. N4 v% u" ~, I    dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
    " U1 F0 B7 J* `; d' @2 Y+ R    dataset.drop('No', axis=1, inplace=True)7 w+ }( F( ~& ?, v
        # manually specify column names2 V7 z4 o9 R9 w
        dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
    - J$ I  s- V% y5 t$ p; T' z8 g    dataset.index.name = 'date'
    , a2 v+ b8 G2 H4 H: Q1 M6 K; z    # mark all NA values with 0
    ; O  x2 r5 \; A    dataset['pollution'].fillna(0, inplace=True)$ _& n; c& B9 p# s! Z# @9 j: {
        # drop the first 24 hours; D) h: ?- L! F8 R9 N3 \( b2 P
        dataset = dataset[24:]
    ( O/ T3 i" c- a% e/ r! }: j    # summarize first 5 rows) T( u0 K" A' Z3 ?# z
        print(dataset.head(5))
    ; T+ b4 ^  ^8 ~4 ~9 ^. y    # save to file: u  \, D+ f2 y: {% t
        dataset.to_csv('pollution.csv')+ B* Y4 M7 W5 a, N$ h  S( C

    0 S5 M, g1 V( s+ I
    2 Y* {; W1 G/ `) i9 j

    - t7 B8 l& |# t; J/ J

    : ]/ \4 b6 D; y4 _% G5 j) H# convert series to supervised learning: y* n! B6 r$ _* v0 i
    def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):8 _9 d% S( ~+ ?) M  N/ i- Z
        n_vars = 1 if type(data) is list else data.shape[1]
    ! @3 N  h. X8 }+ H; a/ Z3 o# A. t    df = DataFrame(data)2 |, a, v" h- R" Z2 X# K
        cols, names = list(), list()/ Q9 Q& b; I3 `" L/ h# o7 i
        # input sequence (t-n, ... t-1)$ @2 r' d6 Z1 Y2 |/ ]9 z6 m! V
        for i in range(n_in, 0, -1):
    9 E6 s  s/ O3 L3 h& J, T2 U; d        cols.append(df.shift(i))0 U6 ?5 \" R% w9 W" m7 C
            names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
    + V" @% r6 t6 v: ^/ w    # forecast sequence (t, t+1, ... t+n)% j9 i7 ?+ T, u* Y/ f! T9 F
        for i in range(0, n_out):" T! [, S8 t/ J1 ~
            cols.append(df.shift(-i)), \; s4 A) \' G2 B+ N* F
            if i == 0:
    ( e( b* L3 j. L) a4 ^! O+ F4 r/ f            names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
    8 Z1 p: B; ]6 R: W        else:  Y4 l" s1 X7 W# o
                names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
    8 Q; Z$ k* \) o) W    # put it all together; ^8 P9 r# K5 H3 i/ f
        agg = pd.concat(cols, axis=1)
    + B. ?8 W: C) T" J! e) W    agg.columns = names
    9 {/ t4 x' @2 @4 e" @    # drop rows with NaN values
    2 D, d$ H- R+ t    if dropnan:% e/ l( y, e! B; p+ C
            agg.dropna(inplace=True)& W' \6 `; _  Y( H* f
        return agg6 E. U$ ~2 P( m5 ]' n
    2 i; z% }" H2 k9 x( U
    # load dataset
    2 s7 ^# ~3 s% t( E7 p$ z- d7 {" d+ Kdataset = read_csv('pollution.csv', header=0, index_col=0)2 o8 O& E. R# `$ p& o: h3 Q. s
    values = dataset.values
    $ H7 }' Z  a: K: o5 y3 ?0 ~& [2 f, V, T+ c6 ~

    2 n7 g) }1 o& H6 F# integer encode direction
    " x/ `$ |. w/ Aencoder = LabelEncoder()
    ' n: W, F) H4 ?5 X& G! B& Sprint(values[:,4]); T  Z$ J4 g* d% |2 }
    values[:,4] = encoder.fit_transform(values[:,4])
    ; s- R# S- A! R3 {# ensure all data is float
    , G% c4 C/ W% _6 u8 G2 Bvalues = values.astype('float32')  m8 `4 X, ^9 ^8 W; g
    # normalize features# k- b, x# [5 ?% j
    scaler = MinMaxScaler(feature_range=(0, 1))
    . ]. u1 m# x/ ~7 x0 k5 V' Dscaled = scaler.fit_transform(values), W- b; _& c; h/ q
    # frame as supervised learning
    % U* y. `  W. T' C  y% |reframed = series_to_supervised(scaled, 1, 1) & D) W( r9 z: q- d( c/ `
    #reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
    . W$ b! I7 _$ n  L' ~- ~print("columns:", reframed.columns)  a  ^) Q9 D! x5 j
    # drop columns we don't want to predict) }9 ?; m( j. |/ k' T* w
    reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据5 D  `! H9 O3 b  S+ R2 P: c' i
    #reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
    " T2 y& F' E( a7 Eprint(reframed.head())
    : }" b6 }2 O( B. c! n  Vprint("new columns:", reframed.columns)  [/ Z' V6 \' h% Q  [, D* _
    # split into train and test sets
    ' W1 ^# C/ V" |: l  _values = reframed.values2 w' x& I* W/ A, l2 Z  Y
    n_train_hours = 365 * 24
    # q, F+ r; e. n! f& e" G3 h! G# ptrain = values[:n_train_hours, :]
    3 h3 w0 j8 H- n* n; x& m0 ?test = values[n_train_hours:, :]
    5 L" b4 G0 r$ Q* q3 f3 [9 `# split into input and outputs
    ) r$ y4 x+ @% C+ t) [$ I* I( mtrain_X, train_y = train[:, :-1], train[:, -1]
    * ?: H, M1 K/ I6 X- jtest_X, test_y = test[:, :-1], test[:, -1]6 l( P2 u% l, l5 [/ z
    # reshape input to be 3D [samples, timesteps, features]# K, O- d% n# \- e
    #使用Dense()模型时不用变换, O7 K; G, C( ^0 N% y% I( M
    train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
    $ M' x% O/ E, W! \  p/ }9 V/ D  ktest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))# q8 m! j# q& [) F; x
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
    ; V, V% W# ~: Y: p" x/ ^# design network3 s, s; [- m* x4 v7 [2 d
    model = Sequential()% T& x+ w" V) E  G8 \
    #model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))) A1 t7 P/ c! V$ p$ z
    #model.add(Dense(50, activation='relu', input_dim = 8))" P2 x& l1 b8 M3 ]2 S. `
    model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    # S6 W* l+ @' l$ N( e4 u( Umodel.add(Dense(1))9 o4 J; w8 [; f( g; p% H2 }
    model.compile(loss='mae', optimizer='adam')
    " t- h/ N7 M8 B# fit network: P% v9 d! b: o+ w) f3 n  }
    history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)& H: B+ f: ^; y9 c: R' c
    # make a prediction" l& z8 h9 c' H* p
    yhat = model.predict(test_X)( i+ B- s; L& f1 X
    print("yhat shape:", yhat.shape)
    4 T7 F: [! W* l'''
    " g/ ~: G! w% E& ~7 t* Z计算在测试集上的均方差; L. w8 M, C2 I+ w- O8 |& l
    test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))* f% [/ ]9 m' X2 u% ~- U! b
    print("test_X shape:", test_X.shape)! U; ]8 B4 j9 ~- k7 _) D, F2 r
    7 B6 R1 Z% D" _$ {3 C
    ! e( O) h" r7 k( ?" e9 m- O
    # invert scaling for forecast
    # h% \5 J8 g2 B- @2 |inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)# i1 l5 c; ^8 [; H& K
    inv_yhat = scaler.inverse_transform(inv_yhat)
    # ^# U2 p. n! W/ d" t, \inv_yhat = inv_yhat[:,0]4 }- E8 t. u! F
    # invert scaling for actual
    # i4 y* s# `  u4 v* }test_y = test_y.reshape((len(test_y), 1))# x- s9 n! V/ l
    inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)( T9 a* I, u, v; T8 R0 y" Y1 Y
    print("inv_y:", inv_y[:10])
    + J0 E/ }, V- pprint("inv_y shape:", inv_y.shape)) m8 s& Q) N" S9 k7 k/ [
    ; s5 ]/ e3 w# I" m1 s- o
    4 c9 x; u- A3 ]: S
    inv_y = scaler.inverse_transform(inv_y): ~( c6 l: G) P% {
    print(inv_y, "*"*30)
    % d- y1 H" \  e# M2 |) N) ~/ Y3 x$ b! I
    ) m# E. u2 V$ M
    inv_y = inv_y[:,0]2 D( B* r2 N) z  @9 D3 s3 J) P
    # calculate RMSE" d+ w  ]" `' Y! O; l
    rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
    * D% E3 N# p9 Iprint(inv_y[:100], inv_yhat[:100])
    ! ~) ?: z2 N; u1 {+ Qprint('Test RMSE: %.3f' % rmse); v7 E% f" B. p0 m9 r
    ) s. ~$ F, I/ U; z# i
    % x7 O) }. D8 W. s9 W2 ~( Y1 R  k2 `
    '''- t9 l6 \) A; @; Q  F& b% z
    实验结果
    * q# r2 n9 ^8 ~4 Y6 [
    实验1:用前一天的天气数据,预测某一天的空气质量0 y4 y7 O7 r0 f' K5 o4 X
    使用LSTM模型  W# l3 `  W6 j' U# f' m* @8 N
    结果:* i$ a2 R, Q+ @+ E  b( A  S7 Q% {4 ]
    Epoch 49/50
    8 T0 ]1 _. V% D( X( ?# a0s - loss: 0.0144 - val_loss: 0.0133
    7 W( @; M+ e4 yEpoch 50/50
    ; D: G( `/ Q- F9 K& l" Y0s - loss: 0.0144 - val_loss: 0.0133
    $ f2 w( V* G$ S1 ^
    ; w" Y9 k7 E+ {: `% O5 U0 D

    4 w/ M( x5 I0 Q3 M( _' d实验2:用前3天的天气数据,预测某一天的空气质量: A/ O9 r2 P9 C$ t' T7 M, b, d
    使用LSTM模型
    3 g- P, {) J5 x( B% [! T
    : G* p3 w5 K( P5 i. n

    8 |/ R( p% q* p8 I% A结果:  Q" r9 K# j% |' E5 N
    Epoch 49/507 d' M6 N7 u* Y7 l5 k
    0s - loss: 0.0147 - val_loss: 0.0149( R, ?0 q7 Z' b& e+ f6 k
    Epoch 50/50
    ! K" D: _$ }- I% e0s - loss: 0.0147 - val_loss: 0.0150. r6 R2 f# S0 m

      m5 a) V: u$ y/ ?

    0 ^  D, |+ k8 d  N0 M6 l* Y实验3:用前一天的天气数据,预测某一天的空气质量7 A: c# S1 {, n+ j' `3 |$ E
    使用普通的全连接模型 Dense()
    , E8 t" H( ]& V8 [7 C" d结果:1 f2 k; E7 i: V8 F& @- D
    Epoch 49/506 Y9 \$ E9 G1 a: D; ]5 }$ T- L" h
    0s - loss: 0.0144 - val_loss: 0.01465 ^) t" P( ~8 d( u2 U1 S
    Epoch 50/504 q; `$ h  q: T! i9 V
    0s - loss: 0.0148 - val_loss: 0.0151
    1 `2 ~6 F2 U) m7 s0 m" X: s& c
    1 \9 q" b5 q' C) a
    ) m& d$ u% |6 j& [0 V  F" [
    实验4:用前三天的天气数据,预测某一天的空气质量5 Z4 J3 ]: Y' ?$ Z
    使用普通的全连接模型 Dense()
    ( b" B- r0 W6 x& c7 P结果:
    / Y) z4 f0 a3 N" S% M. m, w% e9 B/ dEpoch 49/50
    5 @' }0 z/ h( E2 z2 K+ I0s - loss: 0.0150 - val_loss: 0.01651 U4 j0 v, I6 m
    Epoch 50/50
    9 n  z8 j6 p+ K0 q% s+ e! W0s - loss: 0.0148 - val_loss: 0.0141- b/ n0 L: q" u! C; z- H% t
    : `+ B7 Y1 Y9 B) {/ @; K
    2 @2 [) o/ v% Q' _
    实验5:用前一天的天气数据,预测某一天的空气质量& D  I- h  K0 l. S
    使用SimpleRNN
    ! o' o+ `3 R) Y0 kEpoch 49/50! B9 E: x, t+ f, q! O& V
    0s - loss: 0.0160 - val_loss: 0.0140' U& m% }9 J) |6 }/ b
    Epoch 50/50
    : Z+ }: u7 D# Z0s - loss: 0.0147 - val_loss: 0.0150  P* n- T- Z9 H( K
    , ^3 W. N- ^6 C! k* d2 y% M7 ~

    2 x! c! N* t& g8 b8 f4 z实验6:用前三天的天气数据,预测某一天的空气质量* v% W! l- ^! U8 I
    使用SimpleRNN
    / ^7 Q1 w/ u! H9 |* b" p' yEpoch 49/50; A- D" ~- L9 M0 v
    0s - loss: 0.0164 - val_loss: 0.0233
    0 g+ |" \) ~* u& Z  q. c* A' _9 uEpoch 50/50
    # C& N3 X5 v0 b' w$ @0s - loss: 0.0166 - val_loss: 0.02277 o+ d6 j, B. B: c6 |
    RNN和DNN的区别

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

    5 v0 G6 P9 g+ b4 Y4 W$ d

    # P9 L1 L; ?6 F- s
    * h5 ]3 {# O. e) d3 n1 Q
    RNN和LSTM的区别
    ; ^9 w1 e- _2 Q9 c0 d* MLSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
    9 X) c; T- d' G  a' ~9 ^  O+ O  I: _  }4 ?

    ( x6 D% H1 s0 d: l但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。
    # F& k/ B% {# ?. k
    3 ?* j% e$ u2 q9 x( e8 w7 A: {1 e; h' L/ I1 i" C9 \
    请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员

    ) Q1 ^1 L1 }1 F% q+ G3 J0 Z' M) C
    + M' A  \' C' a6 k. A7 Q0 }8 p' I* U/ O( I# L% g
    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-10-12 01:58 , Processed in 0.909868 second(s), 56 queries .

    回顶部