TowardsDataScience 博客中文翻译 2016~2018(二十八)
Python 中随机森林的实现和解释
(Source)
通过从单个决策树构建来使用和理解随机森林的指南。
幸运的是,有了 Scikit-Learn 这样的库,现在用 Python 实现数百种机器学习算法已经很容易了。它是如此简单,以至于我们经常不需要任何关于模型如何工作的基础知识来使用它。虽然没有必要知道所有的细节,但了解机器学习模型如何在引擎盖下工作仍然是有帮助的。这让我们能够在模型表现不佳时对其进行诊断,或者解释它是如何做出决策的,如果我们想说服他人相信我们的模型,这一点至关重要。
在本文中,我们将看看如何在 Python 中构建和使用随机森林。除了查看代码之外,我们还将尝试了解这个模型是如何工作的。因为随机森林由许多决策树组成,所以我们将从理解单个决策树如何对简单问题进行分类开始。然后,我们将在现实世界的数据科学问题上使用随机森林。本文的完整代码可以从 GitHub 上的 Jupyter 笔记本中获得。
**注:**本文最初出现在 enlight 上,这是一个社区驱动的开源平台,为那些希望学习机器学习的人提供教程。
理解决策树
决策树是随机森林的构建块,是一种直观的模型。我们可以把决策树想象成一系列关于我们的数据的是/否问题,最终导致一个预测的类(或者在回归情况下的连续值)。这是一个可解释的模型,因为它使分类更像我们所做的:我们对我们所拥有的可用数据进行一系列查询,直到我们做出决定(在理想世界中)。
决策树的技术细节在于如何形成关于数据的问题。在 CART 算法中,通过确定问题(称为节点分裂)来构建决策树,当回答这些问题时,将导致基尼系数杂质的最大减少。这意味着决策树试图通过在特征中查找值来形成包含来自单个类的高比例样本(数据点)的节点,这些值将数据清晰地划分到各个类中。
我们稍后将详细讨论基尼系数杂质,但首先,让我们建立一个决策树,这样我们就可以在高层次上理解它。
简单问题的决策树
我们将从一个非常简单的二进制分类问题开始,如下所示:
The goal is to divide the data points into their respective classes.
我们的数据只有两个特征(预测变量),x1和x2,6 个数据点——样本——分成 2 个不同的标签。虽然这个问题很简单,但它不是线性可分的,这意味着我们不能通过数据画一条直线来对点进行分类。
然而,我们可以画出一系列的直线,将数据点分成盒子,我们称之为节点。事实上,这就是决策树在训练时所做的事情。实际上,决策树是通过构建许多线性边界而构建的非线性模型。
为了创建一个决策树并在数据上训练(fit)它,我们使用 Scikit-Learn。
在训练过程中,我们为模型提供了特征和标签,因此它可以学习根据特征对点进行分类。(对于这个简单的问题,我们没有测试集,但在测试时,我们只给模型提供特征,并让它对标签进行预测。)
我们可以在训练数据上测试我们的模型的准确性:
我们看到它获得了 100%的准确率,这是我们所期望的,因为我们给了它训练的答案(y),并且没有限制树的深度。事实证明,这种完全学习训练数据的能力可能是决策树的一个缺点,因为它可能会导致过度拟合,我们将在后面讨论。
可视化决策树
那么,当我们训练决策树时,实际上发生了什么呢?我发现理解决策树的一个有用的方法是可视化它,我们可以使用 Scikit-Learn 函数来实现(详情请查看笔记本或本文)。
Simple decision tree
除了叶节点(彩色终端节点)之外,所有节点都有 5 个部分:
- 根据某个要素的值询问有关数据的问题。每个问题都有一个对或错的答案来划分节点。基于问题的答案,数据点沿着树向下移动。
gini:节点的基尼杂质。随着我们沿着树向下移动,平均加权基尼系数减少。samples:节点中的观察次数。value:每类样本的数量。例如,顶部节点具有类别 0 中的 2 个样本和类别 1 中的 4 个样本。class:节点中点的多数分类。在叶节点的情况下,这是对节点中所有样本的预测。
叶节点没有问题,因为它们是进行最终预测的地方。要对一个新点进行分类,只需沿着树向下移动,使用该点的特征来回答问题,直到到达一个叶节点,其中class是预测。
为了以不同的方式查看决策树,我们可以在原始数据上绘制决策树构建的拆分。
Splits made by the decision tree.
每个分割都是一条线,它根据特征值将数据点分成节点。对于这个简单的问题,没有对最大深度的限制,划分将每个点放在一个节点中,只有相同类别的点。(同样,稍后我们会看到这种对训练数据的完美划分可能不是我们想要的,因为它会导致过度拟合。)
基尼杂质
在这一点上,深入了解基尼系数的概念是有帮助的(数学并不可怕!)节点的 Gini 杂质是节点中随机选择的样本如果被该节点中样本的分布标记,将被错误标记的概率。例如,在顶部(根)节点中,有 44.4%的机会对基于节点中的样本标签随机选择的数据点进行错误分类。我们使用以下等式得出该值:
Gini impurity of a node n.
节点n的基尼不纯度是 1 减去所有类别J(对于二进制分类任务,这是 2)中每个类别p_i的样本分数的平方。这在文字上可能有点混乱,所以让我们算出根节点的 Gini 杂质。
Gini Impurity of the root node
在每一个节点,决策树在特征中搜索导致基尼系数杂质最大减少的值。(分裂节点的另一种选择是使用信息增益,一个相关的概念)。
然后,它在贪婪的递归过程中重复该分裂过程,直到它达到最大深度,或者每个节点仅包含来自一个类的样本。每一级别的加权基尼系数都必须降低。在树的第二层,总加权基尼系数为 0.333:
(每个节点的 Gini 杂质由该节点中来自父节点的分数加权。)您可以继续计算每个节点的基尼系数(查看答案的图片)。从一些基本的数学中,一个强大的模型出现了!
最终,最后一层的加权总 Gini 杂质变为 0,这意味着每个节点都是完全纯的,并且从该节点中随机选择的点不会被错误分类。虽然这似乎是积极的,但这意味着模型可能会过度拟合,因为节点仅使用训练数据构建。
过度适应:或者为什么一片森林比一棵树更好
你可能会问为什么不仅仅使用一个决策树呢?它似乎是完美的分类器,因为它没有犯任何错误!需要记住的一个关键点是,采油树在训练数据上没有出现错误**。我们希望如此,因为我们给了树答案,并且没有限制最大深度(级别数)。机器学习模型的目标是很好地推广到从未见过的新数据。**
过度拟合发生在我们有一个非常灵活的模型(该模型具有高容量)时,该模型本质上是通过紧密拟合来记忆训练数据。问题是,模型不仅学习训练数据中的实际关系,还学习存在的任何噪声。一个灵活的模型被称为具有高 方差 ,因为学习到的参数(例如决策树的结构)会随着训练数据而显著变化。
另一方面,不灵活的模型被认为具有高 偏差 ,因为它对训练数据做出假设(它偏向于数据的预先设想的想法。)例如,线性分类器假设数据是线性的,并且不具有拟合非线性关系的灵活性。一个不灵活的模型甚至可能不具备拟合训练数据的能力,并且在两种情况下——高方差和高偏差——该模型都不能很好地推广到新数据。
创建一个如此灵活的模型来记忆训练数据与一个不灵活的模型无法学习训练数据之间的平衡被称为偏差-方差权衡,是机器学习中的一个基本概念。
当我们不限制最大深度时,决策树容易过度拟合的原因是因为它具有无限的灵活性,这意味着它可以保持增长,直到对于每个单独的观察只有一个叶节点,从而对所有的观察进行完美的分类。如果您返回到决策树的图像,并将最大深度限制为 2(只进行一次分割),则分类不再是 100%正确的。我们减少了决策树的方差,但代价是增加了偏差。
作为限制树的深度的一种替代方法,这减少了方差(好的)并增加了偏差(坏的),我们可以将许多决策树组合成一个单一的集成模型,称为随机森林。
随机森林
随机森林是由许多决策树组成的模型。这个模型不是简单地平均预测树木(我们可以称之为“森林”),而是使用了两个关键概念,并因此得名随机:
- 构建树时对训练数据点进行随机采样
- 分割结点时考虑的随机要素子集
训练观察值的随机抽样
训练时,随机森林中的每棵树都从数据点的随机样本中学习。使用替换抽取样本,称为*自举,*这意味着一些样本将在单个树中多次使用。其思想是通过在不同的样本上训练每棵树,尽管每棵树相对于一组特定的训练数据可能具有较高的方差,但总体上,整个森林将具有较低的方差,但不会以增加偏差为代价。
在测试时,通过平均每个决策树的预测来进行预测。这种在不同的数据自举子集上训练每个个体学习者,然后对预测进行平均的过程被称为 bagging ,是 自举聚合 的缩写。
用于分割节点的随机特征子集
随机森林中的另一个主要概念是,在分割每个决策树中的每个节点时,只考虑所有特征的子集。通常,这被设置为sqrt(n_features)用于分类,这意味着如果在每棵树的每个节点有 16 个特征,则只有 4 个随机特征将被考虑用于分裂节点。(也可以考虑每个节点的所有特征来训练随机森林,这在回归中是常见的。这些选项可以在 Scikit-Learn 随机森林实现中控制。
如果你能理解单个决策树、*装袋、*和随机特征子集的概念,那么你就对随机森林的工作原理有了很好的理解:
随机森林组合了数百或数千棵决策树,根据一组略有不同的观察值训练每棵树,考虑有限数量的特征来分割每棵树中的节点。随机森林的最终预测是通过对每棵树的预测进行平均而得到的。
为了理解为什么随机森林比单一决策树更好,想象以下场景:你必须决定特斯拉的股票是否会上涨,并且你可以接触到十几名事先对该公司一无所知的分析师。每个分析师都有较低的偏见,因为他们没有任何假设,并且可以从新闻报道的数据集中学习。
这似乎是一种理想的情况,但问题是,除了真实的信号之外,报告很可能包含噪声。因为分析师的预测完全基于数据——他们有很高的灵活性——他们会被不相关的信息左右。分析师可能会从同一数据集得出不同的预测。此外,每个分析师都有很高的方差,如果给他们一套不同的训练报告,他们会得出截然不同的预测。
解决方案是不要依赖任何一个人,而是集中每个分析师的投票。此外,像在随机森林中一样,允许每个分析师只访问报告的一部分,并希望噪声信息的影响将被抽样抵消。在现实生活中,我们依赖于多个来源(永远不要相信一个单独的亚马逊评论),因此,不仅决策树是直观的,而且在随机森林中组合它们的想法也是如此。
实践中的随机森林
接下来,我们将使用 Scikit-Learn 在 Python 中构建一个随机森林。我们不是学习一个简单的问题,而是使用一个分成训练集和测试集的真实数据集。我们使用测试集来评估模型在新数据上的表现,这也让我们可以确定模型过度拟合的程度。
资料组
我们要解决的问题是一个二元分类任务,目标是预测个人的健康状况。这些特征是个人的社会经济和生活方式特征,标签为健康不佳的0和健康良好的1。该数据集由疾病控制和预防中心收集,可在获得。
Sample of Data
一般来说,数据科学项目的 80%都花在清理、探索和创建数据特征上。然而,对于本文,我们将坚持建模。(其他步骤详见本文)。
这是一个不平衡的分类问题,因此准确度不是一个合适的度量。相反,我们将测量曲线 (ROC AUC)下的接收器操作特征面积,这是一个从 0(最差)到 1(最好)的测量值,随机猜测得分为 0.5。我们也可以绘制 ROC 曲线来评估模型。
笔记本包含了决策树和随机森林的实现,但是这里我们只关注随机森林。读入数据后,我们可以实例化并训练一个随机森林,如下所示:
经过几分钟的训练后,模型可以对测试数据进行预测,如下所示:
我们进行类别预测(predict)和预测概率(predict_proba)来计算 ROC AUC。一旦我们有了测试预测,我们就可以计算 ROC AUC。
结果
随机森林的最终测试 ROC AUC 为 0.87 ,相比之下,具有无限最大深度的单一决策树的 ROC AUC 为 0.67 。如果我们查看训练分数,两个模型都达到了 1.0 ROC AUC,这也是预期的,因为我们给了这些模型训练答案,并且没有限制每个树的最大深度。
虽然随机森林过拟合(在训练数据上比在测试数据上做得更好),但它能够比单个决策树更好地概括测试数据。随机森林具有较低的方差(好),同时保持决策树的低偏差(也是好的)。
我们还可以绘制单一决策树(顶部)和随机森林(底部)的 ROC 曲线。向左上方的曲线是更好的模型:
Decision Tree ROC Curve
Random Forest ROC Curve
随机森林明显优于单决策树。
我们可以采取的模型的另一个诊断措施是绘制测试预测的混淆矩阵(详见笔记本):
这在左上角和右下角显示了模型得到的正确预测,在左下角和右上角显示了模型错过的预测。我们可以使用这样的图来诊断我们的模型,并决定它是否足够好,可以投入生产。
特征重要性
随机森林中的特征重要性表示在该特征上分割的所有节点上基尼系数杂质减少的总和。我们可以用这些来试着找出随机森林认为最重要的预测变量。可以从经过训练的随机森林中提取特征重要性,并将其放入 Pandas 数据帧中,如下所示:
通过告诉我们什么样的变量在类之间是最有辨识力的,特征重要性可以给我们对问题的洞察力。例如,这里的DIFFWALK, 表示患者是否行走困难,这是在问题上下文中有意义的最重要特征。
通过从最重要的要素构建附加要素,要素重要性可用于要素工程。我们也可以通过移除低重要性特征来使用特征重要性进行特征选择。
可视化森林中的树
最后,我们可以想象森林中的一棵决策树。这一次,我们必须限制树的深度,否则它会太大而无法转换成图像。为了制作下图,我将最大深度限制为 6。这仍然会产生一棵我们无法完全解析的大树!然而,考虑到我们对决策树的深入研究,我们掌握了我们的模型是如何工作的。
Single decision tree in random forest.
后续步骤
下一步是优化随机森林,我们可以使用 Scikit-Learn 中的[RandomizedSearchCV](http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html) 通过随机搜索来实现。优化是指在给定数据集上为模型寻找最佳超参数。最佳超参数会因数据集而异,因此我们必须对每个数据集分别执行优化(也称为模型调整)。
我喜欢把模型调整看作是为机器学习算法寻找最佳设置。我们可以在随机森林中优化的示例包括决策树的数量、每个决策树的最大深度、分割每个节点时考虑的最大特征数量以及叶节点中所需的最大数据点数量。
关于随机森林模型优化的随机搜索的实现,请参考 Jupyter 笔记本。
完整的运行示例
下面的代码是用 repl.it 创建的,展示了一个完整的 Python 中随机森林的交互式运行示例。请随意运行并更改代码(加载包可能需要一些时间)。
Complete Python example of random forest.
结论
虽然我们可以在不了解任何东西的情况下用 Python 构建强大的机器学习模型,但我发现了解幕后发生的事情更有效。在本文中,我们不仅用 Python 构建并使用了一个随机森林,而且还从基础开始,加深了对该模型的理解。
我们首先查看了一个单独的决策树,即随机森林的构建块,然后查看了如何通过将数百个决策树组合成一个称为随机森林的集合模型来克服单个决策树的高方差。随机森林使用观察值的随机采样、要素的随机采样和平均预测的概念。
本文中需要理解的关键概念是:
- 决策树:基于一系列关于特征值的问题做出决策的直观模型。具有导致过度拟合训练数据的低偏差和高方差。
- 基尼系数:决策树在分割每个节点时试图最小化的一种度量。表示根据样本在节点中的分布,从节点中随机选择的样本被错误分类的概率。
- Bootstrapping :用替换法对随机观测值集进行抽样。
- 随机特征子集:当考虑决策树中每个节点的分裂时,选择一组随机特征。
- 随机森林:由许多决策树组成的集成模型,使用自举、随机特征子集和平均投票进行预测。这是一个装袋合奏的例子。
- 偏差-方差权衡:机器学习中的一个核心问题,描述了一个具有高灵活性(高方差)的模型和一个不灵活的模型(高偏差)之间的平衡,前者可以很好地学习训练数据,但代价是不能推广到新数据,后者不能学习训练数据。随机森林减少了单个决策树的方差,从而对新数据进行更好的预测。
希望这篇文章已经给了您开始在您的项目中使用 random forest 所需的信心和理解。随机森林是一个强大的机器学习模型,但这不应该阻止我们了解它是如何工作的。我们对一个模型了解得越多,我们就越有能力有效地使用它,并解释它是如何做出预测的。
一如既往,我欢迎评论、反馈和建设性的批评。可以在推特上找到我。本文最初发表在研究机器学习的开源社区 enlight 上。我要感谢 enlight 和 repl.it 在文章中提供代码。
使用 NumPy 和 Google Sheets 的 Word2Vec 实现指南
了解 Word2Vec 的内部工作原理
本文是使用 NumPy 和 Google Sheets 实现 Word2Vec 的指南。如果你读这篇文章有困难,可以考虑在这里订阅中级会员!
Word2Vec 被誉为自然语言处理(NLP)领域最大、最新的突破之一。这个概念简单、优雅且(相对)容易掌握。快速的谷歌搜索会返回多个关于如何使用标准库的结果,比如 Gensim 和 TensorFlow 。此外,出于好奇,请查看 Tomas Mikolov 使用 C 的原始实现。原文可以在这里找到。
本文的重点是详细介绍 Word2Vec。为此,我使用 NumPy 在 Python 上实现了 Word2Vec(在其他教程的帮助下),还准备了一个 Google 工作表来展示计算。以下是代码和谷歌表单的链接。
Fig. 1 — Step-by-step introduction to Word2Vec. Presented in code and Google Sheets
直觉
Word2Vec 的目标是为进一步的 NLP 任务生成带有语义的单词的向量表示。每个单词向量通常有几百个维度,并且语料库中的每个唯一单词被分配一个空间向量。例如,单词“happy”可以表示为 4 维向量[0.24,0.45,0.11,0.49],“sad”具有向量[0.88,0.78,0.45,0.91]。
单词到向量的转换也称为 单词嵌入 *。*之所以要进行这样的转换,是为了让机器学习算法可以对数字(在向量中)而不是单词进行线性代数运算。
要实现 Word2Vec,有两种风格可供选择— 连续词包(CBOW) 或连续跳格(SG) 。简而言之,CBOW 试图从其相邻单词(上下文单词)中猜测输出(目标单词),而连续跳格从目标单词中猜测上下文单词。实际上,Word2Vec 是基于分布假设的,其中每个单词的上下文都在它附近的单词中。因此,通过查看它的相邻单词,我们可以尝试预测目标单词。
根据 Mikolov 的说法(在这篇文章的中引用),Skip-gram 和 CBOW 的区别如下:
***Skip-gram:***好用的 用 少量的训练数据 ,甚至代表好用的 生僻字 或词组
CBOW: 数倍于比【skip-gram】*精度稍好 *为频繁* 单词***
更详细地说,由于 Skip-gram 学习从给定单词预测上下文单词,在两个单词(一个不经常出现,另一个更频繁出现)并排放置的情况下,当涉及到最小化损失时,两者将具有相同的处理,因为每个单词将被视为目标单词和上下文单词。与 CBOW 相比,不常用的单词将只是用于预测目标单词的上下文单词集合的一部分。因此,该模型将为不常用的单词分配低概率。
Fig. 2 — Word2Vec — CBOW and skip-gram model architectures. Credit: IDIL
实现进程
在本文中,我们将实现 Skip-gram 架构。为了便于阅读,内容分为以下几个部分:
- 数据准备 —定义语料库,清理、规范化和分词
- 超参数 —学习率、时期、窗口大小、嵌入大小
- 生成训练数据 —构建词汇,对单词进行一次性编码,构建将 id 映射到单词的字典,反之亦然
- 模型训练 —通过正向传递传递编码的字,计算错误率,使用反向传播调整权重并计算损失
- 推理 —获取词向量,寻找相似词
- 进一步改进 —通过跳过 gram 负采样(SGNS)和分层 Softmax 加快训练时间
1.数据准备
首先,我们从以下语料库开始:
自然语言处理和机器学习既有趣又令人兴奋
为了简单起见,我们选择了一个没有标点符号和大写字母的句子。此外,我们没有删除停用词“和”和“是”。
在现实中,文本数据是非结构化的,可能是“脏的”。清理它们将涉及诸如删除停用词、标点符号、将文本转换为小写(实际上取决于您的使用情况)、替换数字等步骤。KDnuggets 有一篇关于这个过程的优秀文章。或者,Gensim 还提供了一个使用[gensim.utils.simple_preprocess](https://radimrehurek.com/gensim/utils.html#gensim.utils.simple_preprocess)执行简单文本预处理的函数,它将文档转换成一系列小写标记,忽略太短或太长的标记。
在预处理之后,我们继续对语料库进行标记。这里,我们在空白上标记我们的语料库,结果是一个单词列表:
【“自然”、“语言”、“处理”、“和”、“机器”、“学习”、“是”、“有趣”、“和”、“令人兴奋”】
2.超参数
在我们进入实际实现之前,让我们定义一些我们稍后需要的超参数。
[window_size]:如上所述,上下文单词是与目标单词相邻的单词。但是这些词应该有多远或多近才能被认为是邻居呢?这就是我们将window_size定义为 2 的地方,这意味着在目标单词左右 2 的单词被认为是上下文单词。参考下面的图 3,注意,当窗口滑动时,语料库中的每个单词都将是目标单词。
FIg. 3 — With a window_size of 2, the target word is highlighted in orange and context words in green
[n]:这是单词嵌入的维度,通常在 100 到 300 之间,取决于你的词汇量。尺寸大小超过 300 往往会使收益递减(参见第 1538 页图 2 (a))。请注意,尺寸也是隐藏层的大小。
[epochs]:这是训练纪元的数目。在每个时期,我们循环所有的训练样本。
[learning_rate]:学习率控制相对于损失梯度的权重调整量。
3.生成培训数据
在这一节中,我们的主要目标是将我们的语料库转换成用于训练 Word2Vec 模型的一次性编码表示。从我们的语料库中,图 4 放大了 10 个窗口(#1 到#10),如下所示。每个窗口由目标单词及其上下文单词组成,分别以橙色和绿色突出显示。
Fig. 4 — One-hot encoding for each target word and its context words
第一个和最后一个训练窗口中的第一个和最后一个元素的示例如下所示:
# 1【目标( 自然 )】、【上下文(语言、处理)】 【列表()【1,0,0,0,0,0,0,0】** 列表(【0,1,0**
**** * * * * * # 2 至#9 删除*******
#10【目标( 精彩 )】、【上下文(趣味、、)【列表()【0,0,0,0,0,0,1】) 列表(
为了生成一次性训练数据,我们首先初始化word2vec()对象,然后通过传递settings和corpus作为参数,使用对象w2v调用函数generate_training_data。
在函数generate_training_data中,我们执行了以下操作:
self.v_count—词汇长度(注意,词汇是指语料库中唯一词的数量)self.words_list—词汇表中的单词列表self.word_index—以词汇中的每个关键字为词,以值为索引的字典self.index_word—字典,每个关键字作为索引,值作为词汇中的单词for循环使用word2onehot函数将每个目标及其上下文单词的一键表示追加到training_data。
4.模特培训
Fig. 5 — Word2Vec — skip-gram network architecture
用我们的training_data,我们现在准备训练我们的模型。训练从w2v.train(training_data)开始,我们传入训练数据并调用函数train。
Word2Vec 模型由两个权重矩阵(w1和w2)组成,出于演示目的,我们已经将值分别初始化为(9x10)和(10x9)的形状。这有助于计算反向传播误差,这将在本文后面讨论。在实际训练中,您应该随机初始化权重(例如使用np.random.uniform())。为此,注释第 9 行和第 10 行,取消第 11 行和第 12 行的注释。
训练—向前传球
接下来,我们开始使用第一个训练示例来训练我们的第一个纪元,方法是将代表目标词的一键向量的w_t传递给forward_pass函数。在forward_pass函数中,我们在w1和w_t之间执行点积以产生h(第 24 行)。然后,我们使用w2和h执行另一个点积来产生输出层u(第 26 行)。最后,我们运行u到 softmax 来强制每个元素在 0 和 1 的范围内,从而在返回预测矢量y_pred、隐藏层h和输出层u之前给出我们预测的概率(第 28 行)。
我附上了一些截图,以显示第一个窗口(#1)中第一个训练样本的计算,其中目标词是“自然”,上下文词是“语言”和“处理”。请随意查看谷歌表单中的公式。
Fig. 6— Calculate hidden layer, output later and softmax
训练——错误、反向传播和损失
误差— 利用y_pred、h和u,我们继续计算这组特定目标和上下文单词的误差。这是通过总结y_pred和w_c中每个上下文单词之间的差异来完成的。
Fig. 7 — Calculating Error — context words are ‘language’ and ‘processing’
反向传播 —接下来,我们使用反向传播函数backprop,通过传入误差EI、隐藏层h和目标词w_t的向量,计算我们需要使用函数backprop改变权重的调整量。
为了更新权重,我们将待调整的权重(dl_dw1和dl_dw2)乘以学习率,然后从当前权重(w1和w2)中减去它。
Fig. 8 — Backpropagation — Calculating delta for W1 and W2
Fig. 9 — Backpropagation — Adjusting weights to get updated W1 and W2
损失 —最后,我们根据损失函数计算每个训练样本完成后的总损失。注意损失函数由两部分组成。第一部分是输出层中所有元素总和的负值(在 softmax 之前)。第二部分获取上下文单词的数量,并乘以输出层中所有元素的和的对数(在指数之后)。
Fig. 10 — Loss function for Word2Vec skip-gram. Credit: arxiv.org/pdf/1411.27…
5.推理
现在我们已经完成了 50 个纪元的训练,两个权重(w1和w2)现在都准备好执行推理。
获取单词的向量
有了一组训练好的权重,我们可以做的第一件事就是查看词汇表中某个单词的单词向量。我们可以简单地通过对照训练的权重来查找单词的索引(w1)来做到这一点。在下面的例子中,我们查找单词“machine”的向量。
**> print(w2v.word_vec("machine"))[ 0.76702922 -0.95673743 0.49207258 0.16240808 -0.4538815 -0.74678226 0.42072706 -0.04147312 0.08947326 -0.24245257]**
查找相似的单词
我们可以做的另一件事是找到相似的单词。即使我们的词汇量很小,我们仍然可以通过计算单词之间的余弦相似度来实现函数vec_sim。
**> w2v.vec_sim("machine", 3)machine 1.0
fun 0.6223490454018772
and 0.5190154215400249**
6。进一步改进
如果你还在读这篇文章,干得好,谢谢你!但这并不是结束。您可能已经注意到,在上面的反向传播步骤中,我们需要调整训练样本中未涉及的所有其他单词的权重。如果你的词汇量很大(例如几万个),这个过程会花费很长时间。
为了解决这个问题,下面是 Word2Vec 中的两个特性,您可以实现它们来加快速度:
- Skip-gram Negative Sampling(SGNS)有助于加快训练时间,提高生成的单词向量的质量。这是通过训练网络仅修改一小部分权重而不是所有权重来实现的。回想一下上面的例子,我们每隔一个单词更新一次权重,如果 vocab 的大小很大,这将花费很长的时间。使用 SGNS,我们只需要更新目标词和少量(例如 5 到 20 个)随机“负面”词的权重。
- 分级 Softmax 也是另一个加快训练时间的技巧,取代了原来的 Softmax。主要思想是,不需要评估所有的输出节点来获得概率分布,我们只需要评估它的大约 log(以 2 为基数)。它使用二叉树(霍夫曼编码树)表示,其中输出层中的节点表示为树叶,其节点表示为与其子节点的相对概率。
Fig. 11 — Hierarchical Binary Tree — Path from root to W2 is highlighted
除此之外,为什么不尝试调整代码来实现连续词袋(CBOW)架构呢?😃
结论
本文是对 Word2Vec 和 Word 嵌入世界的介绍。同样值得注意的是,有预先训练好的嵌入可用,如 GloVe 、 fastText 和 ELMo 可以直接下载使用。还有 Word2Vec 的扩展比如 Doc2Vec 和最近的 Code2Vec 其中文档和代码被转化为向量。😉
最后,我要感谢任杰谭、莱米和庾信花时间评论和阅读本文的草稿。💪
注:本文首发于我的博客https://derekchia . com/an-implementation-guide-to-word 2 vec-using-numpy-and-Google-sheets/
参考
** [## nathan rooy/word 2 vec-用 python 从头开始
用 Python 从头开始实现了一个非常简单、简单、低效的 skip-gram word2vec
github.com](github.com/nathanrooy/…) [## 用 Python 和 NumPy 从头开始 Word2vec
TL;DR - word2vec 很牛逼,也真的很简单。了解它是如何工作的,并实现您自己的版本。自从加入…
nathanrooy.github.io](nathanrooy.github.io/posts/2018-…) [## word2vec 为什么最大化语义相似词之间的余弦相似度
感谢您为交叉验证提供答案!你过去的一些回答不太受欢迎,你…
stats.stackexchange.com](stats.stackexchange.com/questions/3…) [## 分层软最大值和负采样:值得讲述的简短笔记
感谢观众对我上一篇(也是唯一一篇)帖子的意外和愉快的关注,这篇帖子是献给…
towardsdatascience.com](/hierarchical-softmax-and-negative-sampling-short-notes-worth-telling-2672010dbe08)**
吴恩达深度学习(deeplearning.ai)专业化的深度回顾
You can find a video version of this article on my YouTube.
所以你已经看到了最近关于人工智能(AI)如何改变一切的新闻。然而,AI 的想法由来已久。几十年来,像人类一样思考和说话的机器一直是电影和故事的灵感来源。
但是交易是什么?为什么这几年 AI 越来越好?
最近繁荣的主要驱动力之一是新技术与可靠的真实想法的融合。进入深度学习。
句子中的深度学习:从信息源中分层提取特征。
这个定义会根据你看的地方而变化,但是现在,它已经足够了。
深度学习利用多层神经网络将信息从输入源抽象到更结构化的输出源。这里的关键词是多层。
The ‘deep’ in deep learning refers to neural networks with multiple internal layers.
神经网络的想法从 20 世纪 40 年代就已经存在了。那么,为什么它们最近才出现如此大的回潮呢?
两个原因。
1.更多数据。 2。更强的计算能力。
对于深度学习系统来说,要从大量信息中收集切实的见解,需要有大量的信息(尽管人们正在积极努力解决这个问题)。世界各地都在通过文本、视频和音频转换成数据。我们在过去 5 年里记录的信息比人类历史上所有的信息都多。
好吧,酷。我们比以往拥有更多的数据。但是我家里有一书架的书,光坐在那里不会让我变得更聪明。我必须读它们来了解里面的内容。
这就是更多计算能力发挥作用的地方。我们的带宽有限。我们只能以一定的速度阅读。一本好书可能需要一个月或更长时间才能看完。
即使有地球上所有的人脑,我们也不可能处理我们收集的所有数据。
计算机来拯救我们!
计算硬件和可访问性的突破使得我们通过深度学习收集的所有额外信息变得比以往任何时候都更容易。使用我们的笔记本电脑,你和我现在可以加载到一个计算机仓库的接入点,所有这一切都可以在我们最喜欢的躺椅上舒适地进行。
突然之间,如果我们有一个大数据集,我们想从中收集见解,我们可以做过去需要 1000 个小时(可能几年)才能睡个好觉的事情(有些事情需要更长一点时间)。
好了,技术概述到此为止。所以你对学习深度学习感兴趣?好吧,这篇文章就是来帮忙的。这是目前你能获得的最好的深度学习课程之一的概述。
说真的,如果你想节省自己的时间,现在就去 Coursera 搜索“深度学习”,选择deep learning . ai specialization并加入其中。
还在吗?太好了。先说为什么。
为什么要报名 deeplearning.ai specialisation?
你可能已经体验过深度学习的一些结果了。也许自己都不知道。
脸书的照片标记系统使用它。它们的面部识别能力和人类一样好。
谷歌的所有(或接近)产品都使用它。
随着时间的推移,你的智能手机可能会使用它的一个版本来提高电池寿命。
优步用它来确保你在正确的时间和正确的司机联系。
但是随着我们关于世界的信息量的增加,深度学习的用例也在增加。
律师用它来找出如何对法律案件做出更好的决定,房地产经纪人用它来更好地给房子定价,医生用它来帮助他们做出更好的诊断。
课程讲师吴恩达将人工智能称为新的电力。
人工智能是新的电力。—吴恩达
目前,人工智能仅限于我们的智能手机和智能扬声器,但很快,它将被注入到我们与之互动的一切事物中。就像现在一样,大部分都在幕后。
deeplearning.ai 专业致力于教你最先进的技术以及如何自己构建它们。
如果你是一名软件开发人员,想要建立深度学习模型,或者你有一点编程经验,想要做同样的事情,那么这门课程就是为你准备的。
如果你只是想了解一些用例,以及它会如何影响你的行业,我会去别处看看。
深度学习和机器学习技能很受欢迎。如果你像我一样,正在寻求职业改变,本课程将帮助你踏上这条道路。
不管你有什么理由。开始前确保你有一个。把它写下来,当学习变得困难时,它会给你一些参考。它会提醒你为什么开始。
你需要从什么开始,你会学到什么?
你已经知道为什么了。你想建立影响世界的技术。或者您希望从您的业务数据中收集更好的见解。或者你想要一份新工作。太好了。这些都是合理的理由。
有理由是第一步。现在,你需要从什么开始?
前提条件是什么?
课程页面列出了编程经验以及数学和机器学习的基础知识作为先决条件。
Python 是这门课程和许多深度学习的首选语言。因此,如果你至少有几个月的 Python 经验,或者对其他编程语言和意识形态有经验,你应该处于一个很好的位置。
至于数学,除了高中,我从来没有上过数学课。如果我需要为这门课学习一些数学,我会去可汗学院。
课程中涉及的一些数学话题(全部链接到可汗学院)。
在开始课程之前,这些我都没有深入了解。主要讲师吴恩达做了大量的数学解释,足以让你在课堂上开始。对于更深入的内容,你会发现上面的链接很有帮助。
至于机器学习经验,在开始之前,我已经完成了 Coursera 上的 Andrew 的机器学习课程。100%需要吗?不。但它确实对一些概念有帮助。这个课程是免费的,但它是在 Matlab/Octave 中完成的,我发现这有点难,因为我已经习惯了 Python。
总的来说,如果你接受过高中数学教育,并且习惯于用 Python 编写几行函数,那么你已经有足够的东西可以开始了。
所以你准备好开始了。史诗。你实际上会学到什么?
这门课程分为五个部分。每一个都可以单独完成,但我发现它们是对彼此的很好的补充。
每个部分的时间分配在 2-4 周之间不等,建议每周学习 4-5 小时。我通常可以在一天 6-8 小时内完成一周的课程和评估,包括休息时间。也就是说,整个课程花了我大约 4-5 周的时间。
第 1 部分:神经网络和深度学习
本节介绍神经网络和深度学习的概念。有点像这篇文章的介绍,但有实际的代码和更多的深度。
您将从头开始构建自己的神经网络,并了解 Python 的数值库 NumPy。
白手起家是什么意思?
从头开始不需要使用任何框架。想象一个框架是别人写的代码的集合,它使你写的代码更小(更少的行)。一些流行的深度学习框架有 Keras、TensorFlow 和 PyTorch。每当你看到一篇标题为“11 行代码的最佳结果”的文章时,这篇文章可能会用到这些框架中的一个。
同样的 11 行代码在 NumPy/pure Python 中可能会变成 50 多行。第一部分将带您浏览完整的 50 行代码,以了解框架在幕后做了什么。
第 2 部分:改进深度神经网络:超参数调整、正则化和优化
深度学习通常被称为黑盒,意思是,你的模型学习东西,但你不太确定它是如何学习的。
这样做的问题是,如果你的模型不像你希望的那样工作,就很难改进它。
通过第 2 部分,您将了解常见的深度学习花絮,如超参数调整、初始化、优化、小批量梯度下降和正则化。
哇哦。慢点。这些术语是什么?
现在,只要把它们看作是最大限度地利用你的神经网络的方法。
您还将体验到将数据集分成训练集、验证集和测试集的感觉。训练集是你的神经网络学习的地方,验证和测试集是你可以测试你的网络对看不见的数据的鲁棒性。
第 1 部分从 Python 和 NumPy 开始,第 2 部分将向您展示最流行的深度学习库之一 TensorFlow。
好了,现在你知道了如何构建自己的深度神经网络,并且你对自己想要从事的一些项目有了一些想法。但是怎么做呢?第 3 部分支持你。
第 3 部分:构建机器学习项目
这一节很大,不是就长度而言,而是就实用性而言。能够构建机器学习系统是一回事,但能够在它们出现问题时进行诊断并加以改进以供未来使用则是另一回事。
第 3 部分介绍了两个案例研究。你被放在驾驶座上,决定如何使用深度学习系统来解决他们内部的问题。或者如何改进当前的深度学习系统。
我见过一些团队因为不理解本课程中教授的原则而浪费了几个月或几年的时间。—吴恩达
课程二和课程三对于 deeplearning.ai 专业来说是非常独特的。我还没见过很多其他课程像安德鲁那样谈论这些话题。
第 4 部分:卷积神经网络
当谈到计算机视觉时,卷积神经网络(CNN)是蜜蜂的膝盖。
深度学习带来了面部识别方面令人难以置信的进步(还记得脸书的面部识别吗?),对 x 光报告和自动驾驶汽车系统(如特斯拉的 autopilot)进行分类。
在第一周,你将学习构成卷积神经网络的所有部分,然后进行编程作业,一步一步地构建你自己的模型。
在接下来的三周里,Andrew 将向您展示如何将您在第一周制作的 CNN 带入深度卷积模型(添加更多层)。正是从这里,你将接触到 Keras,一个建立在库 TensorFlow 之上的深度学习框架。
您将练习实现深度 CNN,例如 YOLOv2 算法来检测图像和视频中的对象。你甚至可以上传你自己的图片,我对此很感兴趣。
最后一个项目包括建立一个面部识别系统,只允许微笑的人进入你的家。如果你要举办一个派对,把这个变成现实可能会很方便。
在第 4 部分之后,您现在将知道如何让计算机看到。但是如果你有一堆音频数据呢?文字呢?CNN 可用于此,但序列模型是首选。
第 5 部分:序列模型
你在西班牙。你喝了太多西班牙葡萄酒。现在你需要找到一个浴室,但你不会说一句西班牙语。别担心,你在谷歌翻译中调出你的手机类型“请到洗手间”。你找到离你最近的人,指着你的手机。按下麦克风按钮,你的手机会显示“Bao por favor”。你的新西班牙朋友微笑着指给你看街道。
这整个互动是由葡萄酒和深度学习推动的。谷歌的翻译只是使用深度序列模型的产品的一个例子。
序列模型是一种接受发生在一个时间序列上的任何类型的数据的模型。想想一段时间内的音频波或一个句子中的单词。
您将开始逐步了解递归神经网络,这是一种流行的序列模型。然后你将使用长短期记忆细胞(LTSM 氏)来建立你自己的爵士乐即兴演奏模型。我从来不擅长演奏乐器,但由于深度学习,我能够教计算机为我演奏一首爵士乐独奏。
接下来,您将讨论自然语言处理(NLP)。您将学习如何用数字表示单词,然后如何训练递归神经网络来理解它们。计算机对数字的理解远胜于文字。
最后,Andrew 将带您了解 RNN 在语音识别和触发单词检测中的应用。这两项技术让我们可以说‘嘿,Siri,帮我找一下去最近的咖啡馆的方向。’“嘿,Siri”是触发词,将空气中的声波转化为你的 iPhone 可以理解的东西(一系列数字)的整个过程就是语音识别。
深度学习正在让计算机更好地识别语音和自然语言,但仍有很多改进的空间。与 Alexa 或 Google Home 的任何互动超过几个基本句子和对话就开始中断。这类问题使得 NLP 成为深度学习研究中最令人兴奋的领域之一。
评价
在每周讲座结束时,会有一个测验和与你上周所学内容相关的编程作业。
作业存放在 Jupyter 笔记本上,与课程所在的网页浏览器相同。Jupyter 笔记本是许多不同类型的编码项目的漂亮界面,尤其是数据科学和深度学习。在浏览器中完成评估的一个好处是评分几乎是即时的。你可以直接看到哪里出错了。
每项评估都有一个 80%的门槛。作业或测验不及格?没问题。每 8 小时你有 3 次提交的机会。如果你一直失败,休息一会儿再回来。
我不能分享每个作业中的代码,因为这违反了课程指南。没有代码可以在论坛或其他在线资源上共享。但是,您可以在论坛上使用伪代码(与您的问题类似但不会透露确切细节的代码)提问。
临时演员
对于专业化的前半部分,在每周课程结束时,会对深度学习超级英雄进行采访。安德鲁与 Yann LeCun 和 Geoffrey Hinton 等人坐下来讨论深度学习的现状和该领域的发展方向。这些采访是课程中我最喜欢的部分之一。
从哪里可以学到?
好吧,你知道为什么你想研究深度学习,你会学到什么,但你去哪里找到所有这些美丽的信息?
视频和讲座
所有的视频采访和讲座都可以在 deeplearning.ai YouTube 频道上免费获得。
评估和课程论坛
要访问课程论坛和评估,您需要在 Coursera 上注册。
任何你想去的地方
在线学习的美妙之处在于你可以在任何地方学习。你需要一台能上网的电脑来进行评估,但你可以通过 Coursera 的移动应用程序离线观看视频讲座。
如果你是一个优秀的自学者,在线学习可能对你来说是完美的。我大部分时间都是一个人在寝室学习。但是,如果你更喜欢在一个小组中学习,你可能想说服你的一些朋友和你一起努力深入学习。
你什么时候能学会?
就像网飞一次发布整季一样,当你报名参加课程时,你不必等着获取资料。如果你想的话,你可以在 3 天的马拉松中完成。如果你这样做了,我会印象深刻,但是睡眠确实有助于巩固你所学的东西。
每隔几周就会有新的一批开始。你可以随时开始,但是如果你选择了其中的一天,你将会有全世界的人和你一起学习。这是有帮助的,因为这意味着论坛将会有人在你提问和回答的同时提问和回答。
怎么学?
你已经知道细节了。你知道什么时候开始,你知道你要学什么,现在你该怎么做?
这个没有正确的答案。对我有效的不一定对你有效。
我用特雷罗来追踪我的进度。Trello 是一个免费的应用程序,可以帮助你可视化你的计划。在开始上课之前,我在黑板上画出了课程表。
这是一个示例板的样子。
You can view a public version of the full board here.
在最左边,你会有你需要访问的资源。以下栏目包含您尚未完成的部分课程。
第 2 部分在做栏,因为这是你目前正在做的事情。第一部分被移到完成栏,因为你已经完成了。
Within each part, you have a list of the lectures and assessment items you need to complete and tick them off as you go.
Trello 帮助我想象我已经做了什么和我下一步需要做什么。预产期也有助于我与其他同学保持同步。
你必须遵循时间线吗?
不。你可以想多快就多慢。您将获得评估到期日的更新提醒,但这不是强制性的,它们更多的是为了让您受到鼓励并走上正轨。
从长远来看,我在大约 4-5 周内完成了课程,每周学习 3-4 天,每天学习 6-8 小时。
你如何获得帮助?
很可能你最终会在编程作业中遇到问题。或者也许你想知道更多关于某个话题。当这发生时,论坛是你的朋友。
由于该课程已经推出了几个月,因此有一堆问题已经得到了解答。快速搜索你的问题通常会发现一些学生有类似的问题。
如果你的问题没有得到回答,不要害怕寻求帮助。不管你认为你的问题有多没意义,它仍然是一个问题。过去认为我的问题很愚蠢阻碍了我的学习。现在我意识到,认为你的问题是愚蠢的,是愚蠢的。
当你问一个问题的时候,尽可能的清晰。大声读出来,看看有没有意义。我经常被一个问题困扰,忘记清楚地表达自己,这降低了我被帮助的机会。
这要花多少钱?
你可以在 YouTube 上免费观看所有的课程讲座。但是如果你在 Coursera 上注册完全专业化,费用是每月 64 澳元(约 47 美元)。
完整的专业化建议需要 4-5 个月完成,但因为我完成得更快,我只支付了 2 个月的费用(总共 128 澳元)。
Coursera 经常提供他们专业的 7 天试用期。所以你可以注册,看看这个课程是否适合你,如果不适合,取消你的订阅。
有资格的人可以得到经济资助。要获得这个,你必须在课程报名时申请。
内容的结构是怎样的?
专业化分为五个部分。每一部分都分为 2-4 周的讲座和评估。
讲座时长从 5 分钟到 20 分钟不等,平均每次 10 分钟左右。
我发现我可以用 1.5 倍的速度在 3 小时内听完一周的课。
Andrew 使用 keynote 和画外音来教授内容。他在讲话时经常会在幻灯片上做注解,以进一步阐明观点。我真的很喜欢这种教学风格。
An example lecture slide. The blue writing was annotated alongside Andrew’s voice over.
你如何完成课程?
在每周内容的最后,有一个测验和一个编程作业。一旦你完成了某个部分的所有测验和编程作业,你就可以查看你的竞赛证书了。
完成专业化的所有五个部分意味着你将获得 Coursera 颁发的结业证书。这为你的 LinkedIn 个人资料增添了一个新的亮点。不要害怕分享,你为此付出了努力。
您可以在多长时间内访问这些内容?
无限期。这些讲座在 YouTube 上,我仍然可以在 Coursera 上访问这些讲座,尽管我不再为专业化付费了。
至于评估,我发现在完成一个编程任务后很难回到 Jupyter 笔记本上,所以我确保在工作时下载它们以供将来参考。
摘要
在我学过的所有课程中,这是迄今为止最好的课程之一。Andrew 是一名实践者,他在每堂课中编织他从经验中获得的知识。他参与了这场游戏,所以你知道你所学到的已经付诸实践了。
有时很困难。我遇到了很多障碍。但是有了论坛和互联网,我知道只要我有耐心,我就能解决问题。
我最喜欢的两个部分是第 3 部分和第 5 部分。任何与语言和交流有关的东西都让我着迷,所以第 5 部分是一个真正的亮点。很高兴在第 3 部分听到 Andrew 关于如何从机器学习项目中获得最大收益的内部智慧。
接下来呢?
哇哦。你做到了。恭喜你。你通过了课程。但你总是会的,只是需要一点努力。
一切似乎都很模糊。
“我真的学到什么了吗?”我问我自己当我完成的时候。
这门课程充满了知识。我发现自己在第 5 部分提出的问题在第 2 部分的讲座中得到了回答。但是没关系。我只记得我所学的 1%,所以回顾一些东西有助于在我的大脑中重建更强的联系。
现在我知道,当我遇到深度学习问题时,我可以参考讲座并刷新我的记忆。但我也知道这个领域发展的速度有多快,讲座中的内容可能会过时。这就是补充学习的用武之地。
我发现在完成 deeplearning.ai 专业化的同时完成 Udacity 和 fast.ai 的其他一些深度学习课程非常有帮助。一个过程失败了,另一个过程就开始了,反之亦然。
完成专业化只是新的学习旅程的开始。
无论是将你新发现的技能应用到你自己的项目中,还是用它们来改进现有的项目,都意味着你可能需要不断学习。最终,你会遇到一些你必须自己寻找答案的事情。
如果你做了什么,一定要分享你的作品,写一篇博文,或者制作一个关于它的视频。这样你就可以练习交流你学到的技能,如果你的项目需要改进,其他人可以提供他们的建议。
活着是令人激动的时刻。人工智能被证明是历史上最具影响力的技术之一。深度学习是许多最新进展的一个重要原因,并且可能会有更多进展。
所以,如果你想加入并驾驭社会的潮流,那就去学习吧。或者更好的是,在 Coursera 上注册参加deep learning . ai specialization,获得深度学习。
喜欢你读的书吗?如果你更喜欢视觉效果,我的 YouTube 上有一个视频版本。
我完成了这门课程,作为我自己的人工智能硕士学位的一部分。
彼得·沃斯访谈
人工通用智能 (AGI)是一个新兴领域,旨在建造“思考机器”;即智能堪比人脑的通用系统。目前被贴上‘人工智能’标签的很大程度上是狭义的自动化知识工作,缺乏动物智能中所见的灵活性和适应性。对 AGI 的追求始于基础层面,提出关于认知模型、知识获取、通过理性做出选择、以适应性和直觉的方式思考和构想世界的基本问题。
南加州 AGI 研究员彼得·沃斯访谈。
彼得的第一份职业和爱好是电子工程。25 岁时,他创办了自己的第一家公司 Electronic Designs,在 7 年内上市,成为一家拥有 400 名员工的软件/硬件解决方案公司。Peter 设计了该公司的 ERP 套件,包括其第四代数据库和编程语言。在担任首席执行官/董事长期间,以及通过开发和销售 ERP 软件,他获得了财务和管理方面的丰富专业知识。
从公司退休后,Peter 花了几年时间研究与高级人工智能相关的各种主题:这些主题包括认知心理学、心理测量学、认识论、神经网络和计算机科学的其他方面。2002 年,他创办了自适应人工智能公司(a2i2),这是一家专注于开发 AGI(人工通用智能)的 R&D 公司,2008 年,他分拆出 SmartAction,一家利用 a2i2 智能引擎的商业公司。
在过去的 4 年里,他的重点已经转移回进一步开发智能代理技术。为此,他成立了 AGI 创新公司,这是一家 10 人的技术开发公司,致力于在深度自然语言理解、适应性对话管理和上下文推理方面取得进一步突破。
彼得经常撰写和介绍各种哲学话题,包括理性伦理、自由意志和人造思想;并深深卷入未来主义和激进的生命延续。
你相信【狭义】“AI”领域正在走向第三个“冬天”吗?
不,一点也不——尽管有“狭义人工智能”的限制,但在许多领域都取得了实际成果,我没有看到整体进展有任何放缓。人工智能会一直存在,而且只会变得更好,成为经济中更大的一部分。
然而,当前人工智能技术的几个关键方面将不会达到预期,并将引起一些投资者的反弹。
特别是,我预计,由于“长尾”问题,像全自动(最后一英里)汽车这样的雄心勃勃的项目将比承诺的时间长得多。其次,大数据、统计方法本身不会提供用户期望的那种自然语言能力——它们没有深刻的理解,记忆非常有限(如果有的话),不能进行实时、交互式、一次性或无监督的学习,并且它们不能推理或解释它们的信念和行为。
新的方法,如高度集成的认知架构,需要满足这些要求。
‘狭义 AI’大部分是由一些数学结构和张量上的运算组成,用软件驱动模型训练和数据对其进行‘调优’。当你提到“认知架构”时,这些似乎是根本不同类型的机器,你能进一步阐述吗?
是的,认知架构通常涵盖了自主代理的全部需求,包括输入、输出、焦点选择&记忆、学习、推理、目标、元认知。
另一方面,机器学习/深度学习(ML/DL)通常只在相当封闭的环境中提供特定的功能,如对象识别、分类、字幕或优化。专家和其他逻辑系统只执行预定义的计算集合。
这些非认知架构方法的不同之处还在于,有一个(漫长的)培训、编码或设置周期,随后是基本上“只读”的部署——这些系统通常在执行过程中不学习*。*
然而,应用认知架构本身并不足以实现真正的智能。为了真正有效,认知组件也需要深度整合 -它们需要紧密耦合。知识表征必须充分整合知识和技能,而知识和技能又需要与短时记忆、语境、推理等整合。等等。这个事实被我的理论模型和实际实现经验所证实
大多数认知体系结构是高度模块化和不同的,因此不满足这个关键的需求。
两个主要原因是:a)工程师更喜欢高度模块化的设计,b)各种认知组件是不同计算机科学部门的专业知识表示是一个独立于推理和 NLU 的学科。
你和 AGI 的其他人已经断言‘狭义人工智能’不能进化成 AGI 系统,人工智能社区的其他人正在寻找仅用‘人工智能’就能实现一般智能的‘大方程’,给出足够大量的数据。你为什么认为这是站不住脚的?
狭义人工智能,根据定义,是为解决特定问题而优化的。我不知道有任何方法可以将狭义人工智能结合起来,以概括它们的认知技能——它们没有兼容的架构或知识表示。此外,它们本质上并不是为了提供智能所需的全面集成核心功能而设计的。
你把推进 AGI 的困难归因于什么?(从你的直接经验和总体研究领域来看)为什么从事这方面工作的人相对较少?
从理论/学术的角度来看,很少有广为接受的、可行的类人一般智力理论。事实上,人们更经常听到的是‘我们并不真正知道什么是智能’。除了这个障碍,优秀的软件工程师很少是好的认知心理学家——这是设计真正认知系统的基本要求。第三,商业压力几乎总是更喜欢直接狭隘的设计,而不是更困难、更 AGI 式的方法——它们需要一种罕见的有远见、更长远的观点。
还有其他几个因素阻止了 AGI 得到更多的爱——目前所有这些因素结合起来阻止了深度学习所享受的积极势头。
当然,也有许多困难的技术问题需要克服,但我不认为这些是不可克服的,只要有正确的理论和重点,加上足够的资源。
你一直专注于用机器对语言进行推理的解决方案。人们认为语言理解是一种相对较高水平的认知技能。在语言层面之下存在着更多的基础认知。在处理语言的水平之下,AGI 目前可展示的能力是什么?
我真的不能代表其他 AGI 系统,但我不知道任何活跃的 AGI 项目在一般的“动物智能”方面取得了有意义的(公开)进展——通常是(虚拟)机器人。和语言一样,几乎所有这样的项目都使用狭隘的人工智能方法。
我们系统的核心功能包括概念学习、知识表示、消歧、推理以及一些模式识别和动作序列。然而,我们目前的目标不是开发语言领域之外的内容。
鼠标级别的感知和敏捷很难;它们需要强大的计算能力和昂贵的尖端机器人技术,或者复杂的、通常不可用的模拟环境。
我们认为 NLP 是通向高级智能的更直接、更可行的途径。
这完全取决于应用程序:对于高价值的礼宾服务,可能是这样的。对于下一代“Siri”,不太可能。
请记住,目前的助手真的很笨:没有记忆或推理,只有浅层解析,没有对话支持等。一旦他们有了一点“大脑”(按照我们的方法),他们在没有人参与的情况下将会变得更加有用。需要实时人工支持的系统不太容易扩展。
自然,所有的个人助理系统都会有人在后台做 QA 和额外的训练/调整。
您对 NLP 的兴趣是否与实时语音界面密切相关,或者您的工作是否同样对异步消息应用感兴趣?你认为人类在这些形式中会发挥更大的作用吗?
同等地。然而,我想强调的是,实时操作和学习是真正智能行为的绝对要求。能够实时操作的智能系统(即,具有存储器和一些任务管理能力)通常能够异步操作。
另外,我想澄清一下,人在回路中实际上有两种完全不同的形式:
- 一个人(静静地)在后台,检查并潜在地覆盖人工智能
- 人工智能助手的用户,对要执行的全部任务承担(一些)责任。当然,这是“助手”的默认模式——被助手承担最终责任。
诺姆·乔姆斯基认为我们无法创造出理解语言的机器,因为“我们没有人类语言如何运作的方程式”。你似乎不同意,乔姆斯基缺少什么?
我们不能建造飞行器,因为我们没有鸟类飞行的方程式。也许他不理解'理解'(抱歉这么刻薄,但这确实是一个糟糕的论点)。
在《机器、幽灵和理解的限度》中,乔姆斯基详述了‘理解’的科学史。为了避免陷入这个‘手提箱单词’,让我们将目标陈述改为‘像人一样使用语言的机器’。乔姆斯基的观点是,机器(软件)是基于等式来行动的,而我们没有关于人们如何使用语言的等式,除了表面的方式(单词模式)。你认为对 AGI 和 NLP 的追求是把语言分解成方程式,还是根本不同的东西?
首先,我不认为“方程式”是看待编程的恰当方式。有时术语非算法被用来描述复杂的计算。
其次,正如我之前提到的,要解决 AGI 或 NLP 问题,我们真的需要能够从认知/心理/认识论的角度来看待问题。
理解(上下文)概念的作用是这里的关键。语言理解需要将单词和句子映射到概念,但还需要做更多的工作,包括激活和使用联想、短期和长期记忆、上下文和目标。
认为软件是基于方程的观点,并不比认为人类的认知是基于蛋白质的作用更有用。
你相信人类水平的 AGI 在未来 10 年内是可能的,只要有足够的资源。其他人认为这将需要更长的时间。你已经说过,实现 AGI 不需要“基本的新技术”,而是“巧妙结合现有技术,完善现有算法”。达到人类水平的 AGI 所需要的最重要的里程碑是什么?
- 有一个可行的认知/智力理论
- 构建实现所有必需核心组件的开发框架
- 在适当的实际应用中展示能力(不一定是商业的)
- 迭代更高的认知功能
AGI 开发人员/研究人员如何在系统发展的任何给定阶段测量他们系统的认知能力?
您沿着两个轴进行度量:范围(这里粗略地概括了一下)和能力(它能够处理的复杂程度)。
一个关键要求是两个维度都由一个单一的集成系统服务。此外,系统必须具有可扩展的架构结构和能力,以涵盖所有范围需求和不断增长的能力。
在我们的项目中,我们不断地运行回归测试,以确保当我们扩展系统时,所有先前的功能仍然工作(沿着两个维度)。我们通过系统覆盖更大部分的范围和增加其能力来衡量进展。
例如,实现歧义消除或目标导向行为(新范围),或提高解析/理解/推理能力,使其能够处理:
“猫是动物”…“猫是动物吗?”
能够理解和回答复杂的问题:
“Verallia 生产玻璃瓶和玻璃瓶,是法国香槟和干邑行业的主要供应商,去年的销售额为 23.9 亿欧元,营业收入为 2.3 亿欧元。”
使用真实世界的文本和对话实例进行测试对于开发实用的 AGI 至关重要。
假设一个 AGI 不是单一的结构而是不同组件的组合。马文·明斯基认为,人造大脑将由许多系统组成,就像生物大脑一样。你认为 AGI 系统的主要组成部分是什么?
我真的不认为 AGI 是一个“思想的社会”。根据一个人如何划分功能,他可能想要分离输入处理、输出激活、知识和技能编码、推理和元认知。
在我们当前以 NLP 为中心的系统中,解析、共指消解和 NLG (NL 生成)是相对独立的,但这更多是为了开发方便,而不是基础。
事实上,我想强调的是,为了有效的认知,所有的功能都必须高度集成——这是当前认知架构很少能满足的要求。
在今天为数不多的 AGI 研究人员中,大多数似乎都在研究人类水平的智能。为什么不从低于人类水平的一般智力开始呢?蜜蜂有大约 100 万个神经元,相当聪明:它能在三维空间导航,实现目标,交流等等....这(简单得多的智能)难道不是人工认知更合理的起点吗?
我过去正是这么想的:我们 AGI 发展项目的前三年(始于 2002 年)专注于创造动物智能。如上所述,动物级别的感知和灵巧真的很难,而且计算量很大。在机器人和自动驾驶汽车领域,有许多资金充足的团队在研究这些问题(或至少是相关的问题)。
我们只是决定通过 NLP 开发 AGI 是一个更快、更便宜的途径,并且在这个过程中提供了更多的商业化可能性。我们的 NLP/AGI 引擎的早期版本为一家成功的公司 www。SmartAction.ai,我们看到了许多其他以 NLP 为重点的 proto-agi 的可能性。
术语“原始 AGI”是什么意思?
AGI 的早期版本——即一个尚未达到全面的、人类水平的认知能力的系统,但其特定的、固有的架构和设计能够涵盖一般智能的要求。没有一个狭义的 AI 设计满足这些要求。
在“更多的商业化可能性”和对 AGI 的追求之间似乎有一条不确定的界线,前者不可避免地会给捷径和/或性能带来压力。作为一个既生产研究产品又生产商业产品的人,你如何平衡这些力量?
好不容易!
非常重要的一点是,企业的负责人应该理解在商业化过程中积极坚持 AGI 哲学的长期优势。对我们来说幸运的是,我们已经发展到了 AGI 复杂性和功能性的水平,通常商业目标实际上最好通过通用智能机制来实现,例如,教导系统比硬编码特定需求更容易、更好。
随着我们向人类水平的能力迈进,这将变得更加容易——在这里,普遍性压倒性地成为一种资产而不是一种负担: AGI 逃逸速度!
自动驾驶车辆卡尔曼滤波器介绍
我最近完成了自动驾驶汽车纳米学位项目 的Udacity Term2,我想分享一下我对“卡尔曼滤波器”遇到的一个有趣而又酷的话题的看法。希望这个博客能让你清楚地了解它是什么。享受学习:)
自主车辆由各种设备组成,通过这些设备收集数据并执行动作。下图显示了车辆中使用的几个重要部件的位置。
Components of an Autonomous Vehicle [Image Source]
卡尔曼滤波器使用的数据来自激光雷达和雷达。所以现在我们只关注这两个设备。
为什么要用卡尔曼滤波器?
我们可以使用卡尔曼滤波器做出一个有根据的猜测,在我们对某个动态系统有不确定信息的任何地方,系统下一步会做什么。在自主车辆的情况下,卡尔曼滤波器可以用于基于我们的车辆接收的数据来预测我们的自主车辆前方的车辆将要采取的下一组行动。这是一个使用两步预测和更新的迭代过程。
由于以下因素,它最适合这些类型的操作:
- 它只根据前一个状态预测下一个状态,不需要历史数据
- 计算速度非常快非常适合实时问题
- 即使环境中出现大量噪声/误差/不确定性,使用 高斯分布 ,卡尔曼滤波器也会给出一个好的结果。
我将向您概述所有这些是如何工作的,随后是一个示例,它将帮助您理解背后的数学原理。
卡尔曼滤波器是如何工作的?
卡尔曼滤波是一个迭代过程,遵循两步预测和更新
Flow chart of the Iterative process
预测:
在该步骤中,卡尔曼滤波器从初始值预测新值,然后根据系统中存在的各种过程噪声预测我们预测中的不确定性/误差/方差。
在自动驾驶汽车过程中,噪声可以通过一个简单的例子来理解,即一辆汽车在我们的汽车前面行驶。我们的模型将假设汽车以恒定的速度移动,因为加速度为零,但实际上它会有加速度,即它的速度会不时波动。汽车加速度的这种变化是不确定性/误差/方差,我们利用过程噪声将其引入系统。
更新:
在此步骤中,我们从系统设备中获取实际测量值。在自主车辆情况下,这些设备可以是雷达或激光雷达。然后,我们计算预测值和测量值之间的差值,并通过计算**卡尔曼增益来决定保留哪个值,即预测值还是测量值。**基于由卡尔曼增益做出的决定,我们计算新的值和新的不确定性/误差/方差。
来自更新步骤的该输出再次被反馈到预测步骤,并且该过程继续,直到预测值和测量值之间的差趋向于转换为零。该计算值将是卡尔曼滤波器进行的预测/有根据的猜测。
卡尔曼增益: 它决定了我们的预测值或测量值是否接近实际值。它的值范围从 0 到 1。如果其值接近 0,则意味着预测值接近实际值,或者如果其值接近 1,则意味着最终测量值接近实际值。其值的范围从 0 到 1,因为它使用了预测值和测量值的不确定性/误差,并由如下所示的简单公式表示。
K =预测误差/(预测误差+测量误差)
卡尔曼滤波器在无人驾驶汽车中的实现
在这方面,我们将根据目前掌握的信息,尝试理解卡尔曼滤波器是如何用于自动驾驶汽车的。
让我们假设一个 2D 环境,其中有一辆汽车和一个行人经过,如下所示:
2D representaion of car and pedestrian [Image Source]
p_x 和 p_y 确定 2D 位置,v_x 和 v_y 确定行人的 2D 速度。这可以表示为 x = (p_x,p_y,v_x,v_y) 。我们必须预测行人的 2D 位置(p _ x’,p _ y’)和 2D 速度(v _ x’,v _ y’)即 x’
由于状态向量仅模拟位置和速度,我们还需要不确定性/噪声,以便模拟加速度,这由过程协方差矩阵 P. 完成
预测步骤:使用以下公式计算预测值x′和预测误差P′也称为过程协方差矩阵:
x′= f . x+b .μ+ν
p′=fpfᵀ+q
F : 状态转移矩阵
它用于将状态向量矩阵从一种形式转换为另一种形式。即假设车辆的状态由位置 p 和速度 v 给出,并且在时间 t 没有加速。
X = [p,v]
在一个特定时间之后,比如说 t+1,新的状态向量 X’将是
*p ' = p+v δt
v'=v
在矩阵中,这可以显示如下:
x’ = F*x
那么 F 矩阵将由下式给出:
B: 控制输入矩阵
它决定了由于外力(纵向或横向力)和内力(重力、摩擦力等)引起的控制输入矢量 μ 的变化。).在自动驾驶汽车的背景下,我们无法对外力建模,因为它会因地区而异,也无法对内力建模,因为它会因汽车型号的不同而异。所以大多数情况下 B.μ=0。
v: 过程噪音/不确定性
它只是确定系统中可能存在的随机噪声。添加它是为了使预测位准确。
****问:过程噪音/运动噪音
当预测位置时,它给出了物体位置的不确定性。该模型假设时间间隔之间的速度是恒定的,但实际上我们知道物体的速度会因加速度而变化。该模型通过过程噪声包括了这种不确定性。
****更新步骤:快速回顾在更新步骤中,我们执行以下操作:
第一步:求实测值与预测值的差值
**第二步:计算卡尔曼增益
步骤 3: 根据卡尔曼增益的结果计算新的 x 和 P 。
现在我们将看到这些步骤的数学实现
第一步:
y = z—h . x′
z: 实测数据
这是来自传感器的实际数据。
H: 状态转移矩阵
和 F 一样,我们用 H 来转换状态向量。但是在这里,我们用它来丢弃状态向量中我们不需要的信息。例如,对于雷达进行的测量,我们只需要关注车辆的位置,而不需要担心速度,因为雷达只擅长确定速度的位置。在这种情况下,对于包含车辆位置和速度的状态向量,H 矩阵为:
第二步:
s =hp′hᵀ+r k =p′hᵀs⁻
R: 测量噪音
测量噪声是指传感器测量中的不确定性,它意味着设备本身有噪声并且不是 100%精确的,因此这些噪声测量值是由设备本身的制造商提供的,不需要改变。
S: 总误差
它是预测误差加上测量误差的总和。正如我们在上面的卡尔曼增益公式中看到的,我们需要总误差,所以这里用 s 表示。
K: 卡尔曼增益
我们通过前面给出的简单公式来计算卡尔曼增益。唯一的问题是,在矩阵中我们不能除法,所以这里我们取 S⁻。
第三步:
x = x′+k . y P =(I-KH)P′
最后,我们更新状态向量和协方差矩阵,并继续下一个预测步骤以获得其他值。
卡尔曼滤波器有问题
卡尔曼滤波器中使用所有这些函数都是线性的,因为它们在方程中不包括任何角度参数,因此我们可以将这些线性函数直接馈送给高斯分布,以获得高斯分布均值和方差。但是在现实生活中,大多数问题都是非线性的。由于这个原因,我们不能直接将这个非线性函数提供给高斯分布,因为这将导致非高斯分布,并且我们不能再对其应用卡尔曼滤波器。使用扩展卡尔曼滤波器解决了卡尔曼滤波器中的非线性问题。
你可以通过阅读拉姆齐·法拉格尔的这篇论文来了解更多关于卡尔曼滤波器的知识,这篇论文是基于卡尔曼滤波器,通过简单直观的推导
Scala 简介
欢迎阅读我的 Scala 系列的第一篇文章。本教程旨在教授 Scala 入门知识,作为学习 Apache Spark 的前奏。
第一部分可以在 Medium 上找到,但是本指南的其余部分可以在 project Github 页面的以下链接中找到:
Scala 是一种面向对象的函数式编程语言。它与 Java 关系最密切,所以 Java 程序员应该在学习它上有所帮助。然而,Scala 被设计得更加简洁,并且具有函数式编程语言的特性。
Spark 是一个为大数据处理而设计的开源集群计算框架。它是用 Scala 写的。Spark 可以在 Python ( PySpark )和 R ( SparkR 和 sparklyr )中运行;不过,Spark 的最佳性能可以在 Scala 中实现。
其他资源
我将提供一些其他来源作为替代和参考。何塞·波尔蒂利亚的 Udemy 课程非常棒,我的博客系列将大致遵循他的“ Scala 和 Spark for Big Data and Machine Learning”课程的结构。如果你学视频格式比较好,我强烈推荐那个课程。
Twitter 的 Marius Eriksen 发表了“有效的 Scala ”,可以在网上免费获得。这也是一个很好的资源。
如果你有 Python 背景,你也可以看看这本由 Rob Story 撰写的 Python 转 Scala 电子书。它“短小精悍”,是所有 Pythoners 爱好者和 Pythonistas 的快速参考!
就这样,让我们开始吧!
下载 Scala
第一个任务是下载 Scala。诚然,这可能是该过程中最具挑战性的部分之一。你需要经历几个步骤。如果你用的是 Windows 10,我推荐 YouTube 上的以下教程:
如何在 Windows 10 上安装和设置 SBT+Scala
你也可以自己决定是否要安装 SBT,因为还有其他运行 Scala 的选项(比如 IntelliJ )。
如果你使用的是基于 Linux 的操作系统,这里有一个类似的视频。我不能保证这一点,但它是由同一作者。
最后,这里是一些 Mac 指令。
虽然我发现安装 Scala 比 Python 或 R 更难,但如果你正在努力,网上有很多资源。好消息是,对大多数人来说,这可能是最具挑战性的部分。
VS Scala 的代码
我们将在早期的练习中使用命令提示符,但是我们最终将需要一个代码编辑器。我推荐 VS 代码,我将带你了解如何下载。
显然,您也可以自由使用其他选项,比如 Atom 或 Sublime。或者,如果你想使用一个完整的 IDE, IntelliJ 是一个不错的选择,并且有一个 Scala 插件适合它。
如果你想使用 VS 代码但还没有,在这里下载。
一旦你的计算机上有了 VS 代码,启动它。在屏幕的左侧,您应该会看到一些图标。这些图标中的一个是各种各样的正方形。如果你悬停在它上面,它应该会显示“扩展”点击那个。
在搜索栏中,输入“Scala”。您应该会看到 Scala 的一些插件选项。转到“Scala (sbt)”安装。下面的截图突出显示了框和正确的插件。
你也可以考虑一些其他的 Scala 插件。我没有对其他插件做太多改动,但是我也下载了 Scala 语法插件。
无论如何,现在你应该已经配置好运行 Scala 文件了。
入门
一旦你安装了所有的东西,你应该能够通过你的命令提示符运行 Scala。如果您成功地按照说明操作,并且正在运行 Windows,您可以打开命令提示符(快捷方式:在“开始”菜单的搜索框中输入“cmd ”)并键入:
spark-shell
这将在本地模式下启动 Spark,这是我们用来学习 Scala 基础知识的。
“Hello World”命令行提示
让我们从简单的 print 语句开始。Scala 的打印语句看起来与 Java 相似,但更简洁一些。
println(“Hello world!”)
瞧啊。现在你已经运行了你的第一个 Scala 程序。
《你好世界》VS 代码
在我们上完几课之前,我们不需要代码编辑器,但是如果你也想确保 Scala 在 VS 代码中正常工作,那么进入 File -> New File。将文件另存为“hello_world.scala”。在文件中输入正确的代码,然后保存。
现在打开你的终端:查看->终端。正如我们在命令提示符中所做的那样,在终端中输入“spark-shell”。要运行该程序,请输入:
:load hello_world.scala
有了这个,你应该得到你的打印输出。
第二部
这就是第 1 部分。第 2 部分介绍了数据类型;在项目 Github repo 查看。
贝叶斯推理导论数学冒险
嗨,这是我的第一篇博客文章,所以如果我在写文章时犯了任何错误或错过了任何惯例,请在评论中告诉我。(关于内容的礼貌反馈总是被邀请的:)。
在统计领域,统计学家和数据科学家采用了两种著名的方法来解决现实世界的预测问题,这两种方法被称为频率主义方法和贝叶斯方法。
黄金贝叶斯法则告诉我们:
其中 W 是统计模型的参数,该模型对数据 d 后面的分布进行建模。基于相同的表示,让我们来定义什么是频率主义者和贝叶斯方法?
频率主义方法是一种统计学家认为存在一个参数的真实值,概率是根据频率来定义的方法。遵循贝叶斯方法的统计学家认为,参数没有真实值,但参数本身遵循特定的分布,只有数据是真实的。
在本文中,我们将关注线性回归的贝叶斯版本。那么,现在让我们正确定义贝叶斯推理。
贝叶斯推断是一种方法,其中我们定义了具有某种分布的某些参数的先验。这种分布可以认为相当于我们手中已有的问题知识。使用与我们的问题相关的数据进一步更新该分布,这导致了称为后验分布的新分布。后验分布是我们对问题的先验知识和来自数据集的数据的组合。
但是,当大多数人都在使用频率主义方法时,我们为什么还需要贝叶斯方法呢?这个问题的答案如下:
- 让我们定义一个参数θ的先验,我们想要计算 P( 99 < θ < 100) 这只能在贝叶斯方法的情况下计算,因为频率主义方法给我们一个点估计。
- 与频率主义方法相比,贝叶斯方法提供了更多的概括。
- 贝叶斯方法避免了过度拟合。
等等,那我们为什么不用贝叶斯?,让我们先了解一下贝叶斯方法的缺点。
- 我们必须假设一个先验,这可能是一个非常费力的过程,因为我们假设的分布可能不接近原始分布。这导致后验估计的扰动。
- 在一些甚至大多数情况下,后验概率的计算是难以处理的(这是其不受欢迎的主要原因之一)
现在让我们推导出我们最喜欢的线性回归的贝叶斯版本。
让我们先设置问题:
等式 1 表示可观察到的数据集为 xᵢ 和 yᵢ.
Equation 1
Equation 2
如果 W 代表回归模型的权重,而 Y₁、Y₂,…、Yₙ 是由参数 w 给出的独立随机变量,则 Yᵢ可以定义为:
Equation 3. Description of Random Variable Y.
我们的权重(参数)的先验分布由下式给出:
Equation 4. Description of the distribution of W.
其中 C 是协方差矩阵,因为 w 是多元高斯,因为 Xᵢ是 d 维的。
我们希望每个维度上的权重相互正交,因此我们可以将其定义为 b⁻ I,其中 b 是多元精度矩阵。精度只不过是方差的倒数和 b > 0。
因此,我们的权重遵循以下分布:
Equation 5. Refined notation for distribution of W
类似地,我们也可以精确地表示 Y 的分布:
Equation 6. Refined notation for distribution of Y
其中 a⁻ = σ
在贝叶斯推理中,我们估计后验分布 P(W/D ),它由下式给出:
在哪里
P(D/W)是可能性。
P(W)是先验分布。
P(D)就是证据。
现在首先让我们计算最大似然估计(MLE 实际上是一种解决线性回归的常用方法,因为它假设参数有一个给定的真值) :
Equation 7. Computation of MLE estimate of the weights
Equation 8.
Equation 9.
Equation 10.
现在,如果我们将所有项相乘,那么我们可以将乘积转换为指数幂的和,这将更容易处理。
Equation 11
我们现在将把它转换成矢量化符号,因为这样更容易计算梯度。考虑以下变化:
因此,等式 11 中的求和变为:
Equation 12
为了估计等式 12 的最大值,需要找到它对变量 w 的导数。通过最小化ϕ.可以获得相同的结果现在我们来计算ϕ对 w 的导数
Equation 13
∇ϕ称为梯度向量,它包含 w 的每一维的偏导数
当我们设置∇ϕ = 0 时,可以找到等式 13 的最小值。
(xᵗx)⁻ xᵗ被称为伪逆,它非常接近 x⁻,因为 x 是一个 n x d 矩阵,因此它是不可逆的。所以,我们不能用等式 14。
Equation 14
让我们通过计算黑森∇ ϕ w.r.t 对 w 的二阶导数来验证这一点
Equation 15
为了使一阶导数成为最小值,Hessian 矩阵应该是半正定矩阵。矩阵 xᵗx 确实是半正定的,因为它本质上是可逆的,并且是其内部元素的平方。因此,我们确信我们已经找到了极小点。
最后,现在我们可以根据权重预测 y 的值,如下所示:
我们已经完成了可能性的计算,让我们继续计算后验分布。
我们知道,使用 P(D/W)和 P(W ),我们可以通过对可能性和先验的乘积进行积分来获得 P(D)。因此,我们可以丢弃来自后验计算的证据,因为它将是一个常数。
这里,左边的指数对应于似然,第二个指数对应于先验(我已经从两个等式中删除了乘数常数,因为它们是正的,不会影响计算。)
Equation 16
我们希望我们的后验概率本质上是多元高斯的。也许通过比较等式 17 和等式 16 的参数,我们可以很容易地估计该高斯函数的参数。
Equation 17
通过比较这些等式,我们得到:
Equation 18
Equation 19
因此,根据等式 19,我们可以获得均值等式:
现在我们有了后验分布的均值和精度(方差),但在得出结论之前,我们需要验证ψ的逆是否存在。
从 MLE 计算中我们知道 xᵗx 是半正定的,现在我们加上 bI,其中 b 是协方差矩阵,因此它默认是半正定的。所以这使得ψ是半正定的,因此是可逆的。
MAP 估计表明它本质上是 MLE 和先验的结合。先验的增加有助于映射 n 避免过度拟合,因此这被称为正则化参数。
最后,我们结束了计算参数的 MAP 估计。现在,我们可以用它来预测任意 x 值的 y 值。在下一篇文章中,我们将讨论朴素贝叶斯算法的贝叶斯版本。我希望这篇文章是有帮助的。
谢谢你。
贝叶斯推理导论——数学冒险(二)
在本文的最后一篇文章中,我们探讨了贝叶斯线性回归模型。在本文中,我们将探索贝叶斯朴素贝叶斯分类任务背后所涉及的数学。
在我们开始之前,我想重复一下在朴素贝叶斯的解决方案的推导过程中采用的最重要的假设,即特征是相互独立的。
首先,我们将设置问题,然后一步一步地复习数学。
分类问题的目标是计算 p(y|x,D ),其中 D 是数据集,x 是数据实例,y 是标签。
设置:
这里,xʲ是有限集合 a 上的 d 维向量,yʲ可以从集合{1,2,…,m}中取值
为了建模我们的数据实例,我们选择随机变量 Xʲ和 Yʲ.
我们在 x 和 y 之间的联合分布可以进一步细分为:
现在我们将逐一定义这些概率分布。
由于 y 是分类性质的,我们必须将 p(y|θ)定义为由θ参数化的分类分布。
其中 V(y)是由每个标签的向量的每个维度上的概率组成的向量。
p(x|y,θ)也将被定义为 d 维分类分布,因为 x 具有 d 维。
这种分类分布将是矩阵 W,其中每行对应不同的 y 值,列对应 x 中的不同特征
其中 W(Xⱼ = xⱼ,Y = y)将代表 p(Xⱼ = xⱼ|Y = y,θ)的概率。
矩阵的行总计为 1,因为它表示完整的分类概率分布。
为了进行贝叶斯分析,我们需要定义联合对{V,wⱼ}的先验,因为它们充当我们分布的参数。
现在,我们将定义参数 V 和 w。简化计算的明智选择将用于共轭。因此,我们将采用狄利克雷分布,因为我们的参数 X,Y 本质上是分类的。
我们的最终目标是根据给定的数据集 D. From Bayes 规则计算新数据点所属的类:
因为我们知道每个观察值都是相互独立的,所以我们可以将 x,y,D 之间的联合分布分成 x,y 和 D,给定θ。
现在,我们可以利用朴素贝叶斯算法的条件独立性假设来进一步拆分公式。
让我们用它们实际的公式来代替这些符号。
在未来,我们知道我们需要将这种分类分布与先验的狄利克雷分布相结合,以获得我们的狄利克雷后验分布。因此,我们想把分类分布写成狄利克雷分布,这样就很容易把它们结合起来。
标准的狄利克雷分布采用以下形式:
Equation 1.
其中,ϕ是 m 维参数向量,α是分布的另一个参数,也是向量,β是β函数,根据等式 1 中的公式,最后,s 是概率单纯形。其中 s 是在ϕ.的这 m 个参数上定义的一组 PMF 你可以探究在这个环节中,一个概率单纯形究竟是什么。
回到我们的问题,我们希望我们的分类分布有一种格式,这样我们可以很容易地把它转换成狄利克雷后验分布。
这些方程看起来很完美,因为我们有类似于狄利克雷先验的基。如果你对这个等式感到有点害怕,请保持冷静,因为我们很快就会很好地利用它。
现在,让我们为我们的先验做同样的事情。
让我们把 P(x,y,d)的各项一个一个相乘,让我们用 p(θ)和 p(xʲ,yⱼ|(θ)).开始
我们知道狄利克雷分布和分类分布是共轭的,因此我们将相应的共轭项组合在一起。
相似的术语已经组合在一起,但是由于不同的产品指数,我们不能直接将它们相乘,因此我们需要稍微改变它们。
Cⱼ基本上是 yⱼ拥有标签 j 的次数
c 现在变成了一个向量,类似于狄利克雷分布中的向量。这使得我们更容易将这两者结合起来,现在剩下要做的就是将它们结合在一起。
让我们对另一对也做同样的事情。
现在一切都设置好了,我们只需要将这些项与 P(x,y|θ)相乘
在哪里
我们可以看到一些漂亮的方程,它们是共轭的结果。
在上面的等式中,我们可以看到第一个括号是分布 V(y)的预期值,第二个括号也有些相同,但让我们更深入地研究一下,因为它可能会让人难以理解。
如果 y 等于第二个括号中的 k,则它成为分布 W 的期望值,但是当 y 不等于 k 时,则指数变为 1,因此,底数变为 1,使其成为仅分布值上的积分,从而将其积分为 1。
所以,我们现在要做的就是把这些项替换成它们的期望值。结果是:
我知道这可能有点脱离网格,但我会尝试在一篇完全不同的文章中添加期望值的计算,因为数学已经变得疯狂了。
最后的等式是:
为了计算这个类,我们需要将数据实例的值代入等式,并找到它的 argmax。
因此,我们成功地推导了几乎所有需要达到这一点的步骤。我希望这至少在某些情况下对你有用。下一篇文章将是关于贝叶斯隐马尔可夫模型,我也将写一篇小文章解释狄利克雷分布的期望值的计算。谢谢你。
PyStan 中的贝叶斯推理介绍
使用 Python 和 Stan 演示贝叶斯工作流
介绍
数据科学中贝叶斯方法的许多优点很少被低估。与 20 世纪定义统计学的相对陈旧的频率主义传统不同,贝叶斯方法通过将数据驱动的可能性与对世界的先验信念相结合,更紧密地匹配人类大脑的推理。这种方法在强化学习中得到了卓有成效的应用,努力将其融入深度学习是当前研究的热点领域。事实上,认为贝叶斯统计是两个统计学派中更基础的,并且应该是第一次向学生介绍这门学科时首选的统计学图片。
由于来自贝叶斯推理的预测是概率分布而不是点估计,这允许量化所作出的推理中的不确定性,这通常是机器学习方法所作出的预测所缺少的。
尽管将贝叶斯方法纳入机器学习有明确的动机,但在实际实现它们时存在计算挑战。通常,分析计算所需的分布是不实际的,而使用随机抽样方法,如马尔可夫链蒙特卡罗 (MCMC)。以透明和有效的方式实现 MCMC 方法的一种方式是通过概率编程语言 Stan 。
在本文中,我将提供一些关于贝叶斯推理和 MCMC 的背景知识,然后演示一个简单的例子,其中 Stan 用于通过 Stan 的 Python 接口 PyStan 对生成的数据集执行推理。
贝叶斯定理
贝叶斯推理的关键在于贝叶斯定理,它是由托马斯·贝叶斯牧师在 18 世纪发现的。这是基于概率论的一个基本结果,你可能以前见过:
左边的东西是我们的后验概率,这是我们感兴趣的分布。在右边,我们有可能性,它取决于我们的模型和数据,乘以先验,代表我们预先存在的信念,并除以边际可能性,使分布正常化。
这个定理可以用来得出许多违反直觉的结果,尽管如此,这些结果仍然是正确的。举个例子,当测试人群严重倾斜时,药物测试中的假阳性要高得多。我将继续与 Stan 讨论推理,而不是详细介绍贝叶斯统计的基础知识。威廉·科尔森有一些很好的材料来理解贝叶斯定理背后的直觉。
推动 Stan 的使用
贝叶斯推断是难。根据统计学家唐·贝里的说法,其原因是:
"从思考困难的意义上来说,贝叶斯推理是困难的."—唐·贝里
好吧。我想他在这里的意思是,使用贝叶斯方法进行推理的数学开销很小,所以困难来自概念上的困难,而不是任何技术或方法上的抽象。但更具体地说,贝叶斯推理很难,因为解积分很难。
上面的 P(B)包含了模型参数可能取的所有值的积分。幸运的是,我们并没有完全不知所措,因为通过从中抽取样本,并创建这些采样值的直方图作为所需的后验分布,可以构建后验分布的近似值。
MCMC 方法
在生成这些样本时,我们需要一个方法框架来管理采样器应该如何在参数空间中移动。一个流行的选择是马尔可夫链蒙特卡罗。MCMC 是一类结合了两个强大概念的方法:马尔可夫链和蒙特卡罗抽样。
马尔可夫链是以“无记忆”方式随时间演化的随机过程,被称为马尔可夫属性。Markov 属性意味着 Markov 链的状态转移到另一个状态的概率仅取决于系统的最近状态,而不是其整个历史。
另一方面,蒙特卡罗抽样涉及通过重复随机抽样来解决确定性问题。这样做的标准方式是使用 Metropolis-Hastings 算法。
相反,Stan 使用一种称为哈密顿蒙特卡罗(HMC)的最先进的算法来生成这些样本,该算法通过融入许多物理学理论思想来构建 Metropolis-Hastings 算法。实际上,默认情况下,它实现了一个名为不掉头采样器 (NUTS)的 HMC 版本。
很容易陷入这些方法的概念复杂性中,所以如果您在这个阶段还没有完全掌握,请不要担心;只要记住我们是随机生成样本,并根据一些概率规则接受或拒绝这些样本。
Stan 是一种概率编程语言,由 T2 的 Andrew Gelman 公司开发,主要在哥伦比亚大学。如果你觉得这个名字很奇怪,它是以核物理学家和蒙特卡罗方法之父斯坦尼斯劳·乌拉姆的名字命名的。
虽然它非常有用,但 Stan 的学习曲线相对较陡,而且互联网上也没有足够多的介绍性材料来证明这一点。语法本身大部分是从 Java/C 借用的,但是也有 R、Python、Julia 甚至 MATLAB 的库。对,没错,甚至 MATLAB 。因此,无论你的规划是什么,都可能有适合你的东西。
我选择的语言是 Python,所以我将使用 PyStan。像 Stan 的其他部分一样,PyStan 的代码是开源的,可以在这个 GitHub 库中找到,并且文档相当全面。斯坦的流行替代者,你们中的一些人可能很熟悉,是 PyMc 和 Edward,尽管我对他们没有太多的经验。Stan 的好处在于,你可以简单地在你的模型中指定分布,然后你就开始了,已经朝着你即将到来的推论奖金前进了。斯坦真正闪光的地方是在非常高维的问题中,在那里你可以推断出大量的预测因子。
然而,在本文中,我将保持事情的简单性,将我们的模型限制为简单的单变量线性回归,允许更多地关注 Stan 工作流。我们将实现的模型是
其中我们有截距α和梯度β,我们的数据分布在这条直线上,具有标准差σ的高斯噪声。
让我们建立一个模型
现在我们已经了解了一些背景知识,让我们来实现一些我们已经讨论过的内容。首先,你需要安装 PyStan,你可以这样做:
pip install pystan
让我们从导入相关的包开始,并设置 numpy 种子以实现可再现性。接下来,我们将通过指定线性回归的模型来开始我们的 Stan 脚本。这个模型是用 Stan 编写的,并被赋给一个名为model的 string 类型的变量。这是脚本中唯一需要用 Stan 编写的部分,推理本身将用 Python 完成。
这个模型的代码来自 Stan 参考手册第三章中的第一个示例模型,如果您正在进行任何类型的贝叶斯推理,这是一本推荐的读物。
Stan 模型至少需要三个块,分别用于数据、参数和模型。数据块指定将用于采样的数据的类型和维度,参数块指定相关参数。分布语句放在模型块中,在我们的例子中,它是一条带有附加高斯噪声的直线。尽管此处未包括,但也可以指定转换后的数据和转换后的参数块,以及函数和生成量的块。
请注意,在参数块中,我们将 sigma 的下限指定为 0,因为高斯噪声的幅度不可能为负。这是一个关于参数sigma的先验的例子,更详细的先验可以添加到模型块中。
还要注意,我们没有给我们的alpha和beta参数添加任何先验,尽管可以在模型块中随意试验添加先验,看看它们如何影响后验估计。
数据生成
在这里,我们将指定我们的参数的“基本事实”值,我们的目标是使用 Stan 再现这些值,并使用 numpy 从这些参数生成数据,确保添加高斯噪声。
我们可以绘制这些数据来了解我们在处理什么。
现在我们可以使用 PyStan 模型进行推理。数据需要在 Python 字典中运行采样器,并且我们在 Stan 模型的数据块中指定的每个元素都需要一个键。
然后,在对模型进行采样之前,需要对其进行编译,不过也可以加载一个预编译的模型,这可以通过本文附带的 GitHub 存储库中的这个脚本来完成。这种设置允许我们更改我们想要生成评估的数据,而不必重新编译模型。
抽样
在采样方法中,有许多可以指定的参数。iter是指将从每个马尔可夫链中产生的样本总数,chains是将从其中组合样本以形成后验分布的链的数量。因为潜在的马尔可夫过程是随机的,所以在参数空间的不同位置初始化更多的链是有利的,尽管添加更多的链会增加采样所需的时间。
warmup,也称为“老化”,是从每个链的开始将被丢弃的样本量,因为早期的样本将在马尔可夫链还没有机会达到平衡时被抽取。
默认情况下,这是iter的一半,因此对于每个链,我们将获得 1000 个样本,并丢弃前 500 个。有了 4 条链,我们总共会有 2000 个样本。
thin指定保留样本的采样间隔。因此,如果thin等于 3,则每三个样本保留一个,其余的丢弃。这对于减轻连续样本之间的相关性影响是必要的。这里它被设置为 1,所以每个样本都被保留。最后,seed被指定为允许再现性。
诊断学
一旦采样完成,就可以打印 fit 对象来检查推理的结果。在这里,我们可以看到两个回归参数的汇总统计数据,以及模型中的高斯噪声。
此外,我们可以看到称为lp__的量的相同统计数据,根据 Stan 手册它是达到常数的对数后验密度。检查lp__是否已经收敛可以让我们更加确信整个采样过程已经收敛,但是这个值本身并不是特别重要。
The printed fit upon completion of sampling in Stan.
除了平均值和分位数信息,每个参数还有另外两列,n_eff和Rhat。n_eff是的有效样本量,由于样本之间的相关性,它可以显著低于生成的样本的名义数量。如上所述,可以通过细化马尔可夫链来减轻自相关的影响。
Rhat是 Gelman-Rubin 收敛统计量,一种马尔可夫链收敛的度量,对应于方差减少的比例因子,如果允许采样永远继续,则可以观察到方差减少。因此,如果Rhat约为 1,无论你继续迭代多长时间,你都不会看到采样方差减少,因此马尔可夫链很可能(但不保证)已经收敛。
我们可以将这种拟合输出投射到 pandas 数据框架中,以使我们的分析更容易,从而允许更好地访问相关的汇总统计数据。上面的 fit 对象有一个 plot 方法,但这可能有点混乱,而且似乎已被弃用。相反,我们可以提取每个参数的采样值序列,称为“轨迹”,我们可以将它与相应的后验分布一起绘制,用于诊断目的。
绘制我们的回归线
既然我们已经从拟合的模型中提取了相关的信息,我们可以看一下绘制线性回归的结果。为了从推断参数的不确定性中了解我们在回归线中可以预期看到的分布类型,我们也可以绘制潜在的回归线,其参数从我们的后验中取样。
关于用于生成该图的代码的更多细节,您可以查看 GitHub 上的脚本。
绘制后验概率图
除了将我们的分析局限于汇总统计数据,我们还可以更详细地查看我们之前提取的每个参数的一系列采样值。这将允许更深入地了解采样过程,并且是执行 fit 诊断的重要部分。
这里我定义了一个函数,它绘制了给定参数的轨迹和后验分布。对感兴趣的参数调用该函数,我们可以生成所需的图。
从上面的轨迹图中,我们可以看到通过参数空间的运动类似于随机行走,这表明潜在的马尔可夫链已经如我们所希望的那样达到收敛。我们也可以看一下beta和sigma的对应图。
从后验分布图中我们可以看出,基本事实总体上非常接近我们分布的模式,并且在 95%的可信区间内。由于数据中的噪声,在后验峰值和基础事实之间存在一些偏差。贝叶斯方法的便利之处在于,估计中的不确定性在这些后验分布中被捕获,并且可以通过提供更有洞察力的先验来改进。
结论
我们已经看到了如何在 Stan 中编写模型,如何使用 PyStan 中生成的数据执行采样,以及如何检查采样过程的输出。贝叶斯推理可能非常强大,还有许多 Stan 的特性有待探索。我希望这个例子是有用的,并且您可以在执行自己的采样和推断时使用其中的一些材料。
我的第一篇技术博客就这样结束了。请随意留下任何反馈,并确保查看 GitHub 资源库 以执行您自己的推断并制作您自己的情节。感谢阅读!
Python 中聚类算法的介绍
在数据科学中,我们经常会思考如何利用数据对新的数据点进行预测。这被称为“监督学习”然而,有时我们不想“做预测”,而是想将数据分成不同的类别。这被称为“无监督学习”
为了说明这种差异,假设我们在一家大型披萨连锁店工作,我们的任务是在订单管理软件中创建一个功能,为客户预测送货时间。为了实现这一点,我们得到了一个数据集,其中包含过去几次交付的交付时间、行驶距离、星期几、时间、现有员工和销售量。根据这些数据,我们可以预测未来的交货时间。这是监督学习的一个很好的例子。
现在,让我们假设比萨饼连锁店想要向顾客发送有针对性的优惠券。它想把顾客分成 4 类:大家庭、小家庭、单身人士和大学生。我们获得了之前的订购数据(例如订单规模、价格、频率等),我们的任务是将每个客户归入四个类别之一。这将是“无监督学习”的一个例子,因为我们不做预测;我们只是把顾客分成几组。
聚类是最常用的无监督学习形式之一。在本文中,我们将探讨两种最常见的聚类形式:k-means 和层次聚类。
了解 K-Means 聚类算法
让我们看看 k-means 聚类是如何工作的。首先,让我给你介绍我的好朋友,blobby 即 Python 的 sci-kit 学习库中的 make_blobs 函数。我们将使用 make _ blobs 创建四个随机集群来帮助我们完成任务。
# import statements
from sklearn.datasets import make_blobs
import numpy as np
import matplotlib.pyplot as plt# create blobs
data = make_blobs(n_samples=200, n_features=2, centers=4, cluster_std=1.6, random_state=50)# create np array for data points
points = data[0]# create scatter plot
plt.scatter(data[0][:,0], data[0][:,1], c=data[1], cmap='viridis')
plt.xlim(-15,15)
plt.ylim(-15,15)
你可以在下面看到我们的“斑点”:
我们有四个彩色集群,但是上面的两个集群和下面的两个集群有一些重叠。k-means 聚类的第一步是选择随机质心。因为我们的 k=4,我们需要 4 个随机质心。下面是它在我的实现中从头开始的样子。
接下来,我们取每个点,找到最近的质心。度量距离的方法有很多种,我用的是欧氏距离,可以用 Python 中的 np.linalg.norm 来度量。
现在我们有了 4 个集群,我们找到了集群的新的质心。
然后,我们再次将每个点匹配到最近的质心,重复这个过程,直到我们不能再改进聚类。在这种情况下,当过程结束时,我得到了下面的结果。
请注意,这些集群与我最初的集群有些不同。这是随机初始化陷阱的结果。本质上,我们的起始质心可以决定我们的聚类在 k 均值聚类中的位置。
这不是我们想要的结果,但是解决这个问题的一个方法是使用 k-means ++算法,它提供了更好的初始播种,以便找到最佳的聚类。幸运的是,这是在我们将在 Python 中使用的 k-means 实现中自动完成的。
在 Python 中实现 K-Means 聚类
要在 Python 中运行 k-means,我们需要从 sci-kit learn 中导入 KMeans。
# import KMeans
from sklearn.cluster import KMeans
注意,在文档中,k-means ++是缺省的,所以我们不需要为了运行这个改进的方法而做任何改变。现在,让我们在 blobss 上运行 k-means(这些 blob 被放入一个名为“points”的 numpy 数组中)。
# create kmeans object
kmeans = KMeans(n_clusters=4)# fit kmeans object to data
kmeans.fit(points)# print location of clusters learned by kmeans object
print(kmeans.cluster_centers_)# save new clusters for chart
y_km = kmeans.fit_predict(points)
现在,我们可以通过在 matplotlib 中运行以下代码来查看结果。
plt.scatter(points[y_km ==0,0], points[y_km == 0,1], s=100, c='red')
plt.scatter(points[y_km ==1,0], points[y_km == 1,1], s=100, c='black')
plt.scatter(points[y_km ==2,0], points[y_km == 2,1], s=100, c='blue')
plt.scatter(points[y_km ==3,0], points[y_km == 3,1], s=100, c='cyan')
瞧啊。我们有 4 个集群。请注意,k-means++算法比我在示例中运行的普通 ole' k-means 做得更好,因为它几乎完美地捕捉到了我们创建的初始聚类的边界。
K-means 是最常用的聚类形式,因为它速度快且简单。另一种非常常见的聚类方法是层次聚类。
实现凝聚层次聚类
凝聚层次聚类在一个关键方面不同于 k-means。我们不是选择一些聚类,从随机的质心开始,而是从数据集中的每个点作为一个“聚类”开始然后我们找到最近的两个点,并把它们组合成一个簇。然后,我们找到下一个最近的点,这些成为一个集群。我们重复这个过程,直到我们只有一个巨大的星团。
在这个过程中,我们创建了一个树状图。这是我们的“历史”你可以看到我们下面的数据点的树状图,以了解正在发生的事情。
树状图标出了每个聚类和距离。我们可以使用树状图找到我们选择的任何数字的聚类。在上面的树状图中,很容易看到第一个集群(蓝色)、第二个集群(红色)和第三个集群(绿色)的起点。这里只有前 3 个是用颜色编码的,但是如果你看树状图的红色一边,你也可以发现第 4 个集群的起点。该树状图一直运行,直到每个点都是它自己的单独聚类。
让我们看看凝聚层次聚类在 Python 中是如何工作的。首先,让我们从 scipy.cluster.hierarchy 和 sklearn.clustering 中导入必要的库。
# import hierarchical clustering libraries
import scipy.cluster.hierarchy as sch
from sklearn.cluster import AgglomerativeClustering
现在,让我们创建我们的树状图(上面我已经向您展示过了),确定我们需要多少个聚类,并保存这些聚类中的数据点以绘制它们的图表。
# create dendrogram
dendrogram = sch.dendrogram(sch.linkage(points, method='ward'))# create clusters
hc = AgglomerativeClustering(n_clusters=4, affinity = 'euclidean', linkage = 'ward')# save clusters for chart
y_hc = hc.fit_predict(points)
现在,我们将像使用 k-means 算法一样,使用 matplotlib 查看我们的聚类。
plt.scatter(points[y_hc ==0,0], points[y_hc == 0,1], s=100, c='red')
plt.scatter(points[y_hc==1,0], points[y_hc == 1,1], s=100, c='black')
plt.scatter(points[y_hc ==2,0], points[y_hc == 2,1], s=100, c='blue')
plt.scatter(points[y_hc ==3,0], points[y_hc == 3,1], s=100, c='cyan')
结果如下:
在这种情况下,k-means 和层次聚类之间的结果非常相似。然而,情况并非总是如此。一般来说,凝聚层次聚类的优点是它往往会产生更准确的结果。缺点是,与 k-means 相比,层次聚类更难实现,并且消耗更多的时间/资源。
延伸阅读
如果你想了解更多关于聚类的知识,我强烈推荐 George Seif 的文章“数据科学家需要了解的 5 种聚类算法”
其他资源
数据质量简介
Image Reference: www.datapine.com
1.什么是数据质量?
数据质量有许多定义,一般来说,数据质量是对有多少数据可用并适合其服务环境的评估。
许多因素有助于衡量数据质量,例如:
- 数据一致性:违反数据集定义的语义规则。[1].
- *数据准确性:*当数据库中存储的数据值与真实值相符时,数据是准确的。[1]
- 数据唯一性:针对特定字段、记录或数据集,衡量系统内部或跨系统存在的多余重复。[2]
- *数据完整性:*数据集合中存在的值的程度。[1]
- *数据及时性:*数据的年龄在多大程度上适用于手头的任务。[3]
其他因素也可以考虑[4],如可用性、易操作性、可信度和流通性。
2.为什么数据质量很重要?
提高数据质量是一个关键问题,因为数据被视为组织内所有活动的核心,数据质量差会导致报告不准确,从而导致不准确的决策和经济损失。
3.如何提高数据质量?
通过以下方式提高数据质量:
- 培训员工
- 实施数据质量解决方案
3.1.培训员工
在考虑实现数据质量解决方案之前,首先我们必须尽量减少由组织内的人工活动(如数据输入)导致的数据质量问题。此外,所有开发人员和数据库管理员都必须对业务流程有很好的了解,并且在开发和设计数据库和应用程序时必须参考统一的模式。[5]
3.2.实施数据质量解决方案
提高数据质量的另一种方法是实施数据质量解决方案。数据质量解决方案是一套执行质量任务的工具或应用程序,例如:
- 知识库创建:知识库是用于信息传播的机器可读资源。[6]
- 重复数据删除:根据一组语义规则删除重复的信息。
- 数据清理:从值中删除不需要的字符和符号。
- 数据分析:是检查从现有信息源(例如数据库或文件)获得的数据并收集关于该数据的统计数据或信息摘要的过程。[7]
- 数据匹配:数据匹配描述了使用记录链接和实体解析等技术来比较两组收集的数据。[8]
4.流行的数据质量解决方案
在这一部分,我将展示一些市场上最流行的数据质量解决方案。
4.1.IBM Infosphere 信息服务器
IBM InfoSphere Information Server 是一个市场领先的数据集成平台,它包括一系列产品,使您能够理解、清理、监控、转换和交付数据,并通过协作来弥合业务和 IT 之间的差距。InfoSphere Information Server 提供了大规模并行处理(MPP)能力,以提供一个高度可伸缩和灵活的集成平台,处理所有大小数据量。
InfoSphere Information Server 使您能够灵活地满足您独特的信息集成需求——从数据集成到数据质量和数据治理——以便为您的任务关键型业务计划(如大数据和分析、数据仓库现代化、主数据管理和影响点分析)提供可信的信息。[9]
4.2.信息数据质量
Informatica 数据质量为内部或云中的所有业务应用程序的所有利益相关者、项目和数据域提供值得信赖的数据。[10]
4.3.Oracle 数据质量
Oracle Enterprise Data Quality 为交易方和产品数据提供了一种完整的、同类最佳的方法,可生成与应用程序集成的可信主数据,从而提高业务洞察力。[11]
4.4.Microsoft 数据质量服务
SQL Server 数据质量服务(DQS)是一种知识驱动的数据质量产品。DQS 使您能够建立一个知识库,并使用它来执行各种关键的数据质量任务,包括纠正、丰富、标准化和重复数据删除。DQS 使您能够通过使用参考数据提供商提供的基于云的参考数据服务来执行数据清理。DQS 还为您提供集成到其数据质量任务中的分析,使您能够分析数据的完整性。[12]
4.5.Melissa 数据质量
自 1985 年以来,Melissa 一直在提供具有广泛功能的企业数据质量工具,包括数据分析和标准化、清理、丰富、链接和重复数据删除。我们的使命是为组织提供一流的解决方案,提供可信、可靠、准确的信息,以获得更好的洞察力。[10]
4.6.数据质量
Talend 的企业数据质量工具可以分析、清理和屏蔽数据,同时监控任何格式或大小的数据质量。重复数据消除、验证和标准化为访问、报告、分析和运营创建了干净的数据。利用外部来源丰富数据,用于邮政验证、业务识别、信用评分信息等。[13]
4.7.Syncsort Trillium 软件领先
Syncsort 的 Trillium 云提供了行业领先的企业数据质量解决方案,具有 Syncsort 管理的强化安全 colud 环境的部署便利性和运营灵活性。[14]
4.8.SAS 数据质量
SAS 数据质量软件使您能够提高数据的一致性和完整性。当您提高数据质量时,您就提高了分析结果的价值。
SAS 数据质量软件支持各种数据质量操作。数据质量操作采用预定义的规则,这些规则适用于数据的特定上下文(如姓名或街道地址)。数据质量操作的例子包括大小写、解析、模糊匹配和标准化。[15]
5.参考
- [1] C. Batini,C. Cappiello,C. Francalanci,A. Maurino,“数据质量评估和改进的方法学”, *ACM 计算调查(CSUR),*第 41 卷,第 16 页,2009 年。
- [2] D. McGilvray,“质量数据和可信信息的十个步骤”,麻省理工学院信息质量行业研讨会, 2008。
- [3] R. Y. W. a. D. M. Strong,“超越准确性:数据质量对数据消费者意味着什么”,*《管理信息系统杂志》,*第 12 卷,第 5-33 页,1996 年。
- [4] Sidi Fatimah,Shariat Panahy,Payam Hassany,Lilly Suriani Affendey,Marzanah A. Jabar,Hamidah Ibrahim,Aida Mustapha,“数据质量:数据质量维度调查”,载于Proceedings-2012 International Conference on Information Retrieval and Knowledge Management,CAMP’12,2012 年。
- [5] Herzog,Thomas N .,scheuren,f.j,winkler,“什么是数据质量,我们为什么要关心”,*《工业工程与管理学报》,*第 4 卷(2),第 2 版,第 1–9 页,2016 年。
- [6] M. Rouse,“知识库”,TechTarget,2007 年第 3 期。【在线】。可用:【searchcrm.techtarget.com/definition/… 年 9 月 12 日访问】。
- [7]“数据剖析”,维基百科,[在线]。可用:en.wikipedia.org/wiki/Data_p…【2018 年 9 月 12 日接入】。
- [8]“什么是数据匹配?,“Techopedia,[在线]。可用:www.techopedia.com/definition/…【2018 年 9 月 12 日获取】。
- [9]“IBM 信息服务器”,IBM,[在线]。可用:www.ibm.com/analytics/i…【2018 年 9 月 12 日接入】。
- [10]“最佳数据质量软件”,G2Crowd,[在线]。可用:www.g2crowd.com/categories/…【2018 年 9 月 12 日获取】。
- [11]“Oracle 企业数据质量”,Oracle,[在线]。可用:http://www . Oracle . com/us/products/middleware/data-integration/enterprise-data-quality/overview/index . html【2018 年 12 月 9 日访问】。
- [12]“数据质量服务”,微软,2013 年 10 月 12 日。【在线】。可用:https://docs . Microsoft . com/en-us/SQL/data-quality-services/data-quality-services?view=sql-server-2017。【2018 年 12 月 9 日接入】。
- [13]“数据质量”,塔伦德,[在线]。可用:www.talend.com/products/da…【2018 年 9 月 12 日接入】。
- [14]“Trillium 软件”,Syncsort,[在线]。可用:www.syncsort.com/en/About/Tr…【2018 年 9 月 12 日接入】。
- [15]“SAS 数据质量和数据质量服务器”,SAS,[在线]。可用:http://support . SAS . com/software/products/data qual/index . html【2018 年 9 月 12 日访问】
调试介绍(用 C 和 lldb 编写),第一部分
Source — xkcd.com/1722/
什么是调试?
“bug”这个词(以及由此而来的“debugging”)是如何理解我们(计算机程序员)所联想到的含义的,还不完全清楚。这可能要归功于哈佛大学马克 2 号计算机中传说中的飞蛾,也可能是在比 T1 更早的时候创造的。无论起源是什么,作为程序员,我们都有关于调试的故事要分享。有时它们很悲伤,有时它们描述了几个令人疲惫不堪的小时,但大多数时候它们都有一个快乐的结局。但是我们都有一个共同点,我们会遇到调试。几乎每天。因此,在开始调试之前,让我们先定义一下它是什么。
我建议调试的定义如下—
调试是一个开发人员(他可能是也可能不是他要调试的代码的作者)使用各种可用的工具,努力改变以前编写的代码的一部分,以消除在编译(或语法检查)时没有发现的错误(换句话说,在特定条件下在运行时出现的错误)的过程。
听起来很酷吗?还是恐吓?如果是后者,那么你应该继续读下去。也许这个小帖子终究会帮到你。
不同类型的调试
人们有许多不同的方法来执行调试。但是在列出它们之前,我们需要理解任何调试过程主要(大部分时间)由两个主要活动组成。第一——调查程序执行的不同阶段不同变量的值,第二——检查控制流的方向(我们是否进入了“if”块?“while”循环中的“break”语句到达了吗?…)
- 打印语句 —在运行代码时,使用“Print”(或“printf”或“echo”或任何等效的东西)来输出一些值。这可能是开始调试任何东西的最简单的方法。这也是最笨拙和费时的方法。它之所以笨拙,是因为一旦我们完成了,我们很容易在代码中留下所有那些(或其中的一部分)打印语句,导致不干净的代码(在一些非常罕见的情况下,在生产中破坏它)。).这很费时间,因为我们必须编写所有的打印语句,然后在程序执行的时候监视它们。
- 使用日志记录 —这种方法也是基于文本的,就像打印一样,但是有很多优点。我们实际上可以将结构化消息从我们的程序转发到日志管理平台,然后使用这些工具在文本语料库中执行各种搜索以收集必要的信息,而不是仅仅将“stdout”作为输出机制(对于打印来说)。这是一个非常有效的方法。对于任何严肃的生产应用程序来说,日志记录都是必不可少的。但是它也有自己的局限性。我们仍然必须在代码中手工编写所有的日志语句(如果不需要的话就删除它们),而且我们也不能(在大多数情况下)窥视程序执行的内幕。
- 交互式(符号)调试器——如果你曾经使用过类似“gdb”(或“ipdb”或“pydb”或“lldb”之类的东西,那么你就知道我在说什么。至于其他的,在你自己的开发机器中有可用的工具,这些工具在运行时以一种交互的方式给你一个强大的访问程序的权限,并且让你在一段运行的代码上执行非常低级(和高级)的调查。这种调试的优点是,您不需要做任何额外的工作来开始调试代码。你只需启动调试器并指向可执行文件,瞧!您正在运行一个程序,但是您也拥有实时调查(如果需要,甚至更改)它的所有权力。酷!
关于虚拟内存的几句话
在我们使用调试器进行任何严肃的调试之前,我们需要理解操作系统是如何给程序分配内存的。有一篇由彼得·萨尔兹曼撰写的关于交互式调试的精彩(可能是最好的)介绍,我的帖子只是它的前几页的一个小摘要(由于 lldb 的缘故,有一点额外的内容),但是我仍然会花时间说几句关于 VM 的话。任何感到好奇的人请跟随彼得的指南(和他在那里提到的链接)。
当一个程序启动时,操作系统会在主内存(ram)中分配一块内存,以便该进程可以运行。这被称为*虚拟内存空间。*它是一种复杂的高级机制,涉及操作系统和 CPU 的内存管理单元(MMU)。我们不需要详细讨论这个问题。但是我们确实需要知道,在 VM 内部,有一块内存被分配给两个不同的数据结构所使用的进程。栈和堆(除了一些为其他东西保留的其他块)。它看起来像下面这样—
scource — open4tech.com/concept-hea…
任何由我们或我们正在使用的库分配的动态内存都将位于堆内部。堆栈由“帧”组成。每一帧代表一个函数调用。当一个新的函数被调用时,一个新的帧被插入到栈顶。如果您将分配的 VM 想象为主内存中的一个垂直内存块,那么随着进程的进行,堆栈向下增长,堆向上增长(如上图所示)。
当我们调试时,我们将需要框架的概念。
正在调试
我将展示与 lldb 相关的命令,并在最近的 MacBook Pro 中执行(预装了llvm)。 *cc* 和 *lldb* 的版本都在之后
Apple LLVM version 9.1.0 (clang-902.0.39.2) (result of cc --version)lldb-902.0.79.7 (result of lldb --version)
我们先写一个你能想象到的最简单的 C 程序。我将使用“vim”作为编辑器。你可以用任何你想要的东西。
vim hello.c
进入编辑器后,请复制粘贴(或键入)以下代码—
#include<stdio.h>int main(int argc, char* argv){ printf("Hello World!\n"); return 0;
}
保存并退出编辑器,然后执行以下操作
cc -g --std=c99 -Wall hello.c -o hello
下面是我们为编译器使用的一些标志的描述
-g它告诉我们的编译器在输出文件中嵌入调试信息(例如符号表)--std=c99我们正在使用的 C 语言标准-Wall捕捉所有的警告
为了查看我们所做的实际上运行了,我们可以尝试下面的方法
./hello
Hello World!
到目前为止一切顺利!现在让我们启动调试器。为此,请使用以下命令
lldb hello
如果一切正常,它将显示如下内容—
这是交互式调试器的提示。在我们的例子中是lldb
引用 lldb 文档中的话,gdb中的命令是“自由形式的”。然而,lldb 已经努力使命令标准化。lldb中的命令遵循以下模式—
<noun> <verb> [-options [option-value]] [argument [argument...]]
这里的noun代表你正在努力工作的对象。这可以是thread或frame或类似的。而verb就是实际的命令。所以与gdb不同,要查看当前堆栈的所有帧,你必须输入thread backtrace(对于gdb,它只是简单的backtrace)。如果您在最开始输入这个命令,您将得到“错误:无效进程”。这是因为尽管我们已经用可执行文件的名称启动了调试器(在我们的例子中是hello ),但我们实际上并没有请求运行它。所以下面是您应该运行的第一个命令— run。它将产生如下输出—
我们已经成功地在调试器中运行了可执行文件。但是!我们对此没有任何控制。它跑了。成功了。最后以 0 状态退出。这里没有魔法。所以,让我们创造一些。我们将使用breakpoint set命令。断点是源文件中的特定代码行,调试器将在那里暂停执行,并给我们一个交互提示,以便与正在运行的进程混合:)(-l 10表示我的源文件中我想暂停执行的那一行。对你来说,行号可以不同)
注意这里的魔力。*我们已经在原始源文件的行号后面设置了断点,但是我们正在加载和运行可执行文件,然而调试器不知如何连接它们,并在正确的代码行挂起。*在此阶段,我们可以检查当前框架中的不同变量及其值。为了检查变量,我们这样做
瞧啊。我们有与当前框架相关的所有变量及其类型和值。现在是thread backtrace的时候了——
正如我们所见,我们的函数调用main位于堆栈的顶部。但这不是我们唯一的框架。我们有一些其他的与函数调用相关的帧,但是我们没有做。这些是在运行时加载的动态库。
最后,由于我们没有什么要进一步研究的(我们正在运行一个非常简单的代码),我们需要知道如何从进程暂停的地方恢复它。我们如何前进?嗯,有两个命令。简称step或s,简称continue或c。它们之间的区别在于,step只是执行下一条指令,然后再次挂起。这是一种在运行过程中一步一步的旅程,而c将执行所有的指令,直到遇到下一个断点或过程结束。这里我们不想单步执行流程,所以我们使用c,因为没有更多的断点,流程将结束运行。
这是第一部分的结尾。我们在这里学习了调试的基础知识。但是我们还没有进行任何真正的调试。我们将在第二部分看到这一点。
如果你喜欢这篇小文章,请尽情鼓掌。这将鼓励我多写这样的文章。也请大家分享评论。他们非常有帮助:)
第二部分见。调试愉快!
深度学习导论
近年来,深度学习已经成为科技界的一个热门词汇。我们似乎总是在关于人工智能的新闻中听到它,然而大多数人实际上并不知道它是什么!在这篇文章中,我将揭开深度学习这个时髦词汇的神秘面纱,并提供它如何工作的直觉。
建立直觉
一般来说,深度学习是一种机器学习方法,它接受一个输入 X,并用它来预测一个输出 y。例如,给定过去一周的股票价格作为输入,我的深度学习算法将尝试预测第二天的股票价格。
给定输入和输出对的大型数据集,深度学习算法将尝试最小化其预测和预期输出之间的差异。通过这样做,它试图学习给定输入和输出之间的关联/模式——这反过来允许深度学习模型归纳到它以前没有见过的输入。
作为另一个例子,假设输入是狗和猫的图像,输出是这些图像的标签(即输入图片是狗还是猫)。如果输入具有狗的标签,但是深度学习算法预测猫,那么我的深度学习算法将学习到我的给定图像的特征(例如,锋利的牙齿、面部特征)将与狗相关联。
深度学习算法如何“学习”?
深度学习算法使用一种叫做神经网络的东西来寻找一组输入和输出之间的关联。基本结构如下所示:
神经网络由输入层、隐藏层和输出层组成,所有这些层都由“节点”组成。输入层接受数据的数字表示(例如,具有像素规格的图像),输出层输出预测,而隐藏层与大多数计算相关。
我不会在数学上太深入,但是信息是通过上面显示的函数在网络层之间传递的。这里需要注意的要点是可调权重和偏差参数——在上面的函数中分别用 w 和 b 表示。这些对于深度学习算法的实际“学习”过程是必不可少的。
在神经网络将其输入一直传递到其输出之后,网络通过称为损失函数的东西来评估其预测(相对于预期输出)的好坏。例如,“均方误差”损失函数如下所示。
Y hat 代表预测,而 Y 代表预期产量。如果同时使用输入和输出批次,则使用平均值(n 代表样本数)
我的网络的目标最终是通过调整网络的权重和偏差来最小化这种损失。在通过梯度下降使用被称为“反向传播”的东西时,网络回溯通过它的所有层,以在损失函数的相反方向上更新每个节点的权重和偏差——换句话说,反向传播的每次迭代应该导致比以前更小的损失函数。
在不进行证明的情况下,网络的权重和偏差的持续更新最终会将其变成一个精确的函数逼近器——一个对输入和预期输出之间的关系进行建模的函数逼近器。
那么为什么叫“深度”学习呢?
深度学习的“深度”部分是指创建深度神经网络。这是指具有大量层的神经网络-通过添加更多的权重和偏差,神经网络提高了逼近更复杂函数的能力。
结论和要点
深度学习最终是一个广阔的领域,比我描述的要复杂得多。对于不同的任务,存在各种类型的神经网络(例如,用于计算机视觉的卷积神经网络,用于 NLP 的递归神经网络),并且远远超出了我所介绍的基本神经网络。
上图:一个卷积神经网络
即使你不记得这篇文章的所有内容,这里也有一些要点:
- 深度学习指的是深度神经网络
- 深度神经网络发现一组输入和输出之间的关联
- 反向传播是用来更新神经网络参数的东西
深度学习的含义是疯狂的。虽然我给出了相当简单的应用示例,如图像分类和股票价格预测,但最终还有更多!视频合成、自动驾驶汽车、人类水平的游戏人工智能等等——所有这些都来自深度学习。如果你有兴趣了解更多,我写了一篇关于使用深度强化学习玩 doom 的文章——点击下面的链接查看!
地理数据可视化导论
Choropleth map from Wiki
我一直对那些成功地将数据与地理信息结合起来的数字印象深刻。它们是我能想到的最漂亮的数据可视化的例子,你只需扫一眼就能看到的信息令人震惊。
这类图形被称为 choropleth 地图,根据维基的定义:
专题地图,其中区域根据地图上显示的统计变量(如人口密度或人均收入)的测量值成比例地进行着色或图案化
把它们想象成考虑了地理边界的热图。
我们可以使用 plotly 库制作 choropleth 地图。
我们将从一个简单的例子开始。我们进口如下:
**import** plotly **as** py
**import** plotly.graph_objs **as** go
我们希望创建一个“数据”变量,并将其传递到 go 中。Figure()方法生成 choropleth 图。
先来一张大千世界的地图吧!
我们将“数据”变量定义如下:
data = dict (
type = 'choropleth',
locations = ['China','Canada','Brazil'],
locationmode='country names',
colorscale = ['Viridis'],
z=[10,20,30])
“数据”变量是一个字典。我们把它的“类型”定义为 choropleth。在“位置”中,我们给出了各个国家的名称,在位置模式中,我们告诉我们计划通过国家名称指定位置的方法。最后,我们指定色阶和我们希望分配给每个国家的值。
你可以在线或离线运行 plotly,为了避免创建帐户,我将离线运行它。
我们通过以下方式生成图像:
map = go.Figure(data=[data])
py.offline.plot(map)
得到一张世界地图。请注意,当我们将鼠标悬停在一个国家上方时,我们会得到它的名称和指定值。
我们可以通过绘制每个国家的幸福指数,让这张地图变得更有趣,而不是给几个国家任意赋值。
使用来自 2017 年世界幸福报告的数据,我们可以使用下面的代码创建这个数字
**import** plotly **as** py
**import** plotly.graph_objs **as** go
**import** pandas **as** pddf = pd.read_csv("2017.csv")
data = dict (
type = 'choropleth',
locations = df['Country'],
locationmode='country names',
colorscale = ['Viridis'],
z=df['Happiness.Score'])
map = go.Figure(data=[data])
py.offline.plot(map)
生成下图。无需任何统计分析,我们可以自信地说,一些最幸福的国家在欧洲和北美,而一些最不幸福的国家集中在非洲。这就是地理可视化的力量。
现在让我们对美国做一些深入的可视化。
我们首先更改“数据”变量,以便 locationmode 指定美国各州。接下来,我们添加一个“布局”变量,允许我们自定义地图的某些方面。在这种情况下,我们告诉地图集中在美国,而不是显示整个世界,这是默认的。如果你愿意,你也可以关注亚洲、欧洲、非洲、北美或南美。
综上所述,我们使用以下代码为亚利桑那州、加利福尼亚州和佛蒙特州赋值:
data = dict (
type = 'choropleth',
locations = ['AZ','CA','VT'],
locationmode='USA-states',
colorscale = ['Viridis'],
z=[10,20,30])
lyt = dict(geo=dict(scope='usa'))
map = go.Figure(data=[data], layout = lyt)
py.offline.plot(map)
要获得这张地图:
我们现在可以开始做一些有趣的事情了。
众所周知,世界正在经历蜜蜂数量的快速下降。这太糟糕了,因为这将意味着可爱的蜂蜜坚果麦片早餐的终结。我们可以获得每个州的蜂群数量,并使用我们的绘图技能来查看哪些州拥有最多的蜂群。
df = pd.read_csv("honeyproduction.csv")
data = dict (
type = 'choropleth',
locations = df['state'],
locationmode='USA-states',
colorscale = ['Viridis'],
z=df['numcol'])
lyt = dict(geo=dict(scope='usa'))
map = go.Figure(data=[data], layout = lyt)
py.offline.plot(map)
看起来北达科他州拥有最多的殖民地,紧随其后的是加利福尼亚州,在这个国家的其他地方还有很大的改进空间。我们还遗漏了阿拉斯加和右上角几个州的一些数据,但这是该数据集的局限性。
我们已经谈到了幸福和蜂群。现在只剩下失业了。
让我们更深入地研究,而不是看国家或州,我们可以绘制每个州的县。我们将从这里得到每个县 2016 年的失业率数据。
每一个县都可以用一个 5 位数的 FIP 号码来唯一识别。
我们从导入开始,注意这次我们导入了 plotly.figure_factory
**import** plotly **as** py
**import** plotly.figure_factory **as** ff
**import** numpy **as** np
**import** pandas **as** pd
接下来我们阅读 FIP 的数据和失业率
df=pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/laucnty16.csv")
df ['FIPS'] = df['State FIPS Code'].apply(**lambda** x: str(x).zfill(2)) + df['County FIPS Code'].apply(**lambda** x: str(x).zfill(3))
fips = df['FIPS'].tolist()
values = df['Unemployment Rate (%)'].tolist()
由于失业有许多不同的值,我们不希望我们的色标试图代表 1000 个不同的值,我们将其限制为 12 种颜色,如下所示
colorscale=["#f7fbff","#ebf3fb","#deebf7","#d2e3f3","#c6dbef","#b3d2e9","#9ecae1", "#85bcdb","#6baed6","#57a0ce","#4292c6","#3082be","#2171b5","#1361a9","#08519c","#0b4083","#08306b"]
endpts = list(np.linspace(1, 12, len(colorscale) - 1))
并将所有这些参数传递给我们的 choropleth 方法
fig = ff.create_choropleth(fips=fips, values=values, colorscale= colorscale, binning_endpoints=endpts)
py.offline.plot(fig)
得到
哇,多漂亮的地图啊!
使用这样的图表,我们可以快速发现失业率高的地区(用红色圈出)。
对于未来的分析,弄清楚为什么这些地区正经历更多的失业以及可以做些什么将是有趣的。
我希望您喜欢这篇地理数据可视化的快速介绍。如果您有任何问题,或者您有任何想要分享的很酷的地理数据可视化示例,请告诉我。
谢谢!
GPU 优化简介
借助 GPU 的强大功能加速简单的计算任务
Source: Link
大多数涉及大量计算的任务都需要时间,随着数据集变得越来越大,这将变得更加耗时。解决这个问题的一种方法是使用线程。在本文中,我将介绍 GPU 加速,它是如何完成的,以及一个简单的 GPU 任务 API 和一段代码。首先,让我们考虑矩阵乘法的例子。
矩阵乘法
Matrix Multiplication
在上面的场景中,有两个矩阵,一个大小为3×6,另一个大小为6×6。得到的矩阵大小为3×6。因此,对于矩阵的每个单元,将有 6 个计算。总共会有3×6×6多次乘法。因此,我们可以断定,这项任务需要 O(mn ) 的时间量来计算。这意味着,对于一个大小为 2000 x 2000 的矩阵,将有80 亿 次计算完成。这是大量的 CPU 时间!!!。
GPU 简介
通常 GPU 包含大量的处理核心。通常从 384 到几千不等。下面简单对比一下英伟达的部分最新显卡。(来源)
CUDA Core Count
CUDA 代表计算统一设备架构。这些处理器运行速度相对较低,但通过使用大量 alu(算术和逻辑单元)提供了更高的并行性。点击阅读更多。
此图展示了 CUDA 中的线程模型(这与市场上的其他架构(如 AMD)非常相似)。为了简单起见,我们可以假设每个 CUDA 内核或 GPU 内核一次可以运行一个线程。如果我们有一个大的数据集,我们可以把它分成几个部分。一个网格包含几个块,块是另一个矩阵,包含数量与其大小相等的线程。无论如何,因为这是介绍,所以让我们把注意力放在用 JAVA 开发的更简单的 API 上。
想想 GPU
正如我们所讨论的,每个 GPU 核心都能够运行一个单独的线程。开始类比的最简单方法是假设矩阵的每个单元将由单个 GPU 核心来计算。由于所有内核都是并行运行的,因此所有单元都将被并行计算。因此,我们的时间复杂度突然下降到 O(n) 。现在,对于 2000 x 2000 矩阵我们只需要2000次运行,这对于计算机来说是相当容易计算的。通常我们之前讨论的每个线程都知道它的身份,也就是它所属的 块 和 网格 。或者更简单地说,矩阵的单元位置。此外,矩阵将被加载到 GPU 的共享内存中,我们可以通过索引直接访问单元数据并进行并行处理。简单对吗?让我们检查一下代码。
用 APARAPI 进行 GPU 编程
什么?嗯,**APAR API(A-PARallel-API)是 OpenCL 的 JAVA 包装器,OpenCL 是用于编写 GPU 的开放计算语言。这同时支持 CUDA 架构和 AMD 设备。此外,API 将更好的面向对象的 JAVA 带入了画面,如果我们直接用 C++ 跳转到任务,这可能看起来很混乱。开始很容易。有一个 maven 依赖。但是要确保你已经正确设置了 OpenCL 或者 CUDA 。简单的谷歌搜索应该可以帮助你。大多数设备都捆绑在一起( OSX 和 Windows 设备)。
pom.xml
MatrixMultiplication.java
上述代码的详细说明
内核是由 GPU 执行的代码的一部分。内核可见的变量将被复制到 GPU RAM 中。我们以线性阵列而不是 2D 阵列的形式提供数据,因为这是 GPU 支持的方式。这并不是说它们不能处理 2D 数组,而是它们被处理的方式是通过维度的概念(我们现在还不会谈论它)。
Range range = Range.*create*(SIZE * SIZE);
上述代码在 GPU 中分配内存,以便SIZE x SIZEGPU 中运行的线程数量或更少(如可用)。
int row = getGlobalId() / SIZE;
int col = getGlobalId() % SIZE;
上面的代码从线程的私有内存中获取线程的 Id 。有了这个特定线程,我们就可以确定线程的单元位置。对于每个单元格,我们将执行以下操作。
for (int i = 0; i < SIZE; i++) {
d[row * SIZE + col] += a[row * SIZE + i] * b[i * SIZE + col];
}
这是两个矩阵的相应单元的倍数的简单和。我们只是使用线程索引为单个线程定义内核,它将为所有线程并行运行。
结果
它很快。但是有多快呢?。这是上面程序的输出。
1200 x 1200
Starting single threaded computation
Task finished in 25269ms
Starting GPU computation
Task finished in 1535ms
以下仅针对 GPU 组件运行,因为 CPU 的计算时间非常长。
2000 x 2000 任务用时 3757 毫秒 5000 x 5000 任务用时 5402 毫秒
希望你喜欢阅读。请一定要试试!!干杯!!
高维超参数调谐简介
优化 ML 模型的最佳实践
如果你曾经纠结于调整机器学习(ML)模型,那么你读对了。
超参数调整指的是为学习算法找到一组最佳参数值的问题。
通常,选择这些值的过程是一项耗时的任务。
即使对于像线性回归这样的简单算法,找到超参数的最佳集合也是困难的。有了深度学习,事情变得更糟。
优化神经网络(nn)时要调整的一些参数包括:
- 学习率
- 动力
- 正规化
- 退出概率
- 批量标准化
在这篇短文中,我们将讨论优化 ML 模型的最佳实践。这些实践主要在要优化的参数数量超过两个或三个时出现。
网格搜索的问题是
当我们有少量参数需要优化时,网格搜索通常是一个不错的选择。对于两个甚至三个不同的参数,这可能是正确的方法。
对于每个超参数,我们定义一组候选值进行研究。
然后,想法是详尽地尝试单个参数值的每个可能的组合。
对于每个组合,我们训练和评估不同的模型。
最后,我们保留泛化误差最小的那个。
网格搜索的主要问题是它是一种指数时间算法。它的成本随着参数的数量成指数增长。
换句话说,如果我们需要优化 p 参数,并且每个参数最多取 v 值,那么它在 O(vᵖ)时间内运行。
此外,网格搜索在探索超参数空间方面并不像我们想象的那样有效。
再看一下上面的代码。使用这个设置,我们将训练总共 256 个不同的模型。请注意,如果我们决定再添加一个参数,实验次数将增加到 1024 次。
但是,该设置只研究每个超参数的四个不同值。也就是说,我们训练 256 个模型,只探索学习率、正则化等四个值。
此外,网格搜索通常需要重复尝试。以上面代码中的learning_rate_search值为例。
learning_rate_search = [0.1, 0.01, 0.001, 0.0001]
假设在我们第一次运行(256 次模型试验)之后,我们得到了学习率值为 0.01 的最佳模型。
在这种情况下,我们应该通过“放大”0.01 附近的网格来优化我们的搜索值,希望找到一个更好的值。
为此,我们可以设置新的网格搜索并重新定义学习率搜索范围,例如:
learning_rate_search = [0.006, 0.008, 0.01, 0.04, 0.06]
但是如果我们得到学习率值为 0.0001 的最佳模型呢?
由于该值位于初始搜索范围的最边缘,我们应该移动这些值,并使用不同的集合重试,例如:
learning_rate_search = [0.0001, 0.00006, 0.00002]
并且在找到一个好的候选人之后,可能尝试改进范围。
所有这些细节只是强调了超参数搜索是多么耗时。
一种更好的方法——随机搜索
随机选择我们的超参数候选值怎么样?虽然看起来不太直观,但这个想法几乎总是比网格搜索要好。
一点点直觉
请注意,一些超参数比其他参数更重要。
例如,学习率和动量因子比所有其他因素更值得调整。
然而,除了上面的例外,很难知道哪一个在优化过程中起主要作用。事实上,我认为对于不同的模型架构和数据集,每个参数的重要性可能会有所不同。
假设我们正在优化两个超参数——学习率和正则化强度。此外,考虑到只有学习率对这个问题很重要。
在网格搜索的情况下,我们将运行九个不同的实验,但只尝试三个候选的学习率。
Image Credit: Random Search for Hyper-Parameter Optimization, James Bergstra, Yoshua Bengio.
现在,看看如果我们对候选人进行均匀随机抽样会发生什么。在这个场景中,我们实际上在探索每个参数的九个不同值。
如果你还不相信,假设我们正在优化三个超参数。例如,学习速率、正则化强度和动量。
Optimizing over 3 hyper-parameters using Grid Search.
对于网格搜索,我们将运行 125 次训练运行,但只探索每个参数的五个不同值。
另一方面,使用随机搜索,我们将探索 125 个不同的值。
怎么做
如果我们想要尝试学习率的值,比如说在 0.1 到 0.0001 的范围内,我们可以:
请注意,我们是在对数标度上从均匀分布中采样值。
您可以将值-1 和-4(用于学习率)视为区间[10e-1,10e-4]中的指数。
如果我们不使用对数标度,在给定的范围内取样将是不均匀的。换句话说,您不应该尝试对以下值进行采样:
在这种情况下,大多数值不会从“有效”区域中采样。实际上,考虑到这个例子中的学习率样本,值的 72%将落在区间[0.02,0.1]中。
此外,88%的采样值将来自区间[0.01,0.1]。也就是说,只有 12%的学习率候选值,即 3 个值,将从区间[0.0004,0.01]中被采样。不要那样做。
在下图中,我们从范围[0.1,0.0004]中抽取了 25 个随机值。左上角的图显示了原始值。
在右上角,注意 72%的采样值在区间[0.02,0.1]内。88%的值位于范围[0.01,0.1]内。
底部的图显示了值的分布。只有 12%的值在区间[0.0004,0.01]内。要解决这个问题,请从对数标度的均匀分布中对值进行采样。
正则化参数也会发生类似的行为。
另外,请注意,与网格搜索一样,您需要考虑我们上面提到的两种情况。
如果最佳候选落在非常接近边缘的位置,您的范围可能会偏离,应该进行移位和重新采样。此外,在选择了第一个好的候选值后,尝试重新采样到更精细的值范围。
总之,这些是关键要点。
- 如果您有两个或三个以上的超参数需要优化,请选择随机搜索。它比网格搜索更快/更容易实现并且收敛得更快。
- 使用适当的尺度来选择你的值。对数空间中均匀分布的样本。这将允许您在参数范围内对均匀分布的值进行采样。
- 不管随机还是网格搜索,注意你选择的候选人。确保参数的范围设置正确,并尽可能细化最佳候选值。
感谢阅读!要了解更多关于深度学习的酷东西,请查看我以前的一些文章:
[## 如何使用 TensorFlow Eager execution 训练自己的 FaceID ConvNet
人脸无处不在,从社交媒体网站上的照片和视频,到消费者安全应用程序,如…
medium.freecodecamp.org](medium.freecodecamp.org/how-to-trai…) [## 机器学习 101:梯度下降的直观介绍
毫无疑问,梯度下降是大多数机器学习(ML)算法的核心和灵魂。我绝对相信…
towardsdatascience.com](/machine-learning-101-an-intuitive-introduction-to-gradient-descent-366b77b52645)