简介
特征工程将数据转换为能更好地表示潜在问题的特征,从而提高机器学习性能。
特征工程具体包含内容如下:
- 转换数据的过程。处理的数据经常是表格形式的,此时数据会被组织成行(观察值)和列(属性)。
- 特征。特征是对机器学习过程有意义的数据属性,我们需要经常查看表格,确定哪些列是特征,哪些列只是普通的属性。
- 更好地表示潜在问题。转换数据的目的在于更好地表达更大的问题。
- 提高机器学习性能。特征工程的最终目的在于获取更好的数据,以便学习算法从中挖掘模式,取得更好的效果。
评估特征工程的步骤:
- 在应用任何特征工程之前,得到机器学习模型的基准性能。
- 应用一种或多种特征工程。
- 对于每种特征工程,获取一个性能指标,并与基准性能进行对比。
- 如果性能的增量(变化)大于某个阈值(一般由我们定义),则任务这种特征工程是有益的,并在机器学习流水线上应用。
- 性能的改变一般以百分比计算(如果基准性能从
40%
的准确率提升到76%
的准确率,那么改变就是90%
)。
本篇文章的重点在于理解和转换特征。
前提
当你看到这里时,我想你是真的想要学习特征工程,但这也需要一些前提,希望你都具有:
- 熟悉
Python
的基础语法。 - 理解风控模型相关的知识。
- 挑战已有认知的能力。
前提声明,本文章的大部分内容为作者学习《特征工程入门与实践》一书中的学习笔记,如果需要可以自行购买学习,并且本文不包含原书任何代码内容,见谅。
特征理解
前面我们了解了要做的事情,那么接下来就是开始干一些真实的事情:理解和处理数据。
数据结构
结构化(有组织)数据可以分为观察值和特征的数据,一般以表格的形式组织(行是观察值,列是特征)。
非结构化(无组织)数据作为自由流动的实体,不遵循标准组织结构的数据。
结构化和非结构化数据的区别:
- 以原始文本格式存储的数据。
- 科学仪器报告的气象数据是高度结构化的,因为存在表格的行列结构。
数据分类
定量数据本质上是数值,应该是衡量某样东西的数量。
定性数据本质上是类别,应该是描述某样东西的性质。
但是有时候数据可以同时是定量和定性的。
数据等级
数据的四个等级分别是:
- 定类等级(
nominal level
) - 定序等级(
ordinal level
) - 定距等级(
interval level
) - 定比等级(
ratio level
)
每个等级都有不同的控制和数学操作等级,了解数据的等级十分重要,因为它决定了可以执行的可视化类型和操作。
定类等级
定类等级是数据的第一个等级,其结构最弱,这个等级的数据只按名称分类。这些数据都是定性的。
对于每个等级都会介绍可执行和不可执行的数学操作,而在这个等级上,不能执行任何定量数学操作。定序等级
定序等级在继承了定类等级的所有属性,而且还提供了重要的附加属性:
- 定序等级的数据可以自然排序。
- 排序则意味者列中的某些数据比其他数据更好或更大。
和定类等级一样,定序等级的天然数据属性仍然是类别,即使用数来表示类别也是如此。
定距等级
在定距等级数值数据不仅可以像定序等级的数据一样排序,而且值之间的差异也有意义,这就意味着在定距等级不仅可以对值进行排序和比较,还可以进行加减运算。定比等级
在定比等级我们可以进行最大程度的控制和数学计算能力,和定距等级一样,定比等级的数据也是定量数据,不仅继承了定距等级的加减运算,而且也有了一个绝对零点的概念,可以进行乘除运算。理解数据的不同等级对于特征工程是非常重要的,当需要构建新特征或修复旧特征时,必须确定办法去处理每一列。因此当你拿到一个数据集时,可以按照以下的流程处理:
- 数据是否有组织?数据是否以表格形式存在?是否有不同的列?还是以非结构化的文本形式存在?
- 每列的数据是定量的还是定性的?单元格里的数代表是数值还是字符串?
- 每列处于哪个等级?是定类、定序、定距、还是定比?
- 可以使用哪些图表?条形图、饼图、茎叶图、箱线图、直方图、还是其他图形?
特征增强
到达这里我们在前面已经说了在实际应用中评估和理解出现的不同的数据类型。
下面我们进一步的修改数据集,具体来说就是开始清洗和增强数据,前者是指调整已存在的行和列,而后者则是指在数据集中删除和添加新的列,当然这些所有的目的都是为了优化机器学习的效果。
缺失值
特征增强的第一种方法就是识别数据的缺失值,这样可以让我们更好的明白如何使用真实的数据,因为在实际种总会有各种原因导致数据的确实。
探索性数据分析
首先进行探索性数据分析(EDA
)来识别缺失的值,可以使用Numpy
和Pandas
来存储数据并进行一些简单的计算,还可以使用可视化工具来观察数据的分布情况。处理缺失值
缺失值会引起很多问题,最重要的是大部分学习算法不能处理缺失值。目前两个最主要的处理方法:- 删除缺少值的行。
- 填充缺失值。
填充指的是利用现有知识/数据来确定缺失的数量值并填充的行为。
归一化/标准化
数据尺度的不同导致数据的集合差别很大,因此归一化操作旨在将行与列对齐转化为一致的规则,最常用的方式就是将所有定量列转化为同一个静态范围内的值。而标准化通过确保所有行和列在机器学习中得到平等对待,让数据的处理保持一致。
常用的三种数据归一化方法:
Z
分数标准化Z
分数标准化是最常用的标准化技术,他利用了统计学内最简单的z
分数思想。z
分数标准化的输出会被重新缩放,使均值为0
、标准差为1
,通过缩放特征、统一化均值和方差,可以让KNN
这种模型达到最优化,而不会出现倾向于较大比例的特征。公式很简单,对于每列,用这个公式替换单元格:1
z = (x - μ) / σ
在这个公式中
z
是新的值(z
分数);x
是单元格原来的值;μ
是该列的均值;σ
是列的标准差。z
表示该值到均值的距离,如果它最初低于该列的均值,则z
分数就是负数。min-max
标准化min-max
标准化与Z
分数标准化类似,因为他也是一个公式替换列中的每个值。此处的公式为:1
m = (X - Xmin) / (Xmax - Xmin)
在这个公式中
m
是新的值;X
是单元格原来的值;Xmax
是该列的最大值;Xmin
是该列的最小值。行归一化
行归一化不是计算每列的统计值,而是会保证每行有单位范数,意味着每行的向量长度相同。如果每行数据都在一个n
维空间内,那么每行都有一个向量范数,也就是每行都是空间内的一个向量:1
x = (x1, x2, ..., xn)
那么范数的计算方法为:
1
||x|| = (x1^2 + x2^2 + ... + xn^2) ^ (1/2)
很多算法会受尺度的影响,下面就是一些流行的学习算法:
- KNN
- 依赖欧几里得距离。
- K
均值距类 - 依赖欧几里得距离。
- 逻辑回归、支持向量机、神经网络 - 使用梯度下降来学习权重。
- 主成分分析 - 特征向量将偏向较大的列。
特征增强的意义在于识别有问题的区域,并确定哪种修复方法最有效,当然也可以删除数据,但是我们应该考虑如何用最好的方法解决问题,而不是删除了事。
特征构建
之前研究的特征都是定量的,那么接下来我们研究分类数据,主要的目的就是利用现有的特征构建全新的特征,让模型从中学习。
编码分类变量
将分类数据转化为数值数据。
定类等级编码
主要方法就是将分类数据转换为虚拟变量,这样有两种选择:- 使用
Pandas
自动找到分类变量进行编码。 - 创建自定义虚拟变量编码器,在流水线中工作。
虚拟变量的取值是
1
或0
,代表某个类别的有无,虚拟变量代表定性数据的代理,或者说是数值的替代。
当使用虚拟变量时,需要小心虚拟变量陷阱。虚拟陷阱是指自变量有多重共线性或高度相关,简单来说就是这些变量能依据彼此来预测,当存在多个自变量共线性时,就会陷入虚拟变量陷阱。通常为了避免虚拟变量陷阱我们会忽略一个常量或者虚拟类型。- 使用
定序等级编码
将字符串转换为数值数据,在定序等级中由于数据的顺序有含义,使用虚拟变量是没有意义的,为了保持顺序,我们使用标签编码器。
标签编码器是指顺序数据的每个标签都会有一个相关数据。另外如果数值数据是连续的,那么就可以将其转化为分类变量是有意义的。
Pandas
中有一个函数cut
,可以将数据进行分箱,也可以成为分桶,其意义是将会创建数据的范围。扩展数值特征
有很多种办法从数字特征中创建扩展特征。
在处理数值数据、创建很多特征时,一个关键的方法就是使用scikit-learn
的polynomial-Features
类,这个类会创建新的列,他们是原有列的乘积,用于捕获特征交互。
更具体来说就是这个类会生成一个新的特征矩阵,里面是原始数据各个特征的多项式组合,阶数小于或等于指定的阶数。
文本的特征构建
之前一直处理分类数据和分值数据,虽然分类数据是字符串但是里面的文本仅仅是个类别,下面我们将进行更长的文本数据,这种文本数据比单个类别的文本更复杂的多,因为长文本包含一系列类别,或称为词项。
scikit-learn
有一个 feature_extraction
模块,顾名思义是能以机器学习算法支持的方法提取数据的特征,包括文本数据,这个模块同时也包含了处理文本时需要的一些方法。
将文本数据称为语料库,尤其是指文本内容或文档的集合。
将语料库转换为数值表示(向量化)的常见方法就是词袋,其基本思想是通过单词的出现来描述文档,完全忽略单词在文档中的位置。在他最简单的形式中,用一个袋子来表示文本,不考虑语法和词序,并将这个袋子视为一个集合,其中重复度最高的单词最为重要。
词袋的三个步骤是:
- 分词。分词过程就是用空白、标点将单词分开,将其变为词项,每个可能出现的词项都有一个整数
ID
。 - 计数。简单地计算文档中词项的出现次数。
- 归一化。将词项在大多数文档中的重要性按逆序排列。
下面是常用的几种向量化方法:
CountVectorizer
,将文本数据转换为其向量表示的最常用方法,和虚拟变量类似CountVectorizer
将文本列转换为矩阵,其中的列就是词项,单元值是每个文档中每个词项的出现次数。这个矩阵叫做文档-词矩阵,因为每行代表一个文档,每列代表一个词。
在实际使用中,还可以使用词干提取,可以将词汇中的词干提取出来,也就是把单词转换为其词根,从而缩小词汇量。TF-IDF
向量化器,由两部分组成,表示词频的TF
部分,以及表示逆文档频率 的IDF
部分。TF-IDF
是一个用于信息检索和聚类的词加权方法。TF
词频,衡量词在文档中出现的频率。由于文档的长度不同,词在短文本中出现的频率可能比长文本中小得多,因此一般会对词频进行归一化,用其除以文档长度或文档的总词数。IDF
逆文档频率,衡量词的重要性。在计算词频时,认为所有的单词同等重要,但是一些词(例如of
、is
等)有可能出现多次,但这些词并不重要,因此我们需要减少常见词的权重,加大稀有词的权重。
在这里你已经了解到了在分类数据和分值数据中填充缺失值,针对分类数据进行编码,数值数据和文本数据的特征构建,那么接下来就是选择合适的特征。
特征选择
特征选择是从原始数据中选择对于预测流水线而言最好的特征的过程,更正式的说就是给定 n
个特征,我们搜索其中的 k (k < n)
个特征来改善机器学习的效果,总而言之就是 特征选择尝试剔除数据中的噪声。
特征选择的方法可以分为两大类:基于统计的特征选择和基于模型得到特征选择。基于统计的特征选择很大程度上依赖于机器学习模型之外的统计测试,以便在流水线的训练阶段选择特征。而基于模型的特征选择则依赖于一个预处理步骤,需要训练一个辅助的机器学习模型,并利用其预测能力来选择特征。其实这两种类型都是试图从原始特征中选择一个子集,减少数据大小,只留下预测能力最高的特征。
当然这其中也会存在问题,那么需要解决的问题就是:
- 找到
k
特征子集的办法。 - 在机器学习中对 更好 的定义。
当然对上述目标更好的说明就是我们要实现更好的预测性能,而且仅使用简单的指标进行测量。再更加具体的就是:
- 模型拟合/训练所需的时间。
- 拟合后的模型预测新实例的时间。
- 需要持久化(永久保存)的数据大小。
特征选择算法可以智能地从数据中提取最重要的信号并忽略噪声,达到以下两种结果:
- 提升模型性能,在删除冗余数据之后,基于噪声和不相关数据做出错误决策的情况会减少,而且模型可以在重要的特征上练习,提高预测性能。
- 减少训练时间和预测时间,因为拟合的数据更少,所以模型一般在拟合和训练上有速度提升,让流水线的整体速度更快。
基于统计的特征选择
通过统计数据,可以快速、简便地解释定量和定性数据。下面使用两种概念:- 皮尔逊相关系数。
- 假设检验。
这两种方法都是单变量方法,仅仅是为了提高机器学习性能而每次选择单一特征以创建更好的数据集这种是最简便的。
皮尔逊相关系数会测量列之间的线性关系,该系数在
1 ~ -1
之间变化,其中0
代表没有线性关系,1
或者-1
表示相关性关系最强。假设检验是一种统计学方法,可以对单个特征进行复杂的统计检验,在特征选择中使用假设检验可以尝试从数据集中选择最佳特征,但是这里更依赖传统的依赖于形式化的统计方法,并通过所谓的
P
值进行检验。p
值是介于0
和1
的小数,代表在假设检验下,给定数据偶然出现的概率,简而言之,p
值越低,拒绝零假设的概率越大。当然假设的原则是 特征与响应变量没有关系(零假设)为真还是为假。
作为一种统计检验,假设检验用于在给定数据样本时确定可否在整个数据集上应用某种条件,假设检验的结果会告诉我们是否应该相信或拒绝假设(并选择另一个假设)。基于样本数据,假设检验会确定是否应拒绝零假设,通常会采用p
值来得出结论。基于模型的特征选择
本次使用的两类模型是基于树模型和线性模型,这两类模型都有特征排列的功能,在对特征划分子集时很有用。- 基于树模型,在拟合决策树时,决策树会从根节点开始,在每个节点处贪婪地选择最优分割,优化节点纯净度指标。默认情况下
scikit-learn
每步都会优化 基尼系数,每次分割时,模型会记录每个分割对整体优化目标的帮助,因此在树形结构中,这些指标对特征重要性有作用。 - 基于线性模型,在拟合后线性回归、逻辑回归、支持向量机(
SVM
)等线性模型会将一个系数放在特征的斜率(重要性)前面。
在线性模型中,正则化是一种对模型世家额外约束的方法,目的在于防止过拟合,并改进数据泛化能力。其中正则化通过对需要优化的损失函数添加额外的条件来完成,意味着在拟合时正则化的线性模型有可能严重减少甚至损失特征。
前面说了选择特征的方法,分为基于统计学和基于机器学习模型的二次输出。下面是一些经验可以在判断特征选择时参考:
- 如果特征是分类的,那么从
SelectKBest
开始,用卡方或基于树得到选择器。 - 如果特征基本是定量的,用线性模型和基于相关性的选择器一般效果更好。
- 如果是二元分类问题,考虑使用
SelectFromModel
和SVC
,因为SVC
会查找优化二元分类任务的系数。 - 在手动选择前,收缩性数据分析会很有益处的,同时不要低估领域知识的重要性。
- 基于树模型,在拟合决策树时,决策树会从根节点开始,在每个节点处贪婪地选择最优分割,优化节点纯净度指标。默认情况下
特征转换
在前面总共经历了数据探索性分析、特征理解、特征增强、特征构建和特征选择,下面有一套新的转换数据的方法称为特征转换。
特征转换实际上是一种矩阵算法,会在结构上改变数据,产生本质上全新的数据矩阵。其基本思想是,数据集的原始特征是数据点的描述符/特点,也应该能创造一组新的特征,用更少的列来解释数据点,并且效果不变,或者效果更好。
前面提到的使用更少的列来描述数据,这跟特征选择的概念有类似之处,但是他们的方法却有很大的不同。
特征选择仅限于从原始列中选择特征,而特征转换则是将原始列组合起来,从而创建可以更好描述数据的特征。特征转换使用原始数据集的隐藏结构创建新的列,生成一个全新的数据集,结构与之前不同。特征转换可以使用每个列中的一点点特征创建超级列,所以不需要创建很多新特征就可以捕获所有潜在的特征交互。
特征转换算法可以选择最佳的列,将其与其中的几个列进行组合,从而构建新的特征。一般常用的方法有以下两种:
- 主成分分析(
PCA
) - 线性判别分析(
LDA
)
主成分分析
主成分分析是将有多个相关特征的数据投影到相关特征较少的坐标系上。这些新的、不相关的特征(之前称为超级列)叫主成分。主成分能替代原始特征空间的坐标系,需要的特征少、捕捉的变化多。PCA
的目标在于识别数据集中的模式和潜在结构,以创建新的特征,而非使用原始特征。主成分会产生新的特征,最大化数据的方差,这样每个特征都能解释数据的形状,主成分按可以解释的方差来排序,第一个主成分最能解释数据的方差,第二个其次,最终我们希望尽可能使用多的成分来优化机器学习任务,无论是监督学习还是无监督学习。PCA
本身是无监督任务,意思是PCA
不使用响应列进行投影/转换。PCA
利用了协方差矩阵得到特征值分解。这个过程可以分为四步:- 创建数据集的协方差矩阵。
- 计算协方差矩阵的特征值。
- 保留前
k
个特征值(按特征值降序排列)。 - 用保留的特征向量转换新的数据点。
PCA
也可以用在相关矩阵上,如果特征的尺度类似,那么可以使用相关矩阵。尺度不同时,应使用协方差矩阵。一般建议在缩放数据上使用协方差矩阵。线性判别分析
线性判别分析(LDA
)是特征变换算法,也是有监督分类器。LDA
一般用于分类流水线的预处理步骤,和PCA
一样LDA
的目标在于提取一个新的坐标系,将原始数据集投影到一个低维空间中;但是和PCA
的区别在于LDA
不会专注于数据的方差,而是优化低维空间,以获得最佳的类别可分性。综上所述的意思就是新的坐标系在为分类模型查找决策边界时更有用,非常适合用于构建分类流水线。LDA
极为有用的原因在于基于类别可分性的分类有助于避免机器学习流水线的过拟合,也叫防止维度诅咒。LDA
也会降低计算成本。LDA
与PCA
一样可以作为降维工具使用,但并不会计算整体数据的协方差矩阵的特征值,而是计算类内和类间散布矩阵的特征值和特征向量。LDA
可以分为五个步骤:- 计算每个类别的均值向量。
- 计算类内和类间的散步矩阵。
- 计算
Sw^-1 * Sb
的特征值和特征向量。 - 降序排列特征值,保留前
k
个特征向量。 - 使用前几个特征向量将数据投影到新空间。
PCA
和LDA
都是特征转换工具,用于找出最优的新特征,LDA
特别为类别分离进行了优化,而PCA
是无监督的,尝试用更少的特征表达方差。
PCA
和LDA
都是很强大的工具,但也有局限性,这两个工具都是线性转换,所以只能创建线性的边界,表达数值型数据。他们也是静态转换,无论输入什么,LDA
和PCA
的输出都是可预期的,而且是数学的。如果数据不适合PCA
和LDA
(数据有非线性特征),那么无论我们怎么进行网格搜索,这些算法都不会有帮助。
总结
当你看到了这里,我想你肯定觉得一头雾水,在这里我还是建议你来看看这本书《特征工程入门与实践》,当你看完这本书再来看这篇文章,那你一定会受益良多。
引用
个人备注
此博客内容均为作者学习《特征工程入门与实践》所做笔记,侵删!
若转作其他用途,请注明来源!