QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2513|回复: 1
打印 上一主题 下一主题

使用LSTM预测空气质量pm2.5

[复制链接]
字体大小: 正常 放大

1158

主题

15

听众

1万

积分

  • TA的每日心情
    开心
    2023-7-31 10:17
  • 签到天数: 198 天

    [LV.7]常住居民III

    自我介绍
    数学中国浅夏
    跳转到指定楼层
    1#
    发表于 2021-10-15 10:53 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    使用LSTM预测时间序列数据
      S& T0 {1 `4 f7 v/ Q9 D+ t$ r. r3 q  C4 s  }

    . N- _* I6 k( \: X0 t文章目录" ~0 C6 e9 z! c. ?# u' Z+ |
    背景: b. k" c! M1 M- X7 s) [: x9 W' B
    结论
    ; Z2 O' A; K0 I+ ~) v7 t代码
    & C4 y+ y" ?  F9 k& j0 v1 R实验结果+ `9 m, H" S8 {- h* ^
    RNN和DNN的区别
    7 U* g! J' z" ]) e, _2 z& b. FRNN和LSTM的区别
    ; F$ W8 i& B' W) c2 V背景
    $ m1 j% \7 {$ X) b6 S6 F复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验. g- ^( Y, c$ v$ J$ G/ N
    熟悉用LSTM模型训练
    + S$ C- C' F6 Y验证将时序数据 转化为分类问题后,预测是否有效果
    * L- T: t) B; }+ W对比SimpleRNN与LSTM模型 哪个效果最好?& N! e$ ^& i. A! E2 m, n: g* H) y) `
    验证LSTM相比于Dense()模型 是否有提升?
    , f: J- C7 c' S+ I* Y! r) ?- M1 i对比使用前3天的数据 和使用前1天的数据 哪个效果最好?$ \) Y) ?% Y$ e( M. Q! N7 T+ O  @
    结论, i  B3 t' L7 k8 W9 c1 f6 F9 @
    使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好0 |+ \1 x2 r6 D' v' y! q
    使用LSTM的效果优于SimpleRNN0 b$ Y! }2 A) t6 b
    代码
    ( b6 U4 i$ y# Dfrom pandas import read_csv7 p$ @' ]* i6 P$ I" z
    from datetime import datetime
    + h3 X4 E. Q  Ximport pandas as pd
    ; r; v- K4 N" }; Rfrom pandas import DataFrame
    ; i: \7 f) `; L' ofrom sklearn.preprocessing import LabelEncoder,MinMaxScaler: }3 M3 a# i/ M+ b
    from sklearn.metrics import mean_squared_error. W5 l- X) ]- Z3 e, ?( k
    from keras.models import Sequential& }  Z) v4 @& l5 Z' \5 G
    from keras.layers import Dense, Dropout3 o: l3 n4 j  {0 b
    from keras.layers import LSTM
    : ]+ v/ S, O7 m! w; z4 Ofrom keras.layers.recurrent import SimpleRNN
    4 F! P: M5 ^6 I$ m* A: Z8 `. Pfrom numpy import concatenate! u9 s2 K3 u3 y0 p) N3 b$ K& }
    from math import sqrt8 L  ~" i/ ?* `* E& c9 v+ L4 e9 [
    5 ~4 ?! \" \6 x  R$ o! ?

    & G, r+ {1 J% X5 _/ C) B. v: z% Z0 s( m1 A/ X0 X
    # U" ]% E; |8 [) ]3 T% x
    # load data
    $ B4 l( Q, l+ _def parse(x):1 ^  e6 Z8 A1 Q, [5 O! d9 P
            return datetime.strptime(x, '%Y %m %d %H')7 T9 i6 e( ^6 z0 V% v
    % ?; z3 T0 Q: v' f. c+ p
    def read_raw():
    1 {& m: H8 w2 f2 N    dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)5 q  g5 h  _3 D. R* b+ B* C
        dataset.drop('No', axis=1, inplace=True)
    , F: d0 \  q& h9 O3 I1 o    # manually specify column names
    + l! D0 J$ b0 |# T* A4 a    dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']
    6 `, _1 Q1 n, }; T) i    dataset.index.name = 'date'1 N4 E  h3 }, u; q" I2 N3 |
        # mark all NA values with 0- S( }5 f+ {' R! m! r; L8 F
        dataset['pollution'].fillna(0, inplace=True)% H0 t( j! b0 x2 p5 w/ }) _. u
        # drop the first 24 hours' r' O* y, J  P$ t/ q
        dataset = dataset[24:]( X5 a$ g, Q) i' G6 S: P" ^* F
        # summarize first 5 rows8 D' ?3 G" H$ C; G# @! W7 s/ l
        print(dataset.head(5))% e1 ^0 y: E7 u. A
        # save to file. L# M/ f7 C* F
        dataset.to_csv('pollution.csv')
    + g; q' n# T2 y8 \. |5 e- P
    - Q" g, c1 \7 ]& `. }
    7 r' y1 ]  U$ C7 @+ p; u, F

    $ e5 J! T" {' K2 k( e

    ) C8 u; ^2 H' j% G- r6 Z( h# convert series to supervised learning5 U9 ^* R8 y* N# s0 F8 o. V
    def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):% w% k7 r6 ]6 P- u3 o7 {
        n_vars = 1 if type(data) is list else data.shape[1]
    * D6 Z0 y7 }; X5 x    df = DataFrame(data)6 v0 {  s" m" S* ~7 T- C# |) D
        cols, names = list(), list()
    9 B, H. F  B+ j7 v/ E    # input sequence (t-n, ... t-1)
    0 x+ r# u$ {; _6 V- y# n6 O    for i in range(n_in, 0, -1):
    8 ?% y5 T- x- {: o7 |% ~        cols.append(df.shift(i))
    . O) l  N3 y: t        names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
    + l, T; b% ~, i. w7 X    # forecast sequence (t, t+1, ... t+n)9 m: w& `- d# A+ X9 w% Y, ?
        for i in range(0, n_out):5 s" a# w: C/ h" A! k% s
            cols.append(df.shift(-i))
    9 b: J9 g! _8 \4 [+ }        if i == 0:
    ( B& [3 N2 E, g. l  q3 D            names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
    0 F) \6 `! F2 s0 ?) @+ o4 |- |        else:( @, ^' M3 A9 ?: q% u( H9 K6 q+ S
                names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]7 l& Q: r# a3 j1 m8 s2 |
        # put it all together, h5 C5 u& M/ w8 V% ~3 b
        agg = pd.concat(cols, axis=1)
    . @; b- A! R6 B. u8 S1 A) y9 j9 [    agg.columns = names. D" d. K) P6 i6 J  W$ K( V( s+ t
        # drop rows with NaN values
    ! z" g$ _+ d7 t1 J    if dropnan:0 s0 H' M0 E6 C, ^8 }
            agg.dropna(inplace=True)+ P; l7 p# T5 O( Q( |
        return agg7 T0 K+ [- i7 ^" R' }; W
    2 _1 I' r3 V" n2 m
    # load dataset
    9 X5 d- ?# a5 e) g3 h. P+ Zdataset = read_csv('pollution.csv', header=0, index_col=0)4 F5 J6 f! P1 y2 d$ z& P! S
    values = dataset.values, |7 b7 O; M" D

    " e: t7 _5 T+ I4 k/ ]$ x% p/ y

    ' j, u* R) ~) [4 d3 h$ x# integer encode direction0 x* Y% J9 a$ ~& e
    encoder = LabelEncoder(); v$ Q6 F+ K. M: h
    print(values[:,4])4 W5 {( p- }- y6 H) Z
    values[:,4] = encoder.fit_transform(values[:,4])7 M+ Q- M9 G# ^4 `4 C) v1 o
    # ensure all data is float) b% P2 f: Q: g
    values = values.astype('float32')
    0 h& Z! ~: J2 l1 i- _8 v. Z$ l# normalize features
    # p- ]. A5 X( Y- [3 d- V, q9 lscaler = MinMaxScaler(feature_range=(0, 1))
    4 b  u' ^% v& w8 p: }scaled = scaler.fit_transform(values)
    2 L. ?0 T1 Y8 l) X' @# frame as supervised learning, A8 o( @2 a5 G7 l2 d- s. T
    reframed = series_to_supervised(scaled, 1, 1) * K0 p. {- ]1 M4 d6 Q
    #reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据
    0 l- Q$ N* f8 n, ?, W9 oprint("columns:", reframed.columns)& b. O+ r" |$ i( T. k7 \
    # drop columns we don't want to predict
    ' s1 l2 P) E( ~+ c$ z9 hreframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据
    $ `- `4 ~- l3 s( A( X# j  ^#reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据
    ' L/ `6 v; H4 \- [7 sprint(reframed.head())
    $ X' A+ o1 u& V$ hprint("new columns:", reframed.columns)& ^( _  L; E  H- G0 r
    # split into train and test sets
    8 s7 u, |4 ~9 {* a" a: f, fvalues = reframed.values
    ) g6 R+ a9 k8 d5 k: cn_train_hours = 365 * 24
    . T7 C) ?3 @$ j! e  i" otrain = values[:n_train_hours, :]/ |% z0 q! x' V; g) Y
    test = values[n_train_hours:, :]& q! L( W+ f9 c: d" W3 c+ ?  o) ^
    # split into input and outputs4 o& K( _  U* R9 T6 d2 R! g
    train_X, train_y = train[:, :-1], train[:, -1]8 e$ t# \5 l# q* B
    test_X, test_y = test[:, :-1], test[:, -1]
    , e8 S% u  n" ?# reshape input to be 3D [samples, timesteps, features]8 t) o5 U! k& H, V( Q
    #使用Dense()模型时不用变换
    8 B9 T& q- K, C; Ctrain_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
    ; {/ o! D8 H/ C; gtest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))4 T4 ?2 }8 L! ^; k* y/ l1 t
    print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
    / ]# X1 k$ }' _3 n1 e# design network- G6 }1 }/ v) ]7 M4 w
    model = Sequential()
    5 M0 ~1 j. g; t  a#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))5 |- m% U# e& P
    #model.add(Dense(50, activation='relu', input_dim = 8))
    ) |, S& L9 R5 H. I8 y) C. zmodel.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))1 T7 c+ O# g3 f1 C! @) y
    model.add(Dense(1))3 O2 B7 q$ \2 x. z& W: b
    model.compile(loss='mae', optimizer='adam')
    2 t/ S& n* |  n! x8 `* d( C9 P/ Q# fit network
    % s* u9 K" i4 }" k; C2 O/ Dhistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)& f  i6 o% `# |" M* j8 a
    # make a prediction  I$ x, y* x, ^& a
    yhat = model.predict(test_X)
    + h7 C& l' Y7 o% Q) M; zprint("yhat shape:", yhat.shape)
    5 h+ ^9 }) n) I: M; M( r'''
    . m1 C9 r6 W% S+ k! c计算在测试集上的均方差$ D  N0 T6 i# c! _' r+ i
    test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
    9 {% M" f( o" Q3 @print("test_X shape:", test_X.shape)
    * n" a" Z$ z+ ~
    / i. |4 m9 R+ r3 u" B: |

    . c. \% n! M) o! h5 a; p# invert scaling for forecast/ [% f/ r; O' D" h
    inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
    ! I) t5 H. H3 V& Q/ Z: `4 m& o. vinv_yhat = scaler.inverse_transform(inv_yhat)
    8 D8 x2 X' E5 i* Tinv_yhat = inv_yhat[:,0]
    # O' H& U  x2 l4 n8 k& p' Z$ h# invert scaling for actual% @$ Q/ c7 [- f% I9 R
    test_y = test_y.reshape((len(test_y), 1)): X' D1 [3 U$ l
    inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)* g, s! H/ Y! U1 k* T
    print("inv_y:", inv_y[:10])" ^4 u' |- y1 [. T; L; ~1 i$ k
    print("inv_y shape:", inv_y.shape)
    / n( u& E2 I, O: z( J
    ; @: b9 s9 Y" O, ^

    ( `6 G) e$ p( finv_y = scaler.inverse_transform(inv_y)8 }: p/ C$ H4 ~' J
    print(inv_y, "*"*30)
    , s9 L! \/ ?" _$ d* i7 w$ o2 b% N$ @! y, |
    1 p( c7 Y8 N% n) ~. ]4 E
    inv_y = inv_y[:,0]
    : P- V0 c" Z  V) g  ]  d8 p' ]# calculate RMSE1 `0 s' J2 ]$ y. Y5 V3 m. }
    rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
    8 Z' S/ |! p( L; G; Yprint(inv_y[:100], inv_yhat[:100])
    ; m- r7 f) D: K/ T: zprint('Test RMSE: %.3f' % rmse)/ y8 i7 S) P. ]- l4 R" H% A
    * T' W, E) N' Z1 G3 B1 K

    , m6 ?' R- w( p6 C# E( x# B''') w. |' T4 B6 r% D6 |! a
    实验结果
    - Z0 o, Q& q% j7 f/ b0 D, T* c
    实验1:用前一天的天气数据,预测某一天的空气质量2 D% Q# v1 R4 `* B, B# i' N+ f4 G
    使用LSTM模型
    ) j0 s( A" ^1 o2 g3 g结果:
    7 d! v0 ^3 C/ T7 ~( f/ nEpoch 49/50$ }( {! v3 j$ P. v( Z, Q. c# ]
    0s - loss: 0.0144 - val_loss: 0.01339 y3 @: y+ r/ _
    Epoch 50/50
    8 ^! n5 o9 q1 o  T1 E0s - loss: 0.0144 - val_loss: 0.01337 }, u( E8 V% K; M5 d/ U/ Q

    2 V8 Q" k: P9 K2 H) T6 \/ E" K; E
    . P. B* b+ W. R5 \4 M- I. d
    实验2:用前3天的天气数据,预测某一天的空气质量
    , m# Z) W3 V8 |$ E& {1 t使用LSTM模型; u" l& d$ ]* c0 F
    * `1 ]0 S, @8 h9 [9 Q" u. R$ C! O; _

      l+ p+ }# E/ W* V. p+ \结果:
    * |/ a4 ~% m3 N, |/ e5 G- j. GEpoch 49/509 Q4 o, T. g( _5 {! z2 K4 }
    0s - loss: 0.0147 - val_loss: 0.01497 G3 y/ R8 d1 o3 ~) Q5 n1 T
    Epoch 50/50
    8 v" {% U& [( n1 M7 T& ^" h1 g. D& M. d0s - loss: 0.0147 - val_loss: 0.0150/ B- R1 a) [' i
    0 d6 f. n1 I8 _' U
    " e1 S, P: W2 ^2 O. t
    实验3:用前一天的天气数据,预测某一天的空气质量6 U6 d* x/ J6 V/ G. O' P# y
    使用普通的全连接模型 Dense(), g: Y6 S; g5 J7 i3 g# n" {4 U$ X
    结果:# J# D# G( e; e
    Epoch 49/50: K' R, i* w% k% N" z
    0s - loss: 0.0144 - val_loss: 0.0146
    $ q- g, ?! \6 B; t7 w0 y6 BEpoch 50/50. d- x6 i3 N+ n, q
    0s - loss: 0.0148 - val_loss: 0.0151) g& o7 Z. \+ n- _2 V3 I0 Q0 n

    . ?( V- c. g  N# R0 a" L: Z- z

    * F0 a0 Y; s6 S) |实验4:用前三天的天气数据,预测某一天的空气质量
    % Y% K% Q% _& \" ]: ?" z1 f% l使用普通的全连接模型 Dense()
    - u$ c* d( d5 p8 q结果:
    & i5 ]' N. [6 r+ F6 J3 VEpoch 49/50; [8 z/ g6 V6 J0 U- G  T- q6 g
    0s - loss: 0.0150 - val_loss: 0.01652 o( l6 t  G: r
    Epoch 50/50
    ' N8 M2 v; R+ l" \. h; c0s - loss: 0.0148 - val_loss: 0.0141) g4 N# d7 B$ j) S: m% ^& I

    : e$ X4 |3 e, n+ }- I0 H

    . G' ~( Y+ C" Z4 B: b实验5:用前一天的天气数据,预测某一天的空气质量
    4 N0 s+ v2 Q7 {; B: P使用SimpleRNN- D1 O2 C8 ]1 Z5 C  @: K' l
    Epoch 49/503 |* `8 L+ x1 {
    0s - loss: 0.0160 - val_loss: 0.0140
    ; {5 p+ N4 [( _5 K( dEpoch 50/50- t$ {# I$ q  H, {0 J) S
    0s - loss: 0.0147 - val_loss: 0.01506 x4 P& ~; w, F! M

    0 K- J* q- t: G9 {# t; W# t
    2 L' {* N5 E2 {2 i' v
    实验6:用前三天的天气数据,预测某一天的空气质量3 S8 z8 A  f& K8 B" H
    使用SimpleRNN
    - L9 O& m" Z' S: O7 X1 {* gEpoch 49/50
    $ B7 t' W' l& F# g( e6 p* I5 Z; B$ O0s - loss: 0.0164 - val_loss: 0.0233+ Q; m% y. V. S8 k: v* ?8 S2 I/ W( \
    Epoch 50/50
      }! U( P* H# U4 U' f  D0s - loss: 0.0166 - val_loss: 0.0227
    , ]( C3 B' _4 u; n3 }( rRNN和DNN的区别

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

    $ E- o& I  `; H, G7 B% M

    . i% T' q/ J1 {; W
    # \; t' @/ z$ D; s
    RNN和LSTM的区别" r' B9 S. q, g* O4 R) U1 u, i
    LSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。$ q" i, o( {+ a6 X
    $ o4 e2 |& e, L$ t0 y  [) l
    7 V6 D( \; D" x3 X0 J; K
    但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。) U& Z! A( V$ @7 y( q$ M: {5 r) r
    $ y* n" R0 z' S

    ( E0 r) L6 j* K; w& y# [# \请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员

    9 ?: `+ T8 b/ u6 c7 h2 T* X; Z3 W# X" u4 v1 K3 \4 _) [
      D, Y) \) Y" H1 q4 Z! G' s
    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, 2024-4-29 07:52 , Processed in 0.335147 second(s), 55 queries .

    回顶部