您當前的位置:首頁 > 書法

特徵選擇與特徵工程初探

作者:由 DsFunStudio 發表于 書法時間:2019-01-03

特徵工程是機器學習的第一步,涉及清理現有資料集、提高信噪比和降低維數的所有技術。大多數演算法對輸入資料有很強的假設,當使用原始資料集時,它們的效能可能會受到負面影響。

另外有些特徵之間高度相關,在其中一個特徵提供了足夠的資訊之後,與之相關的其他特徵往往無法提供額外的資訊。這時我們就需要了解如何減少特徵數量或者僅選擇最佳特徵。

一、scikit-learn資料集

scikit-learn提供了一些用於測試的內建資料集,這些資料集包含在sklearn。datasets中,每個資料集都包含了輸入集(特徵集)X和標籤(目標值)y。比如波士頓房價的資料集(用於迴歸問題):

from

sklearn。datasets

import

load_boston

boston

=

load_boston

()

X

=

boston

data

y

=

boston

target

print

‘特徵集的shape:’

X

shape

print

‘目標集的shape:’

y

shape

特徵集的

shape

506

13

目標集的

shape

506

,)

可以看到,這個資料集包含了506個樣本、13個特徵,以及1個目標值。

假如我們不想使用scikit-learn提供的資料集,那麼我們還可以使用scikit-learn提供的工具來手動建立特定的資料集。相關的方法有:

make_classification()

:用於建立適用於測試分類演算法的資料集;

make_regression()

:用於建立適用於測試迴歸模型的資料集;

make_blobs()

:用於建立適用於測試聚類演算法的資料集。

二、建立訓練集和測試集

一般來說,我們要在正式應用我們訓練的模型前對它進行測試。因此我們需要將資料集分為訓練集和測試集,顧名思義,前者用於訓練模型引數,後者用於測試模型效能。在某些情況下,我們甚至還會再分出一個數據集作為交叉驗證集,這種處理方式適用於有多種模型可供選擇的情況。

資料集的分割有一些注意事項:首先,兩個資料集必須要能反映原始資料的分佈,否則在資料集失真的情況下得到的模型對於真實樣本的預測效力會比較差;其次,原始資料集必須在分割之前隨機混合,以避免連續元素之間的相關性。

在scikit-learn中,我們可以使用

train_test_split()

函式來快速實現資料集的分割。

from

sklearn。model_selection

import

train_test_split

X_train

X_test

y_train

y_test

=

train_test_split

X

y

test_size

=

0。25

random_state

=

1000

這裡前兩個位置引數分別是特徵集和目標集,

test_size

用於指定測試集大小佔整個資料集的比例,

random_state

則是指定一個隨機種子,這樣可以確保我們在重複試驗時資料不會發生變化(資料集都變了,那模型效果的變化就不知道該歸因於模型的最佳化還是歸因於資料集的變化了。)

三、管理分類資料

在許多分類問題中,目標資料集由各種類別標籤組成。但是很多演算法是不支援這種資料格式的,因此我們要對其進行必要的編碼。

假設我們有一個由10個樣本組成的資料集,每個樣本有兩個特徵。

import

numpy

as

np

X

=

np

random

uniform

0。0

1。0

size

=

10

2

))

y

=

np

random

choice

((

‘Male’

‘Female’

),

size

=

10

))

print

‘X:’

X

print

‘y:’

y

X

[[

0。48463048

0。21682675

0。27987595

0。28061459

0。13723177

0。45159025

0。42727284

0。99834867

0。61113219

0。31892401

0。14985227

0。71565914

0。048201

0。49254257

0。54466226

0。8419817

0。94426201

0。78924785

0。36877342

0。53250431

]]

y

‘Female’

‘Female’

‘Male’

‘Female’

‘Female’

‘Female’

‘Male’

‘Male’

‘Female’

‘Male’

1。 使用

LabelEncoder

from

sklearn。preprocessing

import

LabelEncoder

le

=

LabelEncoder

()

yt

=

le

fit_transform

y

print

y

print

yt

print

le

classes_

‘Female’

‘Female’

‘Male’

‘Female’

‘Female’

‘Female’

‘Male’

‘Male’

‘Female’

‘Male’

0

0

1

0

0

0

1

1

0

1

‘Female’

‘Male’

獲得逆變換的方法很簡單:

output

=

1

0

1

1

0

0

decoded_output

=

le

classes_

i

for

i

in

output

print

decoded_output

‘Male’

‘Female’

‘Male’

‘Male’

‘Female’

‘Female’

這種方法很簡單,但是有個缺點:所有的標籤都變成了數字,然後使用真實值的分類器會根據其距離考慮相似的數字,而忽略其代表的分類含義。因此我們通常優先選擇獨熱編碼(one-hot encoding,又稱一次有效編碼),將資料二進位制化。

