當咱們嘗試使用統計機器學習方法解決文本的有關問題時,第一個須要的解決的問題是,若是在計算機中表示出一個文本樣本。一種經典並且被普遍運用的文本表示方法,即向量空間模型(VSM),俗稱「詞袋模型」。html
咱們首先看一下向量空間模型如何表示一個文本:python
空間向量模型須要一個「字典」:文本的樣本集中特徵詞集合,這個字典能夠在樣本集中產生,也能夠從外部導入,上圖中的字典是[baseball, specs, graphics,..., space, quicktime, computer]。機器學習
有了字典後即可以表示出某個文本。先定義一個與字典長度相同的向量,向量中的每一個位置對應字典中的相應位置的單詞,好比字典中的第一個單詞baseball,對應向量中的第一個位置。而後遍歷這個文本,對應文本中的出現某個單詞,在向量中的對應位置,填入「某個值」。性能
實際上填入的「某個值」,就是當前特徵詞的權重(Term Weight),目前特徵詞的權重主要有如下四種:學習
表示某個單詞是否在某個文檔中出現,若是出現則記爲1,否認則記爲0。測試
表示某個單詞在文本中出現的次數(上圖中使用的權重),一個文本中,某個特徵詞出現的愈多,可能其在樣本中的貢獻越大。ui
document frequency表示特徵詞在數據集中出現的文檔頻率。某個詞文檔頻率越低,相應的這些文檔,越容易被捕獲。spa
TF-IDF則綜合了上面兩種特徵權重的性質。3d
有關於「教育」的文檔中,「高校」、「學生」等詞出現的頻率很高,而在「體育」類的文檔中,「比賽」, 「選手」出現的頻率比很高。採用TF權重,這些特徵詞有着較高權重是合理的(Term frequency)。可是,某些詞如「這些」,「是」, 「的」,也有着較高的詞頻,可是重要度顯然沒有,「高校」、「學生」、「比賽」, 「選手」來得重要。但「這些」,「是」, 「的」這些詞IDF每每比較低,很好的彌補了TF的缺陷。所以TF-IDF權重,在傳統的文本分類,信息檢索領域有着很是普遍的運用。orm
儘管TF-IDF權重有着很是普遍的應用,並非全部的文本權重採用TF-IDF都會有較好的性能。好比,情感分類(Sentiment Classification)問題上,採用BOOL型的權重每每有較好的性能(Sentiment Classification的不少論文都採用BOOL型權重)。
如今,咱們回到文章開頭提升的向量空間模型。基於向量空間模型表示方法,每一個特徵詞之間相互獨立。因爲這種表示簡單的特色,在開始之初,推進了文本分類相關研究工做,可是隨着時間的推移,傳統的向量空間模型因爲丟棄了詞序、句法和部分語義信息,每每限制了某些領域的發展(如Sentiment Classification),成爲影響性能的瓶頸。目前的解決思路有:
最後,介紹一下sklearn中的文本的表示方法,並以此實現一個簡單的文本分類。
咱們使用的數據集是 movie_reviews 語料(情感分類器任務)。數據集的組織方式是,一個文本存放在文件下,標籤相同的文件放在同一個文件夾下。其數據集的結構以下:
movie_reviews\
pos\
cv000_29590.txt, cv001_18431.txt...cv999_13106.txt
neg\
cv000_29416.txt, cv001_19502.txt, cv999_14636.txt
在sklearn中,sklearn.datasets.load_files,能夠很好的加載這種結構的數據集,數據加載完成後,就能夠利用前面介紹的VSM,將文本樣本表示出來。
sklearn專門提供了文本特徵的提取模塊: sklearn.feature_extraction.text ,完成將一個文本樣本變成一個詞袋。CountVectorizer對應詞頻權重或是BOOL型權重(經過參數binary調節)向量空間模型, TfidfVectorizer提供了Tfidf權重下的向量空間模型。sklearn爲他們提供了大量的參數(全部參數也都提供了默認參數),具備很高的靈活性和實用性。
在movie_reviews語料上,基於 sklearn 文本表示方法,並使用Multinomial Naive Bayes分類器進行情感分類的代碼以下:
#!/usr/bin/env python # coding=gbk import os import sys import numpy as np from sklearn.datasets import load_files from sklearn.cross_validation import train_test_split from sklearn.feature_extraction.text import CountVectorizer from sklearn.naive_bayes import MultinomialNB def text_classifly(dataset_dir_name): #加載數據集,切分數據集80%訓練,20%測試 movie_reviews = load_files(dataset_dir_name) doc_terms_train, doc_terms_test, doc_class_train, doc_class_test = train_test_split(movie_reviews.data, movie_reviews.target, test_size = 0.2) #BOOL型特徵下的向量空間模型,注意,測試樣本調用的是transform接口 count_vec = CountVectorizer(binary = True) doc_train_bool = count_vec.fit_transform(doc_terms_train) doc_test_bool = count_vec.transform(doc_terms_test) #調用MultinomialNB分類器 clf = MultinomialNB().fit(doc_train_bool, doc_class_train) doc_class_predicted = clf.predict(doc_test_bool) print 'Accuracy: ', np.mean(doc_class_predicted == doc_class_test) if __name__ == '__main__': dataset_dir_name = sys.argv[1] text_classifly(dataset_dir_name)