VT-CS4624-Python-机器学习在线指南-全-

VT CS4624:Python 机器学习在线指南(全)

原文:Welcome to Python Machine Learning course!

协议:CC BY-NC-SA 4.0

正则化

原文: https://machine-learning-course.readthedocs.io/en/latest/content/overview/regularization.html

动机

请考虑以下情形。 您正在制作花生酱三明治,并试图调整成分,使其具有最佳的味道。 您可以在决策过程中考虑面包的类型,花生酱的类型或花生酱与面包的比例。 但是您会考虑其他因素,例如房间的温度,早餐吃的东西或穿的袜子是什么颜色? 您可能不会,因为这些东西对三明治的味道影响不大。 对于最终使用的任何食谱,您将更多地关注前几个特征,并避免过多地关注其他特征。 这是正则化的基本思想。

概述

在以前的模块中,我们已经看到了在某些样本集上训练的预测模型,并根据它们与测试集的接近程度对其评分。 我们显然希望我们的模型做出准确的预测,但是预测是否太准确? 当我们查看一组数据时,有两个主要组成部分:基本模式和噪声。 我们只想匹配模式而不是噪声。 考虑下面的代表二次数据的图。 图 1 使用线性模型来近似数据。 图 2 使用二次模型来近似数据。 图 3 使用高级多项式模型来近似数据。

../../_images/Regularization_Linear.png

图 1.线性预测模型 [代码]

../../_images/Regularization_Quadratic.png

图 2.二次预测模型 [代码]

../../_images/Regularization_Polynomial.png

图 3.高级多项式预测模型 [代码]

图 1 不适合数据,图 2 看起来非常适合数据,而图 3 非常适合数据。 在以上所有模型中,第三个可能是最适合测试集的模型。 但这不一定是一件好事。 如果再添加一些测试点,我们可能会发现第三个模型在预测它们时不再那么准确,但是第二个模型仍然相当不错。 这是因为第三种模型存在过拟合的问题。 过拟合意味着它在拟合测试数据(包括噪声)方面确实做得非常好,但在归纳为新数据时却表现不佳。 第二种模型非常适合数据,并且没有那么复杂以至于无法推广。

正则化的目标是通过惩罚更复杂的模型来避免过拟合。 正则化的一般形式涉及在成本函数中增加一个额外项。 因此,如果我们使用成本函数 CF,则正则化可能导致我们将其更改为 CF +λ* R,其中 R 是权重的某些函数,而λ是调整参数。 结果是权重较高(更复杂)的模型将受到更多惩罚。 调整参数基本上使我们可以调整正则化以获得更好的结果。 λ越高,权重对总成本的影响越小。

方法

我们可以使用许多方法进行正则化。 下面,我们将介绍一些更常见的用法以及何时使用它们。

岭回归

Ridge 回归是一种正则化类型,其中函数 R 涉及求和权重的平方。 公式 1 显示了修改后的成本函数的示例。

../../_images/latex-ridge-eq.gif

公式 1。岭回归的成本函数

公式 1 是正则化的示例,其中 w 表示我们的权重。 岭回归迫使权重接近零,但绝不会使权重为零。 这意味着所有特征都将在我们的模型中表示,但过拟合将被最小化。 当我们没有太多特征并且只想避免过拟合时,Ridge 回归是一个不错的选择。 图 4 比较了应用和不应用岭回归的模型。

../../_images/Regularization_Ridge.png

图 4.将岭回归应用于模型 [代码]

在图 4 中,黑线表示未应用 Ridge 回归的模型,红线表示已应用 Ridge 回归的模型。 请注意红线的平滑程度。 针对将来的数据,它可能会做得更好。

在随附的 regularization_ridge.py 文件中,添加岭回归的代码为:

添加 Ridge 回归就像在 Pipeline 调用中添加一个附加参数一样简单。 在这里,参数 alpha 表示我们的调整变量。 有关 scikit-learn 中 Ridge 回归的更多信息,请在处查阅

LASSO 回归

LASSO 回归是一种正则化类型,其中函数 R 涉及求和权重的绝对值。 公式 2 显示了修改后的成本函数的示例。

../../_images/latex-lasso-eq.gif

公式 2。LASSO 回归的成本函数

公式 2 是用 w 表示权重的正则化示例。 请注意,岭回归和 LASSO 回归的相似程度。 唯一明显的区别是权重的平方。 这恰好对他们的工作产生了重大影响。 与岭回归不同,LASSO 回归可以强制权重为零。 这意味着我们生成的模型甚至可能不会考虑某些特征! 在我们拥有一百万个特征仅需少量重要特征的情况下,这是非常有用的结果。 拉索回归使我们避免过拟合,而将注意力集中在所有特征的一小部分上。 在原始情况下,我们最终将忽略那些对我们的三明治饮食体验没有太大影响的因素。 图 5 比较了应用 LASSO 回归和不应用 LASSO 回归的模型。

../../_images/Regularization_Lasso.png

图 5.将 LASSO 回归应用于模型 [代码]

在上图中,黑线表示未应用 Lasso 回归的模型,红线表示已应用 Lasso 回归的模型。 红线比黑线平滑得多。 将 Lasso 回归应用于 10 级模型,但结果看起来它的阶数要低得多! 拉索模型可能会更好地处理未来的数据。

在包含的 regularization_lasso.py 文件中,添加 Lasso 回归的代码为:

添加 Lasso 回归与添加 Ridge 回归一样简单。 在这里,参数 alpha 表示我们的调整变量,max_iter表示要运行的最大迭代次数。 有关 scikit-learn 中 Lasso 回归的更多信息,请在处查阅

总结

在本模块中,我们学习了正则化。 通过正则化,我们找到了避免过拟合数据的好方法。 这是建模中常见但重要的问题,因此最好了解如何进行调解。 我们还探索了一些可在不同情况下使用的正则化方法。 这样,我们已经对机器学习的核心概念有了足够的了解,可以进入下一个主要主题监督学习。

参考文献

  1. https://towardsdatascience.com/regularization-in-machine-learning-76441ddcf99a
  2. https://www.analyticsvidhya.com/blog/2018/04/fundamentals-deep-learning-regularization-techniques
  3. https://www.quora.com/What-is-regularization-in-machine-learning
  4. https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html
  5. https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Lasso.html

监督学习

逻辑回归

原文: https://machine-learning-course.readthedocs.io/en/latest/content/supervised/logistic_regression.html

介绍

Logistic 回归是一种用于二分类的方法。 它可以将数据集中的点划分为两个不同的类或类别。 为了简单起见,我们将它们称为 A 类和 B 类。该模型将为我们提供给定点属于 B 类的可能性。如果该点较低(低于 50% ),则将其归为 A 类。否则,将其分类为 A 类。 同样,必须注意逻辑回归比具有阈值的线性回归更好,因为必须手动设置阈值,这是不可行的。 逻辑回归将创建一种 Sigmoid 曲线(使用 Sigmoid 函数),这也将有助于显示确定性,因为逻辑回归的输出不仅是一或零。 这是标准的逻辑函数,请注意输出始终在 0 到 1 之间,但永远不会达到这些值中的任何一个。

Logistic

参考: https://en.wikipedia.org/wiki/Logistic_regression

何时使用

Logistic 回归非常适合需要在两个类别之间进行分类的情况。 一些很好的例子被接受和拒绝的申请者以及在比赛中的胜利或失败。 这是一个示例表,可以很好地进行逻辑回归。

学习 成功
小时 专心 通过?
1
3
0.5
2

请注意,学生的成功取决于输入,并且该值是二进制的,因此逻辑回归将在这种情况下很好地工作。

它是如何工作的?

Logistic 回归使用输入的线性组合进行工作,因此多个信息源可以控制模型的输出。 模型的参数是各个特征的权重,并表示它们对结果的相对重要性。 在下面的方程式中,您应该认识到线性回归中使用的公式。 从根本上说,逻辑回归是从线性预测变量到 0 到 1 之间的概率的转换。

Equation

参考: https://en.wikipedia.org/wiki/Logistic_regression

与线性回归一样,β值是权重,x 值是变量输入。 该公式给出了输入属于 B 类的可能性,这是逻辑回归模型的目标。

多项式 Lo​​gistic 回归

到目前为止,我们一直在讨论以下情况:恰好有两个不同的输出,例如通过或失败。 但是,如果有两个以上的可能输出呢? 关于数字分类示例,其中输出可以是 0 到 9 之间的任何数字?

好吧,有一种方法可以通过逻辑回归来解决这个问题。 当使用 scikit-learn 库时,如示例代码所示,该功能已经存在。 使用 scikit-learn,您可以使用多项式模式并在训练数据中提供任意数量的类。 您可以将这种方法视为创建多个模型并比较它们的概率,但是确切的详细信息不在本课程的讨论范围之内。

代码

在我们的仓库中,查看示例以进行逻辑回归。

在示例中,使用 scikit-learn 和 numpy 来训练简单的逻辑回归模型。 该模型是基本的,但可扩展。 使用逻辑回归,可以将更多特征无缝添加到数据集中,就像在 2D 数组中作为一列一样。

该代码创建代表训练输入的 2D 数组,在这种情况下为 1000 x 1,因为有 1000 个样本和 1 个特征。 这些输入的总分是 1000 分。还会创建一个训练输出数组,根据阈值将通过分类为 1,失败分类为 0。 然后,使用 scikit-learn 的 LogisticRegression 类将 Logistic 回归分类器拟合到数据中。 之后,下一步就是使用其他数据集测试准确率。 因此,我们创建了另外 100 个随机样本进行测试,并使用模型对其进行预测。

动机

为什么要使用逻辑回归? Logistic 回归非常适合二分类或分为 2 类的情况。 逻辑回归也是一种相对简单的方法,利用输入的加权总和,类似于线性回归。 逻辑回归也很有用,因为它给出一个连续的值,代表给定分类正确的可能性。 出于这些原因,拥护者认为逻辑回归应该是数据科学界首先了解的

总结

逻辑回归通过将线性回归扩展到分类来建立。 尽管它不能分类为两个以上的类,但是它的作用仍然很有效,并且易于实现。 将逻辑回归视为第一个思想通过/失败的方法。 当您仅需要数据通过/失败概率时,逻辑回归是最简单且可能是最佳选择。

机器学习库使使用 Logistic 回归非常简单。 在仓库中查看示例代码,然后继续。 基本思想是将训练数据作为输入和分类对提供,模型将自动构建。 与往常一样,请记住此仓库概述部分中提到的基础知识,因为没有适用于机器学习的万无一失的方法。

参考文献

  1. https://towardsdatascience.com/logistic-regression-b0af09cdb8ad
  2. https://medium.com/datadriveninvestor/machine-learning-model-logistic-regression-5fa4ffde5773
  3. https://github.com/bfortuner/ml-cheatsheet/blob/master/docs/logistic_regression.rst
  4. https://machinelearningmastery.com/logistic-regression-tutorial-for-machine-learning/
  5. https://towardsdatascience.com/logistic-regression-a-simplified-approach-using-python-c4bc81a87c31
  6. https://hackernoon.com/introduction-to-machine-learning-algorithms-logistic-regression-cbdd82d81a36
  7. https://en.wikipedia.org/wiki/Logistic_regression
  8. https://en.wikipedia.org/wiki/Multinomial_logistic_regression
  9. https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html
  10. https://towardsdatascience.com/5-reasons-logistic-regression-should-be-the-first-thing-you-learn-when-become-a-data-scientist-fcaae46605c4

朴素贝叶斯分类

原文: https://machine-learning-course.readthedocs.io/en/latest/content/supervised/bayes.html

动机

机器学习中经常出现的问题是需要将输入分类为某个预先存在的类。 考虑以下示例。

假设我们要对发现的随机分布的水果进行分类。 在此示例中,我们有三个现有的水果类别:苹果,蓝莓和椰子。 这些水果中的每一个都有我们关注的三个特征:大小,重量和颜色。 此信息显示在图 1 中。

