深度學(xué)習(xí):將新聞報道按照不同話題性質(zhì)進(jìn)行分類

深度學(xué)習(xí)的廣泛運(yùn)用之一就是對文本按照其內(nèi)容進(jìn)行分類。例如對新聞報道根據(jù)其性質(zhì)進(jìn)行劃分是常見的應(yīng)用領(lǐng)域。在本節(jié),我們要把路透社自1986年以來的新聞數(shù)據(jù)按照46個不同話題進(jìn)行劃分。網(wǎng)絡(luò)經(jīng)過訓(xùn)練后妖异,它能夠分析一篇新聞稿,然后按照其報道內(nèi)容领追,將其歸入到設(shè)定好的46個話題之一他膳。深度學(xué)習(xí)在這方面的應(yīng)用屬于典型的“單標(biāo)簽,多類別劃分”的文本分類應(yīng)用绒窑。

我們這里采用的數(shù)據(jù)集來自于路透社1986年以來的報道棕孙,數(shù)據(jù)中每一篇新聞稿附帶一個話題標(biāo)簽,以用于網(wǎng)絡(luò)訓(xùn)練,每一個話題至少含有10篇文章蟀俊,某些報道它內(nèi)容很明顯屬于給定話題钦铺,有些報道會模棱兩可,不好確定它到底屬于哪一種類的話題肢预,我們先把數(shù)據(jù)加載到機(jī)器里矛洞,代碼如下:

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

keras框架直接附帶了相關(guān)數(shù)據(jù)集,通過執(zhí)行上面代碼就可以將數(shù)據(jù)下載下來烫映。上面代碼運(yùn)行后結(jié)果如下:


這里寫圖片描述

從上面運(yùn)行結(jié)果看缚甩,它總共有8982條訓(xùn)練數(shù)據(jù)和2246條測試數(shù)據(jù)。跟我們上節(jié)數(shù)據(jù)類型一樣窑邦,數(shù)據(jù)里面對應(yīng)的是每個單詞的頻率編號擅威,我們可以通過上一節(jié)類似的代碼,將編號對應(yīng)的單詞從字典中抽取出來結(jié)合成一篇文章冈钦,代碼如下:

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)

上面代碼運(yùn)行后結(jié)果如下:


這里寫圖片描述

如同上一節(jié)郊丛,我們必須要把訓(xùn)練數(shù)據(jù)轉(zhuǎn)換成數(shù)據(jù)向量才能提供給網(wǎng)絡(luò)進(jìn)行訓(xùn)練,因此我們像上一節(jié)一樣瞧筛,對每條新聞創(chuàng)建一個長度為一萬的向量厉熟,先把元素都初始為0,然后如果某個對應(yīng)頻率的詞在文本中出現(xiàn)较幌,那么我們就在向量中相應(yīng)下標(biāo)設(shè)置為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])

上面代碼運(yùn)行后,我們就把訓(xùn)練數(shù)據(jù)變成含有1或0的向量了:

這里寫圖片描述

其實(shí)我們可以直接調(diào)用keras框架提供的接口一次性方便簡單的完成:

from keras.utils.np_utils import to_categorical

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

接下來我們可以著手構(gòu)建分析網(wǎng)絡(luò)乍炉,網(wǎng)絡(luò)的結(jié)構(gòu)與上節(jié)很像绢片,因?yàn)橐鉀Q的問題性質(zhì)差不多,都是對文本進(jìn)行分析岛琼。然而有一個重大不同在于底循,上一節(jié)我們只讓網(wǎng)絡(luò)將文本劃分成兩種類別,而這次我們需要將文本劃分為46個類別槐瑞!上一節(jié)我們構(gòu)造網(wǎng)絡(luò)時熙涤,中間層網(wǎng)絡(luò)我們設(shè)置了16個神經(jīng)元,由于現(xiàn)在我們需要在最外層輸出46個結(jié)果困檩,因此中間層如果只設(shè)置16個神經(jīng)元那就不夠用祠挫,由于輸出的信息太多,如果中間層神經(jīng)元數(shù)量不足悼沿,那么他就會成為信息過濾的瓶頸等舔,因此這次我們搭建網(wǎng)絡(luò)時,中間層網(wǎng)絡(luò)節(jié)點(diǎn)擴(kuò)大為6個显沈,代碼如下:

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'))
#當(dāng)結(jié)果是輸出多個分類的概率時软瞎,用softmax激活函數(shù),它將為46個分類提供不同的可能性概率值
model.add(layers.Dense(46, activation='softmax'))

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

像上一節(jié)一樣,在網(wǎng)絡(luò)訓(xùn)練時我們要設(shè)置校驗(yàn)數(shù)據(jù)集涤浇,因?yàn)榫W(wǎng)絡(luò)并不是訓(xùn)練得次數(shù)越多越好鳖藕,有了校驗(yàn)數(shù)據(jù)集,我們就知道網(wǎng)絡(luò)在訓(xùn)練幾次的情況下能夠達(dá)到最優(yōu)狀態(tài)只锭,準(zhǔn)備校驗(yàn)數(shù)據(jù)集的代碼如下:

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:]

