為什麼要使用特徵選擇?

就像是我們要分析今年的房價漲跌,假設我們可以拿到任何的數據,那麼在這些數據中我們選擇哪些數據用來分析呢?肯定是經濟增長速度,人均消費水平,人均可支配收入啊等等這樣的因素。 我們不會去選擇那些不相關的,例如人們口味偏辣還是偏淡,每個人每天打幾個噴嚏這些因素,跟房價的漲跌幾乎沒有太大關係啦

這就是特徵選擇,好的特徵能夠給我們帶來重要的信息,因此在研究一個問題的時候,選擇哪些特徵作為我們分析的方向,是很重要的


Tfidf中的特徵選擇

這裡給大家一個直觀的例子來認識特徵選擇,TFidf是一種加權技術,我在[機器學習] 文本學習中提到過,我們來講一下它是如何工作的:

例如我們有一堆的郵件,我們想要通過對郵件中關鍵詞的統計來識別這封郵件是誰發的。

假設每個人都有自己不同的關鍵詞使用偏好,我們利用這一點來識別發送郵件的作者

可以使用tfidf這個方法來統計每封郵件的關鍵詞(其實會統計出來所有單詞的頻率,而這個頻率是經過處理的頻率,並不是一個單詞出現的次數多就是多,而是相較於整個郵件庫中這個單詞出現的平均頻率從而加權得到的一個值)

由於tfidf會統計出來除了停止詞(stop words)之外所有的單詞,這些單詞都可以看作是特徵,而單詞庫中的單詞是非常龐大的,我們不可能把所有的單詞都進行分析,於是可以對這些單詞進行特徵選擇

特徵選擇就是選擇一些最能帶給我們信息的單詞(想想本文的第一張圖,特徵可以帶來信息,但是特徵≠信息),那麼就需要刪除掉一些沒有價值的特徵

在這個項目中,我們要刪除的就是停止詞和會出現在每個郵件中的詞,停止詞就像是「I」「you」「the」沒有意義,而會出現在每個郵件中的詞也沒有代表價值,所以刪掉

例如在以下一個代碼片段中,我們可以看到 vectorizer = TfidfVectorizer(sublinear_tf=True, max_df=0.5,stop_words=english)這個語句,就是把停止詞去除掉,然後把在50%的郵件中都會出現的那些單詞也刪掉

selector = SelectPercentile(f_classif, percentile=1)這句話就是選擇最強大的1%的特徵用作我們的特徵

sklearn 中有兩大單變數特徵選擇工具:SelectPercentile 和 SelectKBest。 兩者之間的區別從名字就可以看出:SelectPercentile 選擇最強大的 X% 特徵(X 是參數),而 SelectKBest 選擇 K 個最強大的特徵(K 是參數)。

### text vectorization--go from strings to lists of numbers
vectorizer = TfidfVectorizer(sublinear_tf=True, max_df=0.5,stop_words=english)
features_train_transformed = vectorizer.fit_transform(features_train)
features_test_transformed = vectorizer.transform(features_test)

### feature selection, because text is super high dimensional and
### can be really computationally chewy as a result
selector = SelectPercentile(f_classif, percentile=1)
selector.fit(features_train_transformed, labels_train)
features_train_transformed = selector.transform(features_train_transformed).toarray()
features_test_transformed = selector.transform(features_test_transformed).toarray()

特徵選擇帶來的影響

選擇更少的特徵,好處就是可以簡化運算,但是壞處就是欠擬合,正確率可能不高;而選擇更多的特徵,雖然誤差減小了,但是帶來的結果就是過擬合,最終正確率可能也不高,因此我們要選擇合適的特徵。

因此我們要達到誤差和特徵數量的一個平衡,可以看一下這個公式,是Lasso Regression中用到的公式,要想達到最好的效果,可以讓下面的值最小

SSE+lambdaeta

SSE: 誤差

λ:懲罰係數

β:參數的數量

那麼假如我們引入了很多的參數,雖然SSE的值小了,但是同時λβ的值大了。相反,假如引入的參數小了,但是SSE誤差就會變大,為了達到一個好的平衡,需要綜合考慮

使用的時候,找到最小值的那個組合,就是我們要的參數的組合

決策樹中的過擬合

決策樹作為傳統演算法非常容易過擬合,獲得過擬合決策樹最簡單的一種方式就是使用小型訓練集和大量特徵。當過擬合的時候,訓練集的正確率非常高,而測試集的正確率卻很低。

比方說我們之前提到的「識別郵件是誰發的」,如果我們用到了一個特徵是簽名,那麼正確率就會及其高,而我們的本意是通過分析每個人使用單詞的偏好來判斷發郵件的是誰。

在這裡,這個簽名的特徵就是我們需要識別出來的,識別的方法是:

選擇(過擬合)決策樹並使用feature_importances_屬性來獲得一個列表, 其中列出了所有用到的特徵的相對重要性(由於是文本數據,因此列表會很長)。 我們建議迭代此列表並且僅在超過閾值(比如 0.2——記住,所有單詞都同等重要,每個單詞的重要性都低於 0.01)的情況下將特徵重要性列印出來。

代碼如下:

fi=clf.feature_importances_

for index, feature, in enumerate(clf.feature_importances_):
if feature>0.2:
print "feature no", index
print "importance", feature
print "freatures name",feature_names[index]

可以看到有一個feature的重要性高達0.7647058823529412 (利用的是安然的數據包,大家看看結果就行),顯示是」sshacklensf「,看起來像是一個異常值,可以把它刪掉

刪除這個異常值:

text=text.replace(["sara", "shackleton", "chris", "germani","sshacklensf"],).replace(
, )

經過反覆的刪除最大importance的特徵,最終可以得到一個比較好的擬合


如果你覺得寫的很好不要吝惜哦??

更多的文章,請看本專欄目錄:

任妍Carol:機器學習小白筆記目錄?

zhuanlan.zhihu.com
圖標

推薦閱讀:
相關文章