TowardsDataScience 博客中文翻译 2019(三百五十七)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

我为你的下一个数据科学项目取得巨大成功的第一天惯例

原文:https://towardsdatascience.com/my-potent-first-day-routine-for-phenomenal-success-on-your-next-data-science-project-c96874f4bf16?source=collection_archive---------16-----------------------

在任何项目中度过前 8 个小时的最佳方式

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Mike Enerio on Unsplash

我记得我的第一个数据科学项目。这很有趣,我学到了很多,但最终,这是一场绝对的灾难。回想起来,我意识到我在那个项目的第一天如何度过时间对它的失败有着巨大的影响。在兴奋之余,我跳过了任何大量的探索性数据分析,直奔最复杂、最疯狂的模型。虽然很有趣,但这意味着我在接下来的几周里试图从我的数据和模型中理清头绪。从那以后,我花了很多时间思考一个系统,它能让我有效地利用的第一天来为任何项目的成功做准备

探索性数据分析(是的,即使是深度学习)

说服自己跳过探索性的数据分析,稍后再来做是如此容易。这是一个巨大的错误。这个过程将会影响你以后的所有决定。在你的前 8 个小时里,我会计划花2-4 个小时在这一步上。以下是一些不容错过的要点:

  • 看看你的数据的很多例子。随机选取输入和输出对,看看它们。请注意您是如何处理这些信息的,并记下可能捕获这些模式的潜在特性或模型架构。此外,要注意噪音和腐败,以便适当地将其过滤掉。
  • 利用 PandasSeaborn 的能力计算汇总统计数据、图表和相关性。如果您需要一些灵感,请查看用于数据分析的Python
  • 在 Jupyter 笔记本上整理你的发现,并与同事分享你学到的东西。这是一种获得额外想法和创意的神奇方式。不用担心笔记本的整洁度。花 15 分钟快速整理,再花 15 分钟分享。你会惊讶于另一双眼睛的帮助。

为优化定义单一指标

这一步听起来很容易。每个 Kaggle 挑战和学术数据集都有一个已经提供的单一指标。所以——如果是分类问题, F1 听起来合理,对于回归均方差。完成了。对吗?没那么快。

你在这里选择的指标有着巨大的影响。它将是你用来决定一个模型是否比另一个更好的价值,如果选择不当,会使你误入歧途。花时间考虑一下你实际上想从你的预测中得到什么。例如,我最近参与了一个项目,我们认为这个项目需要极高的精度。现在,很容易以召回为代价来最大化精确度,所以我们也必须定义一个足够的度量标准。一个充分的度量是必须满足的,但不是最大化的。例如,如果至少有 50%的召回率,您可能会决定最大化精确度。

当您考虑优化指标时,证明拥有多个指标是非常容易的。不惜一切代价避免这种情况。实际上,稍后您可能会发现需要额外的度量,但是在第一天,多个度量会给您的过程增加太多的主观性。您需要一个度量标准,或者几个足够的度量标准。仅此而已。

同样重要的是要注意,你不会永远拘泥于你选择的指标。当你对你的问题了解更多的时候,你可以随时做出改变。现在尽你所能做出一个好的决定,然后进入下一步。这个过程通常需要你前 8 个小时中的 30 分钟**。**

智能拆分您的数据

等等——我们不就是用 scikit-learn 的 train_test_split 函数吗?虽然这可能已经足够了,但请花时间考虑以下几点:

  • 你想随机抽样你的数据吗?还是有时间成分需要考虑?例如,如果你想预测股票市场价格,你最好根据时间而不是随机地分割你的数据。否则,你将包括未来的信息。
  • 你想对你的样品进行分层吗?这通常对分类问题很重要。
  • 确保您有一个培训、开发和测试集。你的测试集应该尽可能的长,并且是对你的模型的真正测试。dev 集可用于错误分析和其他优化。如果您只有一个训练集和测试集,您将最终使用您的测试集进行错误分析,并对性能有一个过于乐观的估计。
  • 分割后,花些时间查看单独的样本,并运行一些统计数据,以确保它们似乎都代表问题。例如,如果您的开发和训练集非常不同,您将很难从开发预测中学习。
  • 考虑您的数据对于您想要解决的实际问题的代表性。假设在某个时候你的模型将面向客户,考虑他们将发送给你的服务的数据是否与你拥有的数据相似。比如,如果他们可能不小心给你发了一张倒立的照片,你的训练数据有倒立的照片吗?还是用一个流程来对齐所有的图像?

这个过程可能需要你一个小时。同样,一个小时的时间不足以达到完美,但通常足以打下一个良好的基础。****

建造你的第一个模型!

假设您花了整整 4 个小时进行探索性数据分析,那么到目前为止您已经花了 5.5 个小时。在我们的 8 小时里,还剩 2.5 小时。我们将用 2 个小时让你的第一个模型启动并运行。

定义非机器学习基线

花 15 分钟快速建立一个不涉及机器学习的基线。对于分类,您可以使用最频繁的类作为预测。对于回归,平均值。或者,如果您有明显的组,则按组计算平均值/频率作为您的预测。例如,如果您知道客户的年龄,您可以定义年龄时段并计算每个时段的平均支出,作为新用户在该年龄时段的支出预测。

拥有这个基线模型对于理解你的模型的有效性是非常有效的。

开始异常简单

从最简单的机器学习模型开始。越容易理解越好。例如,用于结构化数据的线性或逻辑回归,或者用于非结构化数据的简单卷积模型或序列模型。您的目标只是在 1 小时内获得模型学习和开发结果。事实上,这必须在一个小时内完成,这应该迫使你保持非常简单。

如果您的数据非常大并且训练需要很长时间,请对训练集进行采样以快速获得一些结果。还是那句话——你希望某样东西能很快见效。

人类基线

随机抽取一些开发集样本,并做出自己的预测。这将是你人类基线的近似值。在这项任务上花大约 30 分钟。

评估

计算你的基线、机器学习模型和人类预测在你选择的指标上的表现。我还发现创建实际值与预测值的散点图来查看相关性非常有用。你应该可以在 15 分钟内完成。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Cathryn Lavery on Unsplash

写出你学到的东西

你的一天还剩下 30 分钟。花点时间写下你在这个过程中学到了什么,以及你想采取的下一步措施。当你第二天回来继续工作时,你会惊奇地发现这是多么的有帮助。如果你有一个共享的 wiki,比如 confluence,确保上传你的研究笔记供其他人访问,以防他们在某个时候研究这个问题。

好了,8 个小时,这是你下一个机器学习项目非常有效的第一天。在短短一天内,您已经对数据建立了良好的理解,定义了可靠的指标,适当地拆分了数据,并评估了多种类型的模型(非机器学习、机器学习和人类)。你现在已经做好了充分的准备,可以开始微调和构建一个真正伟大的数据科学项目。

你也可以在这里找到这篇文章。

我的产品比你聪明!你真的喜欢它吗?

原文:https://towardsdatascience.com/my-product-is-smarter-than-you-do-you-like-it-6c124ee6ff20?source=collection_archive---------37-----------------------

让您的用户控制您的智能产品

相信我,我是个机器人!

在我之前的故事中,什么是产品经理的人工智能,我讨论了精度和召回作为两个主要的 KPI,你需要决定哪一个来优化你的人工智能模型。我讨论了每种方法的影响和好处,以及它如何影响您的产品和客户的体验。
在这篇文章中,我想讨论产品经理在构建基于人工智能的产品时面临的另一个挑战。

控制。我们都喜欢控制,是的,我们是控制狂。我们喜欢控制我们的生活,控制我们的资源,控制我们的时间,控制我们的健康…你明白了吧。没有人真的喜欢惊喜,我说的惊喜是指不想要的惊喜。2000 万美元的彩票仍然是一个受欢迎的惊喜(对我们大多数人来说)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Lane Smith on Unsplash

产品,尤其是好的产品,通过解决问题或创造机会来提供价值。他们被认为是好的,因为他们也给你你正在寻找的控制。例如,时间管理产品试图让你控制你的时间,项目管理产品让你控制你的资源和项目进度(从而帮助你实现你的目标和满足你的期限)。给你 8 岁的孩子一部智能手机可以让你控制他们的行踪。

我失去控制了!

建立一个基于人工智能的产品,一个预测模型,可能非常有前途,但通常它背后的算法是一个黑盒。它需要大量的数据,试图找到相关性和类似的行为来预测接下来会发生什么。然而,模型通常只给出最终结果,即预测。因此,无论它有多准确,有时甚至“太”准确,消费它的结果的用户都不理解理性以及是什么导致了那个决定。结果可能往往是他们不信任。即使他们相信结果,他们也有一个与之相关的问题。从我的经验来看,是因为控制权被他们拿走了。

机器确实变得越来越聪明。他们分析文本和语音,他们可以对你做出回应,他们可以做出决定,甚至是复杂的决定,但我们,人民,人类,用户——必须仍然感觉参与进来,并在某种程度上控制局势,否则我们就不信任它。

这其实并不新鲜。50 年前,当机器和机器人过于逼真时,人们会感到奇怪。日本机器人学教授森昌弘在 1970 年发现了这种现象,并将其称为“恐怖谷”——这是一种常见的令人不安的感觉,当人形机器人与人类非常相似,但不太逼真时,人们会有这种感觉。

让我们看看现实世界中的一些产品,看看人们对它们有什么感觉:

  • 自动驾驶汽车系统 —安装在一些现代汽车上的车道变换辅助(LCA)系统可以防止司机以不安全的方式变换车道。与那些只是提醒和警告你的产品(被动系统)相反,这些是主动系统,当检测到危险时,它们会侵入并控制你的车。该系统使用计算机视觉,非常精确,提高了乘客的安全性。尽管如此,许多司机还是决定关掉它们,因为他们觉得他们不再能控制自己的车了。
  • IT 产品 —几年前,人们认为自动化 IT 人员的所有决策将使他们有时间专注于更复杂和更重要的任务。然而,用户不一定喜欢它,一些公司理解它,并把他们的营销努力放在口号上,如:“收回控制权”
  • WhatsApp 已读回执——WhatsApp 上著名的蓝色标志,让你知道你的信息何时被阅读。这个特性导致了更大的压力,因为用户感觉他们在阅读信息时必须立即回复。移除蓝色指示实际上是将对接收者的时间和可用性的控制交还给接收者。他们的时间和可用性不再由消息的发送者控制。

为什么人们喜欢某些产品?当然是值。但是,如果没有与产品的联系,没有感觉你理解它,没有感觉产品理解你,价值就无法实现。个性化是产品了解你并满足你特定需求的关键因素。这样,你会感觉到更多的情感联系,但也在控制之中。

机器可能很聪明,但绝不可能有创造力!

他们能吗?!几个月前,OpenAI 项目发布了一篇关于他们名为 GPT-2 的文本分析模型的长文。GPT-2 生成合成文本样本,以响应用任意输入启动的模型。该模型适应条件文本的风格和内容。这允许用户对他们选择的主题产生现实的和连贯的延续。在帖子中,他们提到了这种技术可能带来的负面影响,但我想讨论一下它的心理学方面:

  • 如果书是由机器而不是人类作者写的,你会有什么感受?
  • 买书的时候,你是不是只凭书名和摘要来选书?作者传记和“品牌”在决策中重要吗?
  • 你会愿意为一件由电脑在短短几个小时内创作出来的“艺术品”买单吗?它甚至被认为是“艺术作品”吗
  • 计算机能创作出比人更复杂、更全面、更细致的作品吗?

最近的另一个实验项目是为第 64 届欧洲电视网歌曲大赛创作一首歌曲。这首歌是由一台机器根据多年来为比赛创作的最佳歌曲创作而成的。
我们的未来会是这样吗?歌词和旋律会由机器生成?没有哪个艺人会为了写出有史以来最好的情歌而不得不经历令人心碎的分离?我们怎么能联想到一首由点滴而非鲜血写成的歌呢?

那么,我该如何让我的用户信任我的产品呢?

让他们选择。选择的需要感知控制。选择,就是表达一种偏好。一个选择,即使是最小的选择,也会强化控制感和自我效能感。

控制的需要是由生物学驱动的。动物和人类表现出对选择的偏好,即使选择并不能提高结果回报。尽管从经济学角度来看,这可能被认为是不合理的,但行使控制权可能是有益的,因此对于效用最大化而言,这是合理的。

我认为有必要和我两岁的孩子一起选择。通常当我递给他三明治时,他会立刻拒绝。然后,我拿起三明治,把它从中间切成一模一样的两半。现在我两块都拿着,让他选一个他想要的。高兴的是,他选择了一个,然后吃了它。当他吃完后,他通常也会吃下半块。对我来说,结果是一样的(他吃了三明治),对他来说,这是选择和感知控制。

那么,我们如何把控制权交还给他们呢?注意事项:

  • 不要让你的用户觉得他们在这个过程中毫无用处 —人工智能可能会令人生畏,人们不想觉得自己被机器取代。让他们觉得你的产品能让他们把工作做得更好,并把精力集中在更重要的事情上。让他们觉得他们拥有这个过程。
  • 不要只给出底线——如果你希望你的用户基于产品输出(预测)采取行动或做出决定,围绕它建立一个故事。当检查最终结果时,人们不需要他们的决定总是 100%正确。他们真正需要的是能够解释做出这个决定的过程和动机。
  • 不要构建黑盒子— 构建 Magic 听起来可能很酷,但从长远来看,你的用户不会欣赏它。透明度和填补空白是非常赞赏的。

让你的用户相信结果。让他们感觉一切尽在掌握。

非常感谢您的阅读!
随时联系我这里或者通过我的 LinkedIn

我关于自动睡眠阶段分类的美梦

原文:https://towardsdatascience.com/my-sweet-dreams-about-automatic-sleep-stage-classification-414128441728?source=collection_archive---------21-----------------------

睡眠是我们每天能做的唯一最有效的事情来重置我们的大脑和身体健康——大自然母亲对抗死亡的最大努力。(马修·沃克)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Credits: The Funny Beaver

在过去的五个月里,我花了一些业余时间在一个全新的由法国公司 Dreem 提出的挑战上提高我的 ML 技能,该公司的目标是改善每个人的夜晚。睡眠很少受到我们应有的重视,现在对我们的人口有具体和量化的后果。表现直线下降、注意力不集中、记忆障碍……都是睡眠不足的症状。Dreem 的解决方案是一个头带,在晚上主动刺激你的大脑,监控你的睡眠,并提供不同的程序让你轻松入睡。对于那些对睡眠在我们日常生活中的真正重要性有足够好奇心的人,我推荐你 我们为什么要睡觉 作者是马修·沃克,他目前是加州大学伯克利分校的一名教师。这本书在很多方面让我感到惊讶,它提供了很多原则和建议,让你了解并改善你的睡眠,从而改善你的日常生活。

在我的 GitHub 上可以找到比赛使用的所有代码。请随时查看并给我反馈。我将主要讨论是什么让我登上了领奖台的第二名,尽管解决这个问题的可能性是无限的。你还会发现这个代码可以用于更广泛的与时间序列相关的问题,并且它主要面向可解释性。对于最好奇的人,你还会发现更多: DL 架构、**自动编码器、**和TDA复活节彩蛋。尽情享受吧!

睡眠

在进入整个机器学习问题之前,让我们花一些时间来了解我们的背景和我们将不得不处理的多模态源。正如 Dreem 的网站上介绍的那样,他们的头带可以量化你的大脑活动(六个脑电图电极,相当于 F7、F8、O1、O2、Fpz 和一个参考值)、你的头部运动和呼吸(一个三维加速度计)和你的心率(一个脉搏血氧计)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Credits: Dreem

在你睡眠期间,你的大脑会在不同的状态之间振荡,也称为睡眠阶段(如下所示)。每个阶段对应于特定的电模式和特定的脑电波。与睡眠阶段随时间演变相关的图表被称为睡眠图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Credits: http://www.macmillanhighered.com

在过去的几十年里,人们一直希望用自动化的过程来取代那些阶段的基于专家的注释。当你阅读文献时,你会发现当前与这个话题相关的炒作。这正是机器学习发挥作用的地方!

我不会深入细节,但是每个阶段都有一个关于我们大脑健康的特定功能。精确标注这些阶段将使医学领域能够在更大范围内寻找病理和睡眠障碍。得益于强大的数据基础,更大规模(统计上更准确)的流行病学研究将成为可能。最终,人们将能够根据每天监测的真实指标来改善他们的睡眠。这正是 Dreem 所能提供的!此外,由于公司提出在深度睡眠 (3 & 4)期间进行大脑刺激,他们必须尽可能准确地检测δ波,以正确触发它们。

探索性数据分析

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Actual Data extracted from the Train Dataset

D reem 为我们提供了从集成在头带中的多个传感器获得的时间序列。给定信号为 30 秒周期并以不同频率采样。就像有监督的最大似然问题一样,数据被分成一个标注了相应睡眠阶段的训练集(理论上由睡眠科学家给出)和一个测试集。通过快速查看标签的比率,可以观察到这是一个不平衡的多分类问题。信号极值的分布还突出了数据集中存在的大量伪像(基于 EEG 信号的经典范围为-500 至 500 微伏的假设)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Annotations Ratios for the Five Considered Stages

摆弄数据时,我突然发现了一些意想不到的事情:标签实际上是有序的!这意味着数据集是通过个体的不断聚合而建立起来的,这给了我们暂时性的优势。这当然为模型的构建打开了一个全新的领域(GRU、LSTM……)。从我的理解,Dreem 似乎目前正在使用这样的模型(典型的 LSTM 超过 30 个 30 秒的时期)。然而,由于的计算限制(领域中使用的 DL 模型通常是火箭筒)和对可解释性的渴望,我决定将自己限制在良好的老式且健壮的特征工程方法上。

把时间性放在一边,前面的观察使我能够通过根据长时间的清醒(标签 0)分割指数来提取个体本身。下面给出了提取睡眠图的典型例子。一旦提取出来,这些个体就可以聚集成子集来构建健壮的验证集,以便评估我的模型的泛化能力。我最终得到了 88 个不同长度的子集,这可能是对实际人数的高估(这些片段对应的平均睡眠时间为 4.5 小时)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example of one Extracted Hypnogram

