TowardsDataScience-博客中文翻译-2016-2018-一百八十九-

49 阅读1小时+

TowardsDataScience 博客中文翻译 2016~2018(一百八十九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

机器学习基础—第 4 部分—异常检测、推荐系统和扩展

原文:towardsdatascience.com/machine-lea…

Photo by Fahrul Azmi on Unsplash — unsplash.com/photos/vR-N…

在这篇文章中,我重温了 Andre Ng 在 Coursera 上的《神奇的机器学习课程》中的学习材料,并对这些概念做了一个概述。这篇文章的目的不是作为一个教程,而是更新基本思想。

除非另有明确说明,否则所有引用都是指本课程的材料。

目录

异常检测

异常检测针对该范围内其他示例的行为测试一个新示例。这种想法通常用于欺诈检测、机器制造或监控。如果目标是检测某些异常值,它总是有用的。

使用高斯分布算法意味着示例 x 分布有均值μ和方差适马平方。

μ和适马平方的公式为:

计算概率的公式是:

构建算法的步骤如下

  1. 选择可能代表异常示例的特征 x
  2. 计算参数μ和适马
  3. 计算 x 的概率 p
  4. 根据您设定的概率边界ε进行测试

开发一个异常检测系统

当实现该算法时,引入实数评估度量是很重要的。

与往常一样,建议将数据集分为训练集、交叉验证集和测试集(60–20–20)。

建立该系统的步骤如下:

  1. 在训练集上拟合模型 p(x)
  2. 根据交叉验证和测试集的结果概率预测 y
  3. 使用列联表(真阳性、假阳性等)、精确度/召回方法或 F1 分数评估结果
  4. 改变ε的值(如有必要)

监督学习系统的实用技巧和区别

在以下情况下,应使用异常检测系统

  • 有大量的反面例子,但也有少量正面例子
  • 异常本身不能被分类,并且在将来的例子中可能变化
  • 例如,欺诈检测、监控机器等。

如果分类可以很容易地完成,即有大量的正面和负面的例子,未来的例子将是相似的,建议使用监督学习算法。(例如垃圾邮件、癌症分类)

为了分析误差,有必要绘制特征图,看看它们是否表现为高斯分布。如果没有,可以添加常数(如 log(x)),以尽量使其看起来像高斯分布。

使用异常检测系统的基本假设是异常实例少,正常实例多。如果不满足这一点,则应检查错误分类的示例的行为是否允许提出新的特征。

多元高斯分布

在某些情况下,正态高斯分布不足以准确标记异常。多元高斯分布会立即计算 x 的概率模型,而不是单独为每个要素建立概率模型。它使用协方差矩阵,而不是适马平方。

该公式如下所示:

鉴于:

当样本数远大于特征数时,多元高斯模型是值得考虑的。它捕捉特征之间的相关性,但是计算量很大。当很明显什么特征组合可以捕获异常时,建议首先使用原始高斯模型实现这些特征组合。

推荐系统

推荐系统是在现实生活中应用机器学习算法的最常见和最成功的实例之一。

假设你有一个基于内容的推荐系统。首先,一个问题必须被公式化。这可能类似于预测某个用户对某个产品的评价。

给定电影的评级,为了学习某个用户的参数θ,优化算法可以看起来像这样:

  • 参数θ表示某个用户的向量
  • 特征 x 表示电影的向量
  • y 表示某个用户对某部电影的评价
  • n 表示用户的数量

这是为不同用户(θj)总结的具有正则化的平方误差的基本成本函数。

并且使用梯度下降(将学习率α乘以关于优化目标的参数的偏导数)来逐渐最小化结果。注意,k = 0 时的θ0 不应被正则化(如线性回归中所解释的)。

基于协同过滤的特征学习

给定特定电影的每个用户的参数θ,电影的特征向量可以用优化算法来估计:

解决首先计算哪个向量(电影的特征向量或用户的参数向量)的问题的一种方法是猜测用户的参数向量,然后使用该估计来定义电影的(更好的)特征向量。

这种实现被称为协同过滤,因为对于用户的每个评级,该算法能够定义更好的电影特征向量,并改善所有用户的输出。

为了同时使用协同过滤(同时更新θ和 x),可以使用以下公式:

这导致以下梯度下降实现:

要实现这个公式,您必须

  1. 用小的随机值初始化所有的θ和 x
  2. 使用提供的梯度下降公式最小化成本函数
  3. 用参数θ和学习到的特征 x 预测用户的电影评级。

进一步使用

在实现协同过滤系统之后,另一个步骤可以是推荐相关的电影/产品。

这很容易做到,因为我们已经计算了特征向量 x。现在要找到相关的电影/产品,我们只需找到距离最小的,比如:

请注意,如果您的用户或电影/产品根本没有评级,您应该在实现学习算法之前执行均值归一化。要实现这一点,首先应该从结果矩阵中减去平均值,然后在预测评级时重新相加。但是你应该经常问自己,向一个完全不确定的单位推荐某样东西是否有意义。

扩展机器学习系统

当一个案例有非常多的例子时(大约 1 亿个),总是问自己是否有可能在保留结果的情况下减少数据集。

一种方法是绘制 m 值范围的学习曲线,并验证当 m 小时算法具有高方差。当 th 算法已经具有高偏差时,增加数据集没有帮助。

随机梯度下降

在大的训练集上,梯度下降变得非常计算昂贵。解决这个问题的一个方法是使用随机梯度下降。

不是一次迭代所有训练示例,而是随机打乱数据集,并对单个示例执行梯度下降,如下所示:

这允许改进每个单个示例的参数,因此比一次改进所有示例的参数花费更少的时间。(代价是它可能根本不会收敛,但对于大多数实际用例来说,最终会足够接近)。

小批量梯度下降

作为在每次梯度下降迭代中遍历所有示例或仅遍历 1 个示例的中间方式,小批量允许在每次迭代中设置一定数量 b 的示例。调整后的循环可能如下所示:

收敛性测试

为了测试小批量或随机梯度下降是否收敛,可以绘制并检查成本函数。

对于小批量梯度下降,迭代次数的成本函数可以直接绘制,而对于随机梯度下降,成本函数(在某个例子上)必须根据多个例子的平均值绘制。

如果算法未能收敛,尝试缓慢降低学习速率α。

在线学习

在网上学习的观念中,数据被认为是无穷无尽和免费的。例如在网站上获取用户数据流。在这种情况下,每次可以对一个示例执行梯度下降,次数不限。随着每个输入的例子,算法被改进,并且这样算法也可以根据用户偏好的改变而适应。

映射减少和数据并行

另一种处理大型数据集的方法是使用批量梯度下降,但将其分成不同的子集,允许多台机器处理自己的数据集。之后,可以简单地将结果相加,以符合原始公式(基本上使用函数和)。

在应用程序上使用的技巧

为你的问题创建一个管道

例如

  • 检测文本
  • 分段字符
  • 分类字符

获取更多数据

  • 尝试通过在你已有的数据集上添加变形来创建额外的数据(人工数据合成)
  • 尝试自己收集/标记数据
  • 人群来源数据

上限分析

通过比较准确度的提高,分析管道中哪些部分值得花费时间进行改进。

第四部分到此结束。多么不可思议的课程!:)

感谢阅读我的文章!欢迎留下任何反馈!

丹尼尔是一名商业法的法学硕士学生,在维也纳担任软件工程师和技术相关活动的组织者。他目前的个人学习努力集中在机器学习上。

连接到:

You can support me on www.buymeacoffee.com/createdd

基于 K-最近邻算法的机器学习基础

原文:towardsdatascience.com/machine-lea…

k-最近邻(KNN)算法是一种简单、易于实现的监督机器学习算法,可用于解决分类和回归问题。暂停!让我们打开它。

ABC. We are keeping it super simple!

分解它

有监督的机器学习算法(与无监督的机器学习算法相反)是一种依靠有标签的输入数据来学习一个函数的算法,当给定新的无标签数据时,该函数产生适当的输出。

想象一台计算机是一个孩子,我们是它的监管人(例如父母、监护人或老师),我们希望这个孩子(计算机)学习猪的样子。我们将向孩子展示几种不同的图片,其中一些是猪,其余的可以是任何东西的图片(猫、狗等)。

当我们看到猪时,我们会喊“猪!”当它不是猪的时候,我们就喊“不,不是猪!”对孩子这样做几次后,我们给他们看一张图片,问“猪?”而且他们会正确地(大部分时间)说“猪!”或者“不,不是猪!”取决于图片是什么。那就是监督机器学习。

“Pig!”

监督机器学习算法用于解决分类或回归问题。

一个分类问题有一个离散值作为它的输出。例如,“喜欢比萨饼上的菠萝”和“不喜欢比萨饼上的菠萝”是不连续的。没有中间地带。上面教孩子识别猪的类比是分类问题的另一个例子。

Image showing randomly generated data

此图显示了分类数据的基本示例。我们有一个预测器(或一组预测器)和一个标签。在图中,我们可能试图根据某人的年龄(预测值)来预测他是否喜欢在披萨上放菠萝(1)或不喜欢(0)。

标准做法是将分类算法的输出(标签)表示为整数,如 1、-1 或 0。在这种情况下,这些数字纯粹是代表性的。不应该对它们进行数学运算,因为这样做没有意义。想一想。什么是“喜欢菠萝”+“不喜欢菠萝”?没错。我们不能将它们相加,所以我们不应该将它们的数值表示相加。

一个回归问题的输出是一个实数(一个带小数点的数)。例如,我们可以使用下表中的数据,在给定身高的情况下估计某人的体重。

Image showing a portion of the SOCR height and weights data set

回归分析中使用的数据看起来与上图中显示的数据相似。我们有一个独立变量(或一组独立变量)和一个因变量(给定我们的独立变量,我们试图猜测的东西)。例如,我们可以说身高是自变量,体重是因变量。

此外,每行通常称为示例、观察值或数据点,而每列(不包括标签/因变量)通常称为预测值、维度、自变量或特征。

一种无监督机器学习算法利用没有任何标签的输入数据——换句话说,没有老师(标签)告诉孩子(计算机)什么时候是正确的,什么时候它犯了错误,以便它可以自我纠正。

监督学习试图学习一个函数,该函数将允许我们在给定一些新的未标记数据的情况下进行预测,而非监督学习则不同,它试图学习数据的基本结构,以便让我们对数据有更多的了解。

k-最近邻

KNN 算法假设相似的事物存在于附近。换句话说,相似的事物彼此靠近。

"物以类聚,人以群分."

Image showing how similar data points typically exist close to each other

请注意上图中,大多数时候,相似的数据点彼此接近。KNN 算法取决于这个假设是否足够真实,以使该算法有用。KNN 捕捉到了相似性(有时称为距离、接近度或紧密度)的概念,这与我们童年时可能学过的一些数学有关——计算图表上各点之间的距离。

注: 在继续之前,了解我们如何计算图上点之间的距离是必要的。如果您不熟悉或需要复习如何计算,请通读“ 两点间距离 ”的全文,然后回来。

还有其他计算距离的方法,根据我们要解决的问题,有一种方法可能更好。然而,直线距离(也称为欧几里德距离)是一个流行和熟悉的选择。

KNN 算法

  1. 加载数据
  2. 将 K 初始化为您选择的邻居数量

3.对于数据中的每个例子

3.1 根据数据计算查询示例和当前示例之间的距离。

3.2 将示例的距离和索引添加到有序集合中

4.按距离从小到大(按升序)对距离和索引的有序集合进行排序

5.从排序的集合中挑选前 K 个条目

6.获取所选 K 个条目的标签

7.如果是回归,返回 K 个标签的平均值

8.如果分类,返回 K 标签的模式

KNN 实现(从头开始)

选择正确的 K 值

为了选择最适合您的数据的 K,我们使用不同的 K 值运行 KNN 算法几次,并选择减少我们遇到的错误数量的 K,同时保持算法在给定以前从未见过的数据时准确做出预测的能力。

以下是一些需要记住的事情:

  1. 当我们把 K 值减小到 1 时,我们的预测变得不稳定。只需思考一分钟,想象 K=1,我们有一个由几个红色和一个绿色包围的查询点(我在想上面彩色图的左上角),但绿色是单个最近邻。合理地说,我们会认为查询点最有可能是红色的,但是因为 K=1,KNN 错误地预测查询点是绿色的。
  2. 相反,当我们增加 K 的值时,由于多数投票/平均,我们的预测变得更加稳定,因此,更有可能做出更准确的预测(直到某一点)。最终,我们开始看到越来越多的错误。在这一点上,我们知道我们把 K 值推得太远了。
  3. 如果我们在标签中采取多数投票(例如,在分类问题中选择模式),我们通常将 K 设为奇数,以进行平局决胜。

优势

  1. 该算法简单,易于实现。
  2. 没有必要建立一个模型,调整几个参数,或作出额外的假设。
  3. 算法是通用的。它可以用于分类、回归和搜索(我们将在下一节中看到)。

不足之处

  1. 随着示例和/或预测器/独立变量的数量增加,算法变得明显更慢。

实践中的 KNN

随着数据量的增加,KNN 的主要缺点是速度明显变慢,这使得它在需要快速做出预测的环境中是不切实际的选择。此外,还有更快的算法可以产生更准确的分类和回归结果。

然而,如果你有足够的计算资源来快速处理你用来做预测的数据,KNN 仍然可以用来解决那些依赖于识别相似物体的问题。这方面的一个例子是在推荐系统中使用 KNN 算法,这是 KNN 搜索的一个应用。

推荐系统

从规模上看,这就像在亚马逊上推荐产品,在 Medium 上推荐文章,在网飞上推荐电影,或者在 YouTube 上推荐视频。不过,我们可以肯定的是,由于他们处理的数据量巨大,他们都使用了更有效的方式来提出建议。

然而,我们可以使用我们在本文中学到的知识,在较小的规模上复制这些推荐系统中的一个。让我们来构建一个电影推荐系统的核心。

我们试图回答什么问题?

给定我们的电影数据集,与电影查询最相似的 5 部电影是什么?

收集电影数据

如果我们在网飞、Hulu 或 IMDb 工作,我们可以从他们的数据仓库中获取数据。因为我们不在任何一家公司工作,所以我们必须通过其他途径获取数据。我们可以使用来自 UCI 机器学习库、 IMDb 数据集、的一些电影数据,或者煞费苦心地创建我们自己的数据。

探索、清理和准备数据

无论我们从哪里获得数据,都可能有一些问题需要我们去纠正,以便为 KNN 算法做准备。例如,数据可能不是算法预期的格式,或者可能有我们应该在将数据传送到算法之前填充或删除的缺失值。

我们上面的 KNN 实现依赖于结构化数据。它需要以表格的形式。此外,该实现假设所有列都包含数字数据,并且数据的最后一列有标签,我们可以对其执行一些功能。因此,无论我们从哪里获得数据,我们都需要使它符合这些约束。

下面的数据是我们清理后的数据的一个例子。该数据包含三十部电影,包括七个流派的每部电影的数据及其 IMDB 评级。labels 列全是零,因为我们没有使用这个数据集进行分类或回归。

Self-made movies recommendation data set

此外,当使用 KNN 算法时,电影之间存在不被考虑的关系(例如,演员、导演和主题),这仅仅是因为捕获这些关系的数据从数据集中缺失。因此,当我们对我们的数据运行 KNN 算法时,相似性将只基于所包含的电影类型和 IMDB 评级。

使用算法

想象一下。我们正在浏览电影 Xb 网站,这是一个虚构的 IMDb 衍生网站,我们遇到了 《邮报》。我们不确定是否想看,但它的类型吸引了我们;我们对其他类似的电影很好奇。我们向下滚动到“更像这样”部分,看看 MoviesXb 会做出什么推荐,算法齿轮开始转动。

MoviesXb 网站向其后端发送与帖子最相似的 5 部电影的请求。后端有一个和我们一模一样的推荐数据集。它首先为帖子创建行表示(更好地称为特征向量),然后运行一个类似于下面的程序来搜索与帖子最相似的 5 部电影,最后将结果发送回 MoviesXb 网站。

当我们运行这个程序时,我们看到 MoviesXb 推荐了 12 年的奴隶钢锯岭卡特威女王风起美丽心灵。既然我们完全理解了 KNN 算法是如何工作的,我们就能够准确地解释 KNN 算法是如何提出这些建议的。恭喜你!

摘要

k-最近邻(KNN)算法是一种简单的监督机器学习算法,可用于解决分类和回归问题。它易于实现和理解,但有一个主要缺点,即随着所用数据的增长,速度会明显变慢。

KNN 的工作方式是找出查询和数据中所有示例之间的距离,选择最接近查询的指定数量的示例(K),然后投票选择最频繁的标签(在分类的情况下)或平均标签(在回归的情况下)。

在分类和回归的情况下,我们看到为我们的数据选择正确的 K 是通过尝试几个 K 并挑选一个最有效的来完成的。

最后,我们看了一个 KNN 算法如何用于推荐系统的例子,这是 KNN 搜索的一个应用。

KNN Be Like… ”Show me your friends, and I’ll tell you who you are.”

补遗

[1]为了简单起见,本文中实现的 KNN 电影推荐器不处理电影查询可能是推荐数据集的一部分的情况。这在生产系统中可能是不合理的,应该适当地处理。

如果你学到了新的东西或者喜欢阅读这篇文章,请鼓掌👏并分享给其他人看。也可以随意发表评论。

直觉(还有数学!)在多元梯度下降后面

原文:towardsdatascience.com/machine-lea…

一点一点的机器学习:关于机器学习的小文章

Photo by Dominik Scythe on Unsplash

又见面了!

机器学习一点一滴旨在分享我自己在机器学习方面的探索和实验。

在我的上一篇中,我们讨论了:

  1. 什么是梯度下降。
  2. 它如何在线性回归中有用。
  3. 它实际上是如何处理一个简单的一元函数的。

在这篇文章中,我们将扩展我们对梯度下降的理解,并将其应用于一个多元函数

在我看来,这为将梯度下降应用于更复杂的函数提供了一个平滑的过渡,并帮助您巩固梯度下降的知识,这在本系列的下一个主题—线性回归中是必不可少的。

好吧,我们开始吧。

多元梯度下降—直觉

首先,让我们谈谈直觉。对多元函数应用梯度下降实际上意味着什么?

我将试着通过想象来解释这一点:

  1. 目标多元函数
  2. 梯度下降如何使用它

请记住,梯度下降是一种算法找到一个函数的最小值。因此,我们的目标是找到一个函数的最小值,这个函数有多个变量。

在我的上一篇文章中,我们以一元二次函数为例:

这里是我们今天要看的二元(两个变量)二次函数J(θ1,θ2),:

下面的图 1 以各种方式显示了 J(θ1,θ2)——左边的 3D 图(图 1a )和中间的图 1b) 以及右边的等高线图(图 1c) 。等高线图是在 2D 平面上表示 3D 函数的一种方式。这就好像你从顶部俯视 3D 图形,并沿着 z 轴挤压它。图 1b ,是图 1a 的旋转版,应该能给你一些视觉上的直观。

对该函数应用梯度下降时,我们的目标仍然保持不变,只是现在我们有两个参数 θ1θ2 来优化:

到目前为止一切顺利…

更新规则

梯度下降的另一个特点是,它是一个迭代算法。因此,它使用更新规则在每次迭代之后系统地和有效地更新参数值。

这是单变量梯度下降的更新规则:

其中 α学习率,而 dJ(θ)/dθ 是 J(θ) 的导数——即在给定 θ 处与 J(θ) 相切的切线的斜率。

现在我们有了两个变量,我们需要为每个变量提供一个更新规则:

这些方程看起来几乎和一元函数的方程一样。这里唯一的变化是衍生术语,θ2)/∂θ1 ∂j(θ1θ2)/∂θ2 ∂j(θ1。但不要被它们吓到。符号 而不是 d 仅仅意味着它是偏导数

偏导数

在偏导数中,就像在正态导数中一样,我们仍然对在给定的 θ1θ2 处接触 J(θ1,θ2) 的切线的斜率感兴趣……但是这里的是至关重要的。

本质上,当查看切线时,我们不能同时移动 θ1θ2 。因此,我们一次只关注一个变量,同时保持其他变量不变。因此,得名

我将借助一个图表来更好地解释这一点。让我们把 θ1 看成一个变量,保持 θ2 不变,换句话说,就是 θ1 的一个偏导数。

保持θ2 不变视觉上翻译过来就是一个 θ1 - J(θ1,θ2) 平面(图 2 蓝色方块)以 *θ2 的特定值穿过图形。*图 2 红线代表 θ1 - J(θ1,θ2) 平面与 J(θ1,θ2) 图的交点,成为偏导数中感兴趣的函数。

现在,如果我们沿着红线提取蓝色平面,我们得到的是一个以θ1 为参数的古老的一元函数*,在 2D 平面,就像我们在上一篇文章中看到的一样!*

因此,当 ∂θ1 向零收缩时,我们可以如下计算更新函数中的偏导数项:

偏导数公式的证明(可选)

上面的等式利用了一个众所周知的偏导数公式,所以它省略了你如何实际计算偏导数以达到 2θ1 的证明。如果你没有兴趣证明,请跳过这一节。

现在,这是给你的——你有点像我,有一种强迫性的冲动想看看幕后发生了什么…

瞧吧!

同步更新

将相同的逻辑应用于 θ2 的部分推导,我们可以将更新规则简化如下:

最后但同样重要的是,要提到的是同时更新的概念——也就是说,当梯度下降应用于多元函数时,对每个参数的更新必须同时发生,而不是顺序发生。

我发现了一个非常直观的描述:

一个简单的类比就是走路。你通常不会先走东西向,再走南北向。你走最短的方向,即同时在两个坐标上移动。( StackExchange )

这实际上意味着,在每次迭代中,我们必须将每个新计算的参数赋给一个临时变量,直到我们计算完所有的参数。使用我们的示例,它看起来像这样:

然后,

太好了,我们有了拼图的每一部分。

动作中的梯度下降

时候到了!

我们现在可以看到多元梯度下降在起作用,使用 J(θ1,θ2) = θ1 + θ2 。我们将使用学习率 α = 0.2 和起始值 θ1 = 0.75θ2 = 0.75

图 3a 显示了梯度下降如何接近等高线图上 J(θ1,θ2) 的最小值。图 3bJ(θ1,θ2) 相对于迭代次数的曲线图,用于监控收敛。

在图图例中可以看到,从第七次迭代到第八次迭代, J(θ1,θ2) 减少 0.00056 ,小于 10^(-3) 的阈值,此时我们可以宣告收敛。

因此,我们找到了满足我们目标的参数组合 θ1 = 0.013θ2 = 0.013

总结

好的,这次我们看了梯度下降在多元函数中的应用。下一次,我们将最后看看梯度下降在线性回归中的应用。敬请期待!

请发表任何反馈、问题或主题请求。我也希望👏如果你喜欢这篇文章,那么其他人也可以找到这篇文章。

谢谢!

机器学习一点一滴系列

  1. 单变量梯度下降
  2. 多元梯度下降

资源

[## 可汗学院

免费学习数学、艺术、计算机编程、经济学、物理学、化学、生物学、医学、金融…

www.khanacademy.org](www.khanacademy.org/math/multiv…) [## Matplotlib 中的三维绘图

现在,根据这个参数化,我们必须确定嵌入条带的(x,y,z)位置。想想看,我们…

jakevdp.github.io](jakevdp.github.io/PythonDataS…) [## NumPy mgrid 与 meshgrid

meshgrid 函数对于创建坐标数组以在网格上对函数求值进行矢量化非常有用…

louistiao.me](louistiao.me/posts/numpy…) [## 如何把传说从剧情中剔除

我有一系列的 20 个情节(不是次要情节)要在一个单一的数字。我希望图例在盒子外面…

stackoverflow.com](stackoverflow.com/questions/4…) [## 为什么我们要同时更新梯度下降中的所有变量

在经典的梯度下降算法中,在每一步迭代中,我们同时更新所有的变量,即

math.stackexchange.com](math.stackexchange.com/questions/2…) [## 机器学习-黑客正午

在黑客正午阅读关于机器学习的文章。黑客如何开始他们的下午?

hackernoon.com](hackernoon.com/tagged/mach…)

直觉(还有数学!)在单变量梯度下降之后

原文:towardsdatascience.com/machine-lea…

一点一点的机器学习:关于机器学习的小文章

Photo by Dominik Scythe on Unsplash

欢迎光临!

机器学习一点一滴旨在分享我自己在机器学习方面的探索和实验。

理解并能够玩转背后的数学是理解机器学习的关键。它允许我们选择最合适的算法,并根据我们想要解决的问题对其进行量身定制。

然而,我遇到过许多教程和讲座,其中使用的方程是根本无法理解的。所有的符号看起来都很神秘,在被解释的东西和那些方程式之间似乎有一个巨大的鸿沟。我只是不能把所有的点联系起来。不幸的是,当一些知识被假定,重要的步骤被跳过时,数学往往会妨碍理解。

因此,只要有可能,我将展开方程式并避免走捷径,这样每个人都可以跟随我们如何从方程式的左边到达右边。

让我们直接进入有趣的事情吧!

什么是梯度下降?

第一个主题是梯度下降——寻找目标函数最小值的迭代算法。

它通常用于线性回归中,以找到给定数据的最佳拟合线。通过这样做,我们可以更好地了解数据集的输入和输出之间的关系,更有趣的是,我们能够在给定新输入的情况下以一定的信心预测输出。

在本文中,我们将探索:

  1. 什么是线性回归
  2. 如何使用成本函数找到最佳拟合线
  3. 为什么梯度下降在线性回归中很重要
  4. 梯度下降到底是如何工作的

线性回归

监督学习中最常用的模型之一是线性回归

线性回归模型允许你在给定自变量 x(输入)的情况下预测因变量 y(输出),假设两个变量之间存在线性关系。

这里有一些现实生活中的例子,线性回归可以用来找出两个变量之间的关系:

身高对体重的影响

教育水平对财富的影响

降雨量对水果产量的影响

血液酒精含量对身体协调性的影响

用更实际的话来说,线性回归的目标是找到一条线(称为假设),即最能代表(符合)数据点

但真正的问题是——我们如何知道这种契合有多“好”?

成本函数

事实上,我们用一个成本函数来衡量一个假设的适合度。

本质上,成本函数是一个均方误差(MSE) —真实值(标签)和从假设中得出的估计值(预测)之间偏差的集合度量。成本函数的越小,线和数据点之间的偏差越小,因此的假设越好。

因此,我们的目标是找到一个最小化成本函数的假设,因为它给了我们一条最佳拟合线。

现在,还记得梯度下降的描述吗?

梯度下降是一种寻找函数最小值的迭代算法。

没错,这就是梯度下降在机器学习中发挥作用的地方。我们用它来最小化线性回归中的成本函数,以拟合数据集的直线。

­­­­­­­­

梯度下降算法

话虽如此,梯度下降法并不是专门用来解决线性回归问题的。它是一个通用算法,可以应用于任何一个可微函数求其最小值。

为了更好的理解直觉,我们从最简单的例子开始:单变量梯度下降。也就是说,梯度下降适用于单变量函数。

单变量梯度下降

让我们定义θ的一元函数 J, J(θ) ,如下:

当相对于 θ 作图时,函数 J(θ) 看起来像图 1

我们希望找到一个使 J(θ) 最小的 θ 值:

为了实现这一点,我们需要尝试不同的 θ 值,直到 J(θ) 达到最小值。通常情况下,我们从 θ = 0 开始,但由于在这种情况下,这产生了 J(θ) 的最小值,所以假设我们从 θ = 6 开始。

在详细研究该算法之前,这里有两个关键问题:

  1. 我们如何确定 J(θ) 何时达到最小值?
  2. 如果 J(θ) 不在最小值,我们怎么知道接下来要尝试的 θ 的值是多少?

这些问题可以通过对 J(θ) 进行求导来回答——换句话说,计算出在给定 θ 处与 J(θ) 相交的切线的斜率。如果斜率为正,这意味着 θ 的值需要在下一次迭代中减小,以接近最小值,而如果斜率为负,则 θ 需要增大。

考虑图 2 。由于在 θ = 6 处切线的斜率是正的 (12) ,我们知道 θ 需要减小以接近使 J(θ) (θ = 0) 最小的值。另一方面,一条切线在 θ = -2 处的斜率为负 (-4) ,所以我们知道在下一次迭代中需要增加 θ 的值。

同样重要的是,当我们达到最小值 J(θ) 时,斜率变为 0 。这就是我们如何知道梯度下降何时收敛,即 J(θ) 的值接近足够接近的最小值。在实践中,如果在一次迭代中 J(θ)的下降小于 10^(-3(= 0.001),我们宣布收敛*。*

更新规则

现在,我们需要一种系统有效的方法来更新 θ ,同时我们寻找一个使 J(θ)最小的 θ 值。

在梯度下降中,它是通过在每次迭代后自动应用更新规则来完成的,因此 θ 越来越接近我们的目标值。

单变量函数的更新规则如下:

这里, α 称为学习率dJ(θ)/dθJ(θ)导数——即切线的斜率。

学习速率决定 θ 移动的快慢。选择一个好的学习速率是至关重要的,如果它太大,我们可能会跳过它而错过最佳值,甚至可能不会收敛。另一方面,如果它太小,算法收敛将需要太多的迭代。稍后我会用一些视觉辅助来解释这一点。

对于 J(θ) = θ ,随着 向零收缩, J(θ)导数计算如下:

由此, J(θ) = θ 的更新规则可以简化为θ:=(1–2α)θ

梯度下降在行动

让我们最后看看梯度下降的作用。

我们将对 J(θ) = θ 进行梯度下降,其中 α = 0.3 ,初始值为 θ = 6 ( 图 3 )。

第一次迭代后, θ 更新为θ:=(1–2α)θ= 0.4 * 6 = 2.4 第二次迭代后:θ:=(1–2α)θ= 0.4 * 2.4 = 0.96 第三次迭代后:θ:=(1–2α)θ= 0.4 * 0.96 = 0

诸如此类…

Fig.3a — Steps of gradient descent as it approaches minimum of J(θ). Fig.3b — A plot of J(θ) against the number of iteration, useful to visually monitor convergence.

最后,从第六次迭代到第七次迭代, J(θ) 减少 0.0005 ,小于 10^(-3) 的阈值,此时我们可以宣告收敛。

调整学习速度

正如我所承诺的,这里有一些学习率过大或过小的例子,这将帮助你直观地理解为什么选择正确的学习率是至关重要的。

图 4 是学习率过大时。 θ 的值来回振荡跳过最小值,而不是逐渐接近最小值。即使在第十次迭代之后, θ 仍然离零很远,并且我们预计 θ 会经历更多不必要的曲折,以最终接近 J(θ) 的最小值。事实上,在这种情况下,它需要 23 次迭代才能达到收敛。

相反,图 5 显示了过小的学习率如何显著减缓收敛。在这个极端的例子中,即使经过 100 次迭代,仍然远离收敛。

希望这证明了监控收敛和相应调整学习速率的重要性。

总结

好了,我们讨论了梯度下降的基本应用,使用一元函数作为目标函数。下次讲它在多元函数和线性回归中的应用。

请发表任何反馈、问题或主题请求。我也希望👏如果你喜欢这篇文章,那么其他人也可以找到这篇文章。

谢谢!

机器学习一点一滴系列

  1. 单变量梯度下降
  2. 多元梯度下降

资源

[## 梯度下降和线性回归导论

梯度下降算法是那些“最成功”的算法之一,可以为解决问题提供一个新的视角…

spin.atomicobject.com](spin.atomicobject.com/2014/06/24/…) [## 梯度下降求导克里斯麦考密克

对于线性回归,我们有一个线性假设函数,h(x)= ѳ0+ѳ1*x.我们要找出ѳ0 和ѳ1…的值

mccormickml.com](mccormickml.com/2014/03/04/…) [## 机器学习的线性回归-机器学习掌握

线性回归也许是统计学和机器中最著名和最容易理解的算法之一

machinelearningmastery.com](machinelearningmastery.com/linear-regr…) [## 如何在介质上写数学

技术作者简明指南

medium.com](medium.com/@tylerneylo…)

修正

【2018 年 12 月 9 日—*“梯度下降在行动”*一节学习率出现错别字。最初写为 α = 3 ,而正确的值是 α = 0.3 。感谢阿尼班·杜塔指出这一点。

使用 XGBoost 和 clj-boost 在 Clojure 中进行机器学习

原文:towardsdatascience.com/machine-lea…

机器学习+ REPL = ❤

Clojure 这是一个 LISP 。所以作为一个 LISP,它有很多括号。既然我们已经把那件事一吐为快,我们可以继续谈论更严肃的事情了。

Obligatory xkcd comic

为什么是 Clojure?

你可能从来没有听说过 Clojure ,更不用说数据科学和机器学习了。那么,为什么您会对使用它来做这些事情感兴趣呢?我来告诉你为什么:要让要紧的事(数据)一流

在 Clojure 中我们不处理类、对象等等,一切都只是数据。而那个数据是不可变的。这意味着,如果您搞砸了您的转换,数据将是好的,您不必从头再来。

前一个只是我想到的原因之一,另一个可能是 JVM 。是的,我们都在某种程度上讨厌它,但不要搞错:它自 1991 年开发以来,一直是生产级。这就是为什么全世界的企业仍然在 JVM 上运行和开发软件。考虑到这一点,Clojure 甚至可以被最保守的公司所接受,因为从根本上说,它是他们已经知道的东西。

我想说的第二点是 REPL。这不像通常的语言外壳(例如 Python REPL ),通常非常基础和烦人,但是它有超能力!去现场看看该服务在生产中发生了什么会很好吗?搞定!你想要一个既能用于生产又能用于实验的绘图服务吗?搞定!您是否碰巧有嵌套的数据结构,并且可视化地探索它们以更好地理解它们会很好?搞定!

这意味着你并不真的需要像 jupyter 笔记本这样的东西,尽管如果你在这样的环境中感觉更舒服,有一些选项可以无缝地工作: clojupyter 是用于 Jupyter 笔记本的 Clojure 内核,而大猩猩 REPL 是本地 Clojure 笔记本解决方案。

数据读取

如果你从未看过 Clojure 代码,或者如果你刚刚开始,我的建议是看一看在 Y 分钟内学会 clo jure以便能够跟上这一点,那么当我开始学习时,我最喜欢的来源之一是clo jure for the Brave and True。无论如何,我会仔细解释代码中的每一步,这样每个人都可以很容易地理解。

这只是一个介绍,所以我们将使用臭名昭著的虹膜数据集。如果你还没有 Leiningen 获取并安装它,它真的很容易使用,并且是 Clojure 事实上的构建工具。现在,您可以通过启动以下命令从命令行创建一个新的项目框架:

lein new clj-boost-demo
cd clj-boost-demo

您应该具有如下所示的目录结构:

.
├── CHANGELOG.md
├── doc
│   └── intro.md
├── LICENSE
├── project.clj
├── README.md
├── resources
├── src
│   └── clj_boost_demo
│       └── core.clj
└── test
└── clj_boost_demo
└── core_test.clj

我们最关心的文件是project.clj,它是 Leiningen 正确准备和构建项目的基础,src是我们放置应用程序或库的代码的地方,resources是我们放置 Iris csv 文件的地方,您可以从这里的获得。现在我们可以定义project.clj文件,这是 Clojure 的另一个“明智”之处:你必须显式声明库和版本,这总是一件好事。

(defproject clj-boost-demo "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.9.0"]
                 [org.clojure/data.csv "0.1.4"]
                 [clj-boost "0.0.3"]])

如果我们保存project.clj并在 shell 中启动lein run,Leiningen 将获得所有需要的依赖项并启动一个 REPL。我们可以通过打开和修改src/clj-boost-demo/core.clj文件进入数据加载和传输。我们会在那里找到一些占位符代码,我们可以去掉它,开始写我们的代码。

在 Clojure 中,我们使用名称空间,通常一个文件包含一个定义导入的名称空间:

(ns clj-boost-demo.core
  (:require [clj-boost.core :as boost]
            [clojure.java.io :as io]
            [clojure.data.csv :as csv]))(def iris-path "resources/iris.csv")

定义一个新的名称空间,从名称空间定义导入库是一个好的实践,就像我们在这里做的一样。:require这是一个关键字,它本身就是 Clojure 中的一个类型,我们稍后会看到它们为什么重要,[clj-boost.core :as boost]意味着我们想要使用clj-boost库中的core名称空间,但是我们想要用名称boost引用它下面的所有名称。如果你懂 Python,这和做import library as lbr是一样的。

使用def,我们在当前名称空间中全局创建新的变量。在这种情况下,我们指向一个表示数据集所在路径的字符串。通常在 Clojure 中我们不会定义很多全局名,除了函数名。事实上,iris-path将是我们在本演示中使用的唯一全球名称!

为了读取 Iris csv,我们使用以下代码:

(defn generate-iris
  [iris-path]
  (with-open [reader (io/reader iris-path)]
    (into []
          (comp (drop 1) (map #(split-at 4 %)))
          (csv/read-csv reader))))

这段代码定义了(defn)一个名为generate-iris的函数,它将 Iris csv 的路径作为参数。然后我们在给定的路径下打开一个到文件的连接,当我们完成时这个连接将被关闭(with-open)。当你在一个函数调用之后看到一个向量,它带有一个符号,后面跟着一些代码——[reader (io/reader iris-path)]——这就是局部绑定。

本地绑定有助于避免混淆全局名称空间,并将代码执行分成微小的部分。在这种情况下,我们使用一个 Java 阅读器,确切地说是一个BufferedReader,来打开和读取文件。如您所见,我们通过执行io/reader来使用导入的clojure.java.io名称空间,而name/是访问驻留在导入的名称空间中的名称的语法。

下面的代码可能看起来有点深奥,但这只是习惯问题。让我们从 REPL 开始分解所有的步骤。

(with-open [reader (io/reader iris-path)] 
  (csv/read-csv reader)) 
;IOException Stream closed java.io.BufferedReader.ensureOpen

上面的代码抛出一个错误,那是因为csv/read-csv。默认懒惰是 Clojure 的另一个特性:大部分 Clojure 函数不会返回任何东西,直到你需要那些值。如果你考虑一下,这很好:如果我们有一个非常大的文件,我们不必将它全部加载到内存中来处理它,但是我们可以逐行读取和处理它,同时将结果写入另一个文件。

为了使函数变得更有吸引力,我们可以使用doall:

(with-open [reader (io/reader iris-path)] 
  (doall (csv/read-csv reader))) 
;(["sepal_length" "sepal_width" "petal_length" "petal_width" "species"] 
; ["5.1" "3.5" "1.4" "0.2" "setosa"] 
; ["4.9" "3" "1.4" "0.2" "setosa"]...)

结果是包含字符串的向量序列。序列是 Clojure 中最重要的数据结构之一:它们是懒惰的、不可变的,可以由任何其他 Clojure 数据结构产生。更多关于他们的信息,请查看官方 Clojure 文件。向量非常类似于 Python 列表,区别在于它们是持久的。

为了更好地理解不变性持久性让我们尝试一个小实验:

(def a [1 2 3]) 
(println a) 
;[1 2 3] (conj a 4) 
;[1 2 3 4] (println a) 
;[1 2 3]

正如你所看到的,我们创建了一个向量a,然后conj(向向量追加元素)4 到a,结果是一个全新的数据结构,事实上a仍然有初始值。

数据处理

在这种情况下,我们不再关心标题,因为"species"列是我们想要预测的类,也是最后一个,所以我们可以立即开始处理原始数据。为了简化这个过程,我们定义了一个在 REPL 中使用的demo-reader函数,并开始处理结果数据:

(defn demo-reader [] 
  (with-open [reader (io/reader iris-path)] 
    (doall (csv/read-csv reader))))

然后,我们将使用线程宏来逐步试验和应用转换:

(->> (demo-reader) (take 3)) 
;(["sepal_length" "sepal_width" "petal_length" "petal_width" "species"] 
; ["5.1" "3.5" "1.4" "0.2" "setosa"] 
; ["4.9" "3" "1.4" "0.2" "setosa"])

让我们将一个值作为后续函数的最后一个参数:你肯定还记得在学校时他们教过你,要求解 f(g(x)),你应该从求解 g(x)= x’开始,然后 f(x’)= x”。线程宏它只是语法糖,使代码更可读。

这里有一个简单的例子:

(inc 1) 
;2 (dec (inc 1)) 
;1 (-> 1 inc dec) 
;1

我们inc1加 1,然后(dec (inc 1))表示inc1,然后dec将结果-2-加 1,得到 1。基本上,我们从右到左阅读来理解函数的应用顺序。使用(-> 1 inc dec)我们可以从左至右阅读操作。有关线程宏的更多信息,请查看官方 Clojure 文档

回到(->> (demo-reader) (take 3))正如你看到的结果,我们只从 csv 中获得前 3 个向量。take完全按照您的想法去做:它懒洋洋地从给定的集合中获取n值。这在实验时非常有用,否则我们将不得不处理整个序列。

要从序列中删除标题,我们可以从结果中drop第一行:

(->> (demo-reader) (take 3) (drop 1)) 
;(["5.1" "3.5" "1.4" "0.2" "setosa"] 
; ["4.9" "3" "1.4" "0.2" "setosa"])

现在,因为我们想把 X 值从 Y 值(我们想预测的类)中分离出来,所以最好一次完成。如果您来自 Python 或其他类似 C 语言的语言,您可能会尝试使用循环来做这件事,但是在 Clojure 中,我们做的事情不同。

使用map,我们可以对集合中的所有值应用一个函数:

(map inc [1 2 3]) 
;(2 3 4)

在这种情况下,我们想要分割值,猜猜看,有一个split-at函数在等着我们!

(split-at 2 [1 2 3])
*;[(1 2) (3)]*

这正是我们所需要的,所以我们将定义一个匿名函数并在我们的向量上使用它:

(->> (demo-reader) 
     (take 3) 
     (drop 1) 
     (map #(split-at 4 %))) 
;([("5.1" "3.5" "1.4" "0.2") ("setosa")] 
; [("4.9" "3" "1.4" "0.2") ("setosa")])

为了定义命名函数,我们使用defn,它是一个,让我们避免每次都输入(def my-func (fn [arg] "do something")),所以通过简单的(fn [arg] "I have no name"),我们得到一个匿名函数。

#(split-at 4 %)是另一个和(fn [x] (split-at 4 x))解析一样的简写,所以只是省打字的一种方式。

现在让我们通过使用传感器将所有东西放在一起。如同带有传感器的线程宏一样,我们将函数组合在一起,但是传感器返回一个只传递一次数据的函数。如果它们一开始看起来有点晦涩,不要担心,我也花了一些时间来理解这个概念,我建议你仔细阅读这个写得非常好的关于传感器的系列文章。

(def xf (comp (drop 1) (map #(split-at 4 %)))) (into [] xf [[1 2 3 4 5] [1 2 3 4 5]]) 
;[[(1 2 3 4) (5)]]

使用comp我们将函数组合在一起,只返回一个函数,而使用into我们循环遍历一个集合,并将结果放入作为第一个参数给出的集合中。我喜欢这样来思考这个过程:这就像我们从一个集合中把个值拉到另一个集合中,但是当我们这么做的时候,我们对所有的值都应用了一个函数xf

结果是我们开始的generate-iris函数:

(defn generate-iris
  [iris-path]
  (with-open [reader (io/reader iris-path)]
    (into []
          (comp (drop 1) (map #(split-at 4 %)))
          (csv/read-csv reader))))

现在我们想从这个([("5.1" "3.5" "1.4" "0.2") ("setosa")] [("4.9" "3" "1.4" "0.2") ("setosa")])转到我们能以更简单的方式处理的东西:([5.1 3.5 1.4 0.2 0] [4.9 3.0 1.4 0.2 0])。基本上,我们将字符串解析成数字,并将类( setosavirginicaversicolor )转换成整数。

让我们从抽象出所需的转换开始:

(defn parse-float
  [s]
  (Float/parseFloat s))(->> (generate-iris iris-path) 
     (take 2) 
     (map first)) ; first returns the first element of a collection ;(("5.1" "3.5" "1.4" "0.2") ("4.9" "3" "1.4" "0.2")) (->> (generate-iris iris-path) 
     (take 2) 
     (map first) 
     (map #(map parse-float %))) 
; ((5.1 3.5 1.4 0.2) (4.9 3.0 1.4 0.2)) (->> (generate-iris iris-path) 
     (take 2) 
     (map first) 
     (map #(map parse-float %)) 
     (map vec)) 
; ([5.1 3.5 1.4 0.2] [4.9 3.0 1.4 0.2])

通过这些变换,我们可以为我们的模型构建 X。让我们建造一个名为的变压器:

(def transform-x
  (comp
   (map first)
   (map #(map parse-float %))
   (map vec)))

取而代之的是 Y:

(->> (generate-iris iris-path) 
     (take 2) 
     (map last)) ; last takes the last item from a collection 
;(("setosa") ("setosa")) (let [l (first '("setosa"))] 
  (case l "setosa" 0 "versicolor" 1 "virginica" 2)) 
;0

停一下,用let我们可以创建本地绑定,比如给只存在于本地空间而非全局的数据或函数命名。case这是避免嵌套(if condition "this" "else this")的一种方式。我们说的是:如果l="setosa"那么返回0,如果是="versicolor"返回1,而如果是="virginica"返回 2。

这样,如果给定值与三种情况都不匹配,我们就会得到一个错误。这也有助于检查数据质量。

(->> (generate-iris iris-path) 
     (take 2) 
     (map last) 
     (map (fn [label] 
       (let [l (first label)] 
         (case l "setosa" 0 "versicolor" 1 "virginica" 2))))) 
;(0 0)(def transform-y
  (comp
   (map last)
   (map (fn [label]
          (let [l (first label)]
            (case l
              "setosa"     0
              "versicolor" 1
              "virginica"  2))))))(defn munge-data
  [iris-data]
  (let [x (into [] transform-x iris-data)
        y (into [] transform-y iris-data)]
    (map conj x y)))

列车-测试分离

当进行机器学习时,要做的最重要的事情之一是在一个训练和一个测试集合上分割数据。一个好的分割需要随机采样,所以我们将从头实现一个非常简单的采样器。

(defn train-test-split
  [n dataset]
  (let [shuffled (shuffle dataset)]
    (split-at n shuffled)))

train-test-split在训练集中获取一个集合和一些你想要的实例。shuffle函数只是简单地打乱了集合,所以我们每次都会得到一个随机的结果,并且可以很容易地避免重复。

如果您有一个相当大的数据集,这种解决方案并不是最佳的,在这种情况下,您可能想要看一下采样,这是一个非常好的库,可以处理关于采样的所有事情。

(defn train-set
  [split-set]
  (let [set (first split-set)]
    {:x (mapv drop-last set)
     :y (mapv last set)}))

(defn test-set
  [split-set]
  (let [set (last split-set)]
    {:x (mapv drop-last set)
     :y (mapv last set)}))

利用上述函数,我们生成训练集和测试集,作为带有 2 个 : :x:y的 2 个映射。Clojure 中的地图是一等公民,具有非常好的属性:

; Create a map with mixed types 
{:a 1 "key" "string" 2 1/3}

; Maps are functions 
({:a 1} :a) 
;1 ; Keywords are functions as well 
(:a {:a 1}) 
;1 ; Access other kinds of keys by using the map... 
({1 2} 1) 
;2 ; ...or the get function 
(get {"key" 1} "key") 
;1

地图远不止这些,如果你不知道它们,你应该看看这里的。

训练和预测

XGBoost 是一个集合模型,它使用梯度增强来最小化损失函数。如果你不能理解这些单词,我的建议是查看这个非常好的算法解释(有图片和公式)。

clj-boost 给你一个 Clojure 接口到底层 Java 实现的库,这样我们可以避免 Java 互操作,得到同样的结果。为了训练一个模型,我们必须从数据中创建一个 DMatrix ,我们希望将这些数据提供给算法进行学习。这不是我的选择,我可以将数据转换隐藏在 API 实现的后面,但是有一个问题:一旦你将数据放入一个 DMatrix 中,你就不能再触摸或查看它们了。

(defn train-model
  [train-set]
  (let [data   (boost/dmatrix train-set)
        params {:params         {:eta       0.00001
                                 :objective "multi:softmax"
                                 :num_class 3}
                :rounds         2
                :watches        {:train data}
                :early-stopping 10}]
    (boost/fit data params)))

dmatrix我们序列化我们的训练集,有各种方法生成一个 DMatrix ,所以我建议你看一下文档自述文件:params映射的作用就像是 XGBoost 的配置,这是我们可以用它做什么的一个非常小的例子,要知道所有可能的选项总是参考官方文档

这里我们说 XGBoost 应该以 0.00001 的学习率:eta进行训练,因为我们正在对 3 个类进行分类—setosa、versicolor 和*virginica—*我们将:objective设置为 multi:softmax ,并告诉 XGBoost 我们与:num_class有多少个类。

XGBoost 将进行 2 次:rounds的增强,将通过将训练集传递给:watches图来评估其准确性(这不是一个好的实践,但这只是一个例子),如果准确性将开始连续 10 次迭代增加,它将由于:early-stopping参数而停止训练。

对定义的数据参数调用fit从头训练一个 XGBoost 模型,并返回一个 Booster 实例。我们可以使用 Booster 进行预测,我们可以将它持久化到磁盘上,或者将其作为基线提供给另一个 XGBoost 模型。

(defn predict-model
  [model test-set]
  (boost/predict model (boost/dmatrix test-set)))

(defn accuracy
  [predicted real]
  (let [right (map #(compare %1 %2) predicted real)]
    (/ (count (filter zero? right))
       (count real))))

虽然我们通过训练装置本身来检查训练性能,但我们将在之前准备的测试装置上检查准确性。predict需要一个模型和数据作为我们想要预测的 DMatrix 并返回一个预测向量。

让我们把一切都打包成一个-main函数,这样我们就可以从 REPL 和命令行运行整个分析。

(defn -main
  []
  (let [split-set    (->> iris-path
                          generate-iris
                          munge-data
                          (train-test-split 120))
        [train test] (map #(% split-set) [train-set test-set])
        model     (train-model train)
        result    (predict-model model test)]
    (println "Prediction:" (mapv int result))
    (println "Real:      " (:y test))
    (println "Accuracy:  " (accuracy result (:y test)))))

我们生成分裂集,然后我们使用一个小技巧:我们将多个函数映射到一个集合上,而不是相反。然后我们训练 XGBoost 模型并得到预测。

(-main) 
Prediction: [1 1 2 0 2 2 2 2 2 1 1 0 1 2 0 1 1 1 0 1 0 2 1 1 0 0 1 2 1 1] 
Real: [1 1 2 0 2 2 2 2 2 1 1 0 1 2 0 1 1 1 0 1 0 2 1 1 0 0 1 2 2 1]
Accuracy: 29/30

灵活性与生产

您可能没有注意到,尽管我们编写的代码足够简单灵活,可以用于分析和实验,但这也是生产就绪代码。如果您在命令行中从项目的根目录执行lein run,您将获得与从 REPL 执行(-main)相同的结果。因此,向程序添加功能是微不足道的,例如,当程序发生变化时,您可能希望向它输入新数据,并且您希望重新训练您的模型。

如果我们现在在 Jupyter 笔记本上用 Python 做类似的事情,我们可能会到处都是任务,命令式代码必须从头开始重写,以使它在某种程度上为生产做好准备,我不会谈论这样一个事实,即如果数据管理性能可能是一个问题,通过组成转换器,我们几乎可以获得免费的并行化。

现在你可以用 clj-boost 玩一会儿了,不要忘了还有文档可用,这仍然是一项正在进行的工作,所以如果有问题、想法、改进方法或者只是你正在使用它并且你对它感到满意,请让我知道。

你可以在 clj-boost repo 上找到完整的脚本,不要忘记 clj-boost 是自由/开源软件,任何形式的贡献都是可以接受的!

这篇文章最初发表在 rDisorder 上(请特别查看更好的代码片段)

机器学习:外行使用 Spark 的决策树

原文:towardsdatascience.com/machine-lea…

目标

在本文中,我们将回顾决策树的定义、直觉和算法。

然后,我们将编写自己的代码,而不使用任何 ML 库(如 tensorflow 等)。这将为实施决策树提供很好的理解和实践经验。

什么是决策树

study.com 的定义

决策树是基于特定条件的决策的可能解决方案的图形表示。它被称为决策树,因为它从单个框(或根)开始,然后分支成许多解决方案,就像树一样。

直觉

让我们考虑一些访问 ecom 网站的用户的数据。让我们假设我们知道访问网站的用户的概况,如他们的年龄、工作、信用额度等。

该表包含一些销售记录,数据的模式是

  • 第一列是购买者来自的城市。
  • 第二列“工作”表示采购员正在做的工作。
  • 第三列是该人的信用额度
  • 第四栏是购买者的年龄

最后一个最重要的列表示用户最终是否购买了任何商品。“是”表示用户购买了商品,“否”表示用户没有购买。

我们想要做的是,基于这些数据,我们想要建立一个决策树来进一步预测任何新用户是否会在网站上购买任何商品。

怎么

让我们看看数据,看看四个因素(城市、职业、cc_limit 和年龄)中的哪一个可能会影响用户购买或不购买的决定。

考虑到“年龄”,该属性对于每一行都有不同值。即使对于唯一的输出——“是”和“否”,该属性的值也是随机的。所以我们可以说,年龄肯定不是用户购买产品的决定因素。

但是我们如何从数学上证明年龄不是一个因素,至少不是决定结果的主要因素?让我们看看熵。

熵是随机性(或杂质)的量度。在上面的例子中,年龄是最随机的属性。

但是我们如何测量熵呢?测量熵的公式是。这也被称为香农熵

  • n 是值的数量,并且
  • p 是类中的元素数除以总元素数。

让我们深入了解细节。考虑我们上面的样本数据列有结果值

该属性(即 y)的“是”(“是”类)的数量= 4

‘否’的数目(‘否’类)都= 3

元素总数= 7

  • p(0) is =是类中的元素数/元素总数= 4/7
  • p(1)is = no 类中的元素数/元素总数= 3/7

熵=(-4/7 * log2(4/7)-3/7 * log2(3/7))=(-0.57 *-0.81–0.43 *-1.22)=(0.4617+0.5246)= 0.9863

0.9863 是数据的熵。

属性的可变性

现在我们知道了基于结果的数据集的熵,我们如何从数学上找出对决策有贡献的最有影响力的顶级属性。这将是我们试图构建的决策树的根。

如上所述,“年龄”不能成为任何顾客做出购买决定的因素,因为我们看到人们的年龄几乎随着每个记录而变化。年龄的太多变化使其成为决策中最不重要的因素,因此反过来,变化最小的属性将是最有影响的属性,或者更确切地说是随着结果而变化的属性?提示,是后者。让我看看。

我们已经有了数据集的熵(杂质),对于上面的例子是 0.9863。所以,我们做下面的工作来获得一个属性的信息增益

  • 求每个属性中每个类的熵。在我们的示例中,Eg city 有 2 个班,即班加罗尔和钦奈
  • 按比例分配每个类的熵 wrt 数据集类。

对于城市属性

(班加罗尔市的记录总数/记录总数)*班加罗尔熵

(钦奈市的总记录数/总记录数)*钦奈熵

对每个类的上述值求和,并从数据集的熵中减去它

让我们找出班加罗尔城市熵。查一下班加罗尔的记录。其中 2 个有“是”输出,1 个有“否”输出。所以,班加罗尔熵就是

班加罗尔熵=-2/3log2(⅔)—1/3log2(⅓)= 0.39+0.53 = 0.92

同样,Chennai 熵= -2/2log2(2/2) — 2/2log2(2/2) = 0(其完全一致的性质,相等数量的它属于‘是’和‘否’的结果)

因此,城市的信息增益将如上所述= 0.9863 — { (3/7)*0.92 + 0 } = 0.592

其他属性

“工作”的信息增益— 0.9863 — { 4/7 *就业熵+ 2/7 *失业熵+ }

类似地,我们也得到“信用额度”的信息增益。

特例

让我们添加另一个名为“ownshouse”的属性,它的值随着输出的变化而变化。所以数据集现在看起来像

“拥有房屋”表示客户是否拥有房屋。它与结果属性“y”具有相同的值。让我们调整这个属性的信息增益。

它有两类'是'和'否'。

“是”的熵= — 4/4log2(4/4) — 0(没有属于“否”类的项目)= 0

“否”的熵=—0–3/3 log2(3/3)= 0

“ownshouse”属性的信息增益= 0.9863–0 = 9.9863

刚刚发生了什么?由于该属性的“ownshouse”值的变化与结果完全相同,因此其信息增益与数据集的熵相同。

计算了属性的信息增益,接下来呢?

一旦我们有了属性的信息增益

  • 我们得到具有最大信息增益的属性
  • 将该属性作为树的头
  • 获取该属性的值,并创建该标题的这些分支,例如,假设“城市”具有最大信息增益(实际上,在我们的示例中它没有最大增益,但为了讨论起见,假设它)。

总部设在城市,分支机构设在班加罗尔和钦奈

  • 在下一次迭代中-从属性列表中移除城市。
  • 对于待定属性,获取属于 Bangalore 下分支的每个属性的 city = Bangalore 的记录。
  • 计算 Bangalore city 下属性的信息增益,得到增益最大的属性,成为 Bangalore 下的节点。
  • 继续这样做,直到我们用尽所有属性或者熵为零。

我还有另一个例子,在最后有代码,它为其他数据集实现了这个逻辑,所以你可以看一下它是如何实现的。

我们什么时候停止构建决策树

如上所述,我们在下列情况下停止

  • 我们已经经历了所有的属性或
  • 找到熵为零的属性。

实际上在我们的特例中,我们在第一次迭代中遇到了熵为零的属性。该属性是“ownshouse”。

带代码的完整示例

我们从这里开始动手练习。如果您对编码不感兴趣,那么本文将在这里为您总结。

使用的工具——pySpark、networkx python lib 来可视化决策树

代码也在 github 上,网址是https://github . com/skhurana 333/ml/blob/master/decision _ tree/decision _ tree _ model _ complex . py

基本上,这个数据集列出了影响网球比赛是否可以在室外进行的条件。描述了前景、温度、湿度和风的值,以及在这些条件下是否玩游戏的结果。我们现在将构建决策树。

outlook;temp;humidity;wind;y
Sunny;Hot;High;Weak;no
Sunny;Hot;High;Strong;no
Overcast;Hot;High;Weak;yes
Rain;Mild;High;Weak;yes
Rain;Cool;Normal;Weak;yes
Rain;Cool;Normal;Strong;no
Overcast;Cool;Normal;Strong;yes
Sunny;Mild;High;Weak;no
Sunny;Cool;Normal;Weak;yes
Rain;Mild;Normal;Weak;yes
Sunny;Mild;Normal;Strong;yes
Overcast;Mild;High;Strong;yes
Overcast;Hot;Normal;Weak;yes
Rain;Mild;High;Strong;no

假设具有上述数据的文件保存在位置=/home/me/ml/practice/decision _ tree/datasets/simple _ dataset

我们将讨论流程和算法

让我们加载数据集。

data = sqlContext.read.format('com.databricks.spark.csv').option('header', 'true')\
 .option('delimiter', ';') \ .load("/home/me/ml/practice/decision_tree/datasets/simple_dataset")
  • 因为它包含 header,所以我们在选项中将 header 设置为 true。
  • 分隔符是;
  • 它是 csv 格式的。

我们将把它注册为表,因为我们需要用不同的 where 条件查询这个数据集。

data.registerTempTable('data')

计算数据集的熵

获取结果为“是”和“否”的行数。下面是 pyspark 查询

played = sqlContext.sql("select * from data WHERE y like '%y%' ").count()notplayed = sqlContext.sql("select * from data WHERE y like '%n%' ").count()

因为我们需要获得每个属性的信息增益,并找到具有最大信息增益的属性,所以我们将对所有属性的信息增益计算应用相同的逻辑。创建“流程 _ 数据集”函数。

def process_dataset(excludedAttrs, data, played, notplayed, where_condition):
  • excludedAtttts 将包含已经处理过的属性列表,因此我们不需要再次处理。
  • 数据是该文件的 spark 数据帧
  • 比赛时间——计算比赛时间
  • 未播放—当比赛未播放时计数
  • Where_condition —用于选择数据的条件,在处理属性时,我们会不断更改此条件

让我们从主函数中调用这个函数,

def main(): data = sqlContext.read.format('com.databricks.spark.csv').option('header', 'true')\ .option('delimiter', ';').load("/home/me/ml/practice/decision_tree/datasets/simple_dataset") data.registerTempTable('data') played = sqlContext.sql("select * from data WHERE y like  '%y%' ").count() notplayed = sqlContext.sql("select * from data WHERE y like  '%n%' ").count() process_dataset([], data, played, notplayed, '')

2)加工数据

Process_dataset 将首先计算数据集的熵,然后获得每个属性的信息增益。

我们将声明全局级变量来存储属性的信息增益。并且还会创建有向图来可视化决策树。

attr_name_info_gain = {}G = nx.DiGraph()

让我们也声明数据集的模式。我创建了两个变量来存储模式和类型。如果愿意,您可以创建一个并相应地修改后续代码。

attrs = ["outlook","temp","humidity","wind"]attrs_type = {"outlook":"string","temp":"string","humidity":"string","wind":"string"}

流程 _ 数据集函数

def process_dataset(excludedAttrs, data, played, notplayed, where_condition): total_elements = played + notplayed subs_info = {"played" : played, "notplayed" : notplayed} entropy = calculate_entropy(total_elements, subs_info) print "entropy is " + str(entropy) global attr_name_info_gain attr_name_info_gain = dict() for attr in attrs: if attr not in excludedAttrs: get_attr_info_gain_data_prep(attr, data, entropy, total_elements, where_condition)

它调用 calculate_entropy 函数,然后为每个属性调用 get_attr_info_gain 函数。

3)计算 _ 熵函数

def calculate_entropy(total_elements, elements_in_each_class): *# for target set S having 2 class 0 and 1, the entropy is -p0logp0 -p1logp1* *# here the log is of base 2* *# elements_in_each_class is a dictionary where the key is class label and the* *# value is number of elements in that class* keysInMap = list(elements_in_each_class.keys()) entropy = 0.0 for aKey in keysInMap: number_of_elements_in_class = elements_in_each_class.get(aKey) if number_of_elements_in_class == 0: continue ratio = number_of_elements_in_class/total_elements entropy = entropy - ratio * np.log2(ratio) return entropy

4)属性信息增益数据准备功能

def get_attr_info_gain_data_prep(attr_name, data, entropy, total_elements, where_condition): if not where_condition:
       attr_grp_y = data.where(col('y') == 'yes').groupBy(attr_name).agg({"y": 'count'})\
           .withColumnRenamed('count(y)','played_count')
   else:
       attr_grp_y = data.where(" y like '%yes%'  " + where_condition).groupBy(attr_name).agg({"y": 'count'})\
           .withColumnRenamed('count(y)','played_count') if not where_condition:
       attr_grp_n = data.where(col('y') == 'no').groupBy(attr_name).agg({"y": 'count'})\
           .withColumnRenamed(attr_name,'n_' + attr_name)\
           .withColumnRenamed('count(y)','not_played_count')
   else:
       attr_grp_n = data.where(" y like '%no%'  " + where_condition).groupBy(attr_name).agg({"y": 'count'})\
           .withColumnRenamed(attr_name,'n_' + attr_name)\
           .withColumnRenamed('count(y)','not_played_count') joined_df = attr_grp_y.join(attr_grp_n, on = [col(attr_grp_y.columns[0]) == col(attr_grp_n.columns[0])], how='outer' )\
       .withColumn("total", col(attr_grp_y.columns[0]) + col(attr_grp_n.columns[0]))\
       .select(attr_grp_y.columns[0], attr_grp_y.columns[1],\
                attr_grp_n.columns[1]) \ gain_for_attribute = calculate_info_gain(entropy, joined_df, total_elements)
   attr_name_info_gain[attr_name] = gain_for_attribute

功能说明

它从文件中读取数据。当我们构建树时,我们将只需要获得对应于树的那个分支的数据。“where_condition”属性将包含这些谓词。

对于传递的属性名称,我们将文件中结果为“是”的记录分组

  • 第一次,where_condition 将为空,
  • 第二次迭代之后,在找到树根之后,我们将得到 where_condition
if not where_condition:
   attr_grp_y = data.where(col('y') == 'yes').groupBy(attr_name).agg({"y": 'count'})\
       .withColumnRenamed('count(y)','played_count')
else:
   attr_grp_y = data.where(" y like '%yes%'  " + where_condition).groupBy(attr_name).agg({"y": 'count'})\
       .withColumnRenamed('count(y)','played_count')
  • 类似地,它将文件中结果为“否”的记录分组为传递的属性名。
if not where_condition:
   attr_grp_n = data.where(col('y') == 'no').groupBy(attr_name).agg({"y": 'count'})\
       .withColumnRenamed(attr_name,'n_' + attr_name)\
       .withColumnRenamed('count(y)','not_played_count')
else:
   attr_grp_n = data.where(" y like '%no%'  " + where_condition).groupBy(attr_name).agg({"y": 'count'})\
       .withColumnRenamed(attr_name,'n_' + attr_name)\
       .withColumnRenamed('count(y)','not_played_count')
  • 我们将列 count(y) 重命名为 played_count,将 count(n) 重命名为 not_played_count
  • 将 attr_name 列重命名为 n
.withColumnRenamed(attr_name,'n_' + attr_name)\
  • 现在,我们将这两个数据帧连接起来,一个具有该属性“是”结果的计数,另一个具有同一属性“否”结果的计数
joined_df = attr_grp_y.join(attr_grp_n, on = [col(attr_grp_y.columns[0]) == col(attr_grp_n.columns[0])], how='outer' )\

我们在属性名上连接。我们需要外部连接,如果一个属性没有“是”或“否”结果的记录,那么我们仍然需要当前的“是”或“否”计数。

此外,由于我们有是和否结果的计数,我们还需要总计数(有是和否的记录总数)来计算熵。因此,我们添加了一个新列,其中包含总数

.withColumn("total", col(attr_grp_y.columns[0]) + col(attr_grp_n.columns[0]))\

我们不会选择连接列两次

.select(attr_grp_y.columns[0], attr_grp_y.columns[1],\
        attr_grp_n.columns[1])

我们做了所有这些练习来计算这个特定属性的信息增益,所以让我们来计算一下

gain_for_attribute = calculate_info_gain(entropy, joined_df, total_elements)

我们将在全局变量 attr_name_info_gain 中保存该属性**的信息增益。**我们稍后将对该字典进行排序,以获得具有最大信息增益的属性。接下来描述调用的 Calculate_info_gain 函数。

gain_for_attribute = calculate_info_gain(entropy, joined_df, total_elements)  *#*
 attr_name_info_gain[attr_name] = gain_for_attribute

5)信息增益功能

def calculate_info_gain(entropy, joined_df, total_elements):
   attr_entropy = 0.0
   for anAttributeData in joined_df.rdd.collect():
       yes_class_count = anAttributeData[1]
       no_class_count = anAttributeData[2]
       if yes_class_count is None:
           yes_class_count = 0
       elif no_class_count is None:
           no_class_count = 0 count_of_class = yes_class_count + no_class_count
       *# do the summation part e.g. if age is 56, 60, 45 then its sum of entropy for each of these element*
       classmap = {'y' : yes_class_count, 'n' : no_class_count}
       attr_entropy = attr_entropy + ((count_of_class / total_elements) *\
                                      calculate_entropy(count_of_class, classmap)) gain = entropy - attr_entropy return gain

如果您已经阅读了前面的章节,那么这个函数是不言自明的

6)再次返回主功能

我们一直处理到这个代码行—->“process _ dataset([],data,played,notplayed, '' )”

def main():
   data = sqlContext.read.format('com.databricks.spark.csv').option('header', 'true')\
       .option('delimiter', ';').load("/home/me/ml/practice/decision_tree/datasets/simple_dataset") data.registerTempTable('data')
   played = sqlContext.sql("select * from data WHERE y like  '%y%' ").count()
   notplayed = sqlContext.sql("select * from data WHERE y like  '%n%' ").count()
   process_dataset([], data, played, notplayed, '')
   *# sort by info gain*
   sorted_by_info_gain = sorted(attr_name_info_gain.items(), key=operator.itemgetter(1), reverse=True) processed_attrs = []
   max_gain_attr = sorted_by_info_gain[0][0]
   processed_attrs.append(max_gain_attr)
   build_tree(max_gain_attr, processed_attrs, data, '') nx.draw(G, with_labels=True)
   plt.show()

对信息增益函数进行排序,得到增益最大的属性,将其作为根节点。现在我们调用构建树函数。这是最后一个也是最重要的功能。

此方法的输入是具有最大信息增益的属性的名称。这将成为树的根节点。我们希望获得该属性的不同值。这些值将成为该节点的分支。

这个函数将递归地构建完整的树。

def build_tree(max_gain_attr, processed_attrs, data, where_condition):
   attrValues = sqlContext.sql("select distinct " + max_gain_attr + " from data  where 1==1 " + where_condition)
   orig_where_condition = where_condition for aValueForMaxGainAttr in attrValues.rdd.collect():
       adistinct_value_for_attr = aValueForMaxGainAttr[0]
       G.add_edges_from([(max_gain_attr, adistinct_value_for_attr)]) if attrs_type[max_gain_attr] == "string":
           where_condition = str(orig_where_condition + " and " + max_gain_attr + "=='" + adistinct_value_for_attr + "'")
       else:
           where_condition = str(orig_where_condition + " and " + max_gain_attr + "==" + adistinct_value_for_attr) played_for_attr = sqlContext.sql("select * from data where y like '%yes%' " + where_condition).count()
       notplayed_for_attr = sqlContext.sql("select * from data where y like '%no%' " + where_condition).count()
       *# if either has zero value then entropy for this attr will be zero and its the last attr in the tree*
       leaf_values = []
       if played_for_attr == 0 or notplayed_for_attr == 0:
           leaf_node = sqlContext.sql("select distinct y from data where 1==1 " + where_condition)
           for leaf_node_data in leaf_node.rdd.collect():
               G.add_edges_from([(adistinct_value_for_attr, str(leaf_node_data[0]))])
           continue process_dataset(processed_attrs, data, played_for_attr, notplayed_for_attr, where_condition)
       if not attr_name_info_gain: *# we processed all attributes*
           *# attach leaf node*
           leaf_node = sqlContext.sql("select distinct y from data where 1==1 " + where_condition)
           for leaf_node_data in leaf_node.rdd.collect():
               G.add_edges_from([(adistinct_value_for_attr, str(leaf_node_data[0]))])
           continue *# we are done for this branch of tree* *# get the attr with max info gain under aValueForMaxGainAttr*
       *# sort by info gain*
       sorted_by_info_gain = sorted(attr_name_info_gain.items(), key=operator.itemgetter(1), reverse=True)
       new_max_gain_attr = sorted_by_info_gain[0][0]
       if sorted_by_info_gain[0][1] == 0:
           *# under this where condition, records dont have entropy*
           leaf_node = sqlContext.sql("select distinct y from data where 1==1 " + where_condition)
           *# there might be more than one leaf node*
           for leaf_node_data in leaf_node.rdd.collect():
               G.add_edges_from([(adistinct_value_for_attr, str(leaf_node_data[0]))])
           continue *# we are done for this branch of tree* G.add_edges_from([(adistinct_value_for_attr, new_max_gain_attr)])
       processed_attrs.append(new_max_gain_attr)
       build_tree(new_max_gain_attr, processed_attrs, data, where_condition)

解释

我们希望节点有不同的值。

attrValues = sqlContext.sql("select distinct " + max_gain_attr + " from data  where 1==1 " + where_condition)

对于该节点的每个值

for aValueForMaxGainAttr in attrValues.rdd.collect():

获取该迭代下的属性值

adistinct_value_for_attr = aValueForMaxGainAttr[0]

将此值添加为节点的分支

G.add_edges_from([(max_gain_attr, adistinct_value_for_attr)])

我们需要得到这个属性值下的数据。如果树是

我们正在处理父节点的“Sunny”值,然后在同一个分支(outlook -> sunny)下继续,我们需要获得 outlook = sunny 的数据。所以我们把它作为新的 where 条件添加进来。

此外,如果我们需要在引号下添加值时属性类型是 string,而它是 int 类型,那么我们不添加引号。

if attrs_type[max_gain_attr] == "string":
           where_condition = str(orig_where_condition + " and " + max_gain_attr + "=='" + adistinct_value_for_attr + "'")
       else:
           where_condition = str(orig_where_condition + " and " + max_gain_attr + "==" + adistinct_value_for_attr)

我们将再次从属性列表中找出具有最大信息增益的属性,不包括已经被处理的属性。因此,对于父属性的这个值,我们想知道有多少记录的结果为“是”和“否”

played_for_attr = sqlContext.sql("select * from data where y like '%yes%' " + where_condition).count()
notplayed_for_attr = sqlContext.sql("select * from data where y like '%no%' " + where_condition).count()

如注释所述,如果我们得到的熵值为零,那么我们就到达了这个分支的叶节点,我们只需将结果添加到这个节点下的树中。

*# if either has zero value then entropy for this attr will be zero and its the last attr in the tree*
       leaf_values = []
       if played_for_attr == 0 or notplayed_for_attr == 0:
           leaf_node = sqlContext.sql("select distinct y from data where 1==1 " + where_condition)
           for leaf_node_data in leaf_node.rdd.collect():
               G.add_edges_from([(adistinct_value_for_attr, str(leaf_node_data[0]))])
           continue

如果没有,那么我们继续处理。类似下面的代码已经在主函数中处理并解释过了。也许我们应该把这一次迭代也作为这个递归的一部分,让这成为你的练习。

process_dataset(processed_attrs, data, subscribed_for_attr, unsubscribed_for_attr, where_condition)
if not attr_name_info_gain: *# we processed all attributes*
   *# attach leaf node*
   leaf_node = sqlContext.sql("select distinct y from data where 1==1 " + where_condition)
   for leaf_node_data in leaf_node.rdd.collect():
       G.add_edges_from([(adistinct_value_for_attr, str(leaf_node_data[0]))])
   continue *# we are done for this branch of tree**# get the attr with max info gain under aValueForMaxGainAttr*
*# sort by info gain*
sorted_by_info_gain = sorted(attr_name_info_gain.items(), key=operator.itemgetter(1), reverse=True)
new_max_gain_attr = sorted_by_info_gain[0][0]
if sorted_by_info_gain[0][1] == 0:
   *# under this where condition, records dont have entropy*
   leaf_node = sqlContext.sql("select distinct y from data where 1==1 " + where_condition)
   *# there might be more than one leaf node*
   for leaf_node_data in leaf_node.rdd.collect():
       G.add_edges_from([(adistinct_value_for_attr, str(leaf_node_data[0]))])
   continue *# we are done for this branch of tree*G.add_edges_from([(adistinct_value_for_attr, new_max_gain_attr)])
processed_attrs.append(new_max_gain_attr)
build_tree(new_max_gain_attr, processed_attrs, data, where_condition)

现在,如果我们执行了 main 函数的最后两行,那么您可以直观地看到构建的决策树:-)

nx.draw(G, with_labels=True)
plt.show()

尽情享受吧!!!如果可能的话,提供关于拼写错误或任何其他此类编辑(没有做任何审查或校对),关于算法,优化等的反馈。

机器学习-新兴技术简讯-2017 年 9 月 19 日

原文:towardsdatascience.com/machine-lea…

那么是什么让这些新兴技术如此引人注目呢?几乎很难说。毕竟他们还在不断涌现。我妻子喜欢说,我们人类保留了很多动物本能。我们能感觉到一些东西:危险、变化、敌意、积极的振动等等。我认为新兴技术也有一些这样的东西。我们认为他们将会是有影响力的、决定性的、游戏改变者、生活改变者,但我们几乎不知道具体是如何以及为什么。我们已经习惯了自然语言处理,使用谷歌搜索或 siri,我们习惯了无人机在战区、足球比赛、玉米地和冲浪点上空盘旋。我们每天都生活在网络安全之中。 我创办这份时事通讯是为了填补我发现的一个空白。工程师、开发人员、博士、技术人员的机会很多,但非技术人员、普通业务经理的机会不多。最终,他们将使一项技术成功,一旦他们得到它,一旦他们知道用特定的技术制造哪种产品,事情就会好转。因此,这里我们将重点放在业务应用上。希望有帮助!

机器学习 一切关于我们如何教算法变得更聪明

谷歌于 2016 年推出的移动通讯应用Allo 是该公司试图使用机器学习来进行聊天,如果不是更智能,那么至少更有用和更有表现力。你使用 Allo 越多,它的算法就越能确定你听起来像什么,并产生听起来不固定的预先写好的反应。此外,Allo 可以学习你如何与不同的收件人发短信,因此它可以提供一个“好伙计”来回复你最好的朋友,但不是在你给妈妈发短信时。智能回复还有一个隐秘的目的:向用户介绍谷歌助手,Allo 内部的真正大脑,以及该公司新的谷歌 Home 智能音箱

Amperity 是一家曾经默默无闻的初创公司,它正在为品牌推出一个机器学习平台。诀窍在于: Amperity 不是使用算法将现有规则应用于数据集,而是根据实时上传的信息,在没有人工干预的情况下,教会其算法开发自己的规则。“这个系统正在自我训练,”沙哈尼说。“这使得整个模型更加有效。”那又怎样;有什么大不了的?品牌与 Amperity 的集成方式与它们与数据管理平台的集成方式相同。随着不断吸收原始数据,Amperity 将机器学习应用于重复数据删除记录、创建身份匹配和开发客户资料,这些资料可以被激活用于目标定位、细分、创建相似的受众、媒体购买——所有常见的东西。不同寻常的是 Amperity 在开放生态系统中对身份的处理方式。“像脸书、谷歌或 GitHub 这样的系统首先通过认证建立一个通用身份,为该身份打开一个工具生态系统,”Amperity 的工程副总裁和脸书的前移动工程高管戴夫·费特曼说。Fetterman 说,相比之下, Amperity 在一个组织内“跨不同的数据库”创建身份匹配。在某种意义上,这与围墙花园接近身份的方式相反。

零售中,机器学习可以对供应链产生重大影响。由于物联网,各种传感器、信标、远程访问数据收集器都可以用来建立数据清单。这些数据可以跟踪起点、路线、接触点、条目,机器将开始从这些数据点中学习。然后,分析工具可以预测延迟,以天、小时、周为单位,并发送通知

Broadcast 中,BBC 新闻实验室的一名高级广播系统开发人员表示,该广播公司希望使用机器学习来帮助其记者应对他们在报道重大事件时面临的“内容海啸”。比万说:“想想英国 6 月份的大选,一系列外部消息来源都会参与进来。我们如何使用丰富的元数据并将机器学习技术应用于我们伦敦新闻编辑室中试图在我们的系统中找到内容的数千名记者?

**那么,机器学习泡沫何时会破裂?**根据回答 Coursera 联合创始人吴恩达;斯坦福大学的兼职教授在 Quora 上说:“大约 100 年前,这里有很多关于电力的宣传。这个特殊的泡沫还没有破裂,我们发现电非常有用!更严重的是,因为深度学习已经创造了大量的价值——它被用于网络搜索、广告、语音识别、推荐系统等等— 它显然会继续存在。深度学习,加上更广泛的其他人工智能工具(图形模型,规划,KR 等。),现在已经有了一个清晰的行业转型路径。它的影响将远远超出技术领域。”新闻不断证实安德鲁的观点。脸书将在蒙特娄开设一个研究中心实验室。亚马逊正在巴塞罗纳开设一个机器学习实验室。 本周机器学习:

  • 移动支付公司 iZettle 为 R&D 筹集了 3600 万美元的债务,用于人工智能、机器学习等领域链接
  • 总部位于里士满的机器学习公司 Notch 正在将城市放到地图上链接
  • 机器学习正在释放 3D 打印的潜力链接
  • 严肃对待研究伦理:人工智能和机器学习链接
  • 关于机器学习你应该知道的 10 件事链接
  • 机器学习可用于阻止欺诈链接
  • 计算机科学家正在寻找将好奇心编码到智能机器中的方法。链接

那么,你认为机器学习在你的行业中应用于何处? 您是否看到了在贵公司使用机器学习的商业案例? 你认为你已经准备好使用机器学习了吗?

请在评论中告诉我们你的想法。

谢谢

Melvin Manchau 是一名管理顾问,专门从事金融机构的业务运营、技术和战略。此处表达的观点是他个人的观点,不代表预委会的观点。

机器学习工程 1:房屋销售估算。

原文:towardsdatascience.com/machine-lea…

Visualization of a Custom Loss Function

这篇博客文章将是如何作为机器学习(ML)工程师思考的第一课。我们将研究一个监督学习问题,重点是设计一个定制的损失函数。用这样的技巧思考,你会自信地获得一个入门级的 ML 工程师角色。

这篇博文假设你对现代 ML 有一个基本的了解。

非技术性的序言,请阅读https://medium . com/@ leetandata/machine-learning-preamble-ba 69 BCA 4701d

关于数学和数字代码的详细解释,从https://medium . com/@ leetandata/neural-network-introduction-for-software-engineers-1611d 382 C6 aa开始

有关在 Windows 上安装 Python 进行机器学习的说明,请阅读:https://medium . com/@ leetandata/basic-Python-setup-for-ml-for-Windows-users-aaadb 2 be 534 c

问题介绍

眼下的问题是从模拟数据集中估算出售一套公寓所需的时间。

数据是上市日期、销售日期(如果公寓已经售出)、价格和公寓的数字特征。

回归快速回顾

回归将要素数据作为向量。每个数据点被定义为一些输入特征,例如关于房子的特征。回归模型使用这些特征来预测目标(它猜测 Yhat,这意味着从数据集中逼近真实的 Y 或目标)。该模型通过从数据集学习来训练自己,以最小化损失函数。

回到我们的具体问题

对于简单的回归问题,您的数据以包含要素 X 和目标值 y 的数据集的形式提供给您。您将数据集分为训练集和验证集,在训练集上训练模型,并在验证集上验证其性能。

公寓销售估算类似于简单的回归问题,但提出了 ML 必须考虑的四个错综复杂的问题:

  • 首先,我们需要划分数据。我们将使用一些数据(称为训练数据)来训练我们的模型,并使用一些数据来验证我们训练的模型的性能。对于一般数据集,我们可以随机划分数据集。对于时间序列数据,我们可以将数据切碎,在截止日期之前对数据进行训练,并在截止日期之后对数据进行验证。这模拟了如果我们对过去进行训练,并发布它来实时预测未来,模型会做得有多好。与大多数时间序列问题相比,这对于该数据集来说很困难,因为每个样本都有两个时间戳,即上市日期和销售日期。
  • 其次,我们并不总是知道正确的销售日期。对于尚未售出的公寓,我们知道它们的销售日期发生在数据集中的最后一次销售之后,但我们不知道最后一次销售是什么时候。如果有时我们只知道一个最小值而不知道真实值,我们如何创建我们的损失函数。
  • 第三,我们注意到输入要素数据有缺失值。我们该怎么办?有人可能只是忘记列出卧室或浴室的数量或公寓的平方英尺。我们将探索处理这种复杂性的几种选择。
  • 最后,用来评估我们模型的许多性能的最有意义的评估指标是什么?我们想使用一些标准的东西,如均方差或 T2 R2 系数,但是我们怎么能计算更大的值而不关心小的差异呢?例如,1 天和 5 天看起来差别很大,但是 81 天和 85 天应该被认为是非常准确的。在不知道还没卖出去的房子的真实价值的情况下,我们该怎么做呢?

1:培训/验证/测试步行前进优化

通常情况下,在机器学习中,我们会随机划分(具体数字会因问题而异)70%的数据用于训练模型,20%的数据用于验证性能,10%的数据用于测试发布性能。

我们反复地改变模型、训练和验证,直到我们的验证准确性达到最大。我们相信推广到新的看不见的数据的模型表现最好,所以我们利用在验证集上表现最好的模型。

最后,我们在测试集上评估一次,以估计我们的模型在现实世界中的推广程度。通过这种方式,我们可以构建复杂的模型来表示我们的数据,然后计算不会高估我们对其性能的估计的指标。

Walk Forward Optimization

在时间序列建模中,我们使用前推优化,将时间序列分成许多时间截止点 T1、T2、T3 等。我们首先对 T1 之前的数据进行训练,并在 T1 和 T2 之间的时间段验证我们的性能。然后,我们将我们的训练数据集扩展到 T2,然后在 T2 和 T3 之间的时间段进行验证。因此,我们的整体验证性能指标是来自不同数据切片的平均验证性能,我们的测试集可以是数据的最后一个时间片,或者是从验证数据点中排除的不同时间片中的一些数据点。

但是,我们注意到每个时间步都有两个数据点:上市日期和销售日期。所以,如果我们训练到 T1,那么到那时我们实际上已经知道了什么?

在培训期间,我们将了解 T1 之前的所有列表。在这些公寓中,我们将隐藏 T1 之后的所有销售日期。

在验证过程中,我们需要验证在 T1 和 T2 之间售出的所有公寓,以及在 T2 之前上市但在 T1 之后才售出的所有房源。为了简化我们的验证集,我们验证了在 T1 之后销售、在 T2 之前上市的产品的性能。

以上是至关重要的,因为它允许我们使用所有可用的数据来训练和验证,但不要过于乐观,不允许我们自己欺骗和预见未来。避免数据泄露或作弊在机器学习中非常重要,因为数据泄露让我们相信我们的模型不切实际地准确。然后,我们可以发布我们的模型,并对它在新数据上的表现感到非常惊讶。

2:有意义的损失函数

让我们为问题提出一个合理的基线损失函数。我们关心出售公寓的时间和预测时间之间的差异,我们越是偏离,就越需要修正我们的预测。因此,我们可以提出均方误差(MSE)。但在某种程度上,如果一套公寓在 1 天内售出,而我们预测是 10 天,那么我们就比公寓在 81 年售出,而我们预测是 90 天的情况要差得多。因此,也许我们应该使用均方差百分比误差(MSPE),其中我们根据我们预测的百分比来惩罚模型。这两者似乎都有道理,但既然我们都关心,就让我们取两者的几何平均值,并将其作为我们的损失函数,将两者都考虑在内。这不是业务可解释,但它是我们的损失函数,并不一定是我们的评估度量。我们稍后会谈到这一点。

那么,如果一套公寓卖不出去会怎么样呢?假设一套公寓在 T0 时上市,训练集截止到 T1,但该公寓在 T2 售出(或者从未售出)。在 T1,公寓仍未售出,我们假装看不到 T1 之后的未来,因此我们需要将公寓标记为“尚未售出”。那么我们如何利用这个数据点来改进我们的模型呢?

假设我们的模型预测公寓将在 T0 和 T1 之间出售。在这种情况下,我们知道模型是错误的,并且模型应该预测更大的数字,所以让我们假设在这种情况下真实值是定型数据集的结尾。

但是如果我们的模型预测的值大于 T1 呢?我们不知道这是太大还是太小,因为它正确地在我们的训练数据集结束后,所以我们不要在这种情况下给我们的模型一个损失函数。

通过这种方式,我们使用所有可用的数据,并使用有意义的损失函数优化我们的模型,以获得有商业价值的近似值,从而最小化百分比误差!

3:数据插补

有人忘了在我们的一些数据点上列出卧室或浴室的数量或公寓的平方英尺数。但我们是那些被随意遗忘或被有意忽略的人吗?

我们为每个特征创建额外的标志,来表示数据是否丢失,我们将这些标志输入到模型中,并填充丢失的值。

为了填充缺失的值,我们可以有一个独立的网络来学习预测值或其他自定义解决方案(这对于语言、图像或音频等结构化数据非常流行),但对于我们的情况,让我们只手动输入日期。两种流行的方法是用所在字段的平均值替换缺失值,或者找到一些非常相似的公寓并用相似公寓的平均值替换缺失值。

我们称寻找相似的数据点为插补K-最近邻(KNN) 插补。其工作方式是,我们找到 K 个数据点,这些数据点最接近具有缺失特征的数据点。对于缺失的特征,我们取该特征的 K 个最近点值的平均值。

使用欧几里德距离来测量“最近邻”听起来很合理,但是如果一个要素的值在 0-1000 之间,而另一个要素的值在 0-1 之间呢?在这种情况下,具有大尺度的特征将比小特征更大地影响欧几里德距离。例如,x1,x2 = [600,0.1]可能比[580,0.2]更接近[590,0.9],即使两者具有非常相似的 x1 值,而它们的 x2 值完全在范围的两端。

我们如何使所有特征对“最近邻”插补产生相似的影响?让我们通过首先缩放特征来标准化它们的影响,这样它们都具有均值 0 和标准差 1,这样每个特征对插补都有相同的影响!

4:评估指标

设计有意义的评估指标是任何 ML 项目最重要的任务之一。最能代表“这种模式学点商业有意义的东西”的数字有哪些?

一些工程师有一个坏习惯,坚持使用现成的指标,如均方差,或他们的预测和真实值之间的相关性。然后,他们将这些数字呈现给商业成员,这些商业成员会对这些毫无意义(理所当然)的技术术语感到沮丧。在我们的例子中,我们可以使用许多度量标准,比如时间对数的皮尔逊相关系数,但是这很难解释。

相反,让我们使用业务最简单的基线,平均绝对百分比误差(MAPE) ,它告诉我们您的预测和真实值之间的比率的平均绝对值。为了解释这一指标,0.1 的值平均表示与真实值相差 10%。值 0.2 表示与真实值的平均值相差 20%,例如与正确值的平均值相差 80%或 120%。这个度量不能是负数,0 代表完美。

但是未知的值呢?让我们用 MAPE 来表示我们知道其真实价值的值,让我们用另一个指标来表示未售出公寓中被正确归类为未售出公寓的百分比(销售日期预计超过数据集的末尾)。我们还可以通过假装在数据集的最后一天售出的公寓来替换未售出的公寓,并以此计算 MAPE,这将更容易解释,但不太准确。

对于评估指标,像业务人员一样思考

所以作为一个数学家,我们写了一个优化函数。接下来,我们编写了一个评估函数来构建可解释的结果。但这是理解我们表现的最有意义的方式吗?在这种情况下,答案是否定的,因为我们真的没有尝试去思考什么对我们的问题有意义。

我们计算了一个总结模型性能的指标。很棒?但是我们不应该总结的太全面!我们的数据给我们带来了影响我们性能的重要特性复杂性。一些公寓在一周后售出,一些在一年后售出。此外,一些公寓的价格高达数万,一些高达数千万。特别是因为我们的评估指标是误差除以实际销售时间,我们建议按实际销售时间区域对我们的准确度进行分组,并绘制这些值的平均值和四分位间距

这样,我们可以问这样的问题“对于快速销售的房屋,我们大约打了 X1 折,但是对于我们将在市场上停留更长时间的房屋,我们大约打了 X2 折”。有了这些,商业人士和数学家都应该更乐意了解他们的模型是如何运行的。

转换点:从想法到代码

哇!以上内容很多。我们覆盖了

  • 有意义的 train/val 前向优化循环
  • 自定义损失函数
  • 如何处理缺失的功能
  • 有意义的评估指标和图形表示

我们现在已经完成了概念的提出,所以现在我们只需要实现上面的想法!

履行

让我们从一些导入开始,为评估指标的图像创建一个目录,并读入我们的数据集。

我们的数据在 Pandas 数据框架中,这很像 SQL 表。它的顶部如下图所示:

Pandas DataFrame Data Table

数据准备

现在我们都准备好了。现在让我们构建一个函数,让我们为我们的训练/测试分割切割数据。我们需要接受数据切片的可选开始日期和可选结束日期。

该函数分割整个数据集,只保留开始日期之后或结束日期之前的数据。这将有助于建立训练和验证数据集。

现在我们需要一个定标器来标准化我们的数据,为插补做准备。定标器从训练数据中学习如何归一化,并将这些归一化参数(平均值和标准偏差)应用于验证数据集。

我们还需要从我们的训练数据构建一个估算器,学习估算缺失值,并且我们需要能够将它应用于训练数据集和验证数据集。

上面的代码准备了我们模型的输入数据。

现在来说说我们的目标变量!我们的目标变量是公寓上市和售出之间的天数。当公寓尚未售出时,销售日期设置为当天,我们有一个已售出标志来表示公寓是否已经售出(我们稍后将使用这两个标志)

使用 Tensorflow 建模

我们的模型接受一些输入特征。它有占位符来接受每个数据点的值,售出(公寓是否售出)、x(输入要素)和 y(公寓售出前的天数)。

该模型使用神经网络(简单解释详细解释)来预测公寓需要多长时间才能出售。然后,It 计算损失函数和评估指标,并构建优化器来最小化损失函数。

我们还创建列表来跟踪我们在整个训练过程中的表现,并计算其他损失函数,只是为了在教程中演示。

这里,我们为一个时期训练模型,这是为了将每个数据点看一次并最小化损失函数

我们通过在验证数据集上检查 MAPE 来验证我们的性能。

培训是一个时期的培训和验证我们表现的过程。我们多次调用这个过程来从数据集学习并跟踪我们的表现。

最后,让我们通过跟踪训练和验证损失,以及预测和实际情况之间的 r2 分数来可视化模型的性能。

上面生成了类似下面的图,x 轴是训练的时期,y 轴是损失和 r2 分数:

Sample of what our validation function creates

训练模型

太好了!现在,最后,让我们在一个训练集上进行训练,并在接下来的时间里进行验证。我们将使用上面定义的代码来分割数据集和训练模型。最后,让我们返回我们的最终性能,以便我们可以在向前优化过程中进行跟踪。

总结:我们做了什么?

  1. 我们分割数据,

2.学会了根据训练集缩放和估算数据,

3.将缩放和估算应用于验证数据集,

4.定义我们的模型,训练我们的模型,然后

5.可视化的训练表现。

所有这些都是通过调用我们之前定义的函数来实现的。

向前优化

既然我们已经进行了培训和验证,让我们继续浏览数据集,在后续阶段进行培训和验证。

最后,让我们直观地了解一下整个过程中的前进优化性能。

这产生了关于前推优化切割的最终验证性能的曲线。

最后,下面是从第一个到最后一个截止点运行完整模型的代码,如代码部分开头所定义的。

按组标绘性能

现在我们选择按销售持续时间分组,看看我们的误差百分比在组内如何变化。为了说明我们想要的最终输出(我们将在下面得到),我们提供了下面的图表:

这些图像是通过以下函数调用绘制的,每行一个图像

最后,在下面,我们给出了生成上述图像的代码。

总结

我们做到了!我们使用训练/验证分割来准备数据集,标准化输入数据,输入缺失值,将模型拟合到训练数据集,在验证数据集上进行验证,并在向前优化循环中完成整个结构!呜!

因此,现在我们已经准备好并且可行,我们可以在我们的完整数据集上训练我们的模型,并将其发布到世界上,我们对它在未来分类中的表现有一个预期(根据上述曲线,它的平均绝对百分比误差约为 30%)。

前言如果你有点迷路了,浏览了这篇文章,忘记了我们为什么要用机器学习以及我们在说什么:https://medium . com/@ leetandata/Machine-Learning-前言-ba69bca4701d

数学重磅跟进:https://medium . com/@ leetandata/neural-network-introduction-for-software-engineers-1611d 382 C6 aa

本帖综合来源:https://github . com/leedtan/LeeTanData/blob/master/SimpleML _ house sales/house predictions . ipynb

机器学习,快与慢

原文:towardsdatascience.com/machine-lea…

模型的记忆和概括

假设你经营一家名为米其林人的餐厅点评网站。你从用户那里收集了大量评论,并想分析它们是否连贯

一位刚刚在意大利餐厅用餐的用户写道:

我喜欢这种调料。

解决这个问题的一个常见方法是在单词级别查看消息。

["i", "like", "the", "dressing", "."]

一般化

你可以从理解每个单词的意思开始,通过在大量文本数据上训练一个模型来生成单词表示有很多技术可以做到这一点,但本质上,一个单词最终将由一个数字向量来表示。

like = [.03, -1.45, ..., 0.45, 0.74]

因为这些单词表示是在一大组文本(比如整个互联网)中学习的,所以它们是可概括的。换句话说,你可以把单词“like”的意思编码出来,并把它们放在各种其他的上下文中(例如 SMS 文本、短文写作等)。)而且总体来说,它们会非常合适。

如果您在向量空间中可视化这些表示,您将看到相似的单词将聚集在一起。

Word representations (hence, words) that are similar should be close in vector space. Credit: Colah and Turian.

假设另一个人写道:

我喜欢这种调料。

["i", "admire", "the", "dressing", "."]

现在,“钦佩”和“喜欢”被认为是同义词。因此,各自的单词表示应该相似。

word_similarity("like", "admire") = high

太好了!假设单词表示或多或少是自动学习的,这种学习单词之间关系的方法是可扩展的和有用的。

词语表征的概括能力可以扩展到连贯。定义连贯性的一种方法是看一对词在同一语境中是否搭配得很好。一个简单的计算方法是比较一个句子中两个单词的相似度。

因此,从上面的例子中,你可以分离出单词“dressing ”,并检查它是否与单词“like”和“appraise”兼容。

word_similarity("like", "dressing") = somewhat highword_similarity("admire", "dressing") = somewhat low

这也有道理,“喜欢”比“佩服”更相似。

然而,从上面看不出“钦佩”和“穿着”是否一致。尽管人们赞美一件“衣服”并不是完全不可思议的,但更有可能的是,用户要么是有创意,要么是弄错了。

一般化的弱点是,它经常在一般情况之外失败,即平均而言。尽管“表示”这个词有很多含义,但它认为将“钦佩”和“穿着”放在句子中是合理的,因为“喜欢”与“钦佩”和“穿着”都很接近。在当前的设置下,即使是从未出现过的单词也只会显示出些许相似。

记住

显示连贯性的一个简单方法是计数。通过统计上面的词对,可以清楚地看出它们以前是否存在过。

在谷歌 Ngram 语料库上快速扫描显示“赞美着装”在之前从未发生过。

counts_in_the_same_sentence("like", "dressing") = somecounts_in_the_same_sentence("admire", "dressing") = none

计数基本上没有普遍性,因为你必须记住每一个可能的组合,这需要大量的记忆。但是这一信息是对从单词表示中得出的概括的补充。

从视觉上看,这两种方法的分布非常明显。使用计数方法,绝大多数单词对将为零,而少数单词对将具有指数级的更高计数。相似性一词更为正态分布,尽管通常是右偏的,所以高相似性聚集在一起。

Counts will approximately be an exponential distribution and word similarities will approximately be a normal distribution. Credit: Gunther.

直观地说,这两种方法在其分布斜率最大的地方具有最强的区分能力。计数在低计数时表现良好,而单词表示在高相似度时表现良好。

将不同的模型混合在一起并不是什么新鲜事。如果你想赢得单人游戏比赛,组装几乎是必不可少的。

谷歌最近建立了一个“广度”和“深度”模型,将记忆和归纳模型动态地结合起来。这只是将模型混合在一起的一种方式,但这是向用户展示他们喜欢什么(记忆)和他们可能喜欢什么(概括)的好方法。

面向初学者的机器学习

原文:towardsdatascience.com/machine-lea…

M 机器学习在 90 年代由 亚瑟·塞缪尔 定义为,“ 这是一个研究领域,它赋予计算机自我学习的能力,而无需显式编程 ”,这意味着将知识灌输给机器,而无需硬编码。

机器学习主要专注于开发计算机程序,这些程序可以在接触到新数据时教会自己成长和变化。机器学习研究自我学习做事情的算法。通过学习算法,可以更快地处理海量数据。例如,它会对学习完成一项任务、做出准确的预测或表现得聪明感兴趣。

为什么我们需要机器学习

数据每天都在增长,不可能以更高的速度和更高的准确性理解所有的数据。超过 80%的数据是非结构化的,即音频、视频、照片、文档、图表等。对于人类大脑来说,在地球上的数据中寻找模式是不可能的。数据非常庞大,计算所需的时间会增加,这就是机器学习发挥作用的地方,以帮助人们在最短的时间内处理大量数据。

机器学习是人工智能的一个子领域。通过应用人工智能,我们想要建造更好更智能的机器。这听起来就像一个新生的孩子在自我学习。所以在机器学习中,计算机的一种新能力被开发出来。现在,机器学习出现在如此多的技术领域,以至于我们在使用它时甚至没有意识到它。

机器学习的类型

机器学习主要分为三类,如下所示

Types of Machine Learning

1.监督学习:-

监督学习 是第一种机器学习,其中 标注为 的数据用来训练算法。在监督学习中,使用标记的数据训练算法,其中输入和输出是已知的。我们将数据作为一组输入输入到学习算法中,这些输入被称为特征,由 X 表示,相应的输出由 Y 表示,该算法通过将其实际结果与正确的输出进行比较来发现错误。然后它相应地修改模型。原始数据分为两部分。第一部分用于训练算法,另一部分用于测试训练好的算法。

Supervised Machine Learning

监督学习使用数据模式来预测标签的附加数据的值。这种方法通常用于历史数据预测可能即将发生的事件的应用中。例如:它可以预测何时交易可能是欺诈性的,或者哪个保险客户会提出索赔。

监督学习的类型:-

监督学习主要分为以下两个部分

Types of Supervised Learning

1.1 .回归:-

回归 是监督学习的类型,其中使用标记数据,并且该数据用于以连续的形式进行预测。输入的输出总是持续的,图形是线性的。回归是预测建模技术的一种形式,它调查因变量[ 输出 ]和自变量[ 输入 ]之间的关系。这种技术用于天气预报、时间序列建模、过程优化。例如:回归技术的一个例子是房价预测,房价将根据输入值进行预测,如房间数量、位置、交通便利程度、房龄、住宅面积。

回归算法类型:-

机器学习中有许多回归算法,它们将用于不同的回归应用。一些主要的回归算法如下-

1.1.1 .简单线性回归

在简单的线性回归中,我们根据第二个变量的评分来预测一个变量的得分。我们预测的变量称为标准变量,记为 y。我们预测的变量称为预测变量,记为 x。

1.1.2 .多元线性回归

多元线性回归是回归技术的算法之一,是线性回归分析最常见的形式。作为一种预测分析,多元线性回归用于解释一个因变量与两个或两个以上自变量之间的关系。自变量可以是连续的,也可以是分类的。

1.1.3 多项式回归

多项式回归是另一种形式的回归,其中自变量的最大幂大于 1。在这种回归技术中,最佳拟合线不是直线,而是曲线。

1.1.4 .支持向量回归

支持向量回归不仅可以应用于回归问题,还可以用于分类的情况。它包含了最大间隔算法的所有特征。线性学习机映射将非线性函数倾斜到高维核诱导特征空间中。系统容量由不依赖于特征空间维数的参数控制。

1.1.5 .岭回归:-

岭回归是回归技术中的一种算法。这是一种用于分析多重共线性数据的技术。通过在回归计算中增加一定程度的偏差,可以减少标准误差。净效应将是给出更可靠的计算。

1.1.6 .拉索回归:-

套索回归是一种使用收缩的线性回归。收缩是指数据值向中心点收缩,如平均值。lasso 程序鼓励简单、稀疏的模型(即参数较少的模型)。这种特殊类型的回归非常适合于显示高度多重共线性的模型,或者当您想要自动执行模型选择的某些部分时,如变量选择/参数消除。

1.1.7 .弹性网回归:-

弹性网回归将 L1 范数(LASSO)和 L2 范数(ridge regression)结合到广义线性回归的惩罚模型中,并赋予其稀疏性(L1)和稳健性(L2)特性。

贝叶斯回归:-

贝叶斯回归允许一种合理的自然机制在数据不足或分布不良的情况下生存。它将使您能够将系数放在先验和噪声上,以便先验可以在缺少数据的情况下接管。更重要的是,你可以问贝叶斯回归,它对数据拟合的哪些部分(如果有的话)是有信心的,哪些部分是非常不确定的。

1.1.9 .决策树回归

决策树从回归模型中构建一个类似树结构的表单。它将数据分解成更小的子集,同时相关的决策树也在逐步发展。结果是一个有决策节点和叶节点的树。

1.1.10 .随机森林回归

随机森林也是回归技术中使用的算法之一,它非常灵活,易于使用机器学习算法,即使没有超参数调整。此外,该算法由于其简单性以及可用于回归和分类任务的事实而被广泛使用。它构建的森林是决策树的集合,大部分时间是用“打包”方法训练的。

1.2 .分类:-

分类是一种监督学习类型,其中标记的数据可以使用,并且该数据用于以非连续的形式进行预测。信息的输出并不总是连续的,图形也是非线性的。在分类技术中,算法从提供给它的数据输入中学习,然后使用这种学习来分类新的观察。这个数据集可能仅仅是两类,也可能是多类。分类问题的一个例子是通过训练不同的垃圾邮件单词或电子邮件的算法来检查电子邮件是否是垃圾邮件。

分类算法类型:-

机器学习中有许多分类算法,用于不同的分类应用。一些主要的分类算法如下-

1.2.1 .逻辑回归/分类:-

逻辑回归属于监督学习的范畴;它通过使用逻辑/sigmoid 函数估计概率来测量与一个或多个自变量分类的因变量之间的关系。逻辑回归一般可以用在因变量是二元或二元的地方。这意味着因变量只能取两个可能的值,如“是或否”、“活的或死的”。

1 . 2 . 2 . k-最近的邻居:-

KNN 算法是分类中最简单的算法之一,也是最常用的学习算法之一。一个对象的多数表决通过它的邻居来分类,目的是分配给它的 k 个最近邻居中最常见的类。它还可以用于回归-输出是对象的值(预测连续值)。该值是其 k 个最近邻居的收益的平均值(或中值)。

1.2.3 .支持向量机

支持向量机是一种分类器,其中的判别分类器由分离超平面形式定义。该算法输出对新例子进行分类的最佳超平面。在二维空间中,该超平面是将平面分成两部分的线,其中每一类位于两侧。

1.2.4 .核心支持向量机:-

核 SVM 算法是用于分类技术的算法之一,它是定义为核的数学函数集。核心的目的是将数据作为输入,并将其转换为所需的形式。不同的 SVM 算法使用不同类型的核函数。这些函数可以是不同的类型。例如线性和非线性函数、多项式函数、径向基函数和 sigmoid 函数。

1.2.5 .朴素贝叶斯

朴素贝叶斯是一种分类技术,它基于贝叶斯定理,假设预测器之间是独立的。简而言之,朴素贝叶斯分类器假定一个类中某个特定特征的存在与任何其他函数的存在无关。朴素贝叶斯模型易于构建,对于大规模数据集尤其有用。

1.2.6 .决策树分类

决策树以树结构的形式建立分类模型。一个相关的决策树逐渐发展,同时它将一个大的数据集分解成更小的子集。最终结果是一个有决策节点和叶节点的树。决策节点(例如,根)具有两个或更多分支。叶节点代表一个分类或决策。树中对应于最佳预测器的第一个决策节点,称为根节点。决策树可以处理分类数据和数值数据。

1.2.7 .随机森林分类:-

随机森林是一种监督学习算法。它创造了一个森林,让它看起来很随意。它构建的木头是一个决策树的集合,它大部分时间用“bagging”方法训练决策树算法,这是一个学习模型的组合,增加了整体结果。

2.无监督学习:-

无监督学习是第二种类型的机器学习,其中未标记的数据用于训练算法,这意味着它用于没有历史标签的数据。显示的内容必须由算法计算出来。目的是探索数据并找到其中的一些结构。在无监督学习中,数据是未标记的,原始信息直接输入到算法中,而无需对数据进行预处理,也无需知道数据的输出,并且数据不能分成训练或测试数据。该算法计算出数据,并根据数据段,用新的标签对数据进行聚类。

Unsupervised Machine Learning

这种学习技术对事务性数据非常有效。例如,它可以识别具有相似属性的客户群,然后在营销活动中以相似的方式对待他们。或者它可以找到区分不同客户群的主要品质。这些算法还用于分割文本主题、推荐项目和识别数据异常值。

无监督学习的类型:-

无监督学习主要分为以下两个部分

2.1 .聚类:-

聚类是一种使用未标记数据的无监督学习,它是将相似的实体分组在一起,然后使用分组的数据进行聚类的过程。这种无监督机器学习技术的目标是找到数据点中的相似性,并将相似的数据点分组在一起,并计算出新数据应该属于哪个聚类。

聚类算法的类型:-

机器学习中有许多聚类算法,用于不同的聚类应用。一些主要的聚类算法如下-

2 . 1 . 1 . k-均值聚类:-

K-Means 聚类是聚类技术中的一种算法,将相似的数据聚在一个类中。K-means 是一种迭代聚类算法,旨在每次迭代中找到局部最大值。它以 K 作为输入开始,这是您想要看到的组数。在你的空间中的任意位置输入 k 个质心。现在,使用欧几里德距离方法计算数据点和质心之间的距离,并将数据点分配到靠近它的聚类中。重新计算聚类中心,作为附属于它的数据点的平均值。重复,直到没有进一步的变化发生。

K-Means Clustering showing 3 clusters

2.1.2 .分层聚类:-

层次聚类是聚类技术中的一种算法,将相似的数据聚集在一个簇中。这是一种建立聚类层次的算法。这种算法首先将所有数据点分配给它们自己的一组。然后将两个最近的组合并到同一个群中。最后,当只剩下一个簇时,该算法终止。首先将每个数据点分配到其束中。现在,使用欧几里德距离找到该组中最近的一对,并将它们合并到单个聚类中。然后计算两个最近的聚类之间的距离,并进行组合,直到所有项目都聚集成一个聚类。

2.2 .降维:-

降维是一种无监督学习,通过降低数据的维度来去除输入中不需要的数据。该技术用于移除数据中不需要的特征。它涉及将一组具有大尺寸的数据转换成具有相同数据和小尺寸的数据的过程。这些技术在解决机器学习问题时使用,以获得更好的特征。

降维算法的类型:-

机器学习中有许多降维算法,适用于不同的降维应用。一些主要的降维算法如下-

2.2.1 .主成分分析

主成分分析是降维算法之一,在这种技术中,它将旧变量转化为一组新变量,这些变量是实变量的线性组合。一组特定的新变量被称为主成分。作为变换的结果,第一个主成分具有最显著的可能方差,并且每个随后的元素在与上述成分正交的约束下具有最高的电势差。仅保留前 m < n 个分量减少了数据维数,同时保留了大部分数据信息,

2.2.2 .线性判别分析

线性判别分析是一种降维算法,它也可以创建原始特征的线性组合。然而,与主成分分析不同,LDA 不能最大化解释方差。相反,它优化了类之间的可分性。LDA 可以提高提取特征的预测性能。此外,LDA 还提供了解决特定障碍的变体。

2.2.3 .核心主成分分析:-

核主成分分析是降维算法之一,被转换为新集合变量的变量是原始变量的非线性组合,这意味着非线性版本的主成分分析,称为核主成分分析(KPCA)。它能够捕捉部分高阶统计量,从而从原始数据集中提供更多的信息。

3.强化学习:-

强化学习是第三种类型的机器学习,其中没有原始数据作为输入,而是强化学习算法必须自己找出情况。强化学习常用于机器人、游戏和导航。通过强化学习,算法通过反复试验发现哪些行为产生了最大的回报。这种类型的培训有三个主要组成部分,即可以描述为学习者或决策者的代理,描述为代理交互的一切的环境,以及代表代理可以做什么的动作。

Reinforcement Learning

目标是让代理采取行动,在给定的时间内最大化预期回报。遵循一个好的策略,代理将更快地达到目标。所以强化学习的目的是学习最佳方案。

强化学习算法的类型:-

机器学习中有许多强化学习算法,适用于不同的强化学习应用。一些主要的算法如下-

3.1 . q-学习:-

Q-learning 是强化学习的算法之一,其中代理试图从其与环境的通信历史中学习最优策略。一个代理人的记录是一个状态-行动-回报的序列。Q-learning 学习到一个最优策略,不管代理遵循哪个过程,只要它在任何状态下尝试一个动作的次数没有限制。因为无论执行哪种策略,它都会学习到一个最优策略,所以它被称为非策略方法。

3.2 . sarsa[州行动奖励州行动]:-

SARSA 是强化学习的算法之一,其中它确定它刷新到动作值。这是 SARSA 和 Q-learning 实现之间的微小差异,但它会产生深远的影响。SARSA 方法采用另一个参数 action2,这是代理从第二个状态执行的操作。它允许代理显式地找到未来的奖励值。接下来,随之而来的,而不是假设最优行动将使用和最显着的奖励。

3.3 .深度 Q-网络:-

深度 Q 网络是强化学习的算法之一,虽然 Q 学习是一种非常健壮的算法,但它的主要缺陷是缺乏通用性。如果你把 Q-learning 看作一个二维数组(动作空间*状态空间)中的更新数,实际上,它遵循动态编程。它表明对于 Q 学习代理以前没有见过的状态,它不知道采取哪种动作。换句话说,Q-learning agent 不能估计看不见的状态的值。为了解决这个问题,DQN 通过引入神经网络摆脱了二维数组。

3.4 .马尔可夫决策过程:-

**马尔可夫决策过程是强化学习的算法之一,其中包含*一组可能的世界状态 S. *一组模型。*一组可能的动作 A. 一个实值奖励函数 R(s,A)。一个策略马尔可夫决策过程的解。为了实现一个目标,使用了马尔可夫决策过程,这是一个从交互中学习的简单框架。代理人选择动作和对这些动作作出反应的环境,代理人和环境不断地相互作用,并向代理人呈现新的情况。

3.5 . ddpg[深度确定性策略梯度]:-

深度确定性策略梯度是强化学习的算法之一,其中它依赖于具有两个同名组件 actor 和 critic 的 actor-critic 设计。参与者用于调整策略功能的参数𝜽,即决定特定状态的最佳操作。还借鉴了 DQN 的分目标网络和经验回放的思想。对于 DDPG 来说,很少进行勘探作业是另一个问题。对此的解决方案是向参数空间或动作空间添加噪声。

4.半监督学习:-

半监督学习是第四种类型的机器学习,其中两种类型的原始数据都使用。半监督学习是监督和非监督机器学习的混合。半监督学习用于与监督学习相同的目的,其中它采用标记和未标记数据来训练,通常是少量的标记数据和大量的未标记数据。这种类型的学习可以使用分类、回归和预测等方法。

Semi-supervised machine learning

这种技术很有用,原因有几个。首先,为监督学习标记大量数据的过程通常非常耗时和昂贵。此外,过多的标签会给模型带来人为偏见。这意味着在训练过程中包含大量未标记的数据有助于提高最终模型的准确性,同时减少构建模型所需的时间和成本。

机器学习的应用

机器学习在各个领域都有很多用途,其中一些领域包括医疗、国防、技术、金融、安全等。这些领域涉及监督学习、非监督学习和强化学习的不同应用。这些最大似然算法使用的一些领域如下-

这个博客是为那些想在机器学习领域起步的初学者而写的,他们需要学习机器学习的所有知识或基础知识,比如什么是机器学习,它的类型,一些重要的算法以及它是如何工作的。

网络罪犯的机器学习 101

原文:towardsdatascience.com/machine-lea…

ID 78201212 © Juan Moyano | Dreamstime.com

机器学习(ML)和人工智能(AI)正在网络安全和其他技术领域掀起风暴,你可以很容易地找到大量关于防御和网络攻击两个阵营使用 ML 的信息。

更重要的是,AI 也不能免疫攻击,你可以在这里阅读我的新文章。

将机器学习用于网络攻击仍不明确。然而,2016 年,美国情报界对人工智能的部署提出了担忧,对网络安全构成了潜在威胁。最近的发现证明了机器学习如何被网络犯罪分子用于更高级、更快和更便宜的攻击。

虽然我以前的文章“网络安全的机器学习 101 ”详细介绍了防御的人工智能,但现在是时候轮到网络罪犯的机器学习了。在这里,我对恶意网络空间中机器学习部署的可能或现有方法的信息进行了系统化。本文旨在帮助信息安全团队为即将到来的威胁做好准备。

网络罪犯的任务

攻击者的活动分为 5 组机器学习可以解决的高级任务。

  1. 信息收集——为攻击做准备;
  2. 模仿——试图模仿知己;
  3. 未经授权的访问—绕过限制获得对某些资源或用户帐户的访问权;
  4. 攻击——执行恶意软件或 DDoS 等实际攻击;
  5. 自动化—自动化开发和后期开发。

用于信息收集的机器学习

无论受害者人数多少,信息收集都是每一次网络攻击的第一步。你收集的信息越多,你成功的前景就越好。

信息可以按科目分组整理,可以线上收集,也可以线下收集。信息可以指人或资产。让我们看看所有这些类别。

ML 用于收集网上人们的信息

在网络钓鱼或感染准备的情况下,黑客可以使用分类算法将潜在受害者描述为属于相关组。这意味着在收集了数千封电子邮件后,黑客只向那些点击链接的人发送恶意软件。因此,攻击者减少了及早发现计划攻击的机会。许多因素可能有助于此。例如,黑客可以将写博客的社交网站用户与关注“食物和猫”话题的用户区分开来。后一组人可能没有意识到威胁。

在这种情况下,除了 NLP 分析之外,还可以使用从 K-means 和随机森林到神经网络的各种聚类和分类方法,这些方法应该应用于受害者在社交网络上的帖子。

其他类型的分类可以与受害者的偿付能力有关。第一个受害者检测算法将针对穿着品牌服装的用户,例如,穿着巴黎世家鞋和最新古驰包在私人飞机上拍照的孩子。

这是网络罪犯没有特定目标的信息收集的一个例子。如果攻击者认识受害者并有他或她的照片,ML 可以进一步协助。通过应用图像识别工具,很容易检测社交媒体账户。Trustwave 已经通过其名为 Social Mapper 的工具迈出了自动化的第一步,该工具旨在不同的社交媒体平台中搜索一个人。这个解决方案使用谷歌图片搜索。

我敢打赌,类似于真实图像识别的功能很快就会被开发出来。

ML 用于收集有关在线 IT 资产的信息

有针对性的攻击的信息收集处理一个受害者和复杂的基础设施。目标是收集尽可能多的关于这个基础设施的信息。

这个想法是自动检查,包括收集有关网络的信息。虽然网络扫描器和嗅探器等现有工具能够分析传统网络,但基于软件定义网络(SDN)的新一代网络过于复杂。这就是机器学习可以帮助对手的地方。一个鲜为人知但很有用的了解你的敌人 (KYE)攻击允许秘密收集关于目标 SDN 网络配置的情报,这是将机器学习应用于信息收集任务的一个相关示例。黑客可以收集这些信息,范围从安全工具和网络虚拟化参数的配置到服务质量(QoS)等一般网络策略。攻击者可以通过分析来自一个网络设备的规则被推入网络的条件以及规则的类型,推断出关于网络配置的敏感信息。

在探测阶段,攻击者试图在特定交换机上触发流量规则的安装。探测流量的具体特征取决于黑客想要接收的信息。

在下一阶段,攻击者将分析探测阶段生成的探测流量与安装的相应流量规则之间的相关性。他或她可以从该分析中推断出针对特定类型的网络流实施了什么网络策略。例如,如果攻击者在探测阶段使用网络扫描工具,他或她就可以发现防御策略是通过过滤网络流量来实现的。手动工作可能需要数周来收集数据,并且仍然需要具有预配置参数的算法,例如,需要多少特定分组来做出决定,因为数量取决于各种因素。在机器学习的帮助下,黑客可以自动完成这一过程。

通常,所有需要大量时间的信息收集任务也可以自动化。举个例子,

DirBuster ,一个用于扫描可用目录和文件的工具,可以通过添加一种遗传算法,LSTMs 或 GANs 来改进,以生成与现有目录更相似的目录名。

ML 用于收集离线用户的信息

如果网络犯罪活动涉及任何身体活动,如进入受保护的建筑物,那么网络攻击者最好能够跟踪保安人员。他们足够幸运,因为现在有了解决办法。

研究人员发现了一种在医院或家中监测患者生命体征的方法,无需可穿戴设备或笨重的哔哔声设备。更重要的是,这种方法可以用来看穿墙壁。在激动人心的 TED 演讲中,他们展示了这个系统。

它捕捉无线信号(如 Wi-Fi)从人体反射回来的反射,为医护人员和患者创建可靠的生命体征记录。它给出了详细的跟踪数据,不仅显示了人是睡着还是醒着,还显示了睡眠的一个阶段。像大多数伟大的发明一样,这种设备也可以用于恶意的目的。想象一下,网络罪犯如何能够使用这种设备来检查安全警卫。

ML 用于收集关于离线资产的信息

当想到离线收集有关 IT 资产的信息时,首先想到的是在建筑物内找到摄像机和其他检测设备。所有这些设备都会产生信号,如果我们用这些符号的例子训练某种算法,就有可能检测到它们。

保护

如何保护自己不成为受害者?不言而喻,您的个人信息不得公开。所以不要在社交网络上发布太多关于你自己的信息。这是一件很琐碎但很重要的事情。至于人身攻击,不幸的是,measuresю.没有保护措施目前,攻击的类型只是理论上的。

模仿机器学习

冒充允许网络罪犯根据通信渠道和需要以不同的方式攻击受害者。攻击者能够在发送电子邮件或使用社交工程后,说服受害者点击带有漏洞或恶意软件的链接。因此,即使是打个电话也被认为是一种冒充的手段。假冒分为 3 种类型的网络活动:垃圾邮件,网络钓鱼和欺骗。

垃圾邮件中的机器学习假冒

垃圾邮件是机器学习用于网络安全服务的最古老的领域之一。然而,这可能是最先涉及到 ML 传播网络攻击的领域之一。网络罪犯可以训练一个神经网络来创建垃圾邮件,而不是手动生成垃圾邮件,这不会引起怀疑。

然而,在处理电子邮件垃圾邮件时,很难模仿用户。如果你在电子邮件中代表公司的管理员要求员工更改密码或下载更新,你可能无法以完全相同的方式书写。除非你看到这位管理员写的一堆邮件,否则你无法复制这种风格。至于今天越来越受欢迎的信使,模仿人类甚至更容易。

网络钓鱼中用于冒充的机器学习

与电子邮件网络钓鱼相比,社交媒体网络钓鱼的最大优势是公开性或容易获取个人信息。你可以通过阅读用户的帖子来监控和了解用户的行为。这一想法在最新的研究“将数据科学武器化用于社会工程自动化 Twitter 上的 E2E 鱼叉式网络钓鱼 —自动化e2eT4Twitter 上的鱼叉式网络钓鱼中得到证明,该研究提出了 SNAP_R ,这是一种显著增加网络钓鱼活动的自动化工具。而传统的自动网络钓鱼的准确率为 5%-14%,手动鱼叉式网络钓鱼的准确率为 45%。该方法的准确率在 30%左右,在某些情况下高达 66%,与自动化方法一样。研究人员使用马尔可夫模型根据用户以前的推文生成推文,并将结果与递归神经网络进行比较,特别是 LSTM。LSTM 氏症提供了更高的准确性,但需要更多的时间进行训练。

欺骗中的机器学习模仿

在人工智能的新时代,公司不仅可以创建假文本,还可以创建假声音或视频。专门从事媒体和视频模仿语音的初创公司 Lyrebird 展示了他们可以制造一个和你说话一模一样的机器人。随着数据量的增长和网络的发展,黑客可以展示更好的结果。我们不知道 Lyrebird 是如何工作的,黑客可能无法根据自己的需要使用这项服务,但他们可以发现更多的开放平台,如谷歌的 WaveNet ,它们也能做到这一点。他们应用生成性对抗网络(GANs)。

照片也可以伪造。最近 Nvidia 的一篇论文介绍了一个工具,可以生成高质量的名人图片。

就在几年前,神经网络生成的视频和图像质量很差,只对研究文章有用。现在,几乎每个人都可以制作一个假视频,上面有名人或世界知名的政治家说他们从未说过的话或做他们从未做过的事(例如,你不会相信奥巴马在这个视频中说了什么)。它可以在公开可用的工具的帮助下实现,如 DeepFake

假货无处不在,这个问题越来越严重。下一步是什么?假公司?我们已经看过《T4》的第五集了。一个家伙用猫途鹰的假评论创建了一个假餐馆。手动操作并不容易,但人工智能可以帮助生成假账户。你所需要的只是训练人工智能,以便自动创建虚假资产和公司。想象一下,假城市及其新闻机构使用人工智能来创建新闻挂钩,以维持这个或那个议程。

保护

虽然听起来有争议,但假货是真正的问题。幸运的是,有一些有前途的举措。国防部展示了第一个工具,它能够检测深度伪造。有个有趣的特点——假视频里人脸不眨眼。

AI 基金会在这一领域采取了另一项举措。这个名为 Reality Defender 的项目旨在通过使用一个浏览器插件来保护用户免受假新闻的侵害。

至于网络钓鱼,对于社交媒体账户中的网络钓鱼,最可行的建议是检查并记录通过其他渠道和信使发送可疑消息的用户。他们的几个账户同时受损的可能性很小。

针对未授权访问的机器学习

获得未经授权的访问是一个广泛的话题,但机器学习至少可以在两个最常见的领域发挥作用。这些是验证码旁路和密码暴力。

验证码旁路的机器学习

模拟之后的下一个阶段是获取对用户帐户的未授权访问。

如果网络罪犯需要获得对用户会话的未授权访问,显而易见的方法是破坏帐户。对于大规模黑客攻击来说,令人讨厌的事情之一就是绕过验证码。许多计算机程序可以解决简单的验证码测试,但最复杂的部分是对象分割。

有许多研究论文描述了验证码旁路方法。2012 年 6 月 27 日,Claudia Cruz、Fernando Uceda 和 Leobardo Reyes 发表了机器学习的第一个例子。他们使用支持向量机(SVM)方法破解了运行在 reCAPTCHA 图像上的系统,准确率达到 82%。所有的验证码机制都得到了显著的改进。然而,随后出现了一波论文,他们利用深度学习方法破解 CAPTCHA。

2016 年,发表了一篇文章,详细介绍了如何使用深度学习以 92%的准确率破解 simple-captcha。

另一项研究使用了图像识别的最新进展之一——具有 34 层的深度残差网络来破解印度流行网站 IRCTC 的验证码,准确率也达到 95–98%。这些文章大多采用基于字符的验证码。

一篇最鼓舞人心的论文在黑帽会议上发表。该研究论文名为“我是机器人”。他们曾经破解过最新的语义图像验证码,比较过各种机器学习算法。该论文承诺破解谷歌 reCAPTCHA 的准确率为 98%。

更糟糕的是,一篇新文章指出,科学家警告即将出现的 100%验证码旁路方法。

针对密码暴力的机器学习

网络犯罪分子可能在机器学习的帮助下发现优势的另一个领域是密码暴力。

马尔可夫模型在 2005 年首次被用于生成密码“猜测”,远在深度学习成为热门话题之前。如果你熟悉当前的神经网络和 LSTM,你可能听说过基于训练文本生成文本的网络。如果你给网络一个莎士比亚的作品,它会基于它创建一个新的文本,新生成的文本看起来就像是莎士比亚写的。同样的想法也可以用于生成密码。如果你可以用最常见的密码训练一个网络,它就会产生很多类似的密码。研究人员采用了这种方法,应用于密码,并收到了积极的结果,这比传统的突变更好地创建了密码列表,如将字母改为符号,例如从“s”改为“$”。

另一种方法在论文“ PassGAN:密码猜测的深度学习方法中提到,研究人员使用 GAN 来生成密码。gan 是由两个网络组成的特殊类型的神经网络。一个通常被称为生成性的,另一个是歧视性的。一个是生成对立的例子,另一个是测试这个例子是否真实。其核心思想是训练基于真实密码数据的网络,这些数据来自最近的数据泄露事件。在公布了由 14 亿密码组成的最大数据库之后,这个想法看起来对网络罪犯很有希望。

保护

你如何保护自己?物体识别验证码已经死了。如果你为你的网站选择一个验证码,最好试试 MathCaptcha 或者它的替代品。其次,使用复杂的密码,排除简单的。避免数据库中的那些。唯一安全的随机密码是那些建立在短句基础上并混合了特殊字符的密码,或者是保存在密码管理工具中的完全随机的字符串。

针对攻击的机器学习

网络罪犯想要使用机器学习的下一个领域是攻击本身。总的来说,有 3 个目标:间谍,破坏和欺诈。大多数情况下,它们都是通过恶意软件、间谍软件、勒索软件或任何其他类型的恶意程序来执行的,用户会因网络钓鱼而下载这些程序。攻击者也因为漏洞而上传。除了 DoS 攻击,还有一些不太常见的攻击,比如 crowdturfing。这些攻击比传统攻击更能从 ML 中获益。

用于漏洞发现的机器学习

最常见的漏洞发现方法之一是模糊化。这意味着在应用程序中放入一个随机输入,并监视它是否会崩溃。有 2 个步骤需要自动化和人工智能的帮助。首先是实例的生成。通常如果你拿一个 PDF 文档,研究人员会通过随机改变一些字段来编辑这个文档。使用更智能的方法来产生突变,可以大大加快寻找会使应用程序崩溃的新文档示例的过程。

也可以实现类似 AlphaGo 使用的强化学习方法。如果 AlphaGO 模型在游戏中发现了故障,它也可以帮助发现安全问题。漏洞发现之后是崩溃分析。每一项分析都需要大量的人工工作。如果有可能训练一个模型来选择更相关的崩溃,将会节省时间和精力。此外,它使漏洞发现的成本大大降低。

在这里你可以找到更多关于机器学习的模糊化

针对恶意软件/间谍软件/勒索软件的机器学习

用于恶意软件保护的机器学习可能是网络安全领域第一个商业上成功的 ML 实现。有几十篇科学论文描述了如何利用人工智能(AI)检测恶意软件的不同技术。

网络罪犯如何部署机器学习来创建恶意软件?人们可以尝试使用强化学习。网络罪犯可以获取恶意软件示例,对其进行更改,发送到 VirusTotal,检查结果,进行其他更改,等等。

或者,面部识别可用于执行有针对性的攻击。DeepLocker 是恶意软件的一个例子,它隐藏自己,直到特定事件发生,例如,识别系统检测到目标人脸。

拒绝服务攻击的机器学习

检测 DDoS 攻击最常用的方法是什么?在实施这种攻击的网络数据包中寻找常见模式。DDoS 防护总是像一场猫捉老鼠的游戏。攻击者试图通过伪造每个字段来使 DDoS 数据包与众不同,而防御者试图在欺骗的请求中找出共同的模式。在 AI 的帮助下,攻击者可以生成非常接近真实用户动作的 DDoS 数据包。它们可以嗅探正常流量,然后训练神经网络(如 GAN)发送合法数据包。在 DDoS 攻击中使用 AI 可以给这个领域带来显著的改变。

面向人群漫游的机器学习

大众追随,产生包括假新闻在内的假信息。在机器学习的帮助下,网络犯罪分子可以降低这些攻击的成本,并使其自动化。

在 2017 年 9 月发表的“在线评论系统中的自动众筹攻击和防御”研究中,介绍了该系统在 Yelp 上生成虚假评论的例子。优势不仅仅是无法检测到的 5 星评论,而是比人类写的评论得分更高的评论。

简单来说,众筹就是对众包服务的恶意使用。例如,攻击者为竞争对手的负面在线评论付费。这些评论经常未被发现,因为是真人写的,自动化工具在寻找软件攻击者。

假新闻只是众筹的一个例子。Max Tagmark 的书《生活 3.0 》提到了另一个例子。有一个虚构的故事,一组黑客创造了人工智能,它能够在亚马逊土耳其机器人执行简单的工作任务。最重要的是,在亚马逊网络服务上购买这种人工智能硬件的成本比它在亚马逊 Mturk 上赚的钱要少。他们用了很短的时间就几乎让亚马逊破产了。

用于网络犯罪自动化的机器学习

有经验的黑客可以使用机器学习来自动化各个领域的任务。几乎不可能预测什么时候和什么东西会被自动化,但是要知道网络犯罪组织有数百名成员,这需要不同类型的软件,如支持门户或支持机器人。

至于具体的网络犯罪任务,有一个新术语——Hivenet——代表智能僵尸网络。这个想法是,如果网络罪犯手动管理僵尸网络,艾滋病毒可以有一种大脑来达到特定的事件,并根据它们改变行为。多个机器人将坐在设备中,并根据任务决定谁将使用受害者的资源。这就像是生活在有机体中的一系列寄生虫。

结论

上面的想法只是黑客可以使用机器学习的一些例子。

除了使用更安全的密码和在跟踪第三方网站时更加小心之外,我只能建议关注基于 ML 的安全系统,以便领先于犯罪者。

一两年前,每个人都对机器学习的使用持怀疑态度。今天的研究发现和它在产品中的实现证明了 ML 实际上是有效的,并且它会一直存在下去。否则,黑客将开始向前看,并从 ML 中受益。

如果你喜欢我的文章,请鼓掌,并订阅以了解更多关于机器学习和网络安全的不同方面。干杯。

网络安全的机器学习 101

原文:towardsdatascience.com/machine-lea…

ID 52033957 © Everett Collection Inc. | Dreamstime.com

大量的文章涵盖了用于网络安全的机器学习以及保护我们免受网络攻击的能力。尽管如此,仔细研究人工智能(AI)、机器学习(ML)和深度学习(DL)现在如何帮助网络安全,以及这种炒作到底是怎么回事,仍然很重要。

首先,我要让你失望了。不幸的是,与图像识别或自然语言处理这两个机器学习蓬勃发展的领域相比,机器学习永远不会成为网络安全的银弹。总会有人试图找到系统或 ML 算法的弱点,并绕过安全机制。更糟糕的是,现在黑客能够使用机器学习来实现他们所有的邪恶企图。

更重要的是,AI 也不能免疫攻击,你可以在这里阅读我的新文章。

幸运的是,机器学习可以帮助解决最常见的任务,包括回归、预测和分类。在数据量极大,网络安全人才匮乏的时代,ML 似乎是唯一的解决方案。

本文是一篇介绍性文章,旨在从技术上理解应用于网络安全的 ML 研究的当前进展和未来方向。

机器学习术语

不要把任何东西都叫做“人工智能”——学习术语。

  • AI(人工智能)——一个宽泛的概念。一门使事物变得智能的科学,或者换句话说,由机器执行的人工任务(例如,视觉识别、NLP 等)。).最主要的一点是,AI 不完全是机器学习或智能的东西。它可以是像边缘检测一样安装在你的机器人吸尘器中的经典程序。粗略地说,人工智能是一种以某种方式执行人类任务的东西。
  • ML(机器学习)——人工智能的一种方法*(只是许多方法中的一种),它使用一个能够从经验中学习的系统。它不仅旨在实现人工智能目标(例如,复制人类行为),而且还可以减少简单和困难任务(如股票价格预测)的工作量和/或时间。换句话说,ML 是一个通过使用例子而不是通过编程来识别模式的系统。如果你的系统不断学习,基于数据而不是算法做出决策,并改变其行为,这就是机器学习。*
  • DL(深度学习)——一套技术用于实现机器学习,识别模式的模式——类似图像识别。该系统主要识别物体边缘、结构、物体类型,然后识别物体本身。关键是深度学习并不完全是深度神经网络。还有其他算法,它们被改进以学习模式的模式,例如强化任务中的深度 Q 学习。

这些定义表明,网络安全领域主要是指机器学习(而不是人工智能)。很大一部分任务与人类无关。

机器学习意味着根据你所拥有的数据,使用一种方法和特定的方法来解决某些任务。

大多数任务都是最常见任务的子类,如下所述。

  • 回归(或预测)-根据以前的值预测下一个值的任务。
  • 分类——将事物分成不同类别的任务。
  • 聚类-类似于分类,但类别未知,根据相似性对事物进行分组。
  • 关联规则学习(或推荐)——基于以前的经验推荐某些东西的任务。
  • 降维——或概括,在多个例子中搜索共同的和最重要的特征的任务。
  • 生成模型——基于先前的分布知识创建某物的任务。

除了这些任务之外,还有不同的方法。某些任务只能使用一种方法,但其他任务可以有多种方法。

解决 ML 任务的方法

过去的趋势:

  • 监督学习。任务驱动法。首先,你应该给数据贴上标签,就像给一个模型提供可执行文件的例子,然后说这个文件是不是恶意软件。基于这些标记的数据,模型可以对新数据做出决策。缺点是标记数据的限制。
  • ***汇编学习。*这是监督学习的扩展,同时混合不同的简单模型来解决任务。组合简单模型有不同的方法。

当前趋势

  • ***无监督学习。*数据驱动方法。当没有带标签的数据时,可以使用该方法,并且模型应该基于属性以某种方式自己标记它。通常,它旨在发现数据中的异常,通常被认为是更强大的,因为几乎不可能标记所有数据。目前,它的工作不如监督方法精确。
  • ***半监督学习。*顾名思义,当有一些标记数据时,半监督学习试图结合监督和非监督方法的优点。

未来趋势(嗯,可能)

  • 强化学习。当行为应该以某种方式对变化的环境做出反应时,可以使用环境驱动的方法。这就像一个孩子在通过试错来学习环境。
  • 主动学习。它更像是强化学习的一个子类,可能会成长为一个独立的类。主动学习就像一个老师,除了环境变化之外,还可以帮助纠正错误和行为。

机器学习任务和网络安全

让我们看看可用于解决机器学习任务的不同方法的示例,以及它们如何与网络安全任务相关联。

回归

回归(或预测)很简单。利用关于现有数据的知识来了解新数据。以房价预测为例。在网络安全中,它可以应用于欺诈检测。特征(例如,可疑交易的总量、位置等。)确定欺诈行为的可能性。

关于回归的技术方面,所有的方法都可以分为两大类:机器学习和深度学习。其他任务也是如此。

对于每个任务,都有 ML 和 DL 方法的例子。

回归的机器学习

下面是可用于回归任务的机器学习方法的简短列表(各有优缺点)。

  • 线性回归
  • 多项式回归
  • 里脊回归
  • 决策树
  • 支持向量回归机
  • 随机森林

你可以在这里找到每种方法的详细解释。

用于回归的深度学习

对于回归任务,可以使用以下深度学习模型:

  • 人工神经网络
  • 递归神经网络(RNN)
  • 神经图灵机(NTM)
  • 可微分神经计算机

分类

分类也很简单。想象你有两堆按类型分类的图片(例如,狗和猫)。在网络安全方面,一个将垃圾邮件与其他消息分开的垃圾邮件过滤器可以作为一个例子。垃圾邮件过滤器可能是应用于网络安全任务的第一个 ML 方法。

监督学习方法通常用于分类,其中某些组的例子是已知的。所有的类都应该在开始时定义。

下面是与算法相关的列表。

分类的机器学习

  • 物流回收
  • K-最近邻
  • 支持向量机(SVM)
  • KernelSVM
  • 朴素贝叶斯
  • 决策树分类
  • 随机森林分类

人们认为像 SVM 和随机森林这样的方法效果最好。请记住,没有放之四海而皆准的规则,它们可能不适合您的任务。

用于分类的深度学习

  • 人工神经网络
  • 卷积神经网络

如果你有更多的数据,深度学习方法会更好地工作。但是它们会消耗更多的资源,尤其是当您计划在生产中使用它并定期重新训练系统的时候。

使聚集

聚类类似于分类,唯一但主要的区别是。关于数据类别的信息是未知的。不知道这些数据是否可以分类。这就是无监督学习。

据称,聚类的最佳任务是取证分析。事件的原因、过程和后果是模糊的。需要对所有活动进行分类以发现异常。恶意软件分析的解决方案(即恶意软件防护安全电子邮件网关)可以实现它来将合法文件与离群值分开。

另一个可以应用聚类的有趣领域是用户行为分析。在这种情况下,应用程序用户聚集在一起,以便可以查看他们是否应该属于特定的组。

通常,聚类并不用于解决网络安全中的特定任务,因为它更像是管道中的子任务之一(例如,将用户分组到不同的组中以调整风险值)。

用于聚类的机器学习

  • k-最近邻(KNN)
  • k 均值
  • 混合模型
  • DBSCn
  • 贝叶斯定理的
  • 高斯混合模型
  • 结块的
  • 均值漂移

用于聚类的深度学习

  • 自组织映射(SOM)或 Kohonen 网络

关联规则学习(推荐系统)

网飞和 SoundCloud 根据你的电影或音乐偏好推荐电影或歌曲。在网络安全中,这一原则可主要用于事件响应。如果公司面临一波事故并提供各种类型的响应,则系统会学习特定事故的响应类型(例如,将其标记为误报、更改风险值、运行调查)。风险管理解决方案也可以带来好处,如果它们自动为新的漏洞或基于其描述的错误配置分配风险值。

有用于解决推荐任务的算法。

用于关联规则学习的机器学习

  • 推测的
  • 尤克拉特
  • FP-增长

用于关联规则学习的深度学习

  • 深度受限玻尔兹曼机(RBM)
  • 深度信仰网络(DBN)
  • 堆叠自动编码器

最新的推荐系统基于受限玻尔兹曼机器及其更新版本,如有前途的深度信念网络。

降维

降维或概化没有分类流行,但是如果你处理具有未标记数据和许多潜在特征的复杂系统,降维或概化是必要的。您不能应用聚类,因为典型方法会限制要素的数量或者不起作用。降维可以帮助处理它,削减不必要的特征。与聚类一样,降维通常是更复杂模型中的任务之一。至于网络安全任务,降维在人脸检测解决方案中很常见——你在 IPhone 中使用的那种。

机器学习降维

  • 主成分分析
  • 奇异值分解
  • T 分布随机邻居嵌入(T-SNE)
  • 线性判别分析(LDA)
  • 潜在语义分析(LSA)
  • 因素分析
  • 独立成分分析
  • 非负矩阵分解(NMF)

你可以在这里找到更多关于降维的信息(包括对这些方法及其特性的一般描述)。

生成模型

生成模型的任务与上述不同。虽然这些任务处理现有的信息和相关的决策,但是生成模型被设计成基于先前的决策来模拟实际数据(而不是决策)。

攻击性网络安全的简单任务是生成输入参数列表,以测试特定应用程序的注入漏洞。

或者,您可以拥有一个用于 web 应用程序的漏洞扫描工具。它的一个模块是测试文件的未授权访问。这些测试能够改变现有的文件名来识别新的文件名。例如,如果一个爬虫程序检测到一个名为 login.php 的文件,最好通过尝试类似 login_1.php、login_backup.php、login.php.2017 的名称来检查任何备份的存在或测试其副本。生成模型擅长于此。

机器学习生成模型

  • 马尔可夫链
  • 遗传算法

深度学习生成模型

  • 可变自动编码器
  • 生成对抗网络
  • 玻尔兹曼机器

最近,GANs 展示了令人印象深刻的成果。他们成功模仿了一段视频。想象一下它是如何被用来生成模糊化的例子的。

网络安全任务和机器学习

与其看 ML 任务并试图将其应用于网络安全,不如看看常见的网络安全任务和机器学习机会。有三个维度(为什么、做什么、怎么做)。

第一个维度是目标或任务(例如,检测威胁、预测攻击等。).根据 Gartner 的 PPDR 模型,所有安全任务可以分为五类:

  • 预测;
  • 预防;
  • 检测;
  • 回应;
  • 监控。

第二个维度是技术层和“什么”问题的答案(例如,在哪个级别监控问题)。以下是该维度的层列表:

  • 网络(网络流量分析和入侵检测);
  • 端点(反恶意软件);
  • 应用程序(WAF 或数据库防火墙);
  • 用户(UBA);
  • 流程(反欺诈)。

每一层都有不同的子类别。例如,网络安全可以是有线的、无线的或云的。假设你不能用相同的超参数在两个领域应用相同的算法,至少在不久的将来。原因是缺乏数据和算法来找到三个领域更好的依赖关系,以便有可能将一种算法改变为不同的色调。

第三个维度是“如何”的问题(例如,如何检查特定区域的安全性):

  • 实时传输中;
  • 休息时;
  • 历史上;
  • 等等。

例如,如果您关注端点保护,寻找入侵,您可以监控可执行文件的进程,进行静态二进制分析,分析该端点中的操作历史,等等。

有些任务应该在三维空间中解决。有时,某些任务的某些维度没有值。方法在一个维度上可以是相同的。尽管如此,网络安全任务这一三维空间的每一个特定点都有其复杂性。

很难一一详述,所以让我们把重点放在最重要的方面——技术层。从这个角度看网络安全解决方案。

用于网络保护的机器学习

网络保护不是一个单一的领域,而是一套不同的解决方案,侧重于一种协议,如以太网、无线、SCADA,甚至虚拟网络,如 SDNs。

网络保护是指众所周知的入侵检测系统(IDS)解决方案。他们中的一些人在几年前使用了一种 ML,主要处理基于签名的方法。

网络安全中的 ML 意味着称为网络流量分析(NTA)的新解决方案,旨在深入分析每一层的所有流量,并检测攻击和异常。

ML 在这里能帮上什么忙?有一些例子:

  • 回归预测网络数据包参数,并与正常参数进行比较;
  • 分类以识别不同类别的网络攻击,例如扫描和欺骗;
  • 用于法庭分析的聚类。

你可以在学术研究论文中找到至少 10 篇描述不同方法的论文。

更多资源:

用于端点保护的机器学习

新一代反病毒是端点检测和响应。最好了解可执行文件或流程行为中的特性。请记住,如果您在端点层处理机器学习,您的解决方案可能会因端点的类型而异(例如,工作站、服务器、容器、云实例、移动设备、PLC、物联网设备)。每个端点都有自己的特点,但任务是共同的:

  • 回归预测可执行过程的下一次系统调用,并与实际调用进行比较;
  • 分类将程序分为恶意软件、间谍软件和勒索软件等类别;
  • 安全电子邮件网关上的恶意软件防护群集(例如,将合法文件附件与异常值分开)。

关于终端防护和恶意软件的学术论文越来越受欢迎。这里有几个例子:

面向应用安全的机器学习

顺便说一下,应用程序安全性是我最喜欢的领域,尤其是 ERP 安全性。

在 app 安全中 ML 用在哪里?— WAFs 或静态和动态代码分析。提醒您,应用程序安全性可能会有所不同。有 web 应用、数据库、ERP 系统、SaaS 应用、微服务等。在不久的将来,几乎不可能建立一个通用的 ML 模型来有效地应对所有威胁。然而,你可以尝试解决一些任务。

以下是您可以利用机器学习实现应用安全的示例:

  • 回归以检测 HTTP 请求中的异常(例如,XXE 和 SSRF 攻击以及 auth bypass);
  • 分类检测已知类型的攻击,如注射(SQLi、XSS、RCE 等。);
  • 聚类用户活动以检测 DDOS 攻击和大规模利用。

更多资源提供使用 ML 实现应用安全的想法 :

针对用户行为的机器学习

这一领域始于安全信息和事件管理(SIEM)。

如果配置得当,SIEM 能够解决许多任务,包括用户行为搜索和 ML。然后,UEBA 解决方案宣布 SIEM 无法处理新的、更高级的攻击类型和持续的行为变化。

市场已经接受了这一观点,即如果从用户层面考虑威胁,就需要一个特殊的解决方案。

然而,即使是 UEBA 工具也不能涵盖与不同用户行为相关的所有事情。有域用户、应用程序用户、SaaS 用户、社交网络、信使和其他应该被监控的帐户。

与侧重于普通攻击和训练分类器的可能性的恶意软件检测不同,用户行为是复杂层和无监督学习问题之一。一般来说,没有带标签的数据集,也不知道要找什么。因此,在用户行为领域,为所有类型的用户创建一个通用算法的任务是棘手的。以下是公司在 ML 的帮助下解决的任务:

  • 回归以检测用户动作中的异常(例如,在异常时间登录);
  • 分类以将不同用户分组用于对等组分析;
  • 聚类以分离用户组并检测异常值。

更多资源:

过程行为的机器学习

过程区域是最后的,但也是最重要的。在处理它时,有必要了解一个业务流程,以便发现一些异常。业务流程可能会有很大的不同。你可以在银行和零售系统中寻找欺诈,或者在制造业中寻找工厂车间。两者完全不同,需要大量的领域知识。在机器学习中,特征工程(你向你的算法表示数据的方式)对于获得结果是至关重要的。同样,所有过程中的特征也不同。

一般来说,流程领域中有一些任务示例:

  • 回归预测下一个用户操作,并检测异常值,如信用卡欺诈;
  • 检测已知欺诈类型的分类;
  • 聚类以比较业务流程并检测异常值。

您可以找到与银行欺诈相关的研究论文,因为 ICS 和 SCADA 系统安全性很少被提及。

更多资源

机器学习网络安全书籍

如果你想了解更多关于网络安全中的机器学习,这里有一些书可以帮助你:

  • 机器学习和安全O ' Reilly 著(2018 年 1 月)——目前为止关于这个主题的最好的书,但深度学习的例子很少,大多是一般的机器学习

  • 恶意软件数据科学:攻击检测和归因(2018 年 9 月)——正如标题所示,这本书专注于恶意软件。在我写这篇文章的时候它刚刚发布,所以到目前为止我还不能给出任何反馈。但我敢打赌,这是终端保护团队每个人的必备技能。

结论

还剩下更多的区域。我已经概述了基本情况。一方面,如果你想保护你的系统,机器学习绝对不是一个万全之策。毫无疑问,可解释性存在许多问题(尤其是深度学习算法),但人类也无法解释自己的决定,对吗?

另一方面,随着数据量的增长和专家数量的减少,ML 是唯一的补救方法。它现在起作用了,很快就会强制执行。最好现在就开始。

请记住,黑客也开始在他们的攻击中使用 ML。我的下一篇文章将揭示攻击者究竟如何利用 ML。