03_數據的特徵抽取,sklearn特徵抽取API,字典特徵抽取DictVectorizer,文本特徵抽取CountVectorizer,TF-IDF(TfidfVectorizer),詳細案例

數據的特徵抽取

A:特徵抽取實例演示

通過演示得出結論:

  • 特徵抽取針對非連續型數據
  • 特徵抽取對文本等進行特徵值化

注:特徵值化是爲了計算機更好的去理解數據。

B:sklearn特徵抽取API

sklearn.feature_extraction模塊,可以用於從包含文本和圖片的數據集中提取特徵,以便支持機器學習算法使用。

注意:Feature extraction與Feature Selection是完全不同的:前者將專有數據(文本或圖片)轉換成機器學習中可用的數值型特徵;後者則是用在這些特徵上的機器學習技術。

C:字典特徵抽取

作用:對字典數據進行特徵值化

類:sklearn.feature_extraction.DictVectorizer
以下來自:https://www.cnblogs.com/hufulinblog/p/10591339.html

將特徵與值的映射字典組成的列表轉換成向量。
DictVectorizer通過使用scikit-learn的estimators,將特徵名稱與特徵值組成的映射字典構成的列表轉換成Numpy數組或者Scipy.sparse矩陣。

當特徵的值是字符串時,這個轉換器將進行一個二進制One-hot編碼。One-hot編碼是將特徵所有可能的字符串值構造成布爾型值。

例如:特徵f有一個值ham,一個值spam,轉換後會變成兩個特徵f=ham和f=spam.

注意:轉換器只會將字符串形式的特徵轉換成One-hot編碼,數值型的不會轉換。
一個字典中樣本沒有的特徵在結果矩陣中的值是0.

構造參數:
class sklearn.feature_extraction.DictVectorizer(dtype=<class‘numpy.float64’>, separator=’=’, sparse=True, sort=True)
dtype:callable, 可選參數, 默認爲float。特徵值的類型,傳遞給Numpy.array或者Scipy.sparse矩陣構造器作爲dtype參數。
separator:string,可選參數,默認爲"="。當構造One-hot編碼的特徵值時要使用的分割字符串。分割傳入字典數據的鍵與值的字符串,生成的字符串會作爲特徵矩陣的列名。
sparse: boolearn, 可選參數,默認爲True。transform是否要使用scipy產生一個sparse矩陣。DictVectorizer的內部實現是將數據直接轉換成sparse矩陣,如果sparse爲False, 再把sparse矩陣轉換成numpy.ndarray型數組。
sort:boolearn,可選參數,默認爲True。在擬合時是否要多feature_names和vocabulary_進行排序。

屬性:
vocabulary_: 特徵名稱和特徵索引的映射字典。
feature_names_: 一個包含所有特徵名稱的,長度爲特徵名稱個數的列表。

方法:
fit(X,y=None): 計算出轉換結果中feature name與列索引之間的對照字典vocabulary_,同時會計算出特徵名稱列表 feature_names_。這裏的參數y沒有任何作用。(X:字典或者包含字典的迭代器,返回值:返回sparse矩陣)
fit_transform(X,y=None): 包含fit函數的功能,並且會將X轉換成矩陣。
get_feature_names(): 返回feature_names_ (返回類別名稱)
get_params(deep=True): 返回當前DictVectorizer對象的構造參數。
inverse_transform(X[,dict_type]): 將矩陣還原成特徵字典列表。還原出來的字典跟原數據並不是完全一樣。傳入的X必須是這個DictVectorizer經過transform或者fit_transform產生的X。(X:array數組或者sparse矩陣,返回值:轉換之前數據格式)
restrict(support, indicies=False): 根據傳入的support參數,對特徵矩陣進行篩選。
**set_params(params): 設置DictVectorizer的參數
transform(X): 將X轉換爲numpy.ndarray或者Scipy.sparse (按照原先的標準轉換)

流程:
1、實例化類DictVectorizer。
2、調用fit_transform方法輸入數據並轉換。

案例1:

from sklearn.feature_extraction import DictVectorizer