描述性特征工程:混沌理论

有趣的(也是最长的)部分来了!我如何最好地描述睡眠阶段分类的 EEG 信号?在查阅文献之后,我收集了关于我的管道的多种描述性见解。结果,每个 30 秒的时期变成了一个 1200 特征向量。我不会详细介绍每个特征(仅仅是因为大多数都是经典的),而是将重点放在为睡眠阶段分类提供最佳性能的特征上。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Relative Feature Importance (Best 30 features for XGBoost)

通常,在上图中,我估计了 XGBoost 模型的 30 个最重要特征的重要性,并将其与 LigthGBM、RandomForest 和 ExtraTrees 获得的相对重要性进行了比较。XGB 型号是我在五重交叉验证中表现最好的型号。(这里的重要性是 5 次折叠所得模型的平均值。)

难怪混沌理论最终成为最重要的理论之一。为什么?因为我们试图对发生事件进行分类:周期性和可预测事件的“低级”混沌;一般不可预测事件的“更高”混沌(例如,纺锤波K-复合波,它们是特定于某些睡眠阶段的模式)。到目前为止,这些特性在我的许多项目中都非常有用,所以我将保留一些行来介绍它们。

李亚普诺夫指数指无限接近的轨迹之间的分离率(一般距离)。它们量化了动态系统(此处为非平稳脑电图)的可预测性,必须将其视为一个频谱。

赫斯特指数指的是长期相关性的指数,因为它通过自相关来量化特定时间序列的长期记忆。

分形维数对应于描述图案细节如何随测量尺度变化的复杂性统计指数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Credits: PyEEG

那些是奇异的特征。我还使用了拟合自回归模型的系数,EEG 之间的距离,分解成小波的**,趋势-残差分解频谱图**来确定频率相关性(因为每个波形图【α、δ、θ波】都有特定且显著的频率)。这给了我一个进入模型构建过程的基础。

水平施工和堆放

特征工程和预处理过程现已完成。我能够区分个人的一些子集,以便建立我的训练集和验证集。为了构建每个模型,我使用了 5 重交叉验证(这意味着我将个体的特定子集放在一边,以进行泛化表征)。

最后,为了得到最终的预测,我做了两个考虑:基于噪声水平的区分和通过叠加的聚集

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example of Coverage for the first 1000 Samples

通常,统计模型会受到噪声的影响。我在这里的方法包括根据特定的度量标准构建训练和测试数据的精选子集。通常,为了定义“噪声水平”,我为每个 EEG 信号建立了三个特征:最大值、最小值和曲线下面积。通过(通过中值)相对三个分布的中心,我可以天真地确定噪声水平对应于距离与实际标准偏差的比率。这个方法让我定义了 5 个级别的噪声,如上图中的覆盖级别所示。没有出现在多个电平的信号极有可能包含伪像。这种限制意味着分别针对每个子集的 5 个不同的训练阶段。然而,这些给了我关于多路输出的水平的信心。最后,通过用更精细级别的预测迭代地覆盖它们自己来获得预测。

一旦这 5 个级别被分离,我就开始训练 4 个不同的模型(如特征工程过程中所介绍的):XGBoost、LigthGBM、RandomForest 和 ExtraTrees。超参数是用我自己实现的 超波段 调的。优化的度量标准是 kappa 分数(可以理解为协议间度量标准),用于对该领域进行基准测试。

Definition of the Kappa score

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Cross-Validation Scores (Kappa Score on Validation Sets) on the 5 Levels of Noise

在每一轮交叉验证中,这 4 个模型给了我训练集、验证集和测试集样本的概率。数据集的不平衡也很重要,并在训练和评分过程中通过权重加以考虑。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Credit: No Free Hunch

结果,我得到了那 4 个模型的概率,这让我想到了叠加。这种方法的动机是结果的多样性,如下面模型之间的预测相关性所示。上图所示的基本方法基本上是将概率作为特征,并将其用作训练、验证和测试集。在这种情况下,我使用线性模型(随机梯度下降)并通过基于个人的交叉验证优化 kappa 指标。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Correlations between Model Probabilities relative to actual Sleep Stages

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Confusion Matrixes for the 4 Models (5 Levels of Noise)

让我们关注一下相关性矩阵:由于(XGBoost,LightGBM)和(RandomForest,ExtraTrees)是相似的结构,它们的预测显然是高度相关的。然而,有两个事实值得注意:

  • 第 1 类(第 1 阶段为少数类)最难预测,且在提升的树木中显示出很小的相关性;
  • 第 3 类(阶段 3 & 4)是最容易预测的(这对于 Delta 波的 Dreem 刺激是一件好事)。进一步的分析将表明,类别 1 通常与类别 4(快速眼动睡眠)混淆,如果 EEG 的范围和形状相似,这是可以预料的。

输出平滑

鉴于之前的结果,我的方法有优点也有缺点。它有两个特别的弱点:该模型没有考虑样本之间的时间关系,并且它在预测睡眠阶段 1 时有困难。阶段 1 仅仅是一个过渡阶段,从清醒状态进入真正的睡眠阶段。我的目标是通过在它的基础上构建一个过滤器来改进之前的模型。我首先考虑的是经典输出平滑,以及带通(保持高频微唤醒并坚持连续睡眠阶段)或平均方法(例如 Savitsky Golay)。然后我转向隐马尔可夫模型,因为这些正是我正在寻找的:转移矩阵。然而,最好的结果来自它的近似值,通过基于 20 个时间步长的过度拟合 LSTM 。LSTM 基于输出概率(我为训练集和测试集收集的概率),并考虑了时间关系。有了它,我可以建立一个转移矩阵(就像 HMM 一样),但是对于连续的输入(概率)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,我改进了睡眠阶段的连续性,保留了微唤醒事件,并强调了过渡阶段 1** 的重要性。**

精神食粮

这就是我在这场比赛中所做的部分工作。可以改进的地方很多,而且可能性是无限的。最终我达到了第二的位置,在私服测试集上的最终 kappa 分数为 70.7 。正如所料,所使用的策略并没有完全保护我免于过度拟合,并且在我的内部分数和排行榜分数之间观察到了明显的差距。在这种医疗保健背景下,涉及个人不可挽回地引起了协变量转移的问题。这个问题一直存在,但我的结果显示了推广的巨大潜力。

我感谢我的爱人给了我关于马修·沃克的书的建议!许多类似的项目来了!敬请期待来稿,想要更多就鼓掌;)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

资源

到目前为止,我在媒体上的数据科学博客之旅

原文:https://towardsdatascience.com/my-technical-blogging-journey-on-medium-till-now-38aa9b9804b6?source=collection_archive---------5-----------------------

以及我如何通过我的技术博客获得了大量的浏览量?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Chris Barbalis on Unsplash

文笔清爽。

在全世界面前展示你的想法。并在此过程中获得想法和灵感。

但是这并不容易。

我第一次开始写博客是在 2014 年。我仍然记得我的第一篇博文。这是一场灾难。

但是我记得它帮助了一些人。这可能是一个好的开始。

我后来的帖子也好不到哪里去,经过大量的练习才达到我现在的写作阶段。

当我开始写作时,在数据和动力方面都有很多起伏。 我主要的动机缺失来自于这样一种观念,即我的作品不能被人们理解

直到 2018 年,我的博客上没有多少读者,虽然许多博客作者会要求你不要考虑这个问题,但让我的内容被阅读对我来说很重要。在某种程度上,这是个人的事情。

Medium 为我提供了一个平台,在这里我可以放下我的想法,并让人们阅读它们。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Views and Stats in Last Month

仅这个月我就获得了大约 36k 的浏览量。怎么会?

这篇文章是关于有效的博客实践,s̶o̶m̶e̶的自我推销和一些关于我写统计数据的分析/数据科学,为什么不呢?。

开始

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

My situation really.

我还记得我第一次来 medium 的时候。那是 2017 年 2 月。我重新利用了我在 medium 上的一些博客,想收集一些观点,获得追随者,并向世界展示我的想法。

这个平台看起来很棒,拥有超过数千的追随者。 但是你猜怎么着?我得到了多少次浏览?

你猜对了。在 100 度左右。我发表了 10 多篇博文。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A Broken Start

2017 年 2 月至 12 月期间,我连续发布了几篇帖子,但没有任何实质性的结果。第一次是在二月到三月,它没有起飞。我在 12 月份又试了一次,但无济于事。正如你所看到的,我的后好的 Kaggle 特征构建技术中只有一个有一些视图,这些视图是在大约一年后的 2018 年 11 月出现的。这不足以让我继续在 medium 上工作,因为我的博客获得了更多的浏览量。 所以我在 2017 年 12 月离开了 medium 一年。

但是我做错了什么呢?

事后看来,我会说,当时我不明白媒体是如何工作的。

中基于出版物。获得视图的是出版物。一开始我并不知道。

但是,什么是出版物呢?你可以看到这篇特别的文章是以“走向数据科学”为标题发表的。TDS 拥有 20.6 万用户,每当我在他们那里发表文章时,它就为我提供了接触这些用户的渠道。对我这样的新手来说,那太难了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The Publication Effect

当谈到写作,特别是技术写作时,媒体有许多活动的部分。

因此,以下是我根据自己在这个平台上的经历对 Medium 的一些观察:

  • **总是为出版物写作。**我指的是永远。
  • 用你写的任何出版物来建立声誉。有时编辑会在他们的首页发表你的文章。为此感谢他们。在这一点上,感谢 Ludovic Benistant 为我的一些帖子做了特写。仅出版物中的一个特征就能吸引大量的浏览。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

My posts are on Chatbots and Kaggle Learnings

  • 给你的帖子贴上一些高收视率的标签。如果你不知道该写哪些标签,可以看看高产作者的标签。
  • 关于这一点,跟随一些在媒体上成功的作家,试着理解他们成功的原因。我跟随威尔·科尔森卡西·科济尔科夫。如果你这样做,你会学到很多关于媒介的知识。例如,我注意到大多数优秀的作家都是用短句而不是段落来写作。或者他们如何运用幽默。或者他们是如何把事情分解成更小的更容易理解的部分。这一点本身就证明了我不是一个好作家(既然这么长)。但是我正在努力改进。
  • 在你的文章中使用好图片,使用高清晰的图片。在我最初的几篇帖子中,我没有利用这个工具。目前,我在媒体编辑器中使用 Unsplash 的图片。您也可以尝试 Pixabay 来获得高质量的图像。
  • 尽量让你的帖子被策展人分发给主题。还有一些指引。跟着他们。下面是我在《数据科学》杂志上发表的一篇文章。感觉真好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The story as it got featured in Data Science Topic in Medium.

  • 媒体不是科学期刊。解释数学对某些人来说可能很有效,但对我来说,写直觉最有效。我想说这取决于你的写作风格,你应该努力找到自己的位置。
  • 为你的帖子使用字幕,并为你的帖子添加合适的图片。你的帖子看起来像样是至关重要的。感谢 Ludovic Benistant 的提示。
  • 尽量让你的内容有创意。例如在这篇关于 shell 基础知识的文章中,我用 gif 展示了 shell 是如何工作的。或者在这篇文章中,我如何试图厚颜无耻地使用标题。标新立异。做写作是为了什么。这很有趣。

写什么就写什么。这很有趣。

  • 写各种各样的话题。防止无聊,提高你的写作,甚至可以说让你成为一个更好的人。目前,我写 NLP,编程,可视化,数据科学。这个帖子本身就是试图增加我的话题覆盖面。
  • **写很多。**有时它不会自然而然地出现。我遵循的系统是尝试每天写 x(500)个单词。开始写一些 jibberish,你会注意到当你开始写的时候,你不会停留在 x 个单词上。永远不会。我已经写了 900 字了。我的脑子里充满了想法,所以很难停下来。记住,只有开始写,才很难停下来。

记住,只有当你开始写的时候,才很难停下来。

  • 在发布之前,反复阅读你的文章。也许在第二天。一个普通的提示,但很重要。
  • 最后,为你的观众创造一些有价值的东西。没有它你将一事无成。互联网上有很多信息渠道,让你与众不同的是你自己的观点。无畏地把它展示给全世界。记住,对你来说很自然的事情对别人来说可能不会那么快。让他们更容易。

互联网上有很多信息渠道,让你与众不同的是你自己的观点。

接下来发生了什么?

所以回到这个故事。直到 2017 年 12 月,我在媒体上一次又一次失败。直到 2018 年 11 月,我几乎没有任何观点。

我几乎已经忘记了 Medium,但它在 2018 年 12 月再次引起了我的注意,当时我注意到我的一篇文章在 Kaggle 发推文后成为了热门话题。

我在某种程度上欣喜若狂。我的文章被 Kaggle 发推特了。不错!

得到卡格尔的认可正是我需要的那种动力。这促使我更加努力地写作。

我开始写更多。发表了一些我的文章,这些文章在我的草稿文件夹里积了很长时间的灰尘。

几家出版社联系了我。但是 主要的转折点是作为一名作家被 TDS 接受。

我突然开始有了看法。我的文章开始按主题分类,人们开始阅读我创作的内容。

我现在很开心,所以我写了这篇文章。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The stats after writing for publications

在上面的部分,我提供了一个定性经验的列表。现在让我们谈谈数字。

是什么让一篇文章成功?

粉丝数量是一篇文章成功的合理代表。

让我们来看看哪个因素对某篇文章获得更多粉丝至关重要。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里信息不多。被怀疑的浏览量和阅读量与粉丝数量高度相关。

**数据科学主题>机器学习主题:**从关联图中,我们可以看到,如果我的文章在数据科学中得到策划,那么与在机器学习中得到策划相比,它有很大的机会获得更多的粉丝/视图/阅读数。

此外,如果一篇文章在数据科学中被策划,它在编程中被选中的机会就非常小,反之亦然。基于有限的,可能是有偏见的样本,我的职位只有,我们在这里。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

How the Cumulative views increase

写这篇文章的时候,我的终身浏览量刚刚低于 10 万。希望我通过这篇文章。

未来?

我已经每天统计我的观点。

为什么不建立一个模型来预测未来呢?我们当然是数据科学家。

我将使用脸书的fbprophet软件包来做这个时间序列分析。我喜欢这个包,因为它很简单。没有 ARIMA,萨里玛,自相关图。

只是一个非常干净的 API 来解决你的问题。时间序列模型的五条线。

import fbprophet
model = fbprophet.Prophet()
model.fit(df)
df_future = model.make_future_dataframe(periods=360)
df_predicted = model.predict(df_future)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Monthly predicted views from the model

该模型预测到 2019 年底将有 65,000 次观看。我会更新这篇文章,看看我的预测是否与结果相符。

我们还可以发现工作日对日常视图的影响。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Daily predicted views from the model broken down in components

在这里我们可以看到趋势主导着我们的日常观点并且它还在持续增长。趋势在某种程度上定义了我们的基线观点。这是一件好事,它正以如此高的速度增长。

我们还可以看到,周一比其他任何一个工作日都有更多的浏览量。再次期待,因为这是本周的开始。人们有动力去阅读。

所以周日写,周一发表。检查!

结论

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这篇文章详细介绍了我作为一名作家在 medium 上的旅程。我试着给有抱负的博客写手提供一些技巧和方法,以增加他们的覆盖面,并在媒体上写得更好。

这是一系列的失败,然后我在媒体上取得了小小的成功。希望我能通过让别人知道我的错误来帮助他们。

我也对自己的 medium stats 数据做了一个非常简要的分析。目前我可能没有很多追随者或观点,但我仍在努力,并获得一些不错的追随者。

很抱歉写了这么长的帖子,但你一开始就知道你会遇到什么。当布兰告诉提利昂他的故事很长时,他说:

要是我们被困在一座城堡里就好了,在隆冬时节,无处可去。

将来我也会写更多关于写作的文章。在 关注我,或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系

最后,虽然这一节的标题可能是“结论”,但它不是。这仅仅是开始。

我的十大数据科学 Python 包

原文:https://towardsdatascience.com/my-top-10-python-packages-for-data-science-2dee7f3dee94?source=collection_archive---------21-----------------------

在 4 年前从 SAS 跳到 Python 之后,我再也没有回头。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Kira auf der Heide on Unsplash

在过去的 4 年里,我已经从专门使用 SAS 完成所有数据处理和统计建模任务过渡到使用 Python 完成这些任务。我必须克服的一个障碍是不断发现和学习使用开源社区提供的所有优秀的软件包。

采用这些开源包有很多好处,包括:

  1. 一切都是免费的
  2. 最有可能的是,它们在不断更新和改进
  3. 在像 Stack Overflow 这样的网站上,有一个很大的社区提供相互支持

熟悉这些包确实需要一些时间。然而,如果你是那种对学习新事物充满好奇/兴奋的人,你会很享受这个过程。

今天,我将分享我的 10 大数据科学 Python 包,按任务分组。希望你觉得有用!

数据处理

熊猫

Wes McKinney 在十多年前开发的这个软件包提供了强大的数据处理能力。对于有 SAS 背景的人来说,有点像 SAS 数据步骤。你可以进行排序、合并、过滤等操作。关键的区别是在 pandas 中,你调用一个函数来执行这些任务。

顺便说一下,我真的很惊讶地知道韦斯·麦金尼(Wes McKinney)在只有几年 Python 经验的情况下就能开发出熊猫。有些人真的很有天赋!

如果你刚刚开始你的 Python 数据科学之旅,强烈推荐他的书 Python for Data Analysis

numpy

Pandas 建立在这个包 numpy 之上。所以当你经常依赖这个包进行基本的数据操作时。例如,当您需要根据客户的年龄创建一个新的列时,您需要执行如下操作:

df['isRetired'] = np.where(df['age']>=65, 'yes', 'no')

qgrid

一个惊人的软件包,允许你在 Jupyter 笔记本中排序、过滤和编辑数据框。

绘制图形

接下来的三个包都与绘图有关,这是探索性数据分析的关键步骤。

matplotlib

这个软件包允许你做各种各样的图表。如果您在 Jupyter 笔记本中使用它,请记住运行这行代码来显示图形:

%matplotlib inline

seaborn

在这个包的帮助下,你可以使 matplotlib 图看起来更有吸引力。