2。 使用

LabelBinarizer

from

sklearn。preprocessing

import

LabelBinarizer

lb

=

LabelBinarizer

()

yb

=

lb

fit_transform

y

print

y

print

yb

print

lb

inverse_transform

yb

))

‘Female’

‘Female’

‘Male’

‘Female’

‘Female’

‘Female’

‘Male’

‘Male’

‘Female’

‘Male’

[[

0

0

1

0

0

0

1

1

0

1

]]

‘Female’

‘Female’

‘Male’

‘Female’

‘Female’

‘Female’

‘Male’

‘Male’

‘Female’

‘Male’

可以看到,這裡我們可以使用

LabelBinarizer

類的

inverse_transform

方法進行逆轉化。

當存在多個標籤時,這種方法會將其中一個標籤變換為1,其餘標籤全部為0。這可能會導致的問題顯而易見,也就是我們將多分類問題轉換成了二分類問題。

四、管理缺失特徵

我們可能會經常碰見資料缺失的情況,有以下選項可以解決該問題:

刪除整行:這個選項比較激進,一般只有當資料集足夠大、缺少的特徵值數量很多而且預測風險大時才會選擇;

建立子模型來預測這些特徵值:第二個選項實現起來比較困難,因為需要確定一個監督策略來訓練每個特徵的模型,最後預測它們的值;

使用自動策略根據其他已知值插入這些缺失的特徵值:考慮到以上的利弊,這可能是最好的選項了。

from

sklearn。preprocessing

import

Imputer

data

=

np

array

([[

1

np

nan

2

],

2

3

np

nan

],

-

1

4

2

]])

# 插入均值

imp

=

Imputer

strategy

=

‘mean’

print

‘Mean:

\n

imp

fit_transform

data

))

# 插入中位數

imp

=

Imputer

strategy

=

‘median’

print

‘Median:

\n

imp

fit_transform

data

))

# 插入眾數

imp

=

Imputer

strategy

=

‘most_frequent’

print

‘Mode:

\n

imp

fit_transform

data

))

Mean

[[

1。

3。5

2。

2。

3。

2。

-

1。

4。

2。

]]

Median

[[

1。

3。5

2。

2。

3。

2。

-

1。

4。

2。

]]

Mode

[[

1。

3。

2。

2。

3。

2。

-

1。

4。

2。

]]

五、資料縮放和歸一化

一般的資料集是由不同的值組成的,可以從不同的分佈得到且具有不同的尺度,有時還會有異常值。當不同特徵的取值範圍差異過大時,很可能會對模型產生不良影響。因此我們往往需要先規範資料集。

我們來對比一下原始資料集和經過縮放和中心化的資料集:

from

sklearn。preprocessing

import

StandardScaler

from

sklearn。datasets

import

load_iris

import

seaborn

as

sns

import

matplotlib。pyplot

as

plt

sns

set

()

# 匯入資料

iris

=

load_iris

()

data

=

iris

data

# 繪製原始資料散點圖

fig

axes

=

plt

subplots

1

2

figsize

=

10

5

))

sns

scatterplot

x

=

data

[:,

0

],

y

=

data

[:,

1

],

ax

=

axes

0

])

# 資料歸一化

scaler

=

StandardScaler

()

scaled_data

=

scaler

fit_transform

data

# 繪製規範化資料散點圖

sns

scatterplot

x

=

scaled_data

[:,

0

],

y

=

scaled_data

[:,

1

],

ax

=

axes

1

])

plt

setp

axes

xlim

=

-

2

8

],

ylim

=

-

3

5

]);

特徵選擇與特徵工程初探

可以看到,我們的資料分佈形態沒有變化,但是資料的分佈範圍卻變了。我們將資料轉化成了均值為0(幾乎為0),標準差為1的歸一化資料。

print

‘轉化前均值:

\n

np

mean

data

axis

=

0

))

print

‘轉化後均值:

\n

np

mean

scaled_data

axis

=

0

))

print

‘轉化前方差:

\n

np

std

data

axis

=

0

))

print

‘轉化後方差:

\n

np

std

scaled_data

axis

=

0

))

轉化前均值:

5。84333333

3。054

3。75866667

1。19866667

轉化後均值:

-

1。69031455e-15

-

1。63702385e-15

-

1。48251781e-15

-

1。62314606e-15

轉化前方差:

0。82530129

0。43214658

1。75852918

0。76061262

轉化後方差:

1。

1。

1。

1。

在資料縮放時,我們還可以使用類

RobustScaler

對異常值進行控制和選擇分位數範圍。

from

sklearn。preprocessing

import

