1.使用啞變量轉(zhuǎn)化類型特征
1.啞變量的定義:
啞變量,也被稱為虛擬變量,是一種在統(tǒng)計學(xué)和經(jīng)濟學(xué)領(lǐng)域非常常用的,用來把某些類型變量轉(zhuǎn)化為二值變量的方法,在回歸分析中的使用尤其廣泛。
在決策樹的章節(jié)中,就使用了pandas的get_dummies將adult數(shù)據(jù)集中的類型特征轉(zhuǎn)換成了0和1表達的數(shù)值特征。
舉例來展示get_dummies的使用:
import numpy as np
#導(dǎo)入pandas
import pandas as pd
fruits = pd.DataFrame({'數(shù)值特征':[5,6,7,8,9],'類型特征':['西瓜','香蕉','橘子','蘋果','葡萄']})
#顯示fruits數(shù)據(jù)表
fruits
運行代碼,如下所示:

下面我們使用get_dummies來將類型特征轉(zhuǎn)化為只有0和1的二值數(shù)值特征:
#轉(zhuǎn)化字符串為數(shù)字
fruits_dum = pd.get_dummies(fruits)
fruits_dum
運行代碼,如下圖:

結(jié)果分析:從圖中可以看到,通過get_dummies的轉(zhuǎn)換,之前的類型變量全部變成了只有0或者1的數(shù)值變量,或者說,是一個系數(shù)矩陣。它在默認(rèn)情況下不會對數(shù)值特征進行轉(zhuǎn)化的。
假如我就是希望把數(shù)值特征也進行g(shù)et_dummies轉(zhuǎn)換怎么辦?我們可以先將數(shù)值特征轉(zhuǎn)換成字符串,然后通過get_dummies的colums參數(shù)來轉(zhuǎn)換。
fruits['數(shù)值特征'] = fruits['數(shù)值特征'].astype(str)
pd.get_dummies(fruits,columns=['數(shù)值特征'])
運行代碼,如下所示:

2.對數(shù)據(jù)進行裝箱處理
在機器學(xué)習(xí)中,不同的算法建立的模型會有很多的差別。即便在同一個數(shù)據(jù)集中,這種差別也會存在。這是由于算法的工作原理不同所導(dǎo)致的,如KNN何MLP。下面我們手工生成一點數(shù)據(jù),可以直觀感受下相同數(shù)據(jù)下不同算法的差異,輸入代碼如下:
import numpy as np
import matplotlib.pyplot as plt
rnd = np.random.RandomState(38)
x = rnd.uniform(-5,5,size=50)
y_no_noise = (np.cos(6*x)+x)
X = x.reshape(-1,1)
y = (y_no_noise+rnd.normal(size=len(x)))/2
plt.plot(X,y,'o',c='r')
plt.show()
這只是一個用來生成隨機數(shù)據(jù)的代碼。運行代碼,如下圖所示:

下面分別用MLP算法和KNN算法對這個數(shù)據(jù)集進行回歸分析,輸入代碼:
from sklearn.neural_network import MLPRegressor
from sklearn.neighbors import KNeighborsRegressor
line = np.linspace(-5,5,1000,endpoint=False).reshape(-1,1)
mlpr = MLPRegressor().fit(X,y)
knr = KNeighborsRegressor().fit(X,y)
#繪制圖形
plt.plot(line,mlpr.predict(line),label='MLP')
plt.plot(line,knr.predict(line),label='KNN')
plt.plot(X,y,'o',c='r')
plt.legend(loc='best')
plt.show()
運行代碼如下圖所示:

結(jié)果分析:
從圖中可以看出,MLP產(chǎn)生的回歸線非常接近線性模型的效果,而KNN則相對復(fù)雜一些,它試圖覆蓋更多的數(shù)據(jù)點。
接下來,我們對數(shù)據(jù)集進行一下“裝箱處理”,這種方法也稱為“離散化處理”,輸入代碼如下:
#設(shè)置箱體數(shù)為11
bins = np.linspace(-5,5,11)
#裝箱操作
target_bin = np.digitize(X,bins=bins)
#打印裝箱數(shù)據(jù)范圍
print('裝箱數(shù)據(jù)范圍:\n{}'.format(bins))
#打印前十個數(shù)據(jù)的特征值
print('\n前十個數(shù)據(jù)點的特征值:\n{}'.format(X[:10]))
#找到他們所在的箱子
print('\n前十個數(shù)據(jù)點所在的箱子:\n{}'.format(target_bin[:10]))
運行代碼,如下:

結(jié)果分析:從結(jié)果可以看到,第一個箱子是-5到4之間,第二個箱子是-4到-3之間,以此類推。第一個數(shù)據(jù)點-1.152268所在的箱子是第4個,第二個數(shù)據(jù)點所在箱子是第9個,而第三個數(shù)據(jù)點所在的箱子是第10個,以此類推。
接下來,用新的方法來表達已經(jīng)裝箱的數(shù)據(jù),所用到的方法就是sklearn的熱獨編碼OneHotEncoder。OneHotEncoder和pandas的get_dummies功能是一樣的,但是OneHotEncoder目前只能用于整型數(shù)值的類型變量。輸入代碼如下:
from sklearn.preprocessing import OneHotEncoder
onehot = OneHotEncoder(sparse = False)
onehot.fit(target_bin)
#使用獨熱編碼轉(zhuǎn)化數(shù)據(jù)
X_in_bin = onehot.transform(target_bin)
#打印結(jié)果
print('裝箱后的數(shù)據(jù)形態(tài):{}'.format(X_in_bin.shape))
print('\n裝箱后的前十個數(shù)據(jù)點:\n{}'.format(X_in_bin[:10]))
運行代碼,得到如下圖所示的結(jié)果:

結(jié)果分析:現(xiàn)在可以看到,雖然數(shù)據(jù)集中樣本數(shù)量仍然是50個,但特征數(shù)變成了10個,這是因為我們生成的箱子是10個,而新的數(shù)據(jù)點的特征是用其所在的箱子號碼來表示的。例如,第一個數(shù)據(jù)點在第四個箱子上,則其特征列表中第四個數(shù)字是1,其他數(shù)字是0,以此類推。
下面我們再用MLP和KNN算法重新進行回歸分析,輸入代碼如下:
#使用獨熱編碼進行數(shù)據(jù)表達
new_line = onehot.transform(np.digitize(line,bins=bins))
#使用新的數(shù)據(jù)來訓(xùn)練模型
new_mlpr = MLPRegressor().fit(X_in_bin,y)
new_knr = KNeighborsRegressor().fit(X_in_bin,y)
#繪制圖形
plt.plot(line,new_mlpr.predict(new_line),label='NEW MLP')
plt.plot(line,new_knr.predict(new_line),label='NEW KNN')
plt.plot(X,y,'o',c='r')
plt.legend(loc='best')
plt.show()
運行代碼,得到如下圖所示的結(jié)果:

結(jié)果分析:有意思的事情發(fā)生了,MLP模型和KNN模型變得更加相似了,尤其是在x>0時,兩個模型幾乎完全重合。發(fā)現(xiàn)MLP的回歸模型變得比之前更加復(fù)雜了。而KNN變得更加簡單。所以這是對樣本特征進行裝箱的一個好處:
它可以糾正模型過擬合或者欠擬合的問題。尤其是當(dāng)針對大規(guī)模高緯度的數(shù)據(jù)集使用線性模型的時候,裝箱處理可以大幅提高線性模型的預(yù)測準(zhǔn)確率。