阴谋地

如今,我们到处都能看到交互式图表。它们确实提供了更好的用户体验。

当我们将鼠标悬停在线图上方时,我们希望会弹出一些文本。当我们选择一条线时,我们希望它能从其他线中脱颖而出。有时我们想放大图表的一部分。这些都是交互式图表大放异彩的领域。

plotly 允许您使用 Jupyter 笔记本轻松构建交互式图表。随着时间的推移,我看到了向利益相关者发送带有漂亮图表的 Jupyter 笔记本的巨大潜力。

建模

统计模型

这个软件包允许你建立广义线性模型( GLM s),这些模型至今仍被精算师广泛使用。

它还提供时间序列分析和其他统计建模能力。

scikit-learn

这是主要的机器学习包,允许您完成大多数机器学习任务,包括分类、回归、聚类和降维。

我还使用模型选择和预处理功能。从 k 倍交叉验证到缩放数据和编码分类特征,它提供了如此多的功能。

lightgbm

这是我最喜欢的梯度推进机的机器学习包之一( GBM )。我在 2018 年数据分析研讨会上做了一个关于这个包的演讲

只需花费构建 GLMs 所需的一小部分时间和精力,您就可以运行 GBM,查看重要性矩阵,找出您的模型最重要的特性,并对问题有一个良好的初步理解。这可以是一个独立的步骤,也可以是在构建一个更容易被涉众接受的完整的 GLM 之前的第一步。

石灰

对于像 GBM 这样的机器学习模型来说,模型解释仍然是一个挑战。当涉众不理解一个模型时,他们就不能信任它,结果,就没有采用。

然而,我觉得像 lime 这样的模型解释包正在开始改变这一点。它允许您检查每个模型预测,并找出驱动预测的因素。

结论

我列出了我最喜欢的 10 个包。你遇到过其他有用的软件包吗?请在下面分享你的评论。

"探索确实是人类精神的精髓。"弗兰克·鲍曼

我的前 3 个 SQL 面试问题

原文:https://towardsdatascience.com/my-top-3-sql-interview-questions-8a42597e8505?source=collection_archive---------2-----------------------

我经常面试数据分析师、数据工程师和数据架构师职位的候选人,有时也会参加应用服务器/微服务开发人员的面试。

在我开始面试之前,我总是会想起一个朋友关于面试的名言 “一个傻瓜能问的问题比一个聪明人能回答的还要多”。他在我参加第一次面试前告诉我这件事,我以为他是为了让我放松。随着时间的推移,我意识到他的意思更多。现在,回过头来看,我认为有朋友向你灌输让你永远脚踏实地的道理肯定是有帮助的!

参加面试时,面试官试图用边缘案例或经验教训来迷惑和掩盖候选人,这让我经常摇头,思考面试的真正意图是如何被挫败的。面试官处于权力地位的观念是非常错误的。

对我来说,面试与其说是关于具体的语法,不如说是关于评估候选人对概念的理解、问题解决方法的应用、从错误中学习的能力、测试和验证的方法,以及这个人在多大程度上是一个团队成员。

TL:DR 版本:前 3 个 SQL 面试问题(初级、中级、有经验)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Interview stock image (Photo by Amy Hirschi on Unsplash)

Q1:如果你在 SQL 查询的每一个子句中都打了一个错别字,那么第一个错误会是什么?

这个问题适用于初学者,或者那些将 SQL 作为第二语言的人,通常是 Java、JS 或 dotNET 开发人员。

下面是一个查询示例(每行加 1 表示输入错误)

SELECT count(e.empno1) count_emp, d.dname

FROM emp1 e

INNER JOIN dept d on e.deptno = d.deptno

WHERE e.sal1 > 2000

GROUP BY d.dname1

ORDER BY count_emp1;

问题的答案总是 FROM 子句。为什么?因为 SQL 是关于集合的。以下是用简单英语写的查询。

根据部门名称匹配到部门的员工集,

筛选薪资大于 2000 的,

按部门名称分组,并统计每个部门的员工数,

选择员工人数和部门名称

根据员工人数对结果进行排序。

理解这个流程让我确信候选人了解足够多的 SQL 概念,并且知道 SQL 来自集合论。

从选择开始不是正确的方法。

总的来说,考生思考集合和关系理论是很重要的。

Q2。可以使用 IN 或 EXISTS 将 SQL 查询重写为连接查询吗?它如何影响性能?

这个问题的目标是中级经验丰富的数据库专业人员或那些在数据处理应用程序中工作过一段时间的人。

这个问题的关键是查询重写。当您重构查询或者从一个数据库平台迁移到另一个数据库平台时,查询等价和重写非常重要。它展示了你对 SQL 的理解,你将被认为是一个独立的数据库开发人员。

IN、EXISTS 可以用内部联接代替,但有一些注意事项。

  1. 如果 in 或 EXISTS 中的数据集有多行,则联接将导致比预期更多的行。
  2. IN 或 EXISTS 的处理方式会有所不同。IN 和 EXISTS 有时可能会被查询优化器重写为一个连接。在某些情况下,In 或 EXISTS 子查询将被具体化。但如果不是,它将在外部查询的每一行中被处理。
  3. 在这两种情况下,索引和数据存储位置将在处理方式上扮演重要角色。

我希望人们从他们所工作的数据库的经验谈起,他们在每个数据库平台和配置方面的经验——索引、物化视图、Vertica 投影、SQL Server Columnstore 索引、Oracle 中的混合列存储、红移排序键、Teradata MPP 处理——对了解候选人很有价值。

Q3。解释并讨论散列连接和排序合并连接之间的区别,以及您所使用的数据库是如何处理它们的。

这一个是针对稍微更有经验的数据库专业人员。

理解查询中的连接是如何处理的,阅读查询计划,试图弄清楚数据库是如何处理查询的,总是有经验的工程师应该关注的事情。后续问题可以是检查之前和之后的表现。建立了什么样的测试或验证框架来衡量绩效?如果涉及到查询重写,那么确保数据正确性的验证机制是什么?

谈论经历过的情况,从这种情况中学到的东西,如何处理这种情况,有助于更好地了解候选人。

像以前一样,每个数据库和查询处理引擎都有自己的挑战和选项。一个能够深入讨论问题,并展示出系统思考方法的候选人显然会受到青睐。

结论

有人会说,写下这些问题,我已经亮出了我的底牌。然而,同样的概念可以用其他问题来检验。字面上的问题无关紧要。

我觉得有必要提出这些问题,因为网上大多数 SQL 面试问题的范围从“解释第三范式”到“查找重复记录”。网上的这些问题没有一个真正涉及查询处理的概念,理解数据库技术,或者检查从业者的理解深度。

参考资料和进一步阅读

  1. Faroult,s .和 Robson,P. (2006 年)。SQL 的艺术。奥莱利媒体公司。
  2. 埃文斯朱莉娅。 SQL 查询不以 SELECT 开头— Julia Evans ,jvns . ca/blog/2019/10/03/SQL-Queries-Don-t-Start-with-SELECT/。

用 Python 理解列表的意义

原文:https://towardsdatascience.com/my-trick-to-learning-list-comprehensions-in-python-8a54e66d98b?source=collection_archive---------15-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

快速浏览列表

当我开始探索 Python 时,列表是我学到的第一件事,不久我就意识到它们是编程语言的一个常用特性。Python 语言中的列表是有序且可变的数据结构,它包含存储在一组括号[]之间的项目集合。列表可以包含重复项,列表中的单个项可以通过使用相应的索引值来调用,从[0,…,n]开始。列表中的项目可以被删除、更改或添加,使列表成为一种适应数据的方式。有大量的资源可以帮助你学习更多关于 python 列表的知识,但是这里有一个例子:

#example list
color_list = ["green", "red", "blue", "yellow"]

从列表理解开始

使用列表的一种“python 式”方法叫做*列表理解。*list comprehension 是一个语法结构,它允许您基于现有列表创建一个列表。一般语法如下:

#new_list = [(output value)(for loop)(logical conditions)]#example list comprehension
green_list = [color for color in color_list if color == 'green']

列表理解可以极大地减少完成一个操作所需的代码量。例如,这是使用 For 循环代替列表理解的相同逻辑:

green_list2 = []
for color in color_list:
    if color == 'green':
        green_list2.append(color)

我的尤里卡!列表理解的时刻

在我开始学习 Python 之前,我对 SQL 很熟悉,并且每天都在工作中使用它。 SQL(结构化查询语言)常用于管理 MySQL、微软 SQL Server 等关系数据库中的数据。当我还是一个 python 初学者时,列表看起来相当简单,很容易在很多方面应用,但是列表理解对我来说很难理解。我被这种语法吓倒了,所以我避免使用它们。有一天,在做 python 练习时,我在写一个列表理解,突然意识到语法类似于 SQL SELECT 语句。这是一个尤里卡!给了我信心,让我变得有创造力。

#SQL select statement example
#SELECT color FROM color_list WHERE color IN ('green', 'red', 'blue')#list comprehension selecting the same data as the SQL statement
rgb = [color for color in color_list if color in('green', 'red', 'blue')]
print(rgb)

很容易看出列表理解如何类似于 SQL select 语句。

更多列表理解

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在我灵光一现之后,学习理解列表变得容易多了。虽然这是一个强大的工具,但是有一些事情需要记住。列表理解可以重写为 for 循环,但不是每个 for 循环都可以写成列表理解!此外,就可读性和可维护性而言,写出 for 循环可能是有意义的。
这里还有几个使用列表理解的例子:

使用列表理解映射值的两种方法

#create numeric indicators for colors
color_indicator = [0 if color == 'green'else 1 if color == 'red' else 2 if color == 'blue' else 3 for color in color_list]
print(color_list)
print(color_indicator)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

color_mapping = {'green': 0, 'red': 1, 'blue':2, 'yellow':3}
color_indicator2 = [color_mapping[color] if color in color_mapping else 'na' for color in color_list]
print(color_list)
print(color_indicator2)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

查找长度为 n 的项目

假设我们想在列表中查找长度超过 5 个字符的所有颜色

long_color_words = [color for color in color_list if len(color) > 5]
long_color_words

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在逻辑之间复制也很简单。我们可以找到长度在 4 到 6 之间的所有颜色:

color_length5 = [color for color in color_list if len(color) > 4 and len(color) < 6]
color_length5

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

嵌套循环

您可以嵌套循环来执行操作并返回矩阵。这里我们创建了一个颜色属性矩阵:

color_list1 = ['green', 'red', 'blue', 'yellow']
color_list2 = ['dark', 'bright', 'tinted', 'glowing']color_matrix = [[color2 + ' ' + color1 for color1 in color_list1] for color2 in color_list2]
color_matrix

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结束语

希望这有助于理解 Python 列表,并给你一个简单的方法去思考它们,如果它们起初看起来令人生畏的话。它们是处理列表数据的优雅而强大的方式,因此理解它们是在 Python 中前进的重要一步。将列表理解视为 SQL Select 语句帮助我理解了这个概念,并帮助我更自信地探索其功能。

谢谢大家!

—埃里克·克莱本

深度学习—带有 Keras 的德国交通标志数据集

原文:https://towardsdatascience.com/my-tryst-with-deep-learning-german-traffic-data-set-with-keras-87970dfb18b7?source=collection_archive---------3-----------------------

纽约数据科学院提供的深度学习课程非常适合让您开始深度学习之旅,并鼓励您做一个成熟的深度学习项目。我决定用德国交通标志数据集做一个图像识别的挑战。我以前从未从事过图像识别,因此这个项目对我个人来说是一次很好的学习经历。

问题陈述和项目目标

德国交通标志基准 是在国际神经网络联合会议(IJCNN) 2011 上举办的多类别、单幅图像分类挑战赛。

[## 德国交通标志基准

J.Stallkamp,M. Schlipsing,J. Salmen,C. Igel,《人与计算机:交通领域的基准机器学习算法》。

benchmark.ini.rub.de](http://benchmark.ini.rub.de/?section=gtsrb&subsection=news)

交通标志检测是一个高度相关的计算机视觉问题,是汽车等行业许多应用的基础。交通标志在颜色、形状以及象形图或文字的存在方面可以提供不同类别之间的各种变化。

在这个挑战中,我们将开发一种深度学习算法,该算法将在德国交通标志图像上进行训练,然后对未标记的交通标志进行分类。深度学习模型将使用 Keras(tensor flow 的高级 API)构建,我们还将了解使用 OpenCV 预处理图像的各种方法,并使用云 GPU 服务提供商。

我们将与 Keras 合作构建算法。选择 Keras 是因为它易学易用。Keras 还与 TensorFlow 无缝集成。继 Tensorflow 之后,Keras 似乎是深度学习社区广泛使用的框架。

该项目的全部代码可以在我的 GitHub 账户上找到。

[## nav Kris h04/德语-交通标志-分类

用于图像识别挑战的深度学习算法-nav krish 04/德国-交通标志-分类

github.com](https://github.com/Navkrish04/German-Traffic-Sign-Classification)

算法流程

类似于任何机器学习模型建立过程,我们也将执行相同的黄金步骤定义如下

  1. 了解数据
  2. 预处理数据
  3. 构建模型的架构
  4. 测试模型
  5. 重复相同的过程,直到获得最佳结果
  6. 部署模型(本练习不考虑)

数据理解

图像数据集由 43 类组成(独特的交通标志图像)。

训练集有 34799 幅图像,测试集有 12630 幅图像,验证集有 4410 幅图像。

# Understand the data
print("Training Set:", len(X_train))
print("Test Set:", len(y_test))
print("Validation Set:", len(X_valid))
print("Image Dimensions:", np.shape(X_train[1]))
print("Number of classes:", len(np.unique(y_train)))
n_classes = len(np.unique(y_train))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Sample Images

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Class distribution

我们将在预处理阶段处理的数据中的几个推论

a)阶级偏见问题,因为一些阶级似乎代表性不足

b)对于许多图像,图像对比度似乎较低

建立没有任何预处理的分数

在不做任何预处理的情况下,理解你的模型所处的位置总是一个好的实践,因为这将帮助你为你的模型建立一个分数,你可以在每次迭代中改进它。我们模型的评估标准是“准确性得分。我受到资源限制,在我的 mac (8GB RAM)上运行测试模型,因此使用简单的“密集”或“完全”连接的神经网络架构进行基线评分和其他测试。

密集网络架构

model = Sequential()
model.add(Dense(128, activation='relu', input_shape=(32*32*3,)))
model.add(BatchNormalization())
model.add(Dense(128, activation='relu'))
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(128, activation='relu'))
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(128, activation='relu'))
model.add(BatchNormalization())
model.add(Dense(n_classes, activation='softmax'))

model = Sequential() 语句加载网络。输入形状是 3232 3 (因为图像有 3 个颜色通道)在 Keras 中,没有特定的输入层命令,因为输入图形是隐式输入层。第一层上的参数数量将是393344((32 * 32 * 3 * 128)+128)。我们可以用同样的方式计算其他层的参数数。

激活功能为**“relu”**。在超参数优化过程中,我们可以检查 Tanh、Sigmoid 和其他激活函数是否更适合该任务。现在我们坚持“relu”。

具有 relu 激活的 128 个神经元的 4 个隐藏层,并且在除了最后一个隐藏层之外的每个隐藏层之后,包括一个 dropout(50%)函数。

输出层具有 softmax 激活,因为我们正在处理多类分类,有 43 个类。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

该模型能够在没有任何预处理的情况下实现 84% 的准确度分数。

数据预处理

现在我们手头有一个分数,让我们了解预处理图像是否会导致更好的准确度分数并帮助我们的模型。

数据增加用于增加训练集数据。扩充数据基本上是从可用的图像中创建更多的图像,但是对图像有轻微的改变。我们通常需要与输入神经网络的参数成比例的数据。

我发现 OpenCV 非常适合图像预处理。下面是使用 OpenCV 和 Python 实现的通用教程的链接。在该过程中使用的一些技术是旋转、平移、双边滤波、灰度和局部直方图均衡化。

[## OpenCV-Python 教程简介- OpenCV-Python 教程 1 文档

对于开始为开源项目做贡献的新生来说,这将是一个很好的任务。只需将 OpenCV 插入…

opencv-python-tutro als . readthedocs . io](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_intro/py_intro.html)

**图片轻微旋转:**我用的是图片 10 度旋转。旋转图像的次数超过这个数目是没有意义的,因为这可能会导致交通标志的错误显示。让我们在轻微旋转后查看一些图像(在一些图像中也不明显)

M_rot = cv2.getRotationMatrix2D((cols/2,rows/2),10,1)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Images after 10 degree rotation

**图像翻译:**这是一种移动图像位置的技术。通俗地说,如果图像的位置是(x1,y1)位置,平移后它就移动到(x2,y2)位置。正如你从下面的图片中看到的,位置稍微向下移动了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Images after translation

**双边滤波:**双边滤波是对图像进行降噪、边缘保持平滑处理。

**灰度化:**图像的灰度化是为了减少提供给像素的信息,同时也降低了复杂度。

def gray_scale(image):

    return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

**局部直方图均衡:**这样做是为了增加图像的对比度,因为我们在“数据理解”过程中发现图像可能需要增加对比度。

def local_histo_equalize(image):

    kernel = morp.disk(30)
    img_local = rank.equalize(image, selem=kernel)
    return img_local

这是所有预处理后的图像。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Images after preprocessing

**使用数据扩充解决类别偏差:**我们将使用数据扩充增加训练集图像,解决类别偏差问题也是有意义的。因此,在扩增过程中,所有的班级都有 4000 张图片。在原始数据集中,类别 2 具有最大数量的训练图像,有 2010 条记录。数字 4000 (Max class records * ~2)是我为了让所有类都有相同数量的记录而取的任意数字。我们肯定可以进一步研究这个分布。

下面的代码片段使所有的类都拥有我们需要的相同数量的记录。

