7000 字精華總結,PandasSklearn 進行機器學習之特徵篩選,有效提升模型效能

作者 | 俊欣

今天小編來說說如何透過pandas以及sklearn這兩個模組來對資料集進行特徵篩選,畢竟有時候我們拿到手的資料集是非常龐大的,有著非常多的特徵,減少這些特徵的數量會帶來許多的好處,例如

提高預測的精準度

降低過擬合的風險

加快模型的訓練速度

增加模型的可解釋性

事實上,很多時候也並非是特徵數量越多訓練出來的模型越好,當新增的特徵多到一定程度的時候,模型的效能就會下降,從下圖中我們可以看出,

因此我們需要找到哪些特徵是最佳的使用特徵,當然我們這裡分連續型的變數以及離散型的變數來討論,畢竟不同資料型別的變數處理的方式不同,我們先來看一下對於連續型的變數而言,特徵選擇到底是怎麼來進行的。

7000 字精華總結,PandasSklearn 進行機器學習之特徵篩選,有效提升模型效能

計算一下各個變數之間的相關性

我們先匯入所需要用到的模組以及匯入資料集,並且用

pandas

模組來讀取

from sklearn。datasets import load_boston

import pandas as pd

import numpy as np

import matplotlib

import matplotlib。pyplot as plt

import seaborn as sns

import statsmodels。api as sm

%matplotlib inline

from sklearn。model_selection import train_test_split

from sklearn。linear_model import LinearRegression

from sklearn。feature_selection import RFE

from sklearn。linear_model import RidgeCV, LassoCV, Ridge, Lasso

這次用到的資料集是機器學習中尤其是初學者經常碰到的,波士頓房價的資料集,其中我們要預測的這個物件是

MEDV

這一列

x = load_boston()

df = pd。DataFrame(x。data, columns = x。feature_names)

df[“MEDV”] = x。targetX = df。drop(“MEDV”,1)   #將模型當中要用到的特徵變數保留下來y = df[“MEDV”]          #最後要預測的物件

df。head()

output

CRIM    ZN  INDUS  CHAS    NOX  。。。    TAX  PTRATIO       B  LSTAT  MEDV

0  0。00632  18。0   2。31   0。0  0。538  。。。  296。0     15。3  396。90   4。98  24。0

1  0。02731   0。0   7。07   0。0  0。469  。。。  242。0     17。8  396。90   9。14  21。6

2  0。02729   0。0   7。07   0。0  0。469  。。。  242。0     17。8  392。83   4。03  34。7

3  0。03237   0。0   2。18   0。0  0。458  。。。  222。0     18。7  394。63   2。94  33。4

4  0。06905   0。0   2。18   0。0  0。458  。。。  222。0     18。7  396。90   5。33  36。2

我們可以來看一下特徵變數的資料型別

df。dtypes

output

CRIM       float64

ZN         float64

INDUS      float64

CHAS       float64

NOX        float64

RM         float64

AGE        float64

DIS        float64

RAD        float64

TAX        float64

PTRATIO    float64

B          float64

LSTAT      float64

MEDV       float64

dtype: object

我們看到都是清一色的連續型的變數,我們來計算一下自變數和因變數之間的相關性,透過

seaborn

模組當中的熱力圖來展示,程式碼如下

plt。figure(figsize=(10,8))

cor = df。corr()

sns。heatmap(cor, annot=True, cmap=plt。cm。Reds)

plt。show()

相關係數的值一般是在-1到1這個區間內波動的

相關係數要是接近於0意味著變數之間的相關性並不強

接近於-1意味著變數之間呈負相關的關係

接近於1意味著變數之間呈正相關的關係

我們來看一下對於因變數而言,相關性比較高的自變數有哪些

# 篩選出於因變數之間的相關性

cor_target = abs(cor[“MEDV”])

# 挑選於大於0。5的相關性係數

relevant_features = cor_target[cor_target>0。5]

relevant_features

output

RM         0。695360

PTRATIO    0。507787

LSTAT      0。737663

MEDV       1。000000

Name: MEDV, dtype: float64

篩選出3個相關性比較大的自變數來,然後我們來看一下自變數之間的相關性如何,要是自變數之間的相關性非常強的話,我們也只需要保留其中的一個就行,

print(df[[“LSTAT”,“PTRATIO”

]]。corr())

print(“=”

* 50)

print(df[[“RM”,“LSTAT”

]]。corr())

print(“=”

* 50)

print(df[[“PTRATIO”,“RM”

]]。corr())

output

LSTAT   PTRATIO

LSTAT    1。000000  0。374044

PTRATIO  0。374044  1。000000

=================

RM     LSTAT

RM     1。000000 -0。613808

LSTAT -0。613808  1。000000

=================

PTRATIO        RM

PTRATIO  1。000000 -0。355501

RM      -0。355501  1。000000

