特徵選擇和特徵生成問題初探

Andrew.Hann發表於2018-07-29

1. 為什麼要進行特徵選擇?

0x1:有哪些因素會影響模型利用先驗知識?

我們知道,一個演算法學習可以成功預測,一個很重要的關鍵是目標問題隱含了特定模式的先驗假設(先驗知識),而演算法要做的唯一的事情,就是捕獲這種先驗假設,即通過我們熟悉的模型引數的形式來固話一個生成式或者一個判別式。

從一個具體的虛擬的例子開始說起,但是這個例子和我們再實際工程專案中遇到的所有問題,本質上是一樣的。

有一個廣告公司,每月會投入一定的廣告費,用於提升其銷售額,同時,財務部門收集了歷史上每個月投入的廣告費和銷售額的結果:

這是一個非常具體的問題,專案的目標是需要開發一個預測器,幫助決策層判斷將來需要投入多少廣告費,並且對預期的銷售額收入有一個預期判斷。

1. 特徵數字化編碼 - 如何數值化編碼是第一個影響最終效果的因素

演算法是一個數學的運算和求導得極值過程,要求模型輸入的是一個數字化的向量,但是現實生活中的例子不一定都是純數字化的,當然這個例子本身足夠簡單,輸入和要預測的結果本身已經是數字了,那我們可以直接進行數字化編碼,但是在其他領域利於NLP領域,如何進行數字化特徵編碼就是一個足夠引起慎重思考的問題了。

在這個銷售預測的例子中,我們將輸入樣本編碼為 1 維向量 X,數值即廣告費的數值。預測的結果編碼為 1 維的向量 Y,即銷售額。

我們用 X 表示廣告費,用 Y 表示銷售額,這種從現實世界的具體物體,到用數值表示的抽象數值化變換,我們稱之為特徵函式,簡稱特徵。

如果 X 是向量空間的一個子集,每一個有時候稱為特徵向量。

如何將現實世界物體編碼為輸入空間 X 的方式,對理解我們如何利用問題相關的先驗知識,是非常重要的。

2. 特徵選擇 - 對特徵進行篩選 and 扭曲變換

在完成特徵數字化編碼之後,我們可能會遇到一些問題

1)特徵數量太多

當然,在本文的銷售額預測的例子中沒有這個情況,但是我們假設我們引入的特徵還有例如當月季節、當月氣溫、當月流行熱點等上千個維度,因為其實這個現象在實際專案中是很常見的,由於物體本身(例如NLP文字)或者我們出於“多多益善”的目的經常會盡可能地將我們認為對最終預測有幫助的特徵維度都抽取出來,作為物體的特徵向量。

這本身也沒有太多問題,但是過多的特徵會增大演算法運算過程中的CPU和記憶體需求。

而且很可能還會導致模型欠擬合,這是因為在一些場景下,最終決定結果判斷的可能只能其中3-5個核心特徵,輸入太多的無關特徵,可能導致輸入了一些“假關聯”,這些“假關聯”只是恰好在 這批訓練樣本集中呈現出了某種相關性,但其實其背後並沒有隱含任何真實世界的統計規律。

如果模型在訓練的過程中,“不小心”錯誤地引入了這些“假關聯”特徵,那麼可以想象,模型的預測泛化能力是會大打折扣的。

2)在當前特徵空間中特徵向量線性不可分

這也是一個很常見的問題,線性可分看起來像是實驗課上做demo的場景,在大多數的工程專案中,我們的特徵向量都是在當前空間線性不可分的。例如下面這張圖:

紅星和黑圈無法通過一個線性函式直接進行二分類區分。這個時候其實有兩個辦法:

1. 選擇用非線性分類器進行訓練:
例如adaboost、decision tree、dnn這些,但其實本質上,這些模型在訓練生成模型的過程中,已經隱含了基於線性分類器組合得到非線性分類器的步驟了。

2. 對原始特徵進行扭曲變化,將其轉化到另一個高緯度的新特徵空間中:
例如基於kernel trick的SVM就是這種情況,通過在原空間樣本 X 到希爾伯特空間的特徵對映上學習每一個二分類器來實現分類