for i in range(0,classes):

    class_records = np.where(y_train==i)[0].size
    max_records = 4000
    if class_records != max_records:
        ovr_sample = max_records - class_records
        samples = X_train[np.where(y_train==i)[0]]
        X_aug = []
        Y_aug = [i] * ovr_sample

        for x in range(ovr_sample):
            img = samples[x % class_records]
            trans_img = data_augment(img)
            X_aug.append(trans_img)

        X_train_final = np.concatenate((X_train_final, X_aug), axis=0)
        y_train_final = np.concatenate((y_train_final, Y_aug)) 

        Y_aug_1 = Y_aug_1 + Y_aug
        X_aug_1 = X_aug_1 + X_aug

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Class distribution after fixing class bias

数据扩充和修正类别偏差后的模型得分:

与上面使用的相同的密集神经网络架构能够在数据预处理后将其准确度分数提高到 88.2% ,这向我们表明图像的预处理(扩充数据)是值得努力的。

卷积神经网络

模型构建之旅的下一步将是使用一个更加复杂的架构来提高我们的模型性能。计算机视觉领域的研究已经确定,卷积神经网络在图像识别挑战方面表现得非常好,因此应该是首选。我们的项目目标是系统地建立一个深度学习模型,并了解每个步骤如何影响模型性能。因此,CNN 最初并没有被使用。解释 CNN 的工作也超出了本文的范围。这里有一篇直观的文章。