從上面的結果中我們可以看到,

RM

變數和

LSTAT

這個變數是相關性是比較高的,我們只需要保留其中一個就可以了,我們選擇保留

LSTAT

這個變數,因為它與因變數之間的相關性更加高一些

遞迴消除法

我們可以嘗試這麼一種策略,我們選擇一個基準模型,起初將所有的特徵變數傳進去,我們再確認模型效能的同時透過對特徵變數的重要性進行排序,去掉不重要的特徵變數,然後不斷地重複上面的過程直到達到所需數量的要選擇的特徵變數。

LR= LinearRegression()

# 挑選出7個相關的變數

rfe_model = RFE(model, 7)

# 交給模型去進行擬合

X_rfe = rfe_model。fit_transform(X,y)

LR。fit(X_rfe,y)

# 輸出各個變數是否是相關的,並且對其進行排序

print(rfe_model。support_)print(rfe_model。ranking_)

output

[False False False  True  True  True False  True  True False  True False

True]

[2 4 3 1 1 1 7 1 1 5 1 6 1]

第一行的輸出包含

True

False

,其中

True

代表的是相關的變數對應下一行的輸出中的

1

,而

False

包含的是不相關的變數,然後我們需要所需要多少個特徵變數,才能夠使得模型的效能達到最優

#將13個特徵變數都依次遍歷一遍

feature_num_list=np。arange(1,13)

# 定義一個準確率

high_score=0

# 最優需要多少個特徵變數

num_of_features=0

score_list =[]

for n in range(len(feature_num_list)):

X_train, X_test, y_train, y_test = train_test_split(X,y, test_size = 0。3, random_state = 0)

model = LinearRegression()

rfe_model = RFE(model,feature_num_list[n])

X_train_rfe_model = rfe_model。fit_transform(X_train,y_train)

X_test_rfe_model = rfe_model。transform(X_test)

model。fit(X_train_rfe_model,y_train)

score = model。score(X_test_rfe_model,y_test)

score_list。append(score)

if(score>high_score):

high_score = score

num_of_features = feature_num_list[n]

print(“最優的變數是: %d個” %num_of_features)print(“%d個變數的準確率為: %f” % (num_of_features, high_score))

output

最優的變數是: 10個

10個變數的準確率為: 0。663581

從上面的結果可以看出10個變數對於整個模型來說是最優的,然後我們來看一下到底是哪10個特徵變數

cols = list(X。columns)

model = LinearRegression()

# 初始化RFE模型,篩選出10個變數

rfe_model = RFE(model, 10)

X_rfe = rfe。fit_transform(X,y)

# 擬合訓練模型

model。fit(X_rfe,y)

df = pd。Series(rfe。support_,index = cols)

selected_features = df[df==True]。index

print(selected_features)

output

