[ML with Sklearn]特徵提取與處理
①分類變數特徵提取
分類變數通常用獨熱編碼(One-of-K or One-Hot Encoding),通過二進位制來表示每個自變數特徵。
例如,假設city變數有三個值:New York, San Francisco, Chapel Hill。獨熱編碼方式就是用三位二進位制數表示city特徵,其中每一位代表一個城市。
利用sklearn.feature_extraction.DictVectorizer(dtype=<type ‘numpy.float64’>, separator=’=’,sparse=True, sort=True)類可以用來表示分類特徵:
經過fit_transform函式生成的是一個按行格式壓縮矩陣,csr_matrix物件具有兩個重要屬性:In [1]: from sklearn.feature_extraction import DictVectorizer ...: onehot_encoder = DictVectorizer() ...: instances = [{'city':'New York'},{'city':'San Francisco'},{'city':'Chap ...: el Hill'}] ...: onehot_encoder.fit_transform(instances) ...: Out[1]: <3x3 sparse matrix of type '<class 'numpy.float64'>' with 3 stored elements in Compressed Sparse Row format> In [2]: type(onehot_encoder.fit_transform(instances)) Out[2]: scipy.sparse.csr.csr_matrix In [3]: print(onehot_encoder.fit_transform(instances)) (0, 1) 1.0 (1, 2) 1.0 (2, 0) 1.0
In [4]: onehot_encoder.fit_transform(instances).data
Out[4]: array([ 1., 1., 1.])
In [5]: onehot_encoder.fit_transform(instances).indices
Out[5]: array([1, 2, 0], dtype=int32)
通過上述結果可知:第0行1列、第1行2列、第3行第0列存放元素1,其他位置都是存放0
將行壓縮矩陣轉換成陣列,驗證上述結果
vocabulary_屬性:各個詞彙對應的編碼In [6]: onehot_encoder.fit_transform(instances).toarray() Out[6]: array([[ 0., 1., 0.], [ 0., 0., 1.], [ 1., 0., 0.]])
In [7]: onehot_encoder.vocabulary_
Out[7]: {'city=Chapel Hill': 0, 'city=New York': 1, 'city=San Francisco': 2}
②文字特徵提取
將文字轉換成可以量化的特徵向量,常用的文字表示方法:詞庫模型(Bag-of-words model)
1、詞庫表示法
詞庫模型是文字模型化的最常用方法。詞庫模型可以看成是獨熱編碼的一種擴充套件,它為每個單詞設定一個特徵值。對於一個文件,忽略其詞序、語法、句法,僅僅當成一個詞集合,文件中每個詞的出現都是獨立的,不受其他前後字的影響。詞庫模型可以通過有限的編碼資訊實現有效的文件分類和檢索。
一批文件的集合稱為文集(corpus)。文件的單詞構成詞彙表(vocabulary)。詞庫模型用文集的詞彙表中每個單詞的特徵向量表示每個文件。構成特徵向量的元素稱為維度,用一個詞典來表示詞彙表與特徵向量索引的對應關係。在大多數詞庫模型中,特徵向量的每個元素用一個二進位制數表示單詞是否在文件中出現。
文件詞塊化(tokenize)是把句子分隔成詞塊(token)或者是有意義的字母序列的過程。詞塊大多是單詞,但是他們也可能是一些短語,如標點符號和詞綴。CountVectorizer類會把文件全部轉換成小寫,然後將文件詞塊化(tokenize),CountVectorizer類通過正則表示式用空格分割句子,然後抽取長度大於等於2的字母序列。
In [8]: from sklearn.feature_extraction.text import CountVectorizer
...: corpus = [
...: 'UNC played Duke in basketball',
...: 'Duke lost the basketball game',
...: 'I ate a sandwich'
...: ]
...: vc = CountVectorizer()
...: vc.fit_transform(corpus).toarray()
...:
Out[8]:
array([[0, 1, 1, 0, 1, 0, 1, 0, 0, 1],
[0, 1, 1, 1, 0, 1, 0, 0, 1, 0],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 0]], dtype=int64)
文集中有12個單詞,我們會發現詞彙表中只有10,其中I和a字元長度為1,不滿足CountVectorizer類要求
In [9]: vc.vocabulary_
Out[9]:
{'ate': 0,
'basketball': 1,
'duke': 2,
'game': 3,
'in': 4,
'lost': 5,
'played': 6,
'sandwich': 7,
'the': 8,
'unc': 9}
可以採用歐式距離來計算文件間的相似度,兩向量的歐氏距離就是兩個向量歐氏範數(Euclidean norm)或L2範數差的絕對值E ,向量的歐氏範數是其元素平方和的平方根,在scikit-learn裡面的euclidean_distances函式可以計算若干向量的距離,表示兩個語義最相似的文件其向量在空間中也是最接近的。In [10]: from sklearn.metrics.pairwise import euclidean_distances
...: counts = vc.fit_transform(corpus).todense()
...: for x ,y in [[0,1],[0,2],[1,2]]:
...: dist = euclidean_distances(counts[x],counts[y])
...: print('文件{0}與文件{1}的距離{2}'.format(x,y,dist))
...:
文件0與文件1的距離[[ 2.44948974]]
文件0與文件2的距離[[ 2.64575131]]
文件1與文件2的距離[[ 2.64575131]]
由於文集是所有文章的集合,因此詞彙表中的單詞可能成千上萬,每片文件的特徵向量中會出現大量0元素,出現問題:①稀疏向量,需要利用numpy提供的稀疏向量處理只顯示非0的元素,減少儲存 ,②維度災難問題,維度越多,需要更多的訓練樣本來保證模型能夠充分學習,樣本不夠,可能出現過擬合,因此需要採用降維技術處理
2、停用詞過濾
特徵向量降維:①單詞全部轉換成小寫 ②去掉文集常用詞(停用詞),停用詞通常是構建文件意思的功能詞彙,其字面意義並不體現。CountVectorizer類可以通過設定stop_words引數過濾停用詞,預設是英語常用的停用詞(介詞、助詞等)。
In [12]: from sklearn.feature_extraction.text import CountVectorizer
...: corpus = [
...: 'UNC played Duke in basketball',
...: 'Duke lost the basketball game',
...: 'I ate a sandwich'
...: ]
...: vc = CountVectorizer(stop_words='english')
...: vc.fit_transform(corpus).todense()
...:
Out[12]:
matrix([[0, 1, 1, 0, 0, 1, 0, 1],
[0, 1, 1, 1, 1, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 1, 0]], dtype=int64)
In [13]: vc.vocabulary_
Out[13]:
{'ate': 0,
'basketball': 1,
'duke': 2,
'game': 3,
'lost': 4,
'played': 5,
'sandwich': 6,
'unc': 7}
3、詞根還原(stemming)與詞性還原(lemmatization)
特徵向量裡面的單詞很多都是一個詞的不同形式,詞根還原與詞形還原就是為了將單詞從不同的時態、派生形式還原。
In [14]: from sklearn.feature_extraction.text import CountVectorizer
...: corpus = ['He ate the sandwiches',
...: 'Every sandwich was eaten by him'
...: ]
...: vc = CountVectorizer(binary=True,stop_words='english')
...: vc.fit_transform(corpus).todense()
...:
Out[14]:
matrix([[1, 0, 0, 1],
[0, 1, 1, 0]], dtype=int64)
In [15]: vc.vocabulary_
Out[15]: {'ate': 0, 'eaten': 1, 'sandwich': 2, 'sandwiches': 3}
詞形還原就是用來處理可以表現單詞意思的詞元(lemma)或形態學的詞根(morphological root)的過程。詞元是單詞在詞典中查詢該詞的基本形式。詞根還原與詞形還原類似,但它不是生成單詞的形態學的詞根。而是把附加的詞綴都去掉,構成一個詞塊,可能不是一個正常的單詞。詞形還原通常需要詞法資料的支援。詞根還原演算法通常需要用規則產生詞幹(stem)並操作詞塊,不需要詞法資源,也不在乎單詞的意思。
參考:《.Mastering Machine Learning with scikit-learn》