RNN和LSTM初級配方煉丹對比實驗(Keras)

RNN和LSTM初級配方煉丹對比實驗(Keras)

參考教程:

一、莫煩大佬的教程:
https://morvanzhou.github.io/tutorials/machine-learning/keras/2-4-RNN-classifier/
二、《21個項目玩轉深度學習-基於TensorFlow的實踐詳解》
其實概念性的理解,個人覺得,還是得看看書,雖然很多人(包括我)也詬病一些中文書就知道翻譯,但是有些書在入門階段,作爲完整、快速的理解一門新的知識,真的是最佳的手段了。
有些書就包括這本。

前言

還是得扯扯有的沒的,目前我知道的幾個主要的深度學習分支如下:
後面的幾個經典算法,我沒完全跟的上,簡單寫了一些。
在這裏插入圖片描述
所以發現,這四個大方向,是很有趣的。
作爲一個智能體,需要哪些功能,才能完成一個比較健全的任務呢?
感知、記憶、決策、自我意識等功能都應該得有吧?
計算機視覺一般主要用作提取特徵,作爲視覺感知模塊;
循環一般主要用作時間序列,可以處理像語言、股票等時序任務,也算是一種記憶感知,其實我現在一直不明白,有什麼樣的網絡可以實現:這件東西我曾經見過的!這件東西是啥?的功能,感覺傳統的分類網絡應該不算,或者最後的輸出結構不應該是那樣的,直接預測出是什麼種類,應該還得有一些其他的類似於人認知的功能,比如結合知識圖譜?;
強化學習的前端是全連接,或者是卷積,那麼是用到了計算機視覺的感知功能。最重要的部分其實是後面的決策模塊(可以理解爲actor最後面的全連接層,或者加上critic對actor的更新),基於當前感知做決策,以及根據環境反饋,對actor決策進行更新的critic。這樣就完成了決策任務了。
生成對抗網絡我不太熟悉,所以我就無法描述了,但是今天在“逆強化學習”的課程中,李宏毅老師說,其實inverse reinforcement learning的frame跟gan的就很像很像,所以感覺思路都是交叉的。如果要想在這方面深耕的話,是沒有辦法只關注於一個領域的。
畢竟智能需要各方面的整合才行。

OK,那麼說說我爲啥要學RNN。
RNN太重要了呀,強化學習處理的本來就是時序問題,雖然通過整個結構的循環可以處理一些時序的問題,但是如果能直接在感知部分直接提取時序相關的信息,豈不是更合適?
之前那篇自我感知的小機械臂用的就有一個循環感知的過程,直接提取連續五步的狀態。
所以還是得學習一下的。

RNN的基礎知識

這個比較坑,今天就不在博客上說了,大家可以自己搜一些其他的資料;
或者直接去看那本書。

實驗部分:

實驗描述:

將mnist數據集分爲28*28.第一個28爲time_step,第二個是輸入數據向量維度爲28.
大致的效果是將一張這樣的圖:

從上往下拆分,每次只輸入RNN網絡中一行的數據,分28步輸入進去。
然後通過RNN網絡的權重進行計算後,輸出的維度爲隱層數。

最後將最後一步的輸出接上全連接網絡,再接softmax,進行分類預測。
LSTM的輸入輸出模型差不多,內部細節可以另看其他資料。

數據集:

Mnist數據集

LSTM-40-mnist-Code:

import numpy as np
np.random.seed(1337)

from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense, SimpleRNN, Activation
from keras.optimizers import Adam
TIME_STEPS = 28
TIME_INPUT_SIZE = 28
BATCH_SIZE = 32
BATCH_INDEX = 0
OUTPUT_SIZE = 10
CELL_SIZE = 40
LR = 0.001

(x_train,y_train),(x_test,y_test) = mnist.load_data()
# data pre-processing
x_train = x_train.reshape(-1, 28, 28) / 255.      # normalize
x_test = x_test.reshape(-1, 28, 28) / 255.        # normalize
y_train = np_utils.to_categorical(y_train, num_classes=10)
y_test = np_utils.to_categorical(y_test, num_classes=10)
print(x_train.shape)
print(y_train.shape)
model = Sequential()

model.add(SimpleRNN(
    batch_input_shape=(None, TIME_STEPS, TIME_INPUT_SIZE),
    #     output_dim是隱層節點數目,控制了網絡的擬合能力和每次狀態輸出的維度!
    output_dim=CELL_SIZE,
    unroll=True,
))

