一、文本特征提取概述
在自然語言處理(NLP)和文本挖掘任務中,文本特征提取是將原始文本數據轉換為機器學習模型可以理解的數值特征的關鍵步驟。scikit-learn提供了兩種常用的文本特征提取方法:CountVectorizer(詞頻統計)和TfidfVectorizer(TF-IDF加權)。
二、CountVectorizer:詞頻統計
2.1 CountVectorizer原理
CountVectorizer將文本集合轉換為詞頻矩陣,統計每個文檔中每個詞的出現次數。它執行以下步驟:
-
分詞(Tokenization):將文本拆分為單詞或n-gram
-
構建詞匯表:收集所有文檔中的所有唯一單詞
-
生成詞頻矩陣:統計每個文檔中每個單詞的出現次數
2.2 CountVectorizer API詳解
from sklearn.feature_extraction.text import CountVectorizer# 初始化CountVectorizer
vectorizer = CountVectorizer(input='content', # 輸入類型,'content'表示輸入為字符串或字節encoding='utf-8', # 編碼方式decode_error='strict', # 解碼錯誤處理方式strip_accents=None, # 去除重音符號lowercase=True, # 是否轉換為小寫preprocessor=None, # 預處理函數tokenizer=None, # 自定義分詞器stop_words=None, # 停用詞列表token_pattern=r"(?u)\b\w\w+\b", # 分詞正則模式ngram_range=(1, 1), # n-gram范圍analyzer='word', # 分析單位,'word'或'char'max_df=1.0, # 忽略文檔頻率高于該閾值的詞min_df=1, # 忽略文檔頻率低于該閾值的詞max_features=None, # 最大特征數vocabulary=None, # 自定義詞匯表binary=False, # 是否僅記錄詞是否出現而非頻率dtype=np.int64 # 輸出矩陣的數據類型
)
2.3 CountVectorizer示例代碼?
from sklearn.feature_extraction.text import CountVectorizer# 示例文本數據
corpus = ['This is the first document.','This document is the second document.','And this is the third one.','Is this the first document?'
]# 初始化CountVectorizer
vectorizer = CountVectorizer()# 擬合數據并轉換為詞頻矩陣
X = vectorizer.fit_transform(corpus)# 查看詞匯表
print("詞匯表:", vectorizer.get_feature_names_out())
# 輸出: ['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']# 查看詞頻矩陣
print("詞頻矩陣:\n", X.toarray())
"""
輸出:
[[0 1 1 1 0 0 1 0 1][0 2 0 1 0 1 1 0 1][1 0 0 1 1 0 1 1 1][0 1 1 1 0 0 1 0 1]]
"""# 對新文本進行轉換
new_text = ["This is a new document."]
new_X = vectorizer.transform(new_text)
print("新文本詞頻:", new_X.toarray())
# 輸出: [[0 1 0 1 0 0 0 0 1]]
2.4 參數調優技巧
-
停用詞處理:使用
stop_words='english'
可以過濾常見英文停用詞 -
n-gram范圍:
ngram_range=(1,2)
可以同時捕獲單詞和短語 -
詞匯表限制:
max_features=1000
只保留最常見的1000個詞 -
文檔頻率過濾:
min_df=2
忽略只出現一次的單詞
三、TfidfVectorizer:TF-IDF特征提取
3.1 TF-IDF原理
TF-IDF(Term Frequency-Inverse Document Frequency)是一種統計方法,用于評估一個詞對于一個文檔集或語料庫中的其中一份文檔的重要程度。其計算公式為:
TF-IDF = TF(t,d) × IDF(t)?
其中:
-
TF(t,d)是詞t在文檔d中的詞頻
-
IDF(t)是逆文檔頻率,計算公式為:IDF(t) = log(總文檔數 / 包含詞t的文檔數) + 1
3.2 TfidfVectorizer API詳解?
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np# 初始化TfidfVectorizer
vectorizer = TfidfVectorizer(# 輸入參數設置input='content', # 輸入類型,可選'content'(默認)|'filename'|'file'# 'content'表示直接輸入文本內容,'filename'表示輸入文件路徑encoding='utf-8', # 文本編碼方式,默認utf-8,處理中文時通常保持默認decode_error='strict', # 解碼錯誤處理方式,可選'strict'|'ignore'|'replace'# 'strict'遇到錯誤拋出異常;'ignore'忽略錯誤;'replace'用替換標記錯誤字符strip_accents=None, # 去除重音符號,可選None|'ascii'|'unicode'# None不處理;'ascii'快速處理;'unicode'精確處理但較慢lowercase=True, # 是否將所有字符轉換為小寫,默認True# 預處理設置preprocessor=None, # 自定義預處理函數,在分詞前應用# 例如: lambda x: x.replace('$', 'dollar')tokenizer=None, # 自定義分詞函數,覆蓋默認的分詞行為# 例如中文分詞: lambda x: jieba.cut(x)# 文本分析設置analyzer='word', # 分析單位,可選'word'(默認)|'char'|'char_wb'# 'word'按詞分析;'char'按字符分析;'char_wb'按詞邊界內的字符分析stop_words=None, # 停用詞設置,可選None|'english'|list# None無停用詞;'english'使用內置英文停用詞;list自定義停用詞列表token_pattern=r"(?u)\b\w\w+\b", # 分詞正則表達式模式# 默認匹配至少2個字母數字字符的詞# (?u)表示Unicode匹配模式,\b表示詞邊界ngram_range=(1, 1), # n-gram范圍,元組(min_n, max_n)# (1,1)僅使用unigram;(1,2)使用unigram和bigram# 特征選擇設置max_df=1.0, # 忽略文檔頻率高于該閾值的詞,float表示比例,int表示絕對數量# 例如0.85表示忽略出現在85%以上文檔中的詞min_df=1, # 忽略文檔頻率低于該閾值的詞,同上# 例如2表示忽略出現在少于2個文檔中的詞max_features=None, # 最大特征數,按詞頻選擇前N個特征# None不限制;10000表示只保留最常見的10000個詞vocabulary=None, # 自定義詞匯表,dict或可迭代對象# 例如 {'apple':0, 'banana':1} 或 ['apple', 'banana']binary=False, # 是否僅記錄詞是否出現而非頻率# True生成二進制特征;False(默認)使用實際詞頻# 輸出設置dtype=np.float64, # 輸出矩陣的數據類型,通常np.float32或np.float64# TF-IDF特有參數norm='l2', # 歸一化方式,可選'l1'|'l2'|None# 'l2'(默認)使用歐式范數;'l1'使用曼哈頓范數;None不歸一化use_idf=True, # 是否使用逆文檔頻率(IDF)權重,默認True# 設為False則只使用TF(詞頻)部分smooth_idf=True, # 是否平滑IDF權重,默認True# 平滑避免除零錯誤,公式變為log(1+N/(1+df(t))) + 1sublinear_tf=False # 是否應用次線性TF縮放,默認False# True時使用1+log(tf)代替原始tf值
)
3.3 TfidfVectorizer示例代碼?
from sklearn.feature_extraction.text import TfidfVectorizer# 示例文本數據
corpus = ['This is the first document.','This document is the second document.','And this is the third one.','Is this the first document?'
]# 初始化TfidfVectorizer
tfidf_vectorizer = TfidfVectorizer()# 擬合數據并轉換為TF-IDF矩陣
X_tfidf = tfidf_vectorizer.fit_transform(corpus)# 查看詞匯表
print("詞匯表:", tfidf_vectorizer.get_feature_names_out())
# 輸出: ['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']# 查看TF-IDF矩陣
print("TF-IDF矩陣:\n", X_tfidf.toarray().round(2))
"""
輸出:
[[0. 0.47 0.58 0.38 0. 0. 0.38 0. 0.38][0. 0.69 0. 0.28 0. 0.54 0.28 0. 0.28][0.51 0. 0. 0.27 0.51 0. 0.27 0.51 0.27][0. 0.47 0.58 0.38 0. 0. 0.38 0. 0.38]]
"""# 對新文本進行轉換
new_text = ["This is a new document."]
new_X_tfidf = tfidf_vectorizer.transform(new_text)
print("新文本TF-IDF:", new_X_tfidf.toarray().round(2))
# 輸出: [[0. 0.71 0. 0.5 0. 0. 0. 0. 0.5]]
3.4 TF-IDF參數調優技巧
-
歸一化選擇:
norm='l2'
通常效果最好 -
平滑IDF:
smooth_idf=True
可以避免除零錯誤 -
次線性TF縮放:
sublinear_tf=True
使用1+log(tf)代替原始tf -
自定義IDF權重:可以通過
TfidfTransformer
自定義IDF計算
四、CountVectorizer與TfidfVectorizer對比
特性 | CountVectorizer | TfidfVectorizer |
---|---|---|
特征值類型 | 詞頻 | TF-IDF權重 |
是否考慮詞的重要性 | 否 | 是 |
稀疏矩陣 | 是 | 是 |
適用場景 | 簡單詞頻分析 | 文本分類/檢索 |
計算復雜度 | 較低 | 較高 |
歸一化 | 無 | 通常有 |
五、實際應用案例:文本分類
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.svm import LinearSVC
from sklearn.metrics import classification_report# 示例數據:正面和負面評論
texts = ["This movie is great!","I love this product.","Terrible experience.","Worst service ever.","Amazing performance!","Not worth the money."
]
labels = [1, 1, 0, 0, 1, 0] # 1:正面, 0:負面# 劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(texts, labels, test_size=0.3, random_state=42
)# 使用TF-IDF進行特征提取
tfidf = TfidfVectorizer(stop_words='english', # 移除英文停用詞ngram_range=(1, 2), # 使用unigram和bigrammax_features=1000 # 限制特征數量
)# 轉換訓練數據
X_train_tfidf = tfidf.fit_transform(X_train)# 轉換測試數據
X_test_tfidf = tfidf.transform(X_test)# 訓練分類器
clf = LinearSVC()
clf.fit(X_train_tfidf, y_train)# 評估模型
y_pred = clf.predict(X_test_tfidf)
print(classification_report(y_test, y_pred))
六、常見問題解答
Q1:如何處理中文文本?
A1:中文需要先分詞,可以使用jieba等分詞工具,然后通過自定義tokenizer傳入:
import jiebadef chinese_tokenizer(text):return jieba.lcut(text)vectorizer = CountVectorizer(tokenizer=chinese_tokenizer)
Q2:如何保存和加載訓練好的向量化器?
A2:可以使用joblib或pickle:?
import joblib# 保存
joblib.dump(vectorizer, 'vectorizer.joblib')# 加載
vectorizer = joblib.load('vectorizer.joblib')
Q3:如何處理大規模文本數據?
A3:
-
使用
max_features
限制特征數量 -
使用
min_df
和max_df
過濾罕見和常見詞 -
考慮使用HashingVectorizer替代
-
使用內存映射或分批處理
七、總結
CountVectorizer和TfidfVectorizer是文本特征提取的基礎工具,理解它們的原理和參數對于構建高效的文本處理流水線至關重要。在實際應用中:
-
對于簡單的詞頻統計任務,使用CountVectorizer
-
對于需要考慮詞重要性的任務(如分類、檢索),使用TfidfVectorizer
-
根據具體任務調整參數,特別是停用詞、n-gram范圍和文檔頻率過濾
-
結合后續的機器學習模型進行端到端的評估和調優
通過本教程,您應該能夠熟練使用這兩種文本特征提取方法,并為更復雜的NLP任務打下堅實基礎。
?
?
?
?
?
?
?
?
?
?
?
?