苹果 蓝莓 椰子
尺寸 中等
重量 中等
颜色 红色 蓝色 棕色

我们观察发现的那块水果,确定其大小适中,较重且为红色。 我们可以将这些特征与已知类的特征进行比较,以猜测它是哪种水果。 未知的水果像椰子一样重,但与苹果类具有更多的共同特征。 未知水果在苹果类别中具有 3 个特征中的 2 个,因此我们猜测它是一个苹果。 我们使用随机水果大小适中且像苹果一样红色的事实来猜测。

这个例子有点愚蠢,但是它突出了有关分类问题的一些基本要点。 在这些类型的问题中,我们正在将未知输入的特征与数据集中已知类的特征进行比较。 朴素贝叶斯分类是实现此目的的一种方法。

它是什么?

朴素贝叶斯是一种分类技术,它使用我们已经知道的概率来确定如何对输入进行分类。 这些概率与现有类及其具有的特征有关。 在上面的示例中,我们选择与输入最相似的类作为其分类。 该技术基于贝叶斯定理。 如果您不了解贝叶斯定理是什么,那就不用担心! 我们将在下一部分中对其进行解释。

贝叶斯定理

贝叶斯定理[公式 1 ]是一个非常有用的结果,它在概率论和其他学科中都有体现。

../../_images/Bayes.png

方程 1。贝叶斯定理

利用贝叶斯定理,我们可以检查条件概率(事件发生的概率,如果发生另一事件发生)。 P(A | B)是在事件 B 已经发生的情况下事件 A 将发生的概率。 我们可以使用已知的有关事件 A 和事件 B 的其他信息来确定该值。我们需要知道 P(B | A)(假设事件 A 已经发生,事件 B 发生的概率),P(B)(概率 事件 B 将发生)和 P(A)(事件 A 将发生的概率)。 我们甚至可以将贝叶斯定理应用于机器学习问题!

朴素贝叶斯

朴素贝叶斯分类法使用贝叶斯定理和一些其他假设。 我们将假设特征是独立的。 假设独立性意味着给定特定类别出现一组特征的概率与给定该类别出现每个单个特征的所有概率的乘积相同。 在上面的水果示例中,红色不会影响中等大小的可能性,因此假设颜色和大小之间的独立性很好。 在特征可能具有复杂关系的现实世界问题中通常不是这种情况。 这就是为什么“朴素”是名字的原因。 如果数学看起来很复杂,请不要担心! 该代码将为我们处理数字运算。 请记住,我们假设特征彼此独立以简化计算。

在这项技术中,我们接受一些输入,并计算它发生的可能性,因为它属于我们的类别之一。 我们必须为我们每个类的执行此操作。 掌握了所有这些概率之后,我们将采用最大的概率作为我们对输入所属类别的预测。

算法

以下是用于朴素贝叶斯分类的一些常见模型。 根据使用的特征分布类型,我们将它们分为两种一般情况:连续或离散。 连续表示实数值(可以有十进制答案),离散表示计数(只能有整数答案)。 还提供了每种算法的相关代码段。

高斯模型(连续)

高斯模型假设特征服从正态分布。 据您所知,正态分布只是概率值的一种特定类型,其中值趋于接近平均值。 如您在图 2 中所见,正态分布图呈钟形。 值在图的峰值附近最频繁,并且越远越难得。 这是另一个很大的假设,因为许多特征未遵循正态分布。 虽然这是事实,但假设正态分布会使我们的计算变得容易得多。 当特征不计数且包含十进制值时,我们使用高斯模型。

../../_images/Bell_Curve.png

图 2.具有标志性钟形曲线形状的正态分布 [代码]

相关代码可在 gaussian.py 文件中找到。

在代码中,我们尝试从给定的 RGB 百分比猜测颜色。 我们创建一些数据来处理,其中每个数据点代表一个 RGB 三元组。 三元组的值是从 0 到 1 的十进制数,每个值都有与之关联的颜色类别。 我们创建一个高斯模型并将其拟合到数据中。 然后,我们使用新的输入进行预测,以查看应将其分类为哪种颜色。

多项式模型(离散)

当我们处理离散计数时,将使用多项式模型。 具体来说,我们在计算特征出现的频率时要使用它们。 例如,我们可能想计算“计数”一词在此页面上出现的频率。 图 3 显示了我们可能在多项模型中使用的数据类型。 如果我们知道计数将只是两个值之一,则应改用 Bernoulli 模型。

单词 频率
Algebra 0
Big 1
Count 2
Data 12

相关代码可在 multinomial.py 文件中找到。

该代码基于我们的水果示例。 在代码中,我们尝试从给定的特性中猜出一个结果。 我们创建一些数据以供处理,其中每个数据点都是代表水果特征(即大小,重量和颜色)的三元组。 三元组的值是介于 0 到 2 之间的整数,并且每个都有与之关联的水果类。 整数基本上只是与特征相关的标签,但是使用它们而不是字符串可以使我们使用多项模型。 我们创建一个多项模型并将其拟合到数据中。 然后,我们使用新的输入进行预测,以查看应将其分类为哪种水果。

伯努利模型(离散)

当我们处理离散计数时,也会使用伯努利模型。 与多项式情况不同,这里我们在计算是否发生了特征。 例如,我们可能要检查“ count”一词是否在此页面上全部出现。 当特征只有两个可能的值(例如红色或蓝色)时,我们也可以使用伯努利模型。 图 4 显示了我们可能在伯努利模型中使用的数据种类。

单词 出现?
Algebra
Big
Count
Data

相关代码可在 bernoulli.py 文件中找到。

在代码中,我们尝试根据某物的某些特征来猜测某物是否为鸭子。 我们创建一些数据来处理,每个数据点都是代表特征的三元组:走路像鸭子一样,说话像鸭子一样,很小。 三元组的值为 true 或 false 的值为 1 或 0,并且每个值为鸭子或不是鸭子。 我们创建一个伯努利模型并将其拟合到数据中。 然后,我们用新的输入进行预测,以查看它是否是鸭子。

总结

在本模块中,我们了解了朴素贝叶斯分类。 朴素贝叶斯分类使我们可以根据现有类和特征的概率对输入进行分类。 如代码所示,您不需要大量的训练数据就可以使 Naive Bayes 有用。 另一个好处是速度,它可以用于实时预测。 我们对使用朴素贝叶斯(Naive Bayes)做出了很多假设,因此应以一粒盐作为结果。 但是,如果您没有太多数据并且需要快速得出结果,那么朴素贝叶斯是解决分类问题的理想选择。

参考文献

  1. https://machinelearningmastery.com/naive-bayes-classifier-scratch-python/
  2. https://www.analyticsvidhya.com/blog/2017/09/naive-bayes-explained/
  3. https://towardsdatascience.com/naive-bayes-in-machine-learning-f49cc8f831b4
  4. https://medium.com/machine-learning-101/chapter-1-supervised-learning-and-naive-bayes-classification-part-1-theory-8b9e361897d5

决策树

原文: https://machine-learning-course.readthedocs.io/en/latest/content/supervised/decisiontrees.html

介绍

决策树是机器学习中的一个分类器,它使我们能够根据先前的数据进行预测。 它们就像一系列连续的“ if…then”语句,您将新数据馈入它们以获得结果。

为了演示决策树,让我们看一个例子。 想象一下,我们要预测麦克是否会在任何一天去杂货店购物。 我们可以看看导致 Mike 前往商店的先前因素:

Dataset

图 1.示例数据集

在这里,我们可以查看 Mike 的杂货供应量,天气以及 Mike 每天是否工作。 绿色的行是他去商店的日子,红色的行是他没有去的日子。 决策树的目标是尝试了解为什么 Mike 会去商店,然后将其应用于新数据。

让我们将第一个属性分成一棵树。 迈克的补给量可能少,中或大:

Tree 1

图 2.我们的第一个拆分

在这里,我们可以看到 Mike 的补给量很高,就永远不会去商店。 这称为纯子集,即仅包含正例或仅负例的子集。 使用决策树,无需进一步分解纯子集。

让我们将 Med Supplies 类别划分为 Mike 那天是否工作:

Tree 2

图 3.我们的第二个拆分

在这里我们可以看到我们还有两个纯子集,因此这棵树是完整的。 我们可以用它们各自的答案替换任何纯子集-在这种情况下,是或否。

最后,让我们按“天气”属性划分“供应不足”类别:

Tree 3

图 4.我们的第三个拆分

现在我们有了所有纯子集,我们可以创建最终决策树:

Tree 4

图 5.最终决策树

动机

决策树易于创建,可视化和解释。 因此,它们通常是用于对数据集建模的第一种方法。 决策树的层次结构和分类性质使其实现起来非常直观。 决策树根据您拥有的数据点数对数展开,这意味着较大的数据集对树的创建过程的影响将小于其他分类器。 由于树结构,对新数据点的分类也可以对数地执行。

分类和回归树

决策树算法也称为 CART 或分类和回归树。 与上面显示的树一样,分类树用于从一组可能的值中获取结果。 回归树是决策树,其中结果是连续值,例如汽车价格。

分裂(归纳)

决策树是通过称为归纳的拆分过程创建的,但是我们如何知道何时拆分? 我们需要一种递归算法,该算法确定要拆分的最佳属性。 一种这样的算法是贪婪算法

  1. 从根开始,我们为每个属性创建一个拆分。
  2. 对于每个创建的拆分,请计算拆分成本。
  3. 选择成本最低的拆分。
  4. 递归到子树,然后从步骤 1 继续。

重复此过程,直到所有节点都具有与目标结果相同的值,或者拆分不会为预测增加任何值。 该算法将根节点作为最佳分类器。

分裂成本

分裂的成本由成本函数确定。 使用成本函数的目的是以一种可以计算的方式拆分数据,并提供最大的信息收益。

对于提供答案而不是提供值的分类树,我们可以使用基尼不纯度计算信息增益:

../../_images/Gini_Impurity.png

公式 1.基尼不纯度函数

Ref: https://sebastianraschka.com/faq/docs/decision-tree-binary.html../../_images/Gini_Information_Gain.png

公式 2。基尼信息增益公式

Ref: https://sebastianraschka.com/faq/docs/decision-tree-binary.html

为了计算信息增益,我们首先开始计算根节点的基尼不纯度。 让我们看一下我们之前使用的数据:

供应量 天气 工作 购物?
D1
D2
D3 多云
D4 下雨
D5 多云
D6
D7 下雨
D8 多云
D9 下雨
D10 下雨
D11
D12

我们的根节点是目标变量,无论迈克是否打算去购物。 要计算其基尼不纯度,我们需要找到每个结果的概率平方和,然后从一个结果中减去该结果:

../../_images/Gini_1.png

../../_images/Gini_2.png

../../_images/Gini_3.png

如果我们在第一个属性“供应量”上划分,我们来计算基尼信息增益。 我们可以分为三个不同的类别-低,中和高。 对于这些,我们计算其基尼不纯度:

../../_images/Gini_4.png

../../_images/Gini_5.png

../../_images/Gini_6.png

如您所见,高电源的不纯度为 0。这意味着如果我们分裂电源并接收高输入,我们将立即知道结果是什么。 为了确定此拆分的基尼信息增益,我们计算根的不纯度减去每个孩子的不纯度的加权平均值:

../../_images/Gini_7.png

../../_images/Gini_8.png

对于每个可能的分裂,我们都会继续使用此模式,然后选择能够为我们提供最高信息增益值的分裂。 最大化信息增益使我们可以进行最极化的分裂,从而降低了新输入被错误分类的可能性。

修剪

通过足够大的数据集创建的决策树最终可能会产生过多的拆分,每个拆分的有用性都会降低。 高度详细的决策树甚至可能导致过拟合,如上一模块中所述。 因此,删除决策树中不重要的部分是有益的。 修剪涉及计算每个结束子树(叶节点及其父节点)的信息增益,然后删除信息增益最小的子树:

../../_images/Dec_Trees_Pruning.png

参考: http://www.cs.cmu.edu/~bhiksha/courses/10-601/decisiontrees/

如您所见,子树被更突出的结果所取代,成为新的叶子。 可以重复此过程,直到达到所需的复杂性级别,树高或信息获取量。 由于树是为了节省修剪时间而构建的,因此可以跟踪和存储信息增益。 每个模型都应使用自己的修剪算法来满足其需求。

总结

决策树使您可以快速有效地对数据进行分类。 因为它们将数据塑造为决策的层次结构,所以即使非专家也可以很好地理解它们。 决策树是通过两步过程创建和完善的:归纳和修剪。 归纳法涉及挑选最佳属性进行拆分,而修剪则有助于过滤掉认为无用的结果。 由于决策树非常易于创建和理解,因此通常是用于建模和预测数据集结果的第一种方法。

代码示例

提供的代码 Decisiontrees.py 以本文档中讨论的示例为基础,并从中创建决策树。 首先,定义每个类的每个可能选项。 稍后将其用于适应和显示我们的决策树:

# The possible values for each class
classes = {
    'supplies': ['low', 'med', 'high'],
    'weather':  ['raining', 'cloudy', 'sunny'],
    'worked?':  ['yes', 'no']
}

接下来,我们创建了上面显示的数据集的矩阵,并定义了每行的结果:

# Our example data from the documentation
data = [
    ['low',  'sunny',   'yes'],
    ['high', 'sunny',   'yes'],
    ['med',  'cloudy',  'yes'],
    ['low',  'raining', 'yes'],
    ['low',  'cloudy',  'no' ],
    ['high', 'sunny',   'no' ],
    ['high', 'raining', 'no' ],
    ['med',  'cloudy',  'yes'],
    ['low',  'raining', 'yes'],
    ['low',  'raining', 'no' ],
    ['med',  'sunny',   'no' ],
    ['high', 'sunny',   'yes']
]

# Our target variable, whether someone went shopping
target = ['yes', 'no', 'no', 'no', 'yes', 'no', 'no', 'no', 'no', 'yes', 'yes', 'no']

不幸的是,sklearn 机器学习包无法根据分类数据创建决策树。 有正在进行的工作允许这样做,但是现在我们需要另一种方法来用库在决策树中表示数据。 幼稚的方法是仅枚举每个类别-例如,将晴天/阴天/阴天转换为 0、1 和 2 之类的值。但是这样做有一些不幸的副作用,例如这些值是可比较的(晴天 <正在下雨)且连续。 为了解决这个问题,我们对数据进行“一次热编码”:

categories = [classes['supplies'], classes['weather'], classes['worked?']]
encoder = OneHotEncoder(categories=categories)

x_data = encoder.fit_transform(data)

一种热编码使我们能够将分类数据转换为期望连续数据的 ML 算法可识别的值。 它通过选择一个类并将其划分为每个选项来工作,其中一点代表该选项是否存在。

现在我们有了适合 sklearn 决策树模型的数据,我们只需将分类器拟合到数据即可:

# Form and fit our decision tree to the now-encoded data
classifier = DecisionTreeClassifier()
tree = classifier.fit(x_data, target)

其余代码涉及创建一些随机预测输入,以显示如何使用树。 我们以与上述数据相同的格式创建了一组随机数据,然后将其传递到 DecisionTreeClassifier 的预测方法中。 这为我们提供了一系列预测目标变量-在这种情况下,对 Mike 是否会购物的答案是或否:

# Use our tree to predict the outcome of the random values
prediction_results = tree.predict(encoder.transform(prediction_data))

参考文献

  1. https://towardsdatascience.com/decision-trees-in-machine-learning-641b9c4e8052
  2. https://heartbeat.fritz.ai/introduction-to-decision-tree-learning-cd604f85e23
  3. https://machinelearningmastery.com/implement-decision-tree-algorithm-scratch-python/
  4. https://sebastianraschka.com/faq/docs/decision-tree-binary.html
  5. https://www.cs.cmu.edu/~bhiksha/courses/10-601/decisiontrees/

k 最近邻

原文: https://machine-learning-course.readthedocs.io/en/latest/content/supervised/knn.html

介绍

K 最近邻(KNN)是机器学习的基本分类器。 分类器采用已经标记的数据集,然后尝试将新数据点标记到这些分类之一中。 因此,我们正在尝试确定对象所在的类。为此,我们查看与对象最接近的点(邻居),并且拥有最多邻居的类将成为我们确定对象所属的类。 k 是与对象最近的邻居数。 因此,如果 k = 1,则该对象将属于的类是最近邻的类。 让我们看一个例子。

KNN

参考: https://coxdocs.org

在此示例中,我们尝试将红色星形分类为绿色正方形或蓝色八边形。 首先,如果我们看 k = 3 的内圆,我们可以看到有 2 个蓝色八边形和 1 个绿色正方形。 因此,蓝色八角形占大多数,因此红色星号将被分类为蓝色八角形。 现在我们看 k = 5,即外圆。 在这一个中,有 2 个蓝色八边形和 3 个绿色正方形。 然后,红星将被分类为绿色方块。

它是如何工作的?

我们将研究两种不同的解决方法。 两种方式是暴力法和 K-D 树法。

暴力法

这是最简单的方法。 基本上,它只是计算从要分类的对象到集合中每个点的欧几里德距离。 欧几里得距离就是连接两个点的线段的长度。 当点的尺寸较小或点数较小时,“暴力”方法很有用。 随着点数的增加,该方法必须计算欧几里得距离的次数也增加,因此该方法的表现下降。 幸运的是,K-D 树方法可以更好地处理更大的数据集。

K-D 树法

该方法试图通过减少计算欧几里得距离的次数来改善运行时间。 此方法背后的思想是,如果我们知道两个数据点彼此靠近,并且计算到其中一个的欧几里得距离,那么我们就知道该距离大致接近另一个点。 这是 K-D 树的外观示例。

KNN K-d tree

参考: https://slideplayer.com/slide/3273367/

K-D 树的工作方式是树中的一个节点表示并保存 n 维图中的数据。 每个节点代表图中的一个框。 首先,我们可以根据一组数据构建一个 KD 树,然后当需要对一个点进行分类时,我们只需查看该点将落在树中的位置,然后仅计算它所接近的点之间的欧几里得距离,直到我们 达到 k 个邻居。

如果数据集较大,建议使用此方法。 这是因为,如果数据集较大,则创建 K-D 树的成本相对较低,并且随着数据变大,对点进行分类的成本不变。

选择 k

选择 k 通常取决于您要查看的数据集。 您永远不要选择 k = 2,因为它极有可能不会出现多数类,因此在上面的示例中将每个中都有一个,因此我们无法对红星进行分类。 通常,您希望 k 的值较小。 当 k 趋于无穷大时,所有未识别的数据点将始终归为一类或另一类,具体取决于哪一类具有更多数据点。 您不希望发生这种情况,因此明智的选择一个相对较小的 k。

总结

以下是一些要带走的东西:

  • KNN 的不同方法只会影响表现,而不会影响输出
  • 当点的尺寸或点数较小时,最好使用暴力法
  • 当您拥有更大的数据集时,K-D 树方法是最好的
  • SKLearn KNN 分类器具有一种自动方法,该方法可以根据所训练的数据来决定使用哪种方法。

选择 k 的值将大大改变数据的分类方式。 较高的 k 值将忽略数据的异常值,而较低的 k 值将赋予它们更大的权重。 如果 k 值太高,将无法对数据进行分类,因此 k 需要相对较小。

动机

那么为什么有人会在另一个分类器上使用这个分类器呢? 这是最好的分类器吗? 这些问题的答案取决于它。 没有最好的分类器,这完全取决于给出分类器的数据。 对于一个数据集,KNN 可能是最好的,但对于另一个数据集,则不是。 最好了解支持向量机等其他分类器,然后确定哪个分类器可以最好地对给定的数据集进行分类。

代码示例

请查看我们的代码 knn.py ,以了解如何使用 Python 的 Scikit-learn 库实现 k 最近邻分类器。 有关 Scikit-Learn 的更多信息,请在中找到

knn.py ,对从 Scikit-Learn 的数据集库加载的一组乳腺癌数据进行分类。 该程序将获取数据并将其绘制在图形上,然后使用 KNN 算法来最好地分离数据。 输出应如下所示:

KNN k = 9 output

绿点被分类为良性。 红点归类为恶性。 边界线是分类器做出的预测。 该边界线由 k 值确定,在这种情况下,k = 9。

这将从 Scikit-Learn 的数据集库中加载数据。 您可以将数据更改为所需的任何数据。 只要确保您有数据点和一系列目标即可对这些数据点进行分类。

dataCancer = load_breast_cancer()
data = dataCancer.data[:, :2]
target = dataCancer.target

您还可以更改将更改算法的 k 值或 n_neighbors 值。 建议您选择一个相对较小的 k。

您还可以更改使用的算法,选项为{'auto','ball_tree','kd_tree','brute'}。 这些不会更改预测的输出,只会更改预测数据所需的时间。

尝试在下面的代码中将 n_neighbors 的值更改为 1。

model = KNeighborsClassifier(n_neighbors = 9, algorithm = 'auto')
model.fit(data, target)

如果将 n_neighbors 的值更改为 1,则将按最接近该点的点进行分类。 输出应如下所示:

KNN k = 1 output

将该输出与 k = 9 进行比较,您会发现如何对数据进行分类有很大的不同。 因此,如果您想忽略离群值,则需要较高的 k 值,否则请选择较小的 k(例如 1、3 或 5)。您可以通过选择大于 100 的非常高的 k 进行试验。最终,算法会将所有数据分类为 1 类,并且没有行可以拆分数据。

参考文献

  1. https://medium.com/machine-learning-101/k-nearest-neighbors-classifier-1c1ff404d265
  2. https://www.analyticsvidhya.com/blog/2018/03/introduction-k-neighbours-algorithm-clustering/
  3. https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html
  4. https://turi.com/learn/userguide/supervised-learning/knn_classifier.html

线性支持向量机

原文: https://machine-learning-course.readthedocs.io/en/latest/content/supervised/linear_SVM.html

介绍

支持向量机(简称 SVM)是用于对数据进行分类的另一种机器学习算法。 SVM 的要点是尝试找到一条线或超平面来划分维空间,从而最好地对数据点进行分类。 如果我们试图划分两个类 A 和 B,我们将尝试最好地用一条线将这两个类分开。 线/超平面的一侧将是 A 类的数据,而另一侧将是 B 类的数据。这种分类法在分类中非常有用,因为我们必须一次计算最佳的线或超平面,并且任何新的数据点都可以轻松地计算出来。 仅通过查看它们落在行的哪一侧即可对其进行分类。 这与 k 最近邻算法相反,在 k 算法中,我们必须计算每个数据点最近的邻居。

超平面

超平面取决于它所在的空间,但是它将空间分成两个断开的部分。 例如,一维空间将只是一个点,二维空间将是一条线,三维空间将是一个平面,依此类推。

我们如何找到最佳的超平面/直线?

您可能想知道可能会有多行将数据很好地拆分。 实际上,可以划分两类的行数是无限的。 正如您在下图中所看到的,每一行都将正方形和圆形分开,那么我们选择哪一个呢?

Possible_Hyperplane

参考: https://towardsdatascience.com/support-vector-machine-introduction-to-machine-learning-algorithms-934a444fca47

那么 SVM 如何找到将这两类分开的理想直线呢? 它不仅是随机选择一个。 该算法选择具有最大边距的线/超平面。 最大化边距将为我们提供对数据进行分类的最佳行。 如下图所示。

Optimal_Hyperplane

参考: https://towardsdatascience.com/support-vector-machine-introduction-to-machine-learning-algorithms-934a444fca47

如何最大化边距?

最接近直线的数据是确定最佳直线的因素。 这些数据点称为支持向量。 它们显示为上方的正方形和圆形填充。 这些向量到超平面的距离称为边距。 通常,这些点离超平面越远,正确分类数据的可能性就越大。 找到支持向量并最大化边距会涉及很多复杂的数学运算。 我们不会去讨论; 我们只想了解 SVM 背后的基本思想。

忽略异常值

有时,数据类将具有离群值。 这些数据点与班级其余部分明显分开。 支持向量机将忽略这些离群值。 如下图所示。

Outliers

参考: https://www.analyticsvidhya.com/blog/2017/09/understaing-support-vector-machine-example-code/

带有红色圆圈的星星是异常值。 因此,SVM 将忽略异常值,并创建最佳行以将两个类分开。

核 SVM

会有无法用简单的线或超平面分开的数据类。 这被称为非线性可分离数据。 这是此类数据的示例。

Kernel

参考: https://www.analyticsvidhya.com/blog/2017/09/understaing-support-vector-machine-example-code/

没有明确的方法将星星与圆圈分开。 通过使用称为核技巧的技巧,SVM 将能够对非线性可分离数据进行分类。 基本上,核技巧将点指向更高的维度,以将非线性可分离数据转换为线性可分离数据。 因此,上图将用圆圈分隔,以分隔数据。

这是核技巧的一个示例。

Kernel X Y graph

参考: https://www.analyticsvidhya.com/blog/2017/09/understaing-support-vector-machine-example-code/

有三种类型的核:

  • 线性
  • 多项式
  • 径向基函数(RBF)核

您可以通过将“ model = svm.SVC(kernel ='linear',C = 10000)”中的 kernel 值更改为“ poly”或“ rbf”来查看这些核如何改变最佳超平面的结果。 这是在 linear_svm.py 中。

总结

SVM 是一种很好的机器学习技术,可以对数据进行分类。 现在,我们对 SVM 有了一些了解,我们可以展示使用此分类器的优缺点。

SVM 的优点:

  • 有效地对高维空间进行分类
  • 节省内存空间,因为它仅使用支持向量来创建最佳行。
  • 数据点可分离的最佳分类器

与 SVM 的缺点:

  • 有大量数据集时效果不佳,训练时间更长。
  • 当类重叠时,即不可分离的数据点,表现会很差。

动机

为什么要使用 SVM? 可以对数据进行分类的模型很多。 为什么要使用这个? 如果您知道数据点很容易分离,那么这可能是最好的分类器。 另外,可以使用核技巧来扩展它,因此请尝试使用不同的核,例如径向基函数(RBF)。

代码示例

请查看我们的代码 linear_svm.py ,以了解如何使用 Python 的 Scikit-learn 库实现线性 SVM。 有关 Scikit-Learn 的更多信息,请在中找到

linear_svm.py ,对从 Scikit-Learn 的数据集库加载的一组乳腺癌数据进行分类。 该程序将获取数据并将其绘制在图形上,然后使用 SVM 创建超平面以分离数据。 它还绕圈了确定超平面的支持向量。 输出应如下所示:

Linear SVM output

绿点被分类为良性。 红点归类为恶性。

这将从 Scikit-Learn 的数据集库中加载数据。 您可以将数据更改为所需的任何数据。 只要确保您拥有数据点和一系列目标即可对这些数据点进行分类。

dataCancer = load_breast_cancer()
data = dataCancer.data[:, :2]
target = dataCancer.target

您也可以将核更改为“ rbf”或“多项式”。 这将创建一个不同的超平面来对数据进行分类。 您可以在此处的代码中进行更改:

model = svm.SVC(kernel = 'linear', C = 10000)
model.fit(data, target)

参考文献

  1. https://www.analyticsvidhya.com/blog/2017/09/understaing-support-vector-machine-example-code/
  2. https://stackabuse.com/implementing-svm-and-kernel-svm-with-pythons-scikit-learn/
  3. https://towardsdatascience.com/support-vector-machine-introduction-to-machine-learning-algorithms-934a444fca47
  4. https://towardsdatascience.com/https-medium-com-pupalerushikesh-svm-f4b42800e989
  5. https://towardsdatascience.com/support-vector-machines-svm-c9ef22815589

无监督学习

聚类

原文: https://machine-learning-course.readthedocs.io/en/latest/content/unsupervised/clustering.html

概述

在先前的模块中,我们讨论了监督学习主题。 我们现在准备继续进行无监督学习,我们的目标将有很大的不同。 在监督学习中,我们尝试将输入与某些现有模式进行匹配。 对于无监督学习,我们将尝试在未标记的原始数据集中发现模式。 我们看到有监督学习中经常出现分类问题,现在我们将研究无监督学习中的类似问题:聚类

聚类

聚类是将相似数据分组并隔离不相似数据的过程。 我们希望我们提出的聚类中的数据点共享一些公共属性,以将它们与其他聚类中的数据点分开。 最终,我们将得到一些满足这些要求的小组。 这听起来似乎很熟悉,因为表面上听起来很像分类。 但是请注意,聚类和分类解决了两个非常不同的问题。 聚类用于识别数据集中的潜在组,而分类用于将输入与现有组进行匹配。

动机

聚类是解决无监督学习中常见问题的非常有用的技术。 通过聚类,我们可以通过对相似的数据点进行分组来找到数据集中的基础模式。 考虑玩具制造商的情况。 玩具制造商生产许多产品,并且碰巧拥有多样化的消费群。 对于制造商来说,识别购买特定产品的群体可能很有用,以便可以个性化广告。 有针对性的广告是行销中的普遍愿望,而聚类有助于确定受众特征。 当我们想识别原始数据集中潜在的群体结构时,聚类是一个很好的使用工具。

方法

由于群集只是提供了对数据集的解释,因此有许多方法可以实现它。 在决定群集时,我们可能会考虑数据点之间的距离。 我们还可以考虑一个区域中的数据点密度以确定聚类。 对于此模块,我们将分析两种较常见且流行的方法: K-均值层次。 在这两种情况下,我们都将使用图 1 中的数据集进行分析。

../../_images/Data_Set.png

图 1.用于聚类 的数据集

此数据集表示玩具制造商的产品数据。 该制造商向 5 至 10 岁的幼儿出售 3 种产品,每种产品有 3 种变体。这些产品是可动人偶,积木和汽车。 制造商还指出,哪个年龄段的人群购买每种产品的比例最高。 数据集中的每个点代表购买最多玩具的玩具和年龄组之一。

K 均值

K-均值聚类尝试使用迭代过程将数据集划分为 K 个聚类。 第一步是为每个群集选择一个中心点。 该中心点不需要与实际数据点相对应。 中心点可以随机选择,或者如果我们对它们应该在哪里有很好的猜测,可以选择它们。 在下面的代码中,中心点是使用 k-means ++方法选择的,该方法旨在加快收敛速度​​。 此方法的分析超出了本模块的范围,但是对于 sklearn 中的其他初始选项,请在此处选中

第二步是将每个数据点分配给一个群集。 我们通过测量数据点与每个中心点之间的距离并选择中心点最接近的聚类来做到这一点。 图 2 中说明了此步骤。

../../_images/K_Means_Step2.png

图 2.将每个点与一个群集关联

现在,所有数据点都属于一个群集,第三步是重新计算每个群集的中心点。 这只是属于该群集的所有数据点的平均值。 图 3 中说明了此步骤。

../../_images/K_Means_Step3.png

图 3.找到每个群集的新中心

现在,我们只重复第二和第三步,直到中心在迭代之间停止变化或仅略微变化为止。 结果是 K 个群集,其中数据点比任何其他群集的中心更靠近其群集的中心。 这在图 4 中进行了说明。

../../_images/K_Means_Final.png

图 4.最终簇

K-Means 聚类要求我们输入并非总是容易确定的期望聚类数。 取决于我们在第一步中选择起点的位置,它也可能不一致。 在整个过程中,我们最终可能会看到聚类已被优化,但可能不是最佳的整体解决方案。 在图 4 中,我们以一个红色数据点结束,该数据点与红色中心和蓝色中心的距离相等。 这源于我们最初的中心选择。 相比之下,图 5 显示了在给定不同起始中心的情况下可能达到的另一个结果,并且看起来更好。

../../_images/K_Means_Final_Alt.png

图 5.一组替代聚类

另一方面,K-Means 非常强大,因为它在每个步骤都考虑了整个数据集。 由于我们只计算距离,因此速度也很快。 因此,如果我们需要一种考虑整个数据集的快速技术,并且对底层组的外观有所了解,那么 K-Means 是一个不错的选择。

相关代码可在 clustering_kmeans.py 文件中找到。

在代码中,我们创建了用于分析的简单数据集。 设置聚类非常简单,需要一行代码:

kmeans = KMeans(n_clusters=3, random_state=0).fit(x)

选择n_clusters参数为 3,因为输出数据集中似乎有 3 个簇。 每次运行代码时,random_state参数都可提供一致的结果。 其余代码将显示图 6 中显示的最终图。

../../_images/KMeans.png

图 6.最终的群集数据集

群集用颜色编码,“ x”表示群集中心,虚线表示群集边界。

层次

层次聚类将数据集想象为聚类的层次结构。 我们可以从所有数据点中建立一个巨型群集开始。 这在图 7 中进行了说明。

../../_images/Hierarchical_Step1.png

图 7.数据集中的一个巨型群集*

在此群集内,我们找到两个最不相似的子群集并将其拆分。 这可以通过使用一种算法来实现,以使聚类间距离最大化。 这只是一个群集中的节点与另一群集中的节点之间的最小距离。 这在图 8 中进行了说明。

../../_images/Hierarchical_Step2.png

图 8.巨型群集分为 2 个群集

我们将继续拆分子聚类,直到每个数据点都属于其自己的聚类,或者直到我们决定停止为止。 如果我们从一个巨型群集开始,然后将其分解为较小的群集,则称为自上而下分裂群集。 或者,我们可以从考虑每个数据点的群集开始。 下一步是将两个最接近的群集合并为一个较大的群集。 这可以通过找到每个群集之间的距离并选择它们之间距离最小的一对来完成。 我们将继续此过程,直到只有一个聚类。 这种组合群集的方法称为自下而上聚集群集。 在这两种方法的任何时候,我们都可以在聚类看起来合适时停止。

与 K-Means 不同,层次聚类相对较慢,因此无法很好地扩展到大型数据集。 从好的方面来说,当您多次运行层次聚类时,它会更加一致,并且不需要您知道预期的聚类数量。

相关代码可在 clustering_hierarchical.py 文件中找到。

在代码中,我们创建了用于分析的简单数据集。 设置聚类非常简单,需要一行代码:

hierarchical = AgglomerativeClustering(n_clusters=3).fit(x)

选择n_clusters参数为 3,因为输出数据集中似乎有 3 个簇。 如果我们还不了解这一点,我们可以尝试不同的值,然后看看哪个值效果最好。 其余代码将显示图 9 中显示的最终图。

../../_images/Hierarchical.png

图 9.最终的群集数据集

群集使用颜色编码,大型群集周围有边框,以显示哪些数据点属于它们。

总结

在本模块中,我们了解了聚类。 聚类允许我们通过对相似数据点进行分组来发现原始数据集中的模式。 这是无监督学习中的普遍愿望,而聚类是一种流行的技术。 您可能已经注意到,与以前的模块中一些数学上比较繁重的描述相比,上面讨论的方法相对简单。 这些方法简单但功能强大。 例如,我们能够确定玩具制造商示例中可用于定向广告的聚类。 对于企业而言,这是非常有用的结果,并且只花了几行代码。 通过对聚类的深入了解,您将为在机器学习领域取得成功做好准备。

参考文献

  1. https://www.analyticsvidhya.com/blog/2016/11/an-introduction-to-clustering-and-different-methods-of-clustering/
  2. https://medium.com/datadriveninvestor/an-introduction-to-clustering-61f6930e3e0b
  3. https://medium.com/predict/three-popular-clustering-methods-and-when-to-use-each-4227c80ba2b6
  4. https://towardsdatascience.com/the-5-clustering-algorithms-data-scientists-need-to-know-a36d136ef68
  5. https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html

主成分分析

原文: https://machine-learning-course.readthedocs.io/en/latest/content/unsupervised/pca.html

介绍

主成分分析是一种用于获取大量互连变量并选择最适合模型的技术。 仅关注几个变量的过程称为降维,有助于降低数据集的复杂度。 从根本上讲,主成分分析总结了数据。

../../_images/pca4.png

参考: https://stats.stackexchange.com/questions/2691/making-sense-of-principal-component-analysis-eigenvectors-特征值

动机

主成分分析对于得出具有多个变量的给定数据集的整体线性独立趋势非常有用。 它使您可以从可能相关或不相关的变量中提取重要的关系。 主成分分析的另一种应用是显示-您可以仅代表几个主成分并绘制它们,而不是代表多个不同的变量。

降维

降维有两种类型:特征消除和特征提取。

特征消除仅涉及从我们认为不必要的数据集中修剪特征。特征消除的缺点是,我们会失去从删除的特征中获得的任何潜在信息。

特征提取但是,通过组合现有特征来创建新变量。 以某些简单性或可解释性为代价,特征提取使您可以维护特征中保存的所有重要信息。

主成分分析通过创建一组称为主成分的自变量来处理特征提取(而不是消除)。

PCA 示例

主成分分析是通过考虑所有变量并计算一组表示它们的方向和幅度对(向量)来进行的。 例如,让我们考虑下面绘制的一个小的示例数据集:

../../_images/pca1.png

参考: https://towardsdatascience.com/a-one-stop-shop-for-principal-component-analysis-5582fb7e0a9c

在这里我们可以看到两个方向对,分别由红线和绿线表示。 在这种情况下,红点的幅度更大,因为与绿色方向相比,这些点在更大的距离上更聚集。 主成分分析将使用幅值较大的向量将数据转换为较小的特征空间,从而降低维数。 例如,上面的图将转换为以下内容:

../../_images/pca2.png

参考: https://towardsdatascience.com/a-one-stop-shop-for-principal-component-analysis-5582fb7e0a9c

通过以这种方式转换数据,我们已经忽略了对模型不那么重要的特征-也就是说,沿绿色方向的较大变化比沿红色方向的变化对结果的影响更大。

为简洁起见,本次讨论不包括主成分分析背后的数学,但是如果您有兴趣学习它们,我们强烈建议您访问本页底部列出的参考文献。

成分数

在上面的示例中,我们采用了二维特征空间并将其缩减为一维。 但是,在大多数情况下,您将使用两个以上的变量。 主成分分析可用于仅删除单个特征,但减少多个特征通常很有用。 您可以采用几种策略来决定要执行多少次特征缩减:

  1. 任意

    这仅涉及选择许多特征以保留给定模型。 此方法高度依赖于您的数据集和要传达的内容。 例如,将您的高阶数据表示在 2D 空间进行可视化可能会有所帮助。 在这种情况下,您将执行特征简化,直到拥有两个特征。

  2. 累积变异性的百分比

    主成分分析计算的一部分涉及寻找方差的比例,该方差在每轮 PCA 执行中接近 1。 选择特征减少步骤数的这种方法涉及选择目标方差百分比。 例如,让我们看一下理论数据集在 PCA 各个级别上的累积方差图:

    ../../_images/pca3.png

    参考: https://www.centerspace.net/clustering-analysis-part-i-principal-component-analysis-pca

    上面的图像称为碎石图,它表示每个主成分的累积和当前方差比例。 如果我们希望至少有 80% 的累积方差,我们将根据此 scree 图使用至少 6 个主成分。 通常不建议针对 100% 的差异,因为达到这意味着您的数据集具有冗余数据。

  3. 个体变异性的百分比

    在达到累积的可变性百分比之前,不使用主成分,而可以使用主成分,直到新成分不会增加太多可变性为止。 在上图中,我们可能选择使用 3 个主要成分,因为下一个成分的变异性没有那么大的下降。

总结

主成分分析是一种汇总数据的技术,并且根据您的用例具有很高的灵活性。 在显示和分析大量可能的因变量方面,它可能很有价值。 执行主成分分析的技术范围从任意选择主成分到自动找到它们直到达到差异为止。

代码示例

我们的示例代码 pca.py 展示了如何对随机 x,y 对的数据集执行主成分分析。 该脚本经过很短的生成这些数据的过程,然后调用 sklearn 的 PCA 模块:

# Find two principal components from our given dataset
pca = PCA(n_components = 2)
pca.fit(points)

该过程的每个步骤都包含使用 matplotlib 的有用可视化。 例如,上面拟合的主成分被绘制为数据集上的两个向量:

../../_images/pca5.png

该脚本还显示了如何执行上述降维。 在 sklearn 中,这是通过在安装 PCA 之后简单地调用 transform 方法来完成的,或者使用 fit_transform 同时执行两个步骤:

# Reduce the dimensionality of our data using a PCA transformation
pca = PCA(n_components = 1)
transformed_points = pca.fit_transform(points)

转换的最终结果只是一系列 X 值,尽管该代码示例执行了逆向转换以在下图中绘制结果:

../../_images/pca6.png

参考文献

  1. http://www.cs.otago.ac.nz/cosc453/student_tutorials/principal_components.pdf
  2. https://towardsdatascience.com/a-one-stop-shop-for-principal-component-analysis-5582fb7e0a9c
  3. https://towardsdatascience.com/pca-using-python-scikit-learn-e653f8989e60
  4. https://en.wikipedia.org/wiki/Principal_component_analysis
  5. https://stats.stackexchange.com/questions/2691/making-sense-of-principal-component-analysis-eigenvectors-eigenvalues
  6. https://www.centerspace.net/clustering-analysis-part-i-principal-component-analysis-pca

深度学习

多层感知机

原文: https://machine-learning-course.readthedocs.io/en/latest/content/deep_learning/mlp.html

概述

多层感知机(MLP)是深层的人工神经网络。 神经网络由节点层组成,这些节点根据先前层的节点在不同级别上激活。 在考虑神经网络时,将您的思想隔离到网络中的单个节点可能会有所帮助。

多层感知机是指具有至少三层节点,一个输入层,一些中间层和一个输出层的神经网络。 给定层中的每个节点都连接到相邻层中的每个节点。 输入层就是它,它是网络接收数据的方式。 中间层是网络的计算机,它们实际上将输入转换为输出。 输出层是从神经网络获得结果的方式。 在一个响应为二进制的简单网络中,输出层中可能只有一个节点,该节点输出的概率类似于 logistic 回归

要直观地查看正在运行的神经网络,请使用此网站,您可以在其中看到数字识别神经网络。 在本节中,想法集中在“完全连接”的层上,因此请尝试从这些角度进行思考。

他们需要标记的样本数据,因此他们进行有监督的学习。 对于每个训练样本,节点根据上一层的存储权重激活。 在训练期间(以及以后),权重将不会完全准确,因此需要稍作调整才能达到理想的效果。 MLP 使用一种称为反向传播的方法来从训练数据中学习,我们将在这里对此进行简要介绍。

动机

多层感知机是神经网络的基本类型,在进入更高级的模型之前应充分理解。 通过检查 MLP,我们应该能够避免深度学习中更高级的主题中出现的一些复杂情况,并建立知识基线。

这并不是要低估主题,因为即使是简单的网络也可以取得很好的效果。 被证明,具有单个隐藏层的网络可以近似任何连续函数。

什么是节点?

节点是神经网络中的单个单元。 节点在不同级别上激活,具体取决于上一层节点的加权总和。 实际上,实际激活是将 S 型函数应用于此结果的结果,但为简单起见,我们将在此处跳过该细节。 以这种方式考虑输出不会丢失任何神经网络的魔力,同时避免了一些痛苦的细节。 在 MLP 中,节点根据激活上一层中所有节点的

在此示例中,我们将重点放在单节点层上,这是出于示例目的。 每行代表上一层中节点的权重。 每个连接的权重之和乘以连接的节点的激活数,就可以激活我们的节点。 这里的关键是权重,因为权重决定了节点的输出。 请记住,节点仅从上一层获取输入,因此权重是同一层中节点的唯一区别。

什么定义了多层感知机?

多层感知机(MLP)是前馈神经网络的一种,其特征在于输入层,一些中间层和输出层是完全连接的。 MLP 使用反向传播进行训练。 术语前馈是指网络中的分层架构,特别是网络中没有周期。 层结构可确保不存在循环,因为仅允许层具有来自直接上一层的权重。 术语完全连接是指以下事实:在 MLP 中,给定层中的所有节点都具有前一层中所有节点的权重。

什么是反向传播?

训练神经网络时,预期输出是输出层中每个节点的激活级别。 从该信息和实际激活,我们可以找到每个节点的成本,并相应地调整权重。 反向传播的想法是调整权重,以根据成本确定每个节点的激活状态。

为了使这个想法更深入,我们将避免有关精确数学如何工作的细节,而是着眼于大局。 如果您想看数学,请查看这篇文章

看一下从先前链接的张量流测试站点获取的屏幕截图。 在这里,我们正在训练一个神经网络,对蓝色点和橙色点进行分类。 此处为节点所做的选择是任意的,我们鼓励您弄乱它们。

Tensorflow site 1

要讨论反向传播,让我们考虑一下该网络第一步。 网络将测试网络中的一些训练数据,期望在(隐藏)正确的输出节点上看到完全激活,而在错误的输出节点上没有看到激活。 当模型不正确时,它将从输出向后看,以找出错误之处。 然后,它将相应地改变权重,因此偏离的权重将比接近的权重改变更多。 在这些早期步骤中,它将具有较高的学习率,从而使权重更加不稳定。 经过几次迭代后,它将更加稳定,因为它需要进行较小的调整。 考虑到这一点,让我们前进一步。

Tensorflow site 2

现在,网络对如何对数据进行分类有一个模糊的想法。 它有一个松散的圆圈,随着我们的进行,它将变得更加清晰。 让我们向前走几步。

Tensorflow site 3

如您所见,该模型具有更好的表现,可以对大多数点进行准确分类。 在这一点上,网络减慢了学习率,因为它已经经历了足够的迭代才能获得成功。

总结

在本节中,我们了解了神经网络的多层感知机(MLP)类,以及有关整个神经网络的一些知识。 我们谈到了节点是什么,以及它对周围发生的事情有什么了解。 我们讨论了网络如何从训练数据中学习,特别是使用反向传播。 我们还研究了定义 MLP 网络的内容以及它们与其他神经网络的区别。

更多资源

如果您想了解有关神经网络的更多信息,我们推荐 YouTube 上 3Blue1Brown 的播放列表

播放列表涵盖了一种更直观的神经网络方法,可以帮助您填写神经网络的一些细节。

参考文献

  1. https://playground.tensorflow.org/
  2. https://en.wikipedia.org/wiki/Universal_approximation_theorem
  3. https://www.techopedia.com/definition/20879/multilayer-perceptron-mlp
  4. http://neuralnetworksanddeeplearning.com/chap2.html
  5. https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi
  6. http://cs231n.stanford.edu/

卷积神经网络

原文: https://machine-learning-course.readthedocs.io/en/latest/content/deep_learning/cnn.html

概述

在最后一个模块中,我们通过讨论多层感知机来开始深入学习。 在本模块中,我们将学习卷积神经网络,也称为 CNNConvNets 。 CNN 与其他神经网络的不同之处在于,顺序层不一定完全连接。 这意味着输入神经元的子集只能馈入下一层的单个神经元。 CNN 的另一个有趣特征是其输入。 在其他神经网络中,我们可能会将向量用作输入,但是对于 CNN,我们通常会处理具有许多维度的图像和其他对象。 图 1 显示了一些分别为 6 像素乘 6 像素的示例图像。 第一张图像是彩色的,并具有三个用于红色,绿色和蓝色值的通道。 第二张图像是黑白图像,只有一个通道用于灰度值

../../_images/Images.png

图 1.两个样本图像及其颜色通道

动机

