QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4396|回复: 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预测时间序列数据
    % B; l4 J& p* E% n
    ' T8 V( {, g  G- I

    9 j% n% T- D% h! _. X) p6 c. k文章目录
    $ E7 i& w2 C' H6 T! j背景. C! X: F. `2 Y( [+ m: I% W8 {
    结论9 m* {3 b' G9 r! {( y7 @
    代码
    ) w, l8 v2 e- F; Y- m实验结果
    : [! D! j3 S  y1 M! PRNN和DNN的区别, Q" x& Y9 x" ?) v! n7 ^+ R
    RNN和LSTM的区别
    & Q7 o# K9 ?7 v0 [4 ~背景/ j# s9 a  u  W: s" N  K
    复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验
    ( A( R9 E0 h5 Y7 S4 g0 F9 i, c熟悉用LSTM模型训练. J: P& D; ^, o, u+ q+ o
    验证将时序数据 转化为分类问题后,预测是否有效果
    2 l; _+ S* X6 g+ q: x3 R5 b对比SimpleRNN与LSTM模型 哪个效果最好?
    : m/ j, I  Z" ?8 G& L8 f9 e$ H验证LSTM相比于Dense()模型 是否有提升?
    ' L. ], b) F5 S# y3 E; A7 q( V对比使用前3天的数据 和使用前1天的数据 哪个效果最好?
      E2 t5 a. J% p! _结论
    5 T. y- C7 ]. }: S( d7 d3 j使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好6 G- e3 ~7 i5 }( D- g/ x; Z  Q  Q
    使用LSTM的效果优于SimpleRNN
    . F5 m( W: P$ S& X6 m* w5 y代码: ?: I  W( K3 q1 _- A+ O; \
    from pandas import read_csv
    ) n. g# ^& R# Y% dfrom datetime import datetime7 C- _$ `/ W4 R+ M$ c  D6 m+ A
    import pandas as pd
      H  l9 L- o8 Jfrom pandas import DataFrame
    ! U7 j- R0 [' F7 N' rfrom sklearn.preprocessing import LabelEncoder,MinMaxScaler
    ; j3 ?3 U- S' R; j7 X- _9 ~; xfrom sklearn.metrics import mean_squared_error2 M8 D9 L/ C/ b2 e+ D
    from keras.models import Sequential7 H6 V1 \8 y* J: a) m5 N  A
    from keras.layers import Dense, Dropout) d) ~) l7 [1 R" z, h
    from keras.layers import LSTM
    # h; m8 m7 ~+ Sfrom keras.layers.recurrent import SimpleRNN
    - F. V) F7 y. L" ?2 Q! a  m1 i9 U7 Yfrom numpy import concatenate
    . x. E8 i- n/ m5 @+ {from math import sqrt$ w3 |1 n% v! q; ]  e
    ) z0 `7 t4 m& R# `9 m0 P

    / Q" g9 I8 Q+ X+ b) r+ r! ~7 h
    : T! e1 L9 k9 _( F) Y
    % u8 N; k' p  }) f% Z8 Z
    # load data+ q6 V* v' L! W/ D1 i
    def parse(x):- t1 N6 b6 ^4 W% L. d- {' l0 z
            return datetime.strptime(x, '%Y %m %d %H')
    6 O! p, `$ \! H0 |+ a0 a $ H, N* f2 `" I1 u% j! ^; `
    def read_raw():! H; \+ J/ x( L7 |
        dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse), T+ E( q% F; O7 |3 j
        dataset.drop('No', axis=1, inplace=True)
    : c3 J1 S& k! N    # manually specify column names
    # \# _! J8 O4 w3 K7 \: P9 R4 ~3 i    dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
    * F! k2 v  |: d  U* ^+ y: \6 o1 u& f0 g    dataset.index.name = 'date'' ?, n4 R$ m+ a: F  t' x
        # mark all NA values with 0( J/ O8 d4 @: M
        dataset['pollution'].fillna(0, inplace=True)
    3 g) V  F8 N$ w* [( e0 t7 A6 f  c    # drop the first 24 hours
    5 y( L- Y, E, x$ f$ |8 [    dataset = dataset[24:]& L. @# y3 V! h. m: x
        # summarize first 5 rows
    1 B2 n: e4 i" G  X  i    print(dataset.head(5))  ^) Z0 E! j- X- v) u$ n3 l
        # save to file# K0 x, V8 |5 P7 Y% y7 G
        dataset.to_csv('pollution.csv')- n: G$ p# h0 x1 z3 _5 J: t1 w
    9 P0 z- h: s1 S

    ; i% C0 f9 P2 S, u+ W( `
    ; q" C8 ?! Z  e7 G1 c
      P& E' h# Q! N( p: _5 A
    # convert series to supervised learning
    4 F: x1 o& _3 F& Fdef series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
    $ i7 m, B' ~9 Y    n_vars = 1 if type(data) is list else data.shape[1]
    * @) x  Q2 P  _: ~( O    df = DataFrame(data)
    1 W5 G2 y. z4 n/ \. a5 B    cols, names = list(), list()1 k# |: r* I- @# }9 m' Y
        # input sequence (t-n, ... t-1)
    5 y6 o" N3 G1 \! _6 K+ H: A    for i in range(n_in, 0, -1):8 U# ]' O2 H: U
            cols.append(df.shift(i))
    5 `. d( y# G9 M5 c0 v        names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
    % Q6 M% I* l3 p& Y' n! A2 u( L    # forecast sequence (t, t+1, ... t+n)
    6 S; r4 r" P5 }4 R- n3 h    for i in range(0, n_out):
    1 A/ t; r2 t6 ~3 z" O0 }$ b; o" P        cols.append(df.shift(-i))/ K- C! ?5 n4 K
            if i == 0:/ e$ T' v' Y; v# i6 I1 m) N
                names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
    ' P' e% D( v1 }% e  `        else:
    ! c! o- a0 Z: z, O  e+ w) j# d2 L            names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]' p0 @( W3 o0 E: S' Z
        # put it all together
    ! Y/ |5 ^2 k9 O  m8 J    agg = pd.concat(cols, axis=1)
    ) f4 d$ `) G% }6 f& s2 A2 h    agg.columns = names1 k% i( w* `0 k1 [" P* P2 ?
        # drop rows with NaN values% G# w1 \# g$ }9 u
        if dropnan:
    ; r+ X0 \1 e& f) G        agg.dropna(inplace=True)) d( U7 P+ E1 F( V' t; b, p) ~
        return agg7 s" X# s6 V2 Y

    5 q" ]% w0 X  y8 k! w! C# load dataset/ r6 P5 L* x9 s4 D; H, Q( }  E8 I
    dataset = read_csv('pollution.csv', header=0, index_col=0)
    " C" Z4 v) H5 `1 w/ H% y/ Xvalues = dataset.values
    * r4 n  C: D( [3 r# B
    ; e$ v9 F' t4 w6 K% r

      {) v+ M6 S0 E, p- F1 b# integer encode direction
    8 J9 a1 z$ x. \0 Aencoder = LabelEncoder()
    1 l4 E8 {# o4 H7 p5 p) q( ^' S# rprint(values[:,4])0 F6 D+ d" W- C9 T
    values[:,4] = encoder.fit_transform(values[:,4])) p) G8 w6 U1 q1 l6 `( [
    # ensure all data is float
    % O' x4 @4 ^# K0 y2 E1 h1 gvalues = values.astype('float32')
    4 \- H% R% H: E5 q. a8 }3 E# normalize features: v, Y' ~1 q9 u) q0 W) \/ \
    scaler = MinMaxScaler(feature_range=(0, 1))- }! v" m  _1 H
    scaled = scaler.fit_transform(values)
    / ]- a/ |' g# `: B6 l2 P' C  M# frame as supervised learning% J" Q- g$ }- P& V0 B
    reframed = series_to_supervised(scaled, 1, 1) * E6 ?( {' g7 e1 c2 m
    #reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
    8 s$ R; Q: [4 a6 D5 w" g7 Qprint("columns:", reframed.columns)+ k  `9 K; E: G$ y- z4 A0 y
    # drop columns we don't want to predict
      p: O# D# V! G1 _- preframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
    $ m- u' l" `$ K#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
    ) p8 Y) E7 h% e, o$ M2 s) ^$ p. \print(reframed.head())
    1 x! J" B- X/ b- k6 r; uprint("new columns:", reframed.columns)
    1 q# _5 W# c- S: h( r+ C# split into train and test sets! H2 C/ O- p$ ^
    values = reframed.values
    / f* c1 T- R) y! K3 Wn_train_hours = 365 * 242 @# e) [" ]' ~6 g# Q- V& P# W
    train = values[:n_train_hours, :]" `/ P) e; C1 r( q
    test = values[n_train_hours:, :]  l* v6 Q: G' y7 X  y
    # split into input and outputs# p/ G, C8 w! y/ ]5 Z( h
    train_X, train_y = train[:, :-1], train[:, -1]
    % @# w) W7 \& Mtest_X, test_y = test[:, :-1], test[:, -1]
    % w; @( e# D  m' }# reshape input to be 3D [samples, timesteps, features]& q0 O' f- A( `# Q% [
    #使用Dense()模型时不用变换9 }9 F) U" h' I  I5 c; T1 I
    train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))4 W4 [, n) u. O/ n" c3 U
    test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))" z9 X+ a9 T$ {, H8 {) f$ I  {5 z
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)4 H( r5 o- y! @
    # design network
    . h9 c) q  \1 P& G- Mmodel = Sequential()+ m' j& g: I2 ~# F  Q% I6 }' k% u
    #model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    6 k5 k% G6 Z; o' T( B3 v+ a. _#model.add(Dense(50, activation='relu', input_dim = 8))& z0 F2 t1 h- q, N: i
    model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))
    ' G+ X  u' J' q: ?model.add(Dense(1))
    4 `* |3 i7 U- e# Wmodel.compile(loss='mae', optimizer='adam')
    . Y$ g9 r6 j/ j1 A3 @2 Q" n# [# fit network& j9 r: X* n4 ~
    history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
    ( _% a0 [3 _. Q! m' b' ]8 P# make a prediction
    " P  }$ S/ G9 Tyhat = model.predict(test_X)
    : D' y, E( e4 ^# ?/ Lprint("yhat shape:", yhat.shape)
    - a/ J9 L6 o! v: m% S( T% {'''# i& L0 x" A# G
    计算在测试集上的均方差, C+ O7 O: t# D) H! A* o- w( J# }% ]
    test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))6 Q* M$ v7 n2 }: h+ q- }9 a
    print("test_X shape:", test_X.shape)
    # _; t) u( v6 D/ A% `% O, ?" Y2 ]
    9 M4 p' D; L. }3 D5 V& a
    # invert scaling for forecast& p% y# P) d% n& S$ _6 v( n8 `
    inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
    ' F$ ~6 y% V3 w4 W  ^4 g# p) e8 Ginv_yhat = scaler.inverse_transform(inv_yhat)
    0 \1 M' S8 _1 r& C$ Y& _inv_yhat = inv_yhat[:,0]0 }: G- F7 `) X! J. x) W! T
    # invert scaling for actual
    + ^9 h7 H1 k+ ?4 w; \test_y = test_y.reshape((len(test_y), 1)): ]! A% ]7 Q1 W
    inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)
    # M; P  W9 a- L+ ~print("inv_y:", inv_y[:10])8 Y# _/ r9 X8 h+ T& y$ M
    print("inv_y shape:", inv_y.shape)
    4 [; d1 b$ h  t/ }% R0 k6 Q
    5 b, z" W; L% @( R9 i

    3 o! q7 X3 o; B, l. C4 L7 `4 oinv_y = scaler.inverse_transform(inv_y)  q5 K# k6 F6 ~9 W4 c# T
    print(inv_y, "*"*30)
    8 P* z" \0 y: B  s- w# f' u4 T8 M: v

    : C0 I/ W9 g- ?0 z( d( zinv_y = inv_y[:,0]) A' v% A, ^; j- A' d$ a1 r! S/ k6 |
    # calculate RMSE$ Y: L3 f1 z+ e) K9 q
    rmse = sqrt(mean_squared_error(inv_y, inv_yhat))( J; Q* z$ n5 m" ?& a3 M) P( J
    print(inv_y[:100], inv_yhat[:100])
    , o4 T) J% n* `# c" k! L' t" Bprint('Test RMSE: %.3f' % rmse)! V& d! v" o* o7 u$ q6 i; c

    8 r3 J8 _: @2 H  ~3 s6 R1 y3 {2 y) G

    ) v! [' S! z1 P# t8 w$ O" c'''
    ! n6 u" d$ G, E% @/ s( X实验结果+ v. r5 T0 a) G
    实验1:用前一天的天气数据,预测某一天的空气质量
    ; I; v6 K4 a' Z" p使用LSTM模型
    ) J. T5 \3 l3 V& I/ L  m结果:
    9 _' t% p5 f% l2 b) X3 r% c5 }* EEpoch 49/50( t# D' n. D# g
    0s - loss: 0.0144 - val_loss: 0.0133
    ( ~# b  H9 k* N) ^- B6 GEpoch 50/50
    . y& |0 E/ s% f2 w( Y$ [0s - loss: 0.0144 - val_loss: 0.0133
    9 R& `' W- T8 U9 ^' ~1 X$ T: n3 Y4 k' A3 d

    ' `8 h7 g* `6 @- C$ j* B实验2:用前3天的天气数据,预测某一天的空气质量7 Z' H& e) T& o# n' m/ U
    使用LSTM模型" @/ Q- F- f( r! G

    $ A7 X" ?+ o+ l) P: y6 n- c  K

    9 j& C/ _0 @8 \" G" F4 v结果:
    : {2 Y( A2 v  LEpoch 49/50' a. N& {* m; O2 z
    0s - loss: 0.0147 - val_loss: 0.0149
    ' n& z" ]( i  s4 \' eEpoch 50/502 v& G- W9 v; A6 k: s* v: X
    0s - loss: 0.0147 - val_loss: 0.0150
    ( s, y; x3 U& u' h* T( {) a' K* b& ?" P! U' t

    - h) h6 J1 u% T/ M实验3:用前一天的天气数据,预测某一天的空气质量+ `2 N$ t& W" S6 }: s
    使用普通的全连接模型 Dense(), a& }2 g+ D  i0 e, p+ X
    结果:
    . o) E0 [; H* m$ _1 f' hEpoch 49/50, N" \8 s* d3 Y8 `+ C( k9 [4 R6 M
    0s - loss: 0.0144 - val_loss: 0.01462 K, F/ V" B5 G' d* E
    Epoch 50/50. I& M. k8 K2 g8 s  e, C! e" w- k
    0s - loss: 0.0148 - val_loss: 0.0151( z4 o/ q* \! f4 {  Z7 o

    , R- e4 @$ |" C& y  H4 e% B

    ( w7 F8 k9 l5 Q6 w+ ]' n* ?实验4:用前三天的天气数据,预测某一天的空气质量
    8 f! E. v; X/ e使用普通的全连接模型 Dense()+ D! K7 T% }2 ~9 M# ^. |, q
    结果:  i& X6 g+ a' @" O
    Epoch 49/50/ X9 q& K* T+ K' @
    0s - loss: 0.0150 - val_loss: 0.0165
    ' t; o1 T# x1 A3 \' O7 IEpoch 50/50# e5 S* g6 \3 V  Y+ }- ^
    0s - loss: 0.0148 - val_loss: 0.0141( a' X$ r/ D4 U3 C) R$ l' }2 J

    & D' R* F; V# u% c4 r3 w  X

    2 [; V# z' @  U9 z5 P实验5:用前一天的天气数据,预测某一天的空气质量1 q; {8 U& O1 N
    使用SimpleRNN" \7 \# y' q6 z. D! c
    Epoch 49/50" C* j8 T; N+ R/ w, q5 |
    0s - loss: 0.0160 - val_loss: 0.0140' i: g8 L; H: P5 a& F! S
    Epoch 50/50
    3 `+ H- d& b) h0s - loss: 0.0147 - val_loss: 0.0150
    " O. O: p4 [; U3 ?% f  h9 s9 I; M+ h7 v6 [% Y7 [3 y/ g

    5 E0 R4 m9 @8 Q& B0 S5 D1 V实验6:用前三天的天气数据,预测某一天的空气质量
    4 @3 ]1 h- ~  f5 k: m+ h使用SimpleRNN$ c$ V# \4 m  n2 `# y0 e
    Epoch 49/50
    ! @! C, }9 s  W4 _. s! y0s - loss: 0.0164 - val_loss: 0.0233
    $ Q# b9 ]% r7 z/ TEpoch 50/504 l4 f% u3 F! J& A
    0s - loss: 0.0166 - val_loss: 0.0227/ F' f. v+ [1 r4 k
    RNN和DNN的区别

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


    ( T+ M, R/ u& U6 _' N$ j5 C
    1 g: g/ u, ]+ {" R, e% E

    ' n+ \6 s" U! q
    RNN和LSTM的区别" t% d3 u# @, d4 Z; d4 Z6 a% b
    LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
    2 r" j- C8 k& k" L2 i; `
    # q  d0 L0 f) t, }& {3 \/ ~

    * l7 t4 _8 C- s但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。
    8 u/ s! k( _6 b* g0 p+ {
    $ J$ M8 U9 f0 b, a7 a2 B
      M5 Q: w3 [9 A9 |  r; w请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员
    1 x7 s2 a5 z$ f$ \0 e
    3 s. w( Z- {- @3 q3 s& z0 V
    ( U1 j6 E  [1 B% P+ C8 I/ r
    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-29 03:44 , Processed in 0.378854 second(s), 56 queries .

    回顶部