特征工程
将原始数据映射到特征
我们在进行机器学习的时候,采用的数据样本往往是矢量(特征矢量),而我们的原始数据并不是以矢量的形式呈现给我们的,这是便需要将数据映射到特征
整数和浮点数映射
直接映射便ok(虽然机器学习是根据浮点值进行的训练,但是不需要将整数6转换为6.0,这个过程是默认的)
字符串映射
好多时候,有的特征是字符串,比如此前训练的加利福尼亚房产数据集中的街区名称,机器学习是无法根据字符串来学习规律的,所以需要转换。但是存在一个问题,如果字符特征是''一环'' ''二环'' ''三环''...(代表某个城市的地理位置),那么对其进行数值转换的时候,是不可以编码为形如1,2,3,4...这样的数据的,因为其存在数据大小的问题,学习模型会把他们的大小关系作为特征而学习,所以我们需要引入,(具体解释见链接,解释的很好)
寻找良好特征(的特点)
当得到特征之后,还是要进行筛选的,因为有的特征没有参考价值,就像我们的在做合成特征的时候,正常的特征数据是人均几间房间,而有的人是几十间,这明显没有参考价值
良好特征的几点原则- 避免很少使用的离散特征值:如果只是出现了一两次的特征几乎是没有意义的
- 最好具有清晰明确的含义:特征的含义不仅仅是让机器学习的模型学习的,人也要知道其具体的含义,不然不利于分析数据(最好将数值很大的秒转换为天数,或者年,让人看起来直观一些)
-
将“神奇”的值与实际数据混为一谈:有些特征中会出现一些"神奇的数据",当然这些数据并不是很少的特征,而是超出范围的异常值,比如特征应该是介于0——1之间的,但是因为这个数据是空缺的,而采用的默认数值-1,那么这样的数值就是"神奇",解决办法是,将该特征转换为两个特征:
- 一个特征只存储质正常范围的值,不含神奇值。
- 一个特征存储布尔值,表示的信息为是否为空
- 考虑上游不稳定性:由经验可知,特征的定义不应随时间发生变化,代表城市名称的话,那么特征值始终都该是城市的名称,但是有的时候,上游模型将特征值处理完毕后,返还给下游模型的却变成了数值,这样是不好的,因为这种表示在未来运行其他模型时可能轻易发生变化,那么特征就乱套了
清理数据(整理数据)
清理数据,顾名思义,就是将数据清理(整理一下).....好像是废话。
在上一步后,我们现在得到的数据已经全部是数值化的特征了,(这里肯定有但是的),但是,这样的数据直接拿过来训练效果还是会很糟糕,因为其中存在许许多多的坏数据,就是一些值不是那么正常的数据,像之前说的那种数值特别大的就属于这一种,当然除了数值异常的还有许许多多种的坏数据,下面就来看一看有哪些方法对付这些妖艳贱货缩放特征值
缩放是指将浮点特征值从自然范围(例如 100 到 900)转换为标准范围(例如 0 到 1 或 -1 到 +1)。如果某个特征集只包含一个特征,则缩放可以提供的实际好处微乎其微或根本没有。不过,如果特征集包含多个特征,则缩放特征可以带来以下优势:
- 帮助梯度下降法更快速地收敛(各个特征数值小,这样算的跨的步子大呀)。
- 帮助避免“NaN 陷阱”。当某个值在训练期间超出浮点精确率限制时,数值会变成NaN,并且模型中的所有其他数值最终也会因数学运算而变成 NaN。( NaN)
_NaN_,是Not a Number的缩写,在IEEE浮点数算术标准(IEEE 754)中定义,表示一些特殊数值(无穷与非数值(_NaN_)),为许多CPU与浮点运算器所采用。
- 帮助模型为每个特征确定合适的权重。如果没有进行特征缩放,则模型会对范围较大的特征投入过多精力。(因为如果其他的特征范围过大,模型在训练的时候会认为此种模型的权值大,进而影响模型的判断)
由上可知,我们并不需要对每个浮点特征进行完全相同的缩放。即使特征 A 的范围是 -1 到 +1,同时特征 B 的范围是 -3 到 +3,也不会产生什么恶劣的影响。不过,如果特征 B 的范围是 5000 到 100000,您的模型会出现糟糕的响应。
要缩放数字数据,一种显而易见的方法是将 [最小值,最大值] 以线性方式映射到较小的范围,例如 [-1,+1]。 另一种热门的缩放策略是计算每个值的 Z 得分。Z 得分与距离均值的标准偏差数相关。换而言之: scaledvalue=(value−mean)/stddev.
例如,给定以下条件:* 均值 = 100* 标准偏差 = 20* 原始值 = 130则: scaled_value = (130 - 100) / 20 scaled_value = 1.5使用 Z 得分进行缩放意味着,大多数缩放后的值将介于 -3 和 +3 之间,而少量值将略高于或低于该范围。
处理极端离群值
还是举加利福尼亚州住房数据集中的人均住房数的例子,有的极端值达到了50
对于这些极端值其实很好处理,无非几个办法- 对数缩放
- 特征值限制到 某个上限或者下限
分箱
分箱其实是一个形象化的说法,就是把数据分开来,装在一个个箱子里,这样一个箱子里的数据就是一家人了。
那有什么用呢?下面就举个栗子!
在数据集中,latitude
是一个浮点值(因为是按照一片区域统计的,所以纬度肯的增长肯定是线性的了)。不过,在我们的模型中将 latitude
表示为浮点特征(将其看为一个浮点数,以它的数值大小为特征)没有意义。这是因为纬度和房屋价值之间不存在线性关系(并不是那种纬度高房价就高)。例如,纬度 35 处的房屋并不比纬度 34 处的房屋贵 35/34(或更便宜)。但是,纬度或许能很好地预测房屋价值(在训练之前,我们也不知道能不能呢,但是从之前的散点图可以看出来,房价和位置的分布好像是有关系的,所以我们把纬度也作为特征),因为不是呈线性的关系了,所以把它作为分类特征会更好。(如果无法理解的话,就好好想想模型会怎么处理数值数据和分类数据),所以接下来我们将其分箱处理,如下图。
我们现在拥有 11 个不同的布尔值特征(LatitudeBin1
、LatitudeBin2
、…、LatitudeBin11
),而不是一个浮点特征。拥有 11 个不同的特征有点不方便,因此我们将它们统一成一个 11 元素矢量。这样做之后,我们可以将纬度 37.4 表示为:
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
分箱之后,我们的模型现在可以为每个纬度学习完全不同的权重。(是不是觉得有点像独热编码,没错,就是的)
为了简单起见,我们在纬度样本中使用整数作为分箱边界。如果我们需要更精细的解决方案,我们可以每隔 1/10 个纬度拆分一次分箱边界。添加更多箱可让模型从纬度 37.4 处学习和维度 37.5 处不一样的行为,但前提是每 1/10 个纬度均有充足的样本可供学习。另一种方法是按分箱,这种方法可以确保每个桶内的样本数量是相等的。按分位数分箱完全无需担心离群值。
清查
截至目前,我们假定用于训练和测试的所有数据都是值得信赖的。在现实生活中,数据集中的很多样本是不可靠的,原因有以下一种或多种:
- 遗漏值。 例如,有人忘记为某个房屋的年龄输入值。(值会为-1,所以要分为两个特征,忘了的看上面)
- 重复样本。 例如,服务器错误地将同一条记录上传了两次。
- 不良标签。 例如,有人错误地将一颗橡树的图片标记为枫树。
- 不良特征值。 例如,有人输入了多余的位数,或者温度计被遗落在太阳底下。
一旦检测到存在这些问题,通常需要将相应样本从数据集中移除,从而“修正”不良样本。要检测遗漏值或重复样本,可以编写一个简单的程序。检测不良特征值或标签可能会比较棘手。
除了检测各个不良样本之外,还必须检测集合中的不良数据。直方图是一种用于可视化集合中数据的很好机制。此外,收集如下统计信息也会有所帮助:
- 最大值和最小值
- 均值和中间值
- 标准偏差
考虑生成离散特征的最常见值列表,靠常识来判断是否合理,是否适合自己观察数据
了解数据
遵循以下规则:
- 记住您预期的数据状态。
- 确认数据是否满足这些预期(或者您可以解释为何数据不满足预期)。
- 仔细检查训练数据是否与其他来源(例如信息中心)的数据一致。
像处理任何任务关键型代码一样谨慎处理您的数据。良好的机器学习依赖于良好的数据。