之前做過一些文本挖掘的項目,比如網頁分類、微博情感分析、用戶評論挖掘,也曾經將libsvm進行包裝,寫了一個文本分類的開軟軟件Tmsvm。所以這里將之前做過一些關於文本分類的東西整理總結一下。
1 基礎知識
1. 1 樣本整理
如下面的整理的樣本,1為正類,-1為反類(為了能便於展示,這里使用了一些即時聊天工具中的文本,里面的一些對話都是YY,並非真實的)。
表 1.1‑1 一個訓練樣本的例子
標簽 |
樣本 |
1 |
如要購買商品的請加我qq61517891聯系我購買! |
1 |
聯系qq1121107282 |
1 |
你好需要訂購請加扣扣 |
-1 |
索尼愛立信手機的體驗是一個月嗎 |
-1 |
不好意思這個價錢最便宜了 |
-1 |
3件的那個他是高價在賣 |
1.2 特征選擇
文本分類中最著名的特征提取方法就是向量空間模型(VSM),即將樣本轉換為向量的形式。為了能實現這種轉換,需要做兩個工作:確定特征集和提取特征。
1.2.1 確定特征集
特征集其實就是詞典,而且還需要給每個詞設定一個編號。
一般可以將所有樣本的詞都提取出來作為詞典,而詞典的編號可以隨意設置,默認情況下,所有詞的權重都是等同的。如何從樣本中提取出一個個意義的詞呢?最常用的方法就是使用分詞工具,比如“如要購買商品的請加我qq61517891聯系我購買!”,可以分成“如^要^購買^商品^的^請^加^我^qq61517891^聯系^我^購買^!”,其中“^”是用來分割詞的。現在比較常見的分詞工具有ICTCLAS(C++),Iksegment(Java)。
下圖是一個典型的生成詞典的流程圖。
圖 1.1‑1 從樣本中提取詞典流程圖
1.2.2 特征選擇
根據不同的業務,文本分類中詞典的規模在萬級到千萬級甚至億級。而這么大的維度可能會帶來維度災難,因此就要想辦法從大量的特征中選擇一些有代表性的特征而又不影響分類的效果(而根據文獻中的結果,特征選擇可以在一定程度上提高分類的效果)。特征選擇就是從特征集中選擇一些代表性的詞。而如何衡量詞的代表性呢?一般的計算方法有詞頻、卡方公式、信息增益等。當前文獻中一致認為比較好的方法是卡方公式。
下面幾個鏈接是幾篇寫的比較詳細介紹如何進行特征選擇的文章
1. http://www.blogjava.net/zhenandaci/archive/2009/04/19/266388.html 特征選擇與特征權重計算的區別
2. http://www.blogjava.net/zhenandaci/archive/2009/03/24/261701.html 特征選擇方法之信息增益
3. http://www.blogjava.net/zhenandaci/archive/2008/08/31/225966.html 特征選擇算法之開方檢驗
1.2.3 特征抽取
另外一種解決維度災難的思路就是特征抽取。同樣是降維,相比特征選擇,特征抽取采用了一種高級的方法來進行。Topic Modeling是原理就是將利用映射將高緯度空間映射到低緯空間,從而達到降維的目的。具體可以見2.1特征抽取部分
1.3 計算特征權重
給定一個樣本,如何轉換成向量呢?
首先給一張流程圖:
圖 1.1‑2 計算特征權重的流程
流程:
1)首先,對樣本進行分詞,提取出所有的詞。
2)根據已經生成的詞典,如果詞典中的詞出現,就在相應對應的位置填入該詞的詞頻。
3)對生成的向量進行歸一化
上面的所示的方法是比較簡單的一種,其中特征權重采用的為詞頻來表示,現在比較常用的特征權重的計算方式為TF*IDF,TF*RF。詳見2.3 特征權重
1.4 模型訓練與預測
當把文本轉換成向量的形式后,大部分的工作其實已經做完了。后面所要做的就是利用算法進行訓練和預測了。
現在文本分類的算法很多,常見的有Naïve Bayes,SVM,KNN,Logistic回歸等。其中SVM據文獻中說是在工業界和學術界通吃的,不過據我了解現在公司里用SVM來做分類的不多 = =,而Logistic回歸則是比較常用的,因為相對來說簡單,而且可以並行化訓練。最重要是簡單可依賴。
而至於這些算法具體是什么我這里也不再累述了,因為網絡上介紹相關的算法的文獻很多,而且源程序也很多。可以直接下來下來使用。
資料與程序
1. http://nlp.stanford.edu/IR-book/html/htmledition/naive-bayes-text-classification-1.html介紹NaïveBayes方法如何應用在文本分類上
2. http://blog.163.com/jiayouweijiewj@126/blog/static/17123217720113115027394/ 詳細分析了Mahout中如何實現NaïveBayes
3. http://www.csie.ntu.edu.tw/~cjlin/libsvm/ Libsvm是用來進行SVM訓練與預測的開源工具。下載下來就可以直接用,作者的文檔寫的很詳細。
4. http://www.blogjava.net/zhenandaci/category/31868.htmlSVM的八股介紹,講解的還是通俗易懂的
5. http://blog.pluskid.org/?page_id=683 介紹支持向量機的
6. https://code.google.com/p/tmsvm/ Tmsvm是我之前寫的利用svm進行文本分類的程序,涉及到文本分類的所有流程。
1.5 進一步閱讀:
文本分類的技術已經被研究了很多年,所以相關的資料也是非常多,可以進一步閱讀下面的一些資料
1. http://www.blogjava.net/zhenandaci/category/31868.html?Show=All 這里有一個文本分類的入門系列,介紹的還是比較詳細的。
2. 《文本挖掘中若干關鍵問題研究》,這本書很薄,但是寫的很深入,對文本挖掘的一些重點問題進行了討論
2 若干問題的討論
2.1 特征選擇
特征選擇是就是依據某種權重計算公式從詞典中選擇一些有代表性的詞。常用的特征選擇的方法有很多種,Chi、Mutual Information、Information Gain。另外TF、IDF也可以作為特征選擇的一種方法。在這個問題上很多人做了大量的實驗,Chi方法是效果最好的一種,所以本系統(指的是TMSVM)中采用了這種方法。關於特征選擇無論是Wikipedia還是Paper中都有很細致的講解。
2.2 特征抽取
特征抽取和特征選擇都是為了降維。特征選擇的方法是從詞典中選出一些有代表性的詞,而特征抽取是利用映射將高緯度空間映射到低緯空間,從而達到降維的目的。最常見的特征抽取的方法是Latent Semantic Analysis(潛在語義分析),其中LSA也被稱作Topic Modeling,比較常用的Topic Modeling的方法有LSA、PLSA、LDA。之前使用的方法LSA。
假設原來的詞-文檔矩陣為,即有m個term,n篇文檔。表示第j篇文檔的向量。,經過SVD分解后,選擇前k個特征值后。再去重組文檔的特征向量,,這樣新的文檔特征向量就由原來的m維降至k維。而一個新的文檔即可通過,映射到U空間上。其實還有另外一種方法,就是,但是在實驗中發現,前一種映射效果會更好一點。另外wikipedia上對LSA也有很詳細的闡述
本系統將LSA用來Classification上的方法是一種叫做local relevancy weighted LSI的方法。其主要步驟為
* 模型訓練
① 訓練初始分類器C0
② 對訓練樣本預測,生成初始分值
③ 文檔特征向量變換
④ 設定閾值,選擇top n文檔作為局部LSA區域
⑤ 對局部詞/文檔 矩陣做SVD分解。得到U、S、V矩陣
⑥ 將其他的訓練樣本映射到U空間中
⑦ 對所有經過變換后的訓練樣本進行訓練,得到LSA分類器
* 模型預測
① 利用C0預測得到其初始分值
② 文檔特征向量變換
③ 映射到U空間
④ 利用LSA模型進行預測得分
2.3 特征權重計算
文檔特征向量的特征權重計算的一般公式為,即第i個term在第j篇文檔向量中的權重。其中Local(i,j)被稱為局部因子,與term在文檔中出現的次數有關。global(i)又稱為term的全局因子,與在整個訓練集中term出現有關。通常我們熟悉的公式都可以轉化為這一個通用的表達式。如最常用的tf形式,tf*idf形式。因此我們就可以在構造詞典的時候就計算term的全局因子,把這個值放在詞典中,然后在計算特征權重的時候直接調用。
具體的流程圖如下:
圖 2.3‑1 特征權重的計算流程
在Classification中哪種特征權重的計算方式最好??tf*idf ?在文獻中最常用的是tf*idf,但是其效果並一定好。曾經有人也在這上面做了一些工作,比如新加坡國立大學的Man Lan曾在ACM和AAAI上發表過文章來闡述這個問題。Zhi-Hong Deng也對各種feature weight的方法做了系統的比較,最終的結論是tf*idf並不是最佳的,而最簡單的tf表現不錯,一些具有區分性的方法比如tf*chi等效果差強人意。
后來Man Lan在09年發表了一篇論文,對term weighting方法做了一個綜合細致的闡述,並對其提出的tf*rf方法做了各方面的論證。
2.4 TSVM的模型訓練和預測流程
訓練過程:對文本自動做SVM模型的訓練。包括Libsvm、Liblinear包的選擇,分詞,詞典生成,特征選擇,SVM參數的選優,SVM模型的訓練等都可以一步完成。示意圖見下面
圖 2.4‑1 TMSVM模型訓練流程
模型預測過程:
圖 2.4‑2 多個模型同時預測流程
模型結果:
模型會返回兩個結果:label和score,其中label即其預測的標簽。而score是該樣本屬於該類的隸屬度,分值越大,代表屬於該類的置信度越大。具體的計算方式則是根據公式,,其中k為所有支持判別類得個數,n為所有類別個數,si 為所有支持判別類的分數。返回score的好處是對與information filtering問題,因為訓練樣本的unbalance和randomly sampling 問題,依據判別的標簽得到的結果准確率較低,因此需要通過閾值控制。
2.5 SVM參數選擇
Libsvm中最重要的兩個參數為C和gamma。C是懲罰系數,即對誤差的寬容度。c越高,說明越不能容忍出現誤差。C過大或過小,泛化能力變差。gamma是選擇RBF函數作為kernel后,該函數自帶的一個參數。隱含地決定了數據映射到新的特征空間后的分布,gamma越大,支持向量越少,gamma值越小,支持向量越多。支持向量的個數影響訓練與預測的速度。這個問題Chih-Jen Lin在其主頁上有詳細的介紹。
而Liblinear的C參數也是非常重要的。
因此在系統中會通過5-flods交叉驗證的方法對一定范圍內的C,gamma進行grid 搜索,關於grid搜索可以參考論文以及libsvm中tool文件夾中grid.py源文件。grid搜索是可以得到全局最優的參數的。
為了加快SVM參數搜索的效率,采用兩種粒度的搜索粗粒度和細粒度,兩種搜索方式的區別就是搜索步長不同。粗粒度是指搜索步長較大,為了能在較大的搜索范圍內找到一個最優解所在的大體區域。細粒度搜索搜索步長較小,為了能在一個較小范圍內找到一個精確參數。
而對與大樣本的文件,使用上面的方法仍然會比較耗費時間。為了進一步提高效率,同時在保證得到全局最優的情況下,先對選擇大樣本的子集進行粗粒度的搜索,然后得到在得到的最優區間內對全量樣本進行細粒度的搜索。
2.6 SVM參數選擇的並行化
SVM對訓練過程還是比較久的,尤其是為了能夠找到最合適的參數。自然就想到能不能對SVM的巡檢並行化。我之前做的方法是對參數的選擇並行化,而單個參數的訓練還是放在一個機器上串行進行。我把訓練的方法放在我博客上,就不再粘貼到這里了。
2 Libs與liblinear的多分類策略
2.7 Libsvm 與liblinear的多分類策略
libsvm的多分類策略為one-againt-one。總共有k*(k-1)/2個binary classifier,對這k*(k-1)/2個binary classifier的value進行遍歷,如果第i個類和第j個類binary 的classifier的value大於0,則會給第i個類投1票,否則給第j個類投1票。選擇最終獲得投票數最多的類作為最終的類別。
而liblinear的策略為one-against-rest。總共有k個binary classifier。從所有binary classifier中選擇值最大多對應的類別作為最終的預測類標簽。
重復樣本對SVM模型的影響
2.8 重復樣本對SVM模型的影響
重復樣本對於SVM模型有怎樣的影響呢?
我自己做了個實驗,用來看重復樣本的影響。
原有一個訓練樣本共有Positive樣本1000,Negative樣本2000,然后將Positive樣本*2,構造了一個Positive樣本2000,Negative樣本2000的訓練樣本。然后測試一個包含Positive樣本4494 ,Negative樣本24206的樣本。最終的結果如下:
圖2.8‑1重復樣本對結果影響
從結果上來看:在F值上,無重復的樣本會比重復樣本稍高(圖中保留了2位小數,其實差異不超過0.5%)。而正確率上,重復樣本會比無重復樣本稍高。
然后我又把模型放入到一個包含3千萬樣本中去測試,具體的指標無法測算。但是感覺還是重復樣本會好一點。
具體分析:
1、 一個樣本被重復的多次,意義上相當於增加了該樣本的權重。在SVM有一種WeightedInstance。在正常樣本難免會有些誤判,如果同一條樣本同時出現在Positive和Negative類中,包含重復樣本的Positive類就會把Negative類誤判的樣本的影響抵消。而在SVM分類中對這些離群點會用懲罰函數進行控制。
2、 但是如果保留重復樣本,會增加樣本的量,對libsvm來說,分類的復雜度為O(Nsv3),而且如果一個樣本是支持向量,那么所有重復的樣本也都會被加入到支持向量中去。而且如果要為SVM模型選擇合適的參數的,如果在SVM選擇的是RBF核函數,挑選合適的懲罰cost和RBF的參數gramma,如果在都是在[1,5,0.5]進行挑選,則總共會有9*9=81組參數需要挑選,在每組參數下如果要進行5-flods的交叉驗證,則需要81*5=405次訓練與測試的過程。如果每次訓練與測試花費2分鍾(在樣本達到10萬數量級的時候,libsvm的訓練時間差不多按分鍾計算),則總共需要405*2/60=12.3小時,所以說訓練一個好的SVM模型十分不容易。因此如果去掉重復樣本對訓練效率來說大有裨益。
2.9 將分類應用與信息過濾
分類應用與信息過濾,對最終效果影響最大的是什么?分類算法?詞典大小?特征選擇?模型參數?這些都會影響到最終的過濾效果,但是如果說對過濾效果影響最大的,還是訓練樣本的采樣。
現在基於機器學習的分類算法一般都是基於一個假設:訓練集和測試集的分布是一致的,這樣在訓練集上訓練出來的分類器應用與測試集時其效果才會比較有效。
但是信息過濾面對的數據集一般是整個互聯網,而互聯網的數據集一般很難去隨機采樣。如下圖所示:通常來說,信息過濾或其它面向全互聯網的應用在分類,選擇數據集時,需要包含P(Positive,即用戶感興趣的樣本),N(Negative,即用戶不關心、不敢興趣的樣本)。最理想的情況是:P選擇是用戶感興趣的,而N是全網中除去P,顯而易見N是無限大的,而且很難估計其真正的分布,即無法對其隨機取樣。
圖2.9‑1樣本分布
同樣面對整個互聯網的應用時網頁分類,網頁分類應用一般會選擇Yahoo!或者是專門整理網頁分類專門網站的網頁作為初始訓練樣本。
信息過濾的樣本一般來說,感興趣的樣本是很好隨機采樣的。但是與感興趣相對於的是正常樣本,這個很難去選擇。而正常樣本對全網測試效果是影響非常大的。我曾經做過一個實驗:
首先,有一個包含5萬條樣本的數據集,有2.5萬條Positive樣本,2.5萬條Negative樣本。這里的Negative樣本是以前用關鍵字的方法找出的不正確的樣本。用4萬條樣本做訓練樣本,用1萬條樣本做測試樣本。訓練出得模型交叉驗證的結果可以達到97%以上。在測試樣本中的測試效果,然后選定閾值為0.9,這是的召回率可以達到93%,正確率為96%。
然后把這個模型放到一個包含3千萬條中去測試,設置閾值為0.9,共找出疑似違規樣本300萬條。對這個實驗來說,召回的樣本實在是太多了,其正確率是很低的。
然后,我又更換了一下正常樣本。從這3千萬樣本中隨機采樣出3萬條樣本,然后經過校驗,將其中Positive的樣本剔除掉。剩下大約2萬7千條樣本放入到訓練樣本重新訓練。
把得到的新模型放到3千萬樣本中測試,同樣設置閾值為0.9,共找出疑似樣本15萬。正確率可以達到70%左右。所以正常樣本的隨機選擇對分類來說同樣至關重要。
舉一個小例子:
下圖左面的圖是用P和N訓練出得模型。右面的圖中有一個未知的類C,根據已知的模型,他應該會被分入到P中,但是實際上他是不屬於P的。一般情況下,這種情況可以用閾值來控制。
圖2.9‑2分類用於信息過濾
2.10 SVM解決樣本傾斜的問題
所謂數據偏斜(unbalanced),它指的是參與分類的兩個類別(也可以指多個類別)樣本數量差異很大。比如說正類有10,000個樣本,而負類只給了100個,這會引起的問題顯而易見,可以看看下面的圖:
圖2.10‑1樣本傾斜示例
方形的點是負類。H,H1,H2是根據給的樣本算出來的分類面,由於負類的樣本很少很少,所以有一些本來是負類的樣本點沒有提供,比如圖中兩個灰色的方形點,如果這兩個點有提供的話,那算出來的分類面應該是H’,H2’和H1,他們顯然和之前的結果有出入,實際上負類給的樣本點越多,就越容易出現在灰色點附近的點,我們算出的結果也就越接近於真實的分類面。但現在由於偏斜的現象存在,使得數量多的正類可以把分類面向負類的方向“推”,因而影響了結果的准確性。
具體的解決方法還是看我博客上的文章吧,這里就不單獨貼出來了。
2.11 其他
文本分類的問題點很多,之前還想再寫寫如何對短文本(比如query)進行分類,利用利用Wikipedia的知識增強文本分類的效果,如何利用未標記樣本來提高分類的效果。現在時間不多,等有時間了再繼續深入的寫吧。