QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4368|回复: 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预测时间序列数据* |4 @6 F1 V! o6 ^& l$ c  z+ T
    ! a8 ~1 o2 c" `8 ]3 I

    9 X$ O4 U/ w4 G文章目录. b, e2 Z* s$ s$ x
    背景
    7 J6 [1 N& H* W1 m/ p+ T9 V结论( w# e% l1 ~' b5 e, r
    代码
    8 C' {) `1 l4 a/ }0 ?7 [% W# g  ^实验结果& G; h3 O! m6 @% Z& b
    RNN和DNN的区别2 [6 e4 _  r* S. w
    RNN和LSTM的区别; {7 Y* R9 }9 @) ~5 z
    背景
    4 R: ]8 R5 F! [, a复现 @“使用Keras进行LSTM实战” https://blog.csdn.net/u012735708/article/details/82769711 中的实验
    ; g. U) D) T3 j' T; R熟悉用LSTM模型训练
    ) v# L  o0 }: A验证将时序数据 转化为分类问题后,预测是否有效果9 n% a1 e4 d8 H
    对比SimpleRNN与LSTM模型 哪个效果最好?
    6 C- g! B5 \  [% `6 i& k验证LSTM相比于Dense()模型 是否有提升?
    4 ^- ^2 q$ @( Z$ i; W对比使用前3天的数据 和使用前1天的数据 哪个效果最好?
    + o8 Z/ z: @( Z- q6 s结论$ f5 p) [! l8 K" P" b
    使用前3天的数据预测当天的空气质量的效果 没有 比只用前一天的数据 好0 u' F/ y8 M/ v( w/ l: j- x
    使用LSTM的效果优于SimpleRNN
    - G1 v0 [  o: P( _" F! Q代码
    ) b/ K( F, {$ C2 [from pandas import read_csv
    . f% b5 H! K. M5 }. U7 Z7 S6 Ofrom datetime import datetime* J  Y- w# @& ~
    import pandas as pd/ B% b8 q/ \2 r3 {  t- u2 Z
    from pandas import DataFrame
      N9 p3 e% n, Lfrom sklearn.preprocessing import LabelEncoder,MinMaxScaler( g- t5 f, I& C+ x! F6 V
    from sklearn.metrics import mean_squared_error
    9 B2 H3 n, b% z- o3 O1 T% Afrom keras.models import Sequential
    - C$ F6 X$ K" r" qfrom keras.layers import Dense, Dropout  y  m  F+ {! J" _
    from keras.layers import LSTM
    $ U" O$ K' Y& B" H3 N1 A3 dfrom keras.layers.recurrent import SimpleRNN
    # j+ \4 @6 R5 _: \# {$ }+ Ifrom numpy import concatenate
    % E% b" q2 Z" F0 a+ _! Lfrom math import sqrt. D2 k# u) o( ]9 R$ l: |( Q* @
    ) C0 {& T0 g4 k$ L, L
    # M2 X, b  c: l. \. g5 X! s
    5 G- }. _8 s! _( L9 m, U/ {7 k

    4 d* `. \% E  n7 {1 l5 x6 \# load data8 Z- _( M  ^; q9 d
    def parse(x):. p, M) K  B# e+ ~6 n
            return datetime.strptime(x, '%Y %m %d %H')* |4 J5 O- a* u3 o- ?0 D
    9 _+ Z# _, p" ]. d! F5 \
    def read_raw():0 B$ a+ D7 v; Z" D  B! _9 I
        dataset = pd.read_csv('raw.csv',  parse_dates = [['year', 'month', 'day', 'hour']], index_col=0, date_parser=parse)
    8 Z; n" W- E) F" }( _1 q8 O# s& |. a    dataset.drop('No', axis=1, inplace=True): h( s9 p' t4 b7 o9 q  U3 B
        # manually specify column names9 _+ [' U+ p% D0 k9 a6 m- n2 _% H
        dataset.columns = ['pollution', 'dew', 'temp', 'press', 'wnd_dir', 'wnd_spd', 'snow', 'rain']0 w" q- g* W+ x! m: k+ q9 x
        dataset.index.name = 'date'9 Y; S  i3 M$ A5 \* X  J; |# p: H/ ^
        # mark all NA values with 02 k8 M$ t8 q/ `3 H% e+ M  r
        dataset['pollution'].fillna(0, inplace=True)0 D" {- j$ c- V
        # drop the first 24 hours
    - P6 t- m2 M" J7 P    dataset = dataset[24:]
    . t4 W; Q! V9 a: K/ A3 z1 ?& @    # summarize first 5 rows
    1 p8 b0 H3 h( e4 \    print(dataset.head(5))) }+ V0 I: x/ t% G
        # save to file' }) n1 Z4 ~9 T2 i% ~
        dataset.to_csv('pollution.csv')! L& c: o% e7 l+ f2 ]8 o( g+ x  S; e

    6 i% a; `' s( U7 Y7 @

    2 g. j, M- B/ X, R! W2 w0 y- f/ o+ ~5 f" O. d  f( E3 }
    6 P$ F+ T% O0 }4 f5 x$ K
    # convert series to supervised learning$ M  p6 c( _3 V+ _1 ?! P
    def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):# v( ]7 j' U# X1 U" G2 N( |
        n_vars = 1 if type(data) is list else data.shape[1]
    ) B8 x- T1 A' {9 R" o/ ~0 B    df = DataFrame(data)  D( X. y7 B- Y3 i3 C( [
        cols, names = list(), list()
    3 H* |4 v9 U' A9 V) s( Q    # input sequence (t-n, ... t-1)9 s# q& A! m) q; d
        for i in range(n_in, 0, -1):
    + n9 Y; n/ v, p: |* z/ a        cols.append(df.shift(i)). `' m) |4 V/ s3 Z/ T! I% @' L
            names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
    % _2 U# Y1 F! `9 I/ M5 i7 J    # forecast sequence (t, t+1, ... t+n)+ T4 I+ L8 S0 Q( P0 I
        for i in range(0, n_out):6 y9 o2 i1 f/ M, t/ `
            cols.append(df.shift(-i)): w% S6 Z  `$ X  j1 E7 A# w# n9 ?* v$ O
            if i == 0:
    / |$ S* k3 N. p% p; L7 `            names += [('var%d(t)' % (j+1)) for j in range(n_vars)]! B$ v& X; a) \, ]
            else:
    3 N1 S3 d3 Y# d: \5 g            names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
    8 F& F4 W2 j; J5 f1 n( k    # put it all together
    - K: {, s$ p1 j. ]) k" `0 D' q    agg = pd.concat(cols, axis=1)
    & Y" E, G; n9 f2 e# }, s* ?    agg.columns = names
    9 m, {' ?+ V% t+ ?5 p$ b# l    # drop rows with NaN values
      a8 x0 f5 w7 S* F. J; Y% z/ v2 w    if dropnan:
    & |9 R6 a$ t* K* a3 U7 m! Q        agg.dropna(inplace=True)" w6 D3 v5 o7 R- T; ?1 y
        return agg0 O! H% w/ Y$ W

    4 m1 @- n) v) }* N# load dataset+ q8 R8 c7 a) e% E
    dataset = read_csv('pollution.csv', header=0, index_col=0)
    5 Y/ o0 P( \) B' T- Hvalues = dataset.values4 L7 q- a3 v6 d8 U# x

    8 Z/ d: I1 ~+ |& U: M
    9 f8 X$ P( D9 g; F7 V; J
    # integer encode direction
    - U0 m& ~5 H7 U- T6 vencoder = LabelEncoder()( Q! q: p* A4 \5 L
    print(values[:,4])
    ' {: h: K* _+ u4 |values[:,4] = encoder.fit_transform(values[:,4])5 i$ j8 b5 j* Z5 \% S" r( e  F
    # ensure all data is float
    7 B: M3 o# X1 W; Q+ }values = values.astype('float32')
    ' ]3 i1 {6 f8 {$ z: p* E' e. p# normalize features
    0 h7 a) {% a3 u* z9 Vscaler = MinMaxScaler(feature_range=(0, 1))
    0 U8 J. o+ I' K+ l9 |# L3 H0 K5 Nscaled = scaler.fit_transform(values). C  m  h; g1 t8 o
    # frame as supervised learning
    ! w3 M4 i. P4 xreframed = series_to_supervised(scaled, 1, 1)
    . u# z. P# r0 b; Y4 ?& K# h2 v+ [#reframed = series_to_supervised(scaled, 3, 1) #用前3天的数据,预测当天的数据# X$ G( }2 M' h# u% Q4 D6 x
    print("columns:", reframed.columns), f, x' `& T6 z* x" p$ H
    # drop columns we don't want to predict
    9 E7 U* ^; ~6 p8 q+ G, \$ [* U/ [reframed.drop(reframed.columns[[9,10,11,12,13,14,15]], axis=1, inplace=True) #用前1天的数据,预测当天的数据2 T. I3 B- ?; D2 L3 b- c
    #reframed.drop(reframed.columns[[25,26,27,28,29,30,31]], axis=1, inplace=True)#用前3天的数据,预测当天的数据, L( {+ d$ h3 T7 ^/ f5 G
    print(reframed.head())
    + y! {$ I* P  e1 y# f$ b$ qprint("new columns:", reframed.columns)
    1 o! r7 A; g" g# split into train and test sets
    1 G9 q# T4 v( Jvalues = reframed.values
    7 ^, }3 S* T6 P# Jn_train_hours = 365 * 24
    " D2 B9 _- R; p5 D  atrain = values[:n_train_hours, :]& B8 E- b/ n' H+ Y
    test = values[n_train_hours:, :]1 \3 z- g: @9 q' L
    # split into input and outputs. B5 F" B) u) F
    train_X, train_y = train[:, :-1], train[:, -1]
      E% p& d" H( Q# vtest_X, test_y = test[:, :-1], test[:, -1]
    ; t6 a# D1 J3 m& B# reshape input to be 3D [samples, timesteps, features]; G9 B- R8 z. l
    #使用Dense()模型时不用变换
    " a7 B# j  x8 O) j3 M9 Q1 x. J8 |train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
    # f! u0 o" p6 C1 ~. s( d* p+ W' ytest_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
    & w+ e% C3 D  ]. cprint(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
    3 @  [* V! b  l2 d5 ^( J# design network
    6 D5 K$ |/ l! F2 z+ k, a, bmodel = Sequential()
    % G3 Q1 n. e2 J$ z) y5 O1 C) S#model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2]))), B5 V- G3 l6 j2 S0 p& G  c- B% b/ |
    #model.add(Dense(50, activation='relu', input_dim = 8))& n! ~1 |2 ?1 f* f' x$ d
    model.add(SimpleRNN(50, input_shape=(train_X.shape[1], train_X.shape[2])))) t8 X' U& o4 W, R, C( s
    model.add(Dense(1))
    ! ^" d+ [, @( w2 J5 N, Hmodel.compile(loss='mae', optimizer='adam'): ^5 x- y! {+ d* c" i4 N$ c8 D
    # fit network
    8 A( D9 C% H9 o: Y8 ?: Shistory = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
    4 h' L' j+ H. Y2 O& b9 G8 ]5 a# make a prediction. P& x( m  Y( G0 J: U( j0 p
    yhat = model.predict(test_X)8 q1 h$ e: [: L4 l; }  B- S
    print("yhat shape:", yhat.shape): i) g( E8 J+ j. m2 o- F5 y
    '''3 s% P0 ^# r2 j& D; o
    计算在测试集上的均方差2 {3 t0 r- S2 @, r0 Y+ Z8 `3 R. D
    test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))8 _) _' M8 U: G% j. `# |3 n
    print("test_X shape:", test_X.shape). r/ b4 k9 D. m$ H3 P

    & P1 l* O9 w& s3 `; P) i/ }
    ) r/ c% ~5 b) C. h. k# ?8 o
    # invert scaling for forecast
    " X4 w$ ]3 Q6 E6 p" yinv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1). [9 i) Z$ m% ~" H* f+ |( S
    inv_yhat = scaler.inverse_transform(inv_yhat)
    , |# }8 R7 R& h! g6 ?# L+ L  hinv_yhat = inv_yhat[:,0]
    # z) T4 n& k  r/ I0 }# invert scaling for actual
    # I3 [% Y+ b: I9 c- r# Q- ^, n. ttest_y = test_y.reshape((len(test_y), 1))6 C! f* b: t- [. v# H& B) {5 `
    inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)- t+ B& L4 x2 a: w8 p$ a7 Z/ L2 B; P
    print("inv_y:", inv_y[:10])
    ( H6 ^% Y. ^' I2 Iprint("inv_y shape:", inv_y.shape)
    ! _& ^5 d$ |# F( N- @! y; G( ]! O% q: `4 d5 [7 c* b1 S
    ! V& `* {7 Z1 A8 _
    inv_y = scaler.inverse_transform(inv_y)9 |$ P' y0 x+ l3 ]9 p
    print(inv_y, "*"*30)
    % u6 Z5 g, h1 _+ }3 A$ @2 ]  I
    0 g7 d" n) _1 y6 [1 B

    $ f+ h4 V* q$ U* v+ Zinv_y = inv_y[:,0]/ c% n  U  X! \
    # calculate RMSE( D$ ^" b( n  i3 r+ V( `" |; T& G
    rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
    ) Y5 z' o7 _1 B0 ^print(inv_y[:100], inv_yhat[:100])! H, b! M$ P6 h6 @
    print('Test RMSE: %.3f' % rmse)
    / F$ Z6 b& `. a# ?2 }8 F
    ) _4 d4 |, [: G) i4 n' M5 f) [
    ) k8 R0 m' E& B0 P" z" v: d
    '''
    $ ^. c8 b7 q8 s, J实验结果
    $ R1 H! d4 v$ M
    实验1:用前一天的天气数据,预测某一天的空气质量
    ; O; g$ j( g& g* U3 s# M使用LSTM模型
    % Y* t" m, Z) P. s: V  X+ a+ k结果:
    0 y/ D) Y! f4 F2 i8 Q$ q7 P, E7 wEpoch 49/50+ C/ J: G' ]2 {% X; k2 ?( b" t
    0s - loss: 0.0144 - val_loss: 0.01339 a& P1 i' X& C. P9 W# A  z
    Epoch 50/50
    7 \* t! G  ~( w9 M9 G0s - loss: 0.0144 - val_loss: 0.0133
    : s1 M' p6 _: [' X" O3 E
    3 l# t& y7 h# o7 m( s
    ! A1 Y, q. V8 h  s+ Q5 Y% [
    实验2:用前3天的天气数据,预测某一天的空气质量
    ( G2 K" z/ J: B( t: m7 j使用LSTM模型1 c+ m# H  `) |+ }" V3 {, O: G; N

      B' P  r* Q4 M
    9 c# e% i6 |% y
    结果:
    " ]2 i8 B$ }* M+ j* BEpoch 49/50
    & ~9 L) k) ^9 U2 l- a  t0s - loss: 0.0147 - val_loss: 0.0149
    ' t5 Z; `, Y  M8 nEpoch 50/50
    5 k, \2 G- q) T( {1 Z, W1 w0s - loss: 0.0147 - val_loss: 0.0150$ q6 ^" v4 ]' c, |% I" g

    9 w; g( M- T& N; d. U( b

    8 A. e* @; s' {  M6 h- T1 H实验3:用前一天的天气数据,预测某一天的空气质量
    ! {3 ~" f2 S: [1 q0 b& q4 s使用普通的全连接模型 Dense(): R. E# }8 N2 `+ A/ r
    结果:& q8 f5 |" r# z9 W4 i- o: P
    Epoch 49/50" m- c+ M; m* j  P
    0s - loss: 0.0144 - val_loss: 0.0146
    - q; _! M  X# ]Epoch 50/50
    * N6 [6 S! N: X2 @0s - loss: 0.0148 - val_loss: 0.01511 X$ a: l2 [# v( |5 M0 c

    # a: T/ q4 f7 p. f

    3 q! ~6 }, ]) V# |# D& m" @/ N! y实验4:用前三天的天气数据,预测某一天的空气质量% n" J+ Y1 t- Q# [' j" O9 O* h
    使用普通的全连接模型 Dense(), P# g/ v$ O  h# [$ O
    结果:
    $ c! x8 T4 A* R* X: k2 LEpoch 49/50  p4 ~( |" ^# y) Q0 i( b7 x' y
    0s - loss: 0.0150 - val_loss: 0.01653 p  V3 }% n. h  s
    Epoch 50/507 d, j1 B8 ?8 c& ~$ p2 |1 N4 g
    0s - loss: 0.0148 - val_loss: 0.0141( }9 w* k. M2 f7 K( r$ T! A
    6 `2 r" \5 T4 \0 M& v/ P9 E

    4 E" r. a' G$ r5 X9 [$ ~! C实验5:用前一天的天气数据,预测某一天的空气质量
    ! w/ }7 u# @) R% Z' e4 o# S使用SimpleRNN$ _: N  i% H- i# X
    Epoch 49/50
    # i, u; o; J% u' S0s - loss: 0.0160 - val_loss: 0.0140
    1 J) \  z( Y/ U% y) I) _Epoch 50/508 u+ C: ^) k$ \1 ~$ h% o9 N5 L
    0s - loss: 0.0147 - val_loss: 0.0150
    ) |( i  L9 c! y& I6 d9 F1 b7 Y. N1 N; W4 c& Y# l5 W

    * U' n; i4 I* r3 ?3 t实验6:用前三天的天气数据,预测某一天的空气质量
    ( C3 f/ m( R! ]使用SimpleRNN4 l8 U( O6 _. U5 \; i; |1 O
    Epoch 49/50
    . ?  c  L& f3 W2 K- b/ A$ b: k0s - loss: 0.0164 - val_loss: 0.0233* f& C+ I7 V! `+ J9 I3 R4 @
    Epoch 50/50
    1 G4 u0 g% g7 W! a0s - loss: 0.0166 - val_loss: 0.0227
    ; N$ x! S/ {+ y3 Z5 D3 ^RNN和DNN的区别

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

    8 E( P3 E* o) v5 j, N; T
    # Q, @3 ?7 e! T2 n; j( B
    + w; G: J7 g  C6 X  u- a+ ]
    RNN和LSTM的区别
    9 }2 T1 x) R0 i  S# B! R% XLSTM的内部结构通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。
    - X& r9 N5 `3 ^7 Y/ `8 M' x
    4 H9 n" n$ W! G# v& p1 E

    ( p  C2 t( O( i2 g$ h: s6 ~但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。
    * Q$ I7 o, f  w% p- Q( ~! v+ O6 ~- v, `

    ; S& n  ~# B1 n请关注数学中国微博和数学中国公众号,如有疑问联系数学中国工作人员

    # n# e6 u# N' J2 W% w- ?) b! v; [1 R! f$ m  W5 l+ T* ?

    + H6 o' T) v8 \0 g, i
    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-6-12 01:23 , Processed in 0.602651 second(s), 57 queries .

    回顶部