深度學習:將新聞報道按照不一樣話題性質進行分類

深度學習的普遍運用之一就是對文本按照其內容進行分類。例如對新聞報道根據其性質進行劃分是常見的應用領域。在本節,咱們要把路透社自1986年以來的新聞數據按照46個不一樣話題進行劃分。網絡通過訓練後,它可以分析一篇新聞稿,而後按照其報道內容,將其納入到設定好的46個話題之一。深度學習在這方面的應用屬於典型的「單標籤,多類別劃分」的文本分類應用。微信

咱們這裏採用的數據集來自於路透社1986年以來的報道,數據中每一篇新聞稿附帶一個話題標籤,以用於網絡訓練,每個話題至少含有10篇文章,某些報道它內容很明顯屬於給定話題,有些報道會模棱兩可,很差肯定它到底屬於哪種類的話題,咱們先把數據加載到機器裏,代碼以下:網絡

from keras.datasets import reuters
(train_data, train_label), (test_data, test_labels) = reuters.load_data(num_words=10000)

keras框架直接附帶了相關數據集,經過執行上面代碼就能夠將數據下載下來。上面代碼運行後結果以下:

從上面運行結果看,它總共有8982條訓練數據和2246條測試數據。跟咱們上節數據類型同樣,數據裏面對應的是每一個單詞的頻率編號,咱們能夠經過上一節相似的代碼,將編號對應的單詞從字典中抽取出來結合成一篇文章,代碼以下:框架

word_index = reuters.get_word_index()
reverse_word_index = dict([value, key] for (key, value) in word_index.items())
decoded_newswire = ' '.join([reverse_word_index.get(i-3, '?') for i in train_data[0]])
print(decoded_newswire)

上面代碼運行後結果以下:
函數

如同上一節,咱們必需要把訓練數據轉換成數據向量才能提供給網絡進行訓練,所以咱們像上一節同樣,對每條新聞建立一個長度爲一萬的向量,先把元素都初始爲0,而後若是某個對應頻率的詞在文本中出現,那麼咱們就在向量中相應下標設置爲1,代碼以下:學習

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)

print(x_train[0])

上面代碼運行後,咱們就把訓練數據變成含有1或0的向量了:測試

其實咱們能夠直接調用keras框架提供的接口一次性方便簡單的完成:lua

from keras.utils.np_utils import to_categorical

one_hot_train_labels = to_categorical(train_label)
one_hot_test_labels = to_categorical(test_labels)

接下來咱們能夠着手構建分析網絡,網絡的結構與上節很像,由於要解決的問題性質差很少,都是對文本進行分析。然而有一個重大不一樣在於,上一節咱們只讓網絡將文本劃分紅兩種類別,而此次咱們須要將文本劃分爲46個類別!上一節咱們構造網絡時,中間層網絡咱們設置了16個神經元,因爲如今咱們須要在最外層輸出46個結果,所以中間層若是隻設置16個神經元那就不夠用,因爲輸出的信息太多,若是中間層神經元數量不足,那麼他就會成爲信息過濾的瓶頸,所以此次咱們搭建網絡時,中間層網絡節點擴大爲6個,代碼以下:spa

from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation='relu'))
#當結果是輸出多個分類的機率時,用softmax激活函數,它將爲46個分類提供不一樣的可能性機率值
model.add(layers.Dense(46, activation='softmax'))

#對於輸出多個分類結果,最好的損失函數是categorical_crossentropy
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

像上一節同樣,在網絡訓練時咱們要設置校驗數據集,由於網絡並非訓練得次數越多越好,有了校驗數據集,咱們就知道網絡在訓練幾回的狀況下可以達到最優狀態,準備校驗數據集的代碼以下:.net

x_val = x_train[:1000] partial_x_train = x_train[1000:] y_val = one_hot_train_labels[:1000] partial_y_train = one_hot_train_labels[1000:]設計

有了數據,就至關於有米入鍋,咱們能夠把數據輸入網絡進行訓練:

history = model.fit(partial_x_train, partial_y_train, epochs=20, batch_size=512, 
                   validation_data=(x_val, y_val))

代碼進行了20個週期的循環訓練,因爲數據量比上一節小,所以速度快不少,與上一節同樣,網絡的訓練並非越多越好,它會有一個拐點,訓練次數超出後,效果會愈來愈差,咱們把訓練數據圖形化,以便觀察拐點從哪裏開始:

