基于HYBIRD引擎DCLOUD的家校沟通系统外文翻译资料

 2022-10-26 09:54:21

英语原文共 415 页,剩余内容已隐藏,支付完成后下载完整资料


  1. 训练一个分类器

本章内容

从文本中提取特征

Mahout使用功能转换

训练两个mahout分类器

从mahout中选择学习算法

这节讨论分类的第一阶段:训练模型。开发分类器是个动态过程,要求你新颖地思考出描述数据特征的最好的方式,然后考虑如何在选用的学习算法中如何使用这些数据特征来训练模型。某些数据很容易就能分类,而有些却会给分类工作带来很大挑战,让你同时感受到有价值、沮丧、有趣。

在本章中,你将学会挑选并有效地提取各种特征以构建Mahout分类器。特征提取所涉及的工作比第13章介绍的简化步骤多得多。我们将详细探讨特征提取,包括如何对原始数据进行预处理,将其变成可分类数据变成适用于Mahout分类算法的向量。我们将以一个计算营销问题为例,演示如何从数据库中提取训练数据。

一旦你理解了怎么样为分类准备数据,你将会在14.4节得到一个利用mahout随即梯度下降算法在一个标准数据集20newsgroups上构建分类器的示例。

14.1 提取特征以构建分类器

把数据变成分类器可用的形式是一个复杂的过程,通常也很耗时。我们在这一节会大致介绍一下其中所涉及的工作。第13章中的图13-2展示了如何训练和使用分类模型,而图14-1是图13-2的一个简化视图。这里只需要一步,就可以从训练样本到达分类模型的训练算法。当然,现实情况会更加复杂。图14-1中还展示了第13章没提到的重要细节。

在图13-2中,训练数据到训练算法只用了一步。实际上,原始数据必须经过搜集和预处理,然后才能变成可分类的训练数据。图14-1中的训练样本是可分类数据,我们会在本章讨论从原始数据到可分类数据的处理过程,并在第15章和第16章给出进一步的细节。

原始数据必须经过搜集和预处理,然后才能变成可分类的训练数据。图14-1中的训练样本是可分类数据,我们会在本章讨论从原始数据到可分类数据的处理过程,并在第15章和第16章给出进一步的细节。

原始数据经过预处理变为可分类形式之后,我们需要进行几步操作来选择预测变量和目标变量,并将它们编码为向量,即Mahout分类器所要求的输入形式。回想下第13章的内容,特征中可以用作预测变量的值有四种:

bull; 连续型;

bull; 类别型;

bull; 单词型;

bull; 文本型。

总体来说,这里对预测变量的描述是正确的,但它忽略了一个重要事实,即无论是在训练算法可以读取的内存还是文件格式中,将这些值交付给训练分类器的任何算法时,都必须以数字向量的形式表示。

与图14-1中经过简化的序列相比,图14-2中多了很多细节。为了将原始数据变成训练算法所要求的输入向量,要对其进行一系列的变换。这些变换可以分为两个阶段:预处理,产生用作训练样本的可分类数据;将可分类数据转换成向量。

如图14-2所示,为训练算法准备数据主要包括两步:

1. 原始数据的预处理 经过重新组织,原始数据变成带有相同字段的记录。为了能够用于分类,这些字段可以是4种类型:连续型、类别型、单词型和文本型。

2. 将数据转换为向量 用自定义代码或者Lucene分析器、Mahout向量编码器之类的工具对可分类数据进行解析和向量化。有些Mahout分类器自己也包含向量化代码。

上述的第二步又可以分为两个阶段——词条化和向量化。对于连续变量而言,解析工作可能微不足道,但对于其他类型的变量,比如类别型、单词型或文本型变量,可能要涉及向量化操作。

本章的后续章节会详细讨论这两步处理。

14.2 原始数据的预处理

在特征提取的第一阶段,我们要重新认识一下数据,找出可以用作预测变量的特征。首先,根据分类目标选择目标变量,然后挑选或剔除特征,以得到值得一试的组合。这一步没有既定法则,全凭经验进行猜测,学习本章示例之后,你应该能慢慢积累出自己的经验。

本节简要概述了数据的预处理过程,包括搜集数据或重新将数据组织成单条记录,并从原始数据中提炼出第二层含义(比如将邮政编码转换为三数字编码或用生日来确定年龄)。在本章的示例当中,预处理并不是主要部分,这是因为这里用的数据集基本上已经做好数据提取了。而在第16章和第17章中的示例中,预处理扮演着更重要的角色。

14.2.1 原始数据的转换

在找出要尝试的特征之后,必须先把它们转换成可分类的形式。这个转换涉及将数据重新安排单一位置上并将其转换成合适的具有一致性的形式。

注意:可分类数据由具有相同字段的记录组成,字段的数据类型为下面4种之一:连续型、类别型、单词型或文本型。每条记录都包含一个训练样本的完全非规范化的描述。

乍一看,这一步好像不需要做就已经完成。如果数据看起来像单词,那特征肯定就是单词型,对不对?如果数据看起来像数字,那特征肯定是连续型,对吧?但我们在第13章已经讲过,第一印象可能会误导你。比如邮政编码,乍看像数字,但实际上是一个类别,是一个预先定义的类别的标签。包含单词的东西可能是单词型,或者最好看成类别型或文本型。用户ID或产品ID看起来可能像数值、类别或单词型数据,但更常见的做法为了支持它们所指向的用户或产品的特性对它们进行非规范化(denormalization)处理 。

下面的示例来自计算营销,我们可以将其作为为分类准备原始数据的练习。

14.2.2 一个计算营销的例子

假设你要构建一个分类模型,以确定用户是否会购买你向他们提供的某种产品。这算不上推荐系统,因为它是根据用户和产品的特性进行分类,而不是根据相似用户的集体行为(collective behavior)进行分类。

这个例子中的数据库中有几个数据库表,如图14-3所示。这些表是高度简化的零售系统的经典数据表。这里有用来表示用户和产品的表,有一个表记录展示或提供产品给用户的时间,还有一个表记录展示产品给用户导致的购买行为。这些数据目前还不能作为分类器的训练或测试数据,因为它们分散在几个表中。

图14-3中展示的营销项目有很多种数据类型。用户有人口统计数据,比如生日和性别;产品有型号和颜色。向用户展示的产品数据记录在offer表中,跟offer相关联的产品购买记录放在purchase表中。

图14-4中是将这些数据变成分类器训练数据的一种可能方式。对于offer表中的每条记录,应该都有一条记录与之对应,但要注意是如何用产品和用户的ID来联结product和user表的。在这个过程中,用户的生日表示为年龄。我们用了一个外联结来推导产品展示到产品购买之间的时间延迟,并用一个标志来表明是否有购买行为发生。

为了将表中数据表示为图14-4中所示的可用形式,我们需要把它们集中到一起重新组织。为完成这个任务,可以像下面这样使用SQL查询:

Select

now()-birthDate as age, gender,

typeId, colorId, price, discount, offerTime,

ifnull(purchase.time, 0, purchase.time - offer.time) as purchaseDelay,

ifnull(purchase.time, 0, 1) as purchasedfrom

offer

join user using (userId)

join product using (productId)

left outer join purchase using (offerId);

该查询对存储在不同数据表中的数据进行了非规范化处理,将所有必要数据整合到一起形成记录。在这个例子中,offer表是主表,并且userId、productId以及offerId上的外键本质使得上述查询对offer表中的每条记录都恰好产生一条对应记录。需要注意的是跟purchase表的联结是外联结,这样就可以允许包含purchase.time的ifnull表达式在没有任何购买行为时产生0值。

注意:有时年龄更适合分类,而有时生日却更适合。比如说,在汽车事故的保险数据中,用年龄做变量会更好,因为与客户所属的时代相比,汽车事故跟客户年龄段的关系更大。而在购买音乐的数据中,生日可能更有意义,因为人们通常会保持自己早期对音乐的偏好,其对音乐的品味通常能折射出他们的时代特征。上述查询语句产生的记录是可分类数据,可以用于训练算法的解析和向量化处理过程。向量化处理可以由你编码完成,或者把这些数据变成Mahout分类器可以接受的格式,因为这些分类器通常有自己的解析和向量化代码,可以帮你完成数据的解析和向量化处理。后续的内容和示例将重点讨论如何对解析后的可分类数据做向量化处理。

14.3 将可分类数据转换为向量

在Mahout中,Vector(向量)是一种保存浮点数字的数据类型,并且这些浮点值用整型做索引。本节会告诉你如何将数据编码为Vector,解释什么是特征散列(feature hashing),并演示Mahout API如何进行特征散列。我们还会看一下如何对不同类型的变量值进行编码。

前面有关聚类的各章中已经介绍过了Vector。很多种分类器,特别是Mahout中用的分类器,基本上都是以线性代数为基础,因此要求训练数据以Vector形式输入。

14.3.1 用向量表示数据

怎么用Vector表示可分类数据呢?表14-1中总结了几种办法。

表14-1 将可分类数据编码为向量的办法

Mahout中不同分类器使用了表14-1中的各种办法。我们来看一下如何将单词型、文本型和类别型值编码为向量。

1. 每个词一个分量

将可分类数据编码为Vector的一种办法是遍历两次训练数据:一次确定必需的Vector大小,并构建一个词典记录每个特征放在Vector中的什么位置;一次转换数据。这种方式可以用简单的表示来编码训练和测试样本:每个连续值、每个类别型、单词型和文本型数据中的独立单词或类别在向量表示中都会被分配唯一的位置。

这种方式明显的缺点在于要扫描两次训练数据,所以可能导致分类器的训练计算成本加倍,对于特别大的数据集来说这真是个问题。Mahout中大多数聚类算法用的都是这种两次扫描的办法。

2. 将向量作为词袋

另外一种办法是包含特征名称,或是名称加上类别型、单词型或文本型变量值,而不是Vector对象。这一方法主要是用在朴素贝叶斯和补充朴素贝叶斯等Mahout分类器中。

这种办法的优势是可以不用词典,但这也意味着很难利用Mahout的线性代数功能,这些功能要求涉及的Vector向量长度已知并具有一致性。

3. 特征散列

基于SGD的分类器无需预先确定向量的大小,只要简单挑一个合理的大小,并把训练数据预置进那个大小的向量中。这种办法称为特征散列。预置时,我们通过连续变量变量名的散列,或者类别型、文本型或单词型数据的变量名和类别名或单词本身的散列,来选择一个或多个位置。

这种采用特征散列的办法有明显优势,需要的内存更少,也可以少扫描一次训练数据,但对向量进行逆向工程来确定映射到向量位置的原始特征也更加困难。这是因为多个特征可能会添加散列到同一个位置。当向量较大,或者每个特征对应多个位置时,这对于精确性不是什么问题,但可能会为理解分类器造成困难。

14.3.2 用Mahout API做特征散列

我们在这一节中看一下如何用Mahout API做特征散列。我们详细介绍如何对连续型、类别型、单词型和文本型特征编码。我们还解释特征冲突的概念以及它们对分类器的影响。

1. 对连续型特征编码

连续值是最容易编码的数据。连续变量的值可以直接加到为存储它们而分配的一个或多个位置上。这些位置是由特征的名称确定的。

Mahout对连续值的特征散列编码是通过ContinuousValueEncoder完成的。默认情况下,ContinuousValueEncoder只会更新向量中的一个位置,但你可以用setProbes()方法指定更新的位置数目。要编码变量的值,需要一个Vector,此时可以通过new RandomAccessSparseVector(lmp.getNumFeatures())建立一个新向量。然后,我们用encoder.addToVector(value, vector)对值编码。注意,Mahout假定被编码的值是字符串。如果被编码的值是double,一个null就会被传给String值,并且该值会被看成权重,即encoder.addToVector(null, value, vector)。

2. 对类别型和单词型特征编码

对具有n种不同值的类别特征编码,我们可以在n个向量位

剩余内容已隐藏,支付完成后下载完整资料


资料编号:[154085],资料为PDF文档或Word文档,PDF文档可免费转换为Word

原文和译文剩余内容已隐藏,您需要先支付 30元 才能查看原文和译文全部内容!立即支付

以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。