特徵選擇,是另一種應用先驗知識來處理問題的方法。這是我們本文要重點討論的一個主題。

3)直接窮舉所有特徵子集組合可行嗎?

在理情況下,我們可以嘗試 d 個特徵的所有 k 個特徵組合,然後選擇最優預測結果對應的特徵子集。然而,這種窮盡搜尋方法通常在計算上是不可行的。

在實際工程中使用的演算法中,我們常常採用一些啟發式,迭代式的搜尋方法來儘可能地獲得一個足夠好的特徵子集。

3. 模型選擇

我們知道,雖然有很多可以嘗試的共同的特徵學習方法,但是“沒有免費的午餐”理論指出不存在一種能處理所有問題的極端特徵學習期,任何特徵學習期都可能在某些問題上失敗。

換句話說,每一個特徵學習期的成功依賴於資料分佈的某種先驗假設形式(有時這種先驗假設可能不那麼明顯)。

不同演算法的區別在於能否成功捕獲這種先驗假設,同時也要明白,不同的演算法,其擬合能力是不同的,可能對同一份訓練資料,會發生欠擬或者過擬。

Relevant Link:

https://www.jianshu.com/p/f485dc676e1c

 

2. 濾波器特徵選擇 - 不依賴具體演算法模型的feature selection

濾波器方法可能是最簡單的特徵選擇方法,在濾波方法中,我們將某些特徵看作獨立於其他特徵,然後根據一些質量度量標準來估計這些獨立特徵,然後選擇 k 個獲得最高評分的特徵(此外也可以依據最好的評分確定特徵的數量)

0x1:線性相關係數(皮爾森相關係數)- 評價單個特徵和預測結果標籤的相關性

1. 皮爾森相關係數 - 評價單個特徵在一定的評價標準前提下和待預測標籤的相關性

一種最直接的方法是依據預測期的錯誤率來獲得特徵的評分。

為了說明這個問題,我們考慮採用平方損失的線性迴歸問題。令

表示 m 個訓練樣本第 j 個特徵值形成的向量,令表示 m 個樣本的目標值。

僅僅使用第 j 個特徵的經驗風險最小化線性預測期的經驗平方損失是:

為了求解這個最小化問題,令表示特徵的平均值,令表示目標的平均值。顯然:

等式右邊對 b 求導,令導數等於0,我們得到 b = 0。

同樣,對 a 求導,當 b = 0時,我們得到

將 a,b 的值代入目標函式,我們得到通過選擇右式的特徵組合,我們的目的是讓左式的損失函式值最小

依據最小平方損失對特徵排序,等同於依據下面評分的絕對值進行排序(高分表示好的特徵):

上面的表示式被稱為皮爾森相關係數。分子表示第 j 個特徵和目標值方差的經驗估計,而分母表示第 j 個特徵方差乘上目標值所得方差經驗估計的均方根。

皮爾森相關係數的取值範圍為【-1,1】,這裡如果皮爾森相關係數等於 1 或者 -1,表示 v 和 y 之間有線性相關對映關係,且經驗風險等於0。

2. 單個特徵和待預測標籤線性相關性很低,一定意味著這個特徵不好嗎?

如果皮爾森相關係數等於0,表示 v 到 y 的最優線性對映為各個維度都等於0,這就是說單獨只用 v 不足以預測 y。

但是這並不一定意味著 v 是一個壞的特徵,比如可能出現這種情況,v 和其他特徵組合起來能夠很好地預測 y。

考慮一個簡單的例子,目標通過函式來產生。

假定 x1 是由上的均勻分佈產生,而,這裡 z 也是由上的均勻分佈產生。

那麼,,我們可以得到

因此,對於足夠大的訓練集,第一個特徵的皮爾森相關係數可能等於0,因此它可能不被選擇,然而,如果不知道第一個特徵,沒有函式能夠很好地預測目標值。

3. Pearson相關係數計算的Scikit-learn版本

Pearson Correlation速度快、易於計算,經常在拿到資料(經過清洗和特徵提取之後的)之後第一時間就執行。Scipy的pearsonr方法能夠同時計算相關係數和p-value。

#!/usr/bin/python

import numpy as np
from scipy.stats import pearsonr

np.random.seed(0)
size = 300
x = np.random.normal(0, 1, size)
print "Lower noise", pearsonr(x, x + np.random.normal(0, 1, size))
print "Higher noise", pearsonr(x, x + np.random.normal(0, 10, size))

這個例子中,我們比較了變數在加入噪音之前和之後的差異。

當噪音比較小的時候,p-value接近1,改變後的變數和改變前的變數相關性很強;

當噪音比較大的時候,p-value降低,改變後的變數和改變前的變數相關性降低

Pearson相關係數的一個明顯缺陷是,作為特徵排序機制,他只對線性關係敏感。如果關係是非線性的,即便兩個變數具有一一對應的關係,Pearson相關性也可能會接近0。

#!/usr/bin/python

import numpy as np
from scipy.stats import pearsonr

x = np.random.uniform(-1, 1, 100000)
print pearsonr(x, x**2)[0]

0x2:卡方檢驗 - 變數之間相關性(這裡的變數包括特徵或標籤值)

卡方檢驗是一種用途很廣的計數資料的假設檢驗方法。它屬於非引數檢驗的範疇,主要是比較兩個及兩個以上樣本率( 構成比)以及兩個分類變數的關聯性分析。

其根本思想就是在於比較理論頻數和實際頻數的吻合程度或擬合優度問題。

0. 卡方檢驗概念

卡方檢驗(chi-square test),也叫作χ2檢驗。卡方檢驗有多種方法,最著名的就是皮爾遜卡方檢驗,也是卡爾·皮爾森提出。我們通常用卡方來檢測兩個變數or樣本的獨立性。

卡方檢驗的理論假設是:一個樣本中已發生事件的次數分配會遵守某個特定的理論分配

通常的講:觀測頻數跟實際頻數應該沒有區別,除非兩個變數不是獨立的。舉個例子:XX公司不同部門職員的性別跟部門兩者是獨立的麼?很明顯不是哦。這兒我們的期望男女比例是1.05:1,但是在IT研發部分,比例可能是3:1,在HR、客服等部門,比率可能是1:3了。因此這兒的觀測值就跟實際值不一致,我們就可以說兩個不是獨立的。

1. 通過一個四格卡方檢驗來闡述卡方檢驗

下面的表格將實驗者分成了2組,隨機變數分別為:是否和牛奶、感冒人數。我們現在希望通過卡方檢驗來揭示這兩個變數之間是否具有相關性,即它們之間是否存在依賴推導。

  感冒人數 未感冒人數 合計 感冒率
喝牛奶組 43 96 139 30.94%
不喝牛奶組 28 84 112 25.00%
合計 71 180 251 28.29%

通過簡單的統計我們得出喝牛奶組和不喝牛奶組的感冒率為30.94%和25.00%,兩者的差別可能是抽樣誤差導致,也有可能是牛奶對感冒率真的有影響。

1)建立理論假設統計

為了確定真實原因,我們先假設喝牛奶對感冒發病率是沒有影響的,即喝牛奶喝感冒時獨立無關的。

所以我們可以得出感冒的發病率實際是(43+28)/(43+28+96+84)= 28.29%

這一步實際上裡隱含了條件獨立性假設,即將另一個隨機變數視為無任何影響,無任何依賴推導,直接計算邊緣條件概率。

2)根據理論假設統計重新得到新的概率分佈 - 有點類似EM的過程

所以,理論的四格表應該如下表所示:

  感冒人數 未感冒人數 合計
喝牛奶組 139*0.2829 = 39.3231 139*(1-0.2829) = 99.6769 139
不喝牛奶組 112*0.2829 = 31.6848 112*(1-0.2829) = 80.3152 112
合計 71 180 251

如果喝牛奶喝感冒真的是獨立無關的,那麼四格表裡的理論值和實際值差別應該會很小。 

3)計算理論值和實際值之間的差距

卡方檢驗的計算公式為:,其中,A為實際值,T為理論值。