import matplotlib.pyplot as plt
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(loss) + 1)

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()

上面代碼運行後結果以下:

經過上圖觀察咱們看到,以藍點表示的是網絡對訓練數據的判斷準確率,該準確率一直在不斷降低,可是藍線表示的是網絡對校驗數據判斷的準確率,仔細觀察發現,它一開始是迅速降低的,過了某個點,達到最低點後就開始上升,這個點大概是在epochs=9那裏,因此咱們把前面對網絡訓練的循環次數減小到9:

from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation='relu'))
#當結果是輸出多個分類的機率時,用softmax激活函數,它將爲46個分類提供不一樣的可能性機率值
model.add(layers.Dense(46, activation='softmax'))

#對於輸出多個分類結果,最好的損失函數是categorical_crossentropy
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

history = model.fit(partial_x_train, partial_y_train, epochs=9, batch_size=512, 
                   validation_data=(x_val, y_val))

完成訓練後,咱們把結果輸出看看:

results = model.evaluate(x_test, one_hot_test_labels)
print(results)

上面兩句代碼運行結果爲:

右邊0.78表示,咱們網絡對新聞進行話題分類的準確率達到78%,差一點到80%。咱們從測試數據集中拿出一條數據,讓網絡進行分類,獲得結果再與其對應的正確結果比較看看是否一致:

predictions = model.predict(x_test)
print(predictions[0])
print(np.sum(predictions[0]))
print(np.argmax(predictions[0]))
print(one_hot_test_labels[0])

咱們讓網絡對每一條測試數據一一進行判斷,並把它對第一條數據的判斷結果顯示出來,最後咱們打印出第一條測試數據對應的分類,最後看看網絡給出去的結果與正確結果是否一致,上面代碼運行後結果以下:

從上面運行結果看到,網絡對第一條數據給出了屬於46個分類的機率,其中下標爲3的機率值最大,也就是第一條數據屬於分類4的機率最大,最後打印出來的測試數據對應的正確結果來看,它也是下標爲3的元素值爲1,也就是說數據對應的正確分類是4,由此咱們網絡獲得的結果是正確的。

前面提到過,因爲網絡最終輸出結果包含46個元素,所以中間節點的神經元數目不能小於46,由於小於46,那麼有關46個元素的信息就會遭到擠壓,因而在層層運算後會致使信息丟失,最後導致最終結果的準確率降低,咱們試試看是否是這樣:

from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(4, activation='relu'))
#當結果是輸出多個分類的機率時,用softmax激活函數,它將爲46個分類提供不一樣的可能性機率值
model.add(layers.Dense(46, activation='softmax'))

#對於輸出多個分類結果,最好的損失函數是categorical_crossentropy
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

history = model.fit(partial_x_train, partial_y_train, epochs=9, batch_size=512, 
                   validation_data=(x_val, y_val))
results = model.evaluate(x_test, one_hot_test_labels)
print(results)

上面代碼運行後,輸出的results結果以下:
[1.4625472680649796, 0.6705253784505788]

從上面結果看到,咱們代碼幾乎沒變,導致把第二層中間層神經元數量改爲4,最終結果的準確率就降低10個點,因此中間層神經元的減小致使信息壓縮後,最後計算的準確度缺失。反過來你也能夠試試用128個神經元的中間層看看準確率有沒有提高。

到這裏不知道你發現沒有,神經網絡在實際項目中的運用有點相似於樂高積木,你根據實際須要,經過選定參數,用幾行代碼配置好基本的網絡結構,把訓練數據改形成合適的數字向量,而後就能夠輸入到網絡中進行訓練,訓練過程當中記得用校驗數據監測最優訓練次數,防止過分擬合。

在網絡的設計過程當中,其背後的數學原理咱們幾乎無需瞭解,只須要憑藉經驗,根據項目的性質,設定網絡的各項參數,最關鍵的其實在根據項目數據性質對網絡進行調優,例如網絡設置幾層好,每層幾個神經元,用什麼樣的激活函數和損失函數等等,這些操做與技術無關,取決以我的經驗,屬於「藝術」的範疇。

更詳細的講解,請點擊‘閱讀原文’。



本文分享自微信公衆號 - Coding迪斯尼(gh_c9f933e7765d)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索