為了按照我們預計的特征信息量大小來縮放特征,而不是舍棄那些認為不重要的特征,最常見的一種做法就是使用詞頻-逆向文檔頻率(tf-idf)。這一方法對某個特定文檔中經常出現的術語給與很高的權重,但是堆在語料庫的許多文檔中都經常出現的屬于給與的權重卻不高。如果一個單詞在某個特定文檔中經常出現,但在其他文檔中卻不經常出現,那么這個單詞很可能是對文檔內容的很好描述。
scikit-learn在兩個類中實現了tf-idf方法:TfidfTransformer和TfidfVectorizer,前者接受CountVectorizer生成的稀疏矩陣并將其轉換,后者接受文本數據并完成詞袋特征提取與tf-idf變換。
tf-idf縮放方案有幾種變體。單詞w在文檔d中的tf-idf分數在TfidfTransformer類和TfidfVectorizer類中都有體現,其計算公式如下所示:
tfidf(w,d)=tf log ((N+1)/(+1))+1
其中,N是訓練集中文檔數量,是訓練集中出現單詞w的文檔數量,tf(詞頻)是單詞w在文檔d(想要變換或編碼的文檔)中出現的次數。兩個類在計算td-idf表示之后都還應用了L2范數。換句話說,它們將每個文檔的表示縮放到歐幾里得范數為1。利用這種縮放方法,文檔長度不會改變向量化表示。
由于tf-idf實際上利用了訓練數據的統計學屬性,所以我們將使用管道,以確保網格搜索的結果有效。所以會得到下列代碼:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCVpipe=make_pipeline(TfidfVectorizer(min_df=5),LogisticRegression())
param_grid={'logisticregression__C':[0.001,0.01,0.1,1,10,100]}grid=GridSearchCV(pipe,param_grid=param_grid,cv=5)
grid.fit(text_train,y_train)
tf-idf代替僅統計詞數,模型性能會有所提高。我們還可以查看tf-idf找到的最重要單詞。要記住,tf-idf縮放的目的是找到能夠區分文檔的單詞,但它完全是一種無監督技術。因此,這里的“重要”不一定與最終要尋找的標簽有關。
首先,我們從管道中提取TfidfVectorizer
vectorizer=grid.best_estimator_.named_steps['tfidfvectorizer']
#變換訓練數據集
X_train=vectorizer.transform(text_train)
#找到數據集中每個特征的最大值
max_value=X_train.max(axis=0).toarray().ravel()
sort_by_tfidf=max_value.argsort()
#獲取特征名稱
feature_names=np.array(vectorizer.get_feature_names())
tf-idf較小的特征要么是在許多文檔中都很常用,要么就是很少使用,且僅出現在非常長的文檔中。有趣的是,許多tf-idf較大的特征實際上對應的是特定的內容。