2019/11/19 Caesar
前言
??有這么一句話在業(yè)界廣泛流傳:數(shù)據(jù)和特征決定了機(jī)器學(xué)習(xí)的上限病线,而模型和算法只是逼近這個(gè)上限而已吓著。那特征工程到底是什么呢?顧名思義送挑,其本質(zhì)是一項(xiàng)工程活動(dòng)绑莺,目的是最大限度地從原始數(shù)據(jù)中提取特征以供算法和模型使用。通過(guò)特征提取惕耕,我們能得到未經(jīng)處理的特征纺裁,需要通過(guò)數(shù)據(jù)預(yù)處理手段來(lái)解決。
1. 特征工程
??特征處理是特征工程的核心部分司澎,sklearn提供了較為完整的特征處理方法欺缘,包括數(shù)據(jù)預(yù)處理,特征選擇挤安,降維等谚殊。首次接觸到sklearn,通常會(huì)被其豐富且方便的算法模型庫(kù)吸引蛤铜,但是這里介紹的特征處理庫(kù)也十分強(qiáng)大嫩絮!通過(guò)總結(jié)和歸納,人們認(rèn)為特征工程包括以下方面:
??本文中使用sklearn中的IRIS(鳶尾花)數(shù)據(jù)集來(lái)對(duì)特征處理功能進(jìn)行說(shuō)明昂羡。IRIS數(shù)據(jù)集由Fisher在1936年整理絮记,包含4個(gè)特征(Sepal.Length(花萼長(zhǎng)度)、Sepal.Width(花萼寬度)虐先、Petal.Length(花瓣長(zhǎng)度)怨愤、Petal.Width(花瓣寬度)),特征值都為正浮點(diǎn)數(shù)蛹批,單位為厘米撰洗。目標(biāo)值為鳶尾花的分類(Iris Setosa(山鳶尾)篮愉、Iris Versicolour(雜色鳶尾),Iris Virginica(維吉尼亞鳶尾))差导。導(dǎo)入IRIS數(shù)據(jù)集的代碼如下:
from sklearn.datasets import load_iris
#導(dǎo)入IRIS數(shù)據(jù)集
iris = load_iris()
#特征矩陣
iris.data
#目標(biāo)向量
iris.target
2. 數(shù)據(jù)預(yù)處理
2.1 無(wú)量綱化
??無(wú)量綱化使不同規(guī)格的數(shù)據(jù)轉(zhuǎn)換到同一規(guī)格试躏。常見的無(wú)量綱化方法有標(biāo)準(zhǔn)化和區(qū)間縮放法。標(biāo)準(zhǔn)化的前提是特征值服從正態(tài)分布设褐,標(biāo)準(zhǔn)化后颠蕴,其轉(zhuǎn)換成標(biāo)準(zhǔn)正態(tài)分布。區(qū)間縮放法利用了邊界值信息助析,將特征的取值區(qū)間縮放到某個(gè)特點(diǎn)的范圍犀被,例如[0, 1]等。
2.1.1 標(biāo)準(zhǔn)化
標(biāo)準(zhǔn)化需要計(jì)算特征的均值和標(biāo)準(zhǔn)差外冀,公式表達(dá)為:
使用preproccessing庫(kù)的StandardScaler類對(duì)數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化的代碼如下:
from sklearn.preprocessing import MinMaxScaler #區(qū)間縮放寡键,返回值為縮放到[0, 1]區(qū)間的數(shù)據(jù)MinMaxScaler().fit_transform(iris.data)
2.1.3 標(biāo)準(zhǔn)化與正則化的區(qū)別
??簡(jiǎn)單來(lái)說(shuō),標(biāo)準(zhǔn)化是依照特征矩陣的列處理數(shù)據(jù)雪隧,其通過(guò)求z-score的方法西轩,將樣本的特征值轉(zhuǎn)換到同一量綱下。正則化是依照特征矩陣的行處理數(shù)據(jù)脑沿,其目的在于樣本向量在點(diǎn)乘運(yùn)算或其他核函數(shù)計(jì)算相似性時(shí)藕畔,擁有統(tǒng)一的標(biāo)準(zhǔn),也就是說(shuō)都轉(zhuǎn)化為“單位向量”捅伤。規(guī)則為l2的歸一化公式如下:
正則化的過(guò)程是將每個(gè)樣本縮放到單位范數(shù)(每個(gè)樣本的范數(shù)為1)劫流,如果后面要使用如二次型(點(diǎn)積)或者其它核方法計(jì)算兩個(gè)樣本之間的相似性這個(gè)方法會(huì)很有用。
Normalization主要思想是對(duì)每個(gè)樣本計(jì)算其p-范數(shù)丛忆,然后對(duì)該樣本中每個(gè)元素除以該范數(shù)祠汇,這樣處理的結(jié)果是使得每個(gè)處理后樣本的p-范數(shù)(l1-norm,l2-norm)等于1。
??p-范數(shù)的計(jì)算公式:||X||p=(|x1|p+|x2|p+...+|xn|p)1/p
該方法主要應(yīng)用于文本分類和聚類中熄诡。例如可很,對(duì)于兩個(gè)TF-IDF向量的l2-norm進(jìn)行點(diǎn)積,就可以得到這兩個(gè)向量的余弦相似性凰浮。
使用preproccessing庫(kù)的Normalizer類對(duì)數(shù)據(jù)進(jìn)行歸一化的代碼如下:
>>> X = [[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]]
>>> normalizer = preprocessing.Normalizer().fit(X) # fit does nothing
>>> normalizer
Normalizer(copy=True, norm=‘l2‘)
>>>
>>> normalizer.transform(X)
array([[ 0.40..., -0.40..., 0.81...],
[ 1. ..., 0. ..., 0. ...],
[ 0. ..., 0.70..., -0.70...]])
2.2 對(duì)定量特征二值化
??定量特征二值化的核心在于設(shè)定一個(gè)閾值我抠,大于閾值的賦值為1,小于等于閾值的賦值為0袜茧,公式表達(dá)如下:
??使用preproccessing庫(kù)的Binarizer類對(duì)數(shù)據(jù)進(jìn)行二值化的代碼如下:
from sklearn.preprocessing import Binarizer
#二值化菜拓,閾值設(shè)置為3,返回值為二值化后的數(shù)據(jù)
Binarizer(threshold=3).fit_transform(iris.data)
2.3 對(duì)定性特征啞編碼
??由于IRIS數(shù)據(jù)集的特征皆為定量特征笛厦,故使用其目標(biāo)值進(jìn)行啞編碼(實(shí)際上是不需要的)纳鼎。使用preproccessing庫(kù)的OneHotEncoder類對(duì)數(shù)據(jù)進(jìn)行啞編碼的代碼如下:
from sklearn.preprocessing import OneHotEncoder
#啞編碼,對(duì)IRIS數(shù)據(jù)集的目標(biāo)值,返回值為啞編碼后的數(shù)據(jù)
OneHotEncoder().fit_transform(iris.target.reshape((-1,1)))
2.4 缺失值計(jì)算
??由于IRIS數(shù)據(jù)集沒有缺失值贱鄙,故對(duì)數(shù)據(jù)集新增一個(gè)樣本劝贸,4個(gè)特征均賦值為NaN,表示數(shù)據(jù)缺失逗宁。使用preproccessing庫(kù)的Imputer類對(duì)數(shù)據(jù)進(jìn)行缺失值計(jì)算的代碼如下:
在sklearn的preprocessing包中包含了對(duì)數(shù)據(jù)集中缺失值的處理映九,主要是應(yīng)用Imputer類進(jìn)行處理。
首先需要說(shuō)明的是瞎颗,numpy的數(shù)組中可以使用np.nan/np.NaN(Not A Number)來(lái)代替缺失值件甥,對(duì)于數(shù)組中是否存在nan可以使用np.isnan()來(lái)判定。
使用type(np.nan)或者type(np.NaN)可以發(fā)現(xiàn)改值其實(shí)屬于float類型言缤,代碼如下:
>>> type(np.NaN)
<type 'float'>
>>> type(np.nan)
<type 'float'>
>>> np.NaN
nan
>>> np.nan
nan
因此嚼蚀,如果要進(jìn)行處理的數(shù)據(jù)集中包含缺失值一般步驟如下:
1、使用字符串'nan'來(lái)代替數(shù)據(jù)集中的缺失值管挟;
2、將該數(shù)據(jù)集轉(zhuǎn)換為浮點(diǎn)型便可以得到包含np.nan的數(shù)據(jù)集弄捕;
3僻孝、使用sklearn.preprocessing.Imputer類來(lái)處理使用np.nan對(duì)缺失值進(jìn)行編碼過(guò)的數(shù)據(jù)集。
代碼如下:
>>> from sklearn.preprocessing import Imputer
>>> imp = Imputer(missing_values='NaN', strategy='mean', axis=0)
>>> X=np.array([[1, 2], [np.nan, 3], [7, 6]])
>>> Y=[[np.nan, 2], [6, np.nan], [7, 6]]
>>> imp.fit(X)
Imputer(axis=0, copy=True, missing_values='NaN', strategy='mean', verbose=0)
>>> imp.transform(Y)
array([[ 4. , 2. ],
[ 6. , 3.66666667],
[ 7. , 6. ]])
上述代碼使用數(shù)組X去“訓(xùn)練”一個(gè)Imputer類守谓,然后用該類的對(duì)象去處理數(shù)組Y中的缺失值穿铆,缺失值的處理方式是使用X中的均值(axis=0表示按列進(jìn)行)代替Y中的缺失值。當(dāng)然也可以使用imp對(duì)象來(lái)對(duì)X數(shù)組本身進(jìn)行處理斋荞。
通常荞雏,我們的數(shù)據(jù)都保存在文件中,也不一定都是Numpy數(shù)組生成的平酿,因此缺失值可能不一定是使用nan來(lái)編碼的凤优,對(duì)于這種情況可以參考以下代碼:
>>> line='1,?'
>>> line=line.replace(',?',',nan')
>>> line
'1,nan'
>>> Z=line.split(',')
>>> Z
['1', 'nan']
>>> Z=np.array(Z,dtype=float)
>>> Z
array([ 1., nan])
>>> imp.transform(Z)
array([[ 1. , 3.66666667]])