x2用於衡量實際值與理論值的差異程度(也就是卡方檢驗的核心思想),包含了以下兩個資訊:

1. 實際值與理論值偏差的絕對大小(由於平方的存在,差異是被放大的)
2. 差異程度與理論值的相對大小

上面牛奶的的例子我們計算得:

卡方 = (43 - 39.3231)平方 / 39.3231 + (28 - 31.6848)平方 / 31.6848 + (96 - 99.6769)平方 / 99.6769 + (84 - 80.3152)平方 / 80.3152 = 1.077

4)卡方分佈的臨界值

上一步我們得到了卡方的值 = 1.077,但是這個值意味著什麼呢?如何通過卡方的值來判斷喝牛奶和感冒是否真的是獨立無關的?也就是說,怎麼知道無關性假設是否可靠?

基本上來說:

卡方值越大,假設成立的概率就越小,即隨機變數間相關性越大;

卡方值越小,假設成立的概率就越大,即隨機變數間相關性越小。

下面是卡方分佈的臨界值表。

表格裡的值代表著:如果卡方值大於對應的閾值,則至少有對應的概率,我們的假設是成立的。

而具體應該查表格的哪一行,這裡需要用到一個自由度的概念,自由度等於:F = (行數 - 1) * (列數 - 1)。對這個例子來說,自由度F = 1 * 1 = 1。

在牛奶的這個例子中,對應的是F = 1,即我們需要查第一行。

我們計算得到的卡方檢驗值為 1.077,介於P(0.1)和P(0.5)這兩欄之間,所以我們可以說:

喝牛奶和感冒之間有至少50%的概率,是獨立不相關的;

但是1.077超過了和P(0.9)和和P(0.95)的閾值,所以,“喝牛奶和感冒之間獨立性假設有95%的概率成立”這句話是錯了(有點繞,理解一下)。

所以,綜上,所以喝牛奶和感冒獨立不相關的假設不成立。

Relevant Link:

https://blog.csdn.net/snowdroptulip/article/details/78770088
https://blog.csdn.net/gdanskamir/article/details/54913233

0x3:互資訊估計

以上就是經典的互資訊公式了。想把互資訊直接用於特徵選擇其實不是太方便:

1. 它不屬於度量方式,也沒有辦法歸一化,在不同資料及上的結果無法做比較;
2. 對於連續變數的計算不是很方便(X和Y都是集合,x,y都是離散的取值),通常變數需要先離散化,而互資訊的結果對離散化的方式很敏感。

最大資訊係數克服了這兩個問題。它首先尋找一種最優的離散化方式,然後把互資訊取值轉換成一種度量方式,取值區間在[0,1]。minepy提供了MIC功能。

反過頭來看y=x^2這個例子,MIC算出來的互資訊值為1(最大的取值)。

#!/usr/bin/python

import numpy as np
from minepy import MINE

m = MINE()
x = np.random.uniform(-1, 1, 10000)
m.compute_score(x, x**2)
print m.mic()

0x4:接受操作特徵(ROC)曲線的面積

總體來說,濾波評分方法的思想是:在一定的評價標準(損失函式)下,評估特徵對最終預測標籤結果準確性的貢獻度

Relevant Link:

https://blog.csdn.net/gdanskamir/article/details/54913233
https://www.cnblogs.com/hhh5460/p/5186226.html

 

3. 貪婪特徵選擇方法 - 需要依賴具體演算法模型得到評價分值

貪婪選擇是另一個比較常用的特徵選擇方法。和濾波方法不同,貪婪選擇方法伴隨著學習演算法的過程,迭代地進行。

0x1:前向貪婪選擇方法

最簡單的貪婪選擇的例子是前向貪婪選擇方法。

我們從一個空集開始,然後逐步每次新增一個特徵到選擇的特徵集。

給定當前選擇的特徵集,我們遍歷所有的,然後在特徵集上應用學習演算法。每一個候選特徵選擇都取得一個不同的預測器,我們選擇新增特徵使得預測器的風險最小(經驗最小化原則)。對應這個最小風險的候選特徵就是本輪選擇的特徵。

