# 嘗試理解LSTM和CNN的結合 [TOC] ## 參考資料 * [Machine Learning Mastery](https://machinelearningmastery.com/cnn-long-short-term-memory-networks/) ## 前景提要 發現LSTM其實並沒有想像中的效果,在學弟的提議下發現了不少人在識別圖片/影片時都會使用CNN+LSTM的技術,因此嘗試寫寫看 ## CNN LSTM Architecture CNN+LSTMs當初是用來希望可以解決下述等問題: * 預測連續圖片(=影片)的結果 * 類似猜劇情之類的東西 * 生成連續圖片(=影片)的文字描述 我們也可以將可處理的問題,整理成三種類型: 1. Activity Recognition: 產生a sequence of images的文本形容 2. Image Descritipn: 產生對於單一圖片的文本形容 3. Video Descritipn: 產生對於連續圖片的文本形容 而CNN+LSTM也可以稱為LRCN (long-term recurrent convolutional network),意旨在LSTM前面接上一CNN。 因為該模型是要生成對圖像的文字描述,所以關鍵就是我們需要一個已經train好的CNN,而該CNN是訓練來分類圖片現在我們可以將它用來提取描述所需要的說明 ``` 此處將CNN用來當作圖片的encoder,並且使用用來分類的CNN的最後一層的hidden layer來當作input 給RNN [出處](https://arxiv.org/abs/1411.4555) ``` 該架構也可以用來處理自然語言的相關處理,使用CNN做為特徵提取氣,並使用LSTM來處理一段聲音和文字類型的input data 講了這麼多,簡而言之,該架構適用於下述的情況: 1. 與空間有關的話: * 2D strucutre or pixels in an image * 1D structure of words in as sentence, paragraph, or ducument 2. 與時間有關的話: * order of images in a video * words in text * require the generation of output with temporal structure such as words in a texual description ## Implement CNN LSTM in Keras 直接使用Keras裡面的CNN和LSTM,並將CNN放在一層的LSTM前面 文章中建議我們可以將該架構直接想成兩個子部分: 1. CNN: 提取特徵工具人 2. LSTM: 嘗試解釋按照時間序的特徵 ### CNN 這邊的CNN先假設input為2D的圖片,因此使用了2D-CNN 且在此範例當中input為10\*10 pixel images with 1 channel ``` python= cnn = Sequential() cnn.add(Conv2D(1, (2,2), activation='relu', padding='same', input_shape=(10,10,1))) cnn.add(MaxPooling2D(pool_size=(2, 2))) cnn.add(Flatten()) ``` ### LSTM CNN一次只能處理一張圖片,但我們現在需要處理是一連串的圖片,所以我們在這使用處理時序性的的LSTM CNN可以使用已經訓練好的模型(像是VGG)來提取圖片裡面的特徵。也可以來自LSTM的backprpogation error來訓練CNN ![](https://i.imgur.com/or4H78H.png) 而在CNN+LSTM的架構當中,我們會希望CNN處理單筆資料,LSTM處理時序性資料。所以我們要想辦法允許CNN一次只收一張圖片,並且依照連續的時間段傳送給LSTM。 如果想要達成上述的效果,我們可以使用TimeDistributed layer將做好的CNN包裝起來,把模型加進該layer就可以。因為該layer的用意就是將同時輸出的data包裝成 ``` python= model.add(TimeDistributed(...)) model.add(LSTM(...)) model.add(Dense(...)) ``` ### CNN LSTM Model 上述已經清楚表達了CNN和LSTM要怎麼處理了,我們現在將他合起來八~ 有兩種分法: 1. 寫完整的CNN之後包進TimeDistributed ``` python= # define CNN model cnn = Sequential() cnn.add(Conv2D(...)) cnn.add(MaxPooling2D(...)) cnn.add(Flatten()) # define LSTM model model = Sequential() model.add(TimeDistributed(cnn, ...)) model.add(LSTM(..)) model.add(Dense(...)) ``` 2. 在寫CNN時每一層都包在TimeDistributed裡面 ``` python= model = Sequential() # define CNN model model.add(TimeDistributed(Conv2D(...)) model.add(TimeDistributed(MaxPooling2D(...))) model.add(TimeDistributed(Flatten())) # define LSTM model model.add(LSTM(...)) model.add(Dense(...)) ```