原先寫過兩篇文章,分別介紹了傳統機器學習方法在文本分類上的應用以及CNN原理,而後本篇文章結合兩篇論文展開,主要講述下CNN在文本分類上的應用。前面兩部份內容主要是來自兩位博主的文章(文章中已經給出原文連接),是對兩篇論文的解讀以及總結,基本上闡釋了CNN文本分類模型;後半部分講一個實例和項目實戰html
在短文本分析任務中,因爲句子句長長度有限、結構緊湊、可以獨立表達意思,使得CNN在處理這一類問題上成爲可能,主要思想是將ngram模型與卷積操做結合起來git
如圖所示,輸入層是句子中的詞語對應的wordvector依次(從上到下)排列的矩陣,假設句子有 n 個詞,vector的維數爲 k ,那麼這個矩陣就是 n × k 的(在CNN中能夠看做一副高度爲n、寬度爲k的圖像)。github
這個矩陣的類型能夠是靜態的(static),也能夠是動態的(non static)。靜態就是word vector是固定不變的,而動態則是在模型訓練過程當中,word vector也當作是可優化的參數,一般把反向偏差傳播致使word vector中值發生變化的這一過程稱爲Fine tune。(這裏若是word vector若是是隨機初始化的,不只訓練獲得了CNN分類模型,還獲得了word2vec這個副產品了,若是已經有訓練的word vector,那麼實際上是一個遷移學習的過程)算法
對於未登陸詞的vector,能夠用0或者隨機小的正數來填充。bash
輸入層經過卷積操做獲得若干個Feature Map,卷積窗口的大小爲 h ×k ,其中 h 表示縱向詞語的個數,而 k 表示word vector的維數。經過這樣一個大型的卷積窗口,將獲得若干個列數爲1的Feature Map。(熟悉NLP中N-GRAM模型的讀者應該懂得這個意思)。網絡
接下來的池化層,文中用了一種稱爲Max-over-timePooling的方法。這種方法就是簡單地從以前一維的Feature Map中提出最大的值,文中解釋最大值表明着最重要的信號。能夠看出,這種Pooling方式能夠解決可變長度的句子輸入問題(由於無論Feature Map中有多少個值,只須要提取其中的最大值)。最終池化層的輸出爲各個Feature Map的最大值們,即一個一維的向量。app
池化層的一維向量的輸出經過全鏈接的方式,鏈接一個Softmax層,Softmax層可根據任務的須要設置(一般反映着最終類別上的機率分佈)。機器學習
在倒數第二層的全鏈接部分上使用Dropout技術,Dropout是指在模型訓練時隨機讓網絡某些隱含層節點的權重不工做,不工做的那些節點能夠暫時認爲不是網絡結構的一部分,可是它的權重得保留下來(只是暫時不更新而已),由於下次樣本輸入時它可能又得工做了,它是防止模型過擬合的一種經常使用的trikc。同時對全鏈接層上的權值參數給予L2正則化的限制。這樣作的好處是防止隱藏層單元自適應(或者對稱),從而減輕過擬合的程度。ide
在樣本處理上使用minibatch方式來下降一次模型擬合計算量,使用shuffle_batch的方式來下降各批次輸入樣本之間的相關性(在機器學習中,若是訓練數據之間相關性很大,可能會讓結果不好、泛化能力得不到訓練、這時一般須要將訓練數據打散,稱之爲shuffle_batch)。函數
項目代碼:CNN_sentence 以上部份內容來自:https://www.cnblogs.com/cl1024cl/p/6205012.html
這篇論文主要工做是對「Convolutional Naural Networks for Sentence Classification」這篇論文的模型進行了各類各樣的對比試驗,並給出了調參的建議,進而獲得了一些關於超參數的設置經驗。
上圖句子爲「[I like this movie very much!」 ,一共有兩個單詞加上一個感嘆號,關於這個標點符號,不一樣學者有不一樣的操做,好比去除標點符號。在這裏咱們先不去除,那麼整個句子有7個詞,詞向量維度爲5,那麼整個句子矩陣大小爲7x5
filters的區域大小可使不一樣的,在這裏取(2,3,4)3種大小,每種大小的filter有兩個不一樣的值的filter,因此一共是有6個filter。
咱們在句子矩陣和過濾器矩陣填入一些值,那麼咱們能夠更好理解卷積計算過程,這和CNN原理那篇文章同樣,
0.6 x 0.2 + 0.5 x 0.1 + … + 0.1 x 0.1 = 0.51
,而後將filter向下移動1個位置獲得0.53.最終生成的feature map大小爲(7-2+1x1)=6。 爲了得到feature map,咱們添加一個bias項和一個激活函數,好比Relu
由於不一樣大小的filter獲取到的feature map大小也不同,爲了解決這個問題,而後添加一層max-pooling,選取一個最大值,相同大小的組合在一塊兒 ###4.5 #concat1max 通過max-pooling操做以後,咱們將固定長度的向量給sofamax,來預測文本的類別。
下面是利用Keras實現的CNN文本分類部分代碼:
# 建立tensor
print("正在建立模型...")
inputs=Input(shape=(sequence_length,),dtype='int32')
embedding=Embedding(input_dim=vocabulary_size,output_dim=embedding_dim,input_length=sequence_length)(inputs)
reshape=Reshape((sequence_length,embedding_dim,1))(embedding)
# cnn
conv_0=Conv2D(num_filters,kernel_size=(filter_sizes[0],embedding_dim),padding='valid',kernel_initializer='normal',activation='relu')(reshape)
conv_1=Conv2D(num_filters,kernel_size=(filter_sizes[1],embedding_dim),padding='valid',kernel_initializer='normal',activation='relu')(reshape)
conv_2=Conv2D(num_filters,kernel_size=(filter_sizes[2],embedding_dim),padding='valid',kernel_initializer='normal',activation='relu')(reshape)
maxpool_0=MaxPool2D(pool_size=(sequence_length-filter_sizes[0]+1,1),strides=(1,1),padding='valid')(conv_0)
maxpool_1=MaxPool2D(pool_size=(sequence_length-filter_sizes[1]+1,1),strides=(1,1),padding='valid')(conv_1)
maxpool_2=MaxPool2D(pool_size=(sequence_length-filter_sizes[2]+1,1),strides=(1,1),padding='valid')(conv_2)
concatenated_tensor = Concatenate(axis=1)([maxpool_0, maxpool_1, maxpool_2])
flatten = Flatten()(concatenated_tensor)
dropout = Dropout(drop)(flatten)
output = Dense(units=2, activation='softmax')(dropout)
model=Model(inputs=inputs,outputs=output)
複製代碼
運行結果
英文:
中文: