QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2514|回复: 1
打印 上一主题 下一主题

使用LSTM预测空气质量pm2.5

[复制链接]
字体大小: 正常 放大

1158

主题

15

听众

1万

积分

  • TA的每日心情
    开心
    2023-7-31 10:17
  • 签到天数: 198 天

    [LV.7]常住居民III

    自我介绍
    数学中国浅夏
    跳转到指定楼层
    1#
    发表于 2021-10-15 10:53 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    使用LSTM预测时间序列数据
    8 g, l" }8 G( Q+ Z4 g  I8 b* M& T, k. F1 H

      @; i* y9 [$ n% k- h% O; P& h文章目录
    8 d% J4 d9 X3 M/ K  l8 s背景
    - x% e1 y5 U3 i* c结论4 h) z( ]" I. |. H3 Y: \8 i; b& b
    代码  n( O. q4 @  F$ a. g/ |( L/ }
    实验结果
    5 w! h9 U+ t  j6 V) ]RNN和DNN的区别) _1 I0 t" t; j# X$ c7 M  v
    RNN和LSTM的区别
    ! \" A1 M! l  [. n背景
    ; J, x& V; C6 }复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验6 a6 Y* _8 n- |) l# [+ {2 i) x
    熟悉用LSTM模型训练# O  D: i5 P1 M: d# C0 \
    验证将时序数据 转化为分类问题后,预测是否有效果# j' j% P3 ]. s) q) Q
    对比SimpleRNN与LSTM模型 哪个效果最好?
    $ A8 K/ q  ?& k; v3 p! y验证LSTM相比于Dense()模型 是否有提升?
    : I) O1 L8 _8 F' Y7 s( H/ t对比使用前3天的数据 和使用前1天的数据 哪个效果最好?# s/ B' \( n  i6 V& ?; x7 c
    结论
    $ ~# v& @5 N2 v, |6 v& B* x$ z使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好
    $ C4 w* p  e4 d0 Y& I, K3 [使用LSTM的效果优于SimpleRNN# W  a8 m* `3 f4 ]
    代码/ ?# q) A' w, a# B. y
    from pandas import read_csv; T! M8 D% i: [: n" R8 M. E
    from datetime import datetime; _) f: p" ]- ~; r
    import pandas as pd
    0 i0 \. l- e8 g8 p! S/ N& zfrom pandas import DataFrame
    % b5 b4 F8 z* \; o" O9 Cfrom sklearn.preprocessing import LabelEncoder,MinMaxScaler4 x+ @; m3 I; A+ b: A/ T: V
    from sklearn.metrics import mean_squared_error0 a! p% P2 ?: l( L. |+ C
    from keras.models import Sequential8 k6 p8 L- S0 H$ [0 S
    from keras.layers import Dense, Dropout6 K( `4 A: Z) c
    from keras.layers import LSTM% O7 U/ V9 v8 k# L! l
    from keras.layers.recurrent import SimpleRNN
    , F! Q' C; y$ r! C# {from numpy import concatenate
    2 p8 R! o1 E: x! f% _; Bfrom math import sqrt" ~- H5 a$ [  [( R1 X- r& I! V& }

    ; m7 A& U4 m$ e

    * i- v& v) K  p- q, t( a/ K; V( E" O! ~8 L, Q; `( m& i! m

    8 A% P! u; ]8 Q/ P* p6 O! O. D# load data
    & j% y- F* e' |5 U; W/ W7 ]def parse(x):# O4 v0 X' T' `
            return datetime.strptime(x, '%Y %m %d %H')
    % D3 V7 ~; f* ?& P
    % Y5 L0 s* W3 Z: Q9 }) j0 K: \def read_raw():5 L4 t2 n7 O0 G: x, e6 A! R
        dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
    * N8 W- X# N1 ^" _9 ^$ M    dataset.drop('No', axis=1, inplace=True)
    . h8 G6 x' o; K; b8 n) Q    # manually specify column names+ n9 ~+ Y, X; B7 G* L) W
        dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
    3 |# v. U& P; G: A    dataset.index.name = 'date'
    6 g9 P* g" m% j    # mark all NA values with 0( p) B. `8 Y3 \( o
        dataset['pollution'].fillna(0, inplace=True)" W: }% ]* l+ \5 V! w6 `4 u
        # drop the first 24 hours' B" \$ k( g0 G7 n: J
        dataset = dataset[24:]
    # S5 e% M; f' s8 Y" q    # summarize first 5 rows
    ; t. d6 V* v6 y1 w6 k% G# u1 Q    print(dataset.head(5))
    ! m" d' @6 Y! c" b8 C    # save to file2 l6 u( \# D: q- A9 D7 p4 O
        dataset.to_csv('pollution.csv')
    + `& W) |% C9 i( E( K& w9 }6 x) t/ {# ?7 f) ^5 l+ d* ?

    ! M: x' l0 V% z& Z* K1 ^3 S" j6 b5 n; f5 B$ c
      o' X6 W$ j7 U' |6 ?2 e
    # convert series to supervised learning
      B+ l) V) E; c7 n0 ^' @* a: u2 Fdef series_to_supervised(data, n_in=1, n_out=1, dropnan=True):0 B! w+ L& s/ p: Q1 |1 M
        n_vars = 1 if type(data) is list else data.shape[1]+ o) n, G. E* P) e, d$ E
        df = DataFrame(data)" m6 o7 l6 {/ I; z
        cols, names = list(), list()$ Q% G: V: X% ]/ L4 V
        # input sequence (t-n, ... t-1)
    8 j, O7 Z; T: z' Z+ m/ w2 k4 E    for i in range(n_in, 0, -1):  B( j- h% s+ S) z
            cols.append(df.shift(i))# f9 W+ `; o' q- y1 d% d
            names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
    5 Q7 }' n0 u5 {: `# f    # forecast sequence (t, t+1, ... t+n)
    9 c7 l  D6 E- p9 G7 x" c    for i in range(0, n_out):
    $ q3 y2 n7 g2 s5 F# j" l1 ?4 r        cols.append(df.shift(-i))# Y! }. s4 R' O# B) u! A
            if i == 0:6 m( P2 u4 o% }7 ?$ H# l
                names += [('var%d(t)' % (j+1)) for j in range(n_vars)]6 s8 k( C* r( J# A. ^1 p6 z* \. O
            else:
    " r4 [$ ?: v" O. O- M% w/ a            names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]$ F2 C! @0 T6 t0 [' w$ K
        # put it all together9 B9 ]* t% W  T% E- o
        agg = pd.concat(cols, axis=1)
    % U/ `6 R' r; @+ t7 q4 \    agg.columns = names7 G. }( U1 j3 j! j9 U9 o- o
        # drop rows with NaN values6 t9 C( f3 R, G6 s& N6 Q
        if dropnan:
    . v% u6 y, n% N4 B# Y, L' n* y% r        agg.dropna(inplace=True)
    " N3 A4 E2 X3 f- M    return agg
    & O9 y7 d+ g$ k& R1 _7 K4 @
    5 u) j3 e) Z1 g# c8 K# load dataset
    . r" ^3 m. u$ K# Adataset = read_csv('pollution.csv', header=0, index_col=0)- w/ w3 s. k+ _5 z4 o0 p
    values = dataset.values/ T7 L+ G  V, Z) Q/ h, f9 p3 Y

    & F) Z# J; `$ d: V+ N6 b6 R8 N
    - B% Q9 R( t) l) N4 U- Y
    # integer encode direction+ b3 b2 T% e' o  R- f) w# m
    encoder = LabelEncoder()1 d) P# I$ w+ h- W. t8 G4 ^3 P
    print(values[:,4])
    " l  q, S, A; C' f: W1 M! @values[:,4] = encoder.fit_transform(values[:,4])% e5 g9 F" {4 z. P* i) w
    # ensure all data is float( M& N6 d$ q9 z3 `! i4 d/ ?6 v5 w3 o0 d
    values = values.astype('float32')
    3 D2 N7 H  `# P! b3 z: Z0 A# normalize features9 {% L! u. y+ ]8 ?. c6 ^
    scaler = MinMaxScaler(feature_range=(0, 1))
    + j( e& h2 k, [4 A! Lscaled = scaler.fit_transform(values)
    9 Y" Y1 ~, g. M# frame as supervised learning
    ' k4 \  X) q/ O* creframed = series_to_supervised(scaled, 1, 1) ; t6 T. \' V% z. p" `
    #reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
    6 T; h& ?$ y: v7 bprint("columns:", reframed.columns)
    - J1 R7 n2 P( [" T$ N5 t# drop columns we don't want to predict
    3 y& e" R$ d7 V# w! G% Wreframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
    7 W9 ]/ ?, |2 U$ X+ v: k$ m" y#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据2 T( |0 X& u4 Z+ H0 K+ X$ D$ q; [1 T- A
    print(reframed.head())
    . T8 l) H$ H" d: Kprint("new columns:", reframed.columns)8 |  m% n5 I' H) J# H
    # split into train and test sets
    / `2 K4 R+ `0 Q9 \) N' T6 c" s. E/ gvalues = reframed.values* z2 t7 _  x2 ?
    n_train_hours = 365 * 245 c: @& b; M" a$ x! o& l, Z
    train = values[:n_train_hours, :]
    + ^! ]/ `* k& d2 a# ]test = values[n_train_hours:, :]
    0 s' F+ [3 q7 ^# split into input and outputs6 T  K: d3 ]2 C! P( O, |3 U2 {
    train_X, train_y = train[:, :-1], train[:, -1]5 {4 x) e( L' h3 r9 e
    test_X, test_y = test[:, :-1], test[:, -1]
    0 K% N  S' u1 P9 i! {# reshape input to be 3D [samples, timesteps, features]
    / o! \  @: \, @0 G: e#使用Dense()模型时不用变换; I1 F3 k' ~# k
    train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))" t2 Y8 p9 s! c# h) c( V
    test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))8 H2 D% `2 s+ Z- a
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
    ; `5 w! K# l8 H- E# design network9 q$ N2 f" |0 J" }/ L
    model = Sequential()' a. {2 N; q9 C. ?7 j. {
    #model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))5 D+ P" ]: T* Q. g& l* C* \
    #model.add(Dense(50, activation='relu', input_dim = 8))+ l0 b9 o" g7 n% C
    model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))6 T8 ^6 ?6 U1 G
    model.add(Dense(1))- e! \, E! l: \( \8 ]
    model.compile(loss='mae', optimizer='adam')0 R7 [  a- `1 r; r- f; m* h0 ]8 f% I
    # fit network
    % Y3 Q8 K! Z1 `; [: ihistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
    5 ^  a8 [5 g3 o! e, T) d# make a prediction
    * [. i" I6 R' B+ o. f0 ]yhat = model.predict(test_X): c. Z' q( V; N% u3 C3 M, }
    print("yhat shape:", yhat.shape)
    3 W$ \8 U* ?6 y0 X'''
    % d9 r/ Q( Q* L7 N8 \, ?# P计算在测试集上的均方差) E. ?1 j, E! n( n- f9 Q8 S
    test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
    2 B; e7 @/ A7 `3 l1 C  |! e$ iprint("test_X shape:", test_X.shape)
      Y! n7 ]5 @- e5 ]5 p1 c  \4 ]8 U% c

    " |( ^7 g) C+ B3 q6 f# invert scaling for forecast+ I4 C  B5 ]$ F. l( \
    inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)& J5 M: M% |$ C9 }% k$ b& A0 g
    inv_yhat = scaler.inverse_transform(inv_yhat)+ I, c( c& ^. g* Y& E" W$ R
    inv_yhat = inv_yhat[:,0]/ H2 z- d8 U) M7 h+ J; ?
    # invert scaling for actual
    9 r" A' N7 }! dtest_y = test_y.reshape((len(test_y), 1))
    ) ]4 D& C0 C% ainv_y = concatenate((test_y, test_X[:, 1:]), axis=1)
    7 r: w: r1 N* g6 p" Oprint("inv_y:", inv_y[:10])9 n/ C' t$ p; ^7 A$ t4 R
    print("inv_y shape:", inv_y.shape), d# z" |" T! z
    - n, W& s- W6 Z- m
    7 q6 H; V4 s) M
    inv_y = scaler.inverse_transform(inv_y)3 \' g( V3 F6 Q6 Z* j, ]0 A$ y
    print(inv_y, "*"*30)% w2 _4 l8 E: J. F" n$ j

    6 h0 W5 Y) U4 e9 b' A1 ?

    1 l+ o) ~4 m, U) y# r2 F. ~inv_y = inv_y[:,0]9 f' w6 Z/ r6 X5 r; Y
    # calculate RMSE5 ~; h* Y1 T; |# n) n
    rmse = sqrt(mean_squared_error(inv_y, inv_yhat)), ~' ]0 |- u7 ?& D3 Y% ~
    print(inv_y[:100], inv_yhat[:100]), F0 ]) n8 `% E: G* h9 t3 h# z
    print('Test RMSE: %.3f' % rmse): g- ]( c0 p; {4 I$ C3 G0 P# g
    ! @9 w0 o* s4 [4 I. K$ o  i' Y( ?

    - T: a/ E  x/ E5 d( C% ]8 T# H5 n'''
    5 ]6 o( s; N3 f2 t  v% W实验结果3 e5 m( _" W; h! f. Z/ O
    实验1:用前一天的天气数据,预测某一天的空气质量
    ' m+ z  F/ C% w5 J使用LSTM模型
    * i3 h7 B) Q7 v' ~% Y6 T# a1 L结果:$ Z! h; }- I- ?& V2 s9 F" g. n; r& V
    Epoch 49/50
    8 n/ N) W7 B/ d# ]0s - loss: 0.0144 - val_loss: 0.0133
    4 \6 k) n) M  R+ P* q- W+ VEpoch 50/50" |" n1 n1 J9 O
    0s - loss: 0.0144 - val_loss: 0.0133
    1 L( }' `* S7 \6 P2 n5 T, z! x$ [$ D. \
    0 w1 ~/ [  z6 z) {) k
    实验2:用前3天的天气数据,预测某一天的空气质量: q, j  f2 T. j
    使用LSTM模型! J  z6 E. B, u/ x/ v# b

    4 k9 H9 M) P. f! v4 @  w

    * p0 H0 ~2 }4 t8 L! ?结果:3 p2 }/ E# c8 j! X/ t* v
    Epoch 49/50
    1 v! P3 y+ d( u% U8 T0s - loss: 0.0147 - val_loss: 0.0149
    0 |2 P3 P  l2 b" T( AEpoch 50/50* K; m' K' u2 w+ g3 J$ o
    0s - loss: 0.0147 - val_loss: 0.0150
    . f- K: I$ P. a% I5 }: ~, S' X7 F2 t. Q

    # `" r7 F& f1 x3 T9 K实验3:用前一天的天气数据,预测某一天的空气质量
    7 }6 ]  J6 @; f+ S使用普通的全连接模型 Dense()4 B. Z2 ?& y9 r0 B
    结果:1 p3 [3 j, D0 a& O2 S; h$ b- v
    Epoch 49/50/ h/ G) p" v8 y! m1 v0 M
    0s - loss: 0.0144 - val_loss: 0.0146
    2 i' l. @8 f- z  gEpoch 50/50( v4 V# Z3 z7 J; g2 W
    0s - loss: 0.0148 - val_loss: 0.0151
    5 [' D, H% L2 @" h! n" k5 o3 O7 q. B% w, U6 Q5 C
    / @' B0 {3 C& y
    实验4:用前三天的天气数据,预测某一天的空气质量
    - f. O# Z! c3 P3 M% s* |使用普通的全连接模型 Dense()
    : Y. r9 |3 N& A. |* R% H结果:
    5 Z( T. b! N3 oEpoch 49/50
    6 O  ]0 Q( c" V- E0s - loss: 0.0150 - val_loss: 0.0165' f( P( u7 L8 z7 ?
    Epoch 50/50
    1 v. g" h4 C6 X  t0s - loss: 0.0148 - val_loss: 0.0141
    ; {. i) A/ C) F9 D" W) o! ^! d7 U+ L4 W' S" ]+ ^8 @. e6 P' ]% a" @
    5 e+ ~" X* t: H$ f% y0 l+ Y
    实验5:用前一天的天气数据,预测某一天的空气质量# _" |: q: X; X; ~, E  j
    使用SimpleRNN8 H/ N8 g+ U5 E6 K/ }
    Epoch 49/50
    ! ^# C0 E! T( E2 h0s - loss: 0.0160 - val_loss: 0.0140) h, v! ^$ F# E6 j' o" X1 w
    Epoch 50/503 |! o* m8 @0 Z
    0s - loss: 0.0147 - val_loss: 0.0150
    ; b! u. I( G5 Z: r8 x. B* b9 p6 u- O8 g' I  D

    1 ?8 R" n, q4 G6 V3 f' c实验6:用前三天的天气数据,预测某一天的空气质量; J! R9 B# G/ R3 L
    使用SimpleRNN6 a2 f! y! M& E, S4 t4 b6 O
    Epoch 49/50
    : {7 @: ^5 s& Z# @0s - loss: 0.0164 - val_loss: 0.0233
    2 [, z. O, q- O0 |Epoch 50/50
    ) y" g$ @0 k; _4 b) g0s - loss: 0.0166 - val_loss: 0.02276 r% W& ^! o6 c+ K1 `6 h/ U
    RNN和DNN的区别

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

    7 X* e8 z7 Q& D6 w2 W2 P9 d9 H
    0 Z0 P: C) h% w

    8 E5 p7 u. E9 z7 a8 I
    RNN和LSTM的区别
    ; C8 V- v3 k( D5 XLSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。+ p+ ~8 Q& i& o; Q- k

    * _8 k! a- u: i$ g$ ]
      s' k; t* L9 a/ B# M
    但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。
    5 ^# F. H1 {$ }5 O4 a9 Y$ E9 H7 s2 O9 \, B' u, `- r3 Q5 Q
    5 w( {$ n$ r- w, E: z9 V
    请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员

    # r+ P& Q& t0 c! N. Y5 i" W! F6 c+ Y
    . b1 H0 e& y4 {" {1 F5 W! A
    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, 2024-4-29 10:49 , Processed in 0.284692 second(s), 55 queries .

    回顶部