這只狗子越來越懶,大家可以直接看 notebook 版本的代碼和結果
這篇文章是“閹割”版,主要是分類任務的特征選擇,不完全適用於回歸任務,具體內容和代碼都是從上面摘出來的。
版本說明
python 3.7.6
scikit-learn==0.22.2.post1
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的縮寫,意思就是極度隨機樹。這是一種組合方法,與其說像決策樹,實際上它更像隨機森林。
與隨機森林的相同點:
- bootstrap了樣本。
- 隨機選取了部分特征,來構造一個棵樹。
與隨機森林的不同點:
- 每棵決策樹選擇划分點的方式不同。對於普通決策樹,每個特征都是根據某個標准(信息增益或者gini不純)去進行划分。而對於extra trees中的決策樹,划分點的選擇更為隨機,隨機選擇一個划分點;然后再按照評判標准選擇一個特征。
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