Tensorflow的基礎使用與文本分類應用
知乎大數據比賽官網:
下面是基於知乎大數據比賽的文本分類公開課:
大家好,非常高興大家今晚能參加 Tensorflow 的公開課,我是本次公開課的主講人覃秉豐。今晚的公開課會分成兩個部分, 第一部分 會介紹 Tensorflow 的基礎使用,以及文本分類的思路。 第二部分會 給出具體代碼來給大家講解如何用 Tensorflow 來做文本分類。
Tensorflow 是 google 第二代人工智慧學習系統。支持 python 和c++語言, 支持 CNN、 RNN 和 LSTM 等演算法, 可以被用於語音識 別或圖像處理等多項深度學習領域。它可以在一個或多個 CPU 或GPU 中運行。它可以運行在嵌入式系統(如手機, 平板電腦)中, PC中以及分散式系統中。它是目前全世界最火爆的深度學習平台(沒有之一)。
深度學習這個行業剛剛興起, 急需一個好的平台來提高我們的工作 效率。 google 在 2015 年 12 月 11 日開源了 Tensorflow, google希望把Tensorflow 做成行業標準。我個人也是比較看好 Tensorflow,畢竟 Google 的技術水平和公司實力都是全世界數一數二的。我們學 習了 Tensorflow 之後, 就可以使用 Tensorflow 非常方便地搭建一 些我們自己的深度網路, 實現我們想要的一些功能。

大家先看一下這一頁 PPT,了解一下 Tensorflow 的一些基本概念。

就如同上一張 PPT 所說的,我們需要定義一個會話(Session),會話 中可以有一個或多個圖(Graph),Tensorflow 會有一個默認的圖,一 般情況下使用默認的圖就足夠了。在圖中可以定義計算的節點,稱為OP,一個 OP 可以獲得張量(Tensor)或者變數(Variable),然後進 行計算。計算後得到的結構可以傳給下一個 OP 再進行計算。

下面我們來看看 Tensorflow 中一個最基本的應用-MNIST 數據集分 類。手寫數字圖片數據集分成兩個部分,訓練集有 60000 張圖片,測 試集有 10000 張圖片。圖片都是 0-9 的手寫數字,類似於上面幾張圖 片的樣子。

這裡的重點是每一張圖片都是 28*28 的黑白圖片,然後把二維的圖片變成一維的向量,向量的長度是 28*28=784。

訓練集一共有 60000 張圖片,所以數據的格式就像這樣,是一個形狀 為 [60000, 784] 的張量。

訓練集的標籤是[60000,10]的張量。

我們可以構建一個如圖所示的神經網路,輸入層有 784 個神經元,對 應一張圖片有 784 個像素。輸出層有 10 個神經元,對應 0 到 9 一共10 個數字。下面我們來看看程序。


大家花 3 分鐘看看 MNIST 的代碼,代碼裡面寫了詳細的注釋應該還 是比較好理解的。

接下來我們會講解如何使用 CNN 來做文本分類。內容會涉及到一些CNN 的知識,和 word2vec 的知識,由於時間的問題我們就不具體介 紹了。不太了解的朋友可以到網上查一下相關的知識。

