# 深度學習 04:RNN/LSTM ###### tags: `Deep Learning` RNN: ![](https://i.imgur.com/OB2tyJI.jpg) LSTM: ![](https://i.imgur.com/HBhyszD.jpg) <br> RNN正向傳播公式: <font size=5>$$h_{t} = tanh(h_{t-1}W_h+X_tW_x+b)$$</font> RNN 為下圖左邊的,右邊是為了理解展開後的圖 ![](https://i.imgur.com/SWuQ47L.png) ```python= tf.keras.layers.RNN( cell, return_sequences=False, return_state=False, go_backwards=False, stateful=False, unroll=False, time_major=False, **kwargs ) ``` [tf.keras.layers.RNN](https://www.tensorflow.org/api_docs/python/tf/keras/layers/RNN) 內輸入的參數是 cell,是一個 class,不是 units,不可帶數字。 [tf.keras.layers.SimpleRNNCell](https://www.tensorflow.org/api_docs/python/tf/keras/layers/SimpleRNNCell)\[tf.keras.layers.LSTMCell](https://www.tensorflow.org/api_docs/python/tf/keras/layers/SimpleRNNCell) 為 cell 的一種,參數是 units,代表隱藏層神經元數量。 更新權重是一個 batch 平均 然後一起更新。 --- ## 預測時間序列 <font color="#f00">**RNN 的 input_shape 通常是 [批次大小, 時間維度, 特徵維度]**</font> ![](https://i.imgur.com/CPNbxwr.png) --- ### 預測一個值 1. **Baseline** ![](https://i.imgur.com/B5UgBCJ.png) ```python= np.random.seed(42) tf.random.set_seed(42) model = keras.models.Sequential([ keras.layers.Flatten(input_shape=[50, 1]), keras.layers.Dense(1) ]) model.compile(loss="mse", optimizer="adam") history = model.fit(X_train, y_train, epochs=20, validation_data=(X_valid, y_valid)) ``` MSE = 0.02 2. **簡單 RNN** ![](https://i.imgur.com/zILCylM.png) ```python= model = keras.models.Sequential([ keras.layers.SimpleRNN(1, input_shape=[None, 1]) ]) ``` MSE = 0.014 一共 $W_h$、$W_x$、$b$ 三個參數。 3. **深層 RNN** ![](https://i.imgur.com/ic3i4PT.png) ```python= model = keras.models.Sequential([ keras.layers.SimpleRNN(20, return_sequences=True, input_shape=[None, 1]), keras.layers.SimpleRNN(20), keras.layers.Dense(1) ]) ``` MSE = 0.003 **return_sequences=True** 代表輸出一個 3D array(包含所有時間維度的輸出),若無此參數,將只會輸出一個 2D array(只包含最終時間維度的輸出)。 --- ### 預測多個值 1. **循環預測** ![](https://i.imgur.com/Nb2wS55.png) 將訓練好的深層 RNN 模型預測下一個值,再將那個值加到輸入,並再利用這個模型預測接下來的值,以此類推。 ```python= series = generate_time_series(1, n_steps + 10) X_new, Y_new = series[:, :n_steps], series[:, n_steps:] X = X_new for step_ahead in range(10): y_pred_one = model.predict(X[:, step_ahead:])[:, np.newaxis, :] X = np.concatenate([X, y_pred_one], axis=1) Y_pred = X[:, n_steps:] ``` MSE = 0.029 因為誤差可能會累積,所以預測下個時間特徵通常比循環預測來得準確。 2. **訓練 RNN 同時預測多個值** ![](https://i.imgur.com/kDpQh7S.png) 在最後一個時間特徵預測接下來十個值。 ```python= model = keras.models.Sequential([ keras.layers.SimpleRNN(20, return_sequences=True, input_shape=[None, 1]), keras.layers.SimpleRNN(20), keras.layers.Dense(10) ]) ``` MSE = 0.008 3. **Seq to seq** ![](https://i.imgur.com/CLYxbO6.png) 與其在最後一步預測接下來的十個值,不如在每一步預測接下來的十個值,也就是將 seq-to-vec RNN 轉換成 seq-to-seq RNN($x_0$ -> $y_1$~$y_{11}$ 以此類推)。 ```python= model = keras.models.Sequential([ keras.layers.SimpleRNN(20, return_sequences=True, input_shape=[None, 1]), keras.layers.SimpleRNN(20, return_sequences=True), keras.layers.TimeDistributed(keras.layers.Dense(10)) ]) ``` MSE = 0.006 要將此模型轉換成 seq-to-seq RNN 必須在 Dense 外面包一層 TimeDistributed 層,並在每個時步執行它,它可以將 shape 從 **[批次大小, 時間維度, 輸入維度] 轉換成 [批次大小 x 時間維度, 輸入維度],再經由 Dense 轉回 **[批次大小, 時間維度, 輸入維度]**,雖然 Dense 也能吃 **[批次大小, 時間維度, 輸入維度]**,但如果用 TimeDistributed 層,它只會輸出最後一個時步的十個值。 4. **Conv1D 處理序列** 雖然 LSTM/GRU 比 RNN 能處理更多的序列,然仍難以在 100 個時步以上的序列學習長期模式,如音訊、長句子等。 ![](https://i.imgur.com/CBcFBgj.png) 跟 Seq to seq 不同的是,Seq to seq 是每一個時步預測後十個值,而 Conv1D 是每四個時步組成一個核來預測後十個值。 ```python= model = keras.models.Sequential([ keras.layers.Conv1D(filters=20, kernel_size=4, strides=2, padding="valid", input_shape=[None, 1]), keras.layers.GRU(20, return_sequences=True), keras.layers.GRU(20, return_sequences=True), keras.layers.TimeDistributed(keras.layers.Dense(10)) ]) ``` MSE = 0.006 --- 1. 精通機器學習,使用 Scikit-Learn, Keras 與 Tensorflow-Aurelien Greon 2. Deep Learning:用 Python 進行深度學習的基礎理論實作 - 齋藤康毅 3. [Understanding LSTM Networks](https://colah.github.io/posts/2015-08-Understanding-LSTMs/)