QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4265|回复: 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预测时间序列数据
    ; Z% {7 a; F! j3 m1 z4 v$ `4 r
    5 [* k3 L+ a5 T  z1 S

    # c/ ~0 a; _! q* X' @, `文章目录7 y# ]" t1 k5 g* b. m
    背景6 F2 X3 v5 Z' v
    结论
    % T; A; F& Z* }+ Y9 L6 f代码+ Z# H$ q# y! z% }0 d0 A! `1 s
    实验结果- ^, K; Y3 q' E3 M4 ^
    RNN和DNN的区别
    3 d/ D6 E: H, |5 E$ B# L5 xRNN和LSTM的区别  b# l. V& t4 t, g% M9 b: c: V
    背景
      K& Q5 R) @% K0 |复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验
    5 A+ L4 Y- g! A9 J4 M. Q熟悉用LSTM模型训练0 X% e% L+ O. q! |1 `( o, h
    验证将时序数据 转化为分类问题后,预测是否有效果; k/ a- T1 Y5 [
    对比SimpleRNN与LSTM模型 哪个效果最好?; F0 M6 A" |$ {4 J7 e7 q, U
    验证LSTM相比于Dense()模型 是否有提升?
    . [9 P, d7 C) D2 v7 T4 ~" B- M对比使用前3天的数据 和使用前1天的数据 哪个效果最好?7 U  [* W! x2 U
    结论
    . d& V/ K3 J; ]! M4 M1 ?  q使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好+ N+ I! d/ P, Q: V3 \
    使用LSTM的效果优于SimpleRNN2 U- i# \: l* N0 _
    代码
    3 I6 y/ c2 }0 |: h8 u+ |! dfrom pandas import read_csv
    , r2 _- \' T$ h9 pfrom datetime import datetime
    5 y+ i! {: P0 J  x- jimport pandas as pd0 O2 t$ L1 m" d7 n  r- K& J9 a
    from pandas import DataFrame
    $ i7 E0 z% T! p$ Pfrom sklearn.preprocessing import LabelEncoder,MinMaxScaler
    5 J1 T8 W( ~! q, w' x; A* n9 hfrom sklearn.metrics import mean_squared_error
    6 \/ M: `7 A* U- o* ~2 Qfrom keras.models import Sequential4 I# |  \$ M7 c- v' p2 q
    from keras.layers import Dense, Dropout) m, t+ |: d9 s, O# i" N/ W( I, q
    from keras.layers import LSTM9 V6 i5 l, n' s- Z5 |0 q1 V
    from keras.layers.recurrent import SimpleRNN
    7 b4 i- ]) B4 L- o, f# mfrom numpy import concatenate6 T" G1 d" s# T5 \# j
    from math import sqrt
    ) B& L3 G; T2 j5 ~) S$ B3 ?3 K6 B5 O2 H* p
    ; P# y, ?+ ~1 w

    4 \( f! |) ~0 I/ V& Z' u  f

    3 \9 G( M( A8 I2 J& d* q0 m+ J# load data$ W" L8 t) t1 W/ ]: u
    def parse(x):2 |. w: V5 X4 v- B' r
            return datetime.strptime(x, '%Y %m %d %H')
    6 w$ ]: c3 a) G& I 9 n" [! W+ I4 l1 Y( K- K
    def read_raw():
    # b4 T: n) o  ], r5 a7 m: e+ Z    dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)2 t/ C. L5 D5 Q
        dataset.drop('No', axis=1, inplace=True)9 f) y0 j) _0 _! P3 k
        # manually specify column names4 u+ `; h8 t& K, ?; w
        dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
    # |# ?& V' c  N8 k  J( P2 F    dataset.index.name = 'date'  z4 r' S! u. g2 f* c* `0 @$ X3 h
        # mark all NA values with 0
    . _" F: s/ Y: |, M, _    dataset['pollution'].fillna(0, inplace=True)
    % F' z# u3 A8 j# x* T    # drop the first 24 hours
    . K! j! A9 c, Y! ^6 c) u) t, @! O    dataset = dataset[24:]' f% R4 A& b6 o5 ]1 Y% T
        # summarize first 5 rows, d8 m- P. F( a8 O
        print(dataset.head(5))
    # g6 Z! l! m+ Y' c/ k) d    # save to file& j+ e" n- u# K8 e  ?
        dataset.to_csv('pollution.csv')
    3 g" u) ]& K/ q. u  l( I5 g6 J( B7 x  d
    + K; ?% J4 v3 Z
    & e" v3 u1 C9 D' D8 z0 E) E8 ^

    ) ]; V5 ^. a) J, v! K- _# convert series to supervised learning
    " m$ Z7 Q# s" R5 E. R/ m% ^def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
    # s1 y, L- p# |+ @    n_vars = 1 if type(data) is list else data.shape[1]1 ?' |) F# C2 n# s& b
        df = DataFrame(data)$ L( H3 f! r7 a' d. u
        cols, names = list(), list()0 q6 S% t2 c( P; @; I$ r. `
        # input sequence (t-n, ... t-1)
    - O* X% I( A4 B! k    for i in range(n_in, 0, -1):9 w  @& L/ l( w" o& R5 e
            cols.append(df.shift(i))
    8 y# i( z/ E  q, ?. E6 F        names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]7 L! ?+ e! F2 `& I
        # forecast sequence (t, t+1, ... t+n)
    $ g5 g8 i8 M+ F. ^    for i in range(0, n_out):
    : Z( n9 j. d- y. n        cols.append(df.shift(-i))* q8 W" P: H/ [/ w1 H3 F' g
            if i == 0:
    % |# `. q3 N! L" R5 B* ^            names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
    9 ]+ P9 Z' [$ t6 e        else:8 L. Z& t& o3 L- a- W* @0 X
                names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]3 x5 N/ F3 M6 o8 ~) M, B% [
        # put it all together" g) r" {$ T' |* q
        agg = pd.concat(cols, axis=1)
    * ?; Y8 n2 E# w, Z    agg.columns = names7 W& Y" G+ D, x$ ^* U7 m( N
        # drop rows with NaN values3 K  l5 t; q: b" L
        if dropnan:9 w  J, {0 H* `, f" x2 Q
            agg.dropna(inplace=True)  t: h2 k/ F8 h. U, ]) C0 q. N3 M) r
        return agg/ I. }3 l3 ]* V. x3 P- b  C* ]
    . m* t( B  R# p- [5 M% C
    # load dataset
    6 Z! H/ U' A3 J) f- k3 k$ ldataset = read_csv('pollution.csv', header=0, index_col=0)
    " ?. I. g4 Y/ Jvalues = dataset.values. g  ~$ f) W0 h, @" u
    ( c" k4 H/ V, a  {' ?: D1 w

    9 n# c* q: c. c1 |  z6 l. F( {# integer encode direction
    2 q+ `8 t. Z4 y: _8 d# h3 }encoder = LabelEncoder()( d& V( U" ?# b8 g; w7 k: D
    print(values[:,4])
    : @; X6 @2 n  Avalues[:,4] = encoder.fit_transform(values[:,4])
    + k- h6 |8 S2 F( x$ \* R$ z3 l# ensure all data is float' r  }9 h  y" t( ^" A/ i8 B
    values = values.astype('float32')( {! y2 L" o  N
    # normalize features
    ( b$ ?' ]  f5 f& Mscaler = MinMaxScaler(feature_range=(0, 1))
    $ ?5 {- d) N7 k) zscaled = scaler.fit_transform(values)& Z4 [" o, i' Z; w
    # frame as supervised learning( w6 ~6 z; s6 q7 w  E4 l
    reframed = series_to_supervised(scaled, 1, 1)
    6 [( E0 N) f7 O6 _6 r5 O4 T$ F#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
    # {! i' ]- t) ^! t  Uprint("columns:", reframed.columns)
    6 m. V! ^, t* [+ R# drop columns we don't want to predict3 r* Z( S8 i/ C/ p/ V
    reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据# G9 @$ F: Y' L
    #reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
    : y8 J7 @! [  \% [print(reframed.head())% X8 z9 E5 A8 m9 h
    print("new columns:", reframed.columns)" Y1 H3 w' q3 T; K
    # split into train and test sets3 {1 k) I/ |6 b6 V7 p
    values = reframed.values
    , [% H+ @- o( V9 xn_train_hours = 365 * 24! [* S$ P7 b9 W* f3 f# J/ O
    train = values[:n_train_hours, :]
    7 j" s0 U3 s4 \1 v9 a! A/ Btest = values[n_train_hours:, :]$ p. g: v: p6 f5 v' Q
    # split into input and outputs/ {% |' ~, }  Y, Y0 Q
    train_X, train_y = train[:, :-1], train[:, -1]6 z/ a* z1 r" O6 H' o) U
    test_X, test_y = test[:, :-1], test[:, -1], W  U+ q- P) n; Q1 F
    # reshape input to be 3D [samples, timesteps, features], a) n# ?# w8 m+ t  T8 O
    #使用Dense()模型时不用变换& z; f0 ^! [' z+ f  V$ n& h" o
    train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))" q6 D( t. z1 a( s. I
    test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
    3 v& ^4 E3 A; v8 N+ ^3 e9 J+ T. rprint(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
    - f& p8 F# [# ]+ r. o. z3 Z# design network) W* `- _0 k" X% i9 T/ G
    model = Sequential()+ K* x5 |) T  n& P- r9 [+ a/ `: r
    #model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))  p" {6 {/ W* z  b# R/ Z. r
    #model.add(Dense(50, activation='relu', input_dim = 8))% |8 _# Z! h. V( P
    model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))" a0 k8 L* b! l: {2 K  u
    model.add(Dense(1))# r! _5 y8 A. _0 C4 `
    model.compile(loss='mae', optimizer='adam')
    # ~7 f8 ~3 D8 i) x' L% G/ p# fit network
    8 I% ?0 y. G# Q) p' k& Hhistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)% G. J. i4 G! ^' `
    # make a prediction
    $ z1 h4 o% |: K2 u; p5 c+ B; J8 @yhat = model.predict(test_X)
    9 [6 K- M' [' m" vprint("yhat shape:", yhat.shape); l4 y1 y1 b4 H$ G9 |. i- x
    '''* X2 ~% ], G: l* n+ T
    计算在测试集上的均方差
    ; ~9 Y& j) p1 y! s* [8 Xtest_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
    . p+ [/ O# q6 \$ X# T" @print("test_X shape:", test_X.shape)0 Q' x  ?, X: E( M
    : N: ]7 @  x* x- g

    6 U' l; H/ i1 b& w# F3 M( }8 t# invert scaling for forecast5 y; ]! N  [% X$ b
    inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
    9 T& m( L' ?4 Xinv_yhat = scaler.inverse_transform(inv_yhat)8 ~2 I' m* x  J, V8 N1 a  m  r* P* C
    inv_yhat = inv_yhat[:,0]
    / p$ p- ~0 R4 V  n) D" N3 F. p# invert scaling for actual
    . L; C& E+ f, @! W4 ltest_y = test_y.reshape((len(test_y), 1))
    8 i9 \  C' y! V. k9 b& Z3 d8 Ninv_y = concatenate((test_y, test_X[:, 1:]), axis=1)) n' \$ `- A# l4 a- \* R
    print("inv_y:", inv_y[:10])) K4 Q9 L. l1 s; W
    print("inv_y shape:", inv_y.shape)/ {) {/ Q- n/ \+ S0 c' |, z9 L1 U; ?

    , K) U. u% B( d0 c3 }' q

    1 e+ S$ S, K( W( a1 V, minv_y = scaler.inverse_transform(inv_y)
    1 }7 u- @/ Z9 H( v- K, L& bprint(inv_y, "*"*30); e" R! }& s0 A
    % ^. Q5 Z0 u/ s* r9 [* z; d

    ; n9 ?4 H& \" Q3 V. O: Jinv_y = inv_y[:,0]6 h; Y8 M3 P- }, M9 `: V7 N
    # calculate RMSE5 T0 s7 r! d' U
    rmse = sqrt(mean_squared_error(inv_y, inv_yhat))& x& @! b& N' f! S
    print(inv_y[:100], inv_yhat[:100])% T) {1 L- i! L0 X
    print('Test RMSE: %.3f' % rmse). R! {/ k8 a6 I* Y5 j. v+ T

    7 Q. o4 d2 _, b
    + _" _% K# e& r( p5 d* R0 X
    '''
    4 O, k9 W9 w! E3 a& O/ x1 r# l实验结果
    ) C" L9 Y2 c$ h. N
    实验1:用前一天的天气数据,预测某一天的空气质量$ n! U# H* q  ?0 V' u7 R+ c* U
    使用LSTM模型
    6 C$ g+ x! D) s1 l结果:7 y/ u) O  _4 a2 k
    Epoch 49/502 q0 S" R( _. }8 K" P
    0s - loss: 0.0144 - val_loss: 0.0133
    $ p4 ?* W1 v; V* X' U( `Epoch 50/50
    " A" l3 m+ h( S0s - loss: 0.0144 - val_loss: 0.0133
      O, p5 x7 R/ {1 {: W
    1 L5 _) K; W1 W) }4 ]$ d. J+ p7 H

    8 b* s( L+ O: l& d. t) i7 e* k+ A实验2:用前3天的天气数据,预测某一天的空气质量
    + W( b7 ^2 d6 m4 j使用LSTM模型" z7 n: ]% }; U' m5 ^) d+ T4 N: q
      ~8 m% L& t. N' j( j2 y
    0 c# ^. P/ x! F1 e& }( i0 |; Y  Y
    结果:  j" S8 w! u  @9 s" B
    Epoch 49/50
    ; E# h; s4 \2 Z, a) o) }/ C0s - loss: 0.0147 - val_loss: 0.01493 r$ E+ L; f) X, w* Q* b. U
    Epoch 50/50
    & C9 q1 `: T/ ?; k) T; A) p: T# @0s - loss: 0.0147 - val_loss: 0.0150. M) p0 _. D5 y
    3 @# Z/ e2 O1 @
    3 S# d3 {! w, P; [2 e3 U
    实验3:用前一天的天气数据,预测某一天的空气质量
    : w& \" u' A6 i) \8 c, y使用普通的全连接模型 Dense()3 W" q' }, U5 B, V' U7 c& x
    结果:: T+ S& Z9 _" Z# m4 B
    Epoch 49/500 g2 P" l3 |7 p: v% `# x7 B
    0s - loss: 0.0144 - val_loss: 0.01460 t0 @% p# l' |  _$ |4 p
    Epoch 50/50
    ( Z; {) X2 L: y0s - loss: 0.0148 - val_loss: 0.01514 }" m# G" |5 }* J2 e  Q4 p
    3 J9 x- @$ w7 u  B- I
      g2 @) o4 O0 ]9 |9 m
    实验4:用前三天的天气数据,预测某一天的空气质量
    % H+ N+ r9 B0 s% c6 H使用普通的全连接模型 Dense()
    % U* ?) F; H2 y& X( l结果:( G- s9 N; h! v' C0 D2 g8 E2 P
    Epoch 49/50
    1 C5 T  C1 L+ R* W/ m: e0s - loss: 0.0150 - val_loss: 0.0165
    : J7 D: b9 v% l# k8 S9 V. N+ eEpoch 50/50: r( {5 t- \1 t
    0s - loss: 0.0148 - val_loss: 0.0141
    6 Q; `# P' H9 R* c4 M+ b$ k' C( w" `% q6 u+ p3 g" ~* J) W; j
    $ h9 I/ B$ E+ C3 D' v  X
    实验5:用前一天的天气数据,预测某一天的空气质量
    7 @  f% n0 M( A8 {- {- D使用SimpleRNN; ]5 h5 x/ U% p9 b- O7 b" L! s
    Epoch 49/50
    & w4 J- ]; b; O) {, C0 O0s - loss: 0.0160 - val_loss: 0.0140( _, m( J- Y7 X- E+ U5 r
    Epoch 50/500 p3 r! M: n; d, U  E" R4 d. x! F
    0s - loss: 0.0147 - val_loss: 0.0150- h) ^' ~; ~9 X
    * R5 I0 Z4 n) R5 X
      g( g% p; N. L2 w
    实验6:用前三天的天气数据,预测某一天的空气质量
      c) n/ Q7 X" j4 L0 @) }+ g使用SimpleRNN% l4 V" U$ P* G8 Y, W
    Epoch 49/50
    ' a7 X/ _% c# |# G" i( ?2 y+ O+ E0s - loss: 0.0164 - val_loss: 0.0233; p! d8 K$ a7 T- x
    Epoch 50/508 z  O0 r+ n/ `0 F3 ^; v. d, {0 b; K
    0s - loss: 0.0166 - val_loss: 0.02277 h4 y# Y8 W4 S$ ~$ Z( t" {2 p' ]
    RNN和DNN的区别

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


    0 B8 c* Z6 V9 ~1 `4 `( s

    + e( h9 b+ G4 c2 H0 d, ]' m/ E% d% X
    RNN和LSTM的区别) w7 }4 z  X' }* c2 R
    LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。5 e/ N/ ]% @- d2 L4 T8 @" S$ e( @
    . f4 }! r' B4 h& Q8 m5 r
    1 ]2 E' v2 m& A' F2 s
    但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。9 r! n4 w2 m! v
    0 M0 e) ]" ~. \6 K" K$ C
    & _! J7 Y- A0 X4 h1 `
    请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员

    0 H, Z9 s8 X4 v' V
    ; A6 j& ]* \7 w4 O$ H# Q! Z& J. l+ ]: v$ K9 K" ]! T4 \
    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, 2025-12-29 15:20 , Processed in 0.959521 second(s), 56 queries .

    回顶部