基于libsvm的中文文本分类原型
支持向量機(Support Vector Machine)是Cortes和Vapnik于1995年首先提出的,它在解決小樣本?、非線性及高維模式識別?中表現出許多特有的優勢,并能夠推廣應用到函數擬合等其他機器學習問題中。支持向量機方法是建立在統計學習理論的VC 維理論和結構風險最小?原理基礎上的,根據有限的樣本信息在模型的復雜性(即對特定訓練樣本的學習精度,Accuracy)和學習能力(即無錯誤地識別任意樣本的能力)之間尋求最佳折衷,以期獲得最好的推廣能力(或稱泛化能力)。SVM理論的學習,請參考jasper的博客?。
??? LIBSVM 是臺灣大學林智仁(Chih-Jen Lin)博士等開發設計的一個操作簡單、易于使用、快速有效的通用 SVM 軟件包,可以解決分類問題(包括 C?SVC 、ν?SVC ), 回歸問題(包括 ε ? SVR 、v? SVR )? 以及分布估計(one ? class ? SVM ) 等問題,提供了線性、多項式、徑向基和 S 形函數四種常用的核函數供選擇,可以有效地解決多類問題、交叉驗證選擇參數、對不平衡樣本加權、多類問題的概率估計等。LIBSVM?是一個開源的軟件包,。他不僅提供了 LIBSVM 的 C++語言的算法源代碼,還提供了 Python、Java、R、MATLAB、Perl、Ruby、LabVIEW以及 C#.net 等各種語言的接口,可以方便的在 Windows 或 UNIX 平臺下使用,也便于科研工作者根據自己的需要進行改進(譬如設計使用符合自己特定問題需要的核函數等)。
??? 文本分類,大致分為如下幾件事情:樣本?,分詞?,特征提取?,向量計算?,分類訓練?,測試和調試?。
?
1.樣本選擇
搜狗語料?http://www.sogou.com/labs/dl/c.html?,下精簡版吧,如果實驗用用,這足夠了,你要下107M的也可以。當然,你也可以自己找語料,不過麻煩點而已,把各大門戶網站的對應頻道下的文章都爬下來。
?
2.分詞
Bamboo分詞,這是基于CRF++的分詞模塊,既然是研究統計學習,分詞也得用基于統計的不是,如果還是用一字典來分詞,那就太out啦。
http://code.google.com/p/nlpbamboo/wiki/GettingStarted?。安裝完畢bamboo,還要下載訓練好的模型(這個模型是基于人民日報1月語料)
http://code.google.com/p/nlpbamboo/downloads/list?,下載index.tar.bz2, 解壓到/opt/bamboo/index下。
因為咱主要目的是研究分類,不是分詞,就不要去搞分詞的訓練了,如果想訓練可以看我的另外一篇博客:CRF++中文分詞指南?。
nlpbamboo安裝的幾個要點
1、CRF++使用默認目錄安裝2、編譯完nlpbamboo后執行下/opt/bamboo/bin/bamboo看看bamboo是否安裝成功
如果提示ERROR: libcrfpp.so.0: cannot open shared object file: No such file or directory需要執行以下操作
ln -s /usr/local/lib/libcrfpp.so.* /usr/lib/
ldconfig
3、安裝PHP擴展后下載index.tar.bz2這個模型,然后在php.ini中添加
bamboo.parsers = crf_seg
因為官方的 index.tar.bz2 中只包含 crf_seg 的 model,所以不加 crf_pos 那些;否則php將無法
可以試試:/opt/bamboo/bin/bamboo -p crf_seg filename,如果成功證明裝好了。
??? 稍微注意以下,搜狗的詞庫是gb2312的,所以,請轉為utf8,再分詞,這是python寫的函數:輸入一個文件名,轉為utf8,再分詞,分詞文件以.seg為后綴。
分詞結果如下:
一 家 剛剛 成立 兩 年 的 網絡 支付 公司 , 它 的 目標 是 成為 市值 100億 美元 的 上市 公司 。
這家 公司 叫做 快 錢 , 說 這 句 話 的 是 快錢 的 CEO 關 國光 。 他 之前 曾 任 網易 的 高級 副 總裁 , 負責 過 網易 的 上市 工作 。 對于 為什么 選擇 第三 方 支付 作為 創業 方向 , 他 曾經 對 媒體 這樣 說 : “ 我 能 看到 這個 胡同 對面 是 什么 , 別人 只能 看到 這個 胡同 。 ” 自信 與 狂妄 只 有 一 步 之 遙 ―― 這 幾乎 是 所有 創業者 的 共同 特征 , 是 自信 還是 狂妄 也許 需要 留待 時間 來 考證 。
?
3.特征提取
??? svm不是在高維模式識別具有優勢嗎,咋還要特征提取呢,把所有詞都當成特征不就行了嗎?對于詞庫來說,十幾萬的詞是很常見的,把對類別區分度(GDP,CPI,股票對經濟類的區分度就高,其他一些高頻詞,如我們,大家,一起等就沒有區分度)高的詞挑選出來,一來可以減少計算量,二來應該是可以提高分類效果。
???? 據說,開方檢驗(CHI)信息增益(IG)對于挑選特征好,我選擇的是CHI。兩者的概念,請google。
??? 首先統計詞在文檔中的次數
[python]?view plaincopy?
分別計算每個詞的a/b/c/d
a:在這個分類下包含這個詞的文檔數量
b:不在該分類下包含這個詞的文檔數量
c:在這個分類下不包含這個詞的文檔數量
d:不在該分類下,且不包含這個詞的文檔數量
因為前面統計了每個類下,每個詞,文章數和每個詞,每個類,文章數。所以很容易得到a,b,c,d的值。
z1 = a*d - b*c
x2 = (z1 * z1 * float(N)) /( (a+c)*(a+b)*(b+d)*(c+d) )
?
計算之后,排序,并取出前1000個詞(這里指的每個類別的特征詞)。
li = sorted(termchi.iteritems(), key=lambda d:d[1], reverse = True)
循環每個分類,并把每個類別的特征合并(合并成一個文件,作為特征詞典),合并后存為feature文件,第一列是序號,第二列是對應的詞,序號就是特征號。
1?????? 逐項
2?????? 深市
3?????? 九寨溝
4?????? 島內
5?????? 期望
6?????? 第20分鐘
7?????? 合理
8?????? 謝杏芳
9?????? 賽迪
10????? 毛澤東
?
注:特征選擇的目的就是選擇在該類下,不在其他類下的特征,但是重復是避免不了的,合并的文件肯定是排重過的。先選擇每個類下的1000個詞,假如10個類,則共選擇10 * 1000個詞,然后去重,并生成特征的唯一id。
?
4.訓練和測試樣本組織
搜狐語料的1990篇中的1890作為訓練集,100篇作為測試集,分別形成train和test文件,libsvm的訓練集的格式為:
lable1 index1:featureValue1 index2:featureValue2 index3:featureValue3 ...
lable2 index1:featureValue1 index2:featureValue2 index3:featureValue3 ...
對應到文本分類上就是:類別ID 特征序號(第3步計算的特征序號):特征值(TFIDF值)......
如,我摘了一行,這是一篇文章的例子,8就是類別ID,189是特征“189 指導"的序號,0.171153是特征值:
8 189:0.171153 253:0.081381 298:0.630345 504:0.135512 562:79.423503 578:0.072219 698:0.078896 710:0.036074 740:0.215368 868:0.263524 1336:0.114355 1365:0.076494 1372:0.085780 1555:0.572497 1563:3.932806 1598:0.114717 1685:0.129870 1972:0.193693 2282:0.061828 2865:0.026699 2897:0.099020 3040:0.039621 3041:0.258073 3191:0.091276 3377:0.125544 3454:0.062189 3623:0.139698 3653:0.128304 3932:2.990233 4353:0.202133 4394:0.312992 4420:0.356354 4424:0.482424 4522:0.447795 4675:3.618182 4767:0.065334 4848:0.270417 4875:0.213588 4941:0.407453 5004:0.070447 5125:0.717893 5214:3.222299 5250:0.052897 5251:0.281352 5310:2.010101 5357:0.203956 5474:0.034037 5504:0.193900 5861:0.859426 6120:1.320504 6129:0.107941 6364:0.184225 6373:0.287843 6379:0.080727 6385:0.712241 6847:0.209023 7007:0.147802 7121:1.320504 7547:0.248161 7636:0.108981
采用TFIDF的算法,數據處理和特征選擇類似,計算每個類,每篇文檔,每個詞的次數,以包含這個詞的文檔數。每篇文章的每個特征項,用TF/DF的值作為特征值。(后記:用TF * IDF,然后用svm-scale縮放到0,1之間,效果比TF/DF要好,準確率能達到82%。,計算方式如下:
??? tf = float(times) / total
??? idf = math.log( N / float(term_count[term]) )
??? term_times[term] = tf * idf
)
?
[python]?view plaincopy?
注意:用CHI是提取類別的特征詞,而這里用TFIDF是計算文檔的特征向量,前者是要體現類別的區分度,后者要體現文檔的區分度,兩者概念和所做的事情不一樣,所以采用的方法也不一樣。
?
5.用libsvm訓練
??? 你看,忙活了半天,還沒有到libsvm呢,其實前面幾步很麻煩的,libsvm的資料不少,但是都是一個幾行數據的簡單例子,這不具有實際應用的價值,只有把樣本,分詞,特征提取/特征計算搞定了,分類才能做好。
??? 下載libsvm:http://www.csie.ntu.edu.tw/~cjlin/cgi-bin/libsvm.cgi?+http://www.csie.ntu.edu.tw/~cjlin/libsvm+zip
??? 解壓,make
??? svm-scale:特征縮放的工具??? svm-train:訓練工具? ?? svm-predict:測試工具
??? toos/grid.py:尋找參數的工具
??? 用默認參數試試:
?? ./svm-train train.s model.s
?? ./svm-predict test.s model.s result.s
?? 結果
?? Accuracy = 74.3889% (1339/1800) (classification)
?? 不算太理想,也不算太差。如果只是2個類,結果能到95%。我想可以從如下幾個方面改進:
- 增加分詞的樣本數,訓練更好的分詞模型。
- 特征提取后,用人工進行調整,因為很多詞對于類別區分度不高。
- 用grid.py尋找合適的參數。
?
參考資料:
jasper的博客,SVM理論的學習資料:http://www.blogjava.net/zhenandaci/category/31868.html
通俗易懂,要好好讀讀。
?
libsvm的官方網站:http://www.csie.ntu.edu.tw/~cjlin/libsvm/
看了理論性的東西,最好實踐以下,libsvm就是很好的實踐工具。
?
Vapnik的兩本書,我買了第二本,發現公式太多,好晦澀。準備買第一本,據說第一本比較淺顯易懂一些
《統計學習理論的本質》
http://product.dangdang.com/product.aspx?product_id=20602023&ref=search-0-A
《統計學習理論》
http://product.dangdang.com/product.aspx?product_id=20529098&ref=search-0-A
總結
以上是生活随笔為你收集整理的基于libsvm的中文文本分类原型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 文本分类 特征选取之CHI开方检验
- 下一篇: CRF++使用