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

深度學習的廣泛運用之一就是對文本按照其內容進行分類。例如對新聞報道根據其性質進行劃分是常見的應用領域。在本節,我們要把路透社自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 npdef vectorize_sequences(sequences, dimension=10000): results = np.zeros((len(sequences), dimension)) for i, sequence in enumerate(sequences): results[i, sequence] = 1. return resultsx_train = vectorize_sequences(train_data)x_test = vectorize_sequences(test_data)print(x_train[0])

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

其實我們可以直接調用keras框架提供的接口一次性方便簡單的完成:

from keras.utils.np_utils import to_categoricalone_hot_train_labels = to_categorical(train_label)one_hot_test_labels = to_categorical(test_labels)

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

from keras import modelsfrom keras import layersmodel = 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_crossentropymodel.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

像上一節一樣,在網絡訓練時我們要設置校驗數據集,因為網絡並不是訓練得次數越多越好,有了校驗數據集,我們就知道網絡在訓練幾次的情況下能夠達到最優狀態,準備校驗數據集的代碼如下:

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 pltloss = 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 modelsfrom keras import layersmodel = 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_crossentropymodel.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 modelsfrom keras import layersmodel = 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_crossentropymodel.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個神經元的中間層看看準確率有沒有提升。

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

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

2022 最新版百家樂賺錢秘技全攻略
2022 最新版完全攻略 百家樂預測破解
2022 最新版完全攻略 百家樂教學