QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4329|回复: 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预测时间序列数据% |: n2 I2 y( z' g4 o. X

    & L$ L$ M' Y* ~- E# ^' ~) z

    1 H' f6 _- S/ p2 }# H1 K2 i% c1 Z文章目录" g( p+ Z, k: s" ?( S* ^' P6 m
    背景
    $ U7 Y* h/ a' e$ A结论% ~" }1 O0 p! c8 u7 I9 f
    代码
    : L3 d0 H+ I! a8 Q: c实验结果0 g& V9 w$ Z; {2 X/ a- n2 c  N
    RNN和DNN的区别
    ) u& E4 ?# R6 U% R! b- u5 J5 DRNN和LSTM的区别3 e3 `0 f# l5 O
    背景6 }9 W  B: p3 X
    复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验4 q% b  _( s4 ]' S& l
    熟悉用LSTM模型训练
    , D0 q7 @  T4 t3 A2 E验证将时序数据 转化为分类问题后,预测是否有效果
    ( l8 W" _9 m: w0 B- w对比SimpleRNN与LSTM模型 哪个效果最好?
    ( X( z0 r; s# T验证LSTM相比于Dense()模型 是否有提升?: n) }. s% S, x6 a
    对比使用前3天的数据 和使用前1天的数据 哪个效果最好?- `, d7 M# u/ k$ F) i/ S+ j9 a
    结论/ z  j) e  X. X2 f
    使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好
    3 E3 n6 g& E2 m1 u8 \; Y* X使用LSTM的效果优于SimpleRNN
    $ l7 d- T1 s/ j5 S- \4 L# G, {- s代码/ q1 b9 q8 ^2 A! `, m8 A" R, ~
    from pandas import read_csv
    9 W* `  I- F5 w3 F- e2 A; V2 d8 b5 `from datetime import datetime
    2 S' k2 I1 v; n9 }import pandas as pd
    , B0 V, P0 s/ rfrom pandas import DataFrame  @+ Y9 }  t: U" \  o! k# A+ E
    from sklearn.preprocessing import LabelEncoder,MinMaxScaler5 }/ h7 m" t1 Z* g
    from sklearn.metrics import mean_squared_error' n+ ^# W2 r' T) h4 _
    from keras.models import Sequential
    / k1 T! L; z$ I1 w$ p) nfrom keras.layers import Dense, Dropout/ @: w) |( C' j& N7 B% L; A7 b8 O5 P0 C
    from keras.layers import LSTM
    ) U/ m& J4 k& y% qfrom keras.layers.recurrent import SimpleRNN
    , P1 I* p: M5 v( _* i, `& G/ {from numpy import concatenate: t, v: O  c9 C$ K1 ~
    from math import sqrt; V; T: j) m8 J) {$ N6 w% }

    : y- [; N% i4 \- [2 P! Y; o

    - z( u$ [7 t8 _8 D" ~! {9 m7 K( R6 ^

    " p3 s6 N! C% U: X# load data
    5 K' ?( l1 H( |def parse(x):
    6 x1 G( ], t. s        return datetime.strptime(x, '%Y %m %d %H')6 Z" s, s6 |) c5 n2 D. R! i# v
    " c3 u6 K5 |* G+ Y3 H" p
    def read_raw():
    ; ?7 ~, i7 j; z9 a  `4 r5 e7 g    dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
    , w7 ~* f) E4 h* z    dataset.drop('No', axis=1, inplace=True)& I" J6 \% z! c% p( k
        # manually specify column names
    1 e( _* x% C/ c7 J8 i    dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
    ) k: v7 |& M4 ^! ?& d    dataset.index.name = 'date'
    ! ^/ ?6 ]% t2 A' d1 a" H    # mark all NA values with 0; q; f5 R7 {6 a: Q
        dataset['pollution'].fillna(0, inplace=True)
    % L2 a4 U1 ~! y7 B, r8 ^* _    # drop the first 24 hours
    " H# H9 k; p9 \' H0 O  M1 M    dataset = dataset[24:]- {7 d4 w/ t6 v
        # summarize first 5 rows8 L+ y+ S! ^# O5 T2 ^
        print(dataset.head(5))$ u( y8 k* _& ]( b) H; Y4 P; ?
        # save to file% q7 L6 z2 ^  |
        dataset.to_csv('pollution.csv')/ Z0 N: t% l* J, K/ m! O0 z

    5 y" i# X  E! D* e( |% T

    " ]. R& I  e5 P" z- `+ }4 t
    2 x8 e, V1 E/ }

      O% a7 O" N% |0 |" ^# convert series to supervised learning" N# i8 i- `% x
    def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):" E# l) q' E5 M# Z% K+ C8 k3 F# Y$ J
        n_vars = 1 if type(data) is list else data.shape[1]
    $ D3 i$ V9 c5 O) K3 W; _8 Y    df = DataFrame(data)( W' ?. h3 C  C( y
        cols, names = list(), list()
    4 Y) m# T2 i* F' m& G& A    # input sequence (t-n, ... t-1)# O7 {; L! F) B; t, t: w
        for i in range(n_in, 0, -1):
    0 v: A" @8 j2 x8 f) [- O        cols.append(df.shift(i))
    , Z  j+ I$ E6 l& E; l9 D        names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]/ t/ U: u& F8 O6 T5 \& ~5 e7 b
        # forecast sequence (t, t+1, ... t+n): H$ P6 `" i' i2 z) z# E6 {  {
        for i in range(0, n_out):
    - f* a$ u$ A* ~; g        cols.append(df.shift(-i))4 S% m% L  q% i. E3 S# w* S0 e
            if i == 0:- e% w# R% v: q* J! X/ L
                names += [('var%d(t)' % (j+1)) for j in range(n_vars)]2 H! y* U# F$ S5 E) ?4 n5 j
            else:
    ; F' ~) g0 A- Z$ _$ ^- A            names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]' H' K- \" l! }- M3 k5 h0 V8 Q
        # put it all together- v0 N  u; }2 ~2 o0 E8 b. B
        agg = pd.concat(cols, axis=1)
    0 L* R4 T4 F) C    agg.columns = names( o2 ]' @! z1 W, h0 |9 h$ f. B+ t
        # drop rows with NaN values  r4 A  N3 M# S; T) _% m$ I6 O) t5 n
        if dropnan:9 S! T( |7 \) A( t
            agg.dropna(inplace=True)
    * Y' R9 F+ w% C8 H' n' }2 \; T    return agg+ B' U, ?/ ^9 b8 T, D3 e7 ~
    ! ?) D% w1 T' a' `( `
    # load dataset
    2 H! N; v* ^! d8 W- L4 edataset = read_csv('pollution.csv', header=0, index_col=0)
    ! A' }; P( w, t2 K5 J/ svalues = dataset.values
    5 s2 P/ i9 a5 a! r( l8 G+ h
    1 y( y( V3 t- a* p# a% }+ H1 B
    ' H5 ?4 M: V, H9 E0 I; m0 P
    # integer encode direction% v: @6 S9 ]$ j
    encoder = LabelEncoder()
    5 J/ f, _- s& V% s/ k9 [0 B# \. |print(values[:,4])
    " a& D; k" i2 N$ x6 C+ Vvalues[:,4] = encoder.fit_transform(values[:,4])  Y3 _- s9 R7 v+ d. X3 ]8 {- n1 U
    # ensure all data is float
    $ m, }3 U! G! e; p: v8 \. B9 \values = values.astype('float32')
    * @& [8 q/ `/ [; ^* N. `# normalize features
    2 F; k. V1 {& T* {& j3 g* w7 Rscaler = MinMaxScaler(feature_range=(0, 1))3 m/ G' o8 J6 ~4 P! A
    scaled = scaler.fit_transform(values)" d' Z' _- ~$ J7 }& t8 g) F6 a3 M
    # frame as supervised learning
    % t& R: a) R4 l9 L, Y. Dreframed = series_to_supervised(scaled, 1, 1)
    * m1 h: g. |9 u; f#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据4 V6 y* U( u, e& \2 e
    print("columns:", reframed.columns)
    7 M- z7 E# I6 [# drop columns we don't want to predict7 H: p8 V2 L  P, l- S# T7 V
    reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
    , F! a4 x4 `; o) i/ I* o#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
    # f4 K: ]2 L4 M$ y' Nprint(reframed.head())% C/ W  X4 g, i( ?4 c8 ?
    print("new columns:", reframed.columns)
    " ?7 J; T4 ]5 K$ W# split into train and test sets% ^( y. V7 W4 E" @) B8 ?3 h
    values = reframed.values
    3 r3 z4 C! D- c( k  Vn_train_hours = 365 * 24
    % ]' u: O/ p- b" @train = values[:n_train_hours, :]3 g. X+ D3 ~% ?
    test = values[n_train_hours:, :]
    8 @. D- {; D) b9 I3 J* ~# split into input and outputs
    8 o: x# t% n' Ctrain_X, train_y = train[:, :-1], train[:, -1]1 ]8 L* x  V) r" \' J# k
    test_X, test_y = test[:, :-1], test[:, -1], N. @* J! @" o  k* X! ?, a
    # reshape input to be 3D [samples, timesteps, features]
    ' c9 M5 ]& [. j. p: \0 l#使用Dense()模型时不用变换6 [6 k8 j8 p* a  s+ K/ S
    train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))' p. P' R$ k- q& P4 w% e2 z
    test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1])), z9 ?* o* m/ w- O
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
    # f* w8 R6 ?" x. @# design network5 E- U: h5 }  {' A, o1 D7 [' y
    model = Sequential()  l/ E# [- a# c# J& q8 p
    #model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    & p- m: ?. V5 D* V; V( R. P+ G' o#model.add(Dense(50, activation='relu', input_dim = 8))
    " H$ y& I# y3 e' R2 ]( t) J& tmodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))4 w4 f5 b. t7 V% p& Q3 R2 s9 f
    model.add(Dense(1))
    . n! C! ]6 [1 Smodel.compile(loss='mae', optimizer='adam')3 w  ?' w4 t: O" j
    # fit network
    & n# n6 |+ U0 w/ A. Z  Lhistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)+ I3 y: ]8 K5 X  r5 f
    # make a prediction
    ( g: i5 Y2 J; \: Z. Pyhat = model.predict(test_X)5 e: a7 ?% Y) p! [
    print("yhat shape:", yhat.shape)
    " ]9 `9 A2 p! B2 y# `'''
    + E, `/ ^) l1 `  @& E) X5 q" T计算在测试集上的均方差" X' l: p. V9 Q
    test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))5 M& Y/ H' G' L$ t( l
    print("test_X shape:", test_X.shape)% n! E  K4 f" U1 t* k

    ; l/ T! T: M4 R( G
    , e+ ^% n! B2 Z/ N0 e# s7 X
    # invert scaling for forecast* |6 L+ o% c+ M
    inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)7 c! B/ G, E& Q8 [
    inv_yhat = scaler.inverse_transform(inv_yhat)  J. f2 D' b( @; w- o; P
    inv_yhat = inv_yhat[:,0]! T" Q0 }% ]7 g/ U' A
    # invert scaling for actual9 H5 i; `/ a' ^( \, L2 k* k
    test_y = test_y.reshape((len(test_y), 1))
    ( G( G6 w2 s$ S" \7 w& \inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)8 d, t0 [* W% X/ y0 ~- r
    print("inv_y:", inv_y[:10])
    " m  A% r0 f# n; q5 J7 v3 G1 p5 Oprint("inv_y shape:", inv_y.shape), L2 w4 _! {' B! p$ i% x1 ^, p
    / t: k! j& n7 B! b& {
    , H; O" j! D$ x5 r+ i
    inv_y = scaler.inverse_transform(inv_y)
    ) F6 N) z% F+ E' Iprint(inv_y, "*"*30)  W$ l5 Q2 G2 p) G; k. m

    . K# C, G1 D0 W' W  w% x$ Z
    5 Z! X( V( U$ y( B
    inv_y = inv_y[:,0]
    : b7 c( u1 Q+ C, \- M1 r3 i4 d+ a# calculate RMSE
    " g  m$ A2 R" C7 O+ G' [* trmse = sqrt(mean_squared_error(inv_y, inv_yhat))
    0 }5 t, ?: a4 |! X  f9 l! Qprint(inv_y[:100], inv_yhat[:100])
    " b( T2 N9 |, R0 ?print('Test RMSE: %.3f' % rmse)
    1 c1 r& k2 i, p1 ]8 p5 z5 G' _+ A& M" Y( r$ w* D
    / U; ]$ v/ M! C
    '''8 Q; I9 Y* s6 {6 r) i. L
    实验结果
    ) q, g* A7 D2 U9 F/ G7 j
    实验1:用前一天的天气数据,预测某一天的空气质量8 b' M7 t( d- }
    使用LSTM模型+ `! q/ y1 d: C. s: Z$ S; k
    结果:
    : T* a' g( |2 z" i8 h0 a: {4 U3 kEpoch 49/50
    " ?6 Z* _# F# f$ D0 L3 {0s - loss: 0.0144 - val_loss: 0.0133
    ! U4 C1 G3 h& Z/ p6 }Epoch 50/506 T+ h" o+ v8 _# s9 J
    0s - loss: 0.0144 - val_loss: 0.0133. N7 G& h* |: r5 [& ^4 k7 R

    & @7 O( ]1 {% ~* T: {0 x
    2 g/ k+ i5 g; O! t2 g% v
    实验2:用前3天的天气数据,预测某一天的空气质量
    + F2 d* Z1 p4 |2 o+ A使用LSTM模型; F" x7 |- r3 S( }7 g

    ; u. C6 q2 ^2 t! G7 R) E% o& W

    # \3 J+ H5 m& U结果:
    7 h7 ]4 f  ?4 Q2 o  ^Epoch 49/50
    - n0 Y0 U/ o# L/ l% T  N0s - loss: 0.0147 - val_loss: 0.0149
    6 Z! h4 Z' L- h. O' k, p8 s! pEpoch 50/502 R: n6 G6 F3 V8 C( M, ^
    0s - loss: 0.0147 - val_loss: 0.0150
    # p: ]; e. \$ r! y; Z8 \% M" f
    2 v- R! ^+ c' Q
    4 y* j$ E4 X+ u1 \- m6 X8 [  i
    实验3:用前一天的天气数据,预测某一天的空气质量- U7 \$ ?: O' e
    使用普通的全连接模型 Dense()% p& q6 y& ~  B3 l. ^2 q' K
    结果:
    ' O; f( _  k, l; k' u0 T' HEpoch 49/50
    0 u4 Q2 i; a! `8 @% W3 V+ c6 x0s - loss: 0.0144 - val_loss: 0.01467 E) Z. |+ `3 A8 C! w- O' j
    Epoch 50/509 g# |) ^& E6 U5 |9 G/ R" W$ k
    0s - loss: 0.0148 - val_loss: 0.0151
    % y  `) b) b* s4 |; y% P* a4 d# ^3 x  n; i7 {

    ) \  f3 w3 A* Z6 R% z0 h8 G实验4:用前三天的天气数据,预测某一天的空气质量
    $ y! _  E2 _4 T/ Y, M使用普通的全连接模型 Dense()
    + _8 N" u5 M4 ^6 Z结果:6 ]2 n. H8 ^# V- s% U1 A, f6 _
    Epoch 49/50
      @: I+ e3 s* P) S0 ^0s - loss: 0.0150 - val_loss: 0.0165
    ' S3 u. ~5 \4 a3 ], l! rEpoch 50/50: e! O2 }/ U9 g9 R8 J
    0s - loss: 0.0148 - val_loss: 0.01418 D" B' i3 v7 b6 ~1 X+ M

    # _0 x6 M6 {+ C# s2 a: N$ R! o
    5 d! m! N) @7 I# p7 _* R
    实验5:用前一天的天气数据,预测某一天的空气质量' \7 {. x, G/ Q
    使用SimpleRNN  P  M. g7 b3 z; x3 M
    Epoch 49/50
    " H1 R+ _5 S  s. l0 A6 C$ |0s - loss: 0.0160 - val_loss: 0.0140; ^  j; M1 D+ x, V0 E1 a5 |
    Epoch 50/50# f+ F3 z$ r; ?2 o9 k0 [
    0s - loss: 0.0147 - val_loss: 0.01503 l/ m0 }. s/ M5 x6 `6 D. I
    ! p3 ^4 D' ]+ _! R) _7 S& ]
    % Z% Z2 j8 t; y0 V; Y' p1 q
    实验6:用前三天的天气数据,预测某一天的空气质量% ]7 N  i" H. `! m' {
    使用SimpleRNN& T& O. K" q; w
    Epoch 49/505 A5 ]8 G( ^6 q, Y$ i; a2 P
    0s - loss: 0.0164 - val_loss: 0.0233! U9 q/ E- m6 B/ t
    Epoch 50/50
    , J0 w% {# F; d! [3 R0 Y1 q0s - loss: 0.0166 - val_loss: 0.0227
    ( V, h7 N8 ?, d- _9 _- {* JRNN和DNN的区别

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


    4 W- P  }- _% v3 j. q' m" p+ }
    " K7 [" B$ ^! ]$ X

    % N/ [) g/ {# k: B" _
    RNN和LSTM的区别
    9 ?" _$ n% U5 ^# rLSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
    6 \( T8 v4 i5 C* |: |- P! Z% k. i" }" b. S1 o( ?

    + A* b7 I6 N/ b4 v) @但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。9 s' I# Z( z+ U. f7 v: \
    : ~8 Z! p8 ?+ G& x) V# }$ \
    # `3 r1 F+ z) O
    请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
    ! C8 D8 e' B$ N2 S+ q! O

    ) q% Z$ l, ^% d/ c+ K
    % q9 U; F; ^1 o
    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-4-21 08:25 , Processed in 0.326653 second(s), 56 queries .

    回顶部