CNN 广泛用于我们试图分析视觉图像的计算机视觉中。 CNN 也可以用于其他应用,例如自然语言处理。 我们将在这里集中讨论前一种情况,因为它是 CNN 的最常见应用之一。

因为我们假设我们正在处理图像,所以我们可以设计架构,使其特别擅长分析图像。 图像具有高度,深度和一个或多个颜色通道。 在图像中,可能存在构成形状以及更复杂的结构(例如汽车和人脸)的线条和边缘。 为了正确地对图像进行分类,我们可能需要识别大量相关特征。 但是,仅识别图像中的单个特征通常是不够的。 假设我们有一张可能是或不是脸的图像。 如果我们看到三个鼻子,一个眼睛和一个耳朵,即使这些是脸部的常见特征,我们可能也不会称其为脸部。 因此,我们还必须考虑特征在图像中的位置以及它们与其他特征的接近程度。 这是要跟踪的很多信息! 幸运的是,CNN 的架构将满足很多这些要求。

架构

CNN 的架构可以分为输入层,一组隐藏层和输出层。 这些在图 2 中显示。

../../_images/Layers.png

图 2. CNN 的层

隐藏的层是魔术发生的地方。 隐藏的层将分解我们的输入图像,以识别图像中存在的特征。 最初的层专注于诸如边缘之类的底层特征,而随后的层逐梯度得更加抽象。 在所有层的最后,我们都有一个完全连接的层,其中包含每个分类值的神经元。 我们最终得出的是每个分类值的概率。 我们选择概率最高的分类作为对图像显示内容的猜测。

下面,我们将讨论在隐藏层中可能使用的某些类型的层。 请记住,除最终输出层外,顺序层不一定完全连接。

卷积层

我们将讨论的第一种类型的层称为卷积层。 卷积描述来自数学中的卷积概念。 粗略地讲,卷积是一种作用于两个输入函数并产生输出函数的运算,该输出函数组合了输入中存在的信息。 第一个输入将是我们的图像,第二个输入将是某种过滤器,例如模糊或锐化。 当我们将图像与过滤器组合时,我们会提取一些有关图像的信息。 图 3 中显示了此过程。 这正是 CNN 提取特征的方式。

../../_images/Filtering.png

图 3.过滤前后的图像

在人眼中,单个神经元仅负责我们视野的一小部分。 通过许多具有重叠区域的神经元,我们才能够看到世界。 CNN 相似。 卷积层中的神经元仅负责分析输入图像的一小部分,但重叠,因此我们最终将分析整个图像。 让我们研究一下我们上面提到的过滤器概念。

过滤器是卷积中使用的功能之一。 过滤器的高度和宽度可能会比输入图像小,并且可以认为是在图像上滑动的窗口。 图 4 显示了样本过滤器以及在卷积第一步中将与之交互的图像区域。

../../_images/Filter1.png

图 4.图像的样本过滤器和样本窗口

当过滤器在图像上移动时,我们正在计算卷积输出的值,称为特征图。 在每一步中,我们将图像样本中的每个条目相乘并逐元素过滤,并对所有乘积求和。 这将成为特征地图中的条目。 图 5 中显示了此过程。

../../_images/Filter2.png

图 5.计算特征图中的条目

窗口遍历整个图像后,我们便拥有了完整的特征图。 这在图 6 中显示。

../../_images/Filter3.png

图 6.完整特征图

在上面的示例中,我们将过滤器从某个先前位置水平移动了一个单位或垂直移动了一个单位。 此值称为步幅。 我们可以为跨步使用其他值,但到处使用一个值往往会产生最佳结果。

您可能已经注意到,我们最终得到的特征图的高度和宽度比原始图像样本小。 这是我们在样本周围移动过滤器的方式的结果。 如果希望特征图具有相同的高度和宽度,则可以填充样本。 这涉及在样本周围添加零项,以便移动过滤器以将原始样本的尺寸保留在特征图中。 图 7 说明了此过程。

../../_images/Padding.png

图 7.应用过滤器之前的填充

特征图表示我们要分析图像的一种类型的特征。 通常,我们想分析图像中的一堆特征,因此最终得到一堆特征图! 卷积层的输出是一组特征图。 图 8 显示了从图像转到生成的特征图的过程。

../../_images/Convo_Output.png

图 8.卷积层的输出

在卷积层之后,通常有一个 ReLU (整流线性单元)层。 该层的目的是将非线性引入系统。 基本上,现实世界中的问题很少是线性的,因此我们希望我们的 CNN 在训练时予以考虑。 关于这一层的一个很好的解释需要我们不希望您知道的数学。 如果您对该主题感到好奇,可以在中找到说明

池化层

我们将介绍的下一种类型的层称为池化层。 池化层的目的是减小问题的空间大小。 反过来,这减少了 CNN 中处理所需的参数数量和计算总量。 池化有多种选择,但我们将介绍最常见的方法最大池化

在最大池化中,我们在输入上滑动一个窗口,并在每一步取最大值。 图 9 中显示了此过程。

../../_images/Pooled.png

图 9.特征图上的最大池化

最大池化是好的,因为它保留了有关输入的重要特征,通过忽略较小的值来减少噪声,并减小问题的空间大小。 我们可以在卷积层之后使用这些,以使问题的计算可管理。

全连接层

我们将讨论的最后一种类型的层称为全连接层。 全连接层用于在 CNN 中进行最终分类。 它们的工作就像在其他神经网络中一样。 在移到第一个完全连接的层之前,我们必须将输入值展平为该层可以解释的一维向量。 图 10 显示了将多维输入转换为一维向量的简单示例。

../../_images/Flatten.png

图 10.展平输入值

完成此操作后,我们可能在最终输出层之前有几个完全连接的层。 输出层使用某些函数,例如 softmax ,将神经元值转换为我们类上的概率分布。 这意味着图像有一定的可能性被归类为我们的类别之一,并且所有这些概率之和等于 1。 这在图 11 中清晰可见。

../../_images/Layers_Final.png

图 11.最终概率输出

训练

现在我们已经有了 CNN 的架构,我们可以继续进行训练了。 训练 CNN 与训练普通神经网络几乎完全相同。 由于卷积层的存在,增加了一些复杂性,但是训练策略保持不变。 诸如梯度下降或反向传播之类的技术可用于训练网络中的滤波器值和其他参数。 与我们涵盖的所有其他训练一样,拥有大量训练将提高 CNN 的表现。 训练 CNN 和其他深度学习模型的问题在于,它们比我们先前模块中介绍的模型复杂得多。 这就导致训练需要更多的计算资源,以至于我们需要像 GPU 这样的专用硬件来运行代码。 但是,我们得到了付款,因为深度学习模型比早期模块中涵盖的模型强大得多。

总结

在本模块中,我们学习了卷积神经网络。 CNN 与其他神经网络的不同之处在于,它们通常将图像作为输入,并且可能具有未完全连接的隐藏层。 CNN 是广泛用于图像分类应用的强大工具。 通过使用各种隐藏层,我们可以从图像中提取特征,并使用它们来概率地猜测分类。 CNN 也是复杂的模型,了解 CNN 的工作原理是一项艰巨的任务。 我们希望所提供的信息能使您更好地了解 CNN 的工作方式,以便您可以继续了解 CNN 和进行深度学习。

参考文献

  1. https://towardsdatascience.com/convolutional-neural-networks-for-beginners-practical-guide-with-python-and-keras-dc688ea90dca
  2. https://medium.com/technologymadeeasy/the-best-explanation-of-convolutional-neural-networks-on-the-internet-fbb8b1ad5df8
  3. https://medium.freecodecamp.org/an-intuitive-guide-to-convolutional-neural-networks-260c2de0a050
  4. https://towardsdatascience.com/a-comprehensive-guide-to-convolutional-neural-networks-the-eli5-way-3bd2b1164a53
  5. https://ujjwalkarn.me/2016/08/11/intuitive-explanation-convnets/
  6. https://www.kaggle.com/dansbecker/rectified-linear-units-relu-in-deep-learning
  7. https://en.wikipedia.org/wiki/Convolutional_neural_network#ReLU_layer

自编码器

原文: https://machine-learning-course.readthedocs.io/en/latest/content/deep_learning/autoencoder.html

自编码器及其在 TensorFlow 中的实现

在本文中,您将学习自编码器背后的概念以及如何在 TensorFlow 中实现自编码器。

介绍

自编码器是一种神经网络,可模仿其输入并在其输出处生成确切的信息。 它们通常包括两部分:编码器和解码器。 编码器将输入转换为隐藏空间(隐藏层)。 然后,解码器将输入信息重建为输出。 有多种类型的自编码器:

  • 不完整的自编码器:在这种类型中,隐藏的尺寸小于输入的尺寸。 训练此类自编码器可捕获最突出的特征。 但是,在缺乏足够的训练数据的情况下使用过度参数化的架构会导致过拟合,并妨碍学习有价值的特征。 线性解码器可以用作 PCA。 但是,非线性函数的存在创建了更强大的降维模型。
  • 正则化自编码器:不会限制自编码器的尺寸和用于特征学习的隐藏层大小,将添加损失函数以防止过拟合。
  • 稀疏自编码器:稀疏自编码器允许表示信息瓶颈,而无需减小隐藏层的大小。 取而代之的是,它基于损失函数对层内的激活进行惩罚。
  • 去噪自编码器(DAE):我们希望自编码器足够灵敏以重新生成原始输入,但不严格敏感,因此该模型可以学习通用的编码和解码。 该方法是将不显着地损坏了一些噪声与未损坏的数据作为目标输出的输入数据..
  • 压缩自编码器(CAE):在这种类型的自编码器中,对于较小的输入变化,编码后的特征也应该非常相似。 去噪自编码器强制重建特征抵抗输入的微小变化,而收缩式自编码器强制编码器抵抗输入扰动。
  • 变分自编码器:变分自编码器(VAE)提出了一种概率方式,用于解释在隐藏空间中的观察。 因此,不是创建一个编码器来生成代表每个潜在特征的值,而是为每个隐藏特征生成一个概率分布。

在本文中,我们将在 TensorFlow 中设计一个欠完善的自编码器,以训练低维表示形式。

创建一个不完整的自编码器

我们正在努力构建具有 3 层编码器和 3 层解码器的自编码器。 编码器的每一层都将其输入沿空间维度压缩两倍。 类似地,解码器的每个段将其输入维数增加两倍。

import tensorflow.contrib.layers as lays

def autoencoder(inputs):
    # encoder
    # 32 file code blockx 32 x 1   ->  16 x 16 x 32
    # 16 x 16 x 32  ->  8 x 8 x 16
    # 8 x 8 x 16    ->  2 x 2 x 8
    net = lays.conv2d(inputs, 32, [5, 5], stride=2, padding='SAME')
    net = lays.conv2d(net, 16, [5, 5], stride=2, padding='SAME')
    net = lays.conv2d(net, 8, [5, 5], stride=4, padding='SAME')
    # decoder
    # 2 x 2 x 8    ->  8 x 8 x 16
    # 8 x 8 x 16   ->  16 x 16 x 32
    # 16 x 16 x 32  ->  32 x 32 x 1
    net = lays.conv2d_transpose(net, 16, [5, 5], stride=4, padding='SAME')
    net = lays.conv2d_transpose(net, 32, [5, 5], stride=2, padding='SAME')
    net = lays.conv2d_transpose(net, 1, [5, 5], stride=2, padding='SAME', activation_fn=tf.nn.tanh)
    return net

../../_images/ae.png

图 1:自编码器

MNIST 数据集包含 28X28 的向量图像。 因此,我们定义了一个新函数,将每批 MNIST 图像的形状调整为 28X28,然后调整为 32X32。 调整为 32X32 大小的原因是使其具有 2 的幂,因此我们可以轻松地使用 2 的步幅进行下采样和上采样。

import numpy as np
from skimage import transform

