首頁 >後端開發 >Python教學 >Python文字特徵抽取與向量化演算法學習實例詳解

Python文字特徵抽取與向量化演算法學習實例詳解

小云云
小云云原創
2017-12-23 17:05:575234瀏覽

假設我們剛看完諾蘭的大片《星際效應》,設想如何讓機器自動分析各位觀眾對電影的評價到底是「讚」(positive)還是「踩」(negative)呢?這類問題就屬於情緒分析問題。這類問題處理的第一步,就是將文字轉換為特徵。本文主要為大家詳細介紹了Python文本特徵抽取與向量化演算法,具有一定的參考價值,有興趣的小夥伴們可以參考一下,希望能幫助大家。

因此,這章我們只學習第一步,如何從文本中抽取特徵,並將其向量化。

由於中文的處理涉及分詞問題,本文用一個簡單的例子來說明如何使用Python的機器學習庫,對英文進行特徵提取。

1、資料準備

Python的sklearn.datasets支援從目錄讀取所有分類好的文字。不過目錄必須依照一個資料夾一個標籤名的規則放好。例如本文所使用的資料集共有2個標籤,一個為“net”,一個為“pos”,每個目錄下面有6個文字檔。目錄如下圖所示:

neg
    1.txt
    2.txt
    ......
pos
    1.txt
    2##pos
    1.txt
    2##pos

    1.txt

    2 .txt
    ....


12個檔案的內容總結如下:

neg: 
  shit. 
  waste my money. 
  waste of money. 
  sb movie. 
  waste of time. 
  a shit movie. 
pos: 
  nb! nb movie! 
  nb! 
  worth my money. 
  I love this movie! 
  a nb movie. 
  worth it!


#2、文本特徵

如何從這些英文中抽取情感態度而分類呢?


最直觀的做法就是抽取單字。通常認為,許多關鍵字能夠反映說話者的態度。例如上面這個簡單的資料集,很容易發現,凡是說了「shit」的,就一定屬於neg類。
當然,上面資料集是為了方便描述而簡單設計的。現實中一個字常會有穆稜兩可的態度。但仍然有理由相信,某個單字在neg類中出現的越多,那麼他表示neg態度的機率越大。
同樣我們注意到有些單字對情感分類是毫無意義的。例如上述數據中的“of”,“I”之類的單字。這類字有個名字,叫做「

Stop_Word

」(停用詞)。這類詞是可以完全忽略不做統計的。顯然忽略掉這些詞,詞頻記錄的儲存空間能夠優化,而且建置速度也更快。 把每個單字的字頻當作重要的特徵也存在一個問題。例如上述數據中的」movie「,在12個樣本中出現了5次,但是出現正反兩邊次數差不多,沒有什麼區分度。而」worth「出現了2次,但只出現在pos類中,顯然更具有強烈的剛晴色彩,即區分度很高。 因此,我們需要引入

TF-IDF

(Term Frequency-Inverse Document Frequency,詞頻和逆向檔案頻率)對每個單字做進一步考量。

TF(詞頻)的計算很簡單,就是針對一個檔案t,某個單字Nt 出現在該文件中的頻率。例如文檔“I love this movie”,單字“love”的TF為1/4。如果去掉停用詞“I"和”it“,則為1/2。


IDF(逆向文件頻率)

的意義是,對於某個單字t,凡是出現了該單字的文檔數Dt,佔了全部測試文檔D的比例,再求自然對數。

例如單字「movie「總共出現了5次,而文檔總數為12,因此IDF為ln(5/12)。 很顯然,IDF是為了凸顯那種出現的少,但是佔有強烈感情色彩的字眼。例如「movie」這樣的字的IDF=ln(12/5)=0.88,遠小於「love」的IDF=ln(12/1)=2.48。

TF-IDF就是把二者簡單的乘在一起即可。這樣,求出每個文檔中,每個單字的TF-IDF,就是我們提取得到的文字特徵值。


3、向量化


有了上述基礎,就能夠將文件向量化了。我們先看程式碼,再來分析向量化的意義:

