淺談常見的特征選擇方法


這只狗子越來越懶,大家可以直接看 notebook 版本的代碼和結果

https://gitee.com/dogecheng/python/blob/master/machine_learning/%E7%89%B9%E5%BE%81%E9%80%89%E6%8B%A9.ipynb

這篇文章是“閹割”版,主要是分類任務的特征選擇,不完全適用於回歸任務,具體內容和代碼都是從上面摘出來的。

 

版本說明

python 3.7.6
scikit-learn==0.22.2.post1

 

卡方檢驗

注意事項:特征數值必須非負

卡方檢驗衡量隨機變量之間的依賴性,可以剔除對分類沒有太大幫助的特征

參考文章:https://zhuanlan.zhihu.com/p/69888032

from sklearn.datasets import load_breast_cancer
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

dataset = load_breast_cancer()

print("保留15個重要特征")
new_data = SelectKBest(chi2, k=15).fit_transform(dataset.data, dataset.target)

方差分析

類似卡方檢驗,方差分析過分析研究不同來源的變異對總變異的貢獻大小,從而確定可控因素對研究結果影響力的大小

參考文章:https://www.jianshu.com/p/f5f54a39cb19

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif

selector = SelectKBest(f_classif, k=25).fit(X_train, y_train)  # 保留25個特征
X_new_train = selector.transform(X_train)
X_new_test = selector.transform(X_test)
clf = LogisticRegression(random_state=seed)
clf.fit(X_new_train, y_train)
get_socre(y_test, clf.predict(X_new_test))

互信息

互信息用於衡量兩個變量之間的相關性,如果兩個變量之間相互獨立,那么互信息為0

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import mutual_info_classif

selector = SelectKBest(mutual_info_classif, k=25).fit(X_train, y_train)  # 保留25個特征
X_new_train = selector.transform(X_train)
X_new_test = selector.transform(X_test)
clf = LogisticRegression(random_state=seed)
clf.fit(X_new_train, y_train)
get_socre(y_test, clf.predict(X_new_test))

基於模型的方法

遞歸特征消除(RFE)

遞歸特征消除的主要思想是反復構建模型,每次從當前的一組特征中刪除最不重要的特征,然后對該過程進行遞歸重復,直到最終達到所需的特征數量

from sklearn.feature_selection import RFE

clf = LogisticRegression(random_state=seed)

selector = RFE(clf, 25)   # 保留25個特征
selector = selector.fit(X_train, y_train)
print(selector.support_)  # 保留的特征為True
selector.ranking_         # 保留的特征等級為1

clf = LogisticRegression(random_state=seed)
clf.fit(X_train[:, selector.support_], y_train)
get_socre(y_test, clf.predict(X_test[:, selector.support_]))

隨機森林

參考文章:https://www.jianshu.com/p/8985bc8e4a12

"""
根據 feature_importances_ 屬性選擇特征
"""
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(random_state=seed)
rf.fit(X_train, y_train)
feature_importances = rf.feature_importances_
feature_importances_index = feature_importances.argsort()  # 元素的索引,越往后,索引對應的元素越大
keep_features = feature_importances_index[-35:]            # 保留35個重要特征

極度隨機樹

ExtRa Trees是Extremely Randomized Trees的縮寫,意思就是極度隨機樹。這是一種組合方法,與其說像決策樹,實際上它更像隨機森林。

與隨機森林的相同點:

  1. bootstrap了樣本。
  2. 隨機選取了部分特征,來構造一個棵樹。

與隨機森林的不同點:

  1. 每棵決策樹選擇划分點的方式不同。對於普通決策樹,每個特征都是根據某個標准(信息增益或者gini不純)去進行划分。而對於extra trees中的決策樹,划分點的選擇更為隨機,隨機選擇一個划分點;然后再按照評判標准選擇一個特征。

參考文章:http://sofasofa.io/forum_main_post.php?postid=1000765

from sklearn.ensemble import ExtraTreesClassifier
etclf = ExtraTreesClassifier(random_state=seed)
etclf.fit(X_train, y_train)
feature_importances = etclf.feature_importances_
feature_importances_index = feature_importances.argsort()  # 元素的索引,越往后,索引對應的元素越大
keep_features = feature_importances_index[-35:]            # 保留35個重要特征

相關性分析

使用皮爾遜相關系數檢查兩個變量之間變化趨勢的方向以及程度,值范圍-1到+1,0表示兩個變量不相關,正值表示正相關,負值表示負相關,值越大相關性越強

"""
找出與類別最相關的特征
"""
df = pd.DataFrame(X_train)
df['y'] = y_train
corr= df.corr()
corr_y = abs(corr["y"])
highest_corr = corr_y[corr_y > 0.1]       # 只看大於0.1的
highest_corr.sort_values(ascending=True)  # 發現只有3個特征與標簽最相關

keep_features = highest_corr.sort_values(ascending=True).index[:-1]  # 去掉y
去除相關度高(冗余)的特征,特征較少時可以用畫圖的方式
df_2 = df[corr_y.sort_values(ascending=True)[-11:-1].index]

figure(figsize=(12, 10), dpi=80, facecolor='w', edgecolor='k')
corr_2 = df_2.corr()
sns.heatmap(corr_2, annot=True, fmt=".2g")

L1正則

L1正則可以讓模型的解更加稀疏,相當於做了特征選擇

clf = LogisticRegression(random_state=seed, solver='saga', penalty='l1')  # 大多默認使用L2正則
clf.fit(X_train, y_train)
get_socre(y_test, clf.predict(X_test))

PCA降維

使用奇異值分解將數據投影到較低的k維空間,這k維特征被稱為主成份

參考文章:https://www.jianshu.com/p/bcd196497d94

from sklearn.decomposition import PCA
candidate_components = range(5, 50, 5)  # 有50個特征,我們最低取5維,並以5為步長遞增
explained_ratios = []
for c in candidate_components:
    pca = PCA(n_components=c)
    pca.fit(X_train)
    explained_ratios.append(np.sum(pca.explained_variance_ratio_))
print(explained_ratios)

選擇方差百分比高的主成分數

 

參考文章

https://towardsdatascience.com/feature-selection-techniques-1bfab5fe0784

https://blog.csdn.net/iizhuzhu/article/details/105166295


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM