QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4395|回复: 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预测时间序列数据
    # Y) x: g/ b& a2 A' W/ m& T( q7 I1 G

    . k8 v  B6 K! C  c  B文章目录
    " m8 q; T, |4 i0 l背景
    7 @; E+ {& F5 l  G结论4 K% V& I6 l. l
    代码2 k0 H5 K+ Y' R3 X! F1 t- ]: N  r4 J
    实验结果7 E  V' D* P. _$ ^( z
    RNN和DNN的区别
    ' a& j0 I* T, @. IRNN和LSTM的区别
    . Y8 V3 @3 N; V* O背景
    4 X: P2 G4 R: j复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验/ B5 t# Y6 ]" V4 L& b
    熟悉用LSTM模型训练8 y+ H/ ^5 S. o' S8 X+ T
    验证将时序数据 转化为分类问题后,预测是否有效果
    8 F! @8 q6 D3 d' T对比SimpleRNN与LSTM模型 哪个效果最好?' ]: |7 r* D2 [: ~1 R4 h1 t
    验证LSTM相比于Dense()模型 是否有提升?
    ( O- ]! A5 Z3 i" O对比使用前3天的数据 和使用前1天的数据 哪个效果最好?
    & f: R* K& r5 M结论6 S- o/ R: a) o: [7 E  d: _
    使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好1 L1 y6 S7 K5 S* Y
    使用LSTM的效果优于SimpleRNN8 }/ I! R/ U$ v$ @' A; c6 J
    代码
    & l1 V. {) @9 b4 J6 t8 A6 lfrom pandas import read_csv+ J) k+ q, f  @, v7 ^" \
    from datetime import datetime5 L  w: C, D6 [' X
    import pandas as pd
    2 s# U" q: I% U6 V+ A  qfrom pandas import DataFrame, Q5 K: \6 r; H6 F) P! I
    from sklearn.preprocessing import LabelEncoder,MinMaxScaler
    0 p3 y& L6 g4 G$ ^$ Nfrom sklearn.metrics import mean_squared_error. F/ ^7 m0 W1 c+ Y
    from keras.models import Sequential' `% S; P  X2 M7 W! D/ W$ {3 b' ~4 o  B
    from keras.layers import Dense, Dropout; F' C7 K. i1 }4 U1 t) |
    from keras.layers import LSTM
    & @. j3 _* w; T% A) Ofrom keras.layers.recurrent import SimpleRNN
    & o3 C# c4 ]' l+ M6 n) L8 a% bfrom numpy import concatenate
    ( W* N+ I+ K. O$ o9 y1 }from math import sqrt+ a1 K5 h% |! ]* O4 W
    : B. X" G$ C; d+ ^

    9 t0 @( i, L; G5 b. t& L6 x. f( c  O

    3 [2 u, d! N1 U5 S/ h# load data
    7 ~( k& f8 Y! Ndef parse(x):
    ; R% `$ B! l. `# o        return datetime.strptime(x, '%Y %m %d %H')' b9 y! _7 P) q  e. h# O

    ' w% v; n/ C. F: @) w# gdef read_raw():" J1 b8 ?' L. F% v
        dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
    ! t$ e, e/ L' j. k0 }3 r* g. \! P    dataset.drop('No', axis=1, inplace=True)) v( `$ S3 y/ D  G: q
        # manually specify column names
      f! H) b3 U, ]( W1 b7 \) l' g6 f$ @    dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
    3 E3 x! u% J3 k1 `9 ~% b    dataset.index.name = 'date'
    1 v# L( Z; _+ a; g! i  k    # mark all NA values with 06 z2 f' Z( j: {$ u1 L
        dataset['pollution'].fillna(0, inplace=True): a  |& I  E0 e+ t1 i9 X
        # drop the first 24 hours4 g8 ^$ r/ @% F/ J: W# u7 l
        dataset = dataset[24:]+ q8 ?. M$ N! I+ Y3 R9 n
        # summarize first 5 rows
    * r, L; F9 r+ g; ?    print(dataset.head(5))
    . M/ d/ V; L+ G0 m    # save to file: |7 N, N- |7 w' v) K# t+ {$ k
        dataset.to_csv('pollution.csv')
    : G4 E3 |1 |7 K  T' q
    ) k1 W! F2 z- ?) y2 _  g& y. U) z% ~
    5 d# p/ k% {' t6 H* S

    ! P) _. T  H) \: u/ o" X* \! B
    - q3 f0 g0 w4 U8 z8 A, P: ?
    # convert series to supervised learning1 s' r0 ~; L& U4 S# z; e$ q$ x
    def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
    ; f/ H( _5 c* v1 c% }    n_vars = 1 if type(data) is list else data.shape[1], S3 ]7 p- n. J8 T' [  a5 a1 P1 @; h9 Y
        df = DataFrame(data)6 |. d; n+ E( C7 P! v8 _& f& c8 m5 o
        cols, names = list(), list()
    + M$ h$ z5 L% ~    # input sequence (t-n, ... t-1)
    / `, M& T! U, f/ z    for i in range(n_in, 0, -1):8 p+ a4 g+ l& a7 Q, Y4 p
            cols.append(df.shift(i))
    $ x- o2 u: `; {7 r- ]6 F        names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]0 }0 _6 k  o+ q' q2 p
        # forecast sequence (t, t+1, ... t+n)9 F. P+ L/ M1 v# N! S( W! M
        for i in range(0, n_out):( {. N, m9 m& w
            cols.append(df.shift(-i))
    * P( _& |7 e* ~9 ^        if i == 0:# J9 H$ n4 F& O$ h. e6 X: ~& H1 p
                names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
    ) |" l$ J* D2 n, W8 e7 o        else:) F7 n/ K6 G& r4 t
                names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]3 H: @- k8 Q+ D) c& ?' u
        # put it all together" M. ], v5 }/ N& Y, P5 R7 e# K1 Y
        agg = pd.concat(cols, axis=1)% ^# L$ A  d9 q! j  M" J
        agg.columns = names
    ! E3 C: k- V% R# f6 F) s6 B! k    # drop rows with NaN values" U9 R. Y$ c$ X: c% T
        if dropnan:
    9 e' G; V( s' f        agg.dropna(inplace=True)% ~) t; K2 n" A) T+ B( f
        return agg! ?0 w- @$ E( M* M, {

    , T: @6 _: x9 O8 ?# m# [, s: B/ ~# load dataset# S' E& c: S0 f5 d" A) b
    dataset = read_csv('pollution.csv', header=0, index_col=0): p/ S: w1 s" M; _$ Z
    values = dataset.values
    4 [3 f! G( v. _; G; p& `# l6 r6 F" y
    8 W6 Z% E8 t  e
    # integer encode direction9 S. |) P- _1 T7 H
    encoder = LabelEncoder()9 X9 [, F, e3 U$ @7 n3 I) H* @, O  O# X- h
    print(values[:,4])
    . i5 n3 D6 B' mvalues[:,4] = encoder.fit_transform(values[:,4])/ i/ R& e9 z7 ?& d$ O
    # ensure all data is float$ i- f5 Q7 x) v7 C
    values = values.astype('float32')0 T$ t3 ^& G" G7 l6 f5 o/ c& W) C
    # normalize features
    # w0 l% _" F3 O  oscaler = MinMaxScaler(feature_range=(0, 1))
    # B% _+ b$ \+ q* yscaled = scaler.fit_transform(values)
    8 T  P- O% d  @* j) ~* p' j( b# frame as supervised learning
    & j) o* T( q( t$ M0 z/ A6 Sreframed = series_to_supervised(scaled, 1, 1) . Z; K! x! ^" ?
    #reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据1 m# J+ Y% O! p' d- T
    print("columns:", reframed.columns)
      W  ~& Y& J" A" g# drop columns we don't want to predict
    ' p  G6 ~& r+ e% e6 l! [& ]4 W; G  z! Ireframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据" V5 p+ W8 A; ]6 S" C( F
    #reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据! i( b9 A  Q" y" q- }
    print(reframed.head())* r1 ]3 e, N; e
    print("new columns:", reframed.columns)% b2 w- _! s+ u" G5 Z9 s
    # split into train and test sets1 [$ o) K" h, {; y$ B, K. Y) d
    values = reframed.values
    8 f/ o6 c7 R( t. c! s# r5 r+ d; en_train_hours = 365 * 24
    8 b# N& }/ i* e2 Htrain = values[:n_train_hours, :]+ I4 p% D; S/ Y; F8 N. ?
    test = values[n_train_hours:, :]- m+ V8 V4 h+ [: t( t. k
    # split into input and outputs
      O6 `! ?0 o. h& o& E: Otrain_X, train_y = train[:, :-1], train[:, -1]' l8 g& j) O7 V' n2 }' Q, j
    test_X, test_y = test[:, :-1], test[:, -1]+ P" j. [- p+ |
    # reshape input to be 3D [samples, timesteps, features]
    : }/ d% K. H3 e7 I  W#使用Dense()模型时不用变换
      j* v% v+ b+ strain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
    1 ^8 A( n1 }% htest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))* b9 N& c0 ~6 n6 \4 Y
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
    8 F( g, O0 ?; n/ O; l1 Q5 p- j& [/ o# design network
    1 K  T- Z  O/ h- i2 N2 \0 K# cmodel = Sequential()
    8 A  b. S6 B* \) w) R& X#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))' k. g1 e( ~, c3 o' g, M5 D$ _$ H
    #model.add(Dense(50, activation='relu', input_dim = 8))
    4 U- D0 H; I) B" L9 Z! F( R' Smodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    0 F  o- @7 X( |( Jmodel.add(Dense(1))
    & _% F. r4 i% Rmodel.compile(loss='mae', optimizer='adam')# A2 ~1 `) ~9 t2 @6 F4 w
    # fit network) y8 z0 Y: N8 B% w2 H5 _* {
    history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False). {1 _) M0 s- O/ P$ V* z5 h# {+ n
    # make a prediction
    ' c; \  b- X; r' t, c* M3 [yhat = model.predict(test_X)' h# n1 y' {% p; w8 E' p8 V
    print("yhat shape:", yhat.shape)- |3 A9 X( l# u
    '''
    - Z5 T, ~# G, P) Z; ~. F* {9 i" a. {计算在测试集上的均方差
    : Q' d7 [' S1 d6 ]  D" w. rtest_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))6 \4 i' L# J* s  E  ]
    print("test_X shape:", test_X.shape)
    3 y+ X' m( l5 h- v
    # H5 j7 _# \: `3 M% @. {9 f

    " S" s# M# }8 ]' F# invert scaling for forecast: r2 c3 J: Z( d1 S; L
    inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
    # x4 a6 W4 ^: kinv_yhat = scaler.inverse_transform(inv_yhat)8 ]( o9 F8 `& Z
    inv_yhat = inv_yhat[:,0]
    & ?5 l; G: V: C9 @2 U0 o+ N# invert scaling for actual- M: I; p  E* Q& b2 U* _9 m  l
    test_y = test_y.reshape((len(test_y), 1))
    ; }: }8 Y6 h2 E2 ainv_y = concatenate((test_y, test_X[:, 1:]), axis=1)' V+ b! Q8 b' h" V
    print("inv_y:", inv_y[:10])
    " n; O, G) ~* T% D$ e+ D. bprint("inv_y shape:", inv_y.shape)
    . B+ g1 n& c4 R8 [+ O$ N
    ; z$ L6 N8 k( l8 A* K
    , b" h5 A( J% z& b( g
    inv_y = scaler.inverse_transform(inv_y)
    ) ?7 s$ G; N+ cprint(inv_y, "*"*30)1 G2 K  @. m- Z8 h

    4 v4 N+ R6 s1 [9 u( Q2 F( L

    & A" n2 M8 O2 p! I. N9 s4 G5 j: Cinv_y = inv_y[:,0]  B" r' I8 ]' `+ F4 Z. T; C: @
    # calculate RMSE
    $ O' g$ c( ^7 Drmse = sqrt(mean_squared_error(inv_y, inv_yhat))
    * w" @) k8 [# Lprint(inv_y[:100], inv_yhat[:100])
    * v7 U6 A2 {) P& Y: z& Yprint('Test RMSE: %.3f' % rmse)
      O6 c  O" ~& R( D% r, D) p0 l1 g( b" o( _9 ]& U

    3 F3 c8 H& g5 U- j; ]; L2 g2 J9 r0 ?'''
    & g) Y5 r" j  M实验结果% P& S) t# Q$ g3 H8 P1 k6 n. a2 M
    实验1:用前一天的天气数据,预测某一天的空气质量
    ' Z' h3 V5 u5 z3 F+ e: b9 J/ V) d# _3 }使用LSTM模型' F5 j- N' C4 W0 U  v4 v8 T
    结果:3 c+ v! A/ l) h% d6 r5 B
    Epoch 49/50/ }9 m. ?$ P: d. i4 ^8 Y: L
    0s - loss: 0.0144 - val_loss: 0.0133* x( i/ \( s7 V9 Q5 L: S
    Epoch 50/50
    7 N9 u6 u$ N  f. W0s - loss: 0.0144 - val_loss: 0.01332 N% p, [2 S( ?

    $ W4 i9 V( c& |; v
    : y* z) B* s+ ?3 f+ A
    实验2:用前3天的天气数据,预测某一天的空气质量
    0 s" X+ {9 e1 {! l使用LSTM模型8 B! H9 H% y5 K% _

    + K3 z/ o/ q! z% ?6 S- ^( E' v
    0 Q  e! m- A/ H2 E
    结果:2 j1 ?) ^9 p- v+ r) ]) _9 V
    Epoch 49/50
    7 O5 w8 V$ A! T5 |4 z5 u4 D7 D0s - loss: 0.0147 - val_loss: 0.01491 {; D% U8 K( U  J1 i
    Epoch 50/50
    & P! Y* u+ N6 z7 W# M* [0s - loss: 0.0147 - val_loss: 0.0150
    + y' ]. F, B4 J
      y' r% \9 W0 r2 D( T) @
    ( S1 U2 K- j. q) k
    实验3:用前一天的天气数据,预测某一天的空气质量/ H, @7 \! r$ d% ~9 p& _1 n
    使用普通的全连接模型 Dense()( q+ W3 j1 ]3 X! X6 t
    结果:' l: |3 C! Z+ ^3 D, V' `
    Epoch 49/50
    7 _! E7 r+ b; A% g: ?- B0s - loss: 0.0144 - val_loss: 0.0146, T9 b$ d% _- {( s9 }" L
    Epoch 50/50' K7 u5 e( w3 O, J5 V
    0s - loss: 0.0148 - val_loss: 0.0151
    9 \5 A0 c: e- @/ \0 K& a% P* d( o" o, W
    4 t- }6 D! J$ |/ S

    ) }: H  G3 p* v6 K" \5 C! @/ b实验4:用前三天的天气数据,预测某一天的空气质量7 ~4 C; n: m1 C# \3 c2 V) d
    使用普通的全连接模型 Dense()4 X+ {" g, y' ~+ j/ ^2 f! x
    结果:9 d/ D& o. N6 B' p. a5 ]$ g% \
    Epoch 49/50# r( y1 F" x7 d! [5 l& A! V" {
    0s - loss: 0.0150 - val_loss: 0.01650 F  l$ E3 D* }: C* S
    Epoch 50/50
    9 Y1 g0 X! Z, C+ W& h- z4 n0s - loss: 0.0148 - val_loss: 0.0141
    ( N' b& O5 Q+ Q2 V
      m4 x( A7 C3 F+ q  x+ Z
    : V2 d' @, Y( i+ O: T9 R9 y
    实验5:用前一天的天气数据,预测某一天的空气质量
    ! \1 X1 ~- i% [4 {0 G% i  V) ~使用SimpleRNN
    * }# [: ]3 r; l: f& uEpoch 49/50
    # ]  t8 W& c. a0 l, j8 g# e4 M0s - loss: 0.0160 - val_loss: 0.0140
    / z* U/ P. f' U/ B) X0 Y! x+ vEpoch 50/50% k% C3 y% |5 C/ \& x
    0s - loss: 0.0147 - val_loss: 0.01500 O* S! \. }6 [8 l; e$ }$ P  c
    $ H) ^0 \7 g; l( z" _" Q

    5 t9 y* Z- `* {8 d6 O2 `实验6:用前三天的天气数据,预测某一天的空气质量
    8 L4 Z" _5 R" b使用SimpleRNN: d2 o. |7 k: n6 J
    Epoch 49/50
    ' X# o7 @1 f" U0s - loss: 0.0164 - val_loss: 0.0233
    7 Y. N" E% }. H4 [9 ]9 ^Epoch 50/50
    ) P9 h/ r1 H4 @3 j3 @0s - loss: 0.0166 - val_loss: 0.0227/ R- H' a( C( i2 q/ n5 C
    RNN和DNN的区别

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

    ) \' F/ w7 `7 M8 D' q$ ?! q) b

    + o4 m/ F4 B5 V. r& M2 T/ p4 G+ J/ @. S$ y
    RNN和LSTM的区别' Y( s% V8 k  k0 D- G6 ]: M& ~
    LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。% {1 `' l3 H5 ]) H# h2 {

    % N2 P2 _% P: \; G5 v, r3 ^

    2 B0 p/ D% t( r3 h9 L7 b但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。1 \! j. c, b" l$ M9 a

    ! m1 K2 v" g7 i$ M
    7 q+ b- Y+ N; C请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员

    % w; i4 Q3 o4 S$ d" f
    , N7 ]' U4 G- b+ V) c2 v) q! h. {! d- ?9 u
    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-7-28 05:31 , Processed in 0.851597 second(s), 56 queries .

    回顶部