def dictvec():
    """
    字典數據抽取
    :return:
    """
    #實例化
    dict = DictVectorizer(sparse=False)

    #調用fit_transform
    data = dict.fit_transform([{'city': '北京','temperature': 100}, {'city': '上海','temperature':60}, {'city': '深圳','temperature': 30}])

    print("--------------get_feature_names-----------------------------------------------")
    print(dict.get_feature_names())

    print("--------------data,含有該feature_names的爲1,否則爲0,最終的目標值是實際的值-----")
    print(data)

    print("--------------inverse_transform:通過特徵抽取的結果還原原來的數據---------------")
    print(dict.inverse_transform(data))

    return None

if __name__ == "__main__":
    dictvec()

輸出結果:

--------------get_feature_names-----------------------------------------------
['city=上海', 'city=北京', 'city=深圳', 'temperature']
--------------data,含有該feature_names的爲1,否則爲0,最終的目標值是實際的值-----
[[  0.   1.   0. 100.]         0.   1.   0:表示有'city=北京'這個特徵,'temperature'的值爲100.
 [  1.   0.   0.  60.]
 [  0.   0.   1.  30.]]
--------------inverse_transform:通過特徵抽取的結果還原原來的數據---------------
[{'city=北京': 1.0, 'temperature': 100.0}, {'city=上海': 1.0, 'temperature': 60.0}, {'city=深圳': 1.0, 'temperature': 30.0}]

案例2:

from sklearn.feature_extraction import DictVectorizer

# 設置sparse=False獲得numpy ndarray形式的結果
v = DictVectorizer(sparse=False)
D = [{"foo": 1, "bar": 2}, {"foo": 3, "baz": 1}]

# 對字典列表D進行轉換,轉換成特徵矩陣
X = v.fit_transform(D)
# 特徵矩陣的行代表數據,列代表特徵,0表示該數據沒有該特徵
print(X)
# 獲取特徵列名
print(v.get_feature_names())

# inverse_transform可以將特徵矩陣還原成原始數據
print(v.inverse_transform(X) == D)

# 直接進行轉換,不先進行擬合的話,無法識別新的特徵
print(v.transform([{"foo": 4, "unseen_feature": 3}]))

輸出結果:

[[2. 0. 1.]
 [0. 1. 3.]]
['bar', 'baz', 'foo']
True
[[0. 0. 4.]]

配合特徵選擇:

from sklearn.feature_extraction import DictVectorizer
from sklearn.feature_selection import SelectKBest,chi2

# 設置sparse=False獲得numpy ndarray形式的結果
v = DictVectorizer(sparse=False)
D = [{"foo": 1, "bar": 2}, {"foo": 3, "baz": 1}]

# 對字典列表D進行轉換,轉換成特徵矩陣
X = v.fit_transform(D)
# 特徵矩陣的行代表數據,列代表特徵,0表示該數據沒有該特徵
print(X)
# 獲取特徵列名
print(v.get_feature_names())

# 得到一個篩選器,使用卡方統計篩選出最好的2個特徵
support = SelectKBest(chi2, k=2).fit(X, [0, 1])

# 進行篩選,篩選的結果會自動覆蓋原有的特徵矩陣
print(v.restrict(support.get_support()))
print(v.get_feature_names())

輸出結果爲:

[[2. 0. 1.]
 [0. 1. 3.]]
['bar', 'baz', 'foo']
DictVectorizer(dtype=<class 'numpy.float64'>, separator='=', sort=True,
               sparse=False)
['bar', 'foo']
D:文本特徵抽取

作用:對文本數據進行特徵值化

類:sklearn.feature_extraction.text.CountVectorizer
CountVectorizer()函數只考慮每個單詞出現的頻率;然後構成一個特徵矩陣,每一行表示一個訓練文本的詞頻統計結果。其思想是,先根據所有訓練文本,不考慮其出現順序,只將訓練文本中每個出現過的詞彙單獨視爲一列特徵,構成一個詞彙表(vocabulary list),該方法又稱爲詞袋法(Bag of Words)。