這幅圖很好的描繪了 CNN 網路在自然語言處理中的使用。大家先花2 分鐘自己看一下,等下我再給大家講解。
下面我給大家講解一下這幅圖,我給這些層做了從左到右做了一個編 號,分別為 1,2,3,4,5 層。我們先看第 1 層,第 1 層是輸入層,輸入一 句話,或者一段文本。比如圖中一共有 7 個詞,每個詞用一個向量來 表示(這個的向量可以使用 word2vec),圖中 d=5 意思是維度為 5 的 向量,不過實際使用中一般我們會用 128 維,200 維,256 維,或 300維等比較大的維度。這樣我們就可以得到一個矩陣,每個詞占矩陣中 的一行,列就是詞向量。
我們再看到第 2 層,第 2 層定義了三個尺寸的濾波器。濾波的列數跟 第 1 層矩陣中的列數要是一樣的(圖中是 5 列,假如我們使用 128 維 的詞向量,那麼第 2 層的濾波器就是 128 列),濾波器的行數有三個 尺寸,分別是 2,3,4,每種尺寸的濾波器有 2 個。
使用第 2 層中的濾波對第 1 層的矩陣求卷積,就可以得到第 3 層。使 用尺寸為 4 的濾波器求卷積會得到 4 個輸出值,使用尺寸為 3 的濾波 器求卷積會得到 5 個輸出值,使用尺寸為 2 的濾波器求卷積會得到 6個輸出值。
第 3 層到第 4 層有一個最大池化的操作,其實就是取第 3 層中每個濾 波器輸出的 feature map 的最大值。因為一共有 6 個濾波器,所以會 得到 6 個 feature map,所以第 4 層會得到 6 個值。
第 5 層是分類層,假如我們需要分 2 個類,第 5 層就只有 2 個神經 元。如果我們需要分更多的類,那我們就需要設置更多的神經元。第4 層跟第 5 層之間是全連接的。
我們接著往下講,講解程序之前,我們先來講一下數據預處理,以及 程序設計的思路。

知乎的這次比賽提供的數據種類很多,數據量也很大,所以參賽選手 可以有很大地自由發揮空間。不過我這次分享主要是給大家提供一種 可行的思路和方法,並不是說大家看完我的程序之後就能拿獎。為了 節約時間,我只使用了非常少量的數據進行訓練。後面我也會講到怎 么在我的這個方法上去做提升。

數據預處理的程序比較簡單,我會把程序提供給大家,這裡就不做講 解了。我們看一下思路就可以。數據預處理使用了三個文件question_train_set.txt,question_topic_train_set.txt,topic_info.txt。這 三個文件的描述在上面可以看到。我的數據處理按照以下原則:
1.title通常來說包含的信息最重要。對於question_train_set.txt文件,為了簡單起見,我們只取第三列,title 的詞語編號序列。
2.對於 topic_info.txt,為了簡單起見,我們不考慮 2,3,4,5,6 列。只是 簡單的提取話題 id,然後轉為 0-1998 的數字(一共有 1999 個話 題)
3.然後合併以上一些數據,得到最後處理後的數據。
我們可以看到,處理過後的數據,第 1 列的內容是問題的 title 中的詞 編號,第 2 列是問題所屬的話題 id。其實本質上就是一段文字描述,然後有一個或多個分類。訓練集一共有 2999967 個問題,為了簡單方 便,我把訓練集拆分成了 10 份,前 9 份 300000 個數據,最後一份299967 個數據。我只取其中一份,也就是 300000 個數據來進行訓練。
下面我們開始講解程序。

在程序的最開始先定義一些參數。

接下來讀取訓練數據,並把訓練數據存入 x_text 中,把分類的標籤進 行一些處理,存入 y 中,圖中我們可以看到 x_text 和 y 的數據格式。

建立一個詞典,並且把數據集中的辭彙(如『w305』,『w11』,『w1034』等),變成編號的形式。然後把數據集切分為訓練集和驗證集。圖中 我們可以看到,數據集一共有 300000 行。在所有的數據集中,辭彙 數最多的一段數據一共有 72 個辭彙,所有 x_shape 的列為 72,同時我們要把所有的數據的辭彙數都變成 72,如果不夠 72 個辭彙就填充0,一直填充到 72 個元素。y_shape 的列為 1999,因為一共有 1999個話題的分類。x 和 y 的數據格式如上圖所示。

接下來定義佔位符,tf.placeholder 創建了一個佔位符變數,當我們訓 練或測試的時候,都可以使用它向我們的模型輸入數據。同時還設置 了一些參數。
上面還定義了第一個網路層,這一層的作用是將辭彙索引映射到詞向 量進行表示。它的本質是一個我們從數據中學習得到的辭彙向量表。
W 是我們的嵌入矩陣,這個矩陣是我們從數據訓練過程中得到的。最 開始,我們使用一個隨機均勻分布來進行初始化。tf.nn.embedding_lookup 創建實際的嵌入讀取操作,這個嵌入操作返 回的數據維度是三維張量 [None, sequence_length, embedding_size] 。