有了數(shù)據(jù)著恩,就相當(dāng)于有米入鍋,我們可以把數(shù)據(jù)輸入網(wǎng)絡(luò)進(jìn)行訓(xùn)練:

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

代碼進(jìn)行了20個周期的循環(huán)訓(xùn)練蜻展,由于數(shù)據(jù)量比上一節(jié)小喉誊,因此速度快很多,與上一節(jié)一樣纵顾,網(wǎng)絡(luò)的訓(xùn)練并不是越多越好伍茄,它會有一個拐點(diǎn),訓(xùn)練次數(shù)超出后施逾,效果會越來越差敷矫,我們把訓(xùn)練數(shù)據(jù)圖形化,以便觀察拐點(diǎn)從哪里開始:

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()

上面代碼運(yùn)行后結(jié)果如下:

這里寫圖片描述

通過上圖觀察我們看到汉额,以藍(lán)點(diǎn)表示的是網(wǎng)絡(luò)對訓(xùn)練數(shù)據(jù)的判斷準(zhǔn)確率曹仗,該準(zhǔn)確率一直在不斷下降,但是藍(lán)線表示的是網(wǎng)絡(luò)對校驗(yàn)數(shù)據(jù)判斷的準(zhǔn)確率蠕搜,仔細(xì)觀察發(fā)現(xiàn)怎茫,它一開始是迅速下降的,過了某個點(diǎn)妓灌,達(dá)到最低點(diǎn)后就開始上升轨蛤,這個點(diǎn)大概是在epochs=9那里,所以我們把前面對網(wǎng)絡(luò)訓(xùn)練的循環(huán)次數(shù)減少到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'))
#當(dāng)結(jié)果是輸出多個分類的概率時旬渠,用softmax激活函數(shù),它將為46個分類提供不同的可能性概率值
model.add(layers.Dense(46, activation='softmax'))

#對于輸出多個分類結(jié)果俱萍,最好的損失函數(shù)是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))

完成訓(xùn)練后端壳,我們把結(jié)果輸出看看:

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

上面兩句代碼運(yùn)行結(jié)果為:


這里寫圖片描述

右邊0.78表示告丢,我們網(wǎng)絡(luò)對新聞進(jìn)行話題分類的準(zhǔn)確率達(dá)到78%,差一點(diǎn)到80%损谦。我們從測試數(shù)據(jù)集中拿出一條數(shù)據(jù)岖免,讓網(wǎng)絡(luò)進(jìn)行分類,得到結(jié)果再與其對應(yīng)的正確結(jié)果比較看看是否一致:

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

我們讓網(wǎng)絡(luò)對每一條測試數(shù)據(jù)一一進(jìn)行判斷照捡,并把它對第一條數(shù)據(jù)的判斷結(jié)果顯示出來颅湘,最后我們打印出第一條測試數(shù)據(jù)對應(yīng)的分類,最后看看網(wǎng)絡(luò)給出去的結(jié)果與正確結(jié)果是否一致栗精,上面代碼運(yùn)行后結(jié)果如下:

這里寫圖片描述

從上面運(yùn)行結(jié)果看到闯参,網(wǎng)絡(luò)對第一條數(shù)據(jù)給出了屬于46個分類的概率瞻鹏,其中下標(biāo)為3的概率值最大,也就是第一條數(shù)據(jù)屬于分類4的概率最大鹿寨,最后打印出來的測試數(shù)據(jù)對應(yīng)的正確結(jié)果來看新博,它也是下標(biāo)為3的元素值為1,也就是說數(shù)據(jù)對應(yīng)的正確分類是4脚草,由此我們網(wǎng)絡(luò)得到的結(jié)果是正確的赫悄。

前面提到過,由于網(wǎng)絡(luò)最終輸出結(jié)果包含46個元素馏慨,因此中間節(jié)點(diǎn)的神經(jīng)元數(shù)目不能小于46埂淮,因?yàn)樾∮?6,那么有關(guān)46個元素的信息就會遭到擠壓写隶,于是在層層運(yùn)算后會導(dǎo)致信息丟失倔撞,最后致使最終結(jié)果的準(zhǔn)確率下降,我們試試看是不是這樣:

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'))
#當(dāng)結(jié)果是輸出多個分類的概率時慕趴,用softmax激活函數(shù),它將為46個分類提供不同的可能性概率值
model.add(layers.Dense(46, activation='softmax'))

#對于輸出多個分類結(jié)果误窖,最好的損失函數(shù)是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)

上面代碼運(yùn)行后,輸出的results結(jié)果如下:
[1.4625472680649796, 0.6705253784505788]

