上篇我們編寫了第一段人工智慧程式碼,它可以識別衣服的款式。今天大家就跟著小編來寫一個人工智慧文字分類的程式碼吧。我們以電影評論為例,一部電影可能有幾萬個網友評論,這些裡面嬉笑怒罵的都有,咱們人看一眼就能大概知道網友的評價是正面的還是負面的,那麼機器如何也能判斷出網友評論是正面的還是負面的呢?這就是我們今天要編寫程式碼解決的問題。
imdb = keras.datasets.imdb(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)
下載資料集
接下來我們先看看資料集裡的資料到底長什麼樣子,我們把訓練集的第一個資料打印出來,可以看到它是一串數字,評論不是應該是一句話嗎?這說明資料集已經做了預處理了,體現的是單詞在字典裡的索引值,這樣便於計算和處理。如果需要看到評論的原文,需要查詢字典,用評論裡的每個單詞索引去查字典,即可得到原始的評論句子。從評論原文看,人眼就可以判斷出是正面的,因為第一句話就說了“everyone's really suited the part”。從train_labels[0]的值為1(表示評論是正面的)可以看到確實如此。
print(train_data[0])print(decode_review(train_data[0]))print(train_labels[0])
train_data[0]資料還原
由於電影裡每個評論句子的長度不一樣,有的網友可能就打出一個“頂”,有的網友感情比較細膩,可能寫了好幾百字的感想。而要機器處理這些資料,都先把他們的長度弄成一樣的。這裡我們使用pad方法對長度進行歸一化處理,大於256的截斷,小於256的用<PAD>予以補齊。執行這段程式碼,我們可以看到每個評論資料已經被補齊為256了。
print("處理前:", len(train_data[0]), len(train_data[1]))print(decode_review(train_data[0]))train_data = keras.preprocessing.sequence.pad_sequences(train_data, value=word_index["<PAD>"], padding='post', maxlen=256)test_data = keras.preprocessing.sequence.pad_sequences(test_data, value=word_index["<PAD>"], padding='post', maxlen=256)print("處理後:", len(train_data[0]), len(train_data[1]))print(decode_review(train_data[0]))
補齊資料
資料處理好後我們就開始建立模型吧,在這裡我們先使用了一個嵌入層,構建詞彙向量表,嵌入層的主要目的是把多維空間轉化為低維空間,讓模型不用佔據太大的記憶體。然後使用一個平均池化層,讓長短不一的輸出向量長度統一為平均長度。第三層我們很熟悉,上篇識別衣服用到了,是構建了一個16個神經元的非線性隱藏層,使用Relu折線式啟用函式。最後一層,使用了Sigmoid啟用函式,輸出一個0~1之間的機率。
# 輸入形狀是用於電影評論的詞彙數目(10,000 詞)vocab_size = 10000model = keras.Sequential()model.add(keras.layers.Embedding(vocab_size, 16))model.add(keras.layers.GlobalAveragePooling1D())model.add(keras.layers.Dense(16, activation='relu'))model.add(keras.layers.Dense(1, activation='sigmoid'))model.summary()
模型構建後,我們就需要編譯模型了,與上篇一樣,我們先使用一個adam最佳化器,它能控制學習速率。然後定義一個損失函式binary_crossentropy,這個損失函式非常適合用來評估機率。最後metrics=['accuracy']我們已經學習過了,它表示用準確率來作為模型追求的衡量指標。
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
然後按道理就可以開始訓練了,但在機器學習泛化篇我們知道,為了更好地控制過擬合,我們可以資料分為訓練集、驗證集、測試集三個集合,這樣能最大限度的去泛化模型。於是,我們就把資料集砍成兩段吧,取一段作為驗證集。
x_val = train_data[:10000]partial_x_train = train_data[10000:]y_val = train_labels[:10000]partial_y_train = train_labels[10000:]
準備好模型和資料後,我們就可以開始訓練和驗證了。epochs=40表示訓練40遍,以512個數據為一批。從訓練結果的截圖裡我們可以看到,經過40遍訓練和驗證,訓練準確率已經到達了97%,驗證準確率也達到了88%。
history = model.fit(partial_x_train, partial_y_train, epochs=40, batch_size=512, validation_data=(x_val, y_val), verbose=1)
訓練結果
最後我們再到測試集上評估一下模型質量,評估結果為 [0.3299543261528015, 0.8727200031280518],表示損失函式值為0.33,準確率為87%。我們把40遍訓練過程損失值降低過程打印出來,我們可以發現訓練次數到達20時,訓練集損失繼續減小,但驗證集損失值卻幾乎沒有變化,甚至還有抬頭的趨勢,這就說明訓練次數並不是越多越好。訓練次數太多,會導致過擬合,在驗證集和測試集上,模型的損失反而會變大。
results = model.evaluate(test_data, test_labels, verbose=2)print(results)
訓練次數過程曲線
至此,我們已經寫對電影評論進行正面/負面進行分類的程式碼了。我們不妨小結一下,文字分類與影象分類的處理步驟基本類似,都是先載入資料集,然後預處理資料,再構建模型、編譯模型,最後訓練模型,從而讓機器學會對未曾見過的測試資料進行準確的預測。如果完全不學習理論,只學習程式碼,我們發現理解起來還是非常吃力的,這說明學習人工智慧和學習傳統Java、Android等程式語言完全不同,理論學習在人工智慧領域也非常重要,否則你吃飽了都不知道到底吃的是什麼。