[## 卷积神经网络直观指南

在这篇文章中,我们将探讨卷积神经网络(CNN ),并在一个高层次上,通过他们是如何…

medium.freecodecamp.org](https://medium.freecodecamp.org/an-intuitive-guide-to-convolutional-neural-networks-260c2de0a050)

卷积神经网络架构

这是模型的卷积神经网络架构

model_conv = Sequential()
*## If You preprocessed with gray scaling and local histogram equivalization then input_shape = (32,32,1) else (32,32,3)*
model_conv.add(Conv2D(32, kernel_size=(3, 3),activation='relu', input_shape=(32, 32, 1)))
model_conv.add(MaxPooling2D(pool_size=(2, 2)))
model_conv.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
model_conv.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model_conv.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
model_conv.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model_conv.add(Dropout(0.25))
model_conv.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
model_conv.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model_conv.add(Dropout(0.5))
model_conv.add(Flatten())
model_conv.add(Dense(128, activation='relu'))
model_conv.add(Dropout(0.5))
model_conv.add(Dense(n_classes, activation='softmax'))

有 4 个卷积层+最大池层。卷积层的核大小是(3,3)。内核指的是过滤器的大小。使用的一般尺寸是(5.5)或(3.3)。

这里要注意一点,输入形状是(32,32,1)。在密集网络中,我们有(32,32,3),因为我们没有做灰度。因为我们对图像进行了灰度调整,通道值将变为 1。

添加了一个池大小为(2,2)的最大池层,并进行批处理规范化。最大池层数用于减少维数,这有助于缩短训练时间,也有助于减少过拟合。

那么在输出层之前也有两个完全连接的层。请注意,我们需要在这一层之前展平输出,因为预期的输入是一维向量。

因为这是一个多类分类,所以使用 solftmax 激活。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

CNN Architecture

我在我的电脑上运行这个模型达 100 个时期,花了 4 天完成(很好奇它运行了多久)。模型评分提升至 **97.2%。**某种程度上解释了围绕 CNN 的炒作。

现在,购买一些 GPU 来加快处理速度或者去云服务提供商那里试验不同的架构更有意义。我发现FloydHub在这方面非常优秀。使用 Floydhub 非常简单。我们只需要上传数据集,通过 GitHub 导入 Python 代码或者手动上传代码即可。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,整个代码只需大约 15 分钟就可以运行,我可以肯定地用不同的架构进行测试。

前进的道路

这种从零开始构建深度学习模型并遵循该过程来构建模型的体验是一种很好的学习体验。在这段旅程中,我每天都在不断学习新的东西,尝试新的改进。接下来要实施的几个步骤是

  1. 确定最佳架构和最佳超参数。也可以试试 AlexNet 或者 VGGNet。
  2. 使用迁移学习

MySQL:如何编写一个查询来返回一个组中的前几条记录

原文:https://towardsdatascience.com/mysql-how-to-write-a-query-that-returns-the-top-records-in-a-group-12865695f436?source=collection_archive---------5-----------------------

本文将向您展示 MySQL 5.7 中的一个简单查询示例(以及在 MySQL 8.0 中使用 rank() 函数的示例),该示例将返回订单表中每月前 3 个订单。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果您曾经想要编写一个查询来返回一个组或类别中前 n 条记录,那么您就找对了地方。随着时间的推移,我偶尔需要这种类型的查询,并且我总是以过于复杂的多查询联合工作结束,或者只是在代码中迭代结果集。这两种方法效率都很低,而且(现在回想起来)很愚蠢。

在我寻求学习新的数据库查询技术的过程中,我遇到了 MySQL 8.0 中的 rank()函数,它使这项工作变得非常简单。但是在 MySQL 5.7 和更早的版本中,有一个同样简单的技术可以解决这个常见的难题。

让我们直接进入例子。

样本表

首先,我们将为我们的示例构建一个示例数据库表。这是一个简单的订单表,跨越了四个月的三个不同的客户。它包括一个作为主键的 ordered GUID,并包含订单号、客户号、客户名称、订单日期和订单金额。

我们将在两个 MySQL 版本示例中使用同一个表:

CREATE TABLE orders(
  id BINARY(16),
  order_number INT,
  customer_number INT,
  customer_name VARCHAR(90),
  order_date DATE,
  order_amount DECIMAL(13,2),
  PRIMARY KEY (`id`)
);

INSERT INTO orders VALUES 
  (UNHEX(‘11E92BDEA738CEB7B78E0242AC110002’), 100, 5001, ‘Wayne Enterprises’, ‘2018–11–14’, 100.00),
  (UNHEX(‘11E92BDEA73910BBB78E0242AC110002’), 101, 6002, ‘Star Labs’, ‘2018–11–15’, 200.00),
  (UNHEX(‘11E92BDEA7395C95B78E0242AC110002’), 102, 7003, ‘Daily Planet’, ‘2018–11–15’, 150.00),
  (UNHEX(‘11E92BDEA739A057B78E0242AC110002’), 103, 5001, ‘Wayne Enterprises’, ‘2018–11–21’, 110.00),
  (UNHEX(‘11E92BDEA739F892B78E0242AC110002’), 104, 6002, ‘Star Labs’, ‘2018–11–22’, 175.00),
  (UNHEX(‘11E92BE00BADD97CB78E0242AC110002’), 105, 6002, ‘Star Labs’, ‘2018–11–23’, 117.00),
  (UNHEX(‘11E92BE00BAE15ACB78E0242AC110002’), 106, 7003, ‘Daily Planet’, ‘2018–11–24’, 255.00),
  (UNHEX(‘11E92BE00BAE59FEB78E0242AC110002’), 107, 5001, ‘Wayne Enterprises’, ‘2018–12–07’, 321.00),
  (UNHEX(‘11E92BE00BAE9D7EB78E0242AC110002’), 108, 6002, ‘Star Labs’, ‘2018–12–14’, 55.00),
  (UNHEX(‘11E92BE00BAED1A4B78E0242AC110002’), 109, 7003, ‘Daily Planet’, ‘2018–12–15’, 127.00),
  (UNHEX(‘11E92BE021E2DF22B78E0242AC110002’), 110, 6002, ‘Star Labs’, ‘2018–12–15’, 133.00),
  (UNHEX(‘11E92BE021E31638B78E0242AC110002’), 111, 5001, ‘Wayne Enterprises’, ‘2018–12–17’, 145.00),
  (UNHEX(‘11E92BE021E35474B78E0242AC110002’), 112, 7003, ‘Daily Planet’, ‘2018–12–21’, 111.00),
  (UNHEX(‘11E92BE021E39950B78E0242AC110002’), 113, 6002, ‘Star Labs’, ‘2018–12–31’, 321.00),
  (UNHEX(‘11E92BE021E3CEC5B78E0242AC110002’), 114, 6002, ‘Star Labs’, ‘2019–01–03’, 223.00),
  (UNHEX(‘11E92BE035EF4BE5B78E0242AC110002’), 115, 6002, ‘Star Labs’, ‘2019–01–05’, 179.00),
  (UNHEX(‘11E92BE035EF970DB78E0242AC110002’), 116, 5001, ‘Wayne Enterprises’, ‘2019–01–14’, 180.00),
  (UNHEX(‘11E92BE035EFD540B78E0242AC110002’), 117, 7003, ‘Daily Planet’, ‘2019–01–21’, 162.00),
  (UNHEX(‘11E92BE035F01B8AB78E0242AC110002’), 118, 5001, ‘Wayne Enterprises’, ‘2019–02–02’, 133.00),
  (UNHEX(‘11E92BE035F05EF0B78E0242AC110002’), 119, 7003, ‘Daily Planet’, ‘2019–02–05’, 55.00),
  (UNHEX(‘11E92BE0480B3CBAB78E0242AC110002’), 120, 5001, ‘Wayne Enterprises’, ‘2019–02–08’, 25.00),
  (UNHEX(‘11E92BE25A9A3D6DB78E0242AC110002’), 121, 6002, ‘Star Labs’, ‘2019–02–08’, 222.00);

MySQL 5.7 的例子

rank()函数很酷,但是在 MySQL 8.0 之前是不可用的。因此,我们需要编写一个创造性的嵌套查询来对记录进行排序并提供结果。

首先,我们将编写一个查询,按照年、月和订单金额的降序对表中的所有记录进行排序(这样最大的订单得分最低)。

SELECT order_number, customer_number, customer_name, order_date,
  YEAR(order_date) AS order_year, 
  MONTH(order_date) AS order_month, 
  order_amount, 
  [@order_rank](http://twitter.com/order_rank) := IF([@current_month](http://twitter.com/current_month) = MONTH(order_date),
  [@order_rank](http://twitter.com/order_rank) + 1, 1) AS order_rank,
  [@current_month](http://twitter.com/current_month) := MONTH(order_date) 
FROM orders
ORDER BY order_year, order_month, order_amount DESC;

在我们的 SELECT 语句示例中,我们从表中获取所有字段,并从订单日期和月份中获取年份。因为我们的目标是按月排列订单,所以我创建了一个名为@current_month 的临时 MySQL 变量来跟踪每个月。在每个月的变化中,我们将@order_rank 变量重置为 1,否则我们递增 1。

注意使用:=操作数允许我们动态创建变量,而不需要 SET 命令。

第二个注意事项请记住,该 SELECT 语句将对表中的所有记录进行排序。通常,您希望有一个 WHERE 子句来限制结果集的大小。也许是按客户或日期范围。

上面的查询产生如下所示的结果集:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

您可以看到订单先按年份和月份排序,然后按订单金额降序排序。包含了新的 order_rank 列,该列按月对 1–2–3 序列中的每个订单进行排序。

现在,我们可以将该查询作为子查询包含到 SELECT 语句中,该语句只从每个组中提取前 3 个订单。最终的查询如下所示:

SELECT customer_number, customer_name, order_number, order_date, order_amount 
FROM 
  (SELECT order_number, customer_number, customer_name, order_date,
    YEAR(order_date) AS order_year, 
    MONTH(order_date) AS order_month,
    order_amount, 
    @order_rank := IF(@current_month = MONTH(order_date), 
    @order_rank + 1, 1) AS order_rank,
    @current_month := MONTH(order_date) 
   FROM orders
   ORDER BY order_year, order_month, order_amount DESC) ranked_orders 
WHERE order_rank <= 3;

使用我们的排名查询作为子查询,我们只需要取出报告所需的最终字段。添加了一个 WHERE 子句,该子句只提取等级为 3 或更低的记录。我们的最终结果集如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

您可以在结果中看到,我们每个月都获得了前 3 名的订单。

MySQL 8.0 的例子

MySQL 8.0 引入了 rank()函数,该函数增加了一些额外的功能,用于对结果集中的记录进行排序。使用 rank()函数,结果集按照您指定的值进行分区,然后在每个分区中为每一行分配一个等级。纽带被赋予相同的等级,并且随后的新号码被赋予等级 1 加上它之前的已排序记录的数目。

我们使用这个新特性的排名查询如下所示:

SELECT order_number, customer_number, customer_name, order_date,
 YEAR(order_date) AS order_year, 
 MONTH(order_date) AS order_month, 
 order_amount,
 RANK() OVER (
 PARTITION BY YEAR(order_date), MONTH(order_date)
ORDER BY YEAR(order_date), MONTH(order_date), order_amount DESC) order_value_rank
FROM orders;

这会产生如下所示的结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在本例中,您可以看到 12 月份两个最大的订单金额相同,都是 321.00 美元。rank()函数赋予这两个记录相同的等级 1,后续记录的等级为 3,依此类推。

像以前一样,这个排名查询用作最终查询的子查询:

WITH ranked_orders AS (
 SELECT order_number, customer_number, customer_name, order_date,
 YEAR(order_date) AS order_year, 
 MONTH(order_date) AS order_month, 
 order_amount,
 RANK() OVER (
 PARTITION BY YEAR(order_date), MONTH(order_date)
 ORDER BY YEAR(order_date), 
 MONTH(order_date), order_amount DESC) order_rank
 FROM orders
)
SELECT customer_number, customer_name, order_number, order_date,
 order_amount 
FROM ranked_orders
WHERE order_rank <= 3;

最终的查询与我们的 MySQL 5.7 示例非常相似,但是使用了 MySQL 8.0 的一些优点(如 WITH 语句的可用性)以及更多的排名功能,您可以在 MySQL 8.0 文档中进行研究。该查询的最终结果与上面示例中的 MySQL 5.7 结果相同。

我希望这两个例子能给你一些帮助,下次你想从一个团队中得到最好的结果。

还有呢!

请务必在这里查看我的其他文章,以了解更多关于在 Mac 上设置 PHP 开发环境以及其他编码技巧和示例。

具有纯神经网络的 n 拍统计模型

原文:https://towardsdatascience.com/n-beats-beating-statistical-models-with-neural-nets-28a4ba4a4de8?source=collection_archive---------9-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Chris Liverani on Unsplash

基于残差叠加和元学习的 SOTA 时间序列预测

M 竞赛[1]是一系列声望很高的预测挑战,旨在比较和推进预测研究。在过去,统计算法总是赢。像 ARIMA 和指数平滑这样屡试不爽的模型产生的预测很难被更复杂但不太精确的算法击败。

但这一切在去年都改变了。在这篇文章中,我将谈到 M4 的获奖者,ES-RNN,一个长短期记忆网络和指数平滑的融合体。然后,我详细阐述了我对 N-BEATS 的了解,这是一个甚至击败了 ES-RNN 的纯神经网络。

M4 奖得主:埃斯-RNN

M4 的意外赢家 ES-RNN[2]是一个由优步科技公司的 Slawek Smyl 创建的指数平滑和扩张 LSTM 的混合模型。

在指数平滑法中,一个时间序列可以被分解成 3 个部分,季节性,趋势和水平。扩张的 LSTM 块预测趋势,指数平滑处理剩下的部分。在了解了他是如何做到的之后,我迫不及待地想亲自尝试一下这个网络。我可以理解这些概念,但是这个层次模型的实现是在 Dynet/C++中,所以理解代码很困难,更不用说转录了。

更新:在我写这篇文章的时候,发现了 ES-RNN 的一个 Pytorch 实现![4]

新成员:N-BEATS

在 M4 的发现[1]中,Makridakis 得出结论,纯 ML 模型不如统计模型准确,“尽管可能会有一两个惊喜,这些方法优于统计方法,尽管只有很小的差距”。提交的 6 个纯 ML 模型表现不佳,甚至没有击败竞争基准,这就是证明。因此,如果没有好的统计数据,我们永远也不能建立一个预测模型,对吗?

没那么快。

element ai(yo shua beng io 共同创办的创业公司)最近发表了 N-BEATS :可解释时间序列预测的神经基础扩展分析【3】,这是一种时间序列预测的纯 DL 方法,击败了 M4 的 ES-RNN 分数。该论文证明了以下假设:

“在由 M4 数据集表示的单变量 TS 预测任务集上,可以构建纯 DL 模型,以胜过统计模型及其与 ML 的组合。”[3]

在我读这篇论文之前,我猜测击败 ES-RNN 的东西一定是一个复杂的多堆叠、扩张的双向、多注意力循环网络,带有 XL 变压器——但我很高兴地失望了。N-BEATS 使用一个简单但强大的集成前馈网络架构,该架构具有堆叠的预测和“反向预测”残差块。

作为一篇新论文,我找不到任何可以测试该架构的库,所以我卷起袖子编写了代码,用于一场预测竞赛。我以前从未从零开始实现过一篇论文,但是由于相对简单的架构和 fastai 的教导,我已经能够满足我的竞赛需求。以下是我从报纸上获得的关键信息。

双重剩余叠加或“遗忘门”

据我所知,残差块要么涉及到连接,即 Densenet[7],要么涉及到将原始输入添加到层的输出,即 Resnet[6],使用跳过连接来决定中间层是否有用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

N-BEATS 以不同的方式使用 skip 连接,通过从下一个块的输入中移除“backcast”输出,使后续块更容易预测作业。同时,每个块都有一个“预测”输出,它与该块中的后续预测相加,以提供一个组合预测。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Visual from basic block to stack to multiple stacks combining to get final forecast [3]

我进一步思考了一下,意识到这种架构实际上非常类似于展开的 LSTM(下图),其中的跳过连接就像 LSTM 的遗忘门一样,删除不需要的信息,并将处理后的输入传递给下一个模块,从而越来越容易产生更好的预测。这种“忘记门”的特征可以解释为什么这种新的结构运作良好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Credits: https://colah.github.io/posts/2015-08-Understanding-LSTMs/

下面是我的一个基本泛型块的代码片段。作者在波形发生器 gθ上花了很多心思,但对于一般的 gθ,它实际上只是另一个线性层,所以我对我的基本块进行了这样的编码。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Generic block coded with some fastai help

分解趋势和季节性

N-BEATS 想要证明的另一个假设是,我们可以创建可以分解和解释的 DL 模型。特别是:

“可以在 DL 架构中编码适当的归纳偏差,以使其输出更具可解释性,而不会显著牺牲预测准确性。”[3]

作者通过固定波形发生器 gθ来模拟趋势(单调图)和季节性(循环图)函数,使每个叠加的输出都是可解释的,从而使 N 次搏动是可解释的。此外,通过在堆栈上共享 gθ和 block 参数,他们发现模型性能得到了改善。对我来说,这类似于 RNN 的隐藏状态是如何在所有时间步骤中共享的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过集合进行正则化

我从来没有想过将集成作为一种正则化技术,但是深入思考一下,这显然是因为它使您的整体模型(由几个子模型组成)更好地泛化——每个子模型的权重可以被视为一种惩罚。作者发现,与在单个模型上使用辍学或 L2 范数惩罚相比,具有不同输入范围的集成模型给出了更好的结果。这是有意义的,因为不同的输入范围为模型提供了不同的趋势和季节性数据表示。

M4 的调查结果[1]还得出结论,杂交和组合“是提高预测准确性和使预测更有价值的前进方向”。

将元学习与 N 节拍联系起来

作者提出 N-BEATS 工作良好是因为元学习。在元学习中,学习过程可以分解为内部和外部训练循环[5]。内部训练循环侧重于特定任务的知识,外部循环侧重于跨任务的知识。我们可以将其类比为 N 拍,其中θ在块内学习,并利用从外环学习的参数,其中梯度下降训练θ所依赖的权重矩阵。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Inner loop in each block where θ is updated; Outer loop for the entire network’s parameters’ update

当输入通过模块时,θ被缓慢“更新”,当反向预测与输入进行残差叠加时,我们在数据通过模块时调节θ的学习。

结论和调查结果

这种新颖的残差叠加架构为时间预测带来了全新的视角,并且在理论上表现得非常好。我不确定元学习如何真正提高模型的性能,但这是一个单独的研究课题。

当我在比赛中实现 N-BEATS 时,我意识到它可能不会像预期的那样工作,因为首先测试服务器很容易超时,所以模型必须很小,其次,N-BEATS 是一个单变量模型,可能不太适合我正在处理的多变量数据。因此,我将它应用于一个简单的 BTC 时间序列。这是我的 kaggle 内核实现的通用块堆栈,你可以看到它做得相当好。

更新:发现了一个回购,它更好更精确地实现了代码。

Update2: ElementAI 在此分享了官方回购

[1] Makridakis 等人,《M4 竞争:结果、发现、结论和前进的道路》。

[2] M4 预测竞赛:引入一种新的混合 ES-RNN 模型

[3] Oreshkin 等. N-BEATS:用于可解释时间序列预测的神经基础扩展分析

[4] Redd 等.快速 ES-RNN:ES-RNN 算法的 GPU 实现

[5]安托尼乌、爱德华和斯托基。如何训练你的妈妈?

[6]何国光、张晓松、任少宁和孙军。用于图像识别的深度残差学习

[7]黄高、刘庄、基里安·q·温伯格和劳伦斯·范德马腾。密集连接的卷积网络

朴素贝叶斯和疾病检测

原文:https://towardsdatascience.com/naive-bayes-and-disease-detection-ffefe2cc5c01?source=collection_archive---------18-----------------------

从 pdf 转移到离散值

之前我在 1760 年写过关于贝叶斯推理的文章,在那里我观察了伯努利和贝塔分布。

但是你不需要使用概率密度函数,贝叶斯定理也适用于离散值。让我们看看人群中的疾病检测。

举一个发生在 1%人口中的疾病,你的测试有 99%的准确率:

True Positive (TP): 99% Correctly detects disease
False Positive (FP): 1% Incorrectly detects disease in healthy person
True Negative (TN): 99% Correctly detects absence of disease
False Negative (FN): 1% Incorrectly detects absence of disease in sick person

一个随机的人来到诊所,测试呈阳性——这个人实际上患有这种疾病的概率是多少?在你继续读下去之前,想一个答案。

这个不用 Bayes 也可以数值求解。让我们假设一个 10,000 人的任意人口规模。在这些人中,我们知道有 1%的人患有这种疾病:

100 people with the disease
9900 people without the disease

接下来我们可以计算阳性测试的数量。疾病组为 99%,健康组为 1%;

100 * 99% = 99 True Positive
9900 * 1% = 99 False Positive

这给了我们答案:

TP / (TP + FP) = 99 / (99 + 99) = 50%

一个随机测试呈阳性的人只有 50% 的患病几率,而 1%的人口患有这种疾病,而你的测试却有 99%的准确率!你还记得你猜的那个数字吗?50%的真实答案对大多数人来说都是一个惊喜。

现在再次使用贝叶斯定理:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Bayes’ theorem

P(A ∣ B) = P(B ∣ A) P(A)
          ───────────────
                P(B)
A = Disease
B = Positive test

问题又来了:疾病检测呈阳性的概率是多少,P(A ∣ B)是多少?

假定患者患有该疾病,检测呈阳性的概率:

P(B ∣ A) = 0.99

患病的可能性:

P(A) = 0.01

阳性测试的概率:

P(B) = 0.99 × 0.01 + 0.01 × 0.99 = 2 × 0.99 × 0.01

完成计算:

P(A ∣ B) = P(B ∣ A) × P(A)
          ───────────────
                P(B) 
         =   0.99 × 0.01
           ───────────────
           2 × 0.99 × 0.01
         = 1/2
         = **50%**

一项准确率为 99%的检测,但随机抽取一名检测结果为阳性的患者,其实际患病的几率只有 50 %!这种疾病在人群中的发病率是一个被许多人忽视的关键变量。

看看他们是如何在新闻中弄错的:独立报告称,81%被大都会警察局面部识别技术标记的“嫌疑人”是无辜的

参见:贝叶斯排名系统

Python 中的朴素贝叶斯文档分类

原文:https://towardsdatascience.com/naive-bayes-document-classification-in-python-e33ff50f937e?source=collection_archive---------0-----------------------

我能在多大程度上根据摘要对一篇哲学论文进行分类?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

朴素贝叶斯对于文档分类任务来说是一种相当有效的策略,尽管顾名思义,它是“幼稚的”

朴素贝叶斯分类利用贝叶斯定理来确定一个项目属于某个类别的可能性有多大。如果我有一个包含单词“信任”、“美德”或“知识”的文档,它属于“伦理学”而不是“认识论”的概率是多少朴素贝叶斯根据哪个概率最高来对项目进行分类。

这是“幼稚的”,因为它把每个单词出现在文档中的概率视为独立于任何其他单词出现的概率。这种假设对于我们想要分类的任何文档来说几乎都是不成立的,它们往往遵循语法、句法和交流的规则。当我们遵循这些规则时,一些单词往往会与其他单词相关联。

在这里,我设计了一个我认为有点困难的分类任务:对哲学文章的摘要进行分类。我选择了截然不同但有大量重叠的子学科:认识论和伦理学。两者都使用了证明和理由的语言。它们也经常交叉(例如信仰的伦理、道德知识等等)。最终,朴素贝叶斯在对这些文档进行分类时表现得出奇的好。

什么是朴素贝叶斯分类?

贝叶斯定理

贝叶斯定理告诉我们,给定一些证据的假设的概率等于假设的概率乘以给定假设的证据的概率,然后除以证据的概率。

Pr(H|E) = Pr(H) * Pr(E|H) / Pr(E)

因为我们正在对文档进行分类,所以“假设”是:文档属于类别 c。“证据”是文档中出现的单词 W。

由于分类任务涉及比较两个(或更多)假设,我们可以使用贝叶斯定理的比率形式,它比较每个假设的上述公式的分子(对于贝叶斯爱好者:先验乘以似然性):

pr(c₁|w)/pr(c₂|w)=pr(c₁)*pr(w|c₁)/pr(c₂)*pr(w|c₂)

由于文档中有许多单词,因此公式变为:

Pr(C₁|W₁,W₂ …Wn) / Pr(C₂|W₁,W₂ …Wn)=

pr(c₁)*(pr(w₁|c₁)pr(w₂|c₁)…pr(wn|c₁))/

pr(c₂)*(pr(w₁|c₂)pr(w₂|c₂)…pr(wn|c₂))

例如,如果我想知道包含单词“预热烤箱”的文档是否属于“烹饪书”类别而不是“小说”类别,我会比较以下内容:

Pr(食谱)* Pr(“预热” |食谱)* Pr(“烹饪” |食谱)* Pr(“烤箱” |食谱)

对此:

Pr(小说)* Pr(“预热” |小说)* Pr(" the " |小说)* Pr(“烤箱” |小说)

如果给定文档中出现的单词,它是食谱的概率大于它是小说的概率,则朴素贝叶斯返回“食谱”。如果反过来,朴素贝叶斯返回“小说”。

演示:根据摘要对哲学论文进行分类

  1. 准备数据

我将尝试分类的文件是来自一个名为 PhilPapers 的数据库的文章摘要。Philpapers 是一个综合性的哲学研究数据库。由于这个数据库是由大量的主题编辑管理的,我们有理由相信网站上给出的文档分类是正确的。

我从网站上为二元朴素贝叶斯分类器选择了两个哲学分支学科:伦理学或认识论。从每个分支学科中,我选择了一个主题。对于伦理学,我选择了题目“各种美德伦理学”,对于认识论,我选择了“信任”我收集了 80 篇伦理学和 80 篇认识论摘要。

我最初的数据帧的头部和尾部是这样的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了在 Scikit Learn 中运行朴素贝叶斯分类器,类别必须是数字,所以我将标签 1 分配给所有伦理学摘要,将标签 0 分配给所有认识论摘要(即而不是伦理学):

df[‘label’] = df[‘category’].apply(lambda x: 0 if x==’Epistemology’ else 1)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2。将数据分成训练集和测试集

保留一些数据很重要,这样我们可以验证我们的模型。为此,我们可以使用 Scikit Learn 的 train_test_split。

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(df[‘abstract’], df[‘label’], random_state=1)

3。将摘要转换成字数矢量

朴素贝叶斯分类器需要能够计算每个单词在每个文档中出现多少次,以及在每个类别中出现多少次。要实现这一点,数据需要看起来像这样:

[0, 1, 0, …]

[1, 1, 1, …]

[0, 2, 0, …]

每行代表一个文档,每列代表一个单词。第一行可能是包含“预热”的零、“The”的一和“烤箱”的零的文档。这意味着文档包含单词“the”的一个实例,但没有“preheat”或“oven”

要获得这种格式的摘要,我们可以使用 Scikit Learn 的计数矢量器。CountVectorizer 为每个摘要创建一个字数矢量,形成一个矩阵。每个索引对应一个词,出现在摘要中的每个词都有代表。

from sklearn.feature_extraction.text import CountVectorizercv = CountVectorizer(strip_accents=’ascii’, token_pattern=u’(?ui)\\b\\w*[a-z]+\\w*\\b’, lowercase=True, stop_words=’english’)X_train_cv = cv.fit_transform(X_train)
X_test_cv = cv.transform(X_test)

我们可以使用 strip_accents、token_pattern、lowercase 和 stopwords 参数来排除非单词、数字、冠词和其他对从计数中预测类别没有用的东西。有关详细信息,请参见文档

如果您想查看数据并调查字数,您可以使用以下代码制作一个字数的数据框架:

word_freq_df = pd.DataFrame(X_train_cv.toarray(), columns=cv.get_feature_names())top_words_df = pd.DataFrame(word_freq.sum()).sort_values(0, ascending=False)```

4。拟合模型并进行预测

现在,我们准备将多项式朴素贝叶斯分类器模型拟合到我们的训练数据中,并使用它来预测测试数据的标签:

from sklearn.naive_bayes import MultinomialNB
naive_bayes = MultinomialNB()
naive_bayes.fit(X_train_cv, y_train)
predictions = naive_bayes.predict(X_test_cv)

5。检查结果

让我们看看模型在测试数据上的表现:

from sklearn.metrics import accuracy_score, precision_score, recall_scoreprint(‘Accuracy score: ‘, accuracy_score(y_test, predictions))
print(‘Precision score: ‘, precision_score(y_test, predictions))
print(‘Recall score: ‘, recall_score(y_test, predictions))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了理解这些分数,看一下细目分类会有帮助:

from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
import seaborn as snscm = confusion_matrix(y_test, predictions)
sns.heatmap(cm, square=True, annot=True, cmap=’RdBu’, cbar=False,
xticklabels=[‘epistemology’, ‘ethics’], yticklabels=[‘epistemology’, ‘ethics’])
plt.xlabel(‘true label’)
plt.ylabel(‘predicted label’)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

准确度分数告诉我们:在我们所做的所有识别中,有多少是正确的?

  • 真阳性+真阴性/总观察值:(18 + 19) / 40

精确分数告诉我们:在我们进行的所有道德鉴定中,有多少是正确的?

  • 真阳性/(真阳性+假阳性):18 / (18+2)

回忆分数告诉我们:在所有真实的道德案例中,我们正确识别了多少?

  • 真阳性/(真阳性+假阴性):18/(18+1)

6。调查模型的失误

为了调查不正确的标签,我们可以将实际标签和预测标签并排放在一个数据帧中。

testing_predictions = []for i in range(len(X_test)):
    if predictions[i] == 1:
        testing_predictions.append(‘Ethics’)
    else:
        testing_predictions.append(‘Epistemology’)check_df = pd.DataFrame({‘actual_label’: list(y_test), ‘prediction’: testing_predictions, ‘abstract’:list(X_test)})
check_df.replace(to_replace=0, value=’Epistemology’, inplace=True)
check_df.replace(to_replace=1, value=’Ethics’, inplace=True)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

总的来说,我的朴素贝叶斯分类器在测试集上表现良好。40 个标签中只有 3 个不匹配。

推荐阅读:

[## 归纳逻辑(斯坦福哲学百科全书)

指定归纳支持函数的逻辑公理的一个好方法如下。这些公理显然是…

plato.stanford.edu](https://plato.stanford.edu/entries/logic-inductive/) [## 加法平滑-维基百科

从贝叶斯的观点来看,这对应于后验分布的期望值,使用对称的…

en.wikipedia.org](https://en.wikipedia.org/wiki/Additive_smoothing) [## 朴素贝叶斯:直觉和实现

了解朴素贝叶斯算法及其预测类的能力。

towardsdatascience.com](/naive-bayes-intuition-and-implementation-ac328f9c9718) [## 深度:朴素贝叶斯分类

因为朴素贝叶斯分类器对数据做了如此严格的假设,它们通常不会表现得那么好…

jakevdp.github.io](https://jakevdp.github.io/PythonDataScienceHandbook/05.05-naive-bayes.html) [## 将多项式朴素贝叶斯应用于 NLP 问题:一个实用的解释

1.简介朴素贝叶斯是一个基于应用贝叶斯定理的算法家族,它具有很强的(朴素)推理能力

medium.com](https://medium.com/syncedreview/applying-multinomial-naive-bayes-to-nlp-problems-a-practical-explanation-4f5271768ebf)

朴素贝叶斯解释道

原文:https://towardsdatascience.com/naive-bayes-explained-108c095241eb?source=collection_archive---------11-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从直觉到实施

用于分类的机器学习方法本质上可以是判别型生成型。基本上,一个和另一个之间的区别在于根据我们的数据获得预测的过程。让我们假设我们的数据集由几个实例 x 组成,其中每个实例包含一系列由 1 到 D 索引的特征,其中 D 是我们数据集的维数。鉴于这种直觉,我们可以将 x 表示为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里的特征 x 1、 x 2、 x 3 等。是唯一标识我们的实例的属性。例如,如果我们正在开发一个模型,根据某些标准来预测个人是否应该获得信贷,那么 x 1, x 2, x 3… xD 。将是个人的相关属性,例如他/她的个人信息、工资、债务金额等。鉴于这些数据,我们希望训练一个模型,能够预测这个人是否应该获得信贷。因此,对于这个特殊的问题我们将有两种可能性:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 k = {1,…, K }是类别索引,由于在这个特定的问题中我们有两个类别,那么 K =2。现在,一个判别模型将如何预测 y k ?它会告诉我们,给定数据 x ,一个人获得信贷的概率。我们可以用这个数学表达式来表达这个推理:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过调整一组参数,判别模型的目标将是给我们这个概率作为结果,这将反过来成为我们的预测。另一方面,一个创成式模型会做什么?它的目标是最终给我们同样的概率,但是它遵循的过程会有一点不同。假设我们有p(x*|yk*)和p(yk)。然后,贝叶斯法则将允许我们通过使用以下等式找到p(y*k |*x):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Equation 1. Bayes Theorem for x and y

在这里,p(x|yk)又称为可能性p(yk)是事前,p ( x )是证据,而分母中的证据 p ( x )可以被视为常数,为了简单起见,我们将忽略它。这个贝叶斯框架的好处在于,我们可以通过在概率分布后对其建模来轻松确定可能性*,并且可以通过计算我们的数据集中有多少个***【y】k出现,然后除以数据点的总数来找到先验。事实上,通过知道似然值和先验,我们能够根据我们的数据进行预测。

总之,生成模型将使用贝叶斯定理通过使用可能性和先验来进行预测。在贝叶斯学习领域中,有各种各样的用于不同目的的生成模型。其中之一被称为朴素贝叶斯,我们将在接下来的章节中深入讨论它。稍后,我们将通过使用手写数字的 MNIST 数据集在 Python 中实现这个模型。

推导朴素贝叶斯

让我们回到我们早期预测信用的例子。我们说过 x 将包含一系列属于特定个人的特征。这些特征包含了我们的模型进行信用或非信用预测所需的信息。我们的假设是特征 1,…,D 在统计上相互独立。这意味着,例如,个人的年龄不会决定他/她的债务数额。同样,工资也不是由他/她有多少债务等因素决定的。显然,我们可以看到,这种独立性假设并不总是成立的,但正如我们将在后面看到的,它将使我们的模型更加简单,而不会失去有效性。

然后,通过使用图形表示,我们可以将 p(x|**|y**k)描述如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1. Illustration for independence between features

我们可以看到,特征 x i 它们之间并不相连,而是 y k 连接到每个特征上。由此我们可以清楚地看到,这些特征互为条件独立,但它们只依赖于 y k 。超越信用问题,我们可以将每个 x i 想象为数字图像中的一个像素,如果我们正在进行计算机视觉,或者是句子中的一个单词,如果我们正在进行自然语言处理。事实上,稍后我们将实现朴素贝叶斯来分类手写数字图像。

现在让我们将迪普深入到直觉中,并假设我们有两个相互独立的变量 AB 。通过应用乘积概率,我们知道:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这种情况下,因为独立条件,p(A|B)干脆就变成了 p ( A )。如果我们将同样的推理以及一些归纳应用于 xyk,我们将能够容易地推导出朴素贝叶斯模型的主要关系。

现在我们要做一些归纳!先假设我们只有两个特征 x 1 和 x 2。考虑到我们之前提到的独立性问题,我们应用乘积规则的方式是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

太好了!现在让我们用三个特性来试试 x 1、 x 2 和 x 3:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意到模式了吗?是啊,我们可以把这个概率仅仅表示为 x 1、 x 2、 x 3、…、 xDp(yk)的概率的乘积。因此,我们有:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

厉害!现在你可能已经注意到,这个表达式实际上是我们在等式 1 中定义的。因此,将它代入等式 1,我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Equation 2. Probability of y given x

那么,我们如何将它转化为实际的预测呢?当评估这个表达式时,我们将有一组概率,每个类一个。我们需要做的是找到突出的概率指数,我们将有预测!因此,等式 2 变为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Equation 3. Naive Bayes prediction

很好。这里一个有趣的事情是,我们可以通过采用合适的概率分布来模拟p(xI|yk),其选择将取决于我们数据的性质。例如,如果我们的 x 是二元变量,我们将使用伯努利分布,或者如果它们是实数,那么我们将使用高斯函数。我们将在下一节更详细地讨论后者。

在继续之前,我们只需要对等式 3 做最后一件事。如果仔细观察,会发现 argmax 里面的所有项都是概率,也就是零和一之间的值。当我们把所有这些项相乘时,我们会得到一个越来越接近零的结果。当我们有许多特征时,情况会变得更糟,例如,数字图像中的像素。我们的预测会崩溃!我们能做什么?简单,应用对数。最好是一个大的负数,而不是一个非常接近零的值,这可能会搞乱我们的模型。由于我们只对预测感兴趣,并不关心概率值,我们应用对数不会影响期望的结果。通过这种修改,等式 3 变为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Equation 4. Naive Bayes prediction with logarithms

这将确保在处理许多特征时更好的数值稳定性。接下来,我们讨论高斯朴素贝叶斯处理数据集中的实值 x

高斯朴素贝叶斯

关于朴素贝叶斯,什么叫“幼稚”?是啊,你猜对了!特征的独立性 x 1、 x 2、 x 3 等等。在前几节中,我们一直在讨论这个导致我们得出一些有趣结论的特殊特征。尽管我们不能总是假设我们的特征是独立的,朴素贝叶斯允许我们大大减少进行预测所需的计算成本。

我们现在将注意力转向当 x 为实值时的特殊情况,看看我们如何使用高斯密度函数来模拟p(xI|y)。

我们如何定义多元高斯函数?我们应该记住,它由两个基本参数组成:均值 μ 和协方差σ,由下式给出

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Equation 5. Multivariate Gaussian

并且该表达式的对数由下式给出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Equation 6. Log of Multivariate Gaussian

这里,均值 μ 将是一个具有 K 个元素的向量,协方差σ将是一个 K x K 矩阵。正如我们所见,等式 5 和 6 要求我们计算该矩阵的逆矩阵。我们可以清楚地看到,这个操作将变得非常昂贵,特别是如果我们有大量的功能。那么我们如何利用朴素贝叶斯的独立性假设来简化这些计算呢?我们需要在这里应用一些概念。

让我们阐明一些重要的定义。当两个变量 x 1 和 x 2 独立且服从高斯分布时,那么它们的协方差为零。我们可以很容易地证明这一点,首先说明协方差的一般定义,它由下式给出

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Equation 7. Covariance definition

现在,我们暂时将注意力转向 E[x1x2]。给定 x 1 和 x 2 是独立的,那么我们将有:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们在等式 7 中替换这个表达式,我们会发现 Cov( x 1, x 2)等于零。现在,回到我们之前对高斯密度函数的定义,矩阵σ有哪些元素?让我们来看看:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到,σ实际上是一个仅由特征级方差组成的对角矩阵。这是特征之间独立性假设的结果,因为正如我们刚刚展示的,当xI 和xj 不同时,Cov(xI,xjj)为零。

为了推导高斯朴素贝叶斯模型的似然性,了解以下两个表达式将对我们非常有用:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

它们分别是对角协方差矩阵的行列式和逆矩阵。如果我们将这些代入等式 6,我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Equation 8. Gaussian log-likelihood expression

为了方便起见,我们去掉了涉及 ln(2π) 的第一项。由于这是一个常数,它只会放大我们的结果,所以删除它不会改变实际的预测值。对于给定的 x ,等式 8 是我们模型的对数似然。这意味着,以下表达式实际上是等价的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此,将我们在上一节中推导的等式 8 代入等式 4,我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Equation 9. Prediction for Gaussian Naive Bayes

精彩!我们想出了一个非常简单的方程来进行预测。请注意,我们已经去掉了所有涉及潜在的昂贵计算操作的表达式,如逆协方差、行列式等。我们可以很容易地在任何现代编程语言中实现这个模型,甚至对于包含大量条目的数据集。在下一节中,我们将集中精力使用手写数字的 MNIST 数据集在 Python 中实现高斯朴素贝叶斯。请继续阅读!

用 Python 实现

注意:完整的源代码可以在 https://bit.ly/2T94GF5的 Jupyter 笔记本上获得

我们现在要实现朴素贝叶斯来对手写数字的 MNIST 数据集进行预测[2]。该数据集由 60,000 幅用于训练的图像和 10,000 幅用于测试的图像组成。所有图像都有相应的标签。一个有趣的方面是,Keras 库已经附带了一个 API,允许我们根据需要轻松导入 MNIST。让我们首先导入数据集:

作为预处理步骤的一部分,我们还将 HOG 描述符应用于训练和测试数据集中的每个图像。这已经表明提高了我们的模型的性能。使用这些描述符的另一个优点是,它将需要评估的特征数量减少到一半以下。如果你想用 OpenCV [3]找到更多关于猪的描述符,你可以看看 https://bit.ly/2OJKLOt 的。总共为每个图像计算 108 个 HOG 特征,因此 D =108。

接下来我们计算先验p(yk)。我们可以通过计算属于每个类的项目数,然后除以训练数据集中的条目总数来轻松实现这一点:

然后,我们还有计算高斯对数似然的逻辑,由下式给出

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这方面的 Python 代码如下:

最后,为了进行预测,我们简单地计算后验概率的 argmax。我们根据等式 9 和高斯对数似然性来实现这一点:

我们还通过使用 10,000 张图像进行测试来评估我们的模型。为此,我们计算整体精度:

我们获得了 91.5%的准确率,考虑到我们已经假设了特征独立性,这是一个很好的设置。如果我们不做这样的假设,也许我们的精度会更高,但是反过来,我们在这里确实获得了重要的速度增益。您应该能够在几秒钟内使用整个数据集训练该模型!

以下是通过实施获得的一些预测示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2. Model predictions.
Source: [2] The MNIST Database of Handwritten Digits and own Implementation

结束语

我们已经将朴素贝叶斯作为假设特征级独立性的分类生成模型。我们已经看到,尽管这种假设可能并不总是有效,但它有助于我们提出一个非常容易实现和训练的模型。为了对数据集进行预测,我们可以只计算简单的运算,而不是进行矩阵运算。我强烈建议您查看整个实现,并使用自己的数据集进行尝试。如果你有任何问题或意见,请随时联系我,我真的希望你喜欢这篇文章!

参考

[1]墨菲,凯文 P. 机器学习:概率观点 (2012)麻省理工学院出版社,剑桥,马萨诸塞州。

[2]勒村,扬。科尔特斯科琳娜。克里斯托夫·伯格斯。MNIST 手写数字数据库。在 http://yann.lecun.com/exdb/mnist/有售

[3] OpenCV。 *cv::HOGDescriptor 结构引用。*可从https://docs . opencv . org/3 . 4 . 6/D5/d33/struct cv _ 1 _ 1 hog descriptor . html获得

朴素贝叶斯解释道

原文:https://towardsdatascience.com/naive-bayes-explained-9d2b96f4a9c0?source=collection_archive---------1-----------------------

朴素贝叶斯是一种概率算法,通常用于分类问题。朴素贝叶斯简单、直观,但在许多情况下表现惊人地好。例如,电子邮件应用程序使用的垃圾邮件过滤器是建立在朴素贝叶斯基础上的。在本文中,我将解释朴素贝叶斯背后的基本原理,并用 Python 构建一个垃圾邮件过滤器。(为了简单起见,我将重点讨论二进制分类问题)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Thomas Bayes, the ‘betting man’, from BBC

理论

在我们开始之前,请记住本文中使用的符号:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基本想法

要做分类,我们需要用 X 来预测 Y,换句话说,给定一个数据点 X=(x1,x2,…,xn),Y 是 Y 的奇数是多少,这可以改写为下面的等式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是朴素贝叶斯的基本思想,算法的其余部分实际上更侧重于如何计算上面的条件概率。

贝叶斯定理

到目前为止,贝叶斯先生对算法没有贡献。现在是他发光的时候了。根据贝叶斯定理:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Bayes Theorem

这是一个相当简单的转变,但它弥合了我们想做的和我们能做的之间的差距。我们不能直接得到 P(Y|X),但是可以从训练数据中得到 P(X|Y)和 P(Y)。这里有一个例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Weather dataset, from the University of Edinburgh

在这种情况下,X =(展望,温度,湿度,有风),Y =玩。P(X|Y)和 P(Y)可以通过下式计算:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example of finding P(Y) and P(X|Y)

朴素贝叶斯假设及其原因

理论上,求 P(X|Y)并不难。然而,随着特性数量的增加,这实际上要困难得多。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7 parameters are needed for a 2-feature binary dataset

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Estimate Join Distribution requires more data

模型中有这么多参数是不切实际的。为了解决这个问题,做了一个天真的假设。**我们假设所有的特征都是独立的。**这是什么意思?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Conditional independence

现在借助于这个天真的假设(天真是因为特征很少是独立的),我们可以用少得多的参数进行分类:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Naive Bayes Classifier

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Naive Bayes need fewer parameters (4 in this case)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是一件大事。我们将参数数量从指数型改为线性型。这意味着朴素贝叶斯很好地处理了高维数据。

分类和连续特征

分类数据

对于分类特征,P(Xi|Y)的估计是容易的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Calculate the likelihood of categorical features

然而,一个问题是,如果一些特征值从未出现(可能缺乏数据),它们的可能性将为零,这使得整个后验概率为零。解决这个问题的一个简单方法叫做拉普拉斯估计器:给每个类别添加假想样本(通常是一个)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Laplace Estimator

连续数据

对于连续特征,本质上有两种选择:离散化和连续朴素贝叶斯。

离散化的工作原理是将数据分解成分类值。最简单的离散化是均匀宁滨,它创建具有固定范围的箱。当然,还有更智能和更复杂的方法,如递归最小熵分割或基于 SOM 的分割。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Discretizing Continuous Feature for Naive Bayes

第二种选择是利用已知的分布。如果要素是连续的,朴素贝叶斯算法可以写成:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

f is the probability density function

例如,如果我们将数据可视化并看到一个钟形曲线状的分布,就可以假设该特征是正态分布的

第一步是计算给定标签 y 的特征的均值和方差:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

variance adjusted by the degree of freedom

现在我们可以计算概率密度 f(x):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当然,还有其他发行版:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Naive Bayes, from Scikit-Learn

虽然这些方法在形式上有所不同,但背后的核心思想是一致的:假设特征满足某种分布,估计该分布的参数,进而得到概率密度函数。

优势和劣势

力量

  1. 尽管天真的假设很少是正确的,但该算法在许多情况下表现得出奇的好
  2. 很好地处理高维数据。易于并行化,能够很好地处理大数据
  3. 当数据集较小时,性能优于更复杂的模型

弱点

  1. 由于天真的假设,估计的概率往往是不准确的。不适合回归使用或概率估计
  2. 当数据丰富时,其他更复杂的模型往往优于朴素贝叶斯

总结

朴素贝叶斯利用最基本的概率知识,并做出所有特征都是独立的天真假设。尽管简单(有些人可能会说过于简单),朴素贝叶斯在许多应用程序中都有不错的表现。

现在你明白了朴素贝叶斯的工作原理,是时候在实际项目中尝试一下了!

朴素贝叶斯算法:直觉和在垃圾邮件检测器中的实现

原文:https://towardsdatascience.com/naive-bayes-intuition-and-implementation-ac328f9c9718?source=collection_archive---------5-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Picture from Unsplash

简介:什么是朴素贝叶斯模型?

从广义上讲,朴素贝叶斯模型是一种特殊的分类机器学习算法。它们基于一种叫做“贝叶斯定理”的统计分类技术。

朴素贝叶斯模型被称为“朴素”算法,因为它们假设预测变量相互独立。换句话说,数据集中某个特征的存在与任何其他特征的存在完全无关。

鉴于其简单性,它们提供了一种简单的方法来构建具有良好性能的精确模型。

他们通过提供一种方法来计算某个事件发生的“后验”概率,给定一些“先验”事件的概率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure by Author

例子

我们将通过研究一个示例来介绍关于导航贝叶斯算法的主要概念:

让我们考虑在同一办公室工作的两个同事的情况:爱丽丝和布鲁诺。我们知道:

  • 爱丽丝每周来办公室三天。
  • 布鲁诺每周来办公室一天。

这将是我们的“先验”信息。

我们在办公室,看到有人飞快地从我们身边走过,快到我们都不知道那个人是谁:爱丽丝还是布鲁诺。

给定我们知道的信息,并假设他们每周只工作 4 天,看到的人是爱丽丝或布鲁诺的概率是:

  • p(爱丽丝)= 3/4 = 0.75
  • p(布鲁诺)= 1/4 = 0.25

当我们看到那个人经过时,我们看到他/她穿着一件红色的夹克。我们还知道以下情况:

  • 爱丽丝一周穿两次红色衣服。
  • 布鲁诺一周穿三次红色衣服。

因此,对于有 5 天的每个工作周,我们可以推断如下:

  • 爱丽丝穿红色的概率是→ P(红色|爱丽丝)= 2/5 = 0.4
  • 布鲁诺穿红的概率是→ P(红|布鲁诺)= 3/5 = 0.6

这个新的概率将是“后验”信息。

那么,有了这些信息,我们看到谁路过了呢?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure by Author

最初我们知道 P(爱丽丝)和 P(布鲁诺)的概率,后来我们推断出 P(红|爱丽丝)和 P(红|布鲁诺)的概率。

所以,真正的可能性是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure by Author

形式上,前面的图形应该是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure by Author

监督朴素贝叶斯算法

为了能够使用朴素贝叶斯算法来解决类似于前一个问题的分类问题,要执行的步骤是:

  1. 将数据集转换为频率表
  2. 通过查找事件发生的概率来创建可能性表。
  3. 朴素贝叶斯方程用于计算每一类的后验概率。
  4. 具有较高后验概率的类别是预测的结果。

朴素贝叶斯的优点和缺点

主要优势有:

  • 在二元和多元分类问题中预测类别的简单快捷的方法。
  • 在独立性假设符合的情况下,该算法与其他分类模型相比表现更好,即使训练数据较少。
  • 类别条件特征分布的分离意味着每个分布可以被独立地估计为一维分布。这有助于解决维数灾难带来的问题,并提高性能。+

鉴于使用此方法的主要缺点是:****

  • 尽管朴素贝叶斯是非常好的分类器,但它们被认为是很差的估计器。所以不应该把它输出的概率看得太重。
  • 天真的独立性假设不太可能与现实世界的数据相匹配。
  • 当测试数据集具有在训练 se 中未观察到的特征时,模型将为其分配 0 概率,并且对于进行预测将是无用的。避免这种情况的主要方法之一是平滑技术,拉普拉斯估计是最流行的方法之一。

实施项目:垃圾邮件检测器

目前,机器学习的主要应用之一是垃圾邮件检测。几乎所有最重要的电子邮件服务都提供了垃圾邮件检测器,可以自动对垃圾邮件进行分类,并将其发送到“垃圾邮箱”。

在这个项目中,我们将开发一个朴素贝叶斯模型来分类短信是否是垃圾邮件。它将基于我们提供的培训数据。

通过之前的研究,我们发现垃圾邮件通常:

  • 包含像“免费”、“赢”、“赢家”、“现金”和“奖品”这样的词。
  • 此外,他们倾向于用大写字母书写单词,也倾向于使用许多感叹号。

这是一个监督的二进制分类问题,因为邮件要么是“垃圾邮件”,要么是“非垃圾邮件”,我们将输入一个带标签的数据集来训练模型。

概述

我们将执行以下步骤:

  • 了解数据集
  • 数据预处理
  • 单词包(BoW)和 Sci-kit 实现简介
  • 在训练集和测试集中拆分数据集
  • 应用 BoW 处理我们的数据集。
  • 利用 sci-kit 学习实现朴素贝叶斯
  • 模型评估
  • 结论

了解数据集

我们将使用来自 UCI 机器学习知识库的数据集。这里可以找到链接

数据预览:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这些列没有命名,但是我们可以通过阅读它们来猜测:

  • 第一列确定消息的类别:“垃圾邮件”或“垃圾邮件”。
  • 第二列对应于消息的内容。

我们将首先导入数据集并重命名列名。通过之前的研究,我们还发现数据集是由制表符分隔的,所以实际的分隔符是’ \t '。

****# Import Pandas library**
import pandas as pd**# Dataset from** [**https://archive.ics.uci.edu/ml/datasets/SMS+Spam+Collection**](https://archive.ics.uci.edu/ml/datasets/SMS+Spam+Collection)
df = pd.read_table('smsspamcollection/SMSSpamCollection', 
                   sep='\t', 
                   names=['label','sms_message'])**# Output printing out first 5 rows**
df.head()**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据预处理

现在,由于 sci-kit learn 只处理数值作为输入,我们将把标签转换成二进制变量。0 代表“火腿”,1 代表“垃圾”。

要执行转换,请执行以下操作:

****# Conversion**
df['label'] = df.label.map({'ham':0, 'spam':1})**# Print dataset shape**
df.shape()**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

单词包(BoW)和 Sci-kit 实现简介

我们的数据集是一个大的文本数据集合(5572 行)。由于我们的模型只接受数字数据作为输入,我们应该处理文本消息。这就是单词袋发挥作用的地方。

单词包是一个术语,用于指定需要处理的文本数据集合的问题。这个想法是拿一段文字,统计文字出现的频率。

BoW 独立处理每个单词,顺序无关。

我们可以将一组文档转换成一个矩阵,每个文档是一行,每个单词(标记)是一列,相应的(行,列)值是每个单词或标记在该文档中出现的频率。

以 ann 为例,如果我们有以下 4 个文档:

**['Hello, how are you!', 'Win money, win from home.', 'Call me now', 'Hello, Call you tomorrow?']**

我们将把文本转换成如下的频率分布矩阵:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

文档按行编号,每个单词是一个列名,对应的值是该单词在文档中的出现频率。

我们将使用 skleans C计数矢量器方法,该方法执行以下操作:

  • 它将字符串标记化(将字符串分隔成单个单词),并为每个标记提供一个整数 ID。
  • 它计算这些标记的出现次数。
  • 它会自动将所有标记化的单词转换为小写形式,这样就不会对“he”和“He”这样的单词区别对待。
  • 它还会忽略所有标点符号,以便单词后跟一个标点符号(例如:“你好!”)与不带标点符号前缀或后缀的相同单词(例如:“hello”)没有区别。
  • 第三个需要注意的参数是stop_words参数。停用词是指一种语言中最常用的词。它们包括像’ am ‘,’ an ‘,’ the '等词。通过将该参数值设置为english,CountVectorizer 将自动忽略在 scikit-learn 的内置英语停用词列表中找到的所有单词(来自我们的输入文本)。

sci-kit learn 实现如下:

****# Define the documents**
documents = ['Hello, how are you!',
                'Win money, win from home.',
                'Call me now.',
                'Hello, Call hello you tomorrow?']**# Import the count vectorizer and initialize it**
from sklearn.feature_extraction.text import CountVectorizer
count_vector = CountVectorizer()**# Print the 'count_vector' object which is an instance of 'CountVectorizer()'**
print(count_vector)**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了使文档数据集适合所创建的 CountVectorizer 对象,我们将使用 fit()方法,并使用 get_feature_names()方法获取已被归类为特征的单词列表。这个方法返回这个数据集的特征名,这个数据集是组成我们的“文档”词汇表的一组单词。

**count_vector.fit(documents)
names = count_vector.get_feature_names()
names**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来,我们想要创建一个矩阵,其中行是 4 个文档中的每一个,列是每个单词。相应的(行,列)值将是该单词(在列中)在特定文档(在行中)中的出现频率。

我们可以使用 transform()方法并把文档数据集作为参数传入。transform()方法返回一个 numpy 整数的矩阵,您可以使用 toarray()将它转换为一个数组。

**doc_array = count_vector.transform(documents).toarray()
doc_array**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了更容易理解,我们的下一步是将这个数组转换成 dataframe,并适当地命名这些列。

**frequency_matrix = pd.DataFrame(data=doc_array, columns=names)
frequency_matrix**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们现在已经成功地为我们创建的文档数据集实现了单词袋问题。

使用这种开箱即用的方法可能产生的一个潜在问题是,如果我们的文本数据集非常大,由于语言本身的结构,某些值会比其他值更常见。例如,像“是”、“the”、“an”、代词、语法结构等词会扭曲我们的矩阵,影响我们的分析

为了减轻这种情况,我们将使用 CountVectorizer 类的 stop_words 参数,并将其值设置为 english。

在训练集和测试集中拆分数据集

我们希望拆分数据,使其具有以下形状:

  • X_train是我们为“sms_message”栏目提供的培训数据。
  • y_train是我们用于“标签”列的训练数据
  • X_test是我们对‘SMS _ message’栏目的测试数据。
  • y_test是我们的测试数据的‘标签’列打印出我们在每个我们的训练和测试数据中的行数。
****# split into training and testing sets**
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(df['sms_message'], df['label'], random_state=1)print('Number of rows in the total set: {}'.format(df.shape[0]))print('Number of rows in the training set: {}'.format(X_train.shape[0]))print('Number of rows in the test set: {}'.format(X_test.shape[0]))**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

应用 BoW 处理我们的数据集

现在我们已经分割了数据,下一个目标是将数据转换成所需的矩阵格式。为此,我们将像以前一样使用 CountVectorizer()。这里需要考虑两个步骤:

  • 首先,我们必须将我们的训练数据(X_train)放入CountVectorizer()并返回矩阵。
  • 其次,我们必须转换我们的测试数据(X_test)来返回矩阵。

请注意,X_train是我们数据集中“sms_message”列的训练数据,我们将使用它来训练我们的模型。

X_test是我们对“sms_message”列的测试数据,这是我们将使用的数据(转换为矩阵后)来进行预测。在后面的步骤中,我们将把这些预测与y_test进行比较。

这个部分的代码分为两部分。首先,我们为训练数据学习词汇字典,然后将数据转换成文档-术语矩阵;其次,对于测试数据,我们只是将数据转换成文档术语矩阵。

****# Instantiate the CountVectorizer method**
count_vector = CountVectorizer()**# Fit the training data and then return the matrix**
training_data = count_vector.fit_transform(X_train)**# Transform testing data and return the matrix. Note we are not fitting the testing data into the CountVectorizer()**
testing_data = count_vector.transform(X_test)**

用 Sci-Kit Learn 实现朴素贝叶斯

我们将使用多项式朴素贝叶斯实现。这个特定的分类器适合于具有离散特征的分类(例如在我们的例子中,文本分类的字数)。它接受整数字数作为输入。另一方面,高斯朴素贝叶斯更适合连续数据,因为它假设输入数据具有高斯(正态)分布。

我们将导入多项式 inb 分类器,并使用 fit()将训练数据拟合到分类器中。

**from sklearn.naive_bayes import MultinomialNB
naive_bayes = MultinomialNB()
naive_bayes.fit(training_data, y_train)**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,我们的算法已经使用训练数据集进行了训练,我们现在可以使用 predict()对存储在“testing_data”中的测试数据进行一些预测。

**predictions = naive_bayes.predict(testing_data)**

既然已经对我们的测试集进行了预测,我们需要检查我们预测的准确性。

车型评测

有各种各样的机制可以做到这一点,但首先让我们快速回顾一下。

  • 准确性:衡量分类器做出正确预测的频率。它是正确预测的数量与预测总数(测试数据点的数量)的比率。
  • Precision:告诉我们被我们归类为垃圾邮件的邮件中,实际上是垃圾邮件的比例。它是真阳性(分类为垃圾邮件的单词,实际上是垃圾邮件)与所有阳性(分类为垃圾邮件的所有单词,不管这是否是正确的分类)的比率。

Precision = [True Positives/(True Positives + False Positives)]

  • Recall(sensitivity):告诉我们实际上是垃圾邮件的邮件中有多少被我们归类为垃圾邮件。它是真阳性词(被归类为垃圾邮件的词,以及实际上是垃圾邮件的词)与所有实际上是垃圾邮件的词的比率。

Recall = [True Positives/(True Positives + False Negatives)]

对于像我们这样分类分布不均匀的分类问题,例如,如果我们有 100 条短信,只有 2 条是垃圾邮件,其余 98 条不是,准确性本身就不是一个很好的指标。我们可以将 90 封邮件归类为非垃圾邮件(包括 2 封垃圾邮件,但我们将其归类为非垃圾邮件,因此它们会是假阴性),将 10 封邮件归类为垃圾邮件(所有 10 封邮件都是假阳性),但仍然可以获得相当好的准确度分数。

对于这种情况,精确和回忆非常方便。这两个指标可以结合起来得到 F1 分数,它是精确度和召回分数的加权平均值。该分数的范围从 0 到 1,1 是 F1 的最佳分数。

我们将使用所有 4 个指标来确保我们的模型运行良好。对于数值范围从 0 到 1 的所有 4 个指标,分数尽可能接近 1 是我们的模型表现如何的良好指标。

**from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_scoreprint('Accuracy score: ', format(accuracy_score(y_test, predictions)))print('Precision score: ', format(precision_score(y_test, predictions)))print('Recall score: ', format(recall_score(y_test, predictions)))print('F1 score: ', format(f1_score(y_test, predictions)))**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

  • 与其他分类算法相比,朴素贝叶斯的一个主要优势是它能够处理大量的特征。在我们的例子中,每个单词都被视为一个特征,有成千上万个不同的单词。
  • 此外,即使存在不相关的特征,它也能很好地执行,并且相对不受它们的影响。
  • 它的另一个主要优点是相对简单。朴素贝叶斯开箱即用,很少需要调整它的参数。
  • 它很少过度拟合数据。
  • 另一个重要的优势是,对于它可以处理的数据量来说,它的模型训练和预测时间非常快。

如果你喜欢这篇文章,那么你可以看看我关于数据科学和机器学习的其他文章 这里

如果你想了解更多关于机器学习、数据科学和人工智能的知识 请在 Medium 上关注我,敬请关注我的下一篇帖子!

基于朴素贝叶斯的姓名分类

原文:https://towardsdatascience.com/name-classification-with-naive-bayes-7c5e1415788a?source=collection_archive---------11-----------------------

把手放在某物或者某人身上

建立一个分类器来区分人名的来源/国家。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Olomana Trail, Oahu, Hawaii, where people from all over the world gather; img by Pinterest Best Oahu Hikes

随着越来越多的人出国旅游和生活,看到国际人士(无论是学生/职业人士/配偶)并不罕见。在更加国际化的环境中,来自真实世界的数据会有更多外国人的名字。作为一名商业从业者,每当有一个庞大的名单时,比如医疗/教育机构,(实际上是任何有个人信息的公司),确保客户的信息正确是非常重要的。

比以往任何时候都有更多的人出国旅游、移民或学习,去了解和体验这个世界。

但是手动根据姓名将某人归类到他们的国籍,将是一个痛苦而漫长的过程,这对于机器学习来说是一项完美的任务,特别是对于自然语言处理来说。

令人欣慰的是,有许多机器学习库可以让我们轻松地构建和部署我们的原型。在这里,我们将使用 python 中的 scikit-learn 库实现朴素贝叶斯分类器。

在这个项目中,我

  1. 收集和生成与国籍相关的假姓名数据
  2. 加载、清理和矢量化名称(文本数据)
  3. 训练和评估模型
  4. 想法和结论

我们开始吧!

收集和生成名称数据

收集高质量的数据来训练分类器,实现您想要的工作,这是任何机器学习项目的重要部分。与您使用的模型类型及其体系结构一样,您用来训练模型的数据的质量和数量也会对模型的性能产生巨大影响。在分类问题的情况下,每个类的数据量必须平衡,特征与预测类标签有较高的关系。在真实的应用程序中,您还会希望确保您的数据实际上看起来像您的模型在服务中会遇到的数据。

这里,因为这是一个实验项目,所以使用 python 假数据生成库 Faker 生成了各种国籍的假名字。这个库不仅能生成假名字,还能生成其他假数据,如假地址。您可以选择不同的国家和地区作为数据/名称的来源,有关更多详细信息,请参考文档。

看看不同的名字

我试图创建一个模型来对姓名的国籍进行分类,那么需要注意哪些要点呢?全球有各种不同文化和国家的名字,但在这个项目中,我将主要关注第一世界国家的名字。那么有哪些来自不同文化的名字的例子呢??让我们使用熊猫作为数据帧来加载数据,并查看它。

Names their origin countries

这里,导入了用于数据预处理的 couple 库,并使用 Pandas 作为 DataFrame 对象加载数据。Code列保存国家的名称,name保存与国家相对应的名称字符串。

正如你所看到的,一些名字是英文字母,一些不是,其他人使用汉字,韩文,或日文平假名/汉字。每个名字的姓、(中间)和名(可能更多的成分取决于文化)之间用空格分开。现在最大的问题是,如何将它们输入到模型中…??

数据预处理

作为计算机算法,机器学习模型无法将姓名数据解释为文本数据。首先需要将名称转换成数字表示,有许多技术可以做到这一点。这里我使用了单词袋模型。

一袋单词

机器学习数字的输入和输出向量,在单词袋模型中,文本被转换成数字的向量。基本思想是为文档中出现的每个唯一的单词分配一个唯一的整数,因此文档(本质上是单词序列)可以表示为一个数字序列。

有几种技术可以在单词包模型中进一步表示文档,但是在这个项目中,我使用了来自 scikit-learn计数矢量器 。这种技术产生具有整个词汇长度的向量,每个索引位置代表在文档中出现的唯一单词,并且索引位置中的值表示该单词在文档/文本中出现的频率。这样,文档中单词的顺序不会被保留,但这是用整数表示文档的一种简单而直观的方式。让我们来看看实际情况。

CountVectorizer from scikit-learn

在这里,我已经初始化了 CountVectorizer,并用一个名字列表来匹配它,每个名字都用空格分成姓和名。在拟合过程中,姓名被分为姓氏和名字两部分,并创建单词->整数的映射/字典。之后,名字数据通过.transform()转换成带有词频信息的行向量。输出是 scipy 稀疏矩阵(包含许多 0 和小数字的矩阵,因为大多数姓名中不包含其他姓氏和名字)。

编码国家标签

就像名称数据一样,模型本身不能将标签解释为文本。由于有 10 个类别标签,它们可以在一个列向量中被编码成从 0 到 9 的整数。这可以通过使用 scikit-learn 的 OrdinalEncoder 类来完成。

首先,我们将初始化 OrdinaryEncoder 类,并使用 fit 方法来拟合/训练编码器。在这个过程中,您将创建一个映射,将唯一标签转换为指定的整数。之后,使用.transform()方法,你使用编码器将整个数据编码成整数的列向量。请注意,这个编码器实例可以在以后重新用于编码/解码标签。

最后,数据将被分为训练集和测试集(用与训练集相同的数据来测试模型是不公平的)。通常,训练集和测试集的拆分比例约为 70% : 30%。我们在sklearn.model_selection通过.train_test_split()方法做到这一点。

test_size是一个介于 0~1 之间的浮点值,指定测试集数据与向方法提供的原始数据的比率。xy分别代表数据和标签。

训练和评估模型

多项式朴素贝叶斯分类器

现在我们已经准备好了数据,让我们开始训练模型。我用过 scikit-learn 的多项式朴素贝叶斯类。库中有多种类型的朴素贝叶斯分类器,但是根据文档,这种分类器适合于文本分类

[**MultinomialNB**](https://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.MultinomialNB.html#sklearn.naive_bayes.MultinomialNB)为多项式分布数据实现朴素贝叶斯算法,它是文本分类中使用的两种经典朴素贝叶斯算法之一(其中数据通常表示为词向量计数,…

使用 scikit-learn 训练朴素贝叶斯模型非常容易,第一步是实例化类实例。接下来,将训练数据和标签输入到模型中。这里的训练数据是一个稀疏矩阵,标签是一个带有整数标签的列向量,每个标签代表一个国家。

评估和预测

现在我们有了一个经过训练的模型,让我们看看我们的模型表现如何。我们将使用从数据加载阶段创建的测试数据集。分类模型有几个评分标准,这里使用了准确度。出于项目目的,使用 python 包装类 NameClassifier 进行训练和预测。本文的其余部分使用这个类来演示和分析结果。

为了进行预测测试,创建了一个包含 2 个日本人、2 个美国人和 1 个香港人姓名的姓名列表,并将其输入到训练模型中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正如你所看到的,模型预测 2 个日本名字和第一个英文名字没有问题,但由于某种原因,它错误地将第二个英文名字归类为埃及人(稍后会详细介绍),将香港名字归类为俄罗斯人。

想法和结论

混淆矩阵是一个正方形表,其中有^ 2 元素的类数。表格的行代表真实的标签值,而列是预测的标签,这是分析模型性能的很好的工具。让我们来看看这个模型的一个。看看我在这里写的关于如何绘制混乱矩阵的帖子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

行代表真实标签,而列是预测标签。因此,对角线值代表真实的预测。从这个矩阵中,我们可以看出许多埃及名字被误归类为美式英语名字,反之亦然。它还将一些中国名字归类为日本名字,考虑到它们有多少共同的汉字字符,这并不奇怪。

现在,错误分类英语和埃及语名字的原因是这些名字在训练和测试数据中看起来是一样的。

这可能是由于 Faker 库首先用来生成数据。事实上,在他们的文档中提到

Faker 的本地化是一个持续的过程,我们需要您的帮助。请不要犹豫,为您自己的地区创建一个本地化的提供商,并提交一个拉请求(PR)。

我猜埃及地区还没有准备好,因此它返回默认的美国英语名称。

处理看不见的名字

该模型的测试集也来自 Faker 包。如果模型遇到了它在训练/测试数据中没有见过的名字,会发生什么??名字在不同类型的角色中的不同表现方式呢?

不在原始数据集中的独特的日语名字和英语名字的片假名一起被输入模型。根据训练实例,模型有时会将汉字和片假名表示预测为挪威语、汉语或俄语。它似乎在对看不见的数据进行随机猜测。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测设置

还有几个关于模型/预测设置的其他问题。例如,增加模型的分类标签如何影响其准确性?这个项目是来自日本与否(只是一个二元分类,其中有 90%以上的测试精度)。因此,类别越多,正确预测就越困难。这在直觉上是显而易见的,因为选择越多,就越难从中做出正确的选择。选择正确答案的概率(基于随机猜测)是 50%,而在 10 类分类的情况下,它下降到 10%。

这种模式与不同的模式

  • 使用朴素贝叶斯模型有什么好处和坏处?

朴素贝叶斯的优点是轻量级的。它几乎不需要时间来训练,并且可以体面地用于工业用途。

缺点包括它不能对看不见的名字进行分类,这些名字在训练集中不包含任何姓/名的成分。这意味着它不是学习名称模式/结构,而是“记住”训练数据集。(是因为 Naive Bayes 的工作方式,在给定类标签的情况下,它返回某些名称组件出现的可能性;或者使用的矢量化方法,即简单地统计单词的出现频率)。

  • 可能更好的分类器模型选择,例如神经网络(RNN、CNN 或注意力模型或变压器)

也有可能单词模型包(在这种情况下特别是 CountVectorizer)没有从名称文本中提取必要的信息,以区分国家名称。做这件事的其他选择是什么?

  • 单词包中的其他模型,如哈希、N-gram 等
  • 除了单词袋、单词嵌入之外的不同模型,例如 word2vec、GloVe

了解它们的工作原理很重要,因此能够根据它们的优缺点来使用它们。其他模型或自然语言处理技术将在其他职位上演示。此外,请检查这个名称分类器项目的 jupyter 笔记本。希望这至少是有帮助的或有趣的,并随时提问或提出建议。感谢阅读!

说出你最喜欢的 Excel 函数,我会教你它的熊猫等价物

原文:https://towardsdatascience.com/name-your-favorite-excel-function-and-ill-teach-you-its-pandas-equivalent-7ee4400ada9f?source=collection_archive---------5-----------------------

在这篇文章中,我们利用流行的库 Pandas 来编码实现与 Python 的索引/匹配的方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Glenn Carstens-Peters on Unsplash

所以既然还没人起名字,那我就开始了!迄今为止,我最喜欢的 excel 公式之一是嵌套在索引函数中的匹配函数。但是在我教你它的熊猫等价物之前,让我们先了解一下INDEX/MATCH函数的背景,以及为什么它比VLOOKUP.函数好

INDEX/MATCH优于VLOOKUP的两个原因:

  1. 您可以在整个电子表格中搜索值,而不是被迫只搜索最左边的列。(下面有更多相关信息)
  2. 对于未排序的数据,计算效率提高了 3%,对于排序的数据和近似匹配,计算效率提高了 30%,对于排序的数据和精确匹配,计算效率提高了 13%!(来源 T19)

通过组合INDEX/MATCH公式,你可以绕过VLOOKUP的限制。简而言之,VLOOKUP扫描给定范围最左边的列,直到它落在给定“search_key”的第一个实例上。然后,它返回所提供的索引中单元格的值,该值将始终位于右侧。但是,正如我上面所说的,使用INDEX/MATCH您可以搜索整个电子表格(按列或按行)的值,而不是被迫使用VLOOKUP只搜索最左边的列。

看看这个 月度播客仪表板 吧,这是我在 Vox Media 担任流量分析师时为 Recode 构建的,看看我是如何利用嵌套在INDEX/MATCH函数中的SMALL函数来显示剧集级数据的。

现在让我们进入有趣的部分…如何用熊猫做到这一点!

我将向您展示利用 Pandas 库用 Python 编写代码的四种方法,但是首先,让我们了解一下我们目标的背景。我们有两个名为df_1df_2的数据帧(如下所示)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

df_1 (left) and df_2 (right)

我们的目标是将df_2中的last_name列与df_1中的正确行进行匹配,得到如下结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

解决方案 1:使用。地图()

**code**:df_1[‘last_name’] = df_1.id.map(df_2.set_index(‘id’)[‘last_name’].to_dict())2.3 ms ± 131 µs per loop

这里我们为df_1创建一个新列last_name。这个新列的值是通过将来自df_1的 id 映射到那些 id 匹配的df_2中的姓氏来创建的。通过对我们的系列df_2.last_name调用.to_dict()方法,我们得到了索引的键:值对,这将是:{0: ‘Snow’, 1: ‘Targaryen’, 2: ‘Tyrell’, 3: ‘Lannister’, 4: ‘Stark’}。在这种情况下,.map()方法将不起作用,因为我们的id列中的值与这个字典中的键不匹配。所以我们首先传递了.set_index()方法,将索引改为df_2的 id,这将为我们提供这个字典:{1003: ‘Snow’, 1004: ‘Targaryen’, 1005: ‘Tyrell’, 1002: ‘Lannister’, 1006: ‘Stark’}。我们现在可以使用.map()方法将我们的系列值(id)映射到新字典的相应值。

一位数据科学家同事 Bernard Kurka 帮助我找到了第一个解决方案。也看看他的一些中型帖子

解决方案 2:使用。加入()

**code**: df_1 = df_1.set_index('id').join(df_2.set_index('id'))39.2 ns ± 0.709 ns per loop

.join()方法将连接另一个数据帧的列。默认情况下,它执行左连接,但是您可以通过传递how=超参数并将其更改为“右”、“外”或“内”来指定。我们需要在df_1df_2上调用.set_index()方法,这样我们就可以加入正确的索引。

解决方案 3:使用。合并()

**code**: df_1 = df_1.merge(df_2, how='left', on='id')38 ns ± 0.369 ns per loop

.merge()方法用数据库风格的连接合并数据帧或命名系列对象。在这里,我通过指定on=超参数来指定我希望它如何与how=连接以及在哪个列/索引上连接。

解决方案 4:使用 pd.concat()

**code**: df_1 = pd.concat([df_1.set_index('id'), df_2.set_index('id').last_name], axis=1, sort='id', join='inner')38.5 ns ± 0.379 ns per loop

pd.concat()方法沿着一个特定的轴连接 pandas 对象,沿着其他轴连接可选的 set 逻辑。所以在这里我传递了我想要连接成一个列表的熊猫对象。第一个是 DataFrame,其中我将索引设置为id列,第二个是 Series,但也在id列上进行索引。通过设置axis=1,我指定了要连接的轴,1 表示列,0 表示索引(行)。因为id列没有在df_2上排序,所以我也必须指定sort=超参数。join=超参数指定如何处理其他轴上的索引。

我认为这真的很酷,我们看到有几种方法可以做完全相同的事情。所以现在的问题是,这些方法中哪一个计算效率最高?我包括了上面的时间,但是我会把它们排在这里,这样你就不用向上滚动了。他们将从最快运行时间到最慢运行时间排列。

  1. .merge()每环路 38 纳秒±0.369 纳秒
  2. .concat()每环路 38.5 纳秒±0.379 纳秒
  3. .join()每环路 39.2 纳秒±0.709 纳秒
  4. .map()每循环 2.3 毫秒 131 秒

如果你发现自己需要使用这些方法中的一种,我希望你可以参考这个(或我的 代码 —如果是移动设备,滚动到底部并选择右边的“显示桌面版本”)作为如何做的指导。我很想把这变成一个系列,在那里我会教你如何用 Python 和 Pandas 之类的库在 Excel 中做更多你喜欢做的事情,所以请在下面的评论中告诉我你接下来想看到什么。一如既往,感谢阅读。

基于知识图的命名实体消歧

原文:https://towardsdatascience.com/named-entity-disambiguation-boosted-with-knowledge-graphs-4a93a94381ef?source=collection_archive---------3-----------------------

我们结合基于文本和图形的方法来建立命名实体消歧管道。

作者:Brian Lin,Sheng song(Shane)Ong,Cory Williams,Yun Bin (Matteo) Zhang

特别感谢我们的顶点课程,哈佛大学的AC 297 r,我们的导师 Pavlos Protopapas 和 Chris Tanner,以及我们的顶点合作伙伴 Kensho Technologies。

介绍

命名实体消歧(NED)或命名实体链接是一项自然语言处理(NLP)任务,它为文本中提到的实体分配唯一的身份。这有助于文本分析。例如,一家金融公司可能希望确定一篇新闻文章中提到的所有公司,并随后调查这些公司之间的关系可能会如何影响市场。

在给定文本文档的情况下,将 NED 视为信息提取管道中的一个组件是很有帮助的。例如,如果我们得到一个包含句子“福特总统赦免尼克松总统”的文本文档,我们将首先识别所有感兴趣的单词,例如“Ford”。这被称为命名实体识别(NER)。“福特”一词可以指杰拉尔德·福特总统、亨利·福特或汽车公司“福特”。因此,管道中的第二步是候选词选择,我们缩小感兴趣的已识别单词的可能候选词列表。随后,我们从候选列表中消除实体的歧义,并将每个被识别的实体链接到知识库中的唯一标识符。在上面的例子中,我们应该理想地将实体“Ford”标识为“Gerald Ford”。这最后一步是本文的重点— NED。所有代码都可以在我们的 Github 上找到。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作为人类,我们发现使用来自周围文本的上下文信息来正确地识别‘福特’是前总统杰拉尔德·福特是很容易的。人们可能期望一个合理设计的模型也应该能够使用文本信息来这样做。然而,如果我们能够访问知识图,消歧的过程可以进一步改进。

单词嵌入

我们希望利用文本的上下文来确定正确的实体。为此,我们首先需要将每个单词表示为一个实数向量,这就是所谓的单词嵌入。理论上,我们想要一种嵌入,使得具有相似含义的单词在向量空间中彼此接近。例如,我们希望与政治相关的单词在向量空间的一部分,而与汽车相关的单词在另一部分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

知识图表

知识图本质上是知识库的图形表示,其中实体及其关系分别表示为节点和边。维基数据是维基百科的结构化形式,是一个知识库。例如,在 Gerald Ford 的 Wikidata 知识库条目中,“Ford”是一个实体/节点,带有一个边/关系“party”,它链接到另一个实体/节点“Republican Party”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

重要的是,我们期望在知识图中,文本文档中识别的实体彼此靠近。然后,我们可以根据文本的上下文推断出每个实体的唯一身份!

但是,知识库和图形会占用大量内存。对于深度学习方法,我们使用图形嵌入来表示低维向量空间中的信息。图形嵌入有多种方法。我们使用杨等人(2015)的 DistMult 来嵌入知识图,而不是使用不是为知识图设计的典型图形嵌入方法。DGL——知识图嵌入实现用于高效训练 760 万维基数据实体的子集。对于图完成任务,这产生了 90.1%的前 1 命中率,其中我们试图预测 a(头部,边缘,???)三连音和头在(???、边缘、尾部)三个一组。

动机

大多数当前的 NED 方法依赖于文本方法,其中使用文档的上下文信息来推断实体的身份。还有相当多的研究是关于在知识图上使用图形方法,如图形卷积网络。然而,据我们所知,结合文本和图形信息的方法研究不多。具体来说,我们使用前一节中提到的新的图形嵌入来显著改善消歧结果。

数据

我们使用维基百科的文章和维基数据库来训练我们的模型。几乎所有文章在知识库中都有相应的条目。此外,每篇维基百科文章都有现成的超链接文本,称为锚文本,将维基百科文章相互链接。这些是我们在 NED 任务中使用的数据中的重要特征。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由于维基百科的规模,我们在所有可用维基百科文章的大约 1%上进行训练(385,000)。此外,我们只包括每篇文章的“介绍”部分;由于维基百科不重复超链接,所以在识别所有感兴趣的单词时,介绍部分是最全面的。此外,我们注意到,在典型的 NED 任务中,超链接识别的感兴趣的单词不需要对应于命名的实体。例如,苹果(水果)可能在维基百科的文章中被链接,但它不被认为是一个命名的实体。然而,尽管数据集不完美,但由于数据集的稀有性,它可能是用于 NED 的监督方法的最佳数据集。

以下是所使用的一些相关数据集。我们的数据集是 2019 年 8 月 8 日的维基百科快照。Kensho Technologies 计划向公众开放数据集,我们将相应地更新每个数据集的链接。Kensho 现在已经向公众开放了数据集

  • enwiki.k_link :维基百科文章上链接到其他维基百科文章的超链接数据集。超链接在源页面上,而超链接链接到目标页面。锚文本是超链接的实际可点击文本(即蓝色文本)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • enwiki.k_plaintext :维基百科文章章节的文本数据集。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • enwiki.page :维基百科页面的数据集。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • enwiki.k_raw_anchors :链接到其他维基百科文章的超链接的锚文本数据集。如果是锚文本,则用于指示不是目标维基百科页面标题的实体的同义词/其他名称!=目标页面标题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

以下数据集与维基数据相关:

  • **wiki data . item:**wiki data 项目的数据集。知识图的节点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • wiki data . qpq _ item _ statements:wiki data 三元组数据集:(源,边,目标)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

命名实体识别

在对维基百科介绍进行典型的文本预处理之后,我们使用 SpaCy 库来识别介绍(NER)中的所有命名实体。SpaCy 是一个著名的工业级 NLP 库,具有实体识别功能。

注意:由于 SpaCy 使用广泛的特征工程来降低其模型的复杂性,它在实体识别中对文本的大小写特别敏感。因此,在降低文本的大写字母之前,我们识别所有具有空间的实体。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

候选人选择

对于一个被识别的实体,我们需要从我们的知识图中选择能够对应于被识别实体的真实实体的实体。在这一步中,我们结合了两种方法:锚文本频率和 MinHash 位置敏感哈希(LSH)森林。

锚文本频率

对于维基百科上的每个锚文本,我们有锚文本对应于目标页面的频率。我们存储了一个锚文本字典和它们的目标页面列表,按照锚文本映射到目标页面的频率降序排列。请注意,我们的预处理对锚文本进行了小写处理,因此有一些处理后的锚文本频率的总和不为 1。然后,对于一个被识别的实体,我们得到被识别的实体文本在字典中映射到的前 anchor_k 个实体。直觉上,我们会认为,如果一些锚文本映射到维基百科上出现频率很高的实体,那么当锚文本在维基百科上下文之外被提及时,该锚文本很有可能会引用该实体。

LSH 森林

仅有锚文本方法是不够的,因为它要求被识别的实体与锚文本完全匹配。即使拼写错误导致一个字符的差异也可能导致不匹配。因此,还应该利用相似性匹配,其中我们检索与所识别的实体文本具有相似名称的实体。具体来说,我们利用 Jaccard 相似性。Jaccard 相似性可以用来检查两个文本有多相似,它可以通过米哈斯 LSH 有效地近似。关于 Jaccard 相似性和 MinHash LSH 的更详细的概述,请看这篇教程,我们的代码就是从它改编而来的。我们在字符级别上测量文本的相似性,以解决拼写错误。然后,对于一个已识别的实体文本,我们可以得到前 lsh_k 个相似实体。

因此,对于一个已识别的实体,从我们的候选项选择中,我们可以从锚文本和 LSH 中获得排名靠前的实体,这就是我们的已识别实体的候选项。

实体链接

我们将该模型视为一个分类问题。该模型预测每个候选词是否是感兴趣的词的真实实体。首先,我们在每个感兴趣的单词周围创建一个上下文窗口(例如 10 个单词),并将其作为模型的一部分输入到嵌入层中。这种上下文单词嵌入被馈送到双向 LSTM 中;其输出与知识图嵌入连接,并被馈送到前馈神经网络。FFNN 创建了知识图嵌入和局部上下文嵌入之间的映射。

结果

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于训练,我们包括 10 个假实体,如果可能的话,用真实体作为潜在候选。我们有大约 1200 万个数据点,有 20.11%的正面标签和 79.89%的负面标签。我们将数据分成一个训练/测试集,确保同一识别实体的候选数据在同一个集中,以防止泄漏。我们实现了 0.8678 的测试准确度和 0.9000 的 AUC。我们主要关心 0.57 的召回;我们能够在 57%的时间里预测正确的实体。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然而,有可能不止一个候选被预测为正确的实体,或者没有候选被预测为正确的实体。相反,我们然后预测具有最大概率的候选作为正确的实体。然后,该模型能够在 75.8%的时间内预测正确的实体,这是一个显著的改进。

模型演示

因此,完整的管道是 NER、候选人选择和 NED 阶段的组合。当给定一个文本文档时,我们识别所有感兴趣的单词,并将它们链接到 Wikidata 知识库中的相应条目。为了演示我们的管道,我们使用了一个简单的 Jupyter 小部件,它接收一个文本文档,并返回相同的文本文档,其中包含链接到相应维基百科文章页面的感兴趣的超链接单词。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

测试我们的模型

这是我们的管道的演示,我们的管道在这里完美地工作。

我们可以看到,我们的模型能够区分篮球运动员迈克尔·乔丹和机器学习研究员迈克尔·乔丹。这意味着我们的模型能够根据句子中发现的实体之间的上下文和图形连通性来消除正确候选词的歧义。

这是另一个演示,我们的管道无法获得正确的实体。我们看到,我们的模型指向的不是史蒂夫·乔布斯,而是一部模仿史蒂夫·乔布斯的电影《iSteve》。进一步检查我们的模型,我们看到我们的候选人名单甚至不包括史蒂夫·乔布斯。这表明我们的候选人选择失败,而我们的 NED 模型似乎做出了明智的选择,选择了一部与史蒂夫·乔布斯有关的电影。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

另一方面,第二个失败之处在于 NED 机型对 iOS 的排名高于 iPhone。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个失败是由于 NED 模型仅仅基于来自图嵌入的单词和连接的上下文。值得注意的是,我们可以将句子中的 iOS 替换为 iPhone,这样读起来仍然很好。因此,当考虑实体的 iOS 时,上下文和底层连接是完全合理的。这是一个失败,因为没有在消歧阶段惩罚文本差异。

未来的工作

正如我们的结果所指出的,一个主要的瓶颈肯定是候选人选择阶段。可以通过更仔细的特征工程来改进候选选择字典。至于 NED 模型,我们可以在损失函数中惩罚所选候选的文本不相似性,以避免具有完全不同的文本的实体在相同的上下文中完美地工作而被选为候选的情况。此外,考虑到 BERT 在许多 NLP 任务中的主导性能,它仍然值得考虑作为我们的单词嵌入的替代品,但它需要更强大的 GPU 来进行适当的微调。如果有更多资源,将 NER 和候选人选择公式化为深度学习问题,并共同训练所有阶段,以在每个任务中共享信息,这将是很有趣的。

参考

[1] B. Yang,W. Yih,X. He,J. Gao,L. Deng,在知识库中嵌入用于学习和推理的实体和关系,2015

[2] J. Devlin,M. Chang,K. Lee,K. Toutanova, BERT:用于语言理解的深度双向转换器的预训练,NAACL 2019

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值