持續喝個過程知道我們選擇了 k 個特徵,這裡 k 表示預先定義的可以承擔的特徵數,或者得到一個足夠精度的預測器。

0x2:反向終止演算法

和前向貪婪選擇方法相對的是,反向終止演算法。我們從全部特徵組合的集合開始,然後逐步從特徵集合中一次減少一個特徵。

給定我們當前選擇的特徵集。每個這樣的做法取得一個不同的預測期,然後我們選擇去掉特徵 i 是的預測期從特徵集得到最小的風險(在訓練集或者驗證集上)

0x3:基於有監督學習模型的特徵排序 (Model based ranking)

這種方法的思路是直接使用你要用的有監督機器學習演算法,針對每個單獨的特徵和響應變數(標籤值y)建立預測模型。

其實Pearson相關係數等價於線性迴歸裡的標準化迴歸係數。

假如某個特徵和響應變數之間的關係是非線性的,可以用基於樹的方法(決策樹、隨機森林)、或者擴充套件的線性模型等。基於樹的方法比較易於使用,因為他們對非線性關係的建模比較好,並且不需要太多的除錯。但要注意過擬合問題,因此樹的深度最好不要太大,再就是運用交叉驗證。

我們在著名的波士頓房價資料集上使用sklearn的隨機森林迴歸給出一個單變數選擇的例子:

#!/usr/bin/python

import numpy as np
from sklearn.cross_validation import cross_val_score, ShuffleSplit
from sklearn.datasets import load_boston
from sklearn.ensemble import RandomForestRegressor

#Load boston housing dataset as an example
boston = load_boston()
X = boston["data"]
Y = boston["target"]
names = boston["feature_names"]

rf = RandomForestRegressor(n_estimators=20, max_depth=4)
scores = []
for i in range(X.shape[1]):
     score = cross_val_score(rf, X[:, i:i+1], Y, scoring="r2",
                              cv=ShuffleSplit(len(X), 3, .3))
     scores.append((round(np.mean(score), 3), names[i]))
res = sorted(scores, reverse=True)
for i in res:
    print i

0x3:稀疏誘導範數

 

4. 特徵操作與歸一化

特徵操作或歸一化包括在每一個源特徵上的簡單變換。這些變換可能使得我們假設類的近似誤差或估計誤差更低或者能夠得到一個更快的演算法。

與特徵選擇的問題類似,特徵操作與歸一化充滿了“玄學”,它需要我們具體問題具體分析,這裡沒有絕對好或絕對壞的變換,而是每一個特徵變換與在這些特徵向量上的學習演算法,以及這個問題相關的先驗假設密切相關。

0x1:常用的特徵變換

接下來,我們用表示在 m 個訓練樣本上的特徵 f,同樣,我們用表示所有樣本特徵的經驗均值。

1. 中心化

通過變換,這個變換使得特徵有 0 均值。

2. 歸一化範圍

這個變換使得每一個特徵的範圍都是【0,1】,

當然,很容易將範圍變換為【0,b】或【-b,b】

3. 標準化

這個變換使得所有特徵有 0 均值和 1 方差。形式上,令表示特徵的經驗方差,那麼設定

4. 裁剪變換

這個變換裁剪特徵的高值或低值

5. sigmoidal變換

這個變換在特徵上用到了sigmoid函式,例如,這裡 b 是使用者自定義引數。這個變換可以認為是一種軟版本的裁剪變換。它對接近於 0 的值值有一些作用,並且與遠離 0 的裁剪變換很相似。

6. 對數變換

這個變換是,這裡 b 是使用者自定義引數。這個變換廣泛地用於當特徵是計數型特徵的情況下。例如,假定特徵表示在一個文件中某個詞出現的次數。那麼,某個詞出現一次與沒有出現的區別,要比一個詞出現1000次還是1001次更為重要。

簡單來說,對數變換對值較小時的變化更敏感,值越大,敏感度越低。從本質上看,和標準化和歸一化的思想很類似。

Relevant Link:

https://www.cnblogs.com/hhh5460/p/5186226.html 

 

相關文章