背景介紹
這次主要將神經網絡直接運用到具體的分析項目中僵缺,使用keras來判斷用戶在網絡上編寫的影評中包含的是正能量還是負能量堰氓。
數(shù)據(jù)集介紹
本次主要使用imdb(Internet Movie Database)數(shù)據(jù)集,數(shù)據(jù)集在這->imdb。
這數(shù)據(jù)集包含了50000條偏向明顯的評論阳谍,其中25000條作為訓練集蛀柴,25000作為測試集。label為pos(positive)和neg(negative)矫夯。
我們來看看這些數(shù)據(jù)
from keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=100)
print(train_data[0])
print(train_labels[0])
這一份數(shù)據(jù)采用了一種神奇的結構鸽疾,即所謂單詞向量,這份數(shù)據(jù)對應一份單詞頻率表训貌,這份表的數(shù)據(jù)結構如圖所示
其中的數(shù)字既代表單詞出現(xiàn)的頻率制肮,第一個數(shù)字1,即代表頻率出現(xiàn)排名第一的單詞递沪;對應表下載;
其中做的標記中豺鼻,分為1,0兩種款慨,1代表正能量儒飒,0代表負能量
讓我們來看看這段影評長什么樣。
word_index = imdb.get_word_index()
#我們要把表中的對應關系反轉一下檩奠,變成key是頻率桩了,value是單詞
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
decoded_review = ' '.join([reverse_word_index.get(i-3, '?') for i in train_data[0]])
print(decoded_review)
在train_data所包含的數(shù)值中,數(shù)值1埠戳,2井誉,3對應的不是單詞,而用來表示特殊含義整胃,1表示“填充”颗圣,2表示”文本起始“,
3表示”未知“爪模,因此當我們從trai
n_data中讀到的數(shù)值是1欠啤,2,3時屋灌,我們要忽略它洁段,從4開始才對應單詞,如果數(shù)值是4共郭,
那么它表示頻率出現(xiàn)最高的單詞is
import numpy as np
def vectorize_sequences(sequences, dimension=10000):
results = np.zeros((len(sequences),dimension))
for i, sequence in enumerate(sequences):
results[i, sequence] = 1.
return results
x_train = vectorize_sequences(train_data)
x_test = vectorize_sequences(test_data)
以上函數(shù)為的是把每個評論轉換成一個矩陣祠丝,一條評論對應一個矩陣,矩陣的行對應單詞數(shù)量除嘹,矩陣的列長度是一萬写半,代表一萬個單詞數(shù)量,這一萬個數(shù)一開始全為0尉咕,將出現(xiàn)的詞置為1.從頭到底進行排序叠蝇,接下來為了方便運算,我們將其轉換成浮點數(shù)年缎。
y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')
接下來我們開始構建神經網絡悔捶,我們構建一個四層的神經網絡铃慷。第一層輸入有10000個結點。第二層蜕该,第三層有16個節(jié)點犁柜,第四層有一個節(jié)點,輸出一個概率值堂淡。
from keras import models
from keras import layers
model = models.Sequential()
#構建第一層和第二層網絡馋缅,第一層有10000個節(jié)點,第二層有16個節(jié)點
#Dense的意思是绢淀,第一層每個節(jié)點都與第二層的所有節(jié)點相連接
#relu 對應的函數(shù)是relu(x) = max(0, x)萤悴,相當于神經元函數(shù)
model.add(layers.Dense(32, activation='relu', input_shape=(10000,)))
#第三層有16個神經元,第二層每個節(jié)點與第三層每個節(jié)點都相互連接
model.add(layers.Dense(32, activation='relu'))
#第四層只有一個節(jié)點皆的,輸出一個0-1之間的概率值
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
optimizer參數(shù)指定的是如何優(yōu)化鏈路權重稚疹,事實上各種優(yōu)化方法跟我們前面講的梯度下降法差不多,只不過在存在一些微小的變化祭务,特別是在更新鏈路權值時内狗,會做一些改動,但算法主體還是梯度下降法义锥。當我們的網絡用來將數(shù)據(jù)區(qū)分成兩種類型時柳沙,損失函數(shù)最好使用,輸出是兩種時,binary_crossentroy,它的表達式如下:
Hy′(y):=?∑i(y′ilog(y[i])+(1?y′[i])log(1?y[i]))
其中y[i]對應的是訓練數(shù)據(jù)提供的結果拌倍,y'[i]是我們網絡計算所得的結果赂鲤。metrics用于記錄網絡的改進效率,我們暫時用不上柱恤。接著我們把訓練數(shù)據(jù)分成兩部分数初,一部分用于訓練網絡,一部分用于檢驗網絡的改進情況:
x_val = x_train[:10000]
partial_x_train = x_train[10000:]
y_val = y_train[: 10000]
partial_y_train = y_train[10000:]
history = model.fit(partial_x_train, partial_y_train, epochs=20, batch_size=512,
validation_data = (x_val, y_val))
訓練數(shù)據(jù)總共有60000條梗顺,我們把最前一萬條作為校驗數(shù)據(jù)泡孩,用來檢測網絡是否優(yōu)化到合適的程度,然后我們把數(shù)據(jù)從第一萬條開始作為訓練網絡來用寺谤,把數(shù)據(jù)分割好后仑鸥,調用fit函數(shù)就可以開始訓練過程,上面代碼運行后結果如下:
import matplotlib.pyplot as plt
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)
#繪制訓練數(shù)據(jù)識別準確度曲線
plt.plot(epochs, loss, 'bo', label='Trainning loss')
#繪制校驗數(shù)據(jù)識別的準確度曲線
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Trainning and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
我們看上面圖示能發(fā)現(xiàn)一個問題变屁,隨著迭代次數(shù)的增加眼俊,網絡對訓練數(shù)據(jù)識別的準確度越來越高,也就是loss越來越低粟关,然后校驗數(shù)據(jù)的識別準確的卻越來越低疮胖,這種現(xiàn)象叫“過度擬合”,這意味著訓練的次數(shù)并不是越多越好,而是會“過猶不及”澎灸,有時候訓練迭代次數(shù)多了反而導致效果下降谷市。從上圖我們看到,大概在第4個epoch的時候击孩,校驗數(shù)據(jù)的識別錯誤率開始上升,因此我們將前面的代碼修改鹏漆,把參數(shù)epochs修改成4才能達到最佳效果巩梢。 訓練好網絡后,我們就可以用它來識別新數(shù)據(jù)艺玲,我們把測試數(shù)據(jù)放入網絡進行識別括蝠,代碼如下:
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=2, batch_size=512)
results = model.evaluate(x_test, y_test)