############
# -*- coding: utf-8 -*- 
import scipy as sp 
import numpy as np 
from sklearn.datasets import load_files 
from sklearn.cross_validation import train_test_split 
from sklearn.feature_extraction.text import TfidfVectorizer 
 
'''''加载数据集,切分数据集80%训练,20%测试''' 
movie_reviews = load_files('endata')  
doc_terms_train, doc_terms_test, y_train, y_test\ 
  = train_test_split(movie_reviews.data, movie_reviews.target, test_size = 0.3) 
   
'''''BOOL型特征下的向量空间模型,注意,测试样本调用的是transform接口''' 
count_vec = TfidfVectorizer(binary = False, decode_error = 'ignore',\ 
              stop_words = 'english') 
x_train = count_vec.fit_transform(doc_terms_train) 
x_test = count_vec.transform(doc_terms_test) 
x    = count_vec.transform(movie_reviews.data) 
y    = movie_reviews.target 
print(doc_terms_train) 
print(count_vec.get_feature_names()) 
print(x_train.toarray()) 
print(movie_reviews.target)

运行结果如下:
[b'waste of time.', b'a shit movie.', b'a nb movie.', b'I love this movie!', b'shit.', b'worth my money.', b'sb movie.', b'worth it!']
['love', 'money', 'movie', 'nb', 'sb', 'shit', 'time', 'waste', 'worth']
[[ 0.          0.          0.          0.          0.          0.   0.70710678  0.70710678  0.        ]
 [ 0.          0.          0.60335753  0.          0.          0.79747081   0.          0.          0.        ]
 [ 0.          0.          0.53550237  0.84453372  0.          0.          0.   0.          0.        ]
 [ 0.84453372  0.          0.53550237  0.          0.          0.          0.   0.          0.        ]
 [ 0.          0.          0.          0.          0.          1.          0.   0.          0.        ]
 [ 0.          0.76642984  0.          0.          0.          0.          0.   0.          0.64232803]
 [ 0.          0.          0.53550237  0.          0.84453372  0.          0.   0.          0.        ]
 [ 0.          0.          0.          0.          0.          0.          0.   0.          1.        ]]
[1 1 0 1 0 1 0 1 1 0 0 0]

python输出的比较混乱。我这里做了一个表格如下:

从上表可以发现如下几点:

1、停用词的过滤。

初始化count_vec的时候,我们在count_vec构造时传递了stop_words = 'english',表示使用默认的英文停用词。可以使用count_vec.get_stop_words()查看TfidfVectorizer内置的所有停用词。当然,在这里可以传递你自己的停用词list(比如这里的“movie”)

2、TF-IDF的计算。

这里词频的计算使用的是sklearn的TfidfVectorizer。这个类继承于CountVectorizer,在后者基本的词频统计基础上增加了如TF-IDF之类的功能。
我们会发现这里计算的结果跟我们之前计算不太一样。因为这里count_vec构造时默认传递了max_df=1,因此TF-IDF都做了规格化处理,以便将所有值约束在[0,1]之间。

3、count_vec.fit_transform的結果是一個巨大的矩陣。我們可以看到上表中有大量的0,因此sklearn在內部實作上使用了稀疏矩陣。本範例數據較小。如果讀者有興趣,可以試試機器學習科學研究工作者使用的真實數據,來自康乃爾大學:http://www.cs.cornell.edu/people/pabo/movie-review-data/。這個網站提供了很多資料集,其中有幾個2M左右的資料庫,正反例700個左右。這樣的數據規模也不算大,1分鐘內還是可以跑完的,建議大家試試看。不過要注意這些資料集可能有非法字元問題。所以在構造count_vec時,傳入了decode_error = 'ignore',以忽略這些非法字元。

上表的結果,就是訓練8個樣本的8個特徵的一個結果。這個結果就可以使用各種分類演算法來分類了。

相關推薦:

分享Python文字產生二維碼實例

Python文本相似性計算之編輯距離詳解

實例詳解Python實作簡單網頁圖片抓取

以上是Python文字特徵抽取與向量化演算法學習實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn