特征工程(上)

一个人可以走的很快,但是一群人却可以走的更远

这次学习的内容是《Feature Engineering for Machine Learning》在Apache.cn上的翻译版本。主要是迁移书本里的内容过来,小部分内容根据自己的理解稍微的修改了下。
有九个章节:

  1. 引言
  2. 简单数学学的奇特技巧
  3. 文本数据:展开、过滤和分块
  4. 特征缩放的效果:从词袋到TF—IDF
  5. 类别特征:机器鸡时代的鸡蛋计数
  6. 降维:使用PCA压缩数据集
  7. 非线性特征提取和模型堆叠
  8. 自动化特征提取器:图像特征提取和深度学习
  9. 回到特征:将它们放到一起

引言

什么是机器学习?

将数据拟合到数学模型中来获得结论或者做出预测。

机器学习怎么做?

数学模型将特征作为输入,将原始数据的某些数学表现,转换成机器可以学习的模型格式。

机器学习中重要的事情

从数据中提取特征,因为正确的特征可以减轻模型的难度,得到更高质量的结果。而数据清洗能让特征工程做的更好。

机器学习为什么要这样做?特征工程的原理是什么?

这就是通过后续的章节来不断的了解和学习。要理解为什么这样设计,如何与其他技术相关联,以及每种方法的优缺点。准确的知道如何完成某件事,对底层原则有一个感觉,并且整合到已知的知识网络中。

第1章从数字数据的基本特征工厂开始:过滤、合并、缩放、日志转换和能量转换以及交互功能。

第2章和第3章探讨自然文本的特征工程:bag -of -words , n-gram 和短语检测。

第4章 将tf- idf 作为特征缩放的例子,讨论它的工作原理

第5章 讨论分类变量的高效编码技术,包括特征哈希和 bin-counting,步伐开始加速。

第6章进行主成分分析时,开始深入机器学习领域。

第7章将 k - means 看作特征化技术,它将说明模型堆叠的有效理论。

第8章关于图像的,在特征提取方面比文本数据更具挑战性,在得出深度学习是最新图像特征体术的解释之前,着眼于两种手动特征提取技术 SIFT 和 HOG。

第9章 完成一个端到端示例中的几种不同技术,为学术论文数据集创建推荐器。


前提提示

因为特征工程是一个广泛的话题。所以该书进行了一部分删减,不讨论音频数据的傅里叶分析,也忽略了与傅里叶分析密切相关的随机特征的讨论。对图像数据的深度学习来介绍特征学习,但是不会深入到众多的深度学习模型中。像超出范围的还包括随机投影、复杂文本特征模型(如word2vec和Brown聚类)以及潜在空间模型(如潜在狄里克雷分析和矩阵分解)。

机器学习流水线

数据

像股票市场数据、个人生物识别数据如心率、血糖血压指纹等,购物的清单数据、用户在网站上的点击数据,不同的领域都能获得无数的数据。

任务

关于到我们为什么收集数据?我们弄清楚了我们收集数据的原因,就能更清楚的明白自己要做什么,这样才能更有针对性的去解决问题。

模型

数学模型:尝试从数据中了解世界,就像用不完整的拼图以及一堆额外的碎片拼凑出现实。特别是统计模型。数据的数学模型描述了数据不同方面的关系。

统计中频繁出现的数据特征概念:误差,冗余,缺失。

误差数据:测量中的错误导致的。

冗余数据:数据的多个方面传达完全相同的信息。

缺失:如果数据缺少了一部分,比如在某一个时间段里,数据点找不到某些信息,那么就是缺失了信息

特征

特征作为原始数据的数学表示,有很多方法可以将原始数据转换为数学测量值,这就是为什么特征看起来和很多事情相似。但是,特征必须是来自可用数据的类型。虽然某些特征和模型相关联的样子并不明显;一些模型更适合某些类型的特征。因此,正确的特征应该与手头的任务相关并且容易被模型使用。

特征工程就是给指定数据、模型和任务指定最佳特征的过程。

特征的数量很重要:

  • 没有足够的信息特征,则模型无法完成最终的任务。
  • 过多的特征,或者大多数是无关紧要的,那么训练模型会更加棘手并且代价更大,并且会出现一些错误影响模型的表现。

模型评估

特征和模型位于原始数据和期望的观察结果之间。在机器学习的工作流程中,不仅挑选模型,还要挑选特征。这是一个双节杆,一个选择会影响另一个。良好的特征使后续的建模步骤变得简单,并且得到的模型更能容易实现所需的任务。而糟糕的特征则可能需要更复杂的模型才能达到相同的性能水平。


简单数字的奇特技巧

数字数据的来源可能各种各样:地理位置、人、购买的价格、传感器的测量、交通计数等。

虽然数字数据是数学模型容易消化的格式,但不代表不需要特征工程。转换常常是必要的。数字特征工程计数是基础。当原始数据被转换为数字特征时,才可以被应用。

数值数据几个重要因素:

  • 大小是否重要,是正面还是负面
  • 特征的规模。最大值最小值是什么
  • 逻辑函数对输入特征量表不敏感,如逻辑函数,阶跃函数,以及像基因空间划分树(决策树、梯度提升机、随机森林)的模型对尺度不敏感。
  • 数值的特征分布,承担了特定价值的可能性。对某些模型更重要,比如线性回归模型的训练过程嘉定预测误差分布得像高斯。但是预测目标在几个数量级上扩散,那么高斯误差假设可能不再成立。解决问题的一种方法是转变产出目标,以驯服规模的增长。对数变换,这是一种功率变换,将变量的分布接近高斯。

这里开始讨论复杂特征的最简单示例:交互功能
交互特征易于指定,但特征的组合导致更多的输入到模型中。为了减少计算开销,通常需要使用自动特征选择来修剪输入特征。

先从标量向量空间的基本概念开始,然后再深入到尺度分布交互特征特征选择

标量、向量和空间

单个数字特征称为标量
标量的有序列表称为向量。向量位于向量空间中。
在绝大机器学习应用中,对模型的输入通常表示为数字向量。

向量可以被可视化为空间的一个点。有时人们从原点到那一点画一条线和一个箭头。例如,假设我们有一个二维向量v=[1,-1]。也就是说,向量包含两个数,在第一方向d1中,向量具有1的值,并且在第二方向d2中,它具有-1的值。我们可以在二维图中绘制v。

处理计数

在大数据时代,计数可以快速积累而不受约束。用户可以将歌曲或电影放在无限播放中,或者使用脚本反复检查流行节目的门票可用性,这会导致播放次数或网站访问计数迅速上升。当数据可以以高的体积和速度产生时,它们很可能包含一些极值。这是一个好主意,检查他们的规模,并确定是否保持它们作为原始数字,将它们转换成二进制变量,以指示存在,或将它们放入粗粒度。

二值化

Million Song 数据集中的用户品味画像包含了一百万个用户在 Echo Nest 的完整音乐聆听历史。下面是有关数据集的一些相关统计数据。

Echo Nest 品味画像数据集的统计

  • 有超过4800万个用户ID、音乐ID和监听计数三元组。
  • 完整的数据集包含1019318个独特用户和384546首独特歌曲。
  • 引文:Echo Nest 品味画像的数据子集,官方的 Million Song 数据集的用户数据集,可从这里获得:http://labrosa.ee.columbia.edu/millionsong/tasteprofile

假设任务是建立一个推荐器向用户推荐歌曲。推荐器的一个组件可以预测用户将对一首特别的歌曲会有多少喜欢。由于数据包含实际的听歌次数,这应该是预测的目标吗?如果一个大的听计数意味着用户真的喜欢这首歌,反之亦然,那是正确的。然而,数据表明,虽然99%的听计数是24或更低,也有一些听计数数以千计,最大为9667。(如图所示,直方图最接近于0的bin中的峰值。但是超过10000个三元组的计数更大,几千个则有几个。这些值异常大;如果我们试图预测实际的听计数,那么模型将被这些大的值拉离。

在 Million Song 数据集中,原始监听计数不是用户口味的可靠度量。(在统计术语中,健壮性意味着该方法在各种各样的条件下工作。)用户有不同的听力习惯。有些人可能把他们最喜欢的歌曲放在无限的循环中,而其他人可能只在特殊的场合品尝它们。很难说听一首歌20次的人一定喜欢听10次的人的两倍。

用户偏好的更健壮表示是使计数二元化和修剪所有大于1的计数为1。换句话说,如果用户至少听过一首歌,那么我们将其视为用户喜欢歌曲。这样,模型不需要花费周期来预测原始计数之间的微小差异。二进制目标是用户偏好的简单而稳健的度量。

例子:使million song数据集中听歌计数二进制化

1
2
3
4
5
import pandas as pd 
listen_count = pd.read_csv('millionsong/train_triplets.txt.zip', header=None, delimiter='\t')
# 该表包含用户歌曲计数三元组。只有非零计数
# 因此,要对计数进行二值化,我们只需要将整个计数列设置为1。
listen_count[2] = 1

这是我们设计模型目标变量的一个例子。严格地说, 目标不是一个特征, 因为它不是输入。但有时我们确实需要修改目标以解决正确的问题。

量化或装箱

数据源于第 6 轮 Yelp 数据集挑战中采集数据,创建一个更小的分类数据集。Yelp 数据集包含用户对来自北美和欧洲十个城市的企业的评论。每个商户都标记为零个或多个类别。以下是有关数据集的相关统计信息。

  • 有782种商户类别。
  • 完整的数据集包含 1569264 个(约1.6M)评论和 61184 个(61K)商户。
  • “餐厅”(990627个评论)和“夜生活”(210028个评论)是最流行的类别,评论计数是明智的。
  • 没有一个商户同时属于餐厅和夜生活分类。因此,这两组评论之间没有重叠

每个商户都有一个评论计数。假设我们的任务是使用协同过滤来预测用户可能给企业的评级。评论计数可能是一个有用的输入特征,因为通常在流行和良好的评级之间有很强的相关性。现在的问题是,我们应该使用原始评论计数或进一步处理它吗?图2显示了所有商户评论计数的直方图。我们看到和音乐听歌计数一样的模式。大部分的统计数字都很小,但一些企业有成千上万的评论。

对于许多模型来说,跨越数个数量级的原始计数是有问题的。在线性模型中,相同的线性系数必须对计数的所有可能值工作。大量的计数也可能破坏无监督学习方法,如k-均值聚类,它使用相似性函数来测量数据点之间的相似性。k-均值使用数据点之间的欧几里得距离。数据向量的一个元素中的大计数将超过所有其他元素中的相似性,这可能会丢弃整个相似性度量。

一种解决方案是通过量化计数来包含标量。换句话说,我们将计数分组到容器中,并且去掉实际的计数值。量化将连续数映射成离散数。我们可以把离散化的数字看作是代表强度度量的容器的有序的序列。

为了量化数据,我们必须决定每一个箱子应该有多宽。解决方案分为固定宽度或自适应两种类型。我们将给出每个类型的例子。

固定宽度装箱

对于固定宽度装箱, 每个 bin 都包含一个特定的数值范围。范围可以是定制设计或自动分割, 它们可以线性缩放或指数缩放。例如, 我们可以将一个人的年龄分组为十年: 0-9 岁归纳到bin 1, 10-19 年归纳到 bin 2 等。要从计数映射到 bin, 只需除以 bin 的宽度并取整部分。

也经常看到定制设计的年龄范围更适合于生活的阶段:

  • 0-12 岁
  • 12-17 岁
  • 18-24 岁
  • 25-34 岁
  • 35-44 岁
  • 45-54 岁
  • 55-64 岁
  • 65-74 岁
  • 75 岁以上

当数字跨越多个数量级时,最好用10个幂(或任何常数的幂)来分组:0-9、10-99、100-999、1000-9999等。容器宽度呈指数增长,从O(10)、O(100)到O(1000)和以上。要从计数映射到bin,取计数的log值。指数宽度的划分与对数变换非常相关。

分位数装箱

固定宽度装箱很容易计算。但是如果计数有很大的差距, 那么将会有许多空的垃圾箱没有数据。该问题可以通过基于数据分布的垃圾箱自适应定位来解决。这可以使用分发的分位数来完成。

分位数是将数据划分为相等部分的值。例如, 中位数将数据分成一半;一半的数据是较小的, 一半大于中位数。分位数把数据分成几个部分, 十分位数把数据划分成十份。

通过分位数来装箱,能够更明显的看

通过红色的线来划分每一个数值范围,这样数据的可视化效果会比其他装箱方法好很多。
为了计算分位数和映射数据到分位数箱,我们可以使用 Pandas 库。 pandas.DataFrame.quantile 和 pandas.Series.quantile 用于计算分位数。pandas.qcut将数据映射到所需数量的分位数。

对数转换

在“量化或装箱”中,简要地介绍了把计数的对数映射到指数宽度箱的概念。

对数函数是指数函数的逆。它定义为$\log _{a}\left(\mathrm{a}^{x}\right)=x$ , 其中 a 为正常数, x 可以是任何正数。由于$a^{0}=1$,我们有$\log _{a}(1)=0$。
这意味着对数函数将小范围的数字 (0、1) 映射到负数的整个范围 (-∞, 0)。函数$\log _{10}(\mathrm{x})$将 [1、10] 映射到 [0、1]、将[10、100] 映射到 [1、2] 等等。换言之, 对数函数压缩大数的范围, 并扩展小数的范围。越大的 x , log(x)的增量越慢。通过查看 log 函数的图像, 可以更容易地消化这一点。如下图

对数变换是处理具有重尾分布的正数的有力工具。(重尾分布在尾部范围内的概率比高斯分布的概率大)。它将分布在高端的长尾压缩成较短的尾部,并将低端扩展成较长的头部。下图比较d对数转换之前和之后的YELP商户评论计数的直方图。Y轴现在都在正常(线性)尺度上。在(0.5,1)范围内的 底部图中增加的仓间隔是由于在1和10之间只有10个可能的整数计数。请注意,原始审查计数非常集中在低计数区域,离群值在4000以上。对数变换后,直方图不集中在低端,更分散在X轴上。

下图是在线新闻流行数据集中其中一个特征——文章中的单词数。显示了对数转换前后特征的直方图。请注意, 在对数转换后, 分布看起来更高斯, 除了长度为零的文章 (无内容) 的断裂。

数据可视化的重要性

对数变换在两个不同数据集上的影响的比较,说明了可视化数据的重要性。在这里,我们故意保持输入和目标变量简单,以便我们可以很容易地可视化它们之间的关系。如下图所示的曲线,立即显示所选择的模型(线性)不可能代表所选择的输入和目标之间的关系。另一方面,人们可以令人信服地在给定平均星级模拟评论数的分布。在建立模型时,最好直观地检查输入和输出之间的关系,以及不同输入特征之间的关系。

功率变换:对数变换的推广

对数变换是一个称为功率变换的变换族的特殊例子。在统计方面,这些是方差稳定的变换。为了理解为什么方差稳定是好的,考虑泊松分布。这是一个方差等于它的平均值的重尾分布。因此,它的质量中心越大,其方差越大,尾部越重。功率变换改变变量的分布,使得方差不再依赖于平均值。例如,假设一个随机变量X具有泊松分布。假如我们使用开平方根变换X,$\widetilde{X}=\sqrt{X}$的方差大致是恒定的,而不是平均值。

平方根变换和对数变换的简单推广称为Box-Cox变换:

下图 ,展示出了在 λ = 0 (log变换),λ = 0.25, λ = 0.5(平方根的缩放和移位版本),λ = 0.75, 和 λ = 1.5 时的Box-Cox变换。设置 λ 小于1时压缩较高的值,并且设置 λ 大于1时具有相反的效果。

只有当数据为正值时, Box-Cox 公式才能工作。对于非正数据, 可以通过加上固定常量来移动数值。当应用 Box-Cox 变换或更一般的功率变换时, 必须确定参数 λ 的值。这可能是通过最大似然(找到的λ,使产生的变换信号的高斯似然最大) 或贝叶斯方法。

下图 为可视化评论数的原始、对数转换和 Box-Cox 转换的直方图。

概率图是一种直观地比较数据分布与理论分布的简单方法。这本质上是观察到散点图的与理论分位数。图10显示YELP评论数的原始数据和转换后数据相对正态分布的概率图。由于观测数据是严格正的,高斯可以是负的,所以分位数在负端上永远不会匹配。所以我们关注的是正数这的一边。在这方面,原始评论数明显比正常分布更重尾。(有序值上升到4000,而理论位数仅延伸到4)。简单的对数变换和最优的 Box-Cox 变换都使正尾部接近正态分布。最优的 Box-Cox 变换比对数变换更缩小尾部,由于尾部在红色对角线等值线下平展可以明显看出。

特征缩放或归一化

某些特征的值有界的,如纬度或经度。其他数值特征 (如数量) 可能会在无界的情况下增加。那些关于输入是平滑函数的模型, 如线性回归、逻辑回归或任何涉及矩阵的东西, 都受输入的数值范围影响。另一方面, 基于树的模型不太在意这个。如果模型对输入特征的数值范围敏感, 则特征缩放可能会有所帮助。 特征缩放会更改特征值的数值范围。有时人们也称它为特征规范化。功能缩放通常分别针对单个特征进行。有几种常见的缩放操作, 每个类型都产生不同的特征值分布

Min-max缩放

设X是一个单独的特征值(即,在某些数据点中的一个特征值),以及 min(x) 和 max(x) ,分别是整个数据集上该特征的最小值和最大值。Min-max缩放压缩(或拉伸)所有特征值到[0, 1 ]的范围内。下图演示了这个概念。最小最大尺度的公式是

标准化(方差缩放)

特征标准化的定义为:

减去特征 (所有数据点) 的平均值并除以方差。因此, 它也可以称为方差缩放。缩放后的特征的平均值为0, 方差为1。如果原始特征具有高斯分布, 则缩放特征为标准高斯。下图包含了标准化的说明。

不要中心和稀疏数据

最小最大缩放和标准化都从原始特征值中减去一个数量。对于最小最大缩放, 移动量是当前特征的所有值中最小的。对于标准化, 移动的量是平均值。如果移动量不是零, 则这两种转换可以将稀疏特征(大部分值为零)的向量转换为一个稠密的向量。但是如果移动量为零,那么会给分类器带来巨大的计算负担, 取决于它是如何实现的。词袋是一种稀疏表示, 大多数分类库都对稀疏输入进行优化。如果现在的表示形式包含了文档中没有出现的每个单词, 那就太可怕了。请谨慎对稀疏特征执行最小最大缩放和标准化操作。

L2 normalization

通过所谓的 L2 范数 (也称为欧几里德范数) 正常化 (划分) 原始特征值。

L2范数度量向量在坐标空间中的长度。这个定义可以从众所周知的勾股定理中得到,给出三角形两边的长度,可以得到斜边长度

L2 范数将求特征的各数据点的平方和, 然后取平方根。L2 规范化后, 该特征列具有范数1。它也可以称为 L2 缩放。(不严谨的说, 缩放意味着和常量相乘, 而规范化可能涉及许多操作。)下图说明了 L2 规范化。

数据空间和特征空间

上图中的说明是在数据空间中,而不是特征空间。还可以对数据点进行L2归一化,而不是特征,这将导致具有单位范数(范数为1)的数据向量。不管缩放方法如何,特征缩放总是将特征除以常数(也称为归一化常数)。因此,它不会改变单特征分布的形状。我们将用在线新闻文章标记计数来说明这一点。

我们也可以可视化用不同的特征缩放方法后的数据的分布。如下图所示,与对数变换不同,特征缩放不会改变分布的形状;只有数据的规模发生变化。

在一组输入特征在比例上差异很大的情况下,特征缩放非常有用。例如,一个流行的电子商务网站的每日访问者数量可能是十万,而实际销售额可能是几千。如果这两种功能都投入到模型中,那么该模型需要在确定要做什么的同时平衡它们的规模。输入特征的极大变化会导致模型训练算法的数值稳定性问题。在这些情况下,标准化功能是个好主意。第4章将详细介绍处理自然文本时的特征缩放,包括使用示例。

交互特征

简单的成对交互特征是两个特征的积。类似逻辑与。它以成对条件表示结果:“购买来自邮政编码98121”和“用户的年龄在18到35之间”。这一点对基于决策树的模型没有影响,但交互特征对广义线性模型通常很有帮助。

一个简单的线性模型使用单个输入特征线性组合x1,x2,… xn来预测结果y

$y=w_{I} X_{I}+w_{2} X_{2}+\ldots+w_{n} X_{n}$

一个简单的扩展线性模型的方法是包含输入特征对的组合,如下所示:

$y=w_{I} X_{1}+w_{2} X_{2}+\ldots+w_{n} X_{n}+w_{1,1} X_{1}X_{1}+w_{1,2} X_{1}X_{2}+w_{1,3} X_{1}X_{3}$

这使我们能够捕获特征之间的相互影响,因此它们被称为交互特征。如果x1和x2是二元的,那么它们的积 x1x2 是逻辑函数 x1 AND x2 假设问题是根据他或她的个人资料信息预测客户的偏好。在这种情况下,交互特征不是仅基于用户的年龄或位置进行预测,而交互特征允许模型基于具有特定年龄和特定位置的用户进行预测。

构造交互特征非常简单,但它们使用起来很昂贵。使用成对交互特征的线性模型的训练和得分时间将从O(n)到O(n2),其中n是单身特征的数量。

围绕高阶交互特征的计算成本有几种方法。可以在所有交互特征之上执行特征选择,选择前几个。或者,可以更仔细地制作更少数量的复杂特征。两种策略都有其优点和缺点。特征选择采用计算手段来选择问题的最佳特征。(这种技术不限于交互特征。)一些特征选择技术仍然需要训练多个具有大量特征的模型。

手工制作的复杂特征可以具有足够的表现力,所以只需要少量这些特征,这可以缩短模型的训练时间。但是特征本身的计算可能很昂贵,这增加了模型评分阶段的计算成本。

特征选择

特征选择技术会删除非有用的特征,以降低最终模型的复杂性。最终目标是快速计算的简约模型,预测准确性降低很小或不会降低。为了得到这样的模型,一些特征选择技术需要训练多个候选模型。换句话说,特征选择并不是减少训练时间,实际上有些技巧增加了整体训练时间,但是减少了模型评分时间。

大致分三种特征选择技术:

Filtering(过滤)

预处理可以删除那些不太可能对模型有用的特征。例如,可以计算每个特征与响应变量之间的相关或相互信息,并筛除相关信息或相互信息低于阈值的特征。第3章讨论了文本特征的过滤技术的例子。过滤比下面的包装(wrapper)技术便宜得多,但是他们没有考虑到正在使用的模型。因此他们可能无法为模型选择正确的特征。最好先保守地进行预过滤,以免在进行模型训练步骤之前无意中消除有用的特征。

Wrapper methods(包装方法)

这些技术是昂贵的,但它们允许您尝试特征子集,这意味着你不会意外删除自身无法提供信息但在组合使用时非常有用的特征。包装方法将模型视为提供特征子集质量分数的黑盒子。是一个独立的方法迭代地改进子集。

Embedded methods(嵌入式方法)

嵌入式方法执行特征选择作为模型训练过程的一部分。 例如,决策树固有地执行特征选择,因为它在每个训练步骤选择一个要在其上进行树分裂的特征。另一个例子是$t_{1}$正则,它可以添加到任何线性模型的训练目标中。$t_{1}$鼓励模型使用一些特征而不是许多特征。因此它也被称为模型的稀疏约束。嵌入式方法将特征选择作为模型训练过程的一部分。它们不如包装方法那么强大,但也远不如包装方法那么昂贵。与过滤相比,嵌入式方法会选择特定于模型的特征。从这个意义上讲,嵌入式方法在计算费用和结果质量之间取得平衡。

总结

许多常见的数字特征工程技术:量化,缩放(又称规范化),对数变换(一种功率变换),交互特征以及处理大量交互特征所需的特征选择技术的简要总结。在统计机器学习中,所有数据最终归结为数字特征。

文本数据:展开、过滤和分块

我们知道一个名叫Emma的人和一只乌鸦。这里有一座房子和一棵树,艾玛正想进屋,却看到了乌鸦。这只华丽的乌鸦注意到艾玛,她有点害怕,但正在尝试交流。

那么,这些信息的哪些部分是我们应该提取的显着特征?首先,提取主要角色艾玛和乌鸦的名字似乎是个好主意。接下来,注意房子,门和树的布置可能也很好。关于乌鸦的描述呢?Emma的行为呢,敲门,退后一步,打招呼呢?

Bag of X: 把自然文本变成平面向量

去构建机器学习或者特征工程,都应该要得到一个通俗易懂的结果。

虽然简单和可解释的功能并不一定能得到最精确的模型,但是从简单开始会比较好,必要时再增加复杂性。

对于文本数据,我们可以从称为 BOW 词袋模型。BOW中并没有特别费力来寻找"Emma"或乌鸦这样有趣的实体。但是这两个词在该段落中被重复提到,并且它们在这里的计数比诸如"hello"之类的随机词更高。对于此类简单的文档分类任务,字数统计通常比较适用。它也可用于信息检索,其目标是检索与输入文本相关的文档集。这两个任务都很好解释词级特征,因为某些特定词的存在可能是本文档主题内容的重要指标。

词袋

在词袋特征中,文本文档被转换成向量。(向量只是 n 个数字的集合。)向量包含词汇表中每个单词可能出现的数目。 如果单词"aardvark"在文档中出现三次,则该特征向量在与该单词对应的位置上的计数为 3。 如果词汇表中的单词没有出现在文档中,则计数为零。 例如,“这是一只小狗,它是非常可爱”的句子具有如图所示的 BOW 表示

BOW 将文本文档转换为平面向量。 它是“平面的”,因为它不包含任何原始的文本结构。 原文是一系列词语。但是词袋向量并没有序列;它只是记得每个单词在文本中出现多少次。 它不代表任何词层次结构的概念。 例如,“动物”的概念包括“狗”,“猫”,“乌鸦”等。但是在一个词袋表示中,这些词都是矢量的相同元素。

上图是两个等效的词袋,里面的单词的排序不重要,重要的是它在数据集中的个数和文档中出现的数量是一样的。

重要的是特征空间中数据的几何形状。 在一个词袋矢量中,每个单词成为矢量的一个维度。如果词汇表中有 n 个单词,则文档将成为n维空间中的一个点。 很难想象二维或三维以外的任何物体的几何形状,所以我们必须使用我们的想象力。 下图显示了我们的例句在对应于“小狗”和“可爱”两个维度的特征空间中的样子。

上两个图描绘了特征空间中的数据向量。 坐标轴表示单个单词,它们是词袋表示下的特征,空间中的点表示数据点(文本文档)。 有时在数据空间中查看特征向量也是有益的。 特征向量包含每个数据点中特征的值。 轴表示单个数据点和点表示特征向量。 下图展示了一个例子。 通过对文本文档进行词袋特征化,一个特征是一个词,一个特征向量包含每个文档中这个词的计数。 这样,一个单词被表示为一个“一个词向量”。正如我们将在第 4 章中看到的那样,这些文档词向量来自词袋向量的转置矩阵。

Bag - of - N - gram

Bag-of-N-gram 或者 bag-of-ngram 是 BOW 的自然延伸。 n-gram 是 n 个有序的记号(token)。一个词基本上是一个 1-gram,也被称为一元模型。当它被标记后,计数机制可以将单个词进行计数,或将重叠序列计数为 n-gram。例如,"Emma knocked on the door"这句话会产生 n-gram,如"Emma knocked""knocked on""on the""the door"。 N-gram 保留了文本的更多原始序列结构,故 bag-of-ngram可以提供更多信息。但是,这是有代价的。理论上,用 k 个独特的词,可能有 k 个独立的 2-gram(也称为 bigram)。在实践中,并不是那么多,因为不是每个单词后都可以跟一个单词。尽管如此,通常有更多不同的 n-gram(n > 1)比单词更多。这意味着词袋会更大并且有稀疏的特征空间。这也意味着 n-gram 计算,存储和建模的成本会变高。n 越大,信息越丰富,成本越高。

为了说明随着 n 增加 n-gram 的数量如何增加,我们来计算纽约时报文章数据集上的 n-gram。我们使用 Pandas 和 scikit-learn 中的CountVectorizer转换器来计算前 10,000 条评论的 n-gram。

过滤清晰特征

如何清晰地将信号从噪声中分离出来?

通过过滤,使用原始标记化和计数来生成简单词表或 n-gram 列表的技术变得更加可用。

短语检测,可以看作是一个特别的 bigram 过滤器。 以下是执行过滤的几种方法。

高频词

率统计对滤除语料库专用常用词以及通用停用词很有用。例如,纽约时报文章数据集中经常出现“纽约时报”和其中单个单词。“议院”这个词经常出现在加拿大议会辩论的Hansard语料库中的“众议院”一词中,这是一种用于统计机器翻译的流行数据集,因为它包含所有文档的英文和法文版本。这些词在普通语言中有意义,但不在语料库中。手动定义的停用词列表将捕获一般停用词,但不是语料库特定的停用词。

下图列出了 Yelp 评论数据集中最常用的 40 个单词。在这里,频率被认为是它们出现在文件(评论)中的数量,而不是它们在文件中的数量。正如我们所看到的,该列表涵盖了许多停用词。它也包含一些惊喜。"s""t"在列表中,因为我们使用撇号作为标记化分隔符,并且诸如"Mary's""did not"之类的词被解析为"Mary s""didn t"。词"good""food""great"分别出现在三分之一的评论中。但我们可能希望保留它们,因为它们对于情感分析或业务分类非常有用。

最常用的单词最可以揭示问题,并突出显示通常有用的单词通常在该语料库中曾出现过多次。 例如,纽约时报语料库中最常见的词是“时代”。实际上,它有助于将基于频率的过滤与停用词列表结合起来。

还有一个棘手的问题,即何处放置截止点。 不幸的是这里没有统一的答案。在大多数情况下截断还需手动确定,并且在数据集改变时可能需要重新检查。

稀有词

根据任务的不同,可能还需要筛选出稀有词。对于统计模型而言,仅出现在一个或两个文档中的单词更像噪声而非有用信息。例如,假设任务是根据他们的 Yelp 评论对企业进行分类,并且单个评论包含"gobbledygook"这个词。基于这一个词,我们将如何说明这家企业是餐厅,美容院还是一间酒吧?即使我们知道在这种情况下的这种生意发生在酒吧,它也会对于其他包含"gobbledygook"这个词的评论来说,这可能是一个错误。

不仅稀有词不可靠,而且还会产生计算开销。这套 160 万个 Yelp 评论包含 357,481 个独特单词(用空格和标点符号表示),其中 189,915 只出现在一次评论中,41,162 次出现在两次评论中。超过 60% 的词汇很少发生。

这是一种所谓的重尾分布,在现实世界的数据中非常普遍。许多统计机器学习模型的训练时间随着特征数量线性地变化,并且一些模型是二次的或更差的。稀有词汇会产生大量的计算和存储成本,而不会带来额外的收益。

根据字数统计,可以很容易地识别和修剪稀有词。或者,他们的计数可以汇总到一个特殊的垃圾箱中,可以作为附加功能。下图展示了一个短文档中的表示形式,该短文档包含一些常用单词和两个稀有词"gobbledygook""zylophant"。通常单词保留自己的计数,可以通过停用词列表或其他频率进一步过滤方法。这些难得的单词会失去他们的身份并被分组到垃圾桶功能中.

由于在计算整个语料库之前不会知道哪些词很少,因此需要收集垃圾桶功能作为后处理步骤。

如果文本文档很短,那么它可能不包含有用的信息,并且在训练模型时不应使用该信息。

应用此规则时必须谨慎。维基百科转储包含许多不完整的存根,可能安全过滤。另一方面,推文本身就很短,并且需要其他特征和建模技巧。

词干解释(Stemming)

简单解析的一个问题是同一个单词的不同变体会被计算为单独的单词。例如,"flower""flowers"在技术上是不同的记号,"swimmer""swimming""swim"也是如此,尽管它们的含义非常接近。如果所有这些不同的变体都映射到同一个单词,那将会很好。

词干解析是一项 NLP 任务,试图将单词切分为基本的语言词干形式。有不同的方法。有些基于语言规则,其他基于观察统计。被称为词形化的算法的一个子类将词性标注和语言规则结合起来。

Porter stemmer 是英语中使用最广泛的免费词干工具。原来的程序是用 ANSI C 编写的,但是很多其他程序包已经封装它来提供对其他语言的访问。尽管其他语言的努力正在进行,但大多数词干工具专注于英语。

以下是通过 NLTK Python 包运行 Porter stemmer 的示例。正如我们所看到的,它处理了大量的情况,包括将"sixties""sixty"转变为同一根"sixti"。但这并不完美。单词"goes"映射到"goe",而"go"映射到它自己。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import nltk 
stemmer = nltk.stem.porter.PorterStemmer()
stemmer.stem('flowers')
u'lemon'
stemmer.stem('zeroes')
u'zero'
stemmer.stem('stemmer')
u'stem'
stemmer.stem('sixties')
u'sixti'
stemmer.stem('sixty')
u'sixty'
stemmer.stem('goes')
u'goe'
stemmer.stem('go')
u'go'

词干解析的确有一个计算成本。 最终收益是否大于成本取决于应用程序。

含义的原子:从单词到N-gram到短语

词袋的概念很简单。但是,一台电脑怎么知道一个词是什么?文本文档以数字形式表示为一个字符串,基本上是一系列字符。也可能会遇到 JSON blob 或 HTML 页面形式的半结构化文本。但即使添加了标签和结构,基本单位仍然是一个字符串。如何将字符串转换为一系列的单词?这涉及解析和标记化的任务。

解析和分词

当字符串包含的不仅仅是纯文本时,解析是必要的。例如,如果原始数据是网页,电子邮件或某种类型的日志,则它包含额外的结构。人们需要决定如何处理日志中的标记,页眉,页脚或无趣的部分。如果文档是网页,则解析器需要处理 URL。如果是电子邮件,则可能需要特殊字段,例如 From,To 和 Subject 需要被特别处理,否则,这些标题将作为最终计数中的普通单词统计,这可能没有用处。

解析后,文档的纯文本部分可以通过标记。这将字符串(一系列字符)转换为一系列记号。然后可以将每个记号计为一个单词。分词器需要知道哪些字符表示一个记号已经结束,另一个正在开始。空格字符通常是好的分隔符,正如标点符号一样。如果文本包含推文,则不应将井号(#)用作分隔符(也称为分隔符)。

有时,分析需要使用句子而不是整个文档。例如,n-gram 是一个句子的概括,不应超出句子范围。更复杂的文本特征化方法,如 word2vec 也适用于句子或段落。在这些情况下,需要首先将文档解析为句子,然后将每个句子进一步标记为单词。

字符串对象

字符串对象有各种编码,如 ASCII 或 Unicode。纯英文文本可以用 ASCII 编码。 一般语言需要 Unicode。 如果文档包含非 ASCII 字符,则确保分词器可以处理该特定编码。否则,结果将不正确。

短语检测的搭配提取

连续的记号能立即被转化成词表和 n-gram。但从语义上讲,我们更习惯于理解短语,而不是 n-gram。在计算自然语言处理中,有用短语的概念被称为搭配。

搭配比其部分的总和更有意义。例如,"strong tea"具有超越"great physical strength""tea"的不同含义,因此被认为是搭配。另一方面,“可爱的小狗”这个短语恰恰意味着它的部分总和:“可爱”和“小狗”。因此,它不被视为搭配。

搭配不一定是连续的序列。"Emma knocked on the door"一词被认为包含搭配"knock door",因此不是每一个搭配都是一个 n-gram。相反,并不是每个 n-gram 都被认为是一个有意义的搭配。

由于搭配不仅仅是其部分的总和,它们的含义也不能通过单个单词计数来充分表达。作为一种表现形式,词袋不足。袋子的 ngram 也是有问题的,因为它们捕获了太多无意义的序列(考虑"this is in the bag-of-ngram example"),而没有足够的有意义的序列。

搭配作为功能很有用。但是,如何从文本中发现并提取它们呢?一种方法是预先定义它们。如果我们努力尝试,我们可能会找到各种语言的全面成语列表,我们可以通过文本查看任何匹配。这将是非常昂贵的,但它会工作。如果语料库是非常特定领域的并且包含深奥的术语,那么这可能是首选的方法。但是这个列表需要大量的手动管理,并且需要不断更新语料库。例如,分析推文,博客和文章可能不太现实。

自从统计 NLP 过去二十年出现以来,人们越来越多地选择用于查找短语的统计方法。统计搭配提取方法不是建立固定的短语和惯用语言列表,而是依赖不断发展的数据来揭示当今流行的语言。

基于频率的方法

一个简单的黑魔法是频繁发生的 n-gram。这种方法的问题是最常发生的,这种可能不是最有用的。下图 显示了整个 Yelp 评论数据集中最流行的 bigram(n=2)。 正如我们所知的,按文件计数排列的最常见的十大常见术语是非常通用的术语,并不包含太多含义。

用于搭配提取的假设检验

原始流行度计数(Raw popularity count)是一个比较粗糙的方法。我们必须找到更聪慧的统计数据才能够轻松挑选出有意义的短语。关键的想法是看两个单词是否经常出现在一起。回答这个问题的统计机制被称为假设检验。

假设检验是将噪音数据归结为“是”或“否”的答案。它涉及将数据建模为从随机分布中抽取的样本。随机性意味着人们永远无法 100% 的确定答案;总会有异常的机会。所以答案附在概率上。例如,假设检验的结果可能是“这两个数据集来自同一分布,其概率为 95%”。对于假设检验的温和介绍,请参阅可汗学院关于假设检验和 p 值的教程。

在搭配提取的背景下,多年来已经提出了许多假设检验。最成功的方法之一是基于似然比检验(Dunning,1993)。对于给定的一对单词,该方法测试两个假设观察的数据集。假设 1(原假设)表示,词语 1 独立于词语 2 出现。另一种说法是说,看到词语1对我们是否看到词语2没有影响。假设 2(备选假设)说,看到词 1 改变了看到单词 2 的可能性。我们采用备选假设来暗示这两个单词形成一个共同的短语。因此,短语检测(也称为搭配提取)的似然比检验提出了以下问题:给定文本语料库中观察到的单词出现更可能是从两个单词彼此独立出现的模型中生成的,或者模型中两个词的概率纠缠?

这是有用的。让我们算一点。(数学非常精确和简洁地表达事物,但它确实需要与自然语言完全不同的分析器。)

The final statistic is the log of the ratio between the two:

似然函数L(Data; H)表示在单词对的独立模型或非独立模型下观察数据集中词频的概率。为了计算这个概率,我们必须对如何生成数据做出另一个假设。最简单的数据生成模型是二项模型,其中对于数据集中的每个单词,我们抛出一个硬币,并且如果硬币朝上出现,我们插入我们的特殊单词,否则插入其他单词。在此策略下,特殊词的出现次数遵循二项分布。二项分布完全由词的总数,词的出现次数和词首概率决定。

似然比检验分析常用短语的算法收益如下。

  1. 计算所有单体词的出现概率:p(w)
  2. 计算所有唯一双元的条件成对词发生概率:p(W2 × W1)
  3. 计算所有唯一的双对数似然比对数。
  4. 根据它们的似然比排序双字节。
  5. 以最小似然比值作为特征。

掌握似然比测试

关键在于测试比较的不是概率参数本身,而是在这些参数(以及假设的数据生成模型)下观察数据的概率。可能性是统计学习的关键原则之一。但是在你看到它的前几次,这绝对是一个令人困惑的问题。一旦你确定了逻辑,它就变得直观了。

还有另一种基于点互信息的统计方法。但它对真实世界文本语料库中常见的罕见词很敏感。因此它不常用,我们不会在这里展示它。

请注意,搭配抽取的所有统计方法,无论是使用原始频率,假设测试还是点对点互信息,都是通过过滤候选词组列表来进行操作的。生成这种清单的最简单和最便宜的方法是计算 n-gram。它可能产生不连续的序列,但是它们计算成本颇高。在实践中,即使是连续 n-gram,人们也很少超过 bi-gram 或 tri-gram,因为即使在过滤之后,它们的数量也很多。为了生成更长的短语,还有其他方法,如分块或与词性标注相结合。

分块(chunking)和词性标注(part-of-Speech Tagging)

分块比 n-gram 要复杂一点,因为它基于词性,基于规则的模型形成了记号序列。

例如,我们可能最感兴趣的是在问题中找到所有名词短语,其中文本的实体,主题最为有趣。 为了找到这个,我们使用词性标记每个作品,然后检查该标记的邻域以查找词性分组或“块”。 定义单词到词类的模型通常是语言特定的。 几种开源 Python 库(如 NLTK,Spacy 和 TextBlob)具有多种语言模型。

每个库找到的名词短语有些不同。spacy 包含英语中的常见单词,如"a""the",而 TextBlob 则删除这些单词。这反映了规则引擎的差异,它驱使每个库都认为是“名词短语”。 你也可以写你的词性关系来定义你正在寻找的块。使用 Python 进行自然语言处理可以深入了解从头开始用 Python 进行分块。

总结

词袋模型易于理解和计算,对分类和搜索任务很有用。但有时单个单词太简单,不足以将文本中的某些信息封装起来。为了解决这个问题,人们寄希望于比较长的序列。Bag-of-ngram 是 BOW 的自然概括,这个概念仍然容于理解,而且它的计算开销这就像 BOW 一样容易。

Bag of-ngram 生成更多不同的 ngram。它增加了特征存储成本,以及模型训练和预测阶段的计算成本。虽然数据点的数量保持不变,但特征空间的维度现在更大。因此数据密度更为稀疏。n 越高,存储和计算成本越高,数据越稀疏。由于这些原因,较长的 n-gram 并不总是会使模型精度的得到提高(或任何其他性能指标)。人们通常在n = 2或 3 时停止。较少的 n-gram 很少被使用。

防止稀疏性和成本增加的一种方法是过滤 n-gram 并保留最有意义的短语。这是搭配抽取的目标。理论上,搭配(或短语)可以在文本中形成非连续的标记序列。然而,在实践中,寻找非连续词组的计算成本要高得多并且没有太多的收益。因此搭配抽取通常从一个候选人名单中开始,并利用统计方法对他们进行过滤。

所有这些方法都将一系列文本标记转换为一组断开的计数。与一个序列相比,一个集合的结构要少得多;他们导致平面特征向量。

Just for fun!
------------- 文章已经到尾 -------------