1.使用哑变量转化类型特征
1.哑变量的定义:
哑变量,也被称为虚拟变量,是一种在统计学和经济学领域非常常用的,用来把某些类型变量转化为二值变量的方法,在回归分析中的使用尤其广泛。
在决策树的章节中,就使用了pandas的get_dummies将adult数据集中的类型特征转换成了0和1表达的数值特征。
举例来展示get_dummies的使用:
import numpy as np
#导入pandas
import pandas as pd
fruits = pd.DataFrame({'数值特征':[5,6,7,8,9],'类型特征':['西瓜','香蕉','橘子','苹果','葡萄']})
#显示fruits数据表
fruits
运行代码,如下所示:
下面我们使用get_dummies来将类型特征转化为只有0和1的二值数值特征:
#转化字符串为数字
fruits_dum = pd.get_dummies(fruits)
fruits_dum
运行代码,如下图:
结果分析:从图中可以看到,通过get_dummies的转换,之前的类型变量全部变成了只有0或者1的数值变量,或者说,是一个系数矩阵。它在默认情况下不会对数值特征进行转化的。
假如我就是希望把数值特征也进行get_dummies转换怎么办?我们可以先将数值特征转换成字符串,然后通过get_dummies的colums参数来转换。
fruits['数值特征'] = fruits['数值特征'].astype(str)
pd.get_dummies(fruits,columns=['数值特征'])
运行代码,如下所示:
2.对数据进行装箱处理
在机器学习中,不同的算法建立的模型会有很多的差别。即便在同一个数据集中,这种差别也会存在。这是由于算法的工作原理不同所导致的,如KNN何MLP。下面我们手工生成一点数据,可以直观感受下相同数据下不同算法的差异,输入代码如下:
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()
这只是一个用来生成随机数据的代码。运行代码,如下图所示:
下面分别用MLP算法和KNN算法对这个数据集进行回归分析,输入代码:
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()
运行代码如下图所示:
结果分析:
从图中可以看出,MLP产生的回归线非常接近线性模型的效果,而KNN则相对复杂一些,它试图覆盖更多的数据点。
接下来,我们对数据集进行一下“装箱处理”,这种方法也称为“离散化处理”,输入代码如下:
#设置箱体数为11
bins = np.linspace(-5,5,11)
#装箱操作
target_bin = np.digitize(X,bins=bins)
#打印装箱数据范围
print('装箱数据范围:\n{}'.format(bins))
#打印前十个数据的特征值
print('\n前十个数据点的特征值:\n{}'.format(X[:10]))
#找到他们所在的箱子
print('\n前十个数据点所在的箱子:\n{}'.format(target_bin[:10]))
运行代码,如下:
结果分析:从结果可以看到,第一个箱子是-5到4之间,第二个箱子是-4到-3之间,以此类推。第一个数据点-1.152268所在的箱子是第4个,第二个数据点所在箱子是第9个,而第三个数据点所在的箱子是第10个,以此类推。
接下来,用新的方法来表达已经装箱的数据,所用到的方法就是sklearn的热独编码OneHotEncoder。OneHotEncoder和pandas的get_dummies功能是一样的,但是OneHotEncoder目前只能用于整型数值的类型变量。输入代码如下:
from sklearn.preprocessing import OneHotEncoder
onehot = OneHotEncoder(sparse = False)
onehot.fit(target_bin)
#使用独热编码转化数据
X_in_bin = onehot.transform(target_bin)
#打印结果
print('装箱后的数据形态:{}'.format(X_in_bin.shape))
print('\n装箱后的前十个数据点:\n{}'.format(X_in_bin[:10]))
运行代码,得到如下图所示的结果:

结果分析:现在可以看到,虽然数据集中样本数量仍然是50个,但特征数变成了10个,这是因为我们生成的箱子是10个,而新的数据点的特征是用其所在的箱子号码来表示的。例如,第一个数据点在第四个箱子上,则其特征列表中第四个数字是1,其他数字是0,以此类推。
下面我们再用MLP和KNN算法重新进行回归分析,输入代码如下:
#使用独热编码进行数据表达
new_line = onehot.transform(np.digitize(line,bins=bins))
#使用新的数据来训练模型
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()
运行代码,得到如下图所示的结果:
结果分析:有意思的事情发生了,MLP模型和KNN模型变得更加相似了,尤其是在x>0时,两个模型几乎完全重合。发现MLP的回归模型变得比之前更加复杂了。而KNN变得更加简单。所以这是对样本特征进行装箱的一个好处:
它可以纠正模型过拟合或者欠拟合的问题。尤其是当针对大规模高纬度的数据集使用线性模型的时候,装箱处理可以大幅提高线性模型的预测准确率。