CountVectorizer語法:
CountVectorizer(max_df=1.0,min_df=1,…)

  • 返回詞頻矩陣

  • CountVectorizer.fit_transform(X,y)
    X:文本或者包含文本字符串的可迭代對象
    返回值:返回sparse矩陣

  • CountVectorizer.inverse_transform(X)
    X: array數組或者sparse矩陣
    **返回值:**轉換之前數據格式

  • CountVectorizer.get_feature_names()
    **返回值:**單詞列表

流程:
1、實例化類CountVectorizer
2、調用fit_transform方法輸入數據並轉換

注意返回格式,利用toarray()進行sparse矩陣轉換array數組

案例:

from sklearn.feature_extraction.text import CountVectorizer

texts = ["orange banana apple grape","banana apple apple","grape", "orange apple"]
cv = CountVectorizer()
cv_fit = cv.fit_transform(texts)

print("------------cv.get_feature_names()-----------------")
print(cv.get_feature_names())
"""
結果爲:
['apple', 'banana', 'grape', 'orange']
"""

print("-----------------cv.vocabulary_--------------------")
print(cv.vocabulary_)
"""
結果是:
{'orange': 3, 'banana': 1, 'apple': 0, 'grape': 2}
這裏是根據首字母順序,將texts變量中所有單詞進行排序,按照單詞首字母排序的順序:
apple     序號:0
banana    序號:1
grape     序號:2
orange    序號:3
"""

print("-----------------cv_fit----------------------------")
print(cv_fit)
"""
結果是:
  (0, 3)	1
  (0, 1)	1
  (0, 0)	1
  (0, 2)	1
  (1, 1)	1
  (1, 0)	2
  (2, 2)	1
  (3, 3)	1
  (3, 0)	1

其中括號裏面的第一列表示的是字符串的序號,以下針對第一列進行說明  
0:表示字符串"orange banana apple grape"
1:表示字符串"banana apple apple"
2:表示字符串"grape"
3:表示字符串"orange apple"

組合起來:
  (0, 3)	1    表示第一個字符串"orange banana apple grape"中出現orange的次數是1
  (0, 1)	1    表示第一個字符串"orange banana apple grape"中出現banana的次數是1
  依次類推
  (1, 0)	2    表示第一個字符串"banana apple apple"中出現apple的次數是2
  ...
"""

print("--------------cv_fit.toarray()---------------------")
print(cv_fit.toarray())
"""
結果爲:
[[1 1 1 1]
 [2 1 0 0]
 [0 0 1 0]
 [1 0 0 1]]
 
可以理解爲:
{'orange': 3, 'banana': 1, 'apple': 0, 'grape': 2}
                               'apple'  'banana'   'grape'   'orange'
"orange banana apple grape"     [[1         1         1           1]
"banana apple apple"            [ 2         1         0           0]
"grape"                         [ 0         0         1           0]
"orange apple"                  [ 1         0         0           1]]

即行表示字符串,列表示單詞
"""

再如案例:

from sklearn.feature_extraction.text import CountVectorizer,TfidfVectorizer

X_test = ['I am a student','You can’t even make this stuff up']
# stop_words=None表示不去掉停用詞,若改爲stop_words='english'則去掉停用詞
count_vec=CountVectorizer(stop_words=None)
#訓練count_vec中的屬性,並返回數組
arr = count_vec.fit_transform(X_test).toarray()


print('vocabulary list:\n', count_vec.get_feature_names())
"""
輸出的結果爲:
['am', 'can', 'even', 'make', 'student', 'stuff', 'this', 'up', 'you']
"""


print('result array:\n',arr)
"""
輸出結果爲:
 [[1 0 0 0 1 0 0 0 0]             #這裏表示am和student都出現了1次,其它的出現了0次
 [0 1 1 1 0 1 1 1 1]]             #這裏表示am和student沒出現,其它的單詞都出現了一次
 
 上面的數組的列對應:
 ['am', 'can', 'even', 'make', 'student', 'stuff', 'this', 'up', 'you']
 
 上面的數組有兩行,表示有2段字符串
"""

