1. 程式人生 > >[ML with Sklearn]特徵提取與處理

[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)類可以用來表示分類特徵:

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
經過fit_transform函式生成的是一個按行格式壓縮矩陣,csr_matrix物件具有兩個重要屬性:
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

將行壓縮矩陣轉換成陣列,驗證上述結果

In [6]: onehot_encoder.fit_transform(instances).toarray()
Out[6]:
array([[ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.]])
vocabulary_屬性:各個詞彙對應的編碼
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》