從上面結(jié)果看到秩贰,我們代碼幾乎沒變霹俺,致使把第二層中間層神經(jīng)元數(shù)量改成4,最終結(jié)果的準(zhǔn)確率就下降10個點(diǎn)毒费,所以中間層神經(jīng)元的減少導(dǎo)致信息壓縮后丙唧,最后計算的準(zhǔn)確度缺失。反過來你也可以試試用128個神經(jīng)元的中間層看看準(zhǔn)確率有沒有提升想际。

到這里不知道你發(fā)現(xiàn)沒有,神經(jīng)網(wǎng)絡(luò)在實(shí)際項目中的運(yùn)用有點(diǎn)類似于樂高積木溪厘,你根據(jù)實(shí)際需要胡本,通過選定參數(shù),用幾行代碼配置好基本的網(wǎng)絡(luò)結(jié)構(gòu)畸悬,把訓(xùn)練數(shù)據(jù)改造成合適的數(shù)字向量侧甫,然后就可以輸入到網(wǎng)絡(luò)中進(jìn)行訓(xùn)練,訓(xùn)練過程中記得用校驗(yàn)數(shù)據(jù)監(jiān)測最優(yōu)訓(xùn)練次數(shù)蹋宦,防止過度擬合披粟。

在網(wǎng)絡(luò)的設(shè)計過程中,其背后的數(shù)學(xué)原理我們幾乎無需了解冷冗,只需要憑借經(jīng)驗(yàn)守屉,根據(jù)項目的性質(zhì),設(shè)定網(wǎng)絡(luò)的各項參數(shù)蒿辙,最關(guān)鍵的其實(shí)在根據(jù)項目數(shù)據(jù)性質(zhì)對網(wǎng)絡(luò)進(jìn)行調(diào)優(yōu)拇泛,例如網(wǎng)絡(luò)設(shè)置幾層好滨巴,每層幾個神經(jīng)元,用什么樣的激活函數(shù)和損失函數(shù)等等俺叭,這些操作與技術(shù)無關(guān)兢卵,取決以個人經(jīng)驗(yàn),屬于“藝術(shù)”的范疇绪颖。

更詳細(xì)的講解和代碼調(diào)試演示過程秽荤,請點(diǎn)擊鏈接

更多技術(shù)信息,包括操作系統(tǒng)柠横,編譯器窃款,面試算法,機(jī)器學(xué)習(xí)牍氛,人工智能晨继,請關(guān)照我的公眾號:


這里寫圖片描述
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市搬俊,隨后出現(xiàn)的幾起案子紊扬,更是在濱河造成了極大的恐慌,老刑警劉巖唉擂,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件餐屎,死亡現(xiàn)場離奇詭異,居然都是意外死亡玩祟,警方通過查閱死者的電腦和手機(jī)腹缩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來空扎,“玉大人藏鹊,你說我怎么就攤上這事∽猓” “怎么了盘寡?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長撮慨。 經(jīng)常有香客問我竿痰,道長,這世上最難降的妖魔是什么甫煞? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任菇曲,我火速辦了婚禮,結(jié)果婚禮上抚吠,老公的妹妹穿的比我還像新娘。我一直安慰自己弟胀,他們只是感情好楷力,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布喊式。 她就那樣靜靜地躺著,像睡著了一般萧朝。 火紅的嫁衣襯著肌膚如雪岔留。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天检柬,我揣著相機(jī)與錄音献联,去河邊找鬼。 笑死何址,一個胖子當(dāng)著我的面吹牛里逆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播用爪,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼原押,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了偎血?” 一聲冷哼從身側(cè)響起诸衔,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颇玷,沒想到半個月后笨农,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帖渠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年磁餐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阿弃。...
    茶點(diǎn)故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡诊霹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出渣淳,到底是詐尸還是另有隱情脾还,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布入愧,位于F島的核電站鄙漏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏棺蛛。R本人自食惡果不足惜怔蚌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望旁赊。 院中可真熱鬧桦踊,春花似錦、人聲如沸终畅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至杖狼,卻和暖如春炼蛤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蝶涩。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工理朋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绿聘。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓嗽上,卻偏偏與公主長得像,于是被迫代替她去往敵國和親斜友。 傳聞我的和親對象是個殘疾皇子炸裆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 來到石磨村不久,我就近在北京成府小學(xué)二分校入學(xué)鲜屏。 可能是老師看錯了烹看,把二多加了一橫,我一下子從1年...
    王馳1960閱讀 471評論 1 4
  • 文/藝莫 親愛的我就是要這樣寵著你 親愛的讓我親親你的眼 親愛的外面冷洛史,和我一起回家吧惯殊! 親愛的不生氣了,來我讓我...
    藝莫閱讀 282評論 0 2
  • 文/辛夏禾yuan 其實(shí)要真的說起來也殖,我不算是一個特別能言善辯的姑娘土思,尤其是對父親,有的時候便是連語言都顯得有些格...
    辛夏禾yuan閱讀 680評論 17 29