TensorFlow 的卷積操作conv2d需要一個四維的輸入數據,對應的維 度分別是批處理大小,寬度,高度和通道數。在我們嵌入層得到的數 據中不包含通道數,所以我們需要手動添加它,所以最終的數據維度 是 [None, sequence_length, embedding_size, 1] 。
這一部分是構建卷積層和池化層。因為我們使用的卷積核是不同尺寸 的,所以我們需要為每一個卷積核創建一層網路,最後再把這些經過 卷積和池化之後的數據合成一個大的特徵向量。整個過程就跟右邊的 圖差不多。

接下來定義 dropout 層,輸出層。並且定義 loss 函數和優化器。這裡我們可以看到 num_filters_total 等於 3072,說明倒數第 2 層有 3072 個 神經元,話題一共有 1999 個分類,所以倒數第 2 層跟最後的輸出層 是 3072×1999 的全連接網路。

這裡定義了一個批次數據的生成程序,使用生成器生成num_epochs×num_batches_per_epoch 個批次的數據用於訓練。

這裡定義了知乎提供的評測方案。

最後就是調用之前的函數,生成批次數據,在會話中訓練模型。每訓 練 50 次測試 1 次模型效果,每訓練 200 次保存一次模型。
模型訓練好之後,我們再調用訓練好的模型去預測question_eval_set.txt 就可以了。預測的程序我也會提供給大家,這裡 就不做詳細介紹了。
我按照前面說的方法簡單預處理過後,取十分之一的數據進行訓練,訓練了 2-3 個周期。最後在知乎比賽官網提交結果得到了 0.3 左右的 分數。結果不算很好也不算很差,排名在中等的位置吧。
最後我再給大家提供幾個優化的思路,以供參考。

1.把所有的數據訓練完。因為我只用了十分之一的數據,如果你使用 了所有的數據來訓練,最後的預測準確率應該會有較大提升。
2.增加訓練周期,使用動態學習率。因為我只訓練了 2 個周期,還是 比較少的,模型應該還有優化空間。同時我使用的是固定的學習率,如果改成動態的學習率,也就是開始的時候學習率比較大,隨著訓 練的進行,學習率越來越小,比較有助於網路進一步優化。
3.使用知乎提供的 word_embedding.txt 文件來初始化辭彙向量表。 我的程序中辭彙向量表示隨機初始化的,如果使用知乎提供的文 件來初始化辭彙向量表,那麼可以使用模型的收斂速度更快,並且 模型最後應該可以獲得更高的準確率。
4.考慮使用更多種類的數據。在我的程序中我只使用的問題 title 的 辭彙數據,如果合理使用問題 title 的字元數據,問題描述的字元數 據、辭彙數據,合理使用 topic_info.txt 中話題之間的聯繫,話題的 描述。應該可以取得更好的效果。
5.調節網路參數。我基本上沒有怎麼優化網路參數。如果對卷積核大 小,每一種卷積核個數,dropout 參數,l2 正則化係數,批次大小,優化器選擇,學習率選擇等等參數進行一些調試應該可以使得模 型效果有所提升。
6.優化網路結構。我使用的用於文本分類的 CNN 的網路結構幾乎是 最簡單的網路結構,所以如果對網路結構進行優化,選擇更深層的,結構更複雜的卷積神經網路,那麼結果應該會有很大提升。
優化方案當然不止這些,大家也可以自己考慮一些其他優化方案。
最後大家可以加一下我的公眾號:深度學習與神經網路

今天分享的內容都放到了我的 github 上,代碼在我的 github 上可以 下載,之後我也會放更多深度學習的分享內容到 github 上面。
github鏈接
推薦閱讀:
※[Scikit-learn教程] 文本處理:分類與優化
※在文本分類任務中,有哪些論文中很少提及卻對性能有重要影響的tricks?
※LDA話題模型訓練後,該如何進行文本分類?
TAG:深度学习DeepLearning | TensorFlow | 文本分类 |
