QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4357|回复: 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预测时间序列数据" @! {8 g3 X, O

    5 |+ I2 I1 }( p3 p7 |

    ; E, a1 N- O1 w1 @文章目录
    1 V# Q5 u7 E5 k& _背景
    / C5 Z6 F* P/ w7 g& B! E结论
    + f( C, O& B- L: k: e. x. c% ?( K/ k! P代码
    0 L& a' @  L2 ^( t( u实验结果
    ; _8 D  N5 \- QRNN和DNN的区别
    ) a* B+ S/ a: wRNN和LSTM的区别7 S9 t) U' |" ^$ P
    背景
    / m2 J6 a2 u" b  M5 W复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验
    & x' I, l6 D( m; Q/ B7 A熟悉用LSTM模型训练
    & p0 K9 F: w0 i验证将时序数据 转化为分类问题后,预测是否有效果6 ^# T8 {  O1 B  C- Q+ N) a4 A+ H$ P
    对比SimpleRNN与LSTM模型 哪个效果最好?
    0 N7 Q% J# d; e) C, p! K验证LSTM相比于Dense()模型 是否有提升?- |5 T$ k7 ]0 Z7 e
    对比使用前3天的数据 和使用前1天的数据 哪个效果最好?6 l) b/ \2 t/ I+ W( i- S/ \
    结论
    1 v6 w; n7 s: K使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好
    3 j4 a& O2 d3 \/ Y5 X6 v/ U2 `使用LSTM的效果优于SimpleRNN) m9 l. q( i8 D5 }; g& c
    代码6 J  q. D5 q* j  r9 }
    from pandas import read_csv+ c" f- p1 i( [9 H2 {, w" b# j
    from datetime import datetime
    + o* O$ C6 d$ A5 V$ L. k3 t% Uimport pandas as pd
    ' L& C$ L3 J. _  Efrom pandas import DataFrame9 g0 O8 N9 ], w5 e
    from sklearn.preprocessing import LabelEncoder,MinMaxScaler7 u4 t2 {2 I% h+ p( x$ ^
    from sklearn.metrics import mean_squared_error4 y5 i+ ?/ e% e3 W0 ]( y: }
    from keras.models import Sequential6 X; g7 e: h9 A# `- S1 L& [
    from keras.layers import Dense, Dropout
    1 s7 \0 F& [, u3 pfrom keras.layers import LSTM3 R& o0 P: {. y3 h! E+ {, O( u) x: i
    from keras.layers.recurrent import SimpleRNN
    5 F& Q" u0 J+ b3 P6 y8 k* N* Q! Mfrom numpy import concatenate
    & b/ j! Z: M/ }% jfrom math import sqrt  k9 I0 X3 i& i  e8 W& J
    6 G6 k' l5 S# y& {: ?  q) f

    ' k9 A* t5 J/ a7 W- _1 o
    + A8 h' n# a7 c& q2 G7 p

    + q4 y; Q2 ^2 J5 M4 j# load data
      e" x; f3 D6 E/ o6 L! x4 ydef parse(x):. c5 b$ [, G. X# I; ?
            return datetime.strptime(x, '%Y %m %d %H')
    + Q6 }9 s( W  Y2 R " C5 m3 ?8 I, K1 f9 K# q. y/ l0 E
    def read_raw():* f' P" e: I5 T' V" H
        dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
    9 z3 Z2 ]  |$ Y  @4 b    dataset.drop('No', axis=1, inplace=True)
    1 ]( C3 K) I1 K    # manually specify column names) o# J. l4 b9 ^
        dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
    ! V! x0 Y) p8 N: P; g1 n    dataset.index.name = 'date'
    ' O7 v0 k1 l1 e$ J    # mark all NA values with 0
    . @/ n0 G) v  x3 M    dataset['pollution'].fillna(0, inplace=True)/ Z: T+ @2 K5 L, a
        # drop the first 24 hours
    ; k7 b% s1 Q. r; J+ k* x5 G    dataset = dataset[24:]; S* M2 Y! L) `3 f. c: T4 Y# T9 U, }' f
        # summarize first 5 rows
    9 C; r( P7 g1 X+ P) }4 z! Y    print(dataset.head(5))& a! ?7 r2 i+ U* `8 ~1 D: M
        # save to file
    9 c3 p& a5 O$ X: e* D4 g    dataset.to_csv('pollution.csv')" X% m' o$ W; Q  s* n) |  z2 ?1 a

    $ \2 @) o% X+ ~2 k. j: h. E

    & u: I& T! G" N- A) O  N1 T8 U: j) I+ Q9 M* {. D1 m2 P

    ! Y, u) z8 |( }3 K4 x* m# convert series to supervised learning
    - v5 @1 g  z- [) v7 d* _# _def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):' f9 b( _# m; O2 l, C+ C$ M  K
        n_vars = 1 if type(data) is list else data.shape[1]6 C" g3 B' B5 D0 J$ A2 m3 A2 V
        df = DataFrame(data)
    : w( B7 s7 v8 T3 _+ B1 J    cols, names = list(), list()
    ( j/ A& T# g3 s/ ~/ F    # input sequence (t-n, ... t-1)
    * z* X. D6 `6 a7 ~    for i in range(n_in, 0, -1):  n" P8 E! J1 L: G* g7 P. I
            cols.append(df.shift(i))  y3 [- x7 c; E1 j4 _6 H4 z
            names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]3 z. M+ z  W# i( W  T) t' Z4 i* s5 u
        # forecast sequence (t, t+1, ... t+n)
    - Y) B! `! x! c- f5 v! b0 H% x    for i in range(0, n_out):; d: P4 T+ b" k3 S
            cols.append(df.shift(-i))+ M8 Q: `% {6 c3 C) Z" `& X
            if i == 0:% L9 v4 C9 B" h, R! x$ g3 d% {) h# Z- n
                names += [('var%d(t)' % (j+1)) for j in range(n_vars)]$ P' o2 k8 Y0 y" ?
            else:
    9 p3 f% k# v" s# R            names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
    4 Y8 W/ z+ Q6 B6 O6 G    # put it all together
    2 ~' X; M, W% N8 H    agg = pd.concat(cols, axis=1); i5 j3 q4 u) ]: P  L
        agg.columns = names  l; @& p. Z9 R, A
        # drop rows with NaN values# j( C3 M5 o5 R# H4 Q6 m
        if dropnan:
    + i" \5 ]3 e: j+ M" f        agg.dropna(inplace=True)
    6 D  v) v1 y% H( h6 Y    return agg) k& d! A& E4 V; W- s4 L& e! h

      s) w$ j0 g- I/ Z5 b. K# load dataset
    & I( ^5 p& @2 Udataset = read_csv('pollution.csv', header=0, index_col=0)! A4 D6 Y6 W* d. g! t: Y
    values = dataset.values
    # M; N' B/ H9 A9 x' L7 J0 m' O

    2 h! k. S8 K; ^, P1 r# integer encode direction3 ?0 ?/ |- u* ~( D+ ^" O
    encoder = LabelEncoder()9 ^% H+ l  T8 v) d, V
    print(values[:,4])  m4 T$ G% q0 J# J$ y1 ]
    values[:,4] = encoder.fit_transform(values[:,4])% G& S0 B' |" i7 h/ @9 ~
    # ensure all data is float" r2 @* u3 X- B
    values = values.astype('float32')9 @: ?8 o3 a8 Q7 B6 V, N4 h
    # normalize features2 N* C4 Z. b0 ^
    scaler = MinMaxScaler(feature_range=(0, 1))
    ; S2 _  m, y( [+ a- i' X+ V( sscaled = scaler.fit_transform(values)
    : v  E; Q- v, M3 n# frame as supervised learning8 S9 `& x% r; V' V: b
    reframed = series_to_supervised(scaled, 1, 1)
      o% j' g; R4 p/ f! E2 @. z#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据4 z4 y2 o9 k% g; O6 Y
    print("columns:", reframed.columns). D) ^) o) p1 B) T! n! |( ~
    # drop columns we don't want to predict
    / m. r3 C- S$ Zreframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据/ Z* A7 F5 y8 h/ t; e% K- i  `
    #reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据0 p5 t5 u; t6 g, V) j
    print(reframed.head())- o3 u0 A4 P  _3 ?/ U; G) S
    print("new columns:", reframed.columns)0 R7 B, G* |1 t: Y
    # split into train and test sets
    , A2 L" a* d7 svalues = reframed.values, M6 w; ]# n: @3 ?$ Z2 a7 F
    n_train_hours = 365 * 24& e3 j4 e, _  d  }
    train = values[:n_train_hours, :]
    3 T) U) w7 G4 ~4 ]% vtest = values[n_train_hours:, :]! V; ~: p5 T! }& s  Q
    # split into input and outputs) w' a" L9 Y  e; k& ]8 I; v
    train_X, train_y = train[:, :-1], train[:, -1]
    - k2 H  l. O# i. Vtest_X, test_y = test[:, :-1], test[:, -1]( Y6 C; d; M6 B
    # reshape input to be 3D [samples, timesteps, features]: _0 ^  b( S& t6 n7 a5 `1 z
    #使用Dense()模型时不用变换
    4 }: o, a9 }( G& l( \& Strain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))( ~4 _+ a$ r7 Y9 a) \2 m, ^
    test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))& W, c- y# j1 M. k/ z, |# x6 ]; I, a
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape): s: r5 \# |, k! {6 [2 C1 ~
    # design network
    ' R( u5 R0 C" a" e- ^/ _model = Sequential()" t8 {+ L; T; P
    #model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2]))): t; _* P* G0 d/ l# j
    #model.add(Dense(50, activation='relu', input_dim = 8))
    - A4 Q4 D& [9 ]; R( B! M3 amodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    1 w1 S8 X* ^6 X0 r9 pmodel.add(Dense(1))' t+ [/ G, _! [4 f+ t" @  v/ D
    model.compile(loss='mae', optimizer='adam')
    3 a1 ~; u( X% o# fit network
    $ y9 ]* T% B. Ahistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
    ) A' v" ~" D0 H2 ]6 q- I# make a prediction
    / T+ r7 c/ v8 W8 Qyhat = model.predict(test_X)' c4 O0 _5 L2 B) m. r/ V2 |
    print("yhat shape:", yhat.shape)
    5 i; g9 q5 B6 c5 o, q" c' f( I''': h' f5 @! \4 S2 @; R! \0 G
    计算在测试集上的均方差
    / t, J6 ]) t8 d4 |4 j' htest_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
    & V, ]: F* N4 |5 o3 L; `. ~print("test_X shape:", test_X.shape)
    4 A/ b: ^3 l6 E% t* N- S4 P3 e  ]/ }0 o; _+ P# U

    * H) \2 ^9 [6 d- B1 w# invert scaling for forecast
    7 ^( s" }. h/ J5 T; S5 @inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)% H% ^1 s9 K7 z9 e
    inv_yhat = scaler.inverse_transform(inv_yhat)
    ; l7 e4 s* ^9 K$ }4 y# ninv_yhat = inv_yhat[:,0]2 O+ g1 @" c) {6 @- ]
    # invert scaling for actual, Y" g, W/ N5 y2 p8 l8 x
    test_y = test_y.reshape((len(test_y), 1))" B) m+ v1 f, t# A! p
    inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)0 I9 H/ P3 B9 P8 p; Q1 P1 y2 @( M1 X
    print("inv_y:", inv_y[:10])7 c2 D+ n9 p  l; g
    print("inv_y shape:", inv_y.shape)5 h  n+ A7 }0 `4 ]- d/ T

    ! l8 h" t5 H+ I6 G
    ( j3 h( T; D+ A0 _
    inv_y = scaler.inverse_transform(inv_y), J7 K4 H6 p, k
    print(inv_y, "*"*30)
    ' U; T9 r" v# M; X9 `
    : H! Q" B5 q% V4 M
    : j" Q. l% Q1 g: w/ P9 [7 k
    inv_y = inv_y[:,0]" y7 v- v) y( h& Y2 F% J3 b
    # calculate RMSE8 ?' }. T$ b5 h2 T* A
    rmse = sqrt(mean_squared_error(inv_y, inv_yhat))' K/ ^3 }0 r3 {7 s* W  e  e
    print(inv_y[:100], inv_yhat[:100])
    4 C# a& F* N$ J4 o$ qprint('Test RMSE: %.3f' % rmse)
    9 ]9 _2 S% q6 Y( q- P1 k# g* Z2 J' K3 ~& i7 \2 U4 m% O
    6 Y7 g4 a# l& b
    '''
    5 B; j& F: L5 \% l0 K实验结果
    & A" n/ ^# x3 j) C) M0 _$ J: M
    实验1:用前一天的天气数据,预测某一天的空气质量0 b* f' W3 ?) }( ?
    使用LSTM模型! V0 K7 D; y3 b' U7 a+ ?4 L9 L) {
    结果:, _2 B4 y9 z3 [$ W5 N# s. w
    Epoch 49/50
    ( U# l) V! H- n0s - loss: 0.0144 - val_loss: 0.0133
    4 H3 b, F4 X, F+ _Epoch 50/50
    - B+ ~7 F# D& Y' h* p9 q' M0s - loss: 0.0144 - val_loss: 0.0133
    ) h6 b2 [  {1 c+ u5 _
    3 ~( [4 O$ a# E) O* g- {' N
    + h; K( p& R! v* N' I+ n
    实验2:用前3天的天气数据,预测某一天的空气质量
    6 l( e+ J& i8 F- V0 {4 N7 y9 a0 ?使用LSTM模型
    + @" ^4 n) \6 ]# V
    - W+ b( W% z' Y) ?% @

    , p. S/ U3 s" Y0 K结果:) N% O* x! }2 o/ [- V
    Epoch 49/50/ F. U! |( @) G/ [. ]
    0s - loss: 0.0147 - val_loss: 0.0149
    " v7 R( A7 L3 i* kEpoch 50/50
    7 P, k% \) V- ?2 [6 l, n0s - loss: 0.0147 - val_loss: 0.0150
    1 E, [0 j' g8 Z6 Q. w- {" L1 r" F
    9 f* C! Z  E: t# @
    ; a( L+ C: s7 E& i
    实验3:用前一天的天气数据,预测某一天的空气质量
    5 _" }7 {8 u: L0 j& k使用普通的全连接模型 Dense()
    $ K+ k' x) o0 \: R5 c结果:1 D6 N8 {- u8 f7 b7 J1 h
    Epoch 49/501 n4 Y) o+ V8 D' z" g6 B8 h5 H
    0s - loss: 0.0144 - val_loss: 0.0146" D! k7 R5 y$ v
    Epoch 50/50
    ! K; n5 d. \* S0s - loss: 0.0148 - val_loss: 0.0151
    . R/ T9 B' K; w. @/ {- e
    0 o- p0 i, B6 X1 l8 u

    ( k2 ]' P, h4 f8 p  C3 j实验4:用前三天的天气数据,预测某一天的空气质量% w7 W4 |5 \; g! W+ j& k* C* b
    使用普通的全连接模型 Dense(); C: V" }; `' k# X0 b
    结果:
    . V  _9 i+ @9 B0 \% `/ b% AEpoch 49/50
    % O5 P7 [4 S. L0s - loss: 0.0150 - val_loss: 0.0165
    ( `, z6 t1 m8 v7 MEpoch 50/50
    ; S7 u$ ^# ^  D$ C1 z! w0s - loss: 0.0148 - val_loss: 0.01413 T5 z6 k$ Y. M, y

    8 ~5 x' t( y) ^3 z# P
    0 j4 p: U3 @" M+ K/ W7 P
    实验5:用前一天的天气数据,预测某一天的空气质量  g5 j9 h9 q" q1 E' o
    使用SimpleRNN
    . c6 f8 `" Q8 I/ PEpoch 49/50
    2 z" x! g/ C3 y1 P; ^0s - loss: 0.0160 - val_loss: 0.0140
    - v9 u+ ^% A4 yEpoch 50/50* f6 w. m0 R6 ]. a4 s" R' x
    0s - loss: 0.0147 - val_loss: 0.0150$ E2 s: ]- {) b! O: S. j7 [* y. E7 @
    ( `  W/ H8 ]$ t2 V) S5 N

    3 b" I2 ?  q- ?实验6:用前三天的天气数据,预测某一天的空气质量
    7 X, n. Q# i1 N( {使用SimpleRNN
    2 p. e3 ]& D& s3 H4 uEpoch 49/50
    1 q% i! }/ ^! Q/ [' y0 r) m$ M. {0s - loss: 0.0164 - val_loss: 0.0233
    5 X$ p/ y. O6 L- cEpoch 50/50
    ; D! \) ^! `& j& h+ t8 i) U0s - loss: 0.0166 - val_loss: 0.0227
    8 M% k( p  L" K3 c& lRNN和DNN的区别

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


    9 t: X/ K5 W: q6 I( n* `4 z. p

    7 E6 f# j2 t. o; u/ K9 g/ m. H' J/ l' x8 d2 J' s" y
    RNN和LSTM的区别2 C& m; b7 E& u3 A7 _* D
    LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
    / h" c+ p- a  A: R, o; B& X4 e" d3 ]1 s
    + {0 x% N& ^# p
    但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。1 i4 P: _3 n% }  S- s9 G
    * k: X) g) |) r; t/ |" h+ J7 s

    * V3 ~. u4 \+ r3 s5 X5 x& f# @* ]9 @请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
    4 ]" i9 ?5 `& e4 u: ~( j  Z5 p) _% d
    . r! b- e0 Z" e4 i/ y: O( h& ^
    + Y; g; O+ H. ?8 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, 2026-5-25 16:25 , Processed in 0.294111 second(s), 56 queries .

    回顶部