深度學習的普遍運用之一就是對文本按照其內容進行分類。例如對新聞報道根據其性質進行劃分是常見的應用領域。在本節,咱們要把路透社自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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。