Machine Learning Mastery 机器学习算法教程(二)
原文:Machine Learning Mastery协议:CC BY-NC-SA 4.0在实现机器学习算法时,不要从开源代码开始原文: machinelearningmastery.com/dont-start-with-open-source-code-when-implementing-machine-learning-algorithms/Edward Raff 是 Java 机器学习库的
在实现机器学习算法时,不要从开源代码开始
Edward Raff 是 Java 机器学习库的作者,名为 JSAT (Java 统计分析工具的首字母缩写)。
Edward 在创建这个库时实现了很多算法,最近我和他联系并询问他可以给初学者从零开始实现机器学习算法的建议。
在这篇文章中,我们将介绍基于 Edwards 建议实现机器学习算法的技巧。
从零开始实现机器学习算法
照 hackNY.org ,保留一些权利
不要阅读其他人民源代码
至少,不是最初的。
是什么让我问爱德华有关他从零开始实现机器学习算法的建议的问题是他对 Reddit 问题的评论,题目是“实现机器学习算法”。
在他的评论中,Edward 建议初学者尽可能避免查看其他开源实现的源代码。他知道这与大多数建议相反(甚至是我自己的),它确实引起了我的注意。
Edward 开始建议在实现机器学习算法时有两个完全不同的任务:
- ****实现熟知算法。这些在许多论文,书籍,网站讲义等中都有很好的描述。你有很多来源,他们的算法比较直接,他们是自我教育的好案例研究。
- 从论文实现算法。这些算法在文献中具有有限和稀疏的描述,并且需要大量的工作和先前的知识来理解和实现。
获取免费算法思维导图
方便的机器学习算法思维导图的样本。
我已经创建了一个由类型组织的 60 多种算法的方便思维导图。
下载,打印并使用它。
实现众所周知的算法
如果您对实现众所周知的算法感兴趣,Edward 建议阅读代码是一个坏主意。
我从他的评论中提炼了至少 3 个关键原因:
- 代码优化:开源库中的代码很可能针对执行速度,内存和准确率进行了高度优化。这意味着它实现了各种数学和编程技巧。结果,代码将很难遵循。您将花费大部分时间来计算技巧而不是计算出算法,这首先是您的目标。
- 以项目为中心:代码不是一个可以单独运行的通用实现,它将精心设计为在项目框架内工作。框架也很可能从 _ 方便地 _“抽象和隐藏细节。您将花时间学习该框架及其设计,以便了解算法实现。
- 有限理解:研究算法的实现并不能帮助您理解算法,它可以教您高效算法实现的技巧。一开始,最关键的时候,其他人的代码会让你感到困惑。
我认为这里有很深的智慧。
我要指出的是,开源实现有时可以帮助理解特定的技术细节,例如更新规则或其他可能描述不当的模块化数据,但是在代码中的单个函数中实现。我自己经历过很多次,但它是一种启发式的,而不是一种规则。
爱德华建议像 k-means 和随机梯度下降这样的算法作为开始的好例子。
从论文实现算法
Edward 建议如果你没有首先实现众所周知的算法,那么从纸上实现机器学习算法是一个很大的进步,如上所述。
根据 Edwards 的评论,您可以从零开始实现学习机器学习算法的过程。我对该过程的解释如下所示:
- 从零开始实现算法。
- 将表现与现成的实现进行比较。
- 努力工作以满足表现和结果。
- 查看开源代码以了解高级技巧和窍门。
他建议创建自己未经优化的实现将向您指出效率低下的地方,激励您修复它们,激励您深入了解它们并找出它们如何在其他地方得到解决。
他进一步建议,简单地应对实现不会教会您需要了解的内容,您将错过对算法及其未经优化的表现特征的深入理解,以及如何在类似类的算法中推广优化。
给初学者的建议
在通过电子邮件进行一些讨论后,爱德华扩展了他的评论并在一篇题为“初学者关于学习实现 ML 算法的建议”的博客文章中写下了他的想法。
这是一篇很棒的文章。在其中,他提出了三个关键问题:如何从零开始实现机器学习算法,为初学者提供常见陷阱以及可能有用的资源。
这篇文章不仅仅是伟大的,因为这些建议来自于辛苦挣来的智慧(爱德华很难做机器学习 - 他实践它,你应该这样做),但很少有任何帖子那样喜欢它。没人在谈论如何从零开始实现机器学习算法。我的目标是解决这个问题。
爱德华的关键信息是你需要练习。实现机器学习算法要求您了解每种算法的背景,包括该领域的理论,数学和历史以及算法。这不会很快或很容易。你必须努力工作,重复你的理解和实践。
如果你是一名专业的程序员,那么你所知道的,掌握就不会少了。
实现算法的技巧
在他的博客文章中,Edward 提供了 4 个主要技巧,可以帮助您从零开始实现机器学习算法。总之,它们是:
- 阅读全文。慢慢阅读全文。然后沉浸在想法中一段时间,比如说几天。稍后再读一遍,但直到你有一个关于算法如何工作的数据流以及它们如何挂在一起的第一个你自己的心理模型。有意读。随后的读取必须纠正并改进您对算法的现有理解。
- 设计测试问题。找到,选择或设计一个足够简单的测试问题,以便您理解和可视化算法的结果或行为,但复杂程度足以强制程序展示差异化特征或结果。这个问题将是你的试金石,告诉你什么时候实现是正确的,什么时候优化没有引入致命的错误。爱德华称之为“_ 有用的宏功能单元测试 _”。
- 优化最后。首先通过从零开始实现整个过程来理解算法的过程和逻辑,利用很少的现有代码或技巧。只有在您理解并具有可行的实现之后,才应考虑在空间或时间复杂度方面提高表现,或者使用算法扩展来提高表现。
- 了解基础。在生产级实现方面,您可以利用现有库。 Edward 指出了诸如 LIBSVM 和 LIBLINEAR 之类的例子。这些功能强大的库包含数十年的错误修复和优化功能。在采用它们之前,请确信您确切了解您正在利用的是什么,它是如何工作的以及它所提供的好处的特征。有目的地优化您的实现,使用最好的并理解它的作用。
同样,这些提示中有很多智慧。我自己也不能把它变得更好。特别是。我非常同意从零开始无效地实现算法以最大化学习的需要。算法优化是一种进口但完全不同的技能,用于完全不同的目的。
记住这一点。
避免初学者陷阱
爱德华继续强调初学者陷入的常见陷阱。总之,它们是:
- 不要认为研究论文是正确的,同行评审并不完美,错误(有时是大错误)会成为出版物。
- 不要尝试对算法进行无数学理解,数学可以有效且明确地描述算法过程的显着部分,这非常重要。
- 如上所述,不要从其他人的源代码开始。
- 您无法知道如何有效地将算法应用于问题,从类似的论文中寻找可转移的应用程序想法。
- 生成的默认随机数通常不会削减它,使用更好的东西,但不能使用加密强度。
- 脚本语言在优化时不会削减芥末(他的个人观点,并且表明可能存在争议的观点。我个人认为静态类型在大型生产系统中省去了很多头痛)。
摘要
实现机器学习算法是学习机器学习的一种很好的(如果不是最好的)方法。知识是内心的,因为你必须为细节而汗流,背,他们变得亲密。当您尝试从算法中获得最大收益时,这会有所帮助。
在这篇文章中,您发现经常建议的“_ 阅读开源实现 _”并没有错,但需要在您的学习策略中仔细考虑。
爱德华建议你学习机器学习算法的难点,自己弄清楚,以便你成长,然后转向开源实现,学习有效的数学和程序技巧来优化实现,如果你当需要那些效率。
这是一个细微而有价值的建议。
不要使用随机猜测作为基线分类器
原文:
machinelearningmastery.com/dont-use-random-guessing-as-your-baseline-classifier/
我最近通过电子邮件收到了以下问题:
嗨,杰森,快速提问。一类失衡:90 例竖起大拇指向下 10 例。在这种情况下,我们如何计算随机猜测的准确率?
我们可以使用一些基本概率回答这个问题(我打开了 excel 并输入了一些数字)。
不要使用随机猜测作为您的基线分类器
照片由 cbgrfx123 ,保留一些权利。
假设 0 级和 1 级的分割是 90%-10%。我们也说你会用相同的比例随机猜测。
随机猜测两分类问题的理论精度是:
= P(class is 0) * P(you guess 0) + P(class is 1) * P(you guess 1)
我们可以在我们的示例 90%-10%分割中测试这个:
= (0.9 * 0.9) + (0.1 * 0.1)
= 0.82
= 0.82 * 100 or 82%
要检查数学,您可以插入 50%-50%的数据分割,它符合您的直觉:
= (0.5 * 0.5) + (0.5 * 0.5)
= 0.5
= 0.5 * 100 or 50%
如果我们查看 Google,我们会在 Cross Validated 上找到类似的问题“不平衡分类问题的机会级准确度是多少? “答案几乎相同。再次,一个很好的确认。
有趣的是,所有这一切都有一个重要的要点。
不要使用随机猜测作为基线
如果您正在寻找用作基线准确度的分类器,请不要使用随机猜测。
有一个名为 Zero Rule 的分类器(或简称为 0R 或 ZeroR)。这是您可以在分类问题上使用的最简单的规则,它只是预测数据集中的多数类(例如模式)。
在上面的例子中,0 级和 1 级的 90%-10%,它将为每个预测预测 0 级,并达到 90%的准确率。这比使用随机猜测的理论最大值好 8%。
使用零规则方法作为基线。
此外,在这种不平衡的分类问题中,您应该使用除精度之外的度量,例如 Kappa 或 ROC 曲线下的面积。
有关分类问题的替代表现度量的更多信息,请参阅帖子:
有关处理不平衡分类问题的更多信息,请参阅帖子:
你对这篇文章有任何疑问吗?在评论中提问。
浅谈机器学习中的概念漂移
原文:
machinelearningmastery.com/gentle-introduction-concept-drift-machine-learning/
数据可能会随时间而变化。这可能导致预测模型中的预测表现较差且降级,假设输入和输出变量之间存在静态关系。
这种改变数据中潜在关系的问题在机器学习领域被称为概念漂移。
在这篇文章中,您将发现概念漂移的问题,以及您可以在自己的预测性建模问题中解决它的方法。
完成这篇文章后,你会知道:
- 数据随时间变化的问题。
- 什么是概念漂移及其定义方式。
- 如何在您自己的预测性建模问题中处理概念偏差。
让我们开始吧。
机器学习中概念漂移的温和介绍
Joe Cleere 的照片,保留一些权利。
概观
这篇文章分为 3 部分;他们是:
- 随时间变化的数据
- 什么是概念漂移?
- 如何解决概念漂移问题
随时间变化的数据
预测性建模是从历史数据中学习模型并使用模型对我们不知道答案的新数据做出预测的问题。
从技术上讲,预测性建模是在给定输入数据(X)以预测输出值(y)的情况下近似映射函数(f)的问题。
y = f(X)
通常,这种映射被认为是静态的,这意味着从历史数据中学习的映射在将来对新数据同样有效,并且输入和输出数据之间的关系不会改变。
这对许多问题都是如此,但并非所有问题都是如此。
在某些情况下,输入和输出数据之间的关系可能会随着时间的推移而发生变化,这意味着未知的底层映射函数会发生变化。
这些变化可能是重要的,例如,对较旧的历史数据进行训练的模型所做的预测不再正确或者如果模型是根据最近的历史数据进行训练那么正确。
反过来,可以检测这些变化,并且如果检测到,则可以更新学习的模型以反映这些变化。
…许多数据挖掘方法都假设发现的模式是静态的。但是,实际上,数据库中的模式会随着时间的推移而发展。这带来了两个重要挑战。第一个挑战是检测概念漂移何时发生。第二个挑战是使模式保持最新,而不是从零开始引入模式。
- 第 10 页,数据挖掘和知识发现手册,2010 年。
什么是概念漂移?
机器学习和数据挖掘中的概念漂移是指随着时间的推移,潜在问题中输入和输出数据之间关系的变化。
在其他领域,这种变化可能被称为“_ 协变量移位 ”,“ 数据集移位 ”或“ 非平稳性 _”。
在最具挑战性的数据分析应用程序中,数据随着时间的推移而发展,必须近乎实时地进行分析。这些数据中的模式和关系经常随着时间的推移而发展,因此,为分析此类数据而构建的模型会随着时间的推移而迅速变得过时。在机器学习和数据挖掘中,这种现象被称为概念漂移。
- 概念漂移应用概述,2016。
“_ 概念漂移 _”中的概念是指输入和输出变量之间的未知和隐藏关系。
例如,天气数据中的一个概念可能是未在温度数据中明确指定的季节,但可能影响温度数据。另一个例子可能是随着时间的推移客户购买行为可能受到经济实力的影响,其中经济实力没有在数据中明确规定。这些元素也称为“隐藏上下文”。
在许多现实领域中学习的一个难题是感兴趣的概念可能依赖于某些隐藏的上下文,而不是以预测特征的形式明确给出。一个典型的例子是天气预报规则可能随季节而有根本变化。 […]通常隐藏变化的原因,而不是先验的,使学习任务更加复杂。
- 概念漂移的问题:定义和相关工作,2004。
对数据的更改可以采取任何形式。从概念上讲,更容易考虑这样一种情况,即变化存在一定的时间一致性,使得在特定时间段内收集的数据显示出相同的关系,并且这种关系随时间平滑变化。
请注意,情况并非总是如此,这一假设应该受到挑战。其他一些类型的更改可能包括:
- 随着时间的推移逐梯度化。
- 经常性或周期性变化。
- 突然或突然的变化。
每种情况可能需要不同的概念漂移检测和处理方案。通常,经常性变化和长期趋势被认为是系统性的,可以明确地识别和处理。
概念漂移可能出现在监督学习问题上,其中做出预测并且随时间收集数据。这些传统上称为在线学习问题,考虑到数据随时间的变化。
存在按时间排序预测的域,例如时间序列预测和流数据的预测,其中概念漂移的问题更可能并且应该明确地测试和解决。
挖掘数据流时的一个共同挑战是数据流并不总是严格固定的,即数据的概念(输入数据的基础分布)随着时间的推移不可预测地漂移。这促使需要及时检测数据流中的这些概念漂移
- 用于流数据的概念漂移检测,2015。
Indre Zliobaite 在 2010 年的论文题为“在概念漂移下的学习:概述”提供了一个框架,用于思考概念漂移和机器学习从业者所需的决策,如下:
- 未来假设:设计师需要对未来的数据源做出假设。
- 更改类型:设计人员需要识别可能的更改模式。
- 学习器适应性:基于变化类型和未来假设,设计者选择使学习器适应的机制。
- 模型选择:设计者需要一个标准来在每个时间步骤选择所选学习器的特定参数化(例如,整体成员的权重,可变窗口方法的窗口大小)。
在解决您自己的预测性建模问题的概念偏差时,此框架可能有助于思考可用的决策点。
如何解决概念漂移?
解决概念漂移的方法有很多种;我们来看看几个。
1.什么都不做(静态模型)
最常见的方法是根本不处理它并假设数据不会改变。
这使您可以开发一次“最佳”模型,并将其用于所有未来数据。
这应该是您与其他方法进行比较的起点和基线。如果您认为数据集可能会出现概念漂移,则可以通过两种方式使用静态模型:
- 概念漂移检测。监测静态模型随时间的技能,如果技能下降,可能会发生概念漂移并需要一些干预。
- 基线表现。使用静态模型的技能作为基线,与您所做的任何干预进行比较。
2.定期重新适应
良好的第一级干预是使用更新的历史数据定期更新静态模型。
例如,您可以使用从前一时期收集的数据每月或每年更新模型。
这还可以涉及对模型进行反向测试,以便在重新拟合静态模型时选择合适数量的历史数据。
在某些情况下,仅包括最近历史数据的一小部分以最佳地捕获输入和输出之间的新关系(例如,使用滑动窗口)可能是适当的。
3.定期更新
一些机器学习模型可以更新。
这是比先前方法(周期性重新拟合)的效率,其中不是完全丢弃静态模型,而是将现有状态用作适合过程的起点,该过程使用最新历史数据的样本来更新模型拟合。 。
例如,该方法适用于使用权重或系数的大多数机器学习算法,例如回归算法和神经网络。
4.重量数据
某些算法允许您权衡输入数据的重要性。
在这种情况下,您可以使用与数据年龄成反比的加权,以便更多地关注最新数据(较高权重),并且较少关注最近数据(较小权重)。
5.了解变化
可以在静态模型保持不变的情况下使用集合方法,但是新模型学习基于更新近的数据中的关系来校正来自静态模型的预测。
这可以被认为是增强型集合(仅在精神上),其中后续模型校正来自先前模型的预测。这里的关键区别在于后续模型适用于不同的和更新的数据,而不是相同数据集的加权形式,如 AdaBoost 和梯度增强的情况。
6.检测并选择模型
对于某些问题域,可以设计系统来检测变化并选择特定的和不同的模型来做出预测。
这可能适用于预期过去可能发生突然变化并且可以在将来检查的域。它还假设可以开发熟练的模型来处理每个可检测的数据更改。
例如,突然变化可以是范围内的特定观察或观察,或者一个或多个输入变量的分布的变化。
7.数据准备
在某些领域,例如时间序列问题,数据可能会随着时间的推移而发生变化。
在这些类型的问题中,通常以这样的方式准备数据,即通过差分去除随时间的数据的系统变化,例如趋势和季节性。
这很常见,它被内置到 ARIMA 模型等经典线性方法中。
通常,我们不会将数据的系统变化视为概念漂移的问题,因为它可以直接处理。相反,这些示例可能是一种思考问题的有用方法,可以帮助您使用标准化,缩放,预测等方式以特定方式预测变更和准备数据,从而减轻或至少减少变更对输入变量的影响。未来。
进一步阅读
如果您希望深入了解,本节将提供有关该主题的更多资源。
文件
- 在概念漂移和隐藏上下文的存在下学习,1996。
- 概念漂移的问题:定义和相关工作,2004。
- 流媒体数据的概念漂移检测,2015。
- 在概念漂移下学习:概述,2010。
- 概念漂移应用概述,2016。
- 什么是概念漂移和如何测量它?,2010。
- 了解概念漂移,2017 年。
用品
- 维基百科上的概念漂移
- 处理概念漂移:重要性,挑战和解决方案,2011(幻灯片)。
摘要
在这篇文章中,您发现了应用机器学习中数据变化的概念漂移问题。
具体来说,你学到了:
- 数据随时间变化的问题。
- 什么是概念漂移及其定义方式。
- 如何在您自己的预测性建模问题中处理概念偏差。
你有任何问题吗?
在下面的评论中提出您的问题,我会尽力回答。
机器学习中的偏方差权衡的温和介绍
原文:
machinelearningmastery.com/gentle-introduction-to-the-bias-variance-trade-off-in-machine-learning/
通过偏方差权衡的镜头可以最好地理解有监督的机器学习算法。
在这篇文章中,您将发现 Bias-Variance 权衡,以及如何使用它来更好地理解机器学习算法并获得更好的数据表现。
让我们开始吧。
温和地介绍机器学习中的偏方差权衡
Matt Biddulph 的照片,保留一些权利。
偏差和方差概述
在有监督的机器学习中,算法从训练数据中学习模型。
任何监督机器学习算法的目标是在给定输入数据(X)的情况下最佳地估计输出变量(Y)的映射函数(f)。映射函数通常称为目标函数,因为它是给定的监督机器学习算法旨在近似的函数。
任何机器学习算法的预测误差可分为三个部分:
- 偏差错误
- 方差错误
- 不可减少的错误
无论使用何种算法,都不能减少不可减少的误差。这是从选择的问题框架引入的错误,可能是由影响输入变量到输出变量的映射的未知变量等因素引起的。
在这篇文章中,我们将重点关注我们可以用我们的机器学习算法影响的两个部分。偏差误差和方差误差。
获取免费算法思维导图
方便的机器学习算法思维导图的样本。
我已经创建了一个由类型组织的 60 多种算法的方便思维导图。
下载,打印并使用它。
偏差错误
偏差是模型所做的简化假设,使目标函数更容易学习。
通常,参数算法具有较高的偏差,使得它们学习起来快速且易于理解,但通常不太灵活。反过来,它们对复杂问题的预测表现较低,而这些复杂问题无法满足算法偏差的简化假设。
- 低偏差:建议对目标函数形式的假设较少。
- High-Bias :建议对目标函数形式的更多假设。
低偏差机器学习算法的示例包括:决策树,k-最近邻居和支持向量机。
高偏差机器学习算法的示例包括:线性回归,线性判别分析和逻辑回归。
方差错误
方差是如果使用不同的训练数据,目标函数的估计将改变的量。
目标函数是通过机器学习算法从训练数据估计的,因此我们应该期望算法具有一些方差。理想情况下,它不应该从一个训练数据集到下一个训练数据集发生太大变化,这意味着该算法擅长选择输入和输出变量之间隐藏的底层映射。
具有高方差的机器学习算法受到训练数据的细节的强烈影响。这意味着训练的细节会影响用于表征映射函数的参数的数量和类型。
- 低方差:通过更改训练数据集,建议对目标函数估计的微小变化。
- 高方差:建议通过更改训练数据集对目标函数的估计进行大的更改。
通常,具有很大灵活性的非参数机器学习算法具有高方差。例如,决策树具有较高的方差,如果树木在使用前未被修剪,则该方差甚至更高。
低方差机器学习算法的示例包括:线性回归,线性判别分析和逻辑回归。
高方差机器学习算法的示例包括:决策树,k-最近邻居和支持向量机。
偏方差权衡
任何监督机器学习算法的目标是实现低偏差和低方差。反过来,该算法应该实现良好的预测表现。
您可以在上面的示例中看到一般趋势:
- 参数或线性机器学习算法通常具有高偏差但方差较小。
- 非参数或非线性机器学习算法通常具有低偏差但具有高方差。
机器学习算法的参数化通常是平衡偏差和方差的斗争。
以下是为特定算法配置偏方差权衡的两个示例:
- k-最近邻算法具有低偏差和高方差,但是可以通过增加 k 的值来改变折衷,这增加了有助于预测的邻居的数量,并且反过来增加了模型的偏差。
- 支持向量机算法具有低偏差和高方差,但是可以通过增加影响训练数据中允许的余量的违反次数的 C 参数来改变折衷,这增加了偏差但减小了方差。
没有逃避机器学习中的偏差和方差之间的关系。
- 增加偏差会减少差异。
- 增加方差将减少偏差。
在这两个问题和您选择的算法以及您选择配置它们的方式之间存在权衡取舍,在您的问题权衡中寻找不同的余额
实际上,我们无法计算实际偏差和方差误差项,因为我们不知道实际的基础目标函数。然而,作为一个框架,偏差和方差提供了理解机器学习算法在追求预测表现方面的行为的工具。
进一步阅读
如果您希望了解有关偏差,方差和偏方差权衡的更多信息,本节列出了一些推荐资源。
摘要
在这篇文章中,您发现了机器学习算法的偏差,方差和偏方差权衡。
你现在知道:
- 偏差是模型所做的简化假设,使目标函数更容易近似。
- 方差是在给定不同训练数据的情况下目标函数的估计将改变的量。
- 权衡是偏差和方差引入的误差之间的紧张关系。
您对偏差,方差或偏方差权衡有任何疑问吗?发表评论并提出您的问题,我会尽力回答。
机器学习中的梯度下降
原文:
machinelearningmastery.com/gradient-descent-for-machine-learning/
优化是机器学习的重要组成部分。几乎每种机器学习算法都有一个优化算法。
在这篇文章中,您将发现一个简单的优化算法,您可以将其与任何机器学习算法一起使用。它易于理解且易于实现。阅读这篇文章后你会知道:
- 什么是梯度下降?
- 如何在线性回归等算法中使用梯度下降?
- 梯度下降如何扩展到非常大的数据集?
- 从梯度下降中获得最大收益的一些技巧是什么?
让我们开始吧。
机器学习的梯度下降
照片由大峡谷国家公园,保留一些权利。
梯度下降
梯度下降是用于找到函数(f)的参数(系数)的值的优化算法,其最小化成本函数(成本)。
当无法通过分析计算参数(例如,使用线性代数)时,最好使用梯度下降,并且必须通过优化算法进行搜索。
梯度下降的直觉
想象一个大碗,就像你吃谷物或储存水果一样。这个碗是成本函数(f)的图。
大碗
摄影: William Warby ,保留一些权利。
碗表面上的随机位置是系数(成本)的当前值的成本。
碗的底部是最佳系数集的成本,即函数的最小值。
目标是继续尝试不同的系数值,评估其成本并选择具有稍好(较低)成本的新系数。
重复此过程足够的时间将导致碗的底部,您将知道导致最低成本的系数值。
获取免费算法思维导图
方便的机器学习算法思维导图的样本。
我已经创建了一个由类型组织的 60 多种算法的方便思维导图。
下载,打印并使用它。
梯度下降程序
该过程从系数的初始值或函数的系数开始。这些可以是 0.0 或小的随机值。
系数= 0.0
通过将系数插入函数并计算成本来评估系数的成本。
成本= f(系数)
要么
成本=评估(f(系数))
计算成本的导数。导数是来自微积分的概念,指的是给定点处函数的斜率。我们需要知道斜率,以便我们知道移动系数值的方向(符号),以便在下一次迭代中获得更低的成本。
delta =衍生物(成本)
现在我们从导数中知道哪个方向是下坡,我们现在可以更新系数值。必须指定学习率参数(alpha),以控制系数在每次更新时可以更改的程度。
系数=系数 - (alpha * delta)
重复该过程,直到系数(成本)的成本为 0.0 或足够接近零以使其足够好。
你可以看到梯度下降是多么简单。它确实需要您了解成本函数的梯度或您正在优化的函数,但除此之外,它非常简单。接下来我们将看到如何在机器学习算法中使用它。
机器学习的批量梯度下降
所有监督机器学习算法的目标是最佳地估计将输入数据(X)映射到输出变量(Y)的目标函数(f)。这描述了所有分类和回归问题。
一些机器学习算法具有表征目标函数(f)的算法估计的系数。不同的算法具有不同的表示和不同的系数,但是其中许多算法需要优化过程以找到导致目标函数的最佳估计的系数集。
具有可以使用梯度下降优化的系数的算法的常见示例是线性回归和逻辑回归。
可以通过多种不同的方式来计算机器学习模型拟合估计目标函数的接近程度的评估,这些方式通常特定于机器学习算法。成本函数涉及通过计算数据集中每个训练实例的模型预测并将预测与实际输出值进行比较并计算总和或平均误差(例如平方残差之和)来评估机器学习模型中的系数。或线性回归情况下的 SSR)。
根据成本函数,可以为每个系数计算导数,以便可以使用上述更新方程更新它。
对于梯度下降算法的每次迭代,针对整个训练数据集的机器学习算法计算成本。算法的一次迭代称为一批,这种梯度下降形式称为批量梯度下降。
批量梯度下降是机器学习中描述的最常见的梯度下降形式。
机器学习的随机梯度下降
在非常大的数据集上运行时,梯度下降可能会很慢。
因为梯度下降算法的一次迭代需要对训练数据集中的每个实例做出预测,所以当您有数百万个实例时可能需要很长时间。
在有大量数据的情况下,您可以使用称为随机梯度下降的梯度下降变化。
在该变型中,运行上述梯度下降过程,但是对于每个训练实例而不是在该批实例的末尾执行对系数的更新。
该过程的第一步要求训练数据集的顺序是随机的。这是为了混淆对系数进行更新的顺序。因为系数在每个训练实例之后被更新,所以更新将在整个地方嘈杂地跳跃,并且相应的成本函数也是如此。通过混合更新系数的顺序,它利用这种随机游走并避免它分心或卡住。
系数的更新过程与上述相同,除了成本不是对所有训练模式求和,而是针对一个训练模式计算。
对于非常大的训练数据集,随机梯度下降可以更快地学习,并且通常只需要通过数据集的少量传递来达到良好或足够好的系数集,例如, 1 到 10 次通过数据集。
梯度下降的提示
本节列出了一些提示和技巧,可以充分利用梯度下降算法进行机器学习。
- 绘图成本与时间:收集并绘制每次迭代算法计算的成本值。对表现良好的梯度下降运行的期望是每次迭代的成本降低。如果没有减少,请尝试降低学习率。
- 学习率:学习率值是一个小的实际值,如 0.1,0.001 或 0.0001。为您的问题尝试不同的值,看看哪个效果最好。
- 重新定标输入:如果成本函数的形状没有偏斜和扭曲,算法将更快地达到最低成本。您可以通过将所有输入变量(X)重缩放到相同的范围来实现此目的,例如[0,1]或[-1,1]。
- 几次通过:随机梯度下降通常不需要超过 1 到 10 次通过训练数据集就可以收敛到足够好或足够好的系数。
- Plot Mean Cost :当使用随机梯度下降时,每个训练数据集实例的更新可能导致成本随时间的噪声图。平均超过 10,100 或 1000 次更新可以让您更好地了解算法的学习趋势。
摘要
在这篇文章中,您发现了机器学习的梯度下降。你了解到:
- 优化是机器学习的重要组成部分。
- 梯度下降是一个简单的优化过程,可以与许多机器学习算法一起使用。
- 批量梯度下降是指在计算更新之前计算来自所有训练数据的导数。
- 随机梯度下降是指计算每个训练数据实例的导数并立即计算更新。
您对机器学习或此帖的梯度下降有任何疑问吗?发表评论并提出您的问题,我会尽力回答。
机器学习算法如何工作(他们学习输入到输出的映射)
原文:
machinelearningmastery.com/how-machine-learning-algorithms-work/
机器学习算法如何工作?
有一个共同的原则是所有监督机器学习算法的基础,用于预测性建模。
在这篇文章中,您将通过理解作为所有算法基础的共同原则来发现机器学习算法如何实际工作。
机器学习算法如何工作
照片来自 GotCredit ,保留一些权利。
让我们开始吧。
学习功能
机器学习算法被描述为学习目标函数(f),其最佳地将输入变量(X)映射到输出变量(Y)。
Y = f(X)
这是一个通用的学习任务,我们希望在未来(Y)中给出预测输入变量(X)的新例子。
我们不知道函数(f)的外观或形式。如果我们这样做,我们将直接使用它,我们不需要使用机器学习算法从数据中学习它。
这比你想象的要难。还存在与输入数据(X)无关的错误(e)。
Y = f(X)+ e
此错误可能是错误,例如没有足够的属性来充分表征从 X 到 Y 的最佳映射。此错误称为不可减少的错误,因为无论我们在估计目标函数(f)方面有多好,我们都无法减少此错误。
这就是说,从数据中学习函数的问题是一个难题,这就是机器学习和机器学习算法领域存在的原因。
获取免费算法思维导图
方便的机器学习算法思维导图的样本。
我已经创建了一个由类型组织的 60 多种算法的方便思维导图。
下载,打印并使用它。
学习一种功能来做出预测
最常见的机器学习类型是学习映射 Y = f(X)来预测新 X 的 Y.
这称为预测性建模或预测分析,我们的目标是使最准确的预测成为可能。
因此,我们并不真正感兴趣的是我们正在学习的函数(f)的形状和形式,只是它能够做出准确的预测。
我们可以学习 Y = f(X)的映射,以更多地了解数据中的关系,这称为统计推断。如果这是目标,我们将使用更简单的方法和价值理解上面(f)的学习模型和形式进行准确的预测。
当我们学习函数(f)时,我们从我们可用的数据中估计它的形式。因此,此估计将有错误。它不是对给定 X 的 Y 的基本假设最佳映射的完美估计。
在应用机器学习中花费大量时间来尝试改进基础功能的估计并且在术语上改进模型所做出的预测的表现。
学习函数的技巧
机器学习算法是用于估计目标函数(f)以在给定输入变量(X)的情况下预测输出变量(Y)的技术。
不同的表示对所学习的函数的形式做出不同的假设,例如它是线性的还是非线性的。
不同的机器学习算法对函数的形状和结构做出不同的假设,以及如何最好地优化表示以近似它。
这就是为什么在机器学习问题上尝试一套不同的算法非常重要的原因,因为我们无法事先知道哪种方法最适合估计我们试图近似的基础函数的结构。
摘要
在这篇文章中,您发现了解释所有机器学习算法用于预测性建模的目标的基本原理。
您了解到机器学习算法可以在给定输入变量(X)或 Y = f(X)的情况下估算输出变量(Y)的映射函数(f)。
您还了解到,不同的机器学习算法对基础函数的形式做出了不同的假设。当我们对目标函数的形式知之甚少时,我们必须尝试一套不同的算法来看看哪种方法效果最好。
您对机器学习算法或此帖子有何疑问?发表评论并提出您的问题,我会尽力回答。
如何建立机器学习算法的直觉
原文:
machinelearningmastery.com/how-to-build-an-intuition-for-machine-learning-algorithms/
机器学习算法很复杂。要善于应用给定的算法,您需要从多个角度进行研究:算法,数学和经验。
这是我想要强调的最后一点。您需要建立直觉或算法在实际数据上的行为方式。你需要解决很多问题。
在这篇文章中,我想鼓励你在开始和练习机器学习时使用小型内存数据集。
围绕数据
照片由 Nic McPhee 拍照,保留一些权利
研究算法或问题,而不是两者
您无法同时学习问题和算法。
如果你尝试,你将慢慢地和低效地进步。您的重点将被划分,并且理想地执行下面的任务。
当你进入这条赛道时,你会知道,因为你会在深入研究问题和深入到特定算法之间振荡。你会感到沮丧和不堪重负。你承担的太多了。
获取免费算法思维导图
方便的机器学习算法思维导图的样本。
我已经创建了一个由类型组织的 60 多种算法的方便思维导图。
下载,打印并使用它。
分裂你的疑虑
最好的做法是分别研究算法和问题。
您可以通过使用算法来了解问题,并以模型的形式提出候选解决方案。这意味着您将尝试许多模型(点检查)和可能的许多算法配置(调整)。
您通过关注一个问题数据集并使用它来了解算法参数的相互作用及其对模型的影响(例如最终结果或一段时间内的行为)来研究算法。
这是第二类项目,您可以使用经验实验来建立机器学习算法如何工作的直觉。您可以将这种直觉与其工作原理的理论结合起来,并旨在围绕使用哪种算法以及何时针对特定问题做出明智的决策。
扮演科学家
您希望将算法的行为表征为受控问题的系统。
该研究的重点是一个问题,例如:
该算法的信息处理策略是什么?
当给定参数变化时,系统如何表现?
在开始之前,清楚地定义您打算在研究中回答的具体问题。明确答案将采取何种形式。
实际结果
学习算法具有一些特定的实际好处,可以提高您的机器学习技能,例如:
- 算法调整:您正在学习算法如何表现为复杂系统以及算法参数对这些行为的影响。这些是在特定问题实例上调优算法所需的宝贵见解和直觉。
- 问题 - 算法拟合:您正在学习在问题类和问题实例上表现良好的算法类和特定算法实例。这是一种只能通过经验建立起来的直觉。
- 项目生命周期:您正在练习应用机器学习的过程,包括数据准备,算法测试和调整以及结果的呈现。
他们的关键是拥有标准的易于理解的数据集,您可以使用它们来更好地理解所研究的算法。
使用标准数据集
您可以使用一个或少量模型数据集来研究机器学习算法。
有时它们被称为玩具数据集或玩具问题,因为它们的大小。然而,当您学习和实践机器学习算法时,它们发挥着重要作用。
不同的数据集具有不同的已知属性。通常希望选择一小组那些属性来暴露正在研究的算法的不同行为。
例如,某些属性可能包括
- 功能数量
- 类分布
- 数据类型
- 结构关系
模型数据集的 5 个好处
以下是使用标准机器学习数据集的 5 个好处。
- 小:数据集可以放入内存中。这意味着您可以快速运行大量实验,然后快速了解算法。
- 理解:通常理解数据集。它背后可能有重要的文献,或者是算法的常见测试和研究点。它具有用于测试算法能力的已知属性。
- 受控:模型数据集常量,为对照试验提供基础。可以改变算法的行为以查看对结果的影响与良好理解的问题。
- Free :可以下载模型数据集。您无需获得许可或支付许可费。您可以随时使用常用数据集。
- 简单:数据中的结构或关系并不复杂。可以很容易地理解它们,并使用摘要统计和图表进行描述。通常很少有变量。
UCI 机器学习库
有些工具附带了样本数据集,但您可以信赖的一个很好的来源是加州大学欧文机器学习库。
它是一个网站,托管学术界使用的数百个标准机器学习数据集,用于测试,演示和实证表征机器学习算法的行为。
您可以浏览此站点上的数据集,查看数据,并查看已参考数据集的论文和文章。
这是一种宝贵的资源,您可以使用它来查找数据集以研究机器学习算法。
5 个经典模型数据集
下面是我熟悉新算法或我忘记的旧算法时要使用的 5 类数据集的列表。
- 鸢尾花:根据花的尺寸描述鸢尾花,分为三个种类。
- 电离层:描述了表征电离层能量状态的雷达返回数据。所有属性都是数字,类是二进制。
- 皮马印第安人糖尿病:皮马印第安人的各种医疗记录数据,其二元类别是患者在收集医疗数据后 5 年内是否患有糖尿病。
- 玻璃鉴定:根据样品的化学成分鉴定类,多个不平衡类别。
- 威斯康星乳腺癌:乳腺癌患者的医疗活检信息和样本是否癌变的二元类变量。
您可能会发现这些数据集中的一个或多个在您自己的实验中很有用。
摘要
在这篇文章中,您发现了在尝试同时了解问题数据集和算法时遇到的困难。事实上,他们是相互竞争的担忧。
您发现答案是将这些问题分开,以了解您的问题并了解算法,并明确您的目标是什么。
您在了解算法时可以发现小型模型数据集的好处,在哪里可以获得标准的机器学习数据集以及一些您可以开始使用的流行示例。
如果您想了解更多有关如何学习机器学习算法的信息,请查看我的算法描述模板以学习任何算法,小项目方法指导自学项目,包括学习算法。
如何在机器学习中处理大p
小n
(p >> n
)
原文:https://machinelearningmastery.com/how-to-handle-big-p-little-n-p-n-in-machine-learning/
最后更新于 2020 年 8 月 19 日
如果我的数据集中的列比行多怎么办?
机器学习数据集通常是由行和列组成的结构化或表格数据。
作为模型输入的列称为预测器或“ p ”,行是样本“ n ”。大多数机器学习算法假设样本比预测值多得多,表示为 p < < n。
有时情况并非如此,数据集中的预测因子比样本多得多,称为“大 p,小 n ,记为p>T5【n】T3。这些问题通常需要专门的数据准备和建模算法来正确解决。
在本教程中,您将发现大 p、小 n 或 p >> n 机器学习问题的挑战。
完成本教程后,您将知道:
- 大多数机器学习问题比预测器有更多的样本,并且大多数机器学习算法在训练过程中做出这种假设。
- 有些建模问题的预测因子比样本多得多,称为 p >> n。
- 建模预测因子多于样本的机器学习数据集时要探索的算法。
用我的新书掌握机器学习算法启动你的项目,包括分步教程和所有示例的 Excel 电子表格文件。
我们开始吧。
如何处理机器学习中的大 p,小 n(p > > n)Phil Dolby 摄,保留部分权利。
教程概述
本教程分为三个部分;它们是:
- 预测值§和样本(n)
- 机器学习假设 p << n
- 如何处理 p >> n
预测值§和样本(n)
考虑一个预测建模问题,例如分类或回归。
数据集是结构化数据或表格数据,就像您可能在 Excel 电子表格中看到的那样。
有列和行。大多数列将用作模型的输入,一列将代表要预测的输出或变量。
输入有不同的名称,如预测因子、独立变量、特征,或者有时只是变量。输出变量——在本例中为销售额——通常被称为响应或因变量,通常用符号 y 表示
—第 15 页,R中应用的统计学习介绍,2017。
每列代表一个变量或样本的一个方面。表示模型输入的列称为预测器。
每一行代表一个样本,其值跨越每一列或特征。
- 预测器:数据集的输入列,也称为输入变量或特征。
- 样本:数据集的行,也称为观察、示例或实例。
在机器学习中,通常用预测器和样本来描述训练数据集。
使用术语“ p 描述数据集中预测因子的数量,使用术语“ n 或有时使用“ N 描述数据集中样本的数量”。
- p :数据集中预测因子的个数。
- n :数据集中的样本数。
具体来说,我们来看看鸢尾花分类的问题。
下面是该数据集前五行的示例。
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa
5.0,3.6,1.4,0.2,Iris-setosa
...
该数据集有五列 150 行。
前四列是输入,第五列是输出,这意味着有四个预测器。
我们将鸢尾花数据集描述为:
- p=4,n=150。
机器学习假设 p << n
几乎总是预测器的数量( p )会小于样本的数量( n )。
通常要小得多。
我们可以把这个期望概括为 p << n, where “<数学不等式,意思是“比少很多。”
- p < < n :通常我们的预测因子比样本少。
为了演示这一点,让我们看几个更标准的机器学习数据集:
大多数机器学习算法基于样本比预测值多得多的假设进行操作。
考虑预测因子和样本的一种方法是采取几何透视法。
考虑一个超立方体,其中预测数( p )定义了超立方体的维数。这个超立方体的体积是可以从域中提取的可能样本的范围。样本数量( n )是从域中抽取的实际样本,您必须使用这些样本来建模您的预测建模问题。
这是应用机器学习中公理“获取尽可能多的数据”的基本原理。这是一个收集足够有代表性的 T2 问题领域样本的愿望。
随着维数( p )的增加,域的体积呈指数级增加。这又需要来自域的更多样本( n )来为学习算法提供域的有效覆盖。我们不需要领域的全面覆盖,只需要可能观察到的东西。
这种对高维空间进行有效采样的挑战通常被称为维度诅咒。
机器学习算法通过假设从输入到输出的映射函数的数据和结构来克服维数灾难。他们增加了偏见。
维数灾难的根本原因是高维函数可能比低维函数复杂得多,而且这些复杂性更难辨别。打破诅咒的唯一方法是整合关于正确数据的知识。
—第 15 页,图案分类,2000 年。
随着预测器数量的增加,许多使用距离度量和其他局部模型(在特征空间中)的机器学习算法的表现通常会下降。
当特征 p 的数量较大时,KNN 和其他仅使用必须进行预测的测试观测值附近的观测值进行预测的局部方法的表现趋于恶化。这种现象被称为维数灾难,它与非参数方法在 p 较大时通常表现不佳的事实有关。
—第 168 页,R中应用的统计学习介绍,2017。
预测器的数量并不总是少于样本的数量。
如何处理 p >> n
根据定义,一些预测建模问题具有比样本更多的预测因子。
预测因子往往比样本多得多。
这经常被描述为“大-p,小-n ”、“大-p,小-n ”,或者更紧凑地描述为“p > > n”,其中“> >”是一个数学不等式运算符,意思是“比多得多。”
…特征数 p 远大于观测数 N 的预测问题,通常写成 p >> N
—第 649 页,统计学习的要素:数据挖掘、推理和预测,2016。
从几何角度考虑这个问题。
现在,领域不再有几十个维度(或更少),而是有几千个维度,只有几十个样本来自这个空间。我们不能期望有任何领域的代表性样本。
p >> n 问题的很多例子来自医学领域,那里的患者人群少,描述性特征多。
与此同时,出现了一些应用,其中实验单元的数量相对较少,但底层维度却很庞大;说明性的例子可能包括图像分析、微阵列分析、文件分类、天文学和大气科学。
——高维数据的统计挑战,2009。
p >> n 问题的一个常见例子是基因表达阵列,其中可能有数千个基因(预测因子),只有几十个样本。
基因表达阵列通常有 50 到 100 个样本和 5000 到 20000 个变量(基因)。
——表达式数组与 p > > n 问题,2003。
鉴于大多数机器学习算法假设的样本比预测值多得多,这在建模时带来了挑战。
具体来说,标准机器学习模型所做的假设可能会导致模型出现意外行为、提供误导性结果或完全失败。
……模型不能“开箱即用”使用,因为标准拟合算法都要求 p < n;事实上,通常的经验法则是样本数量是变量的五到十倍。
——表达式数组与 p > > n 问题,2003。
当使用机器学习模型时,p >> n 问题的一个主要问题是过度拟合训练数据集。
由于缺少样本,大多数模型无法进行归纳,而是学习训练数据中的统计噪声。这使得模型在训练数据集上表现良好,但在问题域的新示例上表现不佳。
这也是一个很难诊断的问题,因为缺少样本不允许使用测试或验证数据集来评估模型过拟合。因此,在 p >> n 问题上评估模型时,通常使用省略式交叉验证(LOOCV)。
有许多方法可以处理 p >> n 型分类或回归问题。
一些例子包括:
忽略 p 和 n
一种方法是忽略 p 和 n 的关系,评估标准的机器学习模型。
这可以被认为是比较任何其他更专门的干预措施的基线方法。
特征选择
特征选择包括选择预测器的子集,用作预测模型的输入。
常见的技术包括基于特征与目标变量的统计关系(例如相关性)选择特征的过滤方法,以及在预测目标变量时基于特征对模型的贡献选择特征的包装方法(例如 RFE)。
可以对一套特征选择方法进行评估和比较,也许可以采用积极的方式将输入特征的数量大幅减少到那些被确定为最关键的特征。
当 p 较大时,特征选择是分类器的重要科学要求。
—第 658 页,统计学习的要素:数据挖掘、推理和预测,2016。
有关特征选择的更多信息,请参见教程:
投影方法
投影方法创建了样本的低维表示,保留了数据中观察到的关系。
它们通常用于可视化,尽管这些技术的降维特性也可能使它们作为减少预测器数量的数据转换非常有用。
当 p > N 时,通过奇异值分解,计算可以在 N 维空间而不是 p 维空间进行
—第 659 页,统计学习的要素:数据挖掘、推理和预测,2016。
它还可能包括经常用于可视化的多种学习算法,如 t-SNE。
正则化算法
标准机器学习算法可以适于在训练过程中使用正则化。
这将根据所用特征的数量或特征的权重来惩罚模型,鼓励模型表现良好,并最小化模型中使用的预测器的数量。
这可以在训练期间充当一种自动特征选择,并且可以涉及扩充现有模型(例如,正则化线性回归和正则化逻辑回归)或者使用诸如 LARS 和 LASSO 的专门方法。
没有最好的方法,建议使用对照实验来测试一套不同的方法。
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
报纸
- 表达式数组与 p > > n 问题,2003。
- 高维数据的统计挑战,2009。
书
- 图案分类,2000。
- 第十八章,高维问题:p >> N,统计学习的要素:数据挖掘、推理和预测,2016。
- R中应用的统计学习导论,2017。
文章
- 不等式(数学),维基百科。
- 维度的诅咒,维基百科。
- 大 p,小 n ,2016 年。
摘要
在本教程中,您发现了大 p、小 n 或 p >> n 机器学习问题的挑战。
具体来说,您了解到:
- 机器学习数据集可以用预测数§和样本数(n)来描述。
- 大多数机器学习问题比预测器有更多的样本,并且大多数机器学习算法在训练过程中做出这种假设。
- 有些建模问题的预测因子比样本多得多,比如医学上的问题,称为 p >> n,可能需要使用专门的算法。
你有什么问题吗?
在下面的评论中提问,我会尽力回答。
如何实现机器学习算法
原文:
machinelearningmastery.com/how-to-implement-a-machine-learning-algorithm/
在代码中实现机器学习算法可以教会您很多关于算法及其工作原理的知识。
在这篇文章中,您将学习如何有效地实现机器学习算法以及如何最大限度地从这些项目中学习。
摄影:Maura McDonnell,保留一些权利。
实现机器学习算法的好处
您可以使用机器学习算法的实现作为学习应用机器学习的策略。您还可以在算法实现中开辟一个利基和技能。
算法理解
实现机器学习算法将使您对算法的工作方式有深刻而实用的认识。这些知识还可以帮助您通过将向量和矩阵视为数组以及对这些结构进行转换的计算直觉来内化算法的数学描述。
在实现机器学习算法时需要做出许多微决策,并且这些决策通常在正式算法描述中缺失。学习和参数化这些决策可以迅速使您获得对给定方法的中级和高级理解,因为相对较少的人会花时间实现一些更复杂的算法作为学习练习。
获取免费算法思维导图
方便的机器学习算法思维导图的样本。
我已经创建了一个由类型组织的 60 多种算法的方便思维导图。
下载,打印并使用它。
实用技能
当您手动实现机器学习算法时,您正在开发有价值的技能。诸如掌握算法的技能,可以帮助开发生产系统的技能和可用于该领域的经典研究的技能。
列出的三个技能示例包括:
- 掌握:算法的实现是掌握算法的第一步。实现时,您必须非常了解算法。您还可以创建自己的实验室进行修补,以帮助您内化其执行的计算,例如通过调试和添加评估运行过程的措施。
- 生产系统:生产系统通常需要自定义算法实现,因为出于效率和效率的原因需要对算法进行更改。更好,更快,更少资源的结果最终可以降低成本并增加业务收入,手动实现算法可帮助您训练提供这些解决方案的技能。
- 文献综述:在实现算法时,您正在进行研究。您被迫查找并阅读该算法的多个规范和正式描述。您还可能找到并编写代码审查算法的其他实现,以确认您的理解。您正在进行有针对性的研究,并学习如何阅读和实际使用研究出版物。
处理
您可以通过一个过程来加速您从零开始学习和实现机器学习算法的能力。您实现的算法越多,您获得的算法就越快,效率越高,您开发和定制自己的流程的次数就越多。
实现机器学习算法
照片由 Nic 的事件,保留一些权利
您可以使用下面概述的流程。
- 选择编程语言:选择要用于实现的编程语言。此决定可能会影响您可以在实现中使用的 API 和标准库。
- 选择算法:选择要从零开始实现的算法。要尽可能具体。这不仅意味着算法的类和类型,还包括选择要实现的特定描述或实现。
- **选择问题:**选择可用于测试和验证算法实现的规范问题或一组问题。机器学习算法不是孤立存在的。
- 研究算法:找到论文,书籍,网站,库以及您可以阅读和学习的算法的任何其他描述。虽然,理想情况下,您希望对算法的一个关键字描述起作用,但您需要对算法有多个透视图。这很有用,因为多个视角将帮助您更快地内化算法描述,并克服描述中出现的任何歧义或假设的障碍(算法描述中总是存在歧义)。
- 单元测试:为每个函数编写单元测试,甚至从项目开始就考虑测试驱动开发,这样在实现它们之前,您不得不了解每个代码单元的目的和期望。
我强烈建议将算法从一种语言移植到另一种语言,以此作为沿着这条路径快速前进的一种方式。您可以找到许多算法的开源实现,您可以使用其他语言对其进行代码审查,绘图,内化和重新实现。
在开发代码时以及开发代码之后,请考虑开源代码。对它进行评论并确保它提供有关如何构建和使用它的说明。该项目将为您正在开发的技能提供营销,并可能为希望在机器学习中开始的其他人提供灵感和帮助。您甚至可能很幸运地找到了一位对您进行审核或代码审查感兴趣的程序员。你得到的任何反馈都是非常宝贵的(即使是动机),积极寻求它。
扩展
实现算法后,您可以探索对实现进行改进。您可以探索的一些改进示例包括:
- 实验:您可以将您在算法实现中做出的许多微观决策暴露为参数,并对这些参数的变化进行研究。这可以为您提供可以共享和推广的算法实现的新见解和消歧。
- 优化:您可以通过使用工具,库,不同语言,不同数据结构,模式和内部算法来探索提高实现效率的机会。您对经典计算机科学的算法和数据结构的了解对此类工作非常有益。
- 专业化:您可以探索使算法更具体针对问题的方法。创建生产系统时可能需要这样做,这是一项宝贵的技能。使算法更具体问题还可以导致效率(例如运行时间)和功效(例如准确度或其他表现测量)的增加。
- 泛化:可以通过使特定算法更通用来创建机会。程序员(如数学家)在抽象方面具有独特的技能,您可以看到该算法如何完全应用于一类问题或其他问题的更一般情况。
限制
您可以通过手动实现机器学习算法来学习很多东西,但也要记住一些缺点。
- 冗余:许多算法已经实现了,一些非常强大的实现已被全球数百或数千名研究人员和从业者使用。您的实现可能被视为多余的,社区已投入的重复工作。
- Bugs :即使是熟练的程序员和单元测试,用户很少的新代码也更容易出错。使用标准库可以降低算法实现中出现错误的可能性。
- 非直观的飞跃:由于涉及复杂的数学,一些算法依赖于推理或逻辑中的非直观跳跃。不理解这些跳跃的实现是有限的,甚至是不正确的。
很容易评论机器学习算法的开源实现,并在代码审查中引发许多问题。要理解在实现中编码的非直观效率要困难得多。这可能是思考的陷阱。
您可能会发现,在考虑如何将其更改为在程序上不那么优雅但计算效率更高的情况下,从复杂算法的较慢直观实现开始是有益的。
示例项目
有些算法比其他算法更容易理解。在这篇文章中,我想为直观算法提出一些建议,您可以从中选择第一个从零开始实现的机器学习算法。
- 普通最小二乘线性回归:使用二维数据集和 y 中的模型 x。为算法的每次迭代打印出错误。考虑为算法的每次迭代绘制最佳拟合线和预测线,以查看更新如何影响模型。
- k-最近邻:考虑使用具有 2 个类的二维数据集,甚至是使用方格纸创建的两个类,以便您可以绘制它们。一旦您可以绘制并做出预测,您就可以绘制为模型所做的每个预测决策创建的关系。
- Perceptron :被认为是最简单的人工神经网络模型,与回归模型非常相似。您可以在学习数据集时跟踪和绘制模型的表现。
摘要
在这篇文章中,您了解了手动实现机器学习算法的好处。您了解到,通过遵循此路径,您可以了解算法,进行改进并训练宝贵的技能。
您学习了一个简单的过程,您可以在从零开始实现多个算法时遵循和自定义,并且您学习了三种算法,您可以选择这些算法作为从零开始实现的第一个算法。
如何研究机器学习算法行为
原文:
machinelearningmastery.com/how-to-investigate-machine-learning-algorithm-behavior/
机器学习算法是需要学习才能理解的复杂系统。
机器学习算法的静态描述是一个很好的起点,但不足以了解算法的行为方式。您需要查看算法的实际效果。
通过对运行中的机器学习算法进行试验,您可以根据可以在不同类别的问题上实现的结果,建立对算法参数的因果关系的直觉。
在这篇文章中,您将了解如何研究机器学习算法。您将学习一个简单的 5 步过程,您可以使用它来设计和完成您的第一个机器学习算法实验。
您会发现,机器学习实验不仅适用于学术,也可以实现,并且在掌握的过程中需要进行实验,因为您将获得的经验因果知识在其他任何地方都无法获得。
调查机器学习算法行为
照片由美国陆军 RDECOM ,保留一些权利
什么是调查机器学习算法
在研究机器学习算法时,您的目标是找到能够在问题和问题类别中推广的良好结果的行为。
您通过对算法行为进行系统研究来研究机器学习算法。这是通过设计和执行对照试验来完成的。
完成实验后,您可以解释并显示结果。结果可让您了解算法更改之间的因果关系,行为以及您可以实现的结果。
获取免费算法思维导图
方便的机器学习算法思维导图的样本。
我已经创建了一个由类型组织的 60 多种算法的方便思维导图。
下载,打印并使用它。
如何研究机器学习算法
在本节中,我们将介绍一个简单的 5 步过程,您可以使用它来研究机器学习算法。
1.选择算法
选择您有疑问的算法。
这可能是您在问题上使用的算法,或者您认为在将来可能要使用的其他上下文中表现良好的算法。
出于实验目的,采用现成的算法实现是有用的。这为您提供了一个基线,如果有任何错误,很可能很少。
自己实现算法可以是了解算法程序的好方法,但也可以在实验中引入其他变量,如错误和必须的无数微决策为每个算法实现。
2.确定一个问题
您必须有一个您正在寻求回答的研究问题。问题越具体,答案就越有用。
一些示例问题包括:
- 将 kNN 中的 k 增加为训练数据集大小的一部分有什么影响?
- 在 SVM 中选择不同内核对二分类问题的影响是什么?
- 不同属性缩放对二分类问题的逻辑回归有什么影响?
- 在随机森林中将随机属性添加到训练数据集对分类准确率的影响是什么?
设计您想要回答的有关算法的问题。考虑列出问题的五个变体并深入研究最具体的问题。
3.设计实验
选择将构成实验的问题中的元素。
例如,从上面提出以下问题:“_ 不同属性缩放对二分类问题的逻辑回归有什么影响?_ “
您可以从实验设计中选择的元素包括:
- 属性缩放方法。您可以包括规范化,标准化,将属性提升为幂,取对数等方法。
- 逻辑回归。您要使用哪种逻辑回归实现。
- 二分类问题。具有数字属性的不同标准二分类问题。将需要多个问题,一些具有相同比例的属性(如电离层)和其他具有各种尺度属性的问题(如糖尿病)。
- 表现。需要模型表现分数,例如分类准确率。
花点时间仔细选择问题的元素,以便最好地回答您的问题。
4.执行实验和报告结果
完成你的实验。
如果算法是随机的,您可能需要多次重复实验运行并采用均值和标准差。
如果您正在寻找实验运行(例如不同参数)之间的结果差异,您可能需要使用统计工具来指示差异是否具有统计显着性(例如 T 检验)。
像 R 和 scikit-learn / SciPy 这样的工具有完成这些类型实验的工具,但您需要将它们组合在一起并编写实验脚本。其他工具如 Weka 将工具内置到图形用户界面中(请参阅此教程,了解如何在 Weka 中运行您的第一个实验)。您使用的工具比实验设计的问题和严谨性更重要。
总结您的实验结果。您可能想要使用表格和图形。单独呈现结果是不够的。他们只是数字。您必须将数字与问题联系起来,并通过实验设计过滤其含义。
结果表明您的研究问题是什么?
戴上你持怀疑态度的帽子。您可以对结果有什么漏洞或限制。不要回避这一部分。了解这些局限性与了解实验结果同样重要。
5.重复
重复这个过程。
继续调查您选择的算法。您甚至可能希望使用不同的参数或不同的测试数据集重复相同的实验。您可能希望解决实验中的限制。
不要停止一个实验,开始建立知识库和算法的直觉。
通过一些简单的工具,一些好的问题以及严谨和怀疑的良好表现,您可以非常快速地开始对算法的行为提出世界级的理解。
调查算法不仅适用于学者
您可以研究机器学习算法的行为。
你不需要更高的学位,你不需要接受研究方法的训练,你不需要成为一名学者。
机器学习算法的仔细系统调查对任何拥有计算机和兴趣的人都是开放的。事实上,如果你想掌握机器学习,你必须熟悉机器学习算法的系统研究。知识根本就不在那里,你必须自己出去并凭经验收集它。
在谈论您的发现的适用性时,您需要持怀疑态度并要小心。
您不需要有任何独特的问题。通过调查标准问题,您将获得很多收益,例如在一些标准数据集中推广的一个参数的影响。您可能会发现常见的最佳实践启发式的局限性或对立点。
行动步骤
在这篇文章中,您发现了通过对照试验研究机器学习算法行为的重要性。您发现了一个简单的 5 步过程,您可以使用它设计并在机器学习算法上执行第一个实验。
采取行动。使用您在本博文中学到的过程,完成第一次机器学习实验。一旦你完成了一个,即使是非常小的一个,你将拥有完成第二个甚至更多的信心,工具和能力。
我很想知道你的第一个实验。发表评论并分享您的结果或您学到的知识。
如何学习机器学习算法
原文:
machinelearningmastery.com/how-to-learn-a-machine-learning-algorithm/
在电子邮件列表中出现了几次如何学习机器学习算法的问题。
在这篇文章中,我将与您分享我多年来一直使用的策略,以逐步的方式学习和构建算法的结构化描述,我可以添加,改进并一次又一次地参考。我甚至用它来写一本书。
这只是我个人使用的策略,我对这些积极反馈感到非常惊讶。
算法描述已损坏
学习机器学习算法可能是压倒性的。有太多的论文,书籍和网站描述了算法在数学和文本方面的工作原理。如果你真的很幸运,你可能会找到算法的伪代码描述。
实现机器学习算法
照 Nic 的事件,保留一些权利
如果你真的很幸运,你可能会找到一些建议的方法来为不同的情况配置方法。这些描述很少见,通常深埋在原始出版物或原作者的技术说明中。
当您想要从研究论文中实现一种方法时,您很快就会学到的一个事实是,几乎从未详细描述算法以便您重现它们。原因各不相同,从论文中遗漏的微观决策到文本中含糊不清的总体程序,以及使用不一致的符号。
获取免费算法思维导图
方便的机器学习算法思维导图的样本。
我已经创建了一个由类型组织的 60 多种算法的方便思维导图。
下载,打印并使用它。
把它拼凑在一起
要理解一个算法,你必须从不同的描述中自己理解。这是我发现成功的唯一策略。
不同的描述意味着资源,例如主要来源中方法的原始描述以及在评论文章和书籍中对原始描述进行的权威性二级解释。
通常使用主要源发布的方法的原型实现并且读取此代码(通常是 C,FORTRAN,R 或 Matlab)对于重现算法所需的细节非常有启发性。
算法描述
算法是一个研究的岛屿,在所有现实中,很难确定规范的定义。例如,它是主要源中描述的版本,还是包含“最佳实践”的所有修复和增强的版本。
一种解决方案是从多个角度考虑给定的算法,每个角度都可以用于不同的目的。例如,算法的抽象信息处理描述可以通过各种不同的特定计算实现来实现。
我喜欢这种方法,因为它保证了在描述的每个步骤中从许多可能的情况下对算法的特定情况进行望远镜的需要,同时还保留了对变化描述的选项。
根据您的需要,您可以根据不同的特殊性使用许多描述。我喜欢使用的一些包括:算法的灵感,策略的隐喻或类比,信息处理目标,伪代码和代码。
算法处方
当我开始自己的研究项目时,我认为这个问题的答案是阅读算法上的所有内容并在代码中创建明确的实现。也许不错的想法,但代码只是传播算法的一种方式,而且它是有限的。
算法描述比计算更多。围绕算法的元信息对于某些用例来说是非常宝贵的。
例如,算法的使用试探法嵌入在论文中。在一个地方汇总使用启发式的概述可能意味着快速获得足够好的结果和对算法运行灵敏度分析数天或数周的差异。
其他示例包括用于测试算法的标准实验数据集,算法适合的一般问题类别,以及已经为该算法识别和描述的已知限制。
设计算法描述模板
算法描述模板为您提供了一种了解机器学习算法的结构化方法。
您可以从空白文档开始,并列出所需算法类型描述的章节标题,例如应用,实现或您自己的个人参考备忘单。
要确定要在模板中包含哪些部分,请列出您想要回答的有关算法的问题,或者如果您要构建参考,请列出算法。您可以使用的一些问题包括:
- 算法使用的标准和缩写是什么?
- 该算法的信息处理策略是什么?
- 算法的目标或目标是什么?
- 通常使用什么比喻或类比来描述算法的行为?
- 算法的伪代码或流程图描述是什么?
- 使用该算法的启发式或经验法则是什么?
- 算法适合哪些类型的问题?
- 用于演示算法的常用基准或示例数据集是什么?
- 有关该算法的更多信息,有哪些有用的资源?
- 首次描述算法的主要参考或资源是什么?
一旦你解决了一些问题,把它们变成章节标题。
对于每个部分标题,清楚地定义该部分的要求以及该部分中的描述将采用的形式。我希望为每个部分提供激励性问题,一旦回答将满足最低级别的细节。
从小开始并建立起来
这种方法的优点在于您无需成为算法或研究方面的专家。只要您能找到一些提及算法的资源,您就可以开始在模板中捕获有关算法的注释。
您可以非常简单地开始并收集算法的高级描述,其名称和缩写以及您找到的资源和他们谈论的内容。从这里您可以决定是否进一步扩展描述。
您将很快得到一到两页的算法描述。
我用它
我一直在使用算法模板。我发现这个策略实际有用的一些例子包括:
- 使用描述性聚焦模板实现机器学习算法。
- 使用应用聚焦模板应用机器学习算法。
- 构建要使用的算法目录,并参考使用通用模板。
在最后一个案例中,我将我的目录变成了一本由我在 2011 年初出版的 45 种自然启发算法的书。这本书被称为聪明的算法:自然灵感的编程秘籍(会员链接)。
摘要
在这篇文章中,您学习了如何使用算法描述模板作为学习机器学习算法的策略。
您了解到算法描述已被破坏,有效学习算法的答案是设计满足您需求的算法模板,并在阅读和学习算法时填写模板。
您了解到模板是解决压倒性问题的有效且结构化的方法。
如何研究机器学习算法
原文:
machinelearningmastery.com/how-to-research-a-machine-learning-algorithm/
算法是机器学习领域的重要组成部分。
您需要了解那里有哪些算法,以及如何有效地使用它们。
简化这种知识的一种简单方法是回顾已知的算法,研究它。
在这篇文章中,您将发现研究机器学习算法的重要性以及可用于加速理解机器学习算法的 5 种不同来源。
研究机器学习算法
摄影: Anders Sandberg ,保留一些权利
为什么研究机器学习算法
您需要了解算法以掌握机器学习。
机器学习算法与您可能熟悉的其他算法(如排序算法)不同。
机器学习算法不仅依赖于数据,而且还具有自适应性。通常,给定机器学习算法的核心是随机的优化过程,这意味着它具有随机性的元素。因此,这使得机器学习算法更难以分析并且难以对最佳和最差表现做出判断。
您需要应用,实现或深入思考算法以理解它们。
您可以描述算法如何作为数学秘籍,但要理解它在实践中的行为,您必须在行动中研究它。您可以对算法进行实验,将其应用于许多问题并提炼出它的行为以及如何在面对不同的问题类型时公开和利用这些行为。
或者,您可以采用的快捷方式是在您之前深入了解其他人对算法的理解。
您需要算法背景,这些算法只来自研究它们。
获取免费算法思维导图
方便的机器学习算法思维导图的样本。
我已经创建了一个由类型组织的 60 多种算法的方便思维导图。
下载,打印并使用它。
研究算法时要使用的 5 个来源
研究机器学习算法需要从多个来源对算法进行系统研究。
这可能听起来比实际上更可怕。您的目标是建立自己对不同机器学习算法的一致理解,并且对您个人的一致理解,并且需要从多个来源对给定算法的解释进行整理。
不同的来源可用于不同的目的,因此您需要仔细而有目的地挑选这些来源。
首先要清楚地了解为什么要研究给定的机器学习算法,然后选择那些能够最好地回答您所拥有的问题的来源。
您可以在研究机器学习算法时使用 5 种不同的来源,我们将依次对每种来源进行审核。
1.权威来源
权威来源提供专家解释和算法描述。
它们对于快速掌握算法非常有用,因为解释通常是严格且有些标准化的,至少在材料中是这样。
描述也可以是密集的,通常沉浸在数学中,并且使用学术语言专注于理论方面。这样,如果没有足够的背景,它们很难穿透。
权威来源的例子包括:
- 教科书,如研究生机器学习课程中使用的教科书。
- 讲义和幻灯片,例如在研究生机器学习课程中提供的那些。
- 概述文件,例如构成关于某个主题的学术纲要的文章。
2.精神来源
精神来源是专家来源和算法的原始描述。
精神资源有助于进入原作者的头脑或机器学习算法的描述,并梳理出算法参数和过程的意图。
这些来源几乎总是学术和理论,只偶尔包含有用的使用信息。
开创性资料的例子包括:
- 会议论文和期刊文章。
- 可能在该方法的原始出版物之前或补充的技术报告。
3.前沿来源
许多算法正在进行研究。这可以采取扩展,深入研究甚至简单应用的形式,并将该方法与其他方法进行比较。
我将这些来源称为前沿,因为它们暴露了有关机器学习算法的有用的新的和最先进的信息。
可以使用前沿源来很好地了解当前正在处理与算法相关的问题。这些可能代表您可以注意到的算法中的有趣或困难的子过程。
前沿源通常是密集且技术性的,并且需要代表您进行大量工作来解释工作的意图并提取有助于您更好地理解算法的突出细节。
前沿来源的例子包括:
- 会议论文和期刊文章。
- 全体会议和研讨会等会议讲座。
4.使用启发式来源
在研究用于实际和应用目的的机器学习算法时,使用启发式和最佳实践可能是您感兴趣的关键信息类型。
用法启发式源提供了如何在实践中使用给定机器学习算法的专家描述。它们适用于实际使用建议,例如参数配置,建议的数据准备步骤,甚至有关如何针对特定类别的问题调整和扩展算法的建议。
通常,这些来源缺少必须通过直接联系作者推断或寻求的细节。不要期望能够轻松地从这些来源重现结果,专注于提取可用于提示算法使用的启发式方法。
使用启发式源的示例包括:
- 描述机器学习竞赛结果的论文,如 KDD Cup 和 Kaggle。
- “_ 我做了什么 _”博客文章和论坛帖子与机器学习比赛有关。
- 问答网站,如 Cross Validated 和其他机器学习社区网站。
- 应用会议论文。
5.实现来源
您可能对研究算法感兴趣,因为您想要实现它。除了上面列出的其他来源之外,您还应该参考实现源。
这些是由专家或半专家准备的资源,这些资源在库和工具中提供机器学习算法的实现。样本可以在许可或开源许可下发布,供您学习。
这些来源很好地了解了如何将给定的机器学习算法转换为可执行和可用的系统。
实现来源的示例包括:
- 开源项目,如库和工具。
- 相关机器学习博客上的帖子。
- 研究生或研究实验室编写的技术报告。
通常,博客文章的实现是出于教学和理解目的而提供的,并且可能不是为了速度或可伸缩性而编写的。您在库和工具中找到的开源算法实现通常是高度优化的,不是为了可读性而编写的。
研究不仅仅适用于学者
您可以研究机器学习算法。不要被正式的学术语言和论文和文章的媒介所吓倒。
您不需要成为博士研究或机器学习算法专家。
您可以像任何人一样阅读论文,书籍和算法实现。
通常,难以阅读的论文的问题在于作者,而不在于读者。写一个算法或研究的良好技术处理是非常困难的,当你找到它们时,那些好的资源就是宝石。
行动步骤
在这篇文章中,您发现了研究机器学习算法和 5 个源的重要性,您可以使用它们来查找机器学习算法所需的信息。
下一步是练习你新发现的技能。
- 选择要研究的算法。
- 考虑您想要了解的算法,并从上面的列表中选择最能回答您问题的来源。
- 系统地研究算法。从 Google 学术搜索开始,如果您正在寻找论文,请输入算法名称。从 Google 搜索 GitHub 开始,如果您正在寻找算法实现,请输入算法名称。
分享你学到的东西。
如何研究机器学习算法
原文:
machinelearningmastery.com/how-to-study-machine-learning-algorithms/
算法构成了机器学习的重要组成部分。
您可以选择并应用机器学习算法,根据数据构建模型,选择要素,组合多个模型的预测,甚至评估给定模型的功能。
在这篇文章中,您将回顾 5 种不同的方法,您可以使用它们来研究机器学习算法。
如何学习机器学习算法
图片来自 mer chau ,保留一些权利
1.列出机器学习算法
有很多机器学习算法,它可以感觉压倒一切。
即使定义机器学习算法是什么,也可能很棘手。
一个很好的起点是制作自己的算法列表。启动文本文件,word 文档或电子表格并列出算法名称。还列出每种算法所属的一般类别。
这个简单的策略可以帮助您熟悉不同类型和类别的算法。之后,随着您的经验越来越丰富,这样的列表可以提示您并提供不同方法的想法,以便对您的问题进行检查。
一些算法列表的示例包括:
获取免费算法思维导图
方便的机器学习算法思维导图的样本。
我已经创建了一个由类型组织的 60 多种算法的方便思维导图。
下载,打印并使用它。
2.应用机器学习算法
机器学习算法不是孤立存在的,应用于数据集时最好理解它们。
将算法应用于问题以理解它们。 练习应用机器学习。这听起来很简单,但你会惊讶于瘫痪的人数从理论到行动迈出这一小步。
这可能意味着处理对您来说很重要的问题,竞争数据集或经典机器学习数据集。
使用机器学习平台,如 Weka , R 或 scikit-learn ,可以访问许多机器学习算法。
开始为不同类型的算法建立直觉,例如决策树和支持向量机。想想他们所需的前提条件以及参数对结果的影响。
建立应用不同算法的信心。 您应该对您的问题进行抽查算法。
3.描述机器学习算法
理解机器学习算法的下一步是探索已经理解的算法。
这可以在应用算法之前完成,但我认为在深入算法描述之前,将算法的工作直觉作为上下文是有价值的。
你可以研究一种算法。这包括定位和读取首次描述算法的主要来源以及教科书和评论文章中对算法的权威解释。
会议论文,竞赛结果甚至表格以及 Q&amp; A 网站可以帮助您更好地理解算法的最佳实践和使用启发式方法。
在研究算法时,请构建描述。我喜欢使用定义明确的算法描述模板。
您可以继续添加到此模板,以发现有关算法的更多信息。您可以添加引用,列出算法的伪代码并列出最佳实践和使用启发式。
这是一种有价值的技术,您可以构建自己的算法描述迷你百科全书供您自己参考(例如,参见 Clever Algorithms 获取 45 种算法秘籍)。
有关我使用的模板的更多信息,请查看帖子“如何学习机器学习算法”。
4.实现机器学习算法
实现机器学习算法是了解算法如何工作的一种很好的方法。
在实现算法时必须做出许多微决策。其中一些决策点暴露在算法配置参数中,但很多都没有。
通过自己实现算法,您将感受到如何自定义算法并选择要公开的内容以及要修复的决策点。
从零开始实现算法将帮助您理解算法的数学描述和扩展。这听起来可能违反直觉。数学描述是理想化的,并且通常提供算法内给定过程的快照描述。一旦将它们转换为代码,这些描述的含义可能会更加明显。
您可以利用算法的教程和开源实现来帮助您完成这些困难的部分。
请注意,算法的“_ 我的第一个实现 _”将比您在机器学习工具或库中找到的生产级实现更不可扩展且更脆弱。
看看我的教程,在 Python 中从零开始实现 k-最近邻居。
您可能也对我的帖子“如何实现机器学习算法”感兴趣。
5.机器学习算法实验
试验机器学习算法是理解它们的最佳方式。
你需要像科学家一样行事,研究像复杂系统一样运行的机器学习算法。
您需要控制变量,使用易于理解的标准化数据集,并探索结果上参数的因果关系。
了解参数的影响将有助于您在将来更好地配置算法。了解算法在不同情况下的行为将有助于您在将来更好地扩展和调整方法到新的和不同的问题域。
许多机器学习算法本质上是随机的,并且抵抗更经典的算法分析方法。它们通常需要理解经验调查和概率描述。
摘要
在这篇文章中,您发现了五种学习和学习机器学习算法的方法。
他们在哪里:
- 列出机器学习算法
- 应用机器学习算法
- 描述机器学习算法
- 实现机器学习算法
- 机器学习算法实验
您是否使用过这些方法来学习机器学习算法?
也许您有自己的方法来研究机器学习算法?在下面的评论中分享。
如何在 Python 中从零开始实现反向传播算法
原文:
machinelearningmastery.com/implement-backpropagation-algorithm-scratch-python/
反向传播算法是经典的前馈人工神经网络。
这种技术仍然用于训练大型深度学习网络。
在本教程中,您将了解如何使用 Python 从零开始实现反向传播算法。
完成本教程后,您将了解:
- 如何向前传播输入以计算输出。
- 如何反向传播错误并训练网络。
- 如何将反向传播算法应用于实际预测性建模问题。
让我们开始吧。
- 2016 年 11 月更新:修复了 activate()函数中的错误。谢谢 Alex!
- 2017 年 1 月更新:将 cross_validation_split()中的 fold_size 计算更改为始终为整数。修复了 Python 3 的问题。
- 2017 年 1 月更新:更新了 update_weights()中的小错误。谢谢 Tomasz!
- Update Apr / 2018 :添加了直接链接到 CSV 数据集。
- 更新 Aug / 2018 :经过测试和更新,可与 Python 3.6 配合使用。
如何在 Python 中从零开始实现反向传播算法
照片由 NICHD ,保留一些权利。
描述
本节简要介绍了我们将在本教程中使用的反向传播算法和小麦种子数据集。
反向传播算法
反向传播算法是一种来自人工神经网络领域的多层前馈网络的监督学习方法。
前馈神经网络受到一个或多个神经细胞(称为神经元)的信息处理的启发。神经元通过其树突接受输入信号,树突将电信号传递到细胞体。轴突将信号传递给突触,突触是细胞轴突与其他细胞树突的连接。
反向传播方法的原理是通过修改输入信号的内部权重来模拟给定函数,以产生预期的输出信号。使用监督学习方法训练系统,其中系统输出和已知预期输出之间的误差被呈现给系统并用于修改其内部状态。
从技术上讲,反向传播算法是一种在多层前馈神经网络中训练权重的方法。因此,它要求网络结构由一个或多个层定义,其中一个层完全连接到下一层。标准网络结构是一个输入层,一个隐藏层和一个输出层。
反向传播可用于分类和回归问题,但我们将重点关注本教程中的分类。
在分类问题中,当网络在每个类值的输出层中具有一个神经元时,实现最佳结果。例如,具有 A 和 B 类值的 2 类或二分类问题。这些预期输出必须转换为二进制向量,每个类值具有一列。例如分别为 A 和 B 的[1,0]和[0,1]。这称为单热编码。
小麦种子数据集
种子数据集涉及从不同品种的小麦给出测量种子的物种的预测。
有 201 条记录和 7 个数字输入变量。这是一个有 3 个输出类的分类问题。每个数字输入值的比例变化,因此可能需要一些数据标准化以用于加权输入的算法,如反向传播算法。
下面是数据集的前 5 行的示例。
15.26,14.84,0.871,5.763,3.312,2.221,5.22,1
14.88,14.57,0.8811,5.554,3.333,1.018,4.956,1
14.29,14.09,0.905,5.291,3.337,2.699,4.825,1
13.84,13.94,0.8955,5.324,3.379,2.259,4.805,1
16.14,14.99,0.9034,5.658,3.562,1.355,5.175,1
使用预测最常见类值的零规则算法,问题的基线准确度为 28.095%。
您可以从 UCI 机器学习库了解更多信息并下载种子数据集。
下载种子数据集并将其放入当前工作目录,文件名为 seeds_dataset.csv 。
数据集采用制表符分隔格式,因此您必须使用文本编辑器或电子表格程序将其转换为 CSV。
更新,直接下载 CSV 格式的数据集:
教程
本教程分为 6 个部分:
- 初始化网络。
- 向前传播。
- 返回传播错误。
- 训练网络。
- 预测。
- 种子数据集案例研究。
这些步骤将为您提供从零开始实现反向传播算法所需的基础,并将其应用于您自己的预测性建模问题。
1.初始化网络
让我们从简单的事情开始,创建一个可供训练的新网络。
每个神经元都有一组需要维持的权重。每个输入连接一个重量和偏置的额外重量。我们需要在训练期间为神经元存储其他属性,因此我们将使用字典来表示每个神经元并通过名称存储属性,例如权重的’权重’。
网络按层组织。输入层实际上只是我们训练数据集的一行。第一个真实层是隐藏层。接下来是输出层,每个类值都有一个神经元。
我们将层组织为字典数组,并将整个网络视为一个层数组。
最好将网络权重初始化为小的随机数。在这种情况下,我们将使用 0 到 1 范围内的随机数。
下面是一个名为 **initialize_network()**的函数,它创建了一个可供训练的新神经网络。它接受三个参数,输入数量,隐藏层中的神经元数量和输出数量。
您可以看到,对于隐藏层,我们创建 n_hidden 神经元,隐藏层中的每个神经元都有 n_inputs + 1 权重,一个用于数据集中的每个输入列,另一个用于偏见。
您还可以看到连接到隐藏层的输出层具有 n_outputs 神经元,每个神经元具有 n_hidden + 1 权重。这意味着输出层中的每个神经元都连接到隐藏层中每个神经元(具有权重)。
# Initialize a network
def initialize_network(n_inputs, n_hidden, n_outputs):
network = list()
hidden_layer = [{'weights':[random() for i in range(n_inputs + 1)]} for i in range(n_hidden)]
network.append(hidden_layer)
output_layer = [{'weights':[random() for i in range(n_hidden + 1)]} for i in range(n_outputs)]
network.append(output_layer)
return network
让我们测试一下这个功能。下面是一个创建小型网络的完整示例。
from random import seed
from random import random
# Initialize a network
def initialize_network(n_inputs, n_hidden, n_outputs):
network = list()
hidden_layer = [{'weights':[random() for i in range(n_inputs + 1)]} for i in range(n_hidden)]
network.append(hidden_layer)
output_layer = [{'weights':[random() for i in range(n_hidden + 1)]} for i in range(n_outputs)]
network.append(output_layer)
return network
seed(1)
network = initialize_network(2, 1, 2)
for layer in network:
print(layer)
运行该示例,您可以看到代码逐个打印出每个层。您可以看到隐藏层有一个具有 2 个输入权重和偏差的神经元。输出层有 2 个神经元,每个神经元有 1 个权重加上偏差。
[{'weights': [0.13436424411240122, 0.8474337369372327, 0.763774618976614]}]
[{'weights': [0.2550690257394217, 0.49543508709194095]}, {'weights': [0.4494910647887381, 0.651592972722763]}]
现在我们知道了如何创建和初始化网络,让我们看看如何使用它来计算输出。
2.前向传播
我们可以通过在每层传播输入信号直到输出层输出其值来计算神经网络的输出。
我们将此称为前向传播。
我们需要在训练期间生成需要纠正的预测技术,这是我们在训练网络以对新数据做出预测后需要的方法。
我们可以将传播分解为三个部分:
- 神经元激活。
- 神经元转移。
- 前向传播。
2.1。神经元激活
第一步是计算给定输入的一个神经元的激活。
输入可以是我们的训练数据集中的一行,如隐藏层的情况。在输出层的情况下,它也可以是隐藏层中每个神经元的输出。
神经元激活计算为输入的加权和。很像线性回归。
activation = sum(weight_i * input_i) + bias
权重是网络权重,输入是输入, i 是权重或输入的指标,偏差是没有输入的特殊权重(或者你可以认为输入总是为 1.0)。
下面是一个名为 **activate()**的函数的实现。您可以看到该函数假定偏差是权重列表中的最后一个权重。这有助于此处以及稍后使代码更易于阅读。
# Calculate neuron activation for an input
def activate(weights, inputs):
activation = weights[-1]
for i in range(len(weights)-1):
activation += weights[i] * inputs[i]
return activation
现在,让我们看看如何使用神经元激活。
2.2。神经元转移
一旦神经元被激活,我们需要转移激活以查看神经元输出实际是什么。
可以使用不同的传递函数。传统上使用 sigmoid 激活函数,但您也可以使用 tanh(双曲正切)函数来传输输出。最近,整流器传递函数已经在大型深度学习网络中流行。
S 形激活函数看起来像 S 形,它也称为逻辑函数。它可以取任何输入值并在 S 曲线上产生 0 到 1 之间的数字。它也是一个函数,我们可以很容易地计算出反向传播误差后我们将需要的导数(斜率)。
我们可以使用 sigmoid 函数传递激活函数,如下所示:
output = 1 / (1 + e^(-activation))
其中 e 是自然对数的基数(欧拉数)。
下面是一个名为 **transfer()**的函数,它实现了 sigmoid 方程。
# Transfer neuron activation
def transfer(activation):
return 1.0 / (1.0 + exp(-activation))
现在我们已经有了它们,让我们看看它们是如何被使用的。
2.3。前向传播
向前传播输入很简单。
我们通过网络的每一层计算每个神经元的输出。来自一层的所有输出都成为下一层神经元的输入。
下面是一个名为 **forward_propagate()**的函数,它使用我们的神经网络实现数据集中一行数据的前向传播。
您可以看到神经元的输出值存储在神经元中,名称为“输出”。您还可以看到我们收集名为 new_inputs 的数组中的层的输出,该数组成为数组输入,并用作后续层的输入。
该函数返回最后一层的输出,也称为输出层。
# Forward propagate input to a network output
def forward_propagate(network, row):
inputs = row
for layer in network:
new_inputs = []
for neuron in layer:
activation = activate(neuron['weights'], inputs)
neuron['output'] = transfer(activation)
new_inputs.append(neuron['output'])
inputs = new_inputs
return inputs
让我们将所有这些部分放在一起,测试我们网络的前向传播。
我们定义我们的网络内联一个隐藏的神经元,需要 2 个输入值和一个带有两个神经元的输出层。
from math import exp
# Calculate neuron activation for an input
def activate(weights, inputs):
activation = weights[-1]
for i in range(len(weights)-1):
activation += weights[i] * inputs[i]
return activation
# Transfer neuron activation
def transfer(activation):
return 1.0 / (1.0 + exp(-activation))
# Forward propagate input to a network output
def forward_propagate(network, row):
inputs = row
for layer in network:
new_inputs = []
for neuron in layer:
activation = activate(neuron['weights'], inputs)
neuron['output'] = transfer(activation)
new_inputs.append(neuron['output'])
inputs = new_inputs
return inputs
# test forward propagation
network = [[{'weights': [0.13436424411240122, 0.8474337369372327, 0.763774618976614]}],
[{'weights': [0.2550690257394217, 0.49543508709194095]}, {'weights': [0.4494910647887381, 0.651592972722763]}]]
row = [1, 0, None]
output = forward_propagate(network, row)
print(output)
运行该示例会传播输入模式[1,0]并生成打印的输出值。因为输出层有两个神经元,所以我们得到两个数字的列表作为输出。
实际输出值现在只是无意义,但接下来,我们将开始学习如何使神经元中的权重更有用。
[0.6629970129852887, 0.7253160725279748]
3.返回传播错误
反向传播算法以训练权重的方式命名。
在预期输出和从网络传播的输出之间计算误差。然后,这些错误通过网络从输出层向后传播到隐藏层,为错误分配责任并随时更新权重。
反向传播误差的数学基础是微积分,但我们将在本节中保持高水平,并关注计算的内容以及计算采用这种特定形式的方式而不是为什么。
这部分分为两部分。
- 转移衍生品。
- 错误反向传播。
3.1。转移衍生品
给定神经元的输出值,我们需要计算它的斜率。
我们使用 sigmoid 传递函数,其导数可以计算如下:
derivative = output * (1.0 - output)
下面是一个名为 **transfer_derivative()**的函数,它实现了这个等式。
# Calculate the derivative of an neuron output
def transfer_derivative(output):
return output * (1.0 - output)
现在,让我们看看如何使用它。
3.2。错误反向传播
第一步是计算每个输出神经元的误差,这将使我们的误差信号(输入)向后传播通过网络。
给定神经元的误差可以如下计算:
error = (expected - output) * transfer_derivative(output)
预期是神经元的预期输出值,输出是神经元的输出值, **transfer_derivative()**计算神经元输出值的斜率,如上所示。
此错误计算用于输出层中的神经元。期望值是类值本身。在隐藏层中,事情有点复杂。
隐藏层中神经元的误差信号被计算为输出层中每个神经元的加权误差。想象一下错误沿输出层的权重返回到隐藏层中的神经元。
累积反向传播的误差信号,然后用于确定隐藏层中神经元的误差,如下所示:
error = (weight_k * error_j) * transfer_derivative(output)
error_j 是输出层中 j 神经元的误差信号, weight_k 是连接 k 神经元的权重到当前的神经元和输出是当前神经元的输出。
下面是一个名为 **backward_propagate_error()**的函数,它实现了这个过程。
您可以看到为每个神经元计算的误差信号以名称“delta”存储。您可以看到网络层以相反的顺序迭代,从输出开始并向后工作。这确保了输出层中的神经元具有首先计算的“delta”值,隐藏层中的神经元可以在随后的迭代中使用。我选择名称“delta”来反映错误对神经元的改变(例如,权重增量)。
您可以看到隐藏层中神经元的误差信号是从输出层中的神经元累积的,其中隐藏的神经元数 j 也是输出层神经元中神经元重量的指数[ ‘权重’] [j] 。
# Backpropagate error and store in neurons
def backward_propagate_error(network, expected):
for i in reversed(range(len(network))):
layer = network[i]
errors = list()
if i != len(network)-1:
for j in range(len(layer)):
error = 0.0
for neuron in network[i + 1]:
error += (neuron['weights'][j] * neuron['delta'])
errors.append(error)
else:
for j in range(len(layer)):
neuron = layer[j]
errors.append(expected[j] - neuron['output'])
for j in range(len(layer)):
neuron = layer[j]
neuron['delta'] = errors[j] * transfer_derivative(neuron['output'])
让我们将所有部分放在一起,看看它是如何工作的。
我们定义一个具有输出值的固定神经网络,并反向传播预期的输出模式。下面列出了完整的示例。
# Calculate the derivative of an neuron output
def transfer_derivative(output):
return output * (1.0 - output)
# Backpropagate error and store in neurons
def backward_propagate_error(network, expected):
for i in reversed(range(len(network))):
layer = network[i]
errors = list()
if i != len(network)-1:
for j in range(len(layer)):
error = 0.0
for neuron in network[i + 1]:
error += (neuron['weights'][j] * neuron['delta'])
errors.append(error)
else:
for j in range(len(layer)):
neuron = layer[j]
errors.append(expected[j] - neuron['output'])
for j in range(len(layer)):
neuron = layer[j]
neuron['delta'] = errors[j] * transfer_derivative(neuron['output'])
# test backpropagation of error
network = [[{'output': 0.7105668883115941, 'weights': [0.13436424411240122, 0.8474337369372327, 0.763774618976614]}],
[{'output': 0.6213859615555266, 'weights': [0.2550690257394217, 0.49543508709194095]}, {'output': 0.6573693455986976, 'weights': [0.4494910647887381, 0.651592972722763]}]]
expected = [0, 1]
backward_propagate_error(network, expected)
for layer in network:
print(layer)
运行该示例在错误的反向传播完成后打印网络。您可以看到计算错误值并将其存储在输出层和隐藏层的神经元中。
[{'output': 0.7105668883115941, 'weights': [0.13436424411240122, 0.8474337369372327, 0.763774618976614], 'delta': -0.0005348048046610517}]
[{'output': 0.6213859615555266, 'weights': [0.2550690257394217, 0.49543508709194095], 'delta': -0.14619064683582808}, {'output': 0.6573693455986976, 'weights': [0.4494910647887381, 0.651592972722763], 'delta': 0.0771723774346327}]
现在让我们使用错误的反向传播来训练网络。
4.训练网络
使用随机梯度下降训练网络。
这涉及将训练数据集暴露给网络以及向前传播输入的每行数据的多次迭代,反向传播错误并更新网络权重。
这部分分为两部分:
- 更新权重。
- 训练网络。
4.1。更新权重
一旦通过上述反向传播方法计算网络中每个神经元的误差,就可以使用它们来更新权重。
网络权重更新如下:
weight = weight + learning_rate * error * input
当权重是给定权重时, learning_rate 是您必须指定的参数,错误是由神经元和的反向传播程序计算的误差 input 是导致错误的输入值。
除了没有输入项,或者输入是 1.0 的固定值之外,可以使用相同的程序来更新偏差权重。
学习率控制改变重量以校正错误的程度。例如,值为 0.1 将更新可能更新量的 10%的权重。较小的学习率是优选的,导致在大量训练迭代中学习较慢。这增加了网络在所有层上找到一组良好权重的可能性,而不是最小化误差的最快权重集(称为早熟收敛)。
下面是一个名为 **update_weights()**的函数,它在给定输入数据行,学习率的情况下更新网络的权重,并假设已经执行了前向和后向传播。
请记住,输出层的输入是隐藏层的输出集合。
# Update network weights with error
def update_weights(network, row, l_rate):
for i in range(len(network)):
inputs = row[:-1]
if i != 0:
inputs = [neuron['output'] for neuron in network[i - 1]]
for neuron in network[i]:
for j in range(len(inputs)):
neuron['weights'][j] += l_rate * neuron['delta'] * inputs[j]
neuron['weights'][-1] += l_rate * neuron['delta']
现在我们知道如何更新网络权重,让我们看看我们如何重复这样做。
4.2。训练网络
如上所述,使用随机梯度下降来更新网络。
这涉及首先循环固定数量的时期并且在每个时期内更新训练数据集中的每一行的网络。
由于针对每种训练模式进行了更新,因此这种类型的学习称为在线学习。如果在更新权重之前在迭代中累积了错误,则称为批量学习或批量梯度下降。
下面是一个函数,它利用给定的训练数据集,学习率,固定的迭代数和预期的输出值数来实现已经初始化的神经网络的训练。
预期的输出值数量用于将训练数据中的类值转换为单热编码。这是一个二进制向量,每个类值有一列,以匹配网络的输出。这是计算输出层的误差所必需的。
您还可以看到预期输出和网络输出之间的总和平方误差在每个时期累积并打印。这有助于创建网络学习和改进每个时代的痕迹。
# Train a network for a fixed number of epochs
def train_network(network, train, l_rate, n_epoch, n_outputs):
for epoch in range(n_epoch):
sum_error = 0
for row in train:
outputs = forward_propagate(network, row)
expected = [0 for i in range(n_outputs)]
expected[row[-1]] = 1
sum_error += sum([(expected[i]-outputs[i])**2 for i in range(len(expected))])
backward_propagate_error(network, expected)
update_weights(network, row, l_rate)
print('>epoch=%d, lrate=%.3f, error=%.3f' % (epoch, l_rate, sum_error))
我们现在拥有训练网络的所有部分。我们可以汇总一个示例,其中包括我们目前所见的所有内容,包括网络初始化和在小型数据集上训练网络。
下面是一个小型人为的数据集,我们可以用它来测试我们的神经网络的训练。
X1 X2 Y
2.7810836 2.550537003 0
1.465489372 2.362125076 0
3.396561688 4.400293529 0
1.38807019 1.850220317 0
3.06407232 3.005305973 0
7.627531214 2.759262235 1
5.332441248 2.088626775 1
6.922596716 1.77106367 1
8.675418651 -0.242068655 1
7.673756466 3.508563011 1
以下是完整的示例。我们将在隐藏层中使用 2 个神经元。这是一个二分类问题(2 个类),因此输出层中将有两个神经元。该网络将被训练 20 个时代,学习率为 0.5,这很高,因为我们正在训练如此少的迭代。
from math import exp
from random import seed
from random import random
# Initialize a network
def initialize_network(n_inputs, n_hidden, n_outputs):
network = list()
hidden_layer = [{'weights':[random() for i in range(n_inputs + 1)]} for i in range(n_hidden)]
network.append(hidden_layer)
output_layer = [{'weights':[random() for i in range(n_hidden + 1)]} for i in range(n_outputs)]
network.append(output_layer)
return network
# Calculate neuron activation for an input
def activate(weights, inputs):
activation = weights[-1]
for i in range(len(weights)-1):
activation += weights[i] * inputs[i]
return activation
# Transfer neuron activation
def transfer(activation):
return 1.0 / (1.0 + exp(-activation))
# Forward propagate input to a network output
def forward_propagate(network, row):
inputs = row
for layer in network:
new_inputs = []
for neuron in layer:
activation = activate(neuron['weights'], inputs)
neuron['output'] = transfer(activation)
new_inputs.append(neuron['output'])
inputs = new_inputs
return inputs
# Calculate the derivative of an neuron output
def transfer_derivative(output):
return output * (1.0 - output)
# Backpropagate error and store in neurons
def backward_propagate_error(network, expected):
for i in reversed(range(len(network))):
layer = network[i]
errors = list()
if i != len(network)-1:
for j in range(len(layer)):
error = 0.0
for neuron in network[i + 1]:
error += (neuron['weights'][j] * neuron['delta'])
errors.append(error)
else:
for j in range(len(layer)):
neuron = layer[j]
errors.append(expected[j] - neuron['output'])
for j in range(len(layer)):
neuron = layer[j]
neuron['delta'] = errors[j] * transfer_derivative(neuron['output'])
# Update network weights with error
def update_weights(network, row, l_rate):
for i in range(len(network)):
inputs = row[:-1]
if i != 0:
inputs = [neuron['output'] for neuron in network[i - 1]]
for neuron in network[i]:
for j in range(len(inputs)):
neuron['weights'][j] += l_rate * neuron['delta'] * inputs[j]
neuron['weights'][-1] += l_rate * neuron['delta']
# Train a network for a fixed number of epochs
def train_network(network, train, l_rate, n_epoch, n_outputs):
for epoch in range(n_epoch):
sum_error = 0
for row in train:
outputs = forward_propagate(network, row)
expected = [0 for i in range(n_outputs)]
expected[row[-1]] = 1
sum_error += sum([(expected[i]-outputs[i])**2 for i in range(len(expected))])
backward_propagate_error(network, expected)
update_weights(network, row, l_rate)
print('>epoch=%d, lrate=%.3f, error=%.3f' % (epoch, l_rate, sum_error))
# Test training backprop algorithm
seed(1)
dataset = [[2.7810836,2.550537003,0],
[1.465489372,2.362125076,0],
[3.396561688,4.400293529,0],
[1.38807019,1.850220317,0],
[3.06407232,3.005305973,0],
[7.627531214,2.759262235,1],
[5.332441248,2.088626775,1],
[6.922596716,1.77106367,1],
[8.675418651,-0.242068655,1],
[7.673756466,3.508563011,1]]
n_inputs = len(dataset[0]) - 1
n_outputs = len(set([row[-1] for row in dataset]))
network = initialize_network(n_inputs, 2, n_outputs)
train_network(network, dataset, 0.5, 20, n_outputs)
for layer in network:
print(layer)
运行该示例首先打印每个训练时期的总和平方误差。我们可以看到这个错误的趋势随着每个时期而减少。
一旦经过训练,就会打印网络,显示学习的重量。网络中还有输出和 delta 值,可以忽略。如果需要,我们可以更新我们的训练功能以删除这些数据。
>epoch=0, lrate=0.500, error=6.350
>epoch=1, lrate=0.500, error=5.531
>epoch=2, lrate=0.500, error=5.221
>epoch=3, lrate=0.500, error=4.951
>epoch=4, lrate=0.500, error=4.519
>epoch=5, lrate=0.500, error=4.173
>epoch=6, lrate=0.500, error=3.835
>epoch=7, lrate=0.500, error=3.506
>epoch=8, lrate=0.500, error=3.192
>epoch=9, lrate=0.500, error=2.898
>epoch=10, lrate=0.500, error=2.626
>epoch=11, lrate=0.500, error=2.377
>epoch=12, lrate=0.500, error=2.153
>epoch=13, lrate=0.500, error=1.953
>epoch=14, lrate=0.500, error=1.774
>epoch=15, lrate=0.500, error=1.614
>epoch=16, lrate=0.500, error=1.472
>epoch=17, lrate=0.500, error=1.346
>epoch=18, lrate=0.500, error=1.233
>epoch=19, lrate=0.500, error=1.132
[{'weights': [-1.4688375095432327, 1.850887325439514, 1.0858178629550297], 'output': 0.029980305604426185, 'delta': -0.0059546604162323625}, {'weights': [0.37711098142462157, -0.0625909894552989, 0.2765123702642716], 'output': 0.9456229000211323, 'delta': 0.0026279652850863837}]
[{'weights': [2.515394649397849, -0.3391927502445985, -0.9671565426390275], 'output': 0.23648794202357587, 'delta': -0.04270059278364587}, {'weights': [-2.5584149848484263, 1.0036422106209202, 0.42383086467582715], 'output': 0.7790535202438367, 'delta': 0.03803132596437354}]
一旦网络被训练,我们需要使用它来做出预测。
5.预测
使用训练有素的神经网络做出预测很容易。
我们已经看到了如何向前传播输入模式以获得输出。这就是我们做出预测所需要做的。我们可以直接使用输出值本身作为属于每个输出类的模式的概率。
将此输出转换为清晰的类预测可能更有用。我们可以通过选择具有更大概率的类值来做到这一点。这也称为 arg max 函数。
下面是一个名为 **predict()**的函数,它实现了这个过程。它返回网络输出中具有最大概率的索引。它假定类值已从 0 开始转换为整数。
# Make a prediction with a network
def predict(network, row):
outputs = forward_propagate(network, row)
return outputs.index(max(outputs))
我们可以将它与上面的代码一起用于前向传播输入,并使用我们的小型设计数据集来测试使用已经训练过的网络做出预测。该示例对从上一步骤训练的网络进行硬编码。
下面列出了完整的示例。
from math import exp
# Calculate neuron activation for an input
def activate(weights, inputs):
activation = weights[-1]
for i in range(len(weights)-1):
activation += weights[i] * inputs[i]
return activation
# Transfer neuron activation
def transfer(activation):
return 1.0 / (1.0 + exp(-activation))
# Forward propagate input to a network output
def forward_propagate(network, row):
inputs = row
for layer in network:
new_inputs = []
for neuron in layer:
activation = activate(neuron['weights'], inputs)
neuron['output'] = transfer(activation)
new_inputs.append(neuron['output'])
inputs = new_inputs
return inputs
# Make a prediction with a network
def predict(network, row):
outputs = forward_propagate(network, row)
return outputs.index(max(outputs))
# Test making predictions with the network
dataset = [[2.7810836,2.550537003,0],
[1.465489372,2.362125076,0],
[3.396561688,4.400293529,0],
[1.38807019,1.850220317,0],
[3.06407232,3.005305973,0],
[7.627531214,2.759262235,1],
[5.332441248,2.088626775,1],
[6.922596716,1.77106367,1],
[8.675418651,-0.242068655,1],
[7.673756466,3.508563011,1]]
network = [[{'weights': [-1.482313569067226, 1.8308790073202204, 1.078381922048799]}, {'weights': [0.23244990332399884, 0.3621998343835864, 0.40289821191094327]}],
[{'weights': [2.5001872433501404, 0.7887233511355132, -1.1026649757805829]}, {'weights': [-2.429350576245497, 0.8357651039198697, 1.0699217181280656]}]]
for row in dataset:
prediction = predict(network, row)
print('Expected=%d, Got=%d' % (row[-1], prediction))
运行该示例将打印训练数据集中每条记录的预期输出,然后是网络进行的清晰预测。
它表明网络在这个小数据集上达到了 100%的准确率。
Expected=0, Got=0
Expected=0, Got=0
Expected=0, Got=0
Expected=0, Got=0
Expected=0, Got=0
Expected=1, Got=1
Expected=1, Got=1
Expected=1, Got=1
Expected=1, Got=1
Expected=1, Got=1
现在我们准备将反向传播算法应用于现实世界数据集。
6.小麦种子数据集
本节将 Backpropagation 算法应用于小麦种子数据集。
第一步是加载数据集并将加载的数据转换为我们可以在神经网络中使用的数字。为此我们将使用辅助函数 **load_csv()**来加载文件, **str_column_to_float()**将字符串数转换为浮点数, **str_column_to_int()**转换为 class 列到整数值。
输入值的比例不同,需要归一化到 0 和 1 的范围。通常的做法是将输入值标准化为所选传递函数的范围,在这种情况下,输出 0 到 1 之间的值的 sigmoid 函数。 **dataset_minmax()**和 **normalize_dataset()**辅助函数用于标准化输入值。
我们将使用 5 倍折叠交叉验证来评估算法。这意味着每个折叠中将有 201/5 = 40.2 或 40 个记录。我们将使用辅助函数 **evaluate_algorithm()**来评估具有交叉验证的算法和 **accuracy_metric()**来计算预测的准确率。
开发了一个名为 **back_propagation()**的新功能来管理反向传播算法的应用,首先初始化网络,在训练数据集上训练它,然后使用训练好的网络对测试数据集做出预测。
The complete example is listed below.
# Backprop on the Seeds Dataset
from random import seed
from random import randrange
from random import random
from csv import reader
from math import exp
# Load a CSV file
def load_csv(filename):
dataset = list()
with open(filename, 'r') as file:
csv_reader = reader(file)
for row in csv_reader:
if not row:
continue
dataset.append(row)
return dataset
# Convert string column to float
def str_column_to_float(dataset, column):
for row in dataset:
row[column] = float(row[column].strip())
# Convert string column to integer
def str_column_to_int(dataset, column):
class_values = [row[column] for row in dataset]
unique = set(class_values)
lookup = dict()
for i, value in enumerate(unique):
lookup[value] = i
for row in dataset:
row[column] = lookup[row[column]]
return lookup
# Find the min and max values for each column
def dataset_minmax(dataset):
minmax = list()
stats = [[min(column), max(column)] for column in zip(*dataset)]
return stats
# Rescale dataset columns to the range 0-1
def normalize_dataset(dataset, minmax):
for row in dataset:
for i in range(len(row)-1):
row[i] = (row[i] - minmax[i][0]) / (minmax[i][1] - minmax[i][0])
# Split a dataset into k folds
def cross_validation_split(dataset, n_folds):
dataset_split = list()
dataset_copy = list(dataset)
fold_size = int(len(dataset) / n_folds)
for i in range(n_folds):
fold = list()
while len(fold) < fold_size:
index = randrange(len(dataset_copy))
fold.append(dataset_copy.pop(index))
dataset_split.append(fold)
return dataset_split
# Calculate accuracy percentage
def accuracy_metric(actual, predicted):
correct = 0
for i in range(len(actual)):
if actual[i] == predicted[i]:
correct += 1
return correct / float(len(actual)) * 100.0
# Evaluate an algorithm using a cross validation split
def evaluate_algorithm(dataset, algorithm, n_folds, *args):
folds = cross_validation_split(dataset, n_folds)
scores = list()
for fold in folds:
train_set = list(folds)
train_set.remove(fold)
train_set = sum(train_set, [])
test_set = list()
for row in fold:
row_copy = list(row)
test_set.append(row_copy)
row_copy[-1] = None
predicted = algorithm(train_set, test_set, *args)
actual = [row[-1] for row in fold]
accuracy = accuracy_metric(actual, predicted)
scores.append(accuracy)
return scores
# Calculate neuron activation for an input
def activate(weights, inputs):
activation = weights[-1]
for i in range(len(weights)-1):
activation += weights[i] * inputs[i]
return activation
# Transfer neuron activation
def transfer(activation):
return 1.0 / (1.0 + exp(-activation))
# Forward propagate input to a network output
def forward_propagate(network, row):
inputs = row
for layer in network:
new_inputs = []
for neuron in layer:
activation = activate(neuron['weights'], inputs)
neuron['output'] = transfer(activation)
new_inputs.append(neuron['output'])
inputs = new_inputs
return inputs
# Calculate the derivative of an neuron output
def transfer_derivative(output):
return output * (1.0 - output)
# Backpropagate error and store in neurons
def backward_propagate_error(network, expected):
for i in reversed(range(len(network))):
layer = network[i]
errors = list()
if i != len(network)-1:
for j in range(len(layer)):
error = 0.0
for neuron in network[i + 1]:
error += (neuron['weights'][j] * neuron['delta'])
errors.append(error)
else:
for j in range(len(layer)):
neuron = layer[j]
errors.append(expected[j] - neuron['output'])
for j in range(len(layer)):
neuron = layer[j]
neuron['delta'] = errors[j] * transfer_derivative(neuron['output'])
# Update network weights with error
def update_weights(network, row, l_rate):
for i in range(len(network)):
inputs = row[:-1]
if i != 0:
inputs = [neuron['output'] for neuron in network[i - 1]]
for neuron in network[i]:
for j in range(len(inputs)):
neuron['weights'][j] += l_rate * neuron['delta'] * inputs[j]
neuron['weights'][-1] += l_rate * neuron['delta']
# Train a network for a fixed number of epochs
def train_network(network, train, l_rate, n_epoch, n_outputs):
for epoch in range(n_epoch):
for row in train:
outputs = forward_propagate(network, row)
expected = [0 for i in range(n_outputs)]
expected[row[-1]] = 1
backward_propagate_error(network, expected)
update_weights(network, row, l_rate)
# Initialize a network
def initialize_network(n_inputs, n_hidden, n_outputs):
network = list()
hidden_layer = [{'weights':[random() for i in range(n_inputs + 1)]} for i in range(n_hidden)]
network.append(hidden_layer)
output_layer = [{'weights':[random() for i in range(n_hidden + 1)]} for i in range(n_outputs)]
network.append(output_layer)
return network
# Make a prediction with a network
def predict(network, row):
outputs = forward_propagate(network, row)
return outputs.index(max(outputs))
# Backpropagation Algorithm With Stochastic Gradient Descent
def back_propagation(train, test, l_rate, n_epoch, n_hidden):
n_inputs = len(train[0]) - 1
n_outputs = len(set([row[-1] for row in train]))
network = initialize_network(n_inputs, n_hidden, n_outputs)
train_network(network, train, l_rate, n_epoch, n_outputs)
predictions = list()
for row in test:
prediction = predict(network, row)
predictions.append(prediction)
return(predictions)
# Test Backprop on Seeds dataset
seed(1)
# load and prepare data
filename = 'seeds_dataset.csv'
dataset = load_csv(filename)
for i in range(len(dataset[0])-1):
str_column_to_float(dataset, i)
# convert class column to integers
str_column_to_int(dataset, len(dataset[0])-1)
# normalize input variables
minmax = dataset_minmax(dataset)
normalize_dataset(dataset, minmax)
# evaluate algorithm
n_folds = 5
l_rate = 0.3
n_epoch = 500
n_hidden = 5
scores = evaluate_algorithm(dataset, back_propagation, n_folds, l_rate, n_epoch, n_hidden)
print('Scores: %s' % scores)
print('Mean Accuracy: %.3f%%' % (sum(scores)/float(len(scores))))
构建了隐藏层中有 5 个神经元,输出层中有 3 个神经元的网络。该网络训练了 500 个时代,学习率为 0.3。通过一些试验和错误发现了这些参数,但您可以做得更好。
运行该示例打印每个折叠的平均分类准确度以及所有折叠的平均表现。
您可以看到反向传播和所选配置实现了大约 93%的平均分类精度,这明显优于零精度算法,其精确度略高于 28%。
Scores: [92.85714285714286, 92.85714285714286, 97.61904761904762, 92.85714285714286, 90.47619047619048]
Mean Accuracy: 93.333%
扩展
本节列出了您可能希望探索的教程的扩展。
- 调谐算法参数。尝试更长或更短的训练更大或更小的网络。看看你是否可以在种子数据集上获得更好的表现。
- 其他方法。尝试不同的权重初始化技术(如小随机数)和不同的传递函数(如 tanh)。
- 更多层。添加对更多隐藏层的支持,其训练方式与本教程中使用的一个隐藏层相同。
- 回归。更改网络,使输出层中只有一个神经元,并预测实际值。选择回归数据集进行练习。线性传递函数可以用于输出层中的神经元,或者所选数据集的输出值可以缩放到 0 和 1 之间的值。
- 批量梯度下降。将训练程序从在线更改为批量梯度下降,并仅在每个时期结束时更新权重。
你有没有试过这些扩展?
在下面的评论中分享您的经验。
评论
在本教程中,您了解了如何从零开始实现 Backpropagation 算法。
具体来说,你学到了:
- 如何转发传播输入以计算网络输出。
- 如何反向传播错误并更新网络权重。
- 如何将反向传播算法应用于现实世界数据集。
你有什么问题吗?
在下面的评论中提出您的问题,我会尽力回答。
更多推荐
所有评论(0)