原文:
zh.annas-archive.org/md5/8ddea683d78e7bd756401ec665273969译者:飞龙
第二部分:机器学习算法
本节详细解释了不同类型的机器学习算法,如无监督机器学习算法和传统监督学习算法,并介绍了自然语言处理算法。本节以介绍推荐引擎结束。包括在本节中的章节有:
-
第六章,无监督机器学习算法
-
第七章,传统监督学习算法
-
第八章,神经网络算法
-
第九章,自然语言处理算法
-
第十章,推荐引擎
第六章:无监督机器学习算法
本章是关于无监督机器学习算法的。本章以介绍无监督学习技术开始。然后,我们将学习两种聚类算法:k 均值聚类和层次聚类算法。接下来的部分将介绍一种降维算法,当我们有大量输入变量时可能会很有效。接下来的部分展示了无监督学习如何用于异常检测。最后,我们将看看最强大的无监督学习技术之一,关联规则挖掘。本节还解释了从关联规则挖掘中发现的模式如何代表跨交易中各种数据元素之间的有趣关系,这可以帮助我们进行基于数据的决策。
在本章结束时,读者应该能够理解无监督学习如何用于解决一些现实世界的问题。读者将了解目前用于无监督学习的基本算法和方法论。
在本章中,我们将涵盖以下主题:
-
无监督学习
-
聚类算法
-
降维
-
异常检测算法
-
关联规则挖掘
介绍无监督学习
无监督学习的最简单定义是,它是通过发现和利用数据的固有模式来为非结构化数据提供某种结构的过程。如果数据不是由某种随机过程产生的,它在其多维问题空间中的数据元素之间将具有一些模式。无监督学习算法通过发现这些模式并利用它们来为数据集提供一些结构。这个概念在下图中显示:
请注意,无监督学习通过发现现有模式的新特征来添加结构。
数据挖掘生命周期中的无监督学习
理解无监督学习的作用,首先要看数据挖掘过程的整体生命周期。有不同的方法论将数据挖掘过程的生命周期划分为不同的独立阶段,称为阶段。目前,有两种流行的表示数据挖掘生命周期的方式:
-
CRISP-DM(跨行业标准数据挖掘过程)生命周期
-
SEMMA(样本、探索、修改、建模、访问)数据挖掘过程
CRISP-DM 是由一些数据挖掘者联合开发的,他们来自包括克莱斯勒和SPSS(社会科学统计软件包)在内的各种公司。SEMMA 是由SAS(统计分析系统)提出的。让我们看看这两种数据挖掘生命周期的表示之一,CRISP-DM,并尝试理解无监督学习在数据挖掘生命周期中的位置。请注意,SEMMA 在其生命周期内有一些类似的阶段。
如果我们看 CRISP-DM 生命周期,可以看到它包括六个不同的阶段,如下图所示:
让我们逐个了解每个阶段:
- 阶段 1:业务理解:这是收集需求的阶段,涉及从业务角度深入全面地理解问题。根据机器学习(ML)的要求定义问题的范围,并适当地重新表述它是这个阶段的重要部分。例如,对于二元分类问题,有时将需求用可以证明或拒绝的假设来表述是有帮助的。本阶段还涉及记录将在下游阶段 4 中训练的机器学习模型的期望。例如,对于分类问题,我们需要记录可以部署到生产中的模型的最低可接受准确性。
CRISP-DM 生命周期的第一阶段是业务理解,重点是需要做什么,而不是如何做。
-
第二阶段:数据理解:这是关于理解可用于数据挖掘的数据。在这个阶段,我们将找出是否有适合解决问题的正确数据集。在确定数据集之后,我们需要了解数据的质量和结构。我们需要找出可以从数据中提取的模式,这些模式可能会引导我们获得重要的见解。我们还将尝试找到可以根据第一阶段收集的要求用作标签(或目标变量)的正确特征。无监督学习算法可以在实现第二阶段目标方面发挥强大作用。无监督算法可以用于以下目的:
-
在数据集中发现模式
-
通过分析发现的模式来理解数据集的结构
-
识别或推导目标变量
-
第三阶段:数据准备:这是为我们将在第四阶段训练的 ML 模型准备数据的阶段。可用的标记数据被分成两个不相等的部分。较大的部分称为训练数据,用于在第四阶段训练模型。较小的部分称为测试数据,在第五阶段用于模型评估。在这个阶段,无监督机器学习算法可以用作准备数据的工具,例如,它们可以用于将非结构化数据转换为结构化数据,提供可以帮助训练模型的额外维度。
-
第四阶段:建模:这是我们使用监督学习来制定已发现模式的阶段。我们需要根据所选的监督学习算法的要求成功准备数据。这也是确定将用作标签的特定特征的阶段。在第三阶段,我们将数据分为测试集和训练集。在这个阶段,我们形成数学公式来表示我们感兴趣的模式中的关系。这是通过使用第三阶段创建的训练数据来训练模型完成的。如前所述,最终的数学公式将取决于我们选择的算法。
-
第五阶段:评估:这个阶段是关于使用第三阶段的测试数据测试新训练的模型。如果评估符合第一阶段设定的期望,那么我们需要再次迭代所有前面的阶段,从第一阶段开始。这在前面的图像中有所说明。
-
第六阶段:部署:如果评估符合或超过第五阶段描述的期望,那么训练好的模型将被部署到生产环境中,并开始为我们在第一阶段定义的问题提供解决方案。
CRISP-DM 生命周期的第二阶段(数据理解)和第三阶段(数据准备)都是关于理解数据并为训练模型做准备。这些阶段涉及数据处理。一些组织为这个数据工程阶段雇佣专家。
很明显,提出问题的解决方案的过程完全是数据驱动的。结合监督和无监督机器学习用于制定可行的解决方案。本章重点介绍解决方案的无监督学习部分。
数据工程包括第二阶段和第三阶段,是机器学习中最耗时的部分。它可能占据典型 ML 项目时间和资源的 70%。无监督学习算法在数据工程中可以发挥重要作用。
以下各节提供了有关无监督算法的更多细节。
无监督学习的当前研究趋势
多年来,对机器学习算法的研究更多地集中在监督学习技术上。由于监督学习技术可以直接用于推断,因此它们在时间、成本和准确性方面的优势相对容易衡量。无监督机器学习算法的潜力最近才被认识到。由于无监督学习不受指导,因此它不太依赖假设,并且可能在任何维度上收敛解决方案。尽管更难控制无监督学习算法的范围和处理要求,但它们有更多潜力发现隐藏的模式。研究人员还在努力将无监督机器学习技术与监督学习技术相结合,以设计新的强大算法。
实际例子
目前,无监督学习用于更好地理解数据并为其提供更多结构,例如,它用于市场细分、欺诈检测和市场篮分析(稍后在本章中讨论)。让我们看几个例子。
语音分类
无监督学习可以用于对语音文件中的个别声音进行分类。它利用了每个人的声音具有独特的特征这一事实,从而创建可能可分离的音频模式。这些模式可以用于语音识别,例如,谷歌在其 Google Home 设备中使用这种技术来训练它们区分不同人的声音。一旦训练完成,Google Home 可以个性化地为每个用户提供响应。
例如,假设我们有一段录制的三个人互相交谈半个小时的对话。使用无监督学习算法,我们可以识别数据集中不同人的声音。请注意,通过无监督学习,我们为给定的非结构化数据集添加了结构。这种结构为我们的问题空间提供了额外有用的维度,可以用于获取见解并为我们选择的机器学习算法准备数据。以下图表显示了无监督学习用于语音识别的情况:
请注意,在这种情况下,无监督学习建议我们添加一个具有三个不同级别的新特征。
文档分类
无监督机器学习算法也可以应用于非结构化文本数据的存储库,例如,如果我们有一组 PDF 文档的数据集,那么无监督学习可以用于以下目的:
-
发现数据集中的各种主题
-
将每个 PDF 文档与发现的主题之一关联起来
无监督学习用于文档分类的情况如下图所示。这是另一个例子,我们在非结构化数据中添加了更多的结构:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/bafdb93e-edf1-4f72-a99e-dfd51fe936b8.png图 6.4:使用无监督学习进行文档分类
请注意,在这种情况下,无监督学习建议我们添加一个具有五个不同级别的新特征。
理解聚类算法
在无监督学习中使用的最简单和最强大的技术之一是基于通过聚类算法将相似模式分组在一起。它用于理解与我们试图解决的问题相关的数据的特定方面。聚类算法寻找数据项中的自然分组。由于该组不是基于任何目标或假设,因此被归类为无监督学习技术。
各种聚类算法创建的分组是基于在问题空间中找到各种数据点之间的相似性。确定数据点之间的相似性的最佳方法将因问题而异,并且将取决于我们正在处理的问题的性质。让我们看看可以用来计算各种数据点之间相似性的各种方法。
量化相似性
聚类算法创建的分组的可靠性是基于这样一个假设:我们能够准确量化问题空间中各种数据点之间的相似性或接近程度。这是通过使用各种距离度量来实现的。以下是用于量化相似性的三种最流行的方法:
-
欧几里得距离度量
-
曼哈顿距离度量
-
余弦距离度量
让我们更详细地看看这些距离度量。
欧几里得距离
不同点之间的距离可以量化两个数据点之间的相似性,并且广泛用于无监督机器学习技术,如聚类。欧几里得距离是最常见和简单的距离度量。它通过测量多维空间中两个数据点之间的最短距离来计算。例如,让我们考虑二维空间中的两点A(1,1)和B(4,4),如下图所示:
要计算A和B之间的距离——即d(A,B),我们可以使用以下毕达哥拉斯公式:
请注意,此计算是针对二维问题空间的。对于n维问题空间,我们可以计算两点A和B之间的距离如下:
曼哈顿距离
在许多情况下,使用欧几里得距离度量来测量两点之间的最短距离将无法真正代表两点之间的相似性或接近程度——例如,如果两个数据点代表地图上的位置,则使用地面交通工具(如汽车或出租车)从点 A 到点 B 的实际距离将大于欧几里得距离计算出的距离。对于这类情况,我们使用曼哈顿距离,它标记了两点之间的最长路线,并更好地反映了在繁忙城市中可以前往的源点和目的地点之间的接近程度。曼哈顿和欧几里得距离度量之间的比较如下图所示:
曼哈顿距离始终大于或等于相应的欧几里得距离。
余弦距离
欧几里得和曼哈顿距离度量在高维空间中表现不佳。在高维问题空间中,余弦距离更准确地反映了多维问题空间中两个数据点之间的接近程度。余弦距离度量是通过测量由两个连接到参考点的点所创建的余弦角来计算的。如果数据点接近,则角度将很窄,而不管它们具有的维度如何。另一方面,如果它们相距很远,那么角度将很大:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/d5d492a0-e445-4361-80c4-7a92031aebd7.png文本数据几乎可以被视为高维空间。由于余弦距离度量在高维空间中表现非常好,因此在处理文本数据时是一个不错的选择。
请注意,在前面的图中,A(2,5)和B(4.4)之间的角的余弦是余弦距离。这些点之间的参考点是原点——即X(0,0)。但实际上,问题空间中的任何点都可以充当参考数据点,并且不一定是原点。
K 均值聚类算法
k-means 聚类算法的名称来自于它试图创建k个聚类,通过计算均值来找到数据点之间的接近程度。它使用了一个相对简单的聚类方法,但由于其可扩展性和速度而仍然受欢迎。从算法上讲,k-means 聚类使用了一个迭代逻辑,将聚类的中心移动到它们所属的分组的最具代表性的数据点。
重要的是要注意,k-means 算法缺乏聚类所需的非常基本的功能之一。这个缺失的功能是,对于给定的数据集,k-means 算法无法确定最合适的聚类数。最合适的聚类数k取决于特定数据集中自然分组的数量。这种省略背后的哲学是尽可能简化算法,最大限度地提高其性能。这种精益简洁的设计使 k-means 适用于更大的数据集。假设将使用外部机制来计算k。确定k的最佳方法将取决于我们试图解决的问题。在某些情况下,k直接由聚类问题的上下文指定,例如,如果我们想将一类数据科学学生分成两个聚类,一个由具有数据科学技能的学生组成,另一个由具有编程技能的学生组成,那么k将为 2。在其他一些问题中,k的值可能不明显。在这种情况下,将不得不使用迭代的试错程序或基于启发式的算法来估计给定数据集的最合适的聚类数。
k-means 聚类的逻辑
本节描述了 k-means 聚类算法的逻辑。让我们逐一看一下。
初始化
为了对它们进行分组,k-means 算法使用距离度量来找到数据点之间的相似性或接近程度。在使用 k-means 算法之前,需要选择最合适的距离度量。默认情况下,将使用欧氏距离度量。此外,如果数据集中有异常值,则需要制定机制来确定要识别和删除数据集的异常值的标准。
k-means 算法的步骤
k-means 聚类算法涉及的步骤如下:
| 步骤 1 | 我们选择聚类的数量k。 |
|---|---|
| 步骤 2 | 在数据点中,我们随机选择k个点作为聚类中心。 |
| 步骤 3 | 基于所选的距离度量,我们迭代地计算问题空间中每个点到k个聚类中心的距离。根据数据集的大小,这可能是一个耗时的步骤,例如,如果聚类中有 10,000 个点,k=3,这意味着需要计算 30,000 个距离。 |
| 步骤 4 | 我们将问题空间中的每个数据点分配给最近的聚类中心。 |
| 步骤 5 | 现在我们问题空间中的每个数据点都有一个分配的聚类中心。但我们还没有完成,因为初始聚类中心的选择是基于随机选择的。我们需要验证当前随机选择的聚类中心实际上是每个聚类的重心。我们通过计算每个k聚类的组成数据点的平均值来重新计算聚类中心。这一步解释了为什么这个算法被称为 k-means。 |
| 步骤 6 | 如果在步骤 5 中聚类中心发生了变化,这意味着我们需要重新计算每个数据点的聚类分配。为此,我们将回到步骤 3 重复这个计算密集的步骤。如果聚类中心没有发生变化,或者我们的预定停止条件(例如,最大迭代次数)已经满足,那么我们就完成了。 |
下图显示了在二维问题空间中运行 k-means 算法的结果:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/70ce3a57-73b1-4c76-97fe-fdbcc956e36d.png(a)聚类前的数据点;(b)运行 k 均值聚类算法后的结果集群
请注意,在运行 k 均值后创建的两个结果集群在这种情况下有很好的区分度。
停止条件
对于 k 均值算法,默认的停止条件是在第 5 步中不再移动集群中心。但是与许多其他算法一样,k 均值算法可能需要很长时间才能收敛,特别是在处理高维问题空间中的大型数据集时。我们可以明确定义停止条件,而不是等待算法收敛,如下所示:
-
通过指定最大执行时间:
-
停止条件:如果 t>t[max],其中t是当前执行时间,*t[max]*是我们为算法设置的最大执行时间。
-
通过指定最大迭代次数:
-
停止条件:如果 m>m[max],其中m是当前迭代次数,*m[max]*是我们为算法设置的最大迭代次数。
编写 k 均值算法
让我们看看如何在 Python 中编写 k 均值算法:
- 首先,让我们导入编写 k 均值算法所需的软件包。请注意,我们正在导入
sklearn软件包进行 k 均值聚类:
from sklearn import cluster import pandas as pd
import numpy as np
- 要使用 k 均值聚类,让我们在二维问题空间中创建 20 个数据点,这些数据点将用于 k 均值聚类:
dataset = pd.DataFrame({
'x': [11, 21, 28, 17, 29, 33, 24, 45, 45, 52, 51, 52, 55, 53, 55, 61, 62, 70, 72, 10],
'y': [39, 36, 30, 52, 53, 46, 55, 59, 63, 70, 66, 63, 58, 23, 14, 8, 18, 7, 24, 10]
})
- 让我们有两个集群(k=2),然后通过调用
fit函数创建集群:
myKmeans = cluster.KMeans(n_clusters=2)
myKmeans.fit(dataset)
- 让我们创建一个名为
centroid的变量,它是一个包含形成的集群中心位置的数组。在我们的情况下,k=2,数组的大小将为 2。让我们还创建另一个名为label的变量,表示每个数据点分配给两个集群中的一个。由于有 20 个数据点,这个数组的大小将为 20:
centroids = myKmeans.cluster_centers_
labels = myKmeans.labels_
- 现在让我们打印这两个数组,
centroids和labels:
请注意,第一个数组显示了每个数据点与集群的分配,第二个数组显示了两个集群中心。
- 让我们使用
matplotlib绘制并查看这些集群:
请注意,图中的较大点是由 k 均值算法确定的中心点。
k 均值聚类的局限性
k 均值算法旨在成为一种简单快速的算法。由于其设计上的故意简单性,它具有以下限制:
-
k 均值聚类的最大限制是初始集群数量必须预先确定。
-
集群中心的初始分配是随机的。这意味着每次运行算法时,可能会得到略有不同的集群。
-
每个数据点只分配给一个集群。
-
k 均值聚类对异常值敏感。
层次聚类
k 均值聚类使用自上而下的方法,因为我们从最重要的数据点开始算法,即集群中心。还有一种聚类的替代方法,即不是从顶部开始,而是从底部开始算法。在这种情况下,底部是问题空间中的每个单独数据点。解决方案是在向上移向集群中心的过程中不断将相似的数据点分组在一起。这种替代的自下而上方法由层次聚类算法使用,并在本节中讨论。
层次聚类的步骤
层次聚类涉及以下步骤:
-
我们在问题空间中为每个数据点创建一个单独的集群。如果我们的问题空间包含 100 个数据点,那么它将从 100 个集群开始。
-
我们只将彼此最接近的点分组。
-
我们检查停止条件;如果停止条件尚未满足,则重复步骤 2。
生成的集群结构称为树状图。
在树状图中,垂直线的高度决定了物品的接近程度,如下图所示:
请注意,停止条件显示为上图中的虚线。
编写一个分层聚类算法
让我们学习如何在 Python 中编写一个分层算法:
- 我们将首先从
sklearn.cluster库中导入AgglomerativeClustering,以及pandas和numpy包:
from sklearn.cluster import AgglomerativeClustering import pandas as pd
import numpy as np
- 然后我们将在二维问题空间中创建 20 个数据点:
dataset = pd.DataFrame({
'x': [11, 21, 28, 17, 29, 33, 24, 45, 45, 52, 51, 52, 55, 53, 55, 61, 62, 70, 72, 10],
'y': [39, 36, 30, 52, 53, 46, 55, 59, 63, 70, 66, 63, 58, 23, 14, 8, 18, 7, 24, 10]
})
- 然后我们通过指定超参数来创建分层集群。我们使用
fit_predict函数来实际处理算法:
cluster = AgglomerativeClustering(n_clusters=2, affinity='euclidean', linkage='ward')
cluster.fit_predict(dataset)
- 现在让我们看一下每个数据点与创建的两个簇的关联:
您可以看到分层和 k 均值算法的集群分配非常相似。
评估聚类
良好质量的聚类的目标是属于不同簇的数据点应该是可区分的。这意味着以下内容:
-
属于同一簇的数据点应尽可能相似。
-
属于不同簇的数据点应尽可能不同。
人类直觉可以用来通过可视化集群结果来评估集群结果,但也有数学方法可以量化集群的质量。轮廓分析是一种比较 k 均值算法创建的集群中的紧密度和分离度的技术。轮廓绘制了一个图,显示了特定集群中每个点与相邻集群中其他点的接近程度。它将与每个集群关联的数字范围为[-0, 1]。以下表显示了此范围中的数字表示什么:
| 范围 | 意义 | 描述 |
|---|---|---|
| 0.71–1.0 | 优秀 | 这意味着 k 均值聚类导致的组在相当程度上是可区分的。 |
| 0.51–0.70 | 合理 | 这意味着 k 均值聚类导致的组在某种程度上是可区分的。 |
| 0.26–0.50 | 弱 | 这意味着 k 均值聚类导致了分组,但不应依赖分组的质量。 |
| <0.25 | 未找到任何聚类 | 使用选择的参数和使用的数据,无法使用 k 均值聚类创建分组。 |
请注意,问题空间中的每个簇将获得一个单独的分数。
聚类的应用
聚类用于我们需要在数据集中发现潜在模式的地方。
在政府使用案例中,聚类可用于以下目的:
-
犯罪热点分析
-
人口社会分析
在市场研究中,聚类可用于以下目的:
-
市场细分
-
定向广告
-
客户分类
主成分分析(PCA)也用于通常探索数据并从实时数据中去除噪音,例如股票市场交易。
降维
我们数据中的每个特征对应于问题空间中的一个维度。将特征的数量最小化以使问题空间更简单称为降维。可以通过以下两种方式之一来完成:
-
特征选择:选择在我们试图解决的问题的上下文中重要的一组特征
-
特征聚合:使用以下算法之一组合两个或多个特征以减少维度:
-
PCA:线性无监督 ML 算法
-
线性判别分析(LDA):线性监督 ML 算法
-
核主成分分析:一种非线性算法
让我们更深入地了解一种流行的降维算法,即 PCA。
主成分分析
PCA 是一种无监督的机器学习技术,可以使用线性变换来降低维度。在下图中,我们可以看到两个主成分PC1和PC2,它们显示了数据点的分布形状。PC1 和 PC2 可以用适当的系数来总结数据点:
让我们考虑以下代码:
from sklearn.decomposition import PCA
iris = pd.read_csv('iris.csv')
X = iris.drop('Species', axis=1)
pca = PCA(n_components=4)
pca.fit(X)
现在让我们打印我们的 PCA 模型的系数:
请注意,原始的 DataFrame 有四个特征,Sepal.Length、Sepal.Width、Petal.Length和Petal.Width。前面的 DataFrame 指定了四个主成分 PC1、PC2、PC3 和 PC4 的系数,例如,第一行指定了可以用来替换原始四个变量的 PC1 的系数。
根据这些系数,我们可以计算我们输入 DataFrame X 的 PCA 组件:
pca_df=(pd.DataFrame(pca.components_,columns=X.columns))
# Let us calculate PC1 using coefficients that are generated
X['PC1'] = X['Sepal.Length']* pca_df['Sepal.Length'][0] + X['Sepal.Width']* pca_df['Sepal.Width'][0]+ X['Petal.Length']* pca_df['Petal.Length'][0]+X['Petal.Width']* pca_df['Petal.Width'][0]
# Let us calculate PC2
X['PC2'] = X['Sepal.Length']* pca_df['Sepal.Length'][1] + X['Sepal.Width']* pca_df['Sepal.Width'][1]+ X['Petal.Length']* pca_df['Petal.Length'][1]+X['Petal.Width']* pca_df['Petal.Width'][1]
#Let us calculate PC3
X['PC3'] = X['Sepal.Length']* pca_df['Sepal.Length'][2] + X['Sepal.Width']* pca_df['Sepal.Width'][2]+ X['Petal.Length']* pca_df['Petal.Length'][2]+X['Petal.Width']* pca_df['Petal.Width'][2]
# Let us calculate PC4
X['PC4'] = X['Sepal.Length']* pca_df['Sepal.Length'][3] + X['Sepal.Width']* pca_df['Sepal.Width'][3]+ X['Petal.Length']* pca_df['Petal.Length'][3]+X['Petal.Width']* pca_df['Petal.Width'][3]
现在让我们在计算 PCA 组件后打印 X:
现在让我们打印方差比率,并尝试理解使用 PCA 的影响:
方差比率表示如下:
-
如果我们选择用 PC1 替换原始的四个特征,那么我们将能够捕获大约 92.3%的原始变量的方差。我们通过不捕获原始四个特征 100%的方差来引入一些近似。
-
如果我们选择用 PC1 和 PC2 替换原始的四个特征,那么我们将捕获额外的 5.3%的原始变量的方差。
-
如果我们选择用 PC1、PC2 和 PC3 替换原始的四个特征,那么我们现在将捕获原始变量进一步的 0.017%的方差。
-
如果我们选择用四个主成分替换原始的四个特征,那么我们将捕获原始变量的 100%的方差(92.4 + 0.053 + 0.017 + 0.005),但用四个主成分替换四个原始特征是没有意义的,因为我们没有减少维度,也没有取得任何成果。
PCA 的局限性
PCA 的局限性如下:
-
PCA 只能用于连续变量,对于类别变量无关。
-
在聚合时,PCA 近似了组件变量;它以准确性为代价简化了维度的问题。在使用 PCA 之前,应该仔细研究这种权衡。
关联规则挖掘
特定数据集中的模式是需要被发现、理解和挖掘的宝藏。有一组重要的算法试图专注于给定数据集中的模式分析。在这类算法中,较受欢迎的算法之一称为关联规则挖掘算法,它为我们提供了以下功能:
-
衡量模式频率的能力
-
建立模式之间因果关系的能力。
-
通过将它们的准确性与随机猜测进行比较,量化模式的有用性
使用示例
当我们试图调查数据集中不同变量之间的因果关系时,使用关联规则挖掘。以下是它可以帮助回答的示例问题:
-
哪些湿度、云层覆盖和温度值可能导致明天下雨?
-
什么类型的保险索赔可能表明欺诈?
-
哪些药物的组合可能会导致患者并发症?
市场篮分析
在本书中,推荐引擎在第八章“神经网络算法”中进行了讨论。篮子分析是学习推荐的一种简单方法。在篮子分析中,我们的数据只包含有关哪些物品一起购买的信息。它没有任何关于用户或用户是否喜欢个别物品的信息。请注意,获取这些数据要比获取评级数据容易得多。
例如,当我们在沃尔玛购物时,就会产生这种数据,而不需要任何特殊技术来获取数据。这些数据在一段时间内收集起来,被称为交易数据。当将关联规则分析应用于便利店、超市和快餐连锁店中使用的购物车的交易数据集时,就称为市场篮子分析。它衡量了一组物品一起购买的条件概率,有助于回答以下问题:
-
货架上物品的最佳摆放位置是什么?
-
物品在营销目录中应该如何出现?
-
基于用户的购买模式,应该推荐什么?
由于市场篮子分析可以估计物品之间的关系,因此它经常用于大众市场零售,如超市、便利店、药店和快餐连锁店。市场篮子分析的优势在于其结果几乎是不言自明的,这意味着它们很容易被业务用户理解。
让我们来看一个典型的超市。商店中所有可用的唯一物品可以用一个集合https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/ce31fde4-ba41-4fa9-bb71-4c63b428aec9.png={item[1],item[2],…,item[m]}来表示。因此,如果那家超市销售 500 种不同的物品,那么https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/cd637cd5-f4fc-4481-8df6-6dc079d692cb.png将是一个大小为 500 的集合。
人们会从这家商店购买物品。每当有人购买物品并在柜台付款时,它就会被添加到一个特定交易中的物品集合中,称为项目集。在一段时间内,交易被分组在一个由https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/ccfc36fd-6039-44f0-a488-2b03dc777d6a.png表示的集合中,其中https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/ccfc36fd-6039-44f0-a488-2b03dc777d6a.png={t[1],t[2],…,t[n]}。
让我们来看一下只包含四个交易的简单交易数据。这些交易总结在下表中:
| t1 | 球门,护腕 |
|---|---|
| t2 | 球棒,球门,护腕,头盔 |
| t3 | 头盔,球 |
| t4 | 球棒、护腕、头盔 |
让我们更详细地看一下这个例子:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/ce31fde4-ba41-4fa9-bb71-4c63b428aec9.png={球棒,球门,护腕,头盔,球},它代表了商店中所有可用的唯一物品。
让我们考虑来自https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/ccfc36fd-6039-44f0-a488-2b03dc777d6a.png的一个交易 t3。请注意,t3 中购买的物品可以用 itemset[t3]={头盔,球}表示,这表明顾客购买了两件物品。由于这个 itemset 中有两件物品,因此 itemset[t5]的大小被称为两。
关联规则
关联规则通过数学方式描述了各种交易中涉及的物品之间的关系。它通过研究形式为X⇒Y的两个项目集之间的关系来实现这一点,其中X⊂https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/4a0f1bae-4e77-4c84-86a7-6691729c3e57.png,Y⊂https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/1735cf94-543b-47a9-b5b8-24cec3a6055c.png。此外,X和Y是不重叠的项目集;这意味着https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/25efda0c-53d6-46dc-b473-443ee7bc0dfa.png。
关联规则可以用以下形式描述:
{头盔,球}⇒{自行车}
在这里,{头盔,球}是X,{球}是Y。
规则类型
运行关联分析算法通常会从交易数据集中生成大量规则。其中大部分是无用的。为了挑选出可以提供有用信息的规则,我们可以将它们分类为以下三种类型之一:
-
琐碎
-
莫名其妙
-
可操作
让我们更详细地看看每种类型。
琐碎的规则
在生成的大量规则中,许多派生的规则将是无用的,因为它们总结了关于业务的常识。它们被称为琐碎规则。即使琐碎规则的置信度很高,它们仍然是无用的,不能用于任何数据驱动的决策。我们可以安全地忽略所有琐碎规则。
以下是琐碎规则的例子:
-
任何从高楼跳下的人都有可能死亡。
-
更努力工作会导致考试成绩更好。
-
随着温度下降,取暖器的销量会增加
-
在高速公路上超速驾驶会增加事故的可能性。
不可解释规则
在运行关联规则算法后生成的规则中,那些没有明显解释的规则是最难使用的。请注意,规则只有在能帮助我们发现和理解预期最终会导致某种行动的新模式时才有用。如果不是这种情况,我们无法解释事件X导致事件Y的原因,那么它就是一个不可解释的规则,因为它只是一个最终探索两个无关和独立事件之间毫无意义关系的数学公式。
以下是不可解释规则的例子:
-
穿红衬衫的人在考试中得分更高。
-
绿色自行车更容易被盗。
-
购买泡菜的人最终也会购买尿布。
可操作规则
可操作规则是我们正在寻找的黄金规则。它们被业务理解并引发见解。当呈现给熟悉业务领域的观众时,它们可以帮助我们发现事件可能的原因,例如,可操作规则可能根据当前的购买模式建议产品在商店中的最佳摆放位置。它们还可能建议将哪些商品放在一起,以最大化它们一起销售的机会。
以下是可操作规则及其相应的行动的例子:
- **规则 1:**向用户的社交媒体账户展示广告会增加销售的可能性。
**可操作项目:**建议产品的替代广告方式
- **规则 2:**创建更多的价格点会增加销售的可能性。
**可操作项目:**一个商品可能在促销中进行广告,而另一个商品的价格可能会上涨。
排名规则
关联规则有三种衡量方式:
-
物品的支持(频率)
-
置信度
-
提升
让我们更详细地看看它们。
支持
支持度量是一个数字,用来量化我们在数据集中寻找的模式有多频繁。首先计算我们感兴趣的模式出现的次数,然后将其除以所有交易的总数来计算。
让我们看看特定*itemset[a]*的以下公式:
numItemset[a] =包含 itemset[a]的交易数
num[total] =交易总数
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/b03e04f2-449b-4843-ba17-698bb6ffe74c.png仅通过支持,我们就可以了解到模式发生的罕见程度。低支持意味着我们在寻找一种罕见事件。
例如,如果*itemset[a] = {头盔,球}*在六次交易中出现了两次,那么支持(itemset[a])= 2/6 = 0.33。
置信度
置信度是一个数字,通过计算条件概率来量化我们可以将左侧(X)与右侧(Y)关联的强度。它计算了事件X发生的情况下,事件Y会发生的概率。
从数学上讲,考虑规则X ⇒ Y。
这条规则的置信度表示为 confidence(X ⇒ Y),并按以下方式测量:
让我们举个例子。考虑以下规则:
{头盔,球} ⇒ {球门}
这条规则的置信度由以下公式计算:
这意味着如果有人的篮子里有{头盔,球},那么他们还有球门的概率是 0.5 或 50%。
提升
估计规则质量的另一种方法是通过计算提升。提升返回一个数字,量化了规则在预测结果方面相对于仅假设等式右侧的结果的改进程度。如果X和Y项集是独立的,那么提升的计算如下:
关联分析算法
在本节中,我们将探讨以下两种可用于关联分析的算法:
-
Apriori 算法:由 Agrawal, R.和 Srikant 于 1994 年提出。
-
FP-growth 算法:由 Han 等人于 2001 年提出的改进建议。
让我们看看这些算法各自的情况。
Apriori 算法
Apriori 算法是一种迭代和多阶段的算法,用于生成关联规则。它基于生成和测试的方法。
在执行 apriori 算法之前,我们需要定义两个变量:support[threshold]和 Confidence[threshold]。
该算法包括以下两个阶段:
-
候选生成阶段:它生成包含所有高于 support[threshold]的项集的候选项集。
-
过滤阶段:它过滤掉所有低于预期 confidence[threshold]的规则。
过滤后,得到的规则就是答案。
Apriori 算法的局限性
Apriori 算法中的主要瓶颈是第 1 阶段候选规则的生成,例如,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/1486d41a-07b6-45b2-bab4-71873083bfd2.png = {item [1] , item [2] , . . . , item [m] } 可以产生 2^m 个可能的项集。由于其多阶段设计,它首先生成这些项集,然后努力找到频繁项集。这个限制是一个巨大的性能瓶颈,使得 apriori 算法不适用于更大的项。
FP-growth 算法
频繁模式增长(FP-growth)算法是对 apriori 算法的改进。它首先展示频繁交易 FP 树,这是一个有序树。它包括两个步骤:
-
填充 FP 树
-
挖掘频繁模式
让我们一步一步地看这些步骤。
填充 FP 树
让我们考虑下表中显示的交易数据。让我们首先将其表示为稀疏矩阵:
| ID | 球棒 | 球门 | 防护板 | 头盔 | 球 |
|---|---|---|---|---|---|
| 1 | 0 | 1 | 1 | 0 | 0 |
| 2 | 1 | 1 | 1 | 1 | 0 |
| 3 | 0 | 0 | 0 | 1 | 1 |
| 4 | 1 | 0 | 1 | 1 | 0 |
让我们计算每个项的频率,并按频率降序排序:
| 项 | 频率 |
|---|---|
| 防护板 | 3 |
| 头盔 | 3 |
| 球棒 | 2 |
| 球门 | 2 |
| 球 | 1 |
现在让我们根据频率重新排列基于交易的数据:
| ID | 原始项 | 重新排序的项 |
|---|---|---|
| t1 | 防护板,球门 | 防护板,球门 |
| t2 | 球棒,球门,防护板,头盔 | 头盔,防护板,球门,球棒 |
| t3 | 头盔,球 | 头盔,球 |
| t4 | 球棒,防护板,头盔 | 头盔,防护板,球棒 |
要构建 FP 树,让我们从 FP 树的第一个分支开始。FP 树以Null作为根开始。为了构建树,我们可以用一个节点表示每个项,如下图所示(这里显示了 t[1]的树表示)。请注意,每个节点的标签都是项的名称,冒号后面附加了其频率。还要注意pads项的频率为 1:
使用相同的模式,让我们绘制所有四个交易,得到完整的 FP 树。FP 树有四个叶节点,每个节点代表与四个交易相关的项集。请注意,我们需要计算每个项的频率,并在多次使用时增加它-例如,将 t[2]添加到 FP 树时,头盔 的频率增加到了两次。类似地,当添加 t[4]时,它再次增加到了三次。结果树如下图所示:
请注意,前面图中生成的 FP 树是有序树。
挖掘频繁模式
FP-growth 树的第二阶段涉及从 FP 树中挖掘频繁模式。通过创建一个有序树,意图是创建一个高效的数据结构,可以轻松导航以搜索频繁模式。
我们从叶节点(即末端节点)开始向上移动-例如,让我们从叶节点项之一 球棒 开始。然后我们需要计算 球棒 的条件模式基。通过指定从叶节点项到顶部的所有路径来计算条件模式基。球棒 的条件模式基如下:
| 球门: 1 | 护腕: 1 | 头盔: 1 |
|---|---|---|
| 护腕: 1 | 头盔: 1 |
球棒 的 频繁模式 如下:
{球门, 护腕, 头盔} : 球棒
{护腕,头盔} : 球棒
使用 FP-growth 的代码
让我们看看如何使用 Python 中的 FP-growth 算法生成关联规则。为此,我们将使用 pyfpgrowth 软件包。首先,如果我们以前从未使用过 pyfpgrowth,让我们首先安装它:
!pip install pyfpgrowth
然后,让我们导入实现此算法所需的软件包:
import pandas as pd
import numpy as np
import pyfpgrowth as fp
现在我们将创建以 transactionSet 形式的输入数据:
dict1 = {
'id':[0,1,2,3],
'items':[["wickets","pads"],
["bat","wickets","pads","helmet"],
["helmet","pad"],
["bat","pads","helmet"]]
}
transactionSet = pd.DataFrame(dict1)
一旦生成了输入数据,我们将生成基于我们传递给 find_frequent_patterns() 的参数的模式。请注意,传递给此函数的第二个参数是最小支持度,在本例中为 1:
patterns = fp.find_frequent_patterns(transactionSet['items'],1)
模式已生成。现在让我们打印模式。模式列出了项的组合及其支持:
现在让我们生成规则:
每个规则都有左侧和右侧,由冒号(:)分隔。它还为我们提供了输入数据集中每个规则的支持。
实际应用-将相似的推文进行聚类
无监督机器学习算法也可以实时应用于将相似的推文进行聚类。它们将执行以下操作:
-
步骤 1- 主题建模: 从给定的一组推文中发现各种主题
-
步骤 2- 聚类: 将每个推文与发现的主题之一关联起来
这种无监督学习的应用如下图所示:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/8a9a0326-d16f-4c14-9707-a123d24850bb.png请注意,此示例需要实时处理输入数据。
让我们逐一看看这些步骤。
主题建模
主题建模是发现一组文档中的概念的过程,这些概念可以用来区分它们。在推文的背景下,这是关于找出一组推文可以被分成哪些最合适的主题。潜在狄利克雷分配是一种用于主题建模的流行算法。因为每条推文都是一个短的 144 个字符的文档,通常涉及一个非常特定的主题,我们可以为主题建模目的编写一个更简单的算法。该算法描述如下:
-
对推文进行标记化处理。
-
预处理数据。删除停用词、数字、符号并进行词干处理
-
为推文创建一个术语-文档矩阵(TDM)。选择在唯一推文中出现最频繁的前 200 个词。
-
选择直接或间接代表概念或主题的前 10 个单词。例如时尚、纽约、编程、事故。这 10 个单词现在是我们成功发现的主题,并将成为 tweets 的聚类中心。
让我们继续下一步,即聚类
聚类
一旦我们发现了主题,我们将选择它们作为聚类的中心。然后我们可以运行 k-means 聚类算法,将每个 tweet 分配到其中一个聚类中心。
因此,这是一个实际的例子,说明一组 tweets 如何被聚类成发现的主题。
异常检测算法
异常 的词典定义是与众不同、异常、奇特或不容易分类的东西。它是偏离常规规则的。在数据科学的背景下,异常是偏离预期模式很多的数据点。寻找这样的数据点的技术被称为异常检测技术。
现在让我们看看异常检测算法的一些应用:
-
信用卡欺诈
-
在 磁共振成像(MRI) 扫描中发现恶性肿瘤
-
集群中的故障预防
-
考试中的冒名顶替
-
高速公路上的事故
在接下来的章节中,我们将看到各种异常检测技术。
使用聚类
诸如 k-means 的聚类算法可以用来将相似的数据点分组在一起。可以定义一个阈值,任何超出该阈值的点都可以被分类为异常。这种方法的问题在于,由于异常数据点的存在,k-means 聚类创建的分组本身可能会存在偏差,并可能影响方法的实用性和准确性。
使用基于密度的异常检测
基于密度的方法试图找到密集的邻域。k-最近邻(KNN)算法可以用于此目的。远离发现的密集邻域的异常被标记为异常。
使用支持向量机
支持向量机(SVM)算法可以用来学习数据点的边界。任何超出这些发现的边界的点都被识别为异常。
总结
在本章中,我们看了各种无监督的机器学习技术。我们看了尝试减少我们试图解决的问题的维度的情况,以及不同的方法。我们还研究了无监督机器学习技术在哪些情况下非常有帮助,包括市场篮分析和异常检测。
在下一章中,我们将看看各种监督学习技术。我们将从线性回归开始,然后我们将看看更复杂的监督机器学习技术,如基于决策树的算法、SVM 和 XGBoast。我们还将研究朴素贝叶斯算法,它最适合于非结构化的文本数据。
第七章:传统监督学习算法
在本章中,我们将重点介绍监督式机器学习算法,这是现代算法中最重要的类型之一。监督式机器学习算法的显著特征是使用带标签的数据来训练模型。在本书中,监督式机器学习算法分为两章。在本章中,我们将介绍所有传统的监督式机器学习算法,不包括神经网络。下一章将全面介绍使用神经网络实现监督式机器学习算法。事实上,在这一领域有如此多的持续发展,神经网络是一个值得在本书中单独章节讨论的综合性主题。
因此,这一章是关于监督式机器学习算法的两个部分中的第一部分。首先,我们将介绍监督式机器学习的基本概念。接下来,我们将介绍两种监督式机器模型——分类器和回归器。为了展示分类器的能力,我们将首先提出一个真实世界的问题作为挑战。然后,我们将介绍六种不同的分类算法,用于解决这个问题。然后,我们将专注于回归算法,首先提出一个类似的问题,以便为回归器解决问题。接下来,我们将介绍三种回归算法,并使用它们来解决问题。最后,我们将比较结果,以帮助我们总结本章介绍的概念。
本章的总体目标是让您了解不同类型的监督式机器学习技术,并了解对于某些类别的问题,最佳的监督式机器学习技术是什么。
本章讨论了以下概念:
-
理解监督式机器学习
-
理解分类算法
-
评估分类器性能的方法
-
理解回归算法
-
评估回归算法性能的方法
让我们从理解监督式机器学习背后的基本概念开始。
理解监督式机器学习
机器学习专注于使用数据驱动的方法来创建可以帮助我们做出决策的自主系统,无论是否有人类监督。为了创建这些自主系统,机器学习使用一组算法和方法来发现和制定数据中可重复的模式。在机器学习中最流行和强大的方法之一是监督式机器学习方法。在监督式机器学习中,算法被给定一组输入,称为特征,以及它们对应的输出,称为目标 变量。使用给定的数据集,监督式机器学习算法用于训练一个捕捉特征和目标变量之间复杂关系的模型,该关系由数学公式表示。这个训练好的模型是用于预测的基本工具。
通过训练模型,通过生成未知特征集的目标变量来进行预测。
在监督学习中从现有数据中学习的能力类似于人脑从经验中学习的能力。监督学习中的这种学习能力使用了人脑的一个属性,是将决策能力和智能引入机器的基本途径。
让我们考虑一个例子,我们想要使用监督式机器学习技术训练一个模型,可以将一组电子邮件分类为合法邮件(称为合法)和不需要的邮件(称为垃圾邮件)。首先,为了开始,我们需要过去的例子,这样机器才能学习应该将什么样的电子邮件内容分类为垃圾邮件。这种基于内容的文本数据学习任务是一个复杂的过程,可以通过监督式机器学习算法之一来实现。在这个例子中,可以用来训练模型的一些监督式机器学习算法包括决策树和朴素贝叶斯分类器,我们将在本章后面讨论。
制定监督式机器学习
在深入研究监督式机器学习算法的细节之前,让我们定义一些基本的监督式机器学习术语:
| 术语 | 解释 |
|---|---|
| 目标变量 | 目标变量是我们希望模型预测的变量。在监督式机器学习模型中只能有一个目标变量。 |
| 标签 | 如果我们想要预测的目标变量是一个类别变量,那么它被称为标签。 |
| 特征 | 用于预测标签的一组输入变量称为特征。 |
| 特征工程 | 将特征转换为所选监督式机器学习算法准备的过程称为特征工程。 |
| 特征向量 | 在将输入提供给监督式机器学习算法之前,所有特征都被组合在一个称为特征向量的数据结构中。 |
| 历史数据 | 用于制定目标变量和特征之间关系的过去数据称为历史数据。历史数据带有示例。 |
| 训练/测试数据 | 历史数据与示例被分成两部分——一个更大的数据集称为训练数据,一个较小的数据集称为测试数据。 |
| 模型 | 目标变量和特征之间关系的最佳捕捉模式的数学表达。 |
| 训练 | 使用训练数据创建模型。 |
| 测试 | 使用测试数据评估训练模型的质量。 |
| 预测 | 使用模型预测目标变量。 |
经过训练的监督式机器学习模型能够通过估计特征来预测目标变量。
让我们介绍一下本章中将使用的符号,讨论机器学习技术:
| 变量 | 含义 |
|---|---|
| y | 实际标签 |
| ý | 预测标签 |
| d | 总示例数量 |
| b | 训练示例的数量 |
| c | 测试示例的数量 |
现在,让我们看看一些这些术语如何在实际中被制定。
正如我们讨论的,特征向量被定义为一个包含所有特征的数据结构。
如果特征的数量是n,训练示例的数量是b,那么X_train表示训练特征向量。每个示例都是特征向量中的一行。
对于训练数据集,特征向量由X_train表示。如果训练数据集中有b个示例,那么X_train将有b行。如果训练数据集中有n个变量,那么它将有n列。因此,训练数据集将具有n x b的维度,如下图所示:
现在,让我们假设有b个训练示例和c个测试示例。一个特定的训练示例由(X, y)表示。
我们使用上标来指示训练集中的每个训练示例。
因此,我们的标记数据集由 D = {X((1)),y((1))), (X((2)),y((2))), … , (X((d)),y((d)))}表示。
我们将其分为两部分——D[train]和 D[test]。
因此,我们的训练集可以用 D[train] = {X((1)),y((1))), (X((2)),y((2))), … , (X((b)),y((b)))}来表示。
训练模型的目标是对于训练集中的任何第 i 个示例,目标值的预测值应尽可能接近示例中的实际值。换句话说,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/191e0803-78b6-4df4-b1a4-54ac88b95d3f.png。
因此,我们的测试集可以用 D[test] = {X((1)),y((1))), (X((2)),y((2))), … , (X(©),y(©))}来表示。
目标变量的值由向量Y表示:
Y = {y^((1)), y^((2)), …, y^((m))}
理解启用条件
监督式机器学习是基于算法使用示例来训练模型的能力。监督式机器学习算法需要满足一定的启用条件才能执行。这些启用条件如下:
-
足够的示例:监督式机器学习算法需要足够的示例来训练模型。
-
历史数据中的模式:用于训练模型的示例需要具有其中的模式。我们感兴趣事件的发生可能性应取决于模式、趋势和事件的组合。如果没有这些,我们处理的是无法用于训练模型的随机数据。
-
有效的假设:当我们使用示例训练监督式机器学习模型时,我们期望适用于示例的假设在未来也是有效的。让我们看一个实际的例子。如果我们想要为政府训练一个可以预测学生是否会获得签证的机器学习模型,那么理解是在模型用于预测时,法律和政策不会发生变化。如果在训练模型后实施了新的政策或法律,可能需要重新训练模型以纳入这些新信息。
区分分类器和回归器
在机器学习模型中,目标变量可以是类别变量或连续变量。目标变量的类型决定了我们拥有的监督式机器学习模型的类型。基本上,我们有两种类型的监督式机器学习模型:
-
分类器:如果目标变量是类别变量,则机器学习模型称为分类器。分类器可用于回答以下类型的业务问题:
-
这种异常组织生长是否是恶性肿瘤?
-
根据当前的天气条件,明天会下雨吗?
-
基于特定申请人的资料,他们的抵押贷款申请是否应该被批准?
-
回归器:如果目标变量是连续变量,我们训练一个回归器。回归器可用于回答以下类型的业务问题:
-
根据当前的天气条件,明天会下多少雨?
-
具有给定特征的特定房屋的价格将是多少?
让我们更详细地看看分类器和回归器。
理解分类算法
在监督式机器学习中,如果目标变量是类别变量,则模型被归类为分类器:
-
目标变量称为标签。
-
历史数据称为标记数据。
-
需要预测标签的生产数据称为未标记数据。
使用训练模型准确标记未标记数据的能力是分类算法的真正力量。分类器预测未标记数据的标签以回答特定的业务问题。
在我们介绍分类算法的细节之前,让我们首先提出一个业务问题,作为分类器的挑战。然后我们将使用六种不同的算法来回答相同的挑战,这将帮助我们比较它们的方法、途径和性能。
提出分类器挑战
我们将首先提出一个常见的问题,我们将使用它作为测试六种不同分类算法的挑战。这个常见的问题在本章中被称为分类器挑战。使用所有六种分类器来解决同一个问题将帮助我们以两种方式:
-
所有输入变量都需要被处理和组装成一个复杂的数据结构,称为特征向量。使用相同的特征向量可以帮助我们避免为所有六个算法重复数据准备。
-
我们可以通过使用相同的特征向量作为输入来比较各种算法的性能。
分类器挑战是关于预测一个人购买的可能性。在零售行业,可以帮助最大化销售的一件事是更好地了解客户的行为。这可以通过分析历史数据中发现的模式来实现。让我们先阐述问题。
问题陈述
根据历史数据,我们能否训练一个二元分类器,可以预测特定用户最终是否会购买产品?
首先,让我们探索可用于解决这个问题的历史标记数据集:
x € ℜ^b, y € {0,1}
对于特定示例,当y = 1 时,我们称之为正类,当y = 0 时,我们称之为负类。
尽管正类和负类的级别可以任意选择,但定义正类为感兴趣的事件是一个好的做法。如果我们试图为银行标记欺诈交易,那么正类(即y = 1)应该是欺诈交易,而不是相反。
现在,让我们来看一下以下内容:
-
实际标签,用y表示
-
预测的标签,用*y`*表示
请注意,对于我们的分类器挑战,示例中找到的标签的实际值由y表示。如果在我们的示例中,有人购买了一个物品,我们说y = 1。预测值由y`表示。输入特征向量x的维度为 4。我们想确定用户在给定特定输入时购买的概率是多少。
因此,我们希望确定在给定特征向量x的特定值时y = 1 的概率。从数学上讲,我们可以表示如下:
现在,让我们看看如何处理和组装特征向量x中的不同输入变量。在下一节中,将更详细地讨论使用处理管道组装x的不同部分的方法。
使用数据处理管道进行特征工程
为了选择一个特定的机器学习算法的数据准备被称为特征工程,它是机器学习生命周期的一个关键部分。特征工程在不同的阶段或阶段进行。用于处理数据的多阶段处理代码被统称为数据管道。在可能的情况下使用标准处理步骤制作数据管道,使其可重用并减少训练模型所需的工作量。通过使用更多经过测试的软件模块,代码的质量也得到了提高。
让我们为分类器挑战设计一个可重用的处理管道。如前所述,我们将准备数据一次,然后将其用于所有分类器。
导入数据
这个问题的历史数据存储在一个名为dataset的文件中,格式为.csv。我们将使用 pandas 的pd.read_csv函数将数据导入为数据框:
dataset = pd.read_csv('Social_Network_Ads.csv')
特征选择
选择与我们想要解决的问题相关的特征的过程称为特征选择。这是特征工程的一个重要部分。
一旦文件被导入,我们删除User ID列,该列用于识别一个人,并且在训练模型时应该被排除:
dataset = dataset.drop(columns=['User ID'])
现在让我们预览数据集:
dataset.head(5)
数据集如下:
现在,让我们看看如何进一步处理输入数据集。
独热编码
许多机器学习算法要求所有特征都是连续变量。这意味着如果一些特征是类别变量,我们需要找到一种策略将它们转换为连续变量。独热编码是执行这种转换的最有效方式之一。对于这个特定的问题,我们唯一的类别变量是Gender。让我们使用独热编码将其转换为连续变量:
enc = sklearn.preprocessing.OneHotEncoder()
enc.fit(dataset.iloc[:,[0]])
onehotlabels = enc.transform(dataset.iloc[:,[0]]).toarray()
genders = pd.DataFrame({'Female': onehotlabels[:, 0], 'Male': onehotlabels[:, 1]})
result = pd.concat([genders,dataset.iloc[:,1:]], axis=1, sort=False)
result.head(5)
一旦转换完成,让我们再次查看数据集:
请注意,为了将变量从类别变量转换为连续变量,独热编码已将Gender转换为两个单独的列——Male和Female。
指定特征和标签
让我们指定特征和标签。我们将使用y来代表标签,X代表特征集:
y=result['Purchased']
X=result.drop(columns=['Purchased'])
X代表特征向量,包含我们需要用来训练模型的所有输入变量。
将数据集分为测试和训练部分
现在,让我们使用sklearn.model_selection import train_test_split将训练数据集分为 25%的测试部分和 75%的训练部分:
#from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0)
这已经创建了以下四个数据结构:
-
X_train:包含训练数据特征的数据结构 -
X_test:包含训练测试特征的数据结构 -
y_train:包含训练数据集中标签值的向量 -
y_test:包含测试数据集中标签值的向量
缩放特征
对于许多机器学习算法,将变量从0到1进行缩放是一个好的做法。这也被称为特征归一化。让我们应用缩放转换来实现这一点:
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
在我们缩放数据之后,它准备好作为输入用于我们将在后续部分中介绍的不同分类器。
评估分类器
模型训练完成后,我们需要评估其性能。为此,我们将使用以下过程:
-
我们将标签数据集分为两部分——训练部分和测试部分。我们将使用测试部分来评估训练好的模型。
-
我们将使用测试部分的特征来为每一行生成标签。这是我们的预测标签集。
-
我们将比较预测标签集与实际标签以评估模型。
除非我们试图解决的问题非常琐碎,否则在评估模型时会有一些错误分类。我们如何解释这些错误分类以确定模型的质量取决于我们选择使用的性能指标。
一旦我们有了实际标签集和预测标签集,就可以使用一系列性能指标来评估模型。用于量化模型的最佳指标将取决于我们想要解决的业务问题的要求,以及训练数据集的特征。
混淆矩阵
混淆矩阵用于总结对分类器的评估结果。二元分类器的混淆矩阵如下所示:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/ca9d79e4-5e30-4bf9-b81f-d0aee047b206.png如果我们正在训练的分类器的标签有两个级别,则称为二元分类器。监督机器学习的第一个关键用例,特别是二元分类器,是在第一次世界大战期间用于区分飞机和飞行鸟。
分类可以分为以下四类:
-
真正例(TP):正确分类的正分类
-
真负例(TN):正确分类的负分类
-
假正例(FP):实际上是负分类的正分类
-
假阴性(FN):实际上是积极的负面分类
让我们看看如何使用这四个类别来创建各种性能指标。
性能指标
性能指标用于量化训练模型的性能。基于此,让我们定义以下四个指标:
准确率是所有预测中正确分类的比例。在计算准确率时,我们不区分 TP 和 TN。通过准确率评估模型是直接的,但在某些情况下,它不起作用。
让我们看看我们需要更多的东西来量化模型的性能的情况。其中之一是当我们使用模型来预测罕见事件时,比如以下的例子:
-
一个用于预测银行交易数据库中欺诈交易的模型
-
一个用于预测飞机发动机零部件机械故障可能性的模型
在这两个例子中,我们试图预测罕见事件。在这种情况下,比准确率更重要的是召回率和精度。让我们逐个来看:
-
召回率:这计算了命中率。在前面的例子中,它是模型成功标记的欺诈文件占所有欺诈文件的比例。如果在我们的测试数据集中有 100 万笔交易,其中有 100 笔被确认为欺诈交易,模型能够识别出 78 笔。在这种情况下,召回率值将是 78/100。
-
精度:精度衡量了模型标记的交易中实际上是坏的交易有多少。我们不是专注于模型未能标记的坏交易,而是想确定模型标记的坏交易有多精确。
请注意,F1 分数将召回率和精度结合在一起。如果一个模型的精度和召回率都是完美的,那么它的 F1 分数将是完美的。高 F1 分数意味着我们训练了一个高质量的模型,具有高召回率和精度。
理解过拟合
如果一个机器学习模型在开发环境中表现出色,但在生产环境中明显下降,我们说这个模型是过拟合的。这意味着训练模型过于密切地遵循训练数据集。这表明模型创建的规则中有太多细节。模型方差和偏差之间的权衡最能捕捉到这个概念。让我们逐个来看这些概念。
偏差
任何机器学习模型都是基于某些假设进行训练的。一般来说,这些假设是对一些真实世界现象的简化近似。这些假设简化了特征和特征特性之间的实际关系,并使模型更容易训练。更多的假设意味着更多的偏差。因此,在训练模型时,更简化的假设=高偏差,更符合实际现象的现实假设=低偏差。
在线性回归中,忽略了特征的非线性,并将它们近似为线性变量。因此,线性回归模型天生容易表现出高偏差。
方差
方差量化了模型在使用不同数据集训练时对目标变量的估计准确性。它量化了我们的模型的数学公式是否是底层模式的良好概括。
基于特定情景和情况的特定过拟合规则=高方差,而基于广泛情景和情况的泛化规则=低方差。
我们在机器学习中的目标是训练表现出低偏差和低方差的模型。实现这一目标并不总是容易的,通常会让数据科学家夜不能寐。
偏差-方差权衡
在训练特定的机器学习模型时,很难确定训练模型所包含的规则的正确泛化级别。为了找到正确的泛化级别而进行的挣扎被称为偏差-方差权衡。
请注意,更简化的假设=更泛化=低方差=高方差。
偏差和方差之间的权衡是由算法的选择、数据的特征和各种超参数决定的。根据您尝试解决的具体问题的要求,重要的是在偏差和方差之间取得正确的折衷。
指定分类器的阶段
一旦标记的数据准备好,分类器的开发包括训练、评估和部署。在以下图表中,CRISP-DM(数据挖掘的跨行业标准流程)生命周期展示了实施分类器的这三个阶段(CRISP-DM 生命周期在第五章*,图形算法中有更详细的解释)
在实施分类器的前两个阶段——测试和训练阶段,我们使用标记的数据。标记的数据被分成两个分区——一个更大的分区称为训练数据,一个更小的分区称为测试数据。使用随机抽样技术将输入的标记数据分成训练和测试分区,以确保两个分区都包含一致的模式。请注意,如前图所示,首先是训练阶段,使用训练数据来训练模型。训练阶段结束后,使用测试数据评估训练模型。不同的性能指标用于量化训练模型的性能。评估模型后,我们有模型部署阶段,其中训练好的模型被部署并用于推理,通过标记未标记的数据解决现实世界的问题。
现在,让我们看一些分类算法。
我们将在接下来的部分中看到以下分类算法:
-
决策树算法
-
XGBoost 算法
-
随机森林算法
-
逻辑回归算法
-
支持向量机(SVM)算法
-
朴素贝叶斯算法
让我们从决策树算法开始。
决策树分类算法
决策树基于递归分区方法(分而治之),生成一组规则,可用于预测标签。它从根节点开始,分成多个分支。内部节点表示对某个属性的测试,测试的结果由分支到下一级表示。决策树以包含决策的叶节点结束。当分区不再改善结果时,过程停止。
理解决策树分类算法
决策树分类的显著特点是生成可解释的层次规则,用于在运行时预测标签。该算法具有递归性质。创建这些规则层次涉及以下步骤:
-
找到最重要的特征:在所有特征中,算法确定了最能区分训练数据集中数据点的特征。计算基于信息增益或基尼不纯度等指标。
-
分叉:使用最重要的特征,算法创建一个标准,用于将训练数据集分成两个分支:
-
通过满足标准的数据点
-
未通过标准的数据点
-
检查叶节点:如果任何结果分支大多包含一个类的标签,则该分支被确定为最终分支,形成一个叶节点。
-
检查停止条件并重复:如果未满足提供的停止条件,则算法将返回到步骤 1进行下一次迭代。否则,模型被标记为已训练,并且结果决策树的每个最低级节点都被标记为叶节点。停止条件可以简单地定义为迭代次数,或者可以使用默认的停止条件,即一旦每个叶节点达到一定的同质性水平,算法就会停止。
决策树算法可以用以下图解释:
在上图中,根节点包含一堆圆圈和十字。该算法创建了一个标准,试图将圆圈与十字分开。在每个级别,决策树创建数据的分区,预期从第 1 级开始越来越同质。完美的分类器只包含只包含圆圈或十字的叶节点。由于训练数据集固有的随机性,训练完美的分类器通常很困难。
使用决策树分类算法进行分类器挑战
现在,让我们使用决策树分类算法来解决我们之前定义的常见问题,预测客户最终是否购买产品:
- 首先,让我们实例化决策树分类算法,并使用我们为分类器准备的训练部分数据来训练模型:
classifier = sklearn.tree.DecisionTreeClassifier(criterion = 'entropy', random_state = 100, max_depth=2)
classifier.fit(X_train, y_train)
- 现在,让我们使用我们训练好的模型来预测我们标记数据的测试部分的标签。让我们生成一个可以总结我们训练好的模型性能的混淆矩阵:
import sklearn.metrics as metrics
y_pred = classifier.predict(X_test)
cm = metrics.confusion_matrix(y_test, y_pred)
cm
这给出了以下输出:
- 现在,让我们通过使用决策树分类算法来计算所创建分类器的
准确率、召回率和精确度值:
accuracy= metrics.accuracy_score(y_test,y_pred)
recall = metrics.recall_score(y_test,y_pred)
precision = metrics.precision_score(y_test,y_pred)
print(accuracy,recall,precision)
- 运行上述代码将产生以下输出:
性能指标帮助我们比较不同的训练建模技术。
决策树分类器的优势和劣势
在本节中,让我们看看使用决策树分类算法的优势和劣势。
优势
以下是决策树分类器的优势:
-
使用决策树算法创建的模型的规则可被人类解释。这样的模型被称为白盒模型。白盒模型是在需要追踪决策的细节和原因时的必要条件。这种透明性在我们想要防止偏见和保护脆弱社区的应用中至关重要。例如,在政府和保险行业的关键用例中,通常需要白盒模型。
-
决策树分类器旨在从离散问题空间中提取信息。这意味着大多数特征都是类别变量,因此使用决策树来训练模型是一个不错的选择。
劣势
以下是决策树分类器的弱点:
-
如果决策树分类器生成的树太深,规则会捕捉太多细节,导致过拟合的模型。在使用决策树算法时,我们需要意识到决策树容易过拟合,因此我们需要及时修剪树以防止这种情况。
-
决策树分类器的一个弱点是它们无法捕捉规则中的非线性关系。
用例
在本节中,让我们看看决策树算法用于哪些用例。
分类记录
决策树分类器可用于对数据点进行分类,例如以下示例:
-
抵押贷款申请:训练一个二元分类器,以确定申请人是否可能违约。
-
客户细分:将客户分类为高价值、中价值和低价值客户,以便为每个类别定制营销策略。
-
医学诊断:训练一个分类器,可以对良性或恶性生长进行分类。
-
治疗效果分析:训练一个分类器,可以标记对特定治疗产生积极反应的患者。
特征选择
决策树分类算法选择一小部分特征来创建规则。当特征数量很大时,可以使用该特征选择来选择另一个机器学习算法的特征。
理解集成方法
集成是一种机器学习方法,通过使用不同的参数创建多个略有不同的模型,然后将它们组合成一个聚合模型。为了创建有效的集成,我们需要找到我们的聚合标准,以生成最终模型。让我们看看一些集成算法。
使用 XGBoost 算法实现梯度提升
XGBoost 于 2014 年创建,基于梯度提升原理。它已成为最受欢迎的集成分类算法之一。它生成一堆相互关联的树,并使用梯度下降来最小化残差误差。这使其非常适合分布式基础设施,如 Apache Spark,或云计算,如 Google Cloud 或亚马逊网络服务(AWS)。
现在让我们看看如何使用 XGBoost 算法实现梯度提升:
- 首先,我们将实例化 XGBClassfier 分类器,并使用数据的训练部分来训练模型:
- 然后,我们将基于新训练的模型生成预测:
y_pred = classifier.predict(X_test)
cm = metrics.confusion_matrix(y_test, y_pred)
cm
产生以下输出:
- 最后,我们将量化模型的性能:
accuracy= metrics.accuracy_score(y_test,y_pred)
recall = metrics.recall_score(y_test,y_pred)
precision = metrics.precision_score(y_test,y_pred)
print(accuracy,recall,precision)
这给我们以下输出:
接下来,让我们看看随机森林算法。
使用随机森林算法
随机森林是一种集成方法,通过组合多个决策树来减少偏差和方差。
训练随机森林算法
在训练中,该算法从训练数据中获取N个样本,并创建我们整体数据的m个子集。这些子集是通过随机选择输入数据的一些行和列来创建的。该算法构建m个独立的决策树。这些分类树由C[1]到C[m]表示。
使用随机森林进行预测
模型训练完成后,可以用于标记新数据。每个个体树生成一个标签。最终预测由这些个体预测的投票决定,如下所示:
请注意,在上图中,训练了m棵树,表示为C[1]到C[m]。即树 = {C[1],…,C[m]}
每棵树生成一个由一组表示的预测:
个体预测 = P= {P[1],…, P[m]}
最终预测由P[f]表示。它由个体预测的大多数决定。mode函数可用于找到多数决定(mode是最常重复且处于多数的数字)。个体预测和最终预测如下所示:
P[f] = mode §
区分随机森林算法和集成提升
随机森林算法生成的每棵树都是完全独立的。它不知道集成中其他树的任何细节。这使它与其他技术有所不同,如集成增强。
使用随机森林算法进行分类器挑战
让我们实例化随机森林算法,并使用它来训练我们的模型使用训练数据。
这里有两个关键的超参数:
-
n_estimators -
max_depth
n_estimators超参数控制构建多少个独立的决策树,max_depth超参数控制每个独立决策树可以有多深。
换句话说,决策树可以不断分裂,直到它有一个节点代表训练集中的每个给定示例。通过设置max_depth,我们限制了它可以进行多少级别的分裂。这控制了模型的复杂性,并确定了它与训练数据的拟合程度。如果我们参考以下输出,n_estimators控制了随机森林模型的宽度,max_depth控制了模型的深度:
一旦随机森林模型训练好了,让我们用它进行预测:
y_pred = classifier.predict(X_test)
cm = metrics.confusion_matrix(y_test, y_pred)
cm
它的输出是:
现在,让我们量化我们的模型有多好:
accuracy= metrics.accuracy_score(y_test,y_pred)
recall = metrics.recall_score(y_test,y_pred)
precision = metrics.precision_score(y_test,y_pred)
print(accuracy,recall,precision)
我们将观察以下输出:
接下来,让我们来看看逻辑回归。
逻辑回归
逻辑回归是一种用于二元分类的分类算法。它使用逻辑函数来制定输入特征和目标变量之间的交互。它是用于建模二元因变量的最简单的分类技术之一。
假设
逻辑回归假设以下内容:
-
训练数据集没有缺失值。
-
标签是一个二进制类别变量。
-
标签是有序的,换句话说,是一个具有有序值的分类变量。
-
所有特征或输入变量彼此独立。
建立关系
对于逻辑回归,预测值计算如下:
所以现在:
上述关系可以用图形表示如下:
注意,如果z很大,σ (z)将等于1。如果z非常小或非常负,σ (z)将等于0。因此,逻辑回归的目标是找到W和j的正确值。
逻辑回归是根据用于制定它的函数命名的,称为逻辑或Sigmoid 函数。
损失和成本函数
loss函数定义了我们想要量化训练数据中特定示例的错误的方式。cost函数定义了我们想要最小化整个训练数据集中的错误的方式。因此,loss函数用于训练数据集中的一个示例,cost函数用于量化实际值和预测值的整体偏差。它取决于w和h的选择。
逻辑回归中使用的loss函数如下:
Loss (ý^((i)), y^((i))) = - (y^((i))log ý((i))+(1-y((i)) ) log (1-ý^((i)))
注意当*y^((i)) = 1, Loss(ý^((i)), y^((i))**) = - logý((i))*.最小化损失将导致ý((i))的值很大。作为 Sigmoid 函数,最大值将是1。
如果*y^((i)) = 0, Loss (ý^((i)), y^((i))) = - log (1-ý((i))**)*。最小化损失将导致*ý((i))*尽可能小,即0。
逻辑回归的成本函数如下:
何时使用逻辑回归
逻辑回归在二元分类器方面表现出色。当数据量很大但数据质量不佳时,逻辑回归效果不佳。它可以捕捉不太复杂的关系。虽然它通常不会产生最佳性能,但它确实为起步设定了一个很好的基准。
使用逻辑回归算法进行分类器挑战
在本节中,我们将看到如何使用逻辑回归算法进行分类器挑战:
- 首先,让我们实例化一个逻辑回归模型,并使用训练数据对其进行训练:
from sklearn.linear_model import LogisticRegression
classifier = LogisticRegression(random_state = 0)
classifier.fit(X_train, y_train)
- 让我们预测
test数据的值并创建一个混淆矩阵:
y_pred = classifier.predict(X_test)
cm = metrics.confusion_matrix(y_test, y_pred)
cm
运行上述代码后,我们得到以下输出:
- 现在,让我们看看性能指标:
accuracy= metrics.accuracy_score(y_test,y_pred)
recall = metrics.recall_score(y_test,y_pred)
precision = metrics.precision_score(y_test,y_pred)
print(accuracy,recall,precision)
- 运行上述代码后,我们得到以下输出:
接下来,让我们看看SVM。
SVM 算法
现在,让我们看看 SVM。SVM 是一种找到最大化两个类之间间隔的最优超平面的分类器。在 SVM 中,我们的优化目标是最大化间隔。间隔被定义为分隔超平面(决策边界)与最靠近该超平面的训练样本之间的距离,称为支持向量。因此,让我们从一个只有两个维度X1和X2的非常基本的例子开始。我们希望有一条线将圆圈与十字分开。如下图所示:
我们画了两条线,都完美地将十字与圆圈分开。然而,必须有一个最佳线或决策边界,使我们有最佳机会正确分类大多数额外的例子。一个合理的选择可能是一条均匀分布在这两个类之间的线,为每个类提供一点缓冲,如下所示:
现在,让我们看看如何使用 SVM 来训练我们挑战的分类器。
使用 SVM 算法进行分类器挑战
- 首先,让我们实例化 SVM 分类器,然后使用标记数据的训练部分对其进行训练。
kernel超参数确定应用于输入数据的转换类型,以使其线性可分。
from sklearn.svm import SVC
classifier = SVC(kernel = 'linear', random_state = 0)
classifier.fit(X_train, y_train)
- 训练完成后,让我们生成一些预测并查看混淆矩阵:
y_pred = classifier.predict(X_test)
cm = metrics.confusion_matrix(y_test, y_pred)
cm
- 观察以下输出:
- 现在,让我们来看看各种性能指标:
accuracy= metrics.accuracy_score(y_test,y_pred)
recall = metrics.recall_score(y_test,y_pred)
precision = metrics.precision_score(y_test,y_pred)
print(accuracy,recall,precision)
运行上述代码后,我们得到以下值作为输出:
理解朴素贝叶斯算法
基于概率论,朴素贝叶斯是最简单的分类算法之一。如果使用正确,它可以得出准确的预测。朴素贝叶斯算法之所以被如此命名有两个原因:
-
它基于一个天真的假设,即特征和输入变量之间是独立的。
-
它基于贝叶斯定理。
该算法试图基于先前属性/实例的概率对实例进行分类,假设属性完全独立。
有三种类型的事件:
-
独立事件不会影响另一个事件发生的概率(例如,收到一封电子邮件提供免费参加科技活动的机会和公司进行重新组织)。
-
依赖事件会影响另一个事件发生的概率;也就是说,它们在某种程度上是相关的(例如,你准时参加会议的概率可能会受到航空公司员工罢工或航班不准时的影响)。
-
互斥事件不能同时发生(例如,单次掷骰子得到三和六的概率为 0——这两个结果是互斥的)。
贝叶斯定理
贝叶斯定理用于计算两个独立事件A和B之间的条件概率。事件A和B发生的概率由 P(A)和 P(B)表示。条件概率由 P(B|A)表示,这是事件A发生的条件概率,假设事件B已经发生:
计算概率
朴素贝叶斯基于概率基本原理。单个事件发生的概率(观察概率)是通过将事件发生的次数除以可能导致该事件发生的总进程次数来计算的。例如,呼叫中心每天接到 100 多个支持电话,一个月内有 50 次。您想知道基于以前的响应时间,呼叫在 3 分钟内得到响应的概率。如果呼叫中心在 27 次匹配这个时间记录,那么 100 次呼叫在 3 分钟内得到响应的观察概率如下:
- P(3 分钟内 100 个支持电话)=(27/50)= 0.54(54%)*
根据过去的 50 次记录,100 次呼叫大约有一半的时间可以在 3 分钟内得到响应。
AND 事件的乘法规则
要计算两个或更多事件同时发生的概率,请考虑事件是独立还是相关的。如果它们是独立的,则使用简单的乘法规则:
- P(结果 1 和结果 2)= P(结果 1)* P(结果 2)*
例如,要计算收到免费参加技术活动的电子邮件的概率和工作场所发生重新组织的概率,将使用这个简单的乘法规则。这两个事件是独立的,因为其中一个发生并不影响另一个发生的机会
如果收到技术活动的电子邮件的概率为 31%,并且员工重新组织的概率为 82%,则同时发生的概率如下计算:
P(电子邮件和重新组织)= P(电子邮件)* P(重新组织)=(0.31)*(0.82)= 0.2542(25%)
一般乘法规则
如果两个或更多事件是相关的,则使用一般乘法规则。这个公式实际上在独立和相关事件的情况下都是有效的:
- P(结果 1 和结果 2)= P(结果 1)* P(结果 2 | 结果 1)*
请注意,P(结果 2 | 结果 1)指的是结果 1已经发生的情况下结果 2发生的条件概率。该公式包含了事件之间的依赖关系。如果事件是独立的,那么条件概率是无关紧要的,因为一个结果不会影响另一个发生的机会,P(结果 2 | 结果 1)就是P(结果 2)。请注意,在这种情况下,该公式变成了简单的乘法规则。
OR 事件的加法规则
在计算两个事件中的一个或另一个发生的概率(互斥)时,使用以下简单的加法规则:
- P(结果 1 或结果 2)= P(结果 1)+ P(结果 2)*
例如,掷出 6 或 3 的概率是多少?要回答这个问题,首先注意到两个结果不能同时发生。掷出 6 的概率是(1/6),掷出 3 的概率也是如此:
- P(6 或 3)=(1/6)+(1/6)= 0.33(33%)*
如果事件不是互斥的并且可以同时发生,请使用以下一般加法公式,这在互斥和非互斥的情况下都是有效的:
- P(结果 1 或结果 2)= P(结果 1)+ P(结果 2)P(结果 1 和结果 2)*
使用朴素贝叶斯算法进行分类器挑战
现在,让我们使用朴素贝叶斯算法来解决分类器挑战:
- 首先,我们导入
GaussianNB()函数并用它来训练模型:
from sklearn.naive_bayes import GaussianNB
classifier = GaussianNB()
classifier.fit(X_train, y_train)
- 现在,让我们使用训练好的模型来预测结果。我们将用它来预测我们的测试分区
X_test的标签:
Predicting the Test set results
y_pred = classifier.predict(X_test)
cm = metrics.confusion_matrix(y_test, y_pred)
cm
- 现在,让我们打印混淆矩阵:
- 现在,让我们打印性能矩阵来量化我们训练模型的质量:
accuracy= metrics.accuracy_score(y_test,y_pred)
recall = metrics.recall_score(y_test,y_pred)
precision = metrics.precision_score(y_test,y_pred)
print(accuracy,recall,precision)
这将产生以下输出:
对于分类算法,获胜者是…
让我们看一下我们提出的各种算法的性能指标。这在下表中总结如下:
| 算法 | 准确度 | 召回率 | 精确度 |
|---|---|---|---|
| 决策树 | 0.94 | 0.93 | 0.88 |
| XGBoost | 0.93 | 0.90 | 0.87 |
| 随机森林 | 0.93 | 0.90 | 0.87 |
| 逻辑回归 | 0.91 | 0.81 | 0.89 |
| 支持向量机 | 0.89 | 0.71 | 0.92 |
| 朴素贝叶斯 | 0.92 | 0.81 | 0.92 |
从前面的表中可以看出,决策树分类器在准确性和召回率方面表现最佳。如果我们寻求精确度,那么支持向量机和朴素贝叶斯之间存在平局,因此任何一个都适用于我们。
了解回归算法
监督机器学习模型使用回归算法之一,如果目标变量是连续变量。在这种情况下,机器学习模型被称为回归器。
在本节中,我们将介绍各种可用于训练监督机器学习回归模型的算法,或者简单地说,回归器。在我们深入了解算法的细节之前,让我们首先为这些算法创建一个挑战,以测试它们的性能、能力和有效性。
呈现回归器挑战
与分类算法使用的方法类似,我们将首先提出一个问题,作为所有回归算法的挑战来解决。我们将把这个共同的问题称为回归器挑战。然后,我们将使用三种不同的回归算法来解决这个挑战。使用一个共同的挑战来测试不同的回归算法有两个好处:
-
我们可以准备一次数据,然后在所有三个回归算法上使用准备好的数据。
-
我们可以以有意义的方式比较三种回归算法的性能,因为我们将使用它们来解决同一个问题。
让我们看一下挑战的问题陈述。
回归器挑战的问题陈述
预测不同车辆的里程数在当今是很重要的。高效的车辆对环境有益,也具有成本效益。里程数可以根据发动机功率和车辆特性来估算。让我们为回归器创建一个挑战,训练一个能够根据车辆特性预测车辆的每加仑英里数(MPG)的模型。
让我们看看我们将用来训练回归器的历史数据集。
探索历史数据集
以下是我们拥有的历史数据集数据的特征:
| 名称 | 类型 | 描述 |
|---|---|---|
名称 | 类别 | 标识特定车辆 |
CYLINDERS | 连续 | 气缸数量(4 至 8 之间) |
DISPLACEMENT | 连续 | 发动机排量(立方英寸) |
HORSEPOWER | 连续 | 发动机马力 |
ACCELERATION | 连续 | 从 0 到 60 英里/小时的加速时间(秒) |
这个问题的目标变量是一个连续变量,MPG,它指定了每辆车的英里数。
让我们首先为这个问题设计数据处理管道。
使用数据处理管道进行特征工程
让我们看看如何设计一个可重复使用的处理管道来解决回归器挑战。如前所述,我们将一次准备数据,然后在所有回归算法中使用它。让我们按照以下步骤进行:
- 我们首先导入数据集,如下所示:
dataset = pd.read_csv('auto.csv')
- 现在让我们预览数据集:
dataset.head(5)
数据集将如下所示:
- 现在,让我们继续进行特征选择。让我们删除
NAME列,因为它只是一个用于汽车的标识符。用于识别数据集中行的列对于训练模型是不相关的。让我们删除这一列:
dataset=dataset.drop(columns=['NAME'])
- 让我们转换所有的输入变量并填充所有的空值:
dataset=dataset.drop(columns=['NAME'])
dataset= dataset.apply(pd.to_numeric, errors='coerce')
dataset.fillna(0, inplace=True)
填充提高了数据的质量,并准备好用于训练模型。现在,让我们看最后一步:
- 让我们将数据分成测试和训练分区:
from sklearn.model_selection import train_test_split
#from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0)
这创建了以下四个数据结构:
-
X_train:包含训练数据的特征的数据结构 -
X_test:包含训练测试的特征的数据结构 -
y_train:包含训练数据集中标签的值的向量 -
y_test:包含测试数据集中标签的值的向量
现在,让我们使用准备好的数据在三个不同的回归器上,以便比较它们的性能。
线性回归
在所有监督学习技术中,线性回归算法是最容易理解的。我们首先看一下简单线性回归,然后将概念扩展到多元线性回归。
简单线性回归
在其最简单的形式中,线性回归阐述了单个连续自变量和单个连续自变量之间的关系。回归用于显示因变量(显示在 y 轴上)的变化程度可以归因于解释变量(显示在 x 轴上)的变化程度。它可以表示如下:
这个公式可以解释如下:
-
y 是因变量。
-
X 是自变量。
-
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/4dc02d52-61ac-4dc5-ade3-3868a299cd92.png 是斜率,表示每增加一个 X,线就上升多少。
-
α 是截距,表示 X = 0 时 y 的值。
单个连续因变量和单个连续自变量之间关系的一些例子如下:
-
一个人的体重和他们的卡路里摄入量
-
特定社区房屋价格和面积
-
空气中的湿度和下雨的可能性
对于线性回归,输入(自变量)和目标(因变量)变量都必须是数值型的。最佳关系是通过最小化每个点到通过所有点的线的垂直距离的平方和来找到的。假设预测变量和目标变量之间是线性关系。例如,投入研发的资金越多,销售额就越高。
让我们看一个具体的例子。让我们尝试阐明特定产品的营销支出和销售之间的关系。它们被发现直接相关。营销支出和销售在二维图上绘制,并显示为蓝色的钻石。这种关系最好通过绘制一条直线来近似,如下图所示:
一旦画出线性线,我们就可以看到营销支出和销售之间的数学关系。
评估回归器
我们画的线性线是因变量和自变量之间关系的近似值。即使最佳线也会与实际值有一些偏差,如下所示:
评估线性回归模型性能的一种典型方法是使用均方根误差(RMSE)。这通过数学计算训练模型产生的误差的标准偏差。对于训练数据集中的某个示例,loss 函数计算如下:
损失(ý^((i)), y^((i))) = 1/2(ý^((i)-) y^((i)))²
这导致以下cost函数,最小化训练集中所有示例的损失:
让我们尝试解释 RMSE。如果我们的示例模型的 RMSE 为$50,这意味着大约 68.2%的预测值将在真实值(即α)的$50 范围内。这也意味着 95%的预测值将在实际值的$100(即 2α)范围内。最后,99.7%的预测值将在实际值的$150 范围内。
多元回归
事实上,大多数现实世界的分析都有多个自变量。多元回归是简单线性回归的扩展。关键区别在于额外的预测变量有额外的 beta 系数。在训练模型时,目标是找到最小化线性方程误差的 beta 系数。让我们尝试数学上阐述因变量和一组自变量(特征)之间的关系。
与简单线性方程类似,因变量y被量化为截距项的总和,加上β系数乘以每个i特征的x值:
y = α + β [1] x [1] + β [2] x 2 +…+ β [i] x [i] + ε
误差用ε表示,表明预测并不完美。
β系数允许每个特征对y的值有单独的估计影响,因为y每增加一个单位的x[i],y的变化量为β [i]。此外,截距(α)表示当独立变量都为 0 时y的期望值。
请注意,前述方程中的所有变量都可以用一堆向量表示。目标和预测变量现在是带有行的向量,而回归系数β和误差ε也是向量。
使用线性回归算法进行回归挑战
现在,让我们使用数据集的训练部分来训练模型:
- 让我们从导入线性回归包开始:
from sklearn.linear_model import LinearRegression
- 然后,让我们实例化线性回归模型,并使用训练数据集对其进行训练:
regressor = LinearRegression()
regressor.fit(X_train, y_train)
- 现在,让我们使用数据集的测试部分来预测结果:
y_pred = regressor.predict(X_test)
from sklearn.metrics import mean_squared_error
from math import sqrt
sqrt(mean_squared_error(y_test, y_pred))
- 运行上述代码生成的输出将生成以下内容:
如前一节所讨论的,RMSE 是误差的标准差。它表明 68.2%的预测值将在目标变量值的4.36范围内。
何时使用线性回归?
线性回归用于解决许多现实世界的问题,包括以下内容:
-
销售预测
-
预测最佳产品价格
-
量化事件和响应之间的因果关系,例如临床药物试验、工程安全测试或市场研究
-
识别可用于预测未来行为的模式,给定已知条件,例如预测保险索赔、自然灾害损失、选举结果和犯罪率
线性回归的弱点
线性回归的弱点如下:
-
它只适用于数值特征。
-
分类数据需要进行预处理。
-
它无法很好地处理缺失数据。
-
它对数据做出假设。
回归树算法
回归树算法类似于分类树算法,只是目标变量是连续变量,而不是类别变量。
使用回归树算法进行回归挑战
在本节中,我们将看到如何使用回归树算法进行回归挑战:
- 首先,我们使用回归树算法训练模型:
- 一旦回归树模型训练完成,我们就可以使用训练好的模型来预测值:
y_pred = regressor.predict(X_test)
- 然后,我们计算 RMSE 来量化模型的性能:
from sklearn.metrics import mean_squared_error
from math import sqrt
sqrt(mean_squared_error(y_test, y_pred))
我们得到以下输出:
梯度提升回归算法
现在,让我们来看看梯度提升回归算法。它使用一组决策树来更好地表达数据中的潜在模式。
使用梯度提升回归算法来解决回归问题
在这一部分,我们将看到如何使用梯度提升回归算法来解决回归问题:
- 首先,我们使用梯度提升回归算法来训练模型:
- 一旦梯度回归算法模型被训练,我们就可以用它来预测数值:
y_pred = regressor.predict(X_test)
- 最后,我们计算 RMSE 来量化模型的性能:
from sklearn.metrics import mean_squared_error
from math import sqrt
sqrt(mean_squared_error(y_test, y_pred))
- 运行这个将给我们输出值,如下所示:
对于回归算法,获胜者是…
让我们来看看我们在相同数据和完全相同用例上使用的三种回归算法的表现:
| 算法 | RMSE |
|---|---|
| 线性回归 | 4.36214129677179 |
| 回归树 | 5.2771702288377 |
| 梯度提升回归 | 4.034836373089085 |
从所有回归算法的表现来看,很明显梯度提升回归的表现最好,因为它具有最低的 RMSE。其次是线性回归。对于这个问题,回归树算法的表现最差。
实际例子 - 如何预测天气
让我们看看如何使用本章中开发的概念来预测天气。假设我们想根据一年内针对特定城市收集的数据来预测明天是否会下雨。
用于训练该模型的数据在名为weather.csv的 CSV 文件中:
- 让我们将数据导入为一个 pandas 数据框:
import numpy as np
import pandas as pd
df = pd.read_csv("weather.csv")
- 让我们来看看数据框的列:
- 接下来,让我们来看一下
weather.csv数据的前 13 列的标题:
- 现在,让我们来看一下
weather.csv数据的最后 10 列:
- 让我们用
x来代表输入特征。我们将在特征列表中删除Date字段,因为在预测的情境下它没有用处。我们还将删除RainTomorrow标签:
x = df.drop(['Date','RainTomorrow'],axis=1)
- 让我们用
y来代表标签:
y = df['RainTomorrow']
- 现在,让我们将数据分成
train_test_split:
from sklearn.model_selection import train_test_split
train_x , train_y ,test_x , test_y = train_test_split(x,y , test_size = 0.2,random_state = 2)
- 由于标签是一个二元变量,我们正在训练一个分类器。因此,在这里逻辑回归将是一个不错的选择。首先,让我们实例化逻辑回归模型:
model = LogisticRegression()
- 现在,我们可以使用
train_x和test_x来训练模型:
model.fit(train_x , test_x)
- 一旦模型被训练,让我们用它进行预测:
predict = model.predict(train_y)
- 现在,让我们找出我们训练模型的准确性:
现在,这个二元分类器可以用来预测明天是否会下雨。
摘要
在本章中,我们首先了解了监督式机器学习的基础知识。然后,我们更详细地了解了各种分类算法。接下来,我们研究了评估分类器性能的不同方法,并研究了各种回归算法。我们还研究了用于评估我们研究的算法性能的不同方法。
在下一章中,我们将研究神经网络和深度学习算法。我们将研究训练神经网络所使用的方法,还将研究用于评估和部署神经网络的各种工具和框架。
第八章:神经网络算法
各种因素的结合使得人工神经网络(ANNs)成为当今最重要的机器学习技术之一。这些因素包括解决日益复杂的问题的需求,数据的爆炸以及诸如可用的廉价集群等技术的出现,这些技术提供了设计非常复杂算法所需的计算能力。
事实上,这是一个迅速发展的研究领域,负责实现机器人技术、自然语言处理和自动驾驶汽车等领先技术领域所宣称的大部分重大进展。
观察 ANN 的结构,其基本单元是神经元。ANN 的真正优势在于其能够通过将它们组织成分层架构来利用多个神经元的力量。ANN 通过在不同层中将神经元链接在一起来创建分层架构。信号通过这些层传递,并在每个层中以不同的方式进行处理,直到生成最终所需的输出。正如我们将在本章中看到的,ANN 使用的隐藏层充当抽象层,实现了深度学习,这在实现强大的应用程序中被广泛使用,如亚马逊的 Alexa,谷歌的图像搜索和谷歌相册。
本章首先介绍了典型神经网络的主要概念和组件。然后,它介绍了各种类型的神经网络,并解释了这些神经网络中使用的不同类型的激活函数。接下来,详细讨论了反向传播算法,这是训练神经网络最广泛使用的算法。然后,解释了迁移学习技术,可以用来大大简化和部分自动化模型的训练。最后,通过一个真实世界的应用程序案例,探讨了如何使用深度学习来标记欺诈文件。
本章讨论的主要概念如下:
-
理解人工神经网络
-
ANN 的演变
-
训练神经网络
-
工具和框架
-
迁移学习
-
案例研究:使用深度学习进行欺诈检测
让我们从人工神经网络的基础知识开始。
理解人工神经网络
受人脑神经元工作的启发,神经网络的概念是由 Frank Rosenblatt 在 1957 年提出的。要充分理解其架构,有助于简要了解人脑中神经元的分层结构。(参考以下图表,了解人脑中的神经元是如何连接在一起的。)
在人脑中,树突充当检测信号的传感器。然后,信号传递给轴突,轴突是神经细胞的一种长而细的突出部分。轴突的功能是将这个信号传递给肌肉、腺体和其他神经元。如下图所示,信号通过称为突触的相互连接的组织传递,然后传递给其他神经元。请注意,通过这种有机管道,信号一直传递,直到它到达目标肌肉或腺体,引起所需的动作。信号通常需要七到八毫秒才能通过神经元链传递并到达目标位置:
受到这种自然的信号处理的建筑杰作的启发,Frank Rosenblatt 设计了一种意味着数字信息可以在层中处理以解决复杂数学问题的技术。他最初设计的神经网络非常简单,看起来类似于线性回归模型。这种简单的神经网络没有任何隐藏层,被命名为感知器。以下图表对其进行了说明:
让我们尝试开发这个感知器的数学表示。在前面的图表中,输入信号显示在左侧。这是输入的加权和,因为每个输入*(x[1],x[2]…x[n])都会乘以相应的权重(w[1],w[2]… w[n])*,然后求和:
请注意,这是一个二元分类器,因为这个感知器的最终输出取决于聚合器的输出是真还是假(在图表中显示为∑)。如果聚合器能够从至少一个输入中检测到有效信号,它将产生一个真实的信号。
现在让我们来看看神经网络是如何随着时间的推移而发展的。
人工神经网络的演变
在前面的部分中,我们研究了一个没有任何层的简单神经网络,称为感知器。发现感知器有严重的局限性,并且在 1969 年,马文·明斯基和西摩·帕帕特进行了研究,得出结论感知器无法学习任何复杂的逻辑。
事实上,他们表明即使学习像异或这样简单的逻辑函数也是一种挑战。这导致了对机器学习和神经网络的兴趣下降,开始了一个现在被称为AI 寒冬的时代。世界各地的研究人员不会认真对待人工智能,认为它无法解决任何复杂的问题。
所谓的 AI 寒冬的主要原因之一是当时可用的硬件能力的限制。要么是必要的计算能力不可用,要么是价格昂贵。到了 20 世纪 90 年代末,分布式计算的进步提供了易于获得和负担得起的基础设施,这导致了 AI 寒冬的融化。这种融化重新激发了对人工智能的研究。最终导致了将当前时代变成一个可以称为AI 春天的时代,人们对人工智能和神经网络特别感兴趣。
对于更复杂的问题,研究人员开发了一个称为多层感知器的多层神经网络。多层神经网络有几个不同的层,如下图所示。这些层包括:
-
输入层
-
隐藏层
-
输出层:
深度神经网络是一个具有一个或多个隐藏层的神经网络。深度学习是训练人工神经网络的过程。https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/4ec6b21a-e4bb-4c00-b243-d7b438d0f3d9.png
一个重要的事情要注意的是神经元是这个网络的基本单元,每个层的神经元都连接到下一层的所有神经元。对于复杂的网络,这些互连的数量激增,我们将探索不牺牲太多质量的不同减少这些互连的方法。
首先,让我们尝试阐明我们要解决的问题。
输入是一个特征向量x,维度为n。
我们希望神经网络能够预测值。预测值由ý表示。
从数学上讲,我们想要确定在给定特定输入的情况下,交易是欺诈的概率。换句话说,给定特定的x值,y=1 的概率是多少?从数学上讲,我们可以表示如下:
注意,x是一个*n[x]维向量,其中n[x]*是输入变量的数量。
这个神经网络有四层。输入和输出之间的层是隐藏层。第一个隐藏层中的神经元数量用https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/11fb6e2b-3c01-4cb3-b314-0d3f70d33ea8.png表示。各个节点之间的连接由称为权重的参数相乘。训练神经网络就是找到权重的正确值。
让我们看看如何训练神经网络。
训练神经网络
使用给定数据集构建神经网络的过程称为训练神经网络。让我们来看一下典型神经网络的解剖结构。当我们谈论训练神经网络时,我们谈论计算权重的最佳值。训练是通过使用一组示例(训练数据的形式)进行迭代完成的。训练数据中的示例具有不同输入值组合的输出的预期值。神经网络的训练过程与传统模型的训练方式不同(这些在第七章中讨论过,传统监督学习算法)。
理解神经网络的解剖结构
让我们看看神经网络包括什么:
-
层: 层是神经网络的核心构建模块。每一层都是一个数据处理模块,充当过滤器。它接受一个或多个输入,以某种方式处理它,然后产生一个或多个输出。每当数据通过一层时,它都会经过一个处理阶段,并显示与我们试图回答的业务问题相关的模式。
-
损失函数: 损失函数提供了在学习过程的各个迭代中使用的反馈信号。损失函数提供了单个示例的偏差。
-
成本函数: 成本函数是完整示例集上的损失函数。
-
优化器: 优化器确定损失函数提供的反馈信号将如何被解释。
-
输入数据: 输入数据是用于训练神经网络的数据。它指定目标变量。
-
权重: 权重是通过训练网络计算的。权重大致对应于每个输入的重要性。例如,如果特定输入比其他输入更重要,在训练后,它将被赋予更大的权重值,充当乘数。即使对于该重要输入的弱信号也将从大的权重值(充当乘数)中获得力量。因此,权重最终会根据它们的重要性转换每个输入。
-
激活函数: 值将由不同的权重相乘然后聚合。它们将如何被聚合以及它们的值将如何被解释将由所选择的激活函数的类型确定。
现在让我们来看看神经网络训练的一个非常重要的方面。
在训练神经网络时,我们逐个示例地进行。对于每个示例,我们使用正在训练的模型生成输出。我们计算期望输出和预测输出之间的差异。对于每个单独的示例,这种差异称为损失。在整个训练数据集中,损失被称为成本。随着我们不断训练模型,我们的目标是找到导致最小损失值的权重值。在整个训练过程中,我们不断调整权重的值,直到找到导致最小可能总成本的权重值集。一旦达到最小成本,我们标记模型已经训练完成。
定义梯度下降
训练神经网络模型的目的是找到权重的正确值。我们开始训练神经网络时,权重使用随机或默认值。然后,我们迭代使用优化算法,例如梯度下降,以改变权重,使我们的预测改善。
梯度下降算法的起点是需要通过算法迭代优化的随机权重值。在随后的每次迭代中,算法通过以最小化成本的方式改变权重值来进行。
以下图解释了梯度下降算法的逻辑:
在前面的图中,输入是特征向量X。目标变量的实际值是Y,目标变量的预测值是Y’。我们确定实际值与预测值的偏差。我们更新权重并重复这些步骤,直到成本最小化。
在算法的每次迭代中如何改变权重将取决于以下两个因素:
-
方向: 要走的方向以获得损失函数的最小值
-
学习率: 我们选择的方向中变化应该有多大
下面的图表显示了一个简单的迭代过程:
该图显示了通过改变权重,梯度下降试图找到最小成本。学习率和选择的方向将决定要探索的图表上的下一个点。
选择正确的学习率很重要。如果学习率太小,问题可能需要很长时间才能收敛。如果学习率太高,问题将无法收敛。在前面的图中,代表当前解决方案的点将在图表的两条相反线之间不断振荡。
现在,让我们看看如何最小化梯度。只考虑两个变量,x和y。x和y的梯度计算如下:
为了最小化梯度,可以使用以下方法:
while(gradient!=0):
if (gradient < 0); move right
if (gradient > 0); move left
该算法也可以用于找到神经网络的最优或接近最优的权重值。
请注意,梯度下降的计算是在整个网络中向后进行的。我们首先计算最后一层的梯度,然后是倒数第二层,然后是倒数第二层之前的层,直到达到第一层。这被称为反向传播,由 Hinton、Williams 和 Rumelhart 于 1985 年引入。
接下来,让我们看看激活函数。
激活函数
激活函数规定了特定神经元的输入如何被处理以生成输出。
如下图所示,神经网络中的每个神经元都有一个激活函数,确定输入将如何被处理:
在前面的图中,我们可以看到激活函数生成的结果传递到输出。激活函数设置了如何解释输入值以生成输出的标准。
对于完全相同的输入值,不同的激活函数将产生不同的输出。在使用神经网络解决问题时,了解如何选择正确的激活函数是很重要的。
现在让我们逐个查看这些激活函数。
阈值函数
最简单的激活函数是阈值函数。阈值函数的输出是二进制的:0 或 1。如果任何输入大于 1,它将生成 1 作为输出。这可以在下图中解释:
请注意,一旦检测到输入加权和中有任何生命迹象,输出(y)就变为 1。这使得阈值激活函数非常敏感。它很容易被输入中的最轻微的信号或噪音错误触发。
Sigmoid
Sigmoid 函数可以被认为是阈值函数的改进。在这里,我们可以控制激活函数的灵敏度。
Sigmoid 函数y定义如下:
可以在 Python 中实现如下:
def sigmoidFunction(z):
return 1/ (1+np.exp(-z))
请注意,通过降低激活函数的灵敏度,我们可以减少输入中的故障的影响。请注意,Sigmoid 激活函数的输出仍然是二进制的,即 0 或 1。
修正线性单元(ReLU)
本章介绍的前两个激活函数的输出是二进制的。这意味着它们将取一组输入变量并将它们转换为二进制输出。ReLU 是一个激活函数,它将一组输入变量作为输入,并将它们转换为单一的连续输出。在神经网络中,ReLU 是最流行的激活函数,通常用于隐藏层,我们不希望将连续变量转换为类别变量。
下面的图表总结了 ReLU 激活函数:
请注意,当x≤ 0时,y = 0。这意味着输入中的任何信号为零或小于零都被转换为零输出:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/c36cfe68-1975-4d9b-98f9-1e404b75399e.png for https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/9ab31cd7-0b6a-4412-b32f-72ec6a44227f.pnghttps://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/ecea8529-3f94-4351-84bb-3841d873a580.png for https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/0b063a5e-03ee-44f1-8a19-664c6536e069.png
一旦x大于零,它就是x。
ReLU 函数是神经网络中最常用的激活函数之一。它可以在 Python 中实现如下:
def ReLU(x):
if x<0:
return 0
else:
return x
现在让我们来看看 Leaky ReLU,它是基于 ReLU 的。
Leaky ReLU
在 ReLU 中,x的负值导致y的值为零。这意味着在这个过程中丢失了一些信息,这使得训练周期变得更长,特别是在训练开始时。Leaky ReLU 激活函数解决了这个问题。对于 Leaky ReLu,以下内容适用:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/10f3d67b-45d7-44b6-8455-576d8bae3079.png ; for https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/2fd2b88a-3be6-49d4-ae6b-fbb781c0c34e.pnghttps://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/6aab91fb-9ecf-489a-a7d1-f74144c4dcb0.png forhttps://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/01238af1-5c97-438f-9c4d-6eeb770fc177.png
下面的图表显示了这一点:
这里,ß是一个小于一的参数。
它可以在 Python 中实现如下:
def leakyReLU(x,beta=0.01):
if x<0:
return (beta*x)
else:
return x
有三种指定ß值的方法:
-
我们可以指定一个默认值为ß。
-
我们可以在我们的神经网络中将ß设为一个参数,并让神经网络决定该值(这称为参数化 ReLU)。
-
我们可以将ß设为一个随机值(这称为随机化 ReLU)。
双曲正切(tanh)
tanh 函数类似于 Sigmoid 函数,但它也能给出负信号。下图说明了这一点:
y函数如下:
可以通过以下 Python 代码实现:
def tanh(x):
numerator = 1-np.exp(-2*x)
denominator = 1+np.exp(-2*x)
return numerator/denominator
现在让我们来看看 softmax 函数。
Softmax
有时,我们需要激活函数的输出不止两个级别。Softmax 是一个可以为输出提供不止两个级别的激活函数。它最适用于多类分类问题。假设我们有n个类。我们有输入值。输入值将类映射如下:
x = {x((1)),x((2)),…x^((n))}
Softmax 是基于概率理论的。Softmax 的第e类的输出概率计算如下:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/40-algo-shld-know/img/bb2a0fea-2795-46ca-8749-aafbd462c707.png对于二元分类器,最终层的激活函数将是 Sigmoid,对于多类分类器,它将是 Softmax。
工具和框架
在本节中,我们将详细了解用于实现神经网络的框架和工具。
随着时间的推移,许多不同的框架已经被开发出来来实现神经网络。不同的框架有各自的优势和劣势。在本节中,我们将重点关注具有 TensorFlow 后端的 Keras。
Keras
Keras 是最受欢迎和易于使用的神经网络库之一,用 Python 编写。它考虑到易用性,并提供了实现深度学习的最快方式。Keras 只提供高级模块,并被认为是在模型级别上。
Keras 的后端引擎
Keras 需要一个低级别的深度学习库来执行张量级别的操作。这个低级别的深度学习库称为后端引擎。Keras 的可能后端引擎包括以下内容:
-
TensorFlow (www.tensorflow.org):这是同类框架中最受欢迎的框架,由谷歌开源。
-
Theona (deeplearning.net/software/theano):这是在蒙特利尔大学 MILA 实验室开发的。
-
Microsoft Cognitive Toolkit(CNTK):这是由微软开发的。
这种模块化深度学习技术堆栈的格式如下图所示:
这种模块化的深度学习架构的优势在于,Keras 的后端可以在不重写任何代码的情况下进行更改。例如,如果我们发现对于特定任务,TensorFlow 比 Theona 更好,我们可以简单地将后端更改为 TensorFlow,而无需重写任何代码。
深度学习堆栈的低级层
我们刚刚提到的三种后端引擎都可以在 CPU 和 GPU 上运行,使用堆栈的低级层。对于 CPU,使用了一个名为Eigen的张量操作低级库。对于 GPU,TensorFlow 使用了 NVIDIA 的CUDA 深度神经网络(cuDNN)库。
定义超参数
如第六章中所讨论的无监督机器学习算法,超参数是在学习过程开始之前选择其值的参数。我们从常识值开始,然后尝试稍后优化它们。对于神经网络,重要的超参数包括:
-
激活函数
-
学习率
-
隐藏层的数量
-
每个隐藏层中的神经元数量
让我们看看如何使用 Keras 定义模型。
定义 Keras 模型
定义完整的 Keras 模型涉及三个步骤:
- 定义层。
我们可以用两种可能的方式使用 Keras 构建模型:
- **Sequential API:**这允许我们为一系列层构建模型。它用于相对简单的模型,并且通常是构建模型的常规选择:
请注意,在这里,我们创建了三层 - 前两层具有 ReLU 激活函数,第三层具有 softmax 作为激活函数。
- **Functional API:**这允许我们为层的非循环图形构建模型。使用 Functional API 可以创建更复杂的模型。
请注意,我们可以使用顺序和功能 API 来定义相同的神经网络。从性能的角度来看,使用哪种方法来定义模型并没有任何区别。
- 定义学习过程。
在这一步中,我们定义了三件事:
-
优化器
-
损失函数
-
将量化模型质量的指标:
请注意,我们使用model.compile函数来定义优化器、损失函数和指标。
- 训练模型。
一旦定义了架构,就是训练模型的时候了:
请注意,batch_size和epochs等参数是可配置的参数,使它们成为超参数。
选择顺序或功能模型
顺序模型将 ANN 创建为简单的层堆叠。顺序模型易于理解和实现,但其简单的架构也有一个主要限制。每一层只连接到一个输入和输出张量。这意味着如果我们的模型在任何隐藏层的输入或输出处有多个输入或多个输出,那么我们不能使用顺序模型。在这种情况下,我们将不得不使用功能模型。
理解 TensorFlow
TensorFlow 是处理神经网络的最流行的库之一。在前面的部分中,我们看到了如何将其用作 Keras 的后端引擎。它是一个开源的高性能库,实际上可以用于任何数值计算。如果我们看一下堆栈,我们可以看到我们可以用高级语言(如 Python 或 C++)编写 TensorFlow 代码,然后由 TensorFlow 分布式执行引擎解释。这使得它对开发人员非常有用和受欢迎。
TensorFlow 的工作方式是创建一个有向图(DG)来表示您的计算。连接节点的是边,数学运算的输入和输出。它们也代表数据的数组。
介绍 TensorFlow 的基本概念
让我们简要了解一下 TensorFlow 的概念,比如标量、向量和矩阵。我们知道,在传统数学中,简单的数字,比如三或五,被称为标量。此外,在物理学中,向量是具有大小和方向的东西。在 TensorFlow 中,我们使用向量来表示一维数组。延伸这个概念,二维数组被称为矩阵。对于三维数组,我们使用术语3D 张量。我们使用术语等级来捕捉数据结构的维度。因此,标量是一个等级 0的数据结构,向量是一个等级 1的数据结构,矩阵是一个等级 2的数据结构。这些多维结构被称为张量,并在下图中显示:
在前面的图表中,我们可以看到等级定义了张量的维度。
现在让我们看看另一个参数,shape。shape是一个整数元组,指定每个维度中数组的长度。下图解释了shape的概念:
使用shape和等级,我们可以指定张量的详细信息。
理解张量数学
现在让我们看看使用张量进行不同的数学计算:
- 让我们定义两个标量,并尝试使用 TensorFlow 进行加法和乘法:
- 我们可以将它们相加和相乘,并显示结果:
- 我们还可以通过将两个张量相加来创建一个新的标量张量:
- 我们还可以执行复杂的张量函数:
理解神经网络的类型
神经网络可以有多种构建方式。如果每一层中的每个神经元都连接到另一层中的每个神经元,那么我们称之为密集或全连接神经网络。让我们看看一些其他形式的神经网络。
卷积神经网络
卷积神经网络(CNNs)通常用于分析多媒体数据。为了更多地了解 CNN 如何用于分析基于图像的数据,我们需要掌握以下过程:
-
卷积
-
池化
让我们逐一探索它们。
卷积
卷积的过程通过使用另一个较小的图像(也称为过滤器或核)来处理特定图像中感兴趣的模式。例如,如果我们想要在图像中找到物体的边缘,我们可以使用特定的过滤器对图像进行卷积来得到它们。边缘检测可以帮助我们进行物体检测、物体分类和其他应用。因此,卷积的过程是关于在图像中找到特征和特点。
寻找模式的方法是基于寻找可以在不同数据上重复使用的模式。可重复使用的模式称为过滤器或核。
池化
为了进行机器学习的多媒体数据处理的重要部分是对其进行下采样。这提供了两个好处:
-
它减少了问题的整体维度,大大减少了训练模型所需的时间。
-
通过聚合,我们可以提取多媒体数据中不必要的细节,使其更通用并更具代表性。
下采样的执行如下:
请注意,我们已经用一个像素替换了每个四个像素的块,选择了四个像素中的最高值作为该像素的值。这意味着我们已经按四分之一的比例进行了下采样。由于我们选择了每个块中的最大值,这个过程被称为最大池化。我们也可以选择平均值;在那种情况下,它将是平均池化。
循环神经网络
循环神经网络(RNNs)是一种特殊类型的神经网络,它们基于循环架构。这就是为什么它们被称为循环。需要注意的重要事情是 RNNs 具有记忆。这意味着它们有能力存储最近迭代的信息。它们被用于分析句子结构以预测句子中的下一个单词等领域。
生成对抗网络
生成对抗网络(GANs)是一种生成合成数据的神经网络类型。它们是由 Ian Goodfellow 及其同事于 2014 年创建的。它们可以用来生成从未存在过的人的照片。更重要的是,它们用于生成合成数据以增加训练数据集。
在接下来的部分中,我们将看到什么是迁移学习。
迁移学习
多年来,许多组织、研究团体和开源社区内的个人已经完善了一些使用大量数据进行训练的复杂模型,以供通用用途。在某些情况下,他们已经投入了多年的努力来优化这些模型。一些这些开源模型可以用于以下应用:
-
视频中的物体检测
-
图像中的物体检测
-
音频的转录
-
文本的情感分析
每当我们开始训练一个新的机器学习模型时,我们要问自己的问题是:我们是否可以简单地定制一个经过充分验证的预训练模型,而不是从头开始?换句话说,我们是否可以将现有模型的学习迁移到我们的自定义模型,以便回答我们的业务问题?如果我们能做到这一点,它将提供三个好处:
-
我们的模型训练工作将得到一个快速启动。
-
通过使用经过充分测试和建立的模型,我们的模型整体质量可能会得到提高。
-
如果我们没有足够的数据来解决我们正在处理的问题,使用通过迁移学习的预训练模型可能会有所帮助。
让我们看两个实际例子,这将是有用的:
-
在训练机器人时,我们可以首先使用模拟游戏来训练神经网络模型。在那个模拟中,我们可以创建所有那些在现实世界中很难找到的罕见事件。一旦训练完成,我们可以使用迁移学习来训练模型适用于真实世界。
-
假设我们想要训练一个模型,可以从视频源中分类苹果和 Windows 笔记本电脑。已经有成熟的开源目标检测模型可以准确分类视频源中的各种物体。我们可以使用这些模型作为起点,识别笔记本电脑。一旦我们识别出物体是笔记本电脑,我们可以进一步训练模型区分苹果和 Windows 笔记本电脑。
在下一节中,我们将应用本章涵盖的概念来构建一个欺诈文档分类神经网络。
案例研究-使用深度学习进行欺诈检测
使用机器学习(ML)技术识别欺诈文档是一个活跃且具有挑战性的研究领域。研究人员正在调查神经网络的模式识别能力在多大程度上可以用于这个目的。可以使用原始像素而不是手动属性提取器,用于几种深度学习架构结构。
方法论
本节介绍的技术使用了一种称为Siamese 神经网络的神经网络架构,它具有两个共享相同架构和参数的分支。使用 Siamese 神经网络来标记欺诈文档如下图所示:
当需要验证特定文档的真实性时,我们首先基于其布局和类型对文档进行分类,然后将其与预期的模板和模式进行比较。如果偏离超过一定阈值,它被标记为伪造文档;否则,它被视为真实文档。对于关键用例,我们可以添加一个手动流程,用于边界情况,算法无法确定地将文档分类为真实或伪造。
为了比较文档与其预期模板,我们在 Siamese 架构中使用两个相同的 CNN。CNN 具有学习最佳的平移不变局部特征检测器和可以构建对输入图像的几何失真具有鲁棒性的表示的优势。这非常适合我们的问题,因为我们的目标是通过单个网络传递真实和测试文档,然后比较它们的相似性。为了实现这个目标,我们实施以下步骤。
假设我们想要测试一个文档。对于每类文档,我们执行以下步骤:
-
获取真实文档的存储图像。我们称之为真实文档。测试文档应该看起来像真实文档。
-
真实文档通过神经网络层,创建一个特征向量,这是真实文档模式的数学表示。我们称之为特征向量 1,如前图所示。
-
需要测试的文档称为测试文档。我们通过一个类似于用于创建真实文档特征向量的网络来传递这个文档。测试文档的特征向量称为特征向量 2。
-
我们使用特征向量 1 和特征向量 2 之间的欧氏距离来计算真实文档和测试文档之间的相似度分数。这个相似度分数被称为相似度测量(MOS)。MOS 是 0 到 1 之间的数字。较高的数字代表文档之间的距离较小,文档相似的可能性较大。
-
如果神经网络计算的相似度分数低于预定义的阈值,我们将文档标记为欺诈。
让我们看看如何使用 Python 实现 Siamese 神经网络:
- 首先,让我们导入所需的 Python 包:
import random
import numpy as np
import tensorflow as tf
- 接下来,我们将定义将用于处理 Siamese 网络各个分支的神经网络:
def createTemplate():
return tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.15),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.15),
tf.keras.layers.Dense(64, activation='relu'),
])
请注意,为了减少过拟合,我们还指定了0.15的丢失率。
- 为了实现 Siamese 网络,我们将使用 MNIST 图像。MNIST 图像非常适合测试我们的方法的有效性。我们的方法包括以每个样本包含两个图像和一个二进制相似度标志的方式准备数据。这个标志是它们来自相同类别的指示器。现在让我们实现名为
prepareData的函数,它可以为我们准备数据:
def prepareData(inputs: np.ndarray, labels: np.ndarray):
classesNumbers = 10
digitalIdx = [np.where(labels == i)[0] for i in range(classesNumbers)]
pairs = list()
labels = list()
n = min([len(digitalIdx[d]) for d in range(classesNumbers)]) - 1
for d in range(classesNumbers):
for i in range(n):
z1, z2 = digitalIdx[d][i], digitalIdx[d][i + 1]
pairs += [[inputs[z1], inputs[z2]]]
inc = random.randrange(1, classesNumbers)
dn = (d + inc) % classesNumbers
z1, z2 = digitalIdx[d][i], digitalIdx[dn][i]
pairs += [[inputs[z1], inputs[z2]]]
labels += [1, 0]
return np.array(pairs), np.array(labels, dtype=np.float32)
注意,prepareData()将导致所有数字的样本数量相等。
- 我们现在将准备训练和测试数据集:
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = x_train.astype(np.float32)
x_test = x_test.astype(np.float32)
x_train /= 255
x_test /= 255
input_shape = x_train.shape[1:]
train_pairs, tr_labels = prepareData(x_train, y_train)
test_pairs, test_labels = prepareData(x_test, y_test)
- 现在,让我们创建 Siamese 系统的两个部分:
input_a = tf.keras.layers.Input(shape=input_shape)
enconder1 = base_network(input_a)
input_b = tf.keras.layers.Input(shape=input_shape)
enconder2 = base_network(input_b)
- 现在,我们将实现相似度度量(MOS),它将量化我们想要比较的两个文档之间的距离:
distance = tf.keras.layers.Lambda(
lambda embeddings: tf.keras.backend.abs(embeddings[0] - embeddings[1])) ([enconder1, enconder2])
measureOfSimilarity = tf.keras.layers.Dense(1, activation='sigmoid') (distance)
现在,让我们训练模型。我们将使用 10 个 epochs 来训练这个模型:
请注意,我们使用 10 个 epochs 达到了 97.49%的准确率。增加 epochs 的数量将进一步提高准确度水平。
总结
在本章中,我们首先看了神经网络的细节。我们首先看了神经网络多年来的发展。我们研究了不同类型的神经网络。然后,我们看了神经网络的各种构建模块。我们深入研究了用于训练神经网络的梯度下降算法。我们讨论了各种激活函数,并研究了激活函数在神经网络中的应用。我们还看了迁移学习的概念。最后,我们看了一个实际例子,说明了神经网络如何用于训练可以部署到标记伪造或欺诈文件的机器学习模型。
展望未来,在下一章中,我们将探讨如何将这样的算法用于自然语言处理。我们还将介绍网络嵌入的概念,并将研究循环网络在自然语言处理中的应用。最后,我们还将研究如何实现情感分析。

被折叠的 条评论
为什么被折叠?



