卷積神經網絡處理文本序列

我們之前討論了卷積神經網絡,從局部可以提取出特徵,用於小貓小狗的圖片識別處理,非常有效;也討論了循環神經網絡進行文本的處理,因爲文本的順序是順序相關的。基於以上特點,我們把時間或者說文本的前後看做一個維度,那一段文本就是一個一維空間,相比圖片的二維空間,變得更加簡單了,那捲積神經網絡是否可以處理這樣的情況呢?

先亮出結論,答案是肯定的。圖片是二維的數據,文本是一維的數據,因此我們可以對訓練的神經網絡進行簡化,讓網絡去提取一維的特徵。既然如此,一維神經網絡與二維的神經網絡是類似的,因此我們可以把二維卷積神經網絡的特性遷移到一維的卷積神經網絡上。

我們在討論神經網絡的時候,我們知道了卷積神經網絡具有平移不變性,非常好的特性,這個特性可以抓住問題的關鍵,識別出特殊的特徵。在一維的卷積神經網絡(用到的方法:Conv1D)中,一小段文本所具有的特性,進行學習後,在文本的其他位置仍然可以被識別出來。可以這樣理解,一句話在開頭說與在結束的時候說,表達的感情應該是一致的,效果也是一樣的(絕大多數情況下),這就是文本的平移不變性。

同樣的,在處理圖片的時候,爲了防止數據量過大,防止過擬合,我們需要進行池化的操作,在一維的神經網絡中,我們也需要進行池化操作(用到的方法:MaxPooling1D)。

說到這裏,大概的主要內容我們就說完了,比較簡單,我們該舉一個例子了,我們還用之前用到的 IMDB 評論情感分析的數據集,看看效果怎麼樣,老規矩,看看結果然後最後給出完整代碼:

驗證

損失

我不知道你是否實踐了我前面所有的代碼,如果你實踐了,你可能知道在最近的循環神經網絡的執行時間有的超過了一小時(之前的 LSTM),確實太慢了,這是循環神經網絡的弊端。這個網絡幾分鐘就完成了,並且我們看到在第四次左右就開始過擬合了,因此其實只需要訓練四次這個網絡就可以了,並且我們發現相比 LSTM 的準確率下降的幅度非常小,是可以接受的範圍,因此這個網絡有其獨特的優越性。下面看代碼,注意,代碼後面還有非常重要的內容。

#!/usr/bin/env python3
​
import time
​
import matplotlib.pyplot as plt
from keras import layers
from keras.datasets import imdb
from keras.models import Sequential
from keras.optimizers import RMSprop
from keras.preprocessing import sequence
​
​
def imdb_run():
    max_features = 10000
    max_len = 500
    (x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
    x_train = sequence.pad_sequences(x_train, maxlen=max_len)
    x_test = sequence.pad_sequences(x_test, maxlen=max_len)
​
    model = Sequential()
    model.add(layers.Embedding(max_features, 128, input_length=max_len))
    model.add(layers.Conv1D(32, 7, activation='relu'))
    model.add(layers.MaxPooling1D(5))
    model.add(layers.Conv1D(32, 7, activation='relu'))
    model.add(layers.GlobalMaxPooling1D())
    model.add(layers.Dense(1))
    model.summary()
    model.compile(optimizer=RMSprop(lr=1e-4), loss='binary_crossentropy', metrics=['acc'])
    history = model.fit(x_train, y_train, epochs=10, batch_size=128, validation_split=0.2)
​
    # 畫圖
    acc = history.history['acc']
    val_acc = history.history['val_acc']
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    epochs = range(1, len(loss) + 1)
    plt.plot(epochs, acc, 'bo', label='Training acc')
    plt.plot(epochs, val_acc, 'b', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend()
    plt.show()
    plt.figure()
    plt.plot(epochs, loss, 'bo', label='Training loss')
    plt.plot(epochs, val_loss, 'b', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend()
    plt.show()
​
​
if __name__ == "__main__":
    time_start = time.time()
    imdb_run()
    time_end = time.time()
    print('Time Used: ', time_end - time_start)

我們知道卷積神經網絡是用於提取特徵的,準確點說是用於提取局部特徵的,因此對於這種文本序列,能提取一小段序列的特徵,範圍無法過長,這是它的一點侷限性,循環神經網絡的優勢是能獲取較長範圍內的關聯性,那如何將這兩者的優勢結合起來,即可以在較長範圍內將其關聯起來,又可以有一個比較好的訓練速度呢?

沒錯,就是將兩者結合起來,這是個大招,首先用一維卷積神經網絡去提取特徵,然後將提取出的特徵用循環神經網絡將前後相關聯,這既能減少數據量,又能兼顧前後的聯繫,非常高級的用法。

image

網絡結構類似於這種:

model = Sequential()
model.add(layers.Conv1D(32, 5, activation='relu',input_shape=(None, float_data.shape[-1])))
model.add(layers.MaxPooling1D(3))
​model.add(layers.Conv1D(32, 5, activation='relu'))
model.add(layers.GRU(32, dropout=0.1, recurrent_dropout=0.5))
model.add(layers.Dense(1))

本篇討論的問題是將一維卷積神經網絡用於文本序列的處理,就到這裏,文本的處理也將算是告一段落,接下來後續的文章將討論一些其他的問題。

  • 本文首發自微信公衆號:RAIS
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章