赵走x博客
网站访问量:151485
首页
书籍
软件
工具
古诗词
搜索
登录
深入浅出Python机器学习:31、自动特征选择
深入浅出Python机器学习:30、数据“升维”
深入浅出Python机器学习:29、数据表达
深入浅出Python机器学习:28、聚类算法
深入浅出Python机器学习:27、特征提取
深入浅出Python机器学习:26、数据降维
深入浅出Python机器学习:25、数据预处理
深入浅出Python机器学习:24、神经网络实例一一手写识别
深入浅出Python机器学习:23、神经网络的原理及使用
深入浅出Python机器学习:22、神经网络的前世今生
深入浅出Python机器学习:21、SVM 实例一一波士顿房价回归分析
深入浅出Python机器学习:20、SVM 的核函数与参数选择
深入浅出Python机器学习:19、支持向量机SVM 基本概念
深入浅出Python机器学习:18、随机森林实例一一要不要和中目亲对象进一步发展
深入浅出Python机器学习:17、随机森林
深入浅出Python机器学习:16、决策树
深入浅出Python机器学习:15、朴素贝叶斯实战一一判断肿瘤是良性还是恶性
深入浅出Python机器学习:14、朴素贝叶斯算法的不同方法
深入浅出Python机器学习:13、朴素贝叶斯基本概念
深入浅出Python机器学习:12、使用L1 正则化的线性模型一一套索回归
深入浅出Python机器学习:11、使用L2 正则化的线性模型一一岭回归
深入浅出Python机器学习:10、最基本的线性模型一一线性回归
深入浅出Python机器学习:9、线性模型的墓本概念
深入浅出Python机器学习:8、K 最近邻算法项目实战一一酒的分类
深入浅出Python机器学习:7、K最近邻算法用于回归分析
深入浅出Python机器学习:6、K最近邻算法处理多元分类任务
深入浅出Python机器学习:5、k最近邻算法在分类任务中的应用
深入浅出Python机器学习:4、K 最近邻算法的原理
深入浅出Python机器学习:3、一些必需库的安装及功能简介
深入浅出Python机器学习:2、基于python i吾言的环境配置
深入浅出Python机器学习:1、概述
人脸数据集加载faces = fetch_lfw_people()报错
31、直方图
74、插件开发:Android端API实现
Python3之socket编程--3:基于UDP的套接字
15、使用 jQuery 处理 Ajax 请求
深入浅出Python机器学习:29、数据表达
资源编号:75930
人工智能
深入浅出Python机器学习
热度:111
数据表在与特征工程--锦上再添花
> 数据表在与特征工程--锦上再添花 读者朋友们还记得在第6 幸决策树与随机森林中,我们让小C 用机器学习的方法帮助小Q 决定要不要和相亲对象进一步交往的例子吗?细心的读者朋友可能会发现一个问题,那就是在这个例子中,我们使用的adult 数据集和其他的数据集有点不同,其他的数据集中样本的特征一般是一个数值,而adult 数据集中,样本的特征有很多是用字符串来表达的,如工作单位性质,有些是State-gov ,有些是private ,还有一些是Federal - gov 。 我们管这些字符串式的特征称为“类型特征”( categorical features ),而把之前说的数值类型的特征称为“连续特征”( continuous features ) 。在本章中,我们将讨论如何将不同的特征进行转换、如何合理表达数据,以及如何进行特征选择等。 本章主要涉及的知识点有: 1、使用哑变量对类型特征进行转化 2、对数据进行装箱处理 3、几种常用的数据“升维”方法 4、常用的自动特征选择方法 # 1、使用哑变量转化类型特征 首先, 我们要了解一下什么是哑变量( Dummy Variables )。哑变量, 也被称为虚拟变量,是一种在统计学和经济学领域非常常用的, 用来把某些类型变量转化为二值变量的方法,在回归分析中的使用尤其广泛。在第6 章中,我们就是使用了pandas 的get_dummies 将adult 数据集中的类型特征转换成了用0 和1表达的数值特征。 下面我们用一个例子来展示下get_dummies 的使用, 在Jupyter Notebook 中输入代码如下: ``` # 导入pandas import pandas as pd # 手工输入一个数据表 fruits = pd.DataFrame({'数值特征': [5, 6, 7, 8, 9], '类型特征': ['西瓜', '香蕉', '橘子', '苹果', '葡萄']}) # 显示fruits 数据表 display(fruits) ``` 运行代码,会得到如图10-1 所示的结果。  图I0-1 手动生成的水果数据集 [结果分析] 图10-1 就是我们使用pandas 的DataFrame 生成的一个完整数据集, 其中包括整型数值特征[5,6,7,8,9], 还包括字符串组成的类型特征“ 西瓜”“ 香蕉”“桶子”“ 苹果” “ 葡萄”。 下面我们使用get_dummies 来将类型特征转化为只有0 和1的二值数值特征,输入代码如下: ``` # 转化数据表中的字符串为数值 fruits_dum=pd.get_dummies(fruits) # 显示转化后的数据表 display(fruits_dum) ``` 运行代码, 会得到如图10- 2 所示的结果。  图10-2 经过get_dummies 转化的水果数据集 [结果分析}从图1 0-2 中我们看到,通过get_dummies 的转换,之前的类型变量全部变成了只有0 和1的数值变量,或者说,是一个稀疏矩阵。相信有些读者朋友可能会发现,数值特征并没有发生变化,这也是正式get_dummies 的机智过人之处,它在默认情况下是不会对数值特征进行转化的。 那读者朋友可能会问了,假如我就是希望把数值特征也进行get_dummies 转换怎么办呢?没问题的,我们可以先将数值特征转换为字符串,然后通过get_dummies 的columns 参数来转换。下面我们来试一下,在Jupyter Notebook 中输入代码如下: ``` # 令程序将数值也看作字符串 fruits['数值特征']=fruits['数值特征'].astype(str) # 在用get_dummies转化字符串 pd.get_dummies(fruits,columns=['数值特征']) ``` 在代码中,我们首先用.astype ( str) 指定了“数值特征”这一列是字符串类型的数据,然后在get_dummies 中指定co lumns 参数为“数值特征”这一列,这样get_dummies就会只转化数值特征了,运行代码,会得到如图1 0- 3 所示的结果。  图1 0-3 指定get_dummies 转换数值特征的结果 > ⚠️:实际上,如果我们不用fruits [ ‘ 数值特征’ ] = fruits [‘数值特征’] . astype ( str ) 这行代码把数值转化为字符串类型,依然会得到同样的结果。但是在大规模数据集中,还是建议大家进行转化字符串的操作,避免产生不可预料的错误。 # 2、对数据进行装箱处理 在机器学习中,不同的算法建立的模型会有很大的差别。即便是在同一个数据集中,这种差别也会存在。这是由于算法的工作原理不同所导致的,如KNN 和MLP 。下面我们手工生成一点数据,让读者朋友可以直观感受下相同数据下不同算法的差异。输入代码如下: ``` # 导人numpy 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 = ’ E ’ ) plt.plot(X, y, 'o', c='r') # 显示图形 plt.show() ``` 这只是一个用来生成随机数据的代码,大家可以不用太在意它有什么具体的意义。 运行代码,会得到如图10-4 所示的结果。  图10-4 手动生成的数据集 下面我们分别用MLP 算法和KNN 算法对这个数据集进行回归分析,在JupyterNotebook 中输入代码如下: ``` # 导入神经网络 from sklearn.neural_network import MLPRegressor # 导人KNN 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 的参数都为默认值,即MLP 有1 个隐藏层, 节点数为100 ,而KNN 的n _neighbors 数量为5 。运行代码, 会得到如图10-5 所示的结果。  图10-5 MLP 和KNN 进行回归分析的差异 [结果分析] 从图10-5 中可以看出, MLP 产生的回归线非常接近线性模型的结果,而KNN 则相对更复杂一些,它试图覆盖更多的数据点。即便是用肉眼观察,也能发现这两者所进行的回归预测有明显的差别。那么在现实当中,我们应该采用哪个算法的预测结果呢?先不要着急, 接下来我们对数据进行一下“ 装箱处理” ( binning ),这种处理方法也称为“ 离散化处理”( discretization )。现在在Jupyter Notebook 中输入代码如下: ``` # 设置箱体数为11 bins=np.linspace(-5,5,11) # 将数据进行装箱操作 target_bin=np.digitize(X,bins=bins) # 打印装箱数据范围 print('装箱数据范围:{}'.format(bins)) # 打印前十个数据的特征值 print('前十个数据点的特征值:{}'.format(X[:10])) # 找到它们所在的箱子 print('前十个数据点所在的箱子:{}'.format(target_bin[:10])) ``` 由于我们在生成这个实验数据集的时候, 是在- 5 到5 之间随机生成了50 个数据点,因此我们在生成“ 箱子”( 如果觉得这么叫有点土的话,也可以叫它“ 容器”〉的时候,也指定范围是从5 到5 之间,生成11 个元素的等差数列, 这样每两个数值之间就形成了一个箱子, 一共10 个。运行代码, 会得到如图10-6 所示的结果。 ``` 装箱数据范围:[-5. -4. -3. -2. -1. 0. 1. 2. 3. 4. 5.] 前十个数据点的特征值:[[-1.1522688 ] [ 3.59707847] [ 4.44199636] [ 2.02824894] [ 1.33634097] [ 1.05961282] [-2.99873157] [-1.12612112] [-2.41016836] [-4.25392719]] 前十个数据点所在的箱子:[[ 4] [ 9] [10] [ 8] [ 7] [ 7] [ 3] [ 4] [ 3] [ 1]] ``` 图10-6 数据装箱情况 [结果分析] 从结果中可以看到, 第一个箱子是-5 到-4 之间, 第二个箱子是- 4 到- 3之间,以此类推。第1个数据点一1.1522688 所在的箱子是第4 个, 第2 个数据点3.59707847所在的箱子是第9 个,而第3 个数据点4.44199636 所在的箱子是第10 个,以此类推。 接下来我们要做的事情,就是用新的方法来表达己经装箱的数据,所要用到的方法就是sci.kit-learn 的独热编码OneHotEncoder 。On eHotEncoder 和pandas 的get_ dummies 功能基本上是一样的, 但是OneHotEncoder 目前只能用于整型数值的类型变量。现在输入代码如下: ``` # 使用独热编码转化数据 X_in_bin = onehot . transform(target_bin) # 打印结果 print('装箱后的数据形态:{}'.format(X_in_bin.shape)) print('装箱后的前10个数据点:{}'.format(X_in_bin[:10])) ``` 运行结果: ``` 装箱后的数据形态:(50, 10) 装箱后的前10个数据点:[[0. 0. 0. 1. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0. 0. 1. 0.] [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.] [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.] [0. 0. 0. 0. 0. 0. 1. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 1. 0. 0. 0.] [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 1. 0. 0. 0. 0. 0. 0.] [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.] [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]] ``` [结果分析]现在可以看到,虽然数据集中样本的数量仍然是50 个,但特征数变成了10 个。这是因为我们生成的箱子是10 个,而新的数据点的特征是用其所在的箱子号码来表示的。例如, 第1 个数据点在第4 个箱子中,则其特征列表中第4 个数字是1,其他数字是0 ,以此类推。 这样一来,相当于我们把原先数据集中的连续特征转化成了类别特征。现在我们再用MLP 和配刑算法重新进行回归分析,看看结果发生了什么变化。输入代码如下: ``` # 使用独热编码进行数据表达 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() ``` 在这部分代码中,我们对需要预测的数据也要进行相同的装箱操作,这样才能得到正确的预测结果。运行代码,将会得到如图10-8 所示的结果。 图10- 8 特征装箱之后的MLP 回归和KNN回归  [结果分析} 有意思的事情发生了, MLP 模型和KNN 模型变得更相似了,尤其在x > 0的部分, 两个模型几乎完全重合。如果和图10-5 对比的话,你会发现MLP 的回归模型变得更复杂, 而KNN 的模型变得更简单。所以这是对样本特征进行装箱的一个好处:它可以纠正模型过拟合或者欠拟合的问题。尤其是当针对大规模高维度的数据集使用线 性模型的时候,装箱处理可以大幅提高线性模型的预测准确率。 > ⚠️:这种对于样本数据进行装箱的操作对于基于决策树的算法(如随机森林、梯度上升决策树,当然也包括决策树本身)没有太多的作用,因为这类算法本身就是不停在拆分样本的特征数据,所以不需要再使用装箱操作。