print('vocabulary_:\n', count_vec.vocabulary_)
"""
結果是:
 {'am': 0, 'student': 4, 'you': 8, 'can': 1, 'even': 2, 'make': 3, 'this': 6, 'stuff': 5, 'up': 7}
 0    4    8    1 等這些數值表示在單詞在count_vec.get_feature_names()的順序
"""

##########################################################
########## CountVectorizer同樣適用於中文 ##################
##########################################################

X_test = ['中國 你 是 城市 都是 小區', '中國 你 小區 旅行 飲食 學校']
## 默認將所有單個漢字視爲停用詞;
count_vec=CountVectorizer(token_pattern=r"(?u)\b\w\w+\b")
arr = count_vec.fit_transform(X_test).toarray()

print('vocabulary list:\n', count_vec.get_feature_names())
"""
輸出結果爲:
vocabulary list:
 ['中國', '城市', '學校', '小區', '旅行', '都是', '飲食']
"""

print('result array:\n', arr)
"""
輸出結果爲:
result array:
 [[1 1 0 1 0 1 0]
 [1 0 1 1 1 0 1]]
"""

print('vocabulary_:\n', count_vec.vocabulary_)
"""
輸出結果爲:
vocabulary_:
 {'中國': 0, '城市': 1, '都是': 5, '小區': 3, '旅行': 4, '飲食': 6, '學校': 2}
"""

再如:

# 文檔進行特徵值化
# 導入包
from sklearn.feature_extraction.text import CountVectorizer

def countvec():
    """
    對文本進行特徵值化
    :return:
    """

    cv = CountVectorizer()
    data = cv.fit_transform(["人生 苦短,我 喜歡 python","人生漫長,不用 python"])
    print(cv.get_feature_names())
    print(data.toarray())

    return None

if __name__ == "__main__":
    countvec()

輸出結果爲:

['python', '不用', '人生', '人生漫長', '喜歡', '苦短']
[[1 0 1 0 1 1]
 [1 1 0 1 0 0]]

注意:不支持單箇中文字

另外如果文本是一段連續的話,這時候就需要對中文進行分詞才能詳細的進行特徵值化

中文分詞,使用:jieba分詞
下載:

進入Anaconda Prompt裏面執行下面的命令:
pip install jieba

使用方法:

import jieba
jieba.cut("我是一個好程序員")

注意:

返回值:詞語生成器

案例:

from sklearn.feature_extraction.text import CountVectorizer
import jieba
def cutword():
    con1 = jieba.cut("今天很殘酷,明天更殘酷,後天很美好,但絕大部分是死在明天晚上,所以每個人不要放棄今天")

    con2 = jieba.cut("我們看到的從很遠星系來的光是在幾百萬年之前發出的,這樣當我們看到宇宙時,我們是在看它的過去。")

    con3 = jieba.cut("如果只用一種方式瞭解某樣事物,你就纔會真正瞭解它。")

    # 轉換成列表
    content1 = list(con1)
    content2 = list(con2)
    content3 = list(con3)

    # 把列表轉換成字符串
    c1 = ' '.join(content1)
    c2 = ' '.join(content2)
    c3 = ' '.join(content3)

    return c1,c2,c3

def hanzivec():
    """
    中文特徵值化
    :return:
    """
    c1,c2,c3 = cutword()

    print("----------------------c1,c2,c3--------------------------------")
    print(c1,c2,c3)

    cv = CountVectorizer()
    data = cv.fit_transform([c1,c2,c3])

    print("----------------------get_feature_names:----------------------")
    print(cv.get_feature_names())

    print("----------------------data.toarray:---------------------------")
    print(data.toarray())

    return None


if __name__ == "__main__":
    hanzivec()

輸出結果:

----------------------c1,c2,c3--------------------------------
今天 很 殘酷 , 明天 更 殘酷 , 後天 很 美好 , 但 絕大部分 是 死 在 明天 晚上 , 所以 每個 人 不要 放棄 今天 我們 看到 的 從 很 遠 星系 來 的 光是在 幾百萬年 之前 發出 的 , 這樣 當 我們 看到 宇宙 時 , 我們 是 在 看 它 的 過去 。 如果 只用 一種 方式 瞭解 某樣 事物 , 你 就 才 會 真正 瞭解 它 。
----------------------get_feature_names:----------------------
['一種', '不要', '之前', '瞭解', '事物', '今天', '光是在', '幾百萬年', '發出', '只用', '後天', '如果', '宇宙', '我們', '所以', '放棄', '方式', '明天', '星系', '晚上', '某樣', '殘酷', '每個', '看到', '真正', '絕大部分', '美好', '過去', '這樣']
----------------------data.toarray:---------------------------
[[0 1 0 0 0 2 0 0 0 0 1 0 0 0 1 1 0 2 0 1 0 2 1 0 0 1 1 0 0]
 [0 0 1 0 0 0 1 1 1 0 0 0 1 3 0 0 0 0 1 0 0 0 0 2 0 0 0 1 1]
 [1 0 0 2 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0]]

TF-IDF

**TF-IDF的主要思想是:**如果某個詞或短語在一篇文章中出現的概率高,並且在其他文章中很少出現,則認爲此詞或者短語具有很好的類別區分能力,適合用來分類。

TF-IDF作用:用以評估一個字詞對於一個文件集或一個語料庫中的其中一份文件的重要程度

類:sklearn.feature_extraction.text.TfidfVectorizer

語法:
TfidfVectorizer(stop_words=None,…)

  • 返回詞的權重矩陣

TfidfVectorizer.fit_transform(X,y)

  • **X:**文本或者包含文本字符串的可迭代對象
  • **返回值:**返回sparse矩陣

TfidfVectorizer.inverse_transform(X)
X: array數組或者sparse矩陣
返回值: 轉換之前數據格式

TfidfVectorizer.get_feature_names()
**返回值:**單詞列表

案例:

from sklearn.feature_extraction.text import TfidfVectorizer

X_test = ['中國 你 是 城市 都是 小區', '中國 你 小區 旅行 飲食 學校']

# 默認將所有單個漢字視爲停用詞:
tfidf_vec=TfidfVectorizer(token_pattern=r"(?u)\b\w\w+\b")
arr = tfidf_vec.fit_transform(X_test).toarray()

print('vocabulary list:\n',tfidf_vec.get_feature_names())
"""
輸出結果:
下面相當於是特徵值
vocabulary list:
 ['中國', '城市', '學校', '小區', '旅行', '都是', '飲食']
"""

print('result array:\n',arr)
"""
下面的列代表是:['中國', '城市', '學校', '小區', '旅行', '都是', '飲食']
下面矩陣中有兩行,即詞的權重矩陣。
result array:
 [[0.40993715 0.57615236 0.          0.40993715  0.          0.57615236  0.        ]
  [0.35520009 0.         0.49922133  0.35520009  0.49922133  0.          0.49922133]]
"""

機器學習原理這本書的介紹:
詞頻-逆向文件頻率(TF-IDF)是一種在文本挖掘中廣泛使用的特徵向量化方法,它可以體現一個文檔中詞語在語料庫中的重要程度。

詞語由t表示,文檔由d表示,語料庫由D表示。詞頻TF(t,d)是詞語t在文檔d中出現的次數。文件頻率DF(t,D)是包含詞語的文檔的個數。如果我們只使用詞頻來衡量重要性,很容易過度強調在文檔中經常出現而並沒有包含太多與文檔有關的信息的詞語,比如“a”,“the”以及“of”。如果一個詞語經常出現在語料庫中,它意味着它並沒有攜帶特定的文檔的特殊信息。逆向文檔頻率數值化衡量詞語提供多少信息:
在這裏插入圖片描述
其中,|D|是語料庫中的文檔總數。由於採用了對數,如果一個詞出現在所有的文件,其IDF值變爲0。
TFIDF(t,d,D)=TF(t,d) *
在這裏插入圖片描述

詞頻(Term Frequency):某關鍵詞在文本中出現次數
逆文檔頻率(Inverse Document Frequency):大小與一個詞的常見程度成反比
TF = 某個詞在文章中出現的次數/文章的總詞數
IDF = log(查找的文章總數 / (包含該詞的文章數 + 1))
TF-IDF = TF(詞頻) x IDF(逆文檔頻率)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章