model.add(Dense(OUTPUT_SIZE, activation='softmax'))

adam = Adam(LR)
model.compile(optimizer=adam, loss='categorical_crossentropy', metrics=['accuracy'])

import time
import matplotlib.pyplot as plt
train_cost = []
train_accuracy = []
test_cost = []
test_accuracy = []

start_time = time.time()
for step in range(4001):
    x_batch = x_train[BATCH_INDEX: BATCH_INDEX+BATCH_SIZE, :, :]
    y_batch = y_train[BATCH_INDEX: BATCH_INDEX+BATCH_SIZE, :]
    cost, accuracy  = model.train_on_batch(x_batch, y_batch)
    train_cost.append(cost)
    train_accuracy.append(accuracy)

    BATCH_INDEX += BATCH_SIZE
    if BATCH_INDEX >= x_train.shape[0]:
        BATCH_INDEX=0
    if step%50==0:
        print("step:", step)
        print("cost:", cost)
        cost,accuracy = model.evaluate(x_test, y_test, batch_size=y_test.shape[0], verbose=False)
        test_cost.append(cost)
        test_accuracy.append(accuracy)
        print('test cost: ', cost, 'test accuracy: ', accuracy)
        
print("epoch_time:",(time.time()-start_time)/4001)

plt.figure(num = 1)
plt.ion()

plt.xlabel('epoch')
plt.ylabel('loss and accuracy')

plt.plot(train_cost, label = "loss")
plt.plot(train_accuracy, label = "accuracy")
plt.legend(loc = "best")

plt.show()

plt.figure(num = 2)
plt.ion()

plt.xlabel('epoch')
plt.ylabel('loss and accuracy')

plt.plot(test_cost, label = "loss")
plt.plot(test_accuracy, label = "accuracy")
plt.legend(loc = "best")
plt.show()        

實驗內容:

測試LSTM和simpleRNN對精度和時間的影響。
以及隱層節點數變化對精度和時間的影響。
猜想:LSTM更強。時間也長一些。
節點數越多,精度越高

實驗結果:

LSTM-80
test cost: 0.11618449538946152
test accuracy: 0.9639999866485596
epoch_time: 0.04046541754825805

LSTM-40
test cost: 0.20324485003948212
test accuracy: 0.9412999749183655
epoch_time: 0.04428503430506433

Epoch=4001/lr=0.001 RNN-40 RNN-80 LSTM-40 LSTM-80
Test cost 0.3496 0.208 0.203 0.1162
Test accuracy 0.9036 0.943 0.9412 0.964
Epoch time 0.0101 0.0104 0.0443 0.0404

表格分析:

由上面的表格可以看出來以下幾點:

  • simpleRNN的訓練時間確實要少很多,是LSTM的四分之一。

  • 但是cell_size對訓練的時間影響並不大。

  • 另外可以看出來LSTM的訓練精度確實比simpleRNN要好一些。

  • 在同樣的節點數40時,精度提高了四個點,節點數80時上升2個點。

  • 節點數對精度的提升也很明顯,simpleRNN中40-80的差距是4個點,LSTM的40-80的差距是2個點。

但是可以從訓練過程中可以看出,精度和loss的波動比較大。如下圖——

訓練過程記錄

lstm-40-train-accuracy-loss-graph-epoch-40001
在這裏插入圖片描述

lstm-40-test-accuracy-loss-graph-epoch-40001
這裏的epoch-80是不對的,因爲每50個train-epoch才測試一次,因此下面的每個epoch數字需要做一個變換。
也許每個train-epoch都測試的話,可能波動也比較大了。
在這裏插入圖片描述
好了,我又跑了一遍,發現波動性確實蠻大的:
但是大概的趨勢還可以,是不是跟優化策略有關?我試試其他的?
在這裏插入圖片描述

SGD-不收斂

只將優化器換成了SGD,學習率都沒變,仍然是0.001。那就只能再整一下,加點動量。

在這裏插入圖片描述
在這裏插入圖片描述

SGD加動量和牛頓什麼的

加了動量=0.9和牛頓=true之後,可以達到下面的效果:
test cost: 0.9125387668609619 test accuracy: 0.7081999778747559

在這裏插入圖片描述

在這裏插入圖片描述

SGD加動量不加牛頓~

test cost: 0.9364890456199646 test accuracy: 0.7028999924659729
epoch_time: 0.1839553209818235

在這裏插入圖片描述
在這裏插入圖片描述

反正SGD確實沒有Adam好,至少在這個任務,這個數據集下,是這樣的~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章