RobustScaler

# 轉化資料1

rb1

=

RobustScaler

quantile_range

=

15

85

))

scaled_data1

=

rb1

fit_transform

data

# 轉化資料2

rb2

=

RobustScaler

quantile_range

=

25

75

))

scaled_data2

=

rb2

fit_transform

data

# 轉化資料3

rb3

=

RobustScaler

quantile_range

=

30

60

))

scaled_data3

=

rb3

fit_transform

data

# 繪製散點圖

fig

axes

=

plt

subplots

2

2

figsize

=

10

10

))

sns

scatterplot

x

=

data

[:,

0

],

y

=

data

[:,

1

],

ax

=

axes

0

0

])

sns

scatterplot

x

=

scaled_data1

[:,

0

],

y

=

scaled_data1

[:,

1

],

ax

=

axes

0

1

])

sns

scatterplot

x

=

scaled_data2

[:,

0

],

y

=

scaled_data2

[:,

1

],

ax

=

axes

1

0

])

sns

scatterplot

x

=

scaled_data3

[:,

0

],

y

=

scaled_data3

[:,

1

],

ax

=

axes

1

1

])

plt

setp

axes

ylim

=

-

4

5

],

xlim

=

-

2

8

]);

特徵選擇與特徵工程初探

可以看到,資料的大致分佈形態仍然很接近,但是資料的分佈範圍簡直大變樣。另外,由於我們設定了不同的分位數範圍,因此資料的樣本量也不太一樣。

常用的還有

MinMaxScaler

MaxAbsScaler

,前者透過刪除不屬於給定範圍的元素,後者則透過考慮使用最大絕對值來縮放資料。

scikit-learn還為每個樣本規範化提供了一個類:

Normalizer

。它可以對資料集的每個元素應用Max、L1和L2範數。

Max:每個值都除以資料集中的最大值;

L1:每個值都除以資料集中所有值的絕對值之和;

L2:每個值都除以資料集中所有值的平方和的平方根

我們來看一個例子。

from

sklearn。preprocessing

import

Normalizer

# 生成資料

data

=

np

array

([

1

2

])

reshape

1

2

print

‘原始資料:’

data

# Max

n_max

=

Normalizer

norm

=

‘max’

print

‘Max:’

n_max

fit_transform

data

))

# L1範數

n_l1

=

Normalizer

norm

=

‘l1’

print

‘L1範數:’

n_l1

fit_transform

data

))

# L2範數

n_l2

=

Normalizer

norm

=

‘l2’

print

‘L2範數:’

n_l2

fit_transform

data

))

原始資料:

[[

1

2

]]

Max

[[

0。5

1。

]]

L1範數

[[

0。33333333

0。66666667

]]

L2範數

[[

0。4472136

0。89442719

]]

六、特徵選擇和過濾

不是所有的特徵都能提供足夠的資訊的,甚至有些特徵會對我們的模型訓練產生障礙,因此在模型訓練開始前我們要對特徵做出一定的選擇。

接下來我們使用

SelectKBest

方法結合F檢驗來篩選迴歸模型的特徵。

from

sklearn。feature_selection

import

SelectKBest

f_regression

from

sklearn。datasets

import

load_boston

boston

=

load_boston

()

print

‘Boston data shape: ’

boston

data

shape

selector

=

SelectKBest

f_regression

X_new

=

selector

fit_transform

boston

data

boston

target

print

‘Filtered Boston data shape:’

X_new

shape

print

‘F-Scores:’

selector

scores_

Boston

data

shape

506

13

Filtered

Boston

data

shape

506

10

F

-

Scores

88。15124178

75。2576423

153。95488314

15。97151242

112。59148028

471。84673988

83。47745922

33。57957033

85。91427767

141。76135658

175。10554288

63。05422911

601。61787111

然後我們使用

SelectPercentile

結合卡方檢驗來篩選分類模型的特徵。

from

sklearn。feature_selection

import

SelectPercentile

chi2

from

sklearn。datasets

import

load_iris

iris

=

load_iris

()

print

‘Boston data shape: ’

iris

data

shape

selector

=

SelectPercentile

chi2

percentile

=

15

X_new

=

selector

fit_transform

iris

data

iris

target

print

‘Filtered Boston data shape:’

X_new

shape

print

‘F-Scores:’

selector

scores_

Boston

data

shape

150

4

Filtered

Boston

data

shape

150

1

F

-

Scores

10。81782088

3。59449902

116。16984746

67。24482759

在資料預處理時,我們還經常會採用主成分分析等方法來實現資料降維等目的,不過這一部分我們完全可以單獨拆出一個章節來講解,感興趣的朋友可以關注下後續的更新。

標簽: data  female  print  資料  Male