1. 程式人生 > >Keras中卷積LSTM的使用

Keras中卷積LSTM的使用

       Keras官方自帶了很多實用的模型教程,地址在https://github.com/keras-team/keras/tree/master/examples,這裡主要是conv_lstm.py的基礎上進行了一定修改,來實現一個非常簡單的運動預測模型。

       首先匯入庫函式:

from keras.models import Sequential
from keras.layers import Dropout
from keras.layers.convolutional import Conv3D
from keras.layers.convolutional_recurrent import ConvLSTM2D
from keras.layers.normalization import BatchNormalization
import numpy as np
import pylab as plt

       之後可以開始架網路了。個人覺得卷積LSTM對於圖片序列中每一張圖片的處理可以等效於卷積層,同時具備LSTM對序列資訊的處理能力。網路其他結構的處理和一般的卷積神經網路基本相同,因為網路是對序列中各圖片進行依次處理。網路結構如下:

seq = Sequential()
seq.add(ConvLSTM2D(filters=16, kernel_size=(3, 3),
                   input_shape=(None, 16, 16, 1),
                   padding='same', return_sequences=True))
seq.add(BatchNormalization())
seq.add(Dropout(0.3))

seq.add(ConvLSTM2D(filters=32, kernel_size=(3, 3),
                   padding='same', return_sequences=True))
seq.add(BatchNormalization())
seq.add(Dropout(0.3))

seq.add(ConvLSTM2D(filters=32, kernel_size=(3, 3),
                   padding='same', return_sequences=True))
seq.add(BatchNormalization())
seq.add(Dropout(0.5))


seq.add(Conv3D(filters=1, kernel_size=(3, 3, 3),
               activation='sigmoid',
               padding='same', data_format='channels_last'))
seq.compile(loss='binary_crossentropy', optimizer='nadam')
seq.summary()

       可以看到就是把常規的卷積網路中Conv2D換成ConvLSTM2D,其他的區別不大。

       之後按照官方提供的方法生成資料,這裡相比官方文件把影象縮小,並且不生成噪聲資料,方便處理了:

def generate_movies(n_samples=1200, n_frames=15):
    row = 32
    col = 32
    shifted_movies = np.zeros((n_samples, n_frames, row, col, 1),
                              dtype=np.float)

    for i in range(n_samples):
        # Add 3 to 7 moving squares
        n = np.random.randint(3, 8)

        for j in range(n):
            # Initial position
            xstart = np.random.randint(8, 24)
            ystart = np.random.randint(8, 24)
            # Direction of motion
            directionx = np.random.randint(0, 3) - 1
            directiony = np.random.randint(0, 3) - 1

            # Size of the square
            w = np.random.randint(2, 4)

            for t in range(n_frames):
                x_shift = xstart + directionx * t
                y_shift = ystart + directiony * t
                
                x_shift = xstart + directionx * (t + 1)
                y_shift = ystart + directiony * (t + 1)
                shifted_movies[i, t, x_shift - w: x_shift + w,
                               y_shift - w: y_shift + w, 0] += 1

    shifted_movies = shifted_movies[::, ::, 8:24, 8:24, ::]
    shifted_movies[shifted_movies >= 1] = 1
    return shifted_movies

shifted_movies = generate_movies(n_samples=1200)

       之後用生成的前1000組資料作為訓練集,後200組作為測試集。每組資料的前10幀作為已知的輸入,6~15幀作為需要預測的輸出,對網路進行訓練:

seq.fit(shifted_movies[:1000, 0:10], shifted_movies[:1000, 5:15], batch_size=10,
        epochs=20, validation_split=0.05)

       訓練完成之後,檢視網路在測試集上的表現即可:

y_pred = seq.predict(shifted_movies[1000:, 0:10])

       該網路對測試集的預測結果如下所示:

輸入資料:

真實輸出:

預測輸出:

       可以看到,網路輸出結果與真實結果之間差別不大,基本能夠實現對運動狀態的預測。
       當然,在實際應用時,完全可以對視訊流中每一張圖片首先使用卷積神經網路提取出特徵圖,再用特徵圖對卷積LSTM進行學習,通過輸出的特徵圖來反推出目標的位置即可。