Index([

‘CRIM’, ‘ZN’, ‘INDUS’, ‘CHAS’, ‘NOX’, ‘RM’, ‘DIS’, ‘RAD’, ‘PTRATIO’

‘LSTAT’

],

dtype=

‘object’

正則化

例如對於

Lasso

的正則化而言,對於不相關的特徵而言,該演算法會讓其相關係數變為0,因此不相關的特徵變數很快就會被排除掉了,只剩下相關的特徵變數

lasso = LassoCV()

lasso。fit(X, y)

coef = pd。Series(lasso。coef_, index = X。columns)

然後我們看一下哪些變數的相關係數是0

print(“Lasso演算法挑選了 ” + str(sum(coef != 0)) + “ 個變數,然後去除掉了” +  str(sum(coef == 0)) + “個變數”

output

Lasso演算法挑選了10個變數,然後去除掉了3個變數

我們來對計算出來的相關性係數排個序並且做一個視覺化

imp_coef = coef。sort_values()

matplotlib。rcParams[‘figure。figsize’] = (8, 6)imp_coef。plot(kind = “barh”)plt。title(“Lasso Model Feature Importance”)

output

7000 字精華總結,PandasSklearn 進行機器學習之特徵篩選,有效提升模型效能

可以看到當中有3個特徵,‘NOX’、‘CHAS’、‘INDUS’的相關性為0

根據缺失值來進行判斷

下面我們來看一下如何針對離散型的特徵變數來做處理,首先我們可以根據缺失值的比重來進行判斷,要是對於一個離散型的特徵變數而言,

絕大部分的值都是缺失的

,那這個特徵變數也就沒有存在的必要了,我們可以針對這個思路在進行判斷。

首先匯入所需要用到的資料集

train = pd。read_csv(

“credit_example。csv”

train_labels = train[

‘TARGET’

train = train。drop(columns = [

‘TARGET’

])

我們可以先來計算一下資料集當中每個特徵變數缺失值的比重

missing_series = train。isnull()。sum() / train。shape[0]

df = pd。DataFrame(missing_series)。rename(columns = {‘index’: ‘特徵變數’, 0: ‘缺失值比重’})df。sort_values(“缺失值比重”, ascending = False)。head()

output

缺失值比重

COMMONAREA_AVG            0。6953

COMMONAREA_MODE           0。6953

COMMONAREA_MEDI           0。6953

NONLIVINGAPARTMENTS_AVG   0。6945

NONLIVINGAPARTMENTS_MODE  0。6945

我們可以看到缺失值最高的比重將近有70%,我們也可以用視覺化的根據來繪製一下缺失值比重的分佈圖

plt。rcParams[‘font。sans-serif’]=[‘SimHei’] #用來正常顯示中文標籤

plt。figure(figsize = (7, 5))

plt。hist(df[‘缺失值比重’], bins = np。linspace(0, 1, 11), edgecolor = ‘k’, color = ‘blue’, linewidth = 2)

plt。xticks(np。linspace(0, 1, 11));

plt。xlabel(‘缺失值的比重’, size = 14); plt。ylabel(‘特徵變數的數量’, size = 14); plt。title(“缺失值分佈圖”, size = 14);

output

7000 字精華總結,PandasSklearn 進行機器學習之特徵篩選,有效提升模型效能

我們可以看到有一部分特徵變數,它們缺失值的比重在50%以上,有一些還在60%以上,我們可以去除掉當中的部分特徵變數

計算特徵的重要性

在基於樹的眾多模型當中,會去計算每個特徵變數的重要性,也就是

feature_importances_

屬性,得出各個特徵變數的重要性程度之後再進行特徵的篩選

from sklearn。ensemble import RandomForestClassifier

clf = RandomForestClassifier()

# 模型擬合數據

clf。fit(X,Y)

feat_importances = pd。Series(clf。feature_importances_, index=X。columns)

# 篩選出特徵的重要性程度最大的10個特徵

feat_importances。nlargest(10)

我們同時也可以對特徵的重要性程度進行視覺化,

feat_importances。nlargest(10)。plot(kind=

‘barh’

, figsize = (8, 6))

output

7000 字精華總結,PandasSklearn 進行機器學習之特徵篩選,有效提升模型效能

除了隨機森林之外,基於樹的演算法模型還有很多,如LightGBM、XGBoost等等,大家也都可以透過對特徵重要性的計算來進行特徵的篩選

Select_K_Best演算法

Sklearn

模組當中還提供了

SelectKBest

的API,針對迴歸問題或者是分類問題,我們挑選合適的模型評估指標,然後設定K值也就是既定的特徵變數的數量,進行特徵的篩選。

假定我們要處理的是分類問題的特徵篩選,我們用到的是

iris

資料集

iris_data = load_iris()

x = iris_data。data

y = iris_data。target

print(“資料集的行與列的數量: ”, x。shape)

output

資料集的行與列的數量:  (150, 4)

對於分類問題,我們採用的評估指標是卡方,假設我們要挑選出3個對於模型最佳效能而言的特徵變數,因此我們將K設定成3

select = SelectKBest(score_func=chi2, k=3)

# 擬合數據

z = select。fit_transform(x,y)

filter_1 = select。get_support()

features = array(iris。feature_names)

print(“所有的特徵: ”, features)print(“篩選出來最優的特徵是: ”, features[filter_1])

output

所有的特徵:  [

‘sepal length (cm)’‘sepal width (cm)’‘petal length (cm)’

‘petal width (cm)’

篩選出來最優的特徵是:  [

‘sepal length (cm)’‘petal length (cm)’‘petal width (cm)’

那麼對於迴歸的問題而言,我們可以選擇上面波士頓房價的例子,同理我們想要篩選出對於模型最佳的效能而言的7個特徵變數,同時對於迴歸問題的評估指標用的是

f_regression

boston_data = load_boston()

x = boston_data。data

y = boston_data。target

然後我們將擬合數據,並且進行特徵變數的篩選

select_regression = SelectKBest(score_func=f_regression, k=7)

z = select_regression。fit_transform(x, y)

filter_2 = select_regression。get_support()

features_regression = array(boston_data。feature_names)

print(“所有的特徵變數有:”)print(features_regression)print(“篩選出來的7個特徵變數則是:”)print(features_regression[filter_2])

output

所有的特徵變數有:

‘CRIM’

‘ZN’

‘INDUS’

‘CHAS’

‘NOX’

‘RM’

‘AGE’

‘DIS’

‘RAD’

‘TAX’

‘PTRATIO’

‘B’

‘LSTAT’

篩選出來的

7

個特徵變數則是:

‘CRIM’

‘INDUS’

‘NOX’

‘RM’

‘TAX’

‘PTRATIO’

‘LSTAT’

7000 字精華總結,PandasSklearn 進行機器學習之特徵篩選,有效提升模型效能

分享

點收藏

點點贊