def resize_batch(imgs):
    # A function to resize a batch of MNIST images to (32, 32)
    # Args:
    #   imgs: a numpy array of size [batch_size, 28 X 28].
    # Returns:
    #   a numpy array of size [batch_size, 32, 32].
    imgs = imgs.reshape((-1, 28, 28, 1))
    resized_imgs = np.zeros((imgs.shape[0], 32, 32, 1))
    for i in range(imgs.shape[0]):
        resized_imgs[i, ..., 0] = transform.resize(imgs[i, ..., 0], (32, 32))
    return resized_imgs

现在,我们创建一个自编码器,定义一个平方误差损失和一个优化器。

import tensorflow as tf

ae_inputs = tf.placeholder(tf.float32, (None, 32, 32, 1))  # input to the network (MNIST images)
ae_outputs = autoencoder(ae_inputs)  # create the Autoencoder network

# calculate the loss and optimize the network
loss = tf.reduce_mean(tf.square(ae_outputs - ae_inputs))  # claculate the mean square error loss
train_op = tf.train.AdamOptimizer(learning_rate=lr).minimize(loss)

# initialize the network
init = tf.global_variables_initializer()

现在我们可以读取批量,训练网络并最终通过重建一批测试图像来测试网络。

from tensorflow.examples.tutorials.mnist import input_data

batch_size = 500  # Number of samples in each batch
epoch_num = 5     # Number of epochs to train the network
lr = 0.001        # Learning rate

# read MNIST dataset
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

# calculate the number of batches per epoch
batch_per_ep = mnist.train.num_examples // batch_size

with tf.Session() as sess:
    sess.run(init)
    for ep in range(epoch_num):  # epochs loop
        for batch_n in range(batch_per_ep):  # batches loop
            batch_img, batch_label = mnist.train.next_batch(batch_size)  # read a batch
            batch_img = batch_img.reshape((-1, 28, 28, 1))               # reshape each sample to an (28, 28) image
            batch_img = resize_batch(batch_img)                          # reshape the images to (32, 32)
            _, c = sess.run([train_op, loss], feed_dict={ae_inputs: batch_img})
            print('Epoch: {} - cost= {:.5f}'.format((ep + 1), c))

    # test the trained network
    batch_img, batch_label = mnist.test.next_batch(50)
    batch_img = resize_batch(batch_img)
    recon_img = sess.run([ae_outputs], feed_dict={ae_inputs: batch_img})[0]

    # plot the reconstructed images and their ground truths (inputs)
    plt.figure(1)
    plt.title('Reconstructed Images')
    for i in range(50):
        plt.subplot(5, 10, i+1)
        plt.imshow(recon_img[i, ..., 0], cmap='gray')
    plt.figure(2)
    plt.title('Input Images')
    for i in range(50):
        plt.subplot(5, 10, i+1)
        plt.imshow(batch_img[i, ..., 0], cmap='gray')
    plt.show()

原文的协议

原文: https://machine-learning-course.readthedocs.io/en/latest/credentials/LICENSE.html

MIT License
Copyright (c) 2019 Amirsina Torfi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

作者

https://machine-learning-course.readthedocs.io/en/latest/authorship/author.html

创建者:Machine Learning Mindset [博客GitHubTwitter]

总监:Amirsina Torfi [GitHub个人网站Linkedin]

开发者:Brendan Sherman*,James E Hopkins* [Linkedin],Zac Smith [Linkedin]

注意:此项目是由[弗吉尼亚理工大学 CS 4624 多媒体/超文本课程]提供的顶点项目,并由[Machine Learning Mindset]监督和支持。

*:同等贡献

引言

原文: https://machine-learning-course.readthedocs.io/en/latest/intro/intro.html

该项目的目的是提供使用 Python 进行机器学习的全面而简单的课程。

机器学习概述

机器学习如何出现和发展?

您可以争辩说,现代机器学习的开始来自艾伦·图灵(Alan Turing)于 1950 年提出的“图灵测试”。图灵测试旨在确定计算机是否出色(或至少足够聪明,足以愚弄人以为是)。 随着游戏计算机的发展,机器学习继续发展。 这些年来,从跳棋,国际象棋到围棋,这些计算机所玩的游戏变得越来越复杂。 机器学习还被用来模拟自然界中的模式识别系统,例如神经网络。 但是,机器学习不仅限于局限于房间内的大型计算机。 设计了可以使用机器学习自动在障碍物周围导航的机器人。 在今天的自动驾驶汽车中,我们仍然会看到这一概念。 机器学习最终开始用于分析大量数据以得出结论。 这使人类能够通过使用机器学习来消化大型的复杂系统。 对于从事市场营销和广告业以及涉及复杂数据的人来说,这是一个有利的结果。 机器学习也用于图像和视频识别。 机器学习可以对图片和视频中的对象进行分类,以及识别感兴趣的特定地标。 现在可以通过云和大规模分布式系统使用机器学习工具。

为什么机器学习很重要?

机器学习在许多常见业务问题中都有实际应用。 通过使用机器学习,组织可以在更短的时间内更高效地完成任务。 一个示例可能是在需要人工干预的将来阶段预处理一组数据。 以前需要大量用户输入的任务现在可以在某种程度上实现自动化。 然后,可以将节省的资源用于其他需要完成的工作。 除了任务自动化之外,机器学习还可以用于分析大量复杂数据以做出预测。 数据分析是许多企业的基本任务。 例如,一家公司可以分析销售数据,以找出获利的机会在哪里,或者找出在何处亏损的风险。 使用机器学习可以潜在地对复杂数据进行实时分析。 关键任务系统可能需要这种能力。 机器学习也是研究和持续发展的重要主题。 目前,机器学习仍然有很多局限性,并且还无法替代对真人的需求。 机器学习的不断发展可以为棘手的问题提供解决方案,这些问题现在可能占用太多资源,甚至无法考虑。

谁在使用 ML,为什么要使用(政府,医疗保健系统等)?

机器学习将以某种方式影响大多数行业,因此许多经理和高层人士正在尝试至少了解它是什么,如果不是它可以为他们做些什么。 当提供更多信息时,机器学习模型有望更好地进行预测。 如今,轻松获取大量可用于训练非常精确的模型的信息。 如今的计算机也比过去的计算机更强大,并提供诸如云解决方案和分布式处理之类的选项,以解决硬机器学习问题。 几乎所有可以使用机器学习的人都可以轻松获得许多这些选项。 我们可以看到无人驾驶汽车,推荐系统,语言分析,信用评分和安全性等机器学习的示例。 金融服务可以使用机器学习来提供有关客户数据的见解并预测风险领域。 可以访问大量数据并且对精简或至少加速其部分服务感兴趣的政府机构可以利用机器学习。 装有病人数据柜的医疗服务提供者可以使用机器学习来帮助诊断和识别健康风险。 购物服务可以利用客户的购买历史和机器学习技术来提出个性化建议并评估危险产品。 任何拥有大量数据的人都将从使用机器学习中受益。

扩展阅读

核心概念

交叉验证

原文: https://machine-learning-course.readthedocs.io/en/latest/content/overview/crossvalidation.html

动机

针对特定数据集训练模型很容易,但是在引入新数据后该模型的表现如何? 您如何知道要使用哪种机器学习模型? 交叉验证通过确保模型产生准确的结果并将这些结果与其他模型进行比较来回答这些问题。 交叉验证超越了常规验证,即通过评估模型如何对新数据进行分析来分析模型如何在其自身的训练数据上进行的过程。 以下各节讨论了几种不同的交叉验证方法:

Holdout 方法

Holdout 交叉验证方法涉及删除训练数据的特定部分并将其用作测试数据。 首先针对训练集对模型进行训练,然后要求对测试集的输出进行预测。 这是交叉验证技术的最简单形式,如果您有大量数据或需要快速,轻松地实现验证,则此方法很有用。

holdout method

通常,Holdout 方法涉及将数据集分为 20-30% 的测试数据,其余作为训练数据。 这些数字可能会有所不同-较大的测试数据百分比会减少模型的训练经验,从而使您的模型更容易出错,而较小比例的测试数据可能会使模型对训练数据产生不必要的偏差。 缺乏训练或偏置会导致我们模型的欠拟合/过拟合

K 折交叉验证

K 折交叉验证可通过对数据集的 k 个子集重复 Holdout 方法来帮助消除模型中的这些偏差。 借助 K 折交叉验证,数据集可分为多个独特的测试和训练数据折叠。 使用数据的每种组合执行 Holdout 方法,并对结果求平均值以找到总误差估计。

kfold method

这里的“折叠”是测试数据的唯一部分。 例如,如果您有 100 个数据点并使用 10 折,则每折包含 10 个测试点。 K 折叠交叉验证很重要,因为它允许您将完整的数据集用于训练和测试。 当使用较小或有限的数据集评估模型时,此功能特别有用。

Leave-P-Out/留一法交叉验证

Leave-P-Out 交叉验证(LPOCV)通过使用模型上 P 个测试数据点的所有可能组合来测试模型。 举一个简单的例子,如果您有 4 个数据点并使用 2 个测试点,则将按照以下方式训练和测试模型:

1: [ T T - - ]
2: [ T - T - ]
3: [ T - - T ]
4: [ - T T - ]
5: [ - T - T ]
6: [ - - T T ]

其中“ T”是测试点,“-”是训练点。 以下是 LPOCV 的另一种可视化效果:

kfold method

参考: http://www.ebc.cat/2017/01/31/cross-validation-strategies/

LPOCV 可以提供极其准确的误差估计,但是对于大型数据集,它很快就会变得面面俱到。 可以使用数学组合 n C P 来计算使用 LPOCV 模型必须经历的测试迭代次数,其中 n 是我们的数据点总数。 例如,我们可以看到,使用 10 个点的数据集和 3 个测试点运行 LPOCV,将需要 10 C 3 = 120 次迭代。

因此,留一法交叉验证(LOOCV)是一种常用的交叉验证方法。 它只是 LPOCV 的子集,P 为 1。这使我们能够以与数据点相同的步骤数评估模型。 LOOCV 也可以看作是 K 折交叉验证,其中折的数量等于数据点的数量。

kfold method

参考: http://www.ebc.cat/2017/01/31/cross-validation-strategies/

与 K 折交叉验证相似,LPOCV 和 LOOCV 使用完整数据集训练模型。 当您使用小型数据集时,它们特别有用,但会影响表现。

总结

交叉验证是一种针对新数据验证模型的方法。 交叉验证的最有效形式包括针对数据集重复测试模型,直到使用每个点或点的组合来验证模型为止,尽管这需要进行表现折衷。 我们讨论了分割数据集以进行交叉验证的几种方法:

  • Holdout 方法:将一部分数据拆分为测试数据
  • K 折法:将数据划分为多个部分,将每个部分用作测试/训练拆分
  • LPOCV 方法:使用多个点(P)的每一个组合作为测试数据

动机

机器学习模型有很多不同的类型,包括线性/逻辑回归,K 最近邻和支持向量机-但是我们如何知道哪种类型的模型最适合我们的数据集? 使用不适合我们的数据的模型将导致预测的准确率降低,并可能导致财务,自然或其他形式的损害。 个人和公司应确保对使用的任何模型进行交叉验证。

代码示例

提供的代码显示了如何使用 Scikit-Learn (一种 Python 机器学习库),使用三种讨论的交叉验证方法来拆分一组数据。

holdout.py 使用 Holdout 方法拆分一组样本糖尿病数据。 在 scikit-learn 中,这是使用称为train_test_split()的函数完成的,该函数将一组数据随机分为两部分:

TRAIN_SPLIT = 0.7
...

dataset = datasets.load_diabetes()
...

x_train, x_test, y_train, y_test = train_test_split(...)

请注意,您可以通过更改顶部的TRAIN_SPLIT值来更改用于训练的数据部分。 该数字应为 0 到 1 之间的一个数字。此文件的输出显示用于拆分的训练和测试点的数量。 查看实际的数据点可能会有所帮助-如果您想查看这些数据点,请取消注释脚本中的最后两个打印语句。


k-fold.py 使用 K 折方法拆分一组数据。 这是通过创建一个 KFold 对象完成的,该对象初始化为要使用的拆分数。 通过 Scikit-learn,可以轻松调用 KFold 的split()方法来拆分数据:

NUM_SPLITS = 3
data = numpy.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])

kfold = KFold(n_splits=NUM_SPLITS)
split_data = kfold.split(data)

它的返回值是一个训练和测试点的数组。 请注意,您可以通过更改脚本顶部的关联值来使用分割数。 该脚本不仅输出训练/测试数据,还输出一个漂亮的栏,您可以在其中跟踪当前折叠的进度:

[ T T - - - - ]
Train: (2: [5 6]) (3: [7 8]) (4: [ 9 10]) (5: [11 12])
Test:  (0: [1 2]) (1: [3 4])
...


Leave-p-out.py 使用 Leave-P-Out 和 Leave-One-Out 方法拆分一组数据。 这是通过创建 LeavePOut / LeaveOneOut 对象来完成的,该对象使用要使用的拆分数量初始化的 LPO。 与 KFold 相似,训练测试数据拆分是使用split()方法创建的:

P_VAL = 2
data = numpy.array([[1, 2], [3, 4], [5, 6], [7, 8]])

loocv = LeaveOneOut()
lpocv = LeavePOut(p=P_VAL)

split_loocv = loocv.split(data)
split_lpocv = lpocv.split(data)

请注意,您可以在脚本顶部更改 P 值,以查看不同值如何工作。

参考文献

  1. https://towardsdatascience.com/cross-validation-in-machine-learning-72924a69872f
  2. https://machinelearningmastery.com/k-fold-cross-validation/
  3. https://www.quora.com/What-is-cross-validation-in-machine-learning
  4. http://www.ebc.cat/2017/01/31/cross-validation-strategies/

线性回归

原文: https://machine-learning-course.readthedocs.io/en/latest/content/overview/linear-regression.html

动机

当我们看到一个数据集时,我们尝试找出它的含义。 我们在数据点之间寻找连接,看看是否可以找到任何模式。 有时很难看到这些模式,因此我们使用代码来帮助我们找到它们。 数据可以遵循很多不同的模式,因此如果我们可以缩小选择范围并减少编写代码来分析它们的话,将很有帮助。 这些模式之一是线性关系。 如果我们可以在数据中找到这种模式,则可以使用线性回归技术对其进行分析。

概述

线性回归是一种用于分析输入变量和单个输出变量之间的线性关系的技术。 线性关系表示数据点趋向于直线。 简单线性回归仅涉及单个输入变量。 图 1 显示了具有线性关系的数据集。

../../_images/LR.png

图 1.具有线性关系的示例数据集 [代码]

我们的目标是找到最能模拟数据点路径的线,称为最佳拟合线。 公式 1 中的公式是线性公式的示例。

../../_images/Linear_Equation.png

方程 1。线性方程

图 2 显示了我们在图 1 中使用的数据集,并通过了最合适的一行。

../../_images/LR_LOBF.png

图 2.来自图 1 的数据集,具有最佳拟合线 [代码]

让我们分解一下。 我们已经知道 x 是输入值,y 是我们的预测输出。 a₀和 a₁描述我们线的形状。 a₀被称为偏置,而 a₁被称为权重。 更改 a₀将在绘图上向上或向下移动线,更改 a₁会更改线的斜率。 线性回归有助于我们为 a₀和 a₁选择合适的值。

请注意,我们可以有多个输入变量。 在这种情况下,我们称其为多元线性回归。 添加额外的输入变量仅意味着我们需要找到更多权重。 对于本练习,我们将仅考虑简单的线性回归。

何时使用

线性回归是一种有用的技术,但并非总是适合您的数据的正确选择。 当自变量和因变量之间存在线性关系并且您要预测连续值时,线性回归是一个不错的选择[图 1 ]。

当自变量和因变量之间的关系更复杂或输出为离散值时,这不是一个好选择。 例如,图 3 显示的数据集不具有线性关系,因此线性回归将不是一个好选择。

../../_images/Not_Linear.png

图 3。 没有线性关系的样本数据集 [代码]

值得注意的是,有时您可以将转换应用于数据,使其看起来是线性的。 例如,您可以将对数应用于指数数据以使其平坦化。 然后,您可以对转换后的数据使用线性回归。 在此处记录了一种在sklearn中转换数据的方法。

图 4 是看起来不是线性的但可以转换为具有线性关系的数据的示例。

../../_images/Exponential.png

图 4.遵循指数曲线 [代码] 的样本数据集

图 5 是对数转换输出变量后的相同数据。

../../_images/Exponential_Transformed.png

图 5.将对数应用到输出变量 [代码] 后,图 4 中的数据集

成本函数

有了预测后,我们需要某种方法来判断它是否合理。 成本函数可帮助我们完成此任务。 成本函数将所有预测与它们的实际值进行比较,并为我们提供一个可用来对预测函数评分的单一数字。 图 6 显示了一个这样的预测的成本。

../../_images/Cost.png

图 6.来自图 2 的图,其中强调了一个预测的成本 [代码]

成本函数中出现的两个常用术语是误差平方误差。 误差[公式 2 ]离我们的预测的实际值有多远。

../../_images/Error_Function.png

公式 2。示例误差函数

平方该值为我们提供了一个通用误差距离的有用表达式,如公式 3 所示。

../../_images/Square_Error_Function.png

公式 3。平方误差函数示例

我们知道,实际值之上的误差 2 和实际值之下的误差 2 应该彼此差不多。 平方误差使这一点很清楚,因为这两个值都导致平方误差为 4。

我们将使用公式 4 中所示的均方误差(MSE)函数作为我们的成本函数。 此函数查找我们所有数据点的平均平方误差值。

../../_images/MSE_Function.png

公式 4。均方误差(MSE)函数

因为他们衡量我们的模型如何准确的对目标值成本函数对我们非常重要。 确保我们的模型是准确的将始终保持后模块的一个关键主题。

方法

成本较低的函数意味着数据点之间的平均误差较低。 换句话说,较低的成本意味着数据集的模型更准确。 我们将简要介绍一些使成本函数最小化的方法。

普通最小二乘

普通最小二乘法是使成本函数最小化的常用方法。 在这种方法中,我们将数据视为一个大矩阵,并使用线性代数来估计线性方程式中系数的最佳值。 幸运的是,您不必担心做任何线性代数,因为 Python 代码会为您处理它。 这也恰好是用于此模块代码的方法。

以下是此模块中与普通最小二乘法有关的 Python 代码的相关行。

# Create a linear regression object
regr = linear_model.LinearRegression()

梯度下降

梯度下降法是一种猜测线性方程式系数的迭代方法,以最小化成本函数。 该名称来自微积分中的梯度概念。 基本上,此方法将稍微移动系数的值并监视成本是否降低。 如果成本在多次迭代中持续增加,我们会停止,因为我们可能已经达到了最低要求。 可以选择停止前的迭代次数和公差来微调该方法。

以下是此模块经过修改以使用梯度下降的 Python 代码的相关行。

# Create a linear regression object
regr = linear_model.SGDRegressor(max_iter=10000, tol=0.001)

代码

该模块的主要代码位于 linear_regression_lobf.py 文件中。

该模块中的所有图形都是通过 linear_regression.py 代码的简单修改而创建的。

在代码中,我们分析具有线性关系的数据集。 我们将数据分为训练集以训练我们的模型和测试集以测试其准确率。 您可能已经猜到所使用的模型是基于线性回归的。 我们还将显示一条最佳拟合的数据图。

总结

在本模块中,我们学习了线性回归。 此技术可帮助我们使用线性关系对数据进行建模。 线性关系非常简单,但是仍然显示在许多数据集中,因此这是一个很好的技术。 学习线性回归是学习更复杂的分析技术的良好第一步。 在以后的模块中,我们将基于此处介绍的许多概念。

参考文献

  1. https://towardsdatascience.com/introduction-to-machine-learning-algorithms-linear-regression-14c4e325882a
  2. https://machinelearningmastery.com/linear-regression-for-machine-learning/
  3. https://ml-cheatsheet.readthedocs.io/en/latest/linear_regression.html
  4. https://machinelearningmastery.com/implement-simple-linear-regression-scratch-python/
  5. https://medium.com/analytics-vidhya/linear-regression-in-python-from-scratch-24db98184276
  6. https://scikit-learn.org/stable/auto_examples/linear_model/plot_ols.html
  7. https://scikit-learn.org/stable/modules/generated/sklearn.compose.TransformedTargetRegressor.html

过拟合和欠拟合

原文: https://machine-learning-course.readthedocs.io/en/latest/content/overview/overfitting.html

概述

使用机器学习时,有很多方法出错。 机器学习中最常见的一些问题是过拟合过拟合。 为了理解这些概念,我们假设一个机器学习模型正在尝试学习对数字进行分类,并且可以访问一组训练数据和一组测试数据。

过拟合

当模型从训练数据中学到太多时,就会出现过拟合的情况,结果在实践中表现不佳。 这通常是由于模型过多地暴露于训练数据引起的。 对于数字分类示例,如果模型以这种方式过拟合,则可能是在误导的微小细节上出现,例如流浪标记表示特定数字。

当您查看图表中间时,估计值看起来不错,但是边缘的误差很大。 实际上,此误差并不总是出现在极端情况下,并且可能在任何地方弹出。 训练中的噪音可能会导致错误,如下图所示。

Overfit

(使用 https://www.desmos.com/calculator/dffnj2jbow 创建)

在此示例中,数据过拟合多项式。 所示的点对函数 y = x ^ 2 是正确的,但在这些点之外不能很好地近似函数。

欠拟合

如果模型没有从训练数据中学到足够的知识,则会遭受欠拟合的折磨,结果在实践中表现不佳。 与先前的想法形成直接对比,此问题是由于没有让模型从训练数据中学到足够的知识而引起的。 在数字分类示例中,如果训练集太小或模型没有足够的尝试从中学习,则训练集将无法挑选出数字的关键特征。

该估计的问题在人眼中很明显,该模型应该是非线性的,而只是一条简单的线。 在机器学习中,这可能是欠拟合的结果,该模型没有足够的训练数据来适应它,并且目前处于简单状态。

Underfit

(使用 Wolfram Alpha 创建)

动机

找到合适的机器是机器学习中的核心问题之一。 甚至在担心特定方法之前都可以很好地掌握如何避免拟合问题,从而使模型步入正轨。 拥有合适的猎物心态,而不是花费更多的学习时间在模型上,是非常重要的。

代码

过拟合的示例代码显示了一些基于多项式插值的基本示例,试图找到图的方程。 在 overfitting.py 文件中,您可以看到正在建模一个真实的函数,以及一些估计不准确的估计。

估计值代表过拟合和欠拟合。 对于过拟合,使用了更高次的多项式(x 求立方而不是平方)。 尽管所选点的数据相对接近,但它们之外还存在一些伪像。 但是,欠拟合的示例在许多方面甚至都无法达到精度。 欠拟合类似于在对二次函数建模时具有线性模型。 该模型在训练的点上效果很好,在这种情况下,该点用于线性估计,但在其他方面效果不佳。

总结

查看交叉验证和正则化部分,以获取有关如何避免机器学习模型过拟合的信息。 理想情况下,合适的外观如下所示:

Underfit

(使用 Wolfram Alpha 创建)

当以任何能力使用机器学习时,经常会出现诸如过拟合之类的问题,并且掌握这一概念非常重要。 本节中的模块是整个仓库中最重要的模块之一,因为无论采用哪种实现,机器学习始终包括这些基础知识。

参考文献

  1. https://machinelearningmastery.com/overfitting-and-underfitting-with-machine-learning-algorithms/
  2. https://medium.com/greyatom/what-is-underfitting-and-overfitting-in-machine-learning-and-how-to-deal-with-it-6803a989c76
  3. https://towardsdatascience.com/overfitting-vs-underfitting-a-conceptual-explanation-d94ee20ca7f9
posted @ 2026-03-26 12:21  布客飞龙III  阅读(13)  评论(0)    收藏  举报