TowardsDataScience-博客中文翻译-2019-四十七-

TowardsDataScience 博客中文翻译 2019(四十七)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

我对敏捷数据科学研究的最佳建议

原文:https://towardsdatascience.com/my-best-tips-for-agile-data-science-research-b40365cc979d?source=collection_archive---------7-----------------------

如何在最短的时间内带来最大的价值

几天前,我读了 Shay Palachy 和 T2 Ori Cohen 写的两篇关于敏捷数据科学项目管理的文章。这些帖子讨论了数据科学项目的不同阶段,以及它们与常规软件项目的不同之处。这些帖子激励我写下自己对敏捷数据科学的看法,重点是研究方法,而不是整个项目阶段。

敏捷数据科学研究很难,当你不确定你的问题是可解决的,你怎么能给出一个时间估计呢?在看数据之前怎么规划自己的冲刺?你可能不能。敏捷数据科学需要许多调整,在这篇文章中,我将分享一些最适合我的敏捷数据科学研究的最佳实践。

设定项目目标

每个机器学习项目都应该从定义项目的目标开始。我们必须定义什么是好的结果,才能知道什么时候停止研究,进入下一个问题。这个阶段通常由业务涉众完成。

目标由 3 个问题定义:

  • 我们正在优化的 KPI 是什么?这可能是项目中最重要的问题,KPI 必须可以用测试集来衡量,而且尽可能与业务 KPI 相关。
  • 评估方法是什么?测试集的大小是多少?我们需要时间序列分割/分组分割吗?我们需要在线测试吗?
  • 最低有价值的 KPI 是多少?有时,机器学习模型将取代一些简单的启发式方法,即使 65%的准确率对企业来说也是非常有价值的。我们需要定义什么是成功。

始终与基线模型进行比较

什么是好的性能是一个很难回答的问题,这个问题很大程度上取决于问题的难度和业务需求。我的建议是通过建立一个简单的基线模型来开始建模,它可以是一个简单的具有基本功能的机器学习模型,甚至是一个商业规则(启发式),如重要类别中的平均标签。这样,我们可以通过与基线的比较来衡量我们的表现,并监控我们在任务中的改进。

从一个简单的模型开始

迭代是敏捷开发的核心特征之一。在数据科学项目中,我们不像工程团队那样迭代特性,而是迭代模型。从具有少量特征的简单模型开始,并迭代地使其变得越来越复杂,这有许多优点。当你的模型足够好的时候,你可以在任何一点停下来,节省时间和复杂性。你确切地知道你所做的每一个改变是如何影响模型性能的,这为你的下一个实验提供了直觉,也许最重要的是,通过迭代地增加复杂性,你可以更容易和更快地调试你的模型的错误和数据泄漏。

计划子目标

规划研究项目很难,因为它们有很大的不确定性。根据我的经验,最好使用子目标来规划项目,例如,数据探索、数据清理、数据集构建、特征工程和建模是研究的一小部分,至少可以提前几周进行规划。这些子目标可以在没有最终模型的情况下自行带来价值。例如,在数据探索之后,数据科学家可以为业务人员带来可操作的见解,数据集清理和构建可以立即帮助其他数据科学家和分析师开展他们自己的项目。

快速失败

快速失败可能是我最重要的一点,也可能是最难做到的一点。在每次迭代时,你必须问自己,模型性能达到最小有价值 KPI 的概率是多少?我认为迭代地使模型更复杂确实有助于这一部分。添加更多的功能和尝试更多的模型通常会带来渐进式的改进。如果你的模型性能是 70%,而你的最小有价值 KPI 是 90%,你可能不会达到那里,所以,你需要停止你的项目,并转移到下一个问题,或改变一些激烈的事情,如改变你的标签或标记更多的数据。我并不是说你不应该尝试解决非常困难的问题,只是要确保你没有在可能达不到你的项目目标的方法上浪费时间。

尽快投入生产

我的最后一个建议是,在最早的时候,或者在模型有价值的时候,将模型部署到产品中。我知道也许你最终的模型会有完全不同的特征,很多工作会被浪费掉。但是,首先,你的模型给出了价值,为什么要等待?其次,更重要的是,在许多情况下,生产有其自身的限制,有些功能在生产系统中不可用,有些功能采用不同的格式,可能您的模型速度太慢或使用太多 RAM 等。及早解决这些问题可以节省大量不切实际的建模时间。

希望你喜欢我的帖子,非常欢迎你阅读和关注我的博客。

我赌因果强化学习

原文:https://towardsdatascience.com/my-bet-on-causal-reinforcement-learning-d94fc9b37466?source=collection_archive---------16-----------------------

营销科学的下一个杀手级应用

Robert Osazuwa Ness,机器学习工程师博士,定期在 AltDeep 撰写关于数据和决策科学、机器学习和人工智能的微趋势观察。

上周,我开始准备给一些数据科学研究生讲授一个特殊的主题— 强化学习中的因果建模

反思这个话题,我打个赌:因果强化学习将是未来十年内的 AI 杀手级营销 app

RL 和因果建模的背景

强化学习关注的是软件代理应该如何在一个环境中采取行动,以最大化一些累积回报的概念。因果建模是建立可以明确表示和推理因果关系的模型(最近的科普书籍《为什么的书》提供了该主题的通俗易懂的介绍)。

近年来,机器学习研究社区对这两个领域都表现出了越来越大的兴趣。这种对强化学习的兴趣是由结合深度学习和强化学习以创建能够击败人类专家的代理的重大成就推动的。突出的例子包括古代战略游戏围棋基于团队的比赛在幻想电脑游戏 Dota 2有人认为深度强化学习是广义 AI 的路径。

因果建模如何适用

说到玩游戏,人类代理人通过形成其环境的因果模型来“玩”活着的生命的“游戏”。这些是概念模型(“这是一个棒球,那是一扇窗户”),对象之间有因果关系(“如果我把棒球扔向窗户,它就会粉碎”)。因果模型允许我们将知识转移到新的不熟悉的情况(“我敢打赌,如果我把这个奇怪的新的硬的重的东西扔向那个奇怪的新的脆的玻璃状的东西,它也会碎”)。

当决定做什么和不做什么时,人类用这些模型进行推理。你是否曾经思考过你在特定情况下的行为,并认为,“如果我做的事情不同,事情会变得更好。”那叫做反事实后悔,是因果推理的一种形式。你在头脑中使用一个因果模型,在脑海中模拟如果你做出不同的决定,事情会如何发展。反事实后悔是这种模拟的可能结果和实际发生的结果之间的差异。当你基于对过去决策的因果推理做出你认为会避免遗憾结果的决定时,你正在利用强大的认知机制。

一些游戏代理,比如最近在无限注德州扑克中击败人类扑克专家的代理,通过模拟数百万场游戏,做了一个最大限度减少反事实后悔的暴力版本。这比人类玩家依赖更多的经验和计算资源。

缺乏实用的工具

我专注于执行。虽然网上有无穷无尽的深度强化编程教程。然而,在编程强化学习中引入因果建模的实际案例研究还很缺乏。有一些研究(例如由 Vicarious AI 开发的模式网络),但是我实际上还没有看到任何代码。例如,将因果建模中的编程抽象如 Pearl 的 do-operations 与强化学习中的动态编程相结合的最佳方式是什么?我的希望是,将因果建模的理论和方法应用于编程 RL 可能会导致构建有用的编程抽象,用于构建更好的 RL 代理,特别是那些只需要一些真实或模拟经验就可以处理不熟悉情况的代理,就像我们人类一样。

自动化决策科学的赌注

我说我在这个问题上“打赌”,而不是做预测,因为打赌是游戏中有皮肤的预测。当我可以在 deepfakes 或 transformer networks 上工作的时候,我正在解决这个问题(这两个项目都非常值得、有利可图,而且有些令人恐惧),因为我认为这将会有回报。

我看到了一些套利机会。深度强化学习的商业应用实际上是不存在的,除了向 OpenAI 和 Deepmind 投入大量资金,以便他们可以玩视频游戏(这没什么错)。

然而,RL 中的核心理论是为决策科学的各种元素提供动力的相同理论;顺序实验、最优化、决策理论、博弈论、拍卖设计等。将这些理论分支应用于决策问题正是数据科学家影响最大的领域,尤其是在科技领域。

因果建模是连接所有这些领域的线索。它甚至引入了计算认知心理学,在那里人们模拟了人类头脑中的因果模型。这使得人们可以从关于人类行为的数据中模拟人类的非理性,如认知偏差和谬误。在我看来,广告商花了大量时间让人们不理性地花钱。

我认为因果强化学习将是市场营销的圣杯。想象一下,在《黑镜》中,他们可以在数字口袋世界中制造出一个认知克隆体,并进行一百万次模拟,测试你会购买什么样的产品。就像那样。

我的顶点项目:伦敦房地产价格和场馆数据分析

原文:https://towardsdatascience.com/my-capstone-project-real-estate-prices-venues-data-analysis-of-london-c936c0bc4b1d?source=collection_archive---------16-----------------------

Photo by Giammarco on Unsplash

他的文章是为 Coursera 的 IBM 数据科学专业认证的最终顶点项目的一部分。在这篇文章中,我将分享我所面临的困难以及我实现的一些概念。

本文将包含任何数据科学项目所必需的以下步骤:

  1. 问题陈述
  2. 数据收集
  3. 数据预处理
  4. 机器学习
  5. 形象化
  6. 结果

问题陈述

伦敦是英格兰和英国的首都和最大的城市,拥有欧盟最多的城市人口。伦敦有各种各样的人和文化,该地区有 300 多种语言。其 2016 年年中的城市人口(对应大伦敦)估计为 8,787,892 人,是欧盟人口最多的城市,占英国人口的 13.4%。根据 2011 年的人口普查,伦敦市区拥有 9,787,426 名居民,是欧盟第二大人口密集区,仅次于巴黎。人口密度为每平方英里 14,500 人。[1]

伦敦是一个人口和人口密度都很高的城市。从房地产投资者的角度来看,我们希望投资于房价低、设施完善(商店、餐馆、公园、酒店等)的地方。)和社交场所都在附近。记住以上事情,对于一个人来说,在这样一个大城市找到这样一个地方并收集如此多的信息是非常困难的。

当我们考虑所有这些问题时,我们可以创建一个地图和信息图表,其中房地产指数放在伦敦上,并根据场地密度对每个区进行聚类。

数据收集

考虑到上述问题,数据收集如下:

  • 我从维基百科上找到了伦敦地区及其行政区和邮政编码的列表。[2]
  • 关于房价,我搜索并找到了一个很棒的网站,上面有最新的伦敦房价和邮政编码。[3]
  • 我使用 Forsquare API 获取伦敦特定行政区最常见的场所。[4]
  • 我用的氯普图。伦敦 geojson 文件。[5]

数据预处理

首先,从维基百科上搜集的数据必须是干净的。

unclean data from Wikipedia

我删除了所有的超链接,有些地方有不止一个邮政编码,所以我只保留了一个邮政编码。

对于下一张平均房价表,数据最初看起来是这样的:

Unclean data of house prices

首先,我删除了所有的空值,然后去掉了不需要的列,只保留了“面积”和“平均价格”列。然后“平均价格”列包含字符串,所以我通过删除英镑符号和逗号将其处理为整数。

在清理了两个表之后,我执行了两个表的内部连接和合并,并从结果表中删除了“拨号代码”和“操作系统网格参考”列,因为它们没有用。然后,通过使用地理编码器库,我找到了该位置的经度和纬度,并在我的数据帧中添加了每一列。

我使用 pythonfollowlibrary 来可视化伦敦及其行政区的地理细节,并创建了一张叠加了行政区的伦敦地图。我使用纬度和经度值得到如下的视觉效果:

Map of London, with markers of different neighborhoods

我利用 Foursquare API 来探索行政区并对它们进行分段。根据给定的纬度和经度信息,我为每个区设计了 100 个场地和 1400 米半径的限制。这是一个来自 Foursquare API 的场馆名称、类别、经度和纬度信息列表。

This for the first Location

我对所有位置和每个位置的场地计数等重复该过程。是:

最后,通过结合使用 Foursquare API 和创建的数据集,生成了伦敦街区最常去的场所的表。

机器学习

我们在行政区有一些共同的场地类别。为此,我使用了无监督学习 K-means 算法来对行政区进行聚类。K-Means 算法是无监督学习中最常用的聚类方法之一。

首先,我将运行 K-Means 来将这些行政区分成 6 个簇,因为当我用 elbow 方法分析 K-Means 时,它确保了 K-Means 的最佳 K 值为 6 度。

然后我合并了每个区的聚类标签表。在检查每个集群后,我将每个集群标记如下:

  1. 混合社交场所
  2. 酒店和社交场所
  3. 商店和海鲜餐馆
  4. 酒吧和历史古迹
  5. 运动和田径
  6. 餐馆和酒吧

我也想象每个地方的房价:

如上图所示,我们可以将范围定义如下:

  • 500000:“低级别 1”

  • 500000–750000:“低级别 2”
  • 750000–1000000:“平均级别 1”
  • 1000000–1250000:“平均级别 2”
  • 1250000–1750000:“高等级 1”
  • < 1750000:"高等级 2 "

结果表:

形象化

首先,我将集群可视化,您可以看到下面的集群图:

k-means clustering

  1. 红色(聚类 0)
  2. 紫色(第一组)
  3. 蓝色(第 2 组)
  4. 青色(第三组)
  5. 绿色(第 4 组)
  6. 橙色(第 5 组)

接下来,我通过使用叶绿图和顶部的聚类在地图上可视化平均房价。

Average house pricing

结果

我得出的结论是,市中心以及附近酒店和社交场所的房价非常高,你可以在上面的地图中清楚地看到,而郊区和远离市中心的社区房价较低,但设施也很好。几乎所有的低价社区都靠近餐馆、酒吧、体育设施等。一些行政区如威斯敏斯特、肯辛顿和切尔西的房价非常高。贝克斯利、克罗伊登和萨顿区的房价非常低,但附近有很好的场馆可供参观。

结论

随着人们转向大城市创业或工作。由于这个原因,人们可以很容易地解释哪里生活设施齐全,价格便宜。

不仅对于投资者,城市管理者也可以通过使用类似的数据分析类型或平台来更有规律地管理城市。

参考

  1. https://en.wikipedia.org/wiki/London
  2. https://en.wikipedia.org/wiki/List_of_areas_of_London
  3. https://propertydata.co.uk/cities/london
  4. https://developer.foursquare.com/
  5. https://joshuaboyd 1 . carto . com/tables/London _ boroughs _ proper/public

这个项目的代码可以在我的 github 资源库中找到。谢谢大家!

由于这是我的第一篇关于媒体的文章,也是我的第一个完整的项目,可能会有一些错误。请随时评论我可能犯的任何错误,以便我可以纠正自己并学习。

我汇编的简单而实用的数据清理代码

原文:https://towardsdatascience.com/my-compilation-of-simple-yet-practical-data-cleaning-codes-d692ec20dca8?source=collection_archive---------13-----------------------

为了解决混乱数据的常见情况

长话短说,这份数据清理代码汇编是我上一篇文章的更新版本— 简单而实用的数据清理代码 出乎意料地火了起来。

我收到了来自数据科学家和数据专业人员的大量消息,介绍工具箱如何帮助他们完成日常的数据清理任务,我希望通过使用我最新汇编的数据清理代码来更新工具箱,使其更加完整。

在本文结束时,我希望您会发现一些对您的数据清理任务有帮助的数据清理代码,并且您可以在尽可能短的时间内实现它们。

把这个工具箱想象成你作为一个数据科学家的武器库,它有一个通用和有用代码的集合,你可以对它们稍加修改或不加修改地执行你的普通数据清理任务。

我们开始吧!

你为什么需要这个工具箱?

世界是不完美的,数据也是。

无论您是有抱负的数据科学家、有经验的数据科学家还是数据分析师,都没有关系。

在开始分析和理解数据之前,您可能已经有 40%-70%的时间陷入了数据清理任务。

是的,现实是这个过程通常是不可避免的(除非有人帮你清理数据)。

就我个人而言,我已经经历过这段时间的耗时和繁琐的部分,因为数据清理实在是太重要了,不容忽视。

因此,就在几个月前,我开始为数据清理任务构建我的个人工具箱,因为我注意到许多数据清理代码实际上可以重复用于许多常见的数据清理任务。

换句话说,这些代码可以被推广用于其他常见的数据清理场景,在这些场景中,它们具有相似的模式——因此我编译了所有以前的数据清理代码。

这是至关重要的,因为我的工具箱节省了我思考和搜索的大量时间,因为我可以在几秒钟内从我的代码库中“复制和修改”。

通过与您分享这个工具箱,我希望能够节省您的时间,并使您的数据科学工作流程更加高效,以便您可以专注于其他重要任务。

我更新的数据清理工具箱

下面的代码是在以前的数据清理代码基础上添加的。请随意查看我的上一篇文章— 简单而实用的数据清理代码 了解更多的数据清理代码。

在下面的代码片段中,出于不言自明的目的,代码是用函数编写的。您总是可以直接使用这些代码,而无需将它们放入参数稍有变化的函数中。

1.重命名列名

当面对有大写字母或中间有空格的列名时,我们经常需要改变列名,用小写字母和下划线替换它们——这样更简洁、更生动。此外,我们希望列名尽可能明确,这样您的朋友只需查看列名就能大致了解列包含的内容。

听起来微不足道,但很重要。

2.列表理解

你可能认为列表理解是如此普遍,并想知道这怎么能被认为是数据清理的一部分。嗯……对我来说,列表理解是如此的优雅和简洁,以至于你可以在一行代码中抽象出你的逻辑,而不需要任何 for 循环,并且计算起来比 for 循环快得多。

通常,如果我想获得一个基于特定条件的值列表以附加到现有的数据帧或用于进一步分析,我会使用列表理解。

3.为特定列输出不带 NaN 值的数据帧

当您希望输出一个包含列中所有可用数据的数据帧时,这很有用。

例如,您有一个包含所有客户信息的数据帧,您希望输出一个包含所有可用客户 ID 的更新数据帧,并删除缺少客户 ID 的行。在这种情况下,代码应该是这样的:df = df[df['id'].notnull()]

类似的概念可以应用于列为timestamp的时间序列数据。

4.基于列中唯一的最后一个字符串输出数据帧

使用包含所有客户信息的数据帧,并为每个id添加一列timestamp

现在每一个id都不是唯一的,它会在各自的时间段重复出现。对于每个id,您希望获得id的最后一行,因为您只关心每个id的最终客户信息。

这时,您可以使用上面的代码片段删除所有重复的id,只保留最后一行。这确保了我们总是获得具有唯一性id的最终客户信息。同样,这只需要一行代码就可以完成!

5.从数值中获取离散区间

这是我最喜欢的工具之一,当涉及到根据指定的范围将一列中的数值转换成离散的区间时。如果你想把一个连续变量转换成一个分类变量,我强烈推荐你使用pd.cut

例如,在上面的代码片段中,我们有一个由从 1 到 10 的数值组成的rating列。如果我们想将这些评分值转换为给定值和指定范围内的特定组,该怎么办?给定使用pd.cut指定的范围,我们可以在离散区间中存储值,并将它们标记为bad, moderate, good, strong

pd.cut的另一个常见用例是将年龄转换成年龄范围组,这样就可以将每个年龄归类到一个标签中。

最后的想法

(Source)

感谢您的阅读。

在本文结束时,我希望您会发现这些小工具对您的常见数据清理任务很有用,并且会使您的工作更有效率,当然,对于那些必须不时处理杂乱数据的人来说,生活会轻松得多。

同样,代码本质上实现起来相对简单。我希望这个更新的数据清理工具箱——以及我在我的上一篇文章中分享的工具箱——给你更多的方便和信心来执行数据清理,以及根据我的经验更好地了解数据集通常是什么样子。

一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!😄

关于作者

Admond Lee 目前是东南亚排名第一的商业银行 API 平台Staq的联合创始人/首席技术官。

想要获得免费的每周数据科学和创业见解吗?

加入 Admond 的电子邮件简讯——Hustle Hub,每周他都会在那里分享可行的数据科学职业建议、错误&以及从创建他的初创公司 Staq 中学到的东西。

你可以在 LinkedInMediumTwitter脸书上和他联系。

** [## 阿德蒙德·李

让每个人都能接触到数据科学。Admond 正在通过先进的社交分析和机器学习,利用可操作的见解帮助公司和数字营销机构实现营销投资回报。

www.admondlee.com](https://www.admondlee.com/)**

我的数据分析之旅

原文:https://towardsdatascience.com/my-data-analytics-journey-d47cf52e6bd4?source=collection_archive---------29-----------------------

引导我进行数据分析的途径和学到的经验教训

Source: https://unsplash.com/photos/FSFfEQkd1sc

我的背景是会计和医疗保健咨询。在这些经历中,我用 Excel 处理了很多工作,来操作、组织和计算来自医院工资单数据和成本报告的指标。我的日子充满了 vlookups、数据透视表、宏、powerpoints,以及浏览 CMS 网站

总的来说,这是一次很好的经历,我和优秀的人一起工作。我开始旅行,过着四大咨询顾问的狂野生活。然而,就职业道路走向的技术轨迹而言,我并不完全满意。我看了看我的管理层,发现如果我继续走这条路,5-10 年后我会在哪里…主要是通过电话或旅行到网络和向医院管理层推销项目。我知道那不是我想做的。

在这个极其专业的团队工作了 2 年后,我想回到学校,拓展我学习和成长的技能。

全日制 MBA 加上我正在从事的一个初创项目,足以让我提交两周通知,开始人生的另一个阶段。

在学校的第二年(以及我的创业冒险,我计划在未来的帖子中写下这一点),我在各种行业建立了联系、进行了探索和尝试:公共卫生、医疗保健管理、非营利组织、广告、网络开发、运营改进咨询和数据分析。在所有这些经历中,数据分析是我最感兴趣的。我选修了这一领域的其余课程,并以此来满足我的学位要求。通过数据探索和发现洞察,是一个非常深刻和有用的过程。有一个永无止境的学习曲线,当我从事一个项目或有趣的数据集时,几个小时就像几分钟一样流逝。我的第一个数据科学相关项目是自动化和计算“风险”棋盘游戏的概率,你可以看看这里的。我花了很多时间做这个,并在此过程中自学 python。

在风险项目之后,我决定参加 Udemy 课程,并从事其他我觉得有趣和有用的项目。其中包括与统计学、机器学习和数据分析相关的概念。我最喜欢的项目链接在这篇文章的末尾。

这是一次疯狂的经历,在过去的 6 个月里,我学到了很多东西……幸运的是,2 个月前,我在 Regions Financial Corporation 找到了一份改善运营的好工作,所以我没有太多时间去做我想要的个人项目。然而,我正在学习与仪表板构建和项目管理相关的技术技能,并且我也计划写博客。通过一个公司赞助的 DataCamp 账户,我也一直在研究用于数据科学的 python,并计划很快回顾我使用 DataCamp 与使用 Udemy 课程的经历。

这可能需要很多年,但我的目标是精通并自信于我的数据科学能力,这样我有一天可以从事机器学习和高级建模工作。我还有很长的路要走,但我相信在过去的一年里,我承担了健康的风险,付出了很多努力,并取得了很大的进步。

我知道这是老生常谈,但对任何阅读这篇文章的人来说,唯一的教训是每天都努力追求你想要的东西。设置正确的常规,在你的生活中有正确的人,创造迎合你目标的习惯。进步会很慢,但只要你不断努力,就会实现。

感谢所有阅读或关注我的旅程的人。

直到下一次,

安德鲁

我最喜欢的几个项目:

基尼指数 vs 信息熵

优步点评文本分析

随机森林是否优于 Logistic 回归?(一比较)

Excel 与 SQL:概念上的比较

用 Python 中的逻辑回归预测癌症

利用数学和 Python 优化你的投资

从头开始计算 R 平方(使用 python)

Python 中的字云:综合示例

简单线性 vs 多项式回归

我的设计宣言

原文:https://towardsdatascience.com/my-design-manifesto-9ad8f580ef6f?source=collection_archive---------10-----------------------

我希望在我的设计中遵循的一套雄心勃勃的原则

这是我在巴克内尔大学埃文·佩克的人机交互课上的反思。在这篇文章中,我将分享我的设计哲学,以及我希望如何解决未来的设计问题。我将从课堂上参加的四次设计冲刺中汲取经验。特别感谢 Pablo Stanley 设计的漫画

Photo by Kelly Sikkema on Unsplash

设计冲刺的范围从为移动设备重新设计 web 应用程序到创建诱人的可视化效果,从使用 Leap Motion 获得“乐趣”到使用新兴技术建设更美好的未来。以下是我四个项目的一些结果。

[Clockwise] (1) Redesign of the Campus Theatre app (2) Street View Adventure in VR (3) Literacy Rate visualization (4) Slither.io using Leap Motion

在一个充满严格的技术课程的计算机科学课程中,这门关于人机交互的课程对我来说是一种解脱。差不多了。虽然听起来很老套,但我被鼓励以更开阔的思维来处理问题。在我们的项目中,我们采用了双钻石的设计思维过程。

在所有的创意过程中,在提炼和缩小到最佳创意(“聚合思维”)之前,会产生许多可能的创意(“发散思维”),这可以用一个菱形来表示。但是双菱形表示这发生了两次——一次是确认问题定义,一次是创建解决方案。—英国设计委员会

实际上,这个过程要复杂得多。用户测试和反馈有许多阶段,每个阶段都可以显著改变项目的发展方向。有时候,你会推出一个有用的产品。在其他时候,一切都是一团糟。

User testing often changes how you approach the problem that you once set out of solve | Credit to Pablo Stanley

设计原则

以下是我在这学期中学到的一些经验。

—将用户放在首位

你不是在为自己设计,所以不要把你的偏好置于用户之上。通过努力理解你的用户,你在识别真正的问题上迈出了一大步。

设计师被训练去发现真正的问题。对错误问题的绝妙解决方案可能比根本没有解决方案更糟糕:解决正确的问题。—唐·诺曼,日常用品设计

承认你的用户可能无法清楚地表达他们的问题。正如 Andrew Ko 在如何理解问题中建议的那样,进行访谈以了解问题。否则,带他们出去吃午饭,观察他们努力解决你希望改进的设计。斯坦福大学设计学院有一个关于观察用户时要记住的事情的指南。

—在构思过程中不受限制

不要因为担心执行你的想法所必需的工具可能不存在而退缩。想象你拥有世界上所有的资源。鼓励团队内部的参与。

[## 设计套件

设计工具包是 IDEO.org 的平台,学习以人为中心的设计,一种创造性的方法来解决世界上最…

www.designkit.org](http://www.designkit.org/methods/28)

一旦最初的头脑风暴完成,促进评论和反馈。我不认为所有的想法都是“有用的”或者值得同等程度的考虑。你确实希望最终达成共识,但如果不(尊重地)挑战你认为需要更多思考的想法,就没有任何好处。

Credit to Pablo Stanley

如果你缺乏想法,环顾四周,看看已经建成了什么。奥斯汀·克莱恩恰如其分地说,“像艺术家一样偷窃。”

As newbies to Adobe XD, my team was looking for some carousel inspiration. We found a cool Starbucks app redesign and tailored it to our needs.

—让自己熟悉技术

努力理解你的工具的局限性。毫无疑问,知道如何编码会增加团队的价值,然而,并非所有的设计师都需要学习编码。毕竟,他们“仅仅”需要能够估计一项工程任务可能需要的工作量。当然,众所周知,软件开发是不可预测的,这种技能只有在和工程师一起工作一段时间后才能获得。

根据我的经验,在 Leap Motion 和 VR sprints 期间,如果我们都花一些时间来解决技术的限制,我们就可以避免很多令人头疼的沟通问题。这也能让我们更好地相互理解。

—雄心勃勃

用户重视你所付出的努力。如果你采用第一种解决方案起作用,你就剥夺了额外努力带来的快乐。然后你会想这个项目会是什么样的。

Exploring the untrodden paths lead to immense satisfaction and joy. | Credit to Matt R. Trower

在我的 Leap Motion 项目中,我亲身经历了这一点。尽管我们为许多游戏做了《绿野仙踪》测试,我们还是选择了 Slither.io,因为它看起来很容易实现。结果呢?我们没有成就感,如下所示,我们的用户大多反应是“哼”

当你探索无限的可能性时,正如我上面写的,你可以在你的团队中激发能量。在的未来冲刺设计中,我的两个队友为我们的“选择你自己的冒险”游戏想出了一个引人入胜的故事。虽然故事情节太长,无法在两周的冲刺中完全实现,但它让我们所有人都感到兴奋,甚至为实验提供了广度。

A part of the storyline for our Street View Adventure Virtual Reality game. Having many options gave up plenty of room to modify the scenes of the adventure on the fly.

—做让你开心的事

这是前一个原则的后续。在现实世界中,你并不总是能够选择你所从事的工作。但是如果你这样做了,首先贡献给这个项目中最能激励你的东西。咄!

有些人喜欢考虑大局,而有些人喜欢解决细节。就我个人而言,我喜欢添加设计术语中所说的启示。这是一个暗示如何使用界面元素的线索。

一个人如何知道一个界面有哪些启示?这就是意符的概念变得重要的地方。能指是启示存在的任何感官或认知指示器。—安德鲁·柯,用户界面理论

以下是我特别喜欢的两个符号。

  • 对于识字率可视化,我使用了适合在地图上显示连续数据的调色板。这取代了梯度标度,使观察者更容易区分识字率差异水平。如下图所示,大量的分割与渐变有着相同的问题,所以我们坚持只进行四次分割,并增加一次来表示不可用的数据。

Use a sequential color palette over a gradient scale when your users hope to be able to clearly separate any two levels in your data.

  • 在 VR 游戏中,我在一个静态的主屏幕上制作了开始按钮的动画来吸引用户的注意力,让他们更容易进入游戏。

Only after user testing did we realize how much value these signifiers added.

—保持简单

不要过于复杂。功能膨胀是真实存在的,当你忽视用户如何与新功能交互时,它就会发生。

如果你的用户不在乎黑暗模式,你的支持者就不能证明在你的设计中增加黑暗模式是正确的。

Image Source

同样,不要成为沉没成本谬论的牺牲品。通常,在投入大量精力之后,继续追求一个潜在的解决方案是很有诱惑力的。然而,如果你知道一种简化现有设计的方法,可以考虑征求专家的意见,甚至是小规模的 A/B 测试

在我们的可视化项目中,我经历了惨痛的教训。我们花了这么多时间使用 JQVMap 创建一个动画世界地图,即使在得知 Tableau 可以在几分钟内达到类似的效果后,我们仍然坚持我们的原计划。这也是我们没有以正确的方式制作原型的结果。在他的书勾画用户体验:获得正确的设计和正确的设计 中,比尔·巴克斯顿建议早期的原型应该邀请建议,不应该包含个人偏见或依附。如果我们对变化持开放态度,我们可以节省时间,并利用它来创建一个更引人注目的可视化。

—区分优先级

一旦你收到用户的反馈,不要根据你的团队做出某个改变(修复)所花费的时间来进行优先排序。在你的待办事项列表中,将最大化用户互动乐趣的任务放在首位。

可用性通常与美学分开处理。…由于易用性策略似乎没有带来回报,这让我们陷入了一个奇怪的境地:我们有一些产品,乍看起来很好,但一旦我们开始与它们交互,就会感到沮丧。我们认为重点应该从漂亮的外观转移到漂亮的交互,漂亮的外观是其中的一部分。—摘自让我们做些有趣的事情

如果一个改变只需要 10 分钟就能实现,那就想尽一切办法去做吧。如果有更长的时间,停下来分析一下哪些变化会最大程度地提升用户体验。为了指导你的分析,看看 UX 的法律。

[## 主页| UX 法律

UX 法则是设计师在构建用户界面时可以考虑的准则和原则的集合。它…

lawsofux.com](https://lawsofux.com/)

我们优先考虑的一个例子是 VR 游戏中的音效。在用户测试之前,我们知道故事的两个场景之间的过渡可以更平滑。我们的测试人员同意并强调声音需要淡入或淡出来创造一种更加有机的感觉。VR web 框架 A-Frame 在声音组件上没有很好的文档,但我们坚持下来,并能够实现交叉渐变音频效果。

—不要试图让每个人都开心🙁

识别你的主要用户是关键。认清取舍,如果需要的话,放过你的二级用户。

试图取悦每一个人会带来压力、痛苦、资源损失和挫败感。所以不要怕失去人,要怕失去眼光。—未知

在巴克内尔校园剧院网站的重新设计中,我们的目标是根据宾夕法尼亚州刘易斯堡游客的需求定制应用程序。由于时间有限,我们不得不在“待办事项”屏幕和应用内检票之间做出选择。我们最终选择了前者,因为我们一致认为了解正在进行的活动是游客体验的一个重要方面。

Things to do screen of the app. We decided to link the tickets button to the existing Campus Theatre website.

最后的想法

正如我前面提到的,这些原则是我在进入人机交互领域仅仅一个学期后学到的。我自称没有专业知识,但在这个课程之后,我很高兴我开始形成自己的关于好的设计需要什么的观点。

Credit to Pablo Stanley

设计思维很乱,当然也不直截了当。它涉及的不仅仅是漂亮的用户界面。清晰的愿景和关注产品的用户一样重要。它能让你真正理解手头的问题,并做出合理的妥协。一个好的设计不一定包含过度工程化的解决方案。然而,你需要遵循基本原则。获得关于你的低保真度原型的早期反馈,再加上好的(有时是无私的)优先级排序,可以为你的成功做好准备。

在这个课程中,我也学到了很多关于可访问性的知识,这是我以前没有接触过的领域。从不同的角度看问题令人耳目一新,我只希望我们在课堂上有更多的时间讨论这些问题。设计是一个快速发展的领域,所以像我这样的新人感到不知所措是合理的,也是很常见的。从糟糕的设计到好的设计需要努力,不管你选择如何定义它们,但是接受新的挑战会有很大的帮助。

如果你喜欢这个,请看看我的其他媒体帖子和我的个人博客。我一直在寻求提高我的写作水平,所以请在下面写下你的建议。

[## 人机交互设计组合

亚什·米塔尔的个人网站。他是巴克内尔大学计算机科学专业的四年级学生。

yashmittal.me](https://yashmittal.me/hci-portfolio/)

我如何将我的博客从 GitHub 页面迁移到 Netlify

原文:https://towardsdatascience.com/my-experience-migrating-my-blog-from-github-pages-to-netlify-92ff6c85fb04?source=collection_archive---------16-----------------------

作为数据科学家写博客时需要考虑的事情

Migrating Pelican site from GitHub Pages to Netlify

动机

今天我遇到了瑞秋·托马斯的关于“T5”为什么你(是的,你)应该写博客 的故事。她提出了一个很好的观点,所有的数据科学家都应该有自己的博客。她进一步解释说,写博客有助于你理清思路,传播知识,获得关注。所有伟大的观点,我全心全意地同意。所以我想分享我最近写博客的经历,并希望它能给我一些启示,告诉我做这件事需要什么,为什么值得。

和解

我有自己的博客已经有一段时间了。从我在 WordPress.com 的第一篇博客开始,我在多个平台上跌跌撞撞,试图为我的思想和感情找到一个好的归宿。大约一年前,我决定使用 Pelican (一个基于 Python 的静态站点生成器)来生成我的内容,然后将其托管在 GitHub 页面上。这一切都很好。

Python 是一种易于编写但非常强大的编程语言。同样作为一名数据科学家,你很有可能每天都和 Python 生活在一起。所以在所有静态站点生成器中,我挑了鹈鹕,它相当成熟,定期维护。它还支持大量的主题和插件。(我甚至开发了一个 Pelican 插件,它可以像计算媒体一样计算文章阅读时间,并被拉入主分支。).它支持 Jupyter 笔记本电脑,这对于数据科学家来说也是一个优势。

GitHub Pages 是一个非常受欢迎的免费托管服务,由 GitHub 慷慨提供。它基于 Ruby 的 Jekyll 框架,但你不必使用它。这个解决方案是完全免费的,而且维护起来有些简单。一旦你设置好了一切,你只需要专注于把内容和运行一个简单的脚本推送到 GitHub,它会自动让它活起来。我用它写了一段时间的博客。一切似乎都很好。

(注:任何人想了解更多关于如何做到这一点,可以查看这篇详细的博文。)

斗争

斗争开始了。不知何故,我不知道如何使搜索引擎优化工作。我在 GitHub 和我的博客网站上曝光了“master”分支,谷歌认为这是重复的内容,并给出了相当糟糕的排名。似乎很难获得任何流量。此外,作为 GitHub 提供的一项免费“辅助”服务,GitHub 页面上并没有太多的托管功能。正如 Netlify 在 this page 中概述的那样,当你开始写博客时,这是可以的,但当你试图更严肃地对待你的工作时,GitHub Pages 就不会满足你。

Image Credit: Netlify.com

冲突

所以我决定迁移到 Netlify,它也是免费的,但提供了更多的功能,如果我想在未来扩大规模,那里有很多付费计划。

准备好鹈鹕

因为我已经在 GitHub 上准备好了我的 Pelican 站点,所以大部分工作已经完成。(如果你还没有设置鹈鹕站点,可以按照这个教程。)我仍然需要对站点进行一些更改,以便 Netlify 可以顺利地连接到我的 GitHub 帐户并拉动站点进行部署。

依赖关系:

首先,Netlify 需要设置必要的依赖项,这样它才能构建我的站点。这需要我在 site GitHub repo 下提供一个requirements.txt文件。为此,我为它创建了一个 Python 虚拟环境:

$ sudo apt update
$ sudo apt install virtualenv  # install virtualenv
$ cd ~/git/wayofnumbers.github.io/
$ virtualenv venv -p python3.6  # create a virtualenv for Python 3.6
$ source venv/bin/activate  # activate the virtual env

我还在你的.gitignore文件中添加了venv/,这样 GitHub 就不会同步它了。一旦虚拟 env 准备就绪,我只安装了必要的包,如下所示:

$ pip install -U --force-reinstall pip
$ pip install pelican Markdown typogrify ipython beautifulsoup4 nbconvert

现在,依赖项已经全部安装在我的本地虚拟环境中,我使用下面的命令来生成requirements.txt:

$ pip freeze > requirements.txt

CNAME:

我在回购的根文件夹下创建了一个 CNAME 文件,其中包含我的自定义域名(“wayofnumbers.com”)。我还在我的pelicanconf.py文件中添加了以下几行,以确保 CNAME 文件被复制到了output目录的根目录下:

STATIC_PATHS = ['../CNAME']
EXTRA_PATH_METADATA = {'../CNAME': {'path': 'CNAME'}}

插件和主题:

然后是处理插件和主题的时候了。我将我使用的插件和主题(文件夹)复制到 repo 中,并将pelicanconf.py文件设置为指向它们,因为在 Netlify 构建时它需要在 repo 中访问它们。

Runtime.txt:

Netlify 需要一个runtime.txt来决定使用哪个 Python 版本来构建站点。所以我在回购的根目录下创建了一个runtime.txt文件,并将3.7 (Netlify 支持3.73.5)放入其中。

好了,现在鹈鹕已经准备好了,我可以继续设置网络生活了!

连接到网络生活

这部分其实挺容易的。我注册了 Netlify 的免费层,并按照这个分步指南连接我的 GitHub repo。唯一不同的是在'步骤 4:配置您的设置'。因为我使用的是 Pelican,所以我使用的“构建命令”是:

pelican content -s publishconf.py

由于依赖问题,在一些失败的构建之后,我让一切都工作了。Netlify 自动拉了我的 GitHub repo,安装了依赖项,构建了站点。我用谷歌域名申请了一个自定义域名,并按照这个链接设置:https://www.netlify.com/docs/custom-domains/#googledomains。一年 12 美元,完全值得。

我也打开了 SSL,遵循这个指南。

所以现在我的网站在它的新家开始运行了:

My blog with ‘Elegant’ theme

思想

整个迁移过程花了我一天时间。我从中学到了很多新东西。这很有挑战性,但完全可行。我鼓励任何对认真对待你的博客感兴趣的人尝试一下。挺整齐的。有人说数据科学家应该专注于他们的研究和学习,我倾向于不时地走神。在这里学习一些 web 编程技巧,在那里获得一些 DevOps 经验。我发现这种“离题”实际上有点放松,刺激了我大脑的另一部分。这是一种休息和放松的方式。我想玩一个黑客游戏,一路解决问题。了解部署将有助于您更容易、更快速地将您的模型投入生产。拥有一个博客就像拥有了另一个与你的同事和志同道合的人交流的场所。不会错的,对吧?

欢迎任何反馈或建设性的批评。你可以在推特 @ lymenlee 或者我的博客网站【wayofnumbers.com上找到我。

我用遗传算法代替深度学习反向传播(SGD)的实验

原文:https://towardsdatascience.com/my-experiments-in-replacing-deep-learning-backpropagation-sgd-with-a-genetic-algorithm-c6e308382926?source=collection_archive---------19-----------------------

本文描述了我用遗传算法(GA)取代深度学习模型中的随机梯度下降(SGD)和反向传播的实验。

作为一个剧透,让我说,这些早期的实验并没有表现出接近 SGD。然而,我在结论中对此说得更多。

语境

出于本文的目的,我将使用下图来提供今天在训练深度学习模型时使用的突出流程。

成本函数通过比较训练结果和预期结果(基本事实)来计算误差量( E )。反过来,SGD 将更改应用于模型参数,以改进下一个训练结果。值得注意的是,模型中使用的函数必须是可微的,以便 SGD 搜索最优解。

参数更新循环继续,直到达到所需的精度(图中未显示)。

我将用 W 来表示模型参数集。深度学习模型可以轻松包含数千万(如果不是数亿)的参数。训练完成后, W 将形成训练好的模型的基础。

遗传算法方法概述

下图显示了 SGD 被 GA 替换,单个的 W 被群体 W 替换,我将用[W来表示。

成本函数被移除,并由精度函数代替,该精度函数在 GA 术语中提供适应度函数。适合度值是给定一些标准的群体成员的适合度。适合度是一个 0 到 1 的值,0 表示最适合。我用【T24【F】来代表 [ W ]每个成员的适合度。

注意,在 GA 方法中,模型函数不必是可微的,因为 GA 不会使用函数导数来收敛于解。

遗传算法概述

有许多关于 GAs 的学术性和详细的书籍,例如,Goldberg 的“搜索、优化和机器学习中的遗传算法”。在这里,我会停留在(非常)高的水平。

给定一个种群 [ W ] ,以及种群中每个成员的适应度值 [ F ] ,GA 将决定下一代种群的构成。

W下一个=GA(W当前F当前)

一个简单的遗传算法可以描述为:

  1. 选择——将适应度作为一个偏差来配对成员
  2. 组合(combination )-组合所选对以创建下一代。这也被称为交叉,父母的基因在下一代中交叉。
  3. 突变——在释放新群体之前,应用(少量)随机突变

实验

我最初从一个简单的 XOR 问题开始,测试 GA 的流程。GA 确实相对较快地收敛于一个解决方案。然而,对于这篇文章,我将描述一个更实质性的问题。

该实验基于 TensorFlow MNIST 深度示例(mnist _ Deep . py as found the tensor flow GitHub repos)。这是一个用于识别 MNIST 手写数字数据集的深度卷积神经网络。该模型包含数千万个参数;我认为这将是一个很好的非玩具的例子。

我将所有的模型参数(权重和偏差)外化到 TensorFlow 变量中,这样就可以很容易地操纵 TensorFlow 张量之外的值。使用“feed_dict”将参数 W 载入 TensorFlow 模型图。

人口规模参数化为 N 。使用numpy.random.randn(平均值为 0 且方差为 1 的高斯分布)初始化N 个起始模型中的每一个。

然后,对于 [ W ] 中的每个 W ,计算适应度值。要运行的代数是 G (或者直到解收敛)。

*for generation = 1 to G
   for index = 1 to N
       F[index] = session.run(accuracy, feed_dict = W[index])*

计算下一代W的过程是:

*Random pairing of [W], biased towards fitter membersCrossover of each pair in [W]Random mutation of each member of [W]*

交叉

每个 W 由一组矩阵形成,其中每个矩阵代表机器学习模型的一部分(权重和偏差)。给定一对中的两个成员:

*Wa -> [a1, a2, a3, ...] # where each a is a matrix
Wb -> [b1, b2, b3, ...] # where each b is a matrix* 

有许多方法可以跨越 Wa 和 Wb。在这个实验中,我选择随机交叉相应矩阵中的元素。例如:

*mask = random 0 or 1 in shape of a1
mask_inv = opposite of masknew_a1 = a1 * mask + b1 * mask_inv
new_b1 = b1 * mask + a1 * mask_invand so on for (a2,b2), (a3, b3), etc.*

变化

作为 GA 超参数,有一个“变异量”,但变异量本身根据当前解收敛的远近而变化。最终,我发现理解和应用突变是一个挑战。

结果

第一张图显示了 300 代 200 人的种群规模。

上图显示了每一代的最佳结果(橙色)。回想一下,MNIST 数据有 10 位数字,因此在上述范围内随机选择 0.9。随着跑步的进行,有一个明显的拉平。对于每一代,最好的模型也是根据验证数据运行的(数据放在一边,不被视为训练的一部分)。

尽管精确度显然不是最先进的,但在某种程度上,遗传算法能够筛选数百万个参数,并随着时间的推移创建更好的模型;都没有反向传播。

在同一次运行中,下图描绘了每代中最佳模型的 100 个数值。图表显示了最初的波动性和随后的稳定值:

挑战在于早期的稳定会导致性能的上限,但是不稳定会导致在解决方案空间中的随机行走和没有收敛。突变的程度应该是达到平衡的一个因素。

下图显示了将人口规模增加到 1000 的效果。验证精度从 0.65 提高到大约 0.5。然而,验证准确性似乎在训练准确性之前趋于平稳。

结论和讨论

公平地说,200 人甚至 1000 人的人口规模可能太小,不足以取得有意义的结果。也许人口数量应该以百万计。

除了人口规模,还有其他几个超参数可以考虑。一些例子是:

  1. 排名和成对选择。有多少偏向于更适合的成员?在我的实验中,我提升了表现最好的人,这样他们的影响力就超过了严格意义上的健康水平。
  2. 突变。变异有多大?如何应用?是否随收敛而变化?
  3. 交叉。两个模型如何交叉?我选择在矩阵粒度上均匀交叉。两者中较强的一方应该保留更多的价值观吗?矩阵应该被分割然后连接吗?交叉是否应该定义在整个矩阵的交换上?
  4. 批量大小。我尝试了各种批量大小,最终确定为 64。
  5. 过度拟合。看一看 1000 人的运行,可以看到训练结果可能正在改善,而验证结果已经稳定在更高的值。

对我来说,接下来的步骤还没有确定,因为验证收敛的平稳化一直是一个难以克服的障碍(至少在我的计算机能力范围内,MacBook Pro 2018)。

如果你已经做到这一步,感谢你的关注和时间,我希望你喜欢这篇文章!

我用“自然”数据做的实验!

原文:https://towardsdatascience.com/my-experiments-with-natural-data-45eac01ef34f?source=collection_archive---------17-----------------------

我一直对斐波那契数列很着迷!这个序列在宇宙/自然界中比其他任何序列都多,这个事实几个世纪以来一直吸引着科学家。例子包括像树的分枝、茎上叶子的分布、松果的排列、菠萝的幼果和蜜蜂的家谱、星系的螺旋模式、山脉结构等(阅读“更多有待发现的东西”)。黄金比例(phi)的应用,来源于包括艺术,音乐,设计,统计在内的序列。

Kazimir Malevich — Suprematist Composition (1916), mimics Golden Ratio

所以我开始“研究”斐波那契(原名莱昂纳多·皮萨诺)&他是如何偶然发现这个数列的。

事实证明,这个序列早在公元前 2 世纪就被印度数学家阿查里亚·平加拉(平加拉教授)通过他的 Matra-Meru(我们现在知道的帕斯卡三角形)工作而知晓,但是是莱昂纳多·皮萨诺(斐波那契)在他周游地中海世界后把它带到了西方。达芬奇是一个出生于 12 世纪的意大利人。他游历了西方世界,主要通过他在 1202 年的著作《计算之书》来推广印度-阿拉伯数字系统。但是现在,他是如何发现这个序列的。嗯,他试图解决一个涉及兔子数量增长的问题(是的,我猜他是他那个时代的尤塞恩·博尔特,没关系)。兔子的“一代又一代”产生的顺序(我知道,听起来很多,但兔子的妊娠期大约是一个月,所以假设一只兔子一年可以生 12 次,不开玩笑,它们很快)是这样的:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377 ..

这就是我们今天所知道的斐波那契数列。后来人们发现,在自然界中这种序列经常出现,这一事实让科学家们挠头了几个世纪。顺便说一下,斐波那契(意为“波纳契之子”)这个名字是由一位法意历史学家在 1838 年创造的。

嗯,就是这样。所以在多年挠头之后,我已经养成了在任何地方使用这个序列的诀窍(是的,我内心的审问者会间歇性地醒来)。

现在,回到题目(实验)。所以昨晚我浏览了时间序列预测模型&偶然发现了一个奇怪的巧合,如果真是这样的话!?!当我开始阅读指数平滑模型时&当观察数据变老时,权重值如何指数下降。以下等式解释了预测方法:

t =时间段数(t = 0 为最近的时间段,t = 1 为之前的时间段)

Y(t) =周期 t 内的实际值

重量(t) = α(1-α)^t

n =时间段总数

这里,alpha (α)的值在 0 和 1 之间变化,使得所有权重的总和接近 1。

前面提到的我内心的质疑者想,为什么不取斐波那契数列中的数字,用重量来代替它们。所以我就这么做了&取序列中的前 15 个数字(不包括 0),并对它们进行归一化。

现在,我在斐波纳契数列中的权重是:

0.382, 0.236, 0.146, 0.09, 0.0558, 0.0345, 0.0213, 0.013, 0.0081, 0.005 ..

根据这些标准化值,t=0 时的第一个权重为 0.3822。现在,我用上述指数平滑权重等式中的第一个权重替换该值,以便在 t=0 时α = 0.3822。现在让我们在指数平滑的权重等式中替换这个α值:

在 t = 0 时,w(0)= 0.3822 *(1–0.3822)⁰= 0.382

当 t = 1 时,W(1)= 0.3822 *(1–0.3822)= 0.236

在 t = 2 时,W(2)= 0.3822 *(1–0.3822)= 0.1458

在 t = 3 时,W(3)= 0.3822 *(1–0.3822)= 0.0901

在 t = 4 时,w(4)= 0.3822 *(1–0.3822)⁴= 0.055

在 t = 5 时,w(5)= 0.3822 *(1–0.3822)⁵= 0.0344)

明白我的意思了吗?是的,权重与斐波纳契数列的标准化版本完全相同,这意味着在特定的α值下,指数平滑权重模拟了自然!?!取序列中前 50 个数后的α值为:

α = 0.3819966011

这是一个 alpha 值为 0.38199 的预测指数平滑模型示例

精神食粮..

  • 现在,我只是想知道这可能只是一个巧合,或者这可能是第一个提出这个模型的人罗伯特·古德尔·布朗先生设计的?
  • 有了这个 alpha,我们能得到最好的预测模型吗?不,不是所有的时间。
  • 这个方程(近似的)可以进一步应用于时间或后续层的模式吗?

~ 0.38199 * [(0.618)^t ]

现在,在 0 和 1 之间,这些是满足以下等式的值的唯一组合(0.38199 和 0.618):

α = (1-α)它变成α -3α+1=0(这个二次方程的另一个根是 2.618)还有,α -3α+1=0 是α -α-1=0(黄金比例方程)在 y=1 处的镜像!!

所以,上面的等式可以写成

(0.618) * (0.618)^t

(0.618)^(t+2)

现在我们还知道,0.618 的乘法倒数是 1.618,这是黄金分割比率,因此现在该等式可以归结为:

(1/φ)^(t+2)

  • 这种模式可能是微观世界的斐波那契模式的另一个自我吗?

1, 0.6180, 0.3819, 0.236, 0.145, 0.09, 0.055, 0.0344, 0.0213, 0.0131 ..

  • 神经网络会不会以某种方式模仿这种模式,因为它们是由我们自己的神经系统“启发”的?

我最喜欢的书/mooc 从金融数据科学家开始

原文:https://towardsdatascience.com/my-favorite-books-moocs-starting-as-a-financial-data-scientist-a0de577690e9?source=collection_archive---------20-----------------------

希望到目前为止,每个人都有一个美好的年终!寻找改进的材料是一个伟大的旅程,有时可能会有点令人生畏。对于这个想法,本文的主题是基于 Guysnove Lutumba 的以下评论:

“你知道该读什么书或选修什么 MOOCS 课程,才能(帮助你)打下坚实的金融基础吗?”
https://medium . com/@ guysnovelutumba/thank-you-for-this-great-article-d 14 fcd 01 af 28

为了回答 Guysnove 的问题,我决定收集一些资源,这些资源不会让你成为一名金融数据科学家。无论如何,这不是一个全面的列表,而是我个人最喜欢的,我会推荐给任何想进入定量分析师或金融数据科学家领域的朋友。这些资源分为 3 个部分,这对于金融数据科学领域来说是非常传统的,同时我添加了一个额外的部分,我相信在您了解所有技术细节后,这是您职业生涯中达到下一个级别所必需的。

记住这一点,让我们从第一本书开始,原则:雷伊·达里奥的生活和工作。我把这本书放在第一位,因为它是一个伟大的整体框架,告诉你应该如何走向成功。下面是 Dalio 回顾的其中一个过程:

Image from http://jareddees.com/wp-content/uploads/2018/01/raydalio-five-step-process-1.png

要有目的地去任何地方,你必须有目标,但是,在实现这些目标的过程中,你会遇到问题。为了进一步发展,你必须诊断出这些问题,并设计出解决它们的方法。一旦修改完成,你就可以再次继续你的目标。就我个人而言,我喜欢这样的想法,你可以用许多不同的方式获得成功。希望这个方法将来也能帮助你!

数学

在金融或数据科学领域,数学,尤其是统计学,是贯穿整个工作的一个非常常见的潜在主题。理解数学才有意义,因为你整天和数字打交道。现在,我相信你已经听说过要很好地理解数学需要很多年。这是真的,面对这个问题,大多数人都僵住了。但是从上面的 Dalio 的 5 步过程中,我们可以从任何学习材料开始取得更大的进步,并从那里开始努力。我知道在之前的一篇文章中,我推荐可汗学院学习一些基础数学。如果你想要一本更高级的数学但有应用的书,我强烈推荐绍姆的《数理经济学导论提纲》作为一个好的起点。如果我在大学时有这本书,我知道数学课会少花一点时间。

Image from http://mimsy.io/images/Bayes_Final.svg

一旦你解决了微积分和线性代数的问题,你仍然需要处理统计数据。我记得高中的统计课会教我们正态分布的所有特征,但对我来说,很难在现实世界中应用这个过程。在数据科学领域,有大量的贝叶斯统计方法的追随者,这基本上意味着你从最近的大量数据中更新你的信念。上图是贝叶斯的一个直观例子。你的旧信念是先验的,但是,由于新的证据,你建立了一个更好的模型,由你的后验或更新的信念来代表。对我来说,贝叶斯思维的概念和应用方式的一个简单读物是这本书:贝叶斯统计有趣的方式。作者用 R 编写代码,但是如果有人评论,我愿意在下一篇文章中发布 Python 版本!

数据科学

对于那些刚开始学习数据科学并且正在寻找更结构化的方法的人,我非常喜欢 Dataquest 。他们用清晰的解释一步一步地引导你。他们的课程基本上是文本在左边,你编码在右边。所以你主动学习,而不只是被动观察。顺便说一下,他们不是付钱让我说这些的。当我想更好地学习 Python 和数据科学时,我发现它们很有帮助。

金融

好吧,金融是一个巨大的空间,但金融内部是资本市场——我个人的最爱。所以接下来的几个建议会倾向于金融市场。第一个财经推荐是乔尔·格林布拉特的《战胜市场的小书》。如果你曾经想开始股市投资,我认为格林布拉特提供了一个很好的入门框架,告诉你如何从基本面的角度投资股票。这本书基本上给了你筛选潜在股票购买的标准,正如格林布拉特所说:

“在不知道自己在寻找什么的情况下选择个股,就像拿着一根燃烧的火柴跑进炸丨药厂。你可能活着,但你仍然是个白痴。”—乔尔·格林布拉特

如果你认为我们可能会进入衰退,那么下一本书非常有趣。推荐的书是霍华德·马克斯的掌控市场周期:让赔率站在你这边。这本书详细描述和理解了经济周期。我毫不怀疑,一旦你成为一名金融数据科学家,有人会要求你创建一个与你公司的商业模式相关的宏观经济模型。这本书可能有助于你入门。

让我们稍微改变一下思路,更多地关注微观经济。在分析企业及其内在价值时,沃伦巴菲特是一位值得学习的大师。所以,下一个推荐是伯克希尔·哈撒韦大学:丹尼尔·佩科特在年度股东大会上向沃伦·巴菲特&查理·芒格学习的 30 年经验。对于那些不熟悉的人来说,沃伦·巴菲特是一个著名的选股人。他发现那些股价低于其内在价值(他认为公司的价值,而不是股价)的大公司,并以高额回报买入这些公司的股票

在更细致的交易层面上,我发现没有其他书比这本书更好地解释了市场交易的方式,拉里·哈里斯的《交易和交易所:从业者的市场微观结构》。我遇到的自营交易者推荐这本书,甚至在高频领域工作的人也表示,这本书有助于解释订单簿以及市场中的其他参与者如何影响它。

我几乎不想提到这两个,因为它们相对于上面的其他建议来说相当昂贵。但是在金融数据科学领域,获得 STEM 类的学位和更多的学位更受青睐。我发现,如果你在报名攻读硕士之前想找一个介绍,这两个 MOOCs 可以帮助你获得机器学习或金融硕士学位:

沟通

为了在职业生涯中更进一步,你需要硬技能的同时也需要软技能。我所说的软,指的是知道如何与人打交道,如何表现得风度翩翩。我过去见过一些同事,他们技术很好,但是重要的利益相关者不能理解他们。因此,他们的研究或期望的倡议会受到浪费方的影响。戴尔·卡耐基的《如何赢得朋友,影响他人》是一本基本的人际技能书。在金融数据科学这样一个竞争激烈的领域,你需要你能得到的每一个优势。如果更受欢迎能为你赢得胜利,那就这样吧。

Image from: https://www.magicalquote.com/wp-content/uploads/2017/05/Theres-a-small-group-who-can-do-the-math.-Theres-an-even-smaller-group-who-can-explain-it.-But-those-few-who-can-do-both-they-become-billionaires.png

结论

唷,我们讨论了很多话题!简单回顾一下,首先,分离出你的目标,并坚持不懈地克服它们。雷伊·达里奥的书会给你一个走向成功的过程。在数学和统计学中,学习基础知识,这样你实际上就明白你在用什么了。使用这个世界给你的数据,并应用它来做出更好的决定——贝叶斯统计。对于数据科学领域的初学者来说,试试 Dataquest,看看它是否有帮助。至于金融,如果你想选股,乔尔·格林布拉特的书会有所帮助。霍华德·马克的书会让你了解市场周期。丹尼尔·佩科特对沃伦·巴菲特的研究将帮助你找到伟大的企业。如果你想非常详细地了解金融市场,拉里·哈里斯很有帮助。大多数金融数据科学职位需要硕士或更高学位,因此在购买之前,获得硕士学位的 MOOC 可能是一种有用的尝试方式。最后,沟通是关键。你的分析需要别人理解。学会像戴尔·卡耐基的书那样交流,可能会帮助你在漫长的职业道路上获得盟友。

祝你一切顺利,记住成功是一段旅程:

“尽你最大的努力,其他的就别管了。”—托尼·霍顿

免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。投资带有严重的风险,在采取任何投资行动之前,请咨询您的投资顾问。这篇文章包含一些附属链接。

我最喜欢的机器学习模型是科学家应该知道的所有数据

原文:https://towardsdatascience.com/my-favorite-machine-learning-models-all-data-scientists-should-know-2ab94b4db62d?source=collection_archive---------12-----------------------

W 随着大量的机器学习模型每天都在增长,将你的技能集中并磨练成正确的模型和算法可能会非常困难。无论你的目标是连续的,明确的,还是其他的,从模型的湖中找出一条鱼是非常困难的。

虽然有数百万种可供选择,但肯定有一些是我所珍爱的,主观上我真的很喜欢的。虽然我绝对不会有偏见(数据科学笑话),但我承认,不给这些神奇的模型优惠待遇真的很难!

多项式朴素贝叶斯

from sklearn.naive_bayes import MultinomialNB

多项式朴素贝叶斯(MultinomialNB)模型是用于分类规范的目标的奇妙模型。MultinomialNB 因其在谷歌、微软和雅虎等公司的大数据管道中的应用而闻名。以我的经验来看,这个模型是可以用于带有标记化文本的布尔值的最好的模型之一,这使得 MultinomialNB 的任何涉及 NLP 分类的东西都很出名。无论你是在猜测谁最有可能说出一句名言,还是在确定文本是否是垃圾邮件,MultinomialNB 绝对是数据科学家研究烧瓶 HTTP 管道和对用户文本查询进行排序的算法的基本模型。

Regression Tree

from sklearn.tree import DecisionTreeRegressor

回归树是决策树和线性回归的产物。回归树通常使用相关系数来确定要拟合的充分模型,以提高准确性。该模型非常适合具有陡峭曲线和高方差的连续数据。回归树类似于保序回归,主要区别是使用相关系数而不是保序权重。

回归器/分类器

from xgboost import XGBRegressor
from xgboost import XGBClassifier

XGBoost 梯度是非常好的模型,因为它们可以提高传统统计或条件模型的准确性,并且可以很好地应用于两种主要类型的目标。当您需要对您的标准模型进行最终的精度提升时,XGBoost 可能是一个有用的工具。虽然不总是非常有效,但是在大多数情况下,将模型切换到 XGBoost 可以节省 10%到 15%的准确性。

随机森林分类器

from sklearn.ensemble import RandomForestClassifier

随机森林分类器绝对是我最喜欢使用的算法之一。随机森林模型本质上是一棵决策树(因此得名。)随机森林分类器有着非常有趣和丰富的历史,最初是由统计学家田金浩发现的。早期版本的随机森林分类器使用随机子空间算法。

这个新模型非常有趣,并且在某种程度上改变了游戏规则,因为它通常将随机辨别的思想引入机器学习世界。在随机森林模型之前,所有的分类算法都是基于相关性、贝叶斯或基于偶然的概率分布,例如二项式分布。

最近邻居

from sklearn.neighbors import KNeighborsClassifier
from sklearn.neighbors import KNeighborsRegressor

KNearest Neighbor 是一种机器学习算法,用于选择具有最相似特征的最近目标。像 XGBoost 一样,它也是一个分类器或回归器。

k 最近邻因其在搜索和提示功能中的使用而众所周知。特征可以包括属性和类别,例如关于在介质上接下来读什么的建议。不用说,这是为最终用户构建任何 web 工具的绝对必要的工具。从音乐提示器到 Youtube 的自动播放功能,K Nearest neighborhood 无疑在互联网的数据景观上留下了自己的印记。

梯度下降

梯度下降是一个广泛的和极其通用的模型。这是几乎所有神经网络的幕后工作模型。有一些贝叶斯模型不一定被认为是梯度下降,但大多数情况下,它们仍然植根于梯度下降。对于人工智能的现在和未来,梯度下降很有可能成为最重要的模型。梯度下降可以做任何事情,从简单的前馈网络一直到深度递归神经网络,甚至更远。

任何时候你看到机器学习被用来处理图像,梯度下降肯定是罪魁祸首。不用说,我们都应该知道梯度下降;不仅超级爽,还超级好玩!

结论

这些是我主观上最喜欢的模型,也是我发现自己最常求助的模型。每个工作都有一个工具,就像每个工作都有一个模型,就像每个工作都有自己的特性一样。随着时间的推移,美妙的

数据科学超级大国

那就是知道实现哪种模型的最佳方式。一个很好的理解可以来自多种来源,但是作为一个终生学习者,永远不要期望对一个或另一个模型感到太舒服。在某些情况下,我对此有点内疚,因为回到您所知道的东西可能会令人感到安慰,但深入堆栈溢出的黑暗深处可能是您可以获得的关于数据科学的最好教育。在许多其他事情中,机器学习模型的强大知识将很快出现。当你在第一轮测试中获得 92%的准确率时,你肯定会知道你做对了!

我喜欢数据科学可以用一滴信息颠覆你的整个意识形态。某一天你可能正在用梯度下降模型创作绘画,下一件事你知道你正在维基百科上阅读一些晦涩的回归算法。数据科学一直在变化,模型也在变化,所以您喜欢的模型一定会迁移!

Python 3.8 中我最喜欢的新特性

原文:https://towardsdatascience.com/my-favorite-new-features-in-python-3-8-a95d7a0a31c9?source=collection_archive---------8-----------------------

Python 3.8 在几周前发布,我没有急于谈论新特性,而是决定熟悉它们并加以利用,我想指出的是,我绝对会使用 Python 3 中实现的一些关键特性。不管这些新特性是否会被使用取决于程序员,但是我认为熟悉这些新特性是很重要的,这样我们就可以阅读 Python 之后的文章。

海象操作数

我们将以我最喜欢的新功能开始,

海象操作数

为什么这么叫?因为操作数看起来像一头侧翻的海象。这不仅是在 while 循环中使用的好工具,就像 Python 文档中的例子一样:

while (line := file.readline()) != "end":
    print(chunk)

然而,对我来说更重要的是,Walrus 操作数具有在一行中返回和设置的优势,换句话说,我们可以在统计函数的末尾保存一个返回,例如,在最后一次计算时,只需使用 Walrus 操作数。

x  = 5
y = 5
b := y+b

仅位置参数

不那么花哨,但这也是一个很大的变化,不会影响函数参数的经典性质。要创建一个位置参数,我们只需要在定义函数时在参数的末尾添加一个斜杠。

def func(x,y,f=5,/):

现在我们可以使用 f 等于σx+σy 的函数,如下所示:

result = func(x,y,ournum = sum(x) + sum(y))

而在以前,我们必须添加更多的结构来实现这一点。

ournum = sum(x) + sum(y)
result = func(x,y,ournum)

多重处理共享存储器

共享内存归结为在整个 Python 中全局共享数据,而不是手动提取和传输数据,或者将其保存到文件中以供访问,现在可以使用多处理模型在 Python 内部跨位置全局访问数据,这将我们带入下一个添加内容,

新的酸洗协议

pickle 是一个压缩和序列化数据和代码以在其他地方使用的出色工具,随着 Pickle 模块 Python 的新增加,您可以 Pickle 的序列化效率更高,通用性更强,这对于数据科学领域的我们来说非常令人兴奋,对于那些在 Flask 和 Django 中工作并且 VPS web 服务器上剩余空间有限的人来说,这绝对是一项值得贡献的事业。

CPython —改进了!

最后但同样重要的是,Python 吹嘘他们已经改进了 Python 的基于 C 引擎的后端,这是另一个我认为肯定需要注意的特性。作为一名数据科学家,我经常发现自己在处理数据时碰到了 Python 的极限,这很不幸,但确实存在。当仅仅读入数据就使 Jupyter 内核崩溃,并且您正准备尝试为所述数据安装一个管道时,这可能是很可怕的。

好消息是,情况正在好转,并且有望在未来继续好转。当然,我们指的是 C API 中的 Python,而不是 Python 中的 Python,或者只是普通的 Python。当处理绝对庞大的数据集时,在没有配置上述 API 的情况下运行 Python 常常是一场噩梦。

对我们来说更幸运的是,CPython 还做了一些工作来改进其 API 的配置,这是令人兴奋的,因为这将使优化更容易,并且很可能允许新用户使用 Python 中的 C 引擎。

我真的希望 Python 在未来几年继续关注稳定性、速度和效率。这些改进虽然看起来很小,但肯定是一个大胆的方向,并且执行得很好,尤其是我一直很喜欢的东西。这些是我最喜欢的功能,但还增加了一些功能,包括:

  • 性能改进(针对原始 Python 本身)
  • 可逆词典
  • 打字模块返工
  • f 字符串调试支持

这些都是 Python 世界中受欢迎的进步,特别是对于那些处理大型数据集和修改内存限制的人来说。

我最喜欢的 R 编程课程——数据感动我

原文:https://towardsdatascience.com/my-favorite-r-programming-course-data-moves-me-27055c68aac?source=collection_archive---------18-----------------------

注意:本文包括附属链接。意思是对你没有成本(实际上,你得到了折扣,得分!)如果你购买课程,我会收到一点佣金。

我从 2004 年就开始使用 R,远在 Tidyverse 推出之前。我知道完全掌握最新的软件包和功能会让我受益匪浅,所以我最终决定冒险全面更新我的技能。我想要一门涵盖 R 中每个角落的课程。我个人学习 R 的经验是粘贴教程和阅读文档,因为我需要一些东西。我想了解一些现在可能不需要,但将来可能会用到的功能。我想要一切。

我早就知道 Tidyverse 是对使用 base R 功能操作数据的巨大改进。然而,我也知道我以前的学校技能完成了这项工作。我现在明白了。有更好的方法。做出这一举动并不是非常痛苦(尤其是因为我熟悉编程),商业科学的“R 商业分析”课程将在 4 周内带你从 0 到相当危险。

对于没有 R 经验的人来说,他们不想为了达到一个“严肃 R 用户”的水平而多年碰壁。我强烈推荐这门商业科学的“带 R 的商业分析”课程。不要让这个名字欺骗了你,这个课程花了 5 个小时使用 parsnip 包来学习机器技术。更重要的是,如何将这些结果传达给利益相关者。

该课程全面、清晰、简洁。

课程覆盖范围

常规:

本课程将带您从头开始:

  • 安装 R
  • 设置您的工作环境
  • 然后直接进入使用事务数据的相关业务分析

这门课程“牵着你的手”踏上了在 r 中变得自给自足的旅程。我不可能在这篇文章中列出这门课程涵盖的所有内容,那将毫无意义。然而,对我来说改变最大的是:

  • 使用 stringr 的正则表达式
  • 使用 lubridate 处理日期时间
  • 格式化您的可视化

我想要的所有材料都在这里。所有的一切。

建模和创建可交付成果:

同样,不要让课程的名称欺骗了你。这门课程非常注重机器学习。花 5 个小时在欧洲防风图书馆(这是 R 的 scikit learn)。

课程包括:

然后教你如何在 R-markdown 中创建可交付物,在 Shiny 中创建交互式图形。一切都在商业背景下,并始终强调你将如何“与业务沟通”。我再怎么强调课程的布置有多细致,涵盖的材料有多少都不为过。这门课程确实很特别。

这些年来,当你在课堂上时,有多少辅导或培训让你觉得一切都很“好”?然后你试着采用这些技能,并把它们应用到个人项目中,在你成功所需的东西上有巨大的缺口。我有很多用头撞墙试图让事情和 r 一起工作的经验。

你会喜欢的东西:

  • 重复键盘快捷键,这样我就能真正记住它们。
  • 立即使用事务性数据进行分析。你不仅仅是在学习 R,你还在学习应用程序以及为什么这些函数是相关的。
  • 参考流行的 R 备忘单和文档。你将会明白如何阅读文档和 R cheat sheets——老实说,成为一个优秀的程序员很大一部分是有效的 Google 技能。学习阅读文档相当于班门弄斧。
  • 马特有一副好嗓子。好了,我说了。如果你要听几个小时的东西,我觉得这一点很有必要。

对于初学者:

  • 说明从一开始就开始了,而且说明很清楚。
  • 讲座要遵循的代码组织得非常好。商业科学显然以结构为傲。
  • 没有必要再去上一门基础课程,在那里你会重复学习一大堆你以前学过的东西。这门课涵盖了你需要的一切。它。是。全面。
  • 电子商务/交易数据是一个非常常见的用例。如果您不熟悉事务性数据的工作方式,或者您从未连接过多个表,这对于有抱负的数据科学家来说是一个极好的机会/绝佳的用例。
  • 如果您有任何问题,可直接联系 Matt(课程创建者)的松弛渠道。我个人没有使用这个功能,但是作为一个新手,直接访问 Matt 是一个巨大的价值。

老实说,我很嫉妒自己第一次没能学会这种方法,但 Tidyverse 在当时甚至还不存在。这就是生活。

本课程以一个 k-means 示例结束,其中包含一个已经在 R-markdown 中构建的、利益相关方准备好的可交付成果。这门课程实际上是数据科学的非神秘化。

总而言之:

也许我太书呆子了。但是看到一个如此好的课程,提供如此多的价值,对我来说是值得投资的。通过学习这门课程,你将会实现令人难以置信的转变。如果在我刚开始学习 R 的时候,这是可行的,我会省去很多挫折。matt Dancho(Business Science 的所有者)好心地给了我一个链接,这样你就可以在课程中享受 15%的折扣。链接

如果您购买套餐,15%的折扣甚至更划算,但老实说,我还没有选第二道菜。我一定会的!之后我一定会写一篇评论让你知道我的想法。这里是捆绑包的链接:链接

如果你想成为数据科学的摇滚明星,Matt 将推出一个全新的课程,你可以购买 3 门课程的套餐。新课程是“商业预测网络应用与 R Shiny”:链接

如果你参加了这个课程,请告诉我你是否和我一样觉得它很棒。你可以在评论里留下感言或者在 LinkedIn 上联系我。我很想听听你的经历!

原载于 2019 年 6 月 8 日https://datamovesme.com

我在 NLP 的第一次冒险

原文:https://towardsdatascience.com/my-first-adventures-in-nlp-631faa6aadd4?source=collection_archive---------18-----------------------

探索情感分析作为“黑箱”的旅程,并打破它找到见解。

2018 年 11 月 15 日,我开始着手创建一个药品评论情感分析模型。

和大多数想法一样,它开始于的问题。

在过去的 24 个月里,我妻子一直在重度抑郁中挣扎。治疗方案把她从一个药物试验(和失败)带到了下一个。每个药物试验需要 8 到 16 周的时间,这取决于滴定、随访预约和逐渐减少。在整个过程中,她经历了所有的副作用。恶心、疲劳、困倦和严重焦虑等等。一些药物对抑郁症有一点帮助。其他人让情况明显变得更糟。糟糕透顶。

在那些时刻,我感到无力去帮助我爱的人。我唯一能做的就是联系医生并留下信息或便条。通常当我从医生那里得到消息时,副作用已经改变了。

我不会因为医生的反应水平而责怪他。考虑到他们在实践中帮助的人数,他们尽可能地进行沟通。但是我经常会想到“为什么还要给他们打电话或发电子邮件呢?他们不可能很快就收到这条消息,并采取任何措施。”

通常我们会等到复诊时才向医生报告。但是当你在现场时,很难记起每天或每周尝试一种新药有多困难。尤其是在使用一种新药 8 周后。这造成了缓慢、不一致和劳动密集型的药物体验反馈循环。

医患沟通中的这些障碍和瓶颈减缓了治疗过程。如果医生能够立即找到正确的药物,那么患者的治疗效果就会得到改善。正确的药物搭配意味着更少的随访,这有助于降低患者护理的成本。真实成本&问题人命附后。

那么,如果我能创建一个系统,让医疗服务提供者更快地识别有效/无效的药物,会怎么样呢?

一种思路:用药体验反馈分析

量化的评论产生干净简单的数据。可以可视化、分析、监控和比较的数据。

通过收集每日患者药物反馈并进行情绪分析,可以:

  • 检查患者在试验期间对药物的体验,以跟踪药物需要多长时间开始发挥作用。(或者它到底有没有用)
  • 确定患者何时挣扎,并通知医生提供支持。
  • 随着时间的推移,对各种患者类型的药物进行评估,以监测非临床表现。
  • 在随访期间,为医生提供患者持续体验的图表视图。

但是这个系统的成功取决于一个关键因素。一个可以持续准确预测患者对药品审评情绪的模型。

所以这就是我着手去做的,看看我能不能造出来。

走向未知

A bit like wandering down an unfamiliar road.

走进这个项目,除了概念上它能做什么,我对 NLP 和情感分析知之甚少。但是我需要一些高质量的数据来开始。

互联网提供了一些惊人的数据。Felix Gr er&Surya Kallumadi 提供的来自 UCI 机器学习存储库的“药物评论(Drugs.com)数据集”。

“该数据集提供了患者对特定药物以及相关病情的评论,以及反映患者总体满意度的 10 星患者评级。这些数据是通过抓取在线药物评论网站获得的。(Drugs.com)"

一个优秀的数据集,包含文本评论,评级,以及条件和药物的类别字段。

我从导入和探索数据集开始。一旦对掌握了数据的结构感到满意,我就开始寻找情感分析的指导。

尝试 1——瞎猜

我搜索、阅读了许多资料,并选择了一个简单的入门教程来开始我的 NLP 之旅。我对 NLP 的第一次尝试是从 “用 Python 进行情感分析” 教程中提取一段代码,并将其应用于我的数据集。(请点击此处查看我的笔记本)我很快认识到,即使是编写得最好的代码也很难适应新的数据集。为清理数据提供的正则表达式是不够的,所以我编写并测试了自己的正则表达式。

在对评论文本进行标准化和矢量化之后,我将评论评级从 11 个类别分成了 3 个类别。“积极”、“消极”和“中立”。然后,我使用 scikit-learn 的逻辑回归训练了一个模型,并检查了模型性能的准确性。

经过少量调整后,该模型的最终准确率为 81.95%。在这一点上,我不确定如何衡量这个模型的性能,也不确定准确性本身是否是一个有效的指标。

但是当我检查前 10 个和后 10 个特征(单词)的权重时,我意识到有一些我无法解释的差异。

Hmm. These negative weighted words seem pretty positive…

我不是那种会放弃的人。因此,我需要学习更多的东西,并寻找更深入的教程。

尝试 2——解构黑盒

在向我的一个朋友提问后,他推荐了一篇来自 Insight AI 的 Emmanuel Ameisen 的文章。以那篇文章为指导,以 Leonardo Apolonio 的“如何解决 NLP”代码为框架,我带着新检查的数据集开始了我的 NLP 之旅。(我的笔记本在这里。)

我首先回顾了使用数据集发表的原始论文。我已经包含了关于该研究中使用的数据收集、预处理、标记化和建模方法的注释。

在我完成教程的过程中,我遵循了一个简单的过程:每当有我不理解的 ML 词汇时,就“停下来学习”。我学习了数据准备中的嵌入、Word2Vec、单词包、语料库、标记化、规范化、非 ASCII 字符、词干、词汇化和矢量化。这个过程很耗时,但很有效。

我的想法是:让黑盒工作,然后拆开黑盒

我对这些教程的目标很简单:让它工作,然后获得理解。这个过程对于像我这样可以被描述为“机械倾向”的人来说很有效。它允许我们首先建立对整个系统结构的理解,然后深入了解每个部分的知识。我发现这种方法有助于我记住我所学的东西。我的大脑锁定了对细节的解释,因为它们被视为整体的相关和必要部分。(下面是我对这种方法做的一个简短的介绍。)

“碰运气,犯错误,搞得乱七八糟!”弗里兹尔女士

这种方法的危险在于没有探测到工作内部。如果模型的机制永远被当作一个黑盒来对待用户就会错过学习的机会。

但这真的有效吗?

我做了很多工作才让它在我的数据集上干净地工作,但是工作 它做到了 。本教程在评估模型性能的框架内清晰地阐述了新的概念,包括:

  • 通过投影可视化评估各种嵌入的有效性。

  • 利用精度回忆f1、精度来评估 Logistic 回归的表现。

  • 模型性能可视化的混淆矩阵的使用

  • 通过使用重要的单词图来可视化特征检查。
  • 使用 Lime,一个黑盒解释器,让 word2vec 检索和检查特性。

所有这些工作的结果?

最高性能的嵌入+ logreg 模型是我的词袋模型,准确率为 78%。CNN 最终的准确率为 75%,还有很大的提升空间。

但是最终的特征权重和重要性显著提高。

有了这些小小的成功,我仍然渴望找到并建立一个更好的模型。在第三次尝试中,我做到了。

尝试# 3——一次有目的的旅行。

这次尝试与众不同,因为在我之前的尝试中,我一直在阅读和学习 LSTM 的《T1 》,我已经决定用一些新的 LSTM 代码在同一个数据集上试一试。(在这里看我的笔记本)

用我的新锦囊妙计准备数据

在我前两次尝试的所有挣扎之后,这次预处理数据很有趣。

这次我使用 MissingNo 检查了我的 NaN 数据。我觉得这个可视化包超级聪明。

Look for NaN’s with MissingNo

然后,我像以前一样将我的值进行分类,并检查图中的分布。

Bin Test & Training Data by Rating

我从数据集中删除了长度异常的句子。

Outlier length sentence removal

最后,我应用了正则表达式、词干和停用词删除(包括我定制的药品名称停用词语料库)来进一步清理和减少特征大小,同时保持相关的词。最终结果是更小的特征集,更容易有效地处理。

Word counts across all the reviews in the dataset pre/post stemming and stop word removal.

你好,LSTM

我就不详细介绍我是如何通过耗时的反复试验来测试 LSTM 的所有不同组件和评估各种参数的了。但所有这些努力的最终结果是一个比我以前的任何型号都表现更好的型号。

我的简单 LSTM 模型最终达到了 88.4%的准确率。

更令人印象深刻的是,它预测积极情绪的准确率高达 90%。

最令人惊讶的是…这次尝试很有趣。学习预处理的大部分繁重工作已经完成,模型的表现比我预期的好得多。

余波

总的来说,这是一次理解情感分析如何加深我对 NLP 理解的旅程。最重要的是,它帮助我看到了我还有多少要学,我期待着在未来回到这个数据集。

有可能有效地预测评论的情绪吗?

是的。绝对的。

我的模型足以以一种有意义的方式做到这一点吗?

这当然比什么都没有好,但远非完美。

完成>完美。

这篇博文完成了。

读者请注意:在发表这篇文章的时候,由于基因药物测试,我的妻子已经发现她的抑郁症有所缓解。如果你或你所爱的人患有抑郁症,并且对你的药物治疗的有效性感到沮丧,我会强烈推荐它。这应该是每个抑郁症诊断的一部分。

我对数据科学的第一个贡献——一个识别尼古拉斯·凯奇图像的卷积神经网络

原文:https://towardsdatascience.com/my-first-contribution-to-data-science-a-convolutional-neural-network-that-recognizes-images-of-fdf9b01c6925?source=collection_archive---------18-----------------------

了解卷积神经网络如何应用于分类愚蠢的图像

在完成了吴恩达教授的流行的在线斯坦福机器学习课程后,我知道是时候进行我的第一个机器学习/深度学习项目了。我想创建一个愚蠢的神经网络,可以识别图像中的尼古拉斯凯奇。我们将使用卷积神经网络(CNN)来识别凯奇先生的图像。请记住,这是我的代码和我对机器学习/深度学习概念的理解的细分。如果您想只查看源代码或只查看。ipynb 文件将被链接到 GitHub 上的这里

第一步将是导入流行的深度学习库 Keras。Keras 将帮助我们训练 CNN 识别图像

我不喜欢使用我不明白它在做什么的东西,我实际上发现机器学习的数学非常有趣。当我第一次学习数学时,看到数年的微积分课程实际上被用来解决一个问题是很酷的。在后面的代码中,我们将分析在使用每个导入时,每个导入在做什么。

  • 顺序模型-顺序意味着可以逐层创建模型。顺序意味着只有一个输入和一个输出,就像流水线一样。层是深度学习网络中的一个单元。层包含权重、激活和偏差。

这个图表有助于解释我们的 CNN 模型将会是什么样子。注意:这只是为了帮助形象化,我们在输出层中只有一个节点,而不是 7 个。

From the paper Real-time Eye Gaze Direction Classification Using Convolutional Neural Network by Anjith George and Aurobinda Routray (https://arxiv.org/abs/1605.05258)

Conv2D:

Conv2D 该层对初始输入图像执行卷积。下面的 gif 有助于说明卷积在做什么。卷积基本上是在初始图像矩阵上通过一个小的“过滤器”或“权重”框,并对图像像素值执行矩阵乘法。在训练期间,这允许我们的网络在图像中识别尼古拉斯凯奇的特征。

Conv2D 参数:

  • 在这里的代码中,我们将模型对象创建为顺序 Keras 模型
  • 然后我们添加一个卷积层
  • 32 意味着我们有 32 个大小为 3x3 的过滤器
  • 输入形状意味着它是一个 200x200 的图像,3 意味着它是一个 rbg 彩色图像
  • relu 激活函数是一个用于确保我们的值被缩放到特定范围的函数。

  • 因此,如果 relu 的输入是<= 0 it will make the value 0, otherwise, if the input is > 0,那么它将只输出输入
  • 激活功能被用来模拟我们大脑神经元的活动方式。当神经网络进行计算时,层中的节点可能输出不在特定范围(如 0 和 1)之间的值。激活功能有助于将我们的数字线强制或“挤压”成我们想要的特定输出范围。

最大池:

  • 最大池 2d-最大池有时也称为缩减采样。我们从卷积创建的卷积特征矩阵是(初始图像像素矩阵*滤波器矩阵)。池查看该矩阵,并在给定区域中取最大值。下图有助于解释最大池如何对图像进行缩减像素采样。

  • 在这里,我们初始化我们的池层,我们创建它的大小为 2x2,就像上面的图表一样

隐藏层:

  • 这段代码增加了两层卷积和最大池,以帮助我们的网络更好地找到我们的图像特征。我最初没有在我们的网络中添加这些额外的隐藏层,我有 89%的测试准确率。我添加了这两层,达到了 91%的测试精度。

展平:

  • 展平-展平操作采用矩阵或张量,并将其展平为一个很长的 1D 值数组。展平层通常紧跟在最后一个池层之后。展平操作是必要的,因为在我们应用卷积来查找尼古拉斯凯奇的要素后,我们需要将这些值展平到一个长 1D 数组中,并将其馈送到我们完全连接的密集网络层。如果你看看 CNN 图表的末尾,你就会明白我所说的馈入末尾密集层网络的值是什么意思。

密集:

  • 密集-密集图层是一种线性运算,其中每个输入都通过权重连接到每个输出(因此有 n_inputs * n_outputs 个权重)。如果你看我们的第一个 CNN 概观图的末尾,那是密集层被使用的地方。
  • 我们在这里将单位设置为 64。单位是指密集层中的节点数。单位值始终介于输入节点数和输入节点数之间。选择单位数时,建议使用 2 的幂。
  • 我们再次使用 relu activation 函数来避免负值,并将我们的值保持在某个范围内。

辍学:

  • 辍学是深度学习和神经网络中使用的一种正则化技术
  • 正则化是一种技术,用于帮助网络不过度适应我们的数据
  • 过度拟合是指我们的神经网络在训练数据上表现良好,但在测试数据上表现很差。这意味着网络没有很好地概括,这意味着它对以前没有见过的新图像的分类不正确/很差
  • 在正式的论文中解释说:“在神经网络中,每个参数接收到的导数告诉它应该如何改变,从而减少最终的损失函数,给定所有其他单元正在做的事情。因此,单位可能会以某种方式改变,以修正其他单位的错误。这可能导致复杂的共同适应。这反过来会导致过度拟合,因为这些共同适应不会推广到看不见的数据。”
  • 因此,我们本质上关闭了一层中的一些神经元,以便它们在网络权重的更新(反向传播)期间不学习任何信息。这使得其他活跃的神经元可以更好地学习并减少错误。

输出层:

  • 这是输出我们预测的最后一层。我们只让它成为一个单位,因为我们希望它输出 0 或 1。1 是包含尼古拉斯·凯奇的图像,0 是不包含尼古拉斯·凯奇的图像
  • 这里我们使用一个不同的激活函数,称为 sigmoid。Sigmoid 用于“挤压”0 或 1 之间的最后一个值。下面是一张 sigmoid 函数的图片,上面有它的方程式。
  • 它将我们的输出浓缩成 0 或 1。非常负的输入接近 0,非常正的输入接近 1。

编译我们的模型:

  • 这里我们编译我们的模型。我们将会遇到一点数学难题,所以抓紧你的帽子。

梯度下降:

让我们首先分解什么是基本梯度下降。梯度下降是一个最小化损失函数的过程:

  1. 我们从损失函数曲线上的一点开始
  2. 我们选择一个学习率,它将决定下降多少步
  3. 然后我们在这一点上求导,也称为“下降”或梯度
  4. 我们将下降乘以学习率值
  5. 我们将初始点移动到曲线上的这个新的(下降*学习率)值
  6. 我们重复这一过程,直到达到指定的迭代次数或其他停止条件,如收敛于局部最小值
  7. 下面是一个梯度下降的 gif,有助于可视化的过程:

随机梯度下降(SGD):

  • 这里,我们选择使用随机梯度下降优化算法来最小化我们的损失函数。
  • SGD 是常规梯度下降的增强版本。让我们看看数学。

常规梯度下降(有时称为批量梯度下降)对于大型数据集来说效率非常低,因为它会查看所有训练示例。下面是批量梯度下降的数学方程。

  • Jtrain 是成本或损失函数。这个例子摘自吴恩达在斯坦福大学的机器学习课程。他使用平方误差作为损失函数,我们将使用对数损失函数,因此我们的示例略有不同。
  • 然后,我们对每个训练样本进行重复,并计算损失函数的偏导数。

SGD 的数学原理:

  • SGD 与批量梯度下降非常相似,但是它在循环过程中计算相对于一个训练样本的梯度,而不是相对于所有训练样本的梯度。
  • 因此,如果我们有 20,000 个样本,批量梯度下降将扫描所有 20,000 个样本,然后在每次循环 20,000 个样本后改变我们神经网络的参数。
  • 而 SGD 在我们遍历每个例子时会一点一点地调整梯度。所以 SGD 查看单个示例,然后在遍历每个示例时调整我们的参数。以下是新加坡元的数学公式:

二元交叉熵:

  • 通过随时间降低损失函数来训练神经网络。
  • 损失函数衡量我们的模型与实际发生的情况相比表现有多差。
  • 在机器学习/深度学习中,有两种类型的损失函数——一种用于分类,一种用于回归。因为我们正在对图像进行分类,所以我们想要使用分类损失函数。
  • 我们选择二元交叉熵或有时称为对数损失作为我们的损失函数,因为我们希望输出在 0 或 1 之间。
  • 交叉熵的方程式如下图所示

这篇文章解释了我们为什么使用交叉熵:

  • 注意,当实际标签为 1 (y(i) = 1)时,函数的后半部分消失,而当实际标签为 0 (y(i) = 0)时,函数的前半部分消失。简而言之,我们只是将实际预测概率的对数乘以地面真实类。一个重要的方面是,交叉熵损失严重惩罚了那些有信心但却是错误的预测。”
  • 因此,换句话说,交叉熵损失随着预测概率偏离实际标签而增加。因此,当实际观察值为 1 时,预测 0.010 的概率将是糟糕的,并导致高损失值。完美的模型的对数损失为 0。
  • 下图是交叉熵损失函数的样子:

  • 因此,为了用方程阐明我们的上述直觉,请注意,随着预测概率在图上接近 1,对数损失缓慢下降。随着预测概率接近 0,测井曲线损失迅速增加。日志丢失严重惩罚了自信和错误的预测。

指标:

  • 我们将参数度量作为“准确性”传递,因为我们使用准确性作为度量来衡量模型的性能。

创建我们的数据:

尼古拉斯·凯奇:

  • 我找不到尼古拉斯·凯奇的现有图像数据集,所以我创建了自己的数据集,使用包 google-images-download 批量下载尼古拉斯·凯奇的图像。为了避免重复,我在 500 个图片搜索中指定了两个不同的日期。
  • 上面的代码循环遍历我们的数据,并用一个数字和一个 Nicolas cage 的标签标记所有图像。
  • 在手动删除了包含其他人的图片或不正确的图片后,我收集了 207 张尼古拉斯·凯奇的图片。

不是尼古拉斯·凯奇:

  • 从这个项目开始,我想我可以做一个单类分类神经网络。我只会有一类尼古拉斯凯奇的图像,并把它提供给网络。我想在训练期间,网络会学习尼古拉斯凯奇的特征,并能够在照片中认出他。
  • 我最终了解到,网络需要“负面”的例子来帮助它了解 Nic 框架映像和非 Nic 框架映像的样子。因此,我们需要收集随机图像的图像数据集,这些图像不是尼古拉斯·凯奇的。
  • 我用这个 python 代码和 picsum 网站生成并保存了 207 张非尼古拉斯·凯奇的随机图像。
  • 下一步是创建我们的训练集和测试集目录。

训练和测试设备:

  • 因为我有少量的数据,所以我决定只手动创建和组织图像的测试和训练集。在一个有成千上万张图片的项目中,使用 python 来创建目录并使用 for 循环来组织数据会更现实。
  • 我决定对我们的数据使用 70/30 分割,因为我们没有大量的数据。所以 70%的数据作为训练数据,30%作为测试数据。
  • 因此,我们的训练数据将有 145 张尼古拉斯·凯奇的图像,而我们的测试数据将有 62 张尼古拉斯·凯奇的图像。
  • 我在我们的 train 和 test 目录中创建了两个子文件夹,分别名为“class0”和“class1”。类 1 包含我们的尼古拉斯凯奇的图像,类 0 包含我们的随机图像。
  • Keras flow_from_directory 按字母数字顺序读取我们的 train 和 test 目录中的文件夹。我花了一段时间才弄明白这一点,因为起初,我的网络将尼古拉斯·凯奇的照片标记为“0”类。这是因为我有两个文件夹:“尼古拉斯凯奇”和“非尼古拉斯”。当时是把“Nicolas_Cage”读成了 0 类。然后我解决了这个问题,看到了我的网络的巨大成果。

图像数据生成器:

这段代码的打印语句和输出为我们提供了:

Found 290 images belonging to 2 classes.
Found 124 images belonging to 2 classes.
{'class0': 0, 'class1': 1}

在这里,我们希望预处理我们的图像,使它们准备好输入神经网络。我们在 Keras 内部使用 ImageDataGenerator 类。该类接收一批图像,并对图像进行缩放和剪切等增强操作。然后,它将增强的数据传递给神经网络。

什么是数据增强?:

  • 根据超级有用的网站 pyimagesearch 的说法,数据增强通过应用随机抖动和扰动(但同时确保数据的类别标签不变),从原始样本中生成“新的”训练样本。
  • 它本质上创建了与原始训练样本略有“不同”的新训练样本。
  • 应用数据扩充的目标是提高模型的概化能力。我们使用增强,因为我们有这么少量的图像,这将有助于我们的模型概括尼古拉斯·凯奇的新图像。下面是一张有用的图片,解释了增强的作用:

参数:

  • 重新缩放-我们以 1 的比例缩放图像。/255
  • 剪切范围——我们指定图像被剪切或向某个方向移动的范围
  • 缩放范围——我们为图像指定一个随机放大的范围
  • horizontal _ flip 水平随机翻转输入
  • 目标尺寸——是我们输入图像的尺寸,每个图像的尺寸都将调整为 200x200
  • batch _ size——我们分批循环我们的图像,因此我们使我们的批量大小为 32 的图像变大
  • class _ mode——我们将其设置为“二进制”,因为我们只有两个类来预测尼古拉斯·凯奇是否出现在图像中

拟合模型:

Epoch 1/25
1000/1000 [==============================] - 913s 913ms/step - loss: 0.3476 - acc: 0.8502 - val_loss: 2.2280 - val_acc: 0.5000
Epoch 2/25
1000/1000 [==============================] - 907s 907ms/step - loss: 0.1354 - acc: 0.9564 - val_loss: 0.5738 - val_acc: 0.8629
Epoch 3/25
1000/1000 [==============================] - 904s 904ms/step - loss: 0.0675 - acc: 0.9825 - val_loss: 0.6880 - val_acc: 0.8710
Epoch 4/25
1000/1000 [==============================] - 910s 910ms/step - loss: 0.0170 - acc: 0.9956 - val_loss: 0.7560 - val_acc: 0.8710
Epoch 5/25
1000/1000 [==============================] - 952s 952ms/step - loss: 0.0454 - acc: 0.9893 - val_loss: 0.7865 - val_acc: 0.8710
Epoch 6/25
1000/1000 [==============================] - 908s 908ms/step - loss: 0.0158 - acc: 0.9959 - val_loss: 0.7694 - val_acc: 0.8952
Epoch 7/25
1000/1000 [==============================] - 908s 908ms/step - loss: 0.0833 - acc: 0.9851 - val_loss: 0.7052 - val_acc: 0.8790
Epoch 8/25
1000/1000 [==============================] - 914s 914ms/step - loss: 0.0103 - acc: 0.9977 - val_loss: 0.7506 - val_acc: 0.8952
Epoch 9/25
1000/1000 [==============================] - 909s 909ms/step - loss: 0.0043 - acc: 0.9989 - val_loss: 0.7203 - val_acc: 0.9032
Epoch 10/25
1000/1000 [==============================] - 905s 905ms/step - loss: 0.0035 - acc: 0.9992 - val_loss: 0.7409 - val_acc: 0.8952
Epoch 11/25
1000/1000 [==============================] - 934s 934ms/step - loss: 0.0050 - acc: 0.9992 - val_loss: 0.8968 - val_acc: 0.8952
Epoch 12/25
1000/1000 [==============================] - 1193s 1s/step - loss: 0.0017 - acc: 0.9998 - val_loss: 0.7880 - val_acc: 0.9032
Epoch 13/25
1000/1000 [==============================] - 1189s 1s/step - loss: 0.0017 - acc: 0.9996 - val_loss: 0.7822 - val_acc: 0.9113
Epoch 14/25
1000/1000 [==============================] - 1194s 1s/step - loss: 0.0014 - acc: 0.9996 - val_loss: 0.7832 - val_acc: 0.9032
Epoch 15/25
1000/1000 [==============================] - 1196s 1s/step - loss: 0.0011 - acc: 0.9998 - val_loss: 0.7775 - val_acc: 0.9032
Epoch 16/25
1000/1000 [==============================] - 1195s 1s/step - loss: 8.3008e-04 - acc: 0.9998 - val_loss: 0.8340 - val_acc: 0.9032
Epoch 17/25
1000/1000 [==============================] - 1198s 1s/step - loss: 0.0072 - acc: 0.9988 - val_loss: 0.7819 - val_acc: 0.8952
Epoch 18/25
1000/1000 [==============================] - 1201s 1s/step - loss: 0.0020 - acc: 0.9997 - val_loss: 0.7950 - val_acc: 0.9113
Epoch 19/25
1000/1000 [==============================] - 1202s 1s/step - loss: 0.0011 - acc: 0.9997 - val_loss: 0.7827 - val_acc: 0.9113
Epoch 20/25
1000/1000 [==============================] - 1170s 1s/step - loss: 0.0015 - acc: 0.9996 - val_loss: 0.8283 - val_acc: 0.9032
Epoch 21/25
1000/1000 [==============================] - 906s 906ms/step - loss: 0.0015 - acc: 0.9997 - val_loss: 0.8592 - val_acc: 0.8952
Epoch 22/25
1000/1000 [==============================] - 905s 905ms/step - loss: 0.0010 - acc: 0.9997 - val_loss: 0.8227 - val_acc: 0.9032
Epoch 23/25
1000/1000 [==============================] - 907s 907ms/step - loss: 8.1553e-04 - acc: 0.9997 - val_loss: 0.8221 - val_acc: 0.9113
Epoch 24/25
1000/1000 [==============================] - 934s 934ms/step - loss: 0.0010 - acc: 0.9998 - val_loss: 0.8540 - val_acc: 0.9032
Epoch 25/25
1000/1000 [==============================] - 1189s 1s/step - loss: 7.6795e-04 - acc: 0.9998 - val_loss: 0.8570 - val_acc: 0.9113
  • 这段代码使我们的模型能够对尼古拉斯·凯奇的图像进行分类。如你所见,在第 25 个纪元结束时,我们能够达到 99%的测试准确度和 91%的测试准确度。
  • 由于我们在训练期间对数据进行扩充,因此我们使用 classifier.fit_generator 函数。classifier.fit 在这里不起作用,因为我们正在对数据进行扩充。

参数:

  • training_set —我们传入训练集 ImageDataGenerator,以在训练过程中扩充我们的训练图像
  • steps_per_epoch —我们的 fit_generator 无限循环,所以我们指定我们希望它循环多少次
  • 次数-定义学习算法在整个训练数据集中工作的次数
  • test _ set——我们传递测试集 ImageDataGenerator 来增加训练期间的测试图像
  • val _ steps——在每个时期结束时停止之前,测试数据生成器产生的总步骤数(样本批次)

“学习”:

神经网络通过称为反向传播的过程进行学习。喀拉山脉。fit 函数为我们自动执行这个过程,所以我们不必手动编写代码,但是到底什么是反向传播呢?对我理解这一点帮助最大的视频是神经网络揭秘3Blue1Brown 的背部道具视频

正向传播:

  • 神经网络接受输入并执行一个称为前向传播的过程。为了理解反向传播,我们首先需要理解正向传播的过程。
  • 神经网络中连接每个神经元的每一条细线都被称为突触,每一条都有一个“权重”值。下图有助于展示小型网络的可视化示例。

这显然是一个非常简单的神经网络,仅包含一个具有 3 个节点的隐藏层,但是前向传播在更大和更复杂的神经网络上同样有效。它本质上是每次向前馈送前一层输入值,并在我们的输入和权重矩阵加上我们的偏差之间应用矩阵乘法。然后,它应用一个激活函数将我们的值“挤压”到期望的范围内。开始向前传播将输出可怕的预测值。在我们的培训中,您可以看到一个这样的例子,因为我们在第一个时期的测试准确率为 50%。Back prop 将帮助调整我们网络中的权重值,以帮助我们的网络实际学习。

反向传播:

  • 神经网络通过最小化“成本”或“损失”函数来学习。当神经网络在前向传播后输出预测时,我们通过查看成本函数来查看该预测有多错误。我们的成本函数是对数损失函数。所以我们用梯度下降来最小化这个函数。
  • 在梯度下降过程中,我们对曲线上的点求导。这个导数告诉我们切线的斜率。我们想把损失曲线上的点移到负斜率方向。基本上,我们希望将损失曲线上的点导向负斜率,因为我们希望最小化成本函数。但是我们如何得到这个导数呢?

在令人惊叹的 3Blue1Brown 反向传播视频中解释道,在高层次上,反向传播是确定对我们网络中的权重和偏差进行哪些改变或微小“推动”的过程,这些改变或微小“推动”将导致基于单个训练示例的成本函数最有效、最快速地降低。反向传播是递归的,这意味着输出图层斜率取决于前一图层斜率,而前一图层斜率又取决于整个网络中的前一图层斜率,依此类推。让我们用微积分来看看这意味着什么:

将所有这些放在一起:

  • 上述方程被简化为在简单网络的每一层中具有一个神经元。这是计算反向传播中导数的更高级的综合方程。

这基本上与之前的等式相同,但在处理每层中有不止一个神经元的网络时稍微先进了一点,这就是 jk 可迭代索引的来源。

为了让我们的网络运行良好,有必要理解看起来很粗糙的微积分吗?谢天谢地没有,因为 Keras 自动为我们做这个过程,但我认为这是有趣的数学兔子洞。反向传播非常令人困惑,老实说,当我看所有的微积分时,我有时还是会迷路。很多时候,我仍然不得不去回顾它,观看有用的 youtube 视频,试图完善我的理解。

准确度和损耗:

Accuracy

Loss

  • 这段代码让我们可以可视化我们的模型准确性和模型损失。代码来自 Keras 文档中解释的这里的
  • 正如我们所看到的,我们的测试和训练精度非常接近第 25 个纪元,我们的模型损失也是如此!
  • 我们以 91%的测试准确率和 99%的训练准确率结束了我们的训练,这已经很不错了。

做出预测:

  • 正如你所看到的,我们的模特认出了尼古拉斯·凯奇的这些美丽而绝对鼓舞人心的照片。
  • 我们的模型也能识别出不是尼古拉斯凯奇的图像,比如岩石的图片或者天空的图片。
  • 我对我们网络的结果非常满意。我们的网络甚至能够识别尼古拉斯·凯奇的愚蠢的迷因图片,比如他的脸被编辑到比尔·克林顿的脸上。

结论:

  • 在做这个项目的过程中,我学到了很多关于深度学习的知识,并且在创建它的过程中获得了很多乐趣。我在斯坦福上的课是吴恩达教授的很受欢迎的机器学习课。这门课程给了我一个很好的机器学习概念的基础,并向我介绍了神经网络、反向传播、线性回归,甚至支持向量机等概念。但是我知道最重要的学习来自于钻研和创造一个项目。
  • 我想我也许可以收集更多尼古拉斯·凯奇的数据,以获得更高的测试准确性,但不管怎样,我对结果很满意,因为模型能够很好地识别我们的模因。
  • 如果我将二进制分类应用于不同的数据集,如分类星系和黑洞图像,甚至太空中的星座,这个项目可能会更有趣,但神经网络识别尼古拉斯·凯奇图像的想法似乎太有趣了,太好了,不能错过。

联系人:

  • 如果你有问题、担忧、建设性的批评,或者想看到更多未来的项目,请查看我的 github 和我的 linkedin 。感谢阅读!

资源:

我的第一个数据科学项目

原文:https://towardsdatascience.com/my-first-data-science-project-4c842454438?source=collection_archive---------33-----------------------

我为什么要写这篇文章

作为一个在数据科学领域工作了一段时间的人,我收到了不少热情的毕业生的问题,他们问我“如何成为一名数据科学家”或“数据科学家每天都做些什么”。另一方面,我偶尔听到一些声音开玩笑说“数据科学家是 21 世纪最性感的工作”不再是真的了:大多数数据科学家的时间可能会花在繁琐的任务上,如运行 SQL 来提取数据,构建仪表板来做报告,以及(更令人沮丧的)你需要维护它们!他们问我作为一名数据科学家的经历是什么,我对这一现象有什么感觉,以及在最初的声明发表 7 年后,数据科学是否仍然“性感”。许多类似的问题都围绕着这个主题,我认为通过一个关于我的第一个数据科学项目的故事来分享我的个人观点可能会有所帮助。这可以作为一个参考点,希望它也可以激励那些仍然渴望加入该领域的人,或者那些刚刚开始他们的第一份数据科学工作的人,甚至那些已经在该领域工作了很长时间的人。

注意。这不是我作为数据科学家的第一个实际项目,正如你所知道的,开始任何工作,都需要在开始时做一些琐碎的任务,以了解基本知识。这个项目是我 2013 年在 TrueCar,Inc .开始数据科学职业生涯后的第三个月做的。

故事

研究生毕业后,我加入了 TrueCar,开始了我的第一份数据科学家工作。对于那些不知道的人来说,TrueCar 是一个在线购车平台,它提供透明的定价信息(例如,最近的车辆交易价格),因此客户不会为一辆车多付钱。当时,作为一名应届毕业生,我对数据科学团队正在从事的所有项目非常着迷,这些项目几乎涵盖了一家以数据为中心的技术公司运营的所有业务方面:构建定价模型以支持核心产品,用 A/B 测试优化网站等。在第一个两个月的入职期后,我被分配到搜索引擎营销领域工作。

搜索引擎营销(SEM)是搜索引擎巨头,如谷歌,发明的游戏。这个游戏的一个过于简化的观点是:公司决定关键词的竞价价格(例如,“新丰田卡罗拉”是一个 3 个单词长的关键词)。如果用户搜索准确的关键词,并且该公司的出价高于其他竞争对手,它将赢得该位置,并可以将他们的产品信息放在用户将看到的所有搜索结果的顶部。如果用户点击产品链接,该公司就会向搜索引擎巨头付费,通常是第二高的出价。几年来,TrueCar 一直在使用 SEM 来帮助获取客户,系统中已经有成千上万的关键字需要维护,这些关键字是由不同的活动组织的。我分配的项目是报告每个 SEM 活动的表现,并使用 Google 的 AdWords API 自动报告。

我对这个项目非常满意,它是我练习 Python 技能和学习更多 AdWords API 的一种方式,尽管这看起来一点也不“性感”。反正我就开始摆弄 Adwords,写点代码,很快就收集了很多关键词性能数据然后用它们编了一个报告。

有点好奇

在生成第一份活动绩效报告后,我发现“每次转化成本”(CPC)是人们都关心的指标;这并不奇怪,因为这个指标意味着我们为一个转化的客户支付多少钱:越低越好。我还做了一些关于 SEM 行业的研究,并意识到“关键词”是搜索引擎营销的一个重要方面:它们并不平等,两个关键词在“每次转换成本”方面可能有显著不同的表现。当时,我想到了两个问题:1 .哪些关键词性能更好(CPC 更低)?2.我们是否已经在系统中拥有了所有性能更好的关键词?

一些科学,一些算法

手动浏览系统中的所有关键字以获得任何有意义的见解是不可能的,想象一下可能有类似“我真的想买一辆现代索纳塔”的关键字(是的,我刚刚在谷歌中进行了搜索,所以它是其他公司可以竞标的关键字,并且它至少有一个搜索流量)。所以我需要更有策略,在流程中加入一些“科学”成分。我开发的算法或过程如下:

  • 第一步。对于所有活动中的每个现有关键词,生成 1 克和 2 克的子关键词。例如,“新丰田卡罗拉”关键字将生成以下 5 个子关键字:“新”、“丰田”、“卡罗拉”、“新丰田”、“丰田卡罗拉”
  • 第二步。为每个子关键字分配性能,就好像它们是关键字本身一样。例如,如果“新丰田卡罗拉”有 100 美元的 SEM 支出,导致 10 次点击和 2 次转化;那么所有 5 个子关键词都将具有相同的表现。
  • 第三步。按所有子关键词分组,并计算它们各自的成本和转化率,然后我们就可以得到它们的平均每次点击费用,以点击数作为相对大小的参考
  • 第四步。按照点击费的表现对所有子关键词进行排序,较低的点击费排在最上面

这肯定不是最好的算法:有相当多的子关键词完全没有任何意义,比如“购买 a”、“the”等。但是,也有一些有趣的子关键词出现在列表的顶部:其中之一是“最佳价格”。这个子关键词的点击费低得惊人,但只有几百次点击。嗯…,这是什么意思?

貌似合理的商业解释

为什么“最优价格”表现更好?融入一些商业知识,一切开始变得有意义:在 TrueCar 上转换良好的人通常有强烈的“找到一笔好交易”的意图,“最佳价格”是在搜索查询中表达他们兴趣的常见方式。从这个角度来看,与“最佳价格”相关的关键词具有较低的 CPC 是有意义的,因为它们的转化意愿(例如,使用 TrueCar 产品)较高。另一方面,我的分析显示,我们只收到有限的点击,由很少的关键字贡献,这表明有机会进一步扩大!

不久,我用几张幻灯片总结了这一发现,以展示这颗“隐藏的宝石”。人们对我的发现有点怀疑,因为特定关键字的样本非常有限,然而,没有人想拒绝用一半的成本获得更多销售的机会,所以我得到了一个绿灯来测试这个想法!为了避免不必要的技术术语和细节,简而言之,我围绕“最佳价格”创建了一组关键词,将所有内容上传到 AdWords,并开始了新的活动。一周后,它收到了大量的点击量,而每次点击费用却大大降低了,每个人都非常高兴。之后,纯粹是执行:通过各种方式产生更多基于“最佳价格”的关键词,我们扩大了多个活动的规模,它们都表现一致:每次点击费用比同行活动低得多。这为公司带来了大量的廉价转换,幸运的是,我的第一个数据科学项目有了一个美好的结局:)

回首

很快,在过去的 6 年里,许多事情都发生了变化。如今,SEM 行业更加智能化,大多数关键字选择都通过各种工具实现了自动化。就在今天,当我搜索“价格最优的丰田卡罗拉”时,有四个返回的 SEM 结果,而 TrueCar 不在其中。所以我知道我对这个特定关键词的洞察力已经过时了。在数据科学方面,这个项目不能被认为是辉煌的:算法是初步的(简单的 n-gram 特征提取),统计数据缺乏一些严谨性(计算 CPC 置信区间的一种非常简单的方法),工程过程相当粗糙(肯定不是我最好的 Python 代码)。然而,我仍然为这个项目感到自豪,因为它让我尝到了数据的价值;作为一名数据科学家,我可以打开它并享受成功。

我对数据科学的思考

现在,您已经了解了我的第一个数据科学项目故事。当然,这只是作为一名数据科学家的成千上万种开始方式中的一种。希望这个故事揭示了“数据科学家”应该具备的三个要素(我认为):

  1. 良好的数据分析和工程技能:没有这些,你可能会陷入许多步骤(例如,提取 n-gram,自动启动 SEM 活动等)
  2. 合理的商业意识:数据有助于揭示隐藏的商业知识,所以你最好先了解一些基础知识。
  3. (最重要的)你的好奇心:这是让你开心的东西,可以将“繁琐”的任务转化为有趣的项目

作为故事的结尾,我想引用我之前关于“数据科学家”的说法:这是大约五年前我的(当时的)数据科学团队接受当地一家报纸采访时所说的话(链接),我认为这句话现在仍然适用。

“成为一名数据科学家需要统计学、编程和商业意识的结合。“能够从数据中探索洞察(通过编程&统计)以满足公司业务需求的是‘科学家’。”

*感谢您的阅读,并随时与那些可能觉得有用的人分享这个故事。文章首发于 LinkedIn(https://www . LinkedIn . com/pulse/my-first-data-science-project-pan-Wu),转载于 Medium。

我的第一个数据科学项目——伦敦的家庭友好型社区

原文:https://towardsdatascience.com/my-first-data-science-project-family-friendly-neighborhoods-in-london-fe5ea51e48f5?source=collection_archive---------18-----------------------

在过去的两年里,我的生活发生了很多变化。我已经决定从神经科学背景转向数据科学,我从美国搬到了英国伦敦。我搬到伦敦是这个项目的灵感来源,因为我很少知道哪些社区被认为是好的,哪些被认为是坏的。所以当我和我丈夫试图找一个地方和我们的两个小男孩住在一起的时候,我们完全没有头绪。我试着用谷歌搜索伦敦的好社区,有不少网站列出了他们对最佳社区的看法。但是所有这些列表的问题是它们看起来像是意见,而不是基于实际数据。来自科学背景的我需要数据来支持这些列表。我们最后做了最好的猜测,我们相当幸运地在一个好的地区结束。

将来,我想避免这种未知,更好地了解伦敦哪些社区是家庭友好型的。好了,我说完了我对这个项目的灵感,让我们开门见山吧。

  • 注意这篇文章将而不是代码繁多,如果你想了解更多关于所用代码的细节,你可以在 Github 上查看笔记本,点击这里。(看不到叶子地图,但如果你想看地图,可以在 nbviewer 上粘贴 Github 链接)

数据

对于这个项目,我们从 大都会警察局犯罪仪表板 获取伦敦犯罪数据,并使用犯罪数据集中的纬度&经度从 Foursquare API 获取场地数据。

犯罪数据

Original Crime Dataset

我们首先需要通过删除不必要的行和重命名列来清理犯罪数据。

Clean Crime Dataset

现在我们有了一个干净的数据集,我们可以通过 Geopy 的反向地理编码运行纬度和经度,并找到相应的邮政编码,我们将将它追加到一个新的 postal_code 列。

Example of the dataset with Postal Codes

不幸的是,反向地理编码并不像我们希望的那样清晰。缺少超过前缀的数据点和邮政编码(例如:Index 5 Postal_Code 读作“SW1 H ”),我们将手动清理每个邮政编码,并使用以下代码输入缺少的邮政编码:

Snippet of Code to edit Postal_Code Column

Subset of Dataframe after fixing Postal_Code column

然后我们按照邮政编码将犯罪事件加在一起。这将是我们最终的犯罪数据集,总共有 212 行和 4 列。

Final Crime Dataset

犯罪数据可视化

为了确定伦敦的犯罪分布情况,我们将把数据绘制成箱线图。

Box plot of Crime in London

我们将“正常”的犯罪数量定义为落在方框内的所有值,低犯罪数量定义为低于方框的点,高犯罪数量定义为高于方框的点。

我们现在使用叶子在伦敦地图上绘制点。我们对这些点进行如下颜色编码:

  • 高犯罪率= "红色"
  • 普通犯罪= "黄色"
  • 低犯罪率=“绿色”

Crime Map of London

太好了,我们现在对不同邮政编码(街区)的犯罪有了很好的了解。但在寻找家庭友好型社区时,犯罪并不是唯一要考虑的因素。我们还需要考虑儿童友好型活动。为此,我们使用 Foursquare API。

场馆数据

对于这个项目,我们决定重点关注以下几个类别:

  • 公园 ( Foursquare 类别 Id: '4bf58dd8d48988d163941735 ')
  • (Foursquare 类别 Id: '4bf58dd8d48988d12f941735 ')
  • Lidos(Pools)(four square 类别 Id: '4bf58dd8d48988d15e941735 ')
  • 游乐场 (Foursquare 类别 Id: '4bf58dd8d48988d1e7941735 ')
  • 电影院(四方分类 Id: '4bf58dd8d48988d180941735 ')

我们创建一个函数来标识场馆,并将该类别的场馆总数附加到当前数据帧的新列中。下面是函数:

Function for identifying the total number of venues in each category

这是最终的数据集:

Final Dataset

k 均值聚类

最后,我们使用机器学习技术 K-Means。选择这种技术有两个主要原因:

  1. 我们没有标签数据
  2. 我们知道我们想要多少个集群(3:不友好型、友好型和谨慎型)

对于 K-Means,我们选择希望算法使用的功能,这意味着选择“Crime_Incid”、“Park”、“Library”、“Pool”、“Playground”和“Cinemas”列:

在运行 K-Means 之后,我们将聚类标签插入到原始数据集中,然后使用 Folium 绘制数据以可视化不同的聚类。

Final Map of Family-Friendly Neighborhoods

很快,我们可以看到很多红色变成了黄色,现在地图上有了更多的绿色点。这是个好消息,因为不像大多数人认为的那样,在大城市有家庭友好型社区。

只是为了确保没有隐藏的集群,我们运行肘方法,以确保我们有最佳数量的集群。

Optimal k = 3

我们可以看到,3 是集群的最佳数量。耶!

结果和讨论

这是一个好消息,看到在伦敦有更多的家庭友好型社区,而不是要避免的社区。事实上,有 136 个街区可供选择。下面是一个简单的分类:

因此,对于任何像我自己一样在英国伦敦寻找最佳家庭友好型社区的家庭来说。我建议你从这 10 个开始:

Top 10 family-Friendly neighborhoods

他们的犯罪率并不是最低的,但他们的犯罪率仍然很低&有很多适合孩子的活动。

但是如果你在寻找最安全的社区,那么就从这些开始吧:

Neighborhoods with the lowest crime Incidents

但是我给你一个合理的警告,一些邮政编码没有很好的儿童友好活动。但这可能会引起企业、城市规划者和开发商的兴趣,他们可能想建造这些适合儿童的场馆。

现在,对于我们的警察局长、专员和其他安全人员来说,了解哪些社区可以利用更多的资源来降低这些地区的犯罪率将会使你们受益。对于家庭来说,这些是你应该避免居住的地方。

进一步分析&改进思路

没有哪个数据科学项目是真正完整的。总有优化的空间,因此我列出了一些改进结果的想法

1。添加更多适合儿童的分析场所。

  • 公园、操场、图书馆、游泳池和电影院并不是仅有的适合孩子的活动。

2。为每个邮政编码添加边界

  • 目前仅使用 1 英里半径来定义邮政编码分配的纬度和经度的边界。这可能会在搜索地点时导致一些不必要的邮政编码区重叠。这也将允许绘制 choropleth 地图。

3。根据邮政编码内的人口标准化犯罪事件。

  • 注意,许多要避免的邮政编码位于中心,那里的人口密度很可能大于远离中心的邮政编码。这可能导致犯罪率表面上看起来很高。

4。按预算进一步过滤结果

  • 这将有助于更好地迎合各种预算的家庭。伦敦是一个生活成本很高的城市,尤其是在住房方面。根据 Business Insider 的数据,伦敦两居室公寓的平均租金为 2338 美元(1875 英镑),是世界上第六大租金市场。根据平均房价,伦敦在全球最贵的地方排名第八。

结论

很高兴看到大城市可以对孩子友好。很高兴看到我们最终选择的社区被认为是适合孩子的!

孩子是我们的未来,大城市是可以找到机会的地方。因此,重要的是让大城市变得对孩子更加友好。家庭不应该觉得为了抚养孩子他们不得不逃离大城市。

我希望你喜欢阅读这个项目,就像我喜欢为它工作一样。因为这是我的第一个项目,我会喜欢你的反馈,所以请随时与我联系!完整的笔记本可以在 Github 这里 找到,报告可以在 这里

我作为数据分析师的第一份工作:期望与现实

原文:https://towardsdatascience.com/my-first-job-as-a-data-analyst-expectations-vs-reality-3a598412cd52?source=collection_archive---------4-----------------------

@jessedo81

我职业生涯中最重要的一课…

在学校呆了将近 5 年后,毕业典礼终于来临了,我已经准备好测试我的技能了。我并不完全确定我想要什么头衔,我只知道我喜欢处理数据和解决复杂的问题。我后来意识到,我想从事数据科学方面的职业,但那是以后的事了。

毕业后不久,我在当地一家公司获得了一份数据分析师的工作。这似乎与我的技能和我对数据工作的热情完全吻合,所以我马上接受了。我已经可以想象自己坐在办公桌前,做销售预测,创建惊人的报告和可视化。

[## 通过我的推荐链接加入 Medium-Andres Vourakis

阅读安德烈斯·沃拉基斯(以及媒体上成千上万的其他作家)的每一个故事。您的会员费直接支持…

medium.com](https://medium.com/@avourakis/membership)

你可以说,我被最终被推到现实世界的欣快冲昏了头脑,我从来没有花一秒钟来放慢脚步,喘口气,并“降低我的期望”。

我作为数据分析师的头几个月很少涉及数据分析,主要是长时间争论数据。这些是我不止一次使用的短语,完美地总结了最初的几个月。

“我在哪里可以再找到那个?”

虽然我接受了分配给我的项目的培训,但是有太多的东西需要理解。我发现自己很难记住每个文件的位置以及我需要遵循的不同流程。缺少可用的文档是一个巨大的挫折,我最终不得不依靠我的同事四处走动。

“那会花太长时间”

最大的挑战之一是无法访问“正确的”基础架构或工具来处理和分析大型数据集。几乎所有的报告公司都使用 Excel,尽管它不能满足我们所有的需求。公司里的每个人都要求更多,我们根本无法满足。

“我们不应该手动操作”

我们的一些日常任务包括从不同的网站下载 CSV 文件和刷新 Excel 报告。这些任务浪费了我们太多的时间,需要自动化。

“我们还不能相信这些数据……”

由于我们的数据是从这么多不同的来源收集的,而且报告并不总是只由数据团队处理,所以很难相信在我们公司会议上不断抛出的数字的准确性。

我的公司发展迅速,我们需要依靠数据来做出决策。问题是,我们当前的基础架构无法满足我们的需求,而且一路上有太多的权宜之计,裂缝开始显现。我的团队由 3 名数据分析师(包括我自己)组成,但在某种程度上,我们还需要扮演数据工程师和数据科学家的角色。我们根本没有预算来引进更多的人才,因此我们需要做好基础工作,以确保我们能够满足利益相关者的期望。

但是尽管我的工作不是我所期望的(至少在最初的几个月),我学到的东西比我想象的要多。我有机会体验从零开始一个项目的真正感觉,并在过程中处理不同的障碍,相信我,有很多。你看,为了将数据转化为见解或预测,需要做大量的工作来准备数据。我记得在学校里学过,但直到我亲身经历后才真正理解。

当我在学校的时候,我从来没有真正花太多时间问类似“我能相信这些数据吗?”或者“存储数据最有效的方式是什么?”。我更加专注于学习数据分析中令人兴奋的部分,比如可视化、预测等等。你可能在互联网上见过的所有流行词汇。

但是这份工作,尽管充满挫折和挫折,却给我上了非常重要的一课,毫无疑问,这一课在我的职业生涯中会非常有价值:

永远愿意做“肮脏”的工作

我不是指肮脏、无用或令人不快的工作(尽管对一些人来说可能是),我指的是那种经常被推到一边的工作,因为它可能不如预测未来那样令人兴奋,或者不如创造可视化那样华而不实。但是毫无疑问,做“脏”工作是处理数据的重要部分。

不管你是一个有抱负的数据分析师还是数据科学家,如果你愿意清理所有的数据,测试它,编写所有的文档,并清理所有的代码,那么你将永远在数据团队中占有一席之地。你不仅会让你的团队走向成功,还会成为他们可以依赖的人。

如果你对我和我的团队如何克服我之前提到的一些障碍感到好奇,那么看看我写的另一篇文章:

[## 当 Excel 不够用时:使用 Python 清理数据、自动化 Excel 等等…

数据分析师如何在电子表格驱动的组织中生存

towardsdatascience.com](/when-excel-isnt-enough-using-python-to-clean-your-data-automate-excel-and-much-more-a154c6bf9b49)

我希望这篇文章对你有用。如果你有任何问题或想法,我很乐意在评论中阅读:)

另外,如果你希望支持我成为一名作家,可以考虑注册成为❤️的一名媒体成员

我第一次开源贡献的痛苦和狂喜

原文:https://towardsdatascience.com/my-first-open-source-contribution-7698950895a9?source=collection_archive---------21-----------------------

我的第一个开源贡献并不是一帆风顺的,但它肯定是完全值得的

在过去一年左右的时间里,我一直渴望为一个开源 R 包做贡献,但是像许多人一样,我发现处理这个任务的想法令人害怕。

虽然我每天都在一个非常动态和紧密的团队中工作,并且在远程存储库(Git)的世界中,我对这些远程存储库中的协作工作的接触非常有限…我们更倾向于在很大程度上独立完成项目,所以拉请求(PRs)、合并、分叉的概念…嗯,这都有点令人生畏。

以下是旅程中的一瞥,将在本帖中解释:

The journey I took

这篇文章不会是一个详尽的每个接触点的一步一步的指南,而是一个中高层次的总结。

我的孩子,生活本不该是轻松的;但是鼓起勇气:这可能是令人愉快的。——乔治·萧伯纳

记着乔治的话,我想是时候让自己跳进去了。

浏览 Twitter(就像护理新生儿一样),我看到一条关于我在上的一些分析中使用的一个包的推文,不要责怪数据说这个包现在在 CRAN 上直播(一个伟大的成就)。

The tweet that started everything

这很自然地把我带到了 Github 上的仓库,在那里我注意到有一些公开的“问题”,其中之一是为任何回合创建一个梯子的函数。

菲茨罗伊套餐

James Day 开发的 fitzRoy 软件包是一个旨在帮助 R 用户提取和分析澳大利亚足球联盟(AFL)男女比赛数据的软件包:

fitzRoy 的目标是提供一套功能,使用户能够方便地访问来自 afltables.com 和 footywire.com 的 AFL 数据。还有一些工具可以处理和清理这些数据。

虽然我肯定没有在这一点上做任何广泛的分析,但我猜想所有 AFL 数据分析项目的大部分都是在这个软件包的帮助下完成的。

直接跳进来

所以,与其考虑做出贡献有多好,为什么不直接联系詹姆斯,主动提出解决这个公开的问题呢…

詹姆斯非常容易相处,而且他很乐于助人(对这个笨手笨脚的傻瓜很有耐心)。

然后是写函数的时候了。就像写函数一样。幸运的是,我已经为一个线性回归模型编写了这个函数,这个模型是我为预测 AFL 主客场比赛的上座率而构建的这里是。这个函数被恰当地命名为return_ladder() …我是数据科学家,不是诗人。

这个函数做了一些修改,利用包中的get_match_results()函数返回return_ladder的起始数据帧。在编写这个函数的时候,我想解决这个需求,即梯子可以在任何回合返回,并且可以在 2011 赛季之前返回,这是另一个 API 已经提供的。

记住这一点,编写的函数接受三个参数,所有参数都可以选择为空,也可以指定:

  • match_results_df -使用get_match_results()提取的数据帧,
  • season_round -用户想要梯子的季节周期,
  • season -需要梯子的季节。

如果这些都留空,该函数将返回自 1897 赛季以来每个赛季每轮的阶梯。

编写函数是一回事,它还需要 roxygen 注释,这些注释在函数的帮助文档中返回给用户。哈德利的《R 包》一书很好地解释了这些。

我准备好成为一名贡献者

我已经编写了函数、帮助文档,并使用devtools::check()检查了包,以确保我没有犯任何会导致包构建失败的错误……没有什么看起来令人担忧(嗯,有一些关于没有全局变量的可见绑定之类的警告,但我确信没有什么可担心的),但对我来说一切都很好。

我的本地更改已提交,公关也已完成,我准备好成为一名贡献者,然后嘭!codecov 失败!!那是什么?!给詹姆斯发了一封电子邮件,我被告知这是因为没有写测试。好的,我会写一些测试…什么是测试?!我如何编写这些测试?!我发现这个帖子真的很有帮助,还有哈德利在 R Packages 书中的测试。

一旦这些测试被编写,我提交我的更改,我准备好成为一名贡献者,然后砰!我已经对我的 PR 中没有的母版进行了更改…好的,所以我需要将母版合并到我的 PR 中——很容易(对于某些人来说,我可能不知道)。谷歌一下,看起来很容易,但是在输入git merge origin/master之后,我在终端中弹出了这个编辑器:

我最初的想法?这是什么?!

有点谷歌,好吧,这是一个 VIM 编辑器。简单。写一个提交消息,然后一切都会好的…等等?!我如何离开这个屏幕?!再谷歌一下,输入:WQ之后,我们就可以开始摇滚了。

什么?我是。一.在做什么?!!

好吧,事情看起来不错。我提交了我的修改,所有的检查都通过了,快乐的日子。

你知道我之前写的关于的那一行吗?有一些关于‘全局变量没有可见绑定’之类的警告,但是我确信没有什么好担心的。?好吧,这一直困扰着我,因为正如詹姆斯建议的那样,当试图包含 CRAN 的更新时,这些会引起问题。所以我修改了那些,也更新了男士的小插图。在这一点上,我对自己做了什么有点模糊,但我所知道的是,我一定是把自己织进了一张 Git 网…

我的分叉回购的Master比我的分支Ladder晚两次提交,比Origin/Master早五次提交。什么?我是。一.在做什么?!试错,试错。

成功!

在经历了很多心痛之后(我不能强调有多心痛),最终,我把自己整理好了,创造了另一个公关和…成功!!!

最后,我可以说我已经成功地为一个开源项目做出了我的第一份贡献。我希望这个软件包的用户会发现这个功能很有用,并且像其他任何东西一样,可以找到改进的地方,使它变得更好。

本帖原创,发布在不怪数据博客https://www.dontblamethedata.com。去那里看看一些正在使用的新功能的例子。

我的第一个 Python 小项目,用于在 office 中安全浏览 Reddit

原文:https://towardsdatascience.com/my-first-small-project-in-python-for-browsing-reddit-in-office-safely-4d1d6985163a?source=collection_archive---------22-----------------------

TL;DR:你可以用这个包在命令提示符下浏览 Reddit,假装你在办公室工作。

What you can see in your command prompt when you browse subreddit ‘learnpython’ using braw

人们总是说用有趣的方式学习比用无聊的方式学习更有效。而我相信编程也是如此。这就是为什么当我现在学习如何在 Python 上构建一个项目时,我总是寻找一些有趣的项目来给我工作的热情。几天后,我的第一个小项目完成了,我把它叫做 braw(在工作中浏览 Reddit)。此时,该包只允许阅读文章,但不允许创建新文章或发表评论。这将是我这个小项目的第二部分。

完整的代码在这里:https://github.com/wyfok/braw

  1. 准备
  2. 可用功能
  3. 结尾

准备

Python Reddit API 包装器(praw)是一个用于包装 Reddit 的 Python 包。在我的包中,我将使用它来访问 Reddit 并包装内容。有关 praw 的更多信息,请访问 https://praw.readthedocs.io/en/latest/index.html

为了使用这个 braw 包,首先你需要有一个 Reddit 帐户。你还需要从 Reddit 偏好设置->应用程序(https://www.reddit.com/prefs/apps/)获取你的个人客户端 ID 和客户端密码

名称:给出一个名称

选择脚本

描述:空白

关于 url:空白

重定向网址:http://www.example.com/unused/redirect/uri(脚本中不会用到,只是填充用)

然后在下一页,您将获得您的客户端 Id 和客户端密码

此时,创建一个以 JSON 格式存储这些信息的文本文件并保存它。

{
"user_agent":"user_agent",
"client_id":"the string below personal use script",
"client_secret":"secret"
}

由于这个包需要 praw,所以需要先安装 praw。你可以这样做

pip install praw

下载 braw 包后,打开命令提示符,将目录更改到该文件夹。然后运行 Python,导入 braw。

此时,系统会要求您粘贴该文本文件的路径。如果没有错误信息,这意味着您成功连接 Reddit。但是,如果您看到打印结果显示无法连接到 Reddit,这表示您的客户端信息不正确,或者在连接过程中出现问题。

可用功能

以下是您目前可以使用的功能

  1. get_top(s_reddit='all ',time='week ',how_many=10)
  2. get_hot(s_reddit='all ',how_many=10)
  3. get_new(s_reddit='all ',how_many=10)

如果你是 Redditor,那么你应该熟悉前三个。如果你不是,你可以使用每一个来获得热门、热门或新的 Reddit 帖子。您可以选择所有子编辑“all”或选择特定的子编辑,如“learnpython”。然后,您将获得 id 为的各个帖子的标题列表。

4.获取提交(发布标识)

5.获取评论(帖子标识)

使用带有提交 ID 的“get_submission”函数,可以阅读文章的正文。

您还可以使用带有提交 ID 的“get_comment”函数来检查评论。

6.til(多少=10)

有一个著名的教育性的子栏目叫做“今日学习”,里面有很多有趣的事实。该函数将显示该子编辑中的热门帖子。

7.振作起来(多少=10)

我们都知道工作时会非常沮丧。为什么不休息一下,看一些加油的图片呢?“cheer_me_up”将从子编辑“aww”、“dogpictures”和“catpictures”下载图像,并存储在您指定的本地文件夹中。

(PS:我在这里没有任何侵犯任何版权的意图。我尊重所有人的版权。你也应该。所以成功给你加油后请删除所有照片。)

结局

我真不敢相信在设计这个包的时候里面有这么多的乐趣和刺激。我意识到,在 Python 中,我需要做的事情比我想象的要多得多。我希望你喜欢我的第一个小项目,并发现这个包很有用。不仅在办公室,你还可以在公共场所使用这个包,这样别人就不会知道你在浏览 Reddit。如果你发现任何问题或者你想加入其他功能,请在这里或者 GitHub 中留下你的评论。本帖到此结束,下次再见。

我的第一个 Python 小项目,用于在 office 中安全地浏览 Reddit(第 2 部分)

原文:https://towardsdatascience.com/my-first-small-project-in-python-for-browsing-reddit-in-office-safely-part-2-278b56790635?source=collection_archive---------42-----------------------

TL;DR:你可以用这个包在命令提示符下浏览 Reddit (并留下你的评论),假装你在办公室工作。

如果你没有看过我之前关于 braw 的帖子(在工作中浏览 Reddit),请先看看,这样你就可以对我的第一个小项目有个概念。

[## 我的第一个 Python 小项目,用于在 office 中安全浏览 Reddit

TL;DR:你可以用这个包在命令提示符下浏览 Reddit,假装你在办公室工作。

towardsdatascience.com](/my-first-small-project-in-python-for-browsing-reddit-in-office-safely-4d1d6985163a)

正如上一篇文章所说,在一篇文章上留下评论将是这个小项目的第二阶段。现在就在这里。

(PS: W3Schools is a really good place to learn Python, recommended)

完整的代码在这里:【https://github.com/wyfok/braw】T2

新增功能:

1.lcop(在帖子上发表评论)

参数:submission_id

lcop 允许您对提交内容发表评论。您需要提供的只是帖子的提交 id。

由于发表评论需要登录,因此在进行任何操作之前,将首先自动检查用户是否登录。如果用户没有登录,那么程序将询问用户是否想要登录。

有时帖子已经被锁定,不允许任何新的评论。在这种情况下,来自 praw 的 APIException 错误将被引发,因此使用 try exception 来处理。

2.lcoc(在评论上留下评论)

除了在帖子上发表评论,你现在还可以在评论上发表评论。与 lcop 类似,您需要提供评论 id 来引用您想要留下评论的评论。

次要更新

包含函数的文档字符串。

在之前的版本中,我没有包含任何 docstring,后来我意识到这对于一个项目来说是一个非常不好的习惯。所以现在我加了回来

隐藏内部功能

对于一些函数,比如打印标题和正文,用户不需要知道,所以我通过用下划线作为前缀重命名函数名来隐藏它。

结局

这个项目将不断更新以添加一些新功能,例如,下一阶段将把帖子和评论复制到 word 文件中,这样你甚至不需要在命令提示符下阅读它。如果你有一些想法或想法,欢迎在这个帖子或我的 GitHub 中发表评论。

青少年初学者指南

原文:https://towardsdatascience.com/my-first-twitter-app-1115a327349e?source=collection_archive---------9-----------------------

如何使用 Python 和 Tweepy 创建自己的 Twitter 数据集

Photo by Elena Koycheva on Unsplash

分析数据的第一步是找到要分析的数据。Twitter 是一个寻找数据的好地方。

Twitter 的 API 是出了名的有据可查,这使得它成为开始创建你自己的数据集的好地方。

在本教程中,我们将涵盖:

  • 创建 twitter 应用程序
  • Tweepy 获取推文
  • 提取 tweet 属性

创建一个 Twitter 开发者账户和应用

  1. 在这里申请一个账号。
  2. 创建新应用程序。填写必填字段。(如果你没有网站,你可以使用占位符。)
  3. 单击“密钥和令牌”选项卡。创建访问令牌和访问令牌密钥。(消费者和消费者密钥应该已经可见。)

安装 Tweepy

要安装 pip,只需在终端中键入pip install tweepy

证明

现在说说好东西。

Tweepy 确实使 OAuth 几乎没有痛苦——但是我不打算撒谎,我几个小时都无法让它工作……然后我终于意识到我的访问令牌末尾有一个空格。🤦‍♀

现在,为了确保它能正常工作,让我们打印我的流中最近的推文:

成功!我们有一堆随机的推文!但是,这真的不是很有帮助,除非你试图分析你关注的人的推文。

获取用户的推文

Tweepy 有一个有用的方法,可以返回指定用户最近发布的状态。

让我们用这个来看看唐纳德·特朗普今天在推特上发了什么:

现在我们有进展了!我们有 tweet 文本,但这仍然不是非常有用。它只是看起来像一堆随机的文本。

user_timeline函数返回一个 tweet 对象。从 Twitter 的文档中我们可以看到每个 tweet 对象都有一个很长的属性列表,包括我们上面使用的文本属性。

我们可以编写一个函数来提取我们感兴趣的属性,并创建一个数据帧:

现在我们有进展了。在我们的数据框架中有了一些感兴趣的属性后,我们可以继续进行分析。

Twitter 数据的一些流行用途包括主题建模和情感分析。

更有趣的事情,也许是一个现实世界的应用,可能是试图预测特朗普一周会发布多少条推文。

Predictit.com market for Donald Trump tweets

结论

虽然这是数据挖掘的一个很好的开始,但我们仅仅触及了表面。Twitter 的 API 有更多我们可以探索的方法,更不用说互联网的其他部分了!

期待看到你挖出什么有趣的数据!

我第一次在工业界使用自然语言处理(NLP)

原文:https://towardsdatascience.com/my-first-usage-of-natural-language-processing-nlp-in-industry-c20842b37cad?source=collection_archive---------12-----------------------

人们经常听说 NLP 有多棒,但是对于很多人来说,很难看到它是如何应用于商业环境的。带着这个目的,我想我会分享我第一次尝试使用 NLP 来解决一个商业问题。

Photo by Jason Leung on Unsplash

商业问题

发布新产品对企业来说可能是一个令人担忧的时期,产品的成功和公司的形象依赖于产品的广告表现。其中一个最大的影响是产品的可靠性,它需要像客户期望的那样工作。为此,监控投诉和退货非常重要。对于汽车或大型已安装设备,更有可能的情况是工程师会被派去维修,而不是产品被退回进行更换。

然后,质量工程师可以处理和阅读这些工程师报告,以便对是否存在真正的故障以及故障类型进行分类。然后,可以对这些结果进行汇编,以生成故障的帕累托图,甚至开始在其他可能的可靠性统计数据中构建可靠性浴盆曲线。

值得花点时间来解释帕累托曲线和浴缸曲线,让你对可靠性工程有个粗略的了解。

帕累托图

您收到了大量关于产品不同类型故障的报告,您如何确定哪些故障需要优先解决?一个有用的工具是制作一个帕累托图,这是一个图表,显示了每种故障类型的故障数量,并结合了一个组合百分比,这样你就可以看到每种故障占总数的多少和百分比。下面我举了一个例子。

Example of a Pareto chart of failures

如你所见,Pareto 非常清楚地表明“轴承”是最常见的故障类型,占所见故障的 60%以上。因此,这将是调查和解决降低总失败率的主要候选方法,在观察期间内用于制定帕累托图。

但这只是特定时间段的快照。通常,主要的故障类型会随着产品寿命而改变,包括制造缺陷(冷焊点、断线等)。)发生在产品寿命早期和接近寿命末期的故障往往由运动部件磨损(如轴承、金属疲劳等)所主导。).

为了考察产品寿命期间的总体可靠性,绘制浴盆曲线是有用的。

可靠性浴盆曲线

设备中的故障通常有三种不同类型:

  • “早期寿命”——如果这些故障会发生,它们会在设备使用的早期出现,并且随着时间的推移可能性会降低。例如制造缺陷(如冷焊点)或安装错误。故障率随着时间的推移而降低。
  • “有效寿命”——这些故障可能发生在产品寿命的任何时间点。无论一个产品设计得多好,总有一些会不可避免地随机失败。故障率始终保持不变。
  • “磨损寿命”——随着设备年龄的增长,这些故障的可能性也会增加。这类故障的一个例子通常与磨损的运动部件有关,如轴承或电机。故障率随着时间的推移而增加。

当这三者加在一起时,得到的故障率图看起来有点像浴缸,示例如下所示:

An example Bathtub Curve showing how three different failure types to give bathtub shape

值得一提的是,浴缸的形状是一个广义的形状,不同的产品往往看起来不同。

最明显的极端是计算机电子产品,它往往表现出尖锐的早期寿命和非常长的使用寿命,磨损几乎可以忽略不计。这是因为一旦避免了任何制造或组装缺陷,部件的大部分固态使它们具有非常可靠的工作寿命。

另一个极端是电动马达系统,它的寿命很早,使用寿命很短或可以忽略不计,磨损更明显。这意味着它看起来更像“V”形而不是浴缸形。

为什么这些很重要?

了解产品的浴缸曲线可以让你做出重要的商业决策。例如,如果您知道您的产品的大多数故障都发生在产品生命周期的早期阶段,那么它的可靠性非常好,您可以做一些叫做“老化”的事情。这是设备运行一段时间的地方,直到它们通过包装和销售之前的早期生命阶段。这意味着客户获得了更可靠的产品,保修成本也降低了,但代价是设备总寿命的损失。事实上,这种做法在电子领域经常发生,在这种领域,故障对最终用户来说是昂贵的,并且是购买设备时的一个主要关注点。

相反地,例如,如果你有一辆由于同步带磨损故障的汽车,你可以预测更换同步带的最佳里程数,这样你就不会过早地更换同步带,扔掉还有很长寿命的产品。这与过晚更换皮带的成本相平衡,因为过晚更换皮带会导致故障和发动机损坏维修次数过多。

这里的关键点是,组成产品的不同组件通常会表现出不同类型的故障率。通过准确地记录失败的类型和来源,企业可以首先利用他们的资源瞄准最大的改进领域。他们还可以设计最佳的维护和保修期,最大限度地降低企业成本,并增强购买者的信心。

Photo by Franki Chamaki on Unsplash

NLP 在这里如何变得相关?

在我们快速进入可靠性工程领域后,我们知道准确了解什么产品出现故障非常重要,以便准确了解设备的行为以及它们是否按预期运行(如果您需要能够检测到可能需要安全召回的问题,这一点非常重要)。

此信息的主要来源之一是服务工程师报告。他们会记下他们正在修理的设备的年代,并徒手输入完成的工作。这些以及被替换的零件将被交给质量工程师进行编译,并要求他们阅读工程师报告文本(其中可能充满缩写、拼写错误,内容长度可能从冗长到突兀),解释问题是什么,然后分配正确的故障标签(或复杂故障中的标签),以便可以正确地用于构建帕累托图和浴缸图。

查看这些报告很快会成为一个巨大的时间池,因为大量的客户群会生成大量的报告,涵盖制造商可能生产的几十种产品。这通常意味着必须对最重要的报告进行优先排序,以便首先处理,留下大量根本不使用的报告,或者在报告出现后需要很长时间才能处理的报告。

有没有一种方法可以减轻质量工程师解释报告的负担,既降低完成这项任务的成本,又增加可靠性统计可用的信息量?答案是使用自然语言处理(NLP)。

Photo by Markus Spiske on Unsplash

NLP 如何增加可用数据

业务问题现在被定义为有太多的服务工程师报告(内容长度和质量不一)需要阅读和分类。这是一个 NLP 实际上完美设计的问题。

通过收集质量工程师之前处理过的大量带有专业标签的报告,我们现在已经为每份报告分配了故障标签。该数据可用于训练机器学习模型,该模型可被馈送来自报告的文本,并给出服务工程师正在描述的故障的预测。这开启了巨大的新功能,因为这意味着可以密切监控更多的产品,因为预先标记的报告可以交给质量工程师进行抽查,并验证机器学习算法仍然很好地完成工作。这还可能意味着,那些根本没有足够资源来处理的大量积压报告现在可以自动处理、使用和完成,而不必大幅度扩大质量和可靠性部门来执行。这是令人兴奋的东西!

模型的基本过程

仅仅将原始文本注入机器学习模型并期望获得很好的结果通常不是一个好主意。通常需要大量的清洁和处理。这些通常概括为:

  • 拼写检查
  • (可选)行业缩写转换
  • 删除停用词
  • 删除标点符号
  • 词干化或词汇化
  • 符号化和转换成数字

为了提供帮助,我将提供一段示例文本:

变压器上的 WI 导致线路上的 fure。障碍已排除,线路已修复,保险丝已复位。

注意:这些步骤并不总是适用于所有基于文本的问题,事实上可能会使问题变得更难(例如,你试图预测一个丢失的单词),但对于我们的问题,我们试图获取文本的几个句子,并让算法将其总结为一个失败标签。对于这种问题,这些步骤是可以接受的,并提高了所得模型的准确性,最大限度地减少了对异常值或特定工程师(例如,总是有相同错别字的工程师)的过度拟合。

拼写检查

如果你曾经读过你的医生的处方笺,它们是仓促而潦草的,并且经常充满拼写错误。服务工程师也是如此,他们的年终业绩是根据修复日常故障设备的情况来判断的,而不是根据撰写伟大的文献来判断的。这意味着这些报告是在离开客户站点之前完成的最后一件事,并且完成得很快,以便他们可以重新上路。这很有可能会出现拼写错误。

因为我们的机器学习算法不知道英语,如果它看到单词“fire”和“fure”,它会将它们视为单独的单词(但人类会知道这是一个打字错误)。获得太多这样的拼写,你会在文本中失去算法可以使用的信号,并且它还会开始过度适应那些很少发生的独特拼写错误的边缘情况(这是我们不希望的)。因此,必须通过拼写检查来运行文本,以帮助纠正这些问题,因为我们希望人类阅读的文本同样被我们的算法摄取。

在这一点上,纠正行业可能使用的任何缩写也可能是有用的(例如,WI 表示野生动物影响)。你会发现,人们有时会使用缩写,有时会使用完整的单词,所以将文本合并成一种形式(全部是缩写或全部是完整的措辞)在这里很有用,可以最大限度地提高算法训练的信号。

该报告现在写道:

“野生动物对变压器的影响导致线路着火。障碍物已移除,线路已修复,保险丝已重置。”

删除停止字

英语中充满了单词,这些单词虽然有助于创造可读的句子,但提供的信息却很少。在这种应用中,这些是像“a”、“the”等这样的词。这将来自我们的包装(见下文),作为高度使用的词,但在试图获得故障分类时几乎没有什么意义。

确实存在停用词列表,但有时需要调整,因为并非所有停用词在不同的应用中都是停用词。最终的结果是句子现在读作:

“野生动物冲击变压器导致火线。障碍物已移除,线路已修复,保险丝已重置。”

注意:虽然对我们人类来说阅读起来越来越难,但我们正试图将报告提炼为传达算法学习信息的关键词。

删除标点符号

作为人类,标点符号有助于我们阅读,但对于算法来说,它只会被它混淆,因为它会将不同大写的单词(“世界”和“世界”对它来说是不同的)和标点符号视为关键部分。所有的单词都用小写字母表示,并且去掉了标点符号。

“野生动物冲击变压器导致火线阻塞,移除线路,修复保险丝重置”

注意:删除标点符号和停用词都将减少机器学习算法必须接受的输入大小,从而减少它需要处理来训练、预测等的数据量。当您开始使用大量文本数据来构建模型时,这些都是非常好的好处。

词干或引理满足

在英语中,单词可以以不同的形式书写,但仍然具有相同的意思。比如“结果”、“结果”、“结果”。所有这些我们可以解释为意思相同,但对于我们的算法来说,它会将它们视为不同的单词,并且必须了解这三个东西的意思相同。我们可以通过选择词汇化或词干化来使生活变得更容易。

词条满足试图将单词返回到词典术语或“词条”(如果是动词、名词等,则由指示确切形式。),但是使用的一种更常见和更简单的方法是词干法。

词干处理的目的是以一种基于规则和系统的方式砍掉单词的结尾,这样同一个单词的不同形式都返回到一个共同的基本形式(不一定是你将看到的那种形式),最常见的算法是、【雪球】和【波特】

我们将一个雪球词干分析器应用于我们的句子,并得到最终的句子:

“wildlif 冲击变压器导致火线阻塞移除线路维修保险丝重置”

你会注意到,我们保留了单词“transformer ”,因为它是一个在公用事业(它是一件设备)中具有特定含义的单词,我们希望算法将它识别为一个不同于“transform”或“transforming”的单词。这就是获得特定领域的经验非常有用的地方,因此可以确定这样的决定来帮助保存文本中的宝贵信息,否则您可能会意外破坏这些信息。

符号化和转换为数字(单词包)

现在,我们已经为报告中的文本建立了一个清晰和标准化的格式,我们现在需要将其转换为机器学习算法可以解释的形式。我们通过将句子分解成【记号】(或分词)来做到这一点,以便这些可以被转换成算法可以摄取的格式。为此,我们用空格将单词分开,然后统计特定单词在报告中出现的次数。这给了我们一个单词袋模型,它忽略了语法和词序,但保留了单词数。这会产生一个表格,其中每行是每个报告中文本的结果,每列代表报告中出现的唯一单词之一。

这是为训练数据集中的每个报告完成的,当发现新的唯一单词时,添加新的列。

正是这个结果表可以输入到模型中对其进行训练,为了进行预测,只需对数据进行类似的格式化,并将该报告的行输入到模型中。

对于我们的报告示例,单词包表如下所示:

Example of Bag-of-words

注意:单词袋模型是以算法可以接收的形式表示文本的更简单的方法之一,但也存在其他类型,如“术语频率-逆文档频率”( TF_IDF ),它根据单词相对于所有文档对特定文档类型的重要性来加权数量计数。这意味着,如果单词“line”被频繁使用,它的权重会大大降低,而“wildlif”不会被降低,因为它只出现在野生动物引发的故障报告中,而不会出现在其余的报告中。

训练模型

我们现在可以使用我们已经处理成单词袋模型的带标签的服务工程师报告来训练我们的模型。常用的经典算法有朴素贝叶斯的支持向量机( SVM )。然后,可以将训练好的模型用于剩余的已标记报告,以验证其工作正常(抑制测试集),并且被认为非常好,因此用于未标记服务工程师报告的大型存储库

结果呢?

Photo by bruce mars on Unsplash

成功!人们发现,即使这种非常简单的文本处理也会产生非常显著的结果,所得到的模型对于包含足够多关键字的报告来说非常好。甚至可以通过重新标记一些训练集,然后重新训练模型,将一个类别分成三个类别。这为企业节省了大量时间,同时也允许将大量数据汇集到更准确的业务决策中。然后,质量工程师可以重新专注于其他更重要的任务,只是对标签进行抽查,以验证模型仍在充分执行其任务。

可以说,商业案例得到了满足,人们对可能发生的事情印象深刻。下一步是调整模型,使其预先标记所有报告,以帮助仍在手工处理报告的质量工程师(这在更多的业务和安全关键领域中进行)。

摘要

只有使用最经典的 NLP 方法,企业才能够释放巨大的数据存储库,并减轻现有资源的负担,使其他任务(NLP 无法解决)得以完成。

我成为了一名自由职业的数据科学家

原文:https://towardsdatascience.com/my-freelancing-experience-on-upwork-after-two-months-5b7e10b0477a?source=collection_archive---------3-----------------------

Photo by Goran Ivos on Unsplash

2019 年初,我开始从事一些数据相关项目的自由职业工作,目的是(a)加强我的数据科学技能,( b)看看除了日常工作外,我还能赚多少额外收入。整个过程耗时约 2 个月,从 2019 年 1 月到 2019 年 3 月。我想和你分享我的自由职业经历,以及两个月后我最终赚了多少钱。

平台选择

我选择 Upwork 作为自由职业平台,这是最大和最有信誉的在线自由职业平台。在这个平台上有大量的机会,它提供了成功交付项目所需的所有工具,例如公共档案、与客户的实时聊天、安全功能、时间表、分析,以及最重要的管理资金和所得税的工具。

设置个人资料

由于完美主义😅,在开始竞标项目之前,我花了一些时间建立了一个全面的平台简介。这是展示我的真实性、专业性和技能的好方法。概要文件通常由以下部分组成:

  • 传记:这里你可以对自己做一个简单的介绍。如果你已经完成了平台上的项目,工作和收入统计也将显示在这一部分。

  • 作品集:这是你展示自己项目的地方。更吸引人的是,你可以上传情节或截图,并为每个项目添加细节,以便更好地说明。作为一名自由职业的数据科学家,展示数据可视化的作品肯定会有所帮助。我的投资组合中的一个项目如下所示:

  • 技能:描述我专长的关键词。

使用连接发送提议

在我建立了令人惊叹的个人资料后,我准备好开始竞标世界各地的项目。如果你持有免费会员账户,Upwork 每月会给你 60 次“连接”。你发出的每一个提议/出价都需要 2 次“连接”。所以,我每个月有 30 次免费投标的机会,这对于我来说已经足够了。此外,我后来发现,来自回访客户的项目成了我工作量的稳定来源,这不需要任何连接,因为我们已经连接上了。

获得我的第一个项目

Upwork 上的项目数量惊人,尤其是与技术相关的项目。作为一名自由职业的数据科学家,我的默认过滤器是“数据科学和分析”下的每个类别。

在发出 10 多份建议后,我在 2019 年 1 月 21 日完成了我的第一个项目,从公共工作板上收集数据。在与客户讨论了项目的细节、确定了可交付成果并接受了最终合同后,我在周末花了几个小时成功地完成了工作。交货 3 天后我拿到了工资。我工作的速度和质量给我的客户留下了深刻的印象。工作完成后,客户给了我一个五星的好评,如下所示。

A 5-star Review from my First Client

作为跟进,同一个客户又给了我几个任务来继续工作,如果你通过高质量的作品来展示你的价值,这在自由职业者的世界里是非常常见的。通过这个项目,我不仅将我的知识和技能货币化,还通过额外的研究学到了新技术。这坚实的第一步成就了我的一周😆。

两个月总收入

我在业余时间做了大约两个月的自由职业项目。这是一次很好的学习经历,但我应该说,平衡自由职业者的工作和日常工作对我来说真的真的很难。我主要在周末工作,由于更重要的家庭事务,我不得不跳过它(那时我已经结婚,有一个 3 岁的孩子和一个新生儿)。如果你真的想在不放弃主要收入来源的情况下把它作为第二收入来源,你应该做好充分准备,可能需要降低期望值。事后看来,我总共交付了 14 个项目,总收入为 760 美元。如下所示,早期项目之间的时间间隔比后期项目要紧得多,因为几周后我就跟不上早期的进度了。

这些项目可以简单地细分如下:

  • 数据抓取:10 个项目共 510 美元,每个项目 51 美元。每个项目平均需要 2 到 3 个小时。
  • 数据科学教学:3 个项目共 215 美元,也就是每个项目 70 美元。每个项目平均耗时约 1 小时。
  • 数据工程:1 个项目共 35 美元,也就是每个项目 35 美元左右。那个单个项目用了不到 1 个小时。

数据抓取对平台有很大的需求。难怪成了我的大源类型。对我来说,教书的时薪最高。我认为这符合人们的期望,因为一小时的教学或辅导需要事先做一些额外的准备。

结论&最终想法

作为一名自由职业的数据科学家,这真的是一次非常棒的经历!到今天为止,我已经离开自由职业 4 个月了。即使我没有订婚,来自个人的项目邀请也不断地冲击着我的收件箱,不幸的是,我没有时间为此而工作。如果你还没有做数据科学家,我强烈建议你尝试一下自由职业,这不仅是为了赚取一些额外收入,也是加强你的数据科学技能的一种方式。没有什么比做真正的项目更好的了!

我的朋友给了我他们的 Tinder 数据…

原文:https://towardsdatascience.com/my-friends-gave-me-their-tinder-data-7fcd2621c140?source=collection_archive---------2-----------------------

那是 2018 年 10 月 3 日星期三,我坐在联大数据科学课程的后排。我的导师刚刚提到,每个学生必须为数据科学项目提出两个想法,其中一个我必须在课程结束时向全班展示。我的大脑一片空白,这是一种被给予如此自由支配选择几乎任何东西的感觉。接下来的几天,我集中精力想出一个好的/有趣的项目。我为一个投资经理工作,所以我的第一个想法是去做一些与投资经理相关的事情,但后来我想到我每天花 9 个多小时在工作上,所以我不想我神圣的空闲时间也被工作相关的事情占用。

几天后,我在我的 WhatsApp 群组聊天中收到了以下消息:

这引发了一个想法。如果我可以利用在课程中学到的数据科学和机器学习技能来增加 Tinder 上任何特定对话“成功”的可能性,会怎么样?于是,我的项目思路就形成了。下一步?告诉我女朋友…

Tinder 自己公布的一些 Tinder 事实:

  • 该应用拥有约 5000 万用户,其中 1000 万人每天都在使用该应用
  • 自 2012 年以来,Tinder 上已有超过 200 亿场比赛
  • 该应用每天总共发生 16 亿次刷卡
  • 普通用户每天花 35 分钟在这个应用上
  • 由于这款应用,每周约有 150 万次约会

问题 1:获取数据

但是我如何得到数据来分析呢?出于显而易见的原因,用户的 Tinder 对话和比赛历史等。被安全地编码,因此除了用户之外没有人能看到它们。在谷歌搜索了一下之后,我看到了这篇文章:

[## 我向 Tinder 要了我的数据。它寄给我 800 页我最深最黑暗的秘密

约会应用比我更了解我,但这些大量的隐私信息只是冰山一角。什么…

www.theguardian.com](https://www.theguardian.com/technology/2017/sep/26/tinder-personal-data-dating-app-messages-hacked-sold)

这让我意识到,作为《信息自由法案》的一部分,Tinder 现在被迫建立一项服务,你可以从他们那里请求你自己的数据。提示,“下载数据”按钮:

点击之后,你必须等待 2-3 个工作日,Tinder 才会给你发送一个下载数据文件的链接。我急切地等待着这封邮件,在我现在的关系之前,我已经是 Tinder 的狂热用户大约一年半了。我不知道我会有什么感觉,回头浏览这么多最终(或最终没有)失败的对话。

感觉过了一段时间后,电子邮件来了。数据(谢天谢地)是 JSON 格式的,所以快速下载并上传到 python 和 bosh,就可以访问我的整个网上约会历史。

数据

数据文件分为 7 个不同的部分:

其中,只有两个对我真正有趣/有用:

  • 信息
  • 使用

进一步分析,“使用”文件包含关于“应用程序打开”、“匹配”、“收到的消息”、“发送的消息”、“向右滑动”和“向左滑动”的数据,而“消息文件”包含用户发送的所有消息,带有时间/日期戳,以及消息接收人的 ID。我敢肯定你可以想象,这导致一些相当有趣的阅读…

问题 2:获取更多数据

没错,我有自己的 Tinder 数据,但是为了让我得到的任何结果在统计上不完全无足轻重/严重偏颇,我需要得到其他人的数据。但是我该怎么做呢…

暗示一笔不小的乞讨金额。

奇迹般地,我设法说服了我的 8 个朋友给我他们的数据。他们从经验丰富的用户到偶尔“无聊时使用”的用户,这给了我一个合理的用户类型的横截面。最大的成功?我女朋友也给了我她的数据。

另一件棘手的事情是定义“成功”。我决定要么从另一方获得一个号码,要么两个用户去约会。然后,通过提问和分析,我将每一次对话分为成功或失败。

问题 3:现在怎么办?

是的,我已经得到了更多的数据,但是现在呢?数据科学课程侧重于 Python 中的数据科学和机器学习,因此将它导入 Python(我使用了 anaconda/Jupyter 笔记本)并清理它似乎是合乎逻辑的下一步。与任何一位数据科学家交谈,他们都会告诉你,清理数据是 a)他们工作中最乏味的部分,b)占据他们 80%时间的部分。清理是枯燥的,但对于从数据中提取有意义的结果也是至关重要的。

我创建了一个文件夹,将所有 9 个数据文件放入其中,然后编写一个小脚本循环遍历这些文件,将它们导入到环境中,并将每个 JSON 文件添加到一个字典中,关键字是每个人的名字。我还将“用法”数据和消息数据分成两个独立的字典,以便更容易对每个数据集分别进行分析。

问题 4:不同的邮件地址导致不同的数据集

当你注册 Tinder 时,绝大多数人使用他们的脸书账户登录,但更谨慎的人只使用他们的电子邮件地址。唉,我的数据集中有一个这样的人,这意味着我为他们准备了两套文件。这有点痛苦,但总的来说并不太难处理。

将数据导入字典后,我遍历 JSON 文件,将每个相关数据点提取到 pandas 数据帧中,如下所示:

Usage Data with names removed

Message Data with names removed

在有人担心在上面的数据框架中包含 id 之前,Tinder 发表了这篇文章,指出除非你与用户匹配,否则不可能查找用户:

https://www . help . Tinder . com/HC/en-us/articles/115003359366-Can-I-search-for-a-specific-person-on-Tinder-

既然数据的格式很好,我设法生成了一些高级汇总统计数据。数据集包含:

  • 2 女孩
  • 7 伙计们
  • 9 参与者
  • 502 一条消息对话
  • 1330 独特的对话
  • 6344 个匹配
  • 收到 6750 条消息
  • 发送了 8755 条消息
  • 34233app 打开
  • 94027右刷卡
  • 403149左刷卡

太好了,我有大量的数据,但我还没有真正花时间去思考最终产品会是什么样子。最后,我决定最终产品将是一份如何提高网上约会成功率的建议清单。

因此,有了格式良好的数据,探索就可以开始了!

探险

我开始查看“使用”数据,一次一个人,纯粹是出于好奇。为此,我绘制了一些图表,从简单的汇总指标图开始,如下所示:

到更复杂的衍生指标图,如名副其实的“忠诚度图”,如下所示:

第一个图表是相当自明的,但第二个可能需要一些解释。实际上,每一行/水平线代表一个唯一的会话,每行的开始日期是会话中发送的第一条消息的日期,结束日期是会话中发送的最后一条消息的日期。这个计划的想法是试图了解人们如何使用该应用程序同时给多个人发送消息。

虽然有趣,但我真的没有看到任何明显的趋势或模式,我可以进一步询问,所以我转向聚合“使用”数据。我最初开始查看按用户划分的各种指标,试图确定任何高级趋势:

但是没有什么立即引起注意。

然后,我决定更深入地研究消息数据,如前所述,这些数据带有一个方便的时间戳。按照一周中的每一天和一天中的每一个小时来合计邮件数量后,我意识到我偶然发现了我的第一个推荐。

第一个推荐:

周日晚上 9 点是“打火”的最佳时间,下面显示的是我的样本中发送邮件量最大的时间/日期。

在这里,我用发送的消息量来代表每次在线用户的数量,所以这次的“Tindering”将确保你拥有最大的受众。

然后,我开始从单词和字母的角度来看信息的长度,以及每次对话的信息数量。最初,你可以在下面看到没有太多突出的东西……(这里“成功”是红色的)

但是一旦你开始挖掘,有几个明显的趋势:

  • 较长的信息更有可能获得成功(在一定程度上)
  • 发现“成功”的平均对话消息数为 27 条,中位数为 21 条。

这些观察导致我的第第二和第第三个建议

第二个推荐:

花更多的时间来构建你的信息,看在上帝的份上,不要用短信……一般来说,越长的单词越好。这里需要注意的是,数据包含了链接,这些链接被算作长单词,所以这可能会扭曲结果。

第三个推荐:

当试图得到一个数字时,不要太匆忙。“嘿,你好,你的号码是多少”就你的机会而言,这可能是你能说的最糟糕的话。同样的,不要放太久。你的第 20 到第 30 条信息是最好的。

Average message count of successful vs un-successful conversations

在广泛研究了单词/信息/对话的长度之后,我决定研究情绪。但是我完全不知道该怎么做。在这个过程中,我们已经涉及了一些自然语言处理(单词包,一个热编码,所有需要的预处理等)。以及各种分类算法),但没有涉及情感。我花了一些时间研究这个话题,发现nltk sensitivity . Vader sentimentintensitiyanalyzer会是一个很好的口号。

这通过给用户四个分数来实现,基于输入文本的百分比:

  • 积极的
  • 中立的
  • 否定的;消极的;负面的;负的
  • 三者的结合

幸运的是,它还处理诸如单词上下文、俚语甚至表情符号之类的东西。当我查看情感时,没有做任何预处理(小写,删除标点符号等)。)以便不移除任何隐藏的上下文。

我通过将每个完整的对话输入分析器来开始这一分析,但很快意识到这并不真正有效,因为在最初的几条消息后,对话情绪很快倾向于 1,我很难相信 100 条消息的对话在整个时间中都是 100%有信心的。

然后,我将这些对话分解成组成它们的信息,一次输入一条,将分数平均到对话水平。在我看来,这产生了一个更加现实的结果:

将这些数据分为“成功”或“不成功”,我很快发现了一个模式:

这个球座提升了我的第四个推荐。

第四个推荐:

要积极,但不要太积极。

成功对话的平均情绪是 0.31,而不成功对话的平均情绪是 0.20。话虽如此,过于积极几乎和过于消极一样糟糕。

我探索的最后一个问题是关于第一条信息的各种细节对对话成功的影响。对可能产生影响的事情的最初想法是:

  • 长度
  • 是否使用了名称
  • 感情
  • 表情符号的存在
  • 明确的内容

正如所料,第一条信息越长,对话继续“成功”的可能性就越大。作为延伸,你不仅仅使用一个单词开头,例如不仅仅说“嘿”、“嗨”或“daayyuumm”(真实的例子),你成功的概率会加倍。

更令人惊讶的是,在第一条消息中使用一个名字对“成功率”几乎没有影响。

第一条信息情绪结果是“成功的”对话比“不成功的”对话高大约 0.09,这并不令人惊讶……如果你在第一条信息中侮辱某人,直觉上他们不太可能回复。

分析表情符号是一项我没有真正想过的任务,可能会很棘手。幸运的是,有一个名为“表情符号”的包,它可以自动识别文本中的表情符号。不幸的是,令我沮丧的是,在第一条信息中使用表情符号似乎增加了一个人获得“成功”的可能性。

现在到显式内容** …另一个可能相当棘手的问题,因为没有内置的库可以使用脏话等。(据我所知)。幸运的是我偶然发现了这个:**

我可以向你保证,里面有一些绝对的饼干。

然后,我查看哪些第一条消息包含这个列表中的单词,其中 40 条包含。像往常一样,我发现了一些有趣的边缘案例:

仅供参考,这是一个家伙在谈论他的划船紧身裤…

结果?事实证明,包含明确内容的第一条消息没有一条会导致“成功”

这让我想到了我的第五个也是最后一个建议。

第五个推荐:

发送第一条消息时:

  • 积极
  • 8 个单词是最佳的
  • 使用一两个表情符号
  • 不要太露骨

所以总结一下

  1. 在周日晚上 9 点使用 Tinder 可以获得最多的观众
  2. 花时间构建信息,不要使用短信
  3. 准备在第 20 条和第 30 条信息之间询问一个数字或日期
  4. 要积极,但不要太积极
  5. 发送除了“嘿”之外的其他信息作为第一条信息,目标是大约 8 个单词,也许使用表情符号,不要太露骨

数据的几个陷阱:

  1. 我的数据集是一个非常非常小的样本,这使得大部分见解变得毫无用处
  2. 该数据集偏向于我所知道的那类人,也偏向于男性
  3. 数据集只包含对话的一方
  4. 由于用户卸载和重新安装应用程序,消息和使用统计数据不一定一致
  5. 由于人们说话方式的讽刺/变化,没有一种自然语言处理技术是完美的

对未来工作的几点想法:

  • 收集更多数据
  • 做更多的工作来确定具有统计意义的结果和观察结果
  • 根据话题进行对话分析——什么类型的信息构成了好的和坏的情绪
  • 试着调查讽刺
  • 调查其他应用程序(Bumble、Hinge 等)。)
  • 如果有更多的数据的话,可以进行一些分类分析,因为我们只有大约 70 次成功
  • 如果包含更多的数据,请更多地研究性别差异

来自数据的一些有趣的仿真陈述:

  • 单人单日最多刷卡次数:8096 次
  • 男人更有可能在发送第二条信息之前离开很长时间(大约 7 天)
  • 在第一条信息中提问实际上会降低你成功的几率
  • 女性平均有 1%的时间向右滑动,而男性大约有 50%的时间向右滑动
  • 每打开一个应用,女性刷卡次数是男性的 3 倍

延伸阅读:

  • 一篇名为“Tinder 用户活动初步观察”的论文发表了
  • 有一个 Tinder API ,但不幸的是,它只针对使用该应用的人,而不是提供某种数据库的访问权限。无论如何,用它来测试某些假设会很有趣。
  • Tinderbox 是一款软件,可以通过降维来了解你被谁吸引。如果你真的想自动化这个过程,它还有一个内置的聊天机器人…

感谢您的阅读,对未来工作的任何想法都将不胜感激!

我的手是人工智能

原文:https://towardsdatascience.com/my-hand-is-pretty-cool-48373b5dc37a?source=collection_archive---------26-----------------------

这也是一手相当酷的牌。

看看这个:

My hand!

是我的手。很漂亮的手,不是吗?

现在看看后面:

Don’t be fooled, it’s the same hand, it’s just that it’s been turned around.

很酷吧。

这是一个非常简单的工具:它由五个手指组成,其中一个是拇指。然而,这是一个非常有用的工具。我可以用它做各种事情!

我可以用手弹吉他。

我可以用手拿着一杯啤酒。

我能用我的手写文章。

My hand pretending to write a note.

我能用手烹饪食物。

我能用手开车。

我可以用手玩电子游戏。

My hand picking the best stage in Super Smash Bros.

只要由我的大脑提供动力,我的手就可以用来做各种各样的事情。因此,我的手是一个通用算法的例子,或者,正如行话 biz 中的人们喜欢称之为“通用 AI”。

Told you my hand was cool.

“人工智能”这个术语有无数种定义。对人工智能进行分类的许多方法之一是通过术语“通用人工智能”和“模块化人工智能”。通用人工智能是一种能够执行非常广泛的任务的工具,而模块化人工智能是为一个非常特定的目的而制造的。例如,你可能在好莱坞电影中看到的大多数人工智能都是一般人工智能的例子:无论是终结者中的人工智能还是 I 中的机器人,机器人。他们通常看起来或行动起来像人类,并且能够做人类能够做的大多数事情,通常更强、更好、更快。**

好吧。所以艾将军还是挺利索的。

我们应该把它放在电脑里。

My hand, inside of a computer. Tricked ya! It’s not actually inside of the computer, it’s just a photo of my hand displayed on a computer screen.

没人知道怎么做。

How do we get Jacob’s cool hand inside of a computer?

关于艾将军的书不计其数。许多演讲者、许多播客和许多出版物已经讨论并继续讨论这种形式的人工智能,以及它不仅对企业,而且对整个社会的影响,然而人造的通用人工智能实际上并不存在。

嗯。

那我的手是怎么创造出来的?

进化>我的手>人类算法

我的手,顺便说一下,还有我的其余部分,是由进化创造的。你可能以前没想过,进化其实就是一种算法。它是世界上运行时间最长的已知算法,并且运行在最强大的系统上:我们的星球。就像软件在电脑上运行,我的手在大脑上运行一样,进化在地球上运行。

进化论也是机器学习(AI 的一个子类)的五个主要流派之一,其他四个分别是符号主义者(逻辑学家)、连接主义者(神经科学家)、贝叶斯主义者(统计学家)和类比主义者(相似性理论家)。

我们已经知道如何模仿进化。例如,我们可以将进化论应用于经典视频游戏《超级马里奥兄弟》。在这款游戏中,玩家控制着马里奥,试图尽可能地靠近屏幕右侧,克服途中的各种障碍。如果你要训练一个人工智能尽可能有效地击败超级马里奥兄弟,进化论将是一个可以采用的完美算法。产生 100 个不同的马里欧,每个都有一些不同的变量(统计),看看谁能做到最右边。获胜者可以再生育 100 个 Mario——第二代——每一个都继承了获胜者略微改变的 DNA,直到你创造出完美的 Mario。在计算机中使用进化的另一个更实际的例子是垃圾邮件过滤器的创建。许多垃圾邮件过滤器使用基于进化论的算法,其中表示垃圾邮件的单词被配对以产生子术语。

AI learning to play Super Mario Bros. The current generation is listed in the upper left corner. Made by SethBling, reported through Max Plenke.

不管怎样,回到超级马里奥兄弟的例子,我们创造的完美马里奥仍然是模块化人工智能的一个例子。他唯一擅长的就是玩超级马里奥兄弟,他唯一的技能就是能够从左往右走而不被障碍物绊倒。

然而,至少在理论上,进化可以被用来创造一种通用算法,就像机器学习的其他四个学派一样。但是它非常复杂。这需要大量的训练,以及明确定义的程序和流程。更重要的是:它需要一个实际的商业案例。**

我手里的公文包

人工智能是个时髦词。它可能意味着任何事情。但是当你看到今天存在的声称使用“人工智能技术”的实际应用时,他们总是使用某种形式的模块化人工智能。它们是为一个非常特殊的目的而建造的。这就像一只专门为弹钢琴而造的手。

不仅仅是一般的 AI 很难建立,而且也很难证明它的商业价值。在创建人工智能解决方案时,通常最好先制作滑板,然后是踏板车,接下来是自行车,然后是摩托车,然后是汽车,而不是直接制作复杂汽车的各种组件。同样,创造一只擅长做一件事的手有更强的商业理由。您可以看到更清晰的投资回报,并且在销售解决方案时,您有更强的说服力。客户不想要一个庞大的、全面的、难以消化的解决方案,他们想要一个解决他们眼前具体问题的方案。

One of the reasons why my hand hasn’t been put in a computer, is that the business case for hands made for a specific purpose simply has a stronger business case than a hand that can do everything. Photo by Helloquence.

然而,许多伟大的思想家和工程师正在讨论和构建与我的手非常相似的通用人工智能。一些人认为通用算法会非常复杂,可能会有数百万行代码。其他人则持相反的观点,认为通用算法实际上只需要几百行代码。

我的手就是一个很好的例子。如果数据模型和数据足够强大,强大的算法可能会变得异常简单。

就像我冰凉的手。

Wait… You guys have hands too? Photo by William White.

对人工智能感兴趣?这里还有一些你可能会喜欢的文章。

* [## 谁是终结者?

Deepfakes 将成为人类的巨大威胁,AI 创造 deepfakes 和 AI 检测 deepfakes 的竞赛…

medium.com](https://medium.com/swlh/who-is-the-terminator-c5135890651b) [## 人工智能如何让你成为总统

对于那些想要获得更高权力的政治家来说,理解人为的…

towardsdatascience.com](/how-ai-can-make-you-the-president-4756f6b1c0c0)*

我从商业到数据科学的旅程

原文:https://towardsdatascience.com/my-journey-from-commerce-to-data-science-c2932d09f6da?source=collection_archive---------5-----------------------

Image from Pexels

尽管我确信我不会喜欢会计或商业讲师的工作,但我在 2016 年完成了商业硕士学位。完成学业后,我参加了我们州政府机构 KSUM 为期一年的奖学金( TIFP )。

我不知道该选择什么职业,也不知道该朝哪个方向走。我记得我在学士学位的时候学过一些编码,我对学习编码有兴趣。然后我决定试一试。

我开始向代码学院学习。为了找一份前端 web 开发人员的工作,我尝试了 HTML、CSS 和 Javascript。但是没有成功。我找不到任何学习 web 开发的渴望。那时,我开始了解数据科学,这让我印象深刻。尤其是我喜欢编码和统计的混合。这是数据科学最初的驱动因素。

在这篇文章中,我将分享我在过去 9 个月中使用的资源和遵循的方法,以完全相同的顺序开始学习数据科学。

1.Udacity 贝塔斯曼数据科学挑战课程。

在合适的时候,我知道了贝塔斯曼数据科学挑战奖学金。我被选中参加这个项目,并从那里开始了我的数据科学之旅。第一阶段是充满挑战的课程。我必须在 3 个月的期限前完成课程。第一阶段的前 10%的学生获得了 Udacity 的三个纳米学位课程(数据基础、商业分析师、数据分析师)中的任何一个。

在本课程中,我学习了用于描述数据、探索数据、使用统计研究方法、计算简单概率、可视化数据的基本概念,以及 python 和 SQL 的基础知识。我学习了推理统计学,这是挑战课程的选修部分。描述统计学导论推断统计学导论是 Udacity 的免费课程。我们得到了 SQL 和 Python 的额外材料。

课程开始于 2018 年 5 月,我在 6 月下旬加入了 1 个月。我在两个月内完成了课程,但我无法进入第二阶段。但是完成挑战课程给我的学习方式带来了很多改变。其中之一是我开始定期学习至少 8-10 个小时。

学习贝塔斯曼数据科学挑战赛课程给我的感觉足以让我朝着自己的梦想前进。

我最喜欢这门课程的是来自 Udacity 的专家、社区经理和同行的巨大支持。

2.Udemy 的 Python 3

当我寻找到达目的地的替代方法时,我完成了 Udemy 的“Python 3 课程:从初级到高级”。开始时很有趣,后来开始变得令人困惑。课程开始时的 Python 基础知识很有帮助。

3.数据营

就我个人而言,我喜欢数据营。不管你以前是否有任何编码经验。Datacamp 是计划学习数据科学的最佳在线平台之一。

首先,我报名参加了 Python track 的 Data Analyst。当时我没有信心能够理解机器学习的概念和算法。我认为理解这些对我来说将是一项艰巨的任务,因为我来自非计算机科学背景。我最初决定学习数据分析,我认为在获得一份数据分析师的工作后,我可以开始学习机器学习。

DataCamp 中有 7 个职业轨迹。

  1. Python 程序员
  2. 使用 Python 的数据分析师
  3. 使用 Python 的数据科学家
  4. r 程序员
  5. R 的数据分析师
  6. R 的数据科学家
  7. 定量分析师

我用 Python 完成了 Data analyst,然后是 r。在完成每条赛道后,我做了 DataCamp 项目库中的一些项目。

我喜欢 Datacamp 的什么地方

  • 如果没有经验,这是开始的最佳平台。
  • 每个职业轨道中结构合理/设计良好的内容
  • Datacamp 提供的足够从零英雄。你可以从非常基本的概念开始,学习复杂的机器学习算法,并开始解决现实世界的问题。
  • Datacamp 有很好的项目集合。学完之后,如果你对如何从头到尾解决一个现实世界的问题感到困惑,项目部分会给你实践经验。
  • 在每个视频内容之后,您可以在 DataCamp 编码环境中练习您所学的内容。您将逐步了解如何处理给定的数据集。如果你在练习中遇到困难,你可以检查“提示”选项来完成任务,或者你也可以检查答案。

4.卡格尔

获得基本的分析和编程知识以及课程证书是不够的。做真实世界的项目有助于增加我们的知识,并在数据科学领域开始职业生涯。我选择 Kaggle 去寻找数据集来做我自己的项目。

当然,我们可以从 DataCamp 做项目。他们会告诉你如何?但是没有人会一直指导你如何处理数据或者如何转换数据等等。这就是为什么我决定做 DataCamp 之外的项目。我对 2016 自由代码营新编码器调查数据做了探索性的数据分析。然后参加了 2018 Kaggle ML & DS 调查挑战赛

当我读到 NFL 平底船分析比赛时,我决定继续努力。我没有在这次比赛中提交我的内核,但是我花了一些时间玩数据,学习 NFL,并试图找到解决方案。在我迈向数据科学的旅程中,这是一次很棒的经历。

5.Coursera- IBM 数据科学认证

我在考虑更高级的数据科学课程。我从 Coursera ,IBM数据科学专业约翰霍普金斯大学找到了两门课程。我决定从 IBM 的课程开始。这个项目由 9 门课程组成,最后包括一个顶点项目。我们可以免费使用这个项目 7 天。由于我没有足够的存款来支付,我想如果我能在免费试用结束前完成这个项目会更好。
当我浏览课程详情的时候,我意识到,不了解机器学习,我是无法用 7 天时间完成课程的。为了解决这个问题,我使用 DataCamp 的 R 和 Python 完成了数据科学课程,然后报名参加了 IBM 数据科学认证项目。我在免费试用期内完成了课程。

从多个平台学习帮助我更好地理清概念。

我还没说完。我口袋里有一张长长的“待办事项”清单。

我就是这样开始我的数据科学之旅的。我学到了很多,还有很长的路要走…

爬网站时我旅途中最好和最糟糕的时刻

原文:https://towardsdatascience.com/my-journey-of-crawling-website-bd3294322e3c?source=collection_archive---------10-----------------------

一个成为数据科学家的个人分享

如何看待抓取或抓取网站?

许多人可能会将这项技能视为一种自动化工具,或者仅仅是一项通常被人们视为低端技能的技能。

对我来说,你可以把它看作一场战争,只是这场战争发生在互联网上。特别是当你在一个特定的网站上进行例行的网络爬行时,也许最初几次你能够获胜,你会庆祝地狱耶这个网站很容易刮,但你还没有意识到另一方面,也有人可以跟踪你的机器人的可疑活动,然后试图阻止你的机器人爬上网站。

很多时候,人们可能会忽略检索良好数据源的重要性,而是更加重视如何建立一个更准确的机器学习模型。有一个构建机器学习模型的首字母缩略词,叫 GIGO,是“垃圾进,垃圾出”的缩写。因此,重要的是要认识到,如果您能够检索到良好的数据源,再加上您已经具备出色的 EDA 和建模技能,您将能够构建更好的机器学习模型。

回到正题,我要和大家分享一下,我从抓取到抓取网站的历程。给你们一些我的背景,我毕业于新加坡南洋理工大学,拥有数学和经济学学位,不是来自技术背景,学习技术技能通常更难,但如果你努力工作,最终你会擅长它。

自动化刮削初体验

它始于我在南洋理工大学统计研究所的一份兼职工作,当我还在大学学习时,我必须去每个网站,复制并粘贴每个页面到 excel 文件。基本上,我被要求从这个网站获取所有与世界排名和各大学分数相关的信息。

兼职之后,眼睛总是感觉很累。这就是我开始刮网站的原因。没什么特别的,我只是用 Python 库 Request 抓取网站,用 BeautifulSoup 解析 HTML 内容。

结果很好,我对此非常感激。刮刀不仅可以保护我疲劳的眼睛,还可以提高我的工作效率。第一次做抓取,我发现用这两个 Python 包来抓取网站真的很容易。

如果你对这个刮刀感兴趣,可以访问我的 github repo 了解更多信息。

数据科学项目的抓取经验

机器学习是我的兴趣。自从我在电通宙斯盾网络全球数据创新中心第一次实习以来,它就激发了我的兴趣。如果有机会见证数字营销中涉及机器学习的项目,我真的对它的力量印象深刻。所以,未来要成为一名数据科学家,我告诉自己要多做一些涉及机器学习的项目。

我决定做一个基于某些因素的租金价格预测的项目,例如,捷运和出租单元之间的距离,房间的大小,单元中浴室的数量等等。所以,我决定爬上房地产大师网站,这是在新加坡寻找出租单位的最受欢迎的网站之一。

这个网站是一个动态网站,需要我建立一个互动的机器人,因此我选择 Python 包 Selenium 和 BeautifulSoup 来抓取网站。起初,我认为我似乎能够建立一个刮刀,并很容易地检索数据,但该网站实现了完全自动化的公共图灵测试,以区分计算机和人类(验证码)。

我意识到爬行并不容易。它涉及到对特定网站的深入了解,以便您能够检索数据。在花了很大的努力去理解被网站屏蔽的可能原因后,我想出了一个模仿人类行为的方法,最终它非常有效。

长话短说,然后我能够应用机器学习模型进行预测,在应用 EDA 创建多个功能后,结果似乎很好。如果我不能为我的机器学习模型获得准确和干净的数据,这将是不可能的。

工作中爬行的经验

毕业后,我在 Shopee 开始了我的第一份工作,担任商业智能职位。我负责每天搜集大约 12 万件商品,用于竞争对手的分析。这是我爬行技能真正大幅提高的地方。我的机器人又一次被验证码屏蔽了,这就是为什么我学习了一个新的 Python 爬行包,Scrapy。这绝对是一个伟大的爬行包。关于 Scrapy 和 Selenium 包的比较详情,请随时访问本网站:https://hackernoon.com/scrapy-or-selenium-c3efa9df2c06

是的,我设法解决了这个问题,但这次我认为我学到了更多的东西,列举如下:

  1. 维护过去数据的数据库,以便用于分析。
  2. 建立一个仪表板来监控几个爬虫的性能,这样当问题发生时我就能尽快修改代码。
  3. 关于如何绕过反抓取措施,或者创建更高效的爬虫的技巧,更多信息可以访问本网站:https://towards data science . com/https-towards data science-com-5-tips-to-create-a-more-reliable-we B- crawler-3 efb 6878 F8 db
  4. 检索敏感数据的技术,这可能需要您使用 POST 方法。

最终想法

我目前是一名数据科学家,我可以通知你的是,爬行仍然非常重要。我真的希望这篇文章能帮助和启发你解决一些在网页抓取中遇到困难的问题。

感谢你阅读这篇文章。欢迎在下面留下你感兴趣的话题的评论。我将在未来发布更多关于我的经历和项目的帖子。

关于作者

低伟鸿是 Shopee 的数据科学家。他的经验更多地涉及抓取网站,创建数据管道,以及实施机器学习模型来解决业务问题。

他提供爬行服务,能够为你提供你所需要的准确和干净的数据。你可以访问 这个网站 查看他的作品集,也可以联系他获取抓取服务。

你可以在 LinkedInMedium 上和他联系。

我的性能分析之旅 2/2 (HAR 文件)

原文:https://towardsdatascience.com/my-journey-to-performance-analysis-2-2-har-files-8a94a52bfac9?source=collection_archive---------19-----------------------

这篇文章主要是解释我最近进行的第二种类型的性能分析。它是这篇文章的后续。
这篇文章主要介绍了 HAR 文件的分析,以及您可以从中检索到什么类型的 KPI。

什么是 HAR 文件?

继 W3C github 帖子之后,HAR 代表 HTTP 存档格式。它是一种 JSON 格式的归档文件格式,用于记录 web 浏览器与站点的交互。这些文件的通用扩展名是。har

这看起来很有趣,但是它实际上涵盖了什么呢?它涵盖了相当多的指标和信息,这种格式仍在开发中。因此,它可以在未来发展,我的列表将不会是详尽的和/或涵盖信息已被否决从 HAR 文件。

全局对象:

  • 创建者:关于创建此 HAR 文件的应用程序的信息
  • 浏览器:包含有关创建日志的浏览器的信息
  • 日志:这是最有趣的元素,因为它包含以下信息:
  • 条目:条目是由页面触发的请求
  • 页面:正在请求哪个页面

你现在可能会这样想:“这开始看起来像非常有趣的信息了!为什么你一开始就要费心使用你那愚蠢的性能爬虫呢?我浪费了 1000 万的生命去读那篇文章!”

好吧,这很公平 that 文件检索的问题是,它不像我们用 performance . getentries()JavaScript 控制台检索信息那样容易。

如何检索 HAR 文件分析

你可以阅读这篇来自 box.com 的关于 HAR 一代的好文章。
如果您想通过使用爬虫程序来生成相同类型的信息,您将需要使用中间人技术来生成这些文件。

这在 2015-2016 年不会是一件大事,但现在所有网站都在使用 HTTPS,你需要为你的浏览器生成一个证书,这样你的中间人就有权捕捉和解密这些信息。

正如您现在所能想象的,以自动化的方式实现这一点并不是那么简单。
虽然不是不可能,但是如果我设法实现(这是我的计划),仅仅使用我已经创建的模块将需要一些对其他用户不友好的配置。
让我们推迟这个模块的创建,在浏览器中使用传统的检索方式。;)

条目对象

我之前解释过,嵌套在日志对象中的条目数组是我们真正感兴趣的,以便实现性能审查。
条目对象中最有趣的信息如下(完整列表此处):

  • startedDateTime :
    请求开始的日期和时间戳(—YYYY-MM-DDThh:MM:ss . stzd)
  • time:请求的总运行时间,以毫秒为单位。这是计时对象中所有可用计时的总和(即不包括-1 值)
  • 计时(对象)
  • 阻塞:在队列中等待网络连接的时间。如果计时不适用于当前请求,请使用-1。
  • dns : DNS 解析时间。解析主机名所需的时间。如果计时不适用于当前请求,请使用-1。
  • 连接:创建 TCP 连接所需的时间。如果计时不适用于当前请求,请使用-1。
  • send:向服务器发送 HTTP 请求所需的时间。
  • 等待:等待服务器的响应。
  • 接收:从服务器(或缓存)读取整个响应所需的时间。
  • SSL:SSL/TLS 协商所需的时间。如果定义了该字段,则时间也包括在连接字段中(以确保向后兼容 HAR 1.1)。如果计时不适用于当前请求,请使用-1。
  • 请求(对象)
  • 方法 : 请求方法(GET,POST,…)。
  • url:请求的绝对 URL(不包括片段)。
  • cookie:cookie 对象列表。
  • queryString:查询字符串列表
  • postData:帖子中包含的数据信息
  • header size:
    从 HTTP 请求消息的开头到正文前的双 CRLF(包括双)的总字节数。如果信息不可用,则设置为-1。
  • bodySize :
    请求体(POST 数据有效负载)的大小,以字节为单位。如果信息不可用,则设置为-1。
  • 响应(对象)
  • 状态:200 / 404 / 302/ …
  • cookie:cookie 对象列表
  • header size:
    从 HTTP 响应消息的开始直到(包括)正文前的双 CRLF 的总字节数。如果信息不可用,则设置为-1。
  • bodySize :
    接收到的响应正文的大小,以字节为单位。在响应来自高速缓存的情况下设置为零(304)。如果信息不可用,则设置为-1。
  • cache (object):关于缓存的信息。我建议在检索元素时禁用缓存,因为您想知道页面上请求的所有元素。您可以稍后优化缓存。

你会告诉我有很多信息需要消化,你是对的,因为这只有一页。想象一下,您必须分析几十页或几百页的内容…
对于专业人员,有一些工具可以帮助您分析这些文件,并以简化的方式汇总这些数据。

在我们的案例中,有两个主要问题:

  1. 我们无法使用那些工具
  2. 我们不是专业人士:)

第二个评论是半个笑话,因为我们是专业人士,但我们不太了解那些 HAR 文件(我们不是每天都用,也不是每周都用),我的哲学是,当你想了解一些东西时,你需要尽可能多地了解原始信息。这样做将有助于您稍后理解该工具实际上为您做了什么。
(这个评论对任何你想掌握的学科都是有价值的——有时候你不需要掌握,那么快捷键就有用)

分析快捷方式(哈佩模块)

如前所述,这里有大量的数据,为了缩短这篇文章,我将走一点捷径。
在使用 jupyter 笔记本发现数据后,我为我的分析创建了一个新的模块。这个想法很简单,你在所有 HAR 文件所在的文件夹中运行这个模块,它会生成一个。csv 文件”,其中聚集了一些数据。主要是与性能相关的数据。

这个新模块可以在我的 github 账户上获得,它的名字是“ harpy ”。是的,就像神话中的生物,但也因为它是一个 HAR py thon 分析仪。现在明白了;)
在我的其他脚本文件夹:https://github.com/pitchmuc/other_scripts

我很可能会写一篇博文来解释这些方法。

HAR 数据分析

所以你已经在你的文件夹中运行了 harpy 模块,它已经创建了一个。csv”文件。
我们来看看里面是什么,如何解读数据。

import pandas as pd
df = pd.read_csv('summary_blog.csv',delimiter='\t')
df.head()

这应该会给你这样的东西:

查看该列,我们在这里有一个广泛的列表。我创建的 harpy 模块试图在这个数据帧中收集尽可能多的数据。

df.columns
OUT: 
Index(['page', '2XX', '3XX', '4XX', '5XX', 'average_bodySize',       'average_headersSize', 'average_responseSize', 'average_totalSize',       'blocked', 'connect', 'cookies', 'dns', 'missing_blocked',       'missing_bodySize', 'missing_connect', 'missing_dns',       'missing_headersSize', 'missing_receive', 'missing_responseSize',       'missing_send', 'missing_ssl', 'missing_wait', 'nb_cookies',       'nb_entries', 'receive', 'send', 'ssl', 'total_bodySize',       'total_headersSize', 'total_responseSize', 'total_size', 'total_time',       'wait'],dtype='object')

如果你熟悉网络连接词汇,你应该不会迷失在这里。
这里我们可以从熊猫的概况数据开始。

df.describe()

当您在处理大型数据集时,如果您想浏览一下这里的情况,这种方法非常重要。

正如你所看到的,我们很快发现在我们发送的请求中没有 bodySize。大多数信息都是由报头发送的。平均响应大小是 3094 字节,但标准偏差是 2592。
这意味着每个请求的 responseSize 差异很大。
最小值和第三个四分位值(474 和 3705)证实了这一点。

数据会给你每个页面发送的请求的数量,你只需要查看“nb_entries”列

df[['page','nb_entries']]

添加更多列以直观地查看是否存在相关性。

您也可以直接询问您的两列的关联状态:

df[['nb_entries','total_time']].corr()

Positive correlation but nothing crazy

为了对数列的分布有所了解,你也可以使用箱线图。

df['receive'].plot(kind='box')

我们来看看箱线图上的这个极值点是什么。

df[df['receive'] == df['receive'].max()] ## This returns you the specific row for this.

我希望这篇文章向您展示了在分析页面性能时可以做些什么。

正如您可能已经注意到的,这些数据与我们在使用我在关于性能分析的第一篇博文中描述的爬虫时检索到的数据是不同的。因此,如果你需要更多数据来证实你的假设,这两种方法可以互补。

我的云计算之旅

原文:https://towardsdatascience.com/my-journey-to-the-cloud-c03f8ba429ce?source=collection_archive---------29-----------------------

为什么我是倡导者,你也应该是。

Image credit

两周前,我在新加坡参加了 2019 年谷歌云峰会。谷歌每年都会在其主要市场举办类似的活动,宣布其新产品和路线图。这也是一个机会,让人们认识和了解行业的动向。

我特别喜欢领导人交流会议,在那里谷歌分享了它在该地区的见解。他们还主持了一场精彩的互动会议,而每个团队都扮演了一家正在进行数字化转型的全球银行机构的首席技术官。然后,我们面对不同的场景,在这些场景中,我们做出的每个决定都有相关的成本和收益。

Google Cloud Summit 2019 in Singapore

但是我为什么会在那里?

我的云计算之旅

如果几年前你问我什么是云计算,我可能会给你一个茫然的眼神。现在吗?我可以不停地谈论云计算有多棒,以及为什么你应该使用它(如果你还没有使用的话)。

我是越南一家电子商务公司的分析经理。由于本地计算机的海量数据和物理限制,在本地服务器上进行分析变得越来越困难。我们还缺乏用本地系统处理大数据的能力。另一方面,还有许多其他问题,例如开发工作、许可和访问控制等等。

很自然地,我开始寻找解决数据问题的方法。那时,我们可以选择使用开源软件或公共云提供商。我们选择了后者,因为我们希望专注于数据,而不是基础设施。

但是向一个组织介绍一个新的想法是困难的。你经常会面临来自众多利益相关者的阻力。在我的案例中,具体来说,我必须说服我的老板、我的团队和几个安全团队。你需要考虑的事情数不胜数,比如安全性、人才培养和变革管理。换句话说,你试图改变人们日常工作的方式。

你必须走出自己的路,你必须说服人们,你必须成为…一个倡导者。

我成为了组织中的云倡导者。我开始寻找业内人士,学习新东西,召开会议介绍新概念。我推动了一项在公共云上建立数据湖的计划。我们与谷歌云合作来做这件事,它为我打开了许多大门。通过这个项目,我认识了一些非常有才华的人,学到了新的做事方法,也学到了新的概念和技术技能。除了我的项目,我还帮助我们的其他团队也走上了云之路。

我的经验教训

回顾这段经历,我意识到两件事:

  • 成为云倡导者开拓新机遇:如果我不是云倡导者,我今天就不会站在这里。
  • 掌控自己的工作:如果我认为云计算不是我的责任,而是基础架构团队的责任,我也不会来这里。

那么,成为某个事物的倡导者意味着什么呢?

我们退一步来回答这个问题。快速的谷歌搜索给出了倡导者的如下定义:

公开支持或推荐一项特殊事业或政策的人。

成为某事物的倡导者意味着你竭尽全力去推动一个想法、一项事业或一项政策。从你最喜欢的电子游戏到社会经济改革,你可以成为任何事情的倡导者。

Image source: 16 Personalities illustration of an advocate, I’m an INFJ-A by the way.

你很可能已经是一个拥护者了。还记得上一次你向朋友推荐你最喜欢的书或者你刚刚发现的一个很棒的应用吗?你是倡导者!

成为倡导者的好处

Image credit

这些都不能保证,但如果你是一个倡导者,这里有一些潜在的好处,你可以收获。

  • 帮助建立你的个人品牌:如果你倡导某事,人们会因此认可你。如果我一直谈论和使用苹果产品,当你有问题时,你可能会寻求我的帮助。这有助于建立你在这个问题上的个人品牌和可信度。此外,当你帮助别人时,他们往往会回报你。
  • 助人为乐:当我们为陌生人开门或给需要帮助的人一美元时,我们感觉很好。当你向某人主张某事时,你相信你所推动的事情会使另一方受益。简而言之,你在帮助他们,你会感觉很好。
  • 拓展你的人际网络:很有可能有像你一样的人也支持同样的事情。你有机会向他们学习,帮助他们,扩大你的人际网络。我们是群居动物,建立关系网从来都不是一件坏事。
  • 获得新的机会:你将获得新的机会,比如工作中的晋升,甚至是新的工作机会。你的老板可能会意识到你所追求的东西的好处,给你学习的机会或者派你去参加会议。

如何做一个倡导者?

Image credit

那么,你怎么能成为某件事的倡导者呢,尤其是在工作中?以下是一些我认为会有帮助的步骤:

  • 选择:第一步,选择推什么。不要追求只对自己有利而对别人无益的东西。一定要推动对每个人都有利的事情。选择自己感兴趣的,或者自己擅长的。
  • 相信:第二步,相信它。如果你不相信你正在推动的事情,人们会很快发现。当你在追求中遇到困难时,信念也能帮助你坚持下去。
  • 学习:你试图说服人们为了你和他们自己的利益去做一些新的事情。花时间去了解它,彻底了解这门手艺,这样你才能令人信服。
  • 推动:这是最关键的一步,实际上是推动你的主动权。在你的追求中要深思熟虑,始终如一,坚持不懈。向人们展示这对他们有什么好处,并尽力去做。
  • 坚持不懈:有时候,事情并没有按照计划进行。你的时机可能不对,你似乎无法说服别人,或者你只是运气不好。当面临挑战时,重温第二步。如果你仍然相信你所追求的,那就继续前进。

让我们成为组织中的倡导者

Me and my good friend Joe at Google office in Singapore

在这篇文章中,我简单地分享了我的故事和我学到的经验。我了解到作为一名云倡导者为我打开了无数的机会,我应该对我所做的事情负责。

我还讨论了什么是倡导者和四个潜在的好处:帮助你建立你的个人品牌,通过帮助别人给你带来快乐,扩大你的网络,给你新的机会。

我敦促你在你的组织中成为一名倡导者,并通过选择相信推动、坚持不懈来获得利益!

我从零开始进入数据科学的学习计划

原文:https://towardsdatascience.com/my-learning-plan-for-getting-into-data-science-from-scratch-9562f37b4dde?source=collection_archive---------7-----------------------

我在大学的时候就开始了,并且一直持续到今天!

早在 2015 年初,当我还在上大学时,我就决定进入数据科学领域。实际上,我最初并没有打算成为一名数据科学家,而是一名quant——本质上是一名金融分析师,在他们的职能中使用高级数学和编码(例如风险管理和算法交易);然而,9 个月的 quant 实习让我意识到,我想将这些技能应用到更广泛的背景中。读了几篇博文后,我得出结论,数据科学是适合我的领域。

来自应用经济学的背景,我觉得我的计量经济学繁重的课程已经给了我一个不错的数学基础;然而,我仍然没有机器学习中使用的模型的背景(例如,神经网络、随机森林)。此外,我在大学的剩余时间里浏览了所有课程,没有发现任何教我们如何编写自己的算法的内容。

差距显然在于我缺乏编码和机器学习模型方面的知识。

在这篇博文的其余部分,我将浏览我用来填补这一空白并实现我成为一名数据科学家的梦想的在线资源的简短列表。

我们开始吧!

概念学习

Courses and books will give the foundation of your data science skills

下面是我推荐你学习的书籍和课程,以了解数据科学是如何工作的。请注意,下面的学习资源是按照我推荐的顺序显示的(基于我的经验和其他人的反馈)。星号(*)表示我本人没有参加过该课程,但其他数据科学家强烈建议在现阶段参加该课程。

  1. Python for Everybody Specialization—这一系列课程对于想要入门的绝对初学者来说非常棒。为了让你克服学习如何编码的恐惧,最好的方法。
  2. 吴恩达《机器学习》——这门课给了我理解不同机器学习模型的核心基础。吴恩达激励我从事机器学习的职业。****
  3. 艰难地学习 Python 3—这本书将为你的 Python 技能(以及一般的编码技能)打下坚实的基础。我怎么强调这本书在通过实践课和精心设计的练习来教授基本概念方面有多棒都不为过。
  4. 应用数据科学与 Python 专业化 ***** —这一系列课程是将你对机器学习模型的理解与你的编码技能粘合起来的好方法。我个人认识一些人,他们能够在完成这一专业后立即在数据科学领域找到工作,因为到那时,他们已经拥有了一套体面的数据科学技能工具包,可以用来解决现实世界的问题。
  5. 程序员机器学习入门(fast.ai) —本课程由杰瑞米·霍华德教授,他给出了一个非常实用的关于如何正确使用代码进行机器学习的演练。准备好从头开始学习如何编写随机森林算法吧!
  6. 程序员实用深度学习(fast . ai)——这两部分课程是最好的资源,既适合 1)试图进入深度学习的有抱负的数据科学家,也适合 2)试图更深入地了解如何在深度学习中获得最先进的结果的更有经验的数据科学家。在第一课中,杰瑞米·霍华德将向您展示如何使用 fastai 库在 ImageNet 数据集中获得最先进的精度。在后面的章节中,您将越来越习惯于直接在 PyTorch 上实现模型。强烈推荐!

实践学习

Real world projects will teach you how to turn your skills into actual value for people

有些人会说,真正的学习只有在你从事具体项目并利用你的数据科学技能解决现实世界的问题时才会发生。以下是推荐的通过应用你的知识获得经验的方法(即边做边学)。

  1. code signal——当我刚接触编码时,我很难理解如何用我的基本技能来解决现实世界的问题。谢天谢地,CodeSignal(以前叫 CodeFights)有有趣的编码挑战,让我可以与机器人和真人竞争。这让我对用代码解决问题的过程感到很舒服。该网站最初是一个竞争性编码平台,但现在专注于在与科技公司的面试中为开发人员准备编码考试。****
  2. ka ggle——这是一个数据科学家聚集在一起的平台,1)共享数据和代码,2)竞争训练最能达到目标的 ML 算法(例如,最准确地预测房价)。即使你没有明确地参与竞争,我认为 Kaggle 最大的附加值是从竞争中获得“代码解决方案”。阅读其他更有经验的数据科学家的代码是变得更好的最快方法之一,因为它教你最佳实践,同时让你自己从头开始舒适地阅读和编写 ML 代码。****
  3. 激情项目 —即使你没有数据科学的工作,但想进入这个领域,想一个很酷的项目来执行!确定一个你想解决的问题,甚至是你想做的有趣的事情,然后为此创建一个机器学习模型。如果你决定将它部署为一个可在互联网上访问的应用程序,那就更好了!(例如,我最近开发了一个投资分析工具,让智能交易变得更加容易!).
  4. 实习/全职 —这个应该很明显。边做边学的最好方法是给自己找一份数据科学方面的工作。冷启动问题是当公司希望你拥有数据科学技能,但你没有工作经验,如何获得这些技能?上面列举的所有步骤应该使您具备必要的技能,能够立即对数据科学团队有用。所以开始工作吧!

结论

这就是我如何获得我今天所拥有的技能,我还有很多要学!这是一个漫长而艰难的旅程,但每一项努力都是值得的。每天,我都很荣幸能从事一个既有趣又有影响力的职业。我在这个职业中感到如此快乐,所以我花时间创建了这个指南,以便更多的人可以进入这个领域。

最后,我给你留下以下信息:

你能否成功进入数据科学领域的最大决定因素是你是否愿意 1)吸取教训,2)在挑战中坚持不懈,以及 3)抓住现有的机会。

感谢您阅读本文,如果您对如何进入数据科学领域有任何进一步的问题,请在下面的中发表评论。也可以通过邮件( lorenzo.ampil@gmail.com)、 twitterlinkedin 联系我;然而,期待我更快地回复评论:)

我的机器学习之旅和第一次 Kaggle 比赛

原文:https://towardsdatascience.com/my-machine-learning-journey-and-first-kaggle-competition-fcb57523d614?source=collection_archive---------13-----------------------

我如何开始数据科学和第一次经历。

Image taken from Pexel Gavin Tracy

旅程的开始

答在担任电子工程师后,我对数据科学领域产生了兴趣。我已经开始搜索关于这个领域的 Moocs。以下是我发现对我的旅程有帮助的列表,

所有这些课程都解释了核心的机器学习算法。另外,在 Coursera 的机器学习课程中,Andrew NG 解释了这些算法的数学背景。如果你想了解什么是机器学习以及如何使用它,我强烈建议你参加这三门课程。

由于我已经学习了机器学习的基础知识,我已经开始寻找平台来测试我的知识。这是我第一次见到卡格尔。(https://www.kaggle.com)

Kaggle 中有大量的数据集可以测试你的知识。您可以下载数据,也可以使用 Kaggle 内核来编写和测试您的代码。Kaggle 平台最棒的地方在于,它是完全免费的!

我已经开始做一些 EDA,画一些图,运行一些基本的机器学习算法(线性回归,逻辑回归,随机森林等。).但所有这些工作都成了例行公事,我需要一种动力来继续我的旅程。那是我决定参加比赛的时候。

让游戏开始吧…

我花在 Kaggle 上的所有时间都是在看比赛,但从来不敢申请。

我对比赛有偏见,如果你想参加比赛,你至少应该是 10 分中的 8 分。这是一个荒谬的想法。

我第一次申请参加比赛是偶然的。当我阅读比赛规则时,我只需点击“我同意”按钮,然后嘭,我就参加了比赛。

卡苟时间

我参加的竞赛是微软恶意软件预测(https://www.kaggle.com/c/microsoft-malware-prediction/),是关于预测微软机器被恶意软件感染的概率。

数据部分有训练和测试数据。每个都有将近 5 Gb 的大小。数据列包括机器 id 和关于该机器的许多特性。当然,在训练数据中,最后一列包括机器是否被感染。

在第一次恐慌之后,我开始思考如何解决这个问题。

Kaggle 上的所有比赛都有一个讨论页面,人们谈论解决问题的替代方法。还有一个内核页面,人们可以分享他们的代码来激励其他人。

我已经阅读了每一个讨论主题。这非常有帮助。由于我是这个领域的新手,阅读有经验的人的方法帮助我找到了从哪里开始。

我给所有新手的建议是首先阅读人们的经验,不要犯同样的错误。

然后我开始用 Kaggles 内核编码。这是我第一次面对现实生活中的问题。内核计算机的能力不足以读取列车数据。这个问题已经在讨论页讨论过了,并提供了一些解决方案。但是在加载数据后,由于机器学习算法的原因,我会遇到同样的计算能力问题。所以我决定下载数据,在我的个人电脑上工作。

我加载数据;从讨论页选择最著名的机器学习算法,按运行。我还有第二个现实生活中的问题。我电脑的能量也不足以运行这个算法。由于特征(列)的数量以及观察值(行)的数量是巨大的,因此肯定需要特征工程。此外,在 Kaggle 的数据集中,有许多要素缺少值并不常见。但这是现实生活,在现实生活中总会有缺失的价值观。

我把数据页看得更详细了。尝试减少特征的数量,同时将分类数据和非分类数据分开。并对每个数据集分别进行特征工程。

随着我减少特征的数量,我将数据与机器学习算法相匹配。检查混淆矩阵。 Tadaa!!我有%54(比抛硬币还好是!)测试集的 Roc Auc 分数。是时候在测试集上运行模型以创建提交文件了。

我试着用我第三次真实生活经历的测试数据来运行这个模型。在此之前,我总是使用一个数据集,并将其拆分为模型的训练和测试数据。但是在现实生活中,如果你做一些特征工程(删除特征,创建新特征,改变数据类型等),你需要分别训练和测试数据。)你应该对测试数据做同样的事情。我艰难地学会了这一点。我试图在测试集上运行我的训练模型,在等待 2 小时后出现错误。然后弄清楚我上面说的情况。我忘了对测试数据进行一些特征工程。

这是我第一次解决现实生活中的问题,对我来说非常重要。然后,我尝试改进我的解决方案,并开始玩功能。现在我已经把分数提高到 60 分了,还有些事情要做。

结论

总之,如果你想在数据科学领域工作,永远不要悲观,永远不要气馁。永远保持动力,渴望新信息,阅读高质量的内容。

希望能在我的其他机器学习经历中看到你。此外,如果你对我的旅程有任何建议,请写下对这个故事的回应。

项目的 Github 链接:【https://github.com/】T2volkansahn/微软-恶意软件-预测

如果你想支持我的工作,这是我的联系方式:https://www.patreon.com/volkansahin

我的开源机器学习之旅开始了

原文:https://towardsdatascience.com/my-open-source-machine-learning-journey-begins-615dee3a1654?source=collection_archive---------9-----------------------

我的新博客,人类学习机器学习,于 1 月 1 日发布

在技术和其他许多领域,过去的研究和发展与现在的实际情况之间有着重要的联系。探索这种联系对学习过程至关重要。历史是一位伟大的老师,尤其是因为,因为事情不会发生在真空中,所以将现在与过去联系起来考虑通常是明智的。

还有第二个同样重要的联系,在今天的现实和明天的可能之间有一个指导性的问号,它可以帮助加速学习过程。为了理解和指导你今天做的事情,你也应该问问你明天可能会做什么。

沿着这条学习之路走下去的好处是,你能够将过去的知识与现在的背景以及未来的潜力联系起来。这是我们在个人生活中都会做的一项练习,相当于“我去过哪里,我是如何来到这里的,我有能力完成什么?”在技术领域,如果你试图以尽可能少保留盲点的方式解决问题,这一过程尤为重要:如果你希望将技术应用于持久的解决方案,你需要知识、背景、好奇心和视角。

这让我想到了为什么我决定推出一个机器学习博客。现在,分布式系统和分散式区块链正在市场上认真探索,我想更好地了解的技术领域之一是机器学习。原因是我们应该开始问,在未来,人工智能软件可能如何访问和分析在区块链永恒存储的数据,以产生新的见解和解决方案,解决我们今天或明天可能出现的商业、社会和其他问题。

作为我努力学习数据和分析之间的交集的一部分,我最近开始了一个关于我一无所知的领域的学习之旅:机器学习。我花了一年的时间在区块链领域学习和工作,并花了几个月的时间自己定期学习密码学,我已经对开源学习之旅的力量产生了欣赏:分享你正在学习的东西、思考的问题和提出的问题。这样做,你不仅学得更快,而且还能和其他人分享加速学习过程的成果。

下面,我交叉发布了我的前三篇每日博客文章,分别来自 一台人类学习机器学习 。感谢您加入我的学习之旅。

  1. 2019 年 1 月 1 日: 我的开源机器学习之旅开始
  2. 2019 年 1 月 2 日: 机器学习新人资源
  3. 2019 年 1 月 3 日: 机器在学习处理文本之前,是否应该先学习处理语音?

2019 年 1 月 1 日:我的开源机器学习之旅开始了

(交叉贴自 我的开源机器学习之旅开始 )

今天早些时候,在 LinkedIn 上,我写了以下内容:

2018 年是学习的一年……2019 年将是双重运用的一年,学习和应用:学习更多关于分布式系统和去中心化区块链的知识,学习机器学习,尝试应用程序,将我的心应用到更明确的目标上,学习将越来越强的好奇心应用到我的任务上,并允许我自己充分探索我的直觉。

一年多以前,我开始学习区块链、分布式总账和密码学。一旦您了解了使这些功能协同工作的基础知识,就很容易对信息的未来感到兴奋。在一个越来越依赖于存储、访问、分发和分析来自集中式、分布式和分散式存储的数据的世界里,重要的后续问题变成了“人类将如何使用数据来制造有助于推进我们社会目标的机器?”

这种想法促使我在两周前考虑未来几年我还应该学习什么,包括机器学习本身。我相信技术可以而且应该被用来做好事,我们应该用我们最好的想法为我们最好的理想服务,我忍不住试图理解现代技术表面领域的如此重要的一块,即机器学习、神经网络、人工智能和我们选择的明天的交集。

正如我在今天的 LinkedIn 帖子中所写的:

在这样一个问题重重的时代,我们不能不怀着极大的喜悦和坚定的信念,致力于减少阻碍人类进步的神秘事物。

在这个博客中,我的目标是“开源我在机器学习方面的学习之旅”,以便我现在的同龄人和未来的人们可以看到人类学习一项有朝一日将为人类体验的许多基础提供动力的技术是什么样的。由于我最近开始阅读机器学习,提出问题,思考未知,这个空间将作为日记,博客和游乐场的一部分,在未来建立和分享我的神经网络。人类学习过程的奇妙之处在于,它一部分是神经科学,一部分是魔法,是我们的生物神经元与联系、想法、死胡同、错误、突破、敬畏、好奇、好奇、记忆、问题以及生活和想象的双重选择压力斗争和角力的结果。有一天,在非常遥远的未来,在我死后很久,人类可能会创造出能够欣赏前面那句话中包含的所有快乐的学习机器。在那之前,我和我们对人类思维、计算机、数据以及如何利用这些数据来训练计算机代表我们做出更好的预测还有很多要学的。

在这个大脑的机器学习之旅中,我会发现什么?

2019 年 1 月 2 日:机器学习新手的资源

(跨贴自 机器学习新人资源 )

学习如何学习新东西总是很棘手的。这有点像在你知道你将获得什么样的知识,书架应该有多长或多高,或者你需要哪些工具来搭建书架之前,弄清楚如何搭建一个书架来放置新知识。

我想有时候最好的开始方式就是,嗯,开始。你可以边做边做,如果需要的话,你可以向别人借工具,或者在需要的时候帮忙做架子。你也要确定什么与你的目标无关,或者远远超出你目前的知识范围,现在没有用。这就是非结构化试错游戏——人类版的强化学习。但首先,你必须开始。

划分起点的一种方法是按分段,即按资源的来源或类型:

  • 要读的书
  • 要追随的人
  • 要学的课程

诸如此类。

学习部分

以下是我目前为止遇到的或者有人向我建议的一些机器学习资源。这份清单没有优先次序,也不详尽。这是一个及时的快照,所以我不期望在未来添加到这个列表中。

书籍

课程

长阅读

  • 彼得·阿比尔 —伯克利强化学习研究员
  • Francois Chollet——Keras 神经网络库的发明者
  • 莱克斯·弗里德曼——麻省理工学院研究科学家和人工智能播客主持人
  • 戴密斯·哈萨比斯——人工通用智能研究公司 DeepMind 的联合创始人
  • 安德烈·卡帕西——特斯拉的人工智能总监,专注于自动驾驶感知
  • 费-李非——斯坦福大学教授、计算机视觉专家
  • 吴恩达 —教授,Coursera 联合创始人,&深度学习专家
  • 卡罗尔·雷利——机器人专家,自动驾驶公司 drive.ai 的联合创始人
  • 机器人专家,麻省理工学院著名的 CSAIL 实验室主任

杂谈

  • 你希望解决的问题类别如何影响你对学习模型、机器学习算法和神经网络的选择
  • 某些神经网络计算(如矩阵乘法)的计算费用如何限制您对软件和硬件的选择(即机器学习的 GPU 友好性与 CPU 友好性)
  • 您选择学习的编程语言(例如 C++与 Python 或 JavaScript 或 R)对您以后使用的工具和库的影响
  • 使用哪些数据集来训练您的学习模型
  • 哪些神经网络最适合对某些类型的输入进行预测,例如视频对静态图像对语音对文本
  • 与分布式系统和分散式区块链一样,你想要解决的问题和要采用的解决方案组合之间的匹配

花絮

  • 莱克斯·弗里德曼的播客 人工智能播客 ,以采访上述彼得·阿比勒和马克斯·泰格马特以及许多其他人工智能和人工智能领域的人为特色
  • 生成对抗网络(GANs) 的主题显然是一个热门的研究领域
  • 3Blue1Brown 的视频“但是什么是神经网络呢?”是我见过的关于感知机和神经网络结构目的的最好的视频
  • “深度学习汽车”是 Samuel Artz 的一个视频,它模拟了 2D 赛道上的汽车。在视频的描述中有一个模拟源代码的链接
  • 多伦多计算机硬件公司 Xanadu 正在研究高级人工智能和“光子量子计算”芯片,以实现机器学习的量子应用
  • 对于各种神经网络架构的一些优秀的视觉效果和解释,请参见 AI 研究公司阿西莫夫研究所的文章“神经网络动物园前传:细胞和层”“神经网络动物园”。你也可以阅读安德鲁·奇尔科夫的“神经网络的最完整图表,在向数据科学解释
  • 一些神经网络可以在手机应用程序中运行,并捆绑在一个具有特殊扩展名的文件中(例如,)。mlmodel 用于在 iPhone 或上运行 mlmodel 的应用。tflite 针对 Android 设备上运行 TensorFlow Lite 的应用)。因此,举例来说,iPhone 开发人员可以通过使用苹果的核心 ML 框架、核心 ML API 和 MLModel 类将机器学习模型集成到他们的应用中。关键的一点是,一些神经网络在 iPhone 这样的东西上利用 CPU 的有限资源工作,这很神奇,也许是未来在更低功率的物联网设备上运行的神经网络的垫脚石。
  • 亚马逊 AWS 机器学习目前支持三种类型的机器学习模型,分别是二元分类多类分类回归,每一种都非常适合做不同类型的预测
  • 博弈论复杂性理论多种统计,以及主要统计理论(如贝叶斯)和相关技术(如回归);线性代数和其他学科似乎是人工智能工作的重要层面。这非常有趣,机器学习技术似乎与分散系统(区块链)有共同之处:为了工作,它们必须借鉴经济学、统计学、计算机科学和数学的原理
  • 一些大学不仅提供免费的在线课程,还在机器学习的各个子领域提供付费的证书课程,如麻省理工学院在线的专业教育和斯坦福大学在线的研究生教育
  • 关于 Stata 软件中先验分布似然函数、&、后验概率的简短技术介绍,请参见 Chuck Huber 的视频“贝叶斯统计简介,第 1 部分:基本概念”
  • Megan Beck 和 Barry Libert 撰写的麻省理工学院斯隆管理评论文章“机器学习竞赛实际上是一场数据竞赛”提出了关于独特数据对训练商业应用中使用的机器学习模型的重要性的好问题

工具

工具补充说明

  1. 合作实验室“一个免费的 Jupyter 笔记本环境,不需要任何设置,完全在云中运行”,有很多东西值得喜爱,但特别是附带了杰克·范德普拉斯的书的交互式笔记本版本, Python 数据科学手册:处理数据的基本工具 ,以及谷歌的自定进度网站 机器学习速成班
  2. 谷歌云平台在其谷歌云培训平台中有优秀的自定进度材料,其中包括 Qwiklabs 的实验室和三个数据和机器学习学习课程:一个面向数据分析师,一个面向数据工程,一个面向数据科学家
  3. 关于 PyTorch vs TensorFlow 的一个看法,见“tensor flow 和 PyTorch:哪一个的原力强?“作者雅士瓦丹·贾恩

2019 年 1 月 3 日:机器是否应该先学习处理语音,再学习处理文本?

(跨贴自 机器是否应该先学会处理语音再学会处理文本? )

今天我在 LinkedIn 的一个评论里问了一个问题。本质上,我的问题是,在我们教机器学习模型处理文本之前,先教它们处理语音是否有优势。让我告诉你我的推理。

处理自然语言的工具

亚马逊的 Matt Wood 博士最近写了一篇博客文章,宣布 AWS 机器学习可以被开发人员用来在他们的应用程序中建立自然语言处理模型。这依赖于一项名为 Amazon understand 的服务,顾名思义,它可以分析文本并执行阅读理解相关的任务。该服务通过深度学习模型进行训练,能够检测某些单词,对文本语言进行情感分析,甚至按照某些主题对文本进行分类。Wood 博士的声明是关于 understand 的一项新功能:1)根据特定组织的词典进一步定制服务搜索的能力,以及 2)将文档分类到自定义分类(即类别)的能力。显然,这种类型的搜索和分析并不容易做到,这就是为什么使用像 understand 这样的机器学习服务是有用的。这都属于被称为自然语言处理的应用机器学习范畴。

Wood 的博文让我想起了在 Alpaydin 的文字里看到过的一些东西,机器学习 : 单词袋。单词包是一种技术,用于判断文本是否出现在给定的文档中,然后根据其内容将该文档分类。例如,这是用于垃圾邮件过滤的技术之一。

在 Wood 帖子的前一天,AWS 人工智能的 Nino Bice 写了一篇名为“开始使用亚马逊理解定制实体”的帖子。在其中,Bice 描述了 Entities 数据类型现在如何支持特定于组织的“私有的、定制的实体类型”,这些实体类型映射到对该组织重要的单个单词。可以认为这是让机器学习模型更加适应使用由 intensive 的 API 支持的应用程序的公司(或医疗保健等行业)内部使用的语言。该组织的自定义文本数据训练理解的自然语言处理模型,以便在学习模型已经用客户的数据集训练之后,当客户的模型将来暴露于那些文档或文本时,更好地预测如何对文档或文本进行分类。据推测,单词袋技术是在这个过程中的某个地方使用的。

论视觉和听觉的原始性

在这一点上,指出 Alpaydin 书中的一页(第 103 页,图 4.2)是很有帮助的,它描述了一种叫做层次处理的东西是如何工作的。基本上,如果你将一幅文本图像输入计算机,并希望计算机能够识别图像中包含的单词,它会通过使用训练有素的模型来执行分层处理,首先是检测字母的视觉原语,“如弧线和线段”。Alpaydin 的图 4.2 显示了两条曲线如何形成一个 o ,一条垂直线如何形成一个 l ,等等。在分层处理中,机器将处理构成这些图元的像素,然后将这些图元组合成单个字母进行处理,然后确定给定的单词是否有它已经学会识别的字母组合,最后,识别“更抽象的关系,如“book”和[法语中的对等词]“livre”之间的关系”。令人着迷。

我记得当我还是一个小男孩的时候,我就开始学习如何在大的手稿纸上写字母。那些学校例行程序的目标必须是教我们学习、识别和书写字母表中所有字母的所有视觉原语,这可能会提高我们随后学习、识别和阅读字母表中所有字母的能力(我不记得我们是先学习阅读还是先学习书写)。

然而,我们大多数人在学习读或写之前,会先学习做别的事情:我们学习说话。像信件一样,语音也有自己的基本形式,除了它们是口头的(传输时)和听觉的(接收时)而不是视觉的:

Alpaydin(第 67 页):“就像我们认为每个字符图像都是由不同方向的笔画等基本基元组成一样,一个单词被认为是一系列音素,这些音素是基本的语音。在语音的情况下,输入是时间的;单词按时间顺序由这些音素组成,有些单词比其他单词长

作为人类,我们在掌握字母的视觉原语以及它们如何组合起来形成书面单词之前,就开始掌握语音的音素。这就引出了我的问题。

我们的学习机器是否应该先学会听,再去读(或说)?

由于人类在学习读或写之前就学会了听和说,我想知道在训练文本数据上的自然语言处理模型之前,训练语音数据上的语音学习模型是否会有一些计算或其他优势,特别是对于说和写相同的单词,以便提高效率或准确性。我只是还不太了解这两者是如何工作的,所以无法给出答案。

此外,是否存在与用于文档文本分类的单词袋技术等效的语音识别?这种“口语词汇袋”技术可以与书面文本技术结合使用来提高模型的预测吗?

根据我提出的问题:

…是否有一种方法可以获取通常用于训练文本分类模型的书面单词列表,大声说出单词并记录下来,将语音数据通过语音识别算法来训练语音识别 NLP 模型,然后使用结果来训练 Amazon understand 进行文本分类?我问的原因是,在人类学习中,当我们学习阅读单词时,我们可能会将字母的视觉原语与这些字母的口语版本的语音原语联系起来,我认为这加快了阅读和处理单词的能力,因为我们可以说出它们的口语对应物。因此,我想知道在机器学习中,我们是否还在以类似的方式处理事情,在训练过程中将文本的 NLP 与语音的 NLP 结合起来。

有很多值得探索的地方。

进一步学习

[1] 机器学习 作者 Ethem Alpaydin (2016)

[2] 《深度学习》——维基百科

[3] 亚马逊理解常见问题实体——AWS

【4】【情绪分析】——维基百科

【5】【自然语言处理】——维基百科

[6] “词袋模型”“朴素贝叶斯垃圾邮件过滤”——维基百科

【7】亚马逊领悟医疗——AWS

【8】【音素】——维基百科

直到下次

这就是我的新机器学习博客上的博客# 1-3,一个人类学习机器学习。如果你喜欢你读过的内容,那么在 LinkedIn 上添加我,将我的博客加入书签或者添加到你最喜欢的 RSS / Atom 阅读器,并与他人分享这篇中型文章(或原始链接)。

如果你喜欢我的作品,并想把我列为投稿人,向你的媒体刊物投稿,请告诉我。

最后,如果你是一家初创公司或科技公司,需要一名自由撰稿人来完成你的区块链、机器学习或其他项目,请在 LinkedIn 上给我发消息,在 alexoblockchain@gmail.com 发邮件,或者在这里留言。我目前正在接受客户。

感谢阅读。

我的熊猫小抄

原文:https://towardsdatascience.com/my-pandas-cheat-sheet-b71437ab26f?source=collection_archive---------18-----------------------

给我的数据科学家同事的提前圣诞礼物🎄🎁

My wishes for you.

被困在付费墙后面?点击此处阅读我和朋友的‘礼物’链接

上周我在训练一个神经网络,首先我需要在一个内部连接中合并两个数据帧。经过几次测试。合并(),。concat(),。join() 很快我意识到我需要回到我的备忘单,而不是在我自己思考之前:我在训练神经网络,但我不记得如何正确合并我的数据框架,这怎么可能呢?

是啊,我记性很差。令人高兴的是,1。我知道这是可能的,因为我以前做过,2。我手边有我的熊猫小抄。

今天,作为提前的圣诞礼物,我整理了它,我将与你分享我的笔记本-宝石。它包含了我从开始学习 pandas 开始就收集的样本代码和函数,为我节省了很多关于堆栈溢出的时间。

我们开始之前的一个建议:

您可以为该页面添加书签,或者克隆存储库以方便使用,但是 不要复制粘贴代码。 键入所有你曾经记得的执行任务的正确方式。 输入代码中有一个值。它练习编码肌肉记忆 到最终,代码没有小抄。

If you can’t visualize the notebook complete click here: https://gist.github.com/brendahali/2b8f6f218492a94cb74eea5043d64867

或者从这里的存储库中派生并克隆最新的文档:https://github.com/brendahali/python_cheat_sheets

我应该在我们的备忘单中包含什么命令吗?分享给我我再补充。

继续分享知识,我的朋友和…圣诞快乐!

我的便携式 Ubuntu 18 深度学习设置

原文:https://towardsdatascience.com/my-portable-ubuntu-18-deep-learning-setup-66151fe78da9?source=collection_archive---------18-----------------------

简介

从我去年的早期文章开始,重点是在家里拥有一个 DIY 服务器,这是更新的指南,将更加关注使用游戏笔记本电脑的便携式深度学习。

动机

我希望有一个便携式深度学习硬件,在加载到云或 DIY 服务器之前,我可以随身携带进行实验。

笔记本电脑规格

我的笔记本电脑是宏碁 Predator Helios 300

安装和设置

Ubuntu 18.x 安装 -从官方网站获取最新的 Ubuntu 18.04.1,我得到的是最新的 LTS 版本,而不是 18.10
-到目前为止,在宏碁 Predator Helios 300 上安装没有问题,一切正常,但记得在 BIOS 中禁用安全引导。迄今为止 UEFI 工作正常。
-最后从软件&更新的附加驱动程序下安装 NVIDIA 二进制驱动程序。

MicroK8s (Kubernetes)安装
——只需遵循 microk8s
的官方安装指南——我们可以通过以下命令打开 gpu 和注册表

microk8s.enable gpu dns dashboard registry

gpu 将与笔记本电脑 Nvidia 一起开箱即用,注册表是将在本地运行的 docker 注册表
-请注意,我们只为 kubectl 创建别名,而不是 docker one,因为 docker kubernetes 不能很好地工作,需要在 kubernetes 部署环境中运行
-最后,请参考kubernetes wiki来创建一些样本用户,因为我们需要用户令牌来稍后登录仪表板

Docker 安装
比使用 kubernetes docker
更容易官方使用 Docker-从官方指南
安装 Docker-从官方指南
安装 nvidia-docker2 从官方指南

一旦安装了 microk8s 和 docker,我们就可以重启笔记本电脑并使用 Nvidia prime (NVIDIA X 服务器设置)禁用 GPU

它将重新启动,这将为我们提供一个半 nvidia 加载驱动程序环境,我们可以充分利用 GPU 内存,而 X Windows 不会使用它。如果我们选择 Nvidia SMI 作为属性提供商,我们可以使用一些有趣的工具,如
NVIDIA GPU 统计工具

Noticed close to 0% memory

nvidia-smi 命令也可以工作

nvidia-smi command still work even we disable the driver

Tensorflow + Jupyter(Docker-local) 借助 Docker,我们可以轻松部署 tensor flow+Jupyter 设置

docker run -it — rm — runtime=nvidia -p 8888:8888 tensorflow/tensorflow:latest-gpu-py3

Note down the token to login later

The url will be http://localhost:8888

tensor flow+Jupyter(Kubernetes) 要在 Kubernetes 中运行相同的图像,请执行以下命令

microk8s.kubectl run — generator=run-pod/v1 tensorflow — image=tensorflow/tensorflow:latest-gpu-py3

要获得 dashboard 的 kubernetes 令牌,请查找关键字令牌

kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk ‘{print $1}’)

Retrieve the token to login later

那我们需要跑

kubectrl proxy

使用本地主机 url 显示管理面板

Note IP in the tensorflow pod, this will be use to access the jupyter from browser

Then click on Logs to look for jupyter login token

一旦我们有了 IP 和令牌,我们就可以使用浏览器访问 jupyter。

结论

像 docker 这样的容器技术甚至在 kubernetes 中也提供了很好的工作流,我们可以在本地进行实验,特别是在游戏笔记本电脑/台式机上,然后再部署到云中。我们也不需要担心安装 CUDA 库,只需要在 Ubuntu 上使用官方的 Nvidia 驱动程序。

Example runtime output with docker container that allow close to 100% GPU memory utilization

we could easily monitor the stats from here while running tensorflow

这种设置的唯一缺点是电池寿命!因为我们有半激活的 nvidia 驱动环境。

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

原文: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(yk |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

名称唯一性

原文:https://towardsdatascience.com/names-uniqueness-2a7cbd449447?source=collection_archive---------18-----------------------

你的名字有多独特?

有了像我这样的名字,关于名字的话题就出现了很多。幸运的是,我非常喜欢我的名字和它在美国的独特性。不管魔鬼经济学家怎么说,我愿意相信我名字的独特性对我的生活有所帮助,或者至少让它变得更有趣。

为了量化我的名字有多独特,我发现在我出生的那一年,我是美国一个由 101 个名叫简的男孩组成的俱乐部的成员。简单的说,我的名字在那一年出生的所有男婴中不到 0.005%是很不常见的。到目前为止,我还没有见过其他 100 个难以捉摸的简中的一个。

我从 www.ssa.gov社会安全管理局(SSA)网站的美国婴儿名字数据集中找到了这个数据。虽然他们有一些很好的视图(比如某个时期最受欢迎的名字)来找到上面的统计数据,但我需要下载数据并自己使用它。我把它上传到 Tableau,发现自己发现了许多比自己更有趣的名字和趋势。

数据

在开始可视化之前,确保理解数据是如何生成的总是明智的。在阅读了 SSA 文档并发现数据集故意排除了一些出生数据后,我找到了第二个数据来源。将美国的总出生人数(下面的棕色线)与婴儿名字数据集(下面的灰色线)中的每年出生人数进行比较,我可以想象出有多少数据丢失了。

SSA 的文件解释说,许多 1937 年以前出生的人从未申请过社会保障卡,所以他们的名字不包括在婴儿姓名数据集中。这解释了我们在这个日期之前看到的两条线之间的巨大但正在缩小的差异。(接下来,我们将删除这些不完整的数据。)

Visualization 1: Total Births

近年来,这两条线之间的差异越来越大。文档再次告诉我们,出于匿名的原因,任何在给定年份出现少于 5 次的名字都不会被记录。所以,这个差距实际上告诉我们出生时有非常独特的名字(< 5 次)的数量,并表明最近每年比几十年前有更多非常独特的名字。

这引起了我的好奇心,我决定随着时间的推移深入研究名称唯一性和名称通用性的想法。

名称唯一性

当我们观察任何一年中唯一名字的数量(出现 5 次或更多次)时,我们会发现几十年来有很大的变化。下图显示了 20 世纪 40 年代不到 10000 个唯一名称,到 2000 年代增加了两倍多,达到 30000 个。此外,女婴的名字总是比男婴的名字更多样化。

Visualization 2: Unique Names

穿越时间到 20 世纪 60 年代末,我们开始看到独特名字的数量在加速增长,并持续到新千年的开始。20 世纪 60 年代中期标志着婴儿潮一代的结束和 X 一代的开始,虽然美国历史不是我的强项,但我假设当时的大文化转变(部分原因是越战、非裔美国人民权运动、英国入侵等)。)在我们看到的趋势中扮演了一个因素。

继续我们的时间之旅,我们开始看到这种加速在 2000 年代后期逆转。这一次,一代人的转变与我们在图中看到的趋势并不完全一致。维基百科将千禧一代(又名 Y 代)的终结时间定在 20 世纪 90 年代中期至 21 世纪初。这种转变正好发生在一些唯一名称增长最快的地方。当我们看到下降趋势时,我们已经进入 z 世代了。

宏观下降趋势似乎是由独特的女孩名字的减少所驱动的(因为男孩名字持平/略有下降)。很难说为什么会发生这种逆转,我也没有一个很好的假设来解释为什么会这样。根据我的挖掘,以下假设不太可能是原因。

  • 假设 1:与男婴相比,父母给女婴起的独特名字越来越少。不太可能。当研究数据时,在 2010 年代首次使用(或产生)的新的独特名字的百分比代表了 2010 年代男女所有独特名字的 20%。男孩和女孩之间几乎没有差别,这不太可能导致我们上面看到的只生女孩的趋势。

Visualization 3: Unique name distribution by origin decade

  • 假设 2:女孩非常独特的名字(<每年出生 5 个)比男孩增加得多,从而弥补了我们可以测量的独特女孩名字减少的趋势。不太可能。虽然我们无法确定这一点,因为我们无法获得这些数据,但鉴于我们拥有的数据,我们可以提出强有力的理由。下图显示了用独特性桶着色的十年间的增长情况(51-500 独特性桶中的一个名字在该十年中有 51-500 个同名新生儿)。在最近十年中,所有独特性存储桶都以类似的负速率增长,因此,很可能,我们无法衡量的非常独特的存储桶也将以类似的负速率增长(而不是正速率)。最重要的是,我们可以测量的非常独特的名字的数量(第一桶:< 50 个)是男孩的,而不是女孩的。

Visualization 4: “Uniqueness” growth — note that 2010 is not a full decade

虽然我们仍然没有一个很好的假设来解释为什么女婴名字的独特性在几十年来首次下降,但男婴名字的独特性似乎仍在增加——只是速度比以前小。如果你有另一个假设,请在回答中分享(如果你用这个数据集或其他地方的证据支持它,会加分)。

顺便提一下,上图中 20 世纪 70 年代相当有趣的趋势与我们在可视化 1 中看到的增长趋势一致,并为正在发生的事情增添了色彩。随着所有其他存储桶开始加速增长,代表超过 1 万个出生的名称的唯一性开始下降。名字越独特,成长越大。

名称通用性

虽然这些年来我们通过观察名字的独特性学到了很多,但我们忽略了一些非常重要的东西:出生的分布。

这种分布是很重要的,因为如果没有它,我们就不能确定大多数新生儿是只集中在一小部分独特的名字上,还是均匀分布在所有的名字上。快速猜一下是哪一个。

利用帕累托原则(或更广为人知的 80/20 法则),让我们看看最常见的名字有多少出生。简单地说,80/20 法则认为 80%的结果可以归因于 20%的原因。如果这在名字世界中成立,我们应该会发现,20 世纪 40 年代的大约 200 个名字和 21 世纪初的大约 600 个名字应该占出生人数的大约 80%(见我们在第一部分的学习)。

当计算这些数字时,我们发现 20 世纪 40 年代 20%的独特名字占出生人数的 64 %, 2000 年代占 60%。虽然我们没有达到神话中的 80/20 的比例,但这个理论仍然成立,即名字的一小部分促成了许多出生。下图显示了前 100 个最常见的名字在一段时间内的贡献,但是是按性别划分的。

Visualization 5: Contribution of the top 100 names

我们看到男婴的名字比女婴的名字更常见(在 1947 年的高峰期为 78%到 70%)。根据我们之前的发现,这并不奇怪——男孩的名字不那么独特,普通的名字比女孩的名字更受欢迎。

20 世纪 40 年代末,名字的普通性开始减少。女婴的死亡率非常高,而男婴的死亡率则逐渐下降。到 2010 年,我们看到前 100 个男孩和女孩的名字分别只占 11%和 5%。对于男孩来说,这个比例从排名前 100 名的婴儿中的五分之四下降到十分之一。

Visualization 6: Contribution of the top 5 names

看看 1947 年的顶级名字,23%的男婴被命名为詹姆斯、罗伯特、约翰、威廉或理查德。然而,排名前五的女孩名字(见下文)仅占所有女婴出生的 17%。对于女孩来说,名字的共性下降得如此之快,以至于在 1975 年,排名前五的女孩名字只占 2%,而男孩的这一比例仍然是 10%。

Visualization 7: Top 10 — # births in 1947

随着时间的推移,看看这些名字,我们看到其中许多在 1947 年达到顶峰,即婴儿潮一代的开始。看看琳达!这个名字在不到十年的时间里非常流行,然后迅速急剧下降。虽然琳达的变化是最引人注目的,但这些名字中的许多如今远不如婴儿潮一代受欢迎。

Visualization 8: Names over generations — Want to type in your name? Click here

是什么影响了这些尖峰信号?现在流行什么名字?最近有没有什么旧名死灰复燃?如果你想研究这些问题或想发现自己的趋势,请查看这个 Tableau 仪表盘,在这里你可以用任何你喜欢的名字来重现上述情节——你的名字,你妈妈的名字,甚至你的英雄的名字。

感谢阅读。👶

更新:如果你有兴趣阅读更多关于婴儿名字数据集的有趣趋势,请查看这篇后续报道,在这篇报道中,我用这些数据展示了一个初创企业或商业的衡量框架。

纳米神经元——解释机器如何学习的 7 个简单 JS 函数

原文:https://towardsdatascience.com/nanoneuron-7-simple-js-functions-that-explain-how-machines-learn-d2d647b21497?source=collection_archive---------30-----------------------

7 个简单的 JavaScript 函数,让你感受一下机器是如何“学习”的。

Image by mohamed_hassan on pixabay

TL;速度三角形定位法(dead reckoning)

纳米神经元是神经网络中神经元概念的过度简化版本。纳米神经元被训练成将温度值从摄氏温度转换成华氏温度。

NanoNeuron.js 代码示例包含 7 个简单的 JavaScript 函数(模型预测、成本计算、向前和向后传播、训练),这些函数将让您感受到机器实际上是如何“学习”的。没有第三方库,没有外部数据集和依赖,只有纯粹简单的 JavaScript 函数。

☝🏻这些函数无论如何都不是机器学习的完整指南。很多机器学习的概念在那里被跳过,被过度简化!这种简化的目的是让读者对机器如何学习有一个真正基本的理解和感受,并最终使读者有可能称之为“机器学习魔法”而不是“机器学习数学”🤓。

对于更高级的机器学习示例(在 TensorFlow 和 Python 上实现递归和卷积神经网络),您可以继续🤖 交互式机器学习实验 s 知识库。

纳米神经元会学习什么

你可能在神经网络中听说过神经元。我们下面要实现的纳米神经元有点像它,但简单得多。为了简单起见,我们甚至不打算在纳米神经元上建立网络。我们将独自拥有它,为我们做一些神奇的预测。也就是说,我们将教会这个简单的纳米神经元将温度从摄氏温度转换(预测)为华氏温度。

顺便说一下,把摄氏温度转换成华氏温度的公式是这样的:

但是现在我们的纳米神经元还不知道它…

纳米神经元模型

让我们实现我们的纳米神经元模型函数。它实现了xy之间的基本线性依赖,看起来像y = w * x + b。简单的说我们的纳米神经元就是一个可以在XY坐标中画直线的“小孩”。

变量wb是模型的参数。纳米神经元只知道线性函数的这两个参数。
这些参数是纳米神经元在训练过程中将要“学习”的东西。

纳米神经元唯一能做的就是模仿线性依赖。在其predict()方法中,它接受一些输入x并预测输出y。这里没有魔法。

function **NanoNeuron**(w, b) {
  this.w = w;
  this.b = b;
  this.predict = (x) => {
    return x * this.w + this.b;
  }
}

(…等等… 线性回归 是你吗?) 🧐

摄氏到华氏的转换

以摄氏度为单位的温度值可以使用以下公式转换为华氏温度:f = 1.8 * c + 32,其中c是以摄氏度为单位的温度,f是以华氏温度为单位的计算温度。

function **celsiusToFahrenheit**(c) {
  const w = 1.8;
  const b = 32;
  const f = c * w + b;
  return f;
};

最终,我们希望教会我们纳米神经元模仿这一功能(学习w = 1.8b = 32),而无需事先知道这些参数。

这是摄氏到华氏转换函数的样子:

Celsius to Fahrenheit conversion function

生成数据集

在训练之前,我们需要基于celsiusToFahrenheit()函数生成训练测试数据集。数据集由成对的输入值和正确标记的输出值组成。

在现实生活中,大多数情况下,这些数据是收集的,而不是生成的。例如,我们可能有一组手绘数字图像和一组相应的数字,这些数字解释了每张图片上写的是什么数字。

我们将使用训练样本数据来训练我们的纳米神经元。在我们的纳米神经元成长并能够自己做出决定之前,我们需要用训练样本教会它什么是对的,什么是错的。

我们将使用测试示例来评估我们的纳米神经元在训练期间没有看到的数据上的表现。在这一点上,我们可以看到我们的“孩子”已经长大,可以自己做决定了。

function **generateDataSets**() {
  // xTrain -> [0, 1, 2, ...],
  // yTrain -> [32, 33.8, 35.6, ...]
  const xTrain = [];
  const yTrain = [];
  for (let x = 0; x < 100; x += 1) {
    const y = celsiusToFahrenheit(x);
    xTrain.push(x);
    yTrain.push(y);
  } // xTest -> [0.5, 1.5, 2.5, ...]
  // yTest -> [32.9, 34.7, 36.5, ...]
  const xTest = [];
  const yTest = [];
  // By starting from 0.5 and using the same step of 1 as we have used for training set
  // we make sure that test set has different data comparing to training set.
  for (let x = 0.5; x < 100; x += 1) {
    const y = celsiusToFahrenheit(x);
    xTest.push(x);
    yTest.push(y);
  } return [xTrain, yTrain, xTest, yTest];
}

预测的成本(误差)

我们需要一些指标来显示我们的模型预测与正确值的接近程度。纳米神经元产生的正确输出值yprediction之间的成本(误差)的计算将使用以下公式:

这是两个值的简单区别。数值越接近,差异越小。我们在这里使用2的能力只是为了去掉负数,这样(1 - 2) ^ 2就和(2 - 1) ^ 2一样了。除以2只是为了进一步简化反向传播公式(见下文)。

这种情况下的成本函数非常简单:

function **predictionCost**(y, prediction) {
  return (y - prediction) ** 2 / 2; // i.e. -> 235.6
}

正向传播

进行前向传播意味着对来自xTrainyTrain数据集的所有训练样本进行预测,并计算这些预测的平均成本。

我们只是让我们的纳米神经元说出它在这一点上的意见,只是让他猜一猜如何换算温度。这可能是愚蠢的错误。平均成本将显示我们的模型现在是多么的错误。这个成本值非常有价值,因为通过改变纳米神经元参数wb并再次进行正向传播,我们将能够评估纳米神经元在参数改变后是否变得更聪明。

将使用以下公式计算平均成本:

其中m是训练示例的数量(在我们的例子中是100)。

下面是我们如何用代码实现它:

function **forwardPropagation**(model, xTrain, yTrain) {
  const m = xTrain.length;
  const predictions = [];
  let cost = 0;
  for (let i = 0; i < m; i += 1) {
    const prediction = nanoNeuron.predict(xTrain[i]);
    cost += predictionCost(yTrain[i], prediction);
    predictions.push(prediction);
  }
  // We are interested in average cost.
  cost /= m;
  return [predictions, cost];
}

反向传播

现在,当我们知道纳米神经元的预测有多正确或错误(基于此时的平均成本)时,我们应该做些什么来使预测更精确呢?

反向传播是这个问题的答案。反向传播是评估预测成本和调整纳米神经元参数wb的过程,以便下一次预测更加精确。

这就是机器学习看起来像魔法🧞‍♂️.的地方这里的关键概念是导数,它显示了采取什么步骤来接近成本函数最小值。

记住,找到一个成本函数的最小值是训练过程的最终目标。如果我们会发现wb的值使得我们的平均成本函数很小,这将意味着纳米神经元模型做了非常好和精确的预测。

衍生品是一个独立的大话题,我们不会在本文中讨论。MathIsFun 是一个很好的资源,可以让你对它有一个基本的了解。

关于导数,有一点可以帮助你理解反向传播是如何工作的,那就是导数的含义是函数曲线的切线,它指出了函数最小值的方向。

图片来源: 马蒂斯芬

例如,在上面的图中,你可以看到,如果我们在(x=2, y=4)点,那么斜率告诉我们走leftdown到达函数最小值。还要注意,斜率越大,我们向最小值移动的速度越快。

我们的averageCost函数对参数wb的导数如下所示:

其中m是一些训练例子(在我们的例子中是100)。

你可以在这里 阅读更多关于导数规则以及如何得到复杂函数的导数

function **backwardPropagation**(predictions, xTrain, yTrain) {
  const m = xTrain.length;
  // At the beginning we don't know in which way our parameters 'w' and 'b' need to be changed.
  // Therefore we're setting up the changing steps for each parameters to 0.
  let dW = 0;
  let dB = 0;
  for (let i = 0; i < m; i += 1) {
    dW += (yTrain[i] - predictions[i]) * xTrain[i];
    dB += yTrain[i] - predictions[i];
  }
  // We're interested in average deltas for each params.
  dW /= m;
  dB /= m;
  return [dW, dB];
}

训练模型

现在,我们知道如何评估我们的模型对于所有训练集示例的正确性(正向传播),我们也知道如何对纳米神经元模型的参数wb(反向传播)进行小的调整。但问题是,如果我们只运行一次前向传播和后向传播,我们的模型从训练数据中学习任何规律/趋势是不够的。你可以把它和给孩子上一天小学相比较。他/她应该去学校不是一次,而是日复一日,年复一年地学习一些东西。

因此,我们需要为我们的模型多次重复向前和向后传播。这正是trainModel()功能的作用。它就像是我们纳米神经元模型的“老师”:

  • 它将花一些时间(epochs)在我们还有点愚蠢的纳米神经元模型上,并尝试训练/教授它,
  • 它将使用特定的“书籍”(xTrainyTrain数据集)进行训练,
  • 它将通过使用学习率参数alpha来推动我们的孩子更努力(更快)地学习

说几句学习率alpha。这只是我们在反向传播期间计算的dWdB值的乘数。因此,导数为我们指出了找到成本函数的最小值需要采取的方向(dWdB符号),它还为我们指出了需要多快到达那个方向(dWdB绝对值)。现在,我们需要将这些步长乘以alpha,以使我们的移动更快或更慢。有时,如果我们使用一个大值alpha,我们可能会跳过最小值,永远找不到它。

与老师的类比是,他越是逼迫我们的“纳米孩子”,我们的“纳米孩子”就会学得越快,但是如果老师逼得太紧,“孩子”就会精神崩溃,什么也学不到🤯。

下面是我们如何更新模型的wb参数:

这是我们的培训师职能:

function **trainModel**({model, epochs, alpha, xTrain, yTrain}) {
  // The is the history array of how NanoNeuron learns.
  const costHistory = []; // Let's start counting epochs.
  for (let epoch = 0; epoch < epochs; epoch += 1) {
    // Forward propagation.
    const [predictions, cost] = forwardPropagation(model, xTrain, yTrain);
    costHistory.push(cost); // Backward propagation.
    const [dW, dB] = backwardPropagation(predictions, xTrain, yTrain);
    nanoNeuron.w += alpha * dW;
    nanoNeuron.b += alpha * dB;
  } return costHistory;
}

把所有的碎片放在一起

现在让我们使用上面创建的函数。

让我们创建我们的纳米神经元模型实例。此时,纳米神经元不知道参数wb应该设置什么值。所以我们随机设置wb

const w = Math.random(); // i.e. -> 0.9492
const b = Math.random(); // i.e. -> 0.4570
const nanoNeuron = new NanoNeuron(w, b);

生成训练和测试数据集。

const [xTrain, yTrain, xTest, yTest] = generateDataSets();

让我们在70000时期用小的(0.0005)步骤来训练模型。你可以摆弄这些参数,它们是根据经验定义的。

const epochs = 70000;
const alpha = 0.0005;
const trainingCostHistory = trainModel({model: nanoNeuron, epochs, alpha, xTrain, yTrain});

让我们检查一下成本函数在培训期间是如何变化的。我们期望培训后的费用会比以前低得多。这意味着纳米神经元变得更加聪明。相反的情况也是可能的。

console.log('Cost before the training:', trainingCostHistory[0]); // i.e. -> 4694.3335043
console.log('Cost after the training:', trainingCostHistory[epochs - 1]); // i.e. -> 0.0000024

这就是培训成本在不同时期的变化。在x轴上是纪元编号 x1000。

Training cost change over the epochs

让我们来看看纳米神经元的参数,看看它学到了什么。我们期望纳米神经元参数wb与我们在celsiusToFahrenheit()函数中的参数w = 1.8b = 32相似,因为我们的纳米神经元试图模仿它。

console.log('NanoNeuron parameters:', {w: nanoNeuron.w, b: nanoNeuron.b}); // i.e. -> {w: 1.8, b: 31.99}

评估我们的模型对测试数据集的准确性,看看我们的纳米神经元如何处理新的未知数据预测。对测试集进行预测的成本预计将接近训练成本。这将意味着纳米神经元在已知和未知数据上表现良好。

[testPredictions, testCost] = forwardPropagation(nanoNeuron, xTest, yTest);
console.log('Cost on new testing data:', testCost); // i.e. -> 0.0000023

现在,由于我们看到我们的纳米神经元“孩子”在训练期间在“学校”表现良好,即使对于它没有看到的数据,他也可以正确地将摄氏温度转换为华氏温度,我们可以称之为“智能”,并问他一些问题。这是整个培训过程的最终目标。

const tempInCelsius = 70;
const customPrediction = nanoNeuron.predict(tempInCelsius);
console.log(`NanoNeuron "thinks" that ${tempInCelsius}°C in Fahrenheit is:`, customPrediction); // -> 158.0002
console.log('Correct answer is:', celsiusToFahrenheit(tempInCelsius)); // -> 158

如此接近!和所有人一样,我们的纳米神经元是好的,但并不理想:)

祝你学习愉快!

如何发射纳米神经元

您可以克隆存储库并在本地运行它:

git clone https://github.com/trekhleb/nano-neuron.git
cd nano-neuronnode ./NanoNeuron.js

跳过机器学习概念

为了解释简单,跳过并简化了以下机器学习概念。

列车/测试装置拆分

通常你有一大组数据。根据该集合中示例的数量,您可能希望对训练/测试集按 70/30 的比例进行拆分。在分割之前,应该随机打乱数据集中的数据。如果示例的数量很大(即数百万),那么对于训练/测试数据集,拆分可能以更接近 90/10 或 95/5 的比例发生。

网络带来力量

通常你不会注意到仅仅一个独立神经元的使用。力量就在这类神经元的网络中。网络可以学习更复杂的特性。纳米神经元本身看起来更像简单的线性回归,而不是神经网络。

输入归一化

在训练之前,最好将输入值标准化

矢量化实现

对于网络来说,矢量化(矩阵)计算比for循环要快得多。通常,如果以矢量化形式实现并使用 Numpy Python 库进行计算,前向/后向传播会工作得更快。

成本函数的最小值

我们在这个例子中使用的成本函数过于简化。它应该有对数分量。改变成本函数也将改变其导数,因此反向传播步骤也将使用不同的公式。

激活功能

正常情况下,神经元的输出应该通过激活函数,如 SigmoidReLU 或其他。

更多更新和新文章 在 Twitter 上关注我

美国宇航局小行星分类

原文:https://towardsdatascience.com/nasa-asteroid-classification-6949bda3b1da?source=collection_archive---------17-----------------------

对小行星是否危险进行分类。

Source: https://unsplash.com/

介绍

太空中的一切仍然是个谜。科学家们继续努力在外层空间寻找新的东西。虽然预计会发现很多东西,但让我们看看已经发现了什么。

小行星
是的!!意大利牧师兼天文学家朱塞普·皮亚齐在 1801 年的一次偶然发现,导致了我们今天所称的小行星。朱塞佩发现第一颗名为谷神星的小行星在火星和木星之间运行。从那以后,许多小行星被像美国宇航局这样的太空组织发现和研究。

小行星是小行星,尤其是太阳系内部的小行星。较大的小行星也被称为小行星。存在着数百万颗小行星,并且绝大多数已知的小行星在位于火星和木星轨道之间的中央小行星带内运行,或者与木星共轨运行(木星木马)。

对小行星的研究也至关重要,因为历史事件证明其中一些是危险的。还记得希克苏鲁伯陨石坑吗?—6500 万年前,一颗小行星形成的陨石坑可能毁灭了所有的恐龙。

作为一名数据科学爱好者,我想到了使用机器学习来预测小行星是否危险。在 Kaggle 上搜索,我找到了美国国家航空航天局关于迄今发现的一些小行星的数据集。该数据集包含关于小行星的各种信息,并将每个小行星标记为危险或无害。
你可以在这里 找到数据集

现在让我们看看数据集。

小行星数据集

数据是关于小行星的,由 NEOWS(近地天体网络服务)提供

A glimpse of the dataset

数据集由 4687 个数据实例(行)40 个特征(列)组成。此外,数据集中没有空值。

下面给出了一些特征的描述;

  1. ‘近地天体参考号’:该特征表示分配给小行星的参考号。
  2. ‘名字’:这个特征表示给小行星起的名字。
  3. ‘绝对星等’:这个特征表示小行星的绝对星等。一颗小行星的绝对星等是如果小行星被放置在 1 个天文单位(AU)之外,距离太阳 1 个天文单位,并且相位角为零,观察者将记录的视觉星等
  4. ‘以千米(分钟)为单位的估计直径’:该特征表示以千米(公里)为单位的小行星的估计直径。
  5. ‘以米(分)为单位的估计直径’:这个特征表示以米(米)为单位的小行星的估计直径。
  6. ‘相对速度千米每秒’:这个特征表示小行星的相对速度千米每秒。
  7. ‘相对速度千米每小时’:这个特征表示小行星的相对速度千米每小时。
  8. “轨道天体”:这一特征表示小行星围绕其旋转的行星。
  9. “木星 Tisserand 不变量”:该特征表示小行星的 Tisserand 参数。 Tisserand 的参数(或 Tisserand 的不变量)是由一个相对较小的天体和一个更实质的‘扰动体’的几个轨道要素(半长轴、轨道偏心率、倾角)计算出来的值。它被用来区分不同种类的轨道。
  10. ‘偏心度’:该特征表示小行星轨道的偏心度值。就像太阳系中的许多其他天体一样,小行星形成的领域不是正圆,而是椭圆。标有偏心率的轴是每个轨道离圆形有多远的量度:偏心率数字越小,范围越圆。
  11. ‘半长轴’:该特征表示小行星轨道的半长轴的值。如上所述,小行星的领域是椭圆形而不是圆形。因此,半长轴存在。
  12. “轨道周期”:这个特征表示小行星的轨道周期值。轨道周期是指小行星绕其轨道运行一周所需的时间。
  13. ‘近日点距离’:这个特征表示小行星的近日点距离值。对于绕太阳运行的天体,距离最近的点是近日点。
  14. ‘远日点距离’:该特征表示小行星的远日点距离值。对于绕太阳运行的天体来说,最远点是远日点。
  15. ‘危险’:这个特征表示小行星是否危险。

总之,数据集中的特征不仅包括小行星的几何信息,还包括其路径和速度。

方法

和往常一样,你可以在下面的 Github 资源库 中找到这篇文章的代码。

值得注意的事实是,一般来说,体积较大的小行星比相对较小的小行星更危险。
如果我们考虑在这个数据集中被标记为危险的小行星的平均直径,那么结果是 0.70 公里。相比之下,非危险小行星的平均直径为 0.40 公里。 因此,我们得出结论,数据集支持一般理论。

让我们开始吧。

特征工程

可以看出,数据集中存在几个不必要的特征,这些特征对分类几乎没有贡献。
特征“名称”和“近地天体参考号”表示给予小行星的识别号。这些特征对于机器学习模型是没有用的,因为小行星的名称并没有促成它是危险的事实。此外,这两个特征包含相同的值。
因此,我们可以删除这两个特征。

特征‘接近日期’也是不必要的,因为它给出了小行星接近地球的日期。小行星最接近地球的时间并不能说明小行星是否会对 T21 造成危险。相反,当出现时,它会告诉。因此,我们也将删除此功能。
出于类似的原因,我们也将删除‘轨道确定日期’特征

现在,让我们看看‘轨道体’的特性。它只包含一个值“地球”。因此,也删除这个特征(因为只有一个值的特征对机器学习技术没有贡献)。
此外,特征‘Equinox’只包含一个值‘j 2000’,因此也删除了该特征。

考虑以下特征:

‘以千米(分)为单位的预计直径’,
‘以米(分)为单位的预计直径’,
‘以英里(分)为单位的预计直径’,
‘以英尺(分)为单位的预计直径’,

所有这些特征以不同的单位表示小行星的估计直径,公里=公里,米=米,等等。这是冗余数据的一个很好的例子,因为它是以不同方式表示的相同值。这种冗余应该删除。统计分析的美妙之处在于,它能识别数据集中的这类错误,即使数据科学家会忽略它们。让我们现在不要删除这些特征,而是用统计方法识别它们。

到目前为止,对上述特征的去除是基于直觉的。现在让我们看看统计分析,找出哪些特征是统计相关的。

统计分析

在此之前,我们先来看一下‘危险’特性。值为“真”或“假”,分别编码为 1 和 0。

现在,让我们形成数据集的相关矩阵。

Correlation matrix

因此,相关矩阵表示存在一些彼此相关的特征,这意味着它们可以毫不犹豫地被移除。

回到特征:
‘预计直径,单位为千米(最小)’,‘预计直径,单位为千米(最大)’,
‘预计直径,单位为米(最小)’,
‘预计直径,单位为英里(最小)’,‘预计直径,单位为英里(最大)’,
‘预计直径,单位为英尺(最小)’,‘预计直径,单位为英尺(最大)’

就像上面提到的,相关矩阵很快识别出这个冗余,我们现在可以删除重复的信息了。
我要删除特征;
‘以米(最小)为单位的预计直径’,‘以米(最大)为单位的预计直径’,
‘以英里(最小)为单位的预计直径’,
‘以英尺(最小)为单位的预计直径’,‘以英尺(最大)为单位的预计直径’。

对于这些特征可以给出类似的解释;
‘相对速度公里每秒’,‘相对速度公里每小时’,‘脱靶量’。‘天文’,Dist 小姐。‘阴历’,Dist 小姐。‘公里’,‘距离小姐。(英里)'

除了上面提到的特征,我将保留‘相对速度千米每秒’‘脱靶量’。(天文数字)’。

如果我们查看‘预计直径,单位为千米(最大)’‘预计直径,单位为千米(最小)’,我们可以看到它们之间有很强的相关性。

让我们看看他们的散点图,以便有一个清晰的概念。

散点图显示特征‘预计直径,单位为千米(分)’‘预计直径,单位为千米(最)’完全相关,因为从散点图中可以观察到两者之间的线性关系。
所以建议删除其中一个功能。我将删除‘以千米(最大)为单位的估计直径’特征。

现在让我们看看【危险】特性的变化

计数图描述了不平衡数据集的情况。我们有一个类,在数据条目的数量上领先于另一个类。
83.89%的数据实例被标记为 0(不危险),只有
16.10%被标记为 1(危险)。

这意味着,即使我们有一个预测所有值都为 0(不危险)的破损模型,那么准确率也会是 83.89% 。因此,我们不能仅仅依靠准确性来评估在这个数据集上训练的机器学习分类器。为了清楚地了解用于评估分类模型的不平衡数据和众多指标,请阅读 这篇文章

机器学习模型

数据已经过分析和清理;现在,是时候建立那些机器学习模型了。

让我们将数据集分成一个 80:20 的比例,分别作为训练集和测试集。

训练集(根据 my code 生成)包含 3749 个数据实例,并有 610 个案例标记为 1(危险),这意味着如果一个模型预测所有值为 0,那么准确率将为 83.72% 。这将被视为训练集的基线精度。
类似地,测试集的基线精度(根据我的代码)将是 84.54%
我们的模型应该比这些精度做得更好,或者应该足够健壮以处理类别不平衡。

使用了以下模型:

  • 朴素贝叶斯分类器
  • SVM
  • 决策树
  • LightGBM

结果在表中列出,如下所示:

****

如果你想了解更多关于上面用于模型评估的指标,那么请参考这篇文章 。现在让我们来讨论每种型号。

朴素贝叶斯

如果我们查看朴素贝叶斯的表格,我们会看到测试集和训练集的精度等于基线精度。此外,如果我们查看测试集的特异性、Mathews 相关系数假阳性率,则这些是【nan】,意味着模型被破坏,并且预测所有值为 0(无危险)。这样的模型没有任何意义,因为当一个模型永远无法实现它的目的时,使用它是没有意义的。

让我们也看看混淆矩阵,因为没有混淆矩阵,分类问题似乎是不完整的。

Confusion matrices for Naive Bayes Classifier

混淆矩阵清楚地表明,该模型甚至未能将单个数据实例预测为 1(危险),因此该模型不够稳健

SVM

根据记录,就计算速度而言,SVM(SVC)被证明是最慢的。****

SVC 的结果表非常类似于朴素贝叶斯的结果表。因此,它清楚地表明 SVC 也失败(因为特异性、Mathews 相关系数和假阳性率再次为‘nan’)。
让我们看看 SVC 的混淆矩阵。

Confusion matrices of Test and Train set for SVC

测试集的混淆矩阵显示,SVC 甚至无法将单个值预测为 1(危险)。训练集的混淆矩阵显示只有两个数据实例(3749 个中的)被预测为一个,并且所做的两个预测是正确的。

与朴素贝叶斯分类器相比,这是一个微小的(但可以忽略不计的)改进。但尽管如此,我还是要说,这个模型完全被打破了,没有零实际意义。

如果您是数据科学的新手,那么您可能会想知道如何找到一种方法(或模型)来处理数据不平衡,因为这是一个迫在眉睫的严重问题。

多亏了研究人员,一些分类模型足够强大,可以处理这种不平衡的数据。请考虑以下情况。

决策图表

决策树分类器的结果表证明它是一个非常健壮和几乎完美的模型。测试集的准确率为 99.4% ,非常好,而且 Mathews 相关系数和 F1 得分的值几乎接近 1,表明模型实际上是完美的。

让我们看看决策树的相关矩阵。

Confusion matrices for the test set and train set for Decision Tree

混淆矩阵也描述了这样一个事实,即该模型是稳健的,几乎是完美的。

在测试集中只有六个错误预测的值,而在训练集中没有。

决策树是能够处理类别不平衡数据的健壮模型的一个很好的例子。

决策树可能已经给了我们很好的结果,但是还有比它更健壮、更有效的模型。

集合模型更稳健,因为它们是弱预测器的“集合”。因此,我也将使用 LightGBM。

LightGBM

LightGBM 的结果表显示,该模型几乎是完美的,并给出了很好的结果。测试集的准确率99.3%马修斯相关系数为 0.971,F1 得分为 0.996

让我们看看 LightGBM 的混淆矩阵;

Confusion matrices for Train and Test set for LightGBM

测试集的混淆矩阵显示,只有 7 个(比决策树多 1 个)不正确的预测,而训练集只有一个错误的预测。

结论

在这篇文章中,我们了解了小行星,更重要的是建立了一个几乎完美的分类器来预测小行星是否危险。

为数据集选择的特征是完美的,因为机器学习模型获得的结果非常好。

我希望你喜欢这篇文章,我相信你一定从中有所收获。

如果有任何疑问或建议,请在评论中告诉我。

谢谢你。

自然语言生成第 1 部分:回归基础

原文:https://towardsdatascience.com/natural-language-generation-part-1-back-to-basics-2f0b2654624f?source=collection_archive---------8-----------------------

你有没有遇到过那些脸书或推特上的帖子,显示一个人工智能被“强迫”看电视或看书的输出,它得出的新输出与它看到或读到的相似?它们通常非常有趣,并不完全遵循某人实际上是如何说或写的,但它们是自然语言生成的例子。NLG 是 ML 的一个非常有趣的地区,在这里玩玩,想出你自己的模型会很有趣。也许你想做一个瑞克和莫蒂星际迷航穿越脚本,或者只是创建听起来像另一个人的推文的推文。

随着研究和硬件的进步,使用 ML 生成文本、图像和视频变得越来越普遍。随着基于深度学习的系统的最新进展,例如 OpenAI 的 GPT-2 模型,我们现在看到语言模型可以用于从大量其他示例中生成非常真实的声音文本。我对构建一个以另一种风格或人物的风格生成假文本的系统很感兴趣,所以我决定专注于学习不同的 ML 方法,并概述我使用这些不同技术所学到的东西。

回归基础

不要直接跳到花哨的深度学习技术,让我们看看一种非常容易理解和容易实现的技术作为起点。多年来,语言生成最常用的方法之一是 马尔可夫链 ,这是一种非常简单的技术,但却惊人地强大。马尔可夫链是一种随机过程,用于在只给定前一事件的情况下描述序列中的下一事件。这很酷,因为这意味着我们真的不需要跟踪序列中所有先前的状态来推断下一个可能的状态。

在我们的例子中,状态将是前一个单词(一元)或 2 个单词(二元)或 3 个单词(三元)。这些通常被称为 ngrams,因为我们将使用最后 n 个单词来生成序列中的下一个可能的单词。马尔可夫链通常通过概率加权来选择下一个状态,但在我们的例子中,这只会创建在结构和单词选择上过于确定的文本。你可以考虑概率的权重,但是真正的随机选择有助于让生成的文本看起来更有创意。

建立语言模型

创建语言模型相当简单。首先,我们需要一些示例文本作为我们的语料库来构建我们的语言模型。它可以是任何类型的文本,如书籍段落,推文,reddit 帖子,你能想到的。在我的语料库中,我使用了多位总统的总统演讲。

一旦我们收集了文本,我们需要做以下步骤。注意,我将标记“#END#”添加到我的语言模型中,以便于确定任何示例语音中的结束状态。

  • 对文本进行标记
  • 对令牌做任何预处理(在我的例子中没有)
  • 从令牌生成 ngrams
  • 创建从 ngram 到文本中找到的下一个可能单词的映射

为了更好地理解这个模型是如何构建的,让我们看一个超级简单的例子。假设我们有一个简单的文本“狗跳过月亮。狗很有趣。”。使用上面的过程,我们将生成下面的语言模型。

(The, dog)     -> [jumped, is]
(dog, jumped)  -> [over]
(jumped, over) -> [the]
(over, the)    -> [moon.]
(dog, is)      -> [funny.]
(is, funny)    -> [#END#]

一旦我们完成了 ngram 映射,这个模型就可以用来生成一些新的文本了。现在,通过传入一个示例 ngram 的种子(如“The dog ”),或者让系统从提取的 ngram 密钥中随机选择一个起始点,就可以相当容易地做到这一点。一旦我们选择了一个种子 ngram,我们就从可能的单词列表中随机选择下一个单词,然后从目前生成的文本中选择下一个 ngram,并选择下一个状态等等…

简单的 Python 马尔可夫链

既然我们已经从概念上了解了它是如何工作的,那么让我们来看看训练和生成文本的完整代码。下面是我从网上其他例子中拼凑的 python 脚本,它用 python 构建了一个基本的马尔可夫模型。

让我们更深入地研究一些代码。它主要只有两个功能。学习功能和生成功能。让我们首先看一下 learn 函数,它从一系列大小为 n 的记号和 n 元语法中构建模型。

def learn(self,tokens,n=2):
        model = {}

        for i in range(0,len(tokens)-n):
            gram = tuple(tokens[i:i+n])
            token = tokens[i+n]

            if gram in model:
                model[gram].append(token)
            else:
                model[gram] = [token]

        final_gram = tuple(tokens[len(tokens) - n:])
        if final_gram in model:
            model[final_gram].append("#END#")
        else:
            model[final_gram] = ["#END#"]
        self.model = model
        return model

我们从从第一个标记到列表长度减 n 的循环开始。随着我们的进行,我们建立了在标记化文本中找到的相邻单词的 ngrams 字典。在循环之后,我们在输入文本的最后 n 个单词之前停止,并创建最终的令牌变量,然后用“#END#”将其添加到模型中,以表示我们已经到达了文档的末尾。

我要指出的这种方法的一个局限性是,我将所有文本放在一个列表中,所以我们实际上只有一个结束状态。进一步的改进是我们处理的每个文档都有结束状态,或者可以更进一步,在句子的末尾添加结束状态,这样我们可以更好地知道什么时候开始一个新的句子等等。接下来我们有生成函数。

def generate(self,n=2,seed=None, max_tokens=100):
        if seed is None:
            seed = random.choice(list(self.model.keys()))

        output = list(seed)
        output[0] = output[0].capitalize()
        current = seed

        for i in range(n, max_tokens):
            # get next possible set of words from the seed word
            if current in self.model:
                possible_transitions = self.model[current]
                choice = random.choice(possible_transitions)
                if choice is "#END#" : break

                if choice == '.':
                    output[-1] = output[-1] + choice
                else:
                    output.append(choice)
                current = tuple(output[-n:])
            else:
                # should return ending punctuation of some sort
                if current not in string.punctuation:
                    output.append('.')
        return output

生成新文本的代码接受我们训练的 ngrams 的大小,以及我们希望生成的文本有多长。它还接受一个可选的种子参数,如果没有设置,它将从模型中学习的可能的 ngrams 中随机选取一个起始种子。在循环的每次迭代中,我们查看前一个 ngram,并随机选择下一个可能的过渡词,直到我们到达结束状态之一或到达文本的最大长度。

下面是一个使用二元模型作为语言模型的脚本输出示例。

Us from carrying out even the dishonest media report the facts! my hit was on the 1st of december, 1847, being the great reviews &amp; will win on the front lines of freedom. we are now saying you will never forget the rigged system that is what we do at a 15 year high. i can perceive no good reason why the civil and religious freedom we enjoy and by the secretary of war would be 0.0 ratings if not.

如你所见,这很有道理,但听起来也有点随意。如果我们尝试使用三元语法语言模型呢?

Was $7,842,306.90, and during the seven months under the act of the 3d of march last i caused an order to be issued to our military occupation during the war, and may have calculated to gain much by protracting it, and, indeed, that we might ultimately abandon it altogether without insisting on any indemnity, territorial or otherwise. whatever may be the least trusted name in news if they continue to cover me inaccurately and with a group, it’s going to be open, and the land will be left in better shape than it is right now. is that right? better shape. (applause.)  we declined to certify the terrible one-sided iran nuclear deal. that was a horrible deal. (applause.) whoever heard you give $150 billion to a nation

嗯,这听起来好多了…但是等一下,当我深入研究样本语料库时,我注意到它从语料库中提取了大量的文本。在现实中,除非你有大量的数据来构建,否则一旦你开始使用三元模型或更高的模型,大多数模型都会表现出这种行为。这是马尔可夫模型方法的一个缺点。虽然 bigram 模型听起来更随机,但似乎每次运行都会生成相当独特的输出,并且不会从语料库中提取文本部分。

火花分布马尔可夫链

比方说,我们创建了一个更大的数据集,从整个子数据集或多年的推文中提取数据。如果我们想让 python 脚本运行足够长的时间,并在我们的机器上有足够的内存,那么它可能可以处理数据集,但最终它可能不容易扩展。让我们做同样的事情,但是使用 Apache Spark 并使用它的分布式计算能力来构建和存储模型。下面是基于 spark 的模型的完整代码,我们也将深入挖掘它的操作。

最大的障碍是试图找出如何在 Spark 中生成 ngram 模型,创建类似字典的结构并对其进行查询。幸运的是,Sparks mllib 已经在框架中内置了 ngram 特征提取功能,因此 park 已经被处理好了。它只是接收一个 Spark dataframe 对象,即我们的标记化文档行,然后在另一列中将 ngrams 输出到一个新的 dataframe 对象。

ngram = NGram(n=self.n, inputCol='tokenized_text',outputCol='ngram')
ngram_df = ngram.transform(text_df)

使用 Sparks ngram 模块,让我创建一个函数来映射数据帧中的每一行,并处理文本以生成每个 ngram 的相邻单词。这是在 Spark 进程的第一个 map 调用中调用的函数。它的目标是只获取文档的 ngram 列表,并以[(ngram,adjacent term)]的形式循环生成每个文档的元组列表。现在,列表中可能会有重复的(ngram,相邻项)元组。

def generate_adjacent_terms(ngrams):
    adjacent_list = []
    for i in range(0, len(ngrams)):
        if(i == len(ngrams) - 1):
            adjacent_tuple = (ngrams[i], "#END#")
            adjacent_list.append(adjacent_tuple)
        else:
            adjacent_tuple = (ngrams[i], ngrams[i+1].split(" ")[-1])
            adjacent_list.append(adjacent_tuple)
    return adjacent_list

平面映射将所有元组列表放入一个平面 rdd 中,而不是每个 rdd 元素都是来自每个文档的列表。下一个映射是设置 reduceByKey,因此我们获取每个元素并将其修改为一个(ngram,list object)元组,然后可以使用该元组将 ngram 键组合在一起,最终以(ngram,[相邻术语列表])的形式创建模型。重要的是要注意邻接表中会有重复的术语。我保留了这些副本,作为我们算法随机选择特定下一个状态的可能性的加权。

self.ngram_model = ngram_df.rdd.map(lambda x: PreProcess
    .generate_adjacent_terms(x.asDict()['ngram'])) \
    .flatMap(lambda xs: [x for x in xs]) \
    .map(lambda y: (y[0], [y[1]])) \
    .reduceByKey(lambda a, b: a + b)

下面是我用来创建基于 Spark 的马尔可夫链代码的完整代码。文本生成逻辑与其他脚本非常相似,只是我们不是查询字典,而是查询 rdd 来获取序列中的下一个术语。实际上,这很可能是在 api 调用之后,但是现在我们可以直接调用 rdd。

Spark 代码将生成与第一个 python 脚本类似的输出,但是理论上,当在集群上运行大型数据集时,应该可以更好地扩展。

您可以随意查看代码和脚本,并让我知道您的想法/我应该研究哪些改进!https://github.com/GeorgeDittmar/MarkovTextGenerator。下一轮工作是能够保存模型以用新数据扩展它们,以及添加更多的示例脚本供人们使用。

感谢阅读!

自然语言处理:速成班!

原文:https://towardsdatascience.com/natural-language-processing-a-crash-course-73d7a07c240c?source=collection_archive---------8-----------------------

Next word prediction is one of the applications of NLP

自然语言处理(NLP)是机器学习的一个越来越重要的子领域,它通过从各种大型文本语料库开发各种语言模型来处理一般理解。在本文中,我们讨论了 5 种常见的 NLP 问题及其相关模型:

(i) 文本分类

(二)文字嵌入创作

(三)词性标注

(iv) 序列间翻译

(v) 命名实体识别

文本分类

Spam classification is a famous example of Text Classification

这是 NLP 最基本的用途之一,而输入模型给定一个单词或一个单词集,它必须预测给定的一个或多个单词属于一组类别中的哪一个。这与任何其他类型的分类问题非常相似!让我们看一个例子,并介绍一些方法。

文本分类问题的一个主要例子是垃圾邮件分类。这种特殊类型的问题是二元分类,这意味着任何给定的电子邮件只能属于两种可能的类别,即垃圾邮件或非垃圾邮件。现在,让我们强调并讨论解决这个问题的三种可能的方法:

  • 感知器
  • 最大熵分类器
  • 多层感知器(又名神经网络)

感知器

The perceptron algorithm is an error-based approach

单层感知器是一种错误驱动的方法,旨在通过不断调整其权重来最小化训练数据的分类错误数量。

感知器训练算法的伪代码如下:

weights = random vector of weights
for the desired number of epochs:
   for point in training points:
      predicted_class = maximum score index(weights^T*point)
      if predicted_class is not actual_class
         weights[predicted_class]-=point
         weights[actual_class]+=point

让我们一点一点地分析一下:

(1)第一行随机初始化感知器的权重

(2)外部循环指定历元的数量(或者我们将在所有给定的训练数据点上“训练”我们的感知器的次数)

(3)内部循环简单地循环所有的训练数据

(4)第 4 行有意思。表达式 w^Tx 实际上是计算各个类的分数,然后取最大分数的指数表示我们将预测这个特定输入点属于哪个类。

这就是奇迹发生的地方。如果我们的预测类与当前点的实际类不匹配,算法会“惩罚”错误预测类的权重,并“提升”实际类的权重。因此,感知器在未来不太可能犯同样的错误。

感知器预测算法的伪代码非常简单。我们通过训练简单地使用更新的权重来为每个可能的输出类分配单独的分数,并挑选具有最高结果分数的一个:

predicted_class = maximum score index(updated_weights^T*test_point)

最大熵分类器

与单层感知器相反,最大熵分类器试图最大化所有给定训练数据点的可能性,然后旨在找到一组权重,进而最大化该总体可能性。

我们先来探讨一下什么是可能性。一般来说,似然性告诉我们在特定的参数配置下,一组给定的观察值(数据点)的概率。

特别是对于最大熵分类器,唯一的参数是我们用来形成预测的权重向量。因此,存在的单个数据点的概率表达式如下:

以下是上述表达式中两个主要部分的概述:

w -我们的分类器正在训练的一组权重

phi(X,y) —输入向量 X 和输出类别标签 y 的特征向量

此外,整个训练数据的似然性的表达式简单地通过遍历所有单独的训练数据点并乘以单独的概率来获得训练数据出现的总概率而导出:

最后,我们可以将上述个体概率的自然对数(ln)值相加,从而将似然表达式转换为一个称为对数似然的等价表达式,得到以下公式:

因此,这种类型的分类器的整体优化将涉及找到权重以最大化对数似然量,并且可以数学地写成如下:

多层感知器(神经网络)

经常用于文本分类的第三种方法是多层感知器,这只是神经网络的另一个名称。虽然我们不能在这篇文章中深入神经网络如何工作的所有细节,但让我们涵盖一些核心方面。

为了理解多层感知器,我们可以从理解单个神经元如何工作开始。一个神经元只是接受一些

一组输入,将它们乘以各自的权重,然后将这组乘积相加,并将总和传递给激活函数。听起来像是满嘴?下图很好地总结了这个过程:

Structure of a single neuron

这里有三个主要组件:

(1) X1 & X2 :神经元的输入

(2) W1 & W2 :用于乘以输入的权重

(3) f :上述神经元的激活函数

现在,一个多层感知器包括将这些单个的神经元堆叠在一起,这样就会有多层神经元。典型地,多层感知器的最简单结构将包括一个输入层一个单一隐藏层,以及最后一个输出层,如下所示:

Sample Multi-layer Neural Network

具体到垃圾邮件分类的情况,我们最终的神经网络架构如下所示:

上述模型从输入的电子邮件中导出一组特征,将这些特征馈送到多层网络的输入层,然后通过单个隐藏层传播,最后通过输出层,并为每个类别产生大小为 2 的概率向量。在这种情况下,电子邮件是垃圾邮件的概率和不是垃圾邮件的概率。

在上图中,“常规激活函数”是指常用于神经网络的激活函数,包括但不限于:

  • s 形函数

  • ReLU 功能

  • Tanh 功能

Softmax 函数是一种特殊类型的激活函数,它将一组类得分转换成一组等价的类概率:

本质上,上面的 softmax 函数将一个向量作为输入,并返回一个概率向量作为输出。

训练神经网络

在我们结束对神经网络的介绍之前,让我们简单地谈谈训练网络。培训任何网络都涉及到一些基本组件,所以让我们在下面讨论一下:

损失函数

损失函数将用来衡量我们当前的一组预测与相应的真实值之间的差距。机器学习中常用的损失函数的一些例子包括:

  • 均方误差

  • 均方根误差

  • 交叉熵损失(二元分类)

均方误差和均方根误差都用于连续预测,而交叉熵损失用于分类问题,因此交叉熵损失的二进制版本可以用于垃圾邮件分类。

梯度下降

训练神经网络的第二个主要部分是一种称为梯度下降的算法,它能够优化神经网络损失函数。整个伪代码如下所示:

Pick a random start point for a loss function
while magnitude of gradient is < threshold:
   - store current gradient value
   - update the point based on the calculated derivative

可视化这个算法使它变得相当直观,所以让我们走这条路。作为起点,假设我们有以下平滑凸函数:

在这种情况下,我们的主要目标是尝试找到使函数 y 的值最小化的 x 的值。作为这种方法有效的证明,让我们以函数 y 的最小值两侧的点为例。首先,让我们从最小值左侧的点开始:

由于上述函数在点 x0 处的导数为负,我们将在梯度下降更新函数中看到上述移动:

  • 数学上

  • 视觉上

现在很容易看出重复应用这一更新将如何最终找到使函数 y 最小的 x 值。请注意,我们将多快达到这一最小值,或者我们最终是否会完全超过它,在很大程度上取决于我们为学习速率α选择的值。

对于最小值右边的点,很容易看到现在 dy/dx > 0,所以 x 会不断地向左移动,直到它达到函数 y 的全局最小值。

最后但同样重要的是,让我们通过接触前向和后向传播来完成训练神经网络的循环。

正向传播

前向传播,顾名思义,就是遍历构建好的神经网络,得出一组当前预测的过程。

反向传播

反向传播,或称为反向传播,是一种真正开始使实现神经网络可行的算法。它用于有效地计算损失函数相对于权重的导数。

因此,训练神经网络的整个伪代码将如下所示:

for desired number of epochs (aka training cycles):
    for data_point in training_data:
       forward propagate on the current inputs
       backward propagate to calculate dL/dw(current data point)
       dL/dw+=dL/dw(current data point)
    average out dL/dw based on size of training_data
    weight update: w_{i+1} = w_{i} - learning_rate*[dL/dw]

单词嵌入创建

Photo by Giulia May on Unsplash

单词嵌入是简单的向量,用于表示不同的单词,并帮助获得更好的个人和词组的数学意义。在深入研究将单词转换为单词嵌入的技术细节之前,让我们先了解一下单词嵌入的一些最常见的应用:

  • 分析文档/句子/单词相似度:智能地将文档或语料库中的单个单词嵌入组合在一起,可以让我们将该文档或语料库表示为单词嵌入。
  • 序列到序列的转换:这将在本文后面讨论,用于从给定的输入序列预测期望的输出序列。

除此之外,事实仍然是向量更适合机器学习背后的所有数学,因此在 NLP 中到处都使用了单词嵌入。

所以,事不宜迟,让我们直入主题吧。将单词转换为单词嵌入的方法有很多种,但是让我们来看看三种最流行、最基本的方法:

  • 跳格模型
  • 连续词袋(CBOW)模型
  • 单词表示的全局向量(手套)模型

跳格模型

让我们通过首先查看我们可能在极大的训练语料库中遇到的例句来介绍 Skip-Gram 模型:

保持饥饿,保持愚蠢。

我们的第一个目标是大致了解在任何给定的句子中哪些单词可能彼此接近。自然地,我们从定义“近”的含义开始,结果,我们得到了上下文的概念。

你看,上面句子中的每个单词都有一个语境,它仅仅是由周围的单词组成的。此外,我们可以定制我们希望的上下文的大小。例如,在大小为 1 的上下文的情况下,单词“hungry”将具有[“Stay”、“Stay”]的上下文。另一方面,单词“stay”会有[“hungry”、“傻瓜”]的上下文。

The respective length-1 contexts for ‘hungry’ and ‘stay’

对数百个、数千个甚至数百万个句子重复做这个练习会建立一个敏锐的直觉,知道哪些单词可能是给定单词的上下文单词。跳跃语法模型利用了这种直觉,然后根据语料库中每个独特的单词在输入单词的上下文中出现的可能性来分配概率。

连续词袋模型

与 Skip-Gram 模型不同,CBOW 模型将一组上下文单词作为输入,并尝试预测这些单词所在的上下文中的单词。本质上,对于上面的两种情况,这将如下所示:

单词表征的全局向量(GloVe)模型

最后,与上述两个模型不同,GloVe 模型不依赖于单词上下文来训练单词嵌入,而是依赖于共现矩阵的概念。

到底什么是共生矩阵?简单地说,这是一个 2d 整数数组,它捕捉了所有可能的单词组合在同一个句子或跨度中出现的频率。然后,它利用这个矩阵中的所有计数来导出每个单词的嵌入。

词性标注

Photo by Edho Pratama on Unsplash

词性标注是自然语言处理领域的一个研究热点,有多种方法。让我们从回顾一些基本的语言建模概念开始,然后逐步为维特比算法开发一个框架。

隐马尔可夫模型

A sample HMM for M total observations and 3 hidden states

当我们必须表示一系列无法直接观察到的元素时,隐马尔可夫模型非常有用。这使得它们成为用于词性标注的理想模型,因为我们只观察单个单词,并且必须推断它们的相关标签。下面是用于词性标注的 HMM 的基本组件的分类:

  • Q = q_{1}q_{2}…q_{N}【一组隐藏状态】:在我们的例子中,这些将是我们所有可能的词性标签(例如。{'O ',' VBG ',' NN ',' NP ',…})
  • A = a_{11}…a_{ij}…a_{NN}[转移概率矩阵]: 这些将是特定状态之后一个状态的个体概率。比如 a_{11} = Pr(下一个单词的 tag = q_{1} |当前单词的 tag = q_{1})。
  • O = o_{1},…,o_{M}【一组观察值】:这些只是我们模型的一组单独的输入单词。
  • S = s_{1},…,s_{N}【一组起始状态概率】:每个可能状态的一组概率,它们是所讨论的序列的起始状态。

上述 HMM 也受两个假设支配:

  • 马尔可夫假设:一个观察对应的状态只取决于这个观察之前的状态。[ P(q_{i} | q_{i-1}) ]
  • 输出独立性假设:一个观测只与当前对应的状态有关。[ P(o_{i} | q_{i}) ]

An example transition probabilities matrix for the sample HMM from above.

Example emission probabilities for the above examples.

HMMs 的 3 个主要功能

事实证明,hmm 用于对一组顺序观察执行 3 个主要功能:

(1) 序列评分:给定一个观察序列{o_{1},…,o_{n}},指定一个概率,表示该序列有多大可能给出上述一组跃迁和发射概率。

(2) 序列解码:给定一个观测序列,找出最大化该观测序列发生概率的隐藏状态序列。

(3) HMM 学习:给定一个观察序列,调整 HMM 模型的转移和发射概率,以最大化该观察序列发生的概率。

HMMs 的问题是

为什么 hmm 不是我们在顺序位置标签中使用的主要结构?事实证明,我们为了计算一个最优的状态序列而必须经历的概率的绝对数量是非常大的,并且对于具有大的转移矩阵的数据集的计算是不可行的!

让我们通过基于上面的 HMM 计算样本观察值序列{观察值 1、观察值 2、观察值 3 }的可能性的示例来说明这一点:

本质上,这里我们有需要求和的个体概率!扩展也变得很困难。如果总共有 n 个隐藏状态和 m 个观测值,那么总起来说,就有 N^M 总数的情况!

解决方案:动态编程!

在本节的其余部分,我们将利用一种非常流行和有用的算法技术,称为动态编程。虽然了解细节很容易,但您需要理解的是,动态编程通过重用过去已经计算过的信息来加快算法运行时间!

介绍:格子架

听到关于动态编程的总结后,合乎逻辑的下一个问题是我们计划如何重用过去的信息。对于词性标注问题,我们将使用一种称为 Trellis 的结构,它由一组用于每个观察时间戳的节点组成:

A Trellis for our example given {observation 1, observation 2, observation 3}. The first layer of probabilities is labeled.

但是每个单独的节点持有什么确切的信息呢?嗯,隐藏状态 I 在时间步长 j 的节点,代表了处于隐藏状态 I 的概率,给定前 j 个观察值。在数学上,这可以表示如下:

现在,我们可以很容易地计算序列{观察 1,观察 2,观察 3}的可能性,方法是将上面网格的最后一层中的值相加:

介绍:维特比算法(通过词性标注)!

现在我们可以将维特比算法应用于我们的词性标注问题。让我们从设置我们的中心问题开始:我们有一个令牌序列,我们试图找到一组相关的词性标签(我们的隐藏状态)。

这是我们将用来有效重用子序列概率的网格结构:

让我们定义维特比算法的两个主要组成部分,即最佳 POS 标签序列概率和相应的反向指针:

(1)最优序列概率

(2) POS-Tag 反向指针

此外,维特比算法可以分为以下三个阶段:

(1)初始化:这里我们需要为隐藏状态概率以及节点反向指针的初始集合设置第一层的值:

(2)递归:这代表所有中间步骤,在这些步骤中,我们计算所有单个时间步长最佳标签,以及每一层的最佳后向指针:

(3)终止:这最后一个阶段涉及计算可能的最高整体隐藏状态序列概率,并且还设置我们将遵循的最终反向指针,以找到我们的 POS 标签的最佳序列。

下图直观地显示了这三个阶段分别应用于网格的哪些部分:

一旦我们正确地设置了反向指针,我们就可以简单地按照它们来获得我们的 POS 标签的最佳序列!伪代码类似于:

current_tag = end
optimal_tag_sequence = [end]
while backpointers[current_tag] != start:
   current_tag = backpointers[current_tag]
   optimal_tag_sequence = [current_tag] + optimal_tag_sequence
optimal_tag_sequence = [start] + optimal_tag_sequence

序列间翻译

Photo by Romain Vignes on Unsplash

序列到序列的翻译包括利用神经网络结构将输入的单词序列转换成期望的输出单词序列。它经常用于语言翻译,例如将提供的单词集从英语翻译成其他语言,比如法语。

从整体模型的宏观视图开始,然后讨论各个组件如何工作。整个系统看起来如下:

本质上,该模型将输入的令牌序列分解为单个单元,将这些单个单元输入到左侧所示的编码器模型中,然后该编码器模型产生一个整体序列嵌入,这是一个捕获输入序列中整体信息的向量。然后,这个序列嵌入被传递给解码器,解码器又返回一个输出令牌序列。现在,让我们来分解各个组件:

单个 RNN(递归神经网络)节点

与常规的神经网络节点相反,rnn 经常用于我们想要在更广泛的序列中对单个标记进行预测的情况。这种潜在的使用差异在 RNN 节点的整体结构中非常明显:

  • 设 x_{i} =输入序列中的第 I 个记号
  • 设 h_{i} =隐藏层输出中的第 I 个令牌

“展开”上面的 RNN,我们可以看到下面的结构:

到目前为止,我们一直在黑盒子 RNN 节点的内部结构,所以让我们打破它真正快速。它由两个权重组成,一个充当时间戳 t 处的输入令牌的系数,另一个充当时间戳 t 处的隐藏状态的系数。这两个权重分别乘以其对应的权重,两个结果相加并最终传递到激活函数 f:

这是 RNN 节点在时间戳 t 的输出,并作为时间戳(t+1)的节点的隐藏层输出!这种递归性质就是为什么 rnn 是递归神经网络的原因。

编码器型号

好消息是,一个简单的编码器模型遵循了我们前面举例说明的精确结构!它将简单地一个接一个地接受输入标记,并继续计算中间隐藏状态。最后,它将把生成的最终隐藏状态向量传递给解码器模型。

我们可以使用各种各样的创造性策略来提高编码器模型的嵌入能力,其中大多数策略包括将每个单独导出的隐藏状态巧妙地组合到最终的嵌入向量中。你也可以选择使用更复杂的递归神经网络结构,比如 LSTMs(长短转记忆网络)和 GRUs(门控递归单元)。

解码器模型

解码器模型结构将与编码器模型结构非常相似,但在这种情况下,我们将有一个最终的 softmax 层,以便我们为输出词汇表中的每个单词分配概率,并尝试通过最大概率预测输出序列中的每个标记:

Single Decoder Node

A more complete picture of the model.

关于训练序列间模型的简要说明

正如在训练机器学习模型中常见的那样,在序列到序列模型的训练阶段,主要焦点是调整我们之前提到的所有权重,以希望提供最好的结果。然而,简单的梯度下降在这种情况下根本不会很好地工作。相反,必须利用一种称为随机梯度下降的方法来训练模型。

命名实体识别

Photo by Kyle Glenn on Unsplash

最后但同样重要的是,让我们触及命名实体识别问题。命名实体识别(NER) 是一个非常普遍的问题,涉及到给命名实体分配类别。下面是一个简单的例子:

Example from Wikipedia’s Named Entity Recognition article.

命名实体识别的组件

(1)一个输入句子 s,由一串单独的单词标记表示,我们想要在其中识别命名实体。

(2)给定句子中每个标记的一组可能的命名实体标签 t。

(3)一组特征函数 f,其接受诸如给定单词的相邻标签和句子信息的信息,并输出相应的第 I 个标签以分配输入句子中的第 I 个单词。

条件随机场

我们将探索条件随机场(CRFs) ,它是用于 NER 提取和其他类型的顺序分类任务的最基本模型之一。通用报告格式由两个关键部分组成:

(I)评分功能,其接受一组预测的标签和输入的句子,并返回指示标签与句子标记匹配程度的分数;

(ii)用于归一化上面得到的标签序列分数的公式,使得每个分数在 0 和 1 之间:

然后,该模型简单地利用这些导出的概率来返回输入句子的最佳标签序列。

培训通用报告格式

以上两个部分清楚地说明了我们如何为任何输入的句子选择一个最优的 NER 标签序列,但是在训练 CRF 的过程中到底发生了什么呢?我们查看训练数据,并为特征函数 f 的集合调整各个系数(c_{1},…,c_{n})。训练它们的一种方法是利用梯度下降,这一点我们在前面的文本分类部分已经强调过了!

额外挑战

目前,在上面的概率公式中,我们正在查看分母中所有可能的 NER 标签集,这是非常低效的。使用我们之前关于动态编程的讨论,尝试提出一个可以更有效地计算最佳标签集的算法!

摘要

Photo by Aaron Burden on Unsplash

总的来说,本文旨在提供自然语言处理领域中常用的一些主要问题和算法的概述。这是一个压缩在一个地方的大量信息,所以最好是多次重温或按照自己的速度阅读!

自然语言处理和体育子编辑

原文:https://towardsdatascience.com/natural-language-processing-and-sports-subreddits-d470e8bfc2e1?source=collection_archive---------15-----------------------

如果你必须知道关于我的两件事,那就是我热爱运动和在 Reddit 上浪费我的空闲时间。如果你必须知道关于我的三件事,那就是我也喜欢发现新的应用自然语言处理(NLP)技术。因此,当被分配一个项目任务,通过从子数据集获取真实数据来探索我新发现的 NLP 技能时,我欣然接受了这个机会。

一段时间以来,Reddit 上关于体育的讨论让我特别感兴趣。俗话说,“凡事皆有子编辑”,所以自然 reddit 上的每个体育联盟都会有一个社区。从 NFL 和英格兰超级联赛,到 Overwatch 联盟和冰壶大满贯,几乎每个体育迷都有一个社区。他们每个人都有自己讨论体育的语言,更不用说他们自己的笑话和每周的话题讨论了。基于这些兴趣,我想进行一个项目来比较两个最大的体育子街道, r/NFLr/NBA ,看看语言有什么不同,并使用 NLP 来预测一个帖子的来源,仅仅基于它的语言。

我将带您浏览数据、数据清理过程、矢量化、建模、预测,并评估模型在数据的一些有趣变化上的表现。我分析不同子主题中的语言的目的是确定哪些主题或趋势最能区分这些联盟的讨论。对每个模型的最重要的词特征的观察和每个模型的分类性能将用于得出我的结论。

数据是从哪里来的?

实际分析 Reddit 数据的第一步是…从 Reddit 获取数据。然而,这并不是一个非常困难的任务!幸运的是,Reddit 内置的 API 功能允许任何用户在网站上查询给定页面上热门帖子的. json 文件。例如,你可以现在就去 https://www.reddit.com/r/nba.json,你会看到。r/NBA 上前 25 个帖子的 json。然而,出于我的目的,我只需要提取每个帖子的标题和“自我文本”。

因此,我们需要多次遍历 subreddit 的页面来提取这些帖子。Python 的requests模块可以下载。json 文件直接放入代码中,准备好进行操作。然而,为了获得有用的数据,我需要多次这样做。此外,我想只提取这个的特征。在我的建模过程中很有价值的 json。我使用以下函数来完成这项任务:

使用函数的num参数,我告诉函数在页面中循环指定的次数。每个页面都有一个“after”参数,您可以从。json 文件,它引用页面上第一篇文章的文章 ID。您可以将这个参数传递到 URL 中,API 将为您提供在“after”ID 之后索引的所有帖子。

这个函数将返回一个相当大的熊猫 dataframe 对象。我们能够检索 Reddit 帖子的几乎所有功能,包括发布帖子的用户名、其 upvote 分数、任何附加图片的 URL、唯一的帖子 ID,当然还有帖子的标题。这是一个很大的数据量,但它现在能够被清理和建模!

计数矢量化与 TF-IDF

我们已经有了 reddit 帖子,现在我们该做什么呢?我将探索的 NLP 模型不能简单地解释出现在网站上的英语,我们需要在将其用于机器学习模型之前将其转换为数字数据。当文件用数字表示时,计算机想要读取文件。文档是 NLP 模型要评估的文本主体,在我们的例子中,是标题文本和“自身文本”主体的组合。

当文档可以用数字来解释时,计算机和程序员都更容易理解文档。为了对文档进行分类,每个文档都使用一个“输入”,并且类标签是“输出”、,在本例中是 r/NBA 或 r/NFL。大多数分类机器学习算法以数字向量作为输入,因此我们需要将 post 文档转换为固定长度的数字向量。

NLP 中的计数向量化允许我们将文本分割成句子和单词,收集文本文档并建立一个已知单词的词汇表。这是通过评估文档的整个语料库来完成的,获取在语料库的词汇表中找到的每个单词,并基于在单个文档中找到的词汇表为文档分配一个向量。

Word vectors, visualized. Source: https://towardsdatascience.com/natural-language-processing-count-vectorization-with-scikit-learn-e7804269bb5e

本质上,计数矢量器计算每个单词在文档中出现的次数,并根据语料库中已建立的词汇在矢量中为文档分配适当的值。

类似于计数矢量化,术语频率—逆文档频率,或 TF-IDF,查看整个语料库以形成其词汇。TF-IDF 的不同之处在于,它根据单词在文档中出现的频率对单词进行加权。这背后的逻辑是,如果一个单词在文档中多次出现,我们应该提高它的相关性,因为它应该比出现次数较少的其他单词更有意义(TF)。然而,如果一个单词在一个文档中多次出现,而且还出现在许多其他文档中,则模型会降低该单词的权重,就好像它只是一个频繁出现的单词,而不是因为它是相关的或有意义的(IDF)。

因此,现在我已经确定了如何预处理文档以便在模型中使用,我需要清理实际的文档本身。我使用正则表达式,或者说 RegEx ,在每个文档中找到要删除或替换的单词和字符的特定模式。计数矢量器和 TF-IDF 都将把互联网帖子中的杂乱条目(如 URL 和表情符号)解释为令牌,因此只向它们提供字母数字文本非常重要。例如,我用来删除 URL 的代码行如下所示:

sub['text'] = sub['text'].map(lambda x: re.sub(r"((http|ftp|https):\/\/)?[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?", 
' ', 
x)

正如您所看到的,解释正则表达式并不简单,但它是清理文本的一个非常有效的工具。然而,RegEx 是非常通用的,因为它也被用在这个项目中来删除某些扭曲我的结果的单词、短语和字符序列。在这个 URL 清理器的例子中,它也在字符串中寻找独特的模式。

既然我们已经组装了矢量器,并清除了文本中不需要的特征,现在是建模的时候了!

建模!

在我的建模过程中,我的主要兴趣之一是确定在预测源的子编辑时,哪些单词具有更大的重要性,而不是简单地对某些预测单词进行计数。因此,虽然我确实利用了计数矢量化模型,但我发现使用 Scikit-Learn 的 TF-IDF 功能生成的加权矢量化结果TfidfVectorizer在评估每个模型时会产生更多信息。然而,为了便于理解,我将分享两个矢量器产生的结果。

我评估的第一个模型是多项式朴素贝叶斯(NB)模型,同时具有计数矢量器和 TF-IDF 矢量器。计数矢量化 NB 模型在 97%的情况下正确预测了帖子是否在 r/NFL,在 93%的情况下正确预测了帖子是否在 r/NBA。

# run the Count Vectorized model with the optimal hyperparameters
cvec = CountVectorizer(stop_words='english', ngram_range=(1, 2), max_features=20000, max_df=0.60)
train_raw = cvec.fit_transform(X_train)
train_df = pd.SparseDataFrame(train_raw, columns=cvec.get_feature_names())test_raw = cvec.transform(X_test)
test_df = pd.SparseDataFrame(test_raw, columns=cvec.get_feature_names())train_df.fillna(0, inplace=True)
test_df.fillna(0, inplace=True)# fit the multinomial NB model
cvec_nb = MultinomialNB()
cvec_nb.fit(train_df, y_train)

Feature importances for the Count Vectorized NB Model, ranked by class probability.

在对来自 r/NBA 的帖子进行分类时,模型中最重要的词引用了自由球员的举动,如“威斯布鲁克”、“科怀”、“勒布朗”,但“交易”和“挑选”等加权术语也很重要。对来自 r/NFL 的帖子进行分类的最重要的词采取了不同的方向,其中“day”具有最高的计数,在关于实际足球比赛的讨论中发现的术语,如“round”、“yards”和“pass”,也非常重要。

TF-IDF 模型在 98%的时间里正确预测了一个帖子是否在 r/NFL,在 91%的时间里正确预测了 r/NBA。在对 r/NBA 的帖子进行分类时,模型中最重要的词再次引用了自由球员的举动,如“威斯布鲁克”、“科怀”和“勒布朗”。我还看到,在对来自 r/NFL 的帖子进行分类时,最重要的词是在关于实际足球比赛的讨论中发现的术语,如“highlight”、“yard”和“td”。

讨论我收集数据的时间很重要,因为很明显,尽管两个数据集都是在各自运动的休赛期发布的,但两个子数据集的侧重点是不同的。大多数帖子都是在 2019 年 7 月 8 日至 2019 年 7 月 12 日这一周被刮下来的,正如 NBA 球迷可能记得的那样,这是相当疯狂的一周。当 NBA 超级巨星拉塞尔·维斯特布鲁克、凯文·杜兰特、凯里·欧文和科怀·伦纳德决定加入新球队时,他们都在 NBA 世界产生了冲击波,这反映在我正在分析的数据中。这并不是说 r/NFL 或 NFL 媒体不讨论自由球员的转会,但至少 r/NBA 的文化是主要关注这项运动中的人物,而不是这项运动本身。

知道了这一点,我想看看不同的分类算法如何衡量每个文档的特征,以及我是否可以提高我的准确性指标。因此,我决定通过一个支持向量分类器(SVC) 运行这个相同的数据集。SVC 是非常强大的分类模型,它试图使用一个“分离超平面”将一个数据集分类到有标签的类中,例如 origin 的 subreddit。换句话说,给定一个二维空间,这个超平面是一条将平面分成两部分的线,其中每一类位于两侧。在支持向量机之下还有很多事情要做,但是出于我的目的,使用了 SVC,因为它是一个全面而强大的建模工具。

因此,我对从 r/NBA 和 r/NFL 收集的数据运行了 TF-IDF 矢量器和 SVC。该模型的得分不如多项式 NB 模型高,但仍然表现得非常好,发布了 93.14%的准确度得分和 93%的加权精度。带有我选择的超参数的模型如下:

# fit tf-idf svc model for best hyperparameters
tfidf = TfidfVectorizer(max_features=20000, ngram_range=(1, 1), stop_words='english', max_df=.6)
train_raw = tfidf.fit_transform(X_train)
test_raw = tfidf.transform(X_test)svc = SVC(C = 1, kernel='linear', gamma = 'auto', probability=True)
svc.fit(train_raw, y_train)

The weighted coefficients from the SVC model.

该模型选择的重要特征类似于 NB 分类器,但倾向于将专有名词如球员姓名、球队名称甚至记者的权重更高。然而,与主题相关的更一般的术语,如“篮球”和“足球”,也被赋予了更大的权重。

大学体育呢?

在预测涵盖不同运动的两个子主题的帖子来源时,我没有看到模型有太大的差异,所以我想给我的建模过程一个新的挑战。我想确定我是否可以创建一个模型来确定一个帖子的来源,这些帖子来自覆盖同一项运动,但在不同的联盟。

如果你需要知道关于我的四件事,那就是我热爱运动,在 Reddit 上浪费我的空闲时间,发现 NLP 的新应用,为 UVA 篮球队加油。因此,很自然地,我想以某种方式将r/学院篮球纳入这个分析

使用与我收集 r/NFL 和 r/NBA 帖子相同的收集技术,我从 r/CollegeBasketball 收集帖子,清理文本,并将这些帖子与 r/NBA 帖子一起组合在 Pandas 数据框架中。我通过 SVC 模型运行了这些帖子,结果让我有些吃惊。

The SVC model, this time weighting the words from r/collegebasketball posts alongside r/nba.

这个模型表现很好,发布了 91.39%的准确度分数和 91%的加权准确度,但它显然没有根据 r/NFL 的内容对 r/NBA 的帖子进行分类时那么准确。这个模型倾向于给专有名词,比如球员名字和球队名字赋予更高的权重。“锦标赛”、“转会”和“提交”等术语在 r/CollegeBasktball 中非常重要,因为它们在关于 NCAA 篮球的讨论中比在 r/NBA 中使用得更广泛。然而,我们发现像“卡利帕里”这样的教练的名字比球员的名字更重要。一些有趣的区别是“basketball”和“gif ”,这两个词在任一子编辑中都很常见,但 r/CollegeBasketball 的权重更大。

结论

对所有迭代的子网格数据进行分类的所有模型得分都很高,但计数矢量化多项式朴素贝叶斯在训练和测试数据中表现最佳且最一致。支持向量机模型的表现不如 NB 模型,但让我更好地理解了哪些词/术语在分类帖子时是至关重要的。

在这个项目中分析的所有模型中,他们能够让我理解在分类子编辑之间的帖子时什么类型的内容是重要的。对于 r/NBA 来说,很明显,球员姓名和交易是帖子中非常频繁的话题,尤其是考虑到数据拍摄的时间。对于 r/NFL 来说,主题更倾向于面向团队,但是像“td”和“yard”这样的游戏专用术语在所有模型中都很重要。对于 r/CollegeBasketball 来说,很明显学校的骄傲和竞争是帖子主题中出现最多的,因为某些学校的名字权重最大,而教练往往比个人球员更经常进行讨论。

作为一个经常光顾这三个子街道的人,我非常好奇这个项目的结果会告诉我什么。不仅看到每个模型如何解释来自每个子编辑的帖子特别有趣,而且我能够结合我自己对每个社区中讨论的主题语言的知识以及模型来解释结果。虽然像单词云这样的东西是可视化 subreddit 语言选择的一种简洁方式,但对帖子进行矢量化和分类让我对每个社区如何讨论这项运动有了新的认识。

如果你想探索这个项目和收集的数据,Temple 已经上传了所有相关的 Jupyter 笔记本和。csv 文件在他的公共 GitHub 上。

使用深度学习和 Word2Vec 的自然语言处理分类

原文:https://towardsdatascience.com/natural-language-processing-classification-using-deep-learning-and-word2vec-50cbadd3bd6a?source=collection_archive---------3-----------------------

Photo by Victoria Kubiaki on Unsplash

介绍

我以前体验过机器学习算法,用于不同的问题,如货币汇率预测或图像分类。我最近在做一个文本分类的项目,我读了很多关于这个主题的文献。NLP(自然语言处理)的例子很吸引人。当你开始思考的时候,你意识到没那么简单,在分类之前,还有这个问题:
“一个算法到底是怎么读懂文字的?”。一种解决方案是将单词转换成向量,用数字来表示它们。这种解决方案并不新鲜,几年前,一篇文章提出了 Google Word2Vec 无监督算法:向量空间中单词表示的高效估计(Mikolov & al。,2013) 。可以找到许多关于它的文档,但本文的重点是从头到尾详细介绍如何构建用于文本分类的机器学习算法。我将演示如何将 Word2Vec 与预训练的 Google 新闻数据集一起使用,以及如何用您的数据自己训练它。然后,我将演示两种技术;一个是做你的文档词的意思,另一个是保持你的数据像他们一样,这保留了更多的信息,但它有点复杂,需要更多的时间来训练。所以这取决于你,你认为在你的情况下和你的数据下什么更好。

1 首先我们需要导入数据

对于这一步,确保包含您的评论的文件夹与笔记本在同一个文件夹中。

我用的数据是可以在这里找到的影评:影评。我拿的是“句子极性数据集 1.0 版”。我拿的是“句子极性数据集 1.0 版”。我选择这些是因为我可以将我的结果与论文用于句子分类的卷积神经网络(Yoon Kim,2014) 进行比较。本文的优势在于为该数据集提供了一个神经网络,但它将其结果与表 2 中的其他算法进行了比较,这非常有趣,因为我们有许多来自不同论文的算法来比较我们的结果。

提取你下载的带有链接的文件。
好了,现在我们基本上有一个名为“rt-polarity data”的文件夹,其中有两个名为“rt-polarity . neg”“rt-polarity . pos”的文件。负面评价和正面评价)。我们在这里的工作将是把每一个数据放入熊猫数据框进行分析。开始将它们转换成 CSV 文件。

现在,我们正在创建数据的“标签”, 1 表示正面评价,0 表示负面评价。

现在结果应该如下

Figure 1: Our Dataframe, with the text of the review, and its label

好的,看起来很棒!现在,我们将每个评论都放入我们的 pandas dataframe,命名为“评论”,并带有特定的标签(1 表示正面评论,0 表示负面评论)。

2 使用 Word2Vec 查看我们单词之间的相似性距离

ord2Vec 是一个很好的用于单词嵌入的神经网络模型。它主要用于词语的相似上下文。我们将在我们的数据上训练模型,使我们所有的词之间有一个距离,以查看哪些词在语义上彼此接近。还有其他型号,但我选择这款有两个原因:

  1. 这是尹金在他的文章中使用的
  2. 是 Google 开发的模型,似乎是完全推荐的,文档也很容易找到,而这篇文章:向量空间中单词表示的高效估计(Mikolov & al,2013) 很好地解释了所有的过程。

2.1 标记化

现在,你的数据帧应该是这样的

Figure 2 : The dataframe, with the tokens

对于培训来说,重要的是将每个评论表示为单词列表,如“令牌”列中所示。

2.2:使用预先训练好的谷歌新闻数据集

首先你需要在这里下载数据集:谷歌新闻数据集。然后,将其提取到您的文件夹中。我将它提取到名为“model”的子文件夹中

就这么简单!现在你已经有了一个名为“w2v _ model”的模型,它经过了训练,包含了数据集中用向量表示的每个单词。

2.2.1 根据您的数据训练模型

你也可以用你的个人数据来训练这个模型。但是,我不建议对小文档使用这种技术,因为 Word2Vec 不能正确地捕捉单词的上下文,并且它不会给出令人满意的结果。我在这篇文章的数据上进行了测试,结果明显比预先训练的 Google Word2Vec 要好。在另一个平均每个文档 200 个单词的数据集上,它更可靠,并且在某些情况下显示出比预训练模型更好的结果。

我们将把工作分成 3 个步骤

  1. Word2Vec()。用模型的所有参数初始化模型
  2. 从一系列句子中构建词汇
  3. .train()我们训练我们的模型

2.3 结果

现在,我们可以用一些单词来测试我们的模型,看看哪些单词与它们最相似。
我们用以下方式进行测试:

  1. 电影
  2. 小说
  3. 好的

对于“好”这个词,我有这些结果

Figure 3 : Words that are the most similar to “good”

这些结果是通过预先训练的谷歌新闻数据集获得的。

然而,我们可以看到,该模型并不完美,没有捕捉到单词的语义,因为我们有[很好、很差、很棒、不错]。这可能是一个问题,因为在这里好在“语义上”接近坏。事实上,它们可以在相同的上下文中使用,但它们的含义是不一样的。

2.5 一点点数据可视化

上面是我们数据集的一万字的图。语义相近的,在地图上是挨着的。我用散景让地图变得动态,我们可以和它互动,你可以把鼠标放在一个点上,看看对应的单词。我们现在可以清楚地看到所有单词之间的关系,以及哪些是近的或远的。

Figure 4 : Bokeh chart of 10000 words of our dataset

3 对数据做一点工作

3.1 列车测试分割

现在我们有了数据框架,我们需要将数据分成一个训练变量和一个测试变量。通过训练,我们的算法将学习它的参数,通过测试,我们将测试它们。
我们将训练和测试分开,以查看是否存在不过度拟合的问题,这在深度学习领域是经常出现的。这意味着我们的模型对它所学习的数据有很好的结果,但它有一个概括的问题,并且它在其他数据集上会有不好的结果,这显然不是目标。

3.2 构建向量

我们在这里做的是使用来自sklearnTfidfVectorizer。该功能反映了文档中单词的强度。
我们使用行tfidf = dict(zip(vectorizer.get_feature_names(), vectorizer.idf_))将所有的单词放入一个名为tfidf的向量中,如果你执行它,你可以在上面看到。这是我在 Ahmed BESBES 的博客上发现的一个提示。这真的很有趣,值得一读。

现在只是为了好玩,为了形象化,我用 WordCloud 来描绘我们字典中最重要的 100 个单词。我们可以看到像戏剧、电影、场景和故事这样的词,它们显然对关于电影评论家的数据集很重要。我使用了 Ahmed BESBES 的另一个博客来使用这个库。

Figure 5 : The most “important” words in our corpus

现在我们将构建一个函数来计算给定评论家的“平均值”。我们的 w2v_model 给了我们哪些单词彼此接近,所以对于每一个单词,我们都将它们乘以它们在“字典”中的重要性:w2v_model[word].reshape((1, size)) * tfidf[word]
注意:我们使用 reshape 函数,因为我们对语料库的每个文本都这样做,所以例如在X_train中我们有 8529 个文本,如果我们对其应用该函数,我们将得到一个二维形状矩阵(8529,300)。

  1. 8529 代表我们语料库中的文本数量
  2. 300 代表 Word2Vec 创建的向量的大小。

就这样,现在我们把它除以观察次数,我们很好地得到了所有这些的平均值。

该计算可以恢复如下:

Figure 6: Formula of the mean of the words by ponderation with their Tf-idf

其中:

  1. n是文本中的字数
  2. 对于给定的字 i ,向量 Word2Vec 的大小是 300
  3. Ti是给定字 i 的值 tfidf

现在我们将这个函数应用于我们的数据。
所以我说过,buildWordVector有两个参数,令牌,和大小。尺寸是 300 因为 word2vec 模型我们得到了 300 的形状。对于标记,它将循环增加,以覆盖我们的训练语料库的所有 8529 个文本和我们的测试语料库的 2133 个文本。

4 第一个神经网络

第一个神经网络只是一个简单的人工神经网络,只有两个密集层,为了避免过拟合,压差为 0.7。对于这一个,我们把给定评论中每个词的平均向量作为输入。

4.1 构建神经网络

下面是这个简单分类器的特征。

  • 致密层数: 2
  • 激活函数: relu,和 sigmoid 为最后一个密集层
  • 辍学: 0.7
  • 优化器: Adadelta
  • 损失:二元交叉熵

Figure 7 : summary of the classifier

4.2 训练神经网络

现在,我们使用批量为 50 的训练数据和 20 个时期来训练我们的神经网络。
做更多的历元似乎不会改变精度。使用不同的 batch_size 和时期数进行网格搜索以查看更好的参数可能是有用的。

最后,我们绘制训练的历史以观察演变,并比较训练和测试预测

Figure 8: accuracy and loss for the first classifier

最终,我们的训练精度为 0.8342,测试精度为 0.7286。这并不坏,重要的是要注意,我们没有太多的过度拟合。

5 A 卷积神经网络

CNN 主要用于图像分类,因为它可以通过模式的过滤图来识别模式。但在 2014 年,当 Yoon Kim 发表他的文章时,他表明它们也可以用于文本分类。事实上,这个想法并不完全疯狂,因为句子也有模式。

5.1 构建神经网络

首先,我们试图找到所有的参数来构建我们的神经网络。这将是一个 CNN,但不是给他一个句子中所有单词向量的意思,我们会给他一个给定句子中所有的单词向量。
还有,结构有点变化,每层神经元更多。

Figure 9: structure of our CNN

我们的神经网络与我上面描述的 Yoon Kim (2014)构建的神经网络相同。

  • 卷积层数: 3
  • 致密层数: 2
  • 特征图数量:每卷积 128
  • 激活功能: relu,和最后一个致密层的 sigmoid
  • 滤镜尺寸: 3、4、5
  • 辍学: 0.5
  • 优化器: Adadelta
  • 损失:二元交叉熵

这个 CNN 和 Yoon Kim 用的差别不大:
1。他刚有了 1 密层
2。他从来没有用过乙状结肠。他在每个卷积中使用了 100 个特征图,而不是 128 个

然而,我有更好的结果与那些小的变化,所以我保持他们那样。

为了构建它,我们需要一些参数,嵌入维数(word2vec 向量的大小),vocab 大小的最大值(我们有多少个唯一的词),以及最大序列长度(每次评论的最大字数)。
下面的代码为您提供了所有这些参数,如果您用另一个数据集测试它,只需用代码的结果更改三个变量:

现在,我们创建将在 CNN 中使用的训练和测试输入。对于少于最大字数的每个文档,我们用“0”来完成它们。这并没有改变我们的结果,因为 CNN 识别模式,无论在某一点或另一点,模式仍然是相同的。例如,对于一个图像,这意味着如果一个图像比其他图像小,我们将把它的黑色边框。这不会改变形象。

5.2 定义 CNN

汇总的结果应该如下所示:

Figure 10: Summary of the CNN

让我们进行 10 个纪元的训练课程,再来一次批量 50 个!

Figure 11: accuracy and loss for the cnn

在 10 个时期结束时,训练集的准确度为 0.915,测试集的准确度为 0.7768。我们有一点过度拟合,验证损失相当不稳定,但结果在这里。我用更多的纪元来训练它,但这似乎是我们能做到的最好的了。

6 个结论

我们可以清楚地看到 CNN 更适合这个任务,用我的其他数据帧,我个人也有同样的结果。
但是,它仍然有一个不方便的地方,它要更深,有更多的参数,并且需要更多的时间来训练。对于这个小数据集,差异并不重要,但我必须根据我的工作数据来训练它,简单的分类器需要 13 分钟训练,而 CNN 需要 5 个小时!所以要用哪个由你自己决定。
这两个分类器仍然显示出一些不错的结果,我注意到它们拥有的数据越多,文档的长度越重要,它们就越好。对于一个包含 70 000 个数据和最大长度为 2387 个文档的数据集,我的测试精度是 0.9829,这非常令人鼓舞!

7 个视角

我有两个主要的想法去尝试更好的结果。首先,使用第一个分类器,我们可以使用另一个更复杂的神经网络,如递归神经网络(CA-:使用上下文对齐的递归神经网络对句子相似性建模(陈,胡& al ., 2018).)或现在开始使用的注意网络(用于文档分类的分层注意网络(Yang & al .,2016) )。
第二个想法是针对单词嵌入,2018 年谷歌展示了一个新的模型,叫做 BERT ( BERT:用于语言理解的深度双向转换器的预训练(Devlin,Chang & al。,2018) )谁更有优势使用分割令牌。例如,如果我们的数据中有单词考古学家,它可以记住“考古”,当像“考古”这样的单词出现时,它会知道它与考古学家有关,而 word2Vec 会忽略它不认识的单词。

自然语言处理—事件提取

原文:https://towardsdatascience.com/natural-language-processing-event-extraction-f20d634661d3?source=collection_archive---------5-----------------------

从新闻文章中提取事件

每天生成的文本量令人震惊。数以百万计的数据以新闻文章、博客、消息、手稿等形式发布,自动组织和处理它们的能力变得不可或缺。

随着神经网络算法的改进,计算机能力的显著提高,以及对综合框架的轻松访问,自然语言处理似乎从未如此吸引人。它的一个常见应用称为事件提取,这是一个收集文本中发现的周期性事件的知识的过程,自动识别关于发生了什么以及何时发生的信息。

例如:

2018/10-唐纳德·特朗普总统的政府禁止各国进口伊朗石油,七个国家除外。

2019/04-美国国务卿迈克·蓬佩奥宣布,他的国家将不会在最后期限后开放更多的例外。

2019/05-美国结束了允许各国从伊朗进口石油而不受美国制裁的豁免。

这种将信息置于背景中的能力让我们能够将时间分布的事件联系起来,吸收它们的影响,以及一系列事件如何随着时间的推移而展开。这些有价值的见解推动了像 EventRegistryPrimer 这样的组织。AI ,为不同的市场领域提供技术。

在本文中,我们将构建一个简单的事件提取脚本,它接收新闻提要并输出事件。

获取数据

第一步是收集数据。它可以是任何类型的文本内容,只要它可以在时间线中表示。这里我选择使用 newsapi ,这是一个简单的新闻源 api,免费开发者计划每天最多 500 个请求。以下是为处理请求而构建的函数:

给定一个特定的查询,最后一个函数返回大约 2,000 篇文章的列表。我们的目的只是提取事件,因此,为了简化过程,我们只保留标题(理论上,标题应该包含新闻背后的核心信息)。

这给我们留下了一个类似下面的数据框,包括日期、描述和标题。

赋予句子意义

准备好标题后,我们需要用机器可读的方式来表示它们。注意,我们在这里跳过了整个预处理阶段,因为这不是本文的目的。但是如果你从 NLP 开始,确保在应用模型之前包括那些基本的预处理步骤→ 这里有一个很好的教程

为了给独立的单词赋予意义,从而给整个句子赋予意义,让我们使用 Spacy 的预训练单词嵌入模型( en_core_web_lg )。或者,您可以使用任何预先训练的单词表示模型(Word2Vec、FastText、GloVe……)。

默认情况下,Spacy 将句子的向量视为其标记向量之间的平均值。这是一种简单的方法,不考虑单词的顺序来编码句子。对于更复杂的策略,看看像 Sent2VecSkipThoughts 这样的模型。这篇关于无监督摘要的文章很好地介绍了跳过思想。

现在,让我们保持简单:

因此,每个标题都有一个第 300 维的数组,如下所示:

聚集这些向量

即使我们是通过搜索词来过滤文章,不同的主题也可能出现在同一个查询中。例如,搜索“巴黎”可能会得到:

一场毁灭性的火灾后,巴黎团结起来

或者:

巴西足球传奇人物贝利在巴黎住进医院

为了对不同主题的文章进行分组,我们将使用聚类算法。

在这个特殊的例子中,我想尝试 DBSCAN 算法,因为它不需要预先指定集群的数量。相反,它自己决定要创建多少个集群,以及它们的大小。

ε参数决定了两个样本之间的最大距离,使它们被视为处于相同的邻域中,这意味着如果 eps 太大,将形成较少的聚类,但如果太小,大多数点将被分类为不属于某个聚类,这也将导致一些聚类。下图显示了 epsilon 的集群数量:

调整 eps 值可能是最微妙的步骤之一,因为结果会根据您认为句子相似的程度而有所不同。正确的值将通过实验得出,试图保留句子之间的相似性,而不会将相近的句子分成不同的组。

一般来说,因为我们希望在同一个集群中得到非常相似的句子,所以目标应该是返回更多类别的值。因此,我选择了一个介于 0.08 和 0.12 之间的数字。查看 Scikit Learn 文档,了解更多关于该参数和其他参数的信息。

以下是一些集群及其大小:

-1 类代表没有聚类的句子,其余为聚类索引。最大的集群应该代表评论最多的主题。

让我们来看看其中的一个集群:

转换成事件

下一步是按时间顺序排列这些句子,并根据相关性进行过滤。这里,我选择每天显示一篇文章,这样时间线就清晰一致了。

由于每天都有很多关于同一主题的句子,我们需要一个标准来从中选择一个。它应该是最能代表事件本身的,也就是那些标题试图传达的意思。

为此,我们可以对每日标题进行聚类,并为每个聚类选择离聚类中心最近的标题。给定一系列句子,下面是查找中心向量的函数:

s

最后,使用 Plotly,我们可以想出一种方法来绘制一个方便的时间线图:

就是这样。使用 2000 篇随机文章,我们制作了一个脚本来提取和组织事件。想象一下,每天将这种技术应用到数百万篇文章中会有多有用。以股票市场和每日新闻的影响为例,我们可以开始窥视事件提取的价值。

可以包括几个组件来改善结果,比如适当地预处理数据,包括词性标注和 NER ,应用更好的句子到向量模型,等等。但是从这一点出发,可以很快达到一个理想的结果。

感谢你阅读这篇文章。这是一篇关注自然语言处理和事件提取的文章。如果你想了解更多关于数据科学和机器学习的知识,请确保关注我的个人资料,并随时留下任何想法、评论或担忧。

TF IDF | TFIDF Python 示例

原文:https://towardsdatascience.com/natural-language-processing-feature-engineering-using-tf-idf-e8b9d00e7e76?source=collection_archive---------0-----------------------

Photo by Raphael Schaller on Unsplash

自然语言处理(NLP)是人工智能的一个子领域,处理理解和处理人类语言。鉴于机器学习的新进展,许多组织已经开始将自然语言处理应用于翻译、聊天机器人和候选人筛选。

不再拖延,让我们深入一些代码。首先,我们将导入必要的库。

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer

在本文中,我们将使用两个简单的文档,每个文档包含一个句子。

documentA = 'the man went out for a walk'
documentB = 'the children sat around the fire'

机器学习算法不能直接处理原始文本。相反,文本必须转换成数字向量。在自然语言处理中,从文本中提取特征的一种常见技术是将文本中出现的所有单词放在一个桶中。这种方法简称为袋字模型或。它被称为一个 【袋】 的单词,因为任何关于句子结构的信息都丢失了。

bagOfWordsA = documentA.split(' ')
bagOfWordsB = documentB.split(' ')

通过将单词包转换为一个集合,我们可以自动删除任何重复的单词。

uniqueWords = set(bagOfWordsA).union(set(bagOfWordsB))

接下来,我们将为语料库(文档集合)中的每个文档创建一个单词及其出现次数的字典。

numOfWordsA = dict.fromkeys(uniqueWords, 0)for word in bagOfWordsA:
    numOfWordsA[word] += 1numOfWordsB = dict.fromkeys(uniqueWords, 0)for word in bagOfWordsB:
    numOfWordsB[word] += 1

单词袋方法的另一个问题是它没有考虑噪音。换句话说,某些单词被用来构成句子,但没有给文本增加任何语义。例如,英语中最常用的单词是,它代表了所有书面或口头单词的 7%。考虑到文本中包含单词,你无法对文本做出任何推断。另一方面,像 goodawesome 这样的词可以用来确定一个评级是否是正面的。

在自然语言处理中,无用词被称为停用词。python 自然语言工具包库提供了一个英文停用词列表。

*from nltk.corpus import stopwordsstopwords.words('english')*

通常,当以理解文本为目标构建模型时,您会看到所有停用词都被删除了。另一种策略是使用 TF-IDF 对单词的相对重要性进行评分。

词频(TF)

一个单词在文档中出现的次数除以文档中的总单词数。每个文档都有自己的词频。

以下代码在 python 中实现了词频。

*def computeTF(wordDict, bagOfWords):
    tfDict = {}
    bagOfWordsCount = len(bagOfWords)
    for word, count in wordDict.items():
        tfDict[word] = count / float(bagOfWordsCount)
    return tfDict*

下面几行计算了我们每个文档的词频。

*tfA = computeTF(numOfWordsA, bagOfWordsA)
tfB = computeTF(numOfWordsB, bagOfWordsB)*

逆数据频率(IDF)

日志中的文档数除以包含单词 w 的文档数。逆数据频率决定了语料库中所有文档中稀有词的权重。

以下代码在 python 中实现了反向数据频率。

*def computeIDF(documents):
    import math
    N = len(documents)

    idfDict = dict.fromkeys(documents[0].keys(), 0)
    for document in documents:
        for word, val in document.items():
            if val > 0:
                idfDict[word] += 1

    for word, val in idfDict.items():
        idfDict[word] = math.log(N / float(val))
    return idfDict*

所有文件的 IDF 计算一次。

*idfs = computeIDF([numOfWordsA, numOfWordsB])*

最后,TF-IDF 就是 TF 乘以 IDF。

*def computeTFIDF(tfBagOfWords, idfs):
    tfidf = {}
    for word, val in tfBagOfWords.items():
        tfidf[word] = val * idfs[word]
    return tfidf*

最后,我们可以计算语料库中所有单词的 TF-IDF 分数。

*tfidfA = computeTFIDF(tfA, idfs)
tfidfB = computeTFIDF(tfB, idfs)df = pd.DataFrame([tfidfA, tfidfB])*

我们可以使用 sklearn 提供的类,而不是自己手动实现 TF-IDF。

*vectorizer = TfidfVectorizer()vectors = vectorizer.fit_transform([documentA, documentB])feature_names = vectorizer.get_feature_names()dense = vectors.todense()denselist = dense.tolist()df = pd.DataFrame(denselist, columns=feature_names)*

这些值略有不同,因为 sklearn 使用了平滑版本的 idf 和各种其他小优化。在具有更多文本的示例中,单词的得分将大大降低。**

面向自动化特征工程的自然语言处理

原文:https://towardsdatascience.com/natural-language-processing-for-automated-feature-engineering-46a61a3930b1?source=collection_archive---------21-----------------------

如何使用 Featuretools 应用 nlp-primitives 库。

当试图在机器学习管道中利用真实世界的数据时,经常会遇到文本。文本数据可以包含许多有价值的信息,但经常被忽略,因为很难将文本翻译成算法可以解释的有意义的数字。

Featuretools原语函数用于为不同类型的数据自动创建特征,使机器学习模型能够充分利用你的数据集中的数据。

在本文中,我探索了使用 nlp-primitives 库从文本数据中创建特征,通过使用一个示例数据集来研究机器学习模型中的这些附加特征。然后,我解释为什么这些原语对模型的准确性有如此大的影响。

一个使用 nlp 原语的机器学习演示

在这个演示中,我将使用来自这个 Kaggle 数据集的数据,该数据集包含旧金山地区 57 家餐馆的 100 条评论。数据集相对较小,但足以用 Featuretools 和 nlp-primitives 库演示特征工程。您可以使用这个库中的Jupyter 笔记本继续学习。

首先,让我们确定问题:根据每个评论者的反馈,确定他们对餐厅的看法。该模型的成功与否将取决于它能在多大程度上准确预测每个评审者根据给定数据和评审给出的评级。在数据集中,评论有 5 个可能值,从 1 星到 5 星,所以问题是一个 5 类分类问题。

为了评估 NLP 原语的有效性,我还使用没有这些新原语函数的深度特征合成 (DFS)创建了一个基线特征矩阵,以便我可以看到这些新原语的有效性。利用这个基线特征矩阵,我创建了一个机器学习模型,准确率大约为 50%。

baseline_feature_matrix, baseline_features = ft.dfs(entityset=es,
                                            target_entity='reviews',
                                            verbose=True,
                                            ignore_variables=ignore)**built 33 features**base_rfc = RandomForestClassifier(n_estimators=100,
                                  class_weight = "balanced", 
                                  n_jobs=-1)
base_rfc.fit(baseline_train_fm, baseline_y_train)
base_rfc.score(baseline_test_fm, baseline_y_test)**0.5156462585034014**

这个模型预测大多数评论属于最常见的评论类别,所以它的预测不是很准确,正如你在下面的混淆矩阵中看到的。

在基线模型和使用 nlp 原语的模型之间,只有一个因素发生了变化:NLP 原语库的使用。

trans = [DiversityScore, LSA, MeanCharactersPerWord, 
         PartOfSpeechCount, PolarityScore, PunctuationCount, 
         StopwordCount, TitleWordCount, UniversalSentenceEncoder,      
         UpperCaseCount]

features = ft.dfs(entityset=es, target_entity='reviews', 
                  trans_primitives=trans, verbose=True,
                  features_only=True, ignore_variables=ignore,
                  drop_contains=drop_contains, max_depth=4)**Built 333 features**

通过 DFS 调用中的这个小变化,生成的特性数量增加了 10 倍。

这个库非常容易合并,只需要几行额外的代码就可以导入库和原语,然后将这些原语添加到ft.dfs函数用来创建特征的默认原语中。在基线模型和 nlp-图元模型中,DFS 用于查找特征,尽管 NLP-图元具有修改的深度场,允许 DFS 创建堆叠在 NLP 特征之上的图元。

在运行 DFS 并创建结果特征矩阵后,我们可以将数据分成训练集和测试集,并在 sklearn 机器学习模型中使用这些集来测试它们的准确性。

vot = VotingClassifier(voting='soft', 
                       estimators=[('lgr', lgr),('rfc', rfc),   
                                  ('hgbc', hgbc)],
                       weights=[3, 1, 6])
vot.fit(train_feature_matrix, y_train)
vot.score(test_feature_matrix, y_test)**0.6925170068027211**

当使用 nlp-primitives 库时,模型能够实现大约 70%的准确性,混淆矩阵被准确地分布(深蓝色表示猜测),大多数不正确的猜测非常接近实际答案(1-由更明显的对角线上的深蓝色表示)(完美的算法将在向下的对角线上有 1,表示预测和真实标签一致,在每个其他类别中有 0-了解更多关于混淆矩阵的信息此处)。

这两个模型使用相似的训练和测试步骤(基线模型使用稍微不太复杂的函数,因为更复杂的函数不会改变准确性),但是具有 NLP 功能的模型的准确性比基线高大约 40%。由于其他一切都保持不变,很明显 NLP 原语库是准确性大幅提高的原因。此外,当我们检查特性重要性时,我们看到使用 NLP 原语的特性排名最高(更多详细信息,请参见笔记本)。

为什么这些原语会有所不同?

数据必须格式化为数字,以便机器学习模型从中“学习”。文字很难放进数字,或者至少很难放进数字而不失去很多意义。例如,获得一段文本的字数是相当简单的,但是,通常这并不是一个足够的意义度量。尽管这有时可能是一个有用的功能,但文本的意义远不止它包含的字数。

那么,解决办法是什么呢?如何以有意义的方式将文本编码成数字?一种解决方案是将文本的含义矢量化。NLP 原语,如 UniversalSentenceEncoder、LSA(潜在语义分析)和 PartOfSpeechCount 都使用这种方法。它们都是多输出原语,这意味着它们接受一个字段并创建一个具有多个字段的要素。在这种情况下,这些字段表示向量的维数。在下面的例子中,每个文本字符串对应两个输出,因为 LSA(潜在语义分析)为每个给定的字符串创建一个长度为 2 的向量。

from nlp_primitives import LSA
import pandas as pd
data = ["hello, this is a new featuretools library",
        "this will add new natural language primitives",
        "we hope you like it!"]
lsa = LSA()
pd.DataFrame(lsa(data).tolist()).T

在下一个示例中,原语 PartOfSpeechCount 为每个输入生成 15 个值。这个向量的每个维度代表一个词性,以及该词性在输入文本字段中出现的次数。

from nlp_primitives import PartOfSpeechCount
data = ["hello, this is a new featuretools library",
        "this will add new natural language primitives",
        "we hope you like it!"]
pscount = PartOfSpeechCount()
pd.DataFrame(pscount(data).tolist()).T

这些原语以这样一种方式对向量中文本字段的含义进行编码,即具有相似含义的两个文本字段具有相似的向量,即使它们由不同的单词组成。这使得这些方法特别有用,因为以类似方式编码类似含义的能力允许机器学习模型学习特定向量的结果,并将该向量的结果与类似向量相关联。

然而,处理许多输出常常是具有挑战性的,尤其是当试图堆叠原语时——将一些原语的输出用作其他原语的输入。当存在许多实体或数据源时,这会产生更多的信息。Featuretools 很好地处理了这一点,这使用户能够跨实体以及在实体内收集信息,以最大限度地利用当前数据。Featuretools 自动【堆叠】图元的能力进一步增强了这一点,甚至在特征工程步骤中进一步扩展了任何单个图元转化特征的能力。

关键要点

  1. NLP-primitives 库在处理文本数据时增强了模型的准确性。这种额外的准确性源于对文本含义的编码,而不仅仅是计算简单的描述性指标。
  2. 使用正确的工具使机器学习过程变得更容易。当我们修改了几行代码来合并 nlp-primitives 库时,准确性提高了,而代码的复杂性保持不变。
  3. 正确性可以通过多种方式进行评估。当一个模型不准确的时候,理解哪里出了问题是很重要的——它仅仅是错误的(像基线模型)还是错误的,但接近正确的(像 nlp-primitives 模型)?

最后的想法

这个库已经发布,可以独立安装或者通过使用pip的功能工具安装。但是,它仍处于发展的初级阶段,我们欢迎任何关于它的反馈。此外,自然语言处理领域是一个快速发展的领域,所以如果您看到一个添加新原语的机会,请作为 GitHub 问题提出建议,或者尝试自己创建——该库是开源的,因此任何人都可以做出贡献!

原载于 2019 年 8 月 23 日https://blog.featurelabs.com

“神经概率语言模型”中的自然语言处理

原文:https://towardsdatascience.com/natural-language-processing-in-a-neural-probabilistic-language-model-a-summary-19c9cd7cf6c4?source=collection_archive---------29-----------------------

Credit: smartdatacollective.com

这是 PLN(计划):在 Bengio 等人于 2003 年提出的名为 NPL(神经概率语言)的模型中,通过概率的镜头讨论 NLP(自然语言处理)。论文发表的那一年对于一开始就考虑是很重要的,因为它是我们如何使用计算机分析人类语言的历史上的一个支点时刻。诺姆·乔姆斯基的语言学可以被看作是像机器一样使用人类大脑并系统地将语言分解成越来越小的成分的努力。他从句子开始,到单词,然后是语素,最后是音素。计算机化利用了这个强大的概念,并使它成为对人类更重要的东西:它从与个人相关开始,到团队,然后到公司,最后到政府。乔姆斯基博士真正改变了我们交流的方式,这种影响至今仍能感受到。语言学刚引入的时候很强大,今天也很强大。N-gram 分析,或者任何一种计算语言学,都来源于这位伟人,这位先行者的工作。本博客将总结本吉奥小组的工作,他们是思想领袖,高举知识的火炬,推进我们对自然语言以及计算机如何与之交互的理解。

自 2003 年以来,人工智能已经发生了巨大的变化,但本文提出的模型抓住了它为什么能够起飞的本质。自从这篇论文发表以来,机器学习和深度学习都已经成为人工智能经典的一部分,随着计算能力的不断增长,它们变得越来越重要。数据科学是多个领域的融合,今天我们将考察作为该学科基石的一个领域:概率。本文提出的概率分布模型,本质上是我们提高处理自然语言能力的主要原因。

英语,被认为是所有字母语言中单词最多的,是一个概率噩梦。甚至在最基本的句子中排列单词组合的可能性也是不可思议的。我们正面临着所谓的维度的诅咒。为了更具体地说明这一点,作者提供了以下内容:

…如果想要对自然语言中 10 个连续单词的联合分布进行建模,并且词汇量 v 的大小为 100,000,则可能存在 100,000^10 1 = 10^50 1 自由参数。

在数据驱动的自然语言处理任务中,实际上存在无限的离散变量,因为英语词汇的数量以指数形式超过 100K。当试图比较被分成训练集和测试集的数据时,你怎么能期望提出一个容易概括的语言模型呢?你的数据中的这两个部分几乎肯定是非常不同的,非常不可概括的。你被模型中大量的可能性,大量的维度所诅咒。能做些什么?

本吉奥小组的创新不是通过使用神经网络,而是通过大规模使用它们。语言学及其创始人诺姆倾向于了解一个词如何与句子中的所有其他词相互作用。Bengio 等人专注于学习单词序列分布的统计模型。该研究论文首先通过不考虑给定单词如何与同一个句子中的其他单词相似,而是考虑可以填充给定单词角色的新单词来改进 NLP。其次,他们考虑了 n 元语法方法,超出了单元语法( n = 1)、二元语法( n = 2)甚至三元语法(研究人员通常使用的 n )直到 5 的 n

n 元模型的数学公式如下:

该公式用于为要预测的下一个单词构建条件概率表。当对 NLP 建模时,可以通过利用单词顺序,以及通过认识到单词序列中时间上更接近的单词在统计上更具依赖性,来提高对抗维数的几率。在所讨论的上下文中,这最终意味着什么?这是在解决什么问题?提出的语言模型减少了维数灾难,增加了不便。也就是说,计算和存储复杂性是以线性方式而非指数方式增长的。它通过学习每个单词的特征向量来表示相似性,并通过神经网络学习单词如何连接的概率函数,从而改进了过去的工作。让我们仔细看看所说的神经网络。

我们现在看到的是一种叫做多层感知器的东西。那些层是什么?三个输入节点构成了底部的基础,由所研究文本上下文中单词的索引提供。中间标记为 tanh 的层代表隐藏层。Tanh 是一种称为 hyberbolic tangent 的激活函数,是 s 形的,有助于减少在为正在处理的语言赋值时模型“卡住”的机会。这是怎么回事?在该研究团队建立的系统中,负值很大的值被赋予非常接近-1 的值,反之亦然。只有零值输入被映射到接近零的输出。最上层是输出,即 softmax 函数。它用于将我们的值范围带入概率领域(在从 0 到 1 的区间内,其中所有向量分量的总和为 1)。

也不要忽略将输入直接连接到输出的绿色虚线。该特性的可选包含在本文的结果部分中提出。它提供了一个有趣的权衡:包括输入和输出之间的直接连接导致训练时间减半(10 个时期收敛而不是 20 个)。没有它们,模型通过隐藏层中形成的更紧密的瓶颈产生更好的概括。

如果一个句子中包含的单词与之前观察到的单词相似,则该句子有可能获得高概率(即使模型之前从未遇到过它)。难就难在:诺姆·乔姆斯基和后来的语言学家受到批评,说他们发展的系统太脆弱了。这种方法为一种新的学习——深度学习——奠定了基础。当与向量语义结合使用时,这确实是强大的东西。通过这篇论文,Bengio 团队打开了通往未来的大门,并帮助开创了一个新时代。一个 AI 的时代。

作品引用:

一个神经概率语言模型,Bengio 等人。

试图在 5 篇论文中描述 NLP 的历史:第二部分。

https://theclevermachine.wordpress.com/tag/tanh-function/

银行业务中的自然语言处理:当前应用

原文:https://towardsdatascience.com/natural-language-processing-in-banking-current-uses-7fbbaee837de?source=collection_archive---------6-----------------------

银行应用自然语言处理的三个领域

Photo by Jordan on Unsplash

银行正在使用一种称为自然语言处理(NLP)的人工智能分支来自动化某些文档处理、分析和客户服务活动。三种应用包括:

  • 智能文档搜索:在大量扫描文档中查找相关信息。
  • 投资分析:自动化收益报告和新闻的常规分析,以便分析师可以专注于阿尔法世代。
  • 客服&洞察:部署聊天机器人回答客户查询,了解客户需求。

我们将讲述银行在这些领域所做工作的真实例子。首先,让我们回顾一下自然语言处理的能力。

自然语言处理导论

自然语言处理(NLP) 是人工智能的一个分支,使计算机能够理解人类的语言,并做出类似的反应。这包括训练计算机处理文本和语音,并在上下文中解释单词、句子和段落的含义。

人机交互

人机“对话”可以分解如下(我们稍后会谈到具体的人工智能方法):

  1. 我们提供文本或语音输入(例如,键入聊天机器人界面或与智能扬声器交谈)。
  2. 计算机将文本/语音转换成它能理解的格式(例如,将语音转换成文本,将单词转换成矢量)。这有助于计算机对不同的单词进行聚类和分类。
  3. 计算机使用自己的数据集计算出意思和上下文。
  4. 计算机确定一个适当的反应,并将其转换成我们理解的文本或语音,并对我们做出反应。

我们每天都与使用自然语言处理的应用程序进行交互:

  • 谷歌翻译:我们输入文本和语音,谷歌为我们翻译。
  • Gmail 智能撰写:你可能会注意到 Gmail 会提示你已经开始输入的句子的剩余部分。此功能使用电子邮件主题和以前的电子邮件来建议相关文本。有点吓人,但也有点酷。
  • 语法上:你使用的流行的语法检查工具,因为它比微软 Word 的拼写检查好得多。
  • 智能音箱:不,你和 Alexa 的对话并不神奇(抱歉)。

理解、处理和生成语言

自然语言处理实际上是一个包含两种相关方法的总称:自然语言理解自然语言生成

自然语言理解(NLU)指出文本和语音背后的含义。把这个当成阅读或者听力。这包括从人类那里获取非结构化的文本和语音输入,并将其转换为计算机可以理解的结构化格式。例如,当你向 Alexa 请求天气预报时,它会使用自然语言理解来判断你在说什么。

自然语言生成(NLG)是指计算机生成的文本和语音。NLG 将结构化数据转化为人类能够理解的文本和语音。继续我们之前的例子,Alexa 在回应“今天天气晴朗”时使用自然语言生成。你想订购太阳镜吗?

用于自然语言处理的人工智能方法

自然语言处理经常与其他人工智能方法一起使用,如神经网络深度学习光学字符识别。两个流行的自然语言模型是 Word2vec单词包。

在没有获得技术的情况下,神经网络是机器学习的子集。当用于自然语言处理时,它们可以处理文本,对单词进行分类,对相似的单词进行聚类,并将单词和短语与含义相关联。也使用深度学习方法(即多层神经网络),如递归神经网络

光学字符识别(OCR)使计算机能够识别扫描文档中的文本。OCR 可以与自然语言处理一起使用,以分析扫描的文档或手写文本。

各种自然语言技术用于确定语法规则和词义。语法分析涉及确定单词的语法规则,并根据相似度对其进行聚类。语义分析涉及推导意义,用于生成人类语言。语义分析很有挑战性,因为人类语言规则很复杂。单词和短语在不同的上下文中有不同的含义。俗语、习语和讽刺使事情更加复杂。

单词袋相关算法是流行的自然语言技术,通过类别或类型对短语和文档进行分类。单词包简单地统计每个单词在文档中出现的频率(计数)。该算法然后比较文档并确定每个文档的主题。这可以用来训练神经网络。Gmail 的 Smart Compose(前面提到过)使用了谷歌的单词包和递归神经网络模型。搜索引擎也使用这些技术。

Word2vec 是另一种流行的自然语言模型。它是一个两层神经网络对文本进行分类以确定含义。它将单词转换成计算机可以理解的数学“向量”。矢量转换是必需的,因为神经网络更好地处理数字输入。

给定足够大的数据集,代表相似单词的向量被分组在一起——相似单词被数学地检测。如果部署得当,Word2vec 可以根据过去的外观高精度地推断单词含义。这对于文档搜索、情感分析,甚至建议接下来应该用哪些词来完成一个句子都很有用。

银行如何使用自然语言处理

Image by Author

银行可以对大量文本和语音数据应用自然语言处理,以提取信息、获得洞察力并简化手动任务。虽然节省时间和成本是显而易见的好处,但识别关键信息的能力(众所周知的大海捞针)可以成为一个有竞争力的差异制造者。

以下是银行应用自然语言处理的三个领域。

智能文档搜索

摩根大通的 COIN (合同智能)软件使用自然语言处理来帮助银行的法律团队搜索和审查大量的法律文件。

据报道,COIN 每年可以为银行的法律团队节省 360,000 小时或 15,000 天的文档搜索任务。例如,它可以提取关键数据和条款来帮助信贷员审查商业贷款协议。

COIN 显然受过训练,能够识别银行法律团队标记为重要的文档中的关键信息(属性)。这使得软件能够从结构不同的文档中提取关键信息。该银行声称,它在几秒钟内从 12,000 份商业信贷协议中提取了 150 个相关属性。

该软件的工作是不公开的,因为是内部使用。我们可以推测,它可以由自然语言处理(在文档中搜索)、光学字符识别(识别扫描文档中的字符)和机器学习(对文档中的数据进行分类和聚类,并随着时间的推移改进搜索算法)来驱动。

这些方法可以应用于其他银行活动。它可以帮助银行提取他们没有时间跟踪的客户数据类型。这些数据有助于预测客户需求和识别交叉销售机会。它还可以加快需要文档分析的“了解您的客户”( KYC)流程,从而使客户的加入更加容易。

投资分析

银行的证券研究部门正在使用自然语言处理在堆积如山的公司报告和电话会议中寻找有价值的见解。

银行以前雇佣大量分析师来梳理收益报告和其他文件,并将相关数据输入数据库和估值模型。

现在,银行正在使用自然语言处理工具,一次“阅读”数百份文件,并为人类分析师总结关键信息。语音分析工具可以“倾听”分析师电话会议,以确定公司管理层讲话背后的语气和情绪,这可以为股票分析提供洞察力。这些工具节省了大量的时间,并允许分析师专注于 alpha 生成。

银行也使用自然语言处理进行情绪分析。这些工具分析大量新闻和社交媒体帖子,以提取关键见解,确定公司的观感,或跟踪市场对重大事件的反应。这些及时的见解可以为分析师的建议提供信息。

银行要么使用内部开发的工具,要么使用供应商开发的工具。一家供应商 Dataminr 声称可以分析社交媒体和金融新闻,以识别相关信息,包括意想不到的新闻、新兴趋势或风险。

[## 实时事件和风险检测

Dataminr 的客户最先知道关键事件和突发信息,使他们能够更快地采取行动…

www.dataminr.com](https://www.dataminr.com/)

例如,在卖方,自然语言生成工具会根据收益报告和新闻自动生成报告。

客户服务和见解

各大银行正在通过聊天机器人引入某种程度的客户服务自动化。2019 年初,美国银行推出了移动虚拟助理 Erica ,通过美国银行的移动应用程序,很快积累了超过百万用户

Erica 接受语音和文本命令,并将预测分析与自然语言处理相结合,以帮助客户:

  • 检查余额并转账
  • 按需搜索过去的交易和账户信息
  • 跟踪消费习惯(可能使用预测分析,这是一种鼓励更多使用聊天机器人的增值)
  • 帮助客户管理经常性付款或逾期付款

聊天机器人让客户可以在手机上访问账户信息和进行基本交易,而不是使用网上银行或访问当地分行。通过干净的聊天机器人界面执行交易也可能花费更少的时间。

对银行来说,一个更大的胜利将是使用自然语言处理进行客户洞察。使用上述智能文档搜索和情感分析相关方法,银行可以更好地了解和预测客户需求和痛点。情绪分析工具可以监控社交媒体,了解人们对这家银行的看法。文档搜索工具可以分析反馈表和客户信息,以应对问题,提供定制产品,并增加客户保留率。

银行高管的关键要点

银行业领导人意识到,自然语言处理可以实现日常文档分析、研究和客户服务的自动化。

节约成本只是冰山一角。通过更快地分析文本和语音数据,并提取更多关于客户和市场的可行见解,银行可以更好地为客户服务,并做出更好的投资。更大的市场份额和收入的潜力是真正的差异制造者。

虽然我们没有涵盖所有可能的用例,但银行可以将自然语言技术应用于任何处理大量文本或语音数据的功能。例如,在合规、风险管理或订单执行方面有许多应用。

关键考虑因素包括是否在内部构建人工智能和自然语言处理工具,或者从人工智能供应商那里获得软件许可。内部建设需要数据科学家、开发人员和有组织的人工智能战略。虽然这需要时间,但内部开发的解决方案可能比供应商产品更能满足银行的需求。此外,还必须解决跨部门的数据质量和可用性问题。

鉴于自然语言处理可以应用于广泛的银行活动,跨部门应用这些解决方案的银行可能会看到更大的投资回报。

自然语言处理:概述《权力的游戏》的剧本

原文:https://towardsdatascience.com/natural-language-processing-summarizing-the-script-of-game-of-thrones-part-ii-7054839b973a?source=collection_archive---------24-----------------------

这篇文章将使用“现成的”数据科学工具,使用 Trifacta 、数据争论软件和 SkipThoughts 来更好地理解《权力的游戏》。

GOT Script

这篇文章的灵感来自于下面这篇文章中提供的代码: 使用句子嵌入的无监督文本摘要 。本帖包含完整的代码和对实现的详细解释。

然而,这篇文章是在几封短邮件上实现的,所以我对这些技术如何有效地应用于更长更复杂的文本很感兴趣。

包含第七季剧集的剧本可以在 Kaggle 上的这里找到。

仅供参考,一个 Amazon EC2 p2.xlarge 实例断断续续使用了大约一周,粗略估计成本不超过 15 美元。我在使用较小的实例时遇到了超时问题。使用 p2.xlarge,执行在这里找到的笔记本需要大约半个小时。

计算时间不包括为模型定型所花费的计算时间。该模型在 BookCorpus 数据集上进行训练,该数据集包含来自 16 种不同流派的超过 11,000 本书籍。

SkipThoughts 论文陈述了具有 2400 尺寸的单跳、单向编码器和包含具有 1200 尺寸的前向和后向编码器的双跳、双向编码器模型总共花费了四周的时间进行训练。(En 编码器型号 s)

bi-skip 型号包含两个具有不同参数的编码器:一个编码器以正确的顺序给出句子,而另一个编码器以相反的顺序给出句子。然后将输出连接起来形成一个 2400 维的向量。

即使使用扩展的 BookCorpus 仍然有可能没有包括一些单词,为了解决这个问题,使用了 word2Vec 嵌入,并将其映射到包含在 BookCorpus 词汇表中的单词。

如前所述,可以在上面提到的帖子中找到总结文本所需的 NLP 管道的更好、更全面的解释。但是,该逻辑的高级描述如下:

  1. 将文本分词成句子
  2. 将每个句子编码成一个向量,(创建每个句子的数字表示)
  3. 聚类得到的句子嵌入;每个簇代表一个主题句。然后,概要由每个聚类的一个主题句组成,并且每个主题句代表来自原始文本内的所有最相似的句子嵌入。

第一季的每一集都在这个笔记本里有总结,下面包括的一个总结是关于 is 第一季第一集原文的 10% :

This stitch is very... - It's beautiful. I saw the white walkers. Get back on your horse. A man of his... stature? Go on. - Quick, Bran! What is it? Viserys of House Targaryen, the third of his name, the rightful King of the Andals and the First Men, and his sister, Daenerys of House Targaryen. Would you please shut up? It won't be long now. They murdered the last Hand. ...King of the Andals and the First Men... - Father will know if you do. he showed me What was what. No, Your Grace. - Oh. Hey, Hey, Hey, hey. Ned. Who have we here? - No? Go on, Tommy, shear him good. Your Grace. The Dothraki are not known for their punctuality. It's a direwolf. I'm a Northman. Winter is coming. You should be the Hand of the King. Lord Eddard Stark... Now you want Ned to take the job? Of course, they will behead you as a deserter. And I know I'm a deserter. I hear he's more than earned it. - And you never worry about anything. Soon? Where's the Imp? I want to pay my respects. Why is your mother so dead set on us getting pretty for the king? Arya! Thank you for saying yes. - Your Grace. Uncle Benjen. Did I offend you? - Thank you. A different time. I know what I'm putting you through. - Don't get up. It's Maester Luwin, my lord. The king rode for a month to ask for Lord Stark's help. Lady Stark thought it might insult the royal family to seat a bastard in their midst. I take you for a king. I don't know how to say "thank you" in Dothraki. Is this your first time in the North, Your Grace? Jadi, zhey Jorah andahli! No. She always does it and it's not funny! Thank you, ser. - He saw us.

这段文字也来自第一季第一集第 17 集,然而这段摘要只代表了原文的 30%。这种方法在一个方面稍加修改。在开始编码步骤之前,整个段落被分成 4 个相等的部分(桶),并且每个桶被单独处理。每个部分产生的主题句加在一起。这个微小的修改使得 simplify 试图对结果摘要的顺序有更多的控制。

第一集更长的摘要如下…

'They won't trouble us no more.You don't think he'll ask us how they died?Get back on your horse.Whatever did it to them could do it to us.They even killed the children.It's a good thing we're not children.You want to run away south, run away.Of course, they will behead you as a deserter.If I don't catch you first.Get back on your horse.I won't say it again.Your dead men seem to have moved camp.They were here.See where they went.What is it?It's...Go on, Father's watching.And your mother.Fine work, as always. They won't last without their mother.- Right. "Our way is the old way"?The man who passes the sentence should swing the sword.Is it true he saw the white walkers?The white walkers have been gone for thousands of years.So he was lying?A madman sees what he sees.What is it?Mountain lion?There are no mountain lions in these woods.It's a freak.It's a direwolf.Tough old beast.There are no direwolves south of the Wall.Now there are five.You want to hold it?Where will they go?Their mother's dead.They don't belong down here.Better a quick death. "What if Jon Arryn told someone? - we should head back to the Wall.Do the dead frighten you?Our orders were to track the wildlings.We tracked them.'   'Our way is the old way"?The man who passes the sentence should swing the sword.Is it true he saw the white walkers?The white walkers have been gone for thousands of years.So he was lying?A madman sees what he sees.What is it?Mountain lion?There are no mountain lions in these woods.It's a freak.It's a direwolf.Tough old beast.There are no direwolves south of the Wall.Now there are five.You want to hold it?Where will they go?Their mother's dead.They don't belong down here.Better a quick death. - But who would he tell?My husband.If he told the king, both our heads would be skewered on the city gates by now.Whatever Jon Arryn knew or didn't know, it died with him.And Robert will choose a new Hand of the King,someone to do his job while he's off fucking boars and hunting whores.Or is it the other way around?And life will go on.You should be the Hand of the King.That's an honour I can do without.Their days are too long,their lives are too short.All these years,and I still feel like an outsider when I come here.You have five northern children.You're not an outsider.I wonder if the old gods agree.It's your gods with all the rules.I am so sorry, my love.- Tell me. They won't last without their mother.- Right. - There was a raven from King's Landing.Jon Arryn is dead.A fever took him.I know he was like a father to you.- Your sister, the boy? - They both have their health,gods be good.The raven brought more news.The king rides for Winterfell...' 'Our way is the old way"?The man who passes the sentence should swing the sword.Is it true he saw the white walkers?The white walkers have been gone for thousands of years.So he was lying?A madman sees what he sees.What is it?Mountain lion?There are no mountain lions in these woods.It's a freak.It's a direwolf.Tough old beast.There are no direwolves south of the Wall.Now there are five.You want to hold it?Where will they go?Their mother's dead.They don't belong down here.Better a quick death. I won't say it again.Your dead men seem to have moved camp.They were here.See where they went.What is it?It's...Go on, Father's watching.And your mother.Fine work, as always. - But who would he tell?My husband.If he told the king, both our heads would be skewered on the city gates by now.Whatever Jon Arryn knew or didn't know, it died with him.And Robert will choose a new Hand of the King,someone to do his job while he's off fucking boars and hunting whores.Or is it the other way around?And life will go on.You should be the Hand of the King.That's an honour I can do without.Their days are too long,their lives are too short.All these years,and I still feel like an outsider when I come here.You have five northern children.You're not an outsider.I wonder if the old gods agree.It's your gods with all the rules.I am so sorry, my love.- Tell me. They won't last without their mother.- Right. "What if Jon Arryn told someone?' 'Our way is the old way"?The man who passes the sentence should swing the sword.Is it true he saw the white walkers?The white walkers have been gone for thousands of years.So he was lying?A madman sees what he sees.What is it?Mountain lion?There are no mountain lions in these woods.It's a freak.It's a direwolf.Tough old beast.There are no direwolves south of the Wall.Now there are five.You want to hold it?Where will they go?Their mother's dead.They don't belong down here.Better a quick death. - No!Put away your blade.- I take orders from your father, not you. He's got hundreds of people. - But who would he tell?My husband.If he told the king, both our heads would be skewered on the city gates by now.Whatever Jon Arryn knew or didn't know, it died with him.And Robert will choose a new Hand of the King,someone to do his job while he's off fucking boars and hunting whores.Or is it the other way around?And life will go on.You should be the Hand of the King.That's an honour I can do without.Their days are too long,their lives are too short.All these years,and I still feel like an outsider when I come here.You have five northern children.You're not an outsider.I wonder if the old gods agree.It's your gods with all the rules.I am so sorry, my love.- Tell me. - I'm told he drinks all night.How much could he possibly drink?'

此外,第一季每一集的摘要都可以在这个笔记本中找到。

参考文献:

SkipThoughts 论文

SkipThoughts Github

**@article{zhu2015aligning,
    title={Aligning Books and Movies: Towards Story-like Visual Explanations by Watching Movies and Reading Books},
    author={Zhu, Yukun and Kiros, Ryan and Zemel, Richard and Salakhutdinov, Ruslan and Urtasun, Raquel and Torralba, Antonio and Fidler, Sanja}, journal={arXiv preprint arXiv:1506.06724}, year {2015}
}**

使用斯坦福 CoreNLP 的自然语言处理

原文:https://towardsdatascience.com/natural-language-processing-using-stanfords-corenlp-d9e64c1e1024?source=collection_archive---------7-----------------------

只用两行代码分析文本数据

介绍

使用斯坦福的 CoreNLP 分析文本数据使文本数据分析变得简单高效。只需几行代码,CoreNLP 就可以提取所有类型的文本属性,比如命名实体识别或词性标注。CoreNLP 是用 Java 编写的,需要在您的设备上安装 Java,但它为几种流行的编程语言提供了编程接口,包括 Python,我将在本演示中使用 Python。此外,它还支持英语以外的四种语言:阿拉伯语、中文、德语、法语和西班牙语。

一、如何安装 CoreNLP

首先,我们要下载 CoreNLP。如果您使用的是 MacBook,请打开终端,输入以下代码行,然后按回车键:

**wget** https://nlp.stanford.edu/software/stanford-corenlp-full-2018-10-05.zip https://nlp.stanford.edu/software/stanford-english-corenlp-2018-10-05-models.jar

这将开始下载 CoreNLP 的最新版本(截至 2019 年 2 月为 3.9.2)。您应该会在屏幕上看到类似这样的内容:

下载 CoreNLP 需要一段时间,取决于您的互联网连接。下载完成后,剩下的工作就是用以下命令解压文件:

**unzip** stanford-corenlp-full-2018-10-05.zip
**mv** stanford-english-corenlp-2018-10-05-models.jar stanford-corenlp-full-2018-10-05

命令 mv A B 将文件 A 移动到文件夹 B,或者将文件名从 A 改为 B

二。启动服务器并安装 Python API

为了能够使用 CoreNLP,您必须启动服务器。这样做非常简单,因为您所要做的就是移动到步骤 1 中创建的文件夹中,并使用 Java 运行 CoreNLP。让我们看看为此需要的命令:

**cd** stanford-corenlp-full-2018-10-05
**java -mx6g** -cp "*" edu.stanford.nlp.pipeline.StanfordCoreNLPServer **-timeout 5000**

cd 命令打开我们创建的文件夹。然后,为了运行服务器,我们使用 Java。参数**-mx6g** 指定 CoreNLP 允许使用的内存量。在这种情况下,它是 6gb。**-timeout 5000** 参数以毫秒为单位指定超时时间。

现在,您应该看到类似这样的内容:

在 Python 中使用 CoreNLP 时,我所强调的数字将非常重要。

在开始分析文本之前,最后需要安装一个 Python API:

**pip install** pycorenlp

我将使用 py-corenlp,但是还有其他 Python 包,您可以在这里查看。如果您碰巧是 NLTK 的狂热用户,也有一个 NLTK API 可以让您使用 CoreNLP。完整的说明可以在这里找到。

三。带核心语言的语言

安装完 CoreNLP 后,我们终于可以开始分析 Python 中的文本数据了。首先,让我们导入 py-corenlp 并初始化 corenlp。这就是我上面强调的数字发挥作用的地方:

**from** pycorenlp **import** StanfordCoreNLPnlp = StanfordCoreNLP('[http://localhost:**9000**'](http://localhost:9000'))

NLTK 中的语法非常相似:

**from** nltk.parse **import** CoreNLPParser

result = CoreNLPParser(url='http://localhost:**9000**')

本演示的其余部分将集中在 py-corenlp 上,但是正如上面指出的,您也可以使用 NLTK。这两者之间的主要区别是,在 py-corenlp 中,输出一个原始的 JSON 文件,然后您可以用它来提取您特别感兴趣的内容,而 NLTK 为您提供了这样做的函数。

使用 py-corenlp 执行 NLP 所需的唯一其他函数是**nlp.annotate()** 。在函数内部,可以指定 CoreNLP 应该执行什么样的分析。在这个演示中,我将看看四个不同的句子,它们有着不同的情感。所有这些都可以在一行代码中完成,但是出于可读性的考虑,最好将其扩展到几行。

text = "This movie was actually neither that funny, nor super witty. The movie was meh. I liked watching that movie. If I had a choice, I would not watch that movie again."result = nlp.annotate(text,
                   properties={
                       'annotators': 'sentiment, ner, pos',
                       'outputFormat': 'json',
                       'timeout': 1000,
                   })

注释器参数指定 CoreNLP 将要做什么样的分析。在这种情况下,我已经指定让 CoreNLP 进行情感分析以及命名实体识别和词性标注。JSON 输出格式将允许我轻松地对结果进行索引,以便进一步分析。

情感分析

CoreNLP 的情感分析非常简单。运行完上面的代码块后,就不需要进一步的计算了。让我们看看上面定义的四个句子的结果:

for s in result["sentences"]:
    print("{}: '{}': {} (Sentiment Value) {} (Sentiment)".format(
        s["index"],
        " ".join([t["word"] for t in s["tokens"]]),
        s["sentimentValue"], s["sentiment"]))

运行这个 for 循环输出情感分析的结果:

0: 'This movie was actually neither that funny , nor super witty.': 1 (Sentiment Value) Negative (Sentiment)1: 'The movie was meh.': 2 (Sentiment Value) Neutral (Sentiment)2: 'I liked watching that movie.': 3 (Sentiment Value) Positive (Sentiment)3: 'If I had a choice , I would not watch that movie again.': 1 (Sentiment Value) Negative (Sentiment)

情绪值的范围从 0 到 4。零意味着这个句子非常消极,而四意味着它非常积极。如你所见,CoreNLP 做得非常好。第一句话很棘手,因为它包含了像“滑稽”或“机智”这样的积极词汇,然而,CoreNLP 正确地意识到它们被否定了。较简单的句子也能正确分类。

当试图理解这些分类时,另一个选择是看一看情绪分布,其范围也是从零到四。我们来看看第二句的情绪分布:

如您所见,分布峰值在情感值 2 附近,因此可以归类为中性。

词性标注

词性标注,就像情感分析一样,不需要任何额外的计算。与上面的代码块类似,检索所需信息所需要的只是一个 for 循环:

pos = []
for word in result["sentences"][2]["tokens"]:
    pos.append('{} ({})'.format(word["word"], word["pos"]))

" ".join(pos)

运行该代码将返回以下内容:

'I (PRP) liked (VBD) watching (VBG) that (IN) movie (NN) . (.)'

括号中的缩写代表 POS 标签,遵循 Penn Treebank POS 标签集,您可以在这里找到。给你一个直觉,PRP 代表人称代词,VBD 代表过去时态的动词,NN 代表名词。

命名实体识别

CoreNLP 的另一个可能用途是命名实体识别。为了让命名实体识别更有意义,让我们创建一个新句子:

吉姆在美国芝加哥机场逛苹果店时给杰西卡买的耳机很棒

同样,我们需要做的就是定义一个 for 循环:

pos = []
for word in result["sentences"][1]['tokens']:
    pos.append('{} ({})'.format(word['word'], word['ner']))

" ".join(pos)

运行上面的代码会得到以下结果:

'The (O) earphones (O) Jim (PERSON) bought (O) for (O) Jessica (PERSON) while (O) strolling (O) through (O) the (O) Apple (ORGANIZATION) store (O) at (O) the (O) airport (O) in (O) Chicago (CITY) , (O) USA (COUNTRY) , (O) was (O) meh (O) . (O)'

我们可以看到,CoreNLP 已经正确地识别出 Jim 和 Jessica 是人,Apple 是组织,芝加哥是城市,美国是国家。

在解释如何关闭服务器之前,我想指出 CoreNLP 提供了许多其他功能(词汇化、词干化、标记化等。)都可以被访问,而不必运行任何额外的计算。可以在 处找到**nlp.annotate()** 所有参数的完整列表。

四。关闭服务器&结论

如果您想关闭服务器,请导航到您之前用来启动服务器的终端窗口,然后按**Ctrl + C**

总而言之,CoreNLP 的效率是它如此方便的原因。您只需指定一次您感兴趣的分析,并避免不必要的计算,这些计算可能会在处理较大的数据集时降低您的速度。如果你想知道更多关于 CoreNLP 如何工作的细节以及有哪些选项,我推荐你阅读文档

参考文献:

[1] Manning、Christopher D .、Mihai Surdeanu、John Bauer、Jenny Finkel、Steven J. Bethard 和 David McClosky,斯坦福 CoreNLP 自然语言处理工具包 (2014),计算语言学协会第 52 届年会会议录:系统演示,第 55–60 页

[2] Taylor A .、Marcus M .、Santorini B .,宾夕法尼亚树库:概述 (2003),文本、语音和语言技术,第 20 卷

用脸书的快速文本(自然语言处理)介绍文本分类

原文:https://towardsdatascience.com/natural-language-processing-with-fasttext-part-1-an-intro-to-text-classification-with-fasttext-11b9771722d8?source=collection_archive---------12-----------------------

快速文本系列

一个初学者友好的文本分类库。

最初发表于我的博客

文本分类是机器学习的一个非常常见的应用。在这样的应用中,机器学习被用于将一段文本分类成两个或多个类别。文本分类有监督学习模型和非监督学习模型。在这篇文章中,我们将看到如何使用脸书的快速文本库进行一些简单的文本分类。

由脸书开发的 fastText 是一个流行的文本分类库。该库是 GitHub 上的一个开源项目,非常活跃。该库还提供了用于文本分类的预建模型,包括监督和非监督的。在这篇文章中,我们将了解如何在库中训练监督模型进行快速文本分类。该库可以用作命令行工具,也可以用作 Python 包。为了让事情变得简单,在这篇文章中我们将只看几个 CLI 命令。

安装 fastText

为命令行安装 fastText 就像克隆 Git repo 并在目录中运行 make 命令一样简单:

git clone [https://github.com/facebookresearch/fastText.git](https://github.com/facebookresearch/fastText.git)
cd fastText
make

一旦你这样做了,你就已经安装了 fastText CLI,只要你没有得到任何错误。您也可以通过从同一目录运行以下命令来安装 Python 库:

pip install .

您可以通过运行以下命令来验证安装:

./fasttext

您应该在终端中看到类似这样的内容:

usage: fasttext <command> <args>The commands supported by fasttext are:supervised train a supervised classifier
 quantize quantize a model to reduce the memory usage
 test evaluate a supervised classifier
 test-label print labels with precision and recall scores
 predict predict most likely labels
 predict-prob predict most likely labels with probabilities
 skipgram train a skipgram model
 cbow train a cbow model
 print-word-vectors print word vectors given a trained model
 print-sentence-vectors print sentence vectors given a trained model
 print-ngrams print ngrams given a trained model and word
 nn query for nearest neighbors
 analogies query for analogies
 dump dump arguments,dictionary,input/output vectors

这表明您已经安装了该工具。下一步是获取我们的数据集。

获取数据

脸书开发者已经包含了一个测试这个库的数据集。所以我们会用同样的数据。这是一个关于烹饪的 stackexchange 问题集。这里的目的是对问题进行自动分类。因为我们使用监督学习,我们必须确保我们在数据中标记问题的类别。幸运的是,这些数据都带有已经标记的类别。所以先下载数据吧。数据在这里以压缩文件的形式提供:https://dl . fbaipublicfiles . com/fast text/data/cooking . stack exchange . tar . gz。我们可以下载数据并手动解压缩,也可以从 CLI 运行以下命令:

wget [https://dl.fbaipublicfiles.com/fasttext/data/cooking.stackexchange.tar.gz](https://dl.fbaipublicfiles.com/fasttext/data/cooking.stackexchange.tar.gz) && tar xvzf cooking.stackexchange.tar.gz

解压缩后,目录中会有一些文件。但是我们的数据在一个名为cooking . stack exchange . txt的文件里。如果你打开文件或者它,你会看到这样的东西:

__label__sauce __label__cheese How much does potato starch affect a cheese sauce recipe?
__label__food-safety __label__acidity Dangerous pathogens capable of growing in acidic environments
__label__cast-iron __label__stove How do I cover up the white spots on my cast iron stove?
__label__restaurant Michelin Three Star Restaurant; but if the chef is not there
__label__knife-skills __label__dicing Without knife skills, how can I quickly and accurately dice vegetables?
__label__storage-method __label__equipment __label__bread What’s the purpose of a bread box?
__label__baking __label__food-safety __label__substitutions __label__peanuts how to seperate peanut oil from roasted peanuts at home?
__label__chocolate American equivalent for British chocolate terms
__label__baking __label__oven __label__convection Fan bake vs bake
__label__sauce __label__storage-lifetime __label__acidity __label__mayonnaise Regulation and balancing of readymade packed mayonnaise and other sauces

如你所见,这篇文章有些不寻常。在每一行中,我们都有_ _ 标签 __ 文本。这其实就是问题的范畴。因此,在训练数据中指定类别的方法是包含文本 label ,后跟类别。我们也可以为一个问题指定多个类别,从上面的例子可以看出。现在我们已经准备好了数据,让我们把它分成训练和测试数据。

将数据分为训练数据和测试数据

在开始训练我们的模型之前,我们必须分割数据,以便我们有一个数据集用于训练模型,一个数据集用于测试模型的准确性。如果你想知道为什么这是必要的或者如何用 Python 来做,你可以在这里阅读我关于它的帖子。通常,我们将数据分成 80-20 份,80%的数据用于训练,20%用于测试。要做到这一点,我们首先需要看看我们有多少问题。每行有一个问题,所以获取文件中的行数就可以了:

$ wc -l cooking.stackexchange.txt
15404 cooking.stackexchange.txt

正如我们从输出中看到的,文件中有 15404 行。其中 80%是 12323.2,所以我们将前 12324 行作为训练数据集。剩下的 3080 行将是我们的测试数据。为此,我们将运行以下命令:

$ head -n 12324 cooking.stackexchange.txt > training_data.txt
$ tail -n 3080 cooking.stackexchange.txt > testing_data.txt

我们现在将有两个新文件,一个用于培训,一个用于测试。接下来,我们将使用训练数据训练模型。

训练模型

这实际上是这个库的一个非常简单的命令。我们只需使用监督的命令运行 fastText CLI 工具,并提供输入文件(这是我们的训练数据文件),以及将要生成的模型的名称。该命令如下所示:

./fasttext supervised -input training_data.txt -output cooking_question_classification_model

如您所见,这是一个非常容易理解的命令。-输入选项指定输入文件,而-输出选项指定将要生成的模型的名称。运行该命令后,您应该会得到类似如下的输出:

$ ./fasttext supervised -input training_data.txt -output cooking_question_classification_model
Read 0M words
Number of words: 14492
Number of labels: 735
Progress: 100.0% words/sec/thread: 47404 lr: 0.000000 avg.loss: 10.243105 ETA: 0h 0m 0s

我们的模型现在已经训练好了,可以回答一些问题进行分类了。让我们现在试试。

用一些问题测试我们的模型

当我们在上一步中训练我们的模型时,该命令生成了几个新文件:cooking _ question _ class ification _ model . bincooking _ question _ class ification _ model . vec。bin 文件,或者模型的二进制文件,就是我们现在要用的。我们可以通过运行以下命令开始测试模型:

./fasttext predict cooking_question_classification_model.bin -

如您所见,我们使用 predict 命令告诉我们的模型,我们现在要做一些预测。命令末尾的破折号(-)表示我们将在命令行中键入问题。我们也可以给命令一个包含多个问题的文件,但是我们将在下一篇文章中讨论这个问题。一旦你运行这个命令,模型将开始监听问题,你可以输入一个问题,然后点击回车回车键得到一个预测。现在让我们试试:

how to bake a cake
__label__baking
how to cook some rice
__label__food-safety
Does milk make cakes lighter or tougher?
__label__baking
How to prepare dried tortellini?
__label__food-safety
What exactly is a chowder?
__label__baking
How bad is it to freeze vegetables in glass for a maximum of 4 weeks?
__label__baking

我的每个问题都用文本 label 回答,后跟模型认为该问题所属的类别。正如你已经知道的,这个模型没有得到所有的答案或者正确的分类。这是意料之中的,因为我们还没有真正清理我们的数据或调整模型。我们可以通过对数据进行一些预处理来对模型进行微调,使其更加清晰,便于模型理解。

这个例子是您第一次尝试 fastText 时会遇到的。你可以登录 fastText 网站获取更多关于这个库和这个教程的信息。因为我想把这篇文章限制在基础知识上,所以我不打算谈论验证模型或预处理我们的数据以获得更好的结果。

我们可以获得更好结果的另一种方法是使用 n 元语法,并将句子视为单词序列。一旦我们开始以这种方式看待单词,我们将能够更多地了解我们训练的数据中的模式,并更好地预测。我会写另一篇关于什么是 n-gram (因为它值得有一篇自己的帖子)以及我们如何使用概率来更好地理解我们的数据。

Twitter 上关注我,了解更多数据科学机器学习,以及一般技术更新。另外,你可以关注我的个人博客。

如果你喜欢我在 Medium 或我的个人博客上的帖子,并希望我继续做这项工作,请考虑在 Patreon 上支持我。

Node.js 中带空间的自然语言处理

原文:https://towardsdatascience.com/natural-language-processing-with-spacy-in-node-js-87214d5547?source=collection_archive---------4-----------------------

在浏览器中使用 JavaScript 的自然语言处理有很多用例,但不幸的是,在这个领域没有多少工具。为了超越正则表达式和字符串操作,您需要利用一个好的 NLP 框架。SpaCy 自称为工业级自然语言处理,是一个流行的工具包,但它是一个 Python 库。这对那些只使用 JavaScript 的人来说是一个障碍。

SpaCy 的特点是神经网络模型、集成单词向量、多语言支持、标记化、词性标注、句子分割、依存解析和实体识别。SpaCy 拥有 92.6%的准确率,并声称是世界上最快的语法分析器。

一个名为 spacy-nlp 的 npm 包旨在通过向 node.js 公开 spacy 的自然语言处理能力来跨越这一障碍。

  • 句法剖析
  • 名词解析
  • 动词解析
  • 形容词解析
  • 命名实体解析
  • 日期解析
  • 时间解析

一些可用的助手方法有:

  • 拆分大文本
  • 删除重复的字符串
  • 字符串中的前 n 个单词

这个包最初是由华龙径创建的,后来我用它来扩展功能。这里可以找到分叉版 Textalytic 也使用这个包与 Spacy 和其他 Python 自然语言处理框架接口。

装置

首先,推荐使用 Python3,但也可以使用 Python2。您需要首先通过 Python 包索引安装 SpaCy:

**python3 -m pip install spacy**

接下来,您需要通过 Python 安装 socketIO-client。该软件包用于促进内部跨语言交流。

**python3 -m pip install -U socketIO-client**

默认情况下,这个包使用 SpaCy 的 en_core_web_md 语言模型。要下载它,您需要运行以下命令:

**python3 -m spacy download en_core_web_md**

接下来,通过 NPM 安装软件包:

**npm install git+**[**https://github.com/jeffreyflynt/spacy-nlp.git**](https://github.com/jeffreyflynt/spacy-nlp.git)

在您的 JavaScript 文件中,您将导入包并使用公开 spacyIO 的 Python 客户端启动服务器。(默认端口为 6466)。

**const nlp = require("spacy-nlp");
const serverPromise = spacyNLP.server({ port: process.env.IOPORT });**

一些需要注意的事情

  • 将空间加载到内存中可能需要 15 秒。
  • 在应用程序的生命周期中,语言模型将留在内存中。(en_core_web_md —大小:91 MB)
  • 如果你对应用程序的多个实例进行负载平衡,你会希望为每个spacyNLP.server()提供一个唯一的端口。

给我看一些例子

提取日期

假设您想从该文本中提取所有日期:

在这个共产主义国家已经饱受经济停滞之苦的时候,美国增加了对苏联的外交、军事和经济压力。1982 年 6 月 12 日,100 万抗议者聚集在纽约中央公园,呼吁结束冷战军备竞赛,特别是核武器。20 世纪 80 年代中期,新的苏联领导人米哈伊尔·戈尔巴乔夫(Mikhail Gorbachev)引入了改革(“重组”,1987 年)和开放(“开放”,约 1985 年)的自由化改革,并结束了苏联在阿富汗的参与。

输入您的文本并选择返回单词或只返回总数。返回的结果是:

  • 1982 年 6 月 12 日
  • 二十世纪八十年代中期
  • 1987
  • 1985

提取命名实体

或者您可能希望从该文本中提取所有命名实体:

冷战的第一阶段始于 1945 年第二次世界大战结束后的头两年。苏联巩固了对东方集团国家的控制,而美国开始了挑战苏联权力的全球遏制战略,向西欧国家提供军事和财政援助(例如,支持希腊内战中的反共一方)并创建了北约联盟。

这将返回:

  • 冷战
  • 第二次世界大战
  • 苏维埃社会主义共和国联盟
  • 东方集团
  • 美国
  • 苏维埃
  • 西欧
  • 希腊内战
  • 北大西洋公约组织(North Atlantic Treaty Organization)

提取名词

你可以得到更细的粒度,提取一个文本中的所有名词。

【1941 年 6 月 22 日,欧洲轴心国发动了对苏联的入侵,开启了历史上最大的陆地战场,这使得轴心国,最关键的是德国国防军陷入了消耗战。第二次世界大战(通常缩写为 WWII 或 WW2),又称第二次世界大战,是一场从 1939 年持续到 1945 年的全球性战争。

这将返回:

  • 能力
  • 侵略
  • 陆地
  • 戏院
  • 战争
  • 历史
  • 战争
  • 消耗
  • 战争

更多的例子可以在 Github 上找到,更多的方法将很快出现。

结论

上述方法是 NLP 管道的起点。人们可以发挥创意,将日期/时间解析与命名实体提取结合起来,构建演员/玩家事件的时间线。或者用一个 web scraper 来聚合提及,这种可能性是无穷无尽的。

我计划增加更多的功能,如训练模型,文本分类,句子分割,等等。欢迎任何反馈。

感谢阅读这篇文章。如果您有任何问题或意见,可以通过 Twitter @jeffrey_flynt 联系我。

张量流自然语言处理

原文:https://towardsdatascience.com/natural-language-processing-with-tensorflow-e0a701ef5cef?source=collection_archive---------0-----------------------

Photo by Kelly Sikkema on Unsplash

嘿大家好!在这篇文章中,我试图总结 Deeplearning.ai 在 TensorFlow 中关于自然语言处理的课程。

第一周

在处理图片时,我们已经有了像素值,这些像素值就是数字。然而,在处理文本时,必须对其进行编码,以便神经网络能够轻松处理。

为了对单词进行编码,我们可以使用它们的 ASCII 值。然而,使用 ASCII 值限制了我们对句子的语义理解。

例如:-

在上面两个单词中,我们有相同的字母,因此有相同的 ASCII 值,但每个单词都有完全相反的意思。因此,使用 ASCII 值从单词中提取含义是一项艰巨的任务。

现在,我们不再用数字即 ASCII 值来标记每个字母,而是标记每个单词。在上面的句子中,我们已经标注了每个单词。唯一不同的是最后一个词。当我们只看标签时,我们观察到一种模式。

我们现在开始看到句子之间的相似之处。现在我们可以从中得出意义。从这里开始,我们可以开始训练一个能够理解句子意思的神经网络。

Tokenizer 将处理代码中的繁重工作。使用 tokenizer,我们可以标记每个单词,并提供句子中使用的单词的字典。我们创建了一个 tokenizer 实例,并将一个超参数 num_words 赋值为 100。这实际上是将最常见的 100 个单词进行记号化。对于上面的句子,这太大了,因为只有 5 个不同的单词。

使用 fit_on_texts() 方法对句子进行编码。

word_index 方法返回一个键值对字典,其中键是句子中的单词,值是分配给它的标签。人们可以通过印刷来阅读这本词典。

word_index 返回上述键值对。注意“我”已经被“我”代替了。这就是 tokenizer 所做的;它省略了标点符号。

以上句子的 word_index 返回以下词典。

注意,那条‘狗!’不会因为旁边有感叹号就被当作一个单独的词。相反,作为标点符号的感叹号被去掉,只包括单词。“你”是另一个新词,被赋予了新的价值。

将一组句子传递给' text _ to _ sequences()'方法,根据传递给它的单词集将句子转换成它们的标签等价形式。

如果语料库缺少句子中存在的一个单词,则该单词在被编码为等价标签时被省略,而其余的单词被编码和打印。

例如:-在上面的 test_data 中,语料库中缺少了‘真的’这个词。因此,在编码时,省略了单词‘真的’,取而代之的是编码句子‘我爱我的狗’。

同样,对于第二个句子,单词语料库中缺少单词‘loves’,‘manatee’。因此,编码的句子是‘我的狗我的’

为了克服上述示例中面临的问题,我们可以使用巨大的单词语料库,或者使用超参数【oov _ token】并将其分配给某个值,该值将用于对语料库中以前未见过的单词进行编码。【oov _ token】可以赋给任何东西,但是应该给它赋一个唯一的值,这样它才不会和原来的单词混淆。

以上代码片段的输出。注意, ' < 00V > ' 现在是 word_index 的一部分。句子中不存在的任何单词被替换为 ' < 00V > ' 编码。

当向神经网络输入训练数据时,必须保持数据的一致性。例如,在为计算机视觉问题输入图像时,所有输入的图像都具有相似的尺寸。

类似地,在 NLP 中,当以句子的形式输入训练数据时,使用填充来提供句子的一致性。

我们可以看到,在句子的开头生成了形式为‘0’的填充。参考最长的句子进行了填充。

如果要在句子后进行填充,可以将超参数设置为【post】。通常参考最长的句子进行填充,但是可以提供超参数 maxlen 来覆盖它并定义句子的最大长度。现在,有了 maxlen 的知识,人们可能会想,如果只取了句子的一定长度,信息是否会丢失。这是真的,但人们可以指定从哪里单词被省略。将它设置为【post】允许从句尾开始释放单词。

第二周

单词嵌入:将单词和关联单词在多维空间中聚类为向量。*和词出现在一个句子中,意思相近的词往往彼此接近。***

Eg:- “电影本来是 沉闷 无聊 。”;“这部电影是 好玩的 刺激的

现在想象一下,我们在一个更高维度的空间中获得一个向量,假设 16 个维度和单词一起被赋予相似的向量。久而久之,意思相近的词开始聚集在一起。单词的含义可以来自对数据集的标注。

所以以上面的句子为例,单词无聊 在负面评论中出现了很多,因此它们有相似的情感,并且它们在一个句子中出现得很近,因此它们的向量会相似。随着神经网络的训练,它可以学习这些向量,并将它们与标签相关联,以产生所谓的嵌入,即每个单词的向量及其相关的情感。**

相似的词在负面评论中出现很多————>相似的情绪

相似的单词在一个句子中彼此靠近出现— — →相似向量

现在,在构建神经网络时,我们使用嵌入层,该层给出 2D 数组形状的输出,其中句子的长度作为一个维度,嵌入维度(在我们的例子中为 16 个维度)作为另一个维度。

因此,我们使用展平层,就像我们在计算机视觉问题中使用它一样。在基于 CNN 的问题中,像素的 2D 阵列需要被展平以将其馈送到神经网络。在基于 NLP 的问题中,需要展平嵌入的 2D 阵列。

型号摘要:-

或者,我们可以使用GlobalAveragePooling1D层,其工作方式类似。

该模型的摘要现在看起来如下

现在模型更简单,因此速度更快。然而,经分析发现,上述模型虽然比 展平 模型更快,但精度稍低。

损失函数

为了理解损失函数,我们需要根据预测的置信度来处理它。因此,尽管准确预测的数量随着时间的推移而增加,但损失的增加意味着每次预测的可信度实际上降低了。我们需要探索训练集和验证集之间的损失差异。

我们现在尝试调整超参数

现在我们收到以下结果:-

我们注意到损失函数变平了,这比以前的结果好,但精度不高。

对超参数执行另一个调整,其中嵌入向量中使用的维数被改变。

****

得到的结果与前一个没有太大的不同。

总结最终代码:

我们首先通过提供 词汇大小 和 vocab (oov) 标记中的 来实例化一个标记化器。

接下来,我们使用fit _ on _ texts()方法对用于训练的句子进行分词。

word_index 让我们可以查看单个单词被编号或标记了什么。

text _ to _ sequences()以数字格式对用于训练的整个句子进行编码。

接下来,我们通过指定 来填充序列,填充什么,填充是在句子之前还是之后,以及被填充句子的最大长度。

类似于编码训练句子,我们编码验证句子并填充它们。

现在我们创建一个名为label _ tokenizer的单独的标记器来标记标签,并将其安装在标签上进行编码。

现在,我们为训练标签和验证标签创建一个 numpy 编码标签数组。

该模型被创建并被训练 30 个时期。

****

使用下面的代码,可以绘制训练集和验证集的准确性和损失。

我们使用一个帮助函数来反转包含编码单词的字典,该函数有助于我们绘制嵌入。

****

我们创建矢量和元文件,并存储元数据和矢量嵌入。

我们可以在下面提到的链接中上传矢量化和元数据文件,并通过绘制在更高维度的空间中查看单词嵌入。

** [## 嵌入式投影仪-高维数据的可视化

可视化高维数据。

projector.tensorflow.org](http://projector.tensorflow.org/)

第三周

在前几周,我们试图实现一个分类器,试图根据文本对句子进行分类。我们试图通过标记单词来做到这一点,并注意到我们的分类器未能获得任何有意义的结果。原因是当单词被分解成子单词时,很难理解单词的上下文。理解子词出现的顺序对于理解它们的意思是必要的。

例如:-

下图是斐波纳契数列的序列。

上述序列以循环方式工作,即

通过分析这种循环,我们可以确定数字的顺序。没有明确提到这个顺序。提供数据及其标签,并通过神经网络导出序列。

斐波纳契数列的递归函数可以用上图表示,其中 Xt 是数列的初始数字。该函数然后输出 yt,,即前两个数的和。总和值被带入下一次迭代,在那里它被加到第二个数字上并输出另一个值。序列继续。

展开后,上面的递归函数看起来像这样

X0 - > 1,2;f->(1+2);y0 - > 3

X1 - > 2,3;f->(2+3);y1 - > 5

X2 - > 3、5;f->(3+5);y2 - > 8

我们观察到, 电流输出高度依赖于紧接的前一步,并且如果序列特别大,则最不依赖于初始步骤 ,即 y2 高度依赖于前一步( X1,F,y1 )并且较少依赖于( X 0, F,y0 )。类似地, y1 高度依赖于前一个步骤( X 0, F,y0 ),如果它存在于序列中,那么它对初始步骤的依赖性会小一些。

这形成了递归神经网络(RNN)的基础。

这给文本分类带来了新的挑战。

假设在下面的例子中,我们需要预测 blue 后面的单词。

当看这个句子时,我们可以预测,当在上下文中谈论一个美丽的蓝色东西时,我们很可能指的是“天空”。

在这种情况下,帮助我们预测下一个单词的上下文单词与我们感兴趣的单词非常接近,即单词“blue”与我们感兴趣的单词“sky”相邻。

然而,我们也可能遇到预测感兴趣单词所需的上下文单词可能出现在句子开头的情况。在这里,RNN 的概念可能会失败,因为它试图通过考虑紧接在它前面的单词来预测感兴趣的单词。

例如:

在上面的句子中,我们可以观察到上下文单词“Ireland”在句子中出现得更早,而感兴趣的单词“Gaelic”出现得更晚。RNN 人最有可能通过考虑紧接在单词“盖尔语”之前的单词,即“说话”、“说话”、“如何”,来预测单词“盖尔语”;但这些单词都不会有助于“盖尔语”这个词的预测。

在这种情况下,我们需要修改 RNN。

LSTM(长短期记忆)

在这些类型的网络中,除了像在 RNN 中那样传递上下文之外,LSTM 还具有通过网络的称为 信元状态 的附加上下文管道。这有助于保持上下文与前面的令牌或后面的步骤相关,以克服上面示例中刚刚讨论的挑战

单元状态 可以是双向的,以便句子中后面出现的标记可以影响前面的标记。

在代码中实现 LSTMs

LSTM 层是使用上面的代码实现的。传递的参数是该层所需的输出数量。在这种情况下是 64

我们以双向格式包装 LSTM 层,它将使 单元格状态 向两个方向移动。

因此,模型摘要如下所示。

请注意,双向层的输出形状是 128 ,尽管我们已经将 64 作为参数传递。这是由于双向层有效地使 LSTM 层的输出加倍。

我们也可以堆叠 LSTM 层,但是我们需要确保return _ sequences = True存在。这使我们能够将当前 LSTM 图层的输出与下一个 LSTM 图层的输出进行匹配。

该模型的总结如下:

比较准确度和损耗

我们注意到 1 层 LSTM 网络的训练精度似乎不均匀,而 2 层 LSTM 网络的训练精度平滑得多。这种不均匀性的出现通常表明模型需要改进。

在绘制损失函数时,我们注意到类似的结果。1 层 LSTM 网络似乎具有锯齿状的表面,而 2 层 LSTM 网络具有平滑的表面。

当我们训练 50 个时代的网络时,我们注意到 1 层 LSTM 容易出现一些非常急剧的下降。即使最终的精度是好的,这些下降的存在使我们对模型产生怀疑。相比之下,2 层 LSTM 具有平滑的曲线,并且实现了类似的结果,但是因为它是平滑的,所以该模型更加可靠。

在绘制损失函数时,可以观察到类似的趋势。2 层 LSTM 网络的曲线看起来比 1 层 LSTM 网络平滑得多。两条曲线中的损耗都逐渐增加,并且需要密切监控,以检查其是否如所期望的那样在以后的时期变平。

比较非 lstm 和 lstm

i) Without LSTM

ii) With LSTM

当使用池化和扁平化的组合时,我们很快达到了 85%的准确率,然后它变平了。验证集有点不太准确,但是曲线看起来与训练准确性同步,在 80%的准确性处变平。

另一方面,当在网络中使用 LSTM 层时,我们很快就达到了 85%的准确率,并继续上升到 97.5%。验证集的准确率提高到 82.5%,但随后下降到 80%,与之前的网络相似。精确度的下降暗示着某种过度拟合肯定正在发生。要解决这个问题,需要对模型进行一点调整。

当比较损失函数时,观察到类似的趋势。培训损失迅速下降,然后趋于平缓。验证准确性似乎表现类似。而在 LSTM 网络中,训练精度下降得很好,但是验证精度增加了,从而暗示了模型中可能发生的可能的过度拟合。直观地说,这意味着当模型的准确性增加时,对它的信心减少了。

使用卷积层

在网络中应用了卷积层,现在单词将按照滤波器的大小分组,即 5 个卷积将被学习,它们可以将单词分类映射到期望的输出

过滤器数量->128;过滤器尺寸- > 5

我们观察到,我们的模型甚至比以前的模型表现得更好,在训练集上接近 100%的准确性,在验证集上接近 80%的准确性,但与以前一样,我们在验证集上的损失增加,表明过度拟合,因此预测置信度下降。

如果我们回到我们的模型,探索卷积层的参数,我们会注意到每组 5 个字有 128 个滤波器。

在查看模型摘要时,我们注意到句子的输入长度是 120 并且过滤器大小是 5 ,因此前面的 2 个单词和后面的 2 个单词被去掉,留给我们的句子大小是 116 。因为我们使用了一个 128 卷积,所以我们得到了 (116,128) 的输出维数。

第四周

标记器被初始化,并以由 "\n" 分隔的句子的形式提供数据。然后将句子转换成小写字母,并使用拆分方法检索单个句子,并将其作为列表项存储在 【语料库】 列表中。使用 fit_on_texts 方法对列表中的单词进行标记和标注。数据中存在的总唯一字存储在变量 total_words 中。额外的 1 是因为 oov_token 的存在。

上面突出显示的代码给出了下面的输出。检索并编码 语料库 列表中的第一行文本。

下一个循环将整个编码句子分解成一个n _ gram _ sequence,并将每个序列添加到input _ sequences列表中。

下图中的"输入序列"中的每一行都是一个 n_gram_sequence。

然后,我们试图通过遍历所有可用的输入序列来确定最大句子的长度。

一旦确定了最大句子的长度,我们就用prepad输入序列

上面的代码给出了下面的输出。

我们预填充上述输入序列的原因是,我们可以将整个训练数据放在每个输入序列的左侧,而将代表它的标签放在右侧。在这种情况下,由于我们预测每个句子末尾的单词,我们将每个输入序列的最后一个单词视为要预测的目标标签。

现在,我们开始分离输入序列,收集最后一个单词之后的所有编码单词作为模型的输入,最后一个编码单词作为目标标签,并将它们存储在单独的列表中,如下所示。

由于这是一个多类分类模型,我们使用下面的代码对其进行编码。

如前所述,给定编码的句子,直到倒数第二个编码单词的所有编码单词被存储为模型的输入 X 。在如下所示的情况下,所有编码字直到 69 被存储为 X ,最后一个编码字 70 被存储为标签

标签一键编码如下图所示 Y 。第 70 个元素存储为 1 ,因为编码标签与之对应,其余为 0

问题的模型如下所示。我们使用 adam 优化器,因为它碰巧在这种情况下表现得特别好。

上述模型的性能精度绘制如下。

我们注意到,某些已经被预测到的单词在最后往往会重复出现。这是因为模型中使用的 LSTM 层是单向的,并且同一个单词一旦被预测就继续向前传递,从而影响句子中稍后被预测的单词。

为了克服上述问题,我们使用双向 LSTM 层,使得即使在目标单词影响预测之后,单词仍然存在。

包含双向层的精度绘制如下。

包含双向层的输出如下所示。我们观察到单词的重复确实继续存在,但是它的频率降低了。也就是说,下面的文本是一首诗的一部分,其中的单词需要押韵,因此必须遵循一定的顺序。因此,重复可能不是由于模型中的错误,而是由于句子的固有结构。

我们现在尝试通过给它一组初始单词来生成一首诗。

因为单词 Laurence 不在语料库中,所以它没有被编码。

在填充句子之后,我们以下面提到的一个序列结束。

试图预测输入句子后面的大量单词是不可取的,因为最初预测的单词本身是基于某种概率的。随着更多的单词被预测,概率持续降低,因此预测的质量持续恶化,直到预测的单词不再相关并且作为输出出现乱码。

解决上述问题的方法是使用更大的单词库。

我们知道这样一个事实,Adam optimizer 在这类问题中表现良好。为了更好地进行调优,我们可以显式地实例化优化器,并用学习率进行实验。

由于英语的单词比单个字母多,我们可以通过提供编码的字母来训练模型,并训练它预测下一个字母。这样,我们就不必担心拥有一个超大的文本语料库。**

感谢您阅读本博客。我希望听到你对此的想法。

自然语言理解——对话代理的核心组成部分

原文:https://towardsdatascience.com/natural-language-understanding-core-component-of-conversational-agent-3e51357ca934?source=collection_archive---------11-----------------------

摘要

BI Intelligence, https://i.insider.com/5970ca60552be5ad008b56ce?width=600&format=jpeg&auto=webp

我们生活在一个信息应用处理我们各种日常活动的时代,事实上,这些应用已经超过了社交网络,正如 BI Intelligence 报告中所指出的那样。除了这一点之外,消息平台的消费预计在未来几年将进一步显著增长;因此,在人们积极参与的情况下,这是不同企业获得关注的巨大机会。

在这个即时满足的时代,消费者希望公司能够毫不拖延地对他们做出快速反应,当然,这需要公司花费大量的时间和精力来雇佣和投资他们的员工。因此,现在是任何组织考虑与最终用户保持联系的新方法的时候了。

许多正在经历数字化转型的组织已经开始利用人工智能的力量,如人工智能辅助的客户支持系统、使用人工智能辅助面试的人才筛选等。甚至还有许多对话式人工智能应用程序,包括 Siri、谷歌助理、个人旅行助理,这些应用程序可以个性化用户体验。

概述

有两种创建对话代理的方法,即基于规则和自学习/机器学习。对于基于规则的方法,您可以使用正则表达式来创建一个简单的聊天机器人。

在这篇文章中,我将向你展示如何使用机器学习和单词向量来将用户的问题分类成意图。除此之外,我们还将使用一个预建的库来识别文本中的不同实体。这两个组件属于自然语言理解,在设计聊天机器人时非常关键,以便用户可以从机器获得正确的响应。

自然语言理解

NLU(自然语言理解)是自然语言处理的重要组成部分,它允许机器理解人类语言。这有两个重要的概念,即意图和实体:

我想订一张从 A 到 c 的机票。

Intent: 在这种情况下,最终用户的目标是预订从一个地点(A)到另一个地点(C)的航班。因此,这个问题的目的或意图是“预订票”。

实体:这个查询中有两个概念/实体;出发城市(A)和目的地城市(B)。

总而言之,意向“保留票”具有以下实体:

出发城市
目的城市

我们现在可以使用这些信息为我们的用户提取正确的响应。

作为本教程的一部分,我们将使用聊天机器人语料库(https://github.com/sebischair/NLU-Evaluation-Corpora),由 206 个问题组成,由作者标记。数据有两种不同的意图(出发时间和查找连接)和五种不同的实体类型。在本帖中,我们将使用问题和意图进行意图分类。然而,当涉及到实体时,我们不会训练我们的自定义实体,相反,我们将利用预先训练的命名实体识别器从文本中提取实体。当然,可以使用不同的算法来训练自定义实体,但是我们可以稍后再研究它。

第 1 部分:意图分类

为了将用户的话语分类为一个意图,我们可以利用正则表达式,但是当规则很容易定义时,它工作得很好。

我们现在将转向机器学习方法来对用户的话语进行分类;这是一个有监督的文本分类问题,我们将利用训练数据来训练我们的模型来对意图进行分类。

这里的一个重要部分是理解单词向量的概念,以便我们可以将词汇中的单词或短语映射到实数向量,从而使相似的单词彼此接近。例如,单词“冰川”的矢量应该接近单词“山谷”的矢量;出现在相似上下文中的两个单词有相似的向量。因此,单词向量可以捕捉单词集合中的上下文含义。

Please use this link to play with : http://projector.tensorflow.org/

我们将利用 Python 中的 Spacy 包,它自带了加载训练向量的内置支持。经过训练的向量包括 word2vec、glove 和 FastText。

如果我们谈论 word2vec,它有两种风格,连续词包(CBOW)和跳格模型。

http://idli.group/Natural-Language-Processing-using-Vectoriziation.html

连续单词包(CBOW)试图使用相邻单词来猜测单个单词,而 skip gram 使用单个单词来预测其在窗口中的相邻单词。

简要细节

输入以一个热向量的形式输入到网络。

隐藏层是神奇的部分,这就是我们想要的。隐藏层权重矩阵是我们感兴趣的词向量,它只是作为一个查找表,因为当你在输入词的一个热向量和隐藏层的权重矩阵之间应用点积时,它将挑选对应于 1 的矩阵行。(注意:根据词汇量的大小,单词向量的维数通常在 100 到 300 之间)

输出部分是 Softmax 函数,它给出了目标单词的概率。

我们不会深入讨论与此相关的更多细节。

使用预训练的单词向量训练意图分类器

第一步:加载数据

df=pd.read_excel(“Chatbot.xlsx")
queries=np.array(df['text'])
labels=np.array(df['intent'])

Image by author

步骤 2:加载预训练的空间 NLP 模型

Spacy 是 Python 的一个自然语言处理库,带有内置的单词嵌入模型,它使用 300 维的手套单词向量

# spacy NLP Model
nlp = spacy.load(‘en_core_web_lg')

n_queries=len(queries)
dim_embedding = nlp.vocab.vectors_length
X = np.zeros((n_queries, dim_embedding))

第三步:预处理——词向量

现在,如果我们在查询部分看到包含以下内容的数据:

print(queries)

Image by author

为了训练模型,我们需要使用 Spacy 预训练模型将这些句子转换为向量。

for idx, sentence in enumerate(queries):
   doc = nlp(sentence)
   X[idx, :] = doc.vector

Image by author

现在,我们已经将句子转换为向量格式,可以将其输入到机器学习算法中。

步骤 4:使用 KNeighborsClassifier 的训练模型

#########Splitting Part###########

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.30, random_state=42)

Image by author

#############Training Part###########
from sklearn.neighbors import KNeighborsClassifier
neigh = KNeighborsClassifier(n_neighbors=1)
neigh.fit(X_train,y_train)

我们来评价一下。

###########Evaluating##############
print("Accuracy on Test Set: ",np.count_nonzero(neigh.predict(X_test)==y_test)/len(y_test))

让我们检查一下示例查询

请注意,这是正确地标识了 FindConnection 意图。您可以尝试不同的变体来测试这一部分。

恭喜你,我们已经成功构建了我们的意图分类器,它可以理解用户话语的目的。现在机器知道了用户问题的目的,它需要提取实体来完整地回答用户试图问的问题。

第 2 部分:实体识别

实体提取帮助我们计算出正确的字段,以便用户可以从机器得到正确的响应。例如,分类为 FindConnection 的查询“从 olympia einkaufszentrum 到 hauptbahnhof”有两个实体:olympia einkaufszentrum(起始位置)和 hauptbahnhof(目的地位置)。

在从文本中识别出意图和实体之后,我们可以生成一个查询,该查询可以从数据库中获取响应。

EXAMPLE SQL to FETCH from the database:
 SELECT ___ FROM CONNECTIONS
 WHERE START_LOCATION=‘olympia einkaufszentrum’
 AND END_LOCATION=‘hauptbahnhof’
 __________
 FURTHER CONDITIONS IF REQUIRED
 ___________

这只是 SQL 的一个例子,向您展示了意图和实体对于为用户提取正确响应的重要性。

为了识别实体,我们将使用 Spacy 命名实体识别,它已经支持实体类型,如 PERSON、FAC(建筑物、机场、高速公路)、ORG(公司、组织)、GPE(县、州、城市)等。要查看更多的实体类型,请参考此链接:【https://spacy.io/api/annotation

doc = nlp('from olympia einkaufszentrum to hauptbahnhof')
for ent in doc.ents:
    print(ent.text,ent.label_)

Image by author

正如你所看到的,斯帕西·NER 已经从文本中识别出了这两个实体。但是,这个库只支持基本的实体,如人、位置等。在我们的例子中,olympia einkaufszentrum 应被标记为起点位置,hauptbahnhof 应被标记为终点位置。

我们还可以训练自定义实体来支持我们的问题。有各种实体提取器可用,如 CRFEntityExtractor、MitieEntityExtractor、EntitySynonymMapper 等,通过它们可以训练您的自定义实体。你甚至可以用自定义实体来训练 NER 空间。这由你来决定。

结论

在这篇文章中,我们看到了自然语言理解的一个重要概念,它可以推断出最终用户的意思。更准确地说,它是自然语言处理的理解部分,可以消化、理解文本以向最终用户输出相关的响应。意图和实体是 NLU 的两个重要组成部分,我们看到了如何使用 Spacy 和 scikit-learn 的简单方法来执行意图分类和实体识别。有各种支持 NLU 的聊天机器人平台,包括 RASA NLU,Dialog Flow,IBM Watson,Amazon Lex。从文本中提取意图和实体,拉莎·NLU 将是一个很好的起点。

除了自然语言理解,其他几个组件在构建人工智能辅助的聊天机器人中也很重要。你需要探索槽填充部分,内存元素和更多来创建一个好的工作对话代理。

参考

[1]https://medium . com/bhavaniravi/entity-extraction-除雾-rasan Lu-part-3-13a 460451573
【2】https://github.com/sebischair
【3】https://repl.it/@just_a_girl/Datacamp-Using-Spacy-for-NLP
【4】https://www.datacamp.com/community/tutorials
【5】https://www . SIG dial . org/files/workshop/conference 18/proceedings/pdf/sigdial 2

基于序列对序列模型的自然语言理解

原文:https://towardsdatascience.com/natural-language-understanding-with-sequence-to-sequence-models-e87d41ad258b?source=collection_archive---------5-----------------------

如何预测客户询问背后的意图?Seq2Seq 型号说明。使用 Keras 在 ATIS 数据集上演示槽填充。

自然语言理解(NLU),对话式人工智能(聊天机器人、虚拟助理、增强分析)背后的技术通常包括意图分类和槽填充任务,旨在为用户话语提供语义工具。意图分类侧重于预测查询的意图,而槽填充提取查询中的语义概念。例如,用户查询可以是“给我找一部史蒂文·斯皮尔伯格的动作片”。这里的目的是“寻找电影”,而槽是值为“动作”的“类型”和值为“史蒂文·斯皮尔伯格”的“导演”。

意图分类是预测意图标签的分类问题,而槽填充是标记输入单词序列的序列标记任务。在研究中,通常会发现使用基于递归神经网络(RNN)的方法,特别是门控递归单元(GRU)和长短期记忆(LSTM)模型,在意图分类和槽填充方面的最新表现。

本文处理槽填充任务。我们首先介绍机器翻译任务,以激励序列到序列模型,这已经统治了神经机器翻译的世界多年。我们用序列到序列模型来解决槽填充的任务。该方法是从理论上提出的,并使用 ATIS 数据集进行了实践,该数据集是一个广泛用作意图分类和缝隙填充任务的标准基准数据集。

迷失在翻译中

古老的语言

语言翻译很难,不仅仅是对人类。过去,我们使用基于规则的机器翻译,让语言学家在词汇、句法或语义层面创建和维护将源语言文本转换成目标语言的规则。后来,统计机器翻译更倾向于使用统计模型来学习翻译给定的大量例子。给定源语言的文本,例如法语 (f) ,在目标语言中最有可能的翻译是什么,例如英语 (e) ?在平行语料库上训练翻译模型 p(f|e) ,并且仅在目标语料库(英语)上计算语言模型 p(e)

尽管统计机器翻译方法有效,并被 IBM 和 Google 等大公司应用和商业化多年,但它局限于翻译的短语,失去了目标文本的广泛本质。此外,统计方法需要仔细调整翻译管道中的每个模块。

回到过去,传统的基于短语的翻译系统通过将句子分解成多个组块并逐个短语地翻译它们来完成工作。这种方法造成了不流畅的翻译。

神经机器翻译于 2014 年问世,引入了使用神经网络模型来学习机器翻译的统计模型。从那时起,我们不必计算条件概率的规则。网络学习它们的权重,发现所有的规则和概率,语言学家和统计学家将花费巨大的精力来编码。

在我们的上一篇文章中,我们展示了递归神经网络,尤其是 LSTMs 如何在 20 年中根据时间步长 t-1 的前一个元素来预测时间步长 t 的序列元素。递归神经网络也能帮助语言翻译吗?

[## 基于 LSTM 的非洲语言分类

厌倦了德法数据集?看看 Yemba,脱颖而出。力学的 LSTM,GRU 解释和应用,与…

towardsdatascience.com](/lstm-based-african-language-classification-e4f644c0f29e)

直接使用 LSTM 将一系列单词从一种语言映射到另一种语言很快就会遇到问题。要使单个 LSTM 工作,您需要输入和输出序列具有相同的序列长度,而对于翻译来说,这种情况很少发生。例如,两个单词的英语短语“正在播放”被翻译成一个单词的德语短语“spielt”

序列对序列学习

前一节介绍的问题的最佳解决方案是编码器-解码器架构,即所谓的序列到序列学习和神经网络,以及将源文本编码为内部固定长度表示(称为上下文向量)的能力。一旦编码,不同的解码系统可以用来翻译成不同的语言。

Sutskever 等人,2014Cho 等人,2014 发明了这种方法。Sutskever 的模型在 2014 年获得了 34.81 的 BLEU 分数,与统计机器翻译系统为英法翻译开发的 33.30 的基线分数相比,这是一个巨大的飞跃。这是神经机器翻译系统在大规模问题上胜过基于短语的统计机器翻译基线的第一个例子。Sutskever 的模型被用来对最佳翻译名单进行重新评分,并将分数提高到 36.5 分,接近当时的最佳成绩 37.0 分。 BLEU 算法(双语评估替补)通过比较候选译文和参考译文之间的 n 元语法数量来评估译文的质量。Sutslever 的模型是在数据集中 1200 万个句子的子集上训练的,包括 3.48 亿个法语单词和 3.04 亿个英语单词。

source

编码器和解码器通常是 LSTMs 或 gru 的层。虽然不建议太深入,但 Google Translate 使用的是 ca。7 层。很少有博客建议将单词以相反的顺序输入网络以提高性能。在许多实际情况下,在编码器中使用双向架构,通过使用以正常顺序从原始句子学习的层和以单词的相反顺序从原始句子学习的另一层。来自两层的上下文向量被连接以产生唯一的上下文向量,该上下文向量被馈送到解码器中。

在一个对话代理的例子中,输入序列“你好吗”首先通过使用一个预训练嵌入或通过在我们的数据集上训练我们自己的嵌入被转换成单词嵌入。

[## 自然语言处理中的文本表示

理解书面单词:温习 Word2vec、GloVe、TF-IDF、单词袋、N-grams、1-hot 编码…

towardsdatascience.com](/representing-text-in-natural-language-processing-1eead30e57d8)

嵌入向量的大小通常为 200 或 300。这样的向量通过编码器的 LSTM 单元,以创建它的较小维度的表示。该表示然后被转发到解码器网络,该解码器网络生成其自己的表示输出“我很好”的序列。

因为编码器和解码器都是递归神经网络,每个时间步,其中一个 rnn 做一些处理,它根据它的输入和它看到的以前的输入更新它的隐藏状态。编码器的输入是来自输入句子的当前单词的矢量嵌入,例如“Je suis étudiant”。编码器的隐藏状态是先前单词的记忆表示。最后一个隐藏状态实际上是传递给解码器的上下文,它自己生成一个序列,表示输出“我是学生”。

(source: Jay. Alammar, 2018)

上下文是一个数字向量。其大小通常是编码器 RNN 中隐藏单元的数量。下面,我们展示了一个大小为 4 的示例向量,但是上下文向量的大小通常是 256、512 或 1024。

(source: Jay. Alammar, 2018)

编码器-解码器架构中使用的 RNNs 模型可以是单向或双向的、单层或多层的、简单的普通 RNN 或 LSTM 或 GRU。下面我们展示一个使用 LSTM 作为循环单元的深度多层单向 RNN 的示例。这里,“”表示解码过程的开始,而“”告诉解码器停止。

source

解码人类意图

在本节中,我们将实现一个用于自然语言理解的序列到序列模型。通常,这涉及两个任务:意图检测(ID)和槽填充(SF)。前者试图将用户话语分类为意图。后者试图找到这种意图的“论据”是什么。

探索数据集

我们在著名的 ATIS 数据集(航空旅行信息系统)上训练我们的模型。Pickle 格式的数据集的预处理版本从这个库获得。数据集包含旅行者提交给信息系统的查询。用户的意图以及话语被标记(槽填充)。

下面的代码片段将字典和张量中的训练数据存储在单独的变量中。它还显示了几个查询示例、它们的词向量、意图、槽和槽向量。

下面我们用一个漂亮的布局展示了每个意图类的查询示例。

ATIS Intent Dataset

例如,让我们考虑用户查询“我想在上午 838 从波士顿起飞,并在上午 11:10 到达丹佛”。该模型应该将该用户查询分类为“飞行”意图。它还应该解析查询,识别并填充理解查询所需的所有槽。虽然单词“我”、“想要”、“飞”、“从”、“在”、“到达”、“在”、“该”有助于理解意图的上下文,但是模型应该正确地标记实现用户的飞行意图中的目标所需的实体。分别是“波士顿”作为出发城市(B-fromloc.city)、“上午 8:38”作为出发时间(B-departy _ time . time)、“丹佛”作为目的地城市(B-toloc.city_name)、“11:10”作为到达时间(B-arrival _ time . time)以及“早晨”作为一天中的到达时段(B-arrival _ time . period _ of _ day)。下图显示了 129 个插槽类别中的一些。

您可能已经注意到,查询文本已经被标记化,ATIS 数据集中也提供了词汇表。查询有一个开始(“BOS”)和结束(“EOS”)标记,如下所示。

创建张量

我们通过将每个查询向量和槽向量填充到最大长度来创建张量。我们为目标槽提供两个张量。一个是教师张量,它迫使解码器遵循正确的输出时隙。另一个是真正的目标张量,它定义了给定教师张量时解码器应该输出什么。两者之间唯一的区别是目标张量只是左移了一个槽标签的教师张量。这个技巧被用于序列到序列模型的英语到西班牙语翻译(来源)。输入和目标张量都具有形状(无,48)。

换句话说,为了计算词汇表的大小,我们将训练和测试词汇表结合起来。输入词汇有 943 个单词,而输出词汇有 129 个单词。

为槽填充建立 Seq2Seq 模型

seq2seq 模型是在编码器和解码器中使用 GPU 就绪的 LSTM 创建的。输入通过一个编码器模型,该模型给出形状 (batch_size,max_length,hidden_size) 的编码器输出和形状 (batch_size,hidden_size) 的编码器隐藏状态。编码器和解码器都使用嵌入层来投影句子,以学习用户查询的有意义的表示,该表示被馈送到具有 1024 个单元的单向 LSTM 层。

训练 Seq2Seq 模型

因为我们的目标(槽向量)不是一次性编码的,所以我们使用稀疏分类交叉熵作为损失函数。利用 Adam 作为 50 个时期的优化器,我们使用 3982 个训练样本和 996 个验证样本。在训练数据上准确率高达 98%,验证准确率略低于 96%。验证准确性在 45 年左右开始趋于平稳,表明该模型不再真正推断,并开始过度拟合。

Seq2Seq 模型的推理

预测将需要两个独立于训练的模型。我们需要打破编码器和解码器的机制。然后,我们通过编码器运行整个输入序列,然后通过解码器一步一步地预测来创建输出。

下面我们看到为一个看不见的查询预测的槽填充。该模型通过将“最便宜的航班”标识为 B-cost_relative slot,将“波士顿”标识为 B-fromloc.city_name,将“旧金山”标识为 B-toloc.city_name,从而很好地理解了自然语言文本。

我们现在使用 BLEU 算法(双语评估替角)在完整的测试数据集上评估训练的模型,该算法用于通过比较预测的槽填充和真实的槽填充之间的 n-grams 的数量来测量翻译的质量。

下面的结果表明,总的来说,该模型表现非常好,特别是在比较预测槽和真实槽之间的 4-gram 组时。69%的 BLEU 分数是可接受的结果。

结论

在这篇文章中,我们看了自然语言理解,特别是在槽填充的特殊任务。我们介绍了序列数据处理和语言翻译的当前方法。由于在 ATIS 数据集上关于航班请求的几个模型的实际实现,我们展示了序列到序列模型如何在空位填充任务上实现 69%的 BLEU 分数。

最近,提出了几种用于意图分类和槽填充的联合学习方法,以利用注意机制并提高相对于独立模型的性能(郭等人,2014;哈卡尼-图尔等人,2016;刘和巷,2016;咕等, 2018 )。

谢谢你读到这里。在下一篇文章的中,我们用注意力方法改进了我们的序列对序列模型。继续读!

[## NLU 任务注意机制实用指南

测试动手策略以解决注意力问题,从而改进序列到序列模型

towardsdatascience.com](/practical-guide-to-attention-mechanism-for-nlu-tasks-ccc47be8d500)

先天与后天。在人工智能中。

原文:https://towardsdatascience.com/nature-vs-nurture-in-ai-3fec240a10bb?source=collection_archive---------17-----------------------

https://en.wikipedia.org/wiki/Francis_Galton

当查尔斯·达尔文的堂兄弗朗西斯·高尔顿爵士在 19 世纪晚期普及“先天与后天”这个术语时,他当然在思考人类的行为在多大程度上由遗传基因决定,在多大程度上由他们一生的经历决定。这位著名的优生学家研究了人类的特征,并开发了回归的统计概念(大量用于机器学习),作为他改善人类基因库的探索的一部分,并得出结论,人类在很大程度上是其遗传的结果。

虽然高尔顿的提议,比如付钱给名门望族的个人让他们一起生孩子,并不赞成今天的平等主义社会,但是先天与后天的概念仍然是很多争论的主题。在 2007 年由史蒂芬·列维特和史蒂芬·都伯纳合著的有趣的书《魔鬼经济学》中,有人声称在你的房子里放 50 本书可以提高孩子 5%的考试成绩。100 本书进一步提高了 5%。这是养育帮助孩子的明显迹象。但是同样的研究也表明实际阅读和书籍之间没有关联。该理论认为,买书的父母通常是那些将智力基因传递给孩子的人——是天性,而不是后天培养。

人工智能怎么样?

但是,在人工智能中,先天与后天又如何呢?问这样的问题有意义吗?大自然没有进化出人工智能软件。它不会繁殖和传递有利于生存的特征。培育对一台机器来说意味着什么?

自然

AI 软件可能并不处于自我繁殖和进化以及适者生存的阶段,但在人类程序员的帮助下,它最有可能展现出一个进化物种的一些属性。人工智能算法的一个竞争领域是 kaggle 网站。Kaggle 为数据科学家举办比赛,试图编写最好的人工智能,做出最好的预测。数据科学家在这些比赛中相互竞争,获胜者可以赚取巨额金钱。有多大?例如,国土安全部举办了一场奖金为 150 万美元的竞赛,以提高国土安全部威胁识别算法的准确性。

很少有数据科学家自己编写真正原创的算法。相反,大多数人正在结合现有的开源代码,为他们的特定任务制定最佳算法。随着新的开源算法的发布,如果它们成功了,那么越来越多的 kaggle 竞赛项目将使用它们,而较弱的算法的受欢迎程度会下降。好的算法增强,弱的算法忽略。一个著名的例子是陈天琦在 2014 年创建的 xgboost。它是一种梯度推进算法,允许将许多弱算法组合在一起以获得好的结果。它支持正则化的能力使它明显优于早期的算法,现在它可以说是 kagglers 使用的最流行的算法。

这与动物的适者生存有明显的相似之处——最强的算法继续被广泛使用,而较弱的算法成为孤立的 git 库。最强的算法得到大量的拉取请求,并得到增强,变得更强,而弱的算法则无人维护。这是自然推动人工智能向前发展的一个明显例子。

培育

我们已经看到自然选择是如何让最好的人工智能代码茁壮成长,而最弱的代码死亡。培育人工智能怎么可能行得通?在人类中,养育是通过父母为孩子树立榜样来实现的。这可以是良性行为,比如吃光你的蔬菜或读书(或者只是拥有书籍),也可以是不良习惯,比如吸烟。研究表明,如果父母吸烟,青少年吸烟的可能性是 T2 的两倍,而其他研究表明,孩子吃足够蔬菜的最强预测因素是他们的父母也吸烟。但是这怎么能适用于 AI 呢?

今天的人工智能主要是通过机器学习来实现的。在这里,计算机算法被输入带标签的数据,以建立一个世界的模型。或者至少是世界的一小部分。比如我们教机器,猫长这样,狗长那样。或者我们告诉它谁拖欠贷款,谁没有,以及这些人的家庭特征。计算机被告知过去发生了什么,以便它能预测未来会发生什么。这应该允许我们建立一个真实的世界模型。我们从未来的决策中去除人类的个人意见。我们基于过去发生的事实,而不是我们自己习得的偏见。鉴于人工智能只有在我们对数据进行训练的情况下才能建立一个有用的世界模型,它似乎更强烈地依赖于我们如何培养它——我们教给它关于世界的什么。

偏向

但如果过去告诉它的东西有一些偏差,会发生什么呢?一些影响世界的人性弱点。在上面的例子中,有人必须决定什么是猫,什么是狗。也许有些照片贴错了标签。

如果只是一些随机的错误,可能没什么大不了的。但如果更恶意呢?当在英国监狱工作的囚犯将历史人口普查数据数字化时,他们进入了执法人员不喜欢的职业。不仅仅是罪犯也会这么做。大多数图片标签是由人们在网上完成的。想想你在社交媒体上看到的一些人,告诉我你不能想象他们中的任何一个人为了寻求刺激而贴错标签。

或者也许我们的数据集已经为猫和狗训练好了,但是当我第一次给它看一只羊时会发生什么呢?甚至第一百次?它会给它贴上猫或狗的标签,因为这就是它所接受的全部训练。这类似于 2015 年谷歌开始给黑人贴上“大猩猩”的标签。谷歌本来没打算这么做,但是对黑人缺乏足够的图像识别训练,导致它无法正常学习。

[## 当谈到大猩猩时,谷歌照片仍然是盲目的

2015 年,一名黑人软件开发者在推特上发文称谷歌的照片服务将照片标记为…

www.wired.com](https://www.wired.com/story/when-it-comes-to-gorillas-google-photos-remains-blind/)

另一个可能发生的问题是无意中使用了图像中的背景信息。来自弗吉尼亚大学的维森特 more 发现,如果照片是在厨房里拍摄的,他的图像识别人工智能更有可能猜出某人是一名女性。将这两者结合起来,麻省理工学院的 Joy Buolamwini 在 2018 年 2 月发现,虽然 IBM、微软和旷视科技可以在 99%的情况下正确识别白人男性的性别,但他们只能在 35%的情况下正确识别深色皮肤的女性。

[## 性别阴影

性别分类的交叉准确性差异

gendershades.org](http://gendershades.org/overview.html)

贷款违约用例呢?在训练这样的系统时,银行会通过传递过去的贷款来训练算法,并让它学习好贷款和坏贷款的样子。像照片这种棘手的东西不在其中。它使用冷酷的事实。但是如果银行过去在发放贷款时有偏见,人工智能也会有同样的偏见。想象一下,银行过去主要向 40 岁以上的人发放贷款,算法要学习好的借款人年龄都在 40 岁以上。这个算法会有年龄偏差,因为这是我们训练它的依据。直到 1980 年,英国银行还可以拒绝向女性贷款,除非她们有男性担保人。如果没有这些贷款发生的过往数据,人工智能不会认为这是一个有效的选择

当然,我们可以很容易地修正这种偏见。我们只是不告诉算法申请人的年龄或性别。不幸的是,今天的机器学习算法在从数据中挑选线索方面非常惊人。你叫诺曼吗?这一数字在 20 世纪 20 年代达到顶峰,此后一直稳步下降。好的,我们会去掉的。也许你有一个 aol.com 的电子邮件地址。哎呀——这是一个赠送。你有多少份工作,是自己的还是租来的,你有车吗,你打高尔夫吗?所有表明一个年龄段比另一个年龄段的可能性更大的事情。

亚马逊最近试图使用人工智能来改善其招聘流程。这个想法是通过让人工智能查看过去成功聘用的人,并挑选看起来像这样的新候选人,来自动化简历筛选。他们给它输入了 10 年的数据,发现它总是选择男人而不是女人。名字被删除,运动和俱乐部被隐藏。当这些消失时,像语言这样的东西被人工智能选中了——男性比女性更经常使用像“处决”和“俘虏”这样的词。亚马逊最终放弃了这个项目,再也没有用它来雇佣任何人。

[## 亚马逊杀死了一个 AI 招聘系统,因为它无法阻止工具的歧视…

据报道,亚马逊不得不废除一个性别歧视的基于机器学习的招聘系统,因为它偏爱男性候选人。

fortune.com](http://fortune.com/2018/10/10/amazon-ai-recruitment-bias-women-sexist/)

公平

单就 AI 而言偏见不一定是问题。我天生不喜欢进入有饥饿狮子的房间,但大多数人会认为这是完全合理的。我也不喜欢雇佣幼儿园的孩子去扫烟囱,也不喜欢给那些主动给我发邮件的尼日利亚王子们寄钱。大多数人认为这些偏见是合理的。它们并非不公平——在所有这些情况下,我都面临着不小的风险。当我们认为偏见是不公平的时候,人工智能中的偏见问题就出现了。

人工智能的问题在于,公平是人类的产物。我们已经决定了一系列不公平的歧视(性别、愤怒、年龄、宗教),但仍有一些被认为公平的歧视,如智力和犯罪。机器怎么会知道区别呢?简单的答案是,我们需要少关注闪亮的新算法(自然),多关注我们训练系统的方式(培育)。

大自然的模式正在改变:探索 32 年的社区科学数据

原文:https://towardsdatascience.com/natures-patterns-are-changing-explore-32-years-of-community-science-data-4a4fe132e07e?source=collection_archive---------15-----------------------

三十多年来,拉蒂默记录了大自然的秘密

Photo by Landon Martin on Unsplas

拉蒂默记录了蝴蝶抵达、花朵开放和鸟儿出现的时间。这些自然观察和更多的观察都被细致地记录下来,包括日期、时间和地点。这是他在美国明尼苏达州北部农村沿着 100 英里的路线投递邮件时的一个爱好,并在他最后一个信封投递后很快成为一种生活方式。这些类型的观察,称为物候学,被拉蒂默恰当地定义为与气候相关的事件的节律性生物性质。

“物候学是与气候相关的事件的有节奏的生物学性质。~约翰·拉蒂默"

或者换句话说,物候学是研究由环境因素驱动的季节性植物和动物活动。几千年来,一个物种的物候通过自然选择进化,以适应环境条件并最大限度地适应环境。这个渐进的过程使得物种能够很好地适应它们的自然环境。自然科学的一个重点领域是确定变化的气候条件将如何改变物候,物候变化对物种适应性的影响——也许最重要的是——物候变化将如何改变物种的相互作用。

Retired postoffice employee and long-time community scientist John Latimer. For over 32 years Latimer has collected thousands of observations on bird and insect migrations, flowering patterns and tree leaf drop that are now publicly available for you to explore. Photograph by David J. Weston

我们可以用一个野生鸟类的例子来简要说明物候学和物种相互作用的概念。鸟蛋必须在食物(如昆虫)充足时孵化。因此,幼体出生的时间和昆虫的数量已经共同进化成同步的,或者说匹配的。如果气候变化改变了这些环境线索,那么鸟类的物候就会改变,但是鸟类捕食的昆虫的物候又会如何呢?孵化出的幼体和昆虫的数量会继续匹配吗?或者气候变化会改变它们,并且会使高度共同进化的捕食者-猎物的相互作用不匹配吗?

拉蒂默是日益壮大的社区科学运动的一部分。代表那些通常没有被训练成科学家,但是仍然为科学和人类做出贡献的人。

然而,似乎缺少的是关于如何使用和分析社区科学数据的更广泛的讨论。

一个复杂的问题是数据的巨大剪切。仅拉蒂默一人就记录了大约 104,840 个条目!再者,数据质量如何,谁来分析?合乎逻辑的答案是公共机构的科学家和教授,然而资金和资源的限制往往使这几乎不可能。正是带着这样的想法,我产生了下面的问题:

"基于社区的数据分析是科学领域的下一个重大转变吗?"

我最近接触到的 Medium 的开放数据科学社区和的出版物提供了一个关于这个问题的有趣视角,因为它表明并不缺少渴望使用新数据集的有才华的数据科学家。

作为这个小社区基础科学实验的开始,我提供访问 Latimer 的数据和初始exemplarR 代码

这绝不是详尽的,因为目的是向数据科学家介绍环境数据,反过来,向社区科学家介绍 r。

人们希望这种握手能够转化为使用开放数据和复杂分析的协作。

数据初看和数据合成

安装下面的 R 库并加载它们。

*install.packages(c(‘lubridate’, ‘tidyverse’))
library(tidyverse)
library(lubridate)*

将数据读入 R datphen<-read.csv(“Latimer_Cleaned_1.csv”)并查看一下head(datphen)。数据令人印象深刻!在 32 年的时间里,拉蒂默人工收集了 10,484 次物候观测数据。除了记录的日期,拉蒂默和同事南宁加还增加了 9 个其他变量(如属、种、俗名、生活型等。)总共 104,840 个观察值。这只是一个开始,我们的数据集将在 2016 年停止,而拉蒂默将继续记录物候观测,直到今天!

数据是典型的“日期”格式。然而,科学家通常使用儒略日格式来提供从每年 1 月 1 日开始的连续天数。每一年将包含 365 天,如果是闰年,则为 366 天。

*datphen$date<- as.Date(datphen$date, "%m/%d/%y")*

快速浏览一下数据可以发现,拉蒂默并没有每天记录观察结果。这是有道理的,因为植物在冬天处于休眠状态,鸟类季节性迁徙。

这些数据包括对植物、鸟类和其他动物的观察。要对观察到的植物种类有所了解,请使用以下方法:

*datphen2 %>% select(common_name, lifeform, event) %>% filter(lifeform == "PLANTS" & event =="FLOWERING") %>% group_by(common_name) %>% tally() %>% arrange(-n)*

这会生成一个表格,其中包含植物的通用名和 Latimer 对该物种的观察次数。下面是前 10 个条目的表格。

从上表中我们可以看出,有些物种的观测值很多,而有些物种的观测值较少。下面我们使用下面的代码来可视化拉蒂默在 32 年的数据收集过程中对每个物种的观察次数。

*a<-datphen2 %>% select(common_name, lifeform, event) %>% filter(lifeform == "PLANTS" & event =="FLOWERING") %>% group_by(common_name) %>% tally() %>% arrange(-n)ggplot(a, mapping = aes(x = reorder(common_name, -n), y = n)) +
  geom_bar(stat = "identity") +
  geom_hline(yintercept = 15, color="lightblue") +
  theme(axis.text.x=element_blank(),
        axis.text.y=element_text(size=16),
        axis.title=element_text(size=16,face="bold"),
        plot.title = element_text(size=22),
        axis.ticks.x=element_blank()) +
  labs(title = "Observations per plant species over 32 years", x = "Plant Species", y = "Number of observations per species")*

仅就植物而言,拉蒂默就记录了令人印象深刻的 392 种物种——如上面水平 x 轴上的条形数所示。然而,每个物种的观测数量差异很大。为了确保我们对每个物种都有足够的观察来检测物候变化,我们将分析限制在那些有 15 个或更多观察值的物种(观察值在上图蓝线以上的物种),这导致了 76 个物种。

从选出的 76 个物种中,我们将对每个物种拟合一个线性回归模型,以确定开花时间物候的变化是否与一年中的变化一致。

为线性回归循环和图形准备数据:

*#subset species that have 15 or more years of flowering observations # Prep or tidy the data for lm model fittingb<- a %>% filter(n >= 15)
c<-b %>% select(common_name)
lm.data<-inner_join(c, datphen2, by = "common_name") %>% filter(event =="FLOWERING") #%>% group_by(common_name) %>% distinct(year, .keep_all = TRUE)lm.data$year<-as.numeric(lm.data$year)*

以下代码显示了如何通过所有 76 个物种连续运行一个线性模型(即循环),并巧妙地提取模型斜率和 p 值,以识别候选物种供进一步研究。

*library(broom)#run an lm model across all rows, genotypes
lm.results<- lm.data %>% group_by(common_name) %>% do(fitdata = lm(julian ~ year, data = .))#getting tidy data output from model run
lmSlopePvalue <- tidy(lm.results, fitdata) %>% select(common_name, term, estimate, p.value) %>% filter(term =="year")lmRsquare <- glance(lm.results, fitdata) %>% select(common_name, r.squared)lmtidyoutput<-left_join(lmSlopePvalue, lmRsquare, by = c("common_name" = "common_name"))*

回归分析显示,76 个物种中有 10 个物种的 p 值< 0.05. Meaning that there is a significant relationship between when Latimer noticed first flowering (Julian day) for a given species, and the year the observations were recorded (year). Interpreting significance and ensuring that model assumptions are met should be further 被调查,超出了本文的范围。

为了绘制所有重要的物种,按照 R 笔记本中所示准备数据,并运行以下功能:

*#Looping graph function for phenology relationshipplant.species <- function(df, na.rm = TRUE, ...)
  # create list to loop over 
  plant_list <- unique(df$common_name)
  # create for loop to produce ggplot2 graphs 
  for (i in seq_along(plant_list)) { 
    # create plot for each specis in df 
    plot <- 
      ggplot(subset(df, df$common_name==plant_list[i]),
        aes(y= julian, x= year, group = common_name)) + 
        geom_point(size=4, colour = "dark blue")+
        geom_smooth(method = lm) +
        theme(axis.text=element_text(size=12),
        axis.title=element_text(size=16,face="bold"),
        axis.text.x = element_text(angle = 90, vjust = 0.5),
        legend.text=element_text(size=16)) +
        ggtitle(paste(plant_list[i]))
    print(plot)
  }
}*

结果:

上面的代码示例以及在 R 笔记本中详细描述的代码示例可用于调查 Latimer 数据集中的其他植物和动物物种。下面的三个图表被选择来显示物候的各种趋势。例如,黑眼灯心草似乎每年都在同一时间出现,尽管当时的天气条件很好。记住天气变化会在短时间内局部出现,从几分钟到几小时到几天;而气候是鳄龙-长期区域和全球平均值。因此,如果明尼苏达州北部正在经历气候变化,黑眼灯心草迁徙的早期阶段似乎不会受到影响。

与灯心草相反,下面显示的植物显示了开花时间的趋势。假所罗门印章显示,在观察到的年份中,该地点的开花日反应延迟,而白杨显示了较早的开花日物候。请注意,白杨图左侧的观察值比右侧少。排除早年会怎样?你有没有得到同样的趋势——提示,请看 R 笔记本

最终想法:

忘掉任何提到“气候”这个词的帖子似乎都带有的政治意味吧。相反,这意味着向数据科学界介绍拉蒂默毕生的工作。我鼓励你对这些数据形成自己的看法。数据是否足够完整,足以构建稳健的模型?应该使用什么模型,哪些额外数据会有所帮助,例如,与天气相关的变量?或者说,我们应该把物候学留给专业的科学家吗?你准备好为这项事业做出贡献并开始记录你自己的物候数据了吗?

对于社区科学家来说,参与全球数据科学社区能学到什么?你准备好以记录物候的同样热情来看待你的数据了吗?

采访快结束时,我不得不问拉蒂默,是什么驱使着他。为什么他不顾明尼苏达州严寒的气候条件,记录了 30 多年的数据。他的回答很简单:

发现的喜悦,以及对每天都有新发现的期待。

也许基于社区的数据分析是科学领域的下一个重大转变——只有时间能证明,但对拉蒂默来说,这真的无关紧要。他要下床,漫步树林,继续记录大自然的秘密。

关于作者:

韦斯顿最早的记忆中充满了大自然的图像。在专业上,他着迷于宿主-微生物组的相互作用,对能源解决方案和环境以及所有与开放分析相关的事情充满热情。就个人而言,他是一个想当农民的人,和一个了不起的配偶一起抚养三个了不起的孩子。

致谢:

这个故事是由约翰·拉蒂默的辛勤工作促成的,他在过去的 35 年里热切地记录着大自然的秘密。

将拉蒂默的数据翻译并注释成电子表格的艰巨任务是由真正的物候学专家克劳迪娅·南宁加完成的。

非常感谢那些在知识共享许可下制作了白杨、假所罗门海豹Junco 照片的人。

感谢克里斯汀·卡布高的精心剪辑和溢美之词。

用数据科学导航媒体泡沫

原文:https://towardsdatascience.com/navigating-media-bubbles-with-data-science-be9196bc94f2?source=collection_archive---------18-----------------------

通过在世界不同地方生活的经历,我意识到每个人对正在发生的事情的看法是不同的,这主要是因为他们所处的媒体泡沫。我在不同媒体泡沫的地方阅读的新闻报道越多,我就越能通过阅读新闻报道对媒体的偏见变得敏感。这种文化层面造成了人与人之间的脱节。

但除了文化方面,很明显美国目前是如何被左右政治光谱分割的。我认为协同过滤系统影响了它,它使人们与不同意他们观点的信息分离,有效地将他们隔离在他们自己的文化或意识形态泡沫中。

Image attributed to DuckDuckGo

我的目标

我认为,对于人们来说,了解不同的媒体泡沫对任何给定话题的叙述会有所帮助。这促使我创建了一个新闻推荐平台,提供不同出版物的叙述。

但在我开始之前,我如何从经验上证明媒体来源有自己的偏见?

为了回答这个问题,我从两个不同的来源收集了一个数据集:

  • 卡格尔
  • 哈佛数据世界

我的数据集包括来自 18 个不同出版物的 146,394 篇文章。出版物包括:美国保守派、美国自由派、欧洲、俄罗斯报纸。

通过研究数据集,我提出了以下假设。

假设

我的第一个假设是,报纸有自己的偏见,神经网络可以仅凭文本预测任何文章的发表。

因此,上面的陈述意味着,如果不同的新闻媒体以一致可预测的方式报道主题,神经网络将能够预测文本来自哪个出版物,这可能导致出版物出现偏差的概率很高。

在我的情况下,作为神经网络,我将使用长短期记忆网络(LSTM)。

什么是 LSTM?

LSTM 网络是一种特殊的递归神经网络(RNN),能够学习长期依赖关系。

RNN 有能力理解先前事件的推理,并以此来告知后来的事件。

Christopher Olah 写了一个很棒的博客,解释了 LSTM 是如何工作的,我会在参考资料中包含链接。

为什么是 LSTM?

在我的例子中,根据文本预测出版物是一个序列分类问题,LSTM 网络是解决这个问题的最先进的方法。

将 LSTM 网络应用于各种问题已经取得了令人难以置信的成功:语音识别、语言建模、翻译、图像字幕。

流程

下面是使用 LSTM 模型的过程:

为了进一步解释什么是标记化单词以及如何为建模准备数据,我决定包含代码。我使用 NLTK 的包标记器对单词进行了标记。Tokenizer 将文章拆分成标记化的句子,并将标记化的句子转换成序列格式。

当数据准备好适合模型时,我将我的数据分为训练和测试,并将测试集用作验证集。我用 Keras 的框架建立了 LSTM 模型。Keras 内置指标是一个准确度分数。为了确保我的类是平衡的,我手动计算了精确度、召回率和 f1 分数,我将把它们作为额外的指标添加到我的模型中。请参考下面的代码。

将我的数据拟合到模型中后,我的模型给出了以下结果:

我的模型的预测有 73%是正确的,我的 F1 分数是 75%,这意味着我的模型上的所有类都是平衡的。

因为我的模型返回了成功的结果,所以我能够证明我的假设。根据我的假设,神经网络确实可以预测一篇文章的出版,仅基于其文本,这可以表明每个出版物都有可检测的语言偏见。

因此,我受到鼓励,继续推进我的新闻推荐平台。

新闻推荐平台

下面的例子展示了推荐平台的用法。主题是生殖权利立法。

受到质疑的那段文字来自福克斯新闻频道的文章,他们在文章中描述了生孩子对老年人来说是一种经济价值。

结果下面的另一段文字,是我的推荐平台的结果之一,来自《纽约时报》的文章。正文指出,孩子需要情感和物质资源,不是每个人都能负担得起的。我展示这个例子是为了理解阅读不同的视角来理解问题是多么有价值。

流程

平台的过程很简单,因为平台上的推荐是基于余弦相似度的。

余弦相似度是一种度量标准,用于衡量文档的相似程度,而不考虑其大小。在数学上,它测量的是在多维空间中投影的两个向量之间的角度余弦。余弦相似性是有利的,因为即使两个相似的文档相距欧几里德距离很远(由于文档的大小),它们仍有可能更靠近在一起。角度越小,余弦相似度越高。

但在我将数据拟合成余弦相似度之前,我必须经历两个步骤:

首先,使用 Countvectorizer 获得每篇文章中的单词数。它的输出是一个稀疏矩阵。

第二,使用非负矩阵分解(NMF)来分解高维向量并将它们转换成低维向量。

我将这两个步骤分别应用到查询(您输入到平台中的文章或主题)和数据框中。余弦相似性连接查询和数据集以提供推荐。

请参见下面的代码:

烧瓶应用

作为一名数据科学家,我的大部分工作都是在 Jupyter 笔记本上完成的。为了让人们使用我的工作,我决定使用 Flask 应用程序创建一个 web 应用程序。Flask 是一个轻量级的开源 web 应用程序框架。

为了连接我在 Jupyter notebook 中运行的模型和数据,我使用了 pickle 库。Pickle 允许我保存 NMF 模型、数据和计数矢量器,我可以在我的 Flask 应用程序中运行它们。

Pickle Rick from Rick & Morty and Flask logo

下面是 Flask APP 的搭建过程。

我不会在这里发布代码,因为你可以在我的 GitHub 库的 flask app 文件夹中找到所有代码。

下面的视频举例说明了我的应用程序是如何工作的。我使用了 Vox 报纸的文本,只是为了展示你如何从不同的出版物中获得相似的文章推荐,基于你正在寻找的信息。

该应用程序还提供了每篇文章的情感评分,你可以点击出版物访问原始网站。

未来的工作

  1. 公开部署应用程序—应用程序的重量是 30GB,所以我需要找到一种方法来获得一个可以容纳它的开源域或云存储。
  2. 通过自动抓取新文章来更新模型。
  3. 将应用程序部署为 Chrome 扩展。

参考

如何获得 keras 模型的准确度、F1、精度和召回率?

了解 https://colah.github.io/posts/2015-08-Understanding-LSTMs/ LSTM 网络—

谨防网上“过滤泡沫”——https://www . ted . com/talks/Eli _ pariser _ deep _ online _ filter _ bubbles/抄本?language=en

GitHub 知识库

https://github.com/AisOmar/Media_bubbles

在 Python 中导航 NaNs 的地狱

原文:https://towardsdatascience.com/navigating-the-hell-of-nans-in-python-71b12558895b?source=collection_archive---------0-----------------------

了解 nan 并在您的数据中轻松处理它们的摘要。

Photo by Chris Ried on Unsplash

I 我 最近有很多 NaNs 引起的头痛。每个程序员都知道它们是什么,以及它们为什么会发生,但在我的情况下,我并不知道它们的所有特征,或者说还不够好来阻止我的努力。为了找到解决方案并避免令人头疼的问题,我进一步研究了 Python 中 NaNs 值的行为。在 Jupyter Notebook 里摆弄了几个语句之后,我的结果相当令人吃惊,也极其混乱。这是我用 Numpy 的 np.nan 得到的。

np.nan in [np.nan]True

到目前为止还好,但是…

np.nan == np.nanFalse

啊?还有…

np.nan is np.nanTrue

那么 Python 中的 NaNs 到底是怎么回事?

简短介绍

NaN 代表不是一个数字,是一种常见的缺失数据表示。它是一个特殊的浮点值,不能转换为除 float 以外的任何其他类型。甚至在 Python 存在之前,它就由用于算术运算的二进制浮点 I EEE 标准 (IEEE 754)引入,并在遵循该标准的所有系统中使用。NaN 可以被视为某种数据病毒,会感染它所涉及的所有操作。

无对南

None 和 NaN 听起来相似,看起来相似,但实际上很不一样。None 是一个 Python 内部类型,可以认为它等同于 NULL。[None](https://www.w3schools.com/python/ref_keyword_none.asp)关键字用于定义空值,或者根本没有值。None 不同于 0、False 或空字符串。它是自己的数据类型(NoneType ),并且只有 None 可以是… None。数值数组中的缺失值为 NaN,而对象数组中的缺失值为 None。最好通过使用foo is None而不是foo == None which brings来检查无。我们回到上一个问题,我在 NaN 操作中发现了特殊的结果。

南不等于南

起初,读到np.nan == np.nanFalse会引发困惑和沮丧的反应。这看起来很奇怪,听起来真的很奇怪,但如果你稍微思考一下,逻辑就会开始出现,甚至开始变得有意义。

尽管我们不知道每个 NaN 是什么,但不是每个 NaN 都是一样的。

让我们想象一下,我们看到的不是 nan 值,而是一群我们不认识的人。他们对我们来说是完全陌生的人。陌生人对我们来说都是一样的,也就是说我们把他们都描述成陌生人。但是,现实中并不意味着一个不认识的人就等于另一个不认识的人。

离开我这个奇怪的比喻,回到 Python, NaN 不能等于它自己,因为 NaN 是失败的结果,但是失败可以以多种方式发生。一次失败的结果不能等于任何其他失败的结果,未知值也不能彼此相等。

平等与身份

现在,要理解np.nan in [np.nan]为什么是True,我们得看看相等相同的区别。

平等

等式指的是大多数 Python 程序员都知道的“==”这个概念。这用于询问 Python 该变量的内容是否与另一个变量的内容相同。

num = 1
num2 = 1num == num2 

最后一行将导致True两个变量的内容相同。如前所述,一个 NaN 的内容永远不等于另一个 NaN 的内容。

身份

当你问 Python 一个变量是否与另一个变量相同时,你就是在问 Python 这两个变量是否共享相同的标识。Python 为每个创建的变量分配一个 id ,当 Python 在一个操作中查看变量的身份时,会比较 id。然而,np.**nan** 是一个单一的对象,它总是有相同的 id,不管你把它赋给哪个变量。

import numpy as np
one = np.nan
two = np.nan
one is two

np.nan is np.nanTrue``one is two也是True

如果使用id(one)id(two)检查onetwo的 id,将显示相同的 id。

np.nan in [np.nan]之所以是True是因为 Python 中的 list 容器在检查相等之前先检查身份 。然而,根据它们是如何被创造出来的,它们有不同的“味道”。float(‘nan’)用不同的 id 创建不同的对象,所以float('nan') is float('nan')实际上给了假!!稍后我们将再次提到这些差异。****

对付南而不头痛

最初,完整的 nan 概念可能很难理解,也很难处理。令人欣慰的是, pandasnumpy 在处理 nan 值方面非常出色,它们提供了几个函数,可以轻松地选择、替换或删除变量中的 nan 值。

测试值是否为 nan

正如我所说的,每当你想知道一个值是否是一个 nan,你不能检查它是否等于 nan。然而,有许多其他的选择可以做到这一点,我提出的并不是唯一的选择。

import numpy as np
import pandas as pdvar = float('nan')var is np.nan #results in True
#or
np.isnan(var) #results in True
#or
pd.isna(var) #results in True
#or
pd.isnull(var)#results in True

pd.isnull & pd.isna()表现一致。熊猫提供了。isnull()函数,因为它是 Python 中 R 数据帧的改编版。在 R 中,null 和 na 是两种不同的类型,具有不同的行为。

除了 numpy 和从 Python 3.5 开始,你也可以使用math.**nan** 。我在本文中同时写 nan 和 NaN 的原因(除了我缺乏一致性)是值不区分大小写的事实。float(‘nan’)float(‘NAN’)都会产生相同的结果。

import math
var = float('nan')
math.isnan(var) #results in True

小小警告:

import math
import numpy as np
math.nan is math.nan #results in True
math.nan is np.nan #results in False
math.nan is float('nan') #results in False

因为math.nannp.nanfloat('nan')都有不同的 id,所以这些语句为假。他们没有相同的身份。

对于数据帧

import pandas as pddf = pd.DataFrame(some_data)df.dropna()
#will drop all rows of your dataset with nan values. 
#use the subset parameter to drop rows with nan values in specific columnsdf.fillna()
#will fill nan values with the value of your choicedf.isnull()
#same as pd.isnull() for dataframesdf.isna()
#same as pd.isna() for dataframes

不幸的是,我并不认为熊猫文档在丢失数据文档方面非常有用。然而,我真的很欣赏这篇摘自 Python 数据科学手册,它很好地概述了如何处理 Pandas 中的缺失数据。

需要注意什么

type error:“float”对象不可迭代

虽然非类型错误非常清楚,但是由 nan 值引起的错误可能会有点混乱。Nan 值经常会导致错误(更具体地说是 TypeErrors ),这将涉及到它们的类型“ float ”。错误消息可能会令人惊讶,尤其是当您认为您的数据绝对没有浮点数时。您的数据帧可能看起来不包含任何浮点,但实际上,它确实包含。它可能有你不知道的 nan 值,你只需要去掉你的 NaN 值就可以消除这个错误!

作为一名数据科学家和 Python 程序员,我喜欢分享我在这一领域的经验,并将继续撰写关于 Python、机器学习或任何有趣的发现的文章,这些发现可能会使其他程序员的生活和任务变得更容易。在MediumTwitter上关注我,以获得关于 Python &数据科学的任何未来文章的通知!

[## 向你的祖母解释数据科学

或者如何向你的家人或任何与技术世界脱节的人解释数据科学。

towardsdatascience.com](/explaining-data-science-to-your-grandma-f8345621483d)

导航超参数空间

原文:https://towardsdatascience.com/navigating-the-hyperparameter-space-32f48be2c12d?source=collection_archive---------27-----------------------

开始应用机器学习有时会令人困惑。有许多术语需要学习,其中许多术语的使用并不一致,尤其是从一个研究领域到另一个领域——其中一个术语可能意味着两个不同领域中的两种不同事物。

今天我们来讲一个这样的术语:模型超参数

参数 vs .超参数:有什么区别?

让我们从最基本的区别开始,即参数和超参数之间的区别。

模型参数是模型内部的属性,并且是在训练阶段学习到的,并且是模型进行预测所需要的。

另一方面, 模型超参数不能在训练期间学习,而是预先设定。它们的值可以使用经验法则或试错法来设置;但事实上,我们无法知道特定问题的最佳模型超参数— ,因此我们调整超参数以发现具有最佳性能的模型参数

在某种程度上,超参数是我们可以用来调整模型的旋钮。

超参数调谐

也叫超参数优化,是 为一个特定的学习算法 寻找性能最好的超参数集合的问题。

这是一个重要的步骤,因为使用正确的超参数将会发现模型的参数,从而产生最巧妙的预测;这也是我们最终想要的。

这种性质的优化问题有三个基本组成部分:(1)一个目标函数,这是我们想要最大化或最小化的模型的主要目的;(2)控制目标函数的一组变量;(3)一组约束,允许变量取某些值,同时排除其他值。

因此,优化问题是找到最大化或最小化目标函数同时满足约束集的一组变量值。

解决优化问题有不同的方法,也有许多实现这些方法的开源软件选项。在本文中,我们将探索网格搜索、随机搜索和贝叶斯优化

网格搜索

也被称为参数扫描 它被认为是最简单的超参数优化算法。它包括彻底搜索手动指定的一组参数,这意味着为指定子集的所有可能组合训练模型。

如果模型可以快速训练,这种方法可能是一个很好的选择,否则,模型将需要很长时间来训练。这就是为什么不认为使用网格搜索来调整神经网络的超参数是最佳实践。

一个流行的实现是 Scikit-LearnGridSearchCV 。其他实现还有 Talos ,一个包括用于 KerasH2O 的库,一个为不同的机器学习算法提供网格搜索实现的平台。

随机搜索

随机搜索背后的思想与网格搜索非常相似,除了它不是穷尽搜索手动指定参数集的所有可能组合,而是选择组合的随机子集来尝试**

这种方法大大减少了运行超参数优化的时间,但是有一个警告:没有保证会找到最优的超参数集

一些流行的实现有 Scikit-LearnRandomizedSearchCVhyperptTalos

贝叶斯优化

我们已经确定随机搜索网格搜索建立在相似的想法上,它们的另一个共同点是不使用以前的结果来通知每个超参数子集的评估,并且反过来它们花费时间评估不到最优选项

相比之下,贝叶斯优化会跟踪过去的评估结果,使其成为一种自适应的优化方法。寻找满足目标函数的变量的值是一种 强有力的策略,该目标函数评估 是昂贵的。在某种程度上,当我们需要最小化我们在试图 找到全局最优 时所采取的步骤的数量时,贝叶斯技术是最有用的。

贝叶斯优化结合了关于目标函数的先验信念(【f】),并使用从【f】中提取的样本更新先验,以获得更好地逼近的后验概率(f)——马丁·克拉瑟(2018)贝叶斯优化。

为了实现这一点,贝叶斯优化利用了另外两个概念:一个代理模型和一个获取函数。第一个是指用于 逼近目标函数 的概率模型,第二个是用于 确定采样域内的新位置 ,在该位置最有可能对当前最佳评估结果进行改进。这是贝叶斯优化模型效率背后的两个关键因素。

替代模型**有几种不同的选择,最常见的有 高斯过程、随机森林回归和树 Parzen 估计器 。至于采集函数,最常见的有最大概率改善,置信上限 。******

一些流行的实现有Scikit-Optimize贝叶斯优化SMAC兰香MOEhyperpt**

结论

超参数优化对于机器学习任务来说是一件大事。这是提高模型性能的重要一步,但不是实现这一目标的唯一策略。

在我们探索的所有方法中,不同的从业者和专家会根据他们的经验提倡不同的方法,但是他们中的许多人也会同意实际上取决于数据、问题和其他项目考虑因素。最重要的一点是,这是寻找最佳表演模特的关键步骤。****

在可解释的海洋中航行

原文:https://towardsdatascience.com/navigating-the-sea-of-explainability-649672aa7bdd?source=collection_archive---------17-----------------------

设定正确的路线并负责任地驾驶

本文由Joy rim chalaShir Meir Lador合著。

设定正确的路线

近年来复杂机器学习(ML)模型的快速采用给当今公司带来了新的挑战:如何解释、理解和解释这些复杂模型预测背后的推理。将复杂的人工智能系统视为可信赖的黑盒而不进行健全检查已经导致了一些灾难性的结果,正如最近在 GenderShades 中披露的性别和种族偏见所证明的那样。

随着 ML 辅助预测更深入地整合到高风险决策中,如医疗诊断、累犯风险预测、贷款审批流程等。了解 ML 预测的根本原因变得至关重要。如果我们知道某些模型预测反映了偏见,并且不符合我们的最佳知识和社会价值观(如平等机会政策或结果公平),我们可以检测这些不良的 ML 缺陷,防止部署此类 ML 系统,并纠正模型缺陷。

The GenderShades study reported noticeable differences in gender classification accuracy of widely used face detection algorithms including Microsoft Cognitive Services Face API, FACE++, and IBM watson visual recognition. There’s a large gap in gender misclassification rates among different subgroups, with the largest gap of 34.4% observed between a lighter skinned male face compared to darker skinned female face.

我们在 Intuit 的使命是为全世界的繁荣提供动力。为了帮助小企业和个人增加成功的几率,在过去几年中,Intuit 一直在其平台和解决方案中注入人工智能和人工智能。作为 Intuit 的数据科学家,我们拥有独特的特权和权力来开发 ML 模型,这些模型做出的决策会影响人们的生活。有了这种权力,我们也有责任确保我们的模型符合最高标准,不以任何方式进行歧视。“不妥协的诚信”是 Intuit 的核心价值观之一。随着我们成为一个人工智能/人工智能驱动的组织,机器可理解性已经成为 Intuit 人工智能/人工智能产品的优先事项。

今年,Intuit 在 KDD 2019 举办了一场可解释的人工智能研讨会( XAI 2019 )。我们从此次研讨会中获得了许多宝贵的经验,并将开始将其融入我们的产品和服务战略中。

理解可解释性的当前状态

可解释性是一个活跃的研究领域,下面提供的描述旨在提供该领域当前状态的高度概括。根据被解释的模型是(a)黑盒(不可理解)还是(b)玻璃盒(可理解),可解释性方法分为两大类。在下一节中,我们将解释和比较每种方法。我们还将描述如何使用可理解的模型来更好地理解我们的数据。然后,我们将回顾一种检测任何用例(罗生门曲线)的高性能可理解模型的方法。最后,我们将比较局部和全局解释以及基于特征和基于概念的解释。

黑匣子:

黑盒可解释性方法试图解释已经存在的 ML 模型,而不考虑模型的内部工作(即,学习的决策函数)。这类可解释性方法是模型不可知的,可以轻松地与各种 ML 模型集成,从基于决策树的模型到复杂的神经网络。应用黑盒可解释性并不要求 ML 从业者创建和训练模型的方式有任何改变。由于这个原因,黑盒可解释性方法在 ML 从业者中享有更广泛的采用。黑盒可解释性方法也被称为“事后”可解释性,因为它们可以用于在训练和部署后询问 ML 模型,而无需任何训练程序的知识。黑盒可解释性方法的例子包括石灰Shapley⁶、 综合渐变 ⁷、深度提升 ⁸等。事后模型解释是解释的代理。以这种方式得出的解释不一定保证对人友好、有用或可行。

玻璃盒子:

具有可理解的 ML 模型的玻璃盒子方法要求模型在前面是“可解释的”(也称为“预先的”)。这种方法的优点是,ML 从业者可以轻松地梳理出模型解释,检测数据和/或标记缺陷,并且在某些情况下,如果模型决策与从业者的价值观或领域知识不一致,可以编辑模型决策。微软研究院高级首席研究员、KDD·XAI 2019 主题演讲人之一 Rich Caruana ,展示了他的团队如何基于广义可加模型(GAMs) 构建了一个高度准确、可理解、可编辑的 ML 模型,并将其应用于肺炎病例的死亡率预测 这个版本,也被命名为 GA2M(或 "GAM on steroids" ),通过梯度增强而不是原始版本中的三次样条进行优化,并实现了与现代 ML 模型(如随机森林或梯度增强树)相当的结果。

使用可理解的模型

卡鲁阿纳分享了他的团队如何使用可理解的模型来更好地理解和纠正他们的数据。例如,可理解模型了解到一条规则,即有哮喘病史的肺炎患者死于肺炎的风险低于普通人群。这一规则是违反直觉的,但反映了训练数据中的真实模式:有哮喘病史并表现出肺炎症状的患者通常不仅被送入医院,而且直接被送入重症监护室。哮喘性肺炎患者接受的积极治疗非常有效,与普通人群相比,降低了他们死于肺炎的风险。因为这些患者的预后好于平均水平,根据数据训练的模型错误地认为哮喘降低了死亡风险,而事实上哮喘患者的风险要高得多(如果不积极治疗的话)。

如果更简单、更易懂的模型可以学习违反直觉的关联——例如,患有哮喘意味着更低的肺炎风险——更复杂的基于神经网络的算法可能也能做到这一点。即使我们可以从数据中去除哮喘偏见,还有哪些不正确的事情被了解到?这是统计混淆的经典问题:当一个变量(在我们的例子中,治疗强度)同时与因变量和自变量相关时,会导致虚假关联。治疗强度受哮喘变量的影响,从而降低死亡风险。

这一观察说明了模型可理解性在高风险决策中的重要性。捕捉数据中真实但虚假的模式或特质的模型——如肺炎例子中的虚假关联或社会偏见——可能会产生导致不良后果(如虐待患者)的预测。当前的 ML 模型被训练为最小化训练数据的预测误差,而不是与任何人类直觉和概念一致,因此不能保证模型将与人类的价值观一致。通常,在人类管理的数据集上训练的 ML 模型将反映数据中的缺陷或偏差 。一个可理解的模型允许这些缺陷在模型验证期间出现。

目前,只有一小部分算法——即基于决策树的模型和广义加性模型(gam)——是可理解的。基于决策树的模型和 gam 不用于 ML 应用(如计算机视觉、自然语言处理和时间序列预测),因为这些模型的最佳可能版本目前不能在复杂的基于深度神经网络的模型的最先进水平上执行。

为任何用例检测高性能的可理解模型

当我们能够在同等性能的可理解和黑盒模型之间进行选择时,最佳实践是选择可理解的那个 。我们如何知道对于一个特定的应用程序是否存在一个高性能的可理解的模型?杜克大学计算机科学教授、数理统计研究所(IMS)2019 年研究员(也是 KDD XAI 2019 的小组成员)辛西娅·鲁丁提出了一种诊断工具,称为“罗生门曲线”、 ,可以帮助 ML 从业者回答这个问题。

我们先定义几个术语。“罗生门效应”指的是这样一种情况,在这种情况下,存在许多不同的、几乎同样准确的描述来解释一种现象。“罗生门效应”一词源自一部受欢迎的日本电影(罗生门),这部电影以涉及不同角色对同一事件进行自私描述的情节而闻名。在模型类中所有可能模型的假设空间上定义的“罗生门集”,是训练性能接近类中最佳模型的 ML 模型的子集。“罗生门比率”是罗生门集的基数除以所有可能模型的基数(精确度不同)。因此,为每个 ML 任务/数据集对唯一地定义了“罗生门比率”。当罗生门比率较大时,存在几个同样高精度的 ML 模型来解决该 ML 任务。罗生门集合中的这些高精度模型中的一些可能具有期望的属性,例如可理解性,并且寻找这样的模型可能是值得的。因此,罗生门比率作为最大似然问题简单性的指标。

在她的 KDD 2019 主题演讲中,Rudin 介绍了“罗生门曲线” (见下图),这是一条连接模型类层次结构的对数罗生门比率的诊断曲线,其复杂性随着经验风险(模型类上的错误率界限)的增加而增加。

Left figure : Empirical Rashomon sets are defined for each ML task/dataset pair and class of model (hypothesis space). Rashomon curves connect the Rashomon ratio of increasingly complex model classes as a function of empirical risk (the observed error of a particular model class). The horizontal part of the Γ-shape corresponds to a decrease in the empirical risk (increase in model accuracy) as we move through the hierarchy of hypothesis spaces (H1 on the top right to H7 on the bottom left). The length of arrow delta is the generalization error. If the ML problem is too complex for a model class considered, only the horizontal part of the Rashomon curve is observed. This is an indication that the model class considered is not complex enough to learn the training data well. On the other hand, if the ML model class considered is too complex for the training data, only the vertical part of the Rashomon curve is observed. Right Figure: The state-of-the-art for the various public ML problems/datasets on their own Rashomon curve, indicating whether it’s likely to be too complex or too simple for the given ML task/dataset pairs.

当解决一个 ML 问题时,人们可能会考虑从简单到复杂的模型(假设)类的模型类层次结构。起初,模型类对于 ML 任务来说仍然过于简单,并且模型的错误率随着复杂性的增加而不断降低。该观察对应于沿着罗生门曲线的水平部分从右向左移动。在这种情况下,罗生门体积以与所有可能模型的所有集合的体积大约相同的速率增长(具有不同的精度)。在 ML 模型类开始变得对 ML 任务太复杂的情况下,模型错误率保持不变。这相当于从顶部到底部遍历罗生门曲线的垂直部分。在这种情况下,所有可能模型的集合超过了罗生门集合,罗生门比率急剧下降。罗生门曲线的转折点(“罗生门肘”)是较低复杂性(较高的对数罗生门比率)和较高准确性(较低的经验风险)的最佳结合点。因此,在模型类的层次结构中,落在罗生门弯头附近的那些可能具有适当的复杂度水平,以实现高精度与期望属性(如概化和可解释性)之间的最佳平衡。

本地与全球解释

可解释性方法可以提供两种类型的解释:局部和全局 。本地解释描述了模型如何对单个数据实例进行分类,并回答了诸如“哪个(些)数据元素对分类输出最负责?”在图像分类中,这相当于识别哪个像素负责“猫”图像类别预测,以及负责多少。局部解释对于围绕单个数据点研究 ML 决策是至关重要的。

LIME [local interpretable model-agnostic explanations taken from [2]]. The original model’s decision function is represented by the blue/pink background, and is clearly nonlinear. The bright red cross is the instance being explained (let’s call it X). Perturbed instances are sampled around X and are weighted according to their proximity to X (weight here is represented by size). Original model predictions are calculated on these perturbed instances. These are used to train a linear model (dashed line) that approximates the model well in the vicinity of X. Note that the explanation in this case is not faithful globally, but it is faithful locally around X.

This figure illustrates a local explanation of Google’s Inception neural network on some arbitrary image. (4) keep as explanations of the parts of the image that are most positive toward a certain class. In this case, the classifier predicts Electric Guitar, even though the image contains an acoustic guitar. The explanation reveals why it would confuse the two: the fretboard is very similar.

另一方面,全局解释试图提供模型如何为整个对象类或数据集生成预测的整体概括,而不是集中在单个预测和数据点上。

The plots above demonstrate global explanations for a model trained on the census income dataset to predict the income level for adults, based on demographic features. The left figure (calculated using InterpertML) shows the score predicted by a GA2M model as a function of age. This directly illustrates the age contribution to the model. The right figure shows the mean absolute score of each feature to the model (aka feature importance).

两种最流行的全局解释技术是特征重要性和部分依赖图。特征重要性提供了一个分数,表明每个特征在模型构建中的有用性或价值。在基于决策树的模型中(如随机森林或梯度推进),在决策树中用于做出关键决策的特征越多,其相对重要性就越高。部分相关性图(PDP)显示了目标变量和一组“目标”特征之间的相关性,忽略了所有其他特征(“补充”特征)的值。直观上,我们可以将部分相关性解释为作为“目标”特征的函数的预期目标响应。部分相关图有助于我们理解特定特征值如何影响预测,这对模型和数据调试很有用,如 所示。

基于特征与基于概念的解释

早期的可解释性方法依赖于使用输入特征来构建解释。这种方法被称为基于特征的解释。基于特征的解释的一个关键困难是,大多数 ML 模型对特征(如像素值)进行操作,这些特征不符合人类容易理解的高级概念。在她的 KDD XAI 2019 主题演讲中,谷歌大脑的高级研究科学家 Been Kim 指出,基于特征的解释应用于最先进的复杂黑盒模型(如 InceptionV3GoogleLeNet )可能会产生不合理的解释 。更重要的是,对于输入特征具有高维数的 ML 问题的基于特征的解释不一定导致人类友好的解释。

Testing with concept activation vectors (TCAV) quantitatively measures how a “concept” (defined by a collection of inputs) is learned by a trained model by quantifying sensitivity of a model prediction class along the direction of concept activation vectors (CAVs). CAVs are defined per layer and per concept by training a linear classifier [such as support vector machine (SVM)] over the activation states of a layer of a pre-trained network using a collection of “concept-defining” inputs vs. random inputs (CAV testing inputs). These CAV testing inputs can be constructed post-hoc and do not need to be part of the training/evaluation and target task-specific datasets. TCAV can be used with both black box complex models as well as interpretable models. TCAV is currently publicly available at : https://github.com/tensorflow/tcav

基于概念的可解释性基于人类定义的概念构建解释,而不是基于特征和内部模型(激活)状态的输入表示。为了实现这一点,输入特征和模型内部状态以及人类定义的概念分别在两个向量空间中表示:(Em)和(Eh)。这两个向量空间之间的函数映射(如果存在的话)提供了一种从输入特征和 ML 模型内部状态中提取人类定义的概念的方式。

在她的主题演讲中,Kim 介绍了概念激活向量(TCAV)测试,这是一种在人类定义的概念空间(Eh)和模型内部状态(Em) 之间进行定量翻译的程序。TCAV 需要两个主要成分:(1)包含概念的输入和负样本(随机输入),以及(2)测试概念的预训练 ML 模型。为了测试训练的 ML 模型捕获特定概念的程度,在训练的 ML 模型的子组件(层)上推断包含概念的输入和随机输入。然后,训练诸如支持向量机的线性分类器,以区分由包含概念的输入和随机输入引起的网络激活。这种训练的结果是概念激活向量(CAV)。一旦定义了 CAV,就可以为属于一个类的每个实例计算沿着 CAV 的类概率的方向导数。最后,一个类的“概念重要性”被计算为该类中被包含输入的概念相对于随机输入积极激活的实例的分数。这种方法允许人类询问模型是否“学习”了特定的可表达概念,以及学习得如何。

例如,人类可以使用 TCAV 询问计算机视觉模型“X”如何学习关联医生图像中的“白大褂”或“听诊器”的概念。为了做到这一点,人类测试人员可以首先收集一组包含白大褂和随机图像的图像,然后对这组图像应用预训练的“X”来获得预测,并计算“白大褂”概念的 TCAV 分数。该 TCAV 分数量化了在图像分类任务中“白大褂”的概念对于“医生”类别的预测的重要性。TCAV 是一种示例驱动的方法,所以它仍然需要仔细选择概念数据实例作为输入。TCAV 还依赖人类来生成要测试的概念,并让概念可以在概念输入中表达出来。

Example of a realistic use of TCAV to quantify how much the concepts of “white coat,” “stethoscope,” and “male” are important for an image classification model for a positive prediction of the “doctor” class.

像 TCAV 这样基于概念的可解释性方法是提取“人类友好”的 ML 解释的一个步骤。对于模型预测是否明智,以及它们是否符合我们的积极价值观,这取决于今天的 ML 从业者做出负责任和正确的判断。纠正训练有素的黑盒 ML 模型中的缺陷取决于我们,TCAV 可以帮助说明缺陷在哪里。

我们能做得更好吗?

作为一个人工智能实践者的社区,我们有责任清楚地定义我们希望可解释的人工智能成为什么,并建立指导方针,以产生考虑到使用什么条信息、如何(以什么方式)以有益(而不是有害或滥用)的方式构建可解释性,以及何时(在什么情况/背景下和向谁)交付它的解释。虽然今天可解释的人工智能方法有助于查明 ML 系统中的缺陷,但我们面前还有很多工作要做。

现在,这里有一些将可解释性带到当今实践最前沿的技巧:

  • 尽可能选择易于理解的模型。
  • 使用易懂的模型和当地的解释,确保模型和数据符合你的领域知识和社会价值观。
  • 衡量机器学习模型的性能,以确保决策符合社会价值观(例如,当建模数据包括受保护的群体时,优化一致性和平等机会以及准确性)
  • 将因果关系构建到模型解释中
  • 衡量解释的有用性和可操作性

结束语

在短短的几年时间里,可解释的人工智能作为一个领域已经走了很长的路。作为本次研讨会的共同组织者,我们有幸见证了对 ML 中可解释性的巨大热情。对我们所有人来说,可解释性可能是我们的“正北”为了人类的利益,我们如何通过确保“我们的价值观一致,我们的知识得到反映”来负责任地使用 ML。这超出了获得最终用户信任或获得狭义公平的范围。我们希望将可解释性与社会价值观结合起来,为那些生活和生计与多发性硬化症接触或受其影响的人造福。

承认

我们要感谢及时帮助审查 XAI·KDD 研讨会论文的志愿者团体。我们也非常感谢我们的研讨会发言人和小组成员分享他们的知识,智慧和精彩的内容。

参考资料:

【1】Joy Buolamwini,Timnit Gebru。性别差异:商业性别分类的交叉准确性差异。【2018 年 PMLR 第一届公平、问责和透明会议论文集 81:77–91

[2]马尔科·图利奥·里贝罗、萨梅尔·辛格和卡洛斯·盖斯特林。机器学习的模型不可知可解释性。 arXiv 预印本 arXiv:1606.05386 ,2016。

[3]露丝·C·方和安德里亚·韦达尔迪。通过有意义的扰动对黑盒的可解释的解释。2017 年 IEEE 计算机视觉国际会议(ICCV)论文集第 3429–3437 页

[4]彼得·达布考斯基和亚林·加尔。黑盒分类器的实时图像显著性。神经信息处理系统进展(NIPS) 2017,第 6967–6976 页

[5]春-常昊、埃利奥特·克里奇尔、安娜·戈登堡和大卫·杜文瑙德。通过反事实生成解释图像分类器。载于2019 年第三届学习表征国际会议(ICLR)论文集

6 Scoot Lundberg 和 Su-In Lee。解释模型预测的统一方法。于 神经信息处理系统进展,2017

[7]穆昆德·孙达拉扬,安库尔·塔利,奇奇扬。深度网络的公理化属性。载于《第 34 届国际机器学习大会(ICML)论文集》2017 年第 70 卷,第 3319–3328 页

[8]两代情·什里库马尔、佩顿·格林赛德、安舒尔·昆达耶。通过传播激活差异学习重要特征。ICML 2017 与 PMLR 第 70 卷第 3145–3153 页。

[9]基姆、辛西娅·鲁丁和朱莉·沙阿。贝叶斯案例模型:基于案例推理和原型分类的生成方法。在 NIPS 2014 中,第 1952–1960 页

[10] B .乌斯顿和 c .鲁丁。可解释线性分类的方法和模型。arXiv:1405.40472014。**

[11]特雷弗·哈斯蒂·罗伯特·蒂布拉尼。广义可加模型:一些应用。美国统计协会杂志 1987 年 82:398,371–386

【12】里奇·卡鲁阿纳保罗·科赫,尹娄,马克·斯特姆,约翰内斯·戈尔克,小糯米·埃尔哈达德。可理解的医疗保健模型:预测肺炎风险和住院 30 天再入院。第 21 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集第 1721–1730 页

[13] Yair Horesh,Noa Haas,Elhanan Mishraky,Yehezkel S. Resheff,Shir Meir LadorPaired-Consistency:一种基于示例的模型不可知方法,用于机器学习中的公平性正则化。于arXiv:1908.02641,2019。**

14 辛西娅·鲁丁。停止解释高风险决策的黑盒机器学习模型,转而使用可解释的模型。载于《自然机器智能》(2019)第 1 卷,第 206–215 页

[15] Semenova、Lesia 和 Cynthia Rudin。罗生门曲线和体积研究:机器学习中泛化和模型简单性的新视角。arXiv 预印本 arXiv:1908.01755 ,2019。

[16]金,后土和多希-维勒兹,终曲。迈向可解释机器学习的严谨科学。于arXiv:1702.08608,2017。**

[17]朱利叶斯·阿德巴约,贾斯汀·吉尔默,迈克尔·穆勒,伊恩·古德菲勒,莫里茨·哈特,被金。显著图的完整性检查。在neur IPS 2018**

[18]杨和 Been Kim BIM:用地面真值对可解释性方法进行量化评估。在arXiv:1907.09701,2019。

[19] Been Kim、Martin Wattenberg、Justin Gilmer、Carrie Cai、James Wexler、Fernanda Viegas 和 Rory Sayres。特征归因之外的可解释性:用概念激活向量进行定量测试(TCAV)。在 ICML 2018, 第 2673–2682 页

[20]汤米·雅各布拉·大卫·阿尔瓦雷斯-梅利斯。用自解释神经网络实现健壮的可解释性。arXiv:1806.07538 ,2018。

[21] Yash Goyal,Uri Shalit,Been Kim。用因果概念效应(CaCE)解释量词。在arXiv:1907.07165,2019。

*[22]伯克·乌斯顿,亚历山大·斯潘赫,刘洋。线性分类中的可操作追索权。在 2019 年公平、问责和透明会议(FAT)会议记录中,第 10–19 页

NBA 全明星球迷投票与球员价值(VORP):谁真的值得成为全明星首发?

原文:https://towardsdatascience.com/nba-all-star-fan-voting-vs-player-value-vorp-who-really-deserves-to-be-an-all-star-starter-325e750d6f6a?source=collection_archive---------11-----------------------

作为本月早些时候我的帖子的后续,其中 比较了赢份额和上场时间 等游戏内指标中领先的全明星投票接受者,我今天写的是关于哪些球员(根据 1 月 10 日**NBA 报道的球迷投票结果)目前被预测为全明星冷门,哪些可能不是最值得全明星首发的球员。

在这份报告中,我将比较球员的球迷投票和他们的 VORP,或替换球员的价值(定义如下),这是一个有用的高级指标,可以估计每个球员对他们球队的价值。没有一个标准可以完全理解一个球员的价值,但是 VORP 提供了一个很好的指示。

注意,粉丝投票占流程的 50%。剩下的 50%的加权全明星投票被委托给 NBA 球员和媒体。这个规则的改变是几年前做出的,目的是帮助最值得的球员获得全明星首发的荣誉,但是球迷的投票仍然占加权投票的很大一部分。

我来看看全明星投票的四个部分(东部联盟后卫、东部联盟前场、西部联盟后卫和西部联盟前场)的以下指标:

  • 超过替补球员的价值(VORP):篮球参考 将 VORP 定义为一个衡量每个球员对球队的整体贡献的标准,衡量的是理论上的“替补球员”会提供什么,其中“替补球员”被定义为拿最低工资的球员或者不是球队轮换中的正常成员。

-VORP 排名 :每个玩家由 VORP 排名,从高到低决定哪个玩家的 VORP 最高。

  • 上场分钟 :本赛季(截至 2019 年 1 月 11 日)的上场分钟数。

  • 全明星投票 :

o 绿色的 表示基于球迷投票,目前处于全明星首发位置的球员。

o

东部会议守卫

预计全明星首发(基于球迷投票)

东部的首发后卫和他们的 VORP 截然相反。凯里·欧文的 VORP 2.6 的成绩令人印象深刻,比紧随其后的东部后卫高出 0.5,显然他赢得了比赛的首发位置。另一方面,未来的名人堂成员德韦恩·韦德(Dwayne Wade)管理着一个可怜的. 1 VORP,只排在第 39 位,然而他的遗产使他的投票数上升到前 2 位。

谁应该首发(以 VORP 为准)

虽然我不怪球迷多愁善感,但基于本·西蒙斯 2.1 的 VORP,他应该和欧文一起首发。他在粉丝投票中排名前 6,但在第二首发位置的投票中落后于德韦恩·韦德。

气泡上的气泡上的**

肯巴·沃克的赛季在 VORP 排名第三,在投票中也是前六名之一,但是如果他想在这场大赛中首发,他需要与媒体和他的队友和解。

东部联盟前场

预计全明星首发(基于球迷投票)

扬尼斯·阿德托昆博,又名希腊怪胎,以领先的 3.8 VORP,比第二名高出 1 分,碾压东部联盟前场。

科怀·伦纳德乔尔·恩比德分别拥有第四和第五高的 VORPs,但发现自己目前处于首发位置,因为在粉丝投票中名列前三。**

【VORP】谁应该首发

单从 VORP 来看,詹尼斯应该会和尼古拉·武切维奇布雷克·格里芬一起进入首发阵容。尽管拥有第二好的 VORP,奥兰多的尼古拉·武切维奇在球迷投票中甚至没有进入前 6 名,这使得全明星首发不太可能。布雷克·格里芬通过增加一个越来越有效的三分球彻底改变了他的比赛,并在他的新家接受了他的领导角色,产生了第三高的 VORP,但目前在球迷投票中排名前三。**

其他玩家的注意事项

杰森·塔图姆的第二季无论如何都不算差,但从他轰动的新秀赛季开始,表现出了生产力的下降。他的 VORP 目前是 0.6,与上赛季他以 1.8 的 VORP 成绩结束比赛时相差甚远。尽管前场球员 VORP 排名第 30,但他目前在投票中排名前 6。文斯·卡特在仅仅 660 分钟的比赛中拥有 0.0 的 VORP,但仍然是前场领袖之一。**

西部联盟前场球员

预计全明星首发(基于球迷投票):

正如他们在他因伤缺席期间所见证的那样,很容易看出勒布朗·詹姆斯对一支多年未能进入季后赛的湖人队的重要性。然而,特别是由于前面提到的伤停补时,勒布朗发现自己的 VORP 排名第三。不过,看到国王再次领先粉丝投票并不奇怪。保罗·乔治在西部前场球员中拥有第二多的选票。他对 OKC 的成功起了很大作用,即使面对威斯布鲁克糟糕的投篮,但乔治只有第五高的 VORP。排在第 13 位的是卢卡·东契奇,尽管他是年度最佳新秀,但还没有全明星级别的 VORP。然而,球迷们对东契奇感到兴奋,他已经向达拉斯展示了未来几年的期望,他目前在球迷投票中保持着前 3 名的位置,这使他在全明星赛中处于有利的位置。

谁应该首发(以 VORP 为准)

除了詹姆斯,安东尼·戴维斯和尼古拉·约基奇都属于开球时的场地。超级巨星,潜在的交易目标,安东尼·戴维斯以 4.0 的 VORP 领先所有前场球员。这两支球队正在努力在一个满载的西部联盟中生存,但安东尼·戴维斯荒谬的比赛水平仍然让鹈鹕队在几场比赛之内成为第八种子。他是粉丝投票的前六名之一,但不是前三名,需要帮助才能获得首发位置。掘金的尼古拉·约基奇拥有第二高的 VORP,但在球迷投票中甚至没有进入前 6 名。他为西部领先的丹佛掘金队效力,但这仍然不足以让他得到球迷应有的关注。

西域都护府

预计全明星首发(基于球迷投票):

斯蒂芬·库里德里克·罗斯目前被设定为预计的西部首发前锋(根据目前的球迷投票统计),尽管他们分别拥有第 4 和第 16 名最佳前锋,并且本赛季比其他精英后卫多打了数百分钟。**

【VORP】谁应该首发

詹姆斯·哈登传奇般的赛季至今和灼热的 4.4 VORP 不足以使他成为全明星首发,如果粉丝投票保持原样,他将不得不依靠媒体和球员投票。达米恩·利拉德拥有第二高的 VORP,但目前在粉丝投票方面不在前两名之内。****

上泡

尽管拉塞尔·维斯特布鲁克经历了历史上糟糕的投篮赛季,但他仍然拥有第三高的 VORP,显示了他在球场上的积极影响。他在粉丝投票中是前 6 名,但不是前两名。

其他玩家注意

上赛季克莱·汤普森的受欢迎程度已经进入了前 6 名,尽管 VORP 排名第 65 位,VORP 排名惊人的 0.1。

感谢您阅读我最新的数据贴。 点击这里我的第一篇 NBA 全明星帖子,比较全明星投票和上场时间以及赢球份额 。请继续关注我的后续帖子,在那里我将看看哪些值得的玩家目前发现自己在外面观望。作为一名产品营销和数据分析专业人士,我对数据支持的讲故事充满热情。这些数据新闻帖子是我将真实数据与我个人的不同兴趣整合起来的方式,这些兴趣包括从旅行和娱乐到经济和社会问题的任何事情。
如果您有任何评论、故事想法或预期的数据项目,请随时发送电子邮件至 dwpwriting <邮箱至> gmail < dot > com,访问我的网站至
dwpeterson.com
,或通过
LinkedIn
联系我。****

NBA 全明星投票与场上表现:哪些球员真正属于全明星赛?

原文:https://towardsdatascience.com/nba-all-star-votes-vs-on-court-production-which-players-really-belong-in-the-all-star-game-e0749012cb17?source=collection_archive---------25-----------------------

这篇文章分析了迄今为止获得全明星投票最多的 NBA 球员,并将其与他们在球场上的表现进行了比较。

周四,NBA 发布了首届 2019 NBA 全明星投票结果。因为报道的总数是基于球迷的投票,所以有一种固有的偏见倾向于那些知名度更高、过去更成功的球员,或者是在大市场的球员。在今天的报道中,我将通过几个场上指标(上场时间和提前获胜份额统计)来比较这些票数领先的人,以了解这些潜在的全明星球员中谁属于这场大赛,以及谁在场上每分钟获得的票数最多。

在接下来的帖子里,我会看看哪些值得的玩家发现他们自己在看外面。这篇文章着眼于第一轮投票结果,并使用了从1 月 4 日开始的球员数据。

每分钟得分票数(2018-2019 赛季): 谁是每分钟得分最高的全明星球员?

不出所料,勒布朗·詹姆斯进军大市场并没有影响他的人气。詹姆斯在所有投票接受者中领先,本赛季每分钟获得 919.7 票。有点令人惊讶的是,扬尼斯·阿德托昆博(每分钟 851 票)和凯里·欧文(每分钟 828 票)获得票数的速度比斯蒂芬·库里(每分钟 816 票)快。

尽管詹姆斯·哈登的表现超凡脱俗,但他每分钟仅获得 429 张选票,在榜单上仅排在第 14 位。

在名单的底部,华盛顿奇才队的后场约翰·沃尔和布拉德利·比尔分别获得每分钟 49 票和 43 票。

这可能是一个很好的时机来提一下,德马库斯·考辛斯以 92,977 张选票名列前茅,尽管今年到目前为止没有参加一场比赛。

(会议)每分钟收到的投票数

即使吉米·巴特勒和科怀·莱昂哈德转投东部联盟,勒布朗的西部之旅也推动了西部联盟的优势。再一次,尽管本赛季打了 0 分钟,德马库斯·考辛斯获得的票数超过了 7 名东部球员。

全明星投票 vs 赢股:这些潜在的全明星球员在球场上对球队的实际影响如何?

赢股是一种玩家统计,试图将团队成功的功劳分配给团队中的个人。关于赢股更深入的解释可以在 这里 找到。

这个散点图比较了每个顶级投票接受者的全明星投票数和他们对自己团队的估计价值。

为球队的成功做出巨大贡献并获得大量全明星投票的球员:正如你在散点图中看到的,这些超级巨星为他们的球队创造了非凡的价值(赢得 4.8+的股份),迄今为止已获得超过 500,000 次全明星投票。安东尼·戴维斯在赢得份额(6.7)方面领先,但在多数投票中排名第十。

被低估的高影响力玩家:赢得份额高但票数低的玩家。尽管他们为球队的成功做出了很大的贡献,但像凯尔·洛瑞(多伦多)、布雷克·格里芬(底特律)、德马尔·德罗赞(圣安东尼奥)和达米恩·利拉德(波特兰)这样的小市场明星发现自己也在这个名单上。

被高估的低影响力球员:这些球员的投票受欢迎程度目前超过了他们在球场上的影响力。常年全明星如拉塞尔·维斯特布鲁克和克莱·汤普森,以及罗伊候选人卢卡·东契奇发现自己在这个名单上。

在球场上影响力低、投票率低的球员:这个群体是一个大杂烩,既有低迷时期的前全明星球员(克里斯·保罗、德雷蒙德·格林和戈登·海沃德),也有由于市场大而投票率高的优秀球员(但不是全明星球员)(湖人队的朗佐·鲍尔和凯尔·库兹马,凯尔特人队的戈登·海沃德和艾尔·霍福德)。

感谢您阅读我最新的数据帖子。请继续关注我的后续帖子,在那里我将看看哪些值得的玩家目前发现自己在外面观望。作为一名产品营销和数据分析专业人士,我对数据支持的讲故事充满热情。这些数据新闻帖子是我将真实数据与我个人的不同兴趣整合起来的方式,这些兴趣包括从旅行和娱乐到经济和社会问题的任何事情。
如果您有任何评论、故事想法或预期的数据项目,请随时发送电子邮件至 dwpwriting <至> gmail < dot > com 或通过
LinkedIn联系我。

NBA 数据分析:改变游戏

原文:https://towardsdatascience.com/nba-data-analytics-changing-the-game-a9ad59d1f116?source=collection_archive---------3-----------------------

三点射击和数据可视化工具

“分析是我们现在做的几乎所有事情的一部分”——NBA 专员亚当·席尔瓦

如果你是 NBA 的粉丝,你会很清楚 NBA 正在经历一场巨大的变革。比赛本身也在改变,因为球队正在发现新的方法来制定策略,以克服平庸的障碍,成为争夺冠军的球队。成为冠军争夺者的这一“过程”在很大程度上是由于数据分析。尽管备受争议,但它已被证明是将过去的平庸球队转变为竞争者的有效策略。

就在十年前,只有几支 NBA 球队在他们的前台办公室里有分析部门。今天,几乎所有 NBA 球队的前台都有数据分析师员工。利用数据分析是一种趋势,渗透到这项运动的每个方面,从新秀球探,发现被低估的球员,计算有效投篮,三分球的崛起,等等。所有这些都是为了打造一支冠军球队。

尽管这场革命很酷,但它不会没有批评者。查尔斯·巴克利等许多前玩家是数据分析的坚定反对者。

达里尔·莫雷-休斯顿火箭队

真正推动数据分析驱动篮球的个人之一是达里尔·莫雷,他自 2007 年以来一直是休斯顿火箭队的总经理。

因为莫雷的背景是统计学而不是篮球,他受到了评论员和球迷的批评,他们厌倦了莫雷和他的休斯顿火箭队重复的比赛风格。这种玩法是数据驱动的。

但是尽管有这些批评,火箭在最近几年已经证明了他们是强大的对手和竞争者。在 2017-2018 赛季,尽管有伤病,火箭队还是进入了西部决赛。在同一个赛季,他们创造了单赛季三分球数量的历史记录,同时在人才济济的西部联盟中排名第一。

Houston Shot Locations

正如你在上面看到的,休斯顿的投篮选择开始变得可预测了。

三分球的改编

数据分析改变篮球比赛的最大方式之一是三分球尝试的增加。分析师们研究了比赛和投篮,以确定哪些投篮更有可能推动球队取得胜利。

其中一个分析是,很多球员都投了远距离低效的 2 分球。由于缺乏成为一个篮子的可能性,整个联盟的分析师和教练组开始鼓励他们球队的射手在三分线上投更多的球。从统计学上来说,一个相当不错的射手有 35%的几率会投中。如果一个射手投了 3 次球,其中一次成功了,那么这份财产就值了。

主要的收获是,从 3 点线上的额外点获得的 50%的回报使得长距离的尝试是值得的。下面,你可以查看 1998-2017 年平均每场 3 分出手次数的时间线。

斯蒂芬·库里和金州勇士队

另一支从早期就大量采用数据分析的球队是金州勇士队。在过去的 5 年里,他们都进入了 NBA 总决赛。勇士队一贯使用的方法之一是三分球。

The Golden State Warriors hold 4 out of the top 10 record holders for 3 point shots made in a single season.

Source: Welcome to Smarter Basketball

在美国广播公司转播总决赛期间发布的一张图表显示了库里领先他的同龄人有多远。库里在季后赛中的三分球已经超过了 1980 年整个 NBA 的三分球数。

在 2015 年季后赛中,金州勇士队的斯蒂芬·库里在季后赛系列赛中的三分球比 1980 年 NBA 季后赛的所有球员都多。这并不是将 1980 年的球员归类为天赋较低,而是代表了篮球运动在过去十年中发生了多么彻底的变化。

数据可视化工具和视频跟踪

现在数据分析趋势中出现的一个更酷的东西是正在被创建和调整以收集和可视化数据的技术。

NBA 与一家名为 STATS 的公司合作,在每个篮球馆安装 6 个摄像头,以每秒 25 帧的速度跟踪球员和裁判的动作,以获得最具分析性的数据,供球队和 NBA 进行分析。

这个系统的好处是数不胜数的,对于一个推动球队找到最好的竞争策略的联盟来说。

Source: Analyzing NBA Basketball Data with R

有了这项技术,教练团队可以跟踪和分析比赛,根据他们将要对阵的球队或球星调整他们的防守和进攻策略。这些数据让玩家在如何根据对手和个人健康状况调整比赛和努力方面拥有优势。

金州勇士队在过去 5 年中如此成功的原因之一是他们愿意让他们的关键球员休息,如斯蒂芬·库里,T2 减少受伤的可能性,T4 确保球员可以打得更久。

这项技术有助于追踪球员最佳投篮的位置。我在研究中发现了以下网站,完全被玩家信息的详细程度所折服。

看看吧!

这是斯蒂芬·库里在球场某些区域投篮时与联盟其他球队的差距。显然,斯蒂芬·库里更喜欢在三分线和内线投篮。

最后的反思和笔记

当团队考虑将数据分析纳入他们的战略时,他们需要明智地制定决策。策略不是简单的投三分。如果你没有一个能有效投三分球的球员,你就不会成功。

“……团队取得了不同程度的成功。如果没有合适的球员来采用重分析的策略,团队很容易无法实现预期的结果。虽然三分球可能更有效率,但如果一支球队没有任何优秀的三分球手,这种策略仍然会让他们失败。”

也就是说,这种策略在大学篮球赛中也被采用。在 2018 年的三月疯狂中,维拉诺瓦大学打破了一场比赛中最多三分球的四强记录。

许多评论员是数据分析驱动篮球的坚定批评者。如前所述,NBA 鼓励球队在他们的策略中使用数据分析。但 NBA 和球队(特别是休斯顿火箭队)一直因重复的比赛风格和不受欢迎的方法而受到批评。为了避免重复的比赛风格,使比赛成为一场 3 分的比赛,一些人说要把 3 分线推得更远,让比赛变得更困难。

不管用什么方法,在 NBA 总裁亚当·席尔瓦的领导下,我毫不怀疑 NBA 正在考虑每一种可能的方式来保持篮球运动对球迷的吸引力。我确信联盟也在使用数据分析来应对这一挑战。

NBA 对进一步将分析纳入其系统持非常开放的态度。他们实际上在今年九月有一个黑客马拉松。

如果你是一名学生,一名 NBA 球迷,并且正在寻找挑战,我强烈建议你尝试一下。

来源

[## 这不是你爸的 NBA:感谢大数据

随着 NBA 经历其分析革命,大数据的兴起正在使旧学派与新学派对立起来。在…

www.theatlantic.com](https://www.theatlantic.com/entertainment/archive/2015/06/nba-data-analytics/396776/) [## 大联盟图表

编辑描述

bigleaguegraphs.com](https://bigleaguegraphs.com/nba/shot-charts) [## 篮球

流动数据

flowingdata.com](https://flowingdata.com/tag/basketball/) [## 数据分析让 NBA 变得面目全非

这不是你父母的国家篮球协会。它甚至不是你哥哥的。在过去的…

qz.com](https://qz.com/1104922/data-analytics-have-revolutionized-the-nba/) [## 莫雷球:休斯顿火箭队和分析

概述休斯顿火箭队如何将篮球分析带到一个新的水平,并上升到 NBA 的顶端…

digital.hbs.edu](https://digital.hbs.edu/platform-digit/submission/moreyball-the-houston-rockets-and-analytics/) [## 职业队篮球运动员追踪| SportVU |统计

SportVU 帮助 NBA 跟踪球员的运动,以提高他们的比赛水平。体育大学篮球运动员跟踪系统可以…

www.stats.com](https://www.stats.com/sportvu-basketball/)

NBA MVP 预测模型

原文:https://towardsdatascience.com/nba-mvp-predictor-c700e50e0917?source=collection_archive---------12-----------------------

根据团队和个人的成功计算价值

Art Credit to The Ringer NBA Show

最有价值球员奖是美国国家篮球协会(NBA)的最高个人荣誉。它是由媒体成员根据相对开放的价值定义投票产生的。煽动球迷和媒体成员之间关于价值在篮球比赛中真正意味着什么的对话(和激烈的争论)是故意主观的。

然而,这些年来,两个主要的叙事一直是“最佳球队的最佳球员”(即 2018:詹姆斯·哈登2016:斯蒂芬·库里)或拥有历史数字(即 2017:拉塞尔·维斯特布鲁克2014:凯文·杜兰特)。使用这两个叙述作为标准,我开始创建一个统计模型来评估一个玩家的价值基于他们对团队胜利和整体个人产出贡献。

我的目标是建立一个模型,可以准确地从过去 10 个赛季(我的训练数据)中授予 MVP,以便对 2019 年做出可靠的预测。最终的目的不是创造一个客观的价值真相,而是通过一致的统计镜头来看待 MVP 竞赛,这些镜头反映了每年相同的标准。

模型摘要

= . 5()±5(总统计 )**

如上所述,玩家的总价值是基于他们的胜利贡献总统计的平均水平。

注:这不是一个经过统计测试的模型。50/50 重量是一个理论起点。当我在更多的 MVP 比赛中加载和测试该模型时,我调整了权重,看看它会如何影响结果。最终,我以 50/50 的权重结束,以最大限度地提高十年间模型的准确性。

赢得贡献细分

=影响等级***影响质量

影响程度 = ( 队胜 * 比赛场次 /82 * 分钟 /48 * 使用率 /100)

影响质量= . 4(VORP+赢得份额)* + .2( 净价)***

1.影响程度

首先,我想通过比赛和上场时间以及使用率来衡量一个球员对球队胜利的影响程度(高或低)。从数学上来说,这里最重要的数字是团队的胜利。所有其他变量作为评估玩家对这些胜利的影响的比率。

用法在这里可能看起来有争议,但是我想衡量一个球队与他的队友相比有多依赖一个控球球员。例如在 2016 年,金州勇士队赢得了 73 场常规赛的纪录。他们的 3 名最佳球员分别是斯蒂芬·库里、克莱·汤普森和德雷蒙德·格林,他们都打了大约 80 场比赛,平均每场上场 34 分钟。在这种情况下,使用率是队友之间影响力的关键区分因素。

虽然统计数据通常倾向于后卫和持球者——本赛季使用率前 20 名中有 90%都不是中锋,但像乔尔·恩比德、安东尼·戴维斯和德马库斯·考辛斯(阿喀琉斯受伤前)这样的精英大个子由于他们出色的技术一直排在使用率前 10 名。稍后再讨论这个问题。

2.影响质量

接下来,我想测量球员在球场上的冲击质量(好或坏)。这是迄今为止构建模型最困难的方面。与棒球不同,没有一个被篮球界广泛接受的综合统计数据来衡量球员的影响力。因此,我使用了公众可以访问的多个高级统计数据的加权值。下面是他们的意思的快速总结。

  • *:衡量一名球员的相对影响力(方框加/减),根据上场时间与联盟平均水平进行调整。(注:自 2006 年以来,除了 5 次之外,VORP 的联盟领袖每年都获得 MVP)***
  • 净等级 :玩家每 100 次拥有产生多少进攻(进攻等级)和玩家每 100 次拥有放弃多少防守(防守等级)之间的点数差

使用赢球份额和 VORP 是因为要区分一个球员相对于队友的贡献(赢球份额)和对联盟其他成员的贡献(VORP)。净评级被包括在内,以区分球员在球场上的整体输出,并帮助调整等式,以有利于上场时间较短的球员,而 VORP 和 Win Share 对此进行了处罚。

权重的值有些随意,是在一系列反复试验后确定的,以最大限度地提高模型的准确性。尽管如此,净评级的权重较低的原因是它严重偏向大个子,并且它的部分计算(防守评级)也用于计算防守胜利份额,这是胜利份额的一部分。

总统计(单个输出)计算

( *** 真投篮%+1.5(助攻*** ) + 1.2( 篮板)+3(***盖帽********

我想让这个输出尽可能简单,借用了幻想篮球的权重。我添加的几个调整是乘(TS %)对抗得分。这让我可以排除像投篮,罚球,三分球和投篮这样的数据。虽然人们在评估 MVP 时会考虑这些数据,但我觉得(得分* TS%)是一种衡量得分产出与效率的简洁方法。最后一个单位 25 是一个标量,我用来使最终值接近 win 贡献值(也是为了最大化整体模型的准确性而选择的)。********

我想在这里回到使用率,因为当评估总统计数据时,它严重倾向于大个子(净评分也是如此,但这更多地归因于中锋在防守中的作用)。2019 年,鲁迪·戈贝尔和安德烈·德拉蒙德在个人产出方面分别排名第五和第六,超过了保罗·乔治(第九)和达米恩·利拉德(第十四)。这也是为什么我在赢球贡献公式中使用来平衡总统计中大个子的偏见。

对照过去十年的 MVP 测试模型

在预测 2019 MVP 之前,我想根据过去 10 个赛季评估模型的结果和固有偏差。这是一次有趣的回忆之旅,展示了随着时间的推移,全联盟对分析的认知和接受的总体变化。

(注:所有数据来源于 篮球-参考 )

2017–2018

  • 达米恩·利拉德是前五名中唯一的遗漏(第四名实际与第七名预测)****
  • 这里唯一的主要偏差是卡尔-安东尼·唐斯,他没有获得 MVP 的实际票数,而他的队友吉米·巴特勒(实际第 10 对预测第 22)被认为是明尼苏达成功的主要原因,尽管他错过了 23 场比赛

2016–2017

  • 一场历史上难分胜负的 MVP 比赛,但是模型显示拉塞尔·维斯特布鲁克以微弱优势胜出
  • 斯蒂芬·库里被投票者低估(第六名实际对第三名预测),可能是因为在 2016 年休赛期增加了凯文·杜兰特********

2015–2016

  • 在打破常规赛 73 胜的记录后,斯蒂芬·库里在实际投票和预测投票中获得了压倒性的胜利(联盟历史上第一个一致通过的 MVP
  • 尽管实际排名略有偏差,但模型第一次预测出了正确的前 5 名球员
  • 科怀·伦纳德获得预测第五对实际第二尽管赢得了年度最佳防守球员,可能是因为相对不引人注目的总数据(21 分,6.8 个篮板和 2.6 次助攻)****

2014–2015

2013–2014

  • 凯文·乐福,另一个被这个模型高估的明尼苏达大个子(第 11 实际 vs .第 3 预测),发布了一个惊人的个人统计赛季(在 VORP 联盟中排名第 3*仅次于勒布朗和 KD)*******
  • 本赛季的年度最佳防守球员乔吉姆·诺阿是最大的遗漏(实际第四对预测第十),可能是因为他缺乏进攻能力,导致公牛队获得 48 胜

2012–2013

  • 卡梅隆·安东尼是一个重大的遗漏(实际第 3 对预测第 15th】),尽管他是 54 胜尼克斯队的最佳球员(影响水平:12.11,联盟第 5)由于低于标准的先进指标(在 VORP 第 33,赢得份额第 14th】)而在*中遭受胜利质量*************
  • 总的来说,随着时间的推移,由于缺乏公众意识和对这些指标的接受,该模型将低估具有较差高级统计数据的球员(而实际投票者可能会高估他们)**

2011 年至 2012 年

  • 在一个锁定的缩短赛季中,布雷克·格里芬是最大的惊喜参赛。虽然他的个人数据(20.7 分,10.9 个篮板)很稳定,但他可能没有得到任何实际的选票,因为他的“ Lob City ”队友克里斯·保罗是球队的焦点**
  • 最大的遗漏是科比·布莱恩特* ( 实际排名第 4,预测排名第 19),他在 2013 年遭遇了与卡梅隆·安东尼类似的问题,成为一名高产量、低效率的球员(影响力水平 : 12.82,联盟排名第 4)(VORP 联盟第 25,赢球份额联盟第 35)***

2010–2011

  • 该模型的第一个 MVP 预测错误发生在 2011 年,此前勒布朗·詹姆斯于 2010 年决定加入迈阿密热火**
  • 这场失利的主要原因是德里克·罗斯是芝加哥谦逊的家乡后卫。而勒布朗在当时被认为是这个国家最大的体育恶棍
  • 然而,罗斯在的影响力水平上确实比勒布朗有优势,正如我们已经看到的那样,这与 2015 年之前的实际投票有很强的相关性(我将在后面介绍这一年的重要性)**
  • 最后,保罗加索尔很可能取代队友的位置,而科比布莱恩特* ( 第四名实际与第七名预测:影响水平:14.13,联盟第三),延续了该模型高估高效大个子而不是他们的边锋队友的趋势***

2009–2010

  • 一个没有重大失误的赛季,尽管这个模型继续低估科比的价值,但这次只是轻微低估!(第三实际与第六预测****

2008–2009

  • 另一个准确的赛季,尽管在顺序上有小错误,但模型预测了正确的前 5 名球员
  • 一个绝对具有历史意义的赛季,由勒布朗·詹姆斯创造,他创造了 NBA 历史上最高的 13 分,仅次于迈克尔·乔丹**

2018–2019 MVP 预测

…最后是对今年比赛的预测(这可能也是大多数读者所期待的)

该模型显示詹姆斯·哈登是预测的赢家,基于更高的影响水平(更多的比赛,更多的上场时间,更高的使用率)和更高的总数据* (36 分/场,联盟历史上第八高的得分赛季,仅次于威尔特·张伯伦,埃尔金·贝勒和乔丹,十年来第五高的总数据)。结果类似于拉塞尔·维斯特布鲁克 2017 年的胜利,尽管他的胜利较少,但总统计数据更好,但他击败了詹姆斯·哈登***

然而,我认为詹尼斯很可能仍然是最有希望赢得 MVP 的人,因为两个因素,叙事和防守。在叙事方面,詹尼斯是众所周知的“街区新人”,受到媒体和粉丝的喜爱(类似于 2011 年的德里克·罗斯),而哈登,现任获胜者,可能会遭受选民疲劳和对他的比赛风格的总体负面情绪。**

在防守方面,有 2016 年科怀·伦纳德和 2014 年乔吉姆·诺阿(两人都是年度最佳防守球员)被低估的例子。今年,Giannis 也在该奖项的争夺中(防守禁区正负排名联盟第二,防守胜率排名第三)。虽然这两个统计数据都被纳入了模型的计算中,但不难想象公众对詹尼斯的防守影响和整体叙事的看法将他推过了哈登。

结论

这个模型的创建和测试是一个有趣的思考练习,测试了我的统计学和篮球观点。在我对篮球价值的先入为主的观念和模型告诉我的东西之间,以及根据十年的结果对其进行改造,这是一件非常有趣的事情。以下是我的一些结束语:

  • 如前所述,2015 年是 NBA 意义重大的一年。金州勇士队成为第一支赢得总冠军的跳投球队,并帮助改变了全联盟对分析的看法。结果反映了该模型对科比和卡梅隆-安东尼等球员的一贯低估;高使用率、低效率的得分手仍然打 【英雄球】 而不是 【莫雷球】
  • 这个模型高估了像凯文·乐福、卡尔-安东尼·唐斯和布雷克·格里芬这样的大人物,这很有趣,因为这些球员能够出乎意料地进入前 5 名,这是因为他们同时拥有良好的统计数据和有利的先进统计数据。虽然传统智慧会把一些成功放在他们更具控球优势的队友身上,但这让我质疑这些大个子是真的被低估了,还是有利形势和统计数据的产物。**
  • 最后,低估防守是一种偏见,这种偏见不仅反映在这个模型中,而且贯穿于整个篮球运动。其中一部分原因是由于缺乏可靠的(和公开的)个人球员的防守统计数据。虽然这肯定会有助于模型(以及一个衡量公众情绪/叙事的分数),我不知道它会在多大程度上影响球迷对进攻的总体偏好。防守可能会赢得冠军,但一般不会上头条或者吸引赞助。老实说,我不知道任何数量的分析是否会改变这一点。

参考

完整的数据集,包括从 2019 年到 2009 年的球员统计数据,如果你有兴趣深入挖掘的话

使用数据科学和线性回归预测 NBA 薪资

原文:https://towardsdatascience.com/nba-salary-predictions-4cd09931eb55?source=collection_archive---------13-----------------------

用 Python 构建线性回归机器学习模型预测 NBA 球员工资的简要指南

这个项目旨在探索如何利用各种各样的 NBA 统计数据来预测一名 NBA 球员从 1995 年到 2017 年的工资。我对这个项目的目标是:

  1. 发现哪些统计数据是 NBA 球员工资的最佳预测指标
  2. 使用机器学习模型预测 NBA 薪资
  3. 根据给定的和预测的薪水,确定哪些球员被高估和低估了
  4. 确定哪些球队在从他们的球员身上获取价值方面是最好的和最差的,以及这是否与一个球队赢得的比赛数量有关

数据

我得到了我的主要数据,一个从 1950 年开始的大约 50 个 NBA 球员的统计数据和工资信息的数据库。数据的链接可以在这里找到。我决定只使用 1995 赛季开始的数据,因为 1950 年的 NBA 与 21 世纪的 NBA 有很大不同。我选择 1995 年,因为这是第一年有两支新球队加入,使球队总数达到 29 支(第 30 支球队,夏洛特山猫队,于 2004 年加入)。

我使用的另外两个数据源,工资帽信息每个赛季的球队胜率,都来自篮球参考,并被复制到一个 Excel 电子表格中,然后我将其导入到一个 Dataframe 中。

数据确实需要清理一点:总的统计数据,如上场时间或总得分,被他们的每场比赛当量所取代,以使统计数据标准化,假设该球员在那个赛季参加了超过一定数量的比赛(如果没有,他就被从数据集中删除)。此外,有许多球员没有列出该赛季的工资信息,因此被从数据集中删除。

The first five data points

哪些统计数据?

看了数据之后,一个早期的问题出现了。在过去的 20 年里,NBA 的平均工资大幅上涨。

解决方案是通过将工资数据作为联盟工资帽的百分比来标准化工资数据,工资帽是一个球队在给定赛季中可以花在球员身上的总工资限额。工资帽随着球员工资的上涨而上涨。

从那时起,是时候探索工资和统计数据之间的关系了。我从数据集中所有统计数据的关联热图开始。

不幸的是,由于统计数据的数量,从这些数据中没有获得多少有用的信息。因此,我切换到了 8 个统计数据的相关热图,这 8 个统计数据的皮尔逊 r 值最高。

然后,我将统计数据分成三个子类别:基本、普通和高级。基本的统计数据只包括球员的位置、年龄和上场时间。普通球迷会理解常规的统计数据:场均得分,场均篮板,投篮命中率等等。创建了高级统计数据来更详细地评估玩家的表现,其中一些包括玩家效率评级(PER)和获胜份额(WS)。

在统计数据被拆分后,我用同样的方法找到了每个角色中与薪水最相关的 8 个统计数据,并为它们创建了热图和散点图。

Heat map (left) and scatter plots (right) for advanced statistics

每个字符中的一些统计数据之间存在一些多重共线性,因此在分析后,一些统计数据被从前 8 位中删除。

机器学习模型

下一步是确定哪一个统计子类是工资的最佳预测者。为了实现这一点,为三个子类别中的每一个创建了线性回归机器学习模型,将数据分成训练和测试数据,并进行交叉验证。结果是,统计的常规子类别是最好的模型,其均方根误差(RMSE)为 6.46(三者中的最低值),r 为 0.466(三者中的最高值)。下面是剩余价值的图表——每个球员工资的实际工资上限百分比和预测百分比之间的差异。正残差值表示实际值大于预测值。

球员估价

常规线性模型用于预测数据集中每个球员的工资。然后,将这些预测与球员的实际工资进行比较,在数据框中创建一个残差栏,然后根据残差进行排序。下面重点介绍了前 25 名最被低估和最被高估的球员。

The most undervalued players according to the model

Some of the most overvalued players, according to the model

The model states that Michael Jordon in 1997 was the most overvalued player in the last 22 years.

看着这些数据,我开始质疑这个模型。最被高估的球员名单中充满了全盛时期的超级巨星,他们因为自己的能力而获得高薪,包括空前伟大的迈克尔·乔丹。高估和低估球员的统计数据有助于解释发生了什么。

Averages for most undervalued players

Averages for most overvalued players

最被低估的球员大多是年轻的、冉冉升起的新星,他们仍在新秀合同中,因此不会占用太多的工资帽空间。最被高估的球员大多是在他们的最佳巨星时期,他们得到相应的报酬。

认识到这一点后,我决定将残差标准化,将它们除以每个玩家的上限百分比,得到一个残差%。这更好地说明了谁被高估了,谁被低估了。

The new and improved most undervalued players

该模型对最被高估的球员极为不利,预测他们应该接受球队工资帽的负百分比,也就是说,球员应该为打球的特权向球队付费。即便如此,这也有助于确定哪些球员最被高估。

我的最后一项任务是将球员的价值与他们效力的球队联系起来,以及这与球队表现之间的关系。我将球员按球队分组,根据每个球员的平均实际支出百分比与平均预测百分比计算出每个球队的平均百分比百分比,并将过去 22 年的平均获胜次数作为一个附加类别添加进来。

The top section of the data grouped by team

在此基础上,我绘制了剩余百分比与每个团队平均获胜次数的散点图。令我惊讶的是,高估球员的球队通常比低估球员的球队更成功。

问题和潜在改进

我遇到的一个无法解决的问题是来自数据集。有球员通过交易或其他方式在赛季中期更换球队的情况,因此该球员在数据集中有几行(每次一行,一行显示年度总统计数据),但工资相同。我删除了每个球员的“总数”行,并希望其他行包含类似的统计数据,以免扭曲数据。

包括沙奎尔·奥尼尔在内的一些高知名度球员的薪水值缺失,不得不从数据集中删除。工资范围两端的玩家为机器学习模型提供了有价值的信息。此外,一些薪金数据不正确。数据显示卡梅隆·巴尔斯托在 2015 年赚了 1900 万美元,而实际上他赚了不到 100 万美元。

我的项目中的另一个问题是使用的时间段。NBA 在过去的 22 年里经历了巨大的变化,而我的分析没有反映出这一点。近年来,球队给球员提供的薪水比过去几年更多地基于先进的统计数据。此外,球员合同也发生了变化。1995 年,没有最高合同额,球员可以被自己的球队签下任何金额,即使超过工资帽。1997 年,迈克尔·乔丹挣了 3300 万美元,超过了工资帽允许芝加哥公牛队花在整个 T2 队的费用。联盟在接下来的几年里引入了最高合同来防止这种合同。这种新旧合同的混合让我的模型认为,20 世纪 90 年代末和 21 世纪初的超级巨星都签了不合理的大合同,因为最近一批超级巨星赚不到那么多钱。如果把重点放在更近的时间段,这个项目本可以做得更好。

我做了一个假设,所有的球队都会平等地重视球员,因此没有在线性回归模型中使用 team 作为统计数据。在未来的项目中,观察单个球队对球员工资的影响会很有趣。

结论

从我的分析中得出的两个主要结论如下:

  1. 显而易见,得分更多、投篮次数更多的球员将获得更高的薪水,这就是为什么常规子类别比高级模型产生的模型更好,而高级模型是我认为将产生最佳模型的子类别。
  2. 那些对球员的估价高于市场价值的球队实际上取得了更多的团队成功。这最有可能导致这些球队中明星球员的出现,而该模型倾向于认为这些球员被高估了。

代号

使用地理空间数据的最近邻分析

原文:https://towardsdatascience.com/nearest-neighbour-analysis-with-geospatial-data-7bcd95f34c0e?source=collection_archive---------8-----------------------

关于如何在 Python 中查找空间数据的最近邻的指南

Photo by Franck V. on Unsplash

查找一个对象与另一个对象的最近邻是一项常见的空间数据分析任务。例如,确定离家最近的服务点是一个优化问题,需要使用空间数据执行最近邻分析

在本教程中,我们使用芝加哥市的自行车共享数据集执行最近邻分析。数据集由两个独立的文件组成。第一个是自行车站点,第二个是随机生成的点。我们想要确定哪个站靠近第二个数据集中的任意给定点——随机生成的点。随机生成的数据集可以表示真实情况,其中骑车人想要确定哪个自行车站离停放自行车最近。

探索数据

我们使用 pandas 读取数据,并调用第一个数据帧stations,其中包含站点名称、容量和坐标等属性。

stations = pd.read_csv(“data/stations.csv”)
stations.head()

Bike stations

第二个表保存随机生成的点。我们称之为数据帧points。我们在这个表中只有三列,id 和 X 和 y 的坐标。

points = pd.read_csv(“data/points.csv”)
points.head()

Random points

要执行任何地理处理任务,包括本教程中的最近邻分析,我们需要使用 Geopandas 将数据转换为地理数据框架。这将允许我们计算 Geopandas 中可用的任何地理处理任务以及我们想要使用的任何 pandas 方法。

以下函数将两个数据集转换为 Geopandas 地理数据框架。这将创建一个存储几何图形的附加列。我们还为数据集构建了一个坐标参考系统,在本例中,EPSG:4326。

def create_gdf(df, x=”xcoord”, y=”ycoord”):
    return gpd.GeoDataFrame(df, 
    geometry=gpd.points_from_xy(df[y], df[x]), 
             crs={“init”:”EPSG:4326"})stations_gdf = create_gdf(stations)
points_gdf = create_gdf(points)

现在,让我们使用 follow Python 库可视化地图中的数据。

m = folium.Map([41.805379, -87.601501], tiles=”CartoDb dark_matter”)locs_stations = zip(stations_gdf.ycoord, stations_gdf.xcoord)locs_points = zip(points_gdf.ycoord, points_gdf.xcoord)for location in locs_stations:
    folium.CircleMarker(location=location, 
        color=”red”,   radius=4).add_to(m)for location in locs_points:
    folium.CircleMarker(location=location, 
        color=”white”, radius=2).add_to(m)m

下图显示了红色的station_gdf和白色的points_gdf。目标是为随机生成的点找出最近的站。

Map — Bike stations in Red & random points in white

在下一节中,我们将使用 Geopandas 和 Shapely 功能执行最近邻分析。

表演最近邻

我们想找到离其他随机点最近的自行车站。我们可以使用 Shapely function nearest_points功能找出最接近每个位置的几何图形,并在此过程中保存其他属性,例如,车站的名称。这里,我们使用caclulate_nearest 函数,该函数接受目的地(station_gdf)和我们希望从该数据集存储的值(车站名称)。

def calculate_nearest(row, destination, val, col=”geometry”): # 1 - create unary union    
    dest_unary = destination[“geometry”].unary_union # 2 - find closest point
    nearest_geom = nearest_points(row[col], dest_unary) # 3 - Find the corresponding geom
    match_geom = destination.loc[destination.geometry 
                == nearest_geom[1]] # 4 - get the corresponding value
    match_value = match_geom[val].to_numpy()[0] return match_value

我们将该函数应用于第二个数据集points_gdf以导出每个随机点的最近几何图形(从station_gdf中)以及最近几何图形的站名。

# Get the nearest geometry
points_gdf[“nearest_geom”] = points_gdf.apply(calculate_nearest, destination=stations_gdf, val=”geometry”, axis=1)# Get the nearest Bike station name
points_gdf[“nearest_station”] = points_gdf.apply(calculate_nearest, destination=stations_gdf, val=”name”, axis=1)points_gdf.head()

输出是下表,其中有我们在上面创建的两个附加列。

现在,points_gdf里既有nearest_station又有nearest_geom。例如,在id 2 中,我们可以看到最近的车站是林肯大道&百丽平面大道站。我们需要验证我们的结果,让我们从geometrynearest_geom创建一个线地理数据框架,这有助于我们直观地探索数据。

# Create LineString Geometry
points_gdf[‘line’] = points_gdf.apply(lambda row: LineString([row[‘geometry’], row[‘nearest_geom’]]), axis=1)# Create Line Geodataframe
line_gdf = points_gdf[["id", "nearest_station", "line"]].set_geometry('line')# Set the Coordinate reference
line_gdf.crs = crs={"init":"epsg:4326"}

我们有目的点station_gdf,最近点points_gdf,现在还有连接两个数据集的line_gdf。让我们在一个情节中想象它们。

m = folium.Map([41.805379, -87.601501],zoom_start = 12,  
    tiles=”CartoDb dark_matter”)locs_stations = zip(stations_gdf.ycoord, stations_gdf.xcoord)locs_points = zip(points_gdf.ycoord, points_gdf.xcoord)for location in locs_stations:
    folium.CircleMarker(location=location, 
              color=”red”,  radius=8).add_to(m)for location in locs_points:
    folium.CircleMarker(location=location, 
              color=”white”, radius=4).add_to(m)folium.GeoJson(line_gdf).add_to(m)m.save(“map2.html”)m

借助下图所示的地图,您可以轻松浏览数据集并查看每个点的最近站点之间的连接。

Nearest neighbour Visualization

地图用红色圆圈显示自行车站点,用白色显示随机点,用蓝色显示连接线。您可以在附带的笔记本中进一步探索交互式地图。最终结果是准确的,并且可以在您选择的任何其他数据集中复制。

结论

在本教程中,我们讲述了如何使用 Geopandas 执行最近邻分析,以及如何使用芝加哥自行车站执行 Shapely 分析。我们还探索了如何使用 leav 轻松构建和可视化分析结果。

本教程的代码可以在 Github 资源库中找到:

[## shaka som/最近邻-分析

查找一个对象与另一个对象的最近邻是一项常见的空间数据分析任务。例如,确定…

github.com](https://github.com/shakasom/NearestNeighbour-Analysis)

Google Colab 笔记本可以从这里直接访问:

[## shaka som/最近邻-分析

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/shakasom/NearestNeighbour-Analysis/blob/master/NNA.ipynb)

NEAT:神经进化的一种令人敬畏的方法

原文:https://towardsdatascience.com/neat-an-awesome-approach-to-neuroevolution-3eca5cc7930f?source=collection_archive---------1-----------------------

神经进化可以优化和进化神经网络结构,NEAT 算法是第一个显示它是一种可行方法的算法之一!

神经进化的世界

最近,我读了很多关于神经进化的书。从高层次来看,这个想法非常简单。与其让神经网络依赖于固定的结构,为什么不允许它通过遗传算法来进化呢?对我来说,这很有意义。通常,在使用神经网络时,人们会选择一种可能基于经验证据工作的结构。但它是可以使用的最佳结构吗?没办法确定。

在我的阅读中,我看到了一篇名为通过增强拓扑进化神经网络的论文,该论文讨论了增强拓扑的神经进化算法,更普遍的说法是 NEAT。虽然这篇论文发表于 2002 年,并且仅仅关注于逐节点和逐连接地进化密集神经网络,但是这篇论文是我深入研究神经进化的一个关键起点,也是我打算在本文中讨论的一篇论文!

现在,您可能想知道,如果该算法只进化密集的神经网络,并且必须专门进化节点之间的连接,那么它如何仍然有用。这也是我早期思考的问题。但事实是,我们通过梯度下降和反向传播在训练神经网络方面取得的进展不必为了神经进化过程而放弃。其实两者是可以互补的。最近的论文甚至强调了使用 NEAT 和 NEAT-like 算法来进化神经网络结构,然后使用反向传播和梯度下降来优化这些网络的方法,我认为这是一个越来越相关和重要的领域。

但是现在,不多说了,扩充拓扑的神经进化:

拓扑的神经进化问题

在 NEAT 之前,有一些在进化网络拓扑方面的尝试取得了一定的成功,但是,他们发现了一系列问题,在该技术实际上可以做任何令人难以置信的有用的事情之前,需要克服这些问题。使 NEAT 及其论文如此有趣的是它对这些问题提出的一些解决方案,这些解决方案今天仍然使这篇论文有意义!

编码

在生物学中,我们有基因型和表现型。基因型是生物的遗传表现,表型是生物的实际物理表现。进化算法总是在很大程度上反映生物学,神经进化在这方面也不例外。

编码的问题来自于我们希望如何在我们的算法中代表个体的基因。我们对个体进行编码的方式为我们的算法如何处理关键的进化过程铺平了道路:选择、突变和交叉(也称为重组)。任何编码都可以分为两类,直接编码和间接编码。

直接编码将明确指定关于个人的一切。如果它代表一个神经网络,这意味着每个基因将直接链接到网络的某个节点、连接或属性。这可以是 1 和 0 的二进制编码,图形编码(通过加权连接来链接各个节点),或者更复杂的编码。关键是基因型和表现型之间总会有非常明显和可读的直接联系。

间接编码正好相反。间接编码倾向于指定用于创建个体的过程的规则或参数,而不是直接指定结构可能看起来像什么。因此,间接编码要紧凑得多。另一方面,为间接编码设置规则可能会导致搜索空间中的严重偏差,因此,在没有关于如何使用编码的大量知识的情况下,很难创建间接编码。

因此,NEAT 算法选择了直接编码方法。它们的表示比简单的图形或二进制编码稍微复杂一点,但是仍然很容易理解。它只有两个基因列表,一系列节点和一系列连接。为了直观地看这是什么样子,我这里有一张来自原始论文的图片:

输入和输出节点在节点基因列表中没有进化。可以添加或删除隐藏节点。至于连接节点,它们指定了连接进出的位置、此类连接的权重、连接是否启用以及创新数(我们将在下一节讨论)。

变化

简而言之,突变既可以改变现有的连接,也可以给网络增加新的结构。如果在起始节点和结束节点之间添加了新的连接,它会被随机分配一个权重。

如果添加了一个新节点,它将被放置在两个已经连接的节点之间。先前的连接被禁用(尽管仍然存在于基因组中)。先前的开始节点以旧连接的权重链接到新节点,而新节点以权重 1 链接到先前的结束节点。这被发现有助于减轻新结构添加的问题。

竞争公约

进化神经网络拓扑的另一个大问题是被 NEAT 论文称为“竞争约定”的东西。这个想法是,仅仅盲目地跨越两个神经网络的基因组可能会导致网络发生可怕的变异和失去功能。如果两个网络都依赖于网络外的中心节点,我们就有问题了。

不仅如此,基因组可以有不同的大小。我们如何比对看起来不明显兼容的基因组?在生物学中,这是通过一个叫做同源的概念来解决的。同源性是基于特定特征的匹配基因的染色体排列。一旦发生这种情况,与染色体盲目混合在一起相比,交叉发生的错误几率会小得多。

NEAT 通过使用历史标记来解决这个问题(如上所示)。通过用一个历史数字标记新的进化,当需要交叉两个个体时,可以用更少的机会创建没有功能的个体。每个基因都可以被排列和(潜在的)交换。每当一个新的节点或新类型的连接出现时,一个历史标记就被分配了,当繁殖我们的两个个体时,允许容易的排列。点击此处查看:

物种形成

NEAT 提出的一个非常有趣的观点是,大多数新的进化都不是好的进化。事实上,在任何权重优化发生之前添加新的连接或节点通常会导致表现较差的个体。这使得新的结构处于不利地位。我们如何保护新的结构,并让它们在我们完全从人群中消除之前优化?纯净意味着物种形成。

物种形成只是根据拓扑和连接的相似性将种群分成几个物种。如果竞争约定问题仍然存在,这将很难衡量!然而,由于 NEAT 在其编码中使用了历史标记,这就变得更容易衡量了。论文中给出了一个决定如何进行物种分化的函数,但需要注意的重要部分是,种群中的个体只需与该物种中的其他个体竞争。这允许新的结构被创造和优化,而不用担心它会在被真正探索之前被淘汰。

不仅如此,NEAT 还通过一种叫做显性健身分享的方式向前迈进了一步。这意味着个体分享他们在物种间的表现,促进更高性能的物种,尽管仍然允许其他物种在进化之前探索他们的结构优化。

最小结构

NEAT 论文的一个大目标是为进化网络创建一个框架,允许最小的网络进化。作者不想创造一种算法,先找到好的网络,然后在事后减少节点和连接的数量。相反,我们的想法是建立一个算法,从最少的节点和连接开始,随着时间的推移,当且仅当它被认为是有用和必要的时候,才逐渐变得复杂。

NEAT 通过启动所有没有隐藏节点的网络,建立了他们的算法来进化最小网络。初始种群中的每个个体都只是输入节点、输出节点,以及它们之间的一系列连接基因。这本身可能不一定行得通,但当与物种形成的想法结合起来时,这被证明是进化最小但高性能网络的一个强有力的想法。

那么效果如何呢?

早在 2002 年,当这个算法被提出时,它是一个新颖的想法。他们需要证明它甚至可以做基本的事情。为了证明其有效性,作者首先测试的事情之一是它是否能进化出 XOR 函数。显然是这样的,否则我们很可能根本不会讨论这个算法。

他们演示的另一项任务是极点平衡控制任务。如果你不熟悉,这是一个任务,其中有一个模拟环境,允许控制算法移动一辆车。与手推车相连的是一根杆子。控制算法的目标是尽可能长时间地平衡这个极点。这项任务有几种变化,也进行了评估,如双极平衡任务(现在有两个极点!)和双极平衡任务,其中没有给控制算法任何关于极点的速度信息。NEAT 非常成功地完成了这项任务的所有变化!

包扎

现在你已经熟悉了进化神经网络的简洁算法!希望在读完这篇文章后,你会认为这是一个很酷的神经进化方法,并明白为什么它是神经进化中的一个突破。

但这仅仅是开始。我鼓励你通读这篇论文,如果你想了解更多关于算法的细节(包括它们如何具体地进行物种形成过程),或者更好的是,查看你最喜欢的编程语言的代码库!

除了 NEAT 之外,还有更多变体,例如 HyperNEATES-HyperNEATCoDeepNEAT 等等,我希望在不久的将来能够谈到这些变体!所有这些都是对 NEAT 的很好的补充,我鼓励你也去探索一下。

和往常一样,如果你有问题或者我错过了什么,请告诉我!我仍然非常了解这方面的内容,并且很乐意谈论更多(你可以通过 Twitter 联系到我)!

原载于【hunterheidenreich.com】

人工智能和机器人学对可解释性的需求

原文:https://towardsdatascience.com/need-for-explainability-in-ai-and-robotics-75dc6077c9fa?source=collection_archive---------17-----------------------

(Source = https://www.datanami.com/2018/05/30/opening-up-black-boxes-with-explainable-ai/)

介绍

人工智能(AI)在过去几年中取得的突破使计算机有可能执行使用传统软件编程不可能完成的任务。这些进步现在为我们打开了一个人工智能潜在应用的全新世界,如机器人、金融和医学。现代人工智能应用的例子有:手写识别、语音识别、人脸识别、计算机视觉等

人工智能在决策应用(如就业)中的使用最近引起了个人和当局的一些关注。这是因为,当使用深度神经网络时,当前不可能(至少在完全程度上)理解算法在必须执行预定任务时执行的决策过程。由于决策过程缺乏透明度,公众可能会对模型本身的可信度产生困惑。因此,为了防止在人工智能模型中出现任何形式的偏见,对可解释人工智能的需求正在成为下一个预定的进化步骤。

人工智能和机器人

传统编程和人工智能之间的一个主要区别是,非人工智能程序是违背一组指令编写的。相反,人工智能模型无需显式编程即可学习。因此,这可以使我们执行用传统编程看起来不可能的任务。机器学习是最常用的人工智能工具之一。目前如何使用 ML 的一些例子可以是:

  • 通勤时的预测
  • 视频监控
  • 垃圾邮件和恶意软件过滤
  • 搜索引擎结果提炼
  • 产品推荐
  • 在线欺诈检测

机器学习还可以潜在地用于增强工业机器人系统的能力。因为最近的发展,特别是在强化学习和深度学习方面,清楚地表明在这个领域有巨大的潜力。

有两种主要类型的机器人。传统机器人是一种能够执行重复性高度专业化任务的机器(例如工业机器人)。相反,智能机器人能够从周围环境中提取信息,以便做出有意义的决定(例如基于行为的机器人)。

机器学习可以应用于机器人学的四个主要领域[1]:

  • 视觉=物体的检测和识别
  • 抓取=确定抓取物体的最佳方向和位置
  • 运动控制=避障和互动
  • 数据=找到模式以决定采取最佳行动

机器学习如何提高机器人系统性能的两个例子是多机器人系统和集群。这是因为这两类机器人的主要目的是通过集体行为来执行复杂的任务。使用传统编程对集体行为进行编程可能会成为一项极具挑战性的任务,而使用机器学习(例如强化学习)可以使它变得更容易,并可能导致我们无法想到的更具创新性的解决方案。多机器人系统和集群之间的主要区别在于,前者具有环境的全局知识,并且可以具有集中式架构,而后者不具有环境的全局知识,并且使用分散式架构。

机器学习的一个子领域是深度学习(DL),它在机器人系统中有非常重要的应用。例如,使用多层人工网络的 DL 算法已经设法在诸如图像识别的任务中表现得令人难以置信地好,这些任务在机器人系统视觉中具有非常重要的应用。DL 算法的一个问题是,目前,我们不能完全跟踪算法在必须做出决策时做出的决策过程(因此需要可解释的人工智能)。

Figure 1 — Relationship between AI-ML-DL (Image Reproduced from [2])

伦理学

可解释人工智能(XAI)的主要目标是让机器解释自己,并减少有偏见的算法的影响(图 2)。道德在人工智能中越来越重要的一个例子可以在谷歌承诺在实施人工智能算法时遵循的道德原则清单中看到[3]。谷歌决定发布这些原则,以澄清在哪些领域实现人工智能会变得危险,并确认其对生产人工智能自我解释算法的兴趣。

Figure 2 — Explainable AI Revolution (Image Reproduced from [4])

在过去的几年里,首批 XAI 车型已经开始研发。一些最成功的是:反向时间注意模型(RETAIN),局部可解释模型不可知的解释(LIME)和分层相关性传播(LRP) [5]。这些列出的用于产生可解释模型的方法现在仍然不能产生详尽的结果,因此该领域的研究仍然需要进一步发展。

联系人

如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

文献学

[1]将人工智能和机器学习应用于机器人,机器人行业应用。(访问:https://www . Robotics . org/blog-article . cfm/Applying-Artificial-Intelligence-and-Machine-Learning-in-Robotics/103)2019 年 1 月

[2]深度学习系列 1:深度学习入门— Dhanoop Karunakaran —中级。(访问:https://medium . com/intro-to-artificial-intelligence/deep-learning-series-1-intro-to-deep-learning-abb 1780 ee20)2019 年 1 月

[3]谷歌的人工智能——我们的原则——谷歌人工智能。(访问:https://ai.google/principles/)2019 年 1 月

[4]可解释的人工智能(XAI)——David Gunning 先生——DARPA。(访问:https://www . DARPA . mil/program/explaible-artificial-intelligence)2019 年 1 月

[5]对可解释人工智能的介绍,以及我们为什么需要它——帕特里克·费里斯——中等。(访问:https://medium . freecodecamp . org/an-introduction-to-explable-ai-and-why-we-need-it-a 326417 DD 000)2019 年 1 月

机器学习需要特征工程

原文:https://towardsdatascience.com/need-for-feature-engineering-in-machine-learning-897df2ed00e6?source=collection_archive---------8-----------------------

Photo by Franki Chamaki on Unsplash

特性选择真的很重要吗?

特征选择/提取是机器学习中最重要的概念之一,机器学习是选择与问题的建模和商业目标最相关的相关特征/属性(例如表格数据中的列)的子集并忽略数据集中不相关的特征的过程。

是的,特性选择真的很重要。不相关或部分相关的特征会对模型性能产生负面影响。

当特征的数量非常大时,我们不需要使用我们所能支配的每一个特征,这也变得很重要。

对数据集进行要素工程的好处

1.减少过度拟合

2.提高准确性

3.减少培训时间

让我们开始实践,当特征很大并且我们不知道如何从数据集中选择相关信息时,我们如何将各种特征工程技术应用于我们的数据集。

方法 1:计算标准差为零的特征数。这些是不变的特征。由于这些特征没有变化,因此对模型性能没有影响。

import pandas as pd
import numpy as np
data = pd.read_csv('./train.csv')
print("Original data shape- ",data.shape)
# Remove Constant Features
constant_features = [feat for feat in data.columns if data[feat].std() == 0]
data.drop(labels=constant_features, axis=1, inplace=True)
print("Reduced feature dataset shape-",data.shape)

方法 2:计算方差较小的特征数。这可以通过使用 sklearn 库中的 VarianceThreshold 的阈值来应用。

from sklearn.feature_selection import VarianceThreshold
sel= VarianceThreshold(threshold=0.18)
sel.fit(df)
mask = sel.get_support()
reduced_df = df.loc[:, mask]
print("Original data shape- ",df.shape)
print("Reduced feature dataset shape-",reduced_df.shape)
print("Dimensionality reduced from {} to {}.".format(df.shape[1], reduced_df.shape[1]))

方法 3:去除相关性高的特征。相关性可以是正的(增加一个特征值会增加目标变量的值),也可以是负的(增加一个特征值会减少目标变量的值)

皮尔逊相关系数为:

可以使用阈值去除特征,即去除相关系数> 0.8 的那些特征

import seaborn as sns
import numpy as np
corr=df_iter.corr()
mask = np.triu(np.ones_like(corr, dtype=bool))
# Add the mask to the heatmap
sns.heatmap(corr, mask=mask,  center=0, linewidths=1, annot=True, fmt=".2f")
plt.show()

heat map with correlation coefficient

corr_matrix = df_iter.corr().abs()
# Create a True/False mask and apply it
mask = np.triu(np.ones_like(corr_matrix, dtype=bool))
tri_df = corr_matrix.mask(mask)# List column names of highly correlated features (r >0.5 )
to_drop = [c for c in tri_df.columns if any(tri_df[c] > 0.5)]# Drop the features in the to_drop list
reduced_df = df_iter.drop(to_drop, axis=1)print("The reduced_df dataframe has {} columns".format(reduced_df.shape[1]

方法 4:使用逻辑回归找出关于特征的系数。移除那些具有低 lr_coef 的特征。

from sklearn.preprocessing import StandardScaler 
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression#calculating the coeff with respect to columns 
scaler = StandardScaler()
X_std = scaler.fit_transform(X)# Perform a 25-75% train test split
X_train, X_test, y_train, y_test = train_test_split(X_std, y, test_size=0.25, random_state=0)# Create the logistic regression model and fit it to the data
lr = LogisticRegression()
lr.fit(X_train, y_train)# Calculate the accuracy on the test set
acc = accuracy_score(y_test, lr.predict(X_test))
print("{0:.1%} accuracy on test set.".format(acc)) 
print(dict(zip(X.columns, abs(lr.coef_[0]).round(2))))

方法 5:使用 XGBoost 计算特性重要性。

要素重要性为数据的每个要素提供一个分数,分数越高,要素对输出变量越重要或越相关。

import xgboost as xgb
housing_dmatrix = xgb.DMatrix(X,y)# Create the parameter dictionary: params
params = {"objective":"reg:linear","max_depth":"4"}# Train the model: xg_reg
xg_reg = xgb.train(dtrain=housing_dmatrix,params=params,num_boost_round=10)# Plot the feature importances
xgb.plot_importance(xg_reg)

方法 6:使用额外树分类器的特征重要性。

基于树的估计器(参见[**sklearn.tree**](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.tree)模块和[**sklearn.ensemble**](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.ensemble)模块中的森林)可用于计算特征重要性,进而可用于丢弃不相关的特征

X = df.iloc[:,0:370]  #independent columns
y = df.iloc[:,-1]    #target column 
from sklearn.ensemble import ExtraTreesClassifier
import matplotlib.pyplot as plt
model = ExtraTreesClassifier()
model.fit(X,y)
print(model.feature_importances_) 
#use inbuilt class feature_importances of tree based classifiers
#plot graph of feature importances for better visualization
feat_importances = pd.Series(model.feature_importances_, index=X.columns)
feat_importances.nlargest(20).plot(kind='barh')
plt.show()

方法 7:递归特征消除(RFE)

给定将权重分配给特征(例如,线性模型的系数)的外部估计器,递归特征消除([**RFE**](https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFE.html#sklearn.feature_selection.RFE))是通过递归地考虑越来越小的特征集来选择特征。首先,在初始特征集上训练估计器,并且通过coef_属性或feature_importances_属性获得每个特征的重要性。然后,从当前特征集中删除最不重要的特征。该过程在删减集上递归重复,直到最终达到要选择的特征的期望数量。

from sklearn.feature_selection import RFErfe = RFE(estimator=RandomForestClassifier(random_state=0),n_features_to_select=3,step=2,verbose=1)
rfe.fit(X_train,y_train)
mask=rfe.support_
X_new=X.loc[:,mask]
print(X_new.columns)

方法 8:单变量特征选择(ANOVA)

这是通过基于单变量统计测试(ANOVA)选择最佳特征来实现的。基于 f 检验的方法估计两个随机变量之间的线性相关程度。它们假设特征和目标之间是线性关系。这些方法还假设变量遵循高斯分布。

from sklearn.model_selection import train_test_split
from sklearn.feature_selection import f_classif, f_regression
from sklearn.feature_selection import SelectKBest, SelectPercentiledf= pd.read_csv('./train.csv')
X = df.drop(['ID','TARGET'], axis=1)
y = df['TARGET']
df.head()

# Calculate Univariate Statistical measure between each variable and target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=101)
print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)
univariate = f_classif(X_train.fillna(0), y_train)# Capture P values in a series
univariate = pd.Series(univariate[1])
univariate.index = X_train.columns
univariate.sort_values(ascending=False, inplace=True)# Plot the P values
univariate.sort_values(ascending=False).plot.bar(figsize=(20,8))

# Select K best Features
k_best_features = SelectKBest(f_classif, k=10).fit(X_train.fillna(0), y_train)
X_train.columns[k_best_features.get_support()]

# Apply the transformed features to dataset 
X_train = k_best_features.transform(X_train.fillna(0))
X_train.shape

降维技术

主成分分析

原始数据有 9 列。在这一部分中,代码将 9 维的原始数据投影到 2 维。我应该注意的是,降维后,通常每个主成分都没有特定的含义。新组件只是变化的两个主要方面。

from sklearn.decomposition import PCA
dt=pd.read_csv('./dataset.csv')
X=dt.iloc[0:,0:-1]
y=dt.iloc[:,-1]
pca = PCA(n_components=2)
principalComponents = pca.fit_transform(X)
principalDf = pd.DataFrame(data = principalComponents
             , columns = ['principal component 1', 'principal component 2'])
print("Dimension of dataframe before PCA",dt.shape)
print("Dimension of dataframe after PCA",principalDf.shape)
print(principalDf.head())
finalDf = pd.concat([principalDf, y], axis = 1)
print("finalDf")
print(finalDf.head())

#Visualize 2D Projection
fig = plt.figure(figsize = (8,8))
ax = fig.add_subplot(1,1,1) 
ax.set_xlabel('Principal Component 1', fontsize = 15)
ax.set_ylabel('Principal Component 2', fontsize = 15)
ax.set_title('2 component PCA', fontsize = 20)
targets = [0, 1]
colors = ['r', 'g']
for target, color in zip(targets,colors):
    indicesToKeep = finalDf['Class'] == target
    ax.scatter(finalDf.loc[indicesToKeep, 'principal component 1']
               , finalDf.loc[indicesToKeep, 'principal component 2']
               , c = color
               , s = 50)
ax.legend(targets)
ax.grid()

解释方差

解释方差告诉你有多少信息(方差)可以归因于每个主成分。这一点很重要,因为当你可以将 371 维空间转换成 2 维空间时,你会丢失一些方差(信息)。通过使用属性explained _ variance _ ratio _,可以看到第一主成分包含 88.85%的方差,第二主成分包含 0.06%的方差。这两个部分总共包含 88.91%的信息。

谢谢你!

在我的 Youtube 频道上关注我

https://www.youtube.com/channel/UCSp0BoeXI_EK2W0GzG7TxEw

在此与我联系:

领英:https://www.linkedin.com/in/ashishban...

github:https://github.com/Ashishb21

中:https://medium.com/@ashishb21

网站: http://techplanetai.com/

电子邮件 : ashishb21@gmail.com , techplanetai@gmail.com

负二项式回归:逐步指南

原文:https://towardsdatascience.com/negative-binomial-regression-f99031bb25b4?source=collection_archive---------0-----------------------

Brooklyn Bridge with Manhattan in the background ( CC BY-SA 4.0)

外加一个关于负二项式回归的 Python 教程

在本文中,我们将讨论以下主题:

  1. 我们将介绍负二项式(NB)回归模型。NB 模型对于预测基于计数的数据非常有用。
  2. 我们将一步一步地讲解如何使用 statsmodelsGLM 类Python 中创建和测试负二项式回归模型。

使用负二项式回归模型的动机

在我的上一篇文章中,我们介绍了泊松回归模型,并了解了如何将其应用于基于计数的数据,例如布鲁克林大桥上骑自行车者计数的数据集:

Background image: The Brooklyn bridge as seen from Manhattan island

我们还看到,泊松回归模型被证明是不够的建模我们的自行车数据集。

尽管泊松回归模型做出了视觉上令人满意的预测:

Actual daily counts of bicyclists, versus the values predicted by the Poisson regression model. (Data Source: The Poisson Regression Model) (Image by Author)

…其结果在统计学上不令人满意:

Training summary for the Poisson regression model showing unacceptably high values for deviance and Pearson chi-squared statistics (Image by Author)

模型表现不佳是因为数据不符合泊松回归模型要求的 方差=均值 准则。

这个相当严格的标准通常不满足真实世界的数据。通常,方差大于均值,这种性质称为过度分散,有时方差小于均值,称为分散不足。在这种情况下,需要使用一个回归模型,该模型不会使 等分散假设 即假设方差=均值。

负二项式(NB) 回归模型就是这样一种模型,它不做关于数据的 方差=均值 假设。

在本文的其余部分,我们将了解 NB 模型,并了解如何在骑自行车者计数数据集上使用它。

文章的布局

文章布局如下:

  1. 我们将介绍一个真实世界的计数数据集,我们将在本文的其余部分使用它。
  2. 我们将在这个数据集上定义我们的回归目标。
  3. 我们将使用 NB 模型作为我们的回归模型来制定回归策略。
  4. 我们将配置 NB 模型,在数据集上训练它,并在测试数据集上进行一些预测。我们将使用Python stats models库来完成所有这些工作。
  5. 最后,我们将检验 NB 模型的性能是否真的优于泊松模型的性能。

真实世界的计数数据集

下表包含了骑自行车穿过纽约市各种桥梁的人数。从 2017 年 4 月 1 日到 2017 年 10 月 31 日每天测量计数。

Source: Bicycle Counts for East River Bridges (Data source: NYC OpenData) (Image by Author)

我们将集中分析每天通过布鲁克林大桥的骑自行车的人数。这是布鲁克林大桥上自行车数量的时间顺序图:

Daily bicyclist counts on the Brooklyn bridge (Background: The Brooklyn bridge as seen from Manhattan island)

我们的回归目标

我们回归的目标是预测任意一天穿过布鲁克林大桥的骑自行车的人数。

我们的回归策略

给定某一天的一组回归变量的值,我们将使用 NB 模型来预测那天布鲁克林大桥上骑自行车的人数。

我们需要详细说明这个策略,所以让我们更深入地挖掘。让我们从定义一些变量开始:

y = 在第 1 到第 n 天看到的骑车人计数的矢量
从而y =【y _ 1,y_2,y_3,…,y_n】。
y_i
是第 i. 日骑自行车的人数

X =预测值矩阵预测值矩阵又名回归变量矩阵又名解释变量矩阵又名回归变量矩阵。矩阵 X 的大小是一个(n×m),因为在数据集中有 n 个独立的观察值(行),并且每一行包含 m 个解释变量的值。

λ =事件率的向量。向量 λ 是基于计数的数据集的主要特征。 λ 是一个大小为(n×1)的向量。它包含计数向量【y中的 n 个观测计数对应的 n 个速率【λ_ 0,λ_1,λ_2,…,λ_ n】假设观测值‘I’的速率 λ_i 驱动计数向量 y 中的实际观测计数 y_i 。输入数据中不存在 λ 列。相反, λ 向量是由回归模型在训练阶段计算的推导变量。

对于骑自行车者计数数据,每一个λI值被定义为在 i 日的“单位”时间内骑自行车者过桥的人数。单位时间可以是 1 秒、1 小时、1 天、1 周——我们想要测量速率的任何单位时间间隔。假设该速率 λ_i 驱动第 i 天观察到的骑自行车者数量 y_i

下图说明了我们的自行车计数数据集子集上的这些定义:

The regression variables matrix X and the vector of observed bicyclist counts y (Image by Author)

负二项式回归模型的训练算法将使观察计数 y 与回归矩阵 X 拟合。

一旦模型被训练,我们将在一个模型在训练期间根本没有见过的持续测试数据集上测试它的性能。

回想一下,负二项式回归模型并不像泊松回归模型那样做出 方差=均值 的假设。

相反,NB 模型要求我们定义一个新的参数 α ,它用这个参数来表示均值的方差,如下所示 :

The NB model’s variance function (Image by Author)

实际上,这个等式有两种常见的形式:

当 p = 1 时:

The NB1 model’s variance function (Image by Author)

在回归文献中,p=1 的情况被称为 NB1 模型。参见 Cameron,A.C .和 P.K. Trivedi (1986),“基于计数数据的经济计量模型:一些估计量的比较和应用

当 p=2 时:

The NB2 model’s variance function (Image by Author)

p=2 的情况称为 NB2 模型。

我们将使用 NB2 模型。

Python stats models库也支持 NB2 模型,作为它提供的广义线性模型类的一部分。

事实上,statsmodels.genmod.families.family 包中有整整一个类致力于 NB2 模型:

***class*** statsmodels.genmod.families.family.**NegativeBinomial**(*link=None*, *alpha=1.0*)

注意,这个类假定的默认值 alpha=1 ,并不总是所有数据集的正确值。那么,我们如何为我们的自行车计数数据集确定正确的值呢?

找到 α 的正确值

卡梅伦和特里维迪先生又一次拯救了我们。在他们的书《计数数据的回归分析》中, Cameron 和 Trivedi 提出了一种聪明的方法来计算 α ,使用了一种他们称之为辅助的没有常数的 OLS 回归的技术。他们推荐的回归方程如下:

Auxiliary OLS regression to find α for the NB2 model (Image by Author)

你马上就能看出奥克斯 OLS 方程与直线回归方程的关系:Y=B _ 1X+B _ 0*。

如果你很好奇,估计 NB1 模型的 α 的公式如下:

Estimator for α for the NB1 model (Image by Author)

在本文的其余部分,我们将使用 NB2 模型。

一旦我们使用普通最小二乘回归技术对我们的计数数据集拟合了辅助回归方程,我们就可以找到 α 的值。我们很快就会看到如何做到这一点。

但是如何找到包含在辅助 OLS 回归方程中的 λ_i

为了找到 λ_i 我们将泊松回归模型拟合到我们的数据集!实际上,这样做给了我们完整的速率向量λ=【λ_ 1,λ_2,λ_3,…,λ_ n】对应于数据集中所有 n 个观测值。

我们现在已经有了 NB2 回归策略的所有要素。我们来总结一下。

NB2 回归策略总结

  • 第一步:对数据集拟合泊松回归模型。这将给我们拟合率的向量 λ。
  • 步骤 2: 在数据集上拟合辅助 OLS 回归模型。这将给出 α的值。
  • 第 3 步:使用第 2 步中的 α 将 NB2 回归模型拟合到数据集。
  • 步骤 4: 使用拟合的 NB2 模型对测试数据集的预期计数进行预测。
  • 第五步:测试 NB2 模型的拟合优度。

既然我们的回归策略已经勾勒出来了,让我们使用 Python、Pandas 和 statsmodels 来实现它。

如何在 Python 中进行负二项回归

我们将从导入所有需要的包开始。

import pandas as pd
from patsy import dmatrices
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt

接下来,为计数数据集创建一个熊猫数据框架。

df = pd.read_csv('nyc_bb_bicyclist_counts.csv', header=0, infer_datetime_format=True, parse_dates=[0], index_col=[0])

我们将向 X 矩阵添加一些派生的回归变量。

ds = df.index.to_series()
df['MONTH'] = ds.dt.month
df['DAY_OF_WEEK'] = ds.dt.dayofweek
df['DAY'] = ds.dt.day

我们将不使用日期变量作为回归变量,因为它包含一个绝对日期值,但是我们不需要做任何特殊的事情来删除日期,因为它已经作为熊猫数据帧的索引被使用。因此它在 X 矩阵中对我们不可用。

让我们创建训练和测试数据集。

mask = np.random.rand(len(df)) < 0.8
df_train = df[mask]
df_test = df[~mask]
print('Training data set length='+str(len(df_train)))
print('Testing data set length='+str(len(df_test)))

步骤 1:我们现在将在训练数据集上配置和拟合泊松回归模型。

patsy 符号中设置回归表达式。我们告诉 patsy,BB_COUNT 是我们的因变量,它取决于回归变量:DAY、DAY_OF_WEEK、MONTH、HIGH_T、LOW_T 和 PRECIP。

expr = """BB_COUNT ~ DAY  + DAY_OF_WEEK + MONTH + HIGH_T + LOW_T + PRECIP"""

为训练和测试数据集设置 Xy 矩阵。patsy 让这变得非常简单。

y_train, X_train = dmatrices(expr, df_train, return_type='dataframe')
y_test, X_test = dmatrices(expr, df_test, return_type='dataframe')

使用stats models GLM类,在训练数据集上训练泊松回归模型。

poisson_training_results = sm.GLM(y_train, X_train, family=sm.families.Poisson()).fit()

这就完成了泊松回归模型的训练。要查看培训的结果,您可以打印出培训总结。

print(poisson_training_results.summary())

这会打印出以下内容:

Training summary for the Poisson regression model (Image by Author)

我们真正感兴趣的是由训练产生的拟合率向量。这个速率向量包含在参数泊松 _ 训练 _ 结果μ中

*print(poisson_training_results.mu)
print(len(poisson_training_results.mu))*

以下输出显示了拟合的λ向量的前几个和后几个值:

*[1920.39434028 2544.81549207 2651.79330653  743.45309242 1072.77132837 1892.9428398  2320.70412868 3269.73598361 3313.21764921 2915.25363322 2614.39482509 2594.44594144 2415.29471195 3181.91998369 2154.15471026 2268.25625592 1793.29625903 2535.31903414 2566.70835529 970.82159668
 2510.70775659 3016.19901465 2260.265944 3365.04650316 2695.6143122...
...2340.12964253 2568.40001641 2232.26752534 2604.97128321  145.92037793 2060.10442187 2518.70470296]*

这就完成了步骤 1: 拟合泊松回归模型。

步骤 2:我们现在将在数据集上拟合辅助 OLS 回归模型,并使用拟合的模型来获得 α的值。

导入 api 包。

*import statsmodels.formula.api as smf*

λ 向量作为名为‘BB _ LAMBDA’的新列添加到训练数据集的数据帧中。回想一下λ’s 的维数是(n×1)。在我们的例子中,它将是(161 x 1)。还记得 λ 向量在poisson_training_results.mu中可用:

*df_train['BB_LAMBDA'] = poisson_training_results.mu*

接下来,让我们向熊猫数据框添加一个名为“奥克斯 _OLS_DEP”的派生列。这个新列将存储 OLS 回归的因变量的值。它是下面 OLS 回归方程的左侧:

Auxiliary OLS regression to find α for the NB2 model (Image by Author)

*df_train['AUX_OLS_DEP'] = df_train.apply(lambda x: ((**x['BB_COUNT'] - x['BB_LAMBDA'])**2 - x['BB_LAMBDA']) / x['BB_LAMBDA']**, axis=1)*

在上面的代码片段中,粗体部分是上面的辅助 OLSR 方程的左侧。

让我们使用 patsy 来形成 OLSR 的模型规范。我们想告诉 patsy,AUX_OLS_DEP 是因变量,用 BB_LAMBDA 来解释(它是速率向量 λ )。表达式末尾的'-1 '是 patsy 语法,表示:不要使用回归的截距;即就像卡梅伦和特里维迪先生建议的那样,拟合一条穿过原点的直线。

*ols_expr = """AUX_OLS_DEP ~ BB_LAMBDA - 1"""*

我们现在准备好安装一个 OLSR 模型。

配置并适应 OLSR 模型:

*aux_olsr_results = smf.ols(ols_expr, df_train).fit()*

打印回归参数:

*print(aux_olsr_results.params)*

您将看到下面的单个系数被打印出来,对应于单个回归变量 BB_LAMBDA。这个系数就是我们正在寻找的 α :

*BB_LAMBDA    0.037343*

α 有统计学意义吗?

我们现在需要回答一个非常重要的问题。 α的这个值( 0.037343 ) 有统计学意义吗?或者可以认为在所有实际用途中为零吗?

为什么找出这一点如此重要?回想一下,如果 α 为零,那么下面的等式:

The NB2 model’s variance function (Image by Author)

…减少到 方差=平均值 这是泊松回归模型的方差函数。

如果α的值在统计上不显著,则负二项式回归模型不能比泊松回归模型更好地拟合训练数据集。

OLSResults 对象包含回归系数 α的 t 分数。让我们把它打印出来:

*aux_olsr_results.tvalues*

这将打印出:

*BB_LAMBDA    4.814096*

从一个 t 值计算器可以看出,在 99%置信水平下的临界 t 值(右尾),自由度=(161 个观测值)——(1 个离散参数α)=160 为 2.34988 。这远远小于 t 统计量 α 的 4.814096 。我们的结论是,

α= 0.037343 有统计学意义。

这就完成了步骤 2: 确定 α。

步骤 3:我们将步骤 2 中找到的 alpha 的值提供给 statsmodels.genmod.families.family.**NegativeBinomial** 类,并在训练数据集上训练 NB2 模型。

这是 statsmodels 中的一步操作:

*nb2_training_results = sm.GLM(y_train, X_train,family=sm.families.NegativeBinomial(alpha=aux_olsr_results.params[0])).fit()*

和以前一样,我们将打印培训总结:

*print(nb2_training_results.summary())*

它打印以下摘要:

NB2 model’s training summary (Image by Author)

第四步:让我们用训练好的 NB2 模型做一些预测。

在 stats 模型中,预测也是一个单步程序:

*nb2_predictions = nb2_training_results.get_prediction(X_test)*

让我们把预测打印出来:

*predictions_summary_frame = nb2_predictions.summary_frame()
print(predictions_summary_frame)*

以下是输出的前几行:

First few rows of output from nb2_predictions.summary_frame() (Image by Author)

让我们也画出测试数据的预测计数和实际计数。

*predicted_counts=predictions_summary_frame['mean']actual_counts = y_test['BB_COUNT']fig = plt.figure()fig.suptitle('Predicted versus actual bicyclist counts on the Brooklyn bridge')predicted, = plt.plot(X_test.index, predicted_counts, 'go-', label='Predicted counts')actual, = plt.plot(X_test.index, actual_counts, 'ro-', label='Actual counts')plt.legend(handles=[predicted, actual])plt.show()*

以下是输出结果:

Predicted versus actual bicyclist counts on the Brooklyn bridge using the NB2 model

不算太差!NB2 模型似乎或多或少地跟踪了自行车数量的趋势。正如泊松回归模型的表现,在某些情况下,它的预测与实际值相差甚远。

以下是用于训练负二项式回归模型并测试其预测的完整 Python 源代码:

我们面临的最后一个问题是:

从统计上看,我们的 NB2 回归模型比泊松回归模型做得更好吗?

让我们找出答案。

步骤 5:测量 NB2 模型的拟合优度

从拟合优度的角度来看,在 NB2 模型的训练总结中有三件有趣的事情。它们在下图中用红框标出。我们将从对数似然性开始研究每一种方法。

NB2 model’s training summary (Image by Author)

让我们首先比较 NB2 模型和泊松回归模型在相同数据集上的训练摘要:

(Image by Author)

首先要看的统计数据是对数似然值。最大对数似然是通过最大似然估计(MLE )技术生成的,该技术由 statsmodels 在泊松和 NB2 模型训练期间执行。MLE 技术用于将所有模型系数的值固定为一些最佳值,这些最佳值将最大化在训练数据集中看到计数向量 y 的可能性。要了解更多关于 MLE 及其如何用于模型训练的信息,请参考我关于泊松回归模型的文章。

似然比检验

似然比测试用于比较两个模型对数据的拟合程度。

LR 检验统计量是两个模型拟合对数似然性差异的两倍。

*在我们的例子中,NB2 的对数似然是-1383.2,而泊松回归模型是-12616。所以 LR 检验统计量是 2 (12616–1383.2)= 22465.6。在 1%的显著性水平上,该值远大于 χ2(1) 的临界值 5.412。

根据 LR 测试,与泊松回归模型相比,经过训练的 NB2 回归模型在自行车运动员数据集上表现出更好的拟合优度。

现在让我们比较一下 NB2 回归模型的绝对拟合优度。

偏差和皮尔逊卡方统计

NB2 模型的偏差和皮尔逊卡方的报告值分别为 330.99 和 310。为了在某个置信水平(比如 95% (p=0.05))下定量确定拟合优度,我们在 χ2 表中查找 p=0.05 和残差自由度=165 的值。我们将该卡方值与观察到的统计值进行比较,在这种情况下,它是 GLMResults 中报告的偏差或皮尔逊卡方值。我们发现,在 p=0.05 且 DF 残差= 165 时,来自标准卡方表的卡方值为 195.973,小于报告的统计值 330.99 和 310。因此,根据该测试,尽管 NB2 回归模型显示出比泊松回归模型更好的拟合,但仍然是次优的。我们也许能够做得更好。

结论和下一步措施

泊松和负二项式回归模型用于对基于计数的数据集进行建模。这两种模型产生的结果是:

  • 可解释的
  • 可比较的
  • 可辩护的
  • 可用的

这两个模型都有强大且被充分理解的统计理论支持。

对于基于计数的数据集进行回归,一个好的策略是从泊松回归模型开始,然后看看是否可以通过使用负二项式回归模型获得更好的结果。

如果 Poisson 和 NB2 都不适合您的数据集,请考虑使用更高级的技术,例如:

  1. 泊松回归模型的复杂变体,如零膨胀模型
  2. 跨栏模型
  3. 一个基于随机森林的回归模型
  4. 一个基于长短期记忆(LSTM) 神经网络的回归模型

相关阅读

* [## 泊松回归模型图解指南

和使用 Python 的泊松回归教程

towardsdatascience.com](/an-illustrated-guide-to-the-poisson-regression-model-50cccba15958)*

感谢阅读!如果你喜欢这篇文章,请在Sachin Date关注我,以获得关于回归、时间序列分析和预测主题的提示、操作方法和编程建议。

雀巢利用人员分析缩小性别薪酬差距

原文:https://towardsdatascience.com/nestlé-leverages-people-analytics-to-narrow-the-gender-pay-gap-737a0625d0dd?source=collection_archive---------25-----------------------

雀巢如何推动多元化和包容性的发展

Photo by Brooke Cagle on Unsplash

在数字时代,性别薪酬差距仍然广泛存在。不过,公司正在努力缩小这一差距,这是个好消息。更重要的是,最近的立法给公司带来压力,要求他们披露薪酬差距,并开始采取积极措施。 People analytics 提供对人才统计数据的洞察,帮助公司确定他们在平等工作机会方面的不足。

雀巢是世界上最大的食品和饮料公司,拥有 2000 多个品牌,它是一个很好的例子,说明了一家全球性公司应该如何通过人员分析积极努力在工作场所提供多样性和包容性。

雀巢——工作场所性别平等的倡导者

雀巢公司人力分析经理 André Bezemer 在去年的北欧人力分析峰会上,通过人力分析展示了雀巢公司对性别工作场所平等的倡导和倡议。

“如果你问我们的首席执行官(关于性别平等),那很简单,这是应该做的事情。无论是在性别领域,还是在 LGBT 领域,每个人都应该拥有平等的机会,”André说。为了支持他们的信念,雀巢公司签署了 ILO(国际劳工组织)承诺,表明他们对平等、多样性和同工同酬的承诺。除此之外,自去年以来,他们已经开始在整个集团和地方立法之外监测性别薪酬和平等薪酬,以确保所有差距都得到识别和解决。

Photo by Hyperight AB® on Nordic People Analytics Summit / All rights reserved

但是一旦所有的手续都完成了,你承诺男女同工同酬,你就必须实际兑现。因此,雀巢公司决定向内看,看看他们是否真的支付男女相同的工资,如果不是,如何修改。

同酬与性别薪酬差距

在 André继续解释雀巢公司的做法之前,他对术语“同工同酬”和“性别薪酬差距”的含义进行了明确的区分。性别薪酬差距是指公司中所有男性的平均薪酬与所有女性的平均薪酬之比。而同工同酬意味着男女同工同酬。

Photo by rawpixel on Pxhere

雀巢公司的同工同酬人员分析方法

由于在多个市场开展业务,雀巢公司制定了人员分析原则,全球所有部门都将遵循这些原则:

  • 标准化分析
  • 定义和填充数据集以实现洞察力、行动和评估
  • 构建跨人员分析的能力
  • 开发适合用户需求的工具

André说,people analytics 的棘手之处在于,分析是在本地进行的,在比较两个不同的市场时会出现问题。因此,他们专注于开发一种本地方法,以便在全球层面上对不同市场进行比较。主要目的是发现在某些市场中是否存在某些异常值,或者是否存在需要解决的薪酬差异较大的整个劳动力群体。

如果你想改变性别平衡,你必须确保有足够多的女性担任高级职位。

正如我们之前提到的,性别薪酬差距很容易计算——它是男性平均薪酬和女性平均薪酬之间的差异。但是计算男女同工同酬的问题就有点复杂了。雀巢公司使用一个标准模型,该模型考虑了几个变量,如年龄、级别、职能和才能提升,然后计算所有这些是否与性别相关,并将薪酬作为结果。

他们发现的结果是,女性的平均收入是男性的 1.013 倍。“结果是好的,但重要的是他们实际上用它做了什么,以及他们采取的后续行动,”安德烈强调说。

Photo by rawpixel on Unsplash

缩小差距

如果不平等案例涉及到个人,例如工资落后的个人,那么这个问题就相对容易解决。André认为,如果涉及到更大部分的劳动力,就需要一个更加系统化和结构化的方法来弥补差距,例如调整技能差距或影响特定劳动力的政策。同样,关键是要洞察到差距的存在,并在市场中制定行动计划,开始缩小薪酬差距。

仪表板

正如在公司中提供多样性和包容性一样,更重要的是将见解的呈现方式标准化,并使其易于获取,因为正如 André所指出的那样。他们发现,当一家公司像雀巢一样在全球范围内运营时,许多人无法获得数据,或者在查看数据时出现了许多误解。例如,各地的自然减员并不相同

因此,他们发现迫切需要标准化一套全面的指标:

  • 职员总数
  • 消耗
  • 雇用
  • 才能
  • 继承权

安德烈解释说,一个关键的衡量标准是接班人,因为在雀巢公司,你在公司的级别越高,外部招聘的比例就越低,女性的数量就越少,大多数其他公司也是如此。在高管级别,他们的内部流动率是 94%,安德烈承认这不是一个很大的数字,因为从外部招聘是增加性别平衡的一种方式。

对此的一个解决方案是基于对继任指标的洞察制定继任计划,这样不同的部门就可以设计出一个如何培养和准备女性担任这些角色的策略。

Photo by Lukas from Pexels

继任和其他指标可在雀巢公司的全球 D&I 仪表板中获得,该仪表板可供公司的所有利益相关者在全球范围内访问。它完全符合 GDPR 的规定,所有个人数据都受到保护。

Photo by Hyperight AB® on Nordic People Analytics Summit / All rights reserved

雀巢公司的全球 D&I 仪表板还为他们提供了对性别平衡持有者与继任者的洞察,这意味着公司每个级别的女性比例与拥有知识和技能来接替高级职位的女性比例。“因为如果你想推动性别平衡,你必须确保有足够多的女性来担当这些角色”,安德烈强调说。仪表板数据使他们能够采取具体措施解决性别差距,并制定继任计划。如果空缺职位需要填补,但名单上没有女性,或者她们是潜在的女性候选人,但她们将在 3-5 年或更长时间内为该职位做好准备,她们就开始推动议程,为她们继任更高级的职位做准备。这也意味着让高管们为富有挑战性的对话做好准备,并以开放的态度接受变化。André总结道,在这些富有挑战性的对话中,仪表板见解对人员分析部门很有帮助。

原载于 2019 年 9 月 19 日【Hyperight.com】

网飞使用 Twitter 的 API 和 Python 展示推荐

原文:https://towardsdatascience.com/netflix-show-recommendations-using-twitters-api-and-python-65f347706617?source=collection_archive---------23-----------------------

Photo by John-Mark Smith on Pexels

在本帖中,我们将分析推特上的网飞秀推荐。首先,你需要申请一个 Twitter 开发者账户:

Source

您的开发人员帐户获得批准后,您需要创建一个 Twitter 应用程序:

Source

申请 Twitter 开发者账户和创建 Twitter 应用程序的步骤在这里列出。

为了访问 Twitter API,我们将使用免费的 python 库 tweepy。tweepy 的文档可以在这里找到。

  1. 安装

首先,确保您已经安装了 tweepy。打开命令行并键入:

pip install tweepy

2.导入库

接下来,打开您最喜欢的编辑器,导入 tweepy 和 pandas 库:

import tweepy
import pandas as pd

3.认证

接下来,我们需要我们的消费者密钥和访问令牌:

Source

请注意,该网站建议您保持您的密钥和令牌私有!这里我们定义了一个假的密钥和令牌,但是在创建 Twitter 应用程序时,您应该使用真正的密钥和令牌,如上所示:

consumer_key = '5GBi0dCerYpy2jJtkkU3UwqYtgJpRd' 
consumer_secret = 'Q88B4BDDAX0dCerYy2jJtkkU3UpwqY'
access_token = 'X0dCerYpwi0dCerYpwy2jJtkkU3U'
access_token_secret = 'kly2pwi0dCerYpjJtdCerYkkU3Um'

下一步是创建 OAuthHandler 实例。我们传递上面定义的消费者密钥和访问令牌:

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)

接下来,我们将 OAuthHandler 实例传递给 API 方法:

api = tweepy.API(auth)
  1. TWITTER API 请求

接下来,我们为我们有兴趣分析的字段初始化列表。现在,我们可以查看推文字符串、用户和推文时间。接下来,我们在一个 tweepy“Cursor”对象上编写一个 for 循环。在“Cursor”对象中,我们传递“api.search”方法,为我们想要搜索的内容设置查询字符串(q= "best show 网飞" ),并设置“count”= 1000,这样我们就不会超过 twitter 的速率限制。我们还使用“item()”方法将“Cursor”对象转换为 iterable。

为了简化查询,我们可以删除转发,只包含英文推文。为了了解该请求返回的内容,我们还可以打印附加到每个列表的值:

twitter_users = []
tweet_time = []
tweet_string = []
for tweet in tweepy.Cursor(api.search,q="best show netflix", count=1000).items(1000):
        if (not tweet.retweeted) and ('RT @' not in tweet.text):
            if tweet.lang == "en":
                twitter_users.append(tweet.user.name)
                tweet_time.append(tweet.created_at)
                tweet_string.append(tweet.text)
                print([tweet.user.name,tweet.created_at,tweet.text])

在这张推文截图中,人们推荐的节目有格雷斯和弗兰基路西法被抓Visa vsOA。让我们来看看另一张推文截图:

在这里,人们推荐世界末日、黎明、卡明斯基方法、山之屋的闹鬼。我们也可以指定一个流派。如果我们想搜索最佳喜剧(电视剧和电影):

twitter_users = []
tweet_time = []
tweet_string = []
for tweet in tweepy.Cursor(api.search,q="best comedy netflix", count=1000).items(1000):
        if (not tweet.retweeted) and ('RT @' not in tweet.text):
            if tweet.lang == "en":
                twitter_users.append(tweet.user.name)
                tweet_time.append(tweet.created_at)
                tweet_string.append(tweet.text)
                print([tweet.user.name,tweet.created_at,tweet.text])

在这里,人们对席特的《小溪》、《贪得无厌》、塞斯·迈耶的喜剧特辑以及哈桑·米纳吉的《爱国者法案》赞不绝口。我们也可以从电视剧中来看:

和惊悚片:

接下来,我们可以将查询结果存储在数据帧中。为此,让我们定义一个函数,该函数将一个关键字作为参数,并返回一个包含与该关键字相关的 1000 条推文的数据帧:

def get_related_tweets(key_word):
    twitter_users = []
    tweet_time = []
    tweet_string = [] 
    for tweet in tweepy.Cursor(api.search,q=key_word, count=1000).items(1000):
            if (not tweet.retweeted) and ('RT @' not in tweet.text):
                if tweet.lang == "en":
                    twitter_users.append(tweet.user.name)
                    tweet_time.append(tweet.created_at)
                    tweet_string.append(tweet.text)
                    #print([tweet.user.name,tweet.created_at,tweet.text])
    df = pd.DataFrame({'name':twitter_users, 'time': tweet_time, 'tweet': tweet_string})
    df.to_csv(f"{key_word}.csv")
    return df

当我们用“最佳惊悚片网飞”调用函数时,定义一个 dataframe 作为函数的返回值,并打印它的前五行,我们得到:

df_thriller = get_related_tweets("best thriller netflix")
print(df_thriller.head(5))

如果我们为“网飞最佳喜剧”做同样的事情:

df_comedy = get_related_tweets("best comedy netflix")
print(df_comedy.head(5))

我就说到这里。这篇文章的代码可以在 Github 上找到。感谢您的阅读!

基于芝加哥拼车数据的网络分析和社区聚类

原文:https://towardsdatascience.com/network-analysis-and-community-clustering-using-chicago-ride-share-data-1f21a4fb71cd?source=collection_archive---------27-----------------------

这个项目的灵感来自于对“智能城市”发展的兴趣,以及最近在芝加哥市在线数据门户网站上发布的拼车数据。收集、集中和发布数据的智能城市是深入分析社区和资源状况的运动的一部分。考虑到城市人口的增长,了解如何利用这些数据来制定决策和计划以改善城市生活变得越来越重要。

该项目的目标是利用芝加哥的公共拼车数据,以便更好地了解这些拼车发生在哪里,以及特定地理区域如何通过拼车连接起来。我通过以下步骤完成了这个目标 :

1.从芝加哥的开放数据平台获取、清理和分析公开可用的拼车数据

2.使用拼车数据对芝加哥人口普查区域进行网络分析并进行可视化

3.使用聚类技术识别基于拼车的底层社区

数据清理和探索性分析包括以下步骤:

  1. 访问数据集
  2. 删除在芝加哥之外开始/结束的游乐设施
  3. 统计每个
    上下车地点发生的乘车次数(唯一路线)
  4. 为每个人创建经纬度坐标图
    人口普查区域

使用的拼车数据集可以在这里访问:https://data . cityofchicago . org/Transportation/Transportation-Network-Providers-Trips/m6dm-c72p

完整的数据集可以作为平面文件下载,或者通过调用芝加哥数据门户 API 来访问,如下所示:

Example of the API request result

根据芝加哥的数据门户,任何位置字段中的空值都表示该旅程发生在芝加哥以外。由于该数据无法估算,所有相对于坐标为空值的乘坐(行)都将被删除。

Example of the network analysis data-set created using the above code

为了以后在芝加哥的地图上绘制网络,我们需要一个每个独特的人口普查区域和相应的经纬度坐标的列表。创建该坐标图的方法如下所示。

使用 Networkx
进行网络分析在数据集清理完毕并准备就绪的情况下,使用 Networkx 软件包将每个人口普查区域位置可视化为图表中的一个节点,节点(边)之间的连接用黑线表示。

This is a non-directional graph representation of how Chicago census tracts are connected via ride-sharing. Not pretty right?

原始的图形表示几乎没有任何洞察力。通过使用每个普查区域的纬度/经度,我们可以用一种在地理上更像芝加哥的方式来绘制网络的节点。

Great! At least now we can see the graph taking shape. Notice the concentration of rides overlapping in the center of the city.

通过读取公开的芝加哥形状文件以及之前创建的坐标地图,我能够在实际的城市地图上可视化这个图形。我还添加了一个基于每个普查区域的总乘坐量的加权方案,以更好地了解每个区域有多少乘坐开始或结束。

With this we can clearly see that the majority of the rides take place in or around the Loop, a major urban area in Chicago. Also notice In the top left and mid left two large red circles representing Chicago’s two airports.

使用 Louvain 模块性的社区聚类
随着网络的建立,可以使用算法来对网络进行聚类,以便基于共乘数据来识别形成社区的位置。虽然一个芝加哥人可能能够回答这个问题,但我很好奇,仅凭互联网上公开的拼车数据,我能多快了解一个我从未去过的城市的交通状况。

选择的方法来自一篇名为“大型网络中社区的快速展开”的论文根据该论文,与社区外的节点相比,该方法试图最大化每个社区中节点之间的链接数量。它首先将每个节点随机分配到一个社区,然后将每个节点移动到一个新的社区,直到模块性最大化。这就创建了这样的社区,其内部的链接比与属于其他社区的节点的链接更紧密。幸运的是,这个方法是 Networkx 内置的。

The clustering seen here intuitively made sense. There are clear distinctions between the Loop and surrounding nodes, downtown and uptown Chicago. It was interesting to see that both airports were clustered along with the high volume nodes in the Loop. I can assume that’s because many travelers are heading to downtown hotels from these airports.

我学到了什么? 城市收集的数据在合适的人手里可以成为有力的工具。我无需踏足芝加哥,就能看到拼车是如何将某些社区联系在一起的,以及大多数拼车是在哪里发生的。看看社区聚类的结果是否会随着一天或一年的时间而变化,这将是一件有趣的事情!需要注意的一点是,拼车政策的变化会对城市的各个部分产生不同的影响。虽然有些人一直在谈论拼车作为老化的公共交通基础设施的补充的好处,但这里的网络集群清楚地表明,一些社区从拼车中获得的好处很少。

我想做的下一件事是将时间序列预测方法应用于这些社区群中的每一个,以观察我能多好地预测乘车量。希望其他城市能向芝加哥学习,投资于他们自己的开放数据平台,以便在城市规划和政策制定方面做出明智的、有数据支持的决策。

我迄今为止使用这个数据集进行的所有分析的完整代码可以在我的 github 上找到。

[1]Vincent D . Blondel,Jean-Loup Guillaume,Renaud Lambiotte 和 Etienne Lefebvre,大型网络中社区的快速展开 (2008), J. Stat .机甲战士。 (2008) P10008

用 Spacy 和 Neo4j 对《证大囚徒》的网络分析

原文:https://towardsdatascience.com/network-analysis-of-prisoners-of-zenda-book-with-spacy-and-neo4j-b0839a640105?source=collection_archive---------21-----------------------

多年来,互联网已经成为一种社交网络:联系和关系隐藏在众目睽睽之下——等待被发现。由于数据量巨大,这种关系很难用肉眼发现。然而,这并不意味着它们不存在或者不可能找到它们。

这篇博客的想法是在我和来自 Signalfish.io杰瑞米·戴维斯进行头脑风暴时产生的。他们在生产中使用 SpaCy、Neo4j 和 Golang 来提供精选的新闻提要。SpaCy 具有实体识别系统。它提供了一个默认的 NLP 模型,可以识别各种命名实体,包括个人、组织等等。Neo4j 是一个原生图形数据库,从头开始设计用于处理关系和图形。

《T4 权力网》的分析给了我巨大的启发。如果我没记错的话,安德鲁·贝弗里奇在《权力的游戏》一书中用文本中人与人之间的距离来推断人与人之间的关系。我决定用 Spacy 和 Neo4j 做一些类似的事情。

要求

议程

  • 预处理文本
  • 从文本中提取关系
  • 导入到 Neo4j
  • 运行 Louvain 和 Pagerank 算法
  • 结果可视化

数据

我在找一些没有版权的书,这样每个人都可以遵循这个教程。一路走来,我发现了古腾堡项目,该项目提供大部分版权过期的免费书籍。我们将使用安东尼·霍普写的《曾达的囚徒》一书。

图形模型

图模型由带有标签 Person 的节点组成。每个人可以有一个或多个与其他人相关的关系。每个关系都有一个属性分数。在我们的例子中,它代表了两个人在文本中的互动次数。另一个需要注意的重要事情是,我们将把这些关系视为无向的。查看此文章了解更多详情。

Graph model

预处理

古腾堡计划很好地为我们提供了《曾达的囚徒》一书的文本版本。我们将获取文本文件,删除特殊字符,并将文本分成章节。

# [https://www.gutenberg.org/ebooks/95](https://www.gutenberg.org/ebooks/95) Prisoner of Zelda# Fetch the data
target_url = 'https://www.gutenberg.org/files/95/95-0.txt'
import urllib.request
data = urllib.request.urlopen(target_url)
raw_data = data.read().decode('utf8').strip()# Preprocess text into chapters 
import re
chapters = re.sub('[^A-z0-9 -]', ' ', raw_data).split('CHAPTER')[1:]
chapters[-1] = chapters[-1].split('End of the Project Gutenberg EBook')[0]

我们准备运行 Spacy 的命名实体识别。为了简化我们的分析,我们将只使用这本书的第一章。否则,我们将需要拿出一些名称映射系统,因为有时会使用一个人的全名,有时不会。这需要更多的手动方法,我们将在这里避免。

我们还将在文本中用单个单词的 id 替换人名,以简化我们的算法。

# import spacy and load a NLP model
import spacy
nlp = spacy.load("en_core_web_lg", disable=["tagger", "parser"])# Analyze the first chapter
c = chapters[0]
# Get a list of persons 
doc=nlp(c)
involved = list(set([ent.text for ent in doc.ents if ent.label_=='PERSON']))
# replace names of involved in the text
# with an id and save the mapping
decode = dict()
for i,x in enumerate(involved):
    # Get mapping    
    decode['$${}$$'.format(i)] = x
    # Preprocess text
    c = c.replace(x,' $${}$$ '.format(i))

这是一个非常简单的 SpaCy 操作演示。我们只分析了一小段文字。如果你想分析更大的数据集,你应该使用 nlp.pipe(texts) 函数。在文档中了解更多信息。

正如前面我们的图模型所描述的,下面是它的 cypher 查询。

save_query ="""
    MERGE (p1:Person{name:$name1})
    MERGE (p2:Person{name:$name2})
    MERGE (p1)-[r:RELATED]-(p2)
    ON CREATE SET r.score = 1
    ON MATCH SET r.score = r.score + 1"""

该算法设计简单。如果一对人在文本中相距不到 14 个单词,我们就推断出他们之间的关系。配对之间这种出现的次数被存储为关系的属性。

该算法遍历搜索人的单词。当它找到一个单词时(请记住单个单词的 id 系统),它会检查接下来的 14 个单词以查找任何其他人。

# Get an array of words
ws = c.split()
l = len(ws) 
# Iterate through words
for wi,w in enumerate(ws):
    # Skip if the word is not a person
    if not w[:2] == '$$':
        continue
    # Check next x words for any involved person
    x = 14
    for i in range(wi+1,wi+x):
        # Avoid list index error
        if i >= l:
            break
        # Skip if the word is not a person
        if not ws[i][:2] == '$$':
            continue
        # Store to Neo4j
        params = {'name1':decode[ws[wi]],'name2':decode[ws[i]]}
        session.run(save_query, params)
        print(decode[ws[wi]],decode[ws[i]])

图形算法

我们将在分析中运行 PageRankLouvain 算法。Pagerank 是通常用于表示图中节点的重要性的中心性度量。Louvain 算法是一种社区检测算法,它在我们的图中找到社区。

Neo4j 图形算法引擎区分有向和无向图。我们必须使用参数 direction: 'BOTH' 来告诉引擎将关系视为无向关系。

pagerank ="""
CALL algo.pageRank('Person','RELATED',{direction:'BOTH'})
"""
louvain = """
CALL algo.louvain('Person','RELATED',{direction:'BOTH'})
"""
with driver.session() as session:
    session.run(pagerank)
    session.run(louvain)

形象化

我认为对于小型网络来说,一张图片胜过 1000 个字。我们将使用 NeovisJS 来可视化我们的分析结果。可视化的代码是无耻地从马克·李约瑟的 Neo4j 图表笔记本库中复制的。

NeovisJS 配置

我们需要为生成 NeovisJS 可视化的函数提供一个配置文件。它由 Neo4j 的连接参数(主机、用户、密码)和定义可视化的三个参数组成。

可视化参数:

  • cypher:定义要从 Neo4j 获取的(子)图的 Cypher 查询
  • labels_json:定义节点的可视化(标题、大小和颜色)
  • relationships_json:定义关系的可视化(标题,大小)
cypher = "MATCH (p1:Person)-[r:RELATED]->(p2:Person) RETURN *"labels_json = {
    "Person": {
        "caption": "name",
        "size": "pagerank",
        "community": "community"
    }
}relationships_json = {
    "RELATED": {
        "thickness": "score",
        "caption": False
    }
}generate_vis(host, user, password, cypher, labels_json, relationships_json)

结果

鲁道夫似乎是第一章的主角。另一个重要人物是伯利斯顿。有趣的是,他和鲁道夫没有任何关系。右角是鲁道夫三世。我不知道这和鲁道夫是不是同一个人,因为我没读过这本书。在这个示例中,一些手动的名称清理会有所帮助。我们可以在图表中找到四个社区,它们的规模都差不多。

数据丰富

这仅仅是我们所能实现的开始。我们可以添加 SpaCy 在我们的文本中找到的其他类型的标签。例如,让我们将组织添加到我们的图表中。我们简单地看一下课文中的组织,检查一下人物的前五个和后五个单词。数字 5 是完全随意选择的,你可以使用任何你认为最有效的数字。

数据预处理

c = chapters[0]
doc = nlp(c)# Define the mapping
persons = list(set([ent.text for ent in doc.ents if ent.label_=='PERSON']))
orgs = list(set([ent.text for ent in doc.ents if ent.label_=='ORG']))
decode_org = dict()
decode_person = dict()# Replace person with an id
for i,p in enumerate(persons):
    decode_person['$${}$$'.format(i)] = p
    c = c.replace(p,' $${}$$ '.format(i))# Replace organizations with an id
for i,o in enumerate(orgs):
    decode_org['&&{}&&'.format(i)] = o
    c = c.replace(o,' &&{}&& '.format(i))

我们将像以前一样使用类似的 cypher 查询,只是现在我们存储的是个人和组织之间的关系。

save_org_query = """MERGE (p:Person{name:$person})
MERGE (o:Organization{name:$org})
MERGE (p)-[r:PART_OF]->(o)
ON CREATE SET r.score = 1
ON MATCH SET r.score = r.score + 1"""

运行算法并存储到 Neo4j

ws = c.split()
l = len(ws)
for wi,w in enumerate(ws):
    # Skip if the word is not a organization
    if not w[:2] == '&&':
        continue
    # Check previous and next x words for any involved person
    x = 5
    for i in range(wi-x,wi+x):
    # Avoid list index error
        if i >= l:
            break
        # Skip if the word is not a person
        if (ws[i][:2]!='$$') or (i==wi):
            continue
        # Store to Neo4j
        params = {'org':decode_org[ws[wi]],'person':decode_person[ws[i]]}
        session.run(save_org_query, params)
        print(decode_org[ws[wi]],decode_person[ws[i]])

组织对结果并不感兴趣,但是使用这种技术,您可以存储您喜欢的 NLP 引擎返回的所有不同类型的标签。这允许您构建一个知识图,表示任何给定文本中实体之间的关系。我们还可以使用不同的相似性度量,如 Jaccard 指数或重叠相似性来推断实体之间的关系。

另外,你可以在这里找到 Ipython 笔记本的所有代码。

如果你对更多的网络分析感兴趣我推荐:

《三国演义》的网络分析

原文:https://towardsdatascience.com/network-analysis-of-the-romance-of-three-kingdoms-5b1c1b84601d?source=collection_archive---------28-----------------------

最近,我发表了一篇关于 14 世纪小说《三国演义》的社交网络的文章。在文章中,我讨论了在分析小说人物的互动时出现的社会网络。此外,通过使用中心性测量,我确定了谁是最有影响力的人物。这篇文章是非技术性的,我的分析中的一些细节被省略了。

在这里,我提出了分析背后的代码,并进一步讨论了小说的社会网络的技术细节。此外,这段代码可以(稍加修改)用于对其他小说或文本进行类似的分析。

我的分析受到了 Andrew Beveridge 和 Jie Shan 对《权力的游戏》的网络分析的启发。两部文学作品都有错综复杂的情节和大量的人物。这使得《三国演义》成为这种分析的一个很好的候选。

预处理

在开始分析《三国演义》之前,我必须做出一些初步的决定。

  • 第一个决定是在我的分析中包含哪些字符。这部小说中出现了一千多个人物。为了让读者能够更密切地跟踪这些角色,只选择了 70 个角色。为了选择字符,我使用了以下步骤。首先,我选择了名字在整部小说中出现次数最多的 100 个角色。然后,我列出了在关于这部小说的网站和文章中出现最多的人物,在系列中出现的人物,甚至一些我个人认为重要的人物。我比较了这些列表,手动选择了哪些字符将保留在我的最终列表中。
  • 我做的另一个决定是分章节分析这部小说。这部小说的篇幅很大。它包括 120 个章节,英语翻译版本包含超过 50 万字。我决定,为了更好地跟踪人物的互动,在分析全文之前,我应该把小说分成几组章节,并分别分析每一组。由于章节长度相似,我决定创建 30 个章节的组,总共 4 个组。最后,我还处理了整部小说,得到了所有人物的宏大网络。

通过使用 bash 脚本,我将 30 个一组的章节连接到单独的文件中,再加上一个包含全文的文件。接下来,我创建了 python 脚本,它将一个文本文件作为输入,并生成一个图形对象作为输出。然后,我可以用像 Gephi 这样的工具进一步处理图形,以创建漂亮的网络可视化。

The network for chapters 1–30

我们首先导入文件并删除所有特殊字符,因为初始文本中有很多特殊字符

import rewith open(infile, 'r') as file:
    data = file.read().replace('\n', ' ')text = re.sub('[^A-Za-z0–9]+', ' ', data)

接下来,我们需要从文本中创建一个标记列表。Python 的nltk库可以很容易地为我们做到这一点。此外,我们从令牌中删除了停用词

import nltkstopWords = nltk.corpus.stopwords.words('english')def wordTokens(text, stop_words):

    wtokens = nltk.word_tokenize(text.lower())
    wtokens = [w for w in wtokens if w not in stop_words]return wtokens

因为我们在文本中寻找的名字都由两个单词组成,所以我们想要创建二元模型。在nltk的帮助下,这又变得非常简单

bigrm = nltk.bigrams(tokens)
bigrms = list(bigrm)

如果有一个单词的名字或两个以上单词的名字,我们可以通过包含初始标记以及三元模型或任何其他 n 元模型来概括代码。

最后,我们从字符列表中创建元组,以便直接与二元模型进行比较

def char_tuple_f(chars_list):
    char_tuples_list = []
    for char in chars:
        tup = tuple(char.split(" "))
        char_tuples_list.append(tup)return char_tuples_list

The network for chapters 31–60

计数交互

我们的最终目标是分析角色之间的互动。但是什么才算互动呢?在这里,我跟踪贝弗里奇和山,统计了两个角色的名字出现在小说中时,彼此之间的 15 个单词以内的互动。实际上,单词的数量,即字符的“单词距离”,本身也是一个变量。在对不同的值进行试验后,15 似乎是一个产生良好结果的值。

我们用字符的名字作为关键字创建一个字典。每个键的值都是一个所有索引的numpy数组,其中人物的名字出现在二元模型列表中。

def indices_dic(char_tuples, bigr):
    dic = {}
    for tup in char_tuples:
        char_name = " ".join(tup)
        indices = [i for i, x in enumerate(bigr) if x == tup]
        dic[char_name] = np.array(indices)

    return dic

然后,对于上述字典中的每个字符,我们取该字符的索引与其他字符索引的差。如果这种差异低于某个阈值(通常是 15),我们就认为这是角色之间的一次交互。这里,numpy的向量化显著加快了代码的速度。最后,我们将每个角色的所有交互添加到一个字典中。

我们只考虑有 3 次以上互动的角色。这样做的原因如下。有时候,一个段落/行尾的人物名字和下一个段落/行首的人物名字可能会出现在我们的阈值内,即使这些人物之间并没有真正的互动。这种情况通常随机发生,并且对于相同的字符,它们发生三次以上的概率很低。另一方面,如果两个角色真正地相互作用,他们将有超过 3 次的相互作用

def links_dic_f(indices_dic, threshold):

    link_dic = {}
    for first_char, ind_arr1 in indices_dic.items():
        dic = {}
        for second_char, ind_arr2 in indices_dic.items():
            if first_char == second_char:
                continuematr = np.abs(ind_arr1[np.newaxis].T - 
                         ind_arr2) <= threshold
            s = np.sum(matr)
            if s > 3:
                dic[second_char] = s
        link_dic[first_char] = dic

    return link_dic

这部分代码可能还可以进一步优化。然而,对于我所分析的文本的大小,代码几乎是即时运行的,我不觉得需要进一步优化。

The network for chapters 61–90

因为我们在小说的所有部分都使用了相同的角色列表,所以在某些部分,一些角色可能没有出现,或者没有与任何人互动。这已经在交互字典中考虑到了,但是我们也想把它们从字符列表中删除。这样,我们的图中就不会出现没有边的孤立节点。

def remove_zero_link_chars(inter_dic, chars_list):
    rem_set = set()
    for key in inter_dic:
        if inter_dic[key] == {}:
            rem_set.add(key)

    fin_list = [char for char in chars_list if char not in rem_set]
    return fin_list

创建图表

现在我们有了一个包含所有角色互动次数的字典,我们准备创建一个代表角色网络的图。我们将使用networkx库来创建图表。networkx期望图的节点作为一个列表。我们已经有了,这是我们的角色列表。此外,它期望图的边作为两个节点的元组加上边的权重值给出。我们如下创建这些元组

def edge_tuples_f(link_dic):
    edges_tuples = []
    for key in link_dic:
        for item, value in link_dic[key].items():
            tup = (key.title(), item.title(), value)
            edges_tuples.append(tup)return edges_tuples

当我们有两个列表时,用networkx创建图表是非常简单的

import networkx as nxG = nx.Graph()
G.add_nodes_from(node_chars)
G.add_weighted_edges_from(edges_tuples)

最后,我们想要检测存在于我们的图中的社区。社区是我们的图的子集,其成员相互之间的交互多于与其他社区成员的交互。社区检测背后的算法超出了本文的范围。尽管如此,我们想要展示 python 模块community可以只用一行代码就完成这一点。我们将这个分区作为属性添加到图的节点中。Gephi 稍后可以使用它来对节点进行分组。

import communitypartition = community.best_partition(G)
nx.set_node_attributes(G, partition, ‘group’)

我们将图表导出为一个.gexf文件

nx.write_gexf(G, outfile)

使用 Gephi,我们可以生成图形的美丽可视化。在 Gephi 中创建网络的要点是我使用了 Force Atlas 布局。此外,我使用社区组的节点颜色和边的数量来确定节点的大小。

The network of the full text

中心性

为了找到小说中最有影响力的人物,我们研究了中心性测量。我们计算了三种不同的中心性。

  • 度中心性定义为每个节点的边数。一个节点,或者在我们的例子中的一个字符,有更多的边,被认为更有影响力
  • 中间中心性显示一个节点在两个其他节点的最短路径内被发现的次数。实际上,它确定了角色
  • 特征向量中心性根据节点的连接来衡量节点的重要性,但与其他重要节点的连接比与不重要节点的连接贡献更大。它识别与强大角色交互的角色。

我们使用这三个中心来计算一个角色的重要性。由于我们不能直接比较不同的中心性,最终,我们的断言将是定性的。然而,对于小说中的人物,我们认为与重要人物有联系的人比与次要人物有联系的人更有影响力。因此,我们认为特征向量中心性比其他两个中心性更能决定一个字符的重要性。此外,在我们的计算中,特征向量中心性考虑了边的权重。

networkx库包括计算所有三个中心性的算法。我们用每个节点的中心性创建一个pandas数据帧。

def calc_centralities(graph):

    dgc = nx.degree_centrality(graph)
    dgc = pd.DataFrame.from_dict(dgc, orient='index', columns=["DGC"])
    btc = nx.betweenness_centrality(graph)
    btc = pd.DataFrame.from_dict(btc, orient='index', columns=["BTC"])
    evc = nx.eigenvector_centrality(graph, weight='weight')
    evc = pd.DataFrame.from_dict(evc, orient='index', columns=["EVC"])df = pd.concat([dgc, btc, evc], axis=1)

    return dfdf = calc_centralities(G)

最后,我们为所有三个中心创建了一个包含前 10 个角色的图

import matplotlib.pyplot as pltdef plot_centrality(centr, df, title, n, col_list):

    ax = plt.subplot(1, 3, n)
    s = df.sort_values(centr, ascending=False)[:10]
    x = list(s[centr].index)[::-1]
    y = list(s[centr])[::-1]

    for i, v in enumerate(y):
        bars = plt.barh(x[i], v, color=col_list[n-1])

    plt.title(title, size=22)
    ax.get_xaxis().set_visible(False)
    ax.spines['top'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.spines['left'].set_visible(False)
    ax.tick_params(axis='y', length = 0, labelsize=14)col_list = ["peachpuff", "plum", "orange"]
fig, ax = plt.subplots(1,3, figsize=(15, 10))
plot_centrality("DGC", df, 'Degree Centrality', 1, col_list)
plot_centrality("BTC", df, 'Betweeness Centrality', 2, col_list)
plot_centrality("EVC", df, 'Eigenvector Centrality', 3, col_list)plt.savefig(figfile_centr, dpi=300)

当然,对于图中的一种颜色,我们使用“桃子色”,这让我想起了在桃花源的誓言。

Centrality measures for the full text of the novel

完整的jupyter笔记本可以在这里找到。分析的结果可以在这篇文章中找到。

决策优化的网络设计

原文:https://towardsdatascience.com/network-design-with-decision-optimization-3c7fcade523?source=collection_archive---------16-----------------------

Watson Studio 是一个平台,提供数据科学家创建、调试和执行所有类型的模型所需的一切,以使用人工智能(AI)解决业务问题。在本帖中,一个常见的供应链问题,即网络设计,被用来展示如何将不同的体验结合起来,以支持完整的端到端流程。

网络设计问题

网络设计是应用决策优化的常见问题。它帮助许多不同行业的公司设计他们的运营网络,从零售商的供应链到水或能源供应商的物理网络。

一个常见的需求是决定在一组可能的候选节点中使用哪个节点子集。你可能想开一些新的配送中心,有多种选择。打开哪一个?不同的地点有不同的固定成本和可变成本。此外,一方面,这些位置与工厂和/或供应商之间的距离,另一方面,与客户和/或商店之间的距离,将对运输成本产生重大影响。

这也是一个很好的问题示例,它包括不同类型的数据,这将需要不同类型的科学:除了了解您现有的网络,并准确捕捉不同的节点和链路特征(边际成本、容量等),您还需要知道预计流经该网络的流量,为此,还需要预测技术。最后,即使知道什么必须流动也是不够的:您将需要决策优化来利用所有这些数据,以及定义不同约束和目标的模型公式,以找出要选择的最佳位置。

旧演示

前段时间,在 ILOG ,我们卖了一个产品叫 Logic Net Plus,专门解决这类问题。它包括专用的预定义数据和优化模型,这有好有坏:好是因为它为那些不知道如何开始处理这个问题的人提供了最佳实践,坏是因为那些想要进行精确数据或优化建模的人不适合现有的配置功能。

Logic Net Plus 2.0

同样在 ILOG,然后是 IBM,通过决策优化中心 (DOC),我们进行了解决类似问题的演示。DOC 是一个开发和部署业务线应用程序的平台。它包含所有你需要的,优化功能,数据管理和用户界面,但没有具体的数据或优化模型。然而,创建网络设计数据和优化模型以及创建网络设计应用程序非常容易。

Decision Optimization Center

Decision Optimization Center

如何使用沃森工作室/沃森机器学习的决策优化来管理这个问题?

本节将向您逐步展示 Watson Studio 和 Watson Machine Learning 中的新决策优化功能,这些功能可以帮助您解决这类问题。

准备数据和需求预测

如你所知,使用人工智能和数据科学的第一步是捕获和组织数据。例如,在这里,您需要连接到一个数据库来导入工厂、产品和客户,以及候选的新配送中心。

您通常还需要使用机器学习技术从历史数据中提取一些额外的运营数据来扩展它。例如,您需要根据历史数据预测所有产品和客户组合的需求。

这些部分在这篇文章中没有广泛涉及,但 Watson Studio 提供了许多工具来完成这项工作,如数据连接、数据精炼和自动 AI 或 SPSS 流。

Data Refinery

在这种情况下,来自旧的 IBM 决策优化中心供应链演示的数据(已知的和预测的)被重用。

该网络由工厂、配送中心和客户组成。一种或几种产品可以在这个网络中流动,问题的目的是规定在这个供应链中使用哪个(些)决策中心。给出了工厂的产量和客户的需求(根据历史数据预测)。还可以获得关于网络中不同节点和链路的不同成本和容量的一些数据。

创建第一个笔记本

你可以做的第一件事是创建一个 Jupyter Python 笔记本,并开始制定一个优化模型来解决这个问题。在这里可以看到关于这个的介绍。

在前面演示的模型中,新配送中心的固定成本和可变成本,以及不同的运输和存储成本,共考虑了五种不同的成本。

Initial notebook

在 Watson Studio 中,使用 docplex 包创建一个新的 Jupyter 笔记本,导入已经上传到项目中的数据并开始制定优化模型是非常简单的。还预装了解决该问题的 CPLEX 库。

由此产生的笔记本可在这里获得。您可以将它复制到您的项目中并运行它。

在数据初始化单元中,客户和产品的数量是有限的,因此问题足够小,可以在 Watson Studio 中的任何可用环境中解决。为了解决更大的模型,您将需要‘Python 3.6+DO’环境,其中包含无限的 CPLEX 功能。

在笔记本中,一些额外的叶子 python 包也被用来在地图上表示解决方案。

使用模型构建器

在该模型中,要打开的节点数量受最小值和最大值的约束。因此,为不同的值创建不同的场景,以查看对不同成本和 KPI 的影响,并以图形方式显示这些影响,可能会很有意思。

在 Watson Studio 中,一个决策优化模型构建器可用于这类用例。在模型构建器中,您可以遵循 3 个简单的步骤来导入数据、运行模型和探索解决方案。在这种情况下,您可以直接从同一项目中导入相同的数据,然后从之前的笔记本中导入模型公式。仅此而已。

Model Builder

在模型构建器中,您现在还可以创建可视化,以一种易于理解的方式显示模型的结果。例如,您可以看到每个配送中心的不同成本,就像最初的演示一样,如下所示:

然后,您可以创建不同的方案,并在参数表中为每个方案修改新配送中心的数量限制,并解决这些问题。

每个单独的场景都可以在可视化中进行探索,但是也可以配置比较图表来对它们进行比较。

这种创建和解决多个场景以更好地理解最佳解决方案的过程被称为假设分析。决策优化可以清楚地确定成本,以及多一个或少一个配送中心对成本的影响。您还可以探索每个值的最佳解决方案。

以编程方式创建多个场景

在实践中,您可能希望自动化创建修改的场景并解决它们的过程。在 Watson Studio 中,使用另一个非常简单的 Python 笔记本就可以轻松做到这一点。

笔记本使用 dd_scenario 包访问原始场景 1,并根据需要多次复制。对于每个新场景,通过修改输入表参数和重新求解来更改限制。

参见笔记本代号这里

运行此笔记本后,所有新的场景将自动出现在模型构建器和可视化中。

The cost split by KPIs and for each possible value of number of new nodes..

部署优化模型

在基于主题专家的反馈对模型公式进行多次迭代改进之后,经验证的模型可以用于生产。

为此,您可以将模型部署到 WML 并获得一个 web 服务入口点,您可以轻松地将它插入到您的应用程序中。

原型化一个 LoB 应用

模型的验证和实际生产应用程序开发的准备需要一些用户界面,业务用户可以使用这些界面来理解模型的结果。

我贡献了一些代码(do-ws-js),可以让你基于部署在 Watson Machine Learning 上的 Watson Studio 模型轻松创建一个 Node JS 应用程序,包括 do 和 ML 模型。

你可以在这里得到这个代码

使用这个框架,您可以非常容易地部署基于优化的 LoB 应用程序原型,重用已部署的优化模型、场景数据和可视化。在这种情况下,只有地图需要十几行 Javascript 代码。

Deployed prototype application

点击查看此应用的运行

请注意,该应用程序部署在小型基础架构上,可能无法正确扩展。

网络设计只是众多需要决策优化来完成数据科学家工具箱以解决业务问题的应用之一。

alain.chabrier@ibm.com

https://www.linkedin.com/in/alain-chabrier-5430656/

https://twitter.com/AlainChabrier

网络的网络——逆图形的神经符号方法

原文:https://towardsdatascience.com/network-of-networks-a-neural-symbolic-approach-to-inverse-graphics-acf3998ab3d?source=collection_archive---------9-----------------------

许多人一旦熟悉了深度学习和神经网络,他们的第一个想法就是,“如果我们制作一个神经网络的网络会怎么样?”。这是一个完全有效的想法,一个被以许多不同方式探索的想法。人们发现这种方法最常见的地方是在自动机器学习( AutoML )中,其中小块迷你网络被重新组合,以找到理想地适合一些机器学习问题的完整神经架构。我在这篇文章中想要探索的既非常类似于 AutoML,又非常不同。我的目标是传达一个想法,而不是呈现公式。如果你对细节感兴趣,你可以在我们的论文“通过终身元学习改进的逆图形的神经符号架构”(【https://arxiv.org/abs/1905.08910】T2)中找到。

那么,如果我们可以为计算机视觉设计一个网络,其中每个节点代表一些对象,连接指示哪些对象是另一个对象的一部分,会怎么样呢?如果这个网络遇到一个新的对象,简单地把它作为一个节点添加到网络中会怎么样?它可能看起来像这样:

A Network that grows with each new object it sees, by connecting it to other objects that make up its parts.

当然,在某种意义上,我们当前的卷积神经网络(CNN)在内部做着非常类似的事情。通过重新训练它们,你可能也能学到更多的东西。但是,如果大部分网络没有做任何新的事情,为什么要重新培训呢?在什么情况下,我们需要扩大神经网络以适应更多的对象类型?上图似乎表明可能有一种替代方法。

生成语法

让我们后退一步。后退了一大步。让我们看看相反的情况。如果我们想基于一个单词生成一个图像,比如【房子】呢?嗯,我们来看看这个房子是由什么构成的。大概一个【屋顶】和一些【底层】。还有【底楼】是什么做的?多个【墙】s* ,一个【门】和【窗】s 。一切都是由某种东西构成的。这个过程可以用生成语法来概括,我们把放在括号里的单个事物称为符号*

A partial parse-tree of a generative grammar for a [House].

嗯,这看起来有点像我们之前的网络,只是反过来而已…我们会谈到这一点。但是首先,我们将探索如何从【房子】到一个真实的房子的全图。有一组极其原始的图形元素,从中我们可以画出任何东西。最基本的显然是像素,但我们不会去那么深(虽然你可以)。再高一点,假设你只用【正方形】【圆形】和*【三角形】就能画出整个世界,那么我们的房子会是什么样子呢?*****

A [House] drawn from a starting symbol using triangles and squares.

酷毙了。我们能控制这个过程吗?当然可以!每个元素可以有属性来控制它的绘制方式。一个【房屋】有一个位置大小旋转来控制渲染过程。把它们想象成游戏引擎中一个物体的属性。我们还可以包括更复杂的属性,例如多老多黄,也就是形容词。**

此外,一栋的房子可以有多层。这样我们就可以决定一个【房屋】应该画成【屋顶】【底层】还是【屋顶】【地板】【底层】。这些不同的可能性被称为语法的规则。****

基元

让我们暂时集中在一个【方】上。它有自己的属性,但我们仍然需要一种方法将它绘制到屏幕上。因此,我们引入了一个渲染函数来完成这个任务。这对于我们选择的原语来说相当容易。我们将这个渲染函数称为解码器,因为它基本上将属性解码成实际的像素。**

显然,等级中较高的每个符号也需要某种解码器,将它自己的属性转换成对后面的符号有效的属性。例如,规则【房屋】→【屋顶】【底层】的解码器将获取位于中心的房屋位置,并计算屋顶和底层的中心位置。**

非常好。我们可以画图像。与我们实际想要做的正好相反…所以,让我们把整个事情翻转过来。

“Flipping” the Parse-Tree around.

但是我们必须翻转更多的东西,而不仅仅是连接。首先,我们必须反转解码器,使其成为一个编码器

原始胶囊

**【三角形】的编码器接收像素值,并试图找到该三角形的有效属性。很简单。让我们用一些回归模型,然后把它代入。我们甚至可以自己生成所有的训练数据,因为我们知道如何使用属性来绘制三角形。

但这还不够好。如果显示的是一个圆形而不是三角形的图片会怎么样?回归模型不在乎,只会产生怪异的属性。我们需要一种方法来验证图像确实是一个三角形。

不如,我们用回归模型产生的属性,绘制一个三角形,然后检查这些图像是否一致。如果一开始就是一个三角形,我们就应该达成一致,否则就不是!

所以,我们先编码,然后解码..那只是一个自动编码器!不完全是,因为我们手工制作了解码器。但仍然…我们只是添加了一个小的一致函数,这给了我们一个图像是三角形的概率。

A look at the internals of a primitive capsule. An example of agreement (a [Triangle] capsule shown a triangle).

An example of disagreement (a [Triangle] capsule shown a circle).

我们现在两者都有了,所有的属性和来自协议的概率。干净利落。让我们称这个倒置的符号及其所有内部部件(编码器、解码器、协议函数……)为胶囊。更确切地说是一个原语包,因为它代表了图形原语。这些原始的胶囊遵循简单的规则:如果我们可以渲染它,我们可以将其 … 至少去渲染成产生相同图像的东西。

语义胶囊

对于胶囊的下一层,事情有点复杂。这些函数从原语容器中获取原语,并检查它们是否是对象的正确部分。

A Semantic Capsule ([House]) activating based on the output of the Primitive Capsules ([Triangle] and [Square])

我们不知道解码器是如何获取原始胶囊的输出并告诉我们一个对象的属性的。因此,我们不能训练一个编码器…如果我们假装知道编码器是什么样的呢?看起来很奇怪,对吧…但是想想我们的【房子】,它是由一个【三角形】作为屋顶,一个【正方形】代表底层。在向前传递的过程中,我们知道正方形和三角形的所有属性。整个房子的大小可以看作是它的各个部分的大小之和。对于房子的位置和旋转,我们只取正方形和三角形的平均值。同样的过程也适用于所有其他属性,比如颜色,我们可以取平均值。一个旧的底层(1.0)加上一个新的屋顶(0.0),看上去就像一个中年的房子(0.5)。这是一个粗略的想法:我们假设,至少在开始时,我们的编码器类似于一个均值函数。****

显然,有了这样一个一般的均值函数,【三角形】**【正方形】的任何一个构型都会构成一个有效的【房子】。我们不想那样。让我们再次创建一个具有协议功能的编码器-解码器对。这一次,我们需要训练解码器而不是编码器,但我们将在真实的房子上训练它。现在,每次将正方形和三角形的配置传递给【House】胶囊时,它都会对其进行编码,然后尝试根据这些属性重建房子。如果结果与原始结果有些一致,那么它就是一所房子。否则就不是。****

A look at the internals of a semantic capsule.

让我们将这种检查部件配置,即语义一致性的封装称为语义封装

按指定路线发送

现在,我已经提到了这些符号可以有多种不同的产生规则(一栋一层或两层的房子,等等。).我们需要一些方法来处理我们的胶囊。如果我们允许每个胶囊有多个这样的编码器-解码器对,并检查哪一个最适合当前图像,会怎么样?好啊,我们走吧!让我们称每一个这样的可能对为路线。我们将整个过程称为协议路由

Detailed look at the internals of a Capsule (Primitive and Semantic). Note the different routes highlighted in yellow.

(这就是为什么我们称这些东西为胶囊。匹配输入并找到正确路线的想法是基于 Sabour、Frosst 和 Hinton 介绍的胶囊架构。然而,这里展示的胶囊有点不同,我们称它们为 神经象征胶囊 以免混淆

每一个胶囊本质上都是一个神经网络的小容器。

终身元学习

接下来,您可能已经注意到,这里展示的每个胶囊都是独立于其他胶囊的。你是对的!训练一个胶囊对其他的没有影响。我们可以随意添加和移动胶囊(当然要检查属性是否匹配)。不如我们让整个网络随着它遇到的每一个新对象而成长吧!

首先,我们需要找到一种方法来确定网络何时真正遇到了它不理解的东西。因为它是基于语法的,所以这很容易。每次单个胶囊激活和检测一个对象时,都有一些“根”对象,即代表整个图像的一个对象。在语法术语中,这被称为一个公理。在我们的胶囊网络中,这个“根”不需要在最高层。如果图像只包含一个【屋顶】**【房屋】胶囊不会激活,但【屋顶】仍将是完全代表图像的“根”。我们将把这个观察到的“根”也称为公理。****

然而,多个这样的公理可以在单个图像中激活。拿一个【房屋】和一个【车库】来说,这两个都已经激活,但是没有共享一个共同的父级。因此,我们似乎有两个我们不允许的公理。如果发生这种情况,这意味着我们遇到了一个新的对象或场景,所有这些公理都只是其中的一部分,例如【房子】【车库】是*【庄园】的一部分。*****

考虑一个不同的例子,让我们再来看看我们已经学会如何检测【豪斯】的网络。它知道如何处理底层。但是如果有更多呢?如果有五个额外的【楼层】激活呢?那么【房子】胶囊就不会激活。当然,它可以为底层加上五层中的一层生成一些属性,但是它的协议功能会注意到屋顶的位置不合适。我们必须添加一个新的胶囊作为这些激活胶囊的新公理,比如一个【apparent】胶囊。****

Slightly different example of capsules activating (blue), but there is a shared axiom missing (left). This is rectified by adding a new capsule that acts as the parent to all previously dangling capsules (right).

然而,请注意,我们并不停留在不同的物体上,而是描述场景。【办公室】【新加坡乌节路】【棒球赛】,全部完全有效。想象一张有 10 栋房子的图片。我们会有 10 次活动。这又一次违反了“只有一个公理”的规则。于是,我们创建了一个叫做【镇路场景】。****

当然,这个决定需要一些创造力。为 now 胶囊或属性命名仍然是一项人工任务。然而,胶囊网络所能做的是提出一个问题,网络会用元学习来回应。像下面这样:

问:“这些地板和屋顶看起来像房子,但它是什么?(【房屋】没有激活,即使存在多个【楼层】和【屋顶】)**

现在,这会引发人类不同的反应。每个表示不同的元学习过程。

答 1:“是一栋房子。(元学习为现有[豪斯]胶囊训练新路线)**

A.2: " 这是一个明显的事实。(元学习训练一个新的【表观】胶囊)**

这是一栋老房子。 " (元学习继续用[House]胶囊的新数据训练现有属性“old”)

b . 2:“是个有钱人的房子。(元学习为现有的【宅】囊训练一个新属性“富”)**

如果我们收集了足够多的人类决策,我们可以为胶囊网络训练一个决策矩阵。然后,一旦它学习了足够多的响应,网络就可以自己做出这些决定,并改进它原来的问题,甚至自己回答它!

An excerpt of a decision matrix. Each of those features says something about the current activations in the network, the details of which are unimportant at this point. For all features that evaluate to “True”, the values on the right are added up and the column with the highest value is equal to the decision (A.1 — B.2). Training this matrix simply means adding “1” to the column that was chosen by the human for the rows that evaluate to “True”.

但是我们用什么来训练这些新加入的胶囊,路线或者属性呢?用它刚刚收到的数据?当然,但这还不够,不是吗?我们 T12 扩充 T13 数据怎么样!在我们的情况下,这实际上很容易。毕竟我们可以访问所有的属性。移动设备(增加设备的位置属性和产生的楼层/屋顶符号)并不能改变设备的事实,我们这样做可以产生大量的数据。旋转或调整大小也不会改变间隔。我们可以对几乎所有的属性都这样做。如果每个楼层都有一个旧的黄的属性,我们可以一次将它们全部转移并增加训练集。对于一个旧的外观,我们会假设所有的地板和屋顶都是旧的,,但它仍然是一个外观。****

显然,我们会在粗略的扩充中犯错误,但这是一个开始。考虑到我们只有一张照片,聊胜于无。单枪匹马很难,即使我们在作弊。

现在,下一次电视网看到一个节目,它会……也许会理解它。但是,当网络遇到相同类型的图像时,我们总是可以添加更多的训练数据,再次使用我们的增强策略。这不是太密集的计算,因为我们隔离了每个胶囊,不需要重新训练网络的其余部分。而且,慢慢地,它会明白…这整个元学习过程非常像教一个蹒跚学步的孩子什么是对象。和初学走路的孩子一样,这是主观的,很大程度上取决于父母教什么和以什么顺序教。例如,以下面两个以不同方式训练的胶囊网络为例,但是得出相同的结论:

Two capsule networks meant to train for an asteroids like environment, but both end up with a different network configuration.

差别是微妙的,但随着时间的推移,这两个网络将会越来越相互背离。

我们现在有一个完整的网络,可以检测各种对象,随着时间的推移学习检测新的对象,甚至给我们它的属性。

但是我们也可以做一些其他的事情!我们能

  • 生成场景的语义网络!即底层语法的解析树。
  • 重复使用胶囊网络,并简单地在其上扩展!不需要重新培训旧的东西,允许一些联合学习。
  • 反向使用胶囊网络(作为原始语法)并用它生成图像!它只是一个引擎盖下的反向图形引擎。
  • 使用属性来分割图像!我们知道所有的尺寸和位置。
  • 生成图像的基本描述!毕竟一个胶囊的符号只是一个名词(【屋】,…),一个定语只是一个介词(位置,旋转,…),一个形容词(老,黄,…)或者一个动词(后面的部分探讨),它们的量级可以解释为一个副词(0.0 =不,非常= 1.0,…)**
  • 做简单的风格转移!使用多个规则/路线,一个【门】可以被绘制成一个正方形(抽象)或一个实际的门(真实),这将自动转移到任何一个有【门】作为其一部分的对象。****
  • 做物理!有人做过逆向模拟吗?

结论

我已经忽略了在论文中找到的很多细节,比如网络和语法如何处理遮挡,元学习代理如何在网络上扩展,避免使用同一胶囊的多个副本的“观察表”等等。但是我希望我能够传达一个大概的意思。

在下一部分,我想探索物理学如何使用这种方法(https://arxiv.org/abs/1905.09891)以及胶囊网络如何从一个逆向图形引擎演变为一个逆向模拟引擎,希望有一天以一个逆向游戏引擎结束。

是的。到目前为止,大多数结果都不令人印象深刻,如果这甚至可以扩展到真实图像,而不是目前正在处理的 MSPaint 级别的输入,还有待证明。Kosiorek 等人。艾尔。基于类似的原理开发了一种不同的方法,称为“堆叠胶囊自动编码器”(https://arxiv.org/abs/1906.06818),如果你对这种东西感兴趣,绝对值得一试!

我的主要希望是,这种略有不同的方法既有趣,又可能给你一些可以探索的想法,通过融入更多老式的象征方法。

神经结构搜索——限制和扩展

原文:https://towardsdatascience.com/neural-architecture-search-limitations-and-extensions-8141bec7681f?source=collection_archive---------11-----------------------

在过去的几年里,研究人员和公司一直试图通过提供预先训练的计算机视觉或机器翻译模型,让非专家更容易获得深度学习。将预先训练的模型用于另一个任务被称为迁移学习,但它仍然需要足够的专业知识来在另一个数据集上微调模型。这个过程的完全自动化允许更多的用户从 ML 迄今为止取得的巨大进步中受益。

这被称为 AutoML,它可以涵盖预测建模的许多部分,如架构搜索和超参数优化。在本文中,我将重点讨论前者,因为最近出现了大量为给定数据集搜索“最佳”架构的方法。所展示的结果基于与 Jonathan Lorraine 的合作。

神经结构搜索的重要性

作为旁注,请记住,只要该层中有足够的神经元( UAT ),仅具有单个隐藏层和非线性激活函数的神经网络就能够表示任何可能的函数。然而,这样一个简单的架构,虽然理论上能够学习任何功能,但并不代表人类视觉皮层中发生的分层处理。神经网络的架构使其具有归纳偏差,不使用卷积的浅宽网络在图像分类任务方面明显不如深卷积网络。因此,为了让神经网络进行归纳而不过度适应训练数据集,找到具有正确归纳偏差的架构非常重要(不管这些架构是否受大脑的启发)。

神经结构搜索(NAS)概述

NAS 是谷歌的一个鼓舞人心的作品,导致了几个后续作品,如【ENAS】【PNAS】飞镖。它涉及使用强化学习(RL)来训练递归神经网络(RNN)控制器,以自动生成架构。然后,这些架构的权重经过训练,并在验证集上进行评估。它们在验证集上的表现是控制器的奖励信号,然后控制器增加生成表现良好的架构的概率,并降低生成表现不佳的架构的概率。对于非技术读者来说,这基本上是一个人手动调整神经网络,学习什么工作得好,并将其自动化的过程。自动创建神经网络架构的想法并不是由 NAS 提出的,因为使用遗传算法等方法的其他方法很早以前就存在了,但 NAS 有效地使用 RL 来有效地搜索一个大得无法彻底搜索的空间。下面,在我继续讨论该方法的局限性及其更高效的继任者 ENAS 以及一种有趣的故障模式之前,我们将更深入地分析 NAS 的组件。再次比较文本时,可以更好地理解接下来的 2 小节。下图显示了如何对架构进行采样和训练:

Diagram of how NAS Works

LSTM 控制器

控制器通过对预定义的时间步长做出一系列选择来生成架构。例如,当生成卷积架构时,控制器开始仅创建其中有 6 层的架构。对于每一层,控制器只需做出 4 个决定:过滤器高度、过滤器宽度、过滤器数量和步幅(即 24 个时间步长)。假设第一层被编号为 0,那么在特定层𝒍的判决𝑪被采样为:

  • 滤镜高度是𝑪_{𝒍,h} ~ p_{𝒍 x 4)
  • 滤波器宽度为𝑪_{𝒍,w} ~ p_{𝒍 x 4+1)
  • 过滤器的数量是𝑪_{𝒍,f} ~ p_{𝒍 x 4+2)
  • 步幅是𝑪_{𝒍,s} ~ p_{𝒍 x 4+3)

注意,在时间步长𝒕,p_𝒕 = f_𝒕(h_𝒕)的概率分布只是在该时间步长的隐藏状态的线性函数,随后是 softmax。由于控制器是 LSTM,其在初始时间步长 h_0=[0,0,…,0]的隐藏状态被设置为全 0 的向量。每个采样决策都有一组预设的值,例如[24,36,48,64]的过滤器数量(看起来像一个概率网格搜索)。最终,层数增加,因此需要 LSTMs 提供的动态计算。希望 LSTM 的隐藏状态会记住过去的选择,并偏向未来时间步长的概率分布,以将这些选择考虑在内。

训练样本架构

在创建了给定的架构之后,对其进行有限次数(50)的训练,并观察验证准确度 Acc_v。有趣的是,由于在过去 5 个时期观察到的最大验证准确性被立方化,并被视为用于使用策略梯度更新控制器参数的奖励,因此涉及了一点神秘的奖励成形:

Reward Shaping Used by NAS

当我稍后讨论 ENAS 时,需要注意的重要一点是,经过训练的架构的权重被丢弃,每次架构被采样时,它们都被随机初始化。由于架构选择如此简单,所有被抽样的架构的记录,以及它们的验证准确性都被保留。

选择最佳架构

采用在控制器训练期间观察到的最佳性能架构,并且在诸如学习速率和权重衰减的一些基本超参数上执行网格搜索,以便实现接近 STOTA 的性能。

高效建筑搜索(ENAS)概述

从深度学习专家到外行人,NAS 没有被所有人使用的原因是由于其昂贵的计算复杂性。事实上,它需要大约 32,000 个 GPU 小时,这使人想知道为什么不聘请专家来设计一个架构,而不是投入这么多资源来自动搜索一个。创建 ENAS 就是为了解决这个问题。

重量共享

ENAS 没有丢弃在训练过程中采样的所有架构的权重,而是使用了一个不断更新的共享参数池。这意味着当架构 100 被采样时,它被初始化为具有已经提供合理精度的权重,尤其是与随机权重相比。这将寻找具有出色性能的架构所需的 GPU 时间从 32,000 小时减少到大约 50 小时!

这一点可以通过下图得到最好的理解。回想一下,在 NAS 示例中,我展示了如何创建一个完整的 CNN 架构。在这里,我将重点关注一个复发细胞。ENAS 上下文中的单元本质上只是一个有向无环图(DAG)。DAG 中的节点数量是预先指定的,因此只需学习连接。DAG 可以被认为是一个计算图,其边表示将信息从一个节点传输到另一个节点的矩阵乘法,节点表示不同的“隐藏状态”。

通过为每个节点选择以下内容来构建 DAG:

  • 在该节点使用的激活函数,即[tanh,sigmoid,ReLU]
  • 当前节点要连接到的前一个节点,即在节点 4,可能的选择是[1,2,3]

下图中的采样 DAG 由红色箭头表示。剩余的蓝色箭头不是示例体系结构的一部分,只是显示了创建包含 5 个节点的 DAG 时可能出现的一些其他连接。未填充的蓝色节点表示内部节点,橙色节点表示叶节点。叶节点通过平均(或潜在的一些其他机制)来组合它们的输出,并且这被认为是当前时间步长 h_{t}处整个递归单元的隐藏状态。黑色箭头表示硬编码连接(即这里没有选择)。例如,单元总是将当前时间步 x_{t}的特征和前一时间步 h_{t-1}的单元隐藏状态作为输入。

How ENAS Samples DAGs

因为有一个矩阵与 DAG 中的每条边相关联,所以共享参数池就是所有这些矩阵的集合。

为什么这些方法做得这么好

虽然由 NAS 或 ENAS 提供的架构(以及它们的学习权重)在图像分类和语言建模任务上给出了优异的性能,但不清楚这是否是由于搜索方法。

建筑搜索的基本事实

首先,如果不训练每一个可能的架构,并对每个架构执行广泛的超参数搜索,就不可能知道给定数据集的最佳架构。这使得很难说控制器是否真正有效地探索了可能的架构空间,或者它是否仅仅是重新创建了过去提供了高验证准确性的架构。有一个熵参数使控制器在每个时间步输出的概率分布更加均匀,从而增加探索,但这种探索本质上是随机的,或者它倾向于对已经被认为是最好的架构进行轻微的改变。如果我们所关心的是达到某种程度的精度,这可能不是问题,但是对于良好的性能可能有另一种解释。

谁决定搜索空间

管制员在每个时间步做出的决定极其有限。它们相当于从一组选项中进行选择,这些选项在过去已经被认为对递归或卷积架构非常有效。例如,滤波器宽度的选项为[1,3,5,7],这是在 ResNetsDenseNets 等模型中使用的标准值。因此,搜索空间本身存在偏差,很难对表现不佳的架构进行采样。显然,拥有更细粒度的选择会增加搜索算法的样本复杂性,但是如果我们真的相信搜索算法的有效性,我们就不会将它局限于使用我们人类认为有效的值,因为这可能会阻止发现更有效的架构。

与随机搜索的比较

在我们的实验中,以及由 Sciuto 等人Li 和 Talwakar 同时进行的那些实验中,使用基于 RL 的控制器与随机搜索来探索体系结构的空间似乎没有什么好处。我们将重点放在 ENAS 的宾夕法尼亚树库语言建模任务,其目标是生成一个循环细胞。如下图所示,当从受过训练的控制器中采样 1000 个体系结构时,与从未受过训练的控制器中采样 1000 个体系结构相比,受过训练的控制器确实做得更好,但这可以用权重共享方案来解释,而不是控制器探索搜索空间的能力。一个训练有素的控制器对一组不那么多样化的体系结构进行采样,因为根据定义,它必须是有偏差的。这意味着当在训练期间更新共享参数时,它们必须对较少的架构有效。另一方面,随机控制器对更多不同的架构进行采样,因此共享参数被更新以试图对太多架构有效,但最终不会对任何给定架构特别有效。

Trained vs Untrained Controller Performance

控制器正在学习什么

如果使用基于 RL 的控制器并不一定比随机搜索更好,那么控制器在学习什么?深度学习以产生无法解释的黑盒模型而闻名,尽管对于图像分类、对象检测甚至分割等任务,有一些技术可以可视化神经网络关注的输入图像中的什么特征,尽管结果要有所保留,如 Adebyo 等人所示。至少,我们可以预期控制器的循环性质会基于过去的决策来偏向未来的决策。这在 ENAS 不会发生。这种对架构决策的无条件采样是有问题的,因为可能存在需要节点之间特定连接模式的高效单元,并且如果不能以过去的决策为条件,则不能发现这种模式。

下图显示了 100 个采样架构的 RNN 控制器的隐藏状态(每一行对应于单个架构的控制器隐藏状态)。请注意,在(a)中,所有的行都是相同的,即使采样的架构是不同的,这表明控制器不会在其隐藏状态中对架构选择进行编码。

Controller Hidden State Visualization

有可能强迫记忆过去的决定吗?我们通过在用于训练控制器的原始损失上增加一个正则化项来研究这一思想:这是一个自我监督的目标,要求控制器能够再现它所看到的过去的体系结构。明确地

  • 经过 5 个时期的训练后,每个时期采样并存储 1000 个架构(最多 10,000 个)。一旦该缓冲器满了,每个时期随机替换 100 个架构
  • 在第 10 个时期,添加一个监督惩罚,用于从体系结构的内存缓冲区中重建 100 个体系结构的随机样本。在控制器训练的每一步,这个损失被加到策略梯度损失上:L=L_{PG}+L_

这种正则化的工作方式类似于使用 RNNs 以自回归的方式进行语言建模:每个时间步的目标是预测下一个时间步的架构选择。这里似乎有点先有鸡还是先有蛋的问题。如果我们要求控制者重新构建架构,而这些架构在每个时间步的选择并不首先取决于过去的时间步,那么我们不就是在强化这种行为吗?事实上,这并不重要,因为我们试图给控制器记忆和再现序列的能力,这至少迫使控制器的隐藏状态包括过去的选择。上图中的(b)显示了这种正则化的效果,很明显,控制器的隐藏状态现在至少在不同的采样架构之间有所不同。

为了确认这种正则化实际上使得控制器嵌入在架构之间提供了有意义的相似性,我们将架构嵌入之间的 L2 距离与架构相似性的各种直观概念相关联,例如激活函数的数量或采样 Dag 之间的共同连接。如下表所示,正则化给出了最好的 Spearman 相关性,但仍然很低。在控制器中实施架构记忆的不那么特别的方式可能有助于增加更多的相关性。

Spearman Correlation Between Architecture Distance and Other Stats

未来方向

目前比较架构的方式过于简单。仅仅考虑验证集的性能就忽略了许多我们可能希望模型拥有的有用属性。例如,有可能偏向体系结构搜索,以生成对敌对干扰更健壮的体系结构,或者更适合修剪的体系结构。为了赋予架构搜索方法这种能力,以某种方式量化特定架构可以学习的功能空间将是有用的。这样做允许使用更有趣的“更好”的概念,因为许多架构给出了类似的验证准确性,但是即使 A_{1}的性能比 A_{2}稍差,也可能它有其他我们认为 A_{2}没有的属性。随着最近对机器学习社区的关注,例如增加隐私和减少偏见,需要产生满足这些要求的架构的更智能的架构搜索技术。

神经架构搜索(NAS)——深度学习的未来

原文:https://towardsdatascience.com/neural-architecture-search-nas-the-future-of-deep-learning-c99356351136?source=collection_archive---------3-----------------------

作为初学者,你需要知道的是

(本博客的修订版可以在 这里找到 )

我们大多数人可能都听说过 ResNet 的成功,她是 2015 年 ILSVRC 图像分类、检测和定位奖的获得者,也是 2015 年 COCO MS 检测和分割奖的获得者。这是一个巨大的建筑,到处都是跳跃连接。当我使用这个 ResNet 作为我的机器学习项目的预训练网络时,我想“怎么会有人提出这样的架构呢?''

Large Human Engineered Images Classification Architectures(image source)

不久之后,我得知许多工程师和科学家凭借他们多年的经验建造了这个建筑。更多的是直觉而不是完整的数学会告诉你“我们现在需要一个 5x5 滤波器来实现最佳精度”。对于图像分类任务,我们有很好的架构,但对于其他任务,我们必须花费大量精力来寻找一种具有合理性能的架构。如果我们能够像学习机器学习模型的参数一样自动化这个架构建模任务,那当然会更好。

神经架构搜索(NAS),自动化架构工程的过程,即找到我们的机器学习模型的设计。我们需要为 NAS 系统提供数据集和任务(分类、回归等),它将为我们提供体系结构。且当通过所提供数据集进行训练时,对于给定的任务,该架构将在所有其他架构中表现最佳。NAS 可以被视为 AutoML 的一个子领域,与超参数优化有很大的重叠。要了解 NAS,我们需要深入了解它在做什么。它通过遵循搜索策略所有可能的架构中找到一个架构,这将最大化性能。下图总结了 NAS 算法。

Dimensions of NAS method(reference)

它有 3 个独立的维度:搜索空间、搜索策略和性能评估。

搜索空间定义了NAS 方法原则上可能发现什么样的神经架构。它可以是链状结构,其中层(n-1)的输出作为层(n)的输入。也可以是跳接的现代复杂架构(多分支网络)。

A chain-like and multi-branch network (image source)

有时人们确实想使用手工制作的外部建筑(宏观建筑),带有重复的主题或单元。在这种情况下,外部结构是固定的,NAS 只搜索单元体系结构。这种类型的搜索被称为微搜索或小区搜索。

left: The cell architecture right: cells are put in the handcrafted outer structure(source).

在许多 NAS 方法中,微观和宏观结构都以分层的方式进行搜索;它由几个层次的主题组成。第一层由一组基元操作组成,第二层由通过有向非循环图连接基元操作的不同基元组成,第三层基元编码如何连接第二层基元,依此类推。

为了解释搜索策略性能估计,三种不同的 NAS 方法将在以下部分讨论。

强化学习

强化学习是代理(程序)面临的问题,它必须通过与动态环境的试错交互来学习行为,以最大化某些回报。代理(根据由θ参数化的某个策略执行某个动作。然后,该代理根据对所采取行动的奖励来更新策略θ。在 NAS 的情况下,代理产生模型架构,子网络 ( 动作)。然后在数据集上训练模型,模型在验证数据上的表现作为奖励。

The controller plays the role of an agent and accuracy is taken as the reward(reference)

通常,递归神经网络(RNN)被视为控制器或代理。它产生字符串,并随机地从该字符串构建模型。

RNN predicts filter height, filter width, stride height, stride width, and the number of filters for one layer and repeats in a form of string. Each prediction is carried out by a softmax classifier and then fed into the next time step as input. The RNN stops after generating a certain number of outputs. (image source)

上图显示了这种 RNN 的输出示例。卷积神经网络的每一层的超参数重复产生一定次数。然后根据 RNN 的输出建立模型,然后对模型进行训练并计算验证精度。

在这里,RNN 的参数充当了代理人的策略θ。生产管柱(高度、过滤器宽度、步幅高度等)是代理的动作。在这种强化方法中,模型在验证集上的表现是代理人的回报。RNN 以某种方式更新其参数θ,使得所提出的架构的预期验证精度最大化。

通过策略梯度方法训练 RNN,迭代更新策略θ。主要目标是最大化预期精度,即

这里 R 是模型的精度, a_1: T 是 RNN( the action)生产的长度为 T 的字符串, θ 是 RNN 的参数。

由于 J(θ)不可微,采用策略梯度法迭代更新θ。更新函数看起来像这样

这是原始方程的近似值。用采样代替 J(θ)的期望项。该更新方程的外部求和用于该采样,即从 RNN 采样的【m】个模型,并取其平均值。P(a _ t | a _(t1):1;θc),是根据 RNN 用参数 θ ( 参考 ) 预测的策略 θ或,给定从 1 到(t-1) 的所有动作,在时间t采取动作 a_t 的概率。****

Example of strings produced by RNN to create a model(reference)

编码跳过连接有点棘手。为此,每层的 RNN 生成一个名为锚点的输出。锚点用于指示跳过连接。在层 N,处,锚点将包含N-1基于内容的 sigmoids,以指示需要连接的先前层。

渐进式神经架构搜索(PNAS)

PNAS 做了一个小区搜索,如本教程的搜索空间部分所讨论的。他们从块中构造单元,并通过以预定义的方式添加单元来构造完整的网络。

Hierarchy of model architecture(reference)

细胞以预定的数量串联起来形成网络。并且每个单元由几个块(原始论文中使用的 5 个)形成。

(image source)

这些块由预定义的操作组成。

structure of a block. The Combination function is just an element-wise addition (reference)

图中所示的操作在原始文件中使用,可以扩展。

the complete structure of a Cell(reference)

左侧显示了一个完整的示例。甚至在这个单元或微搜索中,总共有 10 个⁴有效组合要检查以找到最佳单元结构。

因此,为了降低复杂性,首先只构建只有一个块的单元。这很容易,因为在上述操作中,只有 256 个不同的单元是可能的。然后,选择前 K 个表现最好的单元来扩展 2 个块单元,并且重复直到 5 个块。

但是对于一个合理的 K 来说,要训练的 2 挡候选人太多了。作为这个问题的解决方案,训练了一个“廉价的”代理模型,它只需通过读取字符串(单元格被编码为字符串)来预测最终性能。这种训练的数据是在构建、训练和验证单元时收集的。

例如,我们可以构建所有 256 个单块单元,并测量它们的性能。并用这些数据训练代理模型。然后使用该模型预测 2 个块单元的性能,而无需训练或测试它们。当然,代理模型应该能够处理可变大小的输入。然后选择由模型预测的前 K 个最佳性能的 2 个块单元。然后对这两个块单元进行训练,对“代理”模型进行微调,将这些单元扩展到 3 个块,并进行迭代,直到得到 5 个块单元。

Steps in PNAS (reference)

差异化架构搜索(DARTS)

神经架构的搜索空间是离散的,即一个架构与另一个架构至少有一层或该层中的一些参数不同,例如, 5x5 滤波器与 7x7 滤波器。在这种方法中,连续松弛被应用于这种离散搜索,这使得能够进行直接的基于梯度的优化。

我们搜索的单元可以被视为有向非循环图,其中每个节点 x 是潜在表示(例如卷积网络中的特征图),并且每个有向 边(I,j) 与一些操作 o(i,j) (卷积、最大池化等)相关联,这些操作变换*并且在节点处存储潜在表示*****

每个节点的输出可以通过左边的等式计算。节点是这样枚举的,从节点x(j)再到 i < j 有一条 边(I,j)**

在连续松弛中,而不是在两个节点之间进行单一操作。使用每个可能操作的凸组合。为了在图中对此进行建模,在两个节点之间保留了多条边,每条边对应一个特定的操作。而且每条边还有一个权重 α

continuous relaxation of the discrete problem(reference)

现在 O(i,j) 节点 x(i)和 x(j)之间的运算是一组运算的凸组合 o(i,j) 其中 o(。) ϵ S ,其中 s 是所有可能操作的集合。

O(i,j) 的输出由左式计算。****

训练和验证损失分别用 L_trainL_val 表示。这两个损耗不仅由架构参数 α 决定,还由网络中的权重‘w’决定。架构搜索的目标是找到最小化验证损失的α∫***L _ val(w∫,α∫),其中通过最小化训练损失来获得与架构相关的权重‘w∫’**。*

w∫= arg minL _ train(w,α∫)**。****

这意味着一个以 α 为上层变量,以 w 为下层变量的双层优化问题:

α= arg minL _ val(w∫(α),α)*****

s . t .w∫(α)= arg minL _ train(w,α)**

训练后,一些边的一些α变得比其它边大得多。为了导出该连续模型的离散架构,在两个节点之间,保留具有最大权重的唯一边。

a) Operations on the edges are initially unknown. b) Continuous relaxation of the search space by placing a mixture of candidate operations on each edge c) some weights increases and some falls during bilevel optimization d) final architecture is constructed only by taking edges with the maximum weight between two nodes. (reference)

当这些细胞被发现时,它们就被用来构建更大的网络。

还有许多其他方法也用于神经结构搜索。他们取得了令人印象深刻的成绩。但是,我们仍然对回答“为什么一个特定的架构工作得更好?”这个问题知之甚少。我想我们正在回答这个问题。

神经协同过滤

原文:https://towardsdatascience.com/neural-collaborative-filtering-96cef1009401?source=collection_archive---------0-----------------------

基于神经网络的增压协同过滤

在信息爆炸的时代,推荐系统在缓解信息过载方面发挥着关键作用,已被许多在线服务广泛采用,包括电子商务、流媒体服务和社交媒体网站。这些推荐系统的主要组成部分是带有隐式反馈的协同过滤(CF)矩阵分解是协同过滤最常用的变体。它使用用户-项目矩阵的固定内积来学习用户-项目交互。神经协同过滤(NCF)用一种神经架构代替用户项内积。通过这样做,NCF 试图实现以下目标:

  1. NCF 试图在其框架下表述和概括 MF。
  2. NCF 试图通过多层感知器来学习用户与物品的交互。

让我们从推荐系统的基础开始。

  1. 协同过滤 基于用户过去的交互对项目的用户偏好进行建模。
  2. 矩阵分解(MF) 将用户/项目表示为潜在特征的向量,这些特征被投影到共享的特征空间中。在这个特征空间中,用户-项目交互可以使用用户-项目潜在向量的内积来建模。MF 的这种普通实现可以通过将其与基于邻居的模型集成、将其与项目内容的主题模型组合并将其扩展到用于特征的一般建模的因式分解机器来增强。
  3. 隐性反馈 通过观看视频、产品购买、点击间接反映用户的喜好。使用隐性反馈的好处是更容易收集,而且是过剩的。缺点是没有现成的负面反馈。
  4. 显性反馈 由评分和点评组成。这是一种直接反馈,负面反馈或产品的可能性很容易通过评级获得。

尽管矩阵分解对于协同过滤是有效的,但是它的性能受到交互函数的简单选择- 内积 的阻碍。通过在交互作用函数中引入用户项目偏差项,可以提高其性能。这证明了潜在特征(内积)的简单乘法可能不足以捕获用户交互数据的复杂结构。

这就要求设计一个更好的、专用的交互功能来模拟用户和项目之间的潜在特征交互。【NCF】神经协同过滤旨在通过:-

  1. 通过神经网络架构对用户-项目特征交互进行建模。它利用一个 多层感知器(MLP) 来学习用户-项目交互。这是对 MF 的升级,因为 MLP 可以(理论上)学习任何连续函数,并且具有高水平的非线性(由于多层),使得它非常适合学习用户-项目交互函数。

2.将 MF 作为 NCF 的特例进行推广和表达。由于 MF 在推荐领域非常成功,这样做会给 NCF 更多的信任。

在下一节中,我们将正式定义推荐问题,并创建一个基本模板来解决它。

问题陈述

给定一组用户 U = { u = 1,…,U},一组项目 I = { i = 1,…,I},以及用户过去对项目 O = ( u,I,y )的偏好日志,我们的目标是向每个用户 U 推荐一个排序的项目列表,该列表将最大化她/他的满意度。 y 可以是 1(情况 1)也可以是 0(情况 2)。

案例 1: O 观察到的条目:
表示用户 u,与物品 I 有过交互,但不代表 u 喜欢 I。

案例 2: 未观察条目:
这并不意味着用户 u 不喜欢项目 I。未观察条目可能只是缺失数据。

使用隐式反馈的一个缺点是负面反馈的自然稀缺性。

直观地说,推荐算法估计 Y 中未观察条目的分数,用于对项目进行排序。

从形式上讲,他们计算

Equation 1

y(u,i): 用户 u 与项目 I 交互的预测得分
theta: 模型参数
f(交互函数): 将模型参数映射到预测得分

为了计算θ, 需要优化一个目标函数。推荐系统的两个最流行的损失函数是逐点损失和成对损失。

  1. 逐点损失遵循回归框架,通过最小化预测得分 y_(u,i) 和目标值 y(u,I)之间的平方损失。为了说明负反馈,要么将所有未观察到的条目视为负面实例,要么将一些未观察到的条目采样为负面实例。
  2. 成对损失 旨在将观察到的条目排列得高于未观察到的条目。它通过最大化观察到的条目和未观察到的条目之间的差额来实现这一点。

总之,成对损失最大化了观察到的和未观察到的条目之间的差额,而逐点损失旨在最小化预测得分和目标得分之间的损失。

NCF 框架使用神经网络来参数化交互作用函数 f 以估计 y_carat(u,I)。它支持成对学习和逐点学习。

矩阵分解

MF 通过用户-项目潜在向量的标量积来模拟用户-项目交互。用数学术语来说,它表示如下

Equation 2

在哪里

【y _ carat(u,i) : 预测得分(看等式 1)
p(u):潜在向量为用户 u
q(I):潜在向量为项
K: 潜在空间的维度

图 1 中的例子示出了由使用简单且固定的内积来估计低维潜在空间中复杂的用户-项目交互所引起的 MF 的可能限制。在浏览图 1 时,请记住以下两个条件。

  1. 当 MF 将用户和项目映射到相同的潜在空间时,用户之间的相似性可以通过他们潜在向量之间的角度的内积或余弦来测量。
  2. Jaccard 系数是 MF 需要恢复的基本事实(2 个用户的相似性)

Jaccard coefficient

Figure 1: Let us first focus on the first three rows (users) in Figure 1a. It is easy to have s23(0.66) > s12(0.5) > s13(0.4). As such, the geometric relations of p1, p2, and p3 in the latent space can be plotted as in Figure 1b. Now, let us consider a new user u4, whose input is given as the dashed line in Figure 1a. We can have s41(0.6) > s43(0.4) > s42(0.2), meaning that u4 is most similar to u1, followed by u3, and lastly u2. However, if an MF model places p4 closest to p1 (the two options are shown in Figure 1b with dashed lines), it will result in p4 closer to p2 than p3, which unfortunately will incur a large ranking loss.

解决这个问题的一个方法是使用大量的潜在因子 K。但是增加 K 会不利地损害泛化能力。

NCF 通过使用深度神经网络(DNN)从数据中学习相互作用函数来克服这一限制。

NCF 建筑

Figure 2: Neural Collaborative Filtering framework

  1. 输入层二进制化用于用户和项目标识的稀疏向量,其中:
    项目(i): 1 表示用户 u 已经与项目(i)
    用户(u):进行了交互,以标识用户
  2. 嵌入层是将稀疏表示投影到密集向量的全连接层。获得的用户/项目嵌入是潜在的用户/项目向量。
  3. 神经 CF 层使用多层神经架构来将潜在向量映射到预测分数。
  4. 最终输出层通过最小化逐点损失/成对损失来返回预测得分。

NCF 以如下方式修改等式 1:

Equation 3: NCF’s construct to calculate user-item interaction

在哪里

P: 潜在因素矩阵 for users(Size = M * K)
Q:潜在因素矩阵 for items(Size = N * K)
Theta(f):模型参数

由于 f 被公式化为 MLP,它可以展开为

Equation 4: Modeling user-item interaction

在哪里

【Psi(out):输出层的映射函数
Psi (x): 第 x 个神经协同过滤层的映射函数

等式 4 充当 NCF 的得分函数。

NCF 损失函数

逐点平方损耗方程表示为

其中 Y:Y 中观察到的交互
y 中的负: 所有/未观察到的交互
w(u,I):
训练实例的权重(超参数)**

如果我们假设观察值来自高斯分布,就可以解释平方损失,但在我们的情况下这是不正确的。加上预测分数 y_carat 应该返回[0,1]之间的分数,以表示给定用户-项目交互的可能性。简而言之,我们需要一种概率方法来学习逐点 NCF,这种方法特别关注隐式数据的二进制属性。

NCF 在输出层使用逻辑/概率单位函数来解决上述问题。

利用上述设置,似然函数被定义为:

取似然函数的负对数

也就是交叉熵损失/对数损失。

通过采用概率处理,NCF 将推荐问题转化为二元分类问题

为了说明负面实例 y- 是从未观察到的交互中均匀采样的。

在下一部分,我们可以看到 GMF(NCF 的一个组成部分)是如何推广 MF 框架的

广义矩阵分解(GMF)

NCF 的预测输出可以表示为

Equation 5

其中
a-out :激活函数
h: 输出层的边缘权重

我们可以使用 a-out 和 h 来创建 GMF 的多种变体。

从上表可以看出,身份激活函数和边权重为 1 的 GMF 确实是 MF。另外两种变化是通用 MF 的扩展。GMF 的最后一个变化是在 NCF 使用乙状结肠作为激活。

NCF 使用具有 sigmoid 的 GMF 作为激活函数,并且从具有对数损失的数据中学习 h(边权重)。

在下一部分,我们将解释 NCF 如何尝试使用 MLP 来建模用户-项目交互

多层感知器(MLP)

NCF 是多模态深度学习的一个例子,因为它包含来自两条路径的数据,即用户和项目。将它们组合起来最直观的方式是通过连接。但是简单的向量拼接没有考虑用户-项目交互,并且不足以对协同过滤效果建模。为了解决这个问题,NCF 在串联的用户-项目向量(MLP 框架)上添加了隐藏层,以学习用户-项目交互。这赋予了该模型很多灵活性和非线性来学习用户-项目交互。这是对 MF 的升级,它在 MF 上使用了固定的元素级产品。更准确地说,MLP 将等式 1 修改如下

Equation 6

其中:
W(x) :权重矩阵
b(x) :偏置向量
a(x) :第 x 层感知器的激活函数
p: 用户的潜在向量
q: 某项的潜在向量

NCF 使用 ReLU 作为其 MLP 部分的激活功能。

由于多个隐藏层,与它们的潜在向量的固定元素方式的乘积(MF 方式)相比,该模型具有足够的复杂性来学习用户-项目交互。

纽姆夫:GMF 和 MLP 的融合

NCF 由 GMF 和 MLP 两部分组成,具有以下优势

  1. GMF 应用线性内核来模拟用户-项目交互,就像香草 MF
  2. MLP 使用多个神经层来分层非线性相互作用

NCF 将这些模型结合在一起,以叠加它们的理想特征。NCF 在将 GMF 和 MLP 的输出馈送到 NeuMF 层之前,将它们连接起来。

需要注意的要点

  1. GMF/MLP 有单独的用户和项目嵌入。这是为了确保它们都独立地学习最优嵌入。
  2. GMF 通过用户项目向量的元素式乘积来复制普通 MF。
  3. MLP 将用户项目潜在向量的串联作为输入。
  4. GMF 和 MLP 的输出在最终的 NeuMF(神经矩阵分解)层中连接。

等式 1 的得分函数被建模为

G:GMF
M:MLP
p:用户嵌入 q: 项目嵌入

该模型通过 NeuMF(神经矩阵分解) 层结合了 MF 的线性和 DNNs 的非线性,用于对用户项潜在结构进行建模。

由于 NeuMF 的非凸目标函数,基于梯度的优化方法只能找到局部最优解。这可以通过良好的权重初始化来解决。为了解决这个 NCF 用预先训练好的模型初始化 GMF 和 MLP 。有两种方法可以做到这一点

  1. 随机初始化
    1。用随机初始化训练 GMF+MLP 直到收敛。
    2。使用模型参数 1 初始化 NCF。
    3。对于输出层,两个模型的权重连接为
  2. GMF + MLP 从零开始

其中
h(GMF) :预训练的 GMF 的 h 向量
h(MLP) :预训练的 MLP 的 h 向量
alpha: 超参数确定两个预训练模型之间的权衡

  1. GMF + MLP 从零开始
    1。 自适应矩估计(Adam) 通过对频繁的参数执行较小的更新和对不频繁的参数执行较大的更新来适应每个参数的学习速率。对于
    两种模型,Adam 方法的收敛速度都比普通 SGD 快,并且减轻了调整学习速率的痛苦。
    2。在将预先训练的参数输入 NeuMF 后,我们用普通的 SGD 而不是 Adam 来优化它。Adam 需要保存动量信息以更新参数。因为预训练网络的初始化不存储动量信息。

这就完成了 NCF 的理论。

Python 示例

这个程序段使用来自这个库的 NCF 实现。首先,按照中给出的步骤安装推荐库。

df.head()

predictions.head()

结论

NCF 学习了一个概率模型,强调隐含数据的二进制属性。我们讨论了如何在 NCF 下表达和推广 MF(使用一般矩阵分解{GMF})。NCF 通过使用多层感知器(MLP)来学习用户-项目交互功能,探索了 DNNs 在协同过滤中的应用。最后,我们讨论了一种新的神经矩阵分解模型 NeuMF,它在 NCF 框架下集成了 MF 和 MLP;它结合了 MF 的线性和 MLP 的非线性的优点来建模用户项目的潜在结构。最后一部分包含一个 NCF 的工作实例。所用代码摘自 Github 的 ncf_deep_dive 笔记本。这个库包含许多例子,非常有用。我强烈建议你仔细阅读。

参考

  1. NCF 论文
  2. 微软推荐库
  3. 原作者代码

神经密码术

原文:https://towardsdatascience.com/neural-cryptography-7733f18184f3?source=collection_archive---------17-----------------------

几年来,加密一直是建立安全连接的方式。它是安全的,计算效率高,几乎每个平台都支持。但是加密的缺点是加密的信息是没有意义的。它是一堆没有意义的比特或字符,任何人都无法解释。在本文中,我们想要设计和训练一个神经网络。它加密和解密信息,而密码是人类可以理解的。更具体地说,每个密码都是一个图像,信息就嵌入其中。给定新图像,网络的另一部分可以从图像中提取信息(句子)。

The whole idea.

网络分为两部分:

  1. 编码器:它获取图像和标记化的文本,并将标记化的文本嵌入到图像中。
  2. 解码器:它获取编码器的输出(新图像)并从中提取标记化的文本。

我们使用随机生成的图像,因为网络必须与任何图像一起工作。消息也是如此。我们使用随机整数来表示标记化的消息,而不是实际文本。有希望的是,一个融合的模型可以在实际的图像和文本上运行。

为了生成随机图像,我们使用:

随机生成图像的一些示例如下:

Randomly generated images.

下面的代码用于生成随机字符消息:

一个随机句子的例子是:

@\x8eUÍbâºq÷3\x8b¸|¼Ó\x91æíÃtÉ/LO¤_

现在,我们可以创建一个生成器,它总是生成一批新的随机图像和消息。

数据现在准备好了。我们现在可以实现我们的模型了。输入图像大小为(100,100),而文本长度为 100。首先,我们使用一个 2D 卷积层,其内核大小为(1,1),滤波器计数为 20,由图像上的 ReLU 激活。然后,我们将序列的每个元素(字符)嵌入到一个新的一百维空间中。嵌入序列的大小现在是(100,100)。接下来,我们将嵌入的序列附加到第三个轴中的图像上。新张量的形状是(100,100,21)。具有三个滤波器的(1,1)卷积层现在用于从新张量重建图像。之后,我们用一个滤波器将重建图像输入到(1,1)卷积层。输出的形状是(100,100,1)。我们可以假设这是一个一百个字符的序列,在一个一百维的空间中。随后,我们使用一个全连接层,然后激活 softmax,将每个字符映射到字典空间。我们期望该模型将每个字符(令牌)重建为一个热点向量。下图显示了模型。

以下代码是该模型的 Keras 实现:

经过所有的努力,我们现在可以训练模型了:

经过 512 个历元的训练,该模型具有合理的精度。在 100%重建字符时,图像重建的绝对误差之和为 0.01。在测试模型之前,我们还需要两个函数来将句子编码和解码成 ASCII 码。

注意:任何其他字符编码都可以代替 ASCII。

是时候用真实世界的数据来检验这个模型了。我们必须选择一个句子和一个形象。我们从维基百科中选择以下句子:

安东尼·爱德华“托尼”斯塔克是小罗伯特·唐尼在 MCU 系列电影中塑造的一个角色

对于图像,我们从文章开始就使用相同的托尼·斯塔克的图像。以下代码用于嵌入和提取消息:

解码后的句子是:

安东尼·爱德华“托尼”斯塔克是小罗伯特·唐尼在 MCU 系列电影中塑造的一个角色

这与输入完全相同。这些图像(包含和不包含嵌入消息)是:

在两个图像之间,像素中的平均颜色变化是 1.67,这是正常人眼无法分辨的。

结论

我们训练了一个网络,它可以通过对图像进行人眼不可见的微小改变,将任何信息嵌入任何图像。感谢您阅读我的文章。我希望它值得你花时间。我还不能说出它的任何应用,因为这只是出于我的好奇。

神经虚拟自我游戏

原文:https://towardsdatascience.com/neural-fictitious-self-play-800612b4a53f?source=collection_archive---------22-----------------------

不完全信息博弈中的深度强化学习

Photo by Paweł Czerwiński on Unsplash

更新:学习和练习强化学习的最好方式是去 http://rl-lab.com

介绍

本文基于 Heinrich & Silver 的一篇科学论文,该论文介绍了第一种可扩展的端到端方法,用于在没有先验知识的情况下学习近似纳什均衡

重要提醒

  • 虚拟游戏:是一种在两人零和游戏中寻找纳什均衡的迭代方法。它的问题是,它适用于标准形式的游戏,这是表格,不捕捉时间或顺序。详情可以在“虚拟玩法简介”一文中找到。
  • 虚拟自我游戏:是一种利用扩展形式的游戏,通过整合时间/序列来解决虚拟游戏问题的方法。它还使用强化学习来寻找最佳反应的近似值,并使用监督学习来更新平均策略。证明了它能收敛到一个纳什均衡。更多详情请见文章"虚构的自我扮演"

不完美信息博弈

在不完全信息下,玩家根本不知道其他玩家选择的行动。然而,他们知道其他玩家是谁,他们可能的策略/行动是什么,以及这些其他玩家的偏好/收益。因此,在不完全信息中关于其他参与者的信息是完全的

另一方面,在不完全信息博弈中,参与者可能知道也可能不知道其他参与者的一些信息,例如他们的“类型”、策略、收益和偏好。

国际象棋是一个拥有完全信息的游戏的例子,因为每个玩家可以随时看到棋盘上的所有棋子。其他完美信息博弈的例子包括井字游戏、跳棋、无限象棋围棋

纸牌游戏中,每个玩家的牌对其他玩家是隐藏的,例如扑克和桥牌,是不完全信息游戏的例子。

储层取样

储层采样是一种对长度为 N 的数据流进行采样的算法,使得选择数据项的概率为 1/N,即使 N 是未知的并且存储器大小是有限的并且小于 N,因此在采样之前不是所有的流数据都可以被缓冲。
总之,该算法工作,例如对于第 与第 项,我们旋转一个带有 i 槽的轮盘,该轮盘仅包含一个获胜槽。如果获胜的位置被选中,那么我们将从样本中提取该项目。可以证明这种方法对于每个要选择的项目都有 1/N 的概率。

预期动态

预期动力学是一种能够使学习游戏动力学的稳定性发生质的变化的方法。在一般和多人游戏的情况下,这意味着收敛到混合策略纳什均衡。更多细节可以在“一般进化博弈中的预期学习”一文中找到。

这项技术背后的想法是将预期的** 修正引入到动作中。理解它最简单的方法,就是想象向一个移动的目标射击。你通过瞄准目标前方一段距离来修正你的射击。**

所以你引入了一个预期修正参数。在神经虚构自我发挥的情况下,这个参数是一个叫做“η”的概率。

神经虚拟自我游戏

神经虚拟自我游戏(NFSP)将神经网络引入虚拟自我游戏。
它使用两个独立的网络 Q(s,a | θ(Q))和π(s,a |θ(π))以及分别分配给它们的两个存储缓冲器 Mrl 和 Msl:

  • Mrl 是一个循环缓冲区,以

  • Msl 是一个以[s(t),a(t)]状态和时间步长 t 的动作的形式存储最佳行为的库。
  • Q(s,a | θ(Q))是一个神经网络,使用非策略强化学习从 Mrl 中的数据预测动作值。这个网络近似于最佳反应策略,β = ε-greedy(Q),以概率ε选择一个随机行动,以概率(1-ε)选择使 Q 值最大化的行动。
  • π(s,a |θ(π)),是一个将状态映射到动作概率的神经网络,定义了智能体的平均策略,π=π。换句话说,它试图从 Msl 中以前的最佳反应行为的历史中使用监督学习来再现最佳反应行为。

所以现在我们有两个神经网络来预测行为。
Q(s,a | θ(Q))通过利用过去的经验,另π(s,a |θ(π))通过从最佳反应的历史中抽取。但是代理必须在每个回合使用一个动作,并且必须从这些网络中选择一个动作。
原则上,代理应该使用 it is average 策略π,并使用 Q 生成最佳响应,该最佳响应将被馈入 Msl 以训练其平均策略网络π(s,a |θ(π))。
然而有一个问题!Q 如何从自己的行动中产生经验?请记住,Q 生成β = ε-greedy(Q)并将其馈送给π(s,a |θ(π)),π将使用监督学习来训练其权重θ(π)。所以从π采样的动作不是β,这对于 Q 的体验来说是有问题的,因为它没有观察到其即时动作的结果。

似乎解决这个问题的最佳方式是通过使用预期参数η,使得它以概率η使用ε-greedy(Q ),以概率(1-η)使用π。

最终算法的主要步骤如下:

  • 定义策略σ,使得它是ε-贪婪的(Q)概率为η,π概率为(1-η)。
  • 从σ 中获取动作,在游戏中执行,观察奖励 r(t+1)和下一个状态 s(t+1)以及 Mrl 中的转移[s(t),a(t),r(t+1),s(t+1)]。
  • 如果σ是ε-greedy(Q),则存储[s(t),a(t)]在 Msl 中。
  • 用 Msl 训练π(s,a |θ(π))
  • 使用 Mrl 来训练 Q(s,a | θ(Q))
  • 定期更新目标网络权重θ(Q') ← θ(Q)

具体算法如下:

结论

Heinrich & Silver 认为,NFSP 是第一个端到端的深度强化学习方法,它从自我博弈中逼近不完全信息博弈的纳什均衡。NFSP 是可扩展的,不需要预先的领域知识。他们表明,在一个小型扑克游戏中,NFSP 可靠地收敛到近似纳什均衡,而 DQN 的贪婪和平均策略没有。NFSP 从零开始学习了一种策略,这种策略可以在现实世界规模的不完全信息游戏中与超人程序竞争,而无需使用明确的先验知识。

参考

Heinrich & Silver 的《不完全信息博弈中自我博弈的深度强化学习》。

“一般进化游戏中的预期学习”格达尔·阿尔斯兰和杰夫·s·莎玛

完美信息”——维基百科

油藏取样——维基百科

神经背包

原文:https://towardsdatascience.com/neural-knapsack-8edd737bdc15?source=collection_archive---------8-----------------------

用神经网络求解背包问题

在数据科学的某些情况下,需要对模型的输出运行特定的算法来获得结果。有时,它就像找到最大输出的索引一样简单,而其他时候,则需要更高级的算法。您可以在运行推理后运行算法。然而,设计一个可以在内部运行算法的模型有一些好处。使用神经网络解决背包问题不仅有助于模型在内部运行背包算法,而且允许模型被端到端地训练。

什么是背包问题?

我可爱的计算机算法老师用这个故事给我解释了背包问题。想象一个小偷在抢劫。有一些物品可供抢劫。每个项目都有自己的重量和价值。小偷有一个容量确定的背包,该背包指示他(或她)能够携带的最大重量。小偷的利润是通过对所选物品的价值求和来计算的。我们的目标是最大化利润,同时保持所选物品的重量总和小于背包的容量。

维基百科:

给定一组项目,每个项目都有一个重量和一个值,确定集合中要包含的每个项目的数量,使总重量小于或等于给定的限制,并且总值尽可能大。它的名字来源于一个人面临的问题,他被一个固定大小的背包所束缚,必须在里面装满最有价值的物品”

在本文中,我们尝试使用神经网络来解决背包问题。

数据

第一步是准备数据。我们使用随机整数来表示物品的重量、价格和背包的容量。创建问题后,我们使用蛮力来寻找最优解。

一个生成背包问题;

Weights:  [13, 10, 13, 7, 2]
Prices:   [8, 7, 9, 6, 4]
Capacity: 27
Optimum solution: [0, 1, 1, 0, 1]

标准化输入是每个机器学习项目的一部分,因为它有助于模型更好地概括。为了标准化每个背包问题:

  • 将价格除以问题的最高价格。
  • 用重量除以容量。
  • 从输入中删除容量,因为它现在包含在权重中。

先前创建的背包问题的规范化形式:

Weights:  [0.48, 0.37, 0.48, 0.26, 0.07]
Prices:   [0.89, 0.44, 1.00, 0.67, 0.44]
Optimum solution: [0, 1, 1, 0, 1]

数据集由一万个用于训练的样本和两百个用于测试的样本组成。

模型

我们为此任务选择的模型是一个相当简单的模型。它有两个输入和一个输出。首先,输入被连接在一起。结果进入由 sigmoid 非线性激活的两个连续的密集层。第二密集层的输出是模型的输出。在 Keras 中实施该模型:

下图显示了模型的体系结构:

Model architecture

衡量标准

背包问题需要除二进制分类精度之外的度量来进行评估。我们引入的第一个指标叫做“定价过高”。顾名思义,它评估所选项目的价格和最优解之间的平均差异。它在 Keras 框架中实现如下:

另一个重要的指标是使用的容量超过背包的容量。“空间违规是所选物品重量之和与背包容量之间的正差值。它可以在 Keras 中实现如下:

监督方法

在监督方法中,我们将权重和价格输入到模型中,并期望最优解作为输出。在此过程中,模型使用交叉熵损失函数进行训练。

在使用监督方法训练模型之后,我们在 512 个时期之后获得了以下结果。

Model results(Train/Test):
Loss:               0.24 / 0.24
Binary accuracy:    0.89 / 0.89
Space violation:    0.04 / 0.06
Overpricing:        0.06 / 0.08

不幸的是,有监督的方法有两个基本问题:

  • 最佳解决方案是强制开始训练。
  • 我们对空间违规定价过高没有任何控制。

我们将尝试在无监督的方法中解决这些问题。

无监督方法

我们希望在不计算最优解的情况下训练模型。因此,我们需要一个新的损失函数。相应地,我们随后将 wpco 定义为物品的重量,物品的价格,背包的容量和模型的产量。首先,我们需要最大化所选商品的价格总和。它可以通过以下方式计算:

同时,我们希望我们的选择不超过背包的容量。该值可以通过以下公式表示:

最后,我们要最大化 总价 同时最小化 空间违例 。这可以通过以下方式制定:

为了控制 空间违逆 ,我们在第二项中加入了 λ 系数。最终损失公式为:

我们可以像这样在 Keras 中实现新的损失:

使用这个损失函数,我们以无监督的方式训练神经网络。

注 1: 背包损耗的 Keras 实现中 λ 参数命名为 cvc

注 2: 虽然我们收到了最优解(y_true)作为函数自变量,但我们并不使用它来计算损失。我们也不能省略参数,因为在损失函数中接收预测和预期输出是一个 Keras 约束。

注 3: 当我们归一化数据时,背包的容量等于 1。

在用非监督方法训练模型之后,我们在 512 个时期之后得到以下结果。

Model results(Train/Test):
Loss:               -1.83 / -1.75
Binary accuracy:    0.89 / 0.89
Space violation:    0.05 / 0.06
Overpricing:        0.12 / 0.14

增加CVC(λ)的值会在更少的空间内造成违规和套印。增加太多也会降低二进制精度。我发现它的合理值可能是 5.75。

结论

如前所述,我们使用神经网络解决了背包问题,而梯度可以通过网络。因此,我们的模型可以使用反向传播算法的任何变体进行端到端的训练。

这篇文章可以用在推荐系统中,特别是那些在保持空间使用率的同时推荐多个项目的系统(比如横幅广告)。

神经机器翻译

原文:https://towardsdatascience.com/neural-machine-translation-15ecf6b0b?source=collection_archive---------2-----------------------

注意使用编码器解码器结构的神经机器翻译指南。包括在 Google Colaboratory 中使用 PyTorch 的详细教程。

Image from pixabay.com

机器翻译(MT)是计算语言学的一个分支,致力于将文本从一种语言翻译成另一种语言。随着深度学习的力量,神经机器翻译(NMT)已经成为执行这项任务的最强大的算法。虽然谷歌翻译是 NMT 领先的行业范例,但全球的科技公司都在向 NMT 进军。这种最先进的算法是深度学习的一种应用,其中翻译句子的大规模数据集用于训练一个能够在任何两种语言之间翻译的模型。随着近年来的大量研究,目前行业中正在研究和部署多种 NMT。编码器解码器结构是 NMT 的一个较老且较成熟的版本。这种体系结构由两个递归神经网络(RNNs)组成,这两个网络一前一后用于创建翻译模型。当与注意力机制的力量相结合时,这种架构可以取得令人印象深刻的结果。

这篇文章分为两个不同的部分。第一部分包括 NMT 和编码器解码器结构的简要说明。接下来,本文的后半部分提供了一个教程,让您有机会自己创建一个这样的结构。这段代码教程很大程度上基于关于 NMT 的 PyTorch 教程,并做了一些改进。最值得注意的是,这个代码教程可以在 GPU 上运行,以获得明显更好的结果。

在我们开始之前,假设如果你正在阅读这篇文章,你至少对神经网络和深度学习有一个大致的了解;特别是前向传播、损失函数和反向传播的概念,以及训练和测试集的重要性。

如果你有兴趣直接跳到代码,你可以在我的 GitHub 页面上找到本文概述的 Google Colab 教程的完整 Jupyter 笔记本(或者 Python 脚本)用于这个项目

NMT 及编解码结构简述

任何 NMT 模型的最终目标都是将一种语言的句子作为输入,并将翻译成不同语言的句子作为输出返回。下图是一个翻译算法(比如 Google Translate)的简单表示,它的任务是将英语翻译成西班牙语。

Figure 1: Translation from English to Spanish of the English sentence “the cat likes to eat pizza”

在深入研究上图中经常用作算法的编码器/解码器结构之前,我们首先必须了解如何克服任何机器翻译任务中的一大障碍。也就是说,我们需要一种方法来将句子转换成可以输入到机器学习模型中的数据格式。本质上,我们必须以某种方式将文本数据转换成数字形式。

为了在机器翻译中做到这一点,每个单词都被转换成一个热编码向量,然后该向量可以被输入到模型中。一个热点编码向量是除了在对应于特定单词的单个索引处为 1 之外,在每个索引处为 0 的简单向量。这样,每个单词都有一个不同的热编码向量,因此我们可以用数字表示来表示数据集中的每个单词。

创建这些向量的第一步是为输入语言中的每个唯一单词分配一个索引,然后对输出语言重复这个过程。在为每个独特的单词分配一个独特的索引时,我们将为每种语言创建一个词汇表。理想情况下,每种语言的词汇表应该简单地包含该语言中的每个独特的单词。然而,鉴于任何一种语言都可能有几十万个单词,因此词汇表通常会被删减为我们正在处理的数据集中最常见的 N 个单词(其中 N 是任意选择的,但根据数据集的大小,范围通常在 1,000 到 100,000 之间)。

为了理解我们如何使用词汇表为数据集中的每个单词创建一个热编码向量,考虑一个只包含下面表 1 中的单词的小型词汇表。

Table 1: Mini-vocabulary for the English language

给定这个表,我们给小词汇表中的每个单词分配了一个惟一的索引 0-12。表中的标记被添加到每个词汇中,分别代表句子的开始和结束。它们被 NMT 模型用来帮助识别句子中的关键点。

现在,假设我们想要将句子“蓝鲸吃了红鱼”中的单词转换成它们的一个热编码向量。使用表 1,我们将这样做,如下图 2 所示。

Figure 2: One Hot Encoding vectors for the sentence “the blue whale ate the red fish”

正如您在上面看到的,每个单词都变成了一个长度为 13 的向量(这是我们的词汇量的大小),并且除了表 1 中分配给该单词的索引处的 1 之外,全部由 0 组成。

通过为输入和输出语言创建词汇表,我们可以在每种语言的每个句子上执行这种技术,以将任何翻译句子的语料库完全转换成适合机器翻译任务的格式。

现在,了解了我们如何用数字的方式表示文本数据,让我们看看这个编码器/解码器算法背后的魔力。在最基本的层面上,模型的编码器部分获取输入语言中的一个句子,并根据这个句子创建一个思维向量。这个思维向量存储了句子的意思,并随后被传递给解码器,该解码器以输出语言输出句子的翻译。这个过程如下图所示。

Figure 3: Encoder Decoder structure translating the English sentence “the cat likes to eat pizza” to the Spanish sentence “el gato le gusta comer pizza”

在上述架构中,编码器和解码器都是递归神经网络(RNN)。在这个特别的教程中,我们将使用长短期记忆(LSTM)模型,这是一种 RNN。然而,其他 RNN 架构,如 GRU,也经常使用。在基本层面上,rnn 是专门设计来处理时间/文本数据的神经网络。这篇文章将给出 RNNs 如何在 NMT 环境中工作的高级概述,但是,如果您还不熟悉它们,我强烈建议您进一步研究这些概念。关于 RNNs 和 lstm 的更全面的解释,请参见这里的,关于 lstm 在语言翻译方面的更深入的文章,请参见这里的

在编码器的情况下,输入句子中的每个单词在多个连续的时间步骤中被分别输入到模型中。在每个时间步 t ,模型使用来自在该时间步输入到模型的单词的信息更新隐藏向量 h ,。这个隐藏向量用于存储关于输入句子的信息。以这种方式,由于在时间步 t= 0 还没有字被输入到编码器,编码器中的隐藏状态在该时间步作为空向量开始。我们用图 4 中的蓝框表示这种隐藏状态,其中下标 t =0 表示时间步长,上标 E 对应于编码器的隐藏状态(而不是解码器的 D)。

Figure 4: Encoder hidden vector at t=0

在每个时间步长,这个隐藏向量从该时间步长的输入单词中获取信息,同时保留它已经从先前的时间步长中存储的信息。因此,在最后的时间步,整个输入句子的含义被存储在隐藏向量中。这个在最后一个时间步长的隐藏向量就是上面提到的思想向量,然后输入到解码器中。对英语句子“猫喜欢吃比萨饼”进行编码的过程如图 5 所示。

Figure 5: Encoding of the sentence “the cat likes to eat pizza”

在上图中,蓝色箭头对应于权重矩阵,我们将努力通过训练来增强权重矩阵,以实现更准确的翻译。

此外,请注意编码器的最终隐藏状态如何成为思想向量,并在 t =0 处用上标 D 重新标记。这是因为编码器的这个最终隐藏向量变成了解码器的初始隐藏向量。通过这种方式,我们将句子的编码含义传递给解码器,由解码器翻译成输出语言的句子。然而,与编码器不同的是,我们需要解码器输出一个长度可变的翻译句子。因此,我们将让我们的解码器在每个时间步输出一个预测字,直到我们输出一个完整的句子。

为了开始这个翻译,我们将输入一个标签作为解码器中第一个时间步长的输入。就像在编码器中一样,解码器将在时间步长 t =1 时使用输入来更新其隐藏状态。然而,解码器将使用额外的权重矩阵来创建输出词汇表中所有单词的概率,而不是仅仅前进到下一个时间步。这样,输出词汇中概率最高的单词就会成为预测输出句子中的第一个单词。解码器的第一步,从“猫喜欢吃比萨饼”翻译成“el gato le gusta comer pizza ”,如图 6 所示。为了简单起见,输出词汇表仅限于输出句子中的单词(但实际上是由整个输出词汇表中的数千个单词组成)。

Figure 6: First step of the Decoder

现在,假设单词“el”被赋予最高的概率,这个单词成为我们输出的预测句子中的第一个单词。我们继续使用“el”作为下一个时间步的输入,如下图 7 所示。

Figure 7: Second step of the Decoder

我们以这种方式处理整个句子,直到遇到如图 8 所示的错误。

Figure 8: Translation error in Decoder

正如你所看到的,解码器预测“pizza”是翻译句子中的下一个单词,而实际上它应该是“comer”。当在测试集上测试模型时,我们不会做任何事情来纠正这个错误,并且会允许解码器使用这个不正确的预测作为下一时间步的输入。然而,在训练过程中,我们将保留“pizza”作为句子中该点的预测单词,但强制我们的解码器输入正确的单词“comer”作为下一时间步的输入。这是一种被称为教师强制的策略,有助于加快培训过程。如下图所示。

Figure 9: Teacher-forcing

现在,由于解码器必须输出可变长度的预测句子,解码器将继续以这种方式预测单词,直到它预测句子中的下一个单词是标签。一旦预测了这个标签,解码过程就完成了,我们剩下的是输入句子的完整预测翻译。对输入句子“猫喜欢吃比萨饼”的思想向量进行解码的整个过程如图 10 所示。

Figure 10: Decoding of the sentence “the cat likes to eat pizza”

然后,我们可以将预测翻译的准确性与输入句子的实际翻译进行比较,以计算损失。虽然有几种损失函数,但最常用的是交叉熵损失。该损失函数的公式详见图 11。

Figure 11: Cross-Entropy Loss function

本质上,这个损失函数所做的是对模型在输出句子的每个位置给予正确单词的负对数可能性求和。假设负对数函数在输入为 1 时的值为 0,并且随着输入接近 0 而呈指数增加(如图 12 所示),则模型在句子中的每个点给出正确单词的概率越接近 100%,损失就越低。

Figure 12: Graph of the function y = -log(x)

例如,假设上面输出句子中正确的第一个单词是“el”,并且我们的模型在该位置给出了单词“el”相当高的概率,则该位置的损失将相当低。相反,由于在时间步长 t =5 的正确单词是“comer”,但是我们的模型给单词“comer”的概率相当低,所以在该步骤的损失会相对较高。

通过对输出句子中每个单词的损失求和,获得句子的总损失。该损失对应于翻译的准确性,较低的损失值对应于较好的翻译。训练时,将一批中几个句子的损失值加在一起,得到总的一批损失。然后,该批量丢失将用于执行小批量梯度下降,以更新解码器和编码器中的所有权重矩阵。这些更新修改了权重矩阵,以略微提高模型翻译的准确性。因此,通过反复执行这个过程,我们最终构建了能够创建高质量翻译的权重矩阵。

如果您不熟悉批量和/或小批量梯度下降的概念,您可以在这里 找到这些概念的简短解释

正如在引言中提到的,注意机制是一个不可思议的工具,它极大地增强了 NMT 模型创建准确翻译的能力。虽然有许多不同类型的注意力机制,其中一些你可以在这里阅读,本教程中建立的模型使用了一个相当简单的全局注意力实现。在这种注意力方法中,在每个时间步,解码器“回顾”编码器的所有隐藏向量,以创建记忆向量。然后,它使用这个记忆向量,连同解码器中的隐藏向量,来预测翻译句子中的下一个单词。在这样做的时候,解码器利用了来自编码器的有价值的信息,否则这些信息会被浪费掉。这个过程的可视化表示如图 13 所示。我建议阅读本段中的链接文章,以了解更多关于计算内存向量的各种方法,从而更好地理解这一重要概念。

Figure 13: Attention mechanism for time-step t=1 in Decoder

注意:注意力机制非常强大,最近有人提出(并证明)当单独使用时(即没有任何 RNN 架构)会更有效。如果你对《NMT》感兴趣,我建议你去看看《变形金刚》,尤其是读读《》这篇文章。

编码教程(Python)

在开始本教程之前,我想重申一下,本教程主要来自 PyTorch 教程“序列到序列网络的翻译和注意”。然而,本教程在许多方面都进行了优化。最值得注意的是,该代码允许将数据分成批次(从而允许我们利用 GPU 的增强并行计算能力),可以将数据集分成训练集和测试集,并且还添加了在各种格式的数据集上运行的功能。

在我们深入学习代码教程之前,先做一点设置。如果你想在 GPU 上运行模型(强烈推荐),本教程将使用 Google Colab 提供免费使用具有 GPU 功能的 Jupyter 笔记本电脑的机会。如果你有其他方法来使用 GPU,那么也可以随意使用。否则,你可以看看其他各种免费的在线 GPU 选项。代码可以在 CPU 上运行,但是任何模型的能力都会受到计算能力的限制(如果您选择这样做,请确保将 batch-size 改为 1)。

要开始,导航到谷歌联合实验室并登录谷歌账户开始。从这里,导航到文件> New Python 3 Notebook 来启动 Jupyter 笔记本。打开新笔记本后,我们首先需要启用 GPU 功能。为此,导航至页面左上角,选择编辑>笔记本设置。从这里,在“硬件加速器”下的下拉菜单中选择 GPU

Figure 14: Enabling GPU capabilities on Google Colab

我们现在有了一个具有 GPU 功能的 Jupyter 笔记本,可以开始创建一个 NMT 模型了!首先,我们将导入所有必需的包。

现在,运行下面的代码来检查是否启用了 GPU 功能。

如果返回 TRUE,则 GPU 可用。现在,在我们开始做任何翻译之前,我们首先需要创建一些准备数据的函数。以下函数用于清理数据,并允许我们删除过长的句子或输入句子不是以特定单词开头的句子。

现在,使用将清理数据的函数,我们需要一种方法来将清理后的文本数据转换为一个热编码向量。首先,我们创建一个 Lang 类,它将允许我们为输入和输出语言构建一个词汇表。

接下来,我们创建一个 prepareLangs 函数,它将获取翻译句子的数据集,并为数据集的输入和输出语言创建 Lang 类。

这个函数能够处理包含在两个独立文件或一个文件中的输入和输出句子。如果句子在两个单独的文件中,每个句子必须用换行符隔开,并且文件中的每一行必须相互对应(即组成一个句子对)。例如,如果您的输入文件是 english.txt,输出文件是 espanol.txt,那么这些文件的格式应该如图 15 所示。

Figure 15: Format for dataset stored in two separate files.

另一方面,如果输入和输出句子存储在一个文件中,句子对中的每个句子必须用制表符分隔,每个句子对必须用换行符分隔。例如,如果您的单个文件名是 data.txt,那么该文件的格式应该如图 16 所示。

Figure 16: Format for dataset stored in one single file.

注意:为了使这个函数同时处理一个和两个文件,file_path 参数必须是元组格式,如果数据存储在两个文件中,则元组中有两个元素,如果数据存储在单个文件中,则元组中有一个元素。

使用一个为输入和输出语言准备语言词汇表的函数,我们可以使用上述所有函数来创建一个函数,该函数将获取输入和目标句子的数据集,并完成所有预处理步骤。因此, prepareData 函数将为每种语言创建 Lang 类,并根据指定的传递参数完全清理和修整数据。最后,这个函数将返回两个语言类,以及一组训练对和一组测试对。

虽然我们已经为每种语言创建了一个词汇表,但是我们仍然需要创建一些函数来使用这些词汇表将句子对转换成它们的 Hot 编码向量表示,或者将它们转换成它们的 Hot 编码向量表示。

NMT 与正常的机器学习没有什么不同,因为小批量梯度下降是训练模型最有效的方式。因此,在我们开始构建我们的模型之前,我们想要创建一个函数来 batchify 我们的句子对,以便我们可以对小批量执行梯度下降。我们还创建了函数 pad_batch 来批量处理变长句子的问题。这个函数本质上是将< EOS >标签附加到每个较短句子的末尾,直到批中的每个句子长度相同。

至此,我们已经创建了所有必要的函数来预处理数据,并最终准备好构建我们的编码器解码器模型!对编码器/解码器架构和注意力机制有了大致的了解后,让我们深入研究创建这些框架的 Python 代码。我不会解释编码器和解码器的每个方面,而是简单地提供代码,如果您对代码的各个方面有任何问题,请参考 PyTorch 文档

现在,为了训练和测试模型,我们将使用以下函数。下面的 train_batch 函数对单个训练批次执行一次训练循环。这包括完成通过模型的正向传递以创建该批中每个句子的预测翻译,计算该批的总损失,然后对该损失进行反向传播以更新编码器和解码器中的所有权重矩阵。

train 函数只是对批次列表中的每个批次重复执行 train_batch 函数。这样,我们可以传递所有训练批次的列表,以通过训练数据完成一个完整的时期。

以下 test_batchtest 功能与 train_batchtrain 功能基本相同,除了这些测试功能是对测试数据执行的,不包括反向传播步骤。因此,这些函数不更新模型中的权重矩阵,并且仅用于评估训练数据的损失(即,准确性)。反过来,这将帮助我们跟踪模型在训练集之外的数据上的表现。

在培训期间,能够以更定性的方式跟踪我们的进展也很好。 evaluate 函数将允许我们通过返回我们的模型对给定输入句子做出的预测翻译来这样做。并且evaluate _ random函数将简单地预测从测试集(如果我们有)或训练集中随机选择的指定数量的句子的翻译。

下面的几个助手函数将绘制我们的训练进度,打印内存消耗,并重新格式化时间测量。

最后,我们可以将所有这些函数放入一个主函数中,我们称之为 train_and_test 。该函数将采用相当多的参数,但是将完全训练我们的模型,同时以指定的间隔评估我们在训练集(和测试集,如果存在的话)上的进展。此外,一些参数将指定我们是否希望将输出保存在一个单独的。txt 文件,创建一个损失值随时间变化的图表,并允许我们保存编码器和解码器的权重以供将来使用。此函数后面的几个单元格将概述如何修改每个参数,但要知道,为了训练模型,我们基本上只需要运行此函数。

现在一切就绪,我们准备导入数据集,初始化所有的超参数,并开始训练!

首先,为了上传数据集,运行以下单元格:

您将看到以下内容:

Figure 17: Upload data to Google Colab

只需点击“选择文件”按钮,并导航到您希望上传的数据集。在本教程中,我们使用的数据集与原始 PyTorch 教程中使用的数据集相同。你可以在这里下载英法翻译数据集。你也可以用各种语言的其他数据集进行实验这里

如果你想获得更多最新的结果,我建议你尝试在更大的数据集上训练。您可以在这里找到一些更大的数据集,但也可以随意使用任何翻译摘录的语料库,只要它们的格式类似于上面的图 15 或图 16。

注意:使用本教程中介绍的上传方法上传大型数据集到 Google Colab 可能会有问题。如果你遇到这样的问题,阅读 这篇文章 学习如何上传大文件。

现在,运行以下单元格以确保数据集已成功上传。

Figure 18: Run ls to ensure dataset has been uploaded

在这里,编辑以下单元格以应用于您的数据集和需求。

下面的单元格由各种超参数组成,为了找到一个有效的 NMT 模型,您需要使用这些超参数。所以,尽情体验这些吧。

最后,您只需要运行下面的单元,根据上面设置的所有超参数来训练您的模型。

瞧!你刚刚训练了一个 NMT 模特!恭喜你。如果保存了任何图形、输出文件或输出权重,可以通过再次运行 ls 来查看所有保存的文件。要下载这些文件,只需运行下面的代码。

现在,如果你想在训练集和测试集之外的句子上测试这个模型,你也可以这样做。只要确保你要翻译的句子和你的模型的输入语言是同一种语言。

我在 PyTorch 教程中使用的同一个数据集上训练我的模型和 PyTorch 教程模型(这是上面提到的英语到法语翻译的同一个数据集)。为了预处理数据,trim 设置为 10,PyTorch 使用的 eng_prefixes 过滤器设置为 TRUE。有了这些限制,数据集被削减到一个相当小的 10,853 个句子对的集合。PyTorch 教程打破了机器学习的一个基本规则,没有使用测试集(这不是好的实践!).因此,仅仅为了比较,我将所有这些句子对保存在我的训练集中,并且不使用测试集(即 perc_train_set = 1.0)。然而,我建议你在训练任何类型的机器学习模型时总是使用测试集。

表 1 显示了我为我的模型选择的超参数与 PyTorch 教程模型中的超参数的比较。图 19 中的下图描绘了在 NVIDIA GeForce GTX 1080 上训练 40 分钟的结果(有点旧的 GPU,使用 Google Colab 实际上可以获得更好的结果)。

Table 1: Hyperparameters comparison

Figure 19: Loss over 40 minute training period for this tutorial model (My Model) vs PyTorch Tutorial Model

由于这个数据集没有训练集,我用训练集中的几个句子评估了这个模型。

Figure 20: Predicted translation of PyTorch tutorial model (Blue) vs. My Model (Orange)

从这些结果中,我们可以看出,本教程中的模型可以在相同的训练时间内创建更有效的翻译模型。然而,当我们试图使用这个模型翻译训练集之外的句子时,它立即崩溃了。我们可以在模型对数据集之外的以下句子的尝试翻译中看到这一点。

Figure 21: Failed translation on sentence outside the dataset.

该模型的失败很大程度上是因为它是在如此小的数据集上训练的。此外,我们没有意识到这个问题,因为我们没有测试集来检查模型翻译训练集之外的句子的能力。为了解决这个问题,我在相同的数据集上重新训练了我的模型,这次使用了 trim=40,并且没有使用 eng_prefixes 过滤器。即使我留出 10%的句子对作为训练集,测试集的规模仍然是之前用于训练模型的 10 倍以上(122,251 个训练对)。我还将模型的隐藏大小从 440 修改为 1080,并将批量大小从 32 减少到 10。最后,我将初始学习率更改为 0.5,并安装了一个学习率时间表,该时间表在每五个时期后将学习率降低五分之一。

利用这个更大的数据集和更新的超参数,模型在相同的 GPU 上被训练。下面显示了训练和测试集在训练期间的损失,以及上面失败的相同句子的翻译。

Figure 22: Train and Test loss vs. time

Figure 23: Improved (yet still imperfect) translation of sentence outside of the dataset.

大家可以看到,这句话的翻译是有显著提高的。然而,为了实现完美的翻译,我们可能需要进一步增加数据集的大小。

结论

虽然本教程介绍了使用编码器和解码器结构的 NMT,但实现的注意机制相当基础。如果你对创建一个更先进的模型感兴趣,我建议你研究一下局部注意力的概念,并尝试在模型的解码器部分实现这种更高级的注意力。

否则,我希望你喜欢教程,并学到了很多东西!这篇文章所涉及的材料的基础来自我在罗耀拉玛丽蒙特大学的论文。如果你想看看我用来分享这些想法的 PPT 演示文稿(包括本文中的大部分图片),你可以在这里找到。你也可以阅读我写的关于这个主题的论文,它更深入地解释了 NMT 背后的数学,这里是。最后,这个项目的完整 Jupyter 笔记本可以在这里找到,或者 Python 脚本版本可以在这里找到。

神经网络

原文:https://towardsdatascience.com/neural-network-74f53424ba82?source=collection_archive---------9-----------------------

更简单直观的解释。

神经网络是用于学习复杂的复杂学习算法,通常是非线性机器学习模型。

A note on the notation. x_{i} means x subscript i and x_{^th} means x superscript th.

线性回归快速回顾

  • 线性回归用于预测+∞和-∞之间任何地方的实值输出。
  • 用于训练线性回归模型的每个示例由其属性或特征定义,这些属性或特征统称为特征向量。你的名字、年龄、联系电话、性别等等对应于描述你的特征向量。
  • 一个线性回归模型 f(x)是输入实例 x 的特征的线性组合,用 f(x) = wx+b 表示。
  • 通过平方或立方来变换原始特征(考虑一维特征向量 x )会产生多项式模型(例如 f(x) = wx +bf(x) = wx +b )。
  • 通常对于具有 R 维特征向量 x 和一维输出 y 的数据集,线性回归建模一个超平面作为决策边界。超平面在 2D 区域的情况下是一条线,在 3D 空间的情况下是一个平面,在 4D 空间的情况下是一个三维形状,例如一个球体,等等。超平面比它们周围的空间少了一个维度。
  • 均方误差成本函数用于找到线性回归模型的最佳值组 w* 和 b* 。

逻辑回归快速回顾

  • 逻辑回归是一种分类算法。给定一个输入示例,逻辑回归模型将该示例分配给相关的类。
  • 使用 sigmoid 函数在 0 和 1 之间处理从线性回归模型获得的实值输出,以获得逻辑回归模型。然后基于阈值对新的示例进行分类。
  • 一个逻辑回归模型表示为f(x)= 1/(1+exp(-(wx+b))),其中 exp 为指数函数。
  • 对数似然函数成本函数用于查找逻辑回归模型的最佳值组 w* 和 b* 。
  • 就像线性回归一样,我们可以将特征转换为包含二次或三次项的更高阶,以使非线性决策边界适合我们的数据集。

构建模块——神经元

让我们来看看神经网络的构建模块。

Elementary unit of a neural network: A neuron

基本单元中发生的操作可以用下面的等式来表示—

Output from a single neuron.

让我们看看这个等式的各个组成部分,以及随之而来的神经元

  • x_{i},i ∈ {1,2,…,n} 对应于馈入神经网络的输入特征向量,
  • b 是偏置项,
  • 对于每个输入特征 x_{i} ,都有一个对应的权重 w_{i},,这表示对应的输入 x_{i} 对输出的影响有多强。例如,考虑一个例子,在给定一个面的面积和立方体的颜色的情况下,计算立方体的总表面积。因为一个立方体有六个面,所以我们用一个面的面积乘以 6 来得到立方体的总表面积。然而,立方体的颜色对它的总表面积没有影响,所以我们把它乘以 0。这里 6 和 0 表示对应于输入特征的权重,一个面的面积和立方体的颜色。权重值越高,表示该要素对输出的影响越大。**

The idea behind weights.

  • 请注意,神经元的输入是特征向量和附加偏差的线性组合。最后,该线性组合通过被称为激活函数的函数 f(x)

激活功能

在继续之前,让我们简单讨论一下激活函数。给定一个数据集,目标是找到适合我们数据集的最佳模型,或者我们可以说,在数据集的输入和输出之间逼近一个数学函数。事实证明,由于激活函数的存在,神经网络在逼近这些数学函数方面非常出色。就一会儿,想象一个没有任何激活函数的神经网络——它将只是一些线性回归模型。

像 sigmoid 这样的激活函数负责非线性转换,从而使神经网络能够学习复杂的假设。

在上面的等式中,如果你用 sigmoid 函数替换函数 f ,你将得到一个逻辑单元。常用的激活函数有 Sigmoid、ReLU 和 Tanh。

Activation functions : Left-to-Right: Rectified Linear Unit (ReLU), the Sigmoid function and the Tanh function.

神经网络

体系结构

神经网络基本上由三层组成——

  • 输入层:它是一个被动层,也就是说它不执行任何计算,而是将其输入传播到后续层进行进一步处理。
  • 隐藏层:这是实际计算发生的层。每个圆圈代表一个神经元。每个神经元接收来自前一层的输入,进行所需的计算,并将结果传播到下一层。在单个隐藏层的情况下,隐藏层从输入层接收输入,并将输出传播到输出层。然而,在多个隐藏层的情况下,一个隐藏层可以从前一个隐藏层接收其输入,并且可以将其输出传递给下一个隐藏层。
  • 输出层:这是最后一层,给出我们想要的输出。在回归问题的输出层中有一个神经元,然而在分类问题的情况下存在多个神经元。
  • 箭头:箭头代表神经网络的参数,称为权重。学习算法的工作是找到一组好的参数,以便神经网络能够很好地泛化。

培养

让我们为某个任意问题假设以下神经网络架构—

Neural Network Architecture

很明显,神经网络主要是由它的权重定义的。一旦找到最佳的权重集,网络就可以进行预测了。

训练过程从随机初始化权重开始,通常在 0 和 1 之间。随机初始化设施对称破坏。考虑一个例子,其中 w_{1 }、 w_{2 }、 w_{3 }和 w_{4 }被初始化为相同的权重值。这将导致 h_{1}h_{2} 产生相同的输出,从而通过引入冗余来降低隐藏层中存在的神经元的可用性。

初始化权重后,接下来的步骤是将输入馈送到神经网络,并获得一些输出y’。这个步骤被称为正向传播

显然,使用第一次向前传递获得的输出不是最准确的。诸如均方误差的误差函数可用于获取网络的成本。我们的目标是轻推神经网络的权重,以最小化这种误差。如果我们知道误差相对于权重如何变化,我们可以相应地更新权重以最小化误差。这就是反向传播方法派上用场的地方。它使用梯度下降,并决定网络的每个权重应该改变多少。

为简化起见,考虑以下函数—

上述函数对 x 的偏导数为 3 ,对 y 的偏导数为 1 。解释该结果的一种方式是,如果我们将 y 的值增加一个因子 k ,那么函数 f(x,y) 的值也会增加与∂ f(x,y)/y = 1 相同的因子 k ,同样,如果我们将 x 的值减少一个因子 k`【也是如此因此,我们可以说一个函数对其变量的导数决定了该函数对该变量的敏感度。本质上,在神经网络的情况下,变量是网络的权重,并且 f(x,y) 对应于神经网络模型。

导数的这一特性有助于我们确定为了使误差最小化并从网络中获得所需的输出,可能需要轻推一个权重的量。

反向传播因以下事实而得名:首先计算输出层的误差,然后通过隐藏层反向传播,在此过程中计算导数。

*A detailed explanation of back-propagation is beyond the scope of this discussion as it can be overwhelming. However the following resource can be useful.*

*[## 反向传播演示

反向传播算法对于快速训练大型神经网络至关重要。这篇文章解释了如何…

google-developers.appspot.com](https://google-developers.appspot.com/machine-learning/crash-course/backprop-scroll/)*

对于分类问题

神经网络也可以用于分类问题。考虑将电子邮件标记为垃圾邮件或非垃圾邮件的二元分类的经典示例。为了使用神经网络来解决这个问题,输出类别被转换成二维向量,其中,如果电子邮件是垃圾邮件,则设置第一维度,如果电子邮件不是垃圾邮件,则设置第二维度。最后,输出的这种变换形式与输入特征向量一起用于训练神经网络。在 n-class 分类的情况下,每个输出被转换成一个 n 维向量,其中如果实例属于相应的类,则设置一个维。

Transformed output variable in case of a spam email.

Architecture of neural network as a classifier.

输出单元 y_{1} 预测电子邮件是垃圾邮件的可能性,而 y_{2} 预测电子邮件不是垃圾邮件的可能性。根据取较高值的输出单位对电子邮件进行分类。

为什么是新算法?

你一定已经学会了线性回归和逻辑回归,那么我们为什么需要训练一个神经网络呢?事实证明,神经网络非常擅长逼近非线性函数。

在我们对线性回归和逻辑回归的回顾中,我们讨论了包含更高次项来近似非线性假设,但是这样做并不能保证更好的假设。此外,假设将取决于我们对高次项的选择。考虑这样一种情况,我们有 10 个参数(比如 a,b,c,…,j),我们决定包括所有平方项,这样做将创建 55 个参数(10+9+8+…+1)。此外,过度拟合的可能性也更高。

神经网络解决了这个问题。观察神经网络的隐含层,隐含层的输入不是简单的原始输入 x_{1}x_{2} ,而是权重,将隐含层的输入转换为原始输入的某个函数。好像神经网络试图找到输入的最佳可能转换,从而解决我们选择更高次项的问题。包括更多的隐藏层允许网络学习甚至更复杂的特征。然而,对于大多数实际用途,两个隐藏层工作得相当好。

神经网络算法—了解如何训练人工神经网络

原文:https://towardsdatascience.com/neural-network-algorithms-learn-how-to-train-ann-736dab9e6299?source=collection_archive---------10-----------------------

Neural Network Algorithms — Learn How To Train ANN

顶级神经网络算法

神经网络的学习是基于被研究群体的样本进行的。在学习过程中,将输出装置输出的值与实际值进行比较。之后,调整所有单元的权重,以改善预测。

有许多神经网络算法可用于训练人工神经网络。现在让我们来看看训练神经网络的一些重要算法:

  • 梯度下降-用于查找函数的局部最小值。
  • 进化算法——基于生物学中自然选择或适者生存的概念。
  • 遗传算法——为问题的解决启用最合适的规则,并选择它。所以,他们把他们的‘遗传物质’送给‘孩子’规则。我们将在下面详细了解它们。

获取神经网络学习规则介绍了解更多神经网络算法。

梯度下降

我们使用梯度下降算法来寻找函数的局部最小值。神经网络算法收敛到局部最小值。与函数梯度的负值成正比。为了找到局部最大值,采取与函数的正梯度成比例的步骤。这是一个梯度上升的过程。

在线性模型中,误差曲面是定义明确且众所周知的抛物线形状的数学对象。然后通过计算找到最小点。与线性模型不同,神经网络是复杂的非线性模型。在这里,误差表面具有不规则的布局,丘陵、山谷、高原和深谷纵横交错。为了找到这个表面上的最后一个点,没有可用的地图,用户必须探索它。

在这种神经网络算法中,沿着斜率最大的线在误差面上移动。它还提供了达到最低点的可能性。然后你必须计算出你应该以什么样的最佳速度下坡。

正确的速度与表面的斜率和学习率成正比。学习速率控制学习过程中权重的修改程度。

因此,神经网络的矩会影响多层感知器的性能。

进化算法

这种算法基于生物学中自然选择或适者生存的概念。自然选择的概念表明,对于一个给定的种群来说,环境条件使用了一种压力,这种压力导致该种群中最适者的上升。

要测量给定群体中的适者,您可以应用一个函数作为抽象的度量。

在进化算法的上下文中,将重组称为操作符。然后将它应用于两个或更多的候选项(称为父项),并产生一个或多个新的候选项(称为子项)。对单个候选项应用变异,并产生新的候选项。通过应用重组和变异,我们可以得到一组新的候选者,并根据它们的最适度量值将其放入下一代。

神经网络中进化算法的两个基本要素是:

  • 变异算子(重组和变异)
  • 选择过程(优胜劣汰)

进化算法的共同特征是:

  • 进化算法是基于种群的。
  • 进化算法使用群体的重组混合候选者,并创建新的候选者。
  • 基于随机选择进化算法的研究。

因此,在细节和应用问题的基础上,我们使用各种形式的进化算法。
一些常见的进化算法有:

  • 遗传算法遗传算法——它为优化问题提供解决方案。它在自然进化过程的帮助下提供了解决方案。比如突变、重组、交叉和遗传。
  • 遗传编程——遗传编程以计算机程序的形式提供了一种解决方案。由解决计算问题的能力来衡量程序的准确性。
  • 进化编程——在模拟环境中开发我们使用的人工智能。
  • 进化策略它是一种优化算法。基于生物科学中适应和进化的概念。
  • 神经进化——为了训练神经网络,我们使用神经进化。通过指定基因组用来开发神经网络的结构和连接权重。

在所有这些神经网络算法中,遗传算法是最常见的进化算法。

遗传算法

遗传算法,由霍兰德的团队在 20 世纪 70 年代早期开发。它能够选择最合适的规则来解决问题。以便它们将它们的“遗传物质”(它们的变量和类别)发送给“子”规则。

这里指的是一组变量的类别。例如,年龄在 36 至 50 岁之间,金融资产不到 2 万美元,月收入超过 2000 美元的客户。

规则相当于决策树的一个分支;它也类似于基因。你可以将基因理解为细胞内控制生物体如何继承其父母特征的单位。因此,遗传算法旨在复制自然选择的机制。通过选择最适合预测的规则,并通过交叉和变异它们,直到获得预测模型。

它们与神经网络一起构成了第二类算法。它模仿自然机制来解释不一定是自然的现象。执行遗传算法的步骤是:

  • 步骤 1:随机生成初始规则——首先生成规则,约束条件是它们必须完全不同。每个规则包含用户选择的随机数量的变量。
  • 步骤 2:最佳规则的选择——通过适应度函数针对目标检查规则,以引导向最佳规则的进化。最佳规则使适应度函数最大化,并且随着规则的改进概率增加而保留。有些规则会消失,而其他规则会选择几次。
  • 第三步:通过变异或交叉生成新规则——首先,转到第二步,直到算法的执行停止。选择的规则被随机变异或交叉。突变是用一个变量或一个类别替换一个原始规则。

两个规则的交叉是它们的一些变量或类别的交换,以产生两个新的规则。杂交比突变更常见。
当满足以下两个条件之一时,神经网络算法结束:

  • 达到的指定迭代次数。
  • 从第 n 代开始,第 n 代、第 n-1 代和第 n-2 代的规则(几乎)相同。

所以,这都是关于神经网络算法的。希望你喜欢我们的解释。

结论

因此,人工神经网络通常难以配置并且训练缓慢,但是一旦准备好,在应用中速度非常快。它们通常被设计成模型来克服数学、计算和工程问题。因为,在数学、神经生物学和计算机科学方面有很多研究。

如果你想分享你的观点,或者对人工神经网络算法有任何疑问,请在评论区提出。

我也推荐你看我以前的文章-

成为数据科学家应该知道的顶级机器学习算法

机器学习中的降维

用于机器学习的人工神经网络—结构&层

用常微分方程重温神经网络反向传播

原文:https://towardsdatascience.com/neural-network-back-propagation-revisited-892f42320d31?source=collection_archive---------30-----------------------

通过使用微分方程的数值解来优化神经网络参数被评论为在反向传播期间收敛到成本函数的全局最小值的替代方法。

Different optimizers at work to find the global minimum of two different functions. The “ODE Solver” optimizer will be the subject of this post. If you focus on the white dot, you can see that the ODE solver reaches the minimum with fewer iterations in the two cases shown here. The animation on the left is the six-hump camel function with a global minimum at (0,0). The animation on the right is the Goldstein-Price function where the global minimum at (0,-1) is only slightly deeper than the many other local minima. The animations have been created by adapting the code by Piotr Skalski. The code to reproduce the animation above can be found here.

这篇文章的重点是介绍一种不同的方法来优化神经网络的参数(又名权重),同时在训练过程中反向传播损失梯度。核心思想是使用常微分方程(ODE)数值解算器来寻找最小化梯度的权重。这个想法是由亚伦·敖文思等人在 1989 年首次提出的。虽然使用数值解算器增加了大量的计算时间,但是这种方法对于相对较小的数据集和/或收敛到稳定解需要额外努力来微调更“标准”优化器的超参数的情况是有意义的。事实上,数值求解器不需要任何超参数来调整。

最近,在神经网络建模中使用 ODE 求解器已经被用来重新设计深度学习可以对健康变化等连续过程进行建模的方式(见此处)。

在介绍了神经网络之后,我将描述如何对反向传播步骤进行更改,以便使用 ODE 解算器和标准优化器在 TensorFlow 中训练神经网络。

神经网络基础。

神经网络是生物启发的数学模型,可以在计算机上编程,以发现和学习观察数据中的复杂关系。关于神经网络背后的数学的详细回顾,读者可以参考迈克尔·尼尔森的在线书籍。节点的输入层和输出层分别表示特征和结果。一个或多个中间层(称为隐藏层)的序列通常用于捕获初始输入特征的越来越复杂的表示。

An example representation of neural network architecture with two input nodes and a single output node created with the VisualizeNN module. Other online tools exist to create publication-ready images (see for example NN-SVG).

利用这种架构进行学习的基本概念是可调权重,其被表示为网络节点之间的连接线。神经网络也被称为多层感知器网络(MLP),因为中间层充当感知器,即传递来自前一层的传入值或阻止它的本地分类器。

神经网络的训练包括两个阶段,前向和反向传播,这两个阶段重复几次,称为时期。在前向传播过程中,输入数据呈现给网络,并通过其各层进行转换。在任何给定的层 l,从前一层𝑙−1 扇出的输入值𝐴使用将层𝑙−1 连接到𝑙的权重( W )和层𝑙的偏置( b )进行线性变换,如下

𝑍是𝑙.图层节点处的值的向量使用如下激活函数将非线性变换应用于𝑍

在反向传播期间,为每一层𝑙.计算成本𝐶相对于网络权重的梯度对于𝑙层来说,

在哪里

知道这些等式就足以使用 numpy 从头开始编写神经网络程序。要查看,可以参考 Piotr Skalski 写的代码,并在他关于介质的文章中查看。

用 sklearn 训练 MLP 网络。

sklearn 中,可以使用任何监督机器学习技术中使用的典型步骤来训练神经网络模型。为了简单起见,我在下面的代码片段中使用了异或(XOR)真值表。

带 ODE 解算器的张量流。

常微分方程(ODE)可以用数值方法求解。事实上,前一节介绍的反向传播方程可以写成

并且是可以用数字求解的颂歌。在大多数情况下,这种 ODE 在数值上是严格的,也就是说,在积分过程中,通过不稳定性收敛到最优解。

刚性常微分方程的解要求积分器的步长非常小,并且可以随时间变化。在 Python 中, ODE 解算器scipy 库中实现。为了使用 ODE 积分器找到最佳权重,我们将变量 t 引入反向传播方程,这对应于改变积分器的步长以达到稳定的数值解。因此,我们将使用下面的等式

本节末尾的笔记本更详细地解释了为了用 ODE 求解器优化张量流神经网络而进行的修改。为此,我们需要在“渴望”模式下运行 TensorFlow,如这里的所示。对于这个练习,我从 MNIST 数据集中提取了两个随机样本,其中一个用于训练,另一个用于验证,即调整网络参数。两个样本都包含 0 到 4 之间的数字的数据,每个数字用 100 个样本来表示。当在 50 次迭代之后没有观察到大于 5%的改进时,停止训练,因为在验证集上有最佳性能。该模型的最终性能是根据数字 0-4 的全部 MNIST 数据(35,000 个样本)计算的,如下所示。

Accuracy of the TensorFlow neural network model on the whole datasets of digits between 0 and 4. (Left) Fewer iterations or presentations of the data to the network are needed to reach optimal performance. (Right) The use of a ODE solver requires significantly greater computation time.

用 ODE 求解器优化神经网络比用标准优化器优化要多花 8 倍的时间。然而,ODE 求解器的精度并不比其他优化器的精度差。

结论。

使用常微分方程(ODE)数值解算器已被视为优化神经网络参数的替代方法。虽然这显著增加了训练神经网络模型的计算时间,但是它不需要任何超参数调整,并且可以成为收敛到成本函数全局最小值而不花费时间微调超参数的替代方式。

基于神经网络的破解大型异或运算的攻击方法

原文:https://towardsdatascience.com/neural-network-based-attack-methods-to-break-the-large-xor-pufs-faebabba1c5a?source=collection_archive---------28-----------------------

XOR-puf 的漏洞向安全应用程序开发人员揭示了有价值的信息,用于决定为了安全风险而避免哪些 puf。

目标

在本文中,我们将讨论对具有五个或更多仲裁器 puf 组件的大型 XOR PUFs 的基于神经网络的攻击的实现。这篇文章展示了基于神经网络的攻击方法如何能够以高精度,在比其他快速机器学习算法少得多的时间内,甚至破解大型 XOR puf(,即处理可能大于存储容量的训练数据集。

我们将使用 keras 预测来自 k -XOR 仲裁器 PUFs 与 n 位挑战输入的最终输出响应。

在直接进入实现之前,让我们先来看一些关键概念,以便更好地理解正在发生的事情。

你说的 PUFs 是什么意思?

PUF(物理不可克隆功能)是一种物理实体,它利用半导体制造过程中自然发生的变化来为半导体器件提供唯一的身份,这使得不同的半导体器件不可克隆并且是唯一的。PUF 有望为资源受限的物联网设备提供高安全性。如今,puf 通常在集成电路中实现,并且通常用于具有高安全性要求的应用中。

Fig : 1

如上图 1 所示,PUF 是一个输入-输出映射,其中输入是 n 位二进制向量(称为挑战),输出是 m 位二进制向量(称为响应)。

为什么我们需要 puf?

在物联网设备中,确保通信安全至关重要。身份认证是保护物联网设备之间通信的方法之一。 经典认证方法 大多依靠密码算法来处理存储在非易失性存储器中的密钥。这些经典的认证技术有其局限性,这促使 puf 出现。让我们讨论一些限制:-

  1. 先前存储在数字非易失性存储器(例如 EEPROM、SRAM)中的密码密钥容易受到不同类型的攻击(例如入侵攻击和旁道攻击)。
  2. 由于这种计算昂贵的加密算法使用非易失性存储器,并且需要更多的制造成本以及更多的功耗等。

因此,puf 被广泛用于认证和密码密钥生成的目的,并且 puf 不是将秘密存储在数字存储器中,而是从集成电路(ic)的物理特性中导出秘密。

让我们现在来理解异或仲裁者 PUF

XOR 仲裁器 puf(也称为 XOR PUFs)由多个仲裁器 puf 构成。首先,我们需要了解仲裁器 PUFs,它测量两条对称路径之间的时间延迟差。如图 2 所示,aribter PUFs 接受输入信号和 n 位挑战,产生单一输出(称为响应)。输入信号根据挑战输入决定其路径,因为它允许输入信号为挑战位的每一位决定每个单独多路复用器中的路径。

Fig-2 : Arbiter PUF circuit.

在图 2 中,仲裁器 PUF 电路为每个输入 X 创建两条具有相同布局长度的延迟路径,并基于哪条路径更快产生输出 Y。

现在在图 3 中,来自 k 仲裁器 puf 的不同响应被一起异或以产生单个和最终响应 r ,其中所有的单个仲裁器 puf 使用相同的 n 位挑战作为挑战输入,这种 k 仲裁器 puf 与 XOR 的组合构成了 k -XOR 仲裁器 puf。

Fig-3 : k-XOR Arbiter PUFs.

理解了与 XOR 仲裁器 puf 相关的所有关键概念后,让我们继续实现。

数据集概述

从 k-XOR 仲裁器 PUFs 模拟中生成了两个数据集:

  1. 5-XOR _ 128 位数据集:该数据集使用 128 位级或 128 位挑战输入的 5-XOR 仲裁器 PUF 生成。它由 6 百万行和 129 个属性组成,其中最后一个属性是类标签或最终响应(1 或-1)。分为两组:训练组(500 万)和测试组(100 万)。
  2. 6-XOR _ 64 位数据集:该数据集使用 6-XOR 仲裁器 puf 生成,具有 64 位级或 64 位挑战输入。它由 240 万行和 65 个属性组成,其中最后一个属性是类标签或最终响应(1 或-1)。分为两组:训练集(200 万)和测试集(400K)。

我们可以用神经网络和不同的机器学习算法来实现这两个数据集。两个数据集都是平衡的或者包含相等比例的类。

我们可以从 这里 访问数据集。

Fig-4 : Balanced Dataset (6-XOR_64bit).

对 k-XOR 仲裁器 PUFs 的神经网络攻击

实施不同的机器学习算法,如逻辑回归(或 LR 与 Rprop)可以揭示 XOR 仲裁器 puf 中的漏洞,如建议的 此处 。但是,在高性能计算服务器上,这可能需要几天的并行计算时间来破解如此大的 XOR PUFs。由于神经网络是监督学习的最强大的方法之一,这就是为什么特别是,我试图实现多层感知器之一,非常有效地打破它,正如在这篇 论文 中所建议的。我们将在 keras 中实现与 论文 中建议的相同的 MLPs 架构和参数,并将观察准确性,即我们在破解 XOR 仲裁 puf 时的准确性。

Fig-5 : List of all parameters of MLPs and their implementation.

代码片段:

一些代码片段有助于您理解使用 keras 来破解具有 n 位挑战输入的 XOR 仲裁器 puf 的 MLPs 的实现。

  1. 对于 5-XOR _ 128 位数据集(仅考虑 100 万):
input_layer = Input(shape = (128,))out1 = Dense(32,activation = 'relu')(input_layer)
out1 = Dropout(0.5)(out1)
out1 = BatchNormalization()(out1)out2 = Dense(32,activation = 'relu')(input_layer)
out2 = Dropout(0.5)(out2)
out2 = BatchNormalization()(out2)out3 = Dense(32,activation = 'relu')(input_layer)
out3 = Dropout(0.5)(out3)
out3 = BatchNormalization()(out3)merge = concatenate([out1,out2,out3])output = Dense(2,activation = 'sigmoid')(merge)model = Model(inputs=input_layer, outputs=output)
# summarize layers
print(model.summary())# plot graph
plot_model(model, to_file='MODEL.png')adam = optimizers.Adam(lr = 0.001)
model.compile(loss='binary_crossentropy', optimizer = adam, metrics=['accuracy'])

2.6-XOR _ 64 位数据集:

input_layer = Input(shape = (64,))out1 = Dense(64,activation = 'relu')(input_layer)
out1 = Dropout(0.5)(out1)
out1 = BatchNormalization()(out1)out2 = Dense(64,activation = 'relu')(input_layer)
out2 = Dropout(0.5)(out2)
out2 = BatchNormalization()(out2)out3 = Dense(64,activation = 'relu')(input_layer)
out3 = Dropout(0.5)(out3)
out3 = BatchNormalization()(out3)merge = concatenate([out1,out2,out3])output = Dense(2,activation = 'sigmoid')(merge)model = Model(inputs=input_layer, outputs=output)
# summarize layers
print(model.summary())# plot graph
plot_model(model, to_file='MODEL.png')adam = optimizers.Adam(lr = 0.001)
model.compile(loss='binary_crossentropy', optimizer = adam, metrics=['accuracy'])

正如我们所见,图 5 考虑了两个数据集的隐藏层数和其他参数,如激活函数和优化器。

结果

在 keras 中实现神经网络后,结果(如图 6 所示)非常好。

Fig-6

在这里,我们许多人可能认为结果是过度拟合的,但事实并非如此,因为当我们考虑实现的一些数据点时,我们可以预期这种结果。

结论

如果你已经到达这里,非常感谢:)。

安全方面最重要的工作是发现或发现所有可能的不安全风险。如果在任何 puf 中发现任何不安全的风险或漏洞,可能会提醒 puf 设计者提出新的 puf,以便他们可以克服这些现有的漏洞。puf 中的漏洞还可以帮助基于 puf 的设备的物联网设备开发人员避免这些 puf。最后,我们能够使用基于神经网络的攻击来发现 XOR 仲裁器 puf 中的漏洞。MLPs 帮助我们用 XOR 仲裁器 puf(即 论文 )的大容量数据集,比其他任何匹配学习算法更快地实现了漏洞。

请参考我的 GitHub 链接 这里 访问 Jupyter 笔记本上写的完整代码。

特别感谢 Srikanth Varma Chekuri 和 AppliedAICourse 团队帮助我在机器学习和深度学习领域学到了这么多东西。

参考

  1. https://www . semantic scholar . org/paper/A-Machine-Learning-Based-Security-Vulnerability-on-Aseeri-Zhuang/c77f 42238 e 6098000 C7 add 21d 517 c7ff 0676 f 54 f
  2. https://dl.acm.org/citation.cfm?id=1866335
  3. https://machine learning mastery . com/keras-functional-API-deep-learning/
  4. https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=6823677
  5. https://www.appliedaicourse.com/

PS: 如果你认为可以改进这个博客,我一定会考虑的。

神经网络解释了地震破裂的物理现象

原文:https://towardsdatascience.com/neural-network-can-explain-the-physics-of-an-earthquake-rupture-8417ee2c058d?source=collection_archive---------27-----------------------

地震破裂动力学的机器学习方法

地震造成的破坏对全世界的人类构成了威胁。为了估计这种危险,科学家们使用不同地点的地震仪记录的历史地震数据和地面运动。然而,目前的方法大多是经验性的,由于缺乏历史地质数据,可能无法捕捉未来大地震中地面震动的全部范围。这导致了危险估计的重大不确定性。不仅如此,由于缺乏足够的历史数据,科学家们大多依赖模拟数据,计算量很大。

在本文中,我将解释使用机器学习预测地震是否会破坏断层的工作流。这个项目是我在孟菲斯大学地震研究和信息中心(CERI)的博士论文的一部分。 Eric.G .涂抹也是这篇论文的合著者,他监督了我和这个项目。最近我们提交了关于 Arxiv 的论文:【https://arxiv.org/abs/1906.06250

在本文的剩余部分,我将讨论机器学习算法在预测真实地表断层破裂和估计地震危险方面的潜力。我也将解释有助于揭示地震破裂过程的复杂模式

地震破裂域

Figure-1: Rupture domain

我们制作了一组 2,000 个不同断层几何形状(高度和宽度)和材料特性(平面外应力、平面内应力、剪切应力、摩擦下降、动态摩擦系数)的破裂模拟,如图 1 所示。我们使用了 Eric 开发的开源数值模拟代码 fdfault 。该区域长 32 公里,宽 24 公里,横跨断层。该图显示了断层的放大视图,以便更好地观察障碍物。地震在离弯曲的几何障碍 10 公里的成核区(红色)开始。根据断层的几何形状和性质,有些地震能够穿过断层,有些则不能。为了简单起见,我们把它变成一个二元分类问题。更多的细节可以在报纸上找到。

Earthquake rupture propagation along the fault

上面的例子是地震无法突破断层的地震破裂停止之一。断裂止于断层的向上弯曲处。用 4 个 CPU 运行这个模拟大约花了 3.5 个小时。我们开发的 ML 可以在几分之一秒内预测这种地震破裂状态。让我们深入 ML 模型的细节和它们的能力。

浅层神经网络

我们使用随机森林和神经网络开发了两个预测模型。在本文中,我只关注神经网络算法。更具体地说,对所学参数的解释帮助我们揭示了地震破裂过程的机制。

Figure-2: Schematic diagram of the neural network topology used in the work

上面的图-2 说明了我们在这项工作中使用的神经网络拓扑的示意图。网络有一个 12 单元的隐层。八个输入参数被映射到这 12 个单元,为模型产生 12×8 的权重矩阵。当每个输入进入一个单元时,前一个单元的输出乘以其权重。然后,该单元将所有这些新输入相加,从而确定中间单元的输出值。然后,我们将非线性激活函数 ReLu 应用于输出权重,它传递所有大于零的值,并将任何负输出设置为零。最后,隐藏层将 12 个输出与输出层合并,并使用结果权重进行预测。

解释模型参数并获得物理特性

Figure-3: The parameters learned by the NN.

神经网络学习到的权重使我们能够对最能预测破裂传播能力的输入参数组合有所了解。为了可视化权重,我们构建了权重对神经单元矩阵图。这如图 2 所示。左侧面板显示了将八个输入(水平)映射到十二个隐藏单元(垂直)的模型权重。右侧面板显示了将隐藏单元合并为右侧一个输出单元的权重。色标表示重量的范围。模型中的权重范围从负值到正值,表示抑制性或兴奋性影响。

如果特定单元的输出图层权重为正,则参数组合是破裂传播的良好预测值,而负权重表示参数组合是破裂停止的良好预测值。类似地,将输入映射到作为正指示器的隐藏单元的权重表示该输入单元的大值有利于破裂。如果输出单元具有负权重,则隐藏单元的大权重表示该参数的大值预示着停滞。权重提供了对哪些参数组合最能预测破裂的洞察。

Table-1: Five parameter combinations and their corresponding possible predictions

图 2 所示的参数提供了对参数组合及其对确定破裂传播的影响的深入了解。比如 unit-4 负输出权重大。该单元的剪切应力、摩擦下降和滑移弱化距离具有较大的负权重,而高度、半宽度、op、ip 正应力、动摩擦系数和摩擦下降具有正权重。这表明,如果断层具有低剪切应力和低摩擦降,但具有高压缩 op、IP 正应力、高动态摩擦系数、高度和半宽度,则断裂可能不会传播而是停止。

另一方面,单元-8 具有相当大的正输出权重。OP、IP 法向摩擦系数和动态摩擦系数具有大的负权重,而摩擦下降、滑移弱化距离和剪切应力具有高的正权重。请注意,这些基本上是与 unit-4 中的值相反的值,表明数据中存在单一的潜在模式。因此,基于输入数据,模型已经精确地确定了如何以更复杂的方式最佳地组合各种输入参数。表-1 列出了参数组合和相应的预测。

学习参数的稳健性

Figure-4: The illustration shows the coefficient of determination (R2 score) among the weights learned by fifteen neural network models

我们证实,通过重复拟合过程,由 ANN 方法找到的参数组合是稳健的。我们开发了另外 15 个神经网络模型,具有相同的训练数据集,但不同的初始权重,以观察模型是否找到预测破裂的相同特征。模型的平均检验准确率为 83%。尽管不同模型的最终权重略有不同,但根据输出权重按升序排序时,它们表现出高度的相关性。图 4 显示了模型学习的参数(升序)中系数(R2 分数)的确定。模型 11 与另一个模型的相关性最小,而模型 10 和 12 的相关性较高。尽管模型 11 与模型 1 的相关系数最低,为 0.71,但它足够高,仍然包含与其他模型相似的模式。高度相关的权重表明,不管模型初始化的随机方式如何,模型都选取一致的特征。

想要在你的领域找到对机器学习和图论感兴趣的人吗?

我将通过分享关于 xoolooloo 的有趣信息来结束这篇文章。它是一个基于位置的搜索引擎,利用相似和多重兴趣寻找当地人。例如,如果你读了这篇文章,你肯定对数据科学、图论、机器学习感兴趣。因此,你可以在你的地区找到有这些兴趣的人;去 www.xoolooloo.com看看

结论

在计算上,这些模型是非常高效的。一旦计算了训练模拟,并且训练了机器学习算法,模型可以在几分之一秒内做出预测。这有可能将动态破裂模拟的结果纳入其他复杂的计算中,如反演或概率地震危险分析,这通常是不可能的。

该方法还可以应用于其他复杂的破裂问题,如分支断层、断层跨越和其他复杂的非均质性,其中地震破裂传播的物理特性尚未完全了解。机器学习提供了一种处理这种复杂的非线性问题的新方法,并帮助科学家理解潜在的地球物理参数如何与产生的滑动和地面运动相关,从而帮助我们限制未来的地震危害和风险。

非常感谢您的阅读。我希望你喜欢整个系列。完整的代码和相关数据可以在 Github 上找到。论文的细节可以在 Arxiv:https://arxiv.org/abs/1906.06250上找到。

我很想收到你的来信。你可以联系我:

Email: sabbers@gmail.com
LinkedIn: [https://www.linkedin.com/in/sabber-ahamed/](https://www.linkedin.com/in/sabber-ahamed/)
Github: [https://github.com/msahamed](https://github.com/msahamed)
Medium: [https://medium.com/@sabber/](https://medium.com/@sabber/)

Python 中张量流用于卫星数据分类的神经网络

原文:https://towardsdatascience.com/neural-network-for-satellite-data-classification-using-tensorflow-in-python-a13bcf38f3e1?source=collection_archive---------2-----------------------

Landsat 5 多光谱数据分类的逐步指南

深度学习已经接管了解决复杂问题的大多数领域,地理空间领域也不例外。这篇文章的标题让你感兴趣,因此,我希望你熟悉卫星数据集;目前,Landsat 5 TM。关于机器学习(ML)算法如何工作的小知识,将帮助你快速掌握这个动手教程。对于那些不熟悉 ML 概念的人来说,简而言之,它是在一个实体的一些特征(特征或 x)与其其他属性(值或标签或 Y)之间建立关系——我们为模型提供了大量的示例(带标签的数据),以便它从中学习,然后预测新数据(未标记的数据)的值/标签。机器学习的理论复习到此为止!

卫星数据的一般问题:

卫星数据中的两个或更多要素类(例如,建筑物/荒地/采石场)可能具有相似的光谱值,这使得分类在过去几十年中成为一项具有挑战性的任务。由于上述问题,传统的监督和非监督方法不能成为完美的分类器,尽管它们稳健地执行分类。但是,总是有相关的问题。让我们通过下面的例子来理解这一点:

在上图中,如果您使用一条垂直线作为分类器,并且只沿着 x 轴移动它,使其将右边的所有图像分类为房屋,那么答案可能不是直截了当的。这是因为数据的分布是这样的,不可能用一条垂直线将它们分开。但是,这并不代表房子完全不能分类!

假设您使用红线(如上图所示)来分隔这两个特征。在这种情况下,分类器识别出了大多数房屋,但仍有一所房屋被遗漏,一棵树被错误分类为房屋。为了确保没有一所房子被落下,你可以使用蓝线。在这种情况下,分类器将覆盖所有的房子;这叫做高召回。然而,并不是所有的分类图像都是真正的房屋,这被称为低精度。同样,如果我们用绿线,所有归类为房屋的图像都是房屋;因此,该分类器具有较高的精度。在这种情况下,召回的次数会少一些,因为还有三所房子没有被召回。在大多数情况下,精确度和召回率之间的这种权衡成立。

上面展示的房屋和树木问题类似于建筑、采石场和荒地的情况。卫星数据的分类优先顺序可能因目的而异。例如,如果您希望确保所有堆积像元都被分类为堆积像元,一个也不留,并且您不太关心具有相似特征的其他类的像素被分类为堆积像元,则需要具有高召回率的模型。相反,如果优先级是只对纯堆积像素进行分类,而不包括任何其他类别的像素,并且您可以放弃混合堆积像素,则需要高精度分类器。通用模型将在房子和树的情况下使用红线,以保持精确度和召回率之间的平衡。

当前范围内使用的数据

这里,我们将把 Landsat 5 TM 的六个波段(波段 2 —波段 7)作为特征,并尝试预测二元组合类。2011 年为班加罗尔获取的多光谱 Landsat 5 数据及其相应的二元组合层将用于培训和测试。最后,2011 年为海得拉巴获取的另一个多光谱 Landsat 5 数据将用于新的预测。要了解更多关于如何为模型创建训练数据,你可以查看这个视频

由于我们使用带标签的数据来训练模型,这是一种受监督的 ML 方法。

Multispectral training data and its corresponding binary built-up layer

我们将使用谷歌在 Python 中的 Tensorflow 库来构建一个神经网络(NN)。将需要以下其他库,请确保您提前安装它们(查看此视频了解安装说明):

  1. pyrsgis —读写 GeoTIFF
  2. sci kit-learn—用于数据预处理和准确性检查
  3. numpy —用于基本数组操作
  4. Tensorflow —建立神经网络模型

不再拖延,让我们开始编码吧。

将所有三个文件放在一个目录中—在脚本中指定路径和输入文件名,并读取 GeoTIFF 文件。

pyrsgis 包的栅格模块分别读取 GeoTIFF 的地理位置信息和数字编号(DN)值作为 NumPy 数组。有关这方面的详细信息,请参阅 pyrsgis 页面

让我们打印出已读取数据的大小。

输出:

*Bangalore multispectral image shape: 6, 2054, 2044
Bangalore binary built-up image shape: 2054, 2044
Hyderabad multispectral image shape: 6, 1318, 1056*

从输出可以明显看出,班加罗尔图像中的行数和列数是相同的,多光谱图像中的层数也是相同的。该模型将学习根据所有波段的相应 DN 值来决定像素是否是累积的,因此,两个多光谱图像应该具有以相同顺序堆叠的相同数量的特征(波段)。

我们现在将把数组的形状改为二维数组,这是大多数 ML 算法所期望的,其中每行代表一个像素。 pyrsgis 包的 convert 模块将为我们完成这项工作。

Schemata of restructuring of data

输出:

*Bangalore multispectral image shape: 4198376, 6
Bangalore binary built-up image shape: 4198376
Hyderabad multispectral image shape: 1391808, 6*

在上面代码片段的第七行,我们提取了所有值为 1 的像素。这是一个自动防故障装置,可以避免由于 NoData 像素通常具有极高和极低的值而导致的问题。

现在,我们将拆分数据进行训练和验证。这样做是为了确保模型没有看到测试数据,并且在新数据上表现得同样好。否则,模型将过拟合,并且仅在训练数据上表现良好。

输出:

*(2519025, 6)
(2519025,)
(1679351, 6)
(1679351,)*

上面代码片段中的 test_size (0.4)表示训练-测试比例是 60/40。

包括神经网络在内的许多 ML 算法期望标准化的数据。这意味着直方图在某个范围内(这里是 0 到 1)被拉伸和缩放。我们将正常化我们的功能,以满足这一要求。归一化可以通过减去最小值并除以范围来实现。由于 Landsat 数据是 8 位数据,因此最小值和最大值分别为 0 和 255 (2⁸ = 256 个值)。

请注意,从数据中计算最小值和最大值进行标准化始终是一个好的做法。为了避免复杂性,我们将坚持使用默认的 8 位数据。

另一个附加的预处理步骤是将特征从二维重新整形为三维,使得每行代表一个单独的像素。

输出:

*(2519025, 1, 6) (1679351, 1, 6) (1391808, 1, 6)*

现在一切就绪,让我们使用构建模型。首先,我们将使用顺序模型,一个接一个地添加图层。有一个节点数等于 nBands 的输入层。使用一个具有 14 个节点的隐藏层和作为 激活函数relu 。最后一层包含二进制组合类的两个节点,具有' softmax '激活功能,适用于分类输出。你可以在这里找到更多的激活功能。**

Neural Network architecture

如第 10 行所述,我们用'亚当'优化器编译模型。(还有几个其他的可以查一下。)我们现在将使用的损失类型是分类稀疏交叉熵。你可以在这里查看详情。模型性能评估的度量是“准确性”。

最后,我们用两个时期(或迭代)在 xTrainyTrain 上运行模型。根据您的数据大小和计算能力,拟合模型需要一些时间。模型编译后可以看到以下内容:

让我们预测我们单独保存的测试数据的值,并执行各种准确性检查。

softmax 函数为每个类类型概率值生成单独的列。我们只对类一(构建的)进行提取,如上面代码片段的第六行所述。地理空间相关分析的模型变得难以评估,因为与其他一般的 ML 问题不同,依赖一个概括的总结误差是不公平的;空间位置是制胜模式的关键。因此,混淆矩阵、精度和召回率可以更清楚地反映模型的表现如何。

Confusion matrix, precision and recall as displayed in the terminal

正如在上面的混淆矩阵中所看到的,有成千上万的堆积像素被分类为非堆积像素,反之亦然,但占总数据大小的比例较小。在测试数据上获得的准确率和召回率都在 0.8 以上。

您总是可以花一些时间并执行一些迭代来找到最佳的隐藏层数量、每个隐藏层中的节点数量以及获得精确度的历元数量。一些常用的遥感指数如 NDBINDWI 也可以在需要时用作特征。达到所需精度后,使用模型预测新数据并导出 GeoTIFF。稍加调整的类似模型可以应用于类似的应用。

请注意,我们导出的是具有预测概率值的 GeoTIFF,而不是其阈值二进制版本。我们始终可以稍后在 GIS 环境中设置 float 类型图层的阈值,如下图所示。

Hyderabad built-up layer as predicted by the model using the multispectral data

模型的精度已经通过精度和召回率进行了评估,您也可以对新的预测栅格进行传统检查(例如 kappa 系数)。除了上述卫星数据分类的挑战之外,其他直观限制包括由于光谱特征的变化,该模型无法预测不同季节和不同地区获得的数据。

我们在本文中使用的模型是神经网络的一个非常基本的架构,一些复杂的模型,包括卷积神经网络(CNN)** 已经被研究人员证明可以产生更好的结果。想入门 CNN 进行卫星数据分类,可以看看这篇帖子“CNN 在中分辨率卫星数据上同样闪亮吗?T13”。这些方法的主要优点是模型训练后的可伸缩性。**

请在此找到使用的数据和完整的脚本

用 NNI 搜索神经结构

原文:https://towardsdatascience.com/neural-network-intelligence-to-learn-function-approximation-44046de9cccb?source=collection_archive---------25-----------------------

探索微软开源 AutoML 工具的强大功能

Photo by Filip Bunkens on Unsplash

神经架构搜索(NAS)是深度学习中的一个困难挑战。我们中的许多人都经历过,对于给定的数据集,网络最初可能很难学习。但只要简单地改变一个超参数,学习就会变得非常有效。手动调整包括架构在内的超参数既耗时又具有挑战性,尽管对某些人来说也很有趣。最近,自动超参数调优变得越来越流行,因为它提供了大规模解决 NAS 的有效机制。

在这篇文章中,我们将展示如何使用自动化机器学习(AutoML)工具来执行超参数搜索——NNI(用于神经网络智能)由微软开源。我刚刚开始和 NNI 一起踢球,到目前为止我都很喜欢它。在这里,我想分享我如何使用 NNI 搜索最佳超参数和架构。

作为一个例子,我们将建立一个神经网络来近似数学函数。假设满足激活函数的某些非线性条件,具有一个或多个隐藏层的神经网络被称为连续函数的函数逼近器[1]。像只有一个隐藏层的浅层网络不如宽度限制的深层网络有效(例如[2])。对于神经网络如何逼近函数,迈克尔·尼尔森给了一个很好的、通俗易懂的解释

简单非线性函数

我们从一个简单的非线性目标函数 y = x 开始。我们用一个有几个隐层的全连通网络,在范围[0,1]内学习这个函数。

下面是将此函数实现为 PyTorch 数据集的代码。输入数据和地面实况标签由 shape (1,1)的张量表示,其中两个分量分别是通道和数据维度。它们都是 1,因为 xy 只保存标量值。如果您有基于图像的神经网络的经验,您可以将数据视为单通道、单像素图像。

我们建立了一个多达三个隐藏层的全连接网络。该网络可以灵活地配置成具有从 1 到 3 范围内的隐藏层深度。

为了让训练进行下去,我们需要做出许多选择。我们必须决定隐藏层的数量,每层的大小,激活函数,优化器,学习率等。我们从一个由 16 个神经元组成的单一隐藏层的网络开始,选择如下:

activation_function: 'Sigmoid'learning_rate: **0.01** optimizer: 'Adam'loss_function: 'MSELoss'

运行脚本250 个时期,您将获得下图所示的学习功能。红点是网络输出,大致遵循实际的二次函数(蓝色曲线)。但显然,还有改进的空间。

Fig. 1

请注意,我们在 Python 中有固定的随机数生成种子,因此每个网络总是以相同的初始权重/偏差集开始,并且结果是可重复的。

作为一个有趣的实验,我们可以让网络架构更宽或更深,看看它是否能提高近似性。下图显示了一个 256 个神经元的单一隐藏层的“更广泛”模型的结果。性能和 16 神经元版本差不多。

Fig. 2

但是,如果我们使用一个“更深”的模型,每层有 16 个神经元的三个隐藏层,网络输出与目标函数非常匹配(见下图)。更具体地说,网络可以描述为{ 隐藏 _ 层 _ 1 _ 大小:16,隐藏 _ 层 _ 2 _ 大小:16,隐藏 _ 层 _ 3 _ 大小:16 }。为了便于我们讨论各种网络架构,我们将使用三个数字{ n1、n2、n3 }的简写来表示一个网络。在这种情况下,模型是{16,16,16}。目标函数和网络输出之间的最大近似误差约为 0.02。误差在 x (1.0)的上限附近达到最大值。其他地方的误差要小得多。

Fig. 3

更具挑战性的功能

现在让我们尝试一个更具挑战性的函数。该函数上下波动几次,变化幅度缓慢衰减。由于没有更好的名字,我将这个函数命名为振荡器。振荡器是连续的,因此神经网络可以近似。然而,它并不平滑,有突然的“跳跃”(令人惊讶的是,神经网络仍然能够处理这些,正如我们稍后看到的那样)。

Fig. 4

该函数可以通过构建一系列点( x,y )来创建,其中 x 均匀分布在[0,1]之间,间距为 0.1,并且 y 从 0.5 开始,并且每个后续的 y 值从其最后一个值计算。

yᵢ₊₁ = -(yᵢ² - 0.5)

现在,找出所有的超参数并不容易。例如,如果我们使用相同的{16,16,16}网络,并运行超过 1000 个时期,结果是:

Fig. 5

注意,由于目标函数比简单的二次函数更复杂,所以我们在更多的时期训练它。学习的函数(红色)不像二次函数那样逼近实际函数(蓝色),即使网络已经“识别”了函数中最显著的特征并逼近它们。

至于之前的二次函数,我们可以把网络架构做得更宽或者更深,看看是否提高了逼近度。但是找到最有效的模型将会很费时间,因为它涉及到大量的试验和错误。

在下一部分,我们将使用 NNI 自动进行搜索。

神经网络智能

NNI 是一个灵活和强大的超参数搜索工具。我发现 NNI 的文档和工作流程很容易理解和遵循,不像其他自动机器学习选项。NNI 可以很容易地配置为在本地机器上运行。对于我们的目的来说,在本地进行搜索就足够了,因为每次训练不超过几分钟,甚至不需要 GPU。

NNI 的一个实验由许多试验组成,每个试验评估一个独特的搜索参数组合。在每次试验中,使用选定的参数从头开始构建模型并进行训练。所有的性能指标都被记录下来,并可以在最后使用提供的 WebUI 进行检查。

有两种方式使用 NNI:通过 NNI API 或通过 NNI Python 注释。主要区别是在哪里指定搜索参数选项。NNI API 方法希望在 JSON 文件中列出选项,而 Python Annotation 方法允许您将选项作为特殊格式的代码注释嵌入到脚本中的参数定义旁边。后者为神经架构搜索提供了更好的支持(命名为神经架构搜索的 NNI 编程接口),允许您在注释中方便地指定不同的架构选项。然而,在撰写本文时,这仍然是一个实验性的特性。在本帖中,我们将使用 NNI API 进行包括架构在内的超参数搜索。与 NNI 编程接口相比,这需要我们编写更多的代码来管理架构搜索,但对于我们的目的来说,这仍然是可管理的。

第一次 NNI 实验

有许多超参数可能会影响我们的模型性能,但同时搜索所有这些参数非常耗时。假设我们想要探索 7 个参数,每个参数有 4 个值要尝试。唯一参数组合的总数是 4⁷ = 16384。运行如此多的试验将需要很长时间,甚至分析最终结果也可能变得棘手。如本文后面所示,我们将使用 NNI WebUI 来可视化和查看结果。但是,如果我们有太多的数据点,这将不会工作得很好。

相反,我们将把搜索分为两步。还记得我们在这篇文章前面选择的四个参数(激活函数、学习率、优化器和损失函数)的值吗?第一步是尝试为这些与网络架构无关的参数找到合适的值。一旦我们摆脱了这些不确定性,我们就可以专注于架构搜索。注意,激活功能可以被视为一个架构参数。但是它与网络的拓扑无关。在我们的实验中,我们将它与其他非体系结构参数分组,以便稍后我们可以从拓扑角度关注体系结构搜索。

请注意,这种两步走的方法是一种妥协。这里,我们隐含地假设非架构参数(如损失函数)的优化不依赖于网络拓扑,因此我们可以将它们解耦并分别优化。但在现实中,拓扑、非架构超参数和初始网络权重/偏差很可能交织在一起,它们的优化在某种程度上都相互依赖。我们采取这种实用的方法来寻找一个很好的解决问题的方法,但我们不能保证它是最好的。

我们在这个实验中使用一个具有{16,16,16}网络的模型。它可能不是最好的架构(我们还不知道),但它将允许我们首先深入了解其他超参数。

我们将首先了解 NNI 是如何运作的。使用 NNI API 运行搜索实验的工作流程如下:

1。定义搜索空间。搜索空间描述了要搜索的每个参数的所有选择。这些选项将在 JSON 文件中列出,如下所示:

"act_func"**:** {"_type"**:** "choice"**,** "_value"**:** ["ReLU"**,** "LeakyReLU"**,** "Sigmoid"**,** "Tanh"**,** "Softplus"]}**,** "learning_rate"**:** {"_type"**:** "quniform"**,** "_value"**:** [**0.005, 0.05, 0.01**]}**,** "optimizer"**:** {"_type"**:** "choice"**,** "_value"**:** ["SGD"**,** "Adam"**,** "RMSprop"]}**,** "loss"**:** {"_type"**:** "choice"**,** "_value"**:** ["SmoothL1Loss"**,** "MSELoss"]}

这里,由于学习率是一个连续变量,我们将其设置为在[0.005,005]的范围内变化,间距为 0.01。

2。修改模型代码以使用 NNI API。该步骤包括在每次试验之前调用 nni.get_next_parameter() 以获得所有搜索参数的唯一组合,在训练期间调用nni . report _ intermediate _ result()以将中间性能指标作为时间序列记录到 nni,并在每次训练会话之后调用nni . report _ final _ result()以记录最终指标。一个这样的培训脚本的例子在这篇文章的报告中提供。

3。创建一个 YAML 配置文件,并在其中启用 NNI API。

authorName: default
experimentName: single_var_func
trialConcurrency: 2
maxExecDuration: 5h
maxTrialNum: 5000
trainingServicePlatform: local
searchSpacePath: search_space_non_arch.json
*#searchSpacePath: search_space_arch.json* useAnnotation: false
tuner:
  builtinTunerName: GridSearch
trial:
  command: python3 func_approx_nni.py oscillator
  codeDir: .
  gpuNum: 0

注意,我们将 useAnnotation 设置为 false 来启用 NNI API。我们使用 GridSearch 搜索调谐器参数builtin tunername来搜索所有可能的参数值组合。NNI 调谐器还有其他选项可以使用不同的搜索算法来减少搜索空间和节省搜索时间。在撰写本文时,我还没有很好地理解这些搜索算法所做的权衡。你需要给他们一个尝试,看看哪个更适合你。

4。进行实验。

像这样运行实验:

nnictl create --config config.yaml

如果一切顺利,这将启动一个 NNI 搜索实验,并告诉你查看结果的网址。用浏览器打开网址,你可以看到 NNI 的网页界面。这个漂亮的 UI 工具非常容易使用。它报告作业运行状态,当实验完成时,它以直观的图形显示所有试验的结果。这是有趣的部分——看看哪个参数组合能给你最好的结果。

下面的超参数视图突出显示了该实验中表现最好的部分(红色部分)。

Fig. 6

我们可以看到, SmoothL1Loss 损失函数、 Adam 优化器和 LeakyReLU 激活函数的组合往往工作得非常好,并且性能对学习速率不太敏感。

超参数视图的一个很大的特点是我们可以向左或向右移动参数线。在下面的屏幕截图中,我们将“loss”参数与“act_func”参数互换。现在很容易看出 ReLU 不管其他参数如何都是一个糟糕的选择,因为它没有与任何接近或高于 2.0 的好的度量值相关联(用红色或橙色标出)。

Fig. 7

同样,如果我们将“优化器”参数移至“默认指标”线附近,我们可以看到 RMSpropSGD 通常与较低的指标值(绿色或黄色)相关联,无法与 Adam 竞争。

Fig. 8

有趣的是,表现最好的人在人群中脱颖而出。这种差异可能不是非常显著,因为一些模型的指标在训练期间波动很大。最佳表现者具有以下参数:

'act_func': 'LeakyReLU'**,** 'learning_rate': **0.005,** 'optimizer': 'Adam'**,** 'loss': 'SmoothL1Loss'

如果我们采用这些参数值并训练相同的{16,16,16}网络,则网络输出与目标函数非常匹配(与图 5 相比):

Fig. 9

建筑搜索

我们的架构搜索是为了找到隐藏层的最佳数量和每个隐藏层的大小,如下面另一个 JSON 文件中所列:

"hidden_size_1"**:** {"_type"**:** "choice"**,** "_value"**:** [**4, 8, 16, 32, 64, 128**]}**,** "hidden_size_2"**:** {"_type"**:** "choice"**,** "_value"**:** [**0, 4, 8, 16, 32**]}**,** "hidden_size_3"**:** {"_type"**:** "choice"**,** "_value"**:** [**0, 4, 8, 16, 32**]}

将零作为 hidden_size_2 和 hidden_size_3 的选项有效地覆盖了不使用隐藏层 2 或 3 的情况。例如,将 hidden_size_2 和 hidden_size_3 都设置为零会产生单个隐藏层网络。

搜索结果如下图所示。表现最好的人用红色或橙色突出显示。我们可以看到,第一个隐藏层中的神经元数量与性能指标大致相关。这一层的神经元越多,我们得到的结果就越好。一般来说,其他隐藏层也是这样,有道理。网络掌握的参数越多,它就越容易学习。

Fig. 10

就网络拓扑而言,没有明显的模式。有这样的网络,每一层的神经元数量随着我们的深入而减少,或者大致保持不变,或者实际上增加。

我们对具有最少层数和最少神经元的简单网络更感兴趣。这就是神经架构搜索的目标——在性能很少或没有妥协的情况下找到高效的网络。所有单隐藏层网络的性能在此图中突出显示:

Fig. 11

{64,0,0}模型可以给出非常好的结果,最大近似误差约为 0.006:

Fig. 12

网络中使用的参数(权重和偏差)数量为 64+64+64+1=193,明显少于我们之前尝试的{16,16,16}网络(有 593 个参数)!

如果一个 64 个神经元的单隐层的网络可以在这里工作,为什么一个 128 个神经元的单隐层的网络不能在比较中表现得更好呢?在 WebUI 上,我们可以轻松地检查每个网络随时间推移的性能。结果是{128,0,0}模型的度量比{64,0,0}模型波动更大。因为我们只报告了最后 5 个指标中的最小值作为最终结果,所以{128,0,0}模型的值碰巧更低。但是来自{128,0,0}模型的最后 5 个指标的上限与该实验中的其他顶级表现者一样具有竞争力。为什么训练时波动这么大?在训练的后期阶段,网络性能可能对微小的参数调整很敏感,对于更大的网络,保持所有神经元以同步方式更新更具挑战性。因此,有时性能会有较大的波动。

另一个有趣的观察是,对于所有只有一个隐藏层的网络,那些不超过 32 个神经元的网络显然不会从目标函数中学习。事实上,我们可以通过粗略的分析来理解这一点。近似振荡器函数所需的最小参数是 112 = 22,因为我们需要知道范围[0,1]中的所有 11 个关键点,并且每个都需要两个值( xy )来指定。参数在 22 左右的网络将由 4 或 8 个神经元的单一隐藏层组成。但这并不意味着{8,0,0}网络可能是最有效的架构,因为我们知道神经网络在默认情况下不会自动学习变得高效和苗条。也就是说,网络不知道如何最有效地利用每个参数的。因此,我们的任务所需的网络可能会比{8,0,0}网络大一点。事实上,如果我们试图训练一个少于 16 个神经元的单一隐藏层的网络,即使经过 5000 多个纪元,我们也无法找到一个像样的解决方案。*

概述

NNI 是一个轻量级,灵活的 AutoML 工具,可以帮助神经架构搜索。在这篇文章中,我们用 NNI 优化了一个近似函数的神经网络。这个实验可以在计算能力一般的台式机上完成。因此,与其他 NAS 框架相比,它很容易上手。我们只探索了使用 NNI 的基本方法。我希望他们是有趣的,并且让你对 NNI 能做什么有一个好的感觉。

这篇文章的全部源代码是在这里

参考文献

[1] G. Cybenko,“通过叠加 sigmoidal 函数的近似法”控制、信号和系统的数学,2(4),303–314,1989。
【2】s . Liang 和 R. Srikant,“为什么深度神经网络要进行函数逼近?ICLR 20172017。

神经网络优化

原文:https://towardsdatascience.com/neural-network-optimization-7ca72d4db3e0?source=collection_archive---------0-----------------------

涵盖优化器,动量,自适应学习率,批量标准化,等等。

“我们的目标是找到最大价值优化的最佳点,在这一点上,愚蠢的风险与过度的谨慎相平衡。”―史蒂文·j·鲍恩

Example of non-convex loss surface with two parameters. Note that in deep neural networks, we’re dealing with millions of parameters, but the basic principle stays the same. Source: Yoshua Bengio.

本文是旨在揭开神经网络神秘面纱并概述如何设计和实现它们的系列文章中的第三篇。在本文中,我将讨论以下与神经网络优化相关的概念:

  • 优化挑战
  • 气势
  • 自适应学习率
  • 参数初始化
  • 批量归一化

您可以访问下面的前几篇文章。第一个为那些不熟悉的人提供了神经网络主题的简单介绍。第二篇文章涵盖了更多的中间主题,如激活函数、神经结构和损失函数。

[## 神经网络简介

神经网络的详细概述,有大量的例子和简单的图像。

towardsdatascience.com](/simple-introduction-to-neural-networks-ac1d7c3d7a2c) [## 神经网络体系结构综合介绍

神经架构、激活函数、损失函数、输出单元的详细概述。

towardsdatascience.com](/comprehensive-introduction-to-neural-network-architecture-c08c6d8e5d98)

这些教程主要基于哈佛和斯坦福大学计算机科学和数据科学系的课堂笔记和例子。

优化挑战

当在神经网络的上下文中讨论优化时,我们讨论的是非凸优化

凸优化 涉及一个只有一个最优的函数,对应全局最优(最大或最小)。凸优化问题没有局部最优的概念,使它们相对容易解决——这些是本科和研究生优化课程中常见的介绍性主题。

非凸优化涉及一个具有多个最优值的函数,其中只有一个是全局最优值。根据损失面的不同,很难找到全局最优解

对于神经网络来说,我们所说的曲线或曲面就是损失曲面。因为我们试图最小化网络的预测误差,所以我们对在这个损失表面上找到全局最小值感兴趣——这是神经网络训练的目的。

与此相关的问题有很多:

  • 什么是合理的学习率?太小的学习率需要太长的时间来收敛,而太大的学习率将意味着网络不会收敛。
  • 我们如何避免陷入局部最优?一个局部最优值可能被一个特别陡峭的损失函数包围,并且可能很难“逃离”这个局部最优值。
  • 如果损失面形态发生变化怎么办?即使我们能找到全局最小值,也不能保证它会无限期地保持全局最小值。一个很好的例子是在不代表实际数据分布的数据集上进行训练时,当应用于新数据时,损失面会有所不同。这就是为什么试图使训练和测试数据集代表整个数据分布如此重要的一个原因。另一个很好的例子是,由于其动态特性,数据的分布习惯性地发生变化——这方面的一个例子是用户对流行音乐或电影的偏好,这种偏好每天和每月都在变化。

幸运的是,有一些方法可以解决所有这些挑战,从而减轻它们潜在的负面影响。

局部最优

以前,局部最小值被认为是神经网络训练中的一个主要问题。如今,研究人员发现,当使用足够大的神经网络时,大多数局部最小值会导致低成本,因此找到真正的全局最小值并不特别重要——具有合理低误差的局部最小值是可接受的。

鞍点

最近的研究表明,在高维空间中,鞍点比局部极小值更有可能出现。鞍点也比局部最小值更成问题,因为接近鞍点的梯度可能非常小。因此,梯度下降将导致可忽略的网络更新,因此网络训练将停止。

Saddle point — simultaneously a local minimum and a local maximum.

经常用于测试鞍点上优化算法性能的一个示例函数是 罗森布鲁克函数 。该函数由公式描述: f(x,y) = (a-x) + b(y-x),(x,y) = (a,a ) 处具有全局最小值。

这是一个非凸函数,其全局最小值位于一个狭长的谷中。找到山谷相对容易,但是由于平坦的山谷,很难收敛到全局最小值,因此具有小的梯度,因此基于梯度的优化过程很难收敛。

A plot of the Rosenbrock function of two variables. Here a=1,b=100, and the minimum value of zero is at (1,1).

Animation of Rosenbrock’s function of three variables. [Source](http://Simionescu, P.A. (2014). Computer Aided Graphing and Simulation Tools for AutoCAD users (1st ed.). Boca Raton, FL: CRC Press. ISBN 978-1-4822-5290-3.)

调理不良

一个重要的问题是代表学习问题的误差函数的特殊形式。早就注意到,误差函数的导数通常是病态的。这种病态反映在包含许多鞍点和平坦区域的误差地形中。

为了理解这一点,我们可以看看 Hessian 矩阵——一个标量值函数的二阶偏导数的方阵。 Hessian 描述了多变量函数的局部曲率。

Hessian 可以用来确定一个给定的驻点是否是鞍点。如果 Hessian 在该位置是不定的,则该驻点是鞍点。这也可以通过查看特征值以类似的方式进行推理。

计算和存储完整的 Hessian 矩阵需要 O(n ) 内存,这对于高维函数如神经网络的损失函数是不可行的。对于这种情况,通常使用截断牛顿拟牛顿算法。后一类算法使用对 Hessian 的近似;最流行的准牛顿算法之一是 BFGS 算法。

通常对于神经网络来说,Hessian 矩阵是不适定的——输入的微小变化都会导致输出快速变化。这是一个不希望的特性,因为这意味着优化过程不是特别稳定。在这些环境中,尽管存在强梯度,学习仍然很慢,因为振荡减慢了学习过程。

消失/爆炸渐变

到目前为止,我们只讨论了目标函数的结构——在这种情况下是损失函数——及其对优化过程的影响。还有一些与神经网络架构相关的问题,这与深度学习应用程序特别相关。

上述结构是具有 n 个隐藏层的深度神经网络的一个例子。当第一层的要素在网络中传播时,它们会经历仿射变换,然后是激活函数,如下所述:

上述等式对于单层是正确的。我们可以写出 n 层网络的输出:

根据 ab 的大小,上述公式有两种可能的情况。

如果值大于 1,对于较大的值 n (深度神经网络),梯度值将在网络中传播时迅速爆炸。除非实现梯度裁剪,否则爆炸梯度会导致“悬崖”(如果梯度超过某个阈值,就会被裁剪)。

An example of clipped vs. unclipped gradients.

Gradient clipping rule.

如果值小于 1,梯度将很快趋于零。如果计算机能够存储无限小的数字,那么这就不是问题,但是计算机只能存储有限的小数位数。如果梯度值变得小于该值,它将被识别为零。

那我们该怎么办?我们已经发现,神经网络注定具有大量的局部最优值,通常包含尖锐和平坦的谷,这导致学习停滞和不稳定的学习。

我现在将讨论一些我们可以帮助减轻我们刚刚讨论的关于神经网络优化的问题的方法,从动量开始。

动力

随机梯度下降(SGD)的一个问题是不利用曲率信息的更新导致的振荡的存在。这导致当曲率较高时 SGD 较慢。

(Left) Vanilla SGD, (right) SGD with momentum. Goodfellow et al. (2016)

通过采用平均梯度,我们可以获得更快的优化路径。这有助于抑制振荡,因为相反方向的梯度被抵消了。

动量这个名称来源于这样一个事实,即它类似于物理学中的线性动量概念。具有运动的对象(在这种情况下,这是优化算法移动的大致方向)具有一些惯性,这导致它们倾向于在运动方向上移动。因此,如果优化算法在大致方向上移动,动量使其“抵抗”方向的变化,这导致高曲率表面的振荡衰减。

动量是目标函数中的一个附加项,它是一个介于 0 和 1 之间的值,通过试图从局部最小值开始跳跃来增加向最小值前进的步长。如果动量项很大,那么学习率应该保持较小。动量值大也意味着收敛速度快。但是如果动量和学习率都保持在大值,那么你可能会跳过最小值一大步。小的动量值不能可靠地避免局部最小值,并且还会减慢系统的训练。如果梯度不断改变方向,动量也有助于平滑变化。动量的正确值可以通过反复试验或交叉验证来学习。

动量使用过去的梯度来更新值,如下式所示。与动量相关的值 v 通常被称为“速度”。将更多的权重应用于较新的渐变,从而创建渐变的指数衰减平均值。

我们可以看到增加动量对优化算法的影响。最初的几次更新并没有显示出相对于普通 SGD 的真正优势——因为我们没有以前的梯度用于我们的更新。随着更新数量的增加,我们的动力开始启动,并允许更快的收敛。

SGD without momentum (black) compared with SGD with momentum (red).

另一种存在的动量是内斯特罗夫动量,我们将简要讨论它。

内斯特罗夫势头

Sutskever,Martens 等人的《论深度学习中初始化和动量的重要性》2013 中对内斯特罗夫动量进行了很好的讨论。

主要的区别是,在经典动量理论中,你首先修正你的速度,然后根据这个速度前进一大步(然后重复),但是在内斯特罗夫动量理论中,你首先向速度方向前进一步,然后根据一个新的位置修正速度矢量(然后重复)。

即经典动量:

vW(t+1) = momentum.*Vw(t) - scaling .* gradient_F( W(t) )
W(t+1) = W(t) + vW(t+1)

而内斯特罗夫的势头是这样的:

vW(t+1) = momentum.*Vw(t) - scaling .* gradient_F( W(t) + momentum.*vW(t) )
W(t+1) = W(t) + vW(t+1)

这种差别很微妙,但在实践中,它会产生巨大的影响。

这个概念可能很难理解,所以下面是传统动量更新和内斯特罗夫动量之间的区别的直观表示。

Source (Stanford CS231n class)

自适应学习率

沿垂直方向的振荡-沿参数 2 的学习速度一定较慢。对每个参数使用不同的学习速度?

阿达格拉德

动量增加了误差函数斜率的更新,从而加快了 SGD 的速度。AdaGrad 根据每个参数的重要性调整更新,以执行更大或更小的更新。

Adagrad 的主要优势之一是,它消除了手动调整学习速度的需要,并在平缓的倾斜方向上取得更大的进步。

AdaGrad 的主要缺点是它在分母中累积平方梯度:因为每个增加的项都是正的,所以累积和在训练期间保持增长。这反过来导致学习速率缩小,最终变得无穷小,此时算法不再能够获得额外的知识。

RMSProp

对于非凸问题,AdaGrad 会过早地降低学习速率。我们可以使用指数加权平均值进行梯度累积。

圣经》和《古兰经》传统中)亚当(人类第一人的名字

Adam 是 RMSprop 和 momentum 的组合(类似地,Nadam 指 RMSprop 和内斯特罗夫 momentum 的组合)。Adam 指的是自适应矩估计,,它是当今用于神经网络的最流行的优化器。

Adam 计算每个参数的自适应学习率。除了存储像 Adadelta 和 RMSprop 这样的过去平方梯度 vt 的指数衰减平均值之外,Adam 还保持过去梯度的指数衰减平均值,类似于动量。

参数初始化

在前面的章节中,我们研究了如何最好地导航神经网络目标函数的损失面,以便收敛到全局最优(或可接受的良好局部最优)。现在,我们将看看如何操纵网络本身,以帮助优化程序。

网络权重的初始化是开发神经网络的一个重要且经常被忽视的特征。初始化不良的网络会带来多种问题,对网络性能不利。

以一个网络为例,我们将其初始化为全零值。在这种情况下会发生什么?网络实际上根本学不到任何东西。即使在梯度更新之后,所有的权重仍然是零,因为我们计算梯度更新的固有方式。

假设我们实现了这一点,并发现这是一个问题,然后决定将我们的网络初始化都设置为相同的值 0.5。现在会发生什么?网络实际上会学习一些东西,但我们过早地规定了神经单元之间的某种对称形式。

一般来说,通过根据正态分布随机化权重来避免预设任何形式的神经结构是一个好主意。在 Keras 中,这通常是通过指定一个随机状态来实现的(这提供了随机性,但确保了测量的可重复性)。

这种初始化的规模应该是多少?如果我们为权重选择大的值,这可能导致爆炸梯度。另一方面,较小的权重值会导致渐变消失。在这两者之间有一个最佳平衡点,但是它不能被先验地知道,必须通过反复试验来推断。

Xavier 初始化

Xavier 初始化是分配网络权重的简单启发式方法。每经过一层,我们希望方差保持不变。这有助于我们防止信号爆炸到高值或消失为零。换句话说,我们需要初始化权重,使得输入和输出的方差保持不变。

权重来自具有零均值和特定方差的分布。对于具有 m 输入的全连接层:

m 有时被称为扇入:传入神经元的数量(权重张量中的输入单元)。

重要的是要记住,这是一个启发,因此没有特别的理论支持-它只是凭经验观察到表现良好。可以在这里阅读原论文

他正常初始化

正常初始化基本上与 Xavier 初始化相同,只是方差要乘以 2 倍。

在这种方法中,记住前一层的大小来初始化权重,这有助于更快更有效地获得成本函数的全局最小值。权重仍然是随机的,但是范围根据前一层神经元的大小而不同。这提供了受控的初始化,因此更快和更有效的梯度下降。

对于 ReLU 装置,建议:

偏置初始化

偏置初始化指的是应该如何初始化神经元的偏置。我们已经描述了权重应该用某种形式的正态分布随机初始化(以打破对称性),但是我们应该如何处理偏差呢?

套用斯坦福 CS231n 课程的话:初始化偏差的最简单、最常见的方式是将其设置为零——因为权重中的小随机数提供了不对称打破。对于 ReLU 非线性,一些人喜欢对所有偏差使用小的常数值,例如 0.01,因为这确保所有 ReLU 单元在开始时启动,并因此获得和传播一些梯度。然而,尚不清楚这是否提供了一致的改善,更常见的是将偏差设置为零。

偏置初始化的一个主要问题是避免隐藏单元在初始化时饱和,例如在 ReLU 中,可以通过将偏置初始化为 0.1 而不是 0 来实现。

预初始化

另一种初始化权重的方法是使用预初始化。这对于用于检查图像的卷积网络来说是常见的。该技术包括输入已经训练好的网络(例如 VGG16)的权重,并使用这些权重作为待训练网络的初始权重。

这种技术只对用于类似数据的网络才是真正可行的,所述数据是网络被训练的数据。例如,VGG16 是为图像分析开发的,如果您计划分析图像,但数据集中的数据样本很少,那么预初始化可能是一种可行的方法。这是迁移学习背后的基本概念,但是术语预初始化和迁移学习不一定是同义词。

批量标准化

到目前为止,我们已经研究了使用动量和自适应学习率来导航神经网络损失面的方法。我们还研究了参数初始化的几种方法,以便最小化网络内的先验偏差。在这一节中,我们将看看如何操作数据本身,以帮助我们的模型优化。

为了做到这一点,我们将研究批处理规范化以及实现批处理规范化以帮助优化神经网络的一些方法。

特征归一化

特征规范化正是它所说的,它包括在应用学习算法之前规范化特征。这涉及到重新缩放特征,通常在预处理过程中完成。

根据论文“批量归一化:通过减少内部协变量移位来加速深度网络训练”,梯度下降在有特征缩放的情况下比没有特征缩放的情况下收敛得快得多。

有几种方法可以缩放数据。一种常见的方法是最小-最大归一化,由此

缩放数据的最简单方法称为最小-最大归一化,它涉及重新缩放要素的范围,以在[0,1]或[1,1]中缩放范围。这是通过用最小值减去每个值,然后用数据集中存在的值的范围对其进行缩放来实现的。如果数据的分布高度倾斜,这可能会导致许多值聚集在一个位置。如果发生这种情况,有时可以通过对特征变量取对数来缓解(因为这有可能会导致异常值崩溃,因此它们对分布的影响不太大)。

另一种常用方法是均值归一化,这基本上与最小-最大归一化相同,只是从每个值中减去平均值。这是本文讨论的三种方法中最不常见的一种。

特征标准化使数据中每个特征的值具有零均值(当减去分子中的均值时)和单位方差。这种方法广泛用于许多机器学习算法(通常是那些涉及基于距离的方法)中的归一化。计算的一般方法是确定每个特征的分布平均值和标准偏差。接下来,我们从每个特征中减去平均值。然后,我们将每个特征的值(平均值已经减去)除以其标准偏差。

通过执行归一化,我们可以改善数据集的失真(例如一个要素相对于另一个要素的拉长)并使其更加均匀。

内部协方差移位

这个思路也来源于之前提到的论文批量归一化:通过减少内部协变量移位加速深度网络训练

作者定义内部协方差移位:

我们将内部协变量移位定义为由于训练期间网络参数的变化而导致的网络激活分布的变化。

这可能有点模糊,所以我会尝试解开这个。在神经网络中,第一层的输出馈入第二层,第二层的输出馈入第三层,依此类推。当一层的参数改变时,对后续层的输入分布也改变。

输入分布的这些变化对于神经网络来说可能是有问题的,因为它有减慢学习的趋势,尤其是可能具有大量层的深度神经网络。

众所周知,如果输入已被白化(即零均值、单位方差)且不相关,则网络收敛更快,而内部协变量移位会导致相反的结果。

批量标准化是一种旨在减轻神经网络内部协变量变化的方法。

批量标准化

批量标准化是将特征标准化的思想扩展到神经网络的其他层。如果输入层可以从标准化中受益,为什么网络层的其余部分不能呢?

为了提高神经网络的稳定性,批标准化通过减去批平均值并除以批标准偏差来标准化先前激活层的输出。

批量标准化允许网络的每一层独立于其他层进行学习。

然而,在通过一些随机初始化的参数对激活输出进行移位/缩放之后,下一层中的权重不再是最优的。如果这是最小化损失函数的一种方式,SGD(随机梯度下降)撤销这种归一化。

因此,批量归一化会向每一层添加两个可训练参数,因此归一化输出会乘以一个“标准差”参数(γ)并添加一个“均值”参数(β)。换句话说,批量规范化让 SGD 通过只改变每次激活的这两个权重来进行反规范化,而不是通过改变所有权重来失去网络的稳定性。

这个过程被称为批量归一化转换

The batch normalization transform.

为了直观地说明这一点,我们可以分析下图。我们正在看第一个隐藏层,紧接着输入层。对于每个 N 小批量,我们可以计算输出的平均值和标准偏差。

随后对所有随后的隐藏层重复这一过程。接下来,我们可以区分 N 个小批量的联合损失,然后通过归一化操作反向传播。

批处理规范化减少了过度拟合,因为它有轻微的正则化效果。类似于脱落,它给每个隐藏层的激活添加一些噪声。

在测试期间,平均值和标准偏差由训练期间收集的运行平均值代替。这与使用总体统计而不是小批量统计是一样的,因为这确保了输出的确定性地依赖于输入。

使用批处理规范化有几个优点:

  1. 减少内部协变移位。
  2. 降低梯度对参数比例或其初始值的依赖性。
  3. 规则化模型,并减少对丢失、光度失真、局部响应归一化和其他规则化技术的需要。
  4. 允许使用饱和非线性和更高的学习率。

最终意见

这就结束了我关于全连接神经网络系列文章的第三部分。在接下来的文章中,我将提供一些深入的编码示例,演示如何执行神经网络优化,以及神经网络的更高级主题,如热重启、快照集成等。

时事通讯

关于新博客文章和额外内容的更新,请注册我的时事通讯。

[## 时事通讯订阅

丰富您的学术之旅,加入一个由科学家,研究人员和行业专业人士组成的社区,以获得…

mailchi.mp](https://mailchi.mp/6304809e49e7/matthew-stewart)

进一步阅读

深度学习课程:

面向 NLP:

以视觉为导向:

重要的神经网络文章:

使用 PyTorch 的梵文字符神经网络教程

原文:https://towardsdatascience.com/neural-network-tutorial-with-devanagari-characters-using-pytorch-6abceb78a020?source=collection_archive---------25-----------------------

用 PyTorch 训练一个人工神经网络用于识别手写的梵文字符。

Source: images.google.com

顾名思义,神经网络是由人脑神经元松散地激发出来的。但是我们不会在这里讨论大脑类比的任何细节。相反,我们将通过一些数学和编码来理解它。

感知器

弗兰克·罗森布拉特(Frank Rosenblatt)在 20 世纪 50 年代提出了感知机(perceptron),表明一种算法可以模仿人类大脑的决策能力(我们仍在尝试)。他在论文中写道,我们可以将输入视为由二进制数组成的神经元。如果这些二进制数可以生成一个二进制数作为输出,如果输出满足某个阈值,则只生成

Perceptron model

你可能会问:

但是 Gopal,我们也可以写一个程序来做这个任务;为什么要写神经网络呢?我很高兴你问了。

选择神经网络而不是任何程序的第一个原因是,它们是通用函数逼近器,可以推断出我们试图建立的模型,或者如果它太复杂,神经网络总是代表那个函数。

我们可以假设将任何函数转化为数学术语,然后我们可以使用神经网络来表示该函数。

第二个原因是可伸缩性和灵活性。我们可以很容易地在神经网络中堆叠层,这将增加神经网络的复杂性。

神经网络的基本架构

神经网络由以下组件组成:

  • 输入层 x
  • 任意数量的隐藏层
  • 输出图层,𝑦
  • 一套 parameters(𝑊)和 biases(𝑏)各 layer,𝑊和𝑏之间
  • 每个隐藏层的激活函数的选择,𝜎

Resource from https://tex.stackexchange.com/questions/132444/diagram-of-an-artificial-neural-network

我们训练神经网络进行 n 次迭代;每次迭代包括两个步骤:

  1. 前馈
  2. 反向传播

前馈:

简单来说,当第一层的输出成为下一层的输入。这种网络称为前馈网络。

我们的网络中没有反馈信息的回路;它将总是被前馈。

反向传播:

这是我们的神经网络实际上从训练数据中学习的过程。

但问题仍然没有答案,我们的网络如何学习分类或预测?如果我们的模型已经预测到了什么,那么我们的模型如何确定它是正确的预测还是错误的呢?

答案是损失函数;它有助于我们的网络预测与原始值相差多少。

我们的模型已经预测了一所房子的价格为 100K 美元,而原始价格为 101K 美元,那么原始价格和预测价格之间的差异将为 1K 美元;这就是损失函数帮助我们的网络决定的。

回到反向传播,在我们借助损失函数计算模型预测和原始值的误差之后,我们发回这个误差以更新我们的输入神经元或 权重和偏差。这被称为反向传播。

但是我们需要多少来更新我们的权重和偏差

为了知道调整权重和偏差的适当量,我们必须推导出我们的 权重和偏差的损失函数

我认为现在我们有足够的直觉来开始我们的编码部分。

实现人工神经网络对手绘天体文字的分类

我们将使用 PyTorch 库来构建我们的神经网络。

我写了一个小程序 plot_images 用于显示字符及其标签。

让我们看看我们的 CSV 文件中有什么。

df.head() 将给出数据帧的前 5 列。在我们的数据集中,我们有从 0 到 1023 的像素值。用于显示特定字符的字符列由特定像素值组成。

让我们运行我们的 plot_images 函数,看看这些图像。

>>plot_images(df, 4, "character")

我们的数据集中有 46 个独特的手绘字符;因此,数字 46 将是我们神经网络的输出维度。

但是在创建神经网络之前,我们需要准备数据加载器,以便将它提供给我们的模型进行训练和测试,因为 NumPy 数据不能与 PyTorch 的库一起工作。

因此,在上面的代码示例中,我们读取数据并从中分离出要素和标签。如果你注意到了,我也在用 255.0 除features _ numpy;我这样做是为了规范我们的像素值。

然后,我将我们的分类标签转换成代码,因为我们只能用数字数据来创建张量值。

在我们的 data_loader 函数中,我们获取特性和目标;如果它们在 NumPy 数据中,我们就把它们转换成张量;之后,我们用torch . utils . Data . tensordataset、创建张量数据,最后将数据转换成数据加载器。

就是这样;我们的数据现在可以输入到模型中了。让我们现在建立神经网络。

在我们的 ANNModel 中,取 32*32,最后一层输入的输出维度为 46。但是我们这里有两个我还没有谈到的新术语。

Dropout:删除带有概率值的随机激活权重。假设我们已经将概率值设置为 0.2。那么对于每一个前馈或者反向传播过程,它都会忽略掉那 20%的神经元。它有助于防止过度合身。

Softmax:在数学中,Softmax 函数,也称为 softargmax 或归一化指数函数,是一个将 K 个实数的向量作为输入,并将其归一化为由 K 个与输入数的指数成比例的概率组成的概率分布的函数。

通过理解这两个术语,我们现在可以继续培训过程。

训练过程简单;我们正在迭代我们的训练数据加载器的图像和标签。然后清除初始梯度值并随后进行预测。运行这个程序后,您应该可以获得超过 94%的测试数据的准确率。

不可能解释每一步;请在评论区问我。

培训结束后,让我们看看我们的培训和验证曲线。

Training vs. Validation loss

看起来不错。😃

推论:

让我们检查一下我们的模型在测试数据上的表现。

>> make_predictions(test_loader, 44)

Inference

它做得非常好。😃

参考

[## Softmax 函数

在数学中,softmax 函数,也称为 softargmax 或归一化指数函数,[2] :198 是一个…

en.wikipedia.org](https://en.wikipedia.org/wiki/Softmax_function)

数据集:

[## 梵文字符集

下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…

www.kaggle.com](https://www.kaggle.com/rishianand/devanagari-character-set)

如何停止使用回调训练神经网络?

原文:https://towardsdatascience.com/neural-network-with-tensorflow-how-to-stop-training-using-callback-5c8d575c18a9?source=collection_archive---------14-----------------------

Photo by Samuel Zeller on Unsplash

Tensorflow 和 Keras 的有用工具

介绍

通常,当训练一个非常深的神经网络时,一旦训练精度达到某个期望的阈值,我们就想停止训练。因此,我们可以实现我们想要的(最优模型权重)并避免资源浪费(时间和计算能力)。

在这个简短的教程中,让我们学习如何在 Tensorflow 和 Keras 中实现这一点,使用回调方法,4 个简单的步骤

深潜

# Import tensorflow
import tensorflow as tf
  1. 首先,设置精度阈值,直到您想要训练您的模型。
ACCURACY_THRESHOLD = 0.95

2.现在实现回调类和函数,在精度达到 ACCURACY_THRESHOLD 时停止训练。

# Implement callback function to stop training
# when accuracy reaches e.g. ACCURACY_THRESHOLD = 0.95class myCallback(tf.keras.callbacks.Callback): 
    def on_epoch_end(self, epoch, logs={}): 
        if(logs.get('acc') > ACCURACY_THRESHOLD):   
        print("\nReached %2.2f%% accuracy, so stopping training!!" %(ACCURACY_THRESHOLD*100))   
        self.model.stop_training = True

这到底是怎么回事?我们正在通过扩展TF . keras . callbacks . callback来创建新的类,并实现 on_epoch_end() 方法。这在每个时期结束时调用。接下来,我们获取该时期结束时的精度值,如果它大于我们的阈值,我们将模型的 stop_training 设置为 True。

3.实例化一个 myCallback 类的对象。

callbacks = myCallback()

接下来,按照 TensorFlow 或 Keras 的正常步骤建立一个 DNN 或 Conv 网络模型。当使用 fit() 方法训练模型时,将使用我们在上面构建的回调。

4.只需将一个参数作为callbacks =[<my callback 类的新实例化对象> ] 传递给 fit()方法。

model.fit(x_train, y_train, epochs=20, callbacks=[callbacks])

仅此而已!训练时,一旦精度达到在 ACCURACY_THRESHOLD 中设置的值,训练将会停止。

为了将所有这些联系在一起,这里有一个完整的代码片段。

结论

凭借我们的想象力,这种方法可以以各种创造性的方式使用,特别是当我们想要运行快速 POC 来测试和验证多个 DNN 架构时。你还能想到什么有趣的用法?请在下面的评论区分享你的想法。

深入探究人工神经网络与生物神经网络的功能

原文:https://towardsdatascience.com/neural-networks-6ef91fa3bb7c?source=collection_archive---------20-----------------------

通信、噪声处理和架构变化

亮点:

生物神经网络由振荡器组成——这赋予了它们过滤输入和与噪音共振的能力。这也让他们有能力保留隐藏的点火模式。

人工神经网络与时间无关,不能过滤其输入。他们在训练后保持固定和明显的(但黑匣子)发射模式。

不同类型的噪声与人工神经网络不同元素的相互作用仍然是一个开放的研究课题。我们知道噪声可以用来调整它们的性能或帮助避免梯度下降中的局部最小值。

大脑重组其连接的能力被称为突触可塑性,它是通过长时程增强来实现的。人工神经网络在训练期间使用梯度下降来确定它们的连通性。梯度是使用反向传播计算的,我们可以将其与赫比长时程增强进行比较。

简介

头脑是大脑做的事情。那么,大脑到底在做什么,我们能造出什么来做类似的事情呢?这些东西到底是怎么做的?**

在本文中,我们深入研究生物和人工神经网络的功能来回答这些问题。我们研究神经元和节点如何通信,它们如何处理噪声,以及网络在学习时如何变化——最终引导我们做出适当的选择和行为。

如果您对这些主题不熟悉,请点击此处了解这些网络的结构组件介绍:

生物神经网络

最终,任何网络的输出都取决于其节点的激活模式。在基本水平上,我们可以说一个神经元拥有一个电位,如果达到某个电阈值,就会触发。神经元通过突触进行交流,突触是细胞之间的间隙,信号在这里变成化学物质。一些化学物质会告诉突触后神经元触发,一些会告诉它不要触发。后面的神经元是否会放电,最终取决于它的电位。

人工神经网络

另一方面,一个节点持有一个称为“激活”的数值——这个数值越大,这个神经元对下一个神经元的影响越强。通常,我们使用一个 sigmoid 函数来保持激活值在 0 和 1 之间,并且我们有一个偏置项来左移或右移激活函数。通常,节点被组织成层,其中一层中的所有节点都连接到前一层中的每个节点。“权重”决定了连接的强度,就像化学物质一样,它们可以向下面的节点发送积极(着火)或消极(不着火)的信息。

通信: 阈值和定时

我们将会非常仔细地观察随着学习的进行,权重和突触是如何变化的,但是首先,一个有效的连接看起来像什么?基本上,人工神经网络权重不必担心基于它们的时序被忽略,而突触传递则需要。正如我们将看到的,其原因对信息处理有深远的影响。

直到 20 世纪末,神经元被认为只是简单地将它们从周围所有神经元接收到的电输入相加,如果总和超过-70 毫伏,就会触发。今天,我们知道神经元作为一个弱混沌振荡器持有能量。这意味着它们有一个轨道吸引子,所以不是每次振荡都走完全相同的路径,而是走近似相同的路径。更具体地说,神经元是非谐振子,这意味着它们振荡的速度不是恒定的。这些也称为松弛振子,因为它们的特点是能量的松弛积累,周期性地转化为能量的突然损失(类似于动作电位)。

让我们以 gy rgy buzáki 的家用放松振荡器为例,这样我们就可以把它分解开来:滴水的水龙头。一个松弛的振荡器有三个阶段:兴奋状态,活跃状态和不应期。第一个对应于一个积累一滴水的水龙头,而如果你点击它或产生某种输入,水就会下降(但如果你等待更多的水积累,水滴可能会更大)。然后,在活动阶段,液滴会自己落下。随着水的下降,在不应期之后,当没有水或水很少时,系统不会受到干扰。

神经元就像水龙头,在激活和不应期对突触活动免疫。这意味着松弛振荡器在信息传输和接收周期之间交替,其中这些周期的长度由振荡器的频率决定。

这种相位重置特性赋予振荡器网络学习和存储模式的能力。人工神经网络也存储连接模式,但它们完全脱离时间(除了我们试图优化它们运行多长时间)。这里,所有节点接收来自前一层中所有节点的信息,我们能做的最好的事情是调整权重和偏置项,以保持激活为 0。神经元结合高通(电压相关)和低通(时间相关)滤波来执行基于频率的输入选择。在现实中,神经元的每个部分(即树突、轴突等。)可以起到这种有滤波能力的谐振振荡器的作用。

为什么这如此重要?除了由输入选择引起的明显的信息处理差异之外,这是网络如何处理噪声的决定性因素。

噪声: 偏差-方差权衡和随机共振

过度拟合是人工神经网络的致命弱点,噪声可以帮助我们解决这个问题。当机器学习模型具有低偏差(它捕捉变量之间的关系)和高方差(它在数据集之间具有高度可变的拟合质量)时,就会发生过度拟合。这是有问题的,因为它使我们的模型在新数据上工作不佳或不可靠。减少过度拟合的过程称为正则化,在该过程中,偏差上升,方差下降。

在训练过程中添加噪声是调整人工神经网络的一个很好的方法。通常怀疑是高斯噪声(即随机噪声),如果应用于输入,这也被认为是一种数据增强技术。我们还可以将噪声添加到权重、梯度(我们将在后面进一步探讨)和激活函数中。这些不同元素中的噪声提高性能的机制还没有被精确地确定下来,但是我们可以从大脑中寻找灵感。

在神经科学中,我们可以从随机共振的角度来看待噪音。在这里,神经元的振荡性质清楚地表明,噪声并不总是干扰信号。相反,它能够通过在适当的时候推动神经元超过激活阈值来放大隐藏或“习得”的信号。这就是众所周知的共振,当能量以其自然频率输入系统时就会发生共振。大脑的节奏将这比作站在钢琴旁边——当力施加到钢琴附近的地板上时,钢琴的弦会振动。好的乐器能做到这一点是因为它们能放大声音,或者就大脑信号而言,它们能产生共鸣。如果不是通过共振,人工智能中的信号如何或是否被噪声放大还有待观察。现在,让我们仔细看看什么是梯度。

架构变化: 梯度下降/反向传播和长时程增强

神经网络在学习时会改变它们的连接。这导致更有效和更准确地处理它们的输入,将我们带到正确的输出,就像一幅图像是猫还是狗。人工神经网络对固定量的输入——训练数据——进行这种操作,而大脑则连续进行这种操作,但它们是如何做到的呢?

在人工神经网络中,连接不会像在大脑中一样出现或消失,它们只会变强或变弱。最终,目标是最小化网络输出中的误差,这可以使用成本函数来测量。这个成本函数就是我们的模型预测的答案和实际答案之间的误差平方和的平均值。这将我们带到梯度下降——我们称之为下降,因为目标是降低误差。梯度这个词指的是我们如何寻找这个最小误差——使用导数来寻找最陡下降的方向。我们可以将此想象为一个在山谷中滚动的球,它将向下运动,直到最低点,此时表面是平坦的(即导数为零)。在 2D 图中,如果斜率为负,我们将向右移动,如果斜率为正,我们将向左移动。这带来了一些挑战,主要是速度和找到真正的最小值,而不是在山谷中的两个山峰之间卡住,而附近还有一个表面。在一些网络中,梯度噪声不仅有助于防止过度拟合,还降低了训练损失,而在其他网络中,它有助于避免局部极小值。

梯度告诉我们如何最小化成本,反向传播是如何计算成本的。想象一个神经网络,其中输出层有 2 个神经元,一个将图像分类为树懒,另一个将图像分类为熊猫。激活程度较高的神经元将是网络预测的结果——那么当这一预测错误时会发生什么呢?我们不能直接改变激活,但我们可以改变前一层神经元的权重。

假设一个图像的正确答案是 panda,我们的 panda-node 只有 0.2 激活,而它应该是 1。我们可以通过增加积极联系的权重,减少消极联系的权重来提高这个数字。由于来自前一层的具有较大激活值的节点具有更强的效果,因此改变这些节点的权重将对损失函数产生更大的影响(无论权重是正还是负)。这可以与神经科学中的 Hebbian 学习相比较,在 Hebbian 学习中,一起放电的神经元之间的联系得到了最大程度的加强。

同时,我们可以尝试给与我们的 panda-node 有大量连接的节点一个更高的激活值,但是正如我们已经建立的,我们不能直接改变激活值。然而,为了实现这一点,我们可以调整从倒数第二层到该节点的权重。事实上,我们有,这就是为什么我们称之为反向传播。现在,回到我们的输出,懒惰节点将对每层权重应如何变化有自己的看法,因此反向传播取平均值,以最小化两者的损失(在现实生活中,这是对训练数据的子集进行的,也称为小批量,导致随机梯度下降)。

另一方面,大脑改变其连接的能力被称为突触可塑性,其中一种机制被称为长时程增强(LTP)。在这里,突触基于最近的活动而被加强/削弱,这被视为学习和记忆的基础。有几种具有不同属性的 LTP,包括 Hebbian-LTP,其中“一起放电的神经元连接在一起”,就像在人工神经网络中一样。然而,也有非 Hebbian-LTP,其中突触前和突触后神经元不需要一起放电,以及反 Hebbian-LTP,其中突触后神经元必须超极化。

到目前为止,对 LTP 最了解的例子是成人 CA1 海马区的 NMDA 受体依赖性 LTP。以此为例,我们可以探究一些最常见的属性。首先,这种 LTP 是输入特异性的,这意味着一个突触的 LTP 诱导不会改变其他突触。其次是关联性。这意味着当一个途径的活性不足以诱导 LTP 时,另一个途径的同时强活性能够在两个途径中诱导 LTP。最后,我们有持久性,这表明这种增强是长期的,持续几分钟到几个月。到目前为止,我们已经确定的这种现象背后的主要机制是树突棘的修改,树突棘是信号交换的微小突起。

随着我们越来越了解 LTP、神经元和突触,我们也就越来越了解大脑。随着人工神经网络的出现,我们正在接近我们建造像我们自己一样复杂的东西的潜力。

最初于 11 月 1 日由 安巴尔·克莱恩波特 发表,并在《分析》杂志 Vidhya 上发表

参考文献:

神经网络和斐波那契数

原文:https://towardsdatascience.com/neural-networks-and-fibonacci-numbers-a7b0848a6c08?source=collection_archive---------22-----------------------

好吧,数学是美丽的,也许是我们可以用来表达自然界模式的最好工具。一个比率形式的特殊数字在自然界中经常出现,它的性质吸引了一代又一代从事构思和探索的精英。

Does this spiral of Parthenon, ring a bell !!

嗯,不是别人,正是黄金比例!!在数学上,它被简单地定义为一个数,该数是由线段的较长部分除以较短部分得到的,等于这两个给定部分之和与较长部分之比。

(a+b)/a = a/b = φ

用 phi(φ)来表示。这个数字可以在整个自然界和时间的历史中看到。从历史上看,从埃及到希腊建筑,从达芬奇的“神圣比例”到萨尔瓦多·达利的艺术作品,这种比例一直在重复出现。一位名叫斐波那契的数学家在 1200 年左右发现了这个数列,它有一个独特的性质,可以表示为数列中前两项之和。这个数列也有与黄金分割率相关的特殊性质。这个序列中两个连续项的比率接近黄金分割率,当项变得更高时,值接近黄金分割率!!

L = φ, for the above mentioned limit at infinity.

简介:神经网络中的斐波那契数

神经网络使用人工神经元来理解和制定嵌套层次概念形式的人类智能。同时,人类和自然界中的许多事物都服从斐波那契数列。因此,在本文中,我们旨在复制 2000 年代的一项研究,该研究声称,以黄金比例作为学习速率的斐波纳契初始化权重矩阵在学习曲线性能方面将优于随机初始化。因为,这是一个合理的假设,相信随着性能的提高,神经网络方程确实用 Fibonacci 值表示其自然对应物,因为它是可调的权重。

因此,在本文中,我们将用斐波那契数初始化权重矩阵,并将它与随机初始化得到的结果进行比较。与 LabVIEW 中的早期研究不同,我们将针对相对复杂和庞大的 MNIST 图像数据集以及 tensorflow 的现代框架来测试我们的网络。在这之后,让我们从实验中观察成本函数学习曲线和准确性,并相应地得出结论。

让我们初始化:编码斐波那契权重

在用不同的斐波纳契数和来自该系列的权重矩阵的排列进行重复实验后。我们提供了一个按比例缩小到 0.001 倍的以下数字列表[0、1、2、3、5、8、13、21、34、55、89、144、233、377、610],这些数字随机排列在权重矩阵中,以获得更好的精度。这里,下面参考 784x100 权重矩阵上的可视化图,该图将输入图像像素映射到大小为 100 的隐藏单元。

Fibonacci Initialization

Fibonacci Initialization

这种可视化给出了关于为给定维度的权重矩阵生成的斐波纳契数列的分布的粗略想法,其以随机方式分布在数组元素上。下面是提到的代码,它将 X 和 Y 维度作为输入,并返回具有斐波纳契权重的给定大小的权重矩阵。

def fib_init(X_val,Y_val):
    # Starting filling array values from F5 of Fibonacci
    mul_fact = 0.001

    fib_series = [0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

    W = np.zeros((X_val, Y_val))for i in range(X_val):
        for j in range(Y_val):
            W[i][j] = random.choice(fib_series) * mul_fact
            if(random.uniform(0, 1)<0.5):
                W[i][j] = -W[i][j]

    return np.float32(W)
# float type-casting is for maintaining compatibility with our tensor-flow code.

以类似的方式,我们设计了基于 Fibonacci 初始化的偏置矩阵‘b’的代码。经过反复实验,我们得出了以下值[5,8,13,21,34,55],按比例缩小到 0.01,以获得更好的偏置矢量精度。下面是一个类似的代码片段,它将向量的大小作为输入,并将 Fibonacci 初始化的向量作为输出返回。

def fib_bias(X_val):
    mul_fact = 0.01
    fib_series = [5, 8, 13, 21, 34, 55]
    b = np.zeros(X_val)
    for i in range(X_val):
        b[i] = random.choice(fib_series) * mul_fact
        if(random.uniform(0, 1)<0.5):
            b[i] = -b[i]
    return np.float32(b)
# float type-casting is for maintaining compatibility with our tensor-flow code.

将上述初始化与随机初始化进行比较,随机初始化即从均匀分布中产生随机数,并缩放到因子 0.01。参考下图,了解分布情况。

Random Initialization

Random Initialization

显然,上述初始化矩阵在初始化数据方面具有更高的幅度。此外,对于随机初始化技术,这导致数据中更多的变化。这可以通过对这两种初始化技术的直方图进行比较研究来观察。

Fibonacci Initialization

Random Initialization

显然,在我们当前设计的实验中,随机初始化具有更大的方差,与斐波那契权重相比,权重的范围要高得多。你可以参考 github 库,获取更新的实验(完成)的斐波那契初始化结果,该实验的数据方差几乎相等,数据分布相似。

让我们来比较一下:在 MNIST 运行我们的网络

在我们的实验中,我们训练了一个前馈神经网络,该网络仅具有单个隐藏层的 300 个隐藏单元输入,并使用交叉熵作为该模型的成本函数。对于与训练模型相关的代码,plot 实用程序脚本会引用 github 。通过这个实验,我们想要比较和观察给定训练模型的损失函数的行为。损失函数是否真的像早期研究声称的那样收敛得更快,以及所使用的两种初始化的准确性。损失函数值越低,精度真的提高了吗?关于两种初始化的成本函数比较曲线,请参考下文。

Cross Entropy Loss Function Comparison

显然,我们可以观察到,利用上述成本函数值与历元数的关系图,模型在斐波纳契初始化上的训练确实优于具有低得多的值的随机初始化。即使在达到饱和之后,对于第 300 个时期,Fibonacci 初始化的损失也低得多。因此,我们的模型确实学习了训练样本到正确输出的非常精确的映射。

我们可以在测试集上比较准确性,看看哪个模型具有更好的准确性。现在,需要回答的一个重要问题是,随着成本函数值的降低,模型能够捕捉到 MNIST 数据集中的高方差,精确度确实得到了提高。意思是在这么多胡言乱语之后什么都没发生。让我们看看下面…

Model Accuracy Comparison 😠

随机初始化确实以 0.33%的小百分比优于我们的斐波纳契初始化的神经网络。但是,考虑到斐波纳契初始化权重的方差较小,斐波纳契初始化仍然产生了良好的精度,我们还需要进行更多的实验。因此,根据我们的结果,我们在训练集上获得了更好的成本函数收敛结果😉和在上述相同条件下重复实验时相对几乎相同或稍低的精确度😠。需要进行更多不同条件的实验。因此,旅程仍在继续!!

结论和未来范围

的研究走得很远,声称神经网络方程是自然重现的对应模式的真实表示,神经网络模拟其自然对应模式,权重为斐波那契数。事实上,我们的实验并不确定这一点,因为精度并没有提高很多,事实上结果是更低,但对于 Fibonacci 初始化的权重,损失函数确实更早得到最小化。这种行为需要一个合理的解释💭。

此外,探索不同的数学上合理的初始化似乎是一个非常酷的构思过程,并在其上对我们的神经网络管道进行建模。未来的工作将在 CNN、RNNs 和初始化数据的更高方差上进行类似的实验。同样,需要添加与 Xaviar 和 He 初始化的比较。关于更新,敬请关注 github 知识库 ( 进行中)以及本文的更新。

将非常感谢您的意见和建议,以改进我们的实验和提到的方法。感谢阅读!!

实验结果更新

  1. 基于高方差 Fibonacci 初始化权重的实验表明,对于这种实验来说,这是一条直线下坡路,并且精度随着基于完全随机分布的选择的较高 Fibonacci 权重而急剧下降。

神经网络和语言哲学

原文:https://towardsdatascience.com/neural-networks-and-philosophy-of-language-31c34c0796da?source=collection_archive---------13-----------------------

为什么维特根斯坦的理论是所有现代自然语言处理的基础

Photo by Alexandra on Unsplash

单词嵌入可能是人工智能历史上最美丽和浪漫的想法之一。如果语言哲学是探索语言和现实之间的关系以及我们如何能够进行有意义的对话以理解彼此的哲学分支,那么现代自然语言处理(NLP)中的这种非常具体的技术在某种意义上就是对上个世纪最相关的哲学家之一路德维希·维特斯坦根的理论的经验证明。对于维特根斯坦来说,词语的使用是社会语言游戏中的一步棋,由相互理解的社区成员进行。一个词的意义仅取决于它在上下文中的有用性,而不仅仅是与现有世界对象的 1:1 关系。

对于我们使用“意义”这个词的一大类情况,它可以这样定义:一个词的意义是它在语言中的用法。

当然,知道一个词的确切含义是一件复杂的事情,涉及许多不同的方面:它可能指代的对象,它是什么词性,它是否是一种习惯表达以及它可能带有的所有味道,等等。所有这些方面,最后都可以归结为一个:懂得利用。

的意思是的概念,以及为什么一组有序的字符在一种语言中具有特定的内涵,这不仅仅是哲学上的兴趣,而是可能是从事 NLP 工作的人工智能专家每天都必须面对的最大挑战。作为说英语的人,理解“狗”是一种“动物”,并且更像“猫”而不是“海豚”,这是非常琐碎的,但是这个任务远不容易以系统的方式来解决。稍微调整一下维特根斯坦的理论,我们可以说狗和猫很相似,因为它们经常出现在相同的上下文中:更有可能找到与“房子”和“花园”等词相关的狗和猫,而不是与“大海”和“海洋”等词相关的狗和猫。这种直觉是 Word2Vec 的核心,这是最著名和最成功的单词嵌入实现之一。如果今天的机器距离真正理解长文本和段落还很遥远,那么毫无疑问,单词嵌入是过去十年中允许该领域朝着这个方向迈出最大一步的唯一技术。

从 BoW 到 Word2Vec

许多计算机科学相关任务中的一个初始问题是用数字形式表示数据;单词和句子可能是以这种方式表示的最具挑战性的数据类型。在我们的设置中,从由 D 个不同单词组成的词汇表中选择单词,集合中的每个单词都可以关联到一个数字索引 i 。几十年来使用的经典方法是将每个单词表示为一个 D 大小的数字向量,由除了位置 I 处的 1 之外的所有 0 组成。以仅由 3 个单词组成的词汇为例:“dog”、“cat”和“dolphin”(D = 3)。每个单词可以表示为一个 3 维向量:“狗”对应于[1,0,0],“猫”对应于[0,1,0],“海豚”,显然对应于[0,0,1]。作为一个简单的扩展,文档可以表示为一个 D 大小的向量,其中每个元素计算文档中第 I 个单词的出现次数。这种方法被称为单词袋(BoW ),已经使用了几十年。

虽然 BoW 在 90 年代取得了成功,但它缺少一个非常酷的词汇特征:意义。我们知道两个非常不同的单词可能有相似的意思,即使从正字法的角度来看它们完全不同。“猫”和“狗”都代表宠物,“国王”和“王后”的意思完全一样,只是体裁不同,“苹果”和“香烟”完全没有关系。我们知道这一点,但是使用弓模型,它们在向量空间中的距离都是一样的,1。同样的问题也可以扩展到文档:使用 BoW,我们可以说,只有当两个文档在一定次数上包含完全相同的单词时,它们才是相似的。这就是 Word2Vec 的用武之地,它将维特根斯坦 60 年前在他的哲学研究中所做的大量哲学讨论用机器学习的术语表达出来。

给定大小为 D 的字典,其中单词由其索引标识,目标是学习每个单词的 N 大小的向量表示,其中 N <<d. ideally="" we="" want="" this="" n-sized="" vector="" to="" be="" dense="" and="" able="" represent="" some="" semantic-specific="" aspects="" of="" meaning.="" for="" example="" that="" class="ls">、狗和猫具有相似的表示,而“苹果”和“香烟”在向量空间中具有非常远的表示。我们希望能够对像 king+woman-man = queen 这样的向量进行一些基本的代数运算,或者说代表“男演员”和“女演员”的向量之间的距离和“王子”和“公主”之间的距离差不多。尽管这些结果非常理想化,但实验表明通过 Word2Vec 获得的载体表现出与这些非常接近的性质。</d.>

Word2Vec 不直接学习这些表示,而是作为无监督分类任务的副产品获得它们。一个平均的 NLP 数据集(称为语料库)由一组句子组成;属于一个句子的每个单词都出现在周围单词的上下文中。分类器的目标是在给定其上下文单词作为输入的情况下预测目标单词。提取像“一只棕色的狗在花园里”这样的句子,单词[a,brown,is,in,the,garden]被提供作为模型的输入,输出单词“dog”是要预测的单词。这项任务被认为是无监督的学习,因为语料库不需要使用外部真实来源进行标记:给定一组句子,总是可以自动创建正面和负面的例子。将“一只棕色的狗在花园里”视为正面示例,我们可以创建大量负面样本,如“一架棕色的飞机在花园里”或“一只棕色的东西在花园里”,用从数据集中提取的随机单词替换目标单词“狗”。

现在维特根斯坦的理论的切入点已经很清楚了:语境对于学习嵌入是至关重要的,正如在他的理论中赋予意义是至关重要的一样。正如两个单词具有相似的意思一样,它们将具有相似的表示(N 维空间中的小距离),因为它们经常出现在相似的上下文中。所以“猫”和“狗”将最终具有相近的向量,因为它们经常出现在相同的上下文中:模型对它们使用相似的嵌入是有用的,因为这是在给定上下文的情况下预测两个单词时具有更好性能的最方便的事情。

原始论文提出了两种不同的体系结构:CBOW 和 Skip-gram。在这两种情况下,单词表示与特定于味道的分类任务一起被训练,提供最佳可能的向量嵌入,最大化模型的性能。

Figure 1 — Architecture comparison between CBOW and Skip-gram

CBOW 代表连续单词包,其目标是在给定输入上下文的情况下正确预测单词。输入和输出被提供为 D 大小的向量,并被投影到共享权重的 N 大小的空间中。用于将 D 大小的向量投影到 N 大小的内部向量的权重是我们正在寻找的嵌入。基本上,单词嵌入被表示为一个 D×N 矩阵,其中每行代表词汇表中的一个单词。所有上下文单词被投影到相同的位置,并且它们的向量表示被平均化;因此,单词的顺序不影响投影。

Skip-gram 做了同样的事情,但是又恢复了:试图预测作为目标词输入的 C 上下文词。预测多个上下文单词的问题可以被重塑为一组独立的二元分类任务,现在的目标是预测上下文单词的存在(或不存在)。

根据经验,Skip-gram 需要更多的时间来训练,并且通常会给出稍微好一点的结果,但是,像往常一样,不同的应用程序有不同的要求,并且很难预先预测两者中哪一个会优于另一个。由于优化模型权重所需的数据量和计算能力,这个概念看起来很简单,训练这种架构是一场噩梦。幸运的是,一些预先训练好的单词嵌入可以在网上找到,并且只需几行代码就可以探索向量空间——最有趣的部分。

可能的改进:手套和快速文本

在经典的 Word2Vec 之上,并遵循或多或少相同的方法,在过去几年中已经提出了大量可能的改进。最有趣和最常用的两个是 GloVe(由斯坦福大学开发)和 fastText(由脸书开发),主要是因为它们强调并试图克服原始算法的局限性。

原始 GloVe 论文中,作者强调了在单独的本地上下文中训练模型如何很好地利用了语料库的全局统计数据。克服这个限制的第一步是创建一个全局矩阵 X ,其中每个元素 I,j 计算单词 j 在单词 i 的上下文中出现的次数。本文的第二个最大贡献是理解了这些原始概率本身在确定意义方面并不强大,引入了一个共现矩阵,从这个矩阵中可以直接提取意义的某些方面。

考虑两个单词 I 和 j,它们展示了感兴趣的特定方面;具体来说,假设我们对热力学相的概念感兴趣,我们可以取 i =冰,j =蒸汽。可以通过研究这些词与各种探测词 k 的共现概率的比率来检查这些词的关系。对于与冰而不是蒸汽相关的词 k,假设 k =固体,我们预计比率 Pik/Pjk 将很大。同样,对于与蒸汽有关但与冰无关的单词 k,比如说 k =气体,比例应该很小。对于像水或时尚这样的词,要么与冰和蒸汽都有关系,要么两者都没有关系,比率应该接近 1。

这个概率比现在是学习嵌入的起点。我们希望能够计算出与特定函数结合的表示,F 在嵌入空间中保持这个比例常数。

Figure 2 — Most general formula for GloVe embeddings

函数 F 和单词 k 的相关性可以被简化,并由指数和固定偏差代替,作为结果给出这个最小平方误差函数 J :

Figure 3 — Final scoring function for computing GloVe embeddings

函数 f 是一个评分函数,它试图不对太频繁和太罕见的共现进行加权,而 bibj 是用于恢复函数对称性的偏差。在论文的最后几段中,展示了如何训练该模型,最终与训练经典的跳格模型没有太大的不同,即使经验测试显示 GloVe 如何优于 Word2Vec 实现。

另一方面,fastText 对 Word2Vec 提出了完全不同的批评:从 D 大小的 one-hot 编码向量开始训练模型的缺点是忽略了单词的内部结构。fastText 提出学习字符 n-gram 的表示,并将单词表示为 n-gram 向量的总和,而不是一次性编码单词来学习单词表示。例如,在 n=3 的情况下,单词“flower”被编码为 6 个不同的 3-gram[<fl、flo、low、owe、wer、er > ]加上特殊序列< flower >。注意尖括号是如何用来表示单词的开始和结束的。因此,一个单词由其在单词字典中的索引及其包含的 n 元语法集来表示,并使用哈希函数映射到整数。这个简单的改进允许跨单词共享 n 元语法表示,并计算没有出现在训练语料库中的单词的嵌入。

实验和可能的应用

正如所承诺的,使用这些嵌入只是几行 Python 代码的问题。我用一个 50 码大小的手套模型和一个 300 码大小的 fastText 模型进行了一些实验,前者训练了 60 亿个单词,这些单词是从主要在维基百科上检索的句子中提取的,后者训练了 6000 亿个令牌。在这一段中,来自两者的结果混合在一起,只是为了证明概念并给出对主题的一般理解。

首先,我想测试一些基本的单词相似性,这是单词嵌入的最简单也是最重要的特性。不出所料,与“狗”这个词最相似的词是“猫”(0.92)、“狗”(0.85)、“马”(0.79)、“小狗”(0.78)、“宠物”(0.77)。请注意,复数形式与单数形式的意思非常相似。再说一次,对我们来说这么说是很琐碎的,但对机器来说,这是完全不同的事实。现在的食物:和“披萨”最相似的词是“三明治”(0.87)、“三明治”(0.86)、“零食”(0.81)、“面包店”(0.79)、“薯条”(0.79)、“汉堡”(0.78)。有道理,结果令人满意,模型表现相当好。

下一步是尝试在向量空间中执行一些基本代数,以检查我们的模型是否正确地学习了一些期望的行为。“女演员”(0.94)这个词可以作为女人+演员-男人的结果得到,“国王”(0.86)作为男人+女王-女人。一般来说,如果在意义上 a : b = c : d,单词 d 应该是 d = b-a+c。更进一步说,这种向量运算甚至能够描述地理方面,这令人难以置信:我们知道罗马是意大利的首都,因为柏林是德国的首都,事实上柏林+意大利-罗马=德国(0.88)和伦敦+德国-英格兰=柏林(0.83)。

现在最有趣的部分,按照同样的想法,我们可以尝试加减概念,看看会发生什么。例如,意大利人的比萨饼在美国相当于什么?披萨+美国-意大利=汉堡(0.60),其次是芝士汉堡(0.59)。自从我搬到荷兰,我总是说这个国家是三种东西的混合体:一点点美国资本主义、瑞典人的冷漠和生活质量,以及最后一点点那不勒斯的繁荣。稍微调整一下原始定理,去掉一点瑞士精度,我们得到荷兰(0.68)为美国+瑞典+那不勒斯-瑞士:老实说,相当令人印象深刻。

Figure 4 — To all the Dutch readers: take this as a compliment. Ok?

可以在这里这里找到使用这种预训练嵌入的良好动手起点。Gensim 是一个用 Python 编写的简单而完整的库,有一些现成的代数和相似函数。这些预先训练的嵌入可以以许多不同的(和有用的)方式使用,例如,提高情感分析器或语言模型的性能。而不是喂养这些模型(不管他们的任务是什么!)对于一个热编码字,使用这些 N 大小的向量将显著提高性能。当然,训练特定领域的嵌入可以带来更好的性能,但是训练这种架构所需的时间和精力可能有点多余。

神经网络:基础

原文:https://towardsdatascience.com/neural-networks-basics-29cc093b82be?source=collection_archive---------8-----------------------

Auditory learner? Listen to this article in podcast form instead!

人工神经网络(ann)是机器学习领域的热门话题。因此,大量的研究正在进行。计算机视觉对噪音数据的容忍度、自动驾驶汽车对道路路线的预测,以及自然语言处理(NLP)的进步,使你可以与你的语音助手交流,这些都归功于人工神经网络。了解神经网络的基础知识将有助于你参与到围绕这个话题的对话中。

让我们从定义开始:人工神经网络是一种数学结构,当给定输入时,它可以映射到期望的输出。这样,十几个问题就会浮现在你的脑海里。让我们继续回答一些常见问题,以了解神经网络的基础知识。

谁发明了神经网络?

这个答案会因你问的人而异。有些人相信沃伦麦卡洛克和沃尔特皮茨的第一个理论。他们被认为描述了一个神经元如何有一个数学表示。然而,在这篇文章中,我们说的是一位名叫弗兰克·罗森布拉特的心理学家。

罗森布拉特

罗森布拉特在 1957 年发表了一篇名为“感知机:感知和识别自动化”的论文。该出版物描述了神经网络的构建模块,感知器。他描述了这些人工神经元如何从数据中学习。他被认为创造了监督学习,允许神经元根据其准确性改变自己的权重。

麦卡洛克和皮茨

麦卡洛克和皮茨在 1943 年发表了一篇名为“神经活动中固有观念的逻辑演算”的论文。他们极大地影响了罗森布拉特的研究。在那篇论文中,他们描述了人类神经元如何在生物神经网络的“全有或全无”特征中进行数学表示。

当神经元接收到一个信号时,它不会自动开始向下游传递信号。它会保持信号,直到达到阈值,然后它沿着轴突发送信息,被邻近的细胞接收。

Hebb

神经心理学的心理学家先驱唐纳德·赫布(Donald Hebb)在 1949 年发表了一篇名为“行为的组织:一种神经心理学理论”的论文。这篇开创性的论文产生了心理学中一个全新的规则,叫做赫布规则。该规则描述了一个神经元如何刺激另一个神经元,在重复激活后,细胞 A 变得有效地激活细胞 b。用 Hebb 的话说,“一起放电的神经元连接在一起”。

“当 A 细胞的轴突足够接近以激活 B 细胞,并重复和持续地参与其激活时,在一个或两个细胞中发生某种类型的生长过程或代谢变化,从而增加 A 细胞激活 B 细胞的效率”

赫布规则定义

什么是感知器,它是如何组成神经网络的?

感知器是神经网络的构建模块,类似于核酸、脂类、碳水化合物和蛋白质的生物构建模块。四个部分也构成了这些:

  1. 输入值
  2. 权重和偏差
  3. 求和函数
  4. 激活功能

输入值受到预定权重值的影响,然后在求和函数中相加在一起。在求和函数之后,该值在激活函数中被压缩在-1 和 1 之间或 0 和 1 之间。这将决定感知器是否会被激活。值越负,越接近最小值(-1 或 0),值越正,越接近最大值(1)。如果它被激活,那么输出将沿着它的路径发送。

单一感知器

如果感知器是单一形式的,那么第一个也是唯一的输出将是 yes 或 no 格式。单感知器非常适合线性可分性数据集,即可以使用具有恒定斜率的单条线来分离的组。

感知器对于“与”、“或”、“异或”逻辑门来说非常优秀。让我们来分解一下:

如果两个输入都为真,那么结果逻辑将为真。

或者,如果一个或两个输入为真,则推理结果为真。

XOR ',exclusive 'OR ',如果信息中的一个(但不是两个)为真,则命题将得出 true。

神经网络

然而,如果有一个以上的感知器存在并以分层的方式连接,我们就产生了一个神经网络。第一层的输出成为第二层的输入,依此类推,直到输出层对总激活进行求和。总激活度是网络最终决策的置信度。

神经网络有哪些层?

神经网络有 3 层:

  1. 输入层
  2. 隐蔽层
  3. 输出层

输入层是网络的起点。这是将用于预测的值引入的图层。隐藏层是网络发挥其“魔力”的地方。在整个区域计算输入值的激活量。隐藏层可以小到 1 层,也可以大到项目所需的数量。最后,输出层是每个最终节点的激活用于选择解决方案的地方。

如您所见,每个单元都连接到后续层的每个单元。这使得附近的感知器可以相互通信,并创建最适合其使用的权重。

只要记住,第一层是输入,最后一层是输出。中间的任何东西都是隐藏层。

计算机如何“看见”神经网络?

经常用于表示神经网络的图表(如上图所示)是人类友好的版本。计算机如何处理和观察它们是以矩阵的形式出现的。

我们将首先讨论前馈或训练部分。这是使用矩阵乘法完成的。

矩阵乘法

让我们分解一个具有 2 个输入值的神经网络,1 个隐藏层包含 3 个节点,我们以 2 个输出层节点结束。

我们将通过对每个元素使用唯一的字母来保持这一点,以便您可以在我们进行的过程中引用它。

权重 x 输入层

矩阵乘法是通过取第一矩阵的行并将每个元素与第二矩阵中的相应元素相乘来完成的。该操作的主要规则是第一个矩阵中的列数必须与第二个矩阵中的行数相匹配。让我们看一下将用于该网络的第一组矩阵。

正如我们所看到的,如果输入值的矩阵是第一个,我们将得到一个未定义的结果,因为上面的规则不被遵守。然而,如果我们翻转矩阵,我们将能够执行乘法。结果/输入矩阵作为第二个或右矩阵,权重矩阵作为第一个或左矩阵。

让我们在这个网络中执行第一次乘法。

我们得到的矩阵包含 3 行,分别对应于隐藏层中的 3 个节点:

权重 x 隐藏层

让我们做最后的乘法。

输出矩阵具有最终结果,它包含与输出层的 2 个节点相关的 2 行:

上述等式的结果将是每个神经元的激活水平。如果 O 0 高于 O 1,那么与 O 0 相关的预测将作为解给出。

神经网络是如何“学习”的?

神经网络分两步学习,前馈(我们刚刚讲过)和反向传播。反向传播本身可以分为两步,计算成本,然后最小化成本。

成本是网络的预测值和数据集的期望值之间的差值。成本越大,误差越大。目标是尽可能降低成本。为了实现这一目标,通过改变权重和偏好来最小化成本是游戏的名称。简单来说,它的前馈是反向的。你正在做矩阵乘法来改变权重,以便根据某些神经元将接收到的内容来给予它们更多的强调。

最小化成本函数的一种常见方法是通过梯度下降。

梯度下降

目标是通过合计实际和预期输出之间的所有差异,然后将其乘以学习率,找到函数的全局成本最小值。最常见的成本函数是均方误差。

J(θ)由梯度下降函数调用。

学习率α基本上是收敛的一大步(换句话说就是找到全局最小值)。为了给你一个视觉效果,想象你站在山顶上,下面是一个美丽的山谷。你开始沿着山坡往下走。对抗听从你内心孩子的冲动,快速滚下山(可能错过你的目标),你从容不迫,轻松地走下来,避开路上的任何石头和树木。

学习率类似于你要走多大步或方法才能到达山谷。如果学习率太大,你可能会继续滚向另一边,并且由于你滚的冲力而完全错过山谷。如果学习率太小,那么在你到达山谷(最佳目标)之前,天就已经黑了。为您的模型找到合适的学习速率对于创建有效且高效的神经网络至关重要。

如果你想知道从哪里开始机器学习的自学,请查看学习机器学习的 5 个简单步骤。这篇文章将帮助你有效地学习这个广泛的主题。

在我们重新学习之前,

神经网络,去神秘化

原文:https://towardsdatascience.com/neural-networks-demystified-49f3426d4478?source=collection_archive---------30-----------------------

Image by Gerd Altmann from Pixabay

你肯定听说过神经网络——这种神秘的、科幻般的技术成为了一个伟大的时髦词汇。但是作为一个非技术人员,你已经把它们当作一个只留给计算机科学书呆子(像我一样)的谜而一笔勾销了。今天,这一关于它们如何工作的初级读本改变了这一点,它是为对计算机科学、编码或数学一无所知的人设计的。

什么是神经网络?

神经网络可以被认为是一个人工信息处理器。它接受输入,以某种方式进行处理,然后产生一些输出。网络的结构决定了它如何进行处理,不同的结构产生不同的输出。其结果是网络可以对图像进行分类,翻译语言等等。

我们很快就会看到,网络的某些部分是固定的,而其他部分,即参数,是可以改变的。我们的目标是调整这些参数,使我们的网络学会解决问题。最初,我们的网络在完成任务时会非常糟糕,就像一个孩子在做微积分一样,因为这些参数是随机设置的。但是,随着我们反复测试网络,并根据其响应更新参数,随着时间的推移,它会变得更好。不出所料,这种测试和更新的重复过程意味着训练数据是神经网络的一大部分。

让我们来看看神经网络是什么样子的。

网络体系结构

神经网络的原始动机是人脑中的神经元,其具有几个重要特征:

  1. 我们大脑中的神经元通过一个巨大的网络相互连接,其中一些神经元的输出可以作为其他神经元的输入。
  2. 神经元之间的连接强度可以根据使用频率而变化,这导致了唐纳德·赫布的流行短语“一起放电的神经元,连接在一起”。
  3. 神经元中的电化学电势可以增加,但神经元不会“激发”,直到电势超过某个阈值。

让我们看看是否可以通过观察神经网络的构建模块——感知器——来人工复制其中的一些功能。

在上图中,我们已经表示了两个相连的神经元 A 和 C,其中神经元 A、 x、的输出等于神经元 C 的输入。我们将用节点(圆圈)表示神经元,用边(线条)表示神经元之间的连接。你可以这样想象一个神经元:它接受一些输入,保存一个值(它的输入的某种组合),然后将该值作为输出传递。到目前为止,这个模型满足上面列出的第一个特征。让我们介绍一下连接强度。

我们可以通过引入一个连接* 权重 w来改变连接的强度,神经元 C 的输入现在将是神经元 A 的输出 x ,乘以权重 w 。直觉上, w 的值越大(越小),两个神经元之间的联系越强(越弱)。这满足了第二个特征。最后,我们来介绍一下潜在门槛。*

我们现在引入了另一个神经元 B,它的值为 b ,连接权重为-1。b 是众所周知的偏差,我们很快就会知道为什么。对 C 的输入成为 A 和 B 的加权和,即 w x + (-1)*b .接下来,我们对 C 处的输入应用阶跃函数定义为 f(x) = 1 如果 x > 0,0 否则。*

The step function

总而言之,如果 w x -b > 0,则 C 处的值变为 1,否则为 0。我们到底为什么要这么做?嗯,如果 w x < b,C 处的值将等于 0。换句话说,偏差 b 充当一个阈值,我们需要通过该阈值才能使 C 处的值不为 0。这和前面讨论的神经元的第三个特征一模一样!正因为如此,我们称阶跃函数为“激活函数”。**

只有一个问题。x = 0 处阶梯图的垂直部分意味着它不可微。如果你不知道那是什么意思,不要着急(不满意看结论)。你只需要知道,我们可以用 sigmoid 函数来近似阶跃函数。

The Sigmoid function

您可以将 sigmoid 函数视为所有可能输入的“压缩”,以适应 0 和 1 之间的值。x 越大(越小) sigmoid(x) 越接近 1 (0)。

我们可以扩展当前的模型,让许多神经元提供输入,每个神经元都有自己的权重。请注意,其中只有一个是偏差。同样,输入成为它之前的神经元的加权和(每个节点的输出与其连接权重的乘积)。

既然如此,为什么不在每一层增加几个节点,增加几层连接呢?我们称第一层和最后一层之间的层为“隐藏层”。这里,每一层将只有一个偏差。

我们通常从填充最左边的神经元层开始,通过计算下一层中每个神经元的值在网络中“向前”移动,等等。最后,我们可以计算输出层中神经元的值。

我们之前说过,我们的网络中有一些固定的特征和一些参数。一般结构,即层数、每层节点数和激活函数是固定的。根据我们在网络中前进的方式,给定神经元及其前面的权重,每个神经元的值是确定的。因此我们唯一能改变的,我们的参数,变成了神经元之间连接的权重。

既然我们已经了解了什么是网络,那么让我们来看看如何使用它来解决问题。

它如何“学习”

我们将看看最著名的机器学习任务之一,识别手写图像。

Source

学习的一般过程是这样的:

  1. 定义一个网络
  2. 将图像传入网络(输入)
  3. 网络将预测图像的标签(输出)
  4. 使用预测以网络“学习”的方式更新网络
  5. 返回第二步并重复

让我们假设每个图像都是 28x28 (784)像素,并且因为它们是灰度的,所以每个像素的值的范围从 0(黑色)到 1(白色)。为了训练网络,我们需要图像及其相关标签形式的训练数据。

我们网络的第一层将代表数据;这就是我们如何将一个数据点(一幅图像)输入我们的网络。在第一层中将有 784 个神经元(加上一个偏差),并且每个神经元的值将是来自训练图像的一个像素的值。网络中的最后一层将代表输出;图像标签的模型预测。这一层将有 10 个神经元,神经元 i 中的值越接近 1,模型越认为图像具有标签 i

最初,我们将图的权重设置为随机值,这就是为什么最初的预测不会很好。选择隐藏层的数量和每层中神经元的数量是一个很难解决的问题,我们将跳过这个问题。出于教育目的,让我们假设有一个 10 个节点的隐藏层,看一个例子。

在这个例子中,图像的值被输入到模型中,我们通过网络向前移动来计算输出神经元的值。该模型认为图像是 4,因为第 4 个神经元的输出最接近最后一层的 1。

如前所述,目标是更新图的权重,以便更好地对数据进行分类。我们怎么才能让它做到这一点?为了做到这一点,我们首先需要定义一个损失函数,在做出预测后,它给我们一个量化的衡量模型表现好坏的方法。一个例子是平方误差损失。我们从图像的标签中知道它是 5,所以我们理想的是输出层的每个神经元都是 0,除了第 5 个应该是 1。下面是我们计算预测损失的方法:

如果模型在正确预测标签方面做得非常好,损失的总和将接近于 0。

使用损失函数和一些被称为“反向传播”的应用微积分(我们将跳过),我们可以找到我们应该如何调整权重以最小化损失函数。换句话说,我们可以找出方向(更大或更小)和每个权重应该改变的量,以便使图表更好地预测这个特定图像的。但是我们不希望它只学习预测这张图像,我们希望它能够预测数据集中的所有图像,并且能够推广到新的图像。所以我们只在反向传播建议的方向上稍微更新一下权重。如果我们对许多不同的图像重复这个过程很多次,网络将学习能够很好地分类手写图像的权重。

这已经很多了,让我们来回顾一下:

  • 网络有代表神经元的节点和代表连接权重的边。我们的目标是以这样一种方式调整权重,使流程能够学习完成一项任务。
  • 我们使用输入层将数据传递到网络中,其中每个节点的值对应于图像中的一个像素。
  • 然后,我们通过图表向前移动,计算训练示例的预测输出。网络的预测最初会很糟糕,因为权重是随机设置的。
  • 我们使用损失函数来计算错误程度的量化指标。
  • 使用损失函数,我们执行反向传播来确定方向,以及每个权重应该调整多少来最小化该训练示例的损失函数。**
  • 我们对权重进行少量更新,并对许多不同的训练示例进行重复

结论

一旦你看到神经网络是如何运作的,它们看起来更像是人工的而不是智能的。我希望从这本初级读本中,你能受到启发,进一步研究它们。为了简单起见,我们跳过了许多重要的想法,其中最主要的是反向传播,尽管它是大多数神经网络的核心,但对于这样的文章来说太“数学化”了。对于感兴趣的人来说,我们需要用 sigmoid 函数代替阶跃函数,因为反向传播依赖于微分,而阶跃函数没有导数。我们建立的特定网络被称为前馈全连接网络。在实践中,卷积神经网络可以更好地识别手写图像。最后,如果你想进一步探索机器学习的世界,我推荐 3blue1brown 的精彩视频系列 (~1 小时)。

神经网络:初学者用。由初学者。

原文:https://towardsdatascience.com/neural-networks-for-beginners-by-beginners-6bfc002e13a2?source=collection_archive---------9-----------------------

一个足智多谋的初学者指南神经网络的本质和实施

Photo by Bit Cloud on Unsplash

挺住!为什么要看一个初学者写的文章?答案很简单——我决定写一篇关于神经网络的文章,它是用一种简单的语言写的,即使像我这样的初学者也能理解,同时也足够足智多谋,可以帮助某人很好地掌握这一庞大的材料。

先决条件

您需要具备以下方面的基本知识:

  • 线性代数
  • 计算机编程语言
  • NumPy

你不需要擅长这些,但是如果你以前用过的话会容易得多。

密码

我在整篇文章中放了你需要的每一段代码,但是如果你想拥有整段代码,这里有 Jupyter 笔记本:

[## KrumovAI/从头开始的神经网络

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/KrumovAI/Neural-Networks-From-Scratch/blob/master/neural_network.ipynb)

介绍

神经网络。这是大多数普通编码人员在听到人工智能和/或机器学习这些流行语时首先想到的。虽然不是书中最基本的材料,但如果用初学者友好的语言来解释,它实际上是一个不错的起点。

在整篇文章中,我将带您开始一段旅程,从神经网络思想的最开始开始,带您通过使其学习的核心现代原则,最后向您展示一个从头开始的神经网络模型的一步一步的实现,其特点是完全连接、激活、扁平化、卷积和池层。这个实现很大程度上基于并受到了 Omar Aflak 的这篇令人惊叹的文章的启发,这篇文章是每个想要了解更多关于神经网络的数学背景的人的必读之作。

[## Python 中从头开始的数学和神经网络

制作自己的机器学习库。

medium.com](https://medium.com/datadriveninvestor/math-neural-network-from-scratch-in-python-d6da9f29ce65)

理解神经网络

神经网络的历史可以追溯到 1943 年,当时神经生理学家沃伦·麦卡洛克和数学家沃尔特·皮茨描绘了一个带有简单电子电路的人脑神经元模型,该电路采用一组输入,将它们乘以加权值,并使它们通过一个阈值门,该阈值门根据阈值给出 0 或 1 的输出值。这个模型被称为麦卡洛克-皮茨感知器。

McCulloch-Pitts perceptron | Source: Wikimedia Commons

一位名叫罗森布拉特的心理学家进一步发展了这一想法,他创建了感知器的数学模型,并将其命名为 Mark I 感知器。它基于麦卡洛克-皮茨模型,是让机器学习的最初尝试之一。感知器模型也接受一组二进制输入,然后乘以加权值(代表突触强度)。然后添加一个值通常为 1 的偏置(该偏置确保使用相同的输入可以计算更多的函数),并再次基于阈值将输出设置为 0 或 1。上面提到的输入要么是输入数据,要么是其他感知器的输出。

虽然麦卡洛克-皮茨模型在当时是一项开创性的研究,但它缺乏良好的学习机制,这使得它不适合人工智能领域。

罗森布拉特从唐纳德·赫布(Donald Hebb)的论文中获得灵感,即学习通过神经元之间突触的形成和变化发生在人脑中,然后提出了以自己的方式复制它的想法。他想到了一种感知器,这种感知器接受一组输入-输出示例的训练集,并通过改变感知器的权重来形成(学习)一个函数。

实施分四步进行:

  1. 用随机权重初始化感知器
  2. 对于训练集中的每个示例,计算输出
  3. 如果输出应该是 1,但却是 0,则用输入 1 增加权重,反之亦然-如果输出是 1,但应该是 0,则用输入 1 减少权重。
  4. 对每个示例重复步骤 2-4,直到感知器输出正确的值

这套指令是现代感知机的基础。然而,由于计算能力的显著提高,我们现在可以与更多的感知器一起工作,形成一个神经网络。

Source: mlxtend

然而,它们并不只是随机放在网络中,而是实际上是另一个构建块(层)的一部分。

一个层由感知器组成,这些感知器连接到前一层和下一层的感知器,如果这样的感知器确实存在的话。每一层都定义了自己的功能,因此服务于自己的目的。神经网络由输入层(获取初始数据)、输出层(返回网络的整体结果)和隐藏层(一个或多个具有不同大小(感知器数量)和功能的层)组成。

Source: cs231n.github.io

为了使网络能够学习并产生结果,每一层必须实现两个功能— 正向传播反向传播(简称为反向传播)。

Base Layer Class

想象一列火车行驶在 A 点(输入)和 B 点(输出)之间,每次到达其中一个点时都会改变方向。从 A 到 B 的过程从输入层提取一个或多个样本,并将其连续通过所有隐藏层的前向传播函数,直到到达 B 点(并产生结果)。反向传播基本上是相同的事情,只是方向相反-本课程以相反的顺序通过所有图层的反向传播方法获取数据,直到数据到达点 a。但这两个课程的不同之处在于这些方法内部发生的情况。

正向传播只负责通过函数运行输入并返回结果。没有学习,只有计算。反向传播有点棘手,因为它负责做两件事:

  • 更新层的参数,以提高正向传播方法的准确性。
  • 实现正向传播函数的导数并返回结果。

那么这到底是怎么发生的,为什么会发生。谜团在 B 点解开——在火车改变方向并通过所有层的反向传播之前。为了调整我们的模型,我们需要回答两个问题:

  • 模型的结果与实际产出相比有多好?
  • 我们如何最小化这种差异?

回答第一个问题的过程被称为计算误差。为此,我们使用成本函数(与损失函数同义)。

成本函数

有不同类型的成本函数进行完全不同的计算,但都服务于相同的目的-显示我们的模型离实际结果有多远。选择成本函数与模型的目的密切相关,但在本文中,我们将只使用最流行的一种方法——均方误差(MSE)。

Formula for Mean Squared Error(MSE) | Source: DataQuest.io

这是一个非常简单的函数——我们对实际输出和模型输出之间的差的平方求和,然后计算平均值。但是帮助我们的模型只实现 MSE 不会有任何显著的帮助。我们也必须实现它的衍生物。

但是我们为什么需要这个呢?因为臭名昭著的…

梯度下降

这里我们需要做的最后一件事是向我们的模型展示如何最小化误差。为此,我们需要一个优化算法(optimizer) 。同样,有许多种类的优化器都服务于相同的目的,但为了保持简单但仍然有意义的事情,我们将使用最广泛使用的一个,许多其他优化算法的基础。看这强大的梯度下降:

Graphical representation of Gradient Descent | Source: Medium

看起来不像听起来那么可怕,对吧?好消息,这是一个相对简单的概念。根据定义,梯度是一个有趣的词,表示导数,或者函数的变化率。

3D representation of Gradient | Source: OReilly

假设我们的模型是一个球。该表面表示误差的梯度(导数)。我们希望球滚下表面(下降)尽可能低,以降低高度(误差)。从数学层面来说——我们需要达到一个全局(或者至少是一个足够好的局部)最小值。

为了让球移动,我们需要以一定的速率更新我们的参数——称为学习速率。这是一个预定义的参数,我们在运行模型之前将它传递给我们的模型。这种参数被称为超参数,在我们的模型性能中有着巨大的作用。我的意思是:

Significance of Learning Rate | Source: analyticsvidhya.com

如果我们选择一个太大的学习率,参数将会剧烈变化,我们可能会跳过最小值。另一方面,如果我们的学习率太小,那么要达到令人满意的结果将花费太多的时间和计算能力。这就是为什么通过用不同的学习率值测试模型来调整这个参数是相当重要的。强烈建议从 0.1 或 0.01 的学习率开始,并从那里开始调优。

背靠背(传播)

现在,我们需要通过将适当的数据传递给反向传播方法来逐层更新模型的参数。反向传播有两个参数——输出误差和学习速率。输出误差的计算方式可以是成本函数的导数,也可以是前一层反向传播的结果(从 B 点到 A 点),如上所述,反向传播应该给出正向传播函数的导数。通过这样做,每一层向它的前一层显示它的错误。

换句话说,如果出于某种原因,我们有一个正弦层,它看起来会像这样:

现在我们已经得到了所需的两个参数,反向传播应该更新层权重(如果存在的话)。由于每种类型的层都是不同的,因此它定义了自己的参数调整逻辑,这一点我们稍后会谈到。

结束梯度下降

当每一层的反向传播完成,我们的列车到达 A 点时,它获取下一个样本(或样本集),并再次通过隐藏层的前向传播函数开始它的过程——只是这一次,它们应该表现得更好一点。这个过程不断继续,直到训练完成和/或达到最小误差。

现在我们已经解释了梯度下降背后的所有理论,下面是它在代码中的样子:

我希望这段代码片段能对算法本身给出更多的解释。唯一我们还没有完全覆盖的是我们可以在网络中使用什么类型的层以及如何实现它们。

基本层

对于初学者来说,似乎有很多种层可供选择,臭名昭著的全连接层无疑是最佳选择。

全连接的

全连接层是使用最广泛的类类型。其工作原理基于罗森布拉特模型,具体如下:

  1. 来自层的每一个感知器都链接到层的每一个感知器
  2. 每个环节都有一个加权值(weight)。
  3. 一个偏差被添加到结果中。
  4. 该层的权重保存在一个 2D 数组中,大小为【m】xn(其中 m 是前一层的感知器数量, n 是该层的感知器数量)。它们被初始化为随机值。
  5. 该层的偏差保存在大小为 n 的 1D 数组中。它被初始化为随机值。

Visual representation of Fully-Connected(FC) Layer | Source: cs231n.github.io

现在让我们来看看我们的实现:

正如你所看到的,只要你知道基本的线性代数,我们的 to 方法的实现并不复杂。虽然相对简单,但这是一个完全有用且优化的层实现,我们将很容易在以后使用它。

然而全连接层的唯一问题是它们是线性的。事实上,大多数层都有完全线性的逻辑。线性函数是一次多项式。仅使用这样的函数妨碍了模型学习复杂函数映射的能力,因此,学习是有限的。这就是为什么(按照惯例)在每个使用激活层的线性层之后添加非线性功能是好的。

活化层

激活层与任何其他类型的层一样,只是它们没有权重,而是对输入使用非线性函数。

这种激活函数的一个很好的例子是代表双曲正切的 tanh

Tanh compared to sinh and cosh | Source: Wikipedia

因为我们在开始构建模型时会用到它,所以我们需要实现它:

现在我们已经实现了最重要的两层,让我们继续实现整个神经网络类。

神经网络实现

有几种方法需要实现

  • 一个构造函数——这里我们需要传递超参数(学习率和历元数——我们的网络在输入数据集上运行的次数);必要字段的初始化
  • 添加层方法—传递层的实例;用于模型构建;可以(应该)用几次才能加几层;
  • 使用成本函数方法-指定训练模型时要使用的成本函数
  • 拟合方法——执行训练过程的方法的标准名称;这里是我们放置之前的渐变下降片段的地方
  • 预测方法—仅用于计算结果的方法的标准名称;一旦训练过程完成,它是有用的

代码是这样的:

您可能已经注意到在每个方法的末尾都出现了return self语句。我这样做的原因是它允许我们做方法链接。如果你不确定我在说什么,你马上就会看到一个很好的例子。

现在让我们将它付诸实践。我们将使用 MNIST 数据库对手写数字进行分类。可以从这里下载,也可以从 Keras 轻松导入。

因为像素值表示在范围[0;255],我们将把它缩小到范围[0.0,1.0]。

我们做的另一件事是让 y (结果)变得更方便一点(注意keras . utils . to _ categorial)。它的作用是在一个独热向量中表示数值结果:

5 =>【0,0,0,0,0,1,0,0,0,0,0】

这很有帮助,因为我们网络的输出层将由 10 个节点组成,每个节点保存一个输出值。由于理想情况下的输出是正确的独热向量,因此成本函数现在更容易完成其工作。

现在,让我们通过放置一些 FC 和激活层来构建我们的第一个网络:

我们只使用前 1000 个样本的原因是,如果我们使用所有的样本,运行时间会太长。在这种情况下,使用更多的样本会得到更好的结果,所以如果有时间,可以尝试更大的范围。

在我们运行这个之前,我们需要再添加一个最后的触摸——另一个预输出激活函数— Softmax 。它所做的是对一个概率分布数组中有 n 个元素的数组进行归一化,该数组由与输入数字的指数成比例的 n 个概率组成,或者简单地说,计算样本匹配某个类别的概率。

Softmax formula | Source: hackernoon.com

以及实现:

让我们再试一次,只是这一次我们将有 Softmax 激活作为我们的最后一层。

现在我们已经训练了我们的数据,让我们评估我们的最终模型。

估价

请记住,我们已经实现了一个用于教育目的的小型模型。它不会产生很高的结果。我强烈建议用它来玩,以获得更好的准确性。

为了评估我们的结果,我们将使用一个来自 sklearn 的简单实用程序,它显示了我们模型的准确性。

现在你知道了神经网络构建的基础,我们可以继续学习更高级的东西…

卷积神经网络(CNN)

使用 FC 层执行图像识别任务的主要问题是,它将每个像素作为一个单独的特征,这似乎不太正确,因为神经网络的目标是复制人脑。帮助我们的大脑识别视觉输入的不仅仅是随机的点,而是点的模式。这就是所谓的卷积相关过程派上用场的地方。

卷积和相关

图像处理中的卷积和相关几乎是相同的过程,只是在实现上有一点小小的不同。两者都取一幅图像 I ,基于另一个矩阵产生一个矩阵 O (称为滤镜特征图 ) F 。我的意思是

先说关联:

Visual representation of Correlation | Source: My Late Night PowerPoint Creations

让我们解释一下发生了什么。过滤器就像一个滑动窗口,一步一步地穿过数组,向右滑动直到到达行的末尾。然后向下滑动,从行的开始处开始。在每个位置,我们对滤波器 F 和输入图像 I 的相应窗口的点积求和。每个位置代表输出中的一个单元格。

那么卷积呢?

Source: Giffy

相关卷积的唯一区别是卷积*与同一个滤波器 F 一起工作,只是旋转了 180 度。*

Visual representation of Convolution | Source: My Late Night PowerPoint Creations

但是这对我们有什么帮助呢?

通过使用这种过滤器,通过我们的图像,我们提取的不仅仅是一个像素,而是整个像素区域,使我们的模型能够映射更复杂的图像特征,如线条和形状。

例如,如果你给一个卷积层一个猫的图像,它将能够识别像鼻子和耳朵这样的小特征。然后通过添加更多的卷积层,它可以识别更大尺度的特征,如头部或尾部。

其工作方式是每个卷积层有几个滤波器,都用随机数初始化。这背后的目标是让每个过滤器激活不同的特征(一个特征训练检测鼻子,另一个特征检测眼睛,等等。).

通常在处理 多通道图像(如 RGB) 时,您的滤镜将是三维的,深度等于图像通道数。这样你就只关注 2D 进程了。

填充和步幅

卷积和相关的问题是角点像素没有得到太多的关注,它们只被处理一次。如果你想改变这一点,你可以添加一个填充。

Visual representation of Padding | Source: My Late Night PowerPoint Creations

现在,即使是角落也会像图像的其他部分一样被处理。

然而,有时我们不想对每个像素都给予太多的关注(在处理较大的图像时非常适用)。让每个过滤器通过每个可能的位置有时是多余的。这就是为什么我们可以配置一个步幅。

步幅告诉我们的过滤器在到达下一个位置时应该滑动多少。步幅为 2 将在每次移位时跳过一个位置,这减小了输出的大小并使得计算量更小。

Visual representation of Stride | Source: My Late Night PowerPoint Creations

没有步幅基本上意味着步幅为 1——过滤器覆盖了所有可能的位置而没有跳跃。

实施

首先让我们列出我们的参数:

  • 滤镜数量——图层中有多少个滤镜
  • 过滤器尺寸——我们的过滤器会有多大
  • 填充 —我们将有多少零填充(我们将对这个使用元组格式 (x,y) ,其中 x 代表列零填充, y 代表行零填充)。
  • 步幅 —只是一个简单的数字,显示一个滤镜每张幻灯片应该移动多少个位置

NB! 因为我们要用随机值初始化我们的过滤器,所以使用 相关性 卷积 实际上没有区别,所以为了简单起见,我们将使用相关性。

这里有一个非常迭代(for-loopy)的方法来实现卷积层:

虽然有点容易理解,但它太慢了,因为它缺乏矢量化(使用 for 循环而不是基于数组的操作)。这就是为什么我四处挖掘,找到了一些非常有用的库方法,帮助我优化我的层:

不幸的是,我找不到一种简单的方法来对 in_error 的计算进行矢量化(我得到的最接近的方法是使用scipy . signal . convolve _ 2d,但它不适用于 stride),直到我意识到矢量化操作通常用于用低级语言编写的循环,所以我使用 Cython (一个库,它允许

更多关于 Cython 的信息,请访问他们的文档

现在我们已经有了所有的拼图,让我们组装我们的优化卷积层:

说到优化,我们将看到的下一组层将帮助我们避免 GPU 融化。

池层

合并图层的目的是减少先前卷积图层输出的空间大小。这有助于我们的模型,原因有二:

  1. 它降低了所需的计算能力。
  2. 它创建输入的较低分辨率版本。这个过程也被称为下采样。这有所帮助的原因是卷积层的过滤器通常被绑定到图像中的准确位置。具有小的移动或失真可能导致不期望的不同输出。下采样图像仍然包含较大的结构特征,只是排除了可能妨碍模型性能的精细细节。

一种可以用来解决这个问题的 下采样 的替代方法是首先在 卷积层 上使用一个 更大的步幅

在大多数 CNN 模型中遇到的通常模式如下:

  • 卷积层
  • 活化层
  • 汇集层

A typical CNN pattern | Source: jefkine.com

工作原理

汇集的工作方式有点类似于卷积相关。我们又一次有了一个窗口(称为)滑过我们的输入。然而不包含任何像过滤器/特征映射那样的数据。当一个池移动到一个位置时,它仅根据该位置的值计算结果(如平均值最大值*)。*

为了帮助您理解它是如何工作的,我们将实现最广泛使用的类型— Max Pooling Layer

最大池层

想法很简单—当池滑动到某个位置时,该位置的最大值存储在输出中。

Visual representation of Max Pooling | Source: My Late Night PowerPoint Creations

因素

这里的列表比卷积层的列表简单得多

  • 池形状 —池的形状,用一个元组来描述,一个好的默认值是(2,2)
  • 步距 —与卷积相同,一个好的默认值是 2(大多数情况下,匹配池的尺寸是好的)

履行

再次实现一个基类是一个好主意,因为一些操作对于所有的池层都是相同的(例如像初始化):

接下来是最大池:

我强烈建议您自己尝试实现平均池层

在我们建立第一个 CNN 模型之前,我们需要重新格式化我们的数据,以便它可以被其他层使用,如全连接。这是需要的,因为当我们解决分类任务时,最后的非激活层应该总是完全连接的。因为如果全连接的输入不是 1D 数组,那么它将会是一团乱麻,我们必须首先展平(将 N-D 数组转换为 1D 数组)数据。

展平图层

这可能是实现起来最简单的一层。我们的正向传播需要展平输入,反向传播需要将其重新格式化回初始形式:

现在让我们建立我们的第一个 CNN…

CNN 模型

我们将使用本文中实现的所有层来构建一个简单的 CNN:

现在让我们看看它的表现如何:

它应该比我们的普通网表现更好,尽管如果你玩它并有耐心等待训练过程结束,它实际上可以取得更高的结果。这里有一些关于如何建立一个更好的神经网络模型的有用资源…

附加链接

* [## 新手问“人工神经网络要用多少个隐层/神经元?”

人工神经网络(ann)的初学者很可能会问一些问题。这些问题包括什么…

towardsdatascience.com](/beginners-ask-how-many-hidden-layers-neurons-to-use-in-artificial-neural-networks-51466afa0d3e) [## EfficientNet:重新思考卷积神经网络的模型缩放

自从 AlexNet 赢得了 2012 年的 ImageNet 竞赛,CNN(卷积神经网络的简称)已经成为设计者

medium.com](https://medium.com/@nainaakash012/efficientnet-rethinking-model-scaling-for-convolutional-neural-networks-92941c5bfb95)

最后的话

感谢大家花时间阅读我的第一篇关于媒体的文章。我真的希望它能帮助你学到一些新的有用的东西,甚至可以帮助你开始学习数据科学和机器学习。

如果您有任何意见、想法或建议,我会非常乐意收到您的反馈,并会尽快回复。

图像参考

https://www . research gate . net/figure/Threshold-Logic-Unit-Source-Wikimedia-Commons _ fig 10 _ 264080882

[## 感知器

一种用于分类的感知器学习算法的实现。分类器导入感知器…

rasbt.github.io](http://rasbt.github.io/mlxtend/user_guide/classifier/Perceptron/) [## 用于视觉识别的 CS231n 卷积神经网络

目录:引入神经网络而不诉诸大脑类比是可能的。在…一节中

cs231n.github.io](http://cs231n.github.io/neural-networks-1/) [## 教程:了解线性回归和回归误差度量

人类大脑的构造是为了识别我们周围世界的模式。例如,我们观察到如果我们练习…

www.dataquest.io](https://www.dataquest.io/blog/understanding-regression-error-metrics/) [## 为什么是随机梯度下降?

随机梯度下降(SGD)是数据科学中最流行和最常用的优化器之一。如果你曾经…

medium.com](https://medium.com/bayshore-intelligence-solutions/why-is-stochastic-gradient-descent-2c17baf016de) [## 深度学习的难点在于

深度学习的核心是一个困难的优化问题。如此之难以至于在引进后的几十年里…

www.oreilly.com](https://www.oreilly.com/radar/the-hard-thing-about-deep-learning/) [## 机器学习中的梯度下降算法(及其变体)简介

介绍优化始终是最终目标,无论你是处理一个现实生活中的问题或建立一个…

www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2017/03/introduction-to-gradient-descent-algorithm-along-its-variants/) [## уакл:Sinh cosh tanh . SVG

504 × 504 пиксела. 240 × 240 пиксела | 480 × 480 пиксела | 600 × 600 пиксела | 768 × 768 пиксела | 1024 × 1024 пиксела.

bg.m.wikipedia.org](https://bg.m.wikipedia.org/wiki/Файл:Sinh_cosh_tanh.svg) [## 训练建筑分类器- II

这是 5 篇文章系列的第 2 部分:训练架构分类器:动机训练架构分类器…

hackernoon.com](https://hackernoon.com/training-an-architectural-classifier-ii-bf29eca3cfa6) [## 卷积神经网络中的反向传播

卷积神经网络(CNN)是多层感知器(MLPs)的生物启发变体…

www.jefkine.com](https://www.jefkine.com/general/2016/09/05/backpropagation-in-convolutional-neural-networks/)*

用于音乐生成的神经网络

原文:https://towardsdatascience.com/neural-networks-for-music-generation-97c983b50204?source=collection_archive---------5-----------------------

能否通过 AI 重现艺术家的创造力?

人工智能最新进展的一个令人兴奋的应用是人工音乐生成。能否通过 AI 重现艺术家的创造力?深度学习模型能否成为音乐人的灵感或生产力工具?这些问题把我们带到了创造力的定义,以及这些工具超出其自身研究兴趣的有用性。

人工音乐生成的目标

模拟人类的创造力

T 这方面研究的第一个目标是人工生成人类发出的音乐或者更具体的艺术家发出的音乐,比如莫札特。这里的一个挑战是创作原创作品,仍然尊重你期望听到的规则和经典模式。

开发一种工具来帮助艺术家进行创作

人工智能可以被用来增强艺术家的创造力吗?除了灵感,还可以通过提供一种工具来有效地开发他们的想法?我们已经看到了像 Ableton 这样强大的作曲软件是如何塑造了现在的音乐空间,比以往更加多样化。现在,AI 会把这种趋势扩大到什么程度?

Image by Clem Onojeghuo — Unsplash

音乐一代面临的挑战

“音乐是情感的速记”列夫·托尔斯泰

人工生成的音乐带来了许多挑战。我们首先需要决定如何对不同的音乐特征进行编码。然后,我们应该确保我们的作品尊重关于结构和力度的主要音乐规则。

“音乐有多个维度,相对差异可能比它们的绝对值更重要;最突出的两个是时机和音高。”[1]

力学

乐器发出的声音的音量。它通常使用作曲家所做的注释进行编码,从最弱音 ppp 到最强音 fff。

音色

这可能是最重要也是最难编码的音乐特征。

“听觉的属性,使听者能够判断两个不同的声音,相似地呈现并具有相同的响度和音高,是不同的”维基百科

如果一架钢琴演奏一个音符,然后一把吉他演奏同样的音符,同样的时间长度,同样的响度,你仍然可以很容易地区分这两种声音,因为这两种乐器的声音是不同的。这种区别在于声音的音色。这是因为乐器的每个音符都是一个包含多个频率的复合波。

粒度和时间范围

什么是时间离散化?通常使用的两种策略是基于最小单位将时间设置为相对持续时间:十六个音符;或者为弹奏的音符固定一个绝对持续时间:例如 30 毫秒。这最后一个策略也能在乐谱的诠释中捕捉到表现力,让作品听起来更人性化。

其他必须表现的音乐特征包括持续时间、休止符、节拍和音高。

Image by Steve Buissinne — Pixabay

最先进的音乐创作方法

H 在我介绍这一领域的几项研究之前,它并不详尽,但提出了一些有趣的解决问题的方法。

洋红色— 2016

这个由 Google Brain 开发的项目旨在为艺术家创造一个新的工具,供他们在工作和开发新歌时使用。他们开发了几种模型来产生音乐。

2016 年底,他们发表了一个用强化学习调整的 LSTM 模型。有趣的想法是使用强化学习来教会模型遵循某些规则,同时仍然允许它保留从数据中学习的信息。[2]

为此,定义了几个指标:首先,那些我们希望降低的,与惩罚相关的指标:

  • 音符不在调上
  • 平均自相关(log1 — log2 — log3): 目标是鼓励多样性,因此如果成分与自身高度相关,模型会受到惩罚
  • 笔记过度重复: LSTM 容易重复相同的模式,这里使用强化学习带来更有创意的方法

然后,我们希望与奖励相关的指标变高:

  • 以主音开始的作品
  • Leaps resolved: 我们希望避免尴尬的间隔,所以当间隔太大时,我们向相反的方向返回。在 RL 术语中:在同一个方向跳跃两次是负奖励
  • 具有唯一最大音符或唯一最小音符的作曲
  • 主题中的音符:模特演奏主题会得到奖励:代表一个简短音乐“想法”的一系列音符

这些标准定义了一种音乐理论规则。这些指标的改进程度取决于对特定行为的奖励程度。这样,我们可以更加强调一些被认为更重要的指标。例如,在这里,每当一个音符被过度重复时,就会给予一个很大的惩罚(-100),而对于一个独特的极值音符(+3),在作品的结尾会给予一个小得多的奖励。度量标准的选择以及权重定义了我们想要创作的音乐的形状。

最近,Magenta 团队使用 GAN 和 Transformers 生成了具有改进的长期结构的音乐。

在变形金刚的模型中,使用了相对自我关注。它根据标记之间的距离调节注意力。这种架构有助于捕捉音乐中自我指涉现象存在的各个层面。

Number of wins for each model. Error bars show standard deviations of mean. (Humans’ comparisons)

然后,这些模型被用来创建艺术家在创作时可以使用的创意工具。这是作为插件添加到 Ableton LiveMagenta 工作室的概念。

“Magenta Studio 是一个基于 Magenta 开源模型的音乐创意工具集合,既可以作为独立应用程序,也可以作为 Ableton Live 的插件。他们使用尖端的机器学习技术来生成音乐。”[3]

Image by Anton Shuvalov — Unsplash

MuseGAN — 2017 年

在这个项目中,为了应对音符的分组,用小节代替音符作为基本的作曲单位。因此,使用 CNN 生成一个又一个小节的音乐,这有利于找到局部的、平移不变的模式。[4]

本文中一个有趣的方法是使用的评估指标。我们希望我们的音乐具有的五个主要特征被定义并用于训练网络。然后,我们对它们进行评估,并评估预测的效果:

  • 空棒比率
  • 每批使用的沥青等级数量(从 0 到 12)
  • “合格票据”的比率。这里,超过三个时间步长的音符被认为是合格的。合格音符显示音乐是否过度碎片化。
  • 鼓模式:8 拍或 16 拍模式中音符的比率
  • 音调距离:测量一对轨道之间的和谐度。较大的音调距离意味着较弱的轨道间和声关系。

Wavenet — 2016 年

这是一个使用连续编码而不是离散编码的项目示例。该模型生成原始音频波形。因此,它能够发出任何声音,比如人声。[5]

该模型是 CNN,其中卷积层具有多个膨胀因子,并且预测仅依赖于先前的时间步长。应用包括钢琴作品的生成和语音生成。

MuseNet — 2019 年

这是 OpenAI 音乐生成模型。它利用最先进的 NLP 架构(大规模变压器模型)来预测序列中的下一个令牌。它可以结合不同著名作曲家以及不同音乐流派的风格。[6]

2D map of the cosine similarity of various musical composer and style embeddings — MuseNet

音乐生成的 Maia 方法

aia 是我在加州大学伯克利分校与 Edward T .和 Louis R .共同开发的一个研究项目,旨在为这一广泛的挑战提供一种可能的解决方案。

背景

我们一开始的意图是创造一个人工智能,它可以完成莫扎特未完成的作品以泪洗面安魂曲的第八个序列——莫扎特去世时,这首曲子只写到第八小节。

我们通过将音乐生成框架化为语言建模问题来解决这个问题。这个想法是将 midi 文件编码成一个记号词汇表,并让神经网络从成千上万个 midi 文件中预测下一个记号。

编码

我们采用了由 OpenAI 的技术人员 Christine Payne 提出的“Notewise”方法[7],将每首乐曲的持续时间、音高和动态编码成一个文本序列,从而产生 150 个单词的词汇量。

Description of the encoding

此外,为了增加我们的数据集,我们使用调制将每首曲子复制 12 次,每次都比下一个音符低一个音符。

标记化和排序

我们探索了为每首乐曲添加特殊标记,以便序列包含关于作曲家、音乐开始时间和结束时间的信息。

Special Tokens

我们还探讨了 ngram 标记化,它将一串 n 个连续的“单词”视为单个标记。动机是看看我们是否能更好地捕捉复合“单词”的语义,这些单词代表共同的和弦或旋律模式。最终,我们仍然坚持在最终模型中使用单字标记,因为与我们的数据集相比,任何更高阶的 ngram 都会大大增加词汇表的大小。

NGram Tokenization

接下来,编码的文本数据被分批成 512 个标记的序列用于训练。我们不是将它们切割成互斥的序列,而是将序列重叠,即每个后续序列与前一序列有 50%的重叠。这样,我们就不会在分割序列的点上丢失任何连续性的信息。

Sequence Overlap

两层堆叠 LSTM

第一个版本是使用递归神经网络架构构建的。特别是,我们使用了 LSTM,因为与 RNN 和格鲁相比,它额外的遗忘门和细胞状态能够携带关于音乐中长期结构的信息——这使我们能够预测长达 1 分钟的更长序列,听起来仍然连贯。我们的基线模型是一个两层堆叠的 LSTM,每个 LSTM 单元中有 512 个隐藏单元。我们使用嵌入层将每个令牌转换成一个向量。

LSTM architecture

为了确保我们生成的序列是多样的,而不是总是在预测中选择最有可能的下一个标记,该模型将根据其相应的概率从前 k 个最有可能的下一个标记中随机采样,其中 k 在 1 和 5 之间。

我们必须调整一些超参数,比如决定每个样本的序列长度。太短,你将学不到足够的东西来产生一串对人类来说连贯的音乐。太长的序列和训练将花费太长的时间而没有学到更多的信息。

优化我们的批处理大小也将允许我们权衡学习迭代与利用 GPU 的并发计算。我们使用网格搜索来寻找序列长度和批量大小的最佳组合。

Loss of our models

GPT —变压器

GPT 是基于堆叠在一起的变压器解码器的架构[8]。Transformer 是一个序列模型,它利用了自我关注,对于涉及长期依赖关系的生成任务,它已经产生了令人印象深刻的结果。它本质上是普通的 Transformer 模型,去掉了它的编码器块和交叉注意机制——因此它可以更有效地执行无人监督的任务。这使得它非常适合音乐表现。

GPT’s architecture

我们使用 6 层 GPT 模型,包括一个嵌入层、6 个解码器块和 1 个线性 softmax 层,它将为我们返回下一个预测令牌的逻辑。每个解码器模块具有 8 个自关注头,前馈层具有 256 维状态和 1024 维内部状态。

使用来自所有作曲家的数据,训练损失在大约 5000 次迭代后收敛。然而,我们决定将训练推进到 20 万次迭代(30 个历元)——这需要大约 60 个小时——来看看我们是否可以获得更高质量的生成样本。

Loss over 30 epochs

我们最初的结果不是特别一致,所以我们把训练集中在一个作曲家身上。

Loss over 100 epochs

总的来说,我们对更长序列建模的尝试受到了我们使用的 GPU 内存的阻碍。在每个序列中,它最多只能支持 512 个令牌。

进一步研究

为了提高我们的模型的长期保持能力,我们探索了最近的 NLP 模型,如 GPT-2 和稀疏变压器。

关于 GPT-2 模型,我们必须在使用预先训练的模型从头开始建造之间做出选择。第一种解决方案将允许我们利用模型被训练的大数据集,但是因为它被训练在文本上而不是音乐上,它可能不能很好地概括我们的数据集。第二种解决方案更有意义,因为该模型只从音乐数据中学习,但数据集的大小将减少总训练量,从而降低整体性能。我们决定采取第二种选择;然而,GPT-2 的二进制编码部分不适合我们的标记化和排序,这阻止了模型的良好表现。

估价

一个可以递归地、快速地、准确地应用于我们模型的量化指标是 BLEU 评分。BLEU 评估生成序列中使用的 ngrams 的数量,这些 ngrams 也存在于一些参考序列中。它被广泛用于评估翻译模型,并假设好的序列在微观层面上看起来与真实的序列相似。这是一个合理的假设,因为我们期望我们生成的作品包含相似的和声、节奏和风格。

然而,我们这里的问题与翻译问题完全不同。我们不是将一个特定的翻译与有限的几种表达方式进行比较。我们正在基于几个音符生成全新的音乐序列,包括其他成分,如创造力一致性

这有几个后果。首先,小的 ngrams 信息量较少。事实上,由于我们在参考文件中使用了大量的组合,我们预计 1 克的值为 1(我们不会在组合中使用新的音符),2 克和 3 克的值也非常接近 1。因此,关于这些 ngrams 的信息很少。此外,我们希望我们生成的作品具有某种的原创性。我们不想从训练数据中重新创建或重复现有的序列,而是真正创造一些新的和独特的东西,这些东西是由现有的音乐激发的——就像艺术家会做的那样。因此,高 n-gram 也应该不被重视,非常高的 n-gram 不被考虑。

基于所有这些考虑,我们构建了一个定制的 BLEU 分数。选择的权重为:

Weight table for the customized BLEU score

我们使用 BLEU 评分来比较我们的 LSTM 基线模型和一些真实的莫扎特作品。结果——在十几个序列上平均——对于 LSTM 是 0.25,对于真实数据是 0.14。这意味着我们生成的样本符合我们定制的标准。LSTM 作品产生的比真实作品更高的分数强调了过度拟合的存在,其中生成的音乐包含来自原始数据的大量重复。

对 GPT 来说,我们面临着不同的挑战。我们的 GPT 版本努力学习长期模式,结果在高 ngrams 或更多)上得分很低。这凸显出我们的新作品可能更具原创性,但也不太忠实于音乐规则,因此显示出更少的结构和更少的和声。

因此,为了将我们的 GPT 与基线模型和真实数据进行比较,我们可视化了累积的 ngrams (从 2 到 5)。总的来说,GPT 在每个累积的 ngrams 中得分较低,强化了之前观察到的模式。

Cumulated ngrams visualization

生成的音乐样本

Generated Music Sheet

结论和未来的改进

选择的编码决定了你正在创建的模型的范围和限制。选取 MIDI 文件的离散表示会导致原始连续音频文件中的信息不可避免地丢失。

另一种方法是直接处理声音文件。这也将有助于更好地分析木材。最近的研究开发了深度学习模型,可以将训练集的音色转移到输入文件,同时保留其音高。[9]

此外,为了应对随着时间的推移不断重复的模式的挑战,但在扩展或压缩版本中,有必要横向和纵向地看待乐谱,以更好地解释乐谱的重复模式和结构。

通过 Magenta 团队和 Flaming Lips 开发的水果精灵项目,了解如何使用这些机器学习模型为艺术家创造新的体验:

Fruit Genie: real-time intelligent musical instrument which combines Magenta’s Piano Genie model with a physical interface consisting of fruits

参考

[1] 陈志诚,安娜·黄,阿什什·瓦斯瓦尼,雅各布·乌兹科雷特,诺姆·沙泽尔,伊恩·西蒙,柯蒂斯·霍桑,安德鲁·M·戴,马修·D·霍夫曼,莫妮卡·丁库莱斯库,道格拉斯·埃克。音乐转换器:生成具有长期结构的音乐

[2] 娜塔莎·杰克斯,·顾,理查德·E·特纳,道格拉斯·埃克。具有强化学习的调谐递归神经网络

[3]品红工作室。【https://magenta.tensorflow.org/studio-announce

[4] 董浩文、萧文怡、杨丽嘉、易。MuseGAN:符号音乐生成和伴奏的多轨道有序生成对抗网络

[5] 亚伦·范德奥尔德、桑德·迪耶曼、黑加·曾、卡伦·西蒙扬、奥里奥尔·维尼亚尔斯、亚历克斯·格雷夫斯、纳尔·卡尔奇布伦纳、老安德鲁、科雷·卡武克库奥卢。WaveNet:原始音频的生成模型

[6] 佩恩,克里斯汀。穆塞内。 OpenAI ,2019 年 4 月 25 日,openai.com/blog/musenet

[7] 佩恩克里斯汀。克拉拉:一个神经网络音乐生成器。http://christinecleavey . com/Clara-a-neural-net-music-generator/。2018.

亚历克·拉德福德,卡蒂克·纳拉辛汉,蒂姆·萨利曼斯,伊利亚·苏茨基弗。通过生成性预训练提高语言理解能力

莱昂纳多·加布里耶利、卡明·塞拉、法比奥·维斯佩里尼、迭戈·德罗基尼、伊曼纽·普林西皮、斯特凡诺·斯夸蒂尼。音色修改和传递的深度学习:一项评估研究

期权定价的神经网络

原文:https://towardsdatascience.com/neural-networks-for-option-pricing-danielcotto-c24569ad0bb?source=collection_archive---------10-----------------------

金融中的人工神经网络

使用 R 在布莱克&斯科尔斯世界中学习

Photo by Alina Grubnyak on Unsplash

本文只是将深度学习应用于期权定价的一种尝试。特别是,主要目标是展示人工神经网络从数据集“学习”模型的能力。

具有多个隐藏层的人工神经网络(ann)已经成为从大数据集检测模式的成功方法。人工神经网络实现通常可以分解为两个独立的阶段:训练部分和测试部分。在训练阶段,人工神经网络从数据集“学习”模型,而在测试阶段,经过训练的人工神经网络可用于预测结果

该架构是由定义数量的神经元组成的不同层的组合。将前一层的神经元与后一层的神经元连接起来,可以使用来自前一步的输出信号作为下一层的输入信号。

激活函数ψ()增加了系统的非线性。虽然有许多函数,但为了本节的目的,我将只使用 ReLu 函数,定义如下:

为了评估性能,均方误差(MSE)

训练过程试图学习最小化损失函数的最优权重和偏差

由于期权价格的历史数据相当昂贵,我决定模拟它们。

已经假设股票价格遵循 gBM 以获得足够数量的股票价格。因此,模拟价值必须有足够的执行价格、到期日、利率和波动性。

根据这些参数,通过布莱克-斯科尔斯公式计算出了欧式看涨期权的价格。因此,假设它处于布莱克-斯科尔斯世界,即模型的所有假设都得到满足。

#BS_closed formula: EU_call_bs = function(S, K, r, sigma,t=0, T){
  d1 = (log(S/K)+(r+((sigma)^2)/2)*(T-t))/(sigma*sqrt(T-t))
  d2 = d1-(sigma*sqrt(T-t))
  return((S*pnorm(d1))-(K*exp(-r*(T-t))*pnorm(d2)))
}#Generate Dataset
sample<-sde::GBM(x=100,N=1000000,r = r,sigma = 0.8,T = 1)mydata <- NULL
mydata$Stock <- sample
mydata$Strike <- sample*runif(length(sample),min = 0.4,max=1)
mydata$Time <- runif(n=length(sample))
mydata$sigma <- runif(n=length(sample), min = 0.1, max = 0.8)
mydata$r <-runif(n=length(sample),min = 0.01, max=0.05)
mydata$BS <-  EU_call_bs(S = mydata$Stock, t = 0, T = mydata$Time, 
r = mydata$r, K = mydata$Strike, sigma = as.numeric(mydata$sigma));

一旦数据集建立起来,它就被分成两个子集:训练集和测试集。人工神经网络已经在训练集上进行了训练,然后在测试数据集上进行了评估。

#Split datasetsplit <- rsample::initial_split(mydata, prop = .7, strata='BS' )train <- rsample::training(split)
test  <- rsample::testing(split)# Create & standardize feature sets
# training features
train_x <- train %>% dplyr::select(-BS)
mean    <- colMeans(train_x)
std     <- apply(train_x, 2, sd)
train_x <- scale(train_x, center = mean, scale = std)# testing features
test_x <- test %>% dplyr::select(-BS)
test_x <- scale(test_x, center = mean, scale = std)# Create & transform response sets
train_y <- log(train$BS)
test_y  <- log(test$BS)

下图显示了用于人工神经网络的超参数。

#MODEL 1
model_1 <- keras_model_sequential() %>%
  layer_dense(units =  200,activation = "relu", input_shape = ncol(train_x)) %>%
  layer_dense(units = 130,activation = "relu") %>%
  layer_dense(units = 50,activation = "relu") %>%
  layer_dense(units = 1)  %>%

  # backpropagation
  compile(
    optimizer = "rmsprop",
    loss = "mse",
    metrics = c("mae")
  )learn_1 <- model_1 %>% fit(
  x = train_x,
  y = train_y,
  epochs = 45,
  batch_size = 256,
  validation_split = .2,
  verbose = TRUE,
)#MODEL 2model_2 <- keras_model_sequential() %>%
  layer_dense(units =  200,activation = "relu", input_shape = ncol(train_x),kernel_regularizer = regularizer_l2(0.001)) %>%
  layer_batch_normalization() %>%
  layer_dropout(rate = 0.2) %>%
  layer_dense(units = 130,activation = "relu",kernel_regularizer = regularizer_l2(0.001)) %>%
  layer_batch_normalization() %>%
  layer_dropout(rate = 0.2) %>%
  layer_dense(units = 50,activation = "relu",kernel_regularizer = regularizer_l2(0.001)) %>%
  layer_batch_normalization() %>%
  layer_dropout(rate = 0.2) %>%
  layer_dense(units = 1)  %>%

  compile(
    optimizer = "rmsprop", #optimizer_adam(lr = 0.01) 
    loss = "mse",
    metrics = c("mae")
  )
learn_2 <- model_2 %>% fit(
  x = train_x,
  y = train_y,
  epochs = 45,
  batch_size = 256,
  validation_split = .2,
  verbose = TRUE,
  callbacks = list(
    #callback_early_stopping(patience = 10),
    callback_reduce_lr_on_plateau(patience = 5))
)

在预测阶段,结果与在训练阶段得到的结果差别不大。

#Storing Predictionrisultati <- NULLrisultati$predcted_values_model_1<- model_1 %>% predict(test_x)
risultati$true_value <- test_yrisultati$predcted_values_model_2<- model_2 %>% predict(test_x)risultati$pred_value_model_1_converted <- exp(risultati$predcted_values_model_1)risultati$true_converted <- exp(risultati$true_value)risultati$pred_value_model_2_converted <- exp(risultati$predcted_values_model_2)risultati$S_K <- test[,1] / test[,2]risultati$Err_model_1 <- abs(risultati$true_converted - risultati$pred_value_model_1_converted )risultati$Err_model_2 <- abs(risultati$true_converted - risultati$pred_value_model_2_converted )

测试集前三行的预测结果是:

下面的图是两个模型的每个选项的实际价格与预测价格,产生了一条偏差很小的窄线。

plot(x=risultati$true_converted, y=risultati$pred_value_model_1_converted , cex= 0.001, xlab='Actual', ylab='Predicted Model 1')plot(x=risultati$true_converted, y=risultati$pred_value_model_2_converted , cex= 0.001, xlab='Actual', ylab='Predicted Model 2')

为了更好地查看结果,模型产生的绝对误差如下图所示。有趣的是,随着 S/K 的增加,两个模型有不同的行为。

plot(x=risultati$S_K, risultati$Err_model_1, xlab='S / K', ylab='|BS Price - Predicted model 1|',cex=0.01)plot(x=risultati$S_K, risultati$Err_model_2, xlab='S / K', ylab='|BS Price - Predicted model 2|',cex=0.01)

对模型进行更深入的分析并对参数进行微调肯定会改善结果。总的来说,在 Black & Scholes 世界中,人工神经网络提供了一种计算欧式衍生产品的好方法。

所有的模型都是错误的,但有些是有用的。

乔治·博克斯,1978 年

[1] R.Kristiansson,奇异衍生品与深度学习 (2019),KTH 皇家理工学院工程科学学院

[2]刘帅强,Cornelis W. Oosterlee,Sander M.Bohte,(2018)

[3] Robert Culkin,Sanjiv R. Das,金融中的机器学习:期权定价的深度学习案例 (2017)

[4]雅各布·迈克尔逊·孔林德、约翰·哈里斯和凯罗尔·普日拜特科夫斯基,使用机器学习对期权进行套期保值和定价 (2009)

[5] D.Stafford,期权定价中的机器学习 (2018),奥卢大学

神经网络|基础

原文:https://towardsdatascience.com/neural-networks-fundamentals-1b4c46e7dbfe?source=collection_archive---------7-----------------------

在这篇文章中,我将试图强调一些与人工神经网络相关的基础知识和基本概念。

Source: Liu Zishan

定义

人工神经网络(ANN) 是一系列算法,旨在通过模拟人脑运作方式的过程来识别一组数据中的潜在关系。这种系统通过分析例子来“学习”执行任务,通常不需要用特定于任务的规则来编程。

全球建筑

神经网络分为不同的层次:

  • 输入层:输入层神经元接收应该解释待分析问题的信息;
  • 隐藏层:隐藏层是一个中间层,允许神经网络模拟非线性现象。这被说成是“隐藏的”,因为没有与外界的直接联系。每个隐含层的输出是下一层单元的输入;
  • 输出层:输出层是网络的最后一层;它产生了结果,预测。

感知器

感知器是第一个也是最简单的神经网络模型,是人工智能领域著名的心理学家 Frank Rosenblatt 在 1957 年发明的监督学习算法。

这个网络之所以简单,是因为它只有两层:一个输入层和一个输出层。这种结构只涉及一个权重矩阵,输入层的所有单元都连接到输出层的。

感知器是用于二元预测的线性分类器,换句话说,它可以将数据分类或分成两类。

3D representation of linearly separable data

感知器操作

首先,简单感知器取 n 个输入值( x1x2 ,…, xn ),同样由 n+1 常量定义:

  • n 突触系数(或权重: w1w2 ,…,wn);
  • 偏置:激活函数等于 1 的神经元。像其他神经元一样,偏差通过一个权重(通常称为阈值)将其自身连接到上一层神经元。

然后,每个输入值必须乘以其各自的权重(),并且这些乘积的结果必须相加,以获得加权和。然后,神经元将生成两个可能值中的一个,这由总和的结果低于或高于阈值 θ 这一事实来确定。

加权和可以转化为两个向量 w (权重)和 x (输入)的点积,其中 w⋅ x = ∑ wixi ,那么不等式可以通过将 θ (阈值)移到另一边来解决。

此外,请记住,偏差就像一个神经元,其中的激活函数等于 1,因此这最后一个与其权重(阈值)的乘积意味着阈值乘以 1。因此,常用的符号包括用变量 b (用于偏置)代替阈值,其中b=θ

完成所有这些步骤会产生以下架构:

Schematic representation of the simple perceptron

一旦获得加权和,有必要应用一个激活函数。简单的感知器使用 Heaviside 阶跃函数将结果值转换为二进制输出,将输入值分类为 0 或 1。

Graphical representation of the Heaviside step function

Heaviside 阶跃函数在输入数据可线性分离的分类任务中特别有用。

多层感知器

多层感知器(MLP)由一个输入层、一个输出层和一个或多个隐藏层组成。所以,它不再是简单感知器那样的神经网络,而是复数形式的神经网络。如果 MLP 有 n 层,那么它有 n-1 个权重矩阵。

理论上,向隐藏层添加足够数量的神经元可能足以逼近任何非线性函数。

多层感知器架构:

Graphical representation of the Multi-Layer Perceptron

神经网络在将所有输入传递到所有层(直到输出层)后生成预测。这个过程称为正向传播。

神经网络的工作方式与感知器相同。所以,为了理解神经网络,必须理解感知机!

激活功能

激活函数,也称为传递函数,是神经网络的重要组成部分。除了将非线性概念引入网络之外,旨在将进入一个单元(神经元)的信号转换成输出信号(响应)。

该函数的名称来自其生物学等价物“动作电位”:一旦达到,就会导致神经元反应的兴奋阈值。

值得注意的是,由于偏置,有可能将激活函数曲线上移或下移,这意味着网络有更大的学习机会。

激活函数有两种:线性和非线性。

线性激活函数

这是一个简单的函数,其形式为: f(x) = x 。输入经过很少或没有修改就传递到输出。这完全是一个相称的问题。

Graphical representation of a linear function

非线性激活函数

非线性函数是最常用的,它可以分离不可线性分离的数据。非线性方程决定了输入和输出之间的对应关系。

主要非线性函数:

  • 乙状结肠:

sigmoid 函数(或逻辑函数)是一条“S”曲线,它产生 0 到 1 之间的输出,用概率表示。

Sigmoid function definition

Graphical representation of the sigmoid function

作为一个“更平滑”的版本,它优于 Heaviside 阶跃函数,但并非没有缺陷。事实上,sigmoid 函数不是以零为中心的,因此负输入可能会产生正输出。此外,它对神经元的影响相对较低,结果通常非常接近 0 或 1,因此它会导致其中一些神经元饱和。最后,指数函数使得该过程作为计算是昂贵的。

  • 双曲正切值:

双曲正切像前一个一样是一个 s 形函数;然而,由于其对称性,它通常比逻辑函数产生更好的结果。实际上,区别在于 TanH 函数的结果映射在-1 和 1 之间。它通常优于 Sigmoid 函数,因为它以零为中心。这个函数非常适合多层感知器,尤其是隐藏层。

Hyperbolic tangent definition

Graphical representation of the TanH function

除此之外,双曲正切函数也有与 Sigmoid 函数相同的缺点。

  • 整流线性单元(ReLU) :

ReLU 函数有助于解决上述函数的饱和问题。它是最常用的。

ReLU function definition

Graphical representation of the ReLU function

如果输入为负,则输出为 0,而如果输入为正,则输出为 z 。该激活函数显著增加了网络收敛,并且不会饱和。

但是,ReLU 函数也并不完美。如果输入值为负,神经元可能保持不活动,因此权重不会更新,网络不再学习。

为什么需要这个激活功能?

没有非线性激活函数,人工神经网络无论有多少层,都将表现为简单的感知器,因为对其层求和只会产生另一个线性函数。

应该使用哪个函数?

是回归还是分类问题?第一种情况,是二元分类情况吗?最终,没有更好的激活函数,这取决于要处理的任务。

价值函数

为了学习,感知机必须知道它犯了一个错误,以及它应该给出的答案。这是监督学习。为此,需要使用一个成本函数,其目的是计算误差,换句话说,量化预测 y_hat 和期望值 y 之间的差距。因此,有必要最小化成本函数,直到最优:这是神经网络训练。

为了定义成本函数 J ,可以使用均方误差:

Mean squared error (MSE)

其中:

  • m 是训练样本数;
  • y 是期望值;
  • y_hat 是预测值。

一旦对预测值和期望值进行了比较,信息必须返回到神经网络,因此它返回到突触并更新权重。这不多也不少于前面提到的正向传播的反向路径。它被称为反向传播。

如前所述,机器学习算法的目的是找到一个权重组合,以便最小化成本函数

延伸阅读:

[## 理解神经网络中的激活函数

最近,我的一个同事问了我几个类似“为什么我们有这么多激活功能?”,“为什么是…

medium.com](https://medium.com/the-theory-of-everything/understanding-activation-functions-in-neural-networks-9491262884e0)

梯度下降

在拥有更多权重从而拥有高维空间的情况下,就出现了一个问题:维度的诅咒。像蛮力这样幼稚的方法不能再用了。因此,有必要使用可行的方法来计算成本函数:梯度下降最流行的算法之一来执行优化。

让我们假设成本函数 J 是凸的:

Tridimensional representation of a convex function

横轴代表参数、权重和偏差的空间,而代价函数 J 是横轴上方的误差面。蓝色圆圈是初始成本值。剩下的就是往下走,但是从这里走哪条路最好呢?

要回答这个问题,必须改变一些参数,即权重和偏差。然后,它将涉及成本函数的梯度,因为梯度向量将自然地指示最陡的斜率。输入值是固定的,这一点很重要,因此权重(和偏差)是唯一可以控制的调整变量。

现在,想象一个球被扔进一个圆形的桶里(凸函数),它必须到达桶的底部。这就是优化。在梯度下降的情况下,它必须从左向右移动,以优化其位置。

从一个初始位置开始,观察倾斜角,以便画出该点的切线:这意味着计算导数。如果斜率是负的,球向右,如果斜率是正的,球向左。

但是缺少了一些东西,至少因为它是一个超参数:学习率( α )。坡度表示要走的方向,但并没有告诉球在那个方向应该走多远。这就是学习率的作用,它决定了每一步达到最小值的大小。

综上所述,梯度下降可定义如下:

Canonical formula for gradient descent

其中:

  • θ 是模型的参数(权重向量);

  • J(θ) 是代价函数 J 的梯度,换句话说,这是包含每一个偏导数的向量。我们将通过对函数求导一次得到它;
  • α 是的学习速率(步长),设定在学习过程之前。

学习率的选择仍然是一个开放性的问题,对于给定数据集上的给定模型,最优值无法通过分析计算得到。相反,足够好的学习率必须通过反复试验来发现,但是要注意,它必须随着时间的推移而降低。

为学习速率选择正确的值很重要,因为它一方面会影响学习速度,另一方面会影响找到局部最优(收敛)的机会。如果选择不当,该值可能会导致预测模型性能不佳的两个主要原因:

  • 过拟合:算法很好地适应了训练数据集,在现实中太好了,这是一个问题,因为它将不再能够概括数据。随着学习率的提高,每一步可以走更远的距离,但是会有超过最低点的风险,因为斜率是不断变化的。简单来说,损失函数在最小值附近波动,甚至可能发散;
  • 设定一个非常低的学习率可以让你自信地走向负梯度。较低的 α 更精确,但是计算斜率需要很多时间,并且导致收敛速度非常慢。

Left: α too small; Middle: decent α; Right: α too big.

有了好的学习率,经过几次迭代,应该会找到一个合适的最小值,然后球就再也下不去了。

最后,确定优化网络的最佳权重。

这就是梯度下降的全部内容:了解每个权重在网络总误差中的贡献,从而收敛到优化的权重配置。

随机梯度下降

然而,还有一个问题:梯度下降需要成本函数是凸的。换句话说,曲线完全在它的每条切线之上,并且这样一个函数的导数在其区间上增加。如前所述,它采用以下形式:∨。但是一个非凸的函数呢?

这一次,让我们假设成本函数 J 是非凸的:

Tridimensional representation of a non-convex function

在这种情况下,采取最陡的坡度是不够的。误差表面在视觉上变得更加复杂,难以理解,并且具有特定的特征,例如局部最小值和可能的鞍点。

因此,风险是导致一些迭代算法的阻塞,大大减慢反向传播,并且落在不是最小整体值(全局最小值)的位置上。

为了克服这个问题,可以使用随机梯度下降(SGD)。

Mathematical formula for SGD

除了外观,这一个更快。它提供了更多的权重波动,这增加了检测到全局最小值而不停留在局部最小值的机会。

事实上,没有必要测试并在内存中加载整个数据集以仅在最后调整权重。随机梯度下降将在每次迭代后完成,使得该过程作为计算变得更轻。此外,标准(或批次)梯度下降是确定性的:如果起始条件(权重)始终相同,那么结果也将始终相同。

进一步阅读:

[## AI 笔记:神经网络中的参数优化- deeplearning.ai

在机器学习中,你从定义一个任务和一个模型开始。该模型由架构和参数组成…

www.deeplearning.ai](http://www.deeplearning.ai/ai-notes/optimization/) [## 理解梯度下降背后的数学。

机器学习中一种常用优化算法背后的简单数学直觉。

towardsdatascience.com](/understanding-the-mathematics-behind-gradient-descent-dde5dc9be06e)

神经网络训练

  1. 用接近(但不同于)0 的值初始化权重;
  2. 发送输入层中的第一个观察值,每个神经元一个变量;
  3. 正向传播:神经元被激活的方式取决于它们被赋予的权重。传播激活直到获得 y_hat 预测;
  4. 将预测值与期望值进行比较,用代价函数度量误差;
  5. 反向传播:错误在网络中再次传播。根据它们在误差中的责任更新权重,调整学习率;
  6. 重复步骤 1 至 5,并在每次观察后调整权重,或者在一批观察后调整权重(批量学习);
  7. 当所有的数据集都通过了神经网络,它被称为一个时期。重复更多的时代。

延伸阅读:

[## AI 笔记:初始化神经网络- deeplearning.ai

为了建立一个机器学习算法,通常你要定义一个架构(例如,逻辑回归,支持向量…

www.deeplearning.ai](http://www.deeplearning.ai/ai-notes/initialization/)

关键要点

  • 感知器是第一个也是最简单的人工神经网络模型。人工神经网络以同样的方式工作;
  • 神经网络由一个输入层、一个或多个隐藏层以及最后一个输出层组成;
  • 输入值是固定的,突触系数(权重)和偏差是唯一可以控制的参数;
  • 神经网络的层数越多,就越深,但将它们相乘可能会适得其反;
  • 还有其他类型的人工神经网络,仅举几个例子,例如卷积神经网络(CNN 或 ConvNet)或递归神经网络(RNN);
  • 成本函数用于量化预测值和期望值之间的差距。由于权重的优化组合(神经网络训练),这必须被最小化;
  • 梯度下降是一种优化算法,也是迄今为止训练神经网络最常用的方法;
  • 知道方向和该方向上每一步的大小(学习率)是执行梯度下降的关键。最后一个必须仔细设置;
  • 过拟合和欠拟合是预测模型性能差的两个主要原因。

更多资源:

课程

阅读

神经网络:概括抽象

原文:https://towardsdatascience.com/neural-networks-generalizing-abstractions-7f4574f1619a?source=collection_archive---------23-----------------------

https://unsplash.com/photos/XookgCxFw6Q

神经网络,只要给出足够多的例子,就能区分猫和狗。然而,当进行区分时,对网络参与的详细研究显示,视觉网络对 T2 纹理非常敏感,而人类看到的是 T4 的轮廓。如果把猫的图片换成猫的形状的绿叶图案,人类还是会识别出它是猫。神经网络见榕树。

总的来说,神经网络似乎从这些微妙的结构差异中获得了大部分性能,而从未理解复杂的关系或构想“整体”。人工智能看不到森林或树木——它们都只是“树叶”。为了处理复杂的任务,就像寻找新的数学证明一样,神经网络将需要形成 抽象 ,并且还需要一种方法在这些抽象之间 概括 。那些是思想的轮廓。

想法气球

考虑一个正在观看数百万个 YouTube 视频的神经网络。它看到一个人拿着一个棒球,让它落入另一只手里。在目睹了棒球的类似事件后,我们希望神经网络能够说“啊,所有这些棒球在释放时都以抛物线方式下落……”抛物线行为是一种抽象,当其条件满足时,可以预测未来。

然后,观看沙滩球的视频,我们希望网络得出结论:“哦,这些沙滩球与棒球类似地下落,尽管它们以大致可预测的方式不同……”神经网络将这两种行为联系起来,在它们之间进行归纳——“沙滩球和棒球都服从重力。”

最后,假设网络观看气球的视频。“哇!这些与沙滩球和棒球不同,但它们做的是一种类似的事情,倒立!”这种网络可以查看所有物理学家的数据,并找到新的理论。那么,我们怎么去呢?

两步

神经网络体系结构的主要范例是创建一个单一的整体网络,一端是输入数据,另一端是输出数据。然后,通过训练,网络被修剪下来。我们看到许多迹象表明,这是而不是构建智能的最佳方式。相比之下,彩票假说是一个奇妙而令人困惑的例子。

彩票的过程很简单,尽管完全违背了的直觉。像平常一样,从一个随机加权的网络开始。像平常一样训练网络。然后,看看每个神经元连接:它要么开始变弱,而保持变弱,要么变强,要么它开始变强,并保持强或变弱。**只保留开始弱变强**的。没错。去掉神经连接,使* 开始*保持 。你不会想要这些的。很奇怪。**

然后,重置所有剩余神经元的权重为你从开始的随机值。是啊,把你刚刚学的东西都扔掉。而且,你不能使用一些新的随机权重——只有原来的随机权重才可以。现在,训练那个微小的网络,它将实现一个更高的最终性能,用更少的训练,只使用十分之一的处理能力。WTF?

显然,我们不知道自己在做什么,甚至盲目地磕磕绊绊也足以发现不可思议的进步。艾是一个果园低垂的果实。

神经网络架构的另一种模式可能会产生我们所寻求的抽象和概括:生成新的迷你网络,然后合并它们。怎么会?

假定翻译,假定共享状态

GANs 擅长获取一组数据,比如一个城市的照片,并将其转换为一组相关的数据——这个城市的一幅画,或者这个城市在秋天,而不是春天。如果我们创建一个迷你网络,其任务是的‘棒球坠落’视频转换成‘沙滩球坠落’视频,我们就有了功能类比的存在证据。

如果在两种行为之间有一个有效的类比,那么这意味着两种情况共享一个隐藏的状态。抽象概念。在我们的例子中重力。要搞清楚这一点,另一个小型网络是必要的:找到一个分类器,将棒球事件和沙滩球事件归类为相同的事件,尽管棒球和沙滩球在 T2 的其他情况下被归类为不同的事件。起初,分类器不能准确地识别重力效应的存在。它只看到“棒球”、“沙滩球”和“落垒/沙滩球”。在排除除重力之外的所有因素之前,你需要在配对之间进行大量的归纳。(并且,隐藏状态本身可以被概括和抽象——例如,将流体动力学与电磁学联系起来……它变得元。)

因为每一个事件群,棒球-沙滩球-气球,都由一个迷你 GAN 联系起来,并且它的区别特征由一个迷你分类器识别,所有这些事件都变成了一个相关现象的 GLOB 。当遇到新的系列事件时,您只需要为glob的一个成员训练一个迷你 GAN,以评估新事件是否属于该 glob 的类型。(“如果游泳的鱼不会像棒球一样落下,它们可能也不会像沙滩球一样落下。”)

Globs 可以训练一个单一的、统一的网络,用于任意两个成员之间的翻译,尽管这可能只值得定期进行。我们需要一段时间来消化和整合新的思想,所以这种局限性并不奇怪。并且,整个 glob 共享相同的隐藏状态,该隐藏状态先前由每个小型分类器识别,因此超级分类器可以从所有这些分类器一起提取相同的结论。不过,随着每一个球的成长,它也需要重新训练。

结婚戒指

如果我们的小型网络可以缝合在一起,而不是针对整个特定实例组进行重新训练,我们将接近一个可行的抽象概括机器。这就是模糊的地方。

彩票假设的运作原理是,如果你从一个单一的整体网络和随机权重开始,那么该网络会有一些子集(…并且你想要哪个子集是特定于随机权重的——因此,你必须将修整后的网络返回到原始的随机权重,而不是新随机权重),这将比任何其他子集训练得更快,结果更好。奇怪的是,精简到那个神奇网络的方法是只挑选“改进最多的”神经连接。

我认为,在我们所有公认的智慧之外,可能有一个相对简单的缝合迷你网络的过程。

以猫的照片为例-在网络的每一层,由于较小要素的存在,较大要素被识别出来。小花絮分层组合,反映了现实的组成性质。然而,图像的某些方面在神经元之间以模糊不清的形式传输,只有在网络的某个更高层才会变得清晰。也有这个完形在起作用。

如果我们想要结合许多小型网络,我们必须提取每个小型网络使用的组合特征——如果这些特征中的一些被多个小型网络共享,我们实现一些压缩。而且,我们必须保留那些模糊的东西,它们只有在更高的层次才会变得清晰。如果我们把这些模糊的东西缝合在一起,找到一种方法来重叠它们,我们就有了一个超级网络而不需要重新训练,它可以形成抽象,并在这些抽象之间进行概括。我想再买一张乐透彩票…

神经网络生成的上帝的羔羊鼓轨道

原文:https://towardsdatascience.com/neural-networks-generated-lamb-of-god-drum-tracks-45d3a235e13a?source=collection_archive---------11-----------------------

使用不同神经网络结构生成鼓点的实验。

Photo by Michael Dobrinski on Unsplash

介绍

从去年 10 月开始,我就有了实现一些简单的神经网络来生成音乐的想法。我当时在 Jupyter 笔记本上做了一些快速实验,最近我终于有时间重写代码并写了一篇关于它的博客。 LSTMetallica# neuralabeats已经做了类似的工作。两位作者都使用 LSTM 在他们选择的几个鼓轨道上进行训练。对我来说,我选择上帝的羔羊。

注:如果只对听成绩感兴趣,可以直接去成绩区。而代码可以在这里 找到

为什么打鼓?上帝的羔羊?

我的目标是敲鼓,这对我来说相当简单,因为在我决定出国留学之前,我一直和我的朋友在一个乐队打鼓。与《上帝的羔羊》相比,我们以前演奏的音乐要柔和得多,但我很欣赏克里斯·阿德勒的低音鼓技巧。(看看他在视频中演示的“简单”节拍。)此外,歌曲中还有更多有趣的鼓点图案。

选择 LoG 的另一个原因可能是因为与我喜欢的其他鼓手如史蒂夫·乔丹和亚伦·斯皮尔斯相比,它有更多的 MIDI 文件资源。

数据预处理

首先,让我们看看人类如何打鼓,以及为什么神经网络可能是产生鼓点的有前途的工具。演奏乐器是一门艺术,它可能受到多种原因的影响:情感、技巧、演奏者的技能等。然而,为了使音乐连贯,最重要的因素之一可能是过去演奏过的模式。

同样,我们可以认为打鼓是一个不断预测节奏的过程,我们要根据之前演奏过的节奏和模式来演奏。(当然,如果你在乐队演奏,需要考虑更多的信息,但这是另一个故事,我们在这里处理的是一个单一的鼓轨道。)

我没有直接在原始音频上训练模型,而是决定使用 MIDI 文件作为数据源,因为这种格式更容易为人理解,在调整模型时给我提供了更多的直觉。在谷歌上搜索一些关键词后,我能够找到一些 LoG MIDI 音轨。在这个实验中,数据预处理几乎花费了我 70%的时间,所以我会更详细地研究这个过程。

为了在 python 中处理 MIDI 格式,我选择使用 Mido 来解析 MIDI 文件。Mido 将 MIDI 文件解析为一个对象,它由几个音轨组成,一般来说,每个音轨包含一个乐器的所有音符。

[<midi track '' 68 messages>,
 <midi track '' 4015 messages>,
 <midi track '' 3946 messages>,
 <midi track '' 3340 messages>,
 <midi track '' 5430 messages>,
 <midi track '' 839 messages>]

每个轨道都有几条信息,控制如何以及何时弹奏音符。如下所示,信息类型“音符开”和“音符关”控制乐器(“通道”)何时播放。通道 9 指示打击乐器和‘音符’代表应该演奏的确切乐器。还有其他类型的信息,但对于这个实验来说,“note_on”是最重要的一种。打击乐器通常不需要“note_off ”,因为它们没有长度,尽管建议在音符打开时使用“note_off”。

{'type': 'note_on', 'time': 0, 'note': 49, 'velocity': 95, 'channel': 9}
{'type': 'note_off', 'time': 240, 'note': 49, 'velocity': 95, 'channel': 9}

有了这些知识,首先要做的是量化,这意味着将信号限制在一个离散的集合中。在这种情况下,我想让每个音符都精确地在 32 个音符上演奏。我知道这可能会扭曲三连音和六连音,但大多数音符可以量化为一个 32 音。下图给出了一些音符经过一键编码后的数据框视图,其中 1 表示播放,0 表示不播放。列中的数字代表仪器。例如 36:大鼓。因此,我们要做的是预测接下来的 32 个音符,根据我们之前的信息应该演奏什么乐器。

为了降低复杂性,我删除了列,只保留了最常用的 n (6 或 8)种乐器,你可能已经注意到了,我也忽略了速度。

还有另一种编码方法,您可以对工具的每种组合进行编码,并创建一个新的分类变量。例如,如果我们选择编码 4 种乐器,那么总共我们将有 2⁴ = 16 种组合。这正是# neural eats所做的。然而,我发现在我的例子中,图中所示的编码方案效果更好。

型号

长短期记忆(LSTM)可能是大多数人在使用神经网络处理序列数据时会想到的。据说 LSTM 能够记住长期的依赖关系。我在这里不再赘述,因为已经有大量的资源解释 LSTM。

另一方面,卷积神经网络(CNN)以图像分类、识别等而闻名,但最近的研究表明,它们也可以很好地处理序列数据。一个例子是 WaveNet ,这是一个最先进的文本到语音的生成模型。作者还表明,它可以用于音乐生成。

我用 Keras 构建并训练了这两个模型。在大多数机器学习项目中,我使用早期停止来防止模型过度拟合,特别是我们不希望模型产生与他们看到的完全相同的节拍。除了模型结构,我还试验了两种模型的不同长度,32 个音符和 128 个音符。下图显示了具有 128 个输入长度的两个模型的训练损失和验证损失。正如你所看到的,CNN 能够很快捕捉模式,但开始在训练集上过度适应,而 LSTM 慢慢改善,直到最后一个时代结束,它仍然优于 CNN。虽然在我增加了周期之后,模型能够进一步改进,但我发现在我的实验中,LSTM 在输入长度较短的情况下工作得更好。我本可以继续尝试不同的 LSTM 设置,比如有状态的 LSTM,甚至是 CNN 和 LSTM 的组合。然而,调整模型以获得最佳性能并不是这个实验的目标。

TensorBoard

结果

预期的

如果我们真的思考我们如何表述这个问题,它实际上并没有那么聪明。音乐中的大多数鼓点在大多数小节中都是重复的。最常见的模式是在每第四个小节的末尾添加鼓填充。从下面的鼓点音符可以看出,通常每行的结尾都有不同的节拍。比方说,如果我们将 32 个 32 音符拟合到一个模型,并要求它预测下一个音符。那么它只需要准确预测输入序列中的第一个 32 音符。困难的部分可能是检测这个 4-bar 循环和预测相应的鼓填充。

Source: https://alanlinmusic.blogspot.com/

除了查看评估指标之外,我决定通过直接听它在两种场景中生成的节拍来检查模型的质量。

首先,由于输入-输出设置,我们需要提前多步预测来创建模式,否则,模型只会提前一步进行预测。(一个 32 注)有几种方法可以做到这一点,其中一种是递归预测,这意味着我们把预测的结果带到下一个输入,递归预测,直到我们达到理想的长度。在递归设置中,我希望模型至少能以相同的长度复制给定的音符,并继续这样做直到结束。

第二个设置是连接所有提前一步的预测,以获得目标长度的鼓点。期望值应该更高,因为在每个时间步,模型都得到鼓手演奏的真实情况。一个好的模型不仅应该能够复制给定的节拍,而且还应该能够检测真正的歌曲所显示的鼓填充和循环

音乐时间!

最后,我们先来听听模型在这两种场景下的表现。

LSTM:递归

节拍全部由在 128 个输入长度上训练的模型生成。我在开始的时候连接了真实的输入,这样我们就可以听到模型实际得到了什么。你可以发现这个模型做得很差,它甚至不能检测到轨道 1 和 2 的 1 条形图案。第三轨道由在 32 个输入长度上训练的 LSTM 产生。幸运的是,它至少捕获了 1 barpattern,并重复生成它,直到结束。

LSTM Recursive

LSTM:直接

正如我们所预期的,由于模型每一步都获得了基本事实,因此模型不会重复预测。但是产生的节拍还是不太好听,尤其是音轨 1 的有线低音鼓。我猜它试图预测六连音,但被迫量化为 32 音。总的来说,我认为 LSTM 可以通过增加周期和减少合理批量的输入长度来改善。如前所述,人们也可以尝试不同的结构。在这篇文章中,我只想展示一个糟糕的模型和一个更好的模型相比听起来会是什么样子。如果你对更好的结果感兴趣,让我们继续。

LSTM Direct

CNN:递归

酷!看起来 CNN 不仅能探测到 1 个条形图案,还能“随机应变”一点。请注意,前 4 个小节是输入。

CNN Recursive

CNN:直接

生成的轨迹越来越逼真。

CNN Direct

模式条形图

除了直接听生成的音轨,我在想一个目测模型质量的方法。对于基数时间序列分析,有自相关图、时间图等。训练模型后,可以使用这些工具来检查残差,看看您的模型是否仍然遗漏了一些有用的信息。

然而,我们处理的是分类时间序列数据,分类变量缺乏自然顺序。最终,我找到了这篇论文,它展示了一些可视化工具,尤其是针对分类时间序列数据。其中之一是模式直方图,我认为比较生成的模式和真实的模式是一种很好的可视化方式。

基本思想是计算事件发生后直到期望时间的频率。例如,如果我们想要得到长度为 128 的低音鼓模式,我们得到所有出现的低音鼓及其后面的 128 个音符,以查看低音鼓在 128 个步骤中每一步演奏的频率。你可以看到下面的数字。低音鼓似乎是最常见的。(是克里斯·阿德勒……)一般来说,每个 8,16,32 音符等都有尖锋。

Bass Drum Pattern

Snare Drum Pattern

Open Hi-hat Pattern

Crash Pattern

如果我们直接将预测的模式条形图与真实的模式条形图进行比较,我们可以看到该模型能够捕捉整个低音鼓模式,对于小鼓,该模型可以检测到每第 16 个音符的尖峰,但似乎无法找到其间的模式。然而,仅仅通过视觉上的比较,很难发现低音鼓有什么不同。更好的解决方法是从真实值中减去预测值。

Patterns Comparison

我认为扣除后的值是某种鼓形预测的残差。如下图所示,一般来说,模型预测的演奏节拍比真实模式少,因为所有乐器都有显著的正差异(真实预测)。例如,这可以通过将阈值从 0.5 降低到 0.4 来解决。

Pattern “Residuals” Comparison

结论

用算法生成音乐并不是什么新鲜事。而且严格来说,经过训练的模型并没有真正“生成”鼓轨。模型的损失函数(二进制交叉熵)的设置只是简单地要求模型完全像 Chris Adler 那样运行,这是分类问题的典型设置。这个小实验中最接近的一个可能是让模型递归预测,但是正如我们可以看到的,模型往往在一定长度后重复相同的模式,而没有捕捉到长期结构。我们不能责怪模型,这只是基于模型训练的最安全的猜测。一些研究引入了额外的结构,如注意力 RNN 和回望 RNN 来解决这个问题。对于 CNN,模型检测长期结构的最直接的方法可能是增加输入的长度以包括大多数模式。

然而,为了更好地实现应用神经网络生成音乐的想法,有一些先进的神经网络结构,如生成对抗网络变化自动编码器。它们已经被应用到图像和音乐一代。实现一个生成网络来生成鼓点将是写另一篇博文的好主意。

[1]韦奥希,2008 年。分类时间序列的可视化分析。统计方法论5 (1),第 56–71 页。

[2]杨立春,周思燕,杨耀辉,2017。一个用于符号域音乐生成的卷积生成对抗网络。 arXiv 预印本 arXiv:1703.10847

神经网络直觉:1。平衡交叉熵

原文:https://towardsdatascience.com/neural-networks-intuitions-1-balanced-cross-entropy-331995cd5033?source=collection_archive---------15-----------------------

大家好!

这是我的第一篇媒体博客。创建这个系列的目的是为了更好地理解从神经网络的基础到损失函数、神经网络架构等等(不需要深入研究数学)。自从我开始深度学习生涯以来,我一直觉得在模型工程期间或解决问题/调试神经网络时,形成直觉对取得进展有很大帮助。这一系列博客文章(我希望以后继续)的主要目的是让洞察正在发生的事情,即使其中的数学部分很难理解。

PS:我也希望向你们学习:-)

问题:在解释什么是平衡交叉熵之前,让我们考虑一个物体(在我们的例子中是正文)检测问题。众所周知的文本检测架构是 DenseBox 和它著名的实现 EAST:一个高效准确的场景文本检测器。 DenseBox 接收输入场景图像并输出激活图(二进制或灰色),其中激活图中的白色区域表示文本区域,黑色或灰色区域表示背景。所以基本上有两类(文本和背景)并且使用的损失函数是二进制交叉熵。因为很明显,在任何给定的文本检测数据集中背景类实例的数量通常多于文本类实例的数量,所以训练神经网络可能使其偏向于输出更多的背景类而不是文本类。所以使用二元交叉熵,或者其他损失函数是行不通的。

我说的“照原样使用二元交叉熵或任何其他损失函数都行不通”是什么意思?

任何深度学习实践者都很清楚这样一个事实,即类不平衡会影响神经网络的性能。类别不平衡的问题可以通过在训练数据中添加不太占优势的类别的更多实例来解决。我不打算深究这个问题,因为有几种方法可以解决阶级不平衡的问题。

有没有什么优雅的方法可以在不修改数据集的情况下解决类不平衡的问题?

解决这个问题的一个方法是调整损失函数,就像 DenseBox 论文中所做的那样。

解决方案:

平衡交叉熵:

  • as mentioned in EAST paper

看着上面的方程,我们可以很好地发现二元交叉熵和平衡交叉熵之间的区别。它是变量 β

那么 β 意味着什么呢?

β =阴性样本数/样本总数。换句话说,β是样本的部分,它在数据集中占优势。1 — β表示另一类的分数(明显!).

β 如何帮助解决阶级失衡问题?

由于乘以 Y = 0 的项(1 — β),损失评估为一个非常小的值,从而导致小于(当β接近 0 时,例如 0.1,0.2)或没有(当β为 0 时)学习。正类的分数越小,Y=0 时的损失值越小。

请注意,在这种情况下,负类(Y=0)比正类(Y=1)更大。

简单来说,你 将损失函数中对应于主导类的部分乘以一个较小的值 ,即乘以次主导类的分数。这使得损失值非常小(当数据集中只有一个类时甚至为零),因此神经网络权重不会经常调整为输出主导类。

上述等式也适用于数据集中正类(Y=1)占优势的情况。在这种情况下,将 Y * log Yˆ乘以 1 — β,可以比实际情况进一步降低损耗。请注意,乘以 β或 1- β 取决于您选择的 β 是什么。

这是我对平衡交叉熵的理解,以及它如何帮助解决类不平衡的问题。请随意指出我博客中的任何错误,或者我对此的直觉是错误的。

干杯:-)

神经网络直觉:2。点积、Gram 矩阵和神经风格转移

原文:https://towardsdatascience.com/neural-networks-intuitions-2-dot-product-gram-matrix-and-neural-style-transfer-5d39653e7916?source=collection_archive---------6-----------------------

大家好!

今天我们要来看看已经用神经网络解决的一个有趣的问题— “图像风格转换”。问题是获取两幅图像,从一幅图像中提取内容,从另一幅图像中提取风格(纹理),并将它们无缝地合并成一幅看起来真实的最终图像。这篇博文是对Gatys 等人的文章一种艺术风格的神经算法的解释。艾尔(https://arxiv.org/abs/1508.06576)

让我们看一个例子来说明问题。

Top left is the content image, bottom left is the style image, result is the one on the right

有趣吧?下面我们来看看如何解决。

概述:让我简单介绍一下该解决方案

  1. 创建随机输入图像
  2. 通过一个预先训练好的主干架构传递输入,比如 VGG、雷斯内特(注意,在反向传播过程中不会训练这个主干)。
  3. 计算损失并计算相对于输入图像像素的梯度。因此,仅调整输入像素,而权重保持不变。

目的是改变输入图像,使其代表各个图像的内容和风格。

这个问题由两个子问题组成:1 .生成内容和 2。来生成样式。

问题— 1。生成内容:问题是生成一个包含内容图像中的内容的图像。

这里需要注意的一点是,图像应该只包含内容(就像内容图像的草图一样,而不是来自内容图像的纹理,因为输出应该包含与样式图像相同的样式)

解决方案:答案应该很简单。使用输入和目标之间的 MSE 损失(或任何相似性度量,如 SSIM,PSNR)。但是这里的目标是什么呢?如果对输出的风格没有限制,那么输入和内容图像之间的 MSE 就足够了。那么如何在不复制图片风格的情况下获取图片的内容呢?

使用特征地图。

卷积特征图通常是输入图像特征的非常好的表示。它们捕捉图像的空间信息,而不包含样式信息(如果按原样使用特征地图),这正是我们需要的。这就是我们在反向传播过程中保持主干权重固定的原因。

因此,输入图像特征和内容图像特征之间的 MSE 损失将起作用!

Content Loss

Backbone used is vgg16_bn

使用早期 conv 图层的要素地图可以更好地表现内容,因为它们更接近输入,因此使用 conv2、conv4 和 conv7 的要素。

SaveFeatures is used to save the activations of conv layers(for content/style/input) during a forward pass

MSE between input and content features

问题— 2。生成样式:问题是生成一个包含样式图像中样式的图像。

解决方案:为了提取一幅图像的风格(或者更具体地说,为了计算风格损失),我们需要一种叫做格拉姆矩阵的东西。等等,什么是克矩阵?

在谈论如何计算风格损失之前,让我先谈谈一些数学基础。

点积:

两个向量的点积可以写成:

(a)

或者

(b)

两个向量的点积是各自坐标乘积的和。

3blue1brown 的话说,点积可以看做是向量 a 在向量 b 上的投影长度乘以向量 b 的长度”。

或者用可汗学园的话来说, “可以看做与向量 b 同向的向量 a 的长度乘以向量 b 的长度”。

图(a)中的术语 |a|cos θ (重新排列为 |b||a|cos θ )本质上是邻边的长度(或投影向量‘a’如 3blue1brown 中的,),因此它归结为邻边乘以向量 b 的长度的乘积

那么这意味着什么呢?

用更直观的方式来说, 点积可以看做两个向量实际上是多么相似 。它们越相似,它们之间的角度就越小,如图(a)所示,或者各自的坐标就越接近,如图(b)所示。在这两种情况下,结果都很大。所以它们越相似,点积就越大。

但是这和神经网络有什么关系呢?

考虑表示输入空间特征的两个向量(更具体地,来自深度为 C 的卷积特征图的 2 个展平特征向量),它们的点积给我们提供了关于它们之间关系的信息。乘积越小,学习的特征越不同,乘积越大,特征越相关。换句话说,乘积越小,两个特征同时出现的次数越少,乘积越大,它们同时出现的次数越多。这在某种意义上给出了关于图像风格(纹理)的信息,而没有给出关于其空间结构的信息,因为我们已经展平了特征并在其上执行了点积。

现在从深度为 C 的卷积特征图中取出所有的 C 特征向量(展平的),并计算它们中每一个的点积(包括特征向量本身)。结果是克矩阵(大小为 CxC)。

Gram matrix

这就对了。

计算输入的 gram 矩阵和样式图像之间的 MSE 损失,就可以生成所需样式的输入图像了。

Summing MSE of Gram matrices for all layers, normalizing and computing a weighted sum in the end

Saving feature maps for style image

考虑从几个卷积层(在实验中)提取风格信息的特征图总是更好的。在上述代码中,使用了卷积层 2、4、7、10 和 13。

Computing gram matrix and style loss

最后,在反向传播之前将内容和样式损失相加,以获得输出图像,该输出图像具有来自内容图像的内容和来自样式图像的样式。

当损失处于不同的范围时,两种损失的正常总和可能不起作用。因此,内容和风格损失的加权总和应该是可行的。

Total loss

compute weighted sum of both losses and then backprop

注意,输入图像可以是任意随机张量,其值与内容和样式图像的范围相同。

我实施的一些结果:

查看我的 github repohttps://github . com/mailcorahul/deep _ learning/tree/master/papers/Neural _ Style _ Transfer,了解 pytorch 实现的论文Gatys 等人使用卷积神经网络进行图像样式转换。艾尔。

干杯-😃

神经网络直觉:3。密集物体探测的焦点损失—论文解释

原文:https://towardsdatascience.com/neural-networks-intuitions-3-focal-loss-for-dense-object-detection-paper-explanation-61bc0205114e?source=collection_archive---------2-----------------------

嘿大家好!

今天,在神经网络直觉系列中,我将讨论 RetinaNet:密集物体检测的焦点损失论文。本文讨论了 RetinaNet,它是一种单次目标检测器,与其他两级检测器相比速度更快,并且还解决了所有单次目标检测器的一个共同问题——单次目标检测器不如两级目标检测器精确。

论文链接:密集物体探测的焦损失

那么 RetinaNet 如何解决所有单次检测器普遍存在的不准确问题呢?像往常一样,让我们深入探讨一下单次检测器的核心问题,看看 RetinaNet 与其他的有何不同:-)。

问题:单次目标检测器不如两级目标检测器精确。

我们来看看为什么上面的说法是真的。

在传统的两级对象检测器中,第一级接收输入图像并输出区域建议,即对象可能存在的位置,并且第二级涉及将每个建议分类到哪个类别。这意味着两级检测器中的分类头通常接收包含更多肯定类别(即相关对象)的建议,并且所提供的否定(背景)样本的数量相对较少(或者在理想情况下甚至可能为零)。因此,分类头不会偏向负面(或背景)类别。这是至关重要的,因为神经网络有这种倾向,偏向于更经常显示给它们的类。

第一阶段接收输入图像并输出区域建议即物体可能存在的位置,并且第二阶段涉及将每个建议分类到哪个类别。

现在让我们看看在单级检测器中发生了什么——单次检测器通常接收输入图像,并输出图像中存在的对象(类)及其相应的边界框坐标。

他们是如何在单镜头中输出班级分数和盒子坐标的?

单发探测器使用来自更快的 R-CNN 的锚盒(或默认盒)的概念。锚点是分配给特征图中每个单元的逻辑框,相对于其进行边界框回归和分类。它们可以有不同的纵横比(取决于我们手头的问题)。我不打算进入锚的细节。这里的关键是不是用另一个神经网络(或任何算法)来生成区域建议,而是将特征图的整个网格视为区域建议,该区域建议又由同一个神经网络分类以产生类分数和边界框偏移。

单发探测器与 fast-RCNN 中的区域建议网络(RPN)相同,除了 RPN 执行前景与背景分类,而单发探测器执行多类分类,即包括所有对象类和背景。

没错。我们现在知道了单触发探测器的工作原理,但是这个过程是如何影响它们的精度的呢?或者更准确地说,这如何使它们不如两级检测器精确?

单发检测器中分类头将特征图网格中存在的每个锚点视为其输入的区域提议集。

Default boxes(or anchors) as mentioned in SSD: Single Shot MultiBox Detector

与包含负面或背景类别的锚的数量相比,包含正面类别(相关对象)的锚的数量非常少(例如 1:1000)。因此,与正样本相比,分类器获得更多的负样本(或者更具体地说,更容易的训练样本),从而导致更有偏向的学习。

如前所述,两级检测器通过级联分类器减少了背景样本的数量。

这就是为什么单级检测器的性能不如两级检测器的原因。请注意,这些准确性基准测试是使用 COCO 等标准对象检测数据集进行的。对于用户可能正在处理的其他自定义数据集,情况不一定如此。

SSD:单次多盒检测器 中,通过使用每个默认盒的最高置信损失对负样本进行排序,并挑选顶部的样本,从而使负样本和正样本之间的比率最多为 3:1,从而解决了这种类别不平衡问题。

现在让我们看看 RetinaNet 如何通过仅仅调整一个对象分类器的损失函数来以一种优雅的方式解决这个类不平衡的问题。

解决方案:本文的作者引入了一个称为焦点损失的损失函数,它对容易分类的例子(即我们案例中的背景)进行惩罚。

考虑用于分类的典型交叉熵损失

Cross entropy Loss

y ∈ {±1} specifies the ground-truth class and p ∈ [0, 1] is the model’s estimated probability for the class with label y = 1

这里要解决的问题是分类损失被来自“简单背景”示例的贡献淹没——如果一个示例不能很好地解释特定类的模式(或者几乎不能帮助区分该类和其他类),则该示例可以被称为简单

这种简单的例子被很好地分类,即概率> > 0.5,因此它们对损失的贡献非常小。但是如果这样的例子远远多于正面例子的数量呢?—阴性与阳性的比例为 10000:1。那么它对损失的贡献是巨大的,从而造成网络偏向背景类。

Focal loss

为了避免这些简单的例子对损失的贡献,1-它们的概率乘以它们的原始损失值,最终减少它们的损失。

因此,如果一个例子很容易分类,那么它的概率 p 将是> > 0.5(接近 0.9–1.0),而 1-p(接近 0)导致 C.E .产生一个非常小的值,最终导致该例子的学习非常低或没有学习。γ项是聚焦参数,它调整简单示例的向下加权速率。

A Balanced C.E variant of Focal Loss is usually used

使用平衡交叉熵(看看我在本系列中的第一篇文章调制因子(1pt)^γ)的组合,因为它产生了更好的精度,如本文所述。

看一下上图,它更直观地给出了如何通过使用调制因子来减少良好/简单分类示例的损失。

这里要注意的另一件重要事情是,它们显示了与 SSD 中使用的硬负挖掘相比,单独使用焦损失如何产生更好的结果。

RetinaNet 架构: RetinaNet 使用带有 Resnet 主干的功能金字塔网络(FPN)。FPN 包括在进行预测之前添加顶层要素地图及其下的要素地图。将顶层特征图与下面的特征图相加通常涉及放大顶层图,使用 1x1 conv 对下面的图进行维度匹配,并对两者进行元素相加。查看用于对象检测的特征金字塔网络论文,了解关于 FPN 的更多详细信息。

训练视网膜网:另一个更重要的方面是在开始训练之前初始化前景类的模型概率。所有正面锚被分配 0.01 的先验概率,以便它们对损失有更大的贡献,并确保大量负面例子不会妨碍初始阶段的训练。

这是我对密集物体探测的纸焦损失的解释。如果我的理解有漏洞,欢迎提问或指正。

干杯:-)

神经网络直觉:4。联结主义时间分类

原文:https://towardsdatascience.com/neural-networks-intuitions-4-connectionist-temporal-classification-9bd042bdcb3a?source=collection_archive---------17-----------------------

乡亲们!

今天我要讲一个我花了很长时间(真的很长时间)才理解的话题,包括使用的动机和作用- 联结主义时间分类(CTC)

在讲 CTC 之前,我们先来了解一下什么是序对序模型:-)

序列对序列模型: 这些是神经网络,它们接受任何序列——字符、单词、图像像素,并给出输出序列,该输出序列可以与输入序列在同一域或不同域。

序列到序列模型的几个例子:

  1. 语言翻译问题 —其中输入是一种语言的单词序列(一个句子),输出是另一种语言的单词序列。

  2. 语音转文本问题— 其中输入是音频序列,输出是音素序列。

递归神经网络通常用于此类序列到序列问题,因为网络不仅要考虑当前输入,还要考虑之前和之后的输入,以便进行预测。**

那么,序列到序列模型与连接主义时间分类(CTC)有什么关系呢?嗯,CTC 是一种算法,用于解决训练 seq-2-seq 模型时面临的一个关键问题,即当输入和输出序列的长度不匹配时的。****

让我深入一个我以前处理过的问题来揭开 CTC 的细节:-)

单词识别 : 问题是预测一幅图像中存在的单词。解决这一问题的一种方法是将其视为序列间问题,并使用卷积和递归神经网络的混合架构。CRNN 的架构如下:

An End-to-End Trainable Neural Network for Image-based Sequence Recognition and Its Application to Scene Text Recognition - Baoguang Shi et al.

这里,输入序列是卷积特征图,输出将是字符序列。

为了更好地理解到底发生了什么,让我来解释一下流程:

  1. Conv 网接受输入单词图像,比如大小为 WxHx3,并产生卷积特征量,比如大小为 W/2×H/2×D,其中 D 是特征量的深度。
  2. 现在,大小为 1 x H/2 x D 的每一列都作为输入(注意,有 W/2 个这样的列)提供给 RNN,后者又从词汇表集中产生一个字符作为输出。
  3. 因此,CRNN 试图预测出现在特征图的每一列中的字符。请注意,一个列可能包含也可能不包含字符,这就是为什么多使用了一个输出标签—空白'-'(检查上图的输出)。

Baoguang Shi et al.

有人可能会问,在图像的情况下,时间依赖性是什么。因为特征图是分开的,并且对每一列都进行预测,所以一个完整的字符不太可能落在一列中。因此,字符的模式学习不仅依赖于当前列,还依赖于它之前和之后的列。

让我们看一下 RNN 的输出,以便搞清楚。

1. input image

2. predicted sequence from RNN

3. decoded output

注意,解码输出(3)是通过折叠重复字符并从来自 RNN 的预测序列(2)中移除空白字符(如果有的话)而形成的。****

为了清楚起见,让我先定义一些东西:

a. 输入 _ 序列 :长度为 W/2输入 序列,反馈给 RNN。

b. 预测 _ 序列:RNN 输出的 预测输出 长度为 W/2 的序列。

c. 目标 _ 序列:地面实况输出** 序列长度 W/2。**

d.解码 _ 序列:解码输出 序列的长度 ≤ W/2。

而训练这样一个网络,我们有的只是 < 1。输入图像,请按 3。解码输出> 对作为训练实例。但是神经网络给出预测序列作为输出,其长度不等于解码输出的长度。

在计算损失时,长度为 W/2 的预测序列不能与长度≤ W/2 的解码序列进行比较。

  • 注意:我们假设输入和预测序列是同步的。即顺序将是相同的。

问题: 所以为了训练这个网,我们需要知道target _ sequence是什么。但是我们如何得到那个目标序列?我们当然不能注释长度为 W/2 的序列中的每个时间步长(那是不可能的!).**

解法: 使用合理的启发式猜测目标 _ 序列。是的,你没看错。对目标 _ 序列进行初步猜测。考虑上面的输入图像,该输入的解码输出是什么?

解码输出→ “状态”

假设目标序列/预测序列(即 RNN 的输出)的长度为 14。现在我们来猜猜 target_sequence【SSSTTAAAATTEEE】(后面再看空白字符)。

假设我们有一个 target_sequence,我们可以在第一步使用该序列训练网络,然后使用网络的预测作为新的 target_sequence(用于下一步),并在训练期间反复迭代它——迭代和估计。

但是这里有一个关键问题。我们如何确保网络预测的目标序列在解码时给出我们想要的输出,在我们的例子中是状态

如果 RNN 输出“ RRRRAAAEEELLLL ”会怎样?我们不能将该输出序列用作训练过程下一步的新目标序列。因此,我们需要对 RNN 预测的序列施加一些限制。

约束 1: 不考虑整个词汇(字母 A 到 Z)的预测,只考虑作为解码输出一部分的字母。

在我们的例子中,字母 T,A,E 是解码输出“状态”的一部分。

Considering only target alphabets. Most probable character for a given timestep is highlighted in orange. For example sake, I have highlighted only 5 steps(decoded output for this eg. is SATAE)

好了,这确保了我们的网络产生一个预测序列,它只包含解码输出中的字母。但是对字母输出的顺序没有限制。

例如:RNN 输出“ SSAAAATTTAAEEE ”,它仍然只包含目标字母,但是当解码时产生 SATAE 而不是状态。

约束 2: 为了确保网络输出一个序列,该序列在解码时给出我们想要的折叠输出,让我们施加以下约束:

不仅要考虑字母 S、T、A、E,还要按照各个字母在解码输出中出现的顺序对它们进行排序(即使这些字母必须重复)。

Use Viterbi algorithm(dynamic programming) to compute the best path from a set of all possible paths starting from S ending with E.

现在,修复第一个输出应该始终是左上角的符号,最后一个输出应该始终是右下角的符号,并且顺序应该始终严格地从上到下,即没有向上移动。从左上符号到右下符号的每条路径都被认为是有效的序列/对齐,因为它总是解码为有效的“解码序列”。

将每个时间步长的每个输出符号可视化为图中的一个节点,边用箭头表示。每个节点的分数是它在该时间步来自网络的概率,边分数是 1。序列(或路径)的分数是包含在其中的所有节点的概率的乘积。

子问题: 给定一组这样的有效序列,找出最可能的序列?

: 这个问题是用维特比算法(动态规划)解决的。

一旦我们确保预测的序列是有效的序列(或比对),我们可以使用 迭代和估计 方法来训练网络。也可以使用在类似任务上受过训练的预训练的 RNN,以使训练过程更加稳健。

但所有这些都严重依赖于如何猜测初始目标序列以及如何在训练期间计算 target_sequence (使用维特比算法的最大可能序列)。因此这种方法不是最佳的。

我们不是选择最可能的序列,而是对所有可能的有效序列使用一个期望值。这同样可以使用动态编程来计算,并且所使用的算法被称为CTC-前向-后向算法** 。我不打算进入向前-向后/维特比算法的细节,因为它对我来说仍然是一个灰色地带。**

最后,考虑输出有重复字符的情况。设输出字为 【字母】预测 _ 序列llleetttteerr现在,当这个预测序列折叠时会发生什么?

我们得到的解码输出为【LETER】,这是不可取的。

因此,为了考虑输出域中的重复字符,将空白字符(-)作为词汇表的一部分。基本上,当词汇表中没有符号出现在该时间步长时,神经网络输出一个空白字符。

因此,代替产生"llleetttteerr",一个带有空白作为词汇一部分的 RNN 现在可能输出"--L-EE-TT-T-E-R ",当解码时产生 "字母"

由于包含了一个空白字符,它可能出现在target _ sequence的任何地方,我们将目标字母+空白排列如下:

Blanks are inserted before and after every target alphabet. Note that only few timesteps are shown in the above diagram.

现在让我来分解一下术语 【连接主义者时态分类】 看看它到底是什么意思?

我们的解决方案现在可以标记(或预测)序列中的每个时间步长。标记未分段数据序列的任务称为时间分类,因为我们使用 RNNs 来标记未分段数据,所以它被称为连接主义时间分类[1]。

[1]如连接主义时间分类中所述:用递归神经网络标记未分段的序列数据— Graves 等人

为了更清楚,这里未分段的数据序列是我们的解码输出,分段的数据序列将是目标序列,我们使用 RNN 来标记它。

我希望你们都有直觉,对于输入和输出序列长度不匹配的序列间问题,神经网络是如何训练的。

我的博客文章是从这个关于 CTC 的精彩的 CMU 演讲中得到启发的:https://www.youtube.com/watch?v=c86gfVGcvh4。看一看吧!

干杯:-)

神经网络直觉:5。锚点和对象检测

原文:https://towardsdatascience.com/neural-networks-intuitions-5-anchors-and-object-detection-fc9b12120830?source=collection_archive---------7-----------------------

大家好!欢迎回到我的神经网络直觉系列。

今天我将谈论一个在物体检测器中引入的优雅的概念——,它们如何帮助检测图像中的物体,以及它们与传统的两阶段检测器有何不同。

像往常一样,让我们看看这些锚被引入作为解决方案的问题:-)

在从锚开始之前,让我们看看两级对象检测器是如何工作的,以及它们实际上如何促进单级检测器的发展。

两级对象检测器: 传统的两级对象检测器分两次检测图像中的对象:

  1. 第一遍 :第一遍取入输入图像,输出可能存在物体的区域(称为区域建议或感兴趣区域)。这个过程既可以通过外部算法(例如:选择性搜索)来执行,也可以通过神经网络来执行。
  2. 第二遍: 第二遍是一个神经网络,它接收这些感兴趣的区域,并将其分类为一个目标对象类别。

为了简单起见,我要讲一个著名的两级检测器——fast——RCNN。 两者都通于更快——RCNN 包含一个神经网络。

(一)。第一个神经网络预测物体可能出现的位置(也称为客观分数)。它基本上执行前景(对象)对背景分类。这个网络被称为区域建议网络,又名 RPN。

㈡。在提取区域提议之后,来自输入图像的相应位置被裁剪并被馈送到下一个神经网络,以在比方说 N 个目标类中执行分类。这个网络预测在那个位置存在什么物体。

步骤(ii)似乎非常琐碎,因为它归结为图像分类,其中对象裁剪被分类为 N 个类别之一。

让我们深入研究第一步。

(a)这个神经网络如何预测这些物体的位置?

(b)如果可以训练神经网络来执行前景与背景分类,那么为什么不训练它来一次预测所有 N 个类别?

(a)的解决方案是锚,( b)的答案是肯定的,我们可以有一个单一的网络来执行 N 路对象检测,这样的网络就是广为人知的单次对象检测器。你没看错。单触发检测器几乎与 fast-RCNN 第一遍中的网络相同。

我说 SSD 是 几乎与 RPN 的 相同,因为 在概念上 两者相同,但在 架构上有*

问题: 神经网络如何检测图像中的物体?

解(1) —单个物体检测: 让我们举一个在图像中寻找单个物体的最简单的例子。给定一幅图像,神经网络必须输出图像中对象的类别及其边界框坐标。所以网络必须输出 4+C 个数字,其中 C 是类的数量。

这可以通过将输入图像通过一些卷积层集合并在末端使用全连接层来直接完成,该全连接层将最终的 conv 体积转换成 4+C 维的向量,其中前四个数字表示物体位置(比如 minx、miny、maxx、maxy ),接下来的 C 个数字表示类别概率分数。

解决方案(2)——多物体检测: 这可以通过将上述方法扩展到 N 物体来实现。所以网络现在输出的不是 4+C 个数字作为输出,而是 N(4+C) 个数字。*

取一幅尺寸为 H x W x 3 的输入图像,让它通过一组卷积层,得到一个尺寸为 h x w x d 的卷积体,其中“d”是深度或通道数。

Pass image through ConvNet to get an output feature map

考虑上面的输出卷积量。假设该卷的大小为 7 x 7 x 512。应用大小为 3 x 3 x 512 的 N 个滤波器,跨距=2,填充=1,产生大小为 4 x 4 x N 的输出音量。

让我们看看这个大小为 4 x 4 x N 的输出,并尝试推断它的含义。

在输出特征图中有 16 个细胞,我们可以说每个细胞在图像中的某个点有一个感受野(或视野)。并且每个这样的单元都有 N 个与之相关联的数字。正如我之前指出的,N 是类的数量,我们可以说每个单元都有关于什么对象出现在特征图中相应位置的信息。以同样的方式,有另一个平行的 conv 头,其中大小为 3×3×512 的 4 个过滤器被应用于相同的 conv 体积,以获得大小为 4×4×4 的另一个输出,这对应于边界框偏移。

这就对了。现在我们知道了如何从单个神经网络中做出多个物体预测。但是等等,我们如何用这个 4 x 4 x N 输出的网格来计算损耗呢?

现在,让我们深入了解我们在输出层使用的 N 个滤波器。从这 N 个滤波器中只取一个,看看它是如何在特征图上卷积得到输出的。

3 x 3 filter convolved on a 7 x 7 feature map(shown in 2d) at stride = 2.

这个 3x3 过滤器可以在 16 个唯一的位置上围绕 7x7 网格移动,并进行预测(如前所述),这是非常明显的。

我们知道,网格中的 16 个单元中的每一个都对应于它之前的层中的特定位置。看下图。我们看到输出网格中第一个单元格的参考框大小为 3x3。

The 1st cell can be associated with a particular location in the input image from which the prediction was made.

类似地,输出中的每个像元都可以与输入图像中进行预测的特定位置相关联。

因此有 16 个这样的参考位置(大小为 3×3),每个位置都有自己相对于输入图像的坐标。现在,在这些参考的帮助下,我们可以实现两个目标:

  1. 分类损失 :如果 N 个对象中的一个落在这 16 个参考位置中,即具有与地面真实对象框的交集(IOU) ≥某个阈值,那么我们知道要匹配什么地面真实向量。
  2. 回归损失 :我们到底为什么需要这个?假设物体落入这些参考框之一,我们可以简单地输出这些参考位置相对于输入图像的实际坐标。原因是因为物体不必是方形的。因此,我们不是天真地输出一组固定的框坐标,而是通过输出 4 个偏移值来调整这些参考位置的默认坐标。现在我们知道了地面实况框坐标和相应的参考位置坐标,我们可以简单地使用 L1/L2 距离来计算回归损失。

与图像分类任务不同,在图像分类任务中,我们只有输出向量进行匹配,而在这里,我们有 16 个参考进行匹配。这意味着网络可以一次预测 16 个目标。可以通过在多个特征图上进行预测或者通过在特征图上增加所谓的参考位置来增加要估计的对象的数量。

这些引用位置只不过是定位框或默认框。

在上面的例子中,只有一个锚盒,即每个滤波器位置进行一次预测。

通常情况下,可以对特征图中的每个过滤器位置进行多次预测,这意味着需要有多少个预测就有多少个引用。

假设每个滤波器位置有 3 个基准电压源。

Three boxes per filter location — one of size 3x3(orange), one of size 1x3(blue) and another of size 3x1(green)

正如我们前面看到的,输出是锚盒的函数,所以如果引用/锚的数量改变,输出大小也会改变。因此,由于锚的数量=3,网络输出将是 4x4x(N3)(和 4x4x(43)),而不是像 1 个锚的情况那样输出 4x4xN(和 4x4x4))。

一般来说,单触发检波器的输出形状可以写成

分类头型:HxWxNA

回归头型:HxWx4A

其中 A 是使用的锚的数量。

还有一个问题!

每个滤波器位置有多个锚/参考盒有什么意义?

这使得网络能够预测每个图像位置的不同大小的多个对象。

这种单触发检测器的变体称为单触发多盒检测器(SSD ),其中在末端使用卷积层来获得输出,而在末端使用全连接层来获得输出的变体称为只看一次(YOLO)。

我希望我已经让主播的概念对你们大家来说很容易理解。主播是一个很难理解的概念,在这篇博客中仍然有一些关于他们的未解问题。我想在我接下来的文章中回答这些问题。到那时再见吧:-)

参考资料:

[1]我的帖子是从这个优秀的视频中得到灵感的:https://www.youtube.com/watch?v=0frKXR-2PBY—FastAI 关于多目标检测的视频**强烈推荐 **

[2]https://arxiv.org/abs/1506.01497

神经网络直觉:6。EAST:一种高效准确的场景文本检测器——论文解读

原文:https://towardsdatascience.com/neural-networks-intuitions-6-east-5892f85a097?source=collection_archive---------8-----------------------

嘿伙计们!再次回来真好:-)

距离我发表上一篇文章已经有一段时间了。在我的系列文章“神经网络直觉”的第六部分中,我将谈论一种使用最广泛的场景文本检测器——EAST(高效准确的场景文本检测) ,顾名思义,与文本检测器相比,它不仅准确,而且更加高效

首先,让我们从总体上看一下场景文本检测的问题,然后深入研究东* 😃*

场景文本检测:

问题:上面已经提到的问题是检测自然场景图像中的文本。场景文本检测是对象检测的一个特例,这里的对象归结为一个单独的实体— “文本”。

Scene Text Detection

但是我们在什么水平上检测文本呢?

我们可以在字符级单词级检测文本。这完全取决于如何对文本检测数据集进行注释,以及我们希望网络如何学习。通常,自然场景图像在单词级别被标记,从而使网络学会检测单词(以及单词之间的空格,以便区分任何两个 单词实例)。

解决方案:既然这里的问题是物体检测,既然我们已经知道了物体检测的基础 ( 神经网络直觉:5 .锚和对象检测 ) ,我们可以简单地使用现有的对象检测器之一——比如 SSD、Faster-RCNN 或 RetinaNet。他们应该能帮我们完成这项工作。

但是我们真的需要每个特征地图单元有多个定位框吗?或者我们是否需要使用锚的概念来完成更具体更简单的任务,比如文本检测?

我之所以说文本检测(或者更具体地说单词检测)是一项更简单的任务,是因为:

a. 单词 的模式/特征并没有那么复杂——尤其是在语言固定的情况下(比如英语),我们基本上有 262(小写和大写字母)+ 10(数字)。*

但是我们不是在字符级别检测,对吗?那么,如果有大量的单词组合,这个任务是如何简单的呢?

让我们看下一点来看原因!

b.如果您以前有过文本检测的工作经验,您可以看到文本检测器可以学习预测没有经过训练的语言中的单词(即使并不完美)。例如 英文 单词检测器检测 日文/泰米尔文 单词。

这很明显地表明,所学的模式并不完全是“语言单词”。那么网络到底在学什么呢?—它可以是学习一起出现在组中的形状,由一定数量的空白分隔,例如,一个连接的组件。

至少这是我对单词检测器可以学习什么的直觉:-)

我们为上述问题制定一个解决方案怎么样?

伪代码:

  1. 将输入场景文本图像传递给 ConvNet(特征提取器)。
  2. 在特征融合阶段合并多尺度特征。
  3. 在特征卷上运行 1x1 conv 滤波器(class head) 以获得范围为 0–1 的激活图/热图,其中1 表示图像中存在文本,而 0 表示背景。**
  4. 对激活图进行阈值处理,并使用 cv2.findContours()之类的逻辑来查找文本区域,并最终从中找到文本单词。

如果我们注意第 3 步,我们可以注意到锚的用法,与大小为 1x1 的过滤器相关联,并且每个特征地图单元* 只有 一个锚框。这一点很关键,因为它有助于我们与传统的单次目标探测器进行比较。*

这几乎就是 EAST 所做的——除了没有使用一些过度的逻辑来查找文本区域,它还有另一个头— box head ,它将输出到最近的[minx,miny,maxx,maxy]边界的 4 个距离值(特征地图中的每个像素)。

EAST——一种高效准确的场景文本检测器;

a .架构:每个单次拍摄物体探测器都包含 3 个主要阶段:

  1. 特征提取阶段。
  2. 特征融合阶段。
  3. 预测网络。

单触发探测器的所有变体在上述三个阶段中的一个阶段有所不同。东方也遵循上述相同的范式。

b .投入产出:

  1. 该网络接收输入图像,并通过某组 conv 层(特征提取器干)来获得四级特征图——f1、f2、f3、f4。
  2. 然后,特性图被解池(x2)、连接(沿通道维度),然后通过 1x1,再通过 3x3 转换器。合并来自不同空间分辨率的特征的原因是为了预测更小的单词区域。

Feature merging

3.然后,最终的特征体积将用于进行分数和盒子预测-深度=1 的 1x1 过滤器用于生成分数图,深度=5 的另一个 1x1 过滤器用于生成 RBOX(旋转的盒子)-四个盒子偏移和旋转角度,深度=8 的另一个 1x1 过滤器用于生成四边形(具有 8 个偏移的四边形)。

c .损失函数:

在进入损失函数之前,让我们先来解释一下网络输出。

1.类头输出可以解释为类似于传统检测器的类输出,只是这里每个特征地图像元只有锚框,因此输出将为 HxWx1 形状,其中 1 表示每个像元的锚框数量。

2.但是在盒子头的情况下,输出(形状 HxWx4)应该在“像素”级别解释,并且没有锚盒的概念。每个像素都有 4 个与之相关的数字—到最近的[minx,miny,maxx,maxy]框的距离。这里需要注意的重要一点是,最终的字级输出是从这个每像素级输出中导出的。

c1。分类损失

我们都很清楚对象检测数据集中存在的类不平衡问题。背景类的样本数量通常非常多,现在我们将每个 1x1 框(基本上是每个像素)作为输出,背景样本的数量变得巨大。

为了解决这个类不平衡的问题,EAST 使用了交叉熵的一个修改版本,叫做 平衡/加权交叉熵。

Balanced Cross Entropy (BCE)

在 BCE 中,高代表类的分数通常与低代表类的损失项相乘(类似地,高代表类的损失项也是如此),以便控制高代表类和低代表类的贡献。注:背景类:=高表示,前景类:=低表示。**

查看这个博客对 BCE ( 神经网络直觉的详细解释:1。平衡交叉熵 )。

c2。IOU 损耗:这里使用的 IOU 损耗不同于传统的包围盒损耗。

IOU Loss

每个像素将有 4 个与之相关的数字——到最近的顶部、左侧、底部、右侧框边界的距离,根据该距离计算 IOU,然后使用负对数似然作为损失,当 IOU 小于 1 时进行惩罚。**

很明显,gt/pred 框的宽度和高度可以通过简单地将它们的 x 和 y 偏移量相加来计算,由此获得 gt 和 pred 框的面积。

为了找到相交矩形的宽度和高度,

现在我们有了 gt 盒的面积,预测盒的面积和相交盒的面积,我们可以计算 IOU 了!

然后我们计算角度损失,

1 — cos(predicted angle — gt angle)

总损失写为,

A weighted sum of both losses.

在我接下来的文章中(编辑到同一篇文章),为了完整起见,我将解释关于如何从网络输出中计算边界框的 EAST post processing

*论文链接:【https://arxiv.org/abs/1704.03155 *

干杯!

时间序列中经典模型上的神经网络

原文:https://towardsdatascience.com/neural-networks-over-classical-models-in-time-series-5110a714e535?source=collection_archive---------19-----------------------

为什么我们不应该止步于时间序列分析中的经典模型,为什么我们应该进一步释放神经网络的力量。

本文讨论了各种神经网络在时间序列建模中的能力。

与监督和非监督学习模型相比,基于时间序列预测的经典机器学习模型很难实现,因为数据中存在时间差异:我们在不同的时间步长对相同数据绘制的数据进行处理。这使得模型拟合和模型评估的过程相对困难。

ARIMA 是市场上非常受欢迎的工具,因为它可以用于几乎任何类型的时间序列数据,并且非常容易理解和有效地实施。深度学习方法可以克服经典模型的 3 个主要限制,如下所述。

经典模型的局限性:(如霍尔特-温特斯,ARIMA,其他指数模型)

  1. 不支持缺少值。
  2. 假设数据具有线性关系,即,显示趋势分量具有总体下降或上升趋势

Types of trends shown in Boston marathon data**

我们可以看到,线性趋势线显示了数据的总体下降趋势。而“三次样条”是一条非线性趋势线,它捕捉了数据中更直观的模式(非线性模式)。

3.这些模型处理单变量数据。时间序列预测中的大多数模型不支持将多个变量作为输入。我们只关注一个变量:感兴趣的结果只是输入变量的未来版本(在未来的时间步)。这种情况的例外是季节性 ARIMA 或萨里玛等模型,它们接受外生变量来建模数据。

深度学习神经网络

像多层感知器、RNNs(递归神经网络)和卷积神经网络这样的深度学习网络在时间序列预测方面有自己的一套优势和功能。

多层感知器:可以处理缺失值,模拟复杂关系(如非线性趋势)并支持多输入。

但是 MLPs 或多层感知器有一个缺点,即必须提供固定数量的输入来产生固定数量的输出:在模型设计中预先指定时间相关性。在这些前馈神经网络中,输入和输出之间有一个固定的映射函数,当向模型提供一系列输入时,这就产生了一个问题。

复杂的神经网络:使用这些网络的主要优势是它们可以很容易地完成特征工程。它们自动从提供给模型的原始输入中提取特征。

它们还共享多变量输入的相同功能,模拟复杂的非线性关系,并且对噪声(缺失值)具有鲁棒性。但是这些神经网络优于前馈神经网络,因为它们不需要直接从滞后观察中学习,而是学习与预测问题最相关的大输入序列的表示。

递归神经网络,特别是 lst ms:lst ms 还提供多变量输入、对噪声的鲁棒性、多变量输出、自动特征提取、对数据中更复杂的关系建模。他们还可以将输入序列数据作为单独的输入向量读入模型。

除了 MLP 和 CNN 提供的功能之外,LSTMs 还可以随着时间的推移学习从输入到输出的映射功能。在模型学习过程中,映射函数不再是固定或静态的。

敬请关注时间序列分析中深度学习实践的更多详细文章!

参考文献:

**图片摘自:Rob J. Hyndman 和 George Athanasopoulos 的《预测原理和实践》[在线文本:【https://otexts.com/fpp2/nonlinear-regression.html]

神经网络:参数、超参数和优化策略

原文:https://towardsdatascience.com/neural-networks-parameters-hyperparameters-and-optimization-strategies-3f0842fac0a5?source=collection_archive---------2-----------------------

神经网络(NNs)是深度学习分析中使用的典型算法。神经网络可以采取不同的形状和结构,但其核心框架如下:

所以我们有我们的输入(x),我们取它们的加权和(权重等于 w),通过一个激活函数 f(.)瞧,,我们得到我们的输出。然后,根据我们的预测有多准确,算法会根据给定的优化策略,通过所谓的“反向传播”阶段进行自我更新。

不用说,这是一个非常糟糕的定义,但是如果你在阅读本文时记住它,你会更好地理解它的核心主题。

事实上,我想重点讨论的是如何处理神经网络的一些特征元素,这些元素的初始化、优化和调整可以使您的算法更加强大。开始之前,让我们看看我在谈论哪些元素:

参数:这些是模型的系数,由模型自己选择。这意味着算法在学习时优化这些系数(根据给定的优化策略)并返回一组使误差最小的参数。举个例子,在线性回归任务中,你有一个看起来像 y=b + ax 的模型,其中 b 和 a 是你的参数。对于这些参数,您唯一要做的事情就是初始化它们(我们将在后面看到它的含义)。

超参数:这些是与之前不同的,你需要设置的元素。此外,模型不会根据优化策略更新它们:总是需要您的手动干预。

策略:这是一些你应该拥有的关于你的模型的技巧和方法。也就是说,在管理您的数据之前,您可能希望对它们进行规范化,特别是当您有不同范围的值时,这可能会影响您的算法的性能。

所以,让我们来检查所有这些。

参数

正如预期的那样,对于参数,您唯一要做的事情就是初始化它们(注意,参数初始化是一种策略)。那么,初始化它们的最好方法是什么呢?当然,你不应该做的是将它们设置为零:事实上,这样做你冒着惩罚整个算法的风险。举一个你可能面临的各种问题的例子,即使在几次重新称重后,仍然坚持重量等于零。

因此,这里有一些根据你决定使用的激活函数正确初始化你的参数的想法(我将在后面详述激活函数)。

如果您使用 Sigmoid 或 Tanh 激活函数,您可以使用具有均匀或正态分布的 Xavier 初始化:

如果您使用的是 ReLU,您可以使用 he 初始化,使用正态分布:

其中 nin0 分别是输入数和输出数。

超参数

这要有趣得多。超参数比参数更需要您的注意力和知识。因此,要想知道如何处理它们,让我们来看看其中的一些:

隐藏层数:这可能是最值得质疑的一点。这个想法是,你想让你的神经网络尽可能简单(你想让它快速和良好的推广),但同时,你想让它很好地分类你的输入数据。在这种情况下(以及许多其他与超参数相关的情况),您应该继续进行手动尝试。在自我学习机器的时代,这听起来可能很“古老”,但请记住,后者需要在学习之前构建。因此,为了提供这种直觉,我建议你在这个 Tensorflow 平台上运行一些实验:你会看到在若干层/神经元之后,精确度不再提高,因此保持算法如此繁重是低效的。

学习率:该超参数指的是反向传播步骤,根据优化函数更新参数。基本上,它代表了重新校准后重量的变化有多重要。但是“重新校准”是什么意思呢?好吧,如果你考虑一个只有一个权重的一般损失函数,图形表示将是这样的:

你想使损失最小化,所以理想情况下,你希望你当前的 w 滑向最小值。该过程应该如下:

对应的功能是:

其中第一项是你当前的体重,第二项是你的函数的梯度(在这个一维的例子中,它将是你的损失函数的一阶导数,很明显,是关于你唯一的体重)。记住,如果切线段的陡度为负,一阶导数就有负值,这就是为什么我们在两项中间放一个负号(直觉:如果陡度为负,权重应该向右移动,如示例所示)。这个优化过程被称为梯度下降。

现在让我们给公式添加一个新术语:

这个 gamma 是我们的学习率,它告诉算法梯度对权重的影响应该有多重要。小伽马的问题是 NN 将非常缓慢地收敛(如果它将收敛的话),并且我们可能招致所谓的“消失梯度”的问题。另一方面,如果伽马值很大,风险就会错过最小值,并导致“爆炸梯度”的情况。

一个好的策略可能是从 0.1 左右的值开始,然后以指数方式减少它:在某个点上,损失函数值在最初的几次迭代中开始减少,这是权重采取正确方向的信号。

动量:这是一种在反向传播阶段使用的技术。如关于学习率所述,参数被更新,使得它们可以向损失函数的最小值收敛。这个过程可能太长,影响算法的效率。因此,一个可能的解决方案是跟踪先前的方向(即损失函数相对于权重的梯度),并将它们作为嵌入信息保存:这就是动量被考虑的原因。它基本上不是在学习速率方面(每次更新多少权重)而是在过去重新校准的嵌入式存储器方面(该算法知道该权重的先前方向,比方说,是正确的,并且它将在下一次传播期间直接朝着该方向前进)提高了收敛速度。如果我们考虑一个双权损失函数的投影(具体地说,一个抛物面),我们可以形象化它:

你可以在这里找到制作这些 3D 图形的来源。

如你所见,如果我们添加动量超参数,下降阶段会更快,因为模型保留了过去梯度方向的痕迹。

如果你决定采用较高的动量值,这意味着它将大量考虑过去的方向:这可能会导致难以置信的快速学习算法,但错过一些正确“偏差”的风险很高。建议总是从低值开始,然后逐渐增加。

激活函数:它是一个函数,我们通过它来传递我们的加权和,以便得到一个有意义的输出,即作为一个概率向量或 0-1 输出。主要的激活函数是 Sigmoid(对于多类分类,使用该函数的变体,称为 SoftMax 函数:它返回和等于 1 的概率向量作为输出)、Tanh 和 RELU。

注意,激活函数可以位于 NN 中的任意点,次数不限。然而,你总是要考虑效率和速度。也就是说,ReLU 函数在训练方面非常快,而 Sigmoid 函数更复杂,需要更多时间。因此,一个好的实践可能是使用 ReLU 的隐藏层,然后,在最后一层,插入你的乙状结肠。

小批量:当你面对数十亿的数据时,向你的神经网络提供所有这些数据可能会导致低效(以及适得其反)。一个好的做法是给它输入较小的数据样本,称为批次:通过这样做,每次算法训练自己时,它都将在相同批次大小的样本上进行训练。典型的大小是 32 或更大,但是你需要记住,如果大小太大,风险是一个过于一般化的模型,不适合新的数据。

历元:它代表你希望你的算法在你的整个数据集上训练多少次(注意,历元不同于迭代:后者是完成一个历元所需的批次数量)。同样,纪元的数量取决于您所面临的数据和任务的类型。一个想法可以是强加一个条件,当误差接近零时,纪元停止。或者,更容易的是,您可以从相对较少的时期开始,然后逐渐增加,跟踪一些评估指标(比如准确性)。

退出:这项技术包括移除一些节点,这样神经网络就不会太重。这可以在培训阶段实施。这个想法是,我们不希望我们的神经网络被信息淹没,特别是当我们考虑到一些节点可能是多余的和无用的。因此,在构建我们的算法时,对于每个训练阶段,我们可以决定以概率 p(称为“保持概率”)保留每个节点,或者以概率 1-p(称为“丢弃概率”)丢弃它。

策略

策略是我们可能希望对我们的算法采用的方法和最佳实践,以使它更好地执行。其中包括以下内容:

参数初始化:我们在第一段已经讲过了。

数据标准化:检查数据时,您可能会注意到一些要素以不同的比例表示。这可能会影响你的神经网络的性能,因为收敛速度较慢。规范化数据意味着将所有数据转换为相同的标度,范围为[0–1]。您也可以决定标准化您的数据,这意味着使它们正态分布,平均值等于 0,标准差等于 1。虽然数据规范化发生在训练神经网络之前,但另一种可以规范化数据的方法是通过所谓的批量规范化:它直接发生在神经网络训练期间,特别是在加权和之后和激活函数之前。

优化算法:上一段我提到了梯度下降作为优化算法。然而,我们有后者的许多变体:随机梯度下降(它根据梯度下降优化来最小化损失,并且对于每次迭代,它随机选择一个训练样本——这就是为什么它被称为随机的),RMSProp(与之前的不同,因为每个参数都有适应的学习速率)和 Adam 优化器(它是 RMSProp + momentum)。当然,这不是完整的列表,但足以理解 Adam optimizer 通常是最佳选择,因为它允许您设置不同的超参数并定制您的 NN。

正则化:如果你想保持你的模型简单,避免过度拟合,这个策略是至关重要的。其思想是,如果权重太大/太多,正则化会给模型增加一个惩罚。事实上,如果重新校准程序增加了权重,它会给我们的损失函数增加一个新项,该新项会增加(因此,损失也会增加)。有两种正则化:套索正则化(L1)和桥正则化(L2):

L1 正则化倾向于将权重缩小到零,存在丢弃一些输入的风险(因为它们将与空值相乘),而 L2 可能将权重缩小到非常低的值,但不会缩小到零(因此输入被保留)。

有趣的是,这一概念与时间序列分析中的信息标准密切相关。事实上,在优化我们的自回归模型的最大似然函数时,我们可能会遇到同样的过度拟合问题,因为这一过程往往会增加参数的数量:这就是为什么如果后者增加,增加惩罚是一个好的做法。

结论

本文并不打算详尽列出神经网络的所有特征元素,但是理解它们之间的主要区别以及初始化和调整的关键思想是很重要的。

神经网络应该学会如何说“我不确定”

原文:https://towardsdatascience.com/neural-networks-should-learn-how-to-say-im-not-sure-a430d665fa7d?source=collection_archive---------14-----------------------

贝叶斯定理使人工智能能够回答不确定性问题

如果有一个机器学习的应用被认为特别有用并且经常成功,那就是分类。分类是将一个给定的条目分配到一个类中的任务(,例如“猫”还是“虎”?).通常,要处理的每个条目都用数字表示为一个数字向量,它可以对高级特征进行编码(例如尾巴的长度、条纹或斑点的存在等)。)或者低级的(例如一个图像中每个像素的值)。多年来,社区已经探索了许多不同的分类器,最流行的是人工神经网络决策树支持向量机,或其他算法,如 k-means 聚类。在这篇文章中,我将集中讨论神经网络,但是这个论点也可以适用于其他类型的分类器。

通常,神经网络由一个输入层(接受输入特征)、多个隐藏层(该数字越大,网络越深)和一个输出层组成。对于二进制分类问题,输出层通常有一个单一节点(例如老虎),或者在不止两个类的情况下有 N 节点(例如老虎狮子)。通常,学生们会遇到一个简单的分类问题,叫做费希尔虹膜数据集。人们必须创建一个分类器,该分类器能够基于四个简单的输入特征(萼片长度和宽度、花瓣长度和宽度)来分离称为( versicolorsetosavirginica )的三种花。统计学家罗纳德·费雪在他 1936 年的论文 中首次介绍了这个数据集。在分类学问题中多重测量的使用 。**

The Iris flowers dataset is one of the best-known datasets found in the classification literature. The goal is to classify Iris flowers among three species (Setosa, Versicolor or Virginica) from measurements of length and width of sepals and petals.

众所周知,这个问题特别容易解决,同时仍然保留了许多教育方面。我们将尝试用嵌入了贝叶斯推理的特定神经网络来解决它,以便不仅给出一个答案,而且给出一个具有相关不确定性的答案。这篇文章使用的代码可以在 https://github.com/rdisipio/DeepBayesIris公开获得。

为什么我们首先关心不确定性,这几乎是一个哲学问题。简单地说,任何人(至少是理性的人)都会感觉到“这是一朵鸢尾”和“这看起来像一朵鸢尾,但有 30%的可能性是一朵海滨鸢尾”之间的区别。大多数分类器只能给出类似于前一句的结果,主要是因为后一句很难计算。实现这一点的方式是依靠贝叶斯定理:在获得关于某件事的新信息时,一个人的信念(“后验概率”)会被观察到的(“证据”)和之前已知的(“先验概率”)的混合所“更新”。特别是,如果最初的信念非常坚定,没有证据可以改变一个人的信念(例如确认偏差)。在实践中,该定理用一个数学公式来表示与假设( H )和数据( D )相关的概率:

在我们的例子中,假设 H 将是一组定义我们的分类器行为的参数,先验将是我们对这些参数的实际值的最初猜测。通过求解贝叶斯定理,我们将得出另一组参数 H* (“最佳拟合”),这些参数提高了分类器将数据集中的每朵花分配到正确类别的整体能力。如果您已经熟悉神经网络,这组参数对应于网络的权重和偏差,以及损失函数的可能性。

对于这个特定的应用程序,我设置了一个完全连接的前馈多层感知器(有点拗口,但实际上这是最简单的神经网络类型!)具有四个输入节点,一个隐藏层具有五个节点和 tanh 激活,一个输出层具有三个节点(每个类别一个)和soft max 激活softmax 函数确保结果可以解释为概率,,即每个节点的值在 0 和 1 之间,所有节点的和为 1。损失函数为 交叉熵 ,恰当地衡量了输出为概率值的分类模型的性能。

Diagram of the architecture of the neural network used in this example. Including the biases, there is a total of 19 weights to be estimated during the training.

在我们深入研究实现的细节之前,让我们澄清一下我们将如何使用这种网络。首先,我们将找到优化损失函数的一组最佳权重和偏差H**——在这种情况下,我们将寻找函数的最大值而不是传统机器学习软件包中出现的最小值。这种“贝叶斯训练”的结果将是一组参数和不确定性。此外,我们希望估计参数之间的相关性,这是我们进行如下解释的推理所需要的。在推理步骤中,我们将通过具有相同架构的神经网络来预测给定条目的类别,但是执行多次,每次使用稍微不同的一组参数。所有这些运行的平均值将给出一个中心值和相关的不确定性。*

实际实现基于高能物理界流行的两个 C++软件库: ROOT (由 CERN 开发)和贝叶斯分析工具包 (BAT)。在幕后,BAT 用一种叫做 Metropolis-Hastings 的统计方法探索了 H 的多维概率分布(见我早先的帖子关于如何用这种方法预测大公司 CEO 的薪酬)。属于一类叫做马尔可夫链蒙特卡罗 (MCMC)的采样算法。众所周知,当要探索的维数非常大时,这种算法特别有效。实际上,必须创建 BAT::BCModel 的派生类,然后定义参数集及其范围(在这个简单的示例中,它们都在范围[-100,100]内)。最重要的是,必须实现虚拟函数 BC model::log likelihood(STD::vector)来计算出现在贝叶斯定理中的“证据”项,作为 MCMC 每次迭代的参数 H 的函数。也可以重新实现对先验分布的估计,但为了简单起见,可以将它们设置为均值为 0 且标准差覆盖 1/4 允许范围的高斯分布(本例中为 100/4 = 25)。这是一个非常粗略的假设,原则上可以用一个更少“信息”的常数先验来代替。然而,使用贝叶斯方法的全部要点是阐明我们先前的信念:在这种情况下,我认为可以公平地说,人们期望参数的值很小,但为更好的估计留有余地。稍后我们将看到这个“更新”实际上是什么样子。

在 LogLikelihood()函数中,参数被传递给一个前馈类,该类重新排列这些参数,然后实际执行神经网络计算。通过相对于已知标签的交叉熵损失来比较输出(对于setosa[1,0,0],对于versicolor[0,1,0],对于virginica[0,0,1】)。MCMC 引擎抽取参数的随机值,计算损耗,并根据 Metropolis-Hastings 算法前进到附近的点。为了进一步优化,由多个并行链(通常为 4 或 8 个,每个 CPU 内核最多一个)执行“探索”,这些并行链在理论上应该收敛到同一个最佳点。

过程结束时,后验分布可用于单个参数(边缘化 1D 分布)或成对参数(边缘化 2D 分布)。理想情况下,这些 1D 分布应该是对应网络权重的最可能值周围的高斯分布。事实上,神经网络是非常复杂的系统,很少有能够被有效识别的全局最大值。更有可能的是,将会有一大组局部最大值,对于手头的分类问题来说足够好。这通过具有多个峰值的后验分布来反映,每个峰值对应于不同的最大值。然而,没有简单的方法来处理这些情况,需要一些近似。在该方法的实现中,我决定使用分布的平均值作为权重,RMS 作为相同权重的不确定性。此外,从 2D 边缘分布可以估计协方差矩阵,其中元素 C_ij 例如由第 i 和第 j 权重的 2D 边缘分布之间的皮尔逊相关系数给出。这些信息被保存到一个文本文件中,用于推理。

Example of a “well-behaving” distribution: the 1D-marginalized posterior probability of the weight prefers a positive value but with large uncertainty

Example of a the 1D-marginalized posterior probability with two peaks, both corresponding a value of the weight that leads to a local maximum of the loss function.

Example of a the 2D-marginalized posterior probability with two peaks. The global optimization (hollow circle) prefers either of the two, but the highest peak in the 2D distribution (hollow square) is the other one.

在推断步骤中,从训练结束时创建的文本文件中加载网络的权重和相关矩阵。神经网络将被执行多次,并且结果将被收集和平均以得到最终结果。

现在是阐明为什么我们需要将协方差矩阵传播到推断步骤的时候了:我们不能简单地抛出随机数,好像权重是彼此独立的,而它们实际上是相关的。原则上,我们希望探索 H 的完整的 N 维概率分布函数,但这太复杂了。相反,我们可以用一个多元正态分布 X ~ N (μ,σ)来近似它,这是高斯分布的N*-维等价物(μ是权重的中心值的向量,σ是标准偏差的向量):

Multinormal distribution. It’s the equivalent in multiple dimensions of the Gaussian distribution.

An example of a 2D multivariate normal (gaussian) distribution.

然而,从 X 采样并不是一件简单的事情。事实证明,在 1D,将标准正态随机变量 Z ~ N (0,1)转化为正态随机变量 N (μ,σ)更容易,首先通过方差的平方根(,标准差)进行缩放,然后移动结果以获得正确的平均值(加上μ), X = μ + √同样的想法适用于多维,但是我们有一个协方差矩阵,而不是方差的标量值。但是等等:一个矩阵 C 的平方根是多少?根据定义,它必须看起来像c=c(1/2)*(*c*(1/2))^t.)找到矩阵 C ^(1/2 的最常见方法是由乔莱斯基分解给出的,其中得到一个三角矩阵 U 使得c=ut*u*(*u*因此,我们可以简单地得到***x*=μ+*u*tz*。

最后,我们对一个给定的事件进行分类,看看神经网络的反应是什么。

在第一种情况下,网络对花的分类没有问题:它是一个…

Classification output for entry #0 (iris setosa)

相反,在这另一种情况下,结果是非常明显的…

Classification output for entry #70 (iris versicolor). The output is consistent with both iris versicolor and iris virginica.

特别是,这最后一个例子似乎表明,类别#1 ( versicolor )比类别#2 ( virginica )更有可能。然而,经过更仔细的检查,人们可以看到两个不确定带重叠,降低了统计意义——事实上,这种情况基本上是未分类的,唯一可以得出的结论是,这种花不太可能是鸢尾

总结一下,这是一个简单而美好的例子,它表明不仅对事物进行分类是多么重要,而且给决策附加一个不确定性也是多么重要。这就是人类在决策过程中吸收新信息并运用理性的方式。在所考虑的情况下,这可能不是什么大事,但正如美国数学家凯茜·奥尼尔在《数学毁灭的武器》一书中所讨论的那样,盲目信任人工智能/人工智能分类器的结果可能会在人而不是花作为输入的社会经济情况下产生可怕的后果。

用近似对数计算训练神经网络

原文:https://towardsdatascience.com/neural-networks-training-with-approximate-logarithmic-computations-44516f32b15b?source=collection_archive---------31-----------------------

Fig 1: Hardware Accelerated Learning

计算内存访问而言,神经网络训练是昂贵的——大约是推理的三到五倍。当在边缘设备(连接到互联网边缘的设备——可穿戴设备、智能手机、无人驾驶汽车等)上训练神经网络时,这两个因素一起对净功率需求产生了显著影响。为了在这种边缘设备上进行实时训练和推理,计算量的减少是至关重要的。尽管已经提出了许多解决上述问题的方法,例如基于稀疏度修剪量化的方法,我们提出了另一种方法——在对数系统中设计端到端训练。注意,

  • 为此,所有重要的神经网络操作都需要在 LNS 中定义。
  • 在 LNS 中,乘法简化为加法。但是加法本身在计算上变得昂贵。
  • 因此,我们借助近似对数计算,直觉地认为反向传播噪声容差能够吸收我们对数域运算的不确定性。

Fig 2: An LNS-DNN-MLP where the neurons have logarithmic activation functions and the activations and weights are in fixed point LNS

实数和对数之间的映射如下所示:

这种对数映射意味着需要修改向量空间ℝ的基本运算,这些运算是加法和乘法。在对数域中,乘法以加法换取计算复杂度。

也就是说,乘法运算被消除,代之以加法运算。另一方面,添加是很棘手的。加法的确切形式如下所示,

在对数域中执行加法时,δ项会导致非线性和大量额外计算。

△ w.r.t. d 的图示清楚地显示了非线性。

Fig 3: Correction term △

以类似的方式也可以定义减法,

由于一次乘法现在只是一次加法,直观地说,我们可以推断出在对数域中求幂也将更简单,

近似值

为了减少每次加法的计算量,我们决定把加到大约就可以了。这意味着我们需要在△项中引入近似值,因为计算这些校正项是加法运算中计算量最大的步骤。我们想到了两种主要的近似方法,接下来我们会介绍这两种方法,

基于 LUT 的近似

思路:将△项存储为由定点宽度、动态范围、分辨率三个参数指定的查找表。

  • 当△项下降到 0 时,动态范围由定点宽度决定
  • 分辨率是一个超参数
  • 定点宽度是一个超参数

例如,下面我们展示了如何使用基于查找表的方法对图 3 中的曲线进行阶梯近似,

Fig 4: r (Resolution) = 0.5. Inverting resolution gives the number of samples per consecutive integers.

另一个例子是由于更小的 r ,每个连续整数有更多的样本,因此查找表更大。

Fig 5: r = 0.125

基于位移的近似

以下表达式的泰勒级数近似给了我们:

将这种近似应用于我们的表达式,

为了便于实现,常数项可以表示为 2 的幂的和,

我们可以将这种近似作为基于查找表的分辨率为 1 的近似的特例,即每个连续整数一个样本。我们在工作中实现的位移近似值显示在下面的图中。

Fig 6: Constant term taken as 1 for the bit-shift approximation to the blue curve and as 1.5 for the same approximation to the purple curve.

对数域中的神经网络运算

现在使用上面描述的数学,我们可以在对数域中重新定义所有的神经网络操作。图 2 中突出显示了单个 LNS 神经元,在其扇入边缘上具有对数编码的定点权重,并从先前的神经元层获取对数编码的定点激活。它对数累加() 权重和激活的对数域乘积() ,在它通过激活函数之后,该激活函数本身是标准激活函数的对数图像。

激活—日志泄漏 ReLU

Fig 7: parametric Leaky ReLU

Fig 8: The log-Leaky ReLU

图 7 描绘了 Leaky ReLU,这是一种特殊的参数 ReLU,在 2015 年的论文中有所描述。在该图中,我们重写了常数 a ,这样我们就可以用公式表示我们的日志激活函数。图 8 中也描绘了相同的激活函数,但是常数表示为' a' 等于 2 的𝛽.幂在这种形式中,我们现在可以很方便地在对数域中表达“ReLU 图像”,利用我们使用的符号和我们迄今为止发展的数学。对数泄漏 ReLU 的数学方程如下所示,

像 Leaky ReLU 一样,log-leaky ReLU 也是由单个超参数超参数化的,这就是上面给出的方程中的𝛽。

初始化 LNS 中的网络权重

  • 我们不应该初始化从某个分布中采样的数十万个参数,然后取对数,而是应该使用标准的概率测量变化方法,直接在从我们期望的分布中导出的分布上初始化我们的参数。
  • 权重从对称分布初始化。因此,符号参数可以随机初始化,并且独立于来自伯努利(0.5) 分布的幅度。
  • 权重幅度分布减少到,

  • 作为说明性的例子,假设通常对于神经网络,我们更喜欢从具有σ标准偏差的零均值正态分布中采样我们的初始权重和偏差值,那么在对数域中,符号参数应该从伯努利(0.5) 分布中采样,并且对数幅度应该从下面给出的分布中采样,

LNS 神经网络中的 Softmax

在训练时,神经网络应该输出通常由软最大层产生的软决策。softmax 的数学表达式为:

这里𝛿是反向传播初始化项, 𝑦 是一次性输出标签。在对数域中,当我们意识到我们想要的是对数概率值时,我们可以简化这个过程。

实验和结果

本节包含在我们的对数域 MLP 上执行的训练实验的详细描述,我们使用迄今概述的数学和神经网络 MLP 架构知识来设计该对数域。

对数域中的定点位宽分析

我们所有的神经网络训练和推理实验都是使用定点运算进行的。但是,当我们谈论对数域中的定点数学时,位宽是如何缩放的呢?确切地说,与线性域中的 16 位标准字相比,对数域字需要多少位才能在精度和动态范围方面具有表示能力?事实证明,我们可以分析并推导出一个悲观的最坏情况表达式,该表达式给出了在线性域中精确表示特定位宽的信息所需的最大位数。这里的术语“精确”是指满足线性域字长的精度和动态范围。

在这个等式中,符号有它们通常的含义。

Fig 9: Log-domain bit-widths versus the integer bits in a linear-domain fixed-point representation

以图形方式直观显示这些信息通常更容易,因此图 9 显示了对数域中所需的位数,以准确描述以 1 字节倍数表示的信息。

在最坏的情况下,我们似乎需要额外的 O(对数 Wₗᵢₙ) 比特来满足精度要求。请注意,上面给出的分析有严格的要求,实际上对于手头的任务来说是多余的,在我们的实验中,我们发现使用 MLPs 使用相同的位宽效果很好。

数字结果

我们用于所有不同数据集的 MLP 具有相同的总体架构,超参数针对每个数据集进行了单独优化。

  • 经过训练的 MLP 只有一个隐藏层。网络结构是每层 784–100–n个𝒸神经元,其中 n 𝒸是数据集中输出类的数量。
  • SGD 优化器与权重衰减正则化一起使用。12 位定点系统的训练需要比 16 位定点系统更高的正则化超参数λ。
  • 近似⊞的查找表有 20 个元素,分辨率为 0.5。这些 lut 用于所有近似⊞运算,除了当计算 softmax 时,由于增加的精度要求,soft max 使用单独的表。用于近似⊞运算的 Softmax LUT 具有 640 个元素,分辨率为 0.015625。
  • 在四个数据集上训练——每个数据集 20 个时期。基线训练也进行了 20 个时期。所有训练都在定点设置中完成。使用的数据集是 MNIST时尚-MNISTEMNIST 字母EMNIST 数字

Fig 10: Performance Plots (Learning Curves)

All numerical results are in percentage

有限精度线性和对数域训练的学习曲线如图 10 所示。在线性域中,使用 16 位定点表示,小数部分使用 11 位,与浮点相比,性能下降可以忽略不计。在对数域中,16 位表示使用 10 个分数位(即,由于符号需要额外的位)。当在 12 位系统上执行实验时,对于线性和对数域,分数位数分别保持在 7 和 6。应当注意,在所有情况下,图 10 中红色圆圈和紫色方块之间的精度损失不超过 1%。该表提供了定点线性处理和全对数域训练以及各种近似推理的测试集精度的比较。

参考

神经网络:为什么它们工作得这么好?

原文:https://towardsdatascience.com/neural-networks-why-do-they-work-so-well-part-i-22f0d3690511?source=collection_archive---------18-----------------------

先决条件

这篇文章需要一些关键的数学对象和技术的知识。一般来说,了解这些要求是非常有用的,所以如果你不熟悉的话,我建议你研究一下。单击该主题中我最喜欢的资源的任何链接。

线性代数

  1. 矢量
  2. 矩阵

结石

  1. 偏导数
  2. 链式法则

基础知识:输入和输出

神经网络是一个函数。它接受一些输入并将其映射到输出。更具体地说,神经网络是一种旨在进行预测的功能。

为了更好地理解这个定义,让我们看一个例子。假设我们希望根据我们掌握的关于您的一些数据来预测您是否患有心脏病:体重、身高、年龄、静息心率和胆固醇水平。

首先,我们可以将您的特征堆叠成一个向量 x ,如下所示:

为了获得神经网络对你患心脏病概率的预测,我们将 x 输入到模型中。这将输出 y-hat —模型对 p(心脏病)的预测。我们可以这样写(其中 N 是神经网络):

这里, y-hat 是 0 和 1 之间的连续值,因为它是概率。然而,真实值 y 是二进制的(即要么 1 要么 0),因为你要么有心脏病(1),要么没有(0)。

好吧!您现在对神经网络的作用以及它为什么有用有了大致的了解。但是,你仍然不知道神经网络是如何预测 y 和 T21 的。让我们再深入一点。

图层:🍰

注意:在这一节中,我使用下划线后跟方括号来表示 Unicode 中没有的文本内下标字符。这里有一个例子:

如前所述,神经网络是一个函数。但是,更具体地说,它是多种功能的组合。在深度学习中,这些功能被称为层。稍后我们将更多地讨论这些层是如何组成的,但现在,让我们只关注一层。

因为层是一个函数,它只是接收输入并产生输出。我们称这个函数为ℓ.层的 _[ℓ按照惯例, f _[ℓ】接收一个输入a _【ℓ-1】并产生一个输出a _【ℓ].】这里,a _【ℓ】被称为层ℓ.的激活

我们已经标记了 f _[ℓ]'s 输入和输出,但是层 f _[ℓ具体做什么呢?嗯, f _[ℓ】分三个阶段映射a _【ℓ-1】→a _【ℓ】。以下是每种情况下发生的情况:

  1. 首先,权重矩阵 W 应用线性变换→ W a _[ℓ-1】
  2. 然后,添加一个偏置向量bw a_[ℓ-1】+b****
  3. 最后,应用非线性激活函数σ→σ(w a_[ℓ-1】+b)****

这个序列可以用下面的等式来概括:

好了,我们对图层的功能做了一些数学标记。但是我不确定我们是否真正理解了什么是层在做。让我们试着通过视觉化来更好地感受一下 _[ℓ是如何改变空间的。**

为了可视化 f _[ℓ】,我们将需要处理低维(1、2 或 3)输入和输出。对于这个可视化,我们将有一个 2D 输入和一个 2D 输出。这意味着输入 a [ℓ-1] ∈ ℝ,输出a[ℓ】∈ℝ。我们也可以说 f _[ℓ】映射ℝ → ℝ。视觉上,这意味着 2D 空间中的每个点都通过 f _[ℓ].映射到 2D 空间中的一个新点

为了绘制出 f _[ℓ】如何在 2D 空间中操纵每个点,我们需要为σ选择一个函数,为 W 、选择一个矩阵,为 b 选择一个向量。对于这个可视化,我们将选择σ、 W、b ,如下所示:

现在我们有了这个具体的函数,我们可以展示它如何影响 2D 空间中的每一点。为了了解发生了什么,我们将只显示位于网格上的点。考虑到这一点,让我们制作一个可视化:

A visualization of a layer f_[ℓ] mapping ℝ² → ℝ².

注意图层 f _[ℓ】是如何通过三种不同的变换得到ℝ的每一个点的。首先, W 拉伸 2D 空间,同时保持所有线条平行。然后, b 将空间从原点移开。最后,σ smooshes 空间不考虑保持网格线平行。当 f _[ℓ】完成其转换时,根据 f _[ℓ].,每个输入激活 a _[ℓ-1】将从其原始位置移动到其相应的输出激活 a _[ℓ】

很好,但是,为什么这很有用?嗯,就其本身而言,单一的一层并不一定有用。只有当我们组合它们的时候,层才真正变得有用。再来说说这是怎么做到的。

组成:y = f(f(f(x)))

如前所述,我们可以通过组成层来构建神经网络。组合层意味着我们将一个层的输出激活输入到下一个层的输入中。

一旦我们连接好每一层,我们就可以将输入 x (也称为 a _[0】)送入第一层 f _[1】。第一层 f _[1】将其输出激活 a _[1】馈入 f _[2】,后者将其激活 a _[2】馈入 f _[3】等等。直到最终到达网络的最后一层 f _[L】,并且产生输出 y-hat (也称为 a _[L】)作为对 y 的预测。

作为这个过程在数学上的一个例子,这里有一个三层神经网络

太好了!这就概括了什么是神经网络。但是,仍然不清楚为什么一系列合成层对预测有用。为了获得更好的直觉,让我们做另一个可视化。**

像最后一个可视化一样,我们将在ℝ处理输入,在ℝ处理输出。这里的关键区别是,我们将展示整个神经网络如何改变ℝ,而不是展示一个层如何改变ℝ。为了保证整个过程可以可视化,每一层的 N ( f _[1】, f _[2】, f _[3],…, f _[L])也会映射ℝ → ℝ。这让我们可以看到神经网络转变的每一步都发生了什么。

对于这个可视化,我还将绘制两条属于橙色或蓝色类的螺旋。这些螺旋将有助于证明网络的有用性。考虑到所有这些,我们得出了以下结论:

A visualization of a neural network separating 2 spirals by mapping ℝ² → ℝ².

很酷,对吧?让我们把这个再打开一点。

首先,注意每一层是如何一层接一层地应用的。第一层 f [1】映射a[0】→a[1】。第二层 f [2】映射a[1】→a[2】。第三层 f [3】映射a[2】→a_[3】以此类推。直到最后f【L】映射a【L-1】→a_【L】(即 y 帽)。这只是遵循了神经网络的基本定义。**

接下来,注意网络的每一层是如何一点一点地分离橙色和蓝色螺旋的。在每个阶段,当前的转换都建立在前一个转换的进度之上。通过这个过程,网络正在为橙色和蓝色点中的每一个点形成其预测。当映射最终结束时,输入点 x 落在模型对 x 的类别的预测上——橙色(-1,-1)或蓝色(1,1)。在这里,模型似乎做得相当不错。**

但是神经网络有用的原因与这个具体的例子无关。模型的威力在于它的灵活性。因为每一层ℓ都可以有它自己的σ_[ℓ], W _[ℓ】,t11】和 b _[ℓ】,所以理论上该模型可以采取无限的配置。**

这意味着神经网络可以做的不仅仅是分离这些橙色和蓝色的螺旋。事实上,它可以在所有不同的配置中分离大量不同的点。它不仅仅可以分离点。事实上,它几乎可以近似任何变换(即函数)。这使得该模型适用于大量的问题。

这是神经网络的另一个例子。这个把三个螺旋分开。

A visualization of a neural network separating 3 spirals by mapping ℝ² → ℝ².

但是等一下。一个模型究竟如何知道如何逼近一个给定的函数?当然,它使用了一系列的层。但是这些层如何知道如何使自己对给定的问题有用呢?更具体地说,神经网络中的每一层如何弄清楚如何设置其参数σ、 W、b 来完成一些有用的事情?

我将把这个问题留到下一篇文章,在那里我们将开始探索神经网络如何学习它的σs、 W s b s。

如果你想知道我是如何在本文中创建可视化效果的,请查看我在 GitHub 上的机器学习模型库。

用 Numpy 从零开始的神经网络第 1 部分:简介

原文:https://towardsdatascience.com/neural-networks-with-numpy-for-absolute-beginners-introduction-c1394639edb2?source=collection_archive---------16-----------------------

在本教程中,您将简要了解什么是神经网络以及它们是如何发展起来的。最后,你会对网络如何学习有一个简单的直觉。

人工智能已经成为当今最热门的领域之一,我们大多数人都愿意从神经网络开始进入这个领域。!

但是在面对神经网络的数学密集型概念时,我们最终只是学习了一些框架,如 Tensorflow、Pytorch 等。,用于实现深度学习模型。

而且,仅仅学习这些框架,不理解底层概念,就像是在玩黑盒。

无论你是想在工业界还是学术界工作,你都将工作、调整和摆弄那些你需要清楚了解的模型。工业界和学术界都希望你对这些概念有充分的了解,包括数学。

在这一系列教程中,我将通过提供一步一步的解释使理解神经网络变得极其简单。此外,你需要的数学将是高中水平。

让我们从人工神经网络的诞生开始,并获得一些关于它如何进化的灵感。

一点点神经网络进化的历史

必须指出的是,在 1950-2000 年期间开发的大多数神经网络算法和现在存在的算法都受到了我们大脑、神经元、它们的结构以及它们如何学习和传输数据的高度启发。最受欢迎的作品包括《感知机》(1958)和《新认知机》(1980)。这些论文对解开大脑密码非常有帮助。他们试图用数学方法建立我们大脑中神经网络的模型。

而一切都是在 1986 年 AI 的教父 Geoffrey Hinton 制定了反向传播算法(没错!你学的东西都 30 多岁了!).

生物神经元

上图显示了一个生物神经元。它有从神经元接收信息的树突。接收到的信息被传递到神经元的细胞体或细胞核是信息被处理并通过轴突传递给下一层神经元的地方。

我们的大脑由大约 1000 亿个这样的神经元组成,这些神经元通过电化学信号进行交流。每个神经元都与 100 个或 1000 个其他神经元相连,这些神经元不断地发送和接收信号。

但是仅仅通过发送电化学信号,我们的大脑是如何处理这么多信息的呢?神经元如何理解哪个信号重要,哪个不重要?神经元如何知道向前传递什么信息?

电化学信号由强信号和弱信号组成。强信号是支配重要信息的信号。因此,只有强信号或它们的组合才能通过细胞核(神经元的 CPU),并通过轴突传递给下一组神经元。

但是怎么有些信号强,有些信号弱呢?

嗯,经过数百万年的进化,神经元对某些信号变得敏感。当神经元遇到特定的模式时,它们被触发(激活),并因此向其他神经元发送强信号,因此信息被传输。

我们大多数人还知道,我们大脑的不同区域被激活(或接受)不同的行为,如视觉、听觉、创造性思维等。这是因为属于大脑中特定区域的神经元被训练成更好地处理特定类型的信息,因此只有在特定类型的信息被发送时才会被激活。下图让我们更好地了解了大脑的不同接收区域。

Different regions of the cortex

如果是这样的话……可以让神经元对不同的模式敏感吗(例如,如果它们真的基于某些模式变得敏感了)?

通过神经可塑性已经表明,大脑的不同区域可以被重新连接以执行完全不同的任务。例如负责触觉的神经元可以被重新连接,变得对气味敏感。看看下面这个很棒的 TEDx 视频,了解更多关于神经可塑性的知识。

TEDx video on Neuroplasticity[Source]

但是神经元变得敏感的机制是什么呢?

不幸的是,神经科学家仍在试图找出答案!!

但幸运的是,AI Geff 的上帝之父通过发明反向传播挽救了这一天,反向传播为我们的人工神经元完成了同样的任务,即,使它们对某些模式敏感。

在下一节中,我们将探索感知器的工作,并获得数学直觉。

感知器/人工神经元

A Perceptron Model

从图中,您可以观察到感知器是生物神经元的反映。与权重( wᵢ )结合的输入类似于树突。这些值被求和并通过激活函数(类似于图 1 所示的阈值函数)。这类似于原子核。最后,激活的值被传输到下一个神经元/感知器,其类似于轴突。

潜在权重( wᵢ )乘以每个输入( xᵢ )描述了相应输入信号的重要性(强度)。因此,权重值越大,特征越重要。

您可以从这个架构中推断出,权重是感知器中学习的内容,以便达到所需的结果。还学习了附加偏置( b ,这里是 w₀ )。

因此,当有多个输入(比如 n )时,等式可以概括如下:

最后,求和的输出(假设为 z )被馈送到阈值激活函数,在此函数输出

一个例子

让我们考虑我们的感知器作为逻辑门来获得更多的直觉。

让我们选择一个和门。闸门的真值表如下所示:

用于与门的感知器可以如图所示形成。很明显,感知机有两个输入(这里 x₁ = Ax₂ = B )。

我们可以看到,对于输入 x₁、x₂x₀ = 1,设置它们的权重为

并且保持阈值函数作为激活函数,我们可以到达与门

现在,让我们动手把它整理出来,并测试一下!

1

类似地,对于或非门,真值表为:

或非门的感知器如下:

您可以将权重设置为

从而获得一个或非门。

您可以继续用代码实现它,如下所示:

0

你实际计算的…

如果你分析你在上面的例子中试图做的事情,你会意识到你实际上是在试图调整权重的值来获得所需的输出。

让我们考虑一下或非门的例子,并将其分解成非常小的步骤,以便获得更多的理解。

你通常首先要做的是简单地设置一些权重值,然后观察结果,比如说

那么输出将如下表所示:

那么,如何固定权重值,以便获得正确的输出呢?

凭直觉,你可以很容易地观察到 w₀ 必须增加而 w₁w₀ 必须减少或者更确切地说是变负,这样你就获得了实际的输出。但是,如果你打破这种直觉,你会发现你实际上是在寻找实际输出和预测输出之间的差异,并最终反映在重量上…

这是一个非常重要的概念,你将会更深入地挖掘它,它将会成为阐明梯度下降反向传播背后的思想的核心。

你学到了什么?

  • 神经元必须对某种模式敏感,才能识别它。
  • 因此,类似地,在我们的感知器/人工神经元中,权重是要学习的

在后面的文章中,你将完全理解如何训练权重来识别模式,以及现有的不同技术。

稍后您将会看到,神经网络与生物神经网络的结构非常相似。

虽然在本文的第一部分我们确实只学到了一些小概念(尽管非常重要),但它们将作为实现神经网络的坚实基础。此外,我将这篇文章写得短小精悍,这样太多的信息不会一下子被丢弃,会有助于吸收更多的信息!

在下一篇教程中,你将详细学习线性回归(也可以称为具有线性激活功能的感知器)并实现它们。详细描述并实现了帮助学习权重的梯度下降算法。最后,在线性回归的帮助下,你将能够预测事件的结果。所以,请阅读下一篇文章来实现它吧!

你可以点击这里查看文章的下一部分:

[## 绝对初学者用的带 Numpy 的神经网络第 2 部分:线性回归

在本教程中,您将详细学习使用 Numpy 实现预测的线性回归,并可视化…

medium.com](https://medium.com/@surajdonthi95/neural-networks-with-numpy-for-absolute-beginners-part-2-linear-regression-e53c0c7dea3a)

用 Numpy 从零开始的神经网络第 2 部分:线性回归

原文:https://towardsdatascience.com/neural-networks-with-numpy-for-absolute-beginners-part-2-linear-regression-e53c0c7dea3a?source=collection_archive---------7-----------------------

在本教程中,您将详细学习使用 Numpy 实现预测的线性回归,并直观了解算法如何逐时段学习。除此之外,您将探索两层神经网络。

在上一个教程中,你对感知器有一个非常简单的概述。

[## 神经网络从零开始与 Numpy:简介

在本教程中,您将简要了解什么是神经网络以及它们是如何发展起来的。在…

towardsdatascience.com](/neural-networks-with-numpy-for-absolute-beginners-introduction-c1394639edb2)

在本教程中,您将深入研究实现一个线性感知器(线性回归),从中您将能够预测问题的结果!

本教程显然会包括更多的数学知识,因为这是不可避免的,但没有必要担心,因为我会解释它们。不管这些,必须认识到,所有的机器学习算法基本上都是最终以代码形式实现的数学公式。

在我们开始之前,还记得我们用阈值激活函数来模拟与门和或非门的功能吗?!

这里我们将使用另一个极其简单的激活函数,叫做线性激活函数(相当于没有任何激活!).

让我们来看看这个激活功能能带来什么样的奇迹吧!

线性激活函数

假设感知器只有一个输入和偏差,如下所示:

Computation graph of Linear Regression

得到的线性输出(即和)将是

。这是直线的方程式,如下图所示。

Graph of Linear Equation

这里必须注意,当没有使用激活函数时,我们可以说激活函数是线性的。

这是一个多元(多变量)线性方程。

让我们看看这是如何用于预测下一部分中的 y 的实际输出,即 线性回归

线性回归

n 维空间中对给定的一组数据拟合一个线性方程称为线性回归。下面的 GIF 图像显示了一个线性回归的例子。

Linear Regression [Source Link]

简单来说,你试着找出最符合上图所示点集的 mb 的最佳值。当我们获得了可能的最佳拟合时,我们可以预测给定×的 y 值。

一个很通俗的例子就是房价预测问题。在这个问题中,给你一组值,比如房子的面积和房间的数量等等。你必须预测给定这些价值的房子的价格。

所以,最大的问题是…预测算法是如何工作的?它是如何学会预测的?

让我们边走边学吧!

让我们从导入所需的包开始。

您将使用sklearn数据集生成器来创建数据集。您还将使用该包将数据分为训练数据和测试数据。如果你不知道sklearn,它是一个丰富的包,有很多机器学习算法。尽管您获得了用于执行线性回归的预建函数,但在本教程中,您将从头开始构建它。

为了创建数据集,您必须首先设置一个超参数列表,而 mb 是参数、样本数量、输入特征数量、神经元数量、学习速率、训练的迭代次数/次数等。被称为超参数。在实现算法时,您将了解这些超参数。

现在,您应该设置训练样本的数量、输入特征的数量、学习速率和时期。你很快就会明白学习的速度和时代。

您的第一个任务是导入或生成数据。在本教程中,您将使用sklearnmake_regression函数生成数据集。

出于学习的目的,我们将保持特征的数量最少,以便于可视化。因此,您必须只选择一个特征。

现在,是时候想象一下数据生成器做了什么了!

让我们检查矢量形状的一致性。

Shape of vector X: (200, 1) Shape of vector y: (200,)

我们需要将 y 的大小重置为(200, 1),这样我们就不会在向量乘法过程中出错。

(200, 1)

接下来,您必须将数据集分为定型集和测试集,以便在定型模型后,可以使用数据集的一部分来测试回归模型的准确性。

现在让我们将数据分为训练集和测试集。

在我们的例子中,训练集是 80%,测试集是 20%。

让我们检查所创建的训练和测试数据集的形状。

(160, 1) (160, 1) (40, 1) (40, 1)

如您所见,80%的数据,即 200 个数据点中的 80%是正确的 160。

那么,到目前为止我们取得了什么成就?

我们已经完成了最初的数据预处理,并且还通过可视化对数据进行了探索。这通常是建模任何机器学习算法的第一步。我们还拆分了数据,以便在模型训练完成后测试其准确性。

我们下一步做什么?

清晰的如上面的线性回归 GIF 图所示,我们首先需要考虑一条随机线,然后通过训练将其拟合到数据上。

因此,下一步是随机生成一条具有随机斜率和截距(偏差)的直线。目标是实现与生产线的最佳匹配。

现在,给定m&b,我们就可以绘制生成的直线了。

让我们更新函数plot_graph来显示预测线。

由于现在已经生成了直线,您需要预测它为给定的 x 值产生的值。根据这个值,我们要做的就是计算它们的均方误差。为什么?

我们怎样才能发现实际产量和预测产量之间的差异呢?

最简单的方法是减去这两个差值。我们有一条随机线,它为每个给定的 x 给出一个输出y_pred,但它肯定不是实际输出。幸运的是,我们也有所有 x 的实际输出!因此,我们要做的不是直接取差(技术上称为绝对距离或 L1 距离),而是将其平方(称为欧几里德距离或 L2 距离),并取所有给定点的平均值&这称为均方误差

现在让我们通过定义一个函数forward_prop根据参数m&b来预测y_pred的值。

成本/损失函数

如前所述,现在您已经得到了X_train的相应值和y_pred的预测值,您将计算成本/误差/损失函数。

损失(均方误差)为:

对所有 M 例求和,得到损失 fn。如下:

我们的目标是将损失明显降至最低,使回归线预测更准确。

让我们现在就把它编纂成法典。

您还可以保存 损耗 的每个值,这些值将被计算出来,以图形方式显示它在训练中的变化。

4005.265725705774

让我们修改上面定义的plot_graph函数来绘制损失。

您会看到由参数 mb 创建的直线。

既然你已经计算了损失,让我们把它减到最小。

线性回归的梯度下降法

由于损失是因变量而m&b是自变量,我们将不得不更新m&b以便找到最小的 损失

所以,迫在眉睫的问题是…

如何更新参数 mb

例如,让我们仅考虑如下所示的单个参数 p ,并让**(目标)成为必须预测的值。我们看到,随着 成本 收敛到最小值,参数 p 达到一个称为最优值的特定值。假设 p 的最优值为 a

Gradient Descent w.r.t p. [Source Link]

你可以从这张图表中观察到一些情况。

从图中可以清楚地看到,随着 p【a(minima)移动,成本降低,随着远离它,成本增加。

现在,如何才能让 p 朝着a 移动,而不管是如图所示的 a 的左边还是右边?**

让我们考虑曲线的 p 。从微积分中我们知道,一条曲线在一点的斜率** 由dy/dx给出(这里是dL/dp其中 L →损耗 )。从图中可以看出,当 pa 的左边时, 斜率 显然是而当它在右边时, 斜率 就会是 +ve 。但是我们看到,如果 pa 的左边,就必须给 p 加一些值。同样,当 pa 的右边时,必须减去一些值。****

Source: https://imgflip.com/i/2dz47q

这就意味着当ve时就隐含着 p = p +(有些 val。) 和当 斜率 +ve寓意p = p ‖(有些 val。)* 向 移动一个 。*******

我们从 p 中减去 斜率 。这样, 斜率 被取反,确保其始终向 a 移动。得到的等式将是,

还必须观察到,如果 成本 过高,则 斜率 也会过高。于是,当从p值中减去斜率时,可能会过冲。因此,有必要减小 斜率 的值,使得 p 不会过冲 a 。因此,我们给斜率引入一个叫做 学习率【α】的阻尼因子。稍后你会看到,通过改变α,误差下降的速率会发生变化。****

我们最终得到的是,

如图所示, pcost 所走的轨迹是一条钟形曲线。

这种方法叫做梯度下降

在我们的例子中,我们使用两个参数 mb 。因此,钟形曲线将是 3- 尺寸,如下图所示。

Gradient Descent w.r.t to parameters m and b.[Source]

如上所述,您将计算损失函数 w.r.t 对参数m&b的偏导数。【注:通常期望你知道偏导数的基本概念。然而,如果你没有,你可以参考这个奇妙的可汗学院视频

****

Source: https://i.chzbgr.com/full/2689942016/h8B269F68/

更新参数

现在我们从它们各自的导数中减去参数 mb 的斜率以及阻尼因子 α(alpha)

****

从减小 mb 的值开始,它们逐渐向最小值移动。因此,以这种方式更新参数必须进行多次迭代,这被称为 时期

让我们定义一个函数grad_desc,它同时调用gradientupdate_params

我们现在已经定义了我们需要的一切,所以让我们把所有的函数编译成一个,看看我们的算法是如何工作的。因此,在实际运行代码之前,您必须设置超参数。

**Epoch: 0 
Loss = 2934.082243250548Epoch: 
10 Loss = 1246.3617292447889**

**Epoch: 20 
Loss = 546.310951004311**

**Epoch: 30 
Loss = 255.88020867147344**

**Epoch: 40 
Loss = 135.36914932067438**

**Epoch: 50 
Loss = 85.35744394597806**

**Epoch: 60 
Loss = 64.60029693013243**

由于您已经训练了 60 个时期的参数,并且回归线看起来符合数据,您可以前进到最后一个阶段,即预测我们的测试数据并检查准确性。

预言;预测;预告

为了检查准确性,您可以取所有测试数据点的百分比误差的平均值。

**Prediction: 
Loss = 56.53060443946197 
Accuracy = 80.1676%Hence 
m = 82.34083095217943 
b = 0.46491578390750576**

如上图所示,考虑到数据中的差异,准确度为 80%,这是“可以的”。

我希望在文章中引入一些真正有趣的东西,作为奖励,我还加入了神经网络的介绍。但这肯定伴随着一个陷阱!

具有线性激活函数的两层神经网络

神经网络如下所示。

从图像中,我们观察到第一层中的两个神经元各有两个输入,第二层中有一个输出神经元。

我们将使用矩阵来表示上述方程。我们可以用向量(单列矩阵)形式将它们表示为:

在进行矩阵计算时,我们需要考虑维数和乘法。因此,我们重新排列一位以达到所需的输出。

方程的展开是不需要的,因此让我们坚持

同样,的价值

****

现在,2ⁿᵈ图层的输出将是:

从上面的一组方程中,我们看到一个具有线性激活函数的神经网络简化为一个线性方程

神经网络的整个目的是创建一个非常复杂的函数,可以适应任何类型的数据,正如可以清楚地看到的那样,具有线性激活函数的神经网络没有达到目的。因此,需要严格注意的是,线性函数不能用作神经网络的激活函数** ,尽管它只能用于回归问题的最后一层。**

那么我想你必须耐心等待下一个教程来实现它!

这里是 Jupyter 笔记本中完整实现的链接:

继续克隆它,并开始在你的 Colab 上运行细胞,看看梯度下降的奇迹!!

** [## SurajDonthi/文章-教程

神经网络相关的文章会贴在这里。-SurajDonthi/文章-教程

github.com](https://github.com/SurajDonthi/Article-Tutorials/blob/master/NN with Numpy 2/Neural_Networks_for_Absolute_Beginners_Part_2_Linear_Regression.ipynb)

结论

在本教程中,您学习了

  1. 线性激活函数执行回归任务,即学习预测和预报值。这种方法到处都叫线性回归
  2. 具有线性激活函数的 MLP(多层感知器)简化为正常的线性回归任务。因此,线性激活不能用于网络的隐藏层。但是,它可以在最后一层用于回归/预测任务。

在下一个教程中,您将学习 Sigmoid 激活函数并执行逻辑回归,这是实现神经网络的最重要的关键。

你可以在这里阅读下一篇关于逻辑回归的文章:

[## 用 Numpy 从零开始的神经网络第 3 部分:逻辑回归

sigmoid 激活函数是神经网络中最基本的概念。在本教程中,您将学习…

towardsdatascience.com](/neural-networks-with-numpy-for-absolute-beginners-part-3-logistic-regression-18b474096a4e)

你在做什么很酷的深度学习项目吗?

你可以在 Linkedin 上联系我:

[## Suraj Donthi | LinkedIn

Suraj Donthi 是一名计算机视觉顾问|机器学习和深度学习实践者和培训师。和他联系...

www.linkedin.com](https://www.linkedin.com/in/suraj-donthi/)

如有任何疑问,请在 Twitter 上给我发消息:

[## Suraj Donthi (@suraj_donthi) |推特

twitter.com](https://twitter.com/suraj_donthi)**

正弦基函数神经网络

原文:https://towardsdatascience.com/neural-networks-with-sine-basis-function-c5c13fd63513?source=collection_archive---------14-----------------------

由于在各个领域的成功,神经网络证明了它们是我们这个世纪的趋势主题。今天我要讲的是用正弦函数代替线性函数作为基的神经网络。我们将实现一个使用正弦函数作为基础的神经网络,我们将评估结果。

这个想法是从哪里来的?

Photo by Benjamin Lizardo on Unsplash

使用正弦函数作为神经网络基础的想法来自于我的信号处理背景。如果你以前听说过傅里叶变换,你知道你可以用余弦和正弦函数来表示任何函数,并且你可以在频域中清楚地显示求和函数。“你可以用余弦和正弦函数来表示任何函数”这句话打动了我。我把这个和神经网络联系起来,因为我们也可以用神经网络来表示任何函数。

说得够多了,我知道你想看到背后的数学,实现和结果。那么,让我们继续……

神经网络中的正弦基函数

Sine Basis Function for Neural Networks

Basic Structure

履行

我使用了 Python 中如何从零开始构建自己的神经网络中的类和代码结构作为我的基础。

import numpy as npclass NeuralNetwork:
    #DEFINE INITIALS
    def __init__(self, x, y):
        self.input      = x
        self.y          = y
        self.weights_in = np.random.uniform(-1, 1,(self.y.shape[1],self.input.shape[1]))
        self.weights_out = np.random.uniform(-1, 1,(self.y.shape[1],self.input.shape[1]))     
        self.output     = np.random.uniform(-1, 1,self.y.shape)
        print('Output:',self.output)
        print('Y:',self.y)#DEFINE FEEDFORWARD
    def feedforward(self,cnt):
        self.output[cnt] = np.sum(self.weights_out*self.input[cnt]*np.sin(np.pi*self.input[cnt]*self.weights_in),axis = 1)

    #DEFINE BACKPROPAGATION
    def backprop(self,cnt):
        error = np.square(self.y[cnt]-self.output[cnt])
        derror_doutput = self.y[cnt]-self.output[cnt]
        doutput_dweights_in = self.weights_out * np.square(self.input[cnt]) * np.pi * np.cos(np.pi*self.input[cnt]*self.weights_in)
        doutput_dweights_out = self.input[cnt]*np.sin(np.pi*self.input[cnt]*self.weights_in)
        dweights_in = np.dot(derror_doutput,doutput_dweights_in)
        dweights_out = np.dot(derror_doutput,doutput_dweights_out)
        self.weights_in += dweights_in*0.05
        self.weights_out += dweights_out*0.05#PREDICT THE TEST DATA
    def predict(self,input_):
        predictions = []
        for elm in input_:
            predictions.append(np.sum(self.weights_out*elm*np.sin(np.pi*elm*self.weights_in),axis = 1).tolist())
        return np.array(predictions)

    #SAVE WEIGHTS
    def save_weights(self,dir_in = './weights_in.npy',dir_out = './weights_out.npy'):
        np.save(dir_in,self.weights_in)
        np.save(dir_out,self.weights_out)

    #IMPORT WEIGHTS
    def import_weights(self,dir_in = './weights_in.npy',dir_out = './weights_out.npy'):
        self.weights_in = np.load(dir_in)
        self.weights_out = np.load(dir_out)

我们定义了我们的阶级。测试时间到了。

我们将用我们的神经网络来表示逻辑门(AND、OR、XOR)(这意味着我们将从神经网络为每个逻辑门获得 3 个输出)。我将为每个输入样本给出 3 个值。输入不是整数,而是浮点数,比如 0.01 而不是 0,或者 0.99 而不是 1。

示例:

输入:[0.01,0.01,0.99]

与:0.01,或:0.99,异或:0.99

x = np.array([[0.01,0.1,0.01],[0.01,0.99,0.99],[0.99,0.99,0.01],[0.99,0.99,0.01],[0.9,0.9,0.9]])
y = np.array([[0.01,0.01,0.01],[0.01,0.99,0.99],[0.01,0.99,0.99],[0.01,0.99,0.99],[0.99,0.99,0.01]])nn = NeuralNetwork(x,y)
#TRAIN NETWORK FOR 2000 TIMES.
for gen_cnt in range(2000):
    for cnt in range(5):
        nn.feedforward(cnt)
        nn.backprop(cnt)#PREDICT THE TEST DATA
predictions = nn.predict(np.array([[0.01,0.2,0.2],[0.9,0.1,0.95]]))
print('Predictions:\n',np.around(predictions),'\nExpected:\n',[[0,0,0],[0,1,1]])

我给出的测试数据是[[0.01,0.2,0.2],[0.9,0.1,0.95]],而不是[[0.01,0.01,0.01],[0.99,0.01,0.99]],看看网络是否做出了概括。

结果

预言:
[[ 0。0.-0.][ 0.1.1.]]
预期:
[[0,0,0],[0,1,1]]

在我训练了几次之后,我发现最好的重量是:

权重 _ 输入:

0.793539-0.866737 0.883148
1.32484-0.20837 0.214222
0.359695-1.21818-0.329374

权重 _ 出:

  • 0.0841964-0.147961 0.854469
    -0.958252 0.0361619 1.2046
    0.73270.0986183-0.305971

结论

正如我们所看到的,“你可以用正弦函数表示任何函数”的概念也适用于神经网络。即使我们创建了一个没有任何隐藏层的神经网络,我们也证明了正弦函数可以代替线性函数作为基函数。因为它们是动态函数,我们不需要添加任何激活函数。由于正弦函数的性质,我们可以很容易地捕捉到非线性。我的下一步是实现深度神经网络的正弦基函数。这是一个复杂的问题,再次感谢正弦函数的性质,但挑战总是受欢迎的…

神经 ODEs:另一个深度学习突破的崩溃

原文:https://towardsdatascience.com/neural-odes-breakdown-of-another-deep-learning-breakthrough-3e78c7213795?source=collection_archive---------0-----------------------

Visualization of the Neural ODE learning the dynamical system

大家好!如果你正在阅读这篇文章,很可能你正在赶上人工智能世界最近的进展。我们今天要复习的题目来自 NIPS 2018,讲的是来自那里的最佳论文奖:神经常微分方程 (Neural ODEs)。在这篇文章中,我将尝试给出一个简短的介绍和这篇论文的重要性,但我将强调实际应用,以及我们如何和为了什么可以在应用中应用这种需要的神经网络,如果可以的话。和往常一样,如果你想直接进入代码,你可以查看这个 GitHub 库,我推荐你在 Google Colab 中启动它。

我们为什么关心颂歌?

首先,让我们快速回顾一下什么是野兽常微分方程。它描述了依赖于一个变量(这就是为什么普通)的一些过程随时间的演变,这种随时间的变化通过导数来描述:

Simple ODE example

通常,我们可以讨论解这个微分方程,如果我们有一些初始条件(在这一点上过程开始)并且我们想看这个过程如何发展到一些最终状态。解函数也叫积分曲线(因为我们可以对方程积分得到解 x(t) )。让我们尝试使用 SymPy 软件包来解决上图中的方程:

from sympy import dsolve, Eq, symbols, Functiont = symbols('t')
x = symbols('x', cls=Function)
deqn1 = Eq(x(t).diff(t), 1 - x(t))
sol1 = dsolve(deqn1, x(t))

它将作为解决方案返回

Eq(x(t), C1*exp(-t) + 1)

其中 C1 是一个常数,可以在给定一些初始条件的情况下确定。如果以适当的形式给出,常微分方程可以解析求解,但通常是数值求解。最古老和最简单的算法之一是欧拉法,其核心思想是使用切线逐步逼近解函数;

http://tutorial.math.lamar.edu/Classes/DE/EulersMethod.aspx

访问图片下面的链接可以得到更详细的解释,但是最后,我们得到了一个非常简单的公式,方程式

http://tutorial.math.lamar.edu/Classes/DE/EulersMethod.aspx

n 时间步长的离散网格上的解为

http://tutorial.math.lamar.edu/Classes/DE/EulersMethod.aspx

关于 ODEs 的更多细节,尤其是如何用 Python 对它们进行编程以及它们的解决方案,我推荐你去看看这本书,它也有很多化学、物理和工业领域中具有这种时间演化的过程的例子,可以用 ODEs 来描述。此外,与 ML 模型相比,有关微分方程的更多直观信息,请访问该资源。与此同时,看看欧拉方程,难道不会让你想起最近的深度学习架构吗?

ResNets 是 ODEs 解?

没错。 y_{n+1} = y_n + f(t_n,y_n) 不过是 ResNet 中的一个剩余连接,其中某一层的输出是该层 f() 本身的输出与该层的输入 y_n 之和。这基本上就是神经 ODE 的主要思想:一个神经网络中的一串残差块,基本上就是用欧拉方法对 ODE 的一个求解!在这种情况下,系统的初始条件是“时间” 0 ,这表示神经网络的第一层,并且作为 x(0) 将服务于正常输入,它可以是时间序列、图像,无论你想要什么!在“时间” t 的最终条件将是神经网络的期望输出:标量值、表示类的向量或任何其他东西。

如果我们记得,这些剩余连接是欧拉方法的离散化时间步骤,这意味着我们可以调节神经网络的深度,只需选择离散化方案,因此,使解决方案(又名神经网络)或多或少准确,甚至使其像无限层一样!

Difference between ResNet with a fixed number of layers and ODENet with a flexible number of layer

欧拉是不是太原始的 ODE 求解方法?的确是这样,所以让我们用一些抽象概念代替 ResNet / EulerSolverNet,如 ODESolveNet ,其中 ODESolveNet 将是一个函数,它提供了一个对 ODE(低调:我们的神经网络本身)的解决方案,比 Euler 的方法具有更好的准确性。网络架构现在可能如下所示:

nn = Network(
  Dense(...), # making some primary embedding
  ODESolve(...), # "infinite-layer neural network"
  Dense(...) # output layer
)

我们忘记了一件事…神经网络是一个可微分的函数,所以我们可以用基于梯度的优化例程来训练它。我们应该如何通过ode solve()函数反向传播,在我们的例子中它实际上也是一个黑盒?特别地,我们需要输入和动力学参数的损失函数的梯度。数学窍门叫做伴随灵敏度法。更多细节我会参考原论文本教程,但本质描述在下图( L 代表我们要优化的主损失函数):**

Making “backpropagation” gradients for the ODESolve() method

简而言之,伴随系统与描述过程的原始动力系统一起,通过链式法则(这就是众所周知的反向传播的根)向后描述过程中每个点的导数状态。正是从它,我们可以通过初始状态获得导数,并且以类似的方式,通过模拟动力学的函数的参数(一个“剩余块”,或“旧”欧拉方法中的离散化步骤)。

如需了解更多详情,我建议您也观看该论文作者之一的演示:

神经微分方程的可能应用

首先,使用它们而不是“正常结果”的优势和动机:

  • 内存效率:在反向传播时,我们不需要存储所有的参数和梯度
  • 自适应计算:我们可以用离散化方案来平衡速度和精度,此外,在训练和推理时使其不同
  • 参数效率:相邻“层”的参数自动绑定在一起(参见论文
  • 规范流新型可逆密度模型
  • 连续时间序列模型:连续定义的动态可以自然地包含在任意时间到达的数据。

根据这篇论文,除了用 ODENet 代替 ResNet 用于计算机视觉之外,我认为现在有点不现实的应用程序是下一个:

  • 将复杂的常微分方程压缩到单个动态建模神经网络中
  • 将它应用于缺少时间步长的时间序列
  • 可逆规范化流(超出了本博客的范围)

对于缺点,查阅原论文,有一些。理论够了,现在来查一些实际例子。提醒一下,所有实验的代码都在这里

学习动力系统

正如我们之前看到的,微分方程被广泛用于描述复杂的连续过程。当然,在现实生活中,我们将它们视为离散的过程,最重要的是,时间步长 t_i 上的许多观察值可能会完全丢失。让我们假设你想用神经网络来模拟这样一个系统。在经典的序列建模范例中,你如何处理这种情况?以某种方式把它扔进循环神经网络,它甚至不是为它设计的。在这一部分,我们将检查神经 ode 如何处理它们。

我们的设置如下:

  1. 定义颂歌本身我们将建模为 PyTorch nn。模块()
  2. 定义一个简单的(或者不是真正的)神经网络,该网络将对从 h_t 到 h_{t+1}的两个后续动态步骤之间的动态进行建模,或者在动态系统的情况下,对 x_t 和 x_{t+1}进行建模。
  3. 运行优化过程,该过程通过 ODE 解算器反向传播,并最小化实际动态和模拟动态之间的差异。

在所有下面的实验中,神经网络将只是下面的(它被认为足以模拟具有两个变量的简单函数):

*self.net = nn.Sequential(
            nn.Linear(2, 50),
            nn.Tanh(),
            nn.Linear(50, 2),
        )*

所有进一步的例子都受到了这个知识库惊人解释的高度启发。在接下来的小节中,我将展示我们所模拟的动态系统在代码中是如何表现它们自己的,以及系统如何随着时间的推移而演化,并且相位图是如何被 ODENet 拟合的。

简单螺旋函数

在这个和所有未来的可视化中,虚线代表试衣模型。

*true_A = torch.tensor([[-0.1, 2.0], [-2.0, -0.1]])class Lambda(nn.Module):
    def forward(self, t, y):
        return torch.mm(y, true_A)*

***

Phase space on the left, time-space on the right. The straight line stands for the real trajectory and dotted one — for the evolution of the learned by the Neural ODE system*

随机矩阵函数

*true_A = torch.randn(2, 2)/2.*

***

Phase space on the left, time-space on the right. The straight line stands for the real trajectory and dotted one — for the evolution of the learned by the Neural ODE system*

沃尔泰拉-洛特卡系统

*a, b, c, d = 1.5, 1.0, 3.0, 1.0
true_A = torch.tensor([[0., -b*c/d], [d*a/b, 0.]])*

***

Phase space on the left, time-space on the right. The straight line stands for the real trajectory and dotted one — for the evolution of the learned by the Neural ODE system*

非线性函数

*true_A2 = torch.tensor([[-0.1, -0.5], [0.5, -0.1]])
true_B2 = torch.tensor([[0.2, 1.], [-1, 0.2]])class Lambda2(nn.Module):

    def __init__(self, A, B):
        super(Lambda2, self).__init__()
        self.A = nn.Linear(2, 2, bias=False)
        self.A.weight = nn.Parameter(A)
        self.B = nn.Linear(2, 2, bias=False)
        self.B.weight = nn.Parameter(B)

    def forward(self, t, y):
        xTx0 = torch.sum(y * true_y0, dim=1)
        dxdt = torch.sigmoid(xTx0) * self.A(y - true_y0) + torch.sigmoid(-xTx0) * self.B(y + true_y0)
        return dxdt*

***

Phase space on the left, time-space on the right. The straight line stands for the real trajectory and dotted one — for the evolution of the learned by the Neural ODE system*

正如我们所看到的,我们的单个“剩余块”不能很好地学习这个过程,所以我们可能会使它在接下来的函数中变得更复杂。

神经网络功能

让我们通过具有随机初始化权重的多层感知器来制作完全参数化的函数:

*true_y0 = torch.tensor([[1., 1.]])
t = torch.linspace(-15., 15., data_size)class Lambda3(nn.Module):

    def __init__(self):
        super(Lambda3, self).__init__()
        self.fc1 = nn.Linear(2, 25, bias = False)
        self.fc2 = nn.Linear(25, 50, bias = False)
        self.fc3 = nn.Linear(50, 10, bias = False)
        self.fc4 = nn.Linear(10, 2, bias = False)
        self.relu = nn.ELU(inplace=True)

    def forward(self, t, y):
        x = self.relu(self.fc1(y * t))
        x = self.relu(self.fc2(x))
        x = self.relu(self.fc3(x))
        x = self.relu(self.fc4(x))
        return x*

***

Phase space on the left, time-space on the right. The straight line stands for the real trajectory and dotted one — for the evolution of the learned by the Neural ODE system*

这里 2–50–2 网络因为太简单而可怕地失败,让我们增加它的深度:

*self.net = nn.Sequential(
            nn.Linear(2, 150),
            nn.Tanh(),
            nn.Linear(150, 50),
            nn.Tanh(),
            nn.Linear(50, 50),
            nn.Tanh(),
            nn.Linear(50, 2),
        )*

***

Phase space on the left, time-space on the right. The straight line stands for the real trajectory and dotted one — for the evolution of the learned by the Neural ODE system*

现在它或多或少像预期的那样工作了,不要忘记检查代码:)

作为生成模型的神经微分方程

作者还声称,他们可以通过 VAE 框架建立一个生成时间序列模型,使用神经微分方程作为其中的一部分。它是如何工作的?

Illustration from the original paper

  • 首先,我们用一些“标准”时间序列算法对输入序列进行编码,比如说 RNN 算法,以获得过程的主要嵌入
  • 通过神经 ODE 运行嵌入以获得“连续”嵌入
  • 以 VAE 方式从“连续”嵌入中恢复初始序列

作为概念验证,我刚刚重新运行了来自这个库的代码,它看起来在学习螺旋轨迹方面工作得很好:

Dots are sampled noisy trajectories, Blue line is true trajectory, the orange line stands for recovered and interpolated trajectory

然后,我决定将心跳从心电图(ECG)转换为相位图,将 x(t) 作为时间-空间,将 x`(t) 作为导数-空间(如本作品所示),并尝试适应不同的 VAE 设置。这个用例可能对像 Mawi Band 这样的可穿戴设备非常有用,在这些设备中,由于噪声或中断的信号,我们必须恢复它(实际上,我们是在深度学习的帮助下完成的,但 ECG 是一个连续信号,不是吗?).不幸的是,它并没有很好地收敛,显示出过度适应单一形式节拍的所有迹象:

***

Phase spaces. Blue line — real trajectory, orange line — sampled and noisy trajectory, green line — auto-encoded trajectory* ***

Time spaces. Blue line — real signal, orange line — sampled and noisy signal, green line — auto-encoded signal*

我还尝试了另一个实验:只在每次心跳的部分学习这个自动编码器,并从中恢复整个波形(也就是说,让我们外推一个信号)。不幸的是,无论我对超参数和数据预处理做了什么,将这段信号向左或向右外推都没有得到任何有意义的结果。或许,读者中的某个人可以帮助理解哪里出错了:(

下一步是什么?

很明显,神经 ode 被设计用来学习相对简单的过程(这就是为什么我们甚至在标题中有普通的,所以我们需要一个能够建模更丰富的函数族的模型。已经有两种有趣的方法了:

也需要一些时间来探索它们:)

结论

依我看,神经微分方程还没有准备好用于实践。这个想法本身很棒,就创新水平而言,它让我想起了杰弗里·辛顿的《胶囊网络》,但它们现在在哪里?和神经 ode 一样,它们在玩具任务上表现出了良好的结果,但在任何接近真实应用或大规模数据集的任务上都失败了。

我目前只能看到两个实际应用:

  • 使用 ODESolve() 层来平衡经典神经网络中的速度/精度权衡
  • 将常规 ode“压缩”到神经架构中,以将其嵌入标准数据科学管道中

就我个人而言,我希望这个方向能有进一步的发展(我在上面展示了一些链接),让这些神经(O)DEs 能代表更丰富的函数类,我会密切关注它。

P.S.
如果你觉得这个内容有用和有观点,你可以在 Bitclout 上支持我。也请在脸书博客上关注我,在那里我会定期发布简短的人工智能文章或新闻,对于媒体来说太短了,在 Instagram 上发布个人信息,在 Linkedin 上发布!如果你想在可解释的人工智能应用或其他人工智能项目上合作,请联系我。

posted @ 2024-10-14 11:47  绝不原创的飞龙  阅读(309)  评论(0)    收藏  举报