TowardsDataScience-博客中文翻译-2016-2018-三十九-

龙哥盟 / 2024-10-13 / 原文

TowardsDataScience 博客中文翻译 2016~2018(三十九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

2017 年大数据趋势点燃

原文:https://towardsdatascience.com/trends-out-of-2017s-big-data-ignite-2efaa93abbe9?source=collection_archive---------9-----------------------

A beautiful downtown view of Grand Rapids, Michigan from the Big Data Ignite conference

我有幸参加了在密歇根州大急流城举行的大数据点燃 2017 大会。为期三天的会议以“指数智能时代”为主题,并为我提供了一个机会,让我后退一步,更广泛地了解大数据和分析市场。我利用这段时间联系并向其他身处战壕的人学习,让这些大数据平台在西密歇根的几家大型企业中发挥作用。与了解各种平台供应商的人交谈并了解推动他们的物联网、数据和数据湖基础设施的工具选择是非常宝贵的。

在这三天里,一些主题固化成了一些有趣的趋势。

企业正在积极追求大数据和分析,而且不仅仅是从 IT 内部。

在会议期间,我观看了演示,并与来自梅耶尔、 Steelcase 、安利和许多其他公司的团队成员进行了多次走廊交谈。这些价值数十亿美元的企业正在努力寻找合适的人才,然后给他们试验的自由。希望这种自由将导致一个成功的大数据计划成为核心业务运营的中心。因此,这些团队正在推动其组织内端到端的变革,因为他们发现了哪些数据可用,如何最好地集中这些数据,并最终开放这些数据供其他人从中获取价值。这些“数据湖”和“企业数据集市”正在收集从系统日志到用户生成的社交内容和来自制造运营的物联网连接资产数据流的一切信息。

数字化转型的核心是由数据和分析驱动的。

今天,我们在报纸上听到了很多关于数字转型的报道。和许多重大趋势一样,这个词再次被滥用和误解。三天来,我们清楚地看到,任何数字化转型努力的核心都是对数据和分析的高度关注。这不仅仅是关于打造一个数字产品或者开辟一个新的数字频道。数字化转型是从公司的核心基础开始,将重点转移到收集和利用数据,以做出更好、更快、更明智的决策。我们与之交谈的进步公司正在考虑如何让组织中的任何人都可以访问数据。他们正在积极地从命令和控制型 IT 组织转变为支持型组织。Meijer 甚至发展到建立开发“沙箱”的程度,在沙箱中,公司内任何参加过他们的“数据训练营”的人都被允许使用生产级数据来评估假设或解决业务线问题。

模具市场错综复杂,充满了管道胶带。

当我坐在各种供应商演示和走廊对话中时,我开始看到更广阔的前景,并对涌入该领域的大量供应商有了更好的理解。我被你可以附加到你的 Hadoop 集群上的一些插件或者有多少类似 ETL 的工具可以让数据流入你的数据湖所震惊。如果你选择生活在微软 Azure 或亚马逊 AWS 生态系统中,事情会简化,但当你离开这些环境时,真相和选择是无穷的。在宏大的计划中,这个空间仍在发展,会有赢家和输家。我们将很快进入一个供应商整合的时期,这将有助于简化选项,但目前,新工具和零碎架构的空间仍然非常大。

每个人都还在试图解决这个问题。

大型企业仍处于采用和实施大数据基础架构以及提供企业级分析平台的早期阶段。我们已经走过了证明技术可以扩展的阶段,现在正在过渡到证明这些数据源可以为整个企业的底线增加指数级价值,而不仅仅是对统计书呆子(你们都还在摇滚!)在商业智能组内。随着这种转变的继续发展,我们开始看到围绕最佳实践出现了更多的问题。数据科学家应该在组织中“生活”在哪里?哪些数据在提供价值,哪些价值只是过度?最后,您如何转变和优化现有的产品和服务,以利用这些新发现的见解?

大数据和分析的范围正在帮助打破传统 IT 的孤岛,并帮助将更多价值提升到底线。在集体想法我们了解并相信在不久的将来,所有规模的公司都需要成为数据驱动型。他们的数据量、速度和多样性将成为其竞争优势的核心部分。你今天是如何开始的?

您如何看待贵公司采用大数据的速度,以及如何应对各种选择?我们希望收到您的来信——发推特给我们@ MAC fowler@ collective idea

排除 GCP + CUDA/NVIDIA + Docker 故障并保持其运行!

原文:https://towardsdatascience.com/troubleshooting-gcp-cuda-nvidia-docker-and-keeping-it-running-d5c8b34b6a4c?source=collection_archive---------4-----------------------

我有一个谷歌云平台(GCP)实例,一天前已经设置好并运行良好,它是在我的之前的教程之后设置的。

[## 设置 GCP 计算实例后会发生什么?使用 Tensorflow 运行自定义 Docker 容器

介绍

medium.com](https://medium.com/@thushv89/whats-after-setting-up-a-gcp-computing-instance-running-a-custom-docker-container-with-tensorflow-eb0f077983c6)

让我告诉你一些关于我的机器的事情,

  • Ubuntu: 16.04
  • GPU: 1 个 P100
  • CUDA: 9.1
  • 英伟达:387.xx

但是,当我昨天启动我的 GCP 实例并尝试运行 docker 容器时,发生了一些非常奇怪的事情,

sudo docker start <container_name>
sudo docker attach <container_name>

发生了什么事?

不,它不像我希望的那样工作,并把我带进了集装箱。相反,它给了我以下错误

Error response from daemon: linux runtime spec devices: error gathering device information while adding custom device “/dev/nvidiactl”: no such file or directory
Error: failed to start containers: x

这很可能已经发生了,因为我的 GCP 实例勇敢地决定继续下去并更新一切本身是完全没问题的,事情会神奇地变得更好!嗯,我有消息!不会这样的。所以如果 GCP 能给我们一个在初始设置时关闭自动更新的方法,我将不胜感激。事实上,已经有许多关于 NVIDIA 驱动程序发疯(或失踪)以及其他更新的报告(证据 1 、 2 、 3 )。

向下钻取…

好了,在进入故障诊断的细节之前,让我一步一步总结一下我要做的事情。

  • 检查机器是否(在物理上)识别了我的 GPU
  • 检查 NVIDIA 是否可以看到 GPU
  • 如果 NVIDIA 看不到 GPU,请查看您是否安装了 CUDA/NVIDIA 软件包,并检查 NVIDIA 驱动程序是否正确加载
  • 如果 CUDA/NVIDIA 软件包安装正确,尝试修复路径变量
  • 如果修复路径变量没有修复,卸载任何现有的 CUDA/NVIDIA 软件包,并尝试重新安装兼容的 CUDA 和 NVIDIA 软件包
  • 关闭自动更新,所以我会手动更新,而不会破坏一切。

我的 GPU 被机器识别了吗?

首先也是最重要的,在检查库是否正确安装之前,请通过键入,

lspci | grep 3D

这应该给出类似于,

00:04.0 3D controller: NVIDIA Corporation Device 15f8 (rev a1)

如果没有,这可能是由于 GPU 被拔掉或只是从插座中轻轻推出,因为你移动了机器或其他东西。

使用 NVIDIA 系统管理界面(NVIDIA-SMI)检查 GPU 的状态

首先要做的是,而不是妄下结论,并严格地开始输入sudo apt-get install <this-and-that> 希望得到最好的结果!事实上,在这种情况下,最好的事情(也是大多数人忽略的)是找出问题所在。首先让我们看看我们有什么。继续打字,

nvidia-smi

理想情况下,您应该得到这样的结果,

Figure 1: Output of nvidia-smi

那没用:(…

如果你得到这样的信息,

NVIDIA-SMI has failed because it couldn’t communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

这可能是由于两个原因,

  • 您没有以 root 用户身份登录,因此 NVIDIA 无法通信(**解决方案:**键入sudo -s以 root 用户身份登录,然后再次尝试nvidia-smi
  • 您实际上没有安装兼容的 NVIDIA 驱动程序(或者配置已损坏)(解决方案需要更多工作)。这也是我在这里讨论的问题类型)

修复缺失的 CUDA/NVIDIA 库

因此,为了让 NVIDIA-SMI 正常工作,您需要一些适当的设置。他们是,

  • CUDA(包括 cuda- 、cuda-blas- 、cuda-nvcc- 、cuda-toolkit- 等。)
  • NVIDIA 库(包括 nvidia- 、nvidia-docker、nvidia-modprobe、nvidia-settings 等)。)

让我们检查一下是否安装了这些,试着键入

dpkg -l | grep nvidia

你应该得到

Figure 2: Output of dpkg -l | grep nvidia

下一次尝试,

dpkg -l | grep cuda

这应该给

Figure 3: Output of dpkg -l | grep cuda

请注意,实际列表要长得多。但是如果 CUDA 获得了相当多的点击,事情应该是好的。但是不要太舒服了!我遇到过即使安装了这些东西也无法工作的情况。

检查是否加载了 NVIDIA 内核模块

让我们再做一次检查,看看 NVIDIA 内核模块是否被正确加载,

dmesg | grep NVIDIA

理想情况下,你应该看到,

[ 2.261511] nvidia: module license ‘NVIDIA’ taints kernel.
[ 2.316304] NVRM: loading NVIDIA UNIX x86_64 Kernel Module 384.111 Tue Dec 19 23:51:45 PST 2017 (using threaded interrupts)
[ 2.319524] nvidia-modeset: Loading NVIDIA Kernel Mode Setting Driver for UNIX platforms 384.111 Tue Dec 19 22:56:18 PST 2017

如果你什么都看不到,那就有问题了!这意味着 NVIDIA 驱动程序没有被正确加载。

会不会是路径变量配置错误?

如果您得到如图所示的这两个输出,但不是正确的dmesg消息,那么您需要的东西都在机器中了。所以这可能是由于路径变量的一些简单的错误配置。所以打开.bashrc文件,在它后面添加下面两行。

PATH=/usr/local/cuda-9.1/bin${PATH:+:${PATH}}
LD_LIBRARY_PATH=/usr/local/cuda-9.1/lib64\                          ${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

然后退出文本编辑器并运行,

source ~/.bashrc

重启机器,再次尝试nvidia-smi看看是否一切正常。(PS:记得用sudo权限试试)

没那么幸运?是时候手动重装了

如果你正在读这部分,你可能没有其他人那么幸运。好吧,让我们继续耕耘土地吧!在我看来,不值得再深入挖掘,试图在满是库的碗里找到一粒错误。事实上,如果我们移除当前损坏的库并从头开始正确安装,事情会容易得多。

找出正确的库版本

首先,我们需要弄清楚哪一个与哪一个相配。我的意思是,我们需要确保我们下载的特定(正确)版本的 CUDA 和 NVIDIA 驱动程序与您的显卡相匹配。所以让我们先去了解一下最新的情况。

转到,

[## 下载驱动程序| NVIDIA

下载 NVIDIA 产品的驱动程序,包括 GeForce 显卡、nForce 主板、Quadro 工作站和…

www.nvidia.com](http://www.nvidia.com/Download/index.aspx?lang=en-us)

并输入详细信息,

  • 显卡:我有一个英伟达特斯拉 P100
  • CUDA:我们用 9.x 吧

这是我得到的结果,

Figure 4: Driver/Library versions

现在,我们将确保在安装时坚持使用这些特定的版本,以避免任何差异。

移除现有的 CUDA/NVIDIA 库

首先让我们删除任何现有的 CUDA/NVIDIA 库,

sudo apt-get remove --purge cuda*
sudo apt-get remove --purge nvidia*

安装 CUDA/NVIDIA

首先获得 CUDA 工具包.deb,

wget [http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.1.85-1_amd64.deb](http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.1.85-1_amd64.deb)sudo dpkg -i cuda-repo-*sudo apt-get updatesudo apt-get install cuda -y

重启系统并尝试,

sudo dpkg -l | grep cuda
sudo dpkg -l | grep nvidia

您应该会看到如图 2 和图 3 所示的正确输出。

是时候进行一些黑客攻击了…

我刚刚意识到搭载 CUDA 9.1 的 NVIDIA 驱动程序 387.xx 在我的 NVIDIA Tesla P100 上不工作。所以我必须先卸载它,然后安装 NVIDIA 384.xx 。根据您实例中的 GPU 卡,这可能会有所不同。

你知道什么是怪异吗!如图 1 所示,我完全可以使用 CUDA 9.1 和 NVIDIA 387.xx。但是现在,NVIDIA 387.xx 不再与 CUDA 9.1 兼容。我不知道为什么,但希望能找到原因!

让我们这样做,

sudo apt-get remove --purge nvidia-*

现在,让我们手动安装 NVIDIA 384.xx 驱动程序,

sudo apt-get install nvidia-384
sudo apt-get install nvidia-modprobe

对于nvidia-docker,你将需要nvidia-modprobe 。现在快速检查一下路径变量,看看它们的设置是否正确

echo $PATH : You should have /usr/local/cuda-<version>/bin in this variable
echo $LD_LIBRARY_PATH : You should have/usr/local/cuda-<version>/lib64 in this variable

现在尝试nvidia-smi,您应该会看到类似于图 1 的内容,这意味着一切都恢复正常了(希望如此!).

关闭自动更新!

还有一件事,不要忘记是什么开始了这整个折磨。是自动更新。更新是重要的,以保持您的机器安全,从外部威胁和一切,但如果它将打破我的机器每 5 秒钟我更新,没有谢谢你!我自己手动更新。为此,请在文本编辑器中打开以下文件,

/etc/apt/apt.conf.d/10periodic

并设置

APT::Periodic::Update-Package-Lists “0”;

这将阻止那些“讨厌的”(然而,重要的)自动更新。但是记住要持续更新你的操作系统,因为你不希望有人侵入你的机器。

结论

pixabay.com

因此,在这篇文章中,我们讨论了如果您遇到配置损坏、驱动程序丢失等问题,如何对 GCP 实例进行故障诊断。我推荐的过程是,

  • 检查机器是否(在物理上)识别了我的 GPU
  • 检查 NVIDIA 是否可以看到 GPU
  • 如果 NVIDIA 看不到 GPU,请查看您是否安装了 CUDA/NVIDIA 软件包,并检查 NVIDIA 驱动程序是否正确加载
  • 如果 CUDA/NVIDIA 软件包安装正确,尝试修复路径变量
  • 如果修复路径变量没有修复,卸载任何现有的 CUDA/NVIDIA 软件包,并尝试重新安装兼容的 CUDA 和 NVIDIA 软件包
  • 关闭自动更新,所以我会手动更新,而不会破坏一切。

干杯!

特朗普,用他自己的话说

原文:https://towardsdatascience.com/trump-in-his-own-words-62af05ad76d4?source=collection_archive---------2-----------------------

对特朗普在 2016 年总统竞选过程中不断变化的优先事项的数据驱动研究

唐纳德·特朗普(Donald Trump)在 2016 年总统竞选过程中的优先事项发生了怎样的变化?随着竞选的临近,他在移民问题上变得更强硬了吗?还是他把重心转移到了经济上?他什么时候开始谈论希拉里的邮件的?

这些都是数据可以帮助我们回答的问题。加州大学圣巴巴拉分校的美国总统项目有一个庞大的目录,记录了几十年来几十位政治人物的文字记录。其中包括唐纳德·川普从 2015 年 6 月 16 日宣布参选到 2016 年 11 月 9 日接受提名的 60 篇竞选演讲。他们也有11 场共和党初选和 3 场大选辩论的抄本。

我冒昧地抓取了这些抄本,并把它们放在一个半结构化的数据库中,可以用于文本分析( GitHub repo )。对于辩论,我做了一些简单的处理,只包括了特朗普本人的部分文字记录。然后,我开始描绘特朗普在竞选过程中使用语言的演变过程。为此,我使用了相当简单的语言分析技术来确定特朗普在一段时间内提到某些话题的频率。我可以画出特朗普提到某些词的次数,但特朗普演讲的数量和长度都随着时间的推移而变化。

正如所料,特朗普在竞选的最后几个月开始发表更多演讲。因此,与其绘制原始字数,我将向你展示特朗普使用某些词的频率图,作为我的文字记录中所有词的比例,在每月一次的水平上汇总。

数据不言自明

我们将从 2016 年竞选中一些常见的政策相关主题的相关单词开始。

Words counted (including variants): “economy”, “tax”, “GDP”, “jobs”, “employment”

特朗普在竞选中提到经济话题的频率似乎没有任何明显的时变趋势。然而,当我们谈到移民问题时,随着竞选活动的进行,似乎有一种轻微的负面趋势。

Words counted (including variants): “wall”, “mexico”, “immigration”, “illegals”

恐怖主义也是 2016 年竞选中的一个大话题,2016 年 6 月初发生了恐怖的 Pulse 夜总会枪击案。事件发生后的第二天,特朗普在新罕布什尔州发表了一个演讲,他在演讲中重点强调了恐怖主义的话题,下图中观察到的大幅飙升就证明了这一点。

Words counted (including variants): “terror”, “terrorist”

我们还可以看看特朗普在整个竞选过程中提到某些人或实体的频率。我们从提到“奥巴马”开始,看下面的图表。特朗普在 2016 年 4 月发表了一次关于外交政策的演讲,他在演讲中花了很多时间批评巴拉克·奥巴马。除此之外,随着时间的推移,奥巴马的提及率似乎有微弱的上升趋势。

我还在下面画出了特朗普讨论“俄罗斯”和“普京”话题的频率。前两次高峰来自于讨论俄罗斯和外交政策的初选辩论。我们还看到,在 2016 年 9 月和 10 月,即维基解密发布波德斯塔电子邮件的时间附近,俄罗斯的提及率出现了飙升。

最后,我们来看看特朗普提到他的民主党对手希拉里的频率。

正如所料,特朗普在大选中比初选中更多地提到了希拉里(在初选中,他的主要对手将是其他共和党人)。特朗普在 2016 年 5 月 26 日获得了党内初选提名,希拉里在 2016 年 6 月 6 日获得了民主党提名,这与上文观察到的趋势中的明显转折点一致。

我们还可以锁定特朗普何时(以何种强度)开始讨论希拉里的电子邮件。在下面的图表中,我们看到了从六月到十一月非常明显的持续上升趋势。特朗普在 6 月份之前只提到过一次希拉里的电子邮件,但随着竞选活动的进行,他越来越关注电子邮件这个话题。

这些都是有趣的趋势,尤其是最后一个趋势,因为人们对希拉里·克林顿电子邮件的关注度急剧上升。虽然我们通常无法确定是什么导致了一个峰值与另一个峰值的对比,但直接进入原始材料并应用一些简单的数据分析技术可以让我们获得一些经验主义的见解,了解特朗普的优先事项似乎是如何在他的竞选活动中演变的。

开型代码

想试试自己的分析吗?你可以在 GitHub 上的 Jupyter 笔记本中找到我用来生成这些图的代码版本。

合成图像

设计信任

原文:https://towardsdatascience.com/trust-by-design-a864f1062baa?source=collection_archive---------13-----------------------

linh-dao

下一次工业革命的发动机不是数据,而是信任。

阿里巴巴没有库存…-谷歌没有创造专有内容,Airbnb 也没有房地产。让这些市场领导者在竞争中脱颖而出的不是数据量或分析的复杂程度,而是他们利用数据增强消费者信任的能力。当欧洲和海外的公司根据他们的数字战略评估 GDPR 时;他们忽略了一个关键点—数据永远不会比利益相关者对其数据实践的信心更有价值。

如果你的组织没有培养消费者的信任,你的市场份额将会萎缩。在过去的几年里,消费者信任的性质发生了很大的变化。几年前,Vanessa Hall 指出,基于对组织领导和产品的信任的“盲目信任”已经成为过去。【1】绝对信任已经被“情境信任”所取代,消费者信任专家,因为他们专注的洞察力和经验。今天,当面对多种数据来源和真相版本时,情境信任反过来让位于基于共同信念感知的“参考信任”。

*如果客户不相信技术能提供合理的价值水平,他们就不太可能深入一个组织的数字空间。*多项研究得出结论,消费者的信任度正处于历史最低点。三种趋势可以解释这种矛盾心理。基于“人是产品”哲学的商业模式越来越受到那些讨厌被分类然后被产品化的人的质疑。基于“越大越好”的数据囤积实践被证明是毫无意义的,因为它们具有潜在的危险。最后,公司对数据的感知需求超过对个人隐私的任何关注的零和经验理所当然地招致公众的鄙视。

消费者信任危机是欧盟通用数据保护条例 2016/679 的主旨。欧洲法规旨在鼓励数据控制者和处理者将隐私、安全和透明嵌入到他们的组织工作流程中。立法意图是对“小”而非“大”数据的使用进行限制。小数据是指允许组织清楚地识别个人的任何信息。它可能是一种生物特征、一种信仰或一种偏好,或者更多基于上下文的东西。这些文本旨在确保数字公民有权知道他们的数据是如何被使用的,有权根据需要访问、修改、删除和传输数据。也就是说,秉承 GDPR 精神只会有助于,而不是保证,消费者的信任。

*信任不是你拥有多少数据的数量的属性,而是消费者如何使用这些数据的结果。*多项举措有助于在您的客户和组织之间建立信任关系。第一步是让消费者对他们的数据有更多的控制权。第二步是将正确的数据交给他们处理——他们对您的产品和组织了解得越多,就越有机会做出更好的决策并应对他们面临的挑战。第三步是帮助他们将数据整合到有意义的故事中,帮助他们了解挑战的性质和手头的潜在解决方案。请记住,在客户的心目中,服务不是在网络上找到的,而是提供明显的方法来改善他们的生活方式。

在后 GDPR 时代,默认的隐私将很快被设计的信任所取代。“设计信任”包含大量数据实践,这些实践在运营流程的每个阶段都嵌入了增加消费者信任的机会。数据透明涉及清楚地传达您打算使用什么样的小数据,以及使用的原因、时间、持续时间和对象。Trust by Design 超越了对数据透明性的关注,实现了充分利用时间的愿景—组织可以使用数据和分析来积极影响客户与周围世界的互动方式。

正如 CareerFoundry 的 Raffaela Rein 所说,在可预见的未来,培养信任将是信息架构师和数据科学家的核心职责。【3】设计信任的影响不仅体现在您组织的设计实践和流程改进上,还体现在您将如何使用数据来帮助您的员工和客户成功应对日常生活的复杂性上。

我将在 11 月 8 日和 9 日的后 GDPR/FODP 峰会上讨论和发展这些主张。请不要犹豫,分享你的想法和建议头导致这一事件。我期待在柏林见到你。

李·施伦克博士

商业分析研究所

2018 年 9 月 15 日

Lee Schlenker 是商业分析和社区管理教授,也是 http://baieurope.com 商业分析研究所的负责人。他的 LinkedIn 个人资料可以在www.linkedin.com/in/leeschlenker.查看,你可以在https://twitter.com/DSign4Analytics的 Twitter 上关注白


【1】凡妮莎·霍尔,商业中信任的真相,2011,翡翠图书公司

【2】例如,参见Forrester 2018 年预测指南、 2017 年爱德曼信托晴雨表

【3】艾米丽·斯蒂文斯,通过 UX 建立信任,CareerFoundry,2018 年 1 月 22 日

“信任流程?”在线体育社区是如何被线下环境塑造的

原文:https://towardsdatascience.com/trust-the-process-the-interplay-between-online-sports-communities-and-offline-context-bc1b37a7ff74?source=collection_archive---------27-----------------------

本博客总结了我们的【CSCW】2018论文“‘这就是我们打球的原因”:NBA 各支球队 【网上球迷社区】由 贾森·吕钦**

( 交叉发布至 ACM CSCW )

许多在线社区不仅存在于虚拟世界中,而且也深深嵌入到线下环境中,吸引着具有类似线下兴趣的人。了解在线社区与线下环境的关联程度和方式是一个重要的研究问题。

职业体育提供了一个有趣的案例,因为在某种程度上,这些在线粉丝社区只是作为线下运动队和游戏的结果而存在。这种联系也突出了结合多种数据源来理解在线社交媒体中粉丝行为如何与他们感兴趣的主题的持续事件相关联的必要性。

在这里我们分享一个 Reddit 上的有趣故事。2018 年 2 月 7 日,NBA 球队菲尼克斯太阳队以 48 分之差输给圣安东尼奥马刺队,追平了球队历史上最糟糕的输球。在巨大的损失之后,当然,太阳队的球迷非常失望。但是,他们没有放弃团队,也没有抛弃团队子编辑,而是把这个体育子编辑变成了科学子编辑,开始讨论太阳系的太阳!那天晚上贴了很多搞笑的标题,比如这个:“你知道吗,太阳包含了太阳系所有质量的 99.86%?”

After the huge loss, the fans of the Phoenix Suns turned their team subreddit into a science subreddit, starting to talk about the Sun in the Solar System.

在我们新的CSCWT2 论文中,我们着迷于在线粉丝社区中的这种用户行为,我们从 Reddit 构建了一个大规模数据集,它结合了 NBA 相关社区(30 个球队子社区和/r/NBA)中的 150 万个帖子和 4300 万个评论,以及记录 NBA 球队表现的离线统计数据。我们在比赛层面和赛季层面研究了球队表现和球迷行为之间的相互作用。

用户活动与 NBA 赛季的结构密切相关。

首先,我们发现 NBA 赛季的结构驱动了 NBA 相关子区域的用户活动。如果我们按月使用/r/NBA 中生成的评论数来衡量用户活跃度,那么在每个休赛期(7 月-10 月中旬),用户活跃度都会急剧下降,因为在此期间没有比赛。在常规赛中(10 月下旬-次年 3 月),用户活跃度稳步上升。活动在五月和六月达到高峰,因为冠军赛在这两个月举行。

User activity in /r/NBA by month.

线上粉丝活动反映了线下的游戏玩法。

NBA 相关 subreddits 的一个重要特点就是支持游戏相关的讨论。实际上,每个游戏在相应的 team subreddit 中都有一个游戏线程。我们鼓励粉丝在游戏主题中发表与游戏相关的评论。通过比较 2017 赛季比赛当天每个小时在每个团队子编辑中发表评论的平均比例(根据一场比赛的开始时间进行归一化),我们观察到比赛时间是团队子编辑中最活跃的时间。用户活动在比赛开始前一个小时开始增加,在第二个小时达到峰值。这一趋势与持续约 2.5 小时的典型 NBA 比赛完全一致。

User activity by hour on the game day.

粉丝都聊些什么?

接下来,我们使用主题建模来分析这些 NBA 相关子主题中的用户评论内容。权重最高的五个主题可以概括为:“个人观点”、“游戏策略”、“赛季前景”、“未来”和“游戏统计数据”我们稍后将回到这一点,看看团队绩效如何影响讨论。

The Top-5 topics discussed by fans in /r/NBA.

游戏层面的团队表现如何影响粉丝活跃度?

有人可能会假设,赢得一场比赛会在团队子编辑中引发更高水平的活动。然而,我们发现并非所有团队都是如此。我们的分层回归分析表明,顶级球队的球迷在输球后往往更活跃,而底层球队的球迷则表现出完全相反的趋势。使用 2017 和 2016 赛季的前 3 名和后 3 名球队,出现了一致的模式:

  • 在所有这些球队中,比赛日的平均评论数明显高于非比赛日;
  • 对于所有排名靠前的球队,输球日的平均评论数都高于赢球日,但对于排名靠后的球队,结果正好相反。

The top-3 team subreddits have more comments on losing days, while the bottom-3 team subreddits show the opposite trend.

顶级团队和底层团队之间的互动表明,“惊喜”可能是一个相当重要的因素。例如,在 2017 赛季,前三名球队的平均胜率在 75%以上。顶级球队的球迷可能习惯于他们支持的球队赢得比赛,在这种情况下,输掉比赛对他们来说是一件令人惊讶的事情。相比之下,倒数三名球队的平均胜率都在 30%以下。看着自己的球队获胜,这些球迷感到振奋。“惊喜”带来了额外的兴奋,可以刺激相应游戏线程中的更多评论。

关于本博客中提到的所有层次回归分析的细节,请参考我们的 论文

赛季级别的团队表现如何与团队子区域中的粉丝忠诚度相关联?

我们的结果表明,团队绩效(根据 FiveThirtyEight.com提供的 Elo 评级估算)对赛季级用户留存率和月度用户留存率都有显著的负面影响。再次使用 2017 和 2016 赛季的前 3 名和后 3 名球队,无论是赛季之间还是月份之间,垫底球队的用户留存率都比顶级球队高得多。

Fans of the top-3 teams are less loyal, and fans of the bottom-3 teams tend to stay.

职业体育中著名的“赶时髦”现象可能有助于解释这一现象:一些球迷可能会“赶时髦”,开始追随一支目前表现最好并卫冕冠军的运动队。只要团队开始表现不佳,他们就会跳下船,加入另一个表现更好的团队。相比之下,糟糕的团队表现可以作为忠诚度过滤器。经过一段时间的糟糕表现,只有铁杆粉丝会保持积极乐观。不管这个队表现得多差,他们都会继续支持他们。

赛季级别的团队表现如何影响团队子栏目中的讨论话题?

我们的结果表明,团队的表现也驱动着球迷们谈论的话题。“赛季展望”和“未来”话题与团队表现高度相关。好的球队更多讨论“赛季前景”,差的球队更多谈论“未来”如果我们对 2017 和 2016 赛季所有 30 支 NBA 球队进行“未来”和“赛季展望”的话题权重投影,可以看到前 3 名球队一致位于右下角(高“赛季展望”,低“未来”),后 3 名球队均位于左上角(低“赛季展望”,高“未来”)。

Fans of the top-3 teams tend to discuss more “season prospects,” and fans of the bottom-3 teams discuss more “future.”

我们的结果呼应了体育管理中的一个早期发现:对于表现不佳的球队的球迷来说,框定未来是一种重要的策略,可以在最近缺乏成功的情况下保持积极的身份认同。结合我们之前对球队表现和球迷忠诚度的观察,这可能表明一支运动队的奋斗可以提供一个与忠诚球迷建立深厚感情的绝佳机会。某些球迷可能愿意与他们支持的球队一起经历几乎任何事情,包括多年的失败,以此来承认自己是铁杆球迷。通过这样做,当球队在未来取得成功时,他们获得了在粉丝群体中收获更多情感意义的感觉。

数据集和更多有趣的观察

本文的数据集可在 http://jasondarkblue.com/.[获得](http://jasondarkblue.com/.)文中还讨论了更多有趣的观察结果。例如,我们发现球队的市场价值、平均年龄、全明星球员的数量和比赛风格都在球迷活动中发挥着重要作用。

还有“这就是我们玩的原因!

合作者:谭和吕钦。

如何使用 Dask 数据帧在 Python 中运行并行数据分析

原文:https://towardsdatascience.com/trying-out-dask-dataframes-in-python-for-fast-data-analysis-in-parallel-aa960c18a915?source=collection_archive---------1-----------------------

Your mind on multi-cores. source: Pixabay

有时候,你打开一个包含 Python 的熊猫的大数据集,试图获得一些指标,整个事情就可怕地冻结了。
如果你从事大数据工作,你知道如果你使用熊猫,你可能会为一个系列的简单平均值等待整整一分钟,我们甚至不要调用应用。这只是几百万行的数据!当你达到数十亿时,你最好开始使用 Spark 或其他东西。

不久前我发现了这个工具:一种加速 Python 中数据分析的方法,而不必获得更好的基础设施或转换语言。如果你的数据集很大,它最终会感到有限,但它比普通的熊猫要好得多,可能正好适合你的问题——特别是如果你没有做大量的重新索引。

可以在 土星云 上马上免费使用 Dask!
土星云是一个端到端的数据科学+机器学习平台,允许数据科学家在云中使用 Dask 扩展他们的 Python 项目。

Dask 是什么?

Dask 是一个开源项目,它为您提供了对 NumPy 数组、Pandas 数据帧和常规列表的抽象,允许您使用多核处理对它们并行运行操作。

这里有一段直接来自教程的摘录:

Dask 提供了模拟 NumPy、lists 和 Pandas 的高级数组、Bag 和 DataFrame 集合,但可以在不适合主存的数据集上并行操作。对于大型数据集,Dask 的高级集合是 NumPy 和 Pandas 的替代方案。

听起来就很牛逼!我开始尝试本文的 Dask 数据框架,并对它们运行了几个基准测试。

(要查看 Dask 在机器学习中的更多应用,请查看我的 并行 k 均值聚类教程 )

阅读文档

我做的第一件事是阅读官方文档,看看在 Dask 的而不是常规数据帧中到底推荐做什么。以下是来自官方文件的相关部分:

  • 操作大型数据集,即使这些数据集不适合内存
  • 通过使用多个内核加速长时间计算
  • 使用标准的 Pandas 操作(如 groupby、join 和时序计算)对大型数据集进行分布式计算

接下来,它列出了一些使用 Dask 数据帧时速度非常快的东西:

  • 算术运算(乘法或加法)
  • 常见聚合(平均值、最小值、最大值、总和等。)
  • 调用 apply(只要它沿着索引-也就是说,不在 groupby('y ')之后,其中' y '不是索引-)
  • 调用 value_counts()、drop_duplicates()或 corr()
  • locisin 过滤,行选择

Just a small brush up on filtering Dataframes, in case you find it useful.

如何使用 Dask 数据帧

Dask 数据帧与 Pandas 数据帧具有相同的 API,除了聚合和应用被延迟计算,并且需要通过调用计算方法来计算。为了生成 Dask 数据帧,你可以像在 Pandas 中一样简单地调用 read_csv 方法,或者,给定一个 Pandas 数据帧 df ,你可以只调用

dd = ddf.from_pandas(df, npartitions=N)

其中 ddf 是您导入 Dask 数据帧时使用的名称,而 npartitions 是告诉数据帧您想要如何对其进行分区的参数。

根据 StackOverflow 的说法,建议将数据帧划分为与计算机内核数量一样多的分区,或者是该数量的几倍,因为每个分区将在不同的线程上运行,如果数量太多,它们之间的通信将变得过于昂贵。

变脏:让我们进行基准测试!

我做了一个 Jupyter 笔记本来测试这个框架,并在 Github 上发布了这个框架,以防你想亲自测试或者运行它。

我运行的基准测试可在 Github 的笔记本中找到,但以下是主要的测试:

这里 df3 是一个普通的熊猫数据帧,有 2500 万行,使用我的熊猫教程中的脚本生成(列是姓名薪水,从列表中随机抽取)。我取了一个 50 行的数据集,并将其连接了 500000 次,因为我对分析本身并不太感兴趣,而只对运行它所花费的时间感兴趣。

dfn 就是基于 df3 的 Dask 数据帧。

第一批结果:不太乐观

我首先用 3 个分区进行了测试,因为我只有 4 个内核,不想让我的电脑超负荷工作。我在 Dask 上得到了非常糟糕的结果,也不得不等待很长时间才能得到它们,但我担心这可能是因为我做的分区太少了:

204.313940048 seconds for get_big_mean
39.7543280125 seconds for get_big_mean_old131.600986004 seconds for get_big_max
43.7621600628 seconds for get_big_max_old120.027213097 seconds for get_big_sum
7.49701309204 seconds for get_big_sum_old0.581165790558 seconds for filter_df
226.700095892 seconds for filter_df_old

你可以看到,当我使用 Dask 时,大多数操作都变慢了很多。这给了我暗示,我可能不得不使用更多的分区。生成惰性求值所花费的时间也可以忽略不计(在某些情况下不到半秒),所以如果我重用它们,它不会随着时间的推移而摊销。

我还用应用方法尝试了这个测试:

得到了非常相似的结果:

369.541605949 seconds for apply_random
157.643756866 seconds for apply_random_old

因此,一般来说,大多数操作变得比原来慢两倍,尽管过滤器快得多。我担心也许我也应该调用计算机来处理这个问题,所以对这个结果要有所保留。

更多分区:惊人的速度

在这样令人沮丧的结果之后,我认为可能是我没有使用足够的分区。毕竟,这样做的全部意义在于并行运行,所以也许我只需要更多的并行化?因此,我对 8 个分区进行了相同的测试,下面是我得到的结果(我省略了非并行数据帧的结果,因为它们基本相同):

3.08352184296 seconds for get_big_mean
1.3314101696 seconds for get_big_max
1.21639800072 seconds for get_big_sum
0.228978157043 seconds for filter_df112.135010004 seconds for apply_random
50.2007009983 seconds for value_count_test

没错!大多数操作比常规数据帧快十倍以上,甚至应用也变得更快了!我还运行了 value_count 测试,它只是在 salary 系列上调用了 value_count 方法。对于上下文,请记住,当我在常规数据帧上运行这个测试时,在等待了整整十分钟之后,我不得不终止这个进程。这次只用了 50 秒!
所以基本上我只是用错了工具,而且速度相当快。比普通的数据帧快得多。

最终外卖

鉴于我们刚刚在一台非常旧的 4 核电脑上一分钟内处理了 2500 万行数据,我可以想象这在行业内会有多么巨大。所以我的建议是,下次您必须在本地或从单个 AWS 实例处理数据集时,尝试一下这个框架。相当快。

我希望你觉得这篇文章有趣或有用!编写它花费的时间比我预期的要多得多,因为一些基准测试花费了这么长的时间。请告诉我在阅读本文之前您是否听说过 Dask,以及您是否在工作中或项目中使用过它。也请告诉我是否还有其他我没有提到的很酷的特性,或者我做错了什么!你的反馈和评论是我写作的最大原因,因为我也在从中学习。

数据科学家的进一步阅读:

  • 自动编码器:深度学习与 TensorFlow 的热切执行其中我介绍了 TensorFlow 的 Keras API,并训练自动编码器进行图像压缩。
  • LSTM:教神经网络像洛夫克拉夫特一样写作在这里我解释了 LSTM 神经网络是如何工作的,并用它来生成文本。
  • 每个数据科学家都应该知道的 5 种概率分布在这些概率分布中,你可以学到一些非常常用的统计学基础知识……以及不那么基础的知识。

关注我,获取更多 Python 教程、技巧和诀窍!如果您喜欢这篇文章,请查看我的网站 或关注我的微博

如果你想成为一名数据科学家,可以看看我推荐的机器学习书籍。

试图改变职业生涯或从数据科学开始?

原文:https://towardsdatascience.com/trying-to-change-careers-or-get-your-start-in-data-science-3f74bc30b027?source=collection_archive---------16-----------------------

如果你想进入数据科学领域,有一些方法可以让你在求职过程中变得更好。

假设你已经积累了工作所需的技能,看看你是否能够利用这些技巧:

  • 针对你想要的工作(T1)优化你的简历(尽你所能),而不是你在 T2 做过的工作(T3)。
  • 尝试在当前的工作中积累经验(如果你想转行的话),或者在家做自己的数据科学项目。(持续学习是一大加分项)。
  • 开发一个杀手级电梯间推介。

为你想要的工作优化你的简历:

用一种显示你注重结果的方式来描述你的项目。

你想在简历上展示的要点需要兼顾:

  • 证明你理解一般的企业文化,展示你的协作、实现结果、解决问题和自我管理的能力。
  • 展示你作为数据科学家的技术能力。

第一点需要深思熟虑——列出工作职责确实很容易,但有效地重新措辞以突出你真正的优势并展示你所做的如何改善了业务却是另一回事。你的要点应该充满动作动词和结果,即使你需要在精神上努力去识别它们。

您是否实现了流程自动化,从而节省了手动执行任务的时间?节省的时间就是商业价值。

再次证明你已经跨职能工作或向企业展示了成果,这是你想要的新工作所需要的(数据科学家)。

阅读职位描述和了解公司在寻找什么是有帮助的,你会发现一致的主题。如果你仔细观察,你会发现这里列出了很多不一定是技术性的技能。在和这些软技能说话时,确保你光彩照人。但是当然,这些软技能需要以仍然展示一个动作和结果的方式来展示。不要只是在简历上放一个“软技能”部分,列出一堆没有上下文的单词。

“展示你作为数据科学家的技术能力”。这很简单。尽量使用你申请的工作的实际工作描述中的措辞。你可能想听起来很奇特,但是“经验贝叶斯三阶段层次模型”可能不在工作描述中。在简历中特别列出这一点不会帮助你通过 ATS(申请人跟踪系统),人力资源部门没有数据科学背景的人也不会知道这是否相关。再次强调,查看多份职位描述,并尝试判断在简历中使用哪种语言是有帮助的。

从当前工作或项目中获得经验:

如果你目前有工作,你有访问 SQL 的权限吗?你的公司有数据仓库或数据库吗?你能向服务台申请一张票来获得 SQL 吗?然后你能玩数据来制作你自己的项目吗?

您甚至可以更进一步,将数据库中的数据导入 R 或 Python。也许你做了一个很好的决策树来回答一个商业问题,然后把你的项目结果精彩而简洁地放在你的简历上。

试着自动化一项你定期做的可重复的任务。这是下一层次的简历内容。在这种情况下,您正在提高效率。

如果你已经独立完成了数据科学项目来完善你的简历,确保那些项目符号充满了动作动词和结果,动作动词和结果。我几乎想说第三遍。

SQL Lite 是开源的,R 是开源的,Python 是开源的,那里有大量的免费数据。这个世界真的可以是你的,但是你需要有效地推销这些积极进取的技能。

开发一个杀手级电梯间营销:

一份强有力的、目标明确的简历可能会打开这扇门,但你需要让这扇门一直开着,并且在门打开后继续对话。简历无非就是开门见山,仅此而已。

把你的简历交到合适的人手里有时会很困难。有效利用 LinkedIn 可以帮助弥合这一差距。如果你在 LinkedIn 上联系某人询问机会,我们该如何开始对话?

重要提示:当你主动联系 LinkedIn 上的人时,这应该是在你已经访问了公司网站,找到了一份你感兴趣并且(相当)胜任的工作,之后的,然后你联系了一个相关的人,向他传达了一个有针对性的信息。

如果你要联系的人在一家没有任何职位空缺的公司工作,那么不可能有很好的针对性。因为你没看职位描述。所以你无法推断业务的需求。数据科学是一个大领域,有许多专业,一刀切的方法是行不通的。

回到球场上。你注重结果,你有创新精神,你从商业的角度看待事物。

  • 我建议从一些对话开始,如果你发信息的人已经被请求淹没了,这将会有所帮助。对他们最近发表的一篇帖子的评论让你的联系看起来更真实。
  • 你发信息的原因:你对这个空缺职位感兴趣,你想把你的简历发给合适的人。
  • 然后简明扼要地提及一些在工作描述中特别提到的事情。基本上是在说“嗨,看看我,我很健康。”
  • 让他们知道,如果他们只是把你转给正确的人,你会非常感激(希望你发信息的人是正确的人,但也有可能不是正确的人,所以不要假设)。
  • 关闭强。你是来为公司增加价值的,而不是来谈论你的需求;暗示你知道你是来谈论如何满足业务需求的。

你好【姓名】,

我很喜欢你最近在【主题】上的帖子,我期待着阅读更多你的帖子。

我注意到[公司]正在招聘[职位名称],我希望我能把我的简历交到合适的人手里。我有统计学硕士学位,加上 7 年的实际建模经验。我是 SQL 高手,用 R 建模,接触过 Python。

我很高兴有机会与合适的人谈论空缺职位,并分享我如何通过使用统计方法为公司提供见解和附加值。

谢谢你,克里斯汀

现在你的背景可能和我很不一样。然而,你可以谈论你所受的教育(简明扼要),你所接触的建模,你的技术水平,以及你想要传递的价值。

我希望你能采纳其中的一些建议。我希望你在数据科学领域取得成功,收获颇丰。如果您对尝试改变数据科学有其他建议,我很想听听您的想法!我发布的下一篇文章将会涵盖如何为你的简历写一些有影响力的简洁内容,那篇文章在这里是。

如果你在寻找数据科学领域工作的帮助,或者需要简历方面的帮助,我想推荐你去找凯尔。我很了解凯尔,这是他的人生目标!。他帮助数据科学家获得数据科学职位。你可以看他谈论这个话题的视频:这里

原载于 2018 年 8 月 22 日datamovesme.com。**

地图数据的聚类

原文:https://towardsdatascience.com/tsne-clustering-for-map-data-507ba4e62b20?source=collection_archive---------9-----------------------

在这篇简短的博文中,我将向您展示如何在 Lat/Lng 坐标对上使用 tSNE 来创建地图数据的一维表示。这种表示有助于开发新的地图搜索算法。这对于诸如“这个 lat/lng 坐标对是在新泽西还是在纽约?”的查询可能是有用的或者“离我最近的披萨店在哪里?”。更快的地图搜索可能对优步、谷歌地图和方向、Yelp 等等非常有用。

在这篇文章中,我们将首先看看如何在真值表逻辑数据集上使用 tSNE 维度映射,然后我们将引入相同的概念来将 Lat/Lng 坐标映射到一维空间。有了一维表示后,我们就可以实现算法,用集合成员操作等方式进行常数时间搜索。

tSNE(t-分布式随机邻居嵌入)是一种聚类技术,其最终结果类似于 PCA(主成分分析)。PCA 使用线性代数概念来构建正交向量的新维度空间,而 tSNE 使用更简单的理解、排斥/吸引方法来将点从高维空间映射到低维空间。许多聚类算法的重点是在高维数据集中识别相似性,从而降低维数。tSNE 算法用于保持较高空间中的线性空间关系,而一些聚类算法,例如在径向基函数网络中使用的算法,试图增加空间关系,使得新空间是线性可分的,例如 XOR 逻辑问题的解决方案。

在 python 中使用 tSNE 的一个简单方法是使用 sklearn 包:

from sklearn.manifold import TSNE
# sample data set
X = np.array([[0,0],[0,1],[1,0],[1,1]])
X_embedded = TSNE(n_components=1).fit_transform(X)

Note to programmer: 1-Dimensional Line Plots can be created in Python by holding the y axis to a constant value using something like: plt.scatter(X_embedded,y=[1,1,1,1])

现在我们已经了解了 tSNE 如何将逻辑真值表映射到一维空间,让我们输入一个示例地图数据集,该数据集由波士顿、迈阿密和旧金山的 lat/lng 对组成。

Boston: [42.3601, -71.0589], 
Miami: [25.7617, -80.1918], 
SF: [37.7749, -122.4194]

# This is done with the following code
from sklearn.manifold import TSNE
X = np.array([[42.3601, -71.0589], [25.7617, -80.1918], [37.7749, -122.4194]])
X_embedded = TSNE(n_components=1).fit_transform(X)

现在,我们已经将这些 Lat/Lng 对转换成一维空间

Boston: [42.3601, -71.0589]  -> 14,473.32
Miami:  [25.7617, -80.1918]  -> 3299.8037
SF:     [37.7749, -122.4194] -> -7838.6094

在与采样的高维空间相同的坐标空间中保存空间信息的同时,具有较低维度的空间表示有许多优点。我们可以对来自基本数据结构的数据使用所有一维排序和搜索算法。此外,将纬度/液化天然气维度减少到 1 维可以将距离计算所需的计算量减少一半。我们可以只取新的一维表示的差,而不是取 lat 和 lng 值之间的差。

如果您对更快的地图搜索算法感兴趣,请查看这篇文章,了解我们如何在二维空间中保持 Lat/Lng 坐标的同时加快搜索速度:

[## kMeans 对地图数据进行哈希搜索

kMeans 聚类算法作为一种“无监督的人工智能”非常受欢迎…

towardsdatascience.com](/kmeans-hash-search-map-search-in-o-n²lgn-33743ece434f)

感谢您的阅读!如果你认为这篇文章有什么问题、想法或问题,请留下评论。

CShorten

Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对数据科学、深度学习和软件工程感兴趣。主要用 Python,JavaScript,C++编码。请关注更多关于这些主题的文章。

周二生日问题

原文:https://towardsdatascience.com/tuesday-birthday-problem-2927e83e5af3?source=collection_archive---------5-----------------------

下面是关于孩子的一系列经典概率问题。它们开始时很温和,逐渐变得越来越难,直到与直觉相悖的程度。这些问题多年来困扰了足够多的人,以至于赢得了“男孩或女孩悖论”的称号。

首先,让我们陈述一些贯穿整个问题的假设。就像现实生活一样,一个孩子生下来是男孩还是女孩的概率是相等的,1/2。每个孩子的性别都是独立的。一个孩子同样有可能在一周中的任何一天出生,而这一天又是独立于他人和性别的。在统计符号中,孩子的性别~iid 伯努利 (1/2)和出生日期在七天内是一致的。

1.生男孩的概率有多大?

答案:1/2

在没有任何额外信息的情况下,我们参考给出的假设,即一个男孩出生有 1/2 的几率。

2.一个家庭有两个孩子。大的那个是个男孩。另一个也是男生的概率有多大?

答案:1/2

大孩子是男孩与小孩子的性别没有关系,因为每个孩子的性别都是独立的。

3.一个家庭有两个孩子。至少有一个孩子是男孩。另一个也是男生的概率有多大?

答案:1/3

惊讶于它不是 1/2?

我们可以从基本原理来解决这个问题。按出生顺序列举二孩家庭的四个等概率事件,得到{GG,GB,BG,BB},其中 B 代表男孩,G 代表女孩。由于问题陈述家庭至少有一个男孩,GG 情况被排除,只剩下 3 个同等概率事件{GB,BG,BB}。其中 1 有两个男孩,给出了 1/3 的答案。

这个问题和上一个类似,只是我们不再知道提到的男孩是哪个孩子。如果他是更小的孩子,两个可能的事件是{GB,BB}。如果他是年长的那个,也存在两种可能:{BG,BB}。看起来,综合起来,有 4 种可能性,其中 2 有两个男孩,但实际上 BB 的情况在两个集合之间是重复的。在合并它们时,我们必须小心不要重复计算。这一见解将在下一个问题中被证明是有用的。

另一种解决问题的方法是应用条件概率的定义:P(A|B) = P(A 和 B)|P(B),其中 P(A|B)是给定 B 已经发生的情况下 A 发生的概率。如果 B 是男生数,问题可以表述为:

P(B=2|B≥1) 
= P(B=2 and B≥1)/P(B≥1)
= P(B=2)/P(B≥1)
= P(B=2)/(P(B=1) + P(B=2)) 
= ((1/2)²)/(2 * (1/2)² + (1/2)²) 
= (1/4) / (3/4) 
= 1/3

4.一个家庭有两个孩子。至少有一个孩子是在星期二出生的男孩。另一个也是男生的概率有多大?

答案:13/27

为什么孩子出生的那一天很重要?给定的信息改变了样本空间,样本空间增长了 7 * 7 倍,现在每个孩子的出生日期是一个因素。

让“w”代表一周中任何一天的生日,而“t”代表星期二。

如果在星期二出生的男孩是更小的孩子,在给定的条件下有两种可能:{GwBt,BwBt}。如果他是年长的那个,那么也有两种可能:{BtBw,BtGw}。在合并这些集合时,我们必须小心地移除重复的 BtBt,它包含在 BwBt 和 BtBw 两种情况中。因此,组合集是:{GwBt,BwBt,BtBw,BtGw} - 。该集合具有 7(GwBt)+7(BwBt)+7(BtBw)+7(BtGw)-1(BtBt)= 27 个元素。其中 7 (BwBt) + 7 (BtBw) - 1 (BtBt) =13 有两个男孩,给出 13/27。

13/27 ~ .48,更接近 1/2 而不是 1/3,上一个问题的答案。

5.概括:一个家庭有两个孩子。至少有一个孩子是男孩,其病情以概率 p 发生,另一个孩子也是男孩的概率是多少?

答案:(2-p)/(4-p)

让 B '是有这种情况的男孩的数量。

如果 p = 1,这意味着条件适用于每个男孩和女孩,因此它没有给出任何信息。我们恢复第三部分列出的“至少有一个是男孩”问题,以及它的概率(2-1)/(4-1) = 1/3。

在第 4 部分中,p = 1/7,其中条件是一周中的生日是星期二。它的概率是(2-(1/7)) / (4-(1/7)) = 13/27。

因为 p,患这种疾病的概率范围是从 0 到 1,一个家庭有两个男孩的概率是从 1/2 到 1/3。

这些问题说明了一种违反直觉的现象,即通常独立的两个变量,在给定某些其他信息的情况下,变得有条件依赖。

调音旅行推销员

原文:https://towardsdatascience.com/tuning-a-traveling-salesman-cadfd7d22e1c?source=collection_archive---------11-----------------------

The Traveling Salesman, a 1921 comedy with the right title for this article

介绍

几个月前,我发现了艾瑞克·斯托罗兹写的这篇关于遗传算法的文章,他写的这篇文章是为了找到旅行推销员问题的最优解。我觉得很有意思,为了更深入的理解,从头重写项目,对问题空间做了一点探索。

我将让读者参考原始帖子来了解算法的一般解释,但我确实做了一些更改:

  • 我在一些/很多/大部分代码中使用了 Python 的显式类型化功能,来感受一下
  • 我使功能更加灵活和模块化,并为每个功能编写了一个简短的单元测试,这样用户就可以看到幕后发生了什么
  • 我添加了一个可视化,这样用户就可以观看算法的运行

本来我开始这个项目是出于自己的学习和兴趣。然而,我发现了一些我认为值得分享的结果,因为它们突出了调整基因模型的容易和力量。此外,我发现选择一个项目并把它推向一个有趣的方向是多么容易。

调谐

作为一个基准,正常的第一代通常从 2100 到 2400 之间的总行驶距离开始。对于这里介绍的实验,城市的初始人口是相同的,但是第一代的初始顺序是随机的。除了动画之外,使用每代中最合适的个体(到达每个城市的最短距离)来生成图和数字。我在大多数实验中使用了 500 代,不是因为 500 是一个科学挑选的数字,而是它似乎为收敛提供了足够的时间,而没有为糟糕的超参数初始化提供足够的时间来收敛。方便的是,500 英镑也提供了合理的等待时间。

突变率

变异率如何影响种群中最佳个体的收敛时间和路径适应度?

  • 总的来说,似乎没有突变的试验以更长的路线结束,大约 1100-1300 的距离。我从未见过第 500 代跑完 1000 米的。没有突变,每一个连续的世代仅仅依靠繁殖和随机产生新的个体来改进。

  • 突变率为 0.01 的种群在 500 代中很少超过 1000。我怀疑这是最佳突变率的正确数量级。5 次连续运行的快照显示了一致性:890、939、998、880、953。

  • 突变率为 0.001 的人群表现良好,但结果的变化比突变率为 0.01 的人群更大。值为 0.001 时,似乎初始的起始路线对于最终的解决方案非常重要。如果起始路线是好的,它可以很快收敛到一个好的解决方案,否则,在没有太多基因变化的情况下,可能会花费更多代。5 次连续运行的快照:866、1046、996、880、1024。

  • 突变率为 0.1 的群体无法收敛。太多的个体经历突变,使得群体无法传递有用的遗传信息。对于交换变异,好路由和差路由之间的区别可能只是几个节点的一次交换。尽管下图中最终最佳个体的平均距离比最初一代的好几百点,但这是高初始路线距离的产物,我不相信有任何真正重大的进化发生。

mutationRate: 0.1

精英人数

精英的数量如何影响种群的遗传多样性和保留率?

分析精英的影响需要比突变率更细微的差别。对于测试的每个“精英数量”,我进行了 10 次试验(我知道,不是很多),并记录了 500 代后种群中最佳个体的最终距离,保持其他超参数不变。取这些值的平均值和标准偏差,得出以下结果:

Total population is 100 individuals, Elites included

我敢说,在只有 5 个数据点的情况下,精英数量与均值和标准差之间的关系看起来大致呈抛物线状,趋势相似。当群体规模为 100 时,精英的最佳数量似乎接近 50。

精英的最佳数量不在任何一个极端,这有一定的直观意义。一些“基因搜索空间”(我肯定有一个技术术语)应该致力于在没有实质性变化的情况下在几代人之间传递好的基因。然而,太多的精英和你的遗传算法没有遇到足够的遗传多样性来快速进步。

群体大小

拥有一大群人会有规模效应吗?

在我所做的大多数试验中,我都在寻找 25 个城市之间的最佳路线,在每一代算法中,都有 100 条可能的路线。在这里,我们可以看到 100 是不是一个好的人口数量选择,或者多生几个会有很大的影响。这可以通过两种方式实现:保持精英的数量不变,或者占总人口的百分比不变。让我们两个都试试。

我运行算法的最大值为 20000 代,但是如果一代中最好的个体的距离小于 852(稍后将详细介绍),我会提前停止并打印这一代。结果是:

Elites = 50, mutationRate = 0.01

Elites = 0.50 * popSize, mutationRate = 0.01

基于这些结果,我敢说将群体规模从 100 个个体增加到 1000 个个体会极大地提高算法的性能。此外,使用精英的数量是人口规模的高百分比,而不是低的、平坦的数字,允许算法一致地找到解决方案。我认为这比增加群体规模带来的性能提升更重要。

我认为值得注意的是,对于 100 popSize 组,有些试验完成得很快,有些试验需要 5000、10000 或超过 20000 代(在我砍掉它之前的最大值)。这个分布有一个长尾巴,这使得持续使用令人沮丧。

这些试验进行了很长时间。我不确定我是不是有记忆问题,还是真的花了很长时间。一些人口规模为 100 和 1000(只有 50 个精英)的试验超过了 20000 代,尽管很难对这种情况发生的频率有好的感觉,因为运行它们需要很长时间。此外,我试图查看 10000 人的人口规模,但在等待第一个解决方案 10 分钟后,我放弃了。对这些结果持保留态度(我没有使用超级计算机),但我确实认为总体趋势是成立的。即使 10000 人口所需的世代数减少了 75%,我觉得我们可能会达到收益递减点。

使用较大群体时需要考虑的一个问题是所需的计算量会增加。这在生产环境中可能非常重要,但这里不做分析。

溶液质量

最终解与最优解有多接近?

一般来说,遗传算法可以很快达到一个体面的次优解。可以在下面的 gif 中观看进化进度:

50 elites, 0.01 mutation rate

然而,在许多情况下,当观看融合解决方案的静态帧时,人眼会立即看到明显的改进。会有交叉的路径,通常效率很低。经常会有两个不相连的城市紧挨着,解决方案倾向于将它们分开。后者很容易通过局部的、较小的路径交换来解决。

通常,到 500 代时,总距离不会有很多大的阶梯式下降,任何改善通常都是微小的。有趣的是,我还没有见过任何距离在 851 以下的解,我多次看到同一个数字(到~10 位小数),有多种设置,让我相信它是这些起点的最优解,或者至少是强局部极小值,所以在这种情况下,有时会找到正确的解。

我看着一大堆 10,000 代的运行完成,在大多数情况下,到 851 的最后一小步花了几代才最终发生。由此,我感觉在从随机初始条件中寻找巨大改进方面,遗传方法要比随机搜索好得多,但是寻找最优解主要是在已经很好的解的基础上进行大量的反复试验。

前进

总的来说,这个项目很有趣,感觉相对简单。仅仅几个小时的工作,我就在性能和一致性方面获得了几个数量级的提升。

有一个很好的调试,我经历了几代人以来最优秀的个体之间的巨大差距。这种现象产生了这样的训练曲线:

The final result is not the most fit individual for its generation.

尽管这通常不会影响算法的收敛,但有时会影响最终的解决方案,如上所示。这是因为在记录最佳个体之前,群体中的个体发生了变异。我肯定我不是第一个考虑到遗传算法的人群适应性令人不安的峰值的人,但我很高兴我找到了我的答案。

我还学到了其他一些东西:

  • 从一种非常自由的 Python 风格转变为一种所有内容都显式类型化的风格是很困难的,并且感觉这剥夺了 Python 的通用性。然而,当你越来越抽象的时候,它确实迫使你更多地思考背景中发生的事情。
  • Matplotlib 中的动画没有我预期的那么难,找到其他人的例子帮助很大,尤其是在使用多个艺术家时。
  • 遗传算法似乎适合于在搜索空间很大的情况下进行优化,并且这种改进具有随机性。
  • 我需要在做项目的时候开始写作,这样我就不会忘记我在工作中遇到的所有小片段。

我也有一些想法给那些希望在这方面有所改进的人:

  • 除了self.fitness = 1 / self.routeDistance()还要考虑健身功能。这可能会也可能不会产生有趣的结果,因为选择过程是单调的。
  • 为估计最佳超参数进行更稳健的实验设计。进行多次运行,改变变异率或精英的数量,并找到不同组合的平均值和标准偏差,并不需要太多时间。为了找到最佳的代数,可以使用诸如“120 代后 95%的运行达到最小值”的度量。
  • 调查不同的突变类型,或更多的局部突变。很多时候,会有一小群 3 到 4 个彼此相邻的点,有一个公认的最佳方式来遍历这些点。可能在一个频率上进行短距离交换,而在另一个频率上进行长距离交换。这可以使用基于提议的交换距离的惩罚变异率来合并。
  • 现在,代码使用了许多“for”循环。研究加速/并行化的方法。

我可以看到遗传算法在航班定价、拼车应用程序中匹配乘客和司机或城市规划等领域的潜在用例。目前,我正在阅读两篇论文:UberAI 实验室的深度神经进化和进化出玩雅达利游戏的简单程序。我对在这个领域更深入一点或者复制论文很感兴趣,所以如果任何人有他们正在做的有趣的项目,请告诉我!

调整超参数(第一部分):成功减半

原文:https://towardsdatascience.com/tuning-hyperparameters-part-i-successivehalving-c6c602865619?source=collection_archive---------7-----------------------

Photo by rawpixel on Unsplash

在这个系列中,我想讨论一些超参数优化技术,它们的优点/缺点等。我目前不打算遵循任何特定的时间顺序。每一部分都应该单独阅读。

介绍

为什么我们应该关心优化超参数?

当我们在机器学习中建立各种模型管道时,我们经常会发现自己有十个、二十个甚至更多的超参数需要我们做出决策。这个决策空间随着每个额外的超参数呈指数增长,使得仔细的分析不切实际,如果不是不可能的话。

为了加速项目的开发过程,我们可能希望将这部分工作自动化。

但是怎么做呢?

简单的网格搜索可能是我们的第一选择,但是正如我们所讨论的,由于维数灾难,这是效率最低(时间)的选择。

下一个最佳解决方案是随机采样超参数空间。这个解决方案是由 Bengio 等人提出的,并且已经被证明优于网格搜索。在这种情况下,通过超越,我的意思是随机搜索能够在更短的时间内使用更少的资源找到模型的更可靠和得分最高的超参数配置。为了理解这一点,让我们看一下图 1。摘自原文。

Figure 1.: Grid Search vs Random Search

正如我们所见,这是经常发生的情况,一些超参数比其他更具决定性。在网格搜索的情况下,尽管采样了 9 次试验,但实际上我们只试验了一个重要参数的 3 个不同值。在随机搜索的情况下,9 次试验将仅测试 9 个不同的决定性参数。

我们能做的比随机搜索更好/更多吗?当然可以!但是*“如何”可能取决于我们所说的“更好*”的确切含义。

存在两种类型的算法,它们是对随机搜索的自然扩展。第一个是贝叶斯优化算法,如 Tree-Parzen Estimators ,它有助于找到统计上更稳健(可靠)和得分更高的配置。

第二种类型,例如成功减半超带,在资源分配上进行优化。在下一节中,我将讨论 成功减半 如何通过比随机搜索更有效地划分和选择随机生成的超参数配置来改进随机搜索,而无需对配置空间的性质做更多假设。更有效的资源分配,意味着给定相同的配置集,成功减半将比随机搜索更快地找到最优配置。

成功减半

那么,我们如何更有效地分配我们的资源呢?让我们来看看摘自本文的图 2。

Figure 2: The validation loss as a function of total resources allocated for two configurations.

通常在实践中,相对于最差的配置,有希望的配置往往得分更高,甚至在过程的早期。

我们走吧!这就是成功减半的意义所在!下面是该算法如何利用这一假设:

  1. 随机抽样一组超参数配置
  2. 评估所有当前剩余配置的性能
  3. 抛出,最差得分配置的下半部分
  4. 回到 2。并重复直到剩下一个配置。

与其浪费大量的训练时间在毫无结果的配置上,不如尽快成功地将投掷减半。因此,可以将更多的训练时间(即资源)分配给更有潜在价值的模型。

实际上…

为了成功应用减半,我们需要找到机器学习库,它允许我们暂时停止模型的训练,最终保存模型,然后稍后重新加载模型并且继续训练

不幸的是,后一点是最有问题的一点。作为一名从业者,不幸的是,您没有时间/预算从头开发自己的库,并且经常依赖于开源云中的可用资源。不幸的是,实践中使用的一些算法缺少这个选项,但幸运的是,我们有很多强大和/或流行的算法!所有 Scikit-Learn 的“热启动”超参数实施都是如此,例如(Extreme)RandomForest、GradientBoosting 等

对于极端的梯度增强库,我只能找到 xgboost 的方法,而 LGBM 在提取增强器时产生了一个 bug。不幸的是,Catboost 没有这个选项,很可能是由于算法本身的性质,它试图通过移动数据来取消每次 boost 迭代的偏向。

对于深度学习,Pytorch,Keras 和 TensorFlow 仍然允许最大的灵活性,所以没有问题!

让我们一步一步来,看看如何在 SuccessiveHalving 的实现中包含所有这些库。

首先,我们需要这些模型的包装器,这迫使我们实现保存/加载模型的定义,更重要的是在重载后进一步训练模型。

下面的基类对此进行了描述:

下面是一个没有提前停止的 XGBOOST 示例:

在这种情况下,我们必须提取助推器并使用功能 API 来进一步训练。出于某种原因,这个类似的技巧会为 Lightgbm 产生一个错误。

借助热启动超参数,Scikit-learn 变得更加简单。

如果这个超参数不存在,恐怕您将不得不完全改装模型,从而损失重新分配资源所获得的时间。

现在我们有了 wapper,我们可以继续实施成功减半了!

变量“eta”是我们增加资源的速率,直到我们达到我们希望使用的资源的最大值。

例如,假设我们最终的 xgboost 模型在 200 个配置的样本中最多应该有 1000 棵树。我们将资源单位设置为 10,这样最初的一批配置将只训练 10 次提升。在每一步,我们用“eta ”= 1.93 倍的估计量来训练新的一批。

更多的例子和实现是可用的这里。

没有灵丹妙药…

应用成功减半时的一个大问题是在总资源和配置总数之间找到合适的平衡。

较小的学习率通常与更多的资源、更多的树(在(极端)梯度提升的情况下)或更多的神经网络时期密切相关。

我们如何能调整这样一个选择? HyperBand 提出了一个解决方案,但这是下次的事了!

我写了更多精彩的东西!

@ 在 TensorFlow 中构建决策树

@tensor flow 中的自定义优化器

@XGBOOST 回归预测区间

参考资料:

  1. J.Bergstra 和 Y. Bengio,超参数优化的随机搜索,2011 年
  2. K.Jamieson,A. Talwalka,非随机最佳臂识别和超参数优化,2015 年
  3. 长度李、贾米森、德萨沃、罗斯塔米扎德、塔瓦尔卡尔。超带:基于 Bandit 的超参数优化新方法。arXiv 预印本 arXiv:1711.09784,2017 年
  4. Scikit-Learn,url,http://scikit-learn.org/stable/
  5. J.Bergstra,R. Bardenet,Y. Bengio,B. Kégl,超参数优化算法
  6. github:【https://github.com/benoitdescamps/Hyperparameters-tuning

把数据变成美元?

原文:https://towardsdatascience.com/turning-data-into-dollars-15fa2d0961af?source=collection_archive---------7-----------------------

Image Credits: Managed Data Center News

上周在 DataWorks 峰会上接受采访时,Bill Schmarzo 提出了一个基本问题,即组织每次点击鼠标收集的数据的价值。【I】当面对“数据是新货币”【ii】以及组织应努力“将数据货币化”【iii】的主张时;应该指出数据的交换价值和使用价值之间的区别。我完全同意他的结论:“数据的价值来自于将其用于做出更好的决策。”正如我们之前所建议的,数据只不过是我们业务现实的代理,除了我们的同事、业务合作伙伴和外部利益相关者的客户体验之外,它没有任何内在价值。哪些类型的数据会突出这些不同的价值观?

*因为人们看待价值的角度不同,所以看待数据的角度也不一样。*几年前,我们与微软的 Kees Pronk 合作推出了 Business Value Matrix(BVM ),以强调手头数据的不同用途,从而强化客户故事。【v】BVM 认为数据提供了将业务挑战与其潜在解决方案联系起来的故事的构建模块。这个立方体用于沿着三个轴探索客户对价值的看法:他们如何使用数据来说明他们的挑战和机遇,他们使用什么类型的证据来证明问题,什么形式的数据将用于判断成功?

The Business Value Matrix™

第一个问题强调了每个利益相关者都有一个主要的信念,即把人、过程或技术作为企业价值的源泉。首先,利益相关者深信人才是企业价值的主要来源——管理层的角色是提高员工、业务合作伙伴和最终客户的知识和技能。在第二种思维模式中,人才不如组织良好的流程重要——业务的价值与组织优化与关键业务流程相关的活动的努力直接相关。最后,在第三种情况下,人们深信技术(信息和物理)的存在本身就足以提高底线。在每种情况下,涉众将收集和监控不同种类的数据,作为组织当前问题和未来机会的证据。

第二个问题说明了关于概念证明的可能性:利益相关者在个人、公司和市场层面寻找证明价值。那些相信个人可以改变公司表现的人;个人生产力的数据是组织成功的代表。对其他人来说,一个企业的好坏取决于它最薄弱的环节——在这里,关于组织如何运作的数据比衡量成功的个人标准更重要。最后,对于一定数量的经理或股东来说,唯一真正的证据是市场本身——组织指标被淡化,而倾向于客户满意度和市场份额的数据。这里,数据科学家需要考虑如何指定组织挑战、分析级别的难度以及哪些证据是可以直接观察到的。

第三个问题集中在利益相关者如何展望成功。对于一定数量的管理者来说,成功就是效率——数据需要关注相关活动的成本和收益。对许多人来说,有效性是比效率更好的成功衡量标准——数据需要衡量组织与其客户之间关系的质量。对于其他人来说,创新是关键指标,数据需要说明组织如何应对外部威胁和机遇。对于其他人来说,利用率是一个不同的指标,这表明当强调组织资源在一段时间内的利用情况时,成功是更好的衡量标准。在这里的每一种情况下,基本问题是数据如何转化为个人或集体行动。客户故事从他们自己在矩阵每个轴上的位置出现。

商业分析与其说是处理数据,不如说是过滤信息,以帮助客户在他们想要讲述的故事中取得成功。如果业务价值矩阵为利益相关方提供了一种工具来设想数据和客户价值之间的潜在桥梁,那么数据科学可以提供将描述性、预测性和规范性分析应用于组织的机制。在我们位于巴约纳的暑期学校,以及我们在欧洲的大师班,我们将帮助您发展您的分析技能。该研究所专注于数据科学在管理人员中的五个应用:在数字时代工作、数据驱动的决策、机器学习、社区管理和可视通信。数据驱动的决策会对你未来的工作和职业产生影响。

Lee Schlenker 是商业分析和社区管理教授,也是 http://baieurope.com 商业分析学院 的负责人。【www.linkedin.com/in/leeschlenker.】你可以在推特上关注我们https://twitter.com/DSign4Analytics

— — — — — — -

【我】艾伯特森,m .(2017)数据的价值?都是关于终结游戏,硅角度

【ii】摩根·l .(2016)8 种数据货币化的方式《信息周刊》

【iii】Wixom,b .和 Ross,J. (2017),如何将你的数据货币化,麻省理工斯隆管理评论

【iv】Schlenker,L. (2017),数据不仅仅是数据…,媒介

Schlenker,l .和 Pronk K. (2009),价值之旅,Goodfellow 出版社

用深度学习把堡垒之夜变成 PUBG(cycle gan)

原文:https://towardsdatascience.com/turning-fortnite-into-pubg-with-deep-learning-cyclegan-2f9d339dcdb0?source=collection_archive---------4-----------------------

理解用于图像风格转换的 CycleGAN 并探索其在游戏图形模块中的应用。

A Neural Network’s attempt at recreating Fortnite in the visual style of PUBG.

如果你是一个游戏玩家,你一定听说过两个疯狂流行的皇家战役游戏,堡垒之夜和 PUBG。这是两个非常相似的游戏,100 名玩家在一个小岛上决一雌雄,直到只剩下一名幸存者。我喜欢堡垒之夜的游戏性,但倾向于更喜欢 PUBG 的更真实的视觉效果。这让我想到,我们能不能有游戏的图形模块,让我们可以选择我们喜欢的视觉效果,而不必依赖游戏开发商为我们提供这种选择?如果有一个 mod 可以在 PUBG 的视觉效果中渲染堡垒之夜的画面会怎么样?这就是我决定探索深度学习是否有所帮助的地方,我遇到了一种叫做 CycleGANs 的神经网络,它碰巧非常擅长图像风格转移。在本文中,我将介绍 CycleGANs 是如何工作的,然后训练它们将堡垒之夜视觉转换成 PUBG。

Fortnite (left) with it’s cartoonish visuals and PUBG (right) with its more realistic visuals.

什么是 CycleGANs?

CycleGANs 是一种用于跨域图像风格传递的生成对抗网络。他们可以被训练将一个领域的图像,比如堡垒之夜,转换成另一个领域的图像,比如 PUBG。这项任务是以无人监督的方式执行的,即,没有来自这两个域的图像的一对一映射。

Original Github implementation and its results can be found here.

网络能够理解原始域的图像中的对象,并应用必要的变换来匹配目标域的图像中的相同对象的外观。该算法的原始实现被训练成将马转换成斑马,将苹果转换成橙子,将照片转换成绘画,结果令人惊叹。

它们是如何工作的?

让我们以堡垒之夜为例,以 PUBG 为例,尝试理解 CycleGANs 是如何工作的。使用两个游戏的大量截图,我们训练了一对生成性对抗网络,其中一个网络学习堡垒之夜的视觉风格,另一个学习 PUBG 的视觉风格。这两个网络以循环的方式同时被训练,以便它们学会在两个游戏中的相同对象之间形成关系,从而进行适当的视觉转换。下图显示了这两个网络循环设置的一般架构。

Cycle from “Real Fortnite” to “Fake PUBG” to “Reconstructed Fortnite”.

我们从堡垒之夜的原始图像开始训练过程。我们将训练两个深度网络,一个生成器和一个鉴别器。随着时间的推移,鉴别者将学会区分堡垒之夜的真假图像。生成器将被训练为使用来自训练集的 PUBG 的随机截图将输入图像从原始域转换到目标域。

为了确保这个转换是有意义的,我们强加了一个重建条件。这意味着我们同时训练另一组生成器/鉴别器,该生成器/鉴别器从伪域重建原始域中的图像。我们强加了这样一个条件,即该重建必须与原始图像相似,给我们一个循环损失值,我们的目标是在训练过程中最小化该值。这类似于自动编码器,除了我们不是在中间步骤的潜在空间中寻找编码,而是在我们的目标域中寻找整个图像。

Overview of Generator F2P shown in the previous figure.

这里使用的发生器网络(F2P)由三个主要卷积模块组成。第一个在低维潜在空间中找到了堡垒之夜截图的编码。这种编码被转换成在相同的潜在空间中表示 PUBG 的编码。然后,解码器从转换后的编码构建输出图像,给我们看起来像 PUBG 的堡垒之夜图像。

在这个培训过程中,我面临的一个限制是,由于 GPU 内存的限制,我只能处理 256x256 的图像。这会显著影响结果,但是如果您的视频内存超过 8gb,您可以尝试生成多达 512x512 的图像。如果可以,请在这里告诉我!

结果

经过 12 个小时的训练后,CycleGAN 生成的图像似乎很有希望。该网络成功地将堡垒之夜的天空、树木和草地的颜色转换成了 PUBG 的颜色。堡垒之夜过度饱和的颜色被转换成了 PUBG 更真实的颜色。

天空看起来不那么蓝,草和树的卡通绿色看起来更接近在 PUBG 看到的。它甚至学会了用 PUBG 的枪和弹药指示器替换屏幕底部的生命计!在这两个领域中无法联系的是玩家的外观,这就是为什么它周围的像素有点模糊。总的来说,该网络在识别跨两个领域的对象并转换它们的外观方面做得不错。

要查看更长的结果,请查看下面嵌入的视频。如果你喜欢你所看到的,别忘了点击这里并订阅我的 YouTube 频道!

游戏中图形模块的应用

虽然结果对我来说很好,但很明显,在我可以用 PUBG graphics 真正玩堡垒之夜之前,我们还有很长的路要走。但是,一旦我们能够使用这些网络实时生成更高分辨率的图像,未来就有可能为游戏构建图形 mod 引擎,而不必依赖游戏开发者。我们可以使用我们喜欢的游戏的视觉风格,并将其应用到任何其他游戏中!

我将探索如何通过使用我在本文中讨论的相同技术将游戏视觉转换成现实生活中的照片来实现游戏中的照片真实感。如果你想保持跟踪,请在媒体或我的 YouTube 频道上关注我。感谢您的阅读!

编辑:这里是一些相同的更新结果。

升温:模型蒸馏的机制

原文:https://towardsdatascience.com/turning-up-the-heat-the-mechanics-of-model-distillation-25ca337b5c7c?source=collection_archive---------5-----------------------

当我第一次读到这篇论文时,我被两种冲动所触动。首先,我绝对应该写一个帖子来解释它,因为它的许多想法都是优雅而令人信服的——从它对网络存储信息意味着什么的思考,到对 softmax 正在做什么的更好的直观感受。第二,也许这样做是白费力气,因为原著本身写得太好了。

在这种情况下,我认为我无法给出比 Hinton,Vinyal & Dean 的原始论文更好的介绍了:

许多昆虫的幼虫形态最适合从环境中吸取能量和营养,而完全不同的成虫形态最适合完全不同的旅行和繁殖要求。…与昆虫的类比表明,如果能更容易地从数据中提取结构,我们应该愿意训练非常繁琐的模型。繁琐的模型可以是单独训练的模型的集合,或者是用非常强的正则化子(例如 dropout [9])训练的单个非常大的模型。一旦繁琐的模型被训练,我们就可以使用不同种类的训练,我们称之为“提炼”,将知识从繁琐的模型转移到更适合部署的小模型

乍一看,这似乎难以置信,违反直觉。提取信息意味着什么?如何使用简单模型的架构和参数结构来表示复杂模型学习到的函数?

一个对我有用的比喻——为简单和抽象道歉——是主模型本质上像一只母鸟,消化她的食物,以便更小、更简单的模型可以更容易地消耗它。最初,每个观察仅由其训练集标签表示:0 或 1(在两个类的情况下)。现实并没有告诉我们单个事件的概率,而是告诉我们表面下的结果有多大的可能性或边际性;我们只看到发生了什么。

但是,在学习决策边界的过程中,复杂模型隐含地开始捕捉更细微的信息。一个给定的例子显然是其类的中心代表,还是它是边缘的,接近决策边界,从而难以与备选类区分?如果我们在一个多种类的环境中操作,这个例子中最有可能的种类“哈士奇”是否更接近作为次优选择的“雪橇犬”或“吉娃娃”的决策界限?希望这些例子能给我们一些直觉,让我们知道在一个模型的输出分数中捕捉到的这类问题的答案,可以为复杂模型所学习到的内部表征提供线索。模型提炼的关键思想是:模仿这种学习到的表示应该比一开始就学习它要容易得多,这意味着(近似)模仿的任务可以通过更简单的模型来完成。

打开暖气

温度在(模型)蒸馏过程中的作用是将模型推到一个极端概率较小的区域,这样它们对我们的计算更有帮助。

为了理解这是怎么回事,我发现绕一圈了解一下 softmax 在做什么以及为什么要这么做是很有价值的。

直到我最近更深入地考虑它,我基本上把 softmax 作为“一个将实数输出压缩成概率分布的运算符”存储在我的脑海中。当然,它确实是这样做的:数学上很清楚,分子中所有类的 sigmas 加起来就是一,只是通过构造。但是我从来没有认真思考过“softmax”名字中的“max”部分。softmax 不仅仅是一个规范化操作符:它是一个规范化操作符,对较大的值有很强的特权。

当其他人第一次看到这个公式时,这可能是他们完全内化的东西,但我在这里找到了放大一些具体细节的价值。(术语注释:在上面的公式中,当您看到下标 x 值时,对于所有 j 类,我将这些值称为“logits ”,有点不精确地遵循输入到逻辑转换中的实数值的命名约定)。如果有(1,2,3)的 logit,那么在 logit 空间中,每对相邻的有序数之间有相等的间隙。然而,在指数空间中,差距随着 logit 的大小而变大。(2.7,7.38,20.08)是这些逻辑在被指数化后的翻译。当在指数空间中进行归一化时,得到的是(0.08,. 25,. 67),而不是仅归一化逻辑本身得到的(. 166,. 33,. 5)。如您所见,指数化的输出更接近于 argmax 函数,它将所有权重放在单个最高值上,而不是其他位置(这里的“argmax”指的是一个布尔函数,它指示哪个类包含某个输入的最高值)

从通常用于训练神经网络的交叉熵损失函数的角度来看,这种与 argmax 的相似性是有益的,因为该损失函数是真正对应于给定观察的类的对数模型分数的-1 倍。不关心精确校准的概率:它希望将尽可能多的概率放在真实类上。像这样的目标函数显然受益于 argmax 框架,而这正是 softmax 想要逼近的。

The cross-entropy loss equation

但是,当您的目标不仅是与另一个模型交流您的最佳猜测类是什么,而且交流可能性较小的类的相对大小时,这种策略就不那么有益了。这是因为,除了夸大最可能类的值,softmax 还会将可能性较小的类的值推得更小、更接近。你可以首先想到两个简单的归一化(即每个值除以所有值的总和),一个是你的值为(1,6,10),另一个是你的值为(1,6,100)。前者的归一化值为(0.06,0.35,0.59)。对于后者,我们得到(0.009,0.056,0.934)。因此,在最大值相对于其他两个值非常大的世界中,较小值之间的相对差异被压缩并且大部分丢失,这两个次要类之间的差异从 0.294 到 0.047。这让我们更接近 arg max 的情况,其中模型只传达一个信号:它认为哪个类更有可能。

考虑到我们希望在模型提炼过程中传递的各种微妙信息,任何导致我们学习到的模型输出崩溃到 1/0,甚至更强烈地倾向于这种离散输出的东西,都是一种障碍。更具体地说,在交叉熵框架中,如果我们想象这些概率进行训练(也就是说:用概率替换 y-i 值),这些概率最终会在该类别的学习概率对你的总体损失的影响的线性组合中起作用。这意味着这种价值上的线性差异将对我们从这些二级课堂中学习信息的能力产生有意义的影响。

The e^x function: a good one to have in your head to build intuition here

Temperature 的工作原理是降低发送到 softmax 函数的逻辑值的绝对值,将它们除以固定的恒定温度值 T,然后对这些较小的值求幂并求和。简单地说,如果您考虑一下标度一端的逻辑值本身和另一端的指数逻辑值,温度可以用于在这两端之间进行插值,随着温度值变高,指数运算的 argmax 倾向会降低。这是因为,当您将 logits 划分为更小的值时,您会将所有指数化的类值进一步推向左侧,从而使给定输入的类输出之间的比例差异变得更接近线性。具体来说,如果你看上面的图,你可以很容易地说服自己,你从(2,1)的输入得到的相对差异与从(1,0.5)的输入产生的相对差异有意义,后者对应于温度 T=2。

这种方法是蒸馏框架的关键,它类似于:

  • 正常训练复杂模型(CM ),即温度为 1
  • 获取一些额外的数据集,并通过 CM 运行,但在 softmax 层中将 logits 转换为概率时使用大于 1 的温度。这个温度值在这里是一个超参数。这里有一个有趣的注意事项是,这个额外的数据集实际上不需要贴上基本事实标签:我们所关心的是了解复杂模型对给定观察的想法,而不是基本事实是什么。也就是说,如果你有基本事实标签,你通常可以通过使用它们来改进训练(为了简单起见,我不会在这里讨论)
  • 使用这些“软目标”概率来训练你的简单模型(SM),也是在温度> 1 的情况下。
  • 一旦你的提取模型被训练,在温度 1 下操作它,这样你得到的结果可能更 argmax-esque,因此可以更清楚地与使用典型 softmax 训练的模型进行比较

更好地在一起:整体应用

尽管该论文概述的提取策略适用于任何可以输出概率得分的分类器,但作者特别关注提取集成的价值。

集成是有效的,因为当你获取多个样本时——在这种情况下,这里的样本是一个模型,用一些不同的初始条件训练——并对它们进行平均,这相对于训练单个模型来说减少了方差。从理论上讲,方差和偏差是模型误差的两个来源,因此方差的减少是集成在许多机器学习应用中表现非常好的经验现实背后的理论证明。

出于解释或部署后勤方面的原因,可能需要将该集合所获得的信息压缩到一个模型中。但是,根据定义,如果您训练组成集成的任何模型的单一版本,您将只获得一个高方差估计点,而不是整个集成的好处。然而,如果你训练的是全体成员的平均值(也可以看作是概率得分),那么你就是在教二级模型学习所有成员的聚合意见,而不是简单地根据原始标签生成它自己的函数。

事实上,作者发现,当他们在语音识别数据集上测试他们的方法时,根据聚合集成输出训练的提取模型比简单地根据真实情况训练的单一模型做得更好。

A diagram from the paper; WER here corresponds to “Word Error Rate”

一些最后的想法

在我最喜欢的漫画《T1》中,主角认为最好的知识是产生有趣的新问题的知识,而不仅仅是答案。虽然我承认这有点浪漫,而不是务实的知识方法,但它对我很有吸引力。

所以,在这篇文章的最后,我将举起一杯从这篇论文留给我的问题中提炼出来的东西。(注意:完全有可能存在回答这些问题的范围研究:我没有对这个领域做全面的文献综述。如果你知道他们,一定要把他们送到我这里来!)

Raise a glass to freed-er, I mean, free parameters

  • 当问题的类别数量较少,因而可供学习的第二类信号不丰富时,蒸馏的有效性会下降到什么程度?
  • 有没有办法将这种温度/插值软目标框架推广到像随机森林这样不使用 softmax 来生成输出的技术?
  • 通过对复杂模型进行更多的剖析,并直接模拟复杂模型的表示空间,我们可以获得多大的性能提升?(即使用 softmax 之前的层的单位作为辅助信号)。

教程:通过手势识别字母——深度学习和 OpenCV 应用

原文:https://towardsdatascience.com/tutorial-alphabet-recognition-deeplearning-opencv-97e697b8fb86?source=collection_archive---------3-----------------------

注意:文章过时了。我更改了我的 GitHub 用户名,结果 GitHub 列表不显示。请在此访问项目代码。

这是一个关于如何构建深度学习应用程序的教程,该应用程序可以实时识别由感兴趣的对象(在这种情况下是瓶盖)书写的字母表。

项目描述

深度学习技术能力的一个流行演示是图像数据中的对象识别。

python 中的这个深度学习应用程序通过网络摄像头实时捕捉的手势来识别字母表。允许用户使用感兴趣的对象(在这种情况下是水瓶盖)在屏幕上书写字母表。

您可以访问完整的项目代码:

[## ACL 21/Alphabet _ Recognition _ 手势

更新]:我将不再关注与回购相关的问题或邮件,因为我目前非常忙…

github.com](https://github.com/acl21/Alphabet_Recognition_Gestures)

工作示例

代码要求

代码在 Python 版本中,使用 OpenCV 和 Keras 库。

跟随这篇中帖在 Python 3 中安装 OpenCV 和 Keras。

数据描述

机器学习和深度学习的对象识别的“扩展 Hello World”是用于手写字母识别的 EMNIST 数据集。它是 MNIST 数据集的扩展版本(物体识别的“Hello World”)。

The letter ‘e’ is stored in a 28 x 28 numpy array as shown above.

代码解释

步骤 1:训练一个多层感知器模型

1.1 负载数据

我们使用 Python 的 mnist 库来加载数据。

现在让我们准备好数据,以供模型使用。将数据分成训练集和测试集,标准化图像和其他初步的东西。

1.2 定义模型

在 Keras 中,模型被定义为一系列层。我们首先初始化一个“序列模型”,然后添加包含各自神经元的层。下面的代码做了同样的事情。

正如预期的那样,该模型采用 28 x 28 像素(我们展平图像,并将每个像素传递到一维向量中)作为输入。模型的输出必须是对其中一个字母的决策,因此我们将输出层设置为 26 个神经元(决策是根据概率做出的)。

1.3 编译模型

既然模型已经定义好了,我们就可以编译它了。编译模型使用了后台(所谓的后端)的高效数值库,如 Theano 或 TensorFlow。

这里,我们指定了训练网络所需的一些属性。通过训练,我们试图找到最佳的权重集来对输入做出决策。我们必须指定用于评估一组权重的损失函数、用于搜索网络的不同权重的优化器以及我们希望在训练期间收集和报告的任何可选指标。

1.4 拟合模型

在这里,我们使用模型检查点来训练模型,这将帮助我们保存最佳模型(根据我们在上一步中定义的指标最佳)。

1.5 评估模型

该模型在 EMNIST 数据集上的测试精度为 91.1%

1.6 把所有东西放在一起

将所有步骤放在一起,我们得到了构建一个基于 EMNIST 数据的体面的 MLP 模型所需的完整代码。

步骤 2:训练卷积神经网络模型

2.1 和 2.2 —加载数据并定义模型

这两个步骤与我们在构建 MLP 模型时实施的步骤完全相同。

2.3 定义模型

出于超出本教程范围的原因,我定义了上面的 CNN 架构来解决手头的问题。要了解更多关于 CNN 的信息,请访问这个教程页面,它是最好的!

2.3 编译模型

Unlike the MLP model, this time I am using the ADADELTA optimizer

2.4 适合车型

要了解模型变量历元 如何影响出模型性能,请访问本。

2.5 评估模型

该模型在 EMNIST 数据集上的测试精度为 93.1%

2.6 把所有东西放在一起

将所有这些放在一起,我们得到了构建一个基于 EMNIST 数据训练的像样的 CNN 模型所需的完整代码。

第三步:初始化东西

在我们研究识别代码之前,让我们初始化一些东西。

首先,我们加载在前面步骤中构建的模型。然后我们创建一个字母字典, blueLowerblueUpper 边界来检测蓝色瓶盖,一个 kernal 来平滑沿途的事物,一个空的 黑板 来存储白色的文字(就像 EMNIST 数据集中的字母表),一个 deque 来存储所有的

第四步:捕捉文字

一旦我们开始逐帧读取输入的视频,我们就试图找到蓝色的瓶盖,并将其用作一支笔。我们使用 OpenCV 的 cv2。VideoCapture() 从视频文件或网络摄像头实时逐帧(使用 while 循环)读取视频的方法。在这种情况下,我们将 0 传递给方法以从网络摄像头读取数据。下面的代码演示了同样的情况。

一旦我们开始读取网络摄像头馈送,我们就会借助 cv2.inRange() 方法不断在帧中寻找蓝色对象,并使用事先初始化的 blueUpperblueLower 变量。一旦我们找到轮廓,我们做一系列的图像操作,并使其平滑。平滑只是让我们的生活更轻松。如果你想知道更多关于这些操作——侵蚀、变形和扩张,请查看这个。

一旦我们找到轮廓(当找到轮廓时, if 条件通过),我们使用轮廓的中心(蓝色帽)在屏幕上绘制它的移动。下面的代码做了同样的事情。

上面的代码检查是否找到了轮廓,如果是,它取最大的一个(假设是瓶盖),使用**cv2 . minenclosingcircle()cv2.circle() 方法围绕它画一个圆,借助cv2 . moments()**方法得到找到的轮廓的中心。最后,中心被存储在一个名为 的 deque 中,这样我们就可以将它们全部连接起来,形成一个完整的文字。

我们在 框架黑板 上显示图纸。一个用于外部显示,另一个将其传递给模型。

注意:我已经写了一个关于建立一个绘图环境的简短教程,它允许我们像在一个画图应用程序中一样绘图,在这里查看以清楚地理解正在发生的事情。

第五步:刮掉书写内容,并将其传递给模型

一旦用户写完了,我们就把之前存储的点连接起来,放在黑板上,然后传给模型。

当我们停止书写时,控制进入这个 elif 块(因为没有检测到轮廓)。一旦我们验证了 deque 不为空,我们现在就可以确定写入已经完成。现在我们取 黑板 图像,再做一次快速轮廓搜索(刮掉字迹)。找到后,我们对其进行适当的剪切,调整其大小以满足我们构建的模型的输入尺寸要求,即 28 x 28 像素。然后传给两个模特。

步骤 6:显示模型预测

然后,我们在 窗口上显示我们的模型做出的预测。然后我们使用 cv2.imshow() 方法显示它。当我们进入 循环从网络摄像头读取数据时,脱离 后,我们释放摄像头并破坏所有窗口。

执行

1。下载数据

从这里下载数据文件夹,放入你的项目目录。

2。建立 MLP 模型

**> python mlp_model_builder.py**

3。建立 CNN 模型

**> python cnn_model_builder.py**

4。运行引擎文件

**> python alphabet_recognition.py**

5。抓起蓝色瓶盖

玩得开心点。

结论

在本教程中,我们建立了两个深度学习模型,一个 MLP 模型和一个 CNN 模型,在著名的 EMNIST 数据上进行训练。并用这些模型来实时预测我们感兴趣的物体所写的字母。我鼓励你调整两个模型的架构,看看它们如何影响你的预测。

希望这个教程是有趣的。感谢阅读。

活也让别人活!

Photo by Amador Loureiro on Unsplash

教程:Python 中的异步语音识别

原文:https://towardsdatascience.com/tutorial-asynchronous-speech-recognition-in-python-b1215d501c64?source=collection_archive---------0-----------------------

一个(相当)简单的技术,用于使用 Google 有点儿有点儿令人困惑的语音识别 API

让我们面对它:它很难与谷歌的机器学习模型竞争。该公司拥有如此多的数据,以至于在准确性和质量方面彻底击败了竞争对手。不幸的是,谷歌在为其 API 提供易于理解和最新的文档方面做得不够好,这使得初级和中级程序员很难入门。

我最近在尝试使用其语音识别 API 转录大约 1,200 条新闻广播时遇到了这个问题。因为 Google 最近改变了它的云 API,所以我在网上找到的很多例子都不是很有帮助。甚至当我更新了云 SDK 的时候,我仍然在尝试运行他们的样本代码时遇到了问题。

一种替代方法是使用 SpeechRecognition 库,但是据我所知,它只适用于同步请求,同步请求的持续时间被限制在一分钟以内。也许一个更好的程序员可以在使用谷歌的 Python API 的同时找到解决方案,但是你被我卡住了。:)

要完成本教程,您需要以下工具:

  • Python 2.7
  • 一个谷歌账户
  • Sox
  • 一个 wav 文件(此处下载

激活云服务

前往谷歌云主页并注册免费试用。只要注册,你就可以获得 300 美元的免费积分。

1)创建一个“项目”来存储你的凭证和账单信息

2)启用谷歌语音 API,按照提示激活计费。不要担心,在您升级到付费帐户之前,不会向您收费。

3)创建一个 API 密匙并保存起来以备后用。

4)创建一个云存储“桶”。这是我们将要存放我们想要转录的文件的地方。不幸的是,为了使用异步服务,你不得不在谷歌存储器上托管文件。

安装 Sox

下一步是在我们的机器上安装 Sox。Sox 是一个非常容易使用的命令行工具,用于操作音频文件。

如果您使用的是 Mac ,您可以通过在终端中运行以下命令来使用 Homebrew 安装 Sox 及其依赖项:

brew install sox

如果你使用的是 Ubuntu ,你可以从终端运行以下命令:

sudo apt-get install libasound2-plugins libasound2-python libsox-fmt-all
sudo apt-get install sox

将音频转换为单声道

现在我们已经安装了 Sox,我们可以开始设置 Python 脚本了。因为 Google 的语音识别 API 只接受单通道音频,我们可能需要使用 Sox 来转换我们的文件。您可以通过查看计算机上的文件属性来进行检查:

如果您的文件已经是单声道的,您可以跳过这一步。如果没有,我们可以使用 Sox 很容易地将其从 Python 转换过来。

  • 1)导入子进程库以访问我们的可执行程序
import subprocess
  • 2)编写并运行 Sox 命令来编写一个只有一个通道的新文件。
filename = "test/test.wav"
newfilename = "test/newtest.wav"
command = ['sox', filename, '-c', '1', newfilename] 
subprocess.Popen(command)
  • 3)验证我们新转换的文件是否正确。

上传转换后的文件

随着我们的音频转换为单声道,我们需要做的就是将新的音频上传到谷歌存储,然后我们就可以开始我们的 Python 脚本了。虽然这可能是您希望使用 Google Storage API 模块以编程方式完成的事情,但这超出了本教程的范围。

相反,我们将只使用我们之前使用的基于 web 的 GUI。您需要选中“公开共享”选项,如图所示。请记住,这将对整个世界开放,直到您将其从 Google Storage 中删除或更改权限。

1)导入请求库,用于向 Google 的 API 和 json 库发出请求,以解析响应。

import requests
import json

2)定义我们在发出请求时将使用的 URL。您需要用您之前制作的 API 密钥来填充空白。

url = "https://speech.googleapis.com/v1/speech:longrunningrecognize?key=YOURAPIKEYHERE"

3)为我们的 JSON 请求创建参数。这些只是我们可以指定的几个可能的参数。你可以在这里 查看其他

payload = {
    "config": {
      "encoding": "LINEAR16",
      "sample_rate_hertz": 48000,
      "language_code": "en-US" },
    "audio": {
        "uri": "gs://BUCKETNAMEHERE/FILENAMEHERE.wav" }
}

发送请求并保存响应。

r = requests.post(url, data=json.dumps(payload))

响应应该包括一个数字标记,我们将使用它来访问我们的转录结果。输出将类似于这样:

Out[1]: {u'name': u'5284939751989548804'}

我们可以这样保存令牌:

json_resp = r.json()
token_resp = json_resp['name']

检索结果(你需要等待几秒钟)。

url = "https://speech.googleapis.com/v1/operations/" + str(token_resp) + "?key=YOURAPIKEYHERE"
content_response = requests.get(url)
content_json = content_response.json()

输出应该是这样的:

瞧啊。

您已经准备好为自己的项目构建语音识别管道。如果您有任何问题(或更可能的建议),请不要犹豫,发表评论。

教程:构建车道检测器

原文:https://towardsdatascience.com/tutorial-build-a-lane-detector-679fd8953132?source=collection_archive---------2-----------------------

Waymo 的自动驾驶出租车服务🚕本月刚刚上路——但是自动驾驶汽车是如何工作的呢?道路上画的线向人类驾驶员指示车道在哪里,并作为相应地驾驶车辆的方向的指导参考,以及车辆代理如何在道路上和谐互动的约定。同样,识别和跟踪车道的能力对于开发无人驾驶车辆的算法至关重要。

在本教程中,我们将学习如何使用计算机视觉技术建立一个跟踪道路车道的软件管道。我们将通过两种不同的方法来完成这项任务。

目录:

方法一:霍夫变换
方法二:空间 CNN

方法 1:霍夫变换

大多数车道设计得相对简单,不仅是为了鼓励有序,也是为了让人类驾驶员更容易以一致的速度驾驶车辆。因此,我们的直观方法可能是首先通过边缘检测和特征提取技术来检测相机馈送中的突出直线。我们将使用 OpenCV,一个计算机视觉算法的开源库来实现。下图概述了我们的管道。

在我们开始之前,这里是我们的成果演示:

1。设置您的环境

如果您尚未安装 OpenCV,请打开终端并运行:

pip install opencv-python

现在,通过运行以下命令克隆教程存储库:

git clone [https://github.com/chuanenlin/lane-detector.git](https://github.com/chuanenlin/lane-detector.git)

接下来,用文本编辑器打开detector.py。我们将在这个 Python 文件中编写本节的所有代码。

2。处理视频

我们将以一系列间隔为 10 毫秒的连续帧(图像)的形式输入车道检测的样本视频。我们也可以随时按“q”键退出程序。

3。应用 Canny 检测器

Canny 检测器是一种针对快速实时边缘检测而优化的多阶段算法。该算法的基本目标是检测亮度的急剧变化(大梯度),例如从白到黑的转变,并在给定一组阈值的情况下将它们定义为边缘。Canny 算法有四个主要阶段:

A .降噪

与所有边缘检测算法一样,噪声是一个至关重要的问题,经常导致错误检测。5x5 高斯滤波器用于卷积(平滑)图像,以降低检测器对噪声的灵敏度。这是通过使用正态分布数字的内核(在本例中为 5x5 内核)在整个图像上运行来实现的,将每个像素值设置为其相邻像素的加权平均值。

5x5 Gaussian kernel. Asterisk denotes convolution operation.

B .强度梯度

然后,沿 x 轴和 y 轴对平滑后的图像应用 Sobel、Roberts 或 Prewitt 内核(Sobel 用于 OpenCV ),以检测边缘是水平的、垂直的还是对角线的。

Sobel kernel for calculation of the first derivative of horizontal and vertical directions

C .非最大抑制

非最大抑制应用于“薄”和有效锐化边缘。对于每个像素,检查该值是否是先前计算的梯度方向上的局部最大值。

Non-maximum suppression on three points

a 在垂直方向的边上。由于梯度垂直于边缘方向,B 和 C 的像素值与 A 的像素值进行比较,以确定 A 是否是局部最大值。如果 A 是局部最大值,则测试下一点的非最大抑制。否则,A 的像素值被设置为零,并且 A 被抑制。

D .滞后阈值

在非最大值抑制之后,强像素被确认为在最终的边缘图中。但是,应该进一步分析弱像素,以确定它是构成边缘还是噪声。应用两个预定义的 minVal 和 maxVal 阈值,我们设置任何强度梯度高于 maxVal 的像素是边缘,任何强度梯度低于 minVal 的像素不是边缘并被丢弃。如果像素连接到强度梯度高于 maxVal 的像素,则强度梯度在 minVal 和 maxVal 之间的像素仅被视为边缘。

Hysteresis thresholding example on two lines

边 A 高于 maxVal,因此被视为边。边 B 位于 maxVal 和 minVal 之间,但不连接到 maxVal 之上的任何边,因此被丢弃。边 C 位于 maxVal 和 minVal 之间,并连接到边 A,即 maxVal 之上的边,因此被视为边。

对于我们的流水线,我们的帧首先被灰度化,因为我们只需要亮度通道来检测边缘,并且应用 5×5 高斯模糊来降低噪声以减少伪边缘。

4。分割车道区域

我们将手工制作一个三角形遮罩来分割车道区域,并丢弃帧中不相关的区域,以增加我们后期的有效性。

The triangular mask will be defined by three coordinates, indicated by the green circles.

5。霍夫变换

在笛卡尔坐标系中,我们可以通过绘制 y 对 x 将直线表示为y = mx + b,然而,我们也可以通过绘制 b 对 m 将该直线表示为霍夫空间中的单个点,例如,具有方程y = 2x + 1的直线可以在霍夫空间中表示为(2, 1)

现在,如果我们要在笛卡尔坐标系中画一个点,而不是一条线。有许多可能的线可以通过该点,每条线具有不同的参数 m 和 b 值。例如,点(2,12)可以通过y = 2x + 8y = 3x + 6y = 4x + 4y = 5x + 2y = 6x等等。这些可能的直线可以在霍夫空间中绘制为(2, 8)(3, 6)(4, 4)(5, 2)(6, 0)。注意,这在霍夫空间中产生了一条 m 对 b 坐标的线。

每当我们看到笛卡尔坐标系中的一系列点,并且知道这些点由一些线连接,我们就可以通过首先将笛卡尔坐标系中的每个点绘制到霍夫空间中的相应线,然后找到霍夫空间中的交点,来找到该线的方程。霍夫空间中的交点表示始终通过系列中所有点的 m 和 b 值。

由于我们通过 Canny 检测器的帧可以简单地解释为表示图像空间中边缘的一系列白点,因此我们可以应用相同的技术来识别这些点中的哪些点与同一条线相连,如果它们相连,其方程是什么,以便我们可以在我们的帧上绘制这条线。

为了解释的简单,我们使用笛卡尔坐标来对应霍夫空间。然而,这种方法有一个数学缺陷:当直线是垂直的时,梯度是无穷大,不能用霍夫空间表示。为了解决这个问题,我们将使用极坐标来代替。过程还是一样的,只是除了在霍夫空间中绘制 m 对 b,我们将绘制 r 对θ。

例如,对于极坐标系统上带有x = 8y = 6x = 4y = 9x = 12y = 3的点,我们可以绘制出相应的霍夫空间。

我们看到霍夫空间中的线相交于θ = 0.925r = 9.6。由于极坐标系统中的一条线由r = xcosθ + ysinθ给出,我们可以推导出穿过所有这些点的单条线被定义为9.6 = xcos0.925 + ysin0.925

通常,在霍夫空间中相交的曲线越多,意味着由该交点表示的线对应的点越多。对于我们的实现,我们将在霍夫空间中定义最小阈值数量的交叉点来检测直线。因此,霍夫变换基本上跟踪帧中每个点的霍夫空间交点。如果交叉点的数量超过定义的阈值,我们用相应的θ和 r 参数识别一条线。

我们应用霍夫变换来识别两条直线,这两条直线将是我们的左右车道边界

6。可视化

车道被可视化为两个浅绿色的线性拟合多项式,它们将覆盖在我们的输入帧上。

现在,打开终端并运行python detector.py来测试您的简单车道检测器!如果您错过了任何代码,这里是完整的解决方案和注释:

方法 2:空间 CNN

方法 1 中的这种手工制作的传统方法似乎还不错……至少在笔直的道路上是这样。然而,很明显,这种方法在弯道或急转弯时会立即失效。此外,我们注意到车道上由直线组成的标记的存在,如彩色箭头标志,可能会不时干扰车道检测器,从演示渲染中的小故障可以明显看出。克服这个问题的一种方法是将三角形遮罩进一步细化为两个独立的、更精确的遮罩。然而,这些相当任意的掩模参数根本不能适应各种变化的道路环境。另一个缺点是,由于没有满足霍夫变换阈值的连续直线,车道检测器也会忽略具有虚线标记或根本没有清晰标记的车道。最后,影响线路可见度的天气和照明条件也可能是一个问题。

1。架构

虽然卷积神经网络(CNN)已被证明是有效的架构,既可以识别图像低层的简单特征(例如边缘、颜色梯度),也可以识别更深层次的复杂特征和实体(例如对象识别),但它们通常难以表示这些特征和实体的“姿态”——也就是说,CNN 在从原始像素中提取语义方面很棒,但在捕捉帧中像素的空间关系(例如旋转和平移关系)方面表现不佳。然而,这些空间关系对于车道检测的任务是重要的,其中存在强的形状先验但弱的外观一致性。

例如,仅通过提取语义特征很难确定交通杆,因为它们缺乏明显和连贯的外观线索,并且经常被遮挡。

The car to the right of the top left image and the motorbike to the right of the bottom left image occlude the right lane markings and negatively affect CNN results

然而,由于我们知道交通杆通常表现出类似的空间关系,例如垂直竖立,并放置在道路的左侧和右侧,我们看到了加强空间信息的重要性。类似的情况也适用于车道检测。

为了解决这个问题, Spatial CNN (SCNN)提出了一种架构,“将传统的深度逐层卷积推广到特征地图内的逐层卷积”。这是什么意思?在传统的逐层 CNN 中,每个卷积层接收来自其前一层的输入,应用卷积和非线性激活,并将输出发送到后续层。SCNN 更进一步,将单个特征图的行和列视为“层”,顺序应用相同的过程(其中顺序是指一个切片仅在接收到来自前面切片的信息后才将信息传递给后面的切片),允许同一层内神经元之间的像素信息的消息传递,有效地增加了对空间信息的重视。

SCNN 相对较新,今年(2018 年)早些时候才发布,但已经超过了 ReNet (RNN)、 MRFNet (MRF+CNN)、更深层次的 ResNet 架构,并以 96.53%的准确率在 TuSimple 基准车道检测挑战中排名第一。

此外,在发表《SCNN》的同时,作者还发布了 CULane 数据集,这是一个大规模数据集,带有带立方刺的车道标注。CULane 数据集还包含许多具有挑战性的场景,包括遮挡和变化的光照条件。

2。型号

车道检测需要精确的逐像素识别和车道曲线预测。SCNN 的作者没有直接训练车道线并在之后进行聚类,而是将蓝色、绿色、红色和黄色车道线作为四个独立的类别。该模型输出每条曲线的概率图(prob map ),类似于语义分割任务,然后通过一个小型网络传递该概率图,以预测最终的立方刺。该模型基于 DeepLab-LargeFOV 模型变体。

对于每个存在值超过 0.5 的车道标志,以 20 个行间隔搜索相应的 probmap,以找到具有最高响应的位置。为了确定是否检测到车道标线,计算地面真实值(正确标签)和预测值之间的交集/并集 (IoU),其中高于设定阈值的 IoU 被评估为真阳性(TP)以计算精度和召回率。

3。测试和培训

你可以跟随这个库来重现 SCNN 论文中的结果,或者用 CULane 数据集测试你自己的模型。

**就这样!**🎉希望本教程向您展示了如何使用传统方法构建一个简单的车道检测器,其中涉及许多手工制作的功能和微调,并向您介绍了一种替代方法,这种方法遵循了解决几乎任何类型的计算机视觉问题的最新趋势:您可以添加一个卷积神经网络!

*亡国?*🙂

教程:R 中的数据争论和映射

原文:https://towardsdatascience.com/tutorial-data-wrangling-and-mapping-in-r-ec828acc8073?source=collection_archive---------2-----------------------

揭露了推动布鲁克林中产阶级化的房东

我想我以前说过…但是我喜欢地图。几乎每个人都在使用它们,这使得地图成为一种惊人的即时交流大量数据的方式,而不用担心淹没你的观众。

我最喜欢的处理空间数据的工具之一是 r。除了非常适合处理数据之外,其广泛的用户基础意味着有许多软件包可以使定制地图制作变得超级快速和简单。

本教程旨在提供一个使用 R 操作和映射数据的粗略的端到端示例。目标是创建一幅地图,展示纽约布鲁克林区住宅建筑所有权的集中情况。

除了最近发布的制图包之外,我们还将使用来自纽约市 OpenData 门户网站的一些数据集。

要完成本教程,您需要以下工具:

  • R
  • R Studio 或任何其他 IDE

设置环境和下载数据

1)克隆 GitHub 库

[git clone https://github.com/spnichol/mapping_tutorial.git](https://github.com/spnichol/mapping_tutorial.git)
cd mapping_tutorial

2)创建一个新的 R 脚本并设置你的工作目录

setwd("/home/you/mapping_tutorial")

3)安装软件包并加载前两个数据集

install.packages(c("cartography", "rgdal", "sp"))

#ownership registrations 
owners <- read.csv("data/owners.csv")

#building data 
bldgs <- read.csv("data/bldg.csv")

第一个文件是多处住所登记,一个有三个或更多单元的住宅建筑的登记。第二个是注册联系人,包含以前文件中与建筑物所有者相关的信息。

探索数据

我们这个项目的目标是了解布鲁克林建筑所有权的集中情况。因此,一个自然的起点是所有权文件。

让我们看几个记录来了解一下我们的情况。

head(owners)

您的输出应该如下所示:

看起来我们有两个 ID 变量: RegistrationContactIDRegistrationID 。第一个是指该行中列出的个人/公司,而第二个是指该个人/实体进行的特定建筑登记。

我们还有 CorporationName 栏,可以提供一些关于谁拥有什么的信息。让我们对 RegistrationContactIDCorporationName 使用aggregate函数。

owner_count <- aggregate(RegistrationID ~ RegistrationContactID, data=owners, FUN=length)
names(owner_count) <- c("RegistrationContactID", "Building_Count")
head(owner_count)
nrow(owner_count[owner_count$Building_Count > 2 ,])

您的输出应该如下所示:

现在,我们有了一个列,其中包含每个唯一的 RegistrationContactID 以及与之对应的建筑数量。除了一些看起来很奇怪的 id(只是杂乱的数据),有点奇怪的是,我们只有 274 个拥有两栋以上建筑的业主。让我们试试公司名称

owner_count <- aggregate(org_agg <- aggregate(RegistrationID ~ CorporationName, data=owners, FUN=length)
names(org_agg) <- c("CorporationName", "Building_Count")
head(org_agg)
nrow(org_agg[org_agg$Building_Count > 2 ,])

输出:

呀。建筑数量要好得多,但这些是一些令人讨厌的错别字。让我们通过删除所有非字母数字字符,然后设置子集以仅保留非空行来修复它们。

org_agg$CorporationName<- gsub("[^[:alnum:][:blank:]]", "", org_agg$CorporationName)
org_agg <- org_agg[org_agg$CorporationName !="" ,]
head(org_agg)
nrow(org_agg[org_agg$Building_Count > 2 ,])

输出:

嗯嗯。公司名称看起来好一点,但我仍然不相信拥有两栋以上建筑的业主数量。这个数据集包括整个纽约市。这个城市有很多建筑,有很多房东。会不会是同一个房东或者管理公司用不同的名字/id 登记了不同的楼栋?

如果我们看看他们的邮寄地址呢?让我们假设一个用不同名字注册的房东仍然想只在一个办公室接收他/她的邮件。我们可以通过合并 BusinessHouseNumber 和 BusinessStreetName 列来创建一个新变量,并再次运行我们的聚合。

owners$RealID <- paste(owners$BusinessHouseNumber, owners$BusinessStreetName, sep=" ")
real_agg <- aggregate(RegistrationID ~ RealID, data=owners, FUN=length)
names(real_agg) <- c("RealID", "Building_Count")
nrow(real_agg[real_agg$Building_Count > 2 ,])

是的——这更有道理。我们不能 100%确定其中的一些实际上不是共享同一个邮件地址的不同房东,但是我认为我们可以假设这不是本教程的情况。

然而,有一个问题。如果您还没有注意到,许多注册 id包括多个联系人,每个联系人的类型的值都不同。在我们开始过滤它们之前,让我们先了解一下值的范围。

summary(owners$Type)

这是我们得到的结果:

现在我们可以对数据帧进行子集化,只保留与所有者相关的角色类型。但这可能会导致一些问题,因为所有者不需要成为这类注册的“联系人”。

相反,让我们删除重复的 RegistrationID 并重新运行我们的aggregate函数。

owners <- owners[! duplicated(owners$RegistrationID) ,]
real_agg <- aggregate(RegistrationID ~ RealID, data=owners, FUN=length)
names(real_agg) <- c("RealID", "Building_Count")
nrow(real_agg[real_agg$Building_Count > 2 ,])

看起来,在删除重复的注册 id 后,我们有大约 5000 名拥有两栋以上建筑物的业主。

在我们进入教程的下一步之前,让我们将 Building_Count 列与主 owners 数据帧结合起来。我们可以用一个简单的merge来做这件事。

owners <- merge(x=owners, y=real_agg, by="RealID")

组合数据帧

既然我们有了如何定义建筑物所有权的策略,我们需要将最近更新的所有者数据框架与建筑物数据集合并。这将为我们提供教程的制图部分所需的 GIS 信息。

1)探索建筑数据框架的变量

head(bldgs)

我的输出如下所示:

很好,看起来两个数据集共享了注册 ID 变量。这意味着该数据帧中的每个条目对应于所有者数据帧中的一个注册 ID。我们可以使用这个列作为merge函数的 ID。

2)注册 ID 合并

bldg_counts<- merge(x=bldgs, y=owners, by="RegistrationID")

合并成功了,但是我们丢失了几行。令人恼火的是,事实证明某些类型的属性被允许使用相同的注册 ID,即使它们有不同的地址。这在数据文档中有更详细的解释。

探索空间变量

现在是有趣的事情。我们需要弄清楚我们可以使用什么样的 GIS 变量来汇总和绘制这些信息。让我们再来看看我们最近合并的数据框架。

bldg_counts<- merge(x=bldgs, y=owners, by="RegistrationID")

输出:

看起来我们有两个地理变量的选择。第一个是建筑物地址,可以通过组合门牌号街道名称列得到。然而,为了绘制这些信息,我们必须首先对地址进行地理编码。工作太多。

我们还有批次变量。纽约市的街区编号是唯一的,这意味着我们可以汇总每个街区的建筑数量,因为房东拥有不止一栋建筑。该城市还提供带有块级多边形的形状文件,允许我们绘制数据。然而,布鲁克林有成千上万个街区,每个街区只有少数几栋建筑,所以这可能不会太有意义。

事实上,这些变量中没有一个能提供我们真正需要的。相反,我们来介绍一个新的数据集:冥王星。冥王星数据集是纽约市建筑统计的圣杯,包括从纬度和经度到财产价值的一切。

1)读入 PLUTO CSV 文件并探索变量

pluto_bk <- read.csv("data/pluto.csv")
names(pluto_bk)

输出:

明白我的意思了吗?让我们只保留相关的列。

2)删除不必要的列

pluto_bk <- pluto_bk[, c(4, 5, 6, 58,71, 73, 74, 75)]

我们只剩下以下几列:

现在我们有很多选择。我选择使用 Census tract,由 CT2010 和 Tract2010 变量以不同的形式表示。这似乎是一个很好的汇总水平,因为布鲁克林大约有 750 个人口普查区。此外,人口普查局提供区域级形状文件,使绘制地图变得轻而易举。

我们需要将这些信息与我们之前创建的建筑列表合并。不幸的是,PLUTO 没有我们之前使用的 RegistrationID 变量。相反,他们使用更常见的 BBL,代表“自治市、街区、地段”

我们的建筑物数据没有 BBL 变量,但是我们可以通过组合区、建筑物和地段列来创建一个变量。然而,首先,我们将使用sprintf函数填充我们的变量。

填充向小于特定位数的值添加额外的零。这使得我们最终的 BBL 长度为十位数,而不管组成它的组件的值。

我们还将借此机会对我们的建筑数据框架进行子集划分,仅包括布鲁克林的房产。我们使用3BoroID 来实现这一点。

3)在建筑物数据框中创建 BBL 变量

#subset dataframe for just Brooklyn 
bldg_counts  <- bldg_counts [bldg_counts $BoroID == 3 ,]#create new columns with padded values 
bldg_counts ["New_Block"] <- lapply(bldg_counts ["Block"], function(x) sprintf("%05d", x))
bldg_counts ["New_Lot"] <- lapply(bldg_counts ["Lot"], function(x) sprintf("%04d", x))#use paste function to combine everything into one variable 
bldg_counts ["BBL"] <- as.numeric(paste(bldg_counts $BoroID, bldg_counts $New_Block, bldg_counts $New_Lot, sep=""))

我觉得不错。让我们继续把这个数据帧和冥王星的数据合并。我们想要的只是每栋建筑的普查区域,因此我们可以相应地进行分组。

4)将区域信息与建筑物数据集合并

names(pluto_bk)
pluto_bk <- pluto_bk[, c(5, 2)]
nrow(bldg_counts)bldg_counts <- merge(x=bldg_counts, y=pluto_bk1, by="BBL")
nrow(bldg_counts)

我们丢失了几百行数据,不管是什么原因,它们都不在 PLUTO 数据集中。

关于 BBL s 的一个重要旁注:这个值实际上不是唯一的标识符——一些地段有不止一个建筑。这没什么大不了的,因为我们需要从冥王星数据帧中提取的只是人口普查区域,这对于位于同一地块上的建筑来说是一样的。

如果我们想要更精确,我们可以通过结合 BBL 和每栋建筑的街道号来创建一个唯一的 ID 变量。

5)按普查地区汇总

#aggregate by census tract 
multiple <- bldg_counts[bldg_counts$Building_Count > 2 ,]
tract_counts <- aggregate(Building_Count ~ CT2010, data=multiple, FUN=length )
names(tract_counts)[1] <- "CTLabel"
nrow(tract_counts)
length(unique(pluto_bk$CT2010))

首先映入我眼帘的是,我们丢失了一些人口普查地图。解释很简单。虽然该区总共有 761 块土地,但其中一些要么 1)非常小,要么 2)几乎全部是平房,不需要在该市登记。由于这些地块没有“多层建筑”房东,它们不会出现在汇总列表中。

好吧。我们有每个普查区域的数据框架和“多层建筑”业主拥有的房产数量。数量少得惊人,但话说回来,人口普查区实际上并没有那么大。我们来绘制地图吧!

绘图

R 中任何映射项目的第一步都是读入我们的 shapefile。我们将在本教程中使用的 shapefile 来自纽约市规划局。虽然人口普查局通常是 shapefiles 的首选资源,但纽约市规划部的版本已经裁剪了水域,因此更加简洁。

1)加载形状文件

bk_shape <- readOGR(dsn = "shapefiles", layer = "nyct2010")
head(bk_shape@data)

我们可以看到这个 shapefile 实际上有 2166 个不同的人口普查区域,因为它包括了所有的行政区。我们还可以看到,它有数据绑定到多边形,使其成为一个空间多边形数据帧(SPDF)。除了关于面本身的信息之外,该数据还包括人口普查区域标签。我们希望将数据绑定到 SPDF,但首先我们需要解决一些问题。

子集 SPDF
给 R 中的 SPDF 设置子集简单得荒谬。你可以像一个普通的数据帧那样做。

#remember "3" is the BoroCode for Brooklyn 
bk_shape <- bk_shape[bk_shape@data$BoroCode == "3" ,]
head(bk_shape@data)

3)将我们的数据与 SPDF 合并

在 R 中向多边形添加数据也很容易。在这种情况下,我们只需要确保 ID 变量有相同的名称,就可以了。

bk_shape <- merge(bk_shape, tract_counts, by="CTLabel")

好了,您可以看到,我们现在已经将数据绑定到了 SPDF,并准备好开始绘制地图。

4)绘制底图
这就是制图包的用武之地。为了开始绘制我们的地图,我们需要首先绘制地图的“范围”(即它将占据的空间区域),然后是陆地。

plot(bk_shape, border = NA, col = NA, bg = "#A6CAE0")
plot(bk_shape, col  = "#E3DEBF", border=NA, add=TRUE)

它应该是这样的:

5)添加边界线
现在我们要添加第三层,这将是人口普查区域的边界。

plot(bk_shape, col = "grey60",border = "white", lwd=0.4, add=TRUE)

现在你应该有这个:

6)选择调色板
制图包中有很多漂亮的预制调色板。我选择了简单的绿色,但你可以在第 4 页的这里看看其他的。我也选择使用 8 种不同的颜色,尽管这总是取决于你所使用的数据的分布。

cols <- carto.pal(pal1 = "green.pal" ,n1 = 8)

7)添加 choropleth 层
这个包有很多不同的显示数据的特性,但是我们将坚持使用一个简单的 choropleth 地图。

choroLayer(spdf = bk_shape, 
           df = bk_shape@data, 
           var = "Building_Count", 
           breaks = c(0, 10, 30, 50, 70, 90, 110, 150), 
           col = cols, 
           border = "grey40", 
           lwd = 0.5, 
           legend.pos = "left",
           legend.title.txt = "Number of Buildings", 
           legend.values.rnd = 10,
           add = TRUE)

嘣。事实证明这很好,因为这非常符合我多年来与布鲁克林房东打交道的经验。深绿色区域也与经历了最大中产阶级化的区域非常接近。

我为布鲁克林公共图书馆制作的许多地图看起来非常相似,尤其是在观察中产阶级化前后收入和租金的变化时。

添加布局层
我们可以通过创建一个布局层来给地图添加一点元数据。

layoutLayer(title = "Census Tracts by Building Ownership Concentration", 
            author = "Pres Nichols",  
            sources = "Source: NYC OpenData", 
            scale = NULL, 
            col = NA, 
            coltitle = "black", 
            frame = FALSE,  
            bg = NA)

结论

有一个重要的方面我没有考虑到:如果地图上的北部地区,拥有更集中的所有权,只是总共有更多的建筑呢?

如果你正在学习这篇教程,我会让你自己去发现并报告你的发现!

注意:那些不熟悉布鲁克林地理的人可能会对地图上的白色区域有点担心。看起来比实际情况更糟。这是因为最大的白色区域(展望公园、格林伍德公墓和洛克威)实际上没有人居住。如果他们仍然困扰你,你可以随时给无人居住的地区一个不同的颜色。

如何匹配《突围》中 DeepMind 的深度 Q-Learning 评分

原文:https://towardsdatascience.com/tutorial-double-deep-q-learning-with-dueling-network-architectures-4c1b3fb7f756?source=collection_archive---------0-----------------------

如果你和我一样对深度 Q 学习着迷,但从来没有时间去理解或实现它,这是给你的:在一个 Jupyter 笔记本中,我将 1)简要解释强化学习与监督学习的不同,2)讨论深度 Q 网络(DQN)背后的理论,告诉你在哪里可以找到论文中相应的解释及其含义,以及 3)如何在 python 和 tensorflow 中实现使其工作所需的组件。

2013 年,一家名为 DeepMind 的伦敦初创公司发表了一篇名为的开创性论文,在 arXiv 上用深度强化学习玩雅达利:作者提出了一种名为 Deep Q-Learning 的强化学习变体,它能够成功学习不同雅达利 2600 游戏的控制策略,只接收屏幕像素作为输入,并在游戏分数变化时获得奖励。在某些游戏中,代理甚至超越了人类专家玩家!这是一个惊人的结果,因为以前的“人工智能”通常局限于一个单一的游戏,例如国际象棋,而在这种情况下,在街机学习环境中的游戏的类型和内容变化很大,但不需要调整体系结构、学习算法或超参数。

难怪 DeepMind 被谷歌以 5 亿美元收购。该公司自此成为推进深度学习研究的领先机构之一,后来讨论 DQN 的文章发表在 Nature 上。

现在,五年后,甚至有了更先进的强化学习算法,但在我看来,深度 Q 学习仍然是一种非常令人印象深刻的方法,非常值得研究(更重要的是开始工作)。

我第一次观看 DeepMind 的视频时,我正在攻读理论天体物理学博士学位的第一年,视频显示一名 DQN 代理人正在学习玩游戏 Breakout,并发现它可以在墙后反弹,从而允许球击中砖块。我很快就被迷住了,并向自己承诺,一旦我有时间,我会努力重现这个结果。

现在,两年后,我实现了 DQN,学到了很多关于神经网络和强化学习的知识,因此决定写一个有希望的全面教程,介绍如何让它为像我一样着迷于深度学习的其他人工作。

深度 Q 学习需要几个组件来工作,如代理可以探索和学习的环境,Atari 游戏帧的预处理,两个卷积神经网络,探索-开发困境(e-greedy)的答案,更新神经网络参数的规则,错误剪辑和称为重放存储器的缓冲区,过去的游戏转换存储在该缓冲区中,并在学习时从中提取。

我详细描述了各个组件,紧接着是它们的实现。如果您想了解更多信息,请继续阅读笔记本:

[## fg91/深度 Q 学习

Deep-Q-Learning - Tensorflow 用决斗网络实现 Deepmind 的双重深度 Q-Learning

github.com](https://github.com/fg91/Deep-Q-Learning/blob/master/DQN.ipynb)

在这里,我现在将描述我使用笔记本进行的实验,更重要的是我在进行这些实验时发现的小细节,这些小细节被证明对 DQN 的良好工作至关重要:几个线程讨论了与 DeepMind 报告的分数匹配的问题(见这里、这里这里和这里),我最初也在与类似的问题进行斗争。

让我们开始吧:乓

我用环境 Pong 开始了我的实验,因为对于一个 DQN 代理来说,学习起来相对容易和快速,因为它很简单:代理控制一个可以上下移动的球拍,目标是以一种对手无法触及的方式击球。一旦一名玩家得分达到 21 分,游戏就结束了。

After 30 minutes of training

笔记本中的实现在每个时期后创建一个 gif,这允许您观察代理学习。我个人从不厌倦看网络的进步,想到人类仅仅通过看着它们就知道如何让机器学会玩这些游戏,我感到惊讶。

在训练开始时,DQN 代理只执行随机动作,因此得到大约-20 的奖励(这意味着它无望地输了)。经过 30 到 45 分钟的训练,代理人已经学会了击球,并能够获得第一个分数。

实线示出了训练奖励(在过去 100 集内平均的训练集分数),虚线示出了评估分数(在 10,000 帧贪婪游戏之后的平均集分数)。一个时期相当于 50,000 次参数更新或 200,000 帧。

Training and evaluation reward for the environment Pong

DQN winning like a boss

评价分数很快达到最大值+21。由于在训练期间使用退火ε的 e-greedy 策略,训练分数保持较低。在左边的 gif 中,所有的分数都以几乎完全相同的方式计分,这意味着代理发现了一个几乎理想的策略。我很想看到两个 DQN 特工学会对战,但目前,OpenAi 的健身房不支持多人 Pong。

下一个:突破

让我们来看看 Breakout ,视频中显示的环境最初让我在看到代理人在屏幕旁边挖了一个隧道,让球通过在墙后反弹击中砖块后,想自己实现 DQN。

在《自然》杂志论文 Mnih 等人 2015 中,DeepMind 报告了《突围》的评估分数为 317。我连夜在笔记本上运行,希望得到类似的结果。在 Pong 取得初步成功后,第二天早上我兴奋地醒来检查代理的改进,却发现奖励在 35 左右达到了一个平台期,没有任何进一步的改进。这里报道了关于 DQN 和突围的同样问题(没有给出问题的最终答案): DQN 解决方案的结果在大约 35 奖励时达到峰值。

在线课程的问题(这是我非常喜欢的,不要误会我的意思)是,一切都倾向于立即工作,只有当事情没有按计划进行,你需要找出原因时,事情才会变得真正令人兴奋(当然有时也会令人沮丧)。

Breakout, first try

通过降低学习率,我得到的奖励达到了 50 左右,但仍然只有 DeepMind 报告的 15%左右。

在接下来的几个星期里,我继续有时对代码进行改进,通宵或更长时间地进行实验,并逐渐达到接近 300 的训练分数和大约 400 的最高评估分数。

Breakout, first vs last try

王等 2016 报道突围得分 418.5(双人)和 345.3(决斗)分(表 2)。我在我的实验过程中看到的最好的评估集的分数是 421(如本文开头所示)。如果您想亲自尝试,可以克隆存储库并运行笔记本。网络的各个参数都包括在内,因为我使用确定性环境(BreakoutDeterministic-v4)训练了 Breakout,所以您应该会得到相同的分数。

实现这一改进需要哪些调整?

  1. 使用正确的初始化器!DQN 使用 Relu 激活函数,右初始值为 何等 2015 方程 10 ( 点击此处详解)。在 tensorflow 中使用tf.variance_scaling_initializerscale = 2
  2. 确保您正在以正确的频率更新目标网络:论文称,目标网络更新频率以参数更新的数量来衡量(每四帧发生一次,参见 Mnih et al. 2015 中的扩展数据表 1),而在 DeepMind 代码中,它以代理看到的动作选择/帧的数量来衡量。我们来看看 DeepMind 的代码:这里你可以看到默认情况下update_freq=4target_q=10000(第 14 行和第 31 行)。此处可以看到,默认情况下,参数更新每 4 步发生一次(self.numSteps%self.update_freq==0),而此处目标网络每 10.000 步更新一次(self.numSteps%self.target_q==1)——因此,目标网络更新频率是在numSteps中测量的,而不是在参数更新中测量的。
  3. 确保您的代理实际上正在尝试学习与 DeepMind 论文中相同的任务!
    我发现,当一个生命丢失时,将终端状态传递给重放记忆(如 DeepMind 所做的)会产生巨大的差异。这是有道理的,因为失去一条生命没有负面的回报,否则代理人不会“注意到失去一条生命是不好的”。
    DeepMind 在 Breakout 中使用了四个动作的最小集合( xitari ),OpenAi gym 的 Breakout 的几个版本有六个动作。额外的动作可以彻底改变代理试图学习的任务的难度! Breakout-v4Breakout deterministic-v4环境有四个动作(与env.unwrapped.get_action_meanings()核对)。
  4. 使用 Huber 损失函数( Mnih et al. 2013 称之为误差削波)来避免爆炸梯度。如果超过某个阈值,渐变会被修剪到该阈值。注意,与二次损失函数相比,下图中绿色曲线的导数对于 x > 1(或 x<1)没有增加(或减少)。

Error clipping to avoid exploding gradients

随意玩笔记本。如果你投资 GPU 时间来优化超参数以获得更好的性能,或者如果你尝试在其他游戏中使用它,请在评论中给我写信,我会很高兴知道。

如果你想自己训练网络,在笔记本的第一个单元格中设置TRAINTrue

考虑让你的电脑可以远程访问,我在这篇博文中描述了这一点:远程访问你的深度学习站,并设置局域网唤醒。您可以使用jupyter-nbconvert --to script DQN.ipynb将笔记本转换为 python 脚本,然后在我在这里描述的 tmux 会话中运行它:tmux 中的 jupyter 和 tensor board。这样做的好处是,您可以从 tmux 会话中分离并远程重新连接到它,以便检查代理的进度或对代码进行更改,无论您在哪里。

Summaries in tensorboard

如果你想使用 tensorboard 来监控网络的改进,在激活相应虚拟环境的终端中输入tensorboard --logdir=summaries。打开浏览器,进入 http://localhost:6006 。这也可以远程操作。

我发现 DQN 开始工作很费劲。有许多小细节要做好,否则效果不好。除此之外,实验经常不得不通宵运行(至少),这意味着如果只有一个 GPU,调试和改进会很慢。

尽管如此,在我看来这是值得的,因为我学到了很多关于神经网络和强化学习的知识,特别是通过调试和改进。看看下面的 gif:在某一点上,代理开始直接瞄准两侧挖隧道,并从上面撞上石块——这正是两年前 DeepMind 的视频中引起我注意的东西,也是我想要复制的东西。

Observe how the agent starts to dig a tunnel at the side 😃

因此,我鼓励你尝试自己从头实现 DQN,必要时看看我的代码进行比较,找出我是如何实现不同组件的。当你需要澄清或提示时,请随时给我留言,我很乐意帮忙。

玩得开心:)

法比奥(男名)

教程:泰国的 ggplot2 热图和交通死亡

原文:https://towardsdatascience.com/tutorial-ggplot2-heatmaps-and-traffic-deaths-in-thailand-d5134908d77e?source=collection_archive---------10-----------------------

Photo by Dan Freeman on Unsplash

在本教程中,我们将根据每 100,000 名居民的交通死亡人数,绘制一张驾车最危险国家的热图。我们将使用 R 和 ggplot2 来可视化我们的结果。

在泰国开车真的有那么危险吗?

人们常说在泰国开车很危险。任何坐在狭窄的ตุ๊กตุ๊ก后座上的人都会明白我在说什么。交通执法的缺失以及出租车和小型货车司机的疯狂驾驶肯定无助于改善泰国作为一个道路危险国家的形象。但是我们来看看数据是否支持这种印象。

为了进行调查,我们将使用来自世卫组织和欧睿信息咨询公司的数据。如上所述,他们跟踪了 1985 年至 2008 年每 100,000 名居民的道路死亡人数,但对于许多国家来说,某些年份的数据缺失。为了保住泰国,我不得不牺牲,增加了很多缺失的价值观。

顺便说一下,我强烈推荐 Gapminder 组织的创始人写的《T2 真相》一书。不管是谁,让我们言归正传。

清理并读入数据

你可以在下面看到很多数据丢失了。

library(tidyverse)
library(RColorBrewer)
df **<-** readxl**::**read_xlsx('cars.xlsx')
colnames(df)[1] **<-** 'country'
head(glimpse(df))## Observations: 148
## Variables: 25
## $ country  <chr> "Albania", "Argentina", "Armenia", "Australia", "Aust...
## $ `1985.0` <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N...

## # A tibble: 6 x 25
##   country   `1985.0` `1986.0` `1987.0` `1988.0` `1989.0` `1990.0` `1991.0`
##   <chr>        <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
## 1 Albania         NA       NA       NA       NA       NA       NA       NA
## 2 Argentina       NA       NA       NA       NA       NA       NA       NA
## 3 Armenia         NA       NA       NA       NA       NA       NA       NA
## 4 Australia       NA       NA       NA       NA       NA       NA       NA
## 5 Austria         NA       NA       NA       NA       NA       NA       NA
## 6 Azerbaij~       NA       NA       NA       NA       NA       NA       NA

哪些数据缺失?

为了找出哪个国家缺少的数据最多,我们可以使用下面的命令来计算每行的 NAs。稍后当我们使用这个专栏过滤热图的结果时,这将会派上用场。如果我们愿意,我们也可以使用百分比缺失阈值。我们暂时保持简单。

df **<-** df**%>%**
  mutate(na_count **=** rowSums(**is.na**(.)))
head(cbind(df**$**country, df**$**na_count))##      [,1]         [,2]
## [1,] "Albania"    "23"
## [2,] "Argentina"  "13"
## [3,] "Armenia"    "23"
## [4,] "Australia"  "14"
## [5,] "Austria"    "14"
## [6,] "Azerbaijan" "23"

为我们的热图创建自定义调色板

让我们使用 colorRampPalette 函数为热图渐变创建 25 个级别的“橙色/红色”。为什么是二十五?我们可以从 glimpse()函数中看到,死亡人数的最高值在十万分之二十五左右。请注意,通常我们只能使用 9 种颜色的“OrRd”调色板,但是 colorRampPalette()允许我们将其扩展到任何数量。如果你做大量的可视化工作,这是一个非常有用的功能。

my_pal **<-** colorRampPalette(brewer.pal(11, "OrRd"))(25)## Warning in brewer.pal(11, "OrRd"): n too large, allowed maximum for palette OrRd is 9
## Returning the palette you asked for with that many colorsmy_pal##  [1] "#FFF7EC" "#FEF2E0" "#FEEDD4" "#FEE8C8" "#FDE1BA" "#FDDAAC" "#FDD49E"
##  [8] "#FDCB95" "#FDC38C" "#FDBB84" "#FCAB75" "#FC9C67" "#FC8D59" "#F77F53"
## [15] "#F3724D" "#EF6548" "#E7533A" "#DF412C" "#D7301F" "#CB2014" "#BF100A"
## [22] "#B30000" "#A10000" "#900000" "#7F0000"

现在我们准备绘制我们的热图

一个关键特征是,我们基本上是对包含少于 18 个 NA 值的国家进行子集划分。还要注意,我们将 scale_fill_gradientn 的颜色参数设置为我们之前创建的自定义颜色渐变。此外,我们设置 na.value='white ',以便绘图与白色背景融为一体。

如果您以前没有制作过热图,请记住,如果您使用 gather()函数将数据帧转换为长格式,效果会更好。

df**%>%**
  filter(na_count **<** 18)**%>%**
  select(1, 13**:**25)**%>%**
  gather(**-**country, key**=**'year', value**=**'deaths')**%>%**
  mutate(year **=** as.factor(**as.integer**(year)))**%>%**
  ggplot(aes(reorder(country,deaths), year, fill**=**deaths))**+**
  geom_tile()**+**
  coord_flip()**+**
  scale_fill_gradientn(colors **=** my_pal, na.value **=** 'white')**+**
  theme(plot.subtitle **=** element_text(hjust **=** 0.5), 
    plot.caption **=** element_text(vjust **=** 1), 
    axis.ticks **=** element_line(linetype **=** "blank"), 
    panel.grid.major **=** element_line(colour **=** **NA**, 
        linetype **=** "blank"), panel.grid.minor **=** element_line(linetype **=** "blank"), 
    axis.text **=** element_text(vjust **=** 0.25), 
    axis.text.x **=** element_text(size **=** 10, 
        vjust **=** 0, angle **=** 90),
    axis.text.y **=** element_text(size **=** 6),
    panel.background **=** element_rect(fill **=** **NA**),
    plot.title **=** element_text(hjust **=** 0.5))**+**
    labs(x**=**'', y**=**'', title**=**'Most Dangerous Roads', subtitle**=**'Car Deaths per 100,000',
         fill**=**'Deaths')

结果:坏的

所以看起来泰国确实是相对危险的驾车之地。1996 年,在这里列出的 58 个国家中,他们的死亡率最高。看起来驾驶在 2000 年代变得更安全了,但有很多数据缺失,所以很难确定。

有趣的是,多米尼加共和国、拉脱维亚、爱沙尼亚、立陶宛、卢森堡和冰岛(在某些年份)在司机安全方面表现不佳。美国和新西兰也做得不太好。我猜冰岛的高死亡率是由于某些年份的恶劣天气。就卢森堡而言,通过谷歌搜索,我发现它确实是欧洲人均交通死亡率最高的国家之一。那里有许多狭窄多风的道路吗?糟糕的司机?天气不好?

结果:好

从积极的一面来看,马耳他、新加坡、摩尔多瓦、智利、哥伦比亚、英国、瑞典和厄瓜多尔对司机来说似乎特别安全。

原载于 2018 年 7 月 29 日https://greenet 09 . github . io

教程:我们如何用 Stan 实现贝叶斯收入估计

原文:https://towardsdatascience.com/tutorial-how-we-productized-bayesian-revenue-estimation-with-stan-a10306437875?source=collection_archive---------6-----------------------

在线广告商正转向优化广告支出的总收入,而不仅仅是提高转化率或点击量。最大化收入是棘手的,因为单个用户带来的收入数量存在巨大的随机变化。如果没有考虑到这一点,很容易对错误的信号做出反应,并在不太成功的广告活动上浪费金钱。幸运的是, 贝叶斯推理 通过对观察到的数据中的变化进行建模,让我们能够在粒度级别上做出合理的决策。

概率编程语言,像 Stan ,让贝叶斯推理变得简单。Stan 提供了一种灵活的方式来定义模型和进行推理,并且它有很棒的诊断工具,如 ShinyStan 。概率编程语言对于贝叶斯建模与 TensorFlow 或 Keras 对于深度学习是一样的。由于框架的发展,近年来深度学习已经被广泛采用。贝叶斯建模现在也是如此。

目前,Stan 主要用于对静态数据收集进行描述性分析。在生产中运行它是可能的,但具有挑战性。在这篇博文中,我们描述了让 Stan 投入生产的经验。我们还为我们的特定用例进行了基本建模:对每次购买的收入进行建模,以比较多个广告之间的性能。我们将详细讨论如何通过在 Stan in production 中使用贝叶斯多层建模来解决这个用例。

1.用例:最大化广告支出的收入

2.如何对收入建模?

  • 模拟每次购买的收入
  • 共享信息的多级建模
  • 分析收入模式

3.Stan 的贝叶斯建模经验

4.讨论

1.用例:最大化广告支出的收入

在线广告传统上侧重于获得印象和点击。近年来,大多数广告商已经转向直接优化他们的网页或移动应用程序的转换。广告中的转换可以意味着任何事情,从在线购买到完成游戏中的一个关卡。在这种情况下,广告商希望最大化他们获得的转化量,或者换句话说,在给定的预算下,最小化每次行动的成本(CPA)。

今天,我们看到广告商的目标是最大化来自转化的总收入,而不仅仅是增加转化数(这就是我们在这篇博文中讨论的)。在未来,广告商将能够最大化单次转换的预期终身价值:客户可能会在未来再次购买更多,或者吸引他们的朋友成为新客户。

我们越深入漏斗,证明我们决策的数据就越少。例如,如果每天有 100,000 人看到您的广告,其中 1%的人会点击该广告,这将导致 1,000 次网站访问。在这些网站访问中,只有 1%导致购买。购买的这 10 个人的收入和终身价值可能会有很大差异。虽然只有很少的随机变化的数据,但你仍然需要决定明天把你的广告预算放在哪里。贝叶斯推理通过量化不确定性解决了这个问题。

在收入方面,最常见的指标是广告支出回报率(ROAS ),这意味着每笔广告支出的总收入。有趣的是,ROAS 可以分为两部分:

因此,要估计单个广告的 roa,您可以分别估计 CPA 和每转换级别的收入。类似地,CPA 可以进一步分为模拟每次花费的印象数、每次印象的点击数和每次点击的转化率。在比较广告之间的表现时,这些部分通常在行为上有很大不同(查看下面的转换漏斗)。

在 Smartly.io,我们已经为每个行动的成本部分建立了一个模型,该模型利用了这个漏斗并能够对变化做出快速反应。它被用作我们的预算分配的一部分,该预算分配基于贝叶斯多臂强盗,并根据其表现在多个广告集之间分配预算。为了改变我们的预测预算分配,以优化 roa 而不是 CPA,我们只需要插入多个广告(或脸书环境中的实际广告集,因为预算和目标受众是在该级别上定义的)的每次转换收入的平均分布的稳定估计值。

2.如何对收入建模?

模拟每次购买的收入

虽然每次转换的收入在单次购买之间会有很大的变化,但大多数变化通常是正常的随机变化,而不是由于广告集之间的差异。例如,如果你购买了 10 次,其中 9 次带来了 10 美元的收入,最后一次带来了 1000 美元,你每次转换的平均收入将接近 100 美元。如果没有那一单大额购买,平均价格将是 10 美元。如果您必须预测未来每次转换的平均收入,您会说它更接近 10 美元而不是 100 美元吗?如果你的第二个广告系列也有 10 次购买,但都带来了接近 20 美元的收入,你会把钱押在哪个广告系列上?

在大多数情况下,我们已经看到,尽管原始数据会显示出很大的差异,但广告组合带来的每次转化的平均收入并没有什么不同。要让广告系列在每次转化产生的收入方面真正有所不同,针对受众或报价的广告应该真正影响广告商的收入产生过程。例如,针对不同国家/地区的广告组合可以带来不同的每次转化收入。

好的,那么我们如何得到稳定的估计来比较广告组之间的性能呢?在这里,贝叶斯多级建模开始发挥作用。在多级建模中,你可以说广告集彼此相似,除非数据证明不是这样。让我们首先估算单个广告集的每次转化收入。

收入通常遵循一个厚尾分布。这意味着大部分收入金额很小,但也可能有一些收入金额非常大的转换。上图是一个真实的例子,展示了电子商务广告账户中所有购买的收入分配。我们通过使用对数正态分布来模拟每次转换的收入。下面,是同样的对数变换分布。它非常接近正态分布,支持对数正态方法的可行性。

因此,我们假设广告组 a 的单次转换 R_a 的收入遵循对数正态分布,位置和比例参数𝜃a和𝜎_ a 可以在广告组之间变化。

我们没有从脸书获得每一次转换的数据,这让事情变得有点复杂。取而代之的是,我们每天或每小时获得广告集的总收入和转化率。我们可以用另一个对数正态分布来近似这些观察水平收入 R _ i ,其均值和方差与 n_i 个独立同分布对数正态随机变量之和的均值和方差相匹配(芬顿-威尔金森近似)。设 a_i 为观察值 i 的 ad 集合。然后

有趣的是,对数正态分布随机变量 R_a 的均值并不直接与分布的众数和中位数 exp(𝜃_ a 相同,而是

这就是为什么在估算收入平均值时,应包括罕见但大量的收入金额。

为了简化模型,我们假设每次转换的收入 R_a 不随时间变化。CPA 模型考虑了时间序列的变化。因此,我们将前两周的所有每小时收入数据集中到一个广告集中。我们使用每小时的数据来尽可能接近交易数据。

现在给定观察到的收入 r_i 和计数 n_i 我们可以通过在 Stan 中编写模型来直接估计对数正态参数𝜃_ a 和𝜎_ a 。我们对获得这些的点估计(最大后验概率,MAP)不感兴趣,而是从后验分布中获得样本,以捕捉估计中的不确定性。

对于一个完整的模型,我们需要一些合理的位置和比例参数的先验知识。如果排除了前科,Stan 会自动使用无信息前科。下面是一个简单的 Stan 代码,它实现了对收入建模的非层次估计。

data {
  int adsets;
  int observations;
  int observation_adset[observations];
  vector[observations] observation_conversion_count; // n_i
  vector[observations] observation_conversion_revenue; // r_i
}
parameters {
  vector[adsets] adset_mu; // theta_a
  vector[adsets] adset_sigma; // sigma_a
}
model {
  vector[observations] observation_mu; // theta_i
  vector[observations] observation_sigma; // sigma_i

  observation_sigma = sqrt(log(1 + (
      exp(square(adset_sigma[observation_adset])) - 1
    ) ./ observation_conversion_count));
  observation_mu = adset_mu[observation_adset] + 
    log(observation_conversion_count) + 0.5 * (
      square(adset_sigma[observation_adset]) - 
      square(observation_sigma)
    );

  observation_conversion_revenue ~ 
    lognormal(observation_mu, observation_sigma);
}
generated quantities {
  vector[adsets] adset_mean;
  adset_mean = exp(adset_mu + 0.5 * square(adset_sigma)); 
}

Stan 的好处在于,我们的模型定义几乎是一行一行地变成了最终代码。然而,让这个模型符合 Stan 是很困难的,因为我们还没有为变量指定任何限制,或者给出合理的先验。这个模型不适合。我们稍后将回到这一点。

共享信息的多级建模

第一种方法的问题是广告集估计将仅仅基于来自单个广告集的数据。在这种情况下,如果只有几十个转换事件(这是一种常见情况),一个随机的 1000 美元的大额购买可以从根本上影响单个广告集的平均估计。由于如此大的收入事件也可能发生在其他广告组中,我们可以通过在广告组之间共享信息来获得更好的估计。

通过多级建模,我们可以实现部分池化方法来共享信息。上面的第一个模型对应于无池方法。完全池化意味着将所有广告集的数据组合在一起,并为所有广告集生成一个共享的评估。如果数据很少,多水平模型产生的结果与完全汇集的结果相似。如果有大量数据,它会产生接近无池的结果。

Examples of different levels of pooling with two ad sets.

由于对数正态分布的收入事件非常不稳定,需要大量数据来进行稳定的估计,这使得部分池化很有吸引力。使用部分池,如果广告集没有足够的数据来估计其自身的参数,则估计被吸引向共享的平均值。

在我们的模型中,我们使用简单的脸书广告层级:广告账户>活动>广告系列。也就是说,一个活动中的广告集应该比客户中其他活动中的广告集更相似。为了指定这个层次,让 c_a 成为广告组 a 所属的活动。我们假设广告设置级别参数𝜃_ a 和𝜎_ a 先前具有共享的活动级别。让我们首先关注我们分三步建模的位置参数𝜃 _a :

  1. 𝜃_ a 的活动级别正常,参数为𝜇_ c 和 t_c
  2. 活动级别位置参数𝜇_ c 的帐户级别优先
  3. 帐户级别比例𝜆的对数比例不正确的统一先验

那么位置部分的多级模型看起来像

因此,如果活动级别尺度 t_ c 小,则广告集级别均值𝜃 _a 预计接近活动级别均值𝜇_ c 。这给出了部分池。

接下来,我们应该为标度参数𝜎 _a 分配先验。这里,我们进一步简化模型,假设所有对数正态比例参数在帐户级别的广告集之间共享。这种简化对应于设置强先验。注意,由于最终模型是对数正态的,这些比例参数变成了相对差异,而不是绝对差异。因为我们主要对分布均值的差异感兴趣,所以这个假设是一个很好的起点,并解决了可能的随机大收入观察的主要问题。

我们对对数正态收入分布的主要尺度参数𝜎建模,以遵循参数为𝛼和𝛽.的逆伽马分布我们通过使用基于真实数据的参数值𝛼 = 6 和𝛽 = 4 来设置信息先验,使得𝜎的平均值大约为先验的 2/3,但是如果有足够的数据存在,允许它容易地变化。

对于一个完整的模型,我们只缺少多级模型中尺度参数 t_ c 和𝜙的超先验。为了再次简化,我们假设活动共享尺度参数 t_ c 。我们给他们两个一个单独的弱指数先验,峰值在 0,平均 1/𝛾在 0.05 左右。

所以最后,定义一个多级模型有很多步骤,尽管我们在开始的时候做了很多简化。为了改进模型,我们也可以通过使用例如加性柯西先验来对分级尺度参数建模,如在陶曼,第 6 章中所解释的。对时序效应建模将是有益的,例如,通过使用贝叶斯结构时序模型。此外,t 分布被广泛用于允许更多的变化,而不是使用正常的多级先验。

然而,最好从一个简单的模型开始,因为我们的目标是得到一些我们可以以可伸缩的方式针对不同类型的数据自动运行的东西。只有在用真实数据验证性能的基础上,才能进行改进。具有新层次结构的更新后的 Stan 模型如下所示。此外,基于对数百个帐户的分析,对参数添加了严格的限制。此外,我们使用了标准的重新参数化来加速模型,更多细节参见标准手册,26.6,分层模型和非中心参数化。

data {
  int<lower=0> adsets;
  int<lower=0> campaigns;
  int<lower=1> adset2campaign[adsets];
  int<lower=0> observations;
  int<lower=1> observation_adset[observations];
  vector<lower=1>[observations] observation_conversion_count; // n_i
  vector<lower=0>[observations] observation_conversion_revenue;//r_i
}
transformed data {
  vector[observations] log_observation_conversion_count = 
    log(observation_conversion_count);
  vector[observations] log_observation_conversion_revenue = 
    log(observation_conversion_revenue);
}
parameters {
  real<lower=-5, upper=20> account_mu; // lambda
  real<lower=0, upper=5> account_mu_sd; // phi
  vector[campaigns] campaign_mu_z;
  real<lower=0, upper=5> campaign_mu_sd; // tau
  vector[adsets] adset_mu_z;
  real<lower=0.001, upper=2.5> revenue_sigma; // sigma
}
transformed parameters {
  vector[campaigns] campaign_mu; // mu_c
  vector[adsets] adset_mu; // theta_a

  campaign_mu = account_mu + account_mu_sd * campaign_mu_z;
  adset_mu = campaign_mu[adset2campaign] + 
    campaign_mu_sd * adset_mu_z;
}
model {
  vector[observations] observation_mu; // theta_i
  vector[observations] observation_sigma; // sigma_i

  campaign_mu_z ~ normal(0, 1);
  adset_mu_z ~ normal(0, 1);

  account_mu_sd ~ exponential(1 / 0.05);
  campaign_mu_sd ~ exponential(1 / 0.05);

  revenue_sigma ~ inv_gamma(6, 4);

  observation_sigma = sqrt(log(1 + (
      exp(square(revenue_sigma)) - 1
    ) ./ observation_conversion_count));
  observation_mu = adset_mu[observation_adset] + 
    log_observation_conversion_count + 
    0.5 * (square(revenue_sigma) - square(observation_sigma));

  log_observation_conversion_revenue ~ 
    normal(observation_mu, observation_sigma);
}
generated quantities {
  vector[campaigns] campaign_mean;
  vector[adsets] adset_mean;
  campaign_mean = exp(campaign_mu + 0.5 * square(revenue_sigma));
  adset_mean = exp(adset_mu + 0.5 * square(revenue_sigma)); 
}

分析收入模式

最后,我们有一个模型,我们可以用 Stan 拟合并分析结果。我们得到每个广告集的收入分布估计。从这个输出中,我们对平均分布特别感兴趣。

通过基于拟合的模型生成新数据并将其与原始数据进行比较,检查我们的模型对数据的描述程度总是好的。这被称为后验预测检查。以下是原始广告集收入观察值(绿色)的后验预测检查结果,数据来自对数标度的模型(蓝色)。该模型似乎与数据吻合得很好。原始数据包含一个更大的峰值。举例来说,可能有一个单一的产品价格来解释这一点,但这没什么可担心的。

我们现在可以比较单个广告集的平均收入分布,以及如下所示的活动级别分布。同一活动中的广告系列共享同一颜色。在这种情况下,我们看到分布重叠了很多,单个活动中的广告集没有什么不同。有很多广告集,但每个广告集的数据很少。这些活动彼此略有不同。

一个有趣的方面是将直接从观测值计算的原始平均值与从模型计算的平均值进行比较。下图以 95%的预测间隔对所有广告集进行了分析。原始平均值在 4.6 和 5.2 之间变化,这意味着在最小和最大的广告集之间,每次转换的观察收入要大 4 倍。在拟合模型中,我们最多只能得到大约 25%的较大估计。这是由于部分汇集效应,在图中几乎所有的点都在一条水平线上。

我们对生产中的所有客户运行了类似的图,以检查模型是否合理。尽管有许多图需要手动检查,但这仍然是识别模型中问题的最简单、最快速的方法。后验预测数据应该与原始数据相匹配。如果数据很少或者确实没有任何差异,部分池应该会使结果变平。

在大多数情况下,我们观察到广告集大量集中在一起。然而,在有些情况下,广告集确实互不相同,并且不会发生池化。此外,与上面的图不同,有时活动层级不会带来额外的价值。

3.Stan 的贝叶斯建模经验

具有不同分布和参数的所有贝叶斯多级建模细节可能看起来很复杂——事实也确实如此。斯坦并没有让事情变得简单。阅读像约翰·k·克鲁施克的做贝叶斯数据分析或者盖尔曼等人的贝叶斯数据分析这样的东西来了解更多关于贝叶斯数据分析的知识是很好的。

然而,当您熟悉了编写模型之后,Stan 是一种表达性语言,它不再需要编写定制优化或采样代码来适应您的模型。它允许您轻松地修改模型和增加复杂性。对于 CPA 建模方面,我们仍然使用 Python 中的定制模型,依赖于共轭分布和近似。它运行良好,但改变它有点麻烦。将来,我们也可以用 Stan 来做这个部分。

Stan 中的模型拟合基于采样和马尔可夫链。粗略地说,该过程从参数的随机初始值开始,并且在每一步中它们都被稍微修改。如果新的参数值更符合数据,则接受它们。如果更糟,他们被接受的概率由大都会-黑斯廷斯马尔可夫链蒙特卡罗 (MCMC)方法定义。预热一段时间后,我们从后验分布中获取样本。

简单的 MCMC 可能非常慢。斯坦使用先进的技术,如不掉头采样 (NUTS)和哈密顿蒙特卡罗 (HMC)来加速采样。对于较大的数据集,这通常仍然太慢。有各种其他的近似方法可以缓解这个问题。例如,您可以只计算最大后验概率 (MAP)点估计,这非常快,但通常不适用于多级模型,并且无法捕捉不确定性。

变分贝叶斯推断是另一种近似方法,其中后验分布由变分分布近似,通常为正态分布。如果模型相当简单,就像我们的例子一样,这就很好。Stan 实现了一个自动微分变分推理 (ADVI),于 2016 年底发布。

当前的 ADVI 实施仍处于早期阶段,在生产中使用它之前,最好确保它能产生与全采样类似的结果。ADVI 在 2017 年 4 月可用于 PyStan Python 接口,现在我们正在生产中使用它。我们已经评估了 Stan 和其他概率编程语言几次,但是它们从来没有扩展到我们的用例。ADVI 使我们能够在生产中使用 Stan。

然而,使用斯坦仍然是痛苦的。如果学习发散,模型拟合很容易崩溃。在大多数情况下,这可以通过为变量添加合理的限制和信息先验,并可能为参数添加自定义初始化来解决。分层模型也需要非中心参数化。

这些是在生产中运行模型的必备条件。您希望模型适合 100%的情况,而不仅仅是 90%的情况,这在交互模式下是很好的。然而,发现模型的问题是困难的。最好是从非常简单的模型开始,一步一步地添加东西。此外,针对各种数据集运行模型并自动生成后验图有助于尽早发现问题。要进一步优化标准代码,请参考第 26 节,效率优化标准代码。

标准代码需要编译,这可能会很慢。可以通过缓存模型来避免。但是当你在开发和调试模型的时候,这真的很令人沮丧。尽管如此,它仍然是通过 PyStan 接口包装的编译后的 C++代码。界面需要更多的爱。离最常用的接口 RStan 还差得远。但是我们使用 Python ,因为它更适合产品化分析。

对于调度,我们使用芹菜,这是一个很好的分布式任务队列。我们还验证了阿兹卡班、气流和其他常见的分析调度系统,但发现标准 Python 调度程序更容易使用。

4.讨论

贝叶斯建模正在成为许多应用领域的主流。应用它仍然需要很多关于分布和建模技术的知识,但是最近概率编程语言的发展已经使它变得更容易处理。Stan 是一种很有前途的语言,非常适合单一的分析案例。随着近似方法的改进,如果在定义和验证模型时小心谨慎,它可以扩展到生产级别。此处描述的模型是我们在生产中运行的模型的基础,并有各种附加的改进。

我们计划将 Stan 与其他概率编程语言进行比较,即 PyMC3 和 Edward ,但是让 Stan 在我们的例子中工作已经足够具有挑战性了。我们希望将来能做这样的比较。幸运的是,鲍勃·卡彭特写了一篇关于同一主题的精彩的对比博文。简而言之,PyMC3 似乎提供了与 Python 最流畅的集成,但缺乏建模特性。另一方面,Edward 是建立在 TensorFlow 之上的非常低级的语言,支持最新的变分推理方法。这是一个非常前沿的技术,有很多突破性的变化,对于生产使用来说,这是一个有点冒险的选择。

我们现在每天晚上都在为数以千计的不同账户运行收入模型,这些账户包含不同数量的活动、广告设置和收入观察。最长的跑步需要几分钟。我们的大多数客户仍在使用转换优化,但正在过渡到使用收入优化功能。总的来说,我们的预测性预算拨款管理了约 100 万欧元的日常广告支出。将来,我们会看到 Stan 或其他概率编程语言在的优化特性中扮演重要角色。

第 1 部分:将 YouTube 的 Python API 用于数据科学

原文:https://towardsdatascience.com/tutorial-using-youtubes-annoying-data-api-in-python-part-1-9618beb0e7ea?source=collection_archive---------0-----------------------

搜索 YouTube 庞大目录的简单技巧

上周,我写了一篇使用谷歌语音识别 API 的快速指南,我将其描述为“有点-有点-真的令人困惑。”你猜怎么着?他们的 YouTube 数据 API 也不是非常清晰。

如果你是一个有几十年经验的编程专家,你可能现在就可以停止阅读了。然而,如果你是一个中级或自学的程序员(像我一样),这个指南应该可以帮助你快速使用 YouTube 进行数据科学研究。

出于时间和整体可读性的考虑,我决定将本教程分成多个部分。在第一部分中,除了进行简单的关键字查询之外,我们将重点关注 API 库的安装和认证。

接下来的部分将关注其他类型的任务,比如评论收集、地理查询和使用频道。

要完成本教程,您需要以下工具:

  • Python 2.7
  • 一个谷歌账户

入门指南

1)克隆 GitHub 库

git clone [https://github.com/spnichol/youtube_tutorial.git](https://github.com/spnichol/youtube_tutorial.git)
cd youtube_tutorial

2)安装 YouTube 官方 Python 客户端库

pip install --upgrade google-api-python-client

3)激活 YouTube API

**注意:**为了完成这一步,您需要创建一个“项目”。如果你不确定如何做到这一点,查看我的语音识别教程作为快速指南。

前往谷歌云控制台,点击左上角的汉堡菜单,选择“API 管理器”。

从 YouTube APIs 中选择“YouTube 数据 API”。

单击“启用”

从左侧导航面板中单击“凭据”,然后选择“创建凭据”您需要从下拉列表中选择 API 键。您应该会看到一条带有字母数字 API 密钥的消息,上面写着“API 密钥已创建”。复制并保存在一个安全的地方!

Click "Enable"

设置我们的 Python 脚本

在代码编辑器中打开 youtube_videos.py。这是 YouTube 的样本代码的大规模修改版本。

将第五行的 DEVELOPER_KEY 变量替换为我们之前创建的 API 密钥,并保存文件。

DEVELOPER_KEY = "REPLACETHISWITHYOURKEY_GOTIT?" 

酷,酷,酷。我们准备开始编写代码来进行关键字查询。继续创建一个新的 python 脚本,并将其保存在相同的目录中。

设置我们的 Python 脚本

我们希望能够使用保存 API 密钥的 youtube_search.py 文件中的函数。一种方法是将该目录附加到我们的 Python 路径中。

1)将目录追加到 Python 路径

import sys
sys.path.append("/home/your_name/youtube_tutorial/")

2)导入 **youtube_search** 功能

既然我们已经设置了路径,我们可以用一个简单的 import 语句从 youtube_videos.py 文件中引入youtube_search函数。

from youtube_videos.py import youtube_search

让我们也导入 json 库,因为它在解析 API 的 json 输出时会派上用场。

import json

太好了。我们已经准备好使用我们的 youtube_search 功能来尝试快速关键字搜索。

4)测试出 **youtube_search** 功能。

假设我们喜欢坐立不安的纺纱工(我们不喜欢),我们想看看 YouTube 上有什么关于他们的视频。

test = youtube_search("spinners")
test

您的输出应该如下所示:

我们的youtube_search的输出是一个 len = 2 的元组。第一项是一些奇怪的六字符字符串。第二项是一堆 JSON。让我们暂时忽略这个奇怪的六字符字符串,只选择 JSON。

just_json = test[1]
len(just_json)

现在你应该有这个:

现在我们可以看到我们有一个 len = 50 的 JSON 对象。每个条目都是一个 YouTube 视频,包含该视频的详细信息,如 ID、标题、发布日期、缩略图 URL、持续时间等。

假设我们想要获得一个视频的标题,我们可以很容易地用 JSON 库循环并解析它。

for video in just_json:
    print video['snippet']['title']

这给了我们:

坐立不安旋转披萨?啊?

好的,继续。现在,我们早些时候发现我们的输出由 50 个不同的视频组成。这很好,当然,关于 spinners 的视频比我想看的要多,但是,这不可能是全部,对吗?

没错。如果我们想要超过 50 个视频,这是我们在一个请求中可以得到的最大值,我们必须要求另一轮 50 个。我们可以通过使用我们前面看到的奇怪的六字符字符串来做到这一点…也称为令牌。

如果我们在下一次请求时发送令牌,YouTube 将知道它停止的位置,并向我们发送接下来的 50 个最相关的结果。让我们试试。

token = test[0]
youtube_search("spinners", token=token)

现在我们有:

太棒了。五十多个关于纺纱工的视频。另外,如果你注意到了,我们得到了另一个令牌。如果我们想继续下去,我们只需用这个令牌冲洗并重复。

显然这样做真的很糟糕。相反,我们可以编写一个函数来稍微自动化这个过程。

自动化流程

  1. 实例化一个字典来存储结果

在我们写函数之前,让我们用我们想要保存的变量名实例化一个字典。

video_dict = {'youID':[], 'title':[], 'pub_date':[]}

2)定义我们的功能

我们可以将我们的函数命名为 grab_videos ,并添加两个参数。第一个是关键字,第二个是令牌的可选参数。

def grab_videos(keyword, token=None):

3)添加 **youtube_search** 并保存我们的变量

就像之前一样,我们将使用youtube_search函数进行简单的搜索,并分别保存我们的令牌和 JSON 结果。

res = youtube_search(keyword)
token = res[0]
videos = res[1]

4)循环遍历结果,追加到字典&返回标记

for vid in videos:
  video_dict['youID'].append(vid['id']['videoId'])
  video_dict['title'].append(vid['snippet']['title'])
  video_dict['pub_date'].append(vid['snippet']['publishedAt'])
**print** "added " + str(len(videos)) + " videos to a total of " + str(len(video_dict['youID']))return token 

我还在这里添加了一个小的 print 语句,用于在每次调用该函数时更新我们收集的视频数量。

最后,我们返回令牌,这样我们可以在下次调用函数时使用它。

5)用 while 语句调用函数

既然我们已经编写了函数,我们可以编写几行简短的代码来使它工作。

首先,我们将使用我们的关键字调用函数,将结果保存到变量令牌

然后,我们可以使用 while 语句来检查函数是否返回了一个有效的令牌(即有更多的结果)或者我们是否已经遍历了所有内容。如果它看到“last_page”,就会停止代码的执行。

token = grab_videos("spinners")
**while** token != "last_page":
    token = grab_videos("spinners", token=token)

输出应该如下所示:

结论

好了,现在你至少部分准备好开始在 YouTube 上收集你自己的数据了。

如果这篇文章有帮助,请通过电子邮件或在评论区告诉我。如果没有,我会从事一些其他的爱好!请继续收看第二和第三部分。

第 2 部分:将 YouTube 的 Python API 用于数据科学

原文:https://towardsdatascience.com/tutorial-using-youtubes-python-api-for-data-science-part-2-8905f72b5b1a?source=collection_archive---------3-----------------------

执行基于位置的视频查询

在第 1 部分中,我们为 Python 设置了 YouTube API,并学习了如何对视频进行简单的关键字查询。现在,我们想更进一步。

关键字查询对于探索性分析来说是很棒的,但是它们太宽泛了,不能对我们正在研究的主题做出任何有意义的结论。相反,让我们尝试一项新技术:地理查询

地理查询

当在数据分析或数据科学中使用任何类型的社交媒体时,我们不仅关注“是什么”——识别有趣现象的存在——还关注“在哪里”——发现我们数据行为的地理差异。

例如,我们在教程的第 1 部分中看到,显然有一个现象需要研究:人们确实录制并上传了关于坐立不安者的 YouTube 视频(可悲的是)。

但是如果有一些我们没有考虑到的地理差异呢?如果美国东海岸的人比西海岸的人更热衷于坐立不安旋转者的粉丝会怎么样?

使用 YouTube API 的 location-radius 查询参数,我们可以很容易地研究这个研究问题。这是一个附加的查询,将返回与我们指定的参数相匹配的视频的纬度和经度。

然而,在我们开始之前,指出位置半径参数的一个主要缺点是很重要的:不是所有的 YouTube 视频都有位置信息。事实上,我敢说大多数人都不知道——这是一个可选功能,用户可以选择激活它。

记住这一点,让我们开始吧!

1)克隆 GitHub 库

git clone [https://github.com/spnichol/youtube_tutorial.git](https://github.com/spnichol/youtube_tutorial.git)
cd mapping_tutorial

如果您已经完成了本教程的前一部分,您可以跳过这一步,只需将新代码添加到现有文件中。

2)修改 **youtube_search** 功能

为了执行基于位置的搜索,我们需要向位于 youtube_videos.py 文件中的youtube_search函数添加一些额外的参数。这些参数是位置位置-半径

位置参数是我们半径中心的纬度和经度,作为字符串传递。例如,如果我们想要搜索位于纽约市 25 公里范围内的 spinners 的视频,那么位置参数的值将是“40.730610,-73.935242”。

位置-半径参数,正如你可能已经猜到的,是半径的大小,以英里或公里为单位(最大为 1000 公里)。在上面的例子中,传递给这个参数的值应该是“25km”。

首先,让我们将这些作为可选参数添加到youtube_search函数中。

def youtube_search(q, max_results=50, order="relevance", token=None, location=None, location_radius=None):

现在我们可以将参数添加到包含在 YouTube Python 库中的youtube.search().list()方法中。

def youtube_search(q, max_results=50, order="relevance", token=None, location=None, location_radius=None):
  search_response = youtube.search().list(
    q=q,
    type="video",
    pageToken=token,
    order = order,
    part="id,snippet",
    maxResults=max_results,
   ** location=location,
    locationRadius=location_radius**

  ).execute()

不幸的是,将这些参数添加到函数中实际上不会给我们提供位置信息。它只保证youtube_search函数返回的视频落在我们指定的半径范围内。烦人…我知道。

3)创建 **geo_query** 功能

为了得到好东西,我们需要使用另一个T4,但是这次我们将为part参数传递记录详细信息统计信息。我们还需要运行我们的build函数,让 API 知道我们是谁。

为了简单起见,让我们用一个叫做geo_query的独立函数来做这件事。

def geo_query(video_id):
    youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=DEVELOPER_KEY)

    video_response = youtube.videos().list(
        id=video_id,
        part='snippet, recordingDetails, statistics'

    ).execute()

    return video_response

要运行这个函数,我们向它传递一个视频 ID,它应该返回视频的纬度和经度,以及关于文件的其他有用的详细信息。让我们试一试。

4)测试我们的 **geo_query** 功能

继续创建一个新的 Python 文件,我们将在其中编写本教程的其余代码。

我们可以从导入我们的库开始,设置工作目录并测试我们对youtube_search函数所做的修改。

让我们执行我在上面使用的纽约市示例查询。

import sys
sys.path.append('/home/you/youtube_tutorial/')
from youtube_videos import youtube_search
import pandas as pd
import json

test = youtube_search("spinners", location="40.730610, -73.935242", location_radius="50km")

您的输出应该与之前的教程没有任何不同——一个带有 nextPageToken 的元组和我们查询的 JSON 结果。

现在我们可以真正测试我们的geo_query函数了。从上面的 JSON 结果中随机选择一个 videoId ,并将其用作函数的参数。

geo_test = geo_query('r2GYzQvfARo')

输出应该是这样的:

Seriously?

酷毙了。如你所见,我们的结果包含了大量的信息,包括纬度和经度。

我们可以从初始查询开始遍历 videoIds ,并将它们的纬度和经度存储在一个 dictionary 对象中。

location_dict = {"youID":[], "lat":[], "lon":[]}
for video in test[1]:
    location_dict['youID'].append((video['id']['videoId']))
    geo = geo_query(video['id']['videoId'])
    location_dict['lat'].append(geo['items'][0]['recordingDetails']['location']['latitude'])
    location_dict['lon'].append(geo['items'][0]['recordingDetails']['location']['longitude'])

结论

现在,您可以开始在未来的数据挖掘项目中整合位置半径功能了。

如果你想了解一个项目可能会是什么样子,看看下面的地图。互动 D3 版本可在我的网站上获得。我通过对美国 200 个最大的城市进行半径为 25 公里的“旋转”地理查询来收集这张地图的数据

每个城市的总数反映了该半径范围内上传的独特视频的数量。我对这些数字如此之小感到有点惊讶…但话说回来,我在现实生活中从未见过坐立不安的人。

感谢阅读!

Check out the interactive D3 version on my site.

教程:使用 OpenCV 的网络摄像头绘画应用程序

原文:https://towardsdatascience.com/tutorial-webcam-paint-opencv-dbe356ab5d6c?source=collection_archive---------3-----------------------

这是一个关于如何构建 OpenCV 应用程序的教程,该应用程序可以跟踪对象的移动,用户可以通过移动对象在屏幕上绘图——我称之为网络摄像头绘画。

项目描述

给定实时网络摄像头数据,这个类似 paint 的 python 应用程序使用 OpenCV 库来跟踪感兴趣的对象(在本例中是一个瓶盖),并允许用户通过移动对象来绘制,这使得绘制简单的东西既令人敬畏又具有挑战性。

您可以在此访问完整的项目代码:

[## acl21/Webcam_Paint_OpenCV

更新]:我将不再关注与回购相关的问题或邮件,因为我目前非常忙…

github.com](https://github.com/acl21/Webcam_Paint_OpenCV)

工作示例

代码要求

这个应用程序是用 Python 3.6 编写的,它使用了非常著名的 OpenCV 库。OpenCV 是一个计算机视觉和机器学习软件库,包括许多常见的图像分析算法,可以帮助我们构建定制的智能计算机视觉应用程序。

按照这篇中帖在 Python 3 中安装 OpenCV。

视频跟踪快速介绍

视频跟踪

为了执行视频跟踪,一种算法分析连续的视频帧,并输出帧之间的目标运动。算法多种多样,各有优缺点。在选择使用哪种算法时,考虑预期用途很重要。视觉跟踪系统有两个主要组成部分:目标表示和定位,以及过滤和数据关联。

视频跟踪是使用摄像机在一段时间内定位一个移动对象(或多个对象)的过程。它有多种用途,其中一些是:人机交互、安全和监控、视频通信和压缩、增强现实、交通控制、医学成像和视频编辑。

更多信息,见。

什么是等高线?

如果你是 OpenCV 的新手,在阅读本文中的代码之前,最好先浏览一下这个关于轮廓的教程页面。也看看这个 Jupyter 笔记本的轮廓。需要明确的是,术语“边缘”和“轮廓”经常互换使用,但这是不对的。如果你对这种差异的理解模糊不清,请浏览一下 ResearchGate 网站上的这个问题帖子。

代码解释

第一步:初始化一些东西

首先,我们导入必要的库。

然后,我们初始化在以下步骤中使用的变量。

blueLowerblueUpper numpy 阵列帮助我们找到蓝色的帽子。一旦发现蓝帽,内核有助于使其平滑。 bpointsgppointsrpoints 和 ypoints deques 分别用于存储蓝色、绿色、红色和黄色屏幕上绘制的点。

步骤 2:设置绘画界面

这是一件痛苦的事情。我们必须手动设置框架上每个彩色框的坐标。我们使用 OpenCV 函数***cv2 . rectangle()***来绘制盒子。

第三步:开始阅读视频(一帧一帧)

现在我们使用 OpenCV 函数 cv2。VideoCapture() 从视频文件或网络摄像头实时逐帧读取视频(使用 while 循环)的方法。在这种情况下,我们将 0 传递给方法以从网络摄像头读取数据。

为了使用方便,我们可以添加完全相同的画图界面。

步骤 4:找到感兴趣的轮廓(瓶盖)

一旦我们开始读取网络摄像头馈送,我们就会借助***cv2 . in range()***方法不断在帧中寻找蓝色对象,并使用在步骤 0 中初始化的 blueUpperblueLower 变量。一旦我们找到轮廓,我们做一系列的图像操作,并使其平滑。它们让我们的生活变得更轻松。如果你想知道更多关于这些操作——腐蚀、变形和扩张,请查看这个。

一旦我们找到轮廓(当找到轮廓时,如果 条件通过,则为 ),我们使用轮廓的中心(蓝色帽)在屏幕上绘制它的移动。下面的代码做了同样的事情。

上面的代码找到轮廓(最大的一个),使用***cv2 . minenclosingcircle()cv2.circle() 方法围绕它画一个圆,借助cv2 . moments()***方法得到找到的轮廓的中心。

第五步:开始绘图并存储绘图

现在我们开始跟踪轮廓中心接触屏幕的每一个点的坐标,以及它的颜色。我们将这些不同颜色的点存储在不同的 deques 中(b 点g 点等)。).当轮廓的中心接触到我们在步骤 1 中放在屏幕上的一个彩色框时,我们将这些点存储在其各自的颜色队列中。

第六步:在屏幕上显示图画

到目前为止,我们将所有点存储在它们各自的颜色队列中。现在我们用他们自己的颜色加入他们。OpenCV 函数 cv2.line() 为我们做到这一点提供了便利。下面的代码做了同样的事情。

一旦我们用一条线连接每一帧中的所有点,并把它放在我们用 cv2.imshow() 方法创建的两个窗口上,它就像一个绘画应用程序一样完美地工作了。当我们进入 循环从网络摄像头读取数据时,从 循环中掉出后,我们释放摄像头并使用以下代码行销毁所有窗口。

就是这样!我们在 OpenCV 中成功地使用了一堆基本的图像处理工具和操作,创建了一个类似绘画的应用程序——网络摄像头绘画!

执行

> python Webcam_Paint_OpenCV.py

结论

这是 OpenCV 图像处理能力的简单演示。如果你觉得这很有趣或容易或无聊,或者认为这没有什么挑战性,我建议你尝试添加更多的绘画功能,如橡皮擦,不同类型的笔刷,颜色填充选项等。为了真正感受 OpenCV 有多有趣。

希望这个教程是有趣的。感谢阅读。

活也让别人活!

Photo by Kelli Tungay on Unsplash

向您的支持团队提交推文—使用机器学习进行情感分析

原文:https://towardsdatascience.com/tweet-escalation-to-your-support-team-sentiment-analysis-with-machine-learning-14db1744d1b4?source=collection_archive---------12-----------------------

用于航空公司支持请求升级的自动推文情感处理解决方案

Source: Pixabay

我将解释端到端技术解决方案,它将有助于简化您的公司支持流程。我将重点关注从 Twitter 收到的航空公司支持请求。如果支持部门能够提前知道哪个请求更重要并且必须以更高的优先级处理,那么他们可以节省大量的时间和金钱。

本文将涵盖哪些内容:

  • 用例解释
  • 预测推文文本情感的机器学习解决方案—检查是否需要支持请求上报
  • 在 AWS SageMaker 中访问机器学习模型
  • Node.js 和 Express 的后端实现
  • 使用 JavaScript 和 Oracle JET toolkit 实现客户端 UI

图表解释了所有技术位是如何连接在一起的。

Solution architecture

让我们从用例解释开始。我认为实现用例会很有趣也很有用,它将允许报告人们向航空公司发送的推文,人们在那里寻求帮助。航空公司每天肯定会收到很多这样的推文,其中一些根本不相关。我的目标是只挑选那些需要升级和人工审核的推文。这应该会改善支持团队的结果,也许有助于保持更多的忠诚客户。

受本书(第 4 章)中给出的指导的启发,我实现了用于推特情感分析的机器学习模型— 商业机器学习。我强烈推荐任何人阅读这本书,他们正在寻找如何在他们的公司实施机器学习的实用方法。

基于航空公司(不仅限于航空公司,可以是任何 Twitter 账户)账户,我们获取 100 条写到该账户的最新 tweets。只有那些需要上报并且必须由人工处理的推文才会显示在列表中。即使 tweet 被归类为要升级的那个,我们也可以通过概率得分来确定它升级的可能性有多大(见红黄绿点)。这有助于进一步过滤掉推文,甚至在选择升级的推文列表中。

AmericanAir 结果— 24%的推文需要升级并由人工处理:

American Air

Delta 结果— 21%的推文需要升级并由人工处理:

Delta

阿联酋结果——19%的推文需要升级并由人工处理:

Emirates

英国航空公司的结果——32%的推文需要升级并由人工处理:

British Airways

Lufthansa 结果— 28%的推文需要升级并由人工处理:

Lufthansa

大约 20%-30%的推文需要所有航空公司升级,这似乎是一种常见的模式。

支持人员可以点击 twitter 帐户名称或更多链接,以获得关于推文的更多详细信息,并做出相应的回应。

我使用 AWS SageMaker 和 BlazingText 机器学习算法来建立一个情感分析模型。你可以在本书(第 4 章)——商业机器学习中阅读 BlazingText 以及如何在 AWS SageMaker 中运行它,所有这些都是一步一步描述的,非常简单易懂。你不需要购买这本书来下载源代码(从源代码链接获得)。在我之前的帖子中阅读更多技术细节— 亚马逊 SageMaker ML 情绪分析的 API。

BlazingText 情感分析模型是使用 Stuart Axelbrooke 从思维向量(【www.thoughtvector.io/】)上传到 Kaggle 的数据集来训练和构建的。原始数据集可以在这里查看:www . ka ggle . com/thought vector/customer-support-on-Twitter/home。除了源代码,您还可以下载经过处理的数据集。图书作者处理了原始数据集——他们删除了除原始推文之外的所有推文,并使用回复将原始推文标记为升级或未升级。大约有 50 万条推文用于构建支持升级情绪模型。

当在 AWS SageMaker 中构建机器学习(ML)模型时,您需要创建一个端点,这将允许从外部访问模型并调用预测函数。端点创建包含在 Jupyter 笔记本中。

有了活动端点,我们就可以创建 AWS Lambda 函数,作为 ML 模型和 REST API 之间的代理。Lambda 允许在调用 ML 模型之前建立数据转换逻辑,并在将结果发送回 REST API 之前处理由 predict 函数返回的结果。点击此处了解更多信息— 来自 Oracle JET 的 Amazon SageMaker 模型端点访问。

Lambda 函数的示例代码:

ENDPOINT_NAME 变量指向运行 Jupyter notebook 时创建的客户支持端点名称。下一步是在 AWS 中定义 REST API(在上面引用的文章中阅读更多相关内容):

AWS REST API

确保为此 API 启用 CORS 支持。CORS 允许从外部主机调用 API,例如从 JavaScript 应用程序:

AWS REST API CORS

总结机器学习部分:

  • 您需要运行 Jupyter 笔记本、培训/验证模型。模型构建完成后,创建 AWS 端点
  • 定义 AWS Lambda 函数以访问 ML 模型
  • 定义 AWS REST API 将传入的请求传递给 AWS Lambda

接下来,我们继续讨论 Node.js 和 Express 的后端实现。我已经用快速应用程序生成器生成了 Node.js 应用程序。点击阅读更多可用命令。您得到 app.js 文件,它充当中央路由器——在这里您可以定义后端处理的所有 REST 端点。每个端点都可以映射到一个单独的模块——在下面的例子中是 invoicerisk.jstwitter.js 。这带来了更大的灵活性,并允许将代码构建到单独的模块中:

Backend app structure

快速路由代码由快速生成器创建。在 app.js 中,我们可以定义 Node.js 模块的路径。我们将使用这个路径从 UI 执行 REST API 调用。

您可以使用以下命令运行使用 Express 生成的 Node.js 应用程序:

DEBUG =: NPM start*

我们为什么要使用 Node.js 后端?原因很明显——要访问 Twitter API,我们需要提供映射到 Twitter 帐户的键,我们不能将这些键保存在客户端。一旦请求来自客户端,它将转到 Node.js 后端 POST handler 方法。在这个方法中,我们将通过 Twitter API 获取最新的 tweets,准备用于分类的数据集,并通过 REST API 调用将其传递给 AWS SageMaker。响应将被解析以构造结果,该结果将被发送回客户端。检查代码段内的注释:

后端的主要任务是帮助获取推文,将它们发送到机器学习模型进行分类,并构建客户端可以处理的响应。

UI 客户端是用 Oracle JET 工具包和 JavaScript 创建的。我使用 Oracle JET 是因为它提供了一套很好的开箱即用的 UI 组件,允许构建美观实用的企业应用程序。

您可以从命令行运行 Oracle JET app:

发球

JavaScript 代码,用于执行后端调用,并构建带有支持升级请求的 tweets 数组。

这段代码使用了许多 Oracle JET 库。我建议浏览一下 Oracle JET cookbook ,它为每个 UI 组件提供了一个交互式示例列表。

图表和列表组件由 Oracle JET 标记呈现:

我的目标是展示用于情感分析的机器学习模型如何适应企业应用架构,包括后端和客户端 UI 实现。我希望这个航空公司支持请求升级的实际用例有助于在您的组织中应用机器学习,并给出如何解决您自己的业务挑战的想法。

像特朗普一样用 One2Seq 模型发推特

原文:https://towardsdatascience.com/tweet-like-trump-with-a-one2seq-model-cb1461f9d54c?source=collection_archive---------0-----------------------

在本文中,我将向您介绍我的项目的大部分内容,我创建了一个一对一的模型,可以生成类似于 Trump 的推文。实际模型与我在我的“如何构建你的第一个聊天机器人”文章中构建的模型非常相似。这个模型的两个关键区别是输入和不包括注意力。注意力被排除在外,因为它没有显著提高生成的推文的质量。创建输入的步骤将是本文的重点。作为预览,我们将遵循以下路径:

  • 清理特朗普的推文。
  • 使用预先训练的单词向量创建单词向量( GloVe — Twitter 200d) )。
  • 平均一条推文的词向量的维度。
  • 使用主成分分析将维数减少到 1。
  • 根据主成分分析值对推文进行排序。
  • 通过文字的质量来限制推文。

我真正喜欢这个模型的地方是,我希望你也会喜欢,我们如何使用这样一个简单的输入,一个值,来生成一条推文。此外,从我们如何创建输入数据,我们将能够在某种程度上控制我们生成的推文的风格。

为了设定你的期望,这里有几个你可以用这个模型创建的推文的例子:

  • 谢谢你亚利桑那!# makamericagreatagain # trump 2016
  • 必须阻止希拉里
  • 记得出来投票!#杂志#特朗普 2016

注意:我将从我的代码中删除注释,以帮助保持简短。如果你想看评论和我的完整代码,请访问这个项目的 GitHub 页面

我们开始吧!

这个项目的数据来自 Kaggle 上的数据集,它包含了 7375 条推文。我们需要做的第一件事是清理我们的推文。

def clean_tweet(tweet):
    tweet = tweet.lower()
    tweet = re.sub(r'https?:\/\/.*[\r\n]*', '', tweet, flags=re.MULTILINE)
    tweet = re.sub(r'[_"\-;%()|.,+&=*%]', '', tweet)
    tweet = re.sub(r'\.', ' . ', tweet)
    tweet = re.sub(r'\!', ' !', tweet)
    tweet = re.sub(r'\?', ' ?', tweet)
    tweet = re.sub(r'\,', ' ,', tweet)
    tweet = re.sub(r':', ' : ', tweet)
    tweet = re.sub(r'#', ' # ', tweet)
    tweet = re.sub(r'@', ' @ ', tweet)
    tweet = re.sub(r'd .c .', 'd.c.', tweet)
    tweet = re.sub(r'u .s .', 'd.c.', tweet)
    tweet = re.sub(r' amp ', ' and ', tweet)
    tweet = re.sub(r'pm', ' pm ', tweet)
    tweet = re.sub(r'news', ' news ', tweet)
    tweet = re.sub(r' . . . ', ' ', tweet)
    tweet = re.sub(r' .  .  . ', ' ', tweet)
    tweet = re.sub(r' ! ! ', ' ! ', tweet)
    tweet = re.sub(r'&amp', 'and', tweet)
    return tweet

这段代码将删除任何链接和无用的字符,并重新格式化文本,以便我们可以最大限度地利用 GloVe 的预训练单词向量。例如,所有的标签都与文本分开。这是因为 GloVe 没有针对 hashtagged 单词的预训练单词向量,所以如果我们想要利用这些预训练向量,我们需要进行这种分离。

注意:我们将使用 GloVe 的 Twitter 矢量。

以下是一些干净的推文示例:

  • 今天,我们向所有曾在我们的军队中服役的人表达最深切的感谢
  • rt @ ivankatrump:投票给我父亲竞选美国总统真是一个超现实的时刻!发出你的声音并投票!#选择 2
  • 晚上 9 : 45 看投票结果#选举之夜#杂志

为了生成单词向量,我们首先需要从 GloVe 的单词向量中创建一个嵌入索引。

embeddings_index = {}
with open('/Users/Dave/Desktop/Programming/glove.twitter.27B/
           glove.twitter.27B.200d.txt', encoding='utf-8') as f:
    for line in f:
        values = line.split(' ')
        word = values[0]
        embedding = np.asarray(values[1:], dtype='float32')
        embeddings_index[word] = embedding

在这个文件中有 1,193,514 个单词嵌入,每个嵌入有 200 个维度。

我们将使用这个嵌入指数为每条推文创建一个“平均”嵌入。为此,我们将从“空”嵌入开始(所有 200 个值[对于 200 个维度]将为 0)。如果 tweet 中的一个单词在索引中,它的嵌入将被添加到“空”嵌入中。如果 tweet 中的一个单词不在索引中,那么“空”嵌入中将不会添加任何内容。在考虑了推文中的每个单词后,我们将根据推文中的单词数对每个维度进行平均。这些平均维度将为每条推文创建我们的“平均”嵌入。

以下是相关的代码:

embedding_dim = 200 embed_tweets = [] # Contains the 'average' embedding for each tweetfor tweet in clean_tweets:
    avg_embed = np.zeros(embedding_dim) 
    for word in tweet.split():
        embed = embeddings_index.get(word)
        if embed is not None:
            avg_embed += embed 
    embed_tweets.append(avg_embed/len(tweet.split()))

为了创建这些 *tweet 嵌入,*我们可以使用其他方法,比如 Word2Vec。Word2Vec 的好处是不会有任何空嵌入,但考虑到我们正在处理的数据量,只有 7375 条推文,我认为利用 GloVe 更大的数据集会更好。你很快就会看到,使用手套效果很好。

我们的下一步是将数据的维度从 200 减少到 1。我们将 reduction 设置为 1,以简化和组织我们的输入数据,并使其易于生成我们想要的 tweet 类型,例如。如果我们想要一条有更多标签或者只有文字的推文。

正如你可能已经预料到的,我们将使用 PCA(主成分分析)来降低数据的维度。

pca = PCA(n_components=1, random_state = 2)
pca_tweets = pca.fit_transform(embed_tweets)

现在,我们的每条推文都有一个 PCA 值,我们将从最小值到最大值对它们进行排序,这样类似的推文将更加接近。

pca_tweets_list = [] # Contains the pca values
for tweet in pca_tweets:
    pca_tweets_list.append(tweet[0])order = np.array(pca_tweets_list).argsort()
pca_labels = order.argsort()
pca_labels *= 2 

我们将我们的pca_labels乘以 2,以便更简单地生成新的推文。虽然我们不会使用所有的 tweet 来训练我们的模型,但是所有的训练 tweet 都是偶数。为了确保生成新的 tweet,你需要做的就是使用一个奇数作为输入。这个生成的 tweet 应该类似于训练数据中的 tweet,其值接近您的输入值。

为了了解 Trump 发布的推文的类型,我们将使用 KMeans 将推文分组。pca_tweets将是我们对 KMeans 的输入,在使用 3-10 个聚类检查该函数的结果后,我认为 4 个聚类最好地将 Trump 的推文分成不同的组。

kmeans = KMeans(n_clusters=4, max_iter = 1000, n_init = 20, random_state=2).fit(pca_tweets)
labels = kmeans.labels_

每组包含以下数量的推文:

1(红色):315,2(橙色):2600,3(黄色):1674,4(蓝色):2782

推文由它们的 KMeans 标签着色,但是输入到 TSNE 的数据是embed_tweets。这张图表明,你可以将推文分成一些合理的不同类别。它并不完美,如果你愿意,你可以为自己创造一些情节,但我认为这是最好的结果。

接下来,我们可以看看 PCA 标签与 tweet 组相比有多好。

I’d make this graph bigger, but Medium won’t let me

正如所料,鉴于 tweet 组是使用 PCA 数据创建的,我们可以看到四个明显的组。这也提供了一个很好的可视化来比较不同大小的推文组,并可以帮助您在想要生成推文时选择推文类型。

在我的 iPython 笔记本中,我会更详细地介绍每个组中的单词和推文,但为了给你一个示例,这里是每个组的一些推文:

Group # 1 - short tweets with hashtags
#1: # electionday 
#2: rt  @ donaldjtrumpjr :  thanks new hampshire ! !
    # nh  # newhampshire  # maga 
#3:  # draintheswamp !

Group # 2 - long tweets that are retweeted
#1: rt  @ ivankatrump :  such a surreal moment to vote for my father 
    for president of the united states ! make your voice heard and 
    vote !  # election2
#2: rt  @ erictrump :  join my family in this incredible movement to  
    # makeamericagreatagain ! now it is up to you ! please  # vote 
    for america ! https : 
#3: rt  @ donaldjtrumpjr :  final push ! eric and i doing dozens of 
    radio interviews we can win this thing ! get out and vote !  # 
    maga  # electionday ht

Group # 3 - typically involve a data/time/location
#1: watching the returns at 9 : 45 pm # electionnight  # maga 
#2: monday  11/7/2016 
    scranton pennsylvania at 5 : 30 pm 
    grand rapids michigan at 11 pm  
#3: rt  @ ivankatrump :  thank you new hampshire !  

Group # 4 - longer tweet, mostly just text
#1: today we express our deepest gratitude to all those who have  
    served in our armed forces  # thankavet 
#2: busy day planned in new york will soon be making some very 
    important decisions on the people who will be running our 
    government !
#3: love the fact that the small groups of protesters last night 
    have passion for our great country we will all come together and 
    be proud !

为了帮助模型生成最佳推文,我们将通过一些措施来限制我们的训练数据。我们要做的第一件事是建立一个词汇到整数(vocab_to_int)字典和 int_to_vocab 字典,其中只包括在特朗普的推文中出现 10 次或更多次的单词。为什么是 10?我对此没有任何“硬”的理由,但这将有助于我们生成的推文听起来更像特朗普的典型推文,而且这将有助于模型更好地理解每个单词的意思,因为它会看到至少 10 次。如果阈值只是 2 或 3,模型将很难理解和使用很少出现的单词。

threshold = 10vocab_to_int = {}value = 0
for word, count in word_counts.items():
    if count >= threshold:
        vocab_to_int[word] = value
        value += 1int_to_vocab = {}
for word, value in vocab_to_int.items():
    int_to_vocab[value] = word

接下来,我们将限制我们将使用的推文的长度。在训练数据中,我选择了 25 作为 tweet 的最大长度。选择该值是因为它是模型仍能很好学习的最大长度。再长一点,模型就很难学习推文,再短一点,我们就会进一步限制我们的训练数据。

我们还将设置一个限制。是一个标记,用于表示不包括在我们的训练词汇中的单词。如果一条推文中出现多个令牌,则该推文将不会用于训练模型。我尝试将限制增加到 2,但这导致在生成的 tweets 中出现太频繁。

max_tweet_length = 25
min_tweet_length = 1
unk_limit = 1short_tweets = []
short_labels = []for i in range(len(int_tweets)):
    unk_count = 0
    if len(int_tweets[i]) <= max_tweet_length and \
       len(int_tweets[i]) >= min_tweet_length:
        if len(int_tweets[i]) == 1:
            if int_tweets[i][0] != vocab_to_int['<UNK>']:
                short_tweets.append(int_tweets[i])
                short_labels.append(pca_labels[i])
        else:
            for word in int_tweets[i]:
                if word == vocab_to_int['<UNK>']:
                    unk_count += 1
            if unk_count <= unk_limit:
                short_tweets.append(int_tweets[i])
                short_labels.append(pca_labels[i])

作为为模型准备数据的最后一步,我们将按长度对推文进行排序。这样做将有助于我们的模型训练得更快,因为早期的批次将包含更短的推文。每批中的推文需要具有相同的长度,因此通过对推文进行排序,将避免长推文与短推文一起被批量处理。

sorted_tweets = []
sorted_labels = []for length in range(1,max_tweet_length+1):
    for i in range(len(short_tweets)):
        if length == len(short_tweets[i]):
            sorted_tweets.append(short_tweets[i])
            sorted_labels.append([short_labels[i]])

这就是创建我们的训练数据!这需要做一些工作,但是可以说你的输入数据是模型中最重要的部分。没有好的训练数据,模型将无法生成好的输出。

本文的最后一部分是如何生成推文。有两种不同的方法可以使用。

选项 1:找一条类似的推文

通过这种方法,你可以输入与最相似的推文匹配的单词或短语。

create_tweet = "I need your help to make america great again! #maga"create_tweet = clean_tweet(create_tweet)create_tweet_vect = vectorize_tweet(create_tweet)create_tweet_pca = pca.transform(create_tweet_vect)similar_tweet = min(pca_tweets_list, 
                    key=lambda x:abs(x-create_tweet_pca))for tweet in enumerate(pca_tweets_list):
    if tweet[1] == similar_tweet:
        print("Most similar tweet:", pca_labels[tweet[0]])
        break
  • create_tweet中,输入您想要匹配的任何文本。
  • 这条推文将被清理,然后使用与我们进行“平均”嵌入时输入数据相同的方法转换为向量。
  • 推文的“平均”嵌入将被用于找到其 PCA 值。这个值将与最接近的 tweet 匹配。
  • 匹配的 tweet 的 PCA 值将用于查找其 PCA 标签。这个标签是模型的输入。

如果你对这条最接近的推文的内容感到好奇,那么下面是给你的代码!

tweet_type = 3464closest_type = min(short_labels, key=lambda x:abs(x-tweet_type))
words = []
for tweet in enumerate(short_labels):
    if tweet[1] == closest_type:
        for num in short_tweets[tweet[0]]:
            words.append(int_to_vocab[num])
print(" ".join(words))

tweet_type可以认为是 PCA 标签。该值将与用于训练模型的最接近的标签相匹配。将打印出与最近标签相关的文本。

作为这种方法局限性的一个例子,我用了这样一句话“我需要你们的帮助,让美国再次伟大!#maga "作为我的create_tweet,返回的tweet_type和文字是:3464,“希拉里是有史以来竞选美国总统最腐败的人# draintheswamp”。

这些文本差别很大,但是它们的结构是相似的,多个普通的单词和一个标签。我同意这是第四组风格的推文的模式。

选项 2:输入一个值

这是更简单的选择,包含了更多的随机性。你需要做的就是选择一个tweet_type,我建议你参考推文组的范围来控制推文的风格。您还可以通过设置 sequence_length 的值来控制您想要生成的 tweet 的长度,但我将其设置为随机整数,因为我喜欢危险地生活。

tweet_type = 3464checkpoint = "./best_model.ckpt"loaded_graph = tf.Graph()
with tf.Session(graph=loaded_graph) as sess:
    loader = tf.train.import_meta_graph(checkpoint + '.meta')
    loader.restore(sess, checkpoint) input_data = loaded_graph.get_tensor_by_name('input:0')
    logits = loaded_graph.get_tensor_by_name('logits:0')
    sequence_length = 
        loaded_graph.get_tensor_by_name('sequence_length:0')
    keep_prob = loaded_graph.get_tensor_by_name('keep_prob:0')tweet_logits = sess.run(logits, 
                        {input_data: [[tweet_type]], 
                         sequence_length: np.random.randint(3,15),
                         keep_prob: 1.0})[0]# Remove the padding from the tweet
pad = vocab_to_int["<PAD>"]print('Tweet')
print('  Word Ids: {}'.format(
         [i for i in np.argmax(tweet_logits, 1) if i != pad]))
print('  Tweet: {}'.format(" ".join([int_to_vocab[i] for i in 
                          np.argmax(tweet_logits, 1) if i != pad])))

这个项目到此为止!我希望你喜欢了解它,如果你想看到整个过程,那么就去我的 GitHub 吧。如果您有任何问题、意见或建议,请在下面发表。

如果你对扩展这项工作感兴趣,我的一个想法是对生成的推文提供更大的控制。我认为如果我们可以在输入数据中包含一个关键字(或多个单词)会很好。这应该有助于我们控制我们想要生成的推文的风格和上下文。

感谢阅读!

你需要人类对人工智能的适当信任

原文:https://towardsdatascience.com/twiml-ai-meetup-trust-and-ai-86c32f91a0e0?source=collection_archive---------4-----------------------

TWiML & AI meetup talk:信任人工智能

我很高兴能在 TWiML 人工智能会议上发表关于人工智能信任的演讲。这个话题的核心是人类如何使用机器,以及他们如何将机器融入他们的团队。正如我们将看到的,这是一个非常重要但难以理解的话题。

“信任促进合作行为”

为了开始讨论,我们回顾了关于信任和自动化主题的四篇论文:

  • 对心智模型的一些观察 (1987)
  • 人类和自动化:使用、误用、废弃、滥用 (1997)
  • 紧急疏散场景中机器人的过度信任 (2016)
  • 自动化中的信任:整合影响信任因素的经验证据 (2015)

所有这些论文的关键在于,它们讨论了过多(误用)和过少(不用)之间的信任平衡。有许多因素可以增加信任度,但是我们应该总是构建具有最大信任度的系统吗?

在回顾了论文之后,我们开始深入研究在将人和机器结合起来时应该考虑的问题。这不是人在回路中(HITL)对人在回路外(OOTL)的人工智能。事物的本来面目也不一样。

说到 HITL,它不再仅仅是一个人和一台机器。它是与智能生态系统一起工作的人类组织。我们需要了解他们如何最好地合作。

如果你认为任何系统对人类来说都是真正的 OOTL,那么你就没有正确设定系统的边界。总有人类以某种方式参与其中。即使只是你的客户受到影响。你需要将他们纳入你的考虑范围。

在考虑信任时,责任是一个重要因素。当事情确实出错时,谁需要对此负责?

That is my exit!

如果上面的车是一辆自动驾驶汽车,从技术上讲它没有发生事故,但它确实需要对它的所作所为负责、而不是其他人类卡车司机。

如何为您的应用程序确定合适的信任度?这可以在不投入月复一月的数据清理和模型训练时间的情况下完成。你可以用非编码原型来做,就像我们在各种项目中做的那样。

最后,有太多的因素影响信任,你需要用真实的人来测试系统,了解他们需要什么。机器不会取代人类的目的。

资源

幻灯片:

[## TWiML & AI:信任与人工智能

信任与爱克里斯巴特勒@ philosophie.is @克里斯博特·https://goo.gl/m1PaVi

docs.google.com](https://docs.google.com/presentation/d/e/2PACX-1vTa6ebnvjGk1agTlztTFK4oJCM28UrkWbYuxzS_5Y5-atyYWxER4uA9N3l7X1dIVl_xb4mOqBox6pPx/pub?start=false&loop=false&delayms=3000)

其他参考:

  • 谷歌的高绩效团队和信任
  • TWiML & AI 播客#110 与 Ayanna Howard
  • 急救机器人视频
  • 为什么部队不信任无人机
  • 机械战警(2014)
  • 安慰剂按钮(假恒温器)
  • 控制偏差的错觉
  • 回路中的机器接近
  • 人在回路中的机器学习:来自 StitchFix 的教训
  • 星球大战社交网络
  • 那是我们的出口!
  • 道德崩溃区
  • 计算机化社会中的问责制
  • WoZ 方式:实现实时远程交互原型&在路上车辆中观察
  • 康奈尔大学的温迪·朱
  • 在用户研究中测试人工智能概念
  • 机器的移情映射
  • 混淆映射

关于克里斯·巴特勒

我帮助团队理解他们应该用以人工智能为中心的解决方案解决的真正的商业问题。我们工作的团队通常被要求用他们拥有的数据“做一些有趣的事情”。我们通过偶发事件相关性帮助他们避免局部极值,并专注于解决巨大的业务问题。我的背景包括在微软、KAYAK 和 Waze 等公司超过 18 年的产品和业务开发经验。在 Philosophie,我创造了像机器移情映射和困惑映射这样的技术,以在构建人工智能产品时创建跨团队对齐。如果你想了解更多或者通过邮箱、 LinkedIn 联系,或者访问http://philosophie.is/human-centered-ai。

Twitter 广告

原文:https://towardsdatascience.com/twitter-advertising-1d497d066fef?source=collection_archive---------4-----------------------

介绍

这是我在大会数据科学沉浸式项目中的顶点项目的非技术性报告。顶点计划是指参加该计划时所学一切的高潮。我选择对 Twitter 数据执行自然语言处理(NLP ),以便协助广告活动。这个项目更多地面向广告商、市场营销和任何想要扩展他们的客户关系平台以与他们的追随者交流的公司。

目标

通过推文的 NLP,公司可以衡量人们对他们产品的感受。我的目标之一是创建一个模型,对一条信息是否具有积极或消极的情感价值进行分类。这种分类的一部分是过滤掉那些正面/负面的推文,看看问题源自哪里。一个公司可以直接联系那些对他们的产品有问题的顾客,同时奖励那些忠诚于这个品牌的顾客。

数据

出于介绍的目的,所有的工作都是用 python 编写的,使用了几个库。这些库包括 Numpy、Pandas、Matplotlib、Scikit Learn 和 Keras。通过使用 Twitter API,tweets 被挖掘和收集。推文以压缩的 JSON 格式返回。如下例所示,信息是嵌套的,通常难以阅读。

通过一个自动化的过程,某些特征被选中,数据被保存到一个熊猫数据框架中。

本项目中使用了以下功能:

  • 创建时间:创建推文的时间戳。
  • 收藏次数:这条推文被“收藏”的总次数
  • 标签:与 tweet 相关联的标签。
  • 位置:用户声明的位置。
  • 挖掘时间:tweet 被挖掘的时间戳。
  • 转发次数:这条推文被“转发”的总次数。
  • 屏幕名称:用户的屏幕名称。
  • 来源:推文的来源(即:设备)。
  • 文本:推文的文本。
  • 字数:一条推文中的总字数。
  • tweet Length:tweet 的字符长度。

返回的数据不干净。我说它不干净是因为为了让我处理数据,我需要一种特定的格式。有许多函数是为处理这个过程而编写的。我清理数据的过程如下:

  • 使用位置变量提取 tweet 的坐标。如果没有,我将它设置为加州旧金山。为什么是 SF?因为 Twitter 总部位于旧金山。
  • created_at 和 mined_at 变量被转换为 datetime 对象以执行与时间相关的函数。
  • hashtags 变量在开头接收' # ',空格被删除。这是为了让所有的标签保持相同的格式。
  • 源变量删除了 html 代码。
  • 文本变量移除了超链接,移除了“@”提及,单词被标记化。示例:

# 纹身 sForShawn 我是 思维 点歌 耳机 ,然后那根线就是歌迷们歌唱生活的声波聚会@ Shawn Mendes

变成了:‘纹身 sforshawn’,‘思考’,‘耳机’,‘电线’,‘声音’,‘海浪’,‘粉丝’,‘唱歌’,‘生活’,‘派对’

下图显示了数据清理后数据帧的外观:

特征工程

除了从 twitter 中挖掘出来的特性,还有其他一些特性是为了更好地理解数据而创建的。VADER(用于情感推理的效价感知词典)库包括情感强度分析器,该分析器是确定给定推文的情感值的基础。这是一个基于规则的情绪分析工具,专门针对社交媒体中表达的情绪。给定一条消息,分析器返回可测量的值:

  • 消极情绪
  • neu:中性情绪
  • 积极情绪
  • 复合:复合(即综合得分)

Nodebox 英语语言学图书馆允许通过回归意象词典进行心理内容分析。RID 对文本中主要、次要和情感过程思想进行评分。这是一个有趣的包,因为它开辟了一种查看信息的新方式。

  • 初级:涉及梦和幻想的自由形式联想思维
  • 二级:逻辑性强,以现实为基础,注重解决问题
  • 情绪:恐惧、悲伤、憎恨、喜爱等的表达。

探索数据

探索性数据分析(EDA)是一种分析数据集以总结其主要特征的方法。我选择从两个不同的角度来看这些数据。第一种是对收集到的所有公共信息进行更全面的概述。第二个通过更具体的观点,好像我是一个对我的信息感兴趣的公司。我们先来看一个大概的看法。

我选择查看每个特性,并查看数据的整体视图。time_created 变量显示,大多数推文是在下午发送的,然后是在午夜之后的几个小时。请注意,这些时间是以太平洋标准时间为基准的。标签聚集了挖掘过程中讨论的主要话题。

收集的推文主要集中在美国,因为情感库是在英语语言上训练的。这也是看外国字符时的编码问题。如果没有命名城市,加利福尼亚州旧金山是默认城市,因此在其他位置中很突出。许多用户在他们的个人资料中没有位置,在他们的推文中也没有。Twitter 的总部在旧金山市中心,所以推文是从那里发出的。

sources 变量显示 twitter 的移动使用占据了首位。前三名依次是 iPhone、Android 和 Twitter 网络客户端。web 客户端指的是通过 web 浏览器在桌面上使用 twitter,以及在移动设备上使用 web 浏览器。

在将推文分成各自的情绪值后,我决定看看字数分布。负面和正面推文的字数分布峰值都是每条推文 15 个字。中性的推文大多在 10 个字及以下。

对于 VADER 情绪分析,我将着眼于复合值。下图中的复合金额是 VADER 情绪分析的聚合值。复合值的范围从-1 到 1;消极情绪,到中性情绪,到积极情绪。大多数推文被评为中性。我认为这是因为 VADER 情绪分析器没有对 2017 年的新词进行训练,即:fleek。

#万豪

在对数据进行总体概述后,我想看看与万豪品牌相关的具体推文。获取数据的过程与之前相同,只是我将标签“#Marriott”传递给一个搜索参数,因此只返回与该标签相关的信息。

我想看的第一件事是#万豪在世界上的什么地方被谈论。使用坐标变量,我可以在地图上画出推文的来源。

通过观察一段时间内的情绪值,我能够衡量与万豪相关的正面或负面推文的数量。大多数推文都是对万豪的正面评价,只有少数是负面评价。

一条复合得分高达 0.951 的推文示例:

一条复合得分为-0.6551 的推文示例:

作为万豪的员工,我能够联系有问题的客户,并提供某种解决方案。同样的道理也适用于奖励评论最好的酒店。

数据建模

VADER 情感分析器是对推文情感价值进行分类的基础。我想看看我是否能利用课堂上学到的模型对推文进行分类。在继续之前,我需要将文本数据转换成 python 可以理解的格式。我用 word2vec 从单词中创建向量。在 word2vec 中,使用了单词的分布式表示。取一个有几百维(比如 300 维)的向量。每个单词都由这些元素的权重分布来表示。因此,向量中的元素和单词之间不是一对一的映射,而是单词的表示分布在向量中的所有元素上,向量中的每个元素都有助于许多单词的定义。单词“dog”的 300 维向量示例:

# creates a vector given a sentence/tweet
# takes a list of words, and array size of w2v vector
# tokens == a list of words (the tokenized tweet)
# size == the dimensional size of the vectorsize = 300def buildWordVector(tokens, size):
    vec = np.zeros(size).reshape((1, size))
    count = 0.
    for word in tokens:
        try:
            vec+= w2v[word].reshape((1,size))
            count += 1.
        except BaseException: # handling the case where the token is not
            try:
                continue

    if count != 0:
        # get centroid of sentence
        vec /= count
    return vec

一旦每个单词都被矢量化,下一步就是创建推文本身的矢量。tweet 中的每个单词向量相加在一起,除以 tweet 中的单词总数,这为 tweet 创建了一个向量,它是相加向量的质心。这是我遇到的强大的东西。通过创建这些向量,您可以执行矩阵数学运算并找到新的模式。可以对这些向量执行余弦相似性,这使你能够看到相似的推文/词以及最相反的推文/词。一旦用户的推文被矢量化,就可以用同样的步骤为用户创建向量。

作为参考,有三类被分类:消极,中立和积极。数据被分成 85/15 的比例,用于训练和测试数据。我的基本估计是多项式逻辑回归。我正在查看更具体的回忆分数,因为回忆是“结果有多完整”。高召回率意味着算法返回了大部分相关结果。如你所见,中性分类高于其他分类。

额外树分类器是尝试的第二个模型。“额外树”分类器,也称为“极度随机化树”分类器,是随机森林的变体。与随机森林不同,在每一步都使用整个样本,并随机选取决策边界,而不是最佳边界。还是那句话,中性分类高于其余。负面分类的表现很糟糕。

我最后一次分类的尝试是用神经网络来完成。Keras 是用 Python 编写的开源神经网络库。我对 Keras 的第一次尝试是创建一个又深又宽的神经网络。它有 5 个致密层,分别含有 500、800、1000、300 和 3 个神经元。以及设置为 0.1、0.5、0.2、0.2 和 0.2 的每个密集层之前的下降层。前四层的激活是“relu”,最后一层是“softmax”。

# in order for keras to accurately multi-classify, must convert from # 1 column to 3 columns
y_train = keras.utils.np_utils.to_categorical(y_train,       num_classes=3)
y_test = keras.utils.np_utils.to_categorical(y_test, num_classes=3)# MULTI-CLASSIFICATION
# Evaluating with a Keras NN# fix random seed for reproducibility
seed = 7
np.random.seed(seed)from keras.constraints import maxnorm# Keras neural network deep and wide.
model_keras = Sequential()
model_keras.add(Dropout(0.1, input_shape=(train_vecs_w2v.shape[1],)))
model_keras.add(Dense(500, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.5))
model_keras.add(Dense(800, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.2))
model_keras.add(Dense(1000, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.2))
model_keras.add(Dense(300, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.2))
model_keras.add(Dense(3, activation=’softmax’))epochs = 20model_keras.compile(loss=’categorical_crossentropy’,
 optimizer=’adam’,
 metrics=[‘accuracy’])history = model_keras.fit(train_vecs_w2v, y_train, epochs=epochs, validation_data=(test_vecs_w2v, y_test), batch_size=32, verbose=2)score = model_keras.evaluate(test_vecs_w2v, y_test, batch_size=128, verbose=0)print ‘Evaluated score on test data:’, score[1]# summarize history for accuracy
plt.figure(num=None, figsize=(8, 6), dpi=100, facecolor=’w’, edgecolor=’k’)
plt.plot(history.history[‘acc’])
plt.plot(history.history[‘val_acc’], c=’r’, ls=’dashed’)
plt.title(‘model accuracy’)
plt.ylabel(‘accuracy’)
plt.xlabel(‘epoch’)
plt.legend([‘train’, ‘test’], loc=’upper left’)
plt.hlines(y=score[1], xmin=0, xmax=epochs)
plt.show()# summarize history for loss
plt.figure(num=None, figsize=(8, 6), dpi=100, facecolor=’w’, edgecolor=’k’)
plt.plot(history.history[‘loss’])
plt.plot(history.history[‘val_loss’], c=’r’, ls=’dashed’)
plt.title(‘model loss’)
plt.ylabel(‘loss’)
plt.xlabel(‘epoch’)
plt.legend([‘train’, ‘test’], loc=’upper left’)
plt.show()

所有的分类模型似乎都有一个模式。负面分类总是比其余的低。再看数据,负面情绪值的推文大概占整个数据集的 20%。中性的占 44%,积极的占 33%。下一步是将所有推文限制在相同的数据量。我决定从每个班级随机抽取 4000 个数据点。该数据然后被放入 70/30 的训练测试分割中;70%的数据用于训练,30%用于测试。我的下一步是尝试短而浅的神经网络设置。三个致密层,分别为 32、16 和 3 个神经元。每个密集层之前的三个下降层设置为 0.1、0.3 和 0.2。纪元已更改为 50,批次大小已更改为 2048。

# df is the pandas dataframe object which contains all the clean data# Function to create targets based on compound score
def get_targets(row):
    if row < 0:
        return 0
    elif row == 0:
        return 1
    else:
        return 2# Creating the targets based of the compound value
df['target'] = df['compound'].map(lambda x: get_targets(x))
neg = df[df.target == 0]
neu = df[df.target == 1]
pos = df[df.target == 2]# Randomly sampling tweets to a limit of 4000 each
neg_sampled = neg.sample(4000)
neu_sampled = neu.sample(4000)
pos_sampled = pos.sample(4000)# concating all sampled datasets together
df_test = pd.concat([neg_sampled, neu_sampled, pos_sampled])
df_test.shape# Creating training/testing data, 70/30 split
X_train, X_test, y_train, y_test = train_test_split(df_test.token_text, df_test.target, train_size=0.7)# For every tweet, creating a word vector array for tweet
X_train = np.concatenate([buildWordVector(z, num_features) for z in X_train])
X_train = scale(X_train)X_test = np.concatenate([buildWordVector(z, num_features) for z in X_test])
X_test = scale(X_test)# in order for keras to accurately multi-classify, must convert from 1 column to 3 columns
y_train = keras.utils.np_utils.to_categorical(y_train, num_classes=3)
y_test = keras.utils.np_utils.to_categorical(y_test, num_classes=3)# MULTI-CLASSIFICATION
# Evaluating with a Keras NN# fix random seed for reproducibility
seed = 7
np.random.seed(seed)leng = X_train.shape[1]
X_train = X_train.reshape(X_train.shape[0], 1, leng)
X_test = X_test.reshape(X_test.shape[0], 1, leng)# Keras neural network short and shallow
model_keras = Sequential()
model_keras.add(Dropout(0.1, input_shape=(X_train.shape[1],)))
model_keras.add(Dense(32, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.3))
model_keras.add(Dense(16, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.2))
model_keras.add(Dense(3, activation=’softmax’))# SGD Parameters
learning_rate = 0.01
decay_rate = learning_rate / epochs
momentum = .95
sgd = SGD(lr=learning_rate, momentum=momentum, decay=decay_rate, nesterov=True)model_keras.compile(loss=’categorical_crossentropy’,
 optimizer=’adam’,
 metrics=[‘accuracy’])# Model parameters
epochs = 50
batch = 2048history = model_keras.fit(X_train, y_train, 
 validation_data=(X_test, y_test), 
 epochs=epochs, 
 batch_size=batch, 
 verbose=0)score = model_keras.evaluate(X_test, y_test, 
 batch_size=batch, verbose=0)print ‘Evaluated score on test data:’, score[1]# summarize history for accuracy
plt.figure(num=None, figsize=(8, 6), dpi=100, facecolor=’w’, edgecolor=’k’)
plt.plot(history.history[‘acc’])
plt.plot(history.history[‘val_acc’], c=’r’, ls=’dashed’)
plt.title(‘model accuracy’)
plt.ylabel(‘accuracy’)
plt.xlabel(‘epoch’)
plt.legend([‘train’, ‘test’], loc=’upper left’)
plt.hlines(y=score[1], xmin=0, xmax=epochs)
plt.show()# summarize history for loss
plt.figure(num=None, figsize=(8, 6), dpi=100, facecolor=’w’, edgecolor=’k’)
plt.plot(history.history[‘loss’])
plt.plot(history.history[‘val_loss’], c=’r’, ls=’dashed’)
plt.title(‘model loss’)
plt.ylabel(‘loss’)
plt.xlabel(‘epoch’)
plt.legend([‘train’, ‘test’], loc=’upper left’)
plt.show()

使用 Keras 分类器的试验比以前的模型表现得更好。从回忆分数来看,负数看起来没有以前那么糟糕了。即使每个情感值都有 4000 个数据点,也可能是中性类有更多独特的词。进一步的测试将尝试添加一个 LSTM 层,以便添加一个记忆层,以及一个卷积层,以便找到隐藏的模式。

结论

获得更好的分类器分数所需的数据必须是特定的。它不可能是随机的推文。从字面上看,最负面的词和最正面的词都要被搜索和收集。这样做之后,我相信这个分类器会像 VADER 情感分析一样出色。

汽车品牌的推特情感分析

原文:https://towardsdatascience.com/twitter-sentiment-analysis-on-car-brands-c13d449eb9fc?source=collection_archive---------2-----------------------

Twitter 数据是一个丰富的来源,可以用来获取任何可以想象的话题的信息。这些数据可用于不同的用例,例如寻找与特定关键字相关的趋势、测量品牌情感以及收集关于新产品和服务的反馈。

在这篇文章中,我将从 twitter 中提取各种汽车品牌的数据。然后,我们将应用情感分析来了解在最近一段时间内,人们对不同汽车品牌的正面/负面看法。情感分析是确定一条内容是正面的、负面的还是中性的过程。这也被称为意见挖掘,得出一个发言者的意见或态度。这项技术的一个常见用例是发现人们对某个特定话题的感受。在我们的例子中,我们使用最近推文中的文字来发现人们对不同汽车品牌的感受。

我发现这篇文章和这段视频有助于弄清楚如何从 twitter api 中提取、过滤和处理数据。

#Import the necessary methods from tweepy library
from tweepy import Stream
from tweepy import OAuthHandler
from tweepy.streaming import StreamListener
import time#Variables that contain the user credentials to access Twitter API
#(Note: replace with your own values from [https://apps.twitter.com/](https://apps.twitter.com/))
consumer_key="consumer key"
consumer_secret="consumer secret"
author_token="author token"
author_secret="author secret"class listener(StreamListener):#This is a basic listener that just prints received tweets
def on_data(self, data):
   try:
     #writing data to file
     saveFile = open('tweetDBcars.csv','a')
     saveFile.write(data)
     saveFile.close()
     return(True)
   except BaseException, e:
     print 'failed ondata,',str(e)
     time.sleep(5)def on_error(self, status):
        print statusauth = OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(author_token, author_secret)twitterStream = Stream(auth, listener())# getting tweets that have any of these words
twitterStream.filter(track=['car' 
 'chevy','ford','toyota',
    'acura','kia','audi',
    'chrystler','dodge','ferrari'
    'fiat','buick','cadillac','chevrolet',
    'bmw','honda','jeep','lexus','mazda',
    'mini','nissan','tesla''volvo','saab','porshe'])

我让这个脚本运行了 6 天,累积了大约 115,000 条推文。Twitter api 在类似于 python 字典的 json 数据结构中为我们提供了关于每条 tweet 的大量数据。我们对 tweet 本身的内容感兴趣,可以通过键[“text”]访问它。

在处理大型数据集时,在 try/except 子句中捕获 tweet = json.loads(line)语句非常重要。尽管从 Twitter api 返回的数据通常是干净的,但可能会有错误,如果遇到一行坏数据,您希望避免破坏脚本。try/except 子句允许脚本跳过一行坏数据,继续处理剩余的 tweets。

tweets_data_path = 'twitDBcars.csv'tweets_data = []
tweets_file = open(tweets_data_path, "r")
for line in tweets_file:
    try:
        tweet = json.loads(line)
        tweets_data.append(tweet)
    except:
        continue

现在我们用微博创建一个熊猫数据框架

tweets = pd.DataFrame()index = 0
for num, line in enumerate(tweets_data):
  try:
     print num,line['text']
     tweets.loc[index,'text'] = line['text']
     index = index + 1 
 except:
     print num, "line not parsed"
     continue

为了提取关于特定品牌的推文,我们将每条推文中的单词与我们感兴趣的每个品牌的名称进行比较。如果我们找到了我们正在寻找的品牌,我们会在数据框中的新列“品牌名称”中对其进行跟踪。

def brand_in_tweet(brand, tweet):
    brand = brand.lower()
    tweet = tweet.lower()
    match = re.search(brand, tweet)
    if match:
        print 'Match Found'
        return brand
    else:
        print 'Match not found'
        return 'none'

下一步是评估每条推文的情绪。有几种方法可以进行情感分析。

从业者最常描述的有两种方法:

  • 一种方法是收集一堆推文,让人们给它们贴上积极或消极的标签。然后使用已标记的数据集来训练算法,如朴素贝叶斯或随机森林。然后,训练好的模型可以用于新的数据,以估计情绪。
  • 第二种方法是使用词典,我们将推文中的单词与词典中的单词(或 n-grams)进行比较,以对每个单词的积极/消极情绪进行评分。然后,我们将每条推文的单词分数相加,得出推文的情感分数。

在本帖中,我们将通过使用 TextBlob 包来使用第二种方法。我们使用 TextBlob 的极性方法来查找每条推文的情感得分,并将其记录在 dataframe 中的新列“sentscore”中。(关于 TextBlob 如何计算情感得分的更多详细信息,请点击查看。)

from textblob import TextBlobfor index, row in tweets.iterrows():
    temp = TextBlob(row['text'])
    tweets.loc[index,'sentscore'] = temp.sentiment.polarity

我喜欢使用 ggplot 进行数据可视化,因为它强大而灵活,所以我将把数据帧写入一个 csv 文件,该文件可以导入到 r。

 for column in tweets.columns:
    for idx in tweets[column].index:
        x = tweets.get_value(idx,column)
        try:
            x = unicode(x.encode('utf-8','ignore'),errors ='ignore')          
            if type(x) == unicode:
                unicode(str(x),errors='ignore')
            else: 
                df.set_value(idx,column,x)
        except Exception:
            print 'encoding error: {0} {1}'.format(idx,column)
            tweets.set_value(idx,column,'')
            continue
tweets.to_csv('tweets_export.csv')

让我们读取 R 中的数据,并直观地检查这些数据

df_tweets = read.csv("tweets_export.csv")#let us look at the mean of sentiment scores for all brands
data_brand = df_tweets %>%
   group_by(brand) %>%
   summarise(mean_sentiment_score = mean(sentscore))ggplot(data=data_brand, aes(x=brand, y=mean_sentiment_score))+
  geom_bar(stat = "identity", aes(fill = brand))

我们注意到雷克萨斯的正面喜好度最高,丰田的负面喜好度最高。假设我们代理的客户是一家汽车经销商,他们想决定增加对哪些品牌的投资,这种从经销商身边的人那里收集的信息可能非常有用。

现在让我们更仔细地研究 3 个品牌:

#We subset the data for the brands ford, mini and kia to drill down into the variance of their sentiment over timedata_week <- df_tweets[df_tweets$brand %in% c("ford","mini","kia"),]ggplot(aes(x = day, y = sentscore), data = data_week) + 
  geom_smooth(aes(colour = brand))

随着时间的推移,起亚的正面喜好度有所上升,而福特的正面喜好度有所下降。假设我们是一家咨询公司,福特是我们的客户之一,我们需要进一步挖掘细节,以了解为什么积极情绪正在减少。

这是非常初步的分析。为了实现情感分析的高准确度,需要考虑几个因素,例如语言、领域、人口、年龄、俚语、词汇分析等。脸书和 AOL 面临的一些挑战和采取的方法分别在这里和这里讨论。我希望在不久的将来进一步研究这一分析。

同一主题的其他重要资源:

  1. 用 twitter 分析大数据 —来自伯克利分校的视频和幻灯片——由来自 twitter 的员工演示的讲座。
  2. 分析推文中表情符号的情感
  3. 如何构建 twitter 情感分析器
  4. 用 python 挖掘 twitter 数据(图书)
  5. twitter 用户对薄荷烟的看法:内容和情感分析(研究论文)

我的其他项目很少在这里

Python NumPy 的两个很酷的特性:通过切片和广播进行变异

原文:https://towardsdatascience.com/two-cool-features-of-python-numpy-mutating-by-slicing-and-broadcasting-3b0b86e8b4c7?source=collection_archive---------1-----------------------

NumPy 是纯金。它快速、易学、功能丰富,因此是 Python 世界中几乎所有流行科学包的核心(包括 SciPy 和 Pandas ,这两个包在数据科学和统计建模领域应用最广泛)。在本文中,让我们简要讨论 NumPy 的两个有趣的特性,即。切片突变

切片突变

事实证明,如果使用 NumPy 的简单切片/索引来创建子数组,子数组实际上指向主数组。简单地说,内存中的图表看起来像,

因此,如果切片数组被更改,它也会影响父数组。这可能是一个有用的特性,可以将所需的链传播到食物链的上游,但有时也可能是一个麻烦,因为您需要保持主数据集不变,并且只对子集进行更改。在这些情况下,您必须显式调用 np.array 方法来定义切片数组,而不仅仅是通过索引来切片。下面的代码说明了这一点,

说明性代码

mat = np.array([[11,12,13],[21,22,23],[31,32,33]])
print("Original matrix")
print(mat)
**mat_slice = mat[:2,:2] # *Simple indexing***
print ("\nSliced matrix")
print(mat_slice)
print ("\nChange the sliced matrix")
mat_slice[0,0] = 1000
print (mat_slice)
print("\nBut the original matrix? WHOA! It got changed too!")
print(mat)

结果看起来像是,

Original matrix
[[11 12 13]
 [21 22 23]
 [31 32 33]]

Sliced matrix
[[11 12]
 [21 22]]

Change the sliced matrix
[[**1000**   12]
 [  21   22]]

But the original matrix? WHOA! **It got changed** too!
[[**1000**   12   13]
 [  21   22   23]
 [  31   32   33]]

为了阻止这种事情发生,这是你应该做的,

# Little different way to create a copy of the sliced matrix
print ("\nDoing it again little differently now...\n")
mat = np.array([[11,12,13],[21,22,23],[31,32,33]])
print("Original matrix")
print(mat)
**mat_slice = np.array(mat[:2,:2]) *# Notice the np.array method***
print ("\nSliced matrix")
print(mat_slice)
print ("\nChange the sliced matrix")
mat_slice[0,0] = 1000
print (mat_slice)
print("\nBut the original matrix? NO CHANGE this time:)")
print(mat)

现在,子矩阵中的任何变化都不会改变原始矩阵,

Original matrix
[[11 12 13]
 [21 22 23]
 [31 32 33]]

Sliced matrix
[[11 12]
 [21 22]]

Change the sliced matrix
[[**1000**   12]
 [  21   22]]

But the original matrix? **NO CHANGE** this time:)
[[**11** 12 13]
 [21 22 23]
 [31 32 33]]

广播

NumPy 操作通常是在逐个元素的基础上对数组对进行的。在一般情况下,两个数组必须具有完全相同的形状(或者对于矩阵乘法,内部维度必须一致)。

当数组的形状满足某些约束 时,NumPy 的 广播规则放松了这个约束。当操作两个数组时,NumPy 按元素比较它们的形状。它从尾部维度开始,向前推进。在以下情况下,二维是兼容的

  • 它们相等,或者
  • 其中一个是 1

如果不满足这些条件,就会抛出一个value error:frames not aligned异常,表明数组具有不兼容的形状。结果数组的大小是沿着输入数组的每个维度的最大大小。

更多详情请查阅:https://docs . scipy . org/doc/numpy-1 . 10 . 1/user/basics . broadcasting . html。

下面的代码块按部就班地说明了这个想法,

用零初始化“开始”矩阵

start = np.zeros((4,3))
print(start)[[ 0\.  0\.  0.]
 [ 0\.  0\.  0.]
 [ 0\.  0\.  0.]
 [ 0\.  0\.  0.]]

创建一个行矩阵(向量),

# create a rank 1 ndarray with 3 values
add_rows = np.array([1, 0, 2])
print(add_rows)[1 0 2]

将零矩阵(4x3)与(1x3)向量相加。自动地,1×3 向量被复制 4 次以使匹配零矩阵的行尺寸,并且这些值被添加到 4×3 矩阵中。

y = start + add_rows  # add to each row of 'start'
print(y)[[ 1\.  0\.  2.]
 [ 1\.  0\.  2.]
 [ 1\.  0\.  2.]
 [ 1\.  0\.  2.]]

创建列矩阵(向量),

# create an ndarray which is 4 x 1 to broadcast across columns
add_cols = np.array([[0,1,2,3]])
add_cols = add_cols.T
print(add_cols)[[0]
 [1]
 [2]
 [3]]

将零矩阵(4x3)与(4x1)向量相加。自动地,4x1 向量被复制 3 次以使匹配零矩阵的列维度,并且这些值被添加到 4x3 矩阵中。

# add to each column of 'start' using broadcasting
y = start + add_cols 
print(y)[[ 0\.  0\.  0.]
 [ 1\.  1\.  1.]
 [ 2\.  2\.  2.]
 [ 3\.  3\.  3.]]

最后,标量被视为 1x1 矩阵,并精确复制到加法矩阵的大小以执行运算。

# this will just broadcast in both dimensions
add_scalar = np.array([100])  
print(start+add_scalar)[[ 100\.  100\.  100.]
 [ 100\.  100\.  100.]
 [ 100\.  100\.  100.]
 [ 100\.  100\.  100.]]

当您使用 NumPy 数组为像梯度下降这样的算法编写矢量化代码时,广播的效用得到了最好的实现。吴恩达 花了一个全视频讲座 **在他新的深度学习课程中用 Python 解释广播的概念。**它使得深度神经网络的前向和反向传播算法的实现相对无痛。

你也可以看看这个关于广播功能演示的视频…

Numpy Broadcasting explanation video

如有问题或想法分享,请联系作者tirthajyoti【AT】Gmail . com。你也可以查看作者的 GitHub 知识库 中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。也可以在 LinkedIn 上关注我。

佛罗里达大学学生政府选举二十年:使用机器学习获得更深刻的见解

原文:https://towardsdatascience.com/two-decades-of-uf-student-government-elections-using-machine-learning-for-deeper-insights-c137c0586466?source=collection_archive---------7-----------------------

三年前,我上了一堂统计学课,这门课涉及回归技术,除了统计学,我什么都不想。像班上的大多数人一样,我发现统计学很无聊、乏味,在我的日常生活中毫无用处。

怀着一丝希望,我问我的教授,我是否可以在我们刚刚被分配的回归项目中调用 audible,并尝试预测学生会选举的结果。从那以后,随着我在数据科学职业生涯中的进步,我从越来越学术和技术的角度零星地参与了这个项目。

这篇文章的其余部分将包含我的发现,我的失败,它们背后的数据,以及如何自己尝试这种类型的工作的说明。希望在我今年 12 月毕业后,其他学生可以利用这些数据,创建更好的模型和更有趣的见解。

数据

对于任何参与过地方选举的人来说,这并不奇怪,但是选举结果却保存在不同格式的几乎无法阅读的 pdf 文件中。通过 pdf 到文本转换器和手抄结果的结合,创造了整个 21 世纪 SG 选举的历史。

关于数据需要注意一些事情(在我的 github 上找到)。“Est”代表建立,我也称之为系统。该系统已经在学术上得到广泛研究,最突出的工作来自大卫·布拉德肖,他在 2013 年写了一篇关于它的论文。他(恰当地)将这一体系定义为“一个令人惊讶的复杂的赞助和讨价还价体系”,即“佛罗里达大学希腊社区的绝大多数和校园内几个最著名的非希腊学生组织的联盟,其中许多组织代表特定的少数群体,通常被称为“社区”。这些社区主要由亚裔美国学生联合会(AASU)、西班牙裔学生联合会(HSA)和黑人学生联合会(BSU)组成。学生政府的职位在希腊各学院之间进行交易,并给予社区的杰出成员,以创造多样性和包容性的外观。该系统在整个 20 世纪 70 年代和 80 年代在佛罗里达大学掌权,以确保除了上层阶级的白人男性,尤其是当时正在整合佛罗里达大学的有色人种,任何人都不能获得校园中重要和有声望的职位。你可以在这里或阅读更多关于系统的信息,甚至可以在这里观看一个关于它的视频,但这个项目的主旨是通过一个统计镜头来探索 SG。

通过探索性数据分析的独立机会

探索性数据分析(或 EDA)在技术上是“分析数据的过程,解释这些过程的结果的技术,以及规划数据收集以使其分析更容易的方法”,这只是“对数据提出问题”的一种更长的说法

数据库完成后,我的第一个问题是“这个系统在 21 世纪的主导地位如何?”系统党赢得了每一次总统选举,除了两次,一次是在 2004 年与贾迈勒·索维尔,另一次是在 2015 年与约瑟林·帕德隆-拉辛斯,但更细致的分析可能吗?我看了一下参议院,并绘制了自 2000 年以来春季选举的胜率,发现独立政党平均只赢得了他们竞选的 21.5%的选票,而系统政党赢得了令人震惊的 81.5%的选票(T3)。这是因为有些年份有多个独立政党,而有些年份则有无竞争的选举。

这张图显示了不同时间的差异。

Winning percentage over the years

事实证明,除了几场选举,这个系统已经成功赢得了绝大多数的选举。有鉴于此,独立政党什么时候表现得好?下面是一张成功聚会的图表,按机构、聚会时间(聚会在校园里有多长时间)分类。

Winning percentage by age of party

独立党派在 T4 的第一个学期和第二个学期表现最好,随着年龄的增长,他们的表现越来越差。随着时间的推移,建制派似乎也变得越来越差,但下降速度要慢得多。

很明显,当权派会赢(在很大程度上是因为贿赂有职位的学生和酒精,以及扣留 食物直到他们投票)。那么独立党派如何才能获胜呢?显然,一个答案是在校园的第一个学期集中精力进行选举,那时的投票率平均要高得多。但另一个潜在的努力是针对个别参议院席位。

SG 选举分为秋季和春季选举,秋季参议员按地理区域(宿舍或邮政编码)选举,春季参议员按学院(工程、商业)或年级(大一、大二)选举。就像在全国选举中一样,有些席位选举系统候选人的比率远远高于已经相当高的平均比率,即使经过一段时间。例如,在 A 区(校园东面的区域,包括所有的女生联谊会和附近的公寓楼),几乎从来没有一个席位是由非体制或独立党派赢得的。根据年份的不同,A 区控制着参议院的大约 5% 到 10% 的席位。

也有倾向独立投票的席位。下面是独立党派的席位胜率图,给出了一个(伪)权力排名。在收集数据时,无穷大的样本大小是 1,平均值肯定是失真的。除此之外,独立党派赢得 50%以上的席位只有两个,家庭住房和毕业。

选举建模

在选举建模领域,学者和媒体机构经常使用所谓的基本面来预测选举结果。大卫·拜勒目前正在为 2018 年 11 月的参议院模型工作,他比我更好地定义了基本面,他说

“基本面基本上涵盖了直接投票之外的一切——总统的批准,……该州过去的选举结果,候选人的信息。”

这基本上是我们所拥有的数据。当处理这样的问题时,我想到了两种主要的方法。

支持向量机

首先,我想创建一个算法,如果数据被投射到二维空间,将能够创建一个超平面(在二维空间,这看起来像一条线。在我们的例子中,它作为一个多维平面存在,具有与数据相同的维数,将每次选举(给定年份、政党年龄、以前的选举结果、候选人数量等)分为两类,即获胜和失败。在数据科学中,我们称之为线性分类器。这项工作有很多潜在的算法,从 K-Nearest Neighbors 到 Perceptron,K-Nearest Neighbors 可以在训练集中找到 K 个最近的点,并允许每个点对预测进行投票,Perceptron 可以根据获得的每个新数据更新算法的权重。我最终选择了 SVM(支持向量机)分类器,因为我从理论上认为,有大量的选举很容易预测,而有少量的选举要困难得多。这让我想到了 SVM 分类器,因为 SVM 在线性分类器中最大化了相近案例之间的间隔。如果最后一段对你来说没有意义,那 100%没关系,因为一些聪明的人制作了一个图表,使这更容易理解。

有相当多的线可以将这两个类别分开,但是 SVM 找到了最大化这两个类别之间差距的线,这正是我们想要的。

在对数据进行大规模清理之后,我使用了 caret 包(用于预测建模/机器学习/统计分析,无论你喜欢怎么称呼它)来实现 SVM 算法。结果呢?回溯测试的准确率约为 80%。附上混淆矩阵(顶行是预测,第一列是实际结果。因此,这可以理解为“对于 SVM 预测参议员将会失败的选举,它得到了 130 个正确和 34 个不正确”)。

这个在 2018 年春季选举前创建的算法预测,Inspire(独立党)将赢得研究生参议院席位,并将输掉所有其他竞争性选举。在这种情况下,它预测了一个行政门票清扫和一个 38/50 参议院系统崩溃。事实证明这几乎是真的,Inspire 赢得了研究生院、牙科和美术院的席位,失去了所有其他竞争席位。参议院的总结果是 36/50 加上行政人员的票数,大约是 96% 准确。还不错!然而,我们得到的精确度超出了 95%的置信区间(精确度在 76%和 84%之间),这可能是 2018 年选举中有第三个政党(尽管相当无组织和草率)而不是通常的两个政党的作用。有一点也是肯定的,政党数量的增加对独立政党赢得的参议院席位数量有显著的影响,对 2018 年春季的选举有影响。

随机森林

我想尝试的第二种方法是使用决策树(到目前为止,我最喜欢的决策树可以在这里找到)。同样,决策树有几十种不同的实现和评分机制,包括经典的分类和算法树,以及像 Boosted 树和 Random Forest 这样的集合树(可以在这里找到一篇很好的背景实现文章)。从图形上看,决策树是这样的。

What should I do with my night? A analysis with decision trees

这是一个相当简单,但非常有用的方法。一个更健壮的模型被称为随机森林,它将大量决策树与随机选择的变量相结合,并使用一组(可能相当糟糕)预测算法来创建一个新模型(这被称为集成学习)。我认为这个模型会表现得更好,因为决策树通常是我对选举的看法。候选人在商学院竞选吗?他们在系统中运行吗?那么他们很可能会赢。

实施后,我们得到了这个混淆矩阵,它转化为 89%的准确率,远远高于 SVM 方法。

随机森林算法的另一个好处是,由于它选择不同变量的方式,我们可以推导出每个变量的重要性(注意:X 轴上的 MeanDecreaseGini 是衡量类别杂质的一种方式。基尼系数的平均降幅越高,意味着该变量越重要)。

不出所料,影响最大的两个变量是席位和候选人是否是体制的一部分。考虑到这一点,仍然有人说这个系统不存在,因为它似乎能很好地预测选举结果,这确实显得很愚蠢。

在 2018 年春季选举中使用随机森林方法,随机森林在 SVM 分类器上的表现完全相同(96%),但在测试数据上的准确率更高,为 89%。尽管如此,我还是决定在推特上发布一个略有改动的预测,说我认为 Inspire 将与工程学和 CLAS 一起赢得毕业生奖。不出所料,人类的表现远不如算法,工程和 CLAS 都受到了影响。吸取教训。

结论:事实证明机器学习是可行的

在整个项目中,我一直着迷于了解联合阵线选举的可预测性,即使是通过前美国参议员兼佛罗里达州州长鲍勃·格雷厄姆描述的选举

"在州和联邦政治中,我从未遇到过像佛罗里达大学那样咄咄逼人的活动."

我最初的目标是预测选举结果,在理解了数据并尝试了几次之后,我对结果非常满意。同样,数据和脚本都是公开的,我随时可以回答关于数据科学、用友 SG、它们的交集或者具体这个项目的问题。通过电子邮件联系我,或者在推特上找到我。

最后一点,我试图用所有领域的专业知识创建这些模型,但没有对系统如何积极地使佛罗里达大学成为一个更糟糕的地方发表意见,并且没有任何好的理由让任何人参与到 20 世纪 70 年代的活遗迹中。但我确信我的偏见会渗透进来。

我想公开感谢 William Ferra,他在该项目的数据收集和清理部分发挥了不可估量的作用。如果没有他,这个项目是不可能的,或者至少要花更长的时间。

两个比一个好:集合模型

原文:https://towardsdatascience.com/two-is-better-than-one-ensembling-models-611ee4fa9bd8?source=collection_archive---------4-----------------------

组装起初听起来像是一个非常吓人的词,但实际上看起来很简单…让我用一个类比来解释集合

Ensembling algorithms to obtain the cake of accuracy

集成有点像整个周末都在看网飞(通用 ML 算法),这很好,但结合一些披萨或一个特殊的朋友,你就可以放松了,我说的“放松”是指达到 90%的准确率

因此,基本上集成/组合两个或更多的算法可以改善或提高你的性能。但是在组合的背后有一个逻辑…你不能只是随机地组合两个模型,并要求提高精确度…每件事背后都有一个数学…..因此,让我们深入探讨几种您可以尝试的组装方法…(如果你喜欢那种东西)

简单平均/加权法:

名字说明了一切…这种组合方法只取两个模型的平均值。但是这是怎么做到的…是山达基吗?

假设你已经使用了名为的算法将和结果是

*Actual_targets: 1 0 1 1 0 1**Predicted vals: 1 0 1 0 1 0*

现在你使用另一种叫做格雷斯的算法,结果是

*Actual_targets: 1 0 1 1 0 1**Predicted vals: 0 1 0 1 0 1*

威尔正确预测了前三个目标,而格雷斯正确预测了后三个目标

如果我们结合这两种算法(WILL & GRACE ),我们会得到一个相当不错的情景喜剧,我们的准确性肯定会增加。这是一个平均模型背后的想法,它是一个非常基本的集合案例。

你可以使用 Sklearn 的投票分类器轻松实现这一点,它甚至允许你为每个算法分配权重。

from sklearn.ensemble import VotingClassifier
ensemble=VotingClassifier(estimators=[('Decision Tree', decisiontree), ('Random Forest', forest)], 
                       voting='soft', weights=[2,1]).fit(train_X,train_Y)
print('The accuracy for DecisionTree and Random Forest is:',ensemble.score(test_X,test_Y))

我们可以根据性能分配权重或取平均值,即给算法设置相等的权重。

装袋方法:

装袋方法和前面的很像,但是我们不用威尔和格蕾丝,而是用速度和激情 1,2,3,4,5,6。这意味着我们不用不同的模型,而是用同一个模型的不同版本。

随机森林是一个著名的 bagging 模型,它使用了多棵树的变种。如果使用相同的树,那么它就是一个袋装决策树。

但是为什么装袋有效呢?我们不是又在做同样的事情吗?

让我们考虑一个模型正在训练,它注意到一个实例,一个蓝眼睛、红衬衫、带着笔记本电脑的白人男子坐在星巴克,我们需要找出他是一个有抱负的编剧的概率…现在,该模型似乎已经深入到无法预测它开始证明这种流行刻板印象的每一个实例的概率。每个符合上述描述的白人都不是编剧…..(他可能是 tho)

总的来说,当一个模型概括了一些它不应该概括的东西时,它有很高的方差,打包可以减轻这个问题

使用 Bagging 确保预测不会读取高方差。

bagging 模型中的每个模型(bag)彼此略有不同,并确保我们不会停留在非常深的表示上,并输出一个对测试集更友好的预测。

下面是随机森林的代码,一种装袋方法

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(dataset.drop('target'),dataset['target'])
trained_model = random_forest_classifier(train_x, train_y)
predictions = trained_model.predict(test_x)

增压方法:

因此,在前面的示例中,我们要么采用几个独立的模型并计算它们的平均值,要么计算它们的加权平均值,但如果我们考虑我们之前的模型表现如何,并将其合并到我们的下一个模型中,会怎么样呢…..有点像用以前模型的预测来推动新模型…好了,你知道了…这就是助推的作用。

此外,重要的是要注意,模型是按顺序添加到集合中的。Boosting 有时会通过减少偏差、方差和许多 kagglers 微调 boosting 算法来获得非常棒的结果。

基于重量的助力:

假设您正在训练一个模型,其中根据预测为每个预测的标签分配一个权重(好的预测意味着权重较小,坏的预测意味着权重较大)。这有点像因果报应,除了升压不是一个婊子。

这些权重在集合中的每个模型上累加,随着权重的增加,你明白你需要更好地预测它们,并且你开始将你的模型集中在它们上,而不是那些权重较低的模型上。这一直持续到达到最大精确度或最大模型数量。

这些重量有点像现实生活中的重量,一个人收获越多,自尊越低,因此需要去健身房,这里健身房是助推算法…..你总是需要在健身房得到激励…:)

例如:Adaboost,强分类器是权重低的地方,弱分类器是权重高的地方。Adaboost 旨在通过添加模型和纠正以前模型的错误,将弱分类器转换为强分类器(必修教科书定义)

*class* sklearn.ensemble.**AdaBoostClassifier**(*base_estimator=None*, *n_estimators=50*, *learning_rate=1.0*, *algorithm=’SAMME.R’*, *random_state=None)*

残基助推:

在这种类型的提升中,我们分配权重的绝对值(预测和实际标签之间的差异),并将其作为新变量分配给下一个模型。但是为什么呢?。…..考虑以下情况

Actual value : 1
Predicted Val: 0.75
Weight       : 0.25For next model let use this weight to minimize the error in the next model where we predict the value

Whaaaaat 所以只要插入一个损失函数,像梯度下降…是的…这种方法也可以被称为梯度推进

这里梯度指的是有限差分,而不是导数

这种方法的一些优点

  • 没有过度拟合(使用学习率)
  • 我们不依赖单一的预测树(估计数)

为了防止过度拟合,我们可以采用深度学习的辍学概念,并将其应用于集成,这确保了随机性和正则化,并确保我们的模型能够很好地推广。即。如果我们在集合中构建了 4 棵树,那么在构建第五棵树时,我们会故意忽略 2 棵随机的树。例如:DART(漏失符合多重可加回归树)。

很多开发者用来赢得比赛的超级棒的助推算法是

  • Xgboost (极限梯度提升),
  • Lighbgm (垂直增长的非常快速的梯度推进)
  • Catboost(带有良好的初始参数,可以自动编码分类变量)。

希望你觉得这篇文章有用和有趣…..

两个月探索深度学习和计算机视觉

原文:https://towardsdatascience.com/two-months-exploring-deep-learning-and-computer-vision-3dcc84b2457f?source=collection_archive---------5-----------------------

I’ve been reading/note taking is using an iPad Pro and LiquidText

我决定熟悉计算机视觉和机器学习技术。作为一名 web 开发人员,我发现这个不断发展的领域令人兴奋,但是我没有任何使用这些技术的相关经验。我将开始为期两年的旅程来探索这个领域。如果你还没有读过,你可以在这里看到第 1 部分:从 webdev 到计算机视觉和地理。

I️最终通过探索 I️拥有的任何激发自己学习的机会来让自己动起来。我最初并没有停留在研究机器学习上,但我想回到对某个主题感到兴奋的状态。I️通过参加为期一天的加密货币学术会议开始了我的研究,到下午会议开始时,我意识到机器学习和计算机视觉对我来说更有意思。

入门指南

大约在一本关于深度学习和计算机视觉交叉领域的伟大著作出版的时候,I️启动了我的探索。来自 PyImageSearch.com 的作者Adrian rose Brock汇编了一部关于计算机视觉和深度学习的高级思想和低级应用的三卷巨著。在探索深度学习的过程中,I️遇到了对线性回归、朴素贝叶斯应用(I️现在意识到,I️已经听到这个名字有很多不同的发音)、随机森林/决策树学习以及所有其他我正在屠杀的东西的无数解释。

I️花了几周时间阅读这本书,并感觉 I️可以将我迄今为止阅读的所有不同的博客帖子与一系列数学概念、抽象概念和实际编程应用联系起来。我快速通读了这本书,并且对如何将这个领域作为一个整体有了更好的理解。我最大的收获是得出了这样的结论:I️想要巩固我自己的工具和硬件,以构建计算机视觉软件。

硬件实现

I️受到启发,得到了一台 Raspberry Pi 和 RPI 相机,I️可以用它来分析视频流。我一点也不知道设置树莓酱会花很长时间。最初,I️希望简单地启动并运行一个视频流,然后在我的电脑上处理视频。I️努力让树莓 Pi 操作系统工作起来。然后,一旦 I️意识到什么是错的,I️不小心安装了错误的图像驱动程序,并意外地安装了冲突的软件。I️最初认为这个过程会充满对相机图像的处理,结果却变成了一场耗时数小时的调试噩梦。

到目前为止,I️已经意识到这是机器学习的一个重要开始,而计算机视觉的“东西”是关于调试的。

第一步。得到一个想法。
第二步。开始寻找做这件事的工具。
第三步。安装所需的软件。
第四步。淹没在冲突和意外的包版本问题中。

https://aiyprojects.withgoogle.com/vision#list-of-materials

树莓派背后我最初的灵感是建立一个简单的设备,有一个摄像头和 GPS 信号的想法。这个想法是基于对未来有多少车辆,自动驾驶或车队车辆,将需要许多摄像头进行导航的思考。无论是出于保险目的还是为了基本功能,I️设想将会有大量的视频素材被创建和使用。在这个过程中,将会有大量的媒体储存库闲置不用,成为了解世界的丰富数据源。

I️最终探索了树莓派的计算机视觉能力,但从未像我希望的那样成功地获得任何有趣的工作。I️发现有许多更便宜的类似树莓派的设备,它们在比全尺寸树莓派更小的 PCB 板上同时具有互连性和相机功能。后来,I️意识到,与其走硬件路线,I️还不如用一部旧 iPhone,开发一些软件。

我在探索深度学习的硬件组件方面的短暂尝试让我意识到,我应该尽可能坚持软件。当软件部分没有解决时,包含一个新的变量只会增加复杂性。

开源工具

在寻找机器学习资源的第一个月,我发现了许多开源工具,它们使启动和运行变得非常容易。我知道方科技公司提供了许多专有服务,但我不确定他们如何与开源软件竞争。可以作为 SAAS 工具使用的图像识别和 OCR 工具来自 IBM、Google、Amazon 和 Microsoft,非常容易使用。令我惊讶的是,有很好的开源替代方案值得配置,以避免不必要的服务依赖。

例如,几年前,我推出了一个 iOS 应用程序,用来收集和分享涂鸦照片。我从带有地理标签的公开 API 中检索图片,比如 Instagram 和 Flickr。利用这些来源,我使用基本特征,如标签和位置数据,来区分图像是否真的是涂鸦。最初,我开始每周拉几千张照片,很快就增加到一个月几十万张。我很快注意到,我索引的许多图像不是涂鸦,而是对我试图培养的社区具有破坏性的图像。我无法阻止人们自拍的低质量照片或对工作不安全的糟糕标记的图像加载到人们的订阅源中。因此,我决定关闭整个项目。

#graffiti results on instagram

现在,有了机器学习服务和用于对象检测和裸体检测的开源实现,我可以推出自己的服务,轻松检查每张被索引的照片。以前,如果我支付一项服务来进行质量检查,我会在 API 费用上花费数百美元,如果不是数千美元的话。相反,我现在可以从一些“数据科学”AWS 盒子下载一个 AMI,并创建自己的 API 来检查不想要的图像内容。这对我来说遥不可及,甚至就在两年前。

概观

在很高的层面上,在经历这个过程之前,我觉得自己理论上理解了大部分的物体识别和机器学习过程。在开始将我一直在消费的所有机器学习内容之间的点连接起来的过程之后,我觉得我对我需要学习的概念更加清楚了。例如,我不仅仅知道线性代数对机器学习很重要,我现在理解了问题如何被分解成多维数组/矩阵,并被大量处理以寻找仅在理论上可表示的模式。之前,我知道在特性之间有一些抽象,以及它们如何被表示为可以在一系列评估项目之间进行比较的数字。现在,我更清楚地理解了在机器学习的背景下,维度是如何通过纯粹的事实来表示的,即有许多因素直接或间接相互关联。特征检测和评估的多维方面的矩阵数学对我来说仍然是一个谜,但是我能够理解高层次的概念。

The previously illegible network architecture graphs are now seemingly approachable.

具体来说,阅读 Adrian Rosebrock 的书给了我解读机器学习算法的盒线图的洞察力。深度学习网络架构的崩溃现在有些可以理解了。我还熟悉常用于测试各种图像识别模型的数据集(MNIST、CIFAR-10 和 ImageNet),以及图像识别模型之间的差异(如 VGG-16、Inception 等)。

时机——公共资金

我认为现在学习机器学习和计算机视觉很重要的一个原因与我从这本书中学到的一个概念有关:政府在研究方面投入大量资金的领域将会有巨大的创新。目前,除了分配给特定机器学习相关项目的特定资金外,还有数亿美元以赠款和奖学金的形式花费在研究项目上。

Example of pix2pix algorithm applied to “cat-ness”. https://distill.pub/2017/aia/

除了政府支出,来自私人机构的公开研究似乎也在增长。目前存在的研究形式,来自大型科技公司和公共基金会,正在推动整个机器学习领域。我个人从未见过像 distill.pub 这样的出版物和 OpenAI foundation 这样的集体形式的私人机构资助的公共项目如此集中。他们所做的工作是无与伦比的。

可行的任务

回顾我一直在阅读的材料,我意识到我的记忆力已经开始衰退了。从现在开始,我要做更多的行动导向的阅读。我现在有一个装有 GPU 的盒子,所以我觉得在训练模型和处理数据集方面没有任何限制。

最近,我参加了一个由 Carto 主办的关于空间数据科学的大型会议。在那里,我非常清楚地意识到我在空间数据科学领域有多少知识。在会议之前,我只是把整个领域称为“地图定位数据的东西”。

我会继续努力在网上结识有相似兴趣的不同的人。我已经能够对我找到的住在纽约并写了与我当前搜索相关的中型帖子的人这样做了。最近,在探索如何构建一个 GPU 盒子时,我得以与一位机器学习探索伙伴共进早餐。

到一月中旬,我希望熟悉围绕涂鸦图像训练模型的技术框架。我认为至少,我希望有一组要处理的图像,将图像关联到的标签,以及对照已训练的标签交叉检查未索引图像的过程。

感谢 Jihii Jolly 纠正我的语法。

深度学习中不同类型卷积的介绍

原文:https://towardsdatascience.com/types-of-convolutions-in-deep-learning-717013397f4d?source=collection_archive---------0-----------------------

让我给你一个快速概述不同类型的卷积和他们的好处。为了简单起见,我只关注 2D 卷积。

回旋

首先,我们需要就定义卷积层的几个参数达成一致。

2D convolution using a kernel size of 3, stride of 1 and padding

  • 内核大小:内核大小定义卷积的视野。2D 的常见选择是 3,即 3x3 像素。
  • 步幅:步幅定义了内核遍历图像时的步长。虽然其默认值通常为 1,但我们可以使用步幅 2 对图像进行缩减采样,类似于 MaxPooling。
  • 填充:填充定义如何处理样本的边框。(一半)填充卷积将保持空间输出维度等于输入维度,而如果内核大于 1,未填充卷积将裁剪掉一些边界。
  • 输入&输出通道:卷积层取一定数量的输入通道(I),计算出特定数量的输出通道(O)。这种层所需的参数可以通过 IOK 来计算,其中 K 等于内核中值的数量。

扩张的回旋

(又名 atrous 卷积)

2D convolution using a 3 kernel with a dilation rate of 2 and no padding

膨胀卷积为卷积层引入了另一个参数,称为膨胀率。这定义了内核中值之间的间距。膨胀率为 2 的 3×3 内核将具有与 5×5 内核相同的视野,同时仅使用 9 个参数。想象一下,取一个 5x5 的内核,每隔一行删除一列。

这以相同的计算成本提供了更宽的视野。膨胀卷积在实时分割领域特别流行。如果你需要一个宽广的视野并且不能负担多重卷积或者更大的内核,使用它们。

转置卷积

(又名去卷积或分数步长卷积)

有些资料来源使用反卷积这个名称,这是不恰当的,因为它不是反卷积。更糟糕的是,反进化确实存在,但它们在深度学习领域并不常见。实际的反卷积反转了卷积的过程。设想将一幅图像输入到一个卷积层中。现在拿出输出,把它扔进一个黑盒子里,你的原始图像又出来了。这个黑盒做反卷积。这是卷积层的数学逆运算。

转置卷积有些类似,因为它产生的空间分辨率与假设的反卷积图层相同。然而,对这些值执行的实际数学运算是不同的。转置卷积层执行常规卷积,但恢复其空间变换。

2D convolution with no padding, stride of 2 and kernel of 3

在这一点上你应该很困惑,所以让我们看一个具体的例子。一个 5x5 的图像被送入卷积层。步幅被设置为 2,填充被停用,并且内核是 3x3。这会产生一个 2x2 的图像。

如果我们想逆转这个过程,我们需要逆向数学运算,这样我们输入的每个像素就产生 9 个值。之后,我们以步长 2 遍历输出图像。这将是一个反卷积。

Transposed 2D convolution with no padding, stride of 2 and kernel of 3

转置卷积不会这样做。唯一的共同点是,它保证输出也将是 5x5 图像,同时仍执行正常的卷积运算。为了实现这一点,我们需要对输入进行一些花哨的填充。

正如你现在所能想象的,这一步不会逆转上面的过程。至少不考虑数值。

它仅仅从以前重建空间分辨率并执行卷积。这可能不是数学上的逆运算,但对于编码器-解码器架构来说,它仍然非常有用。这样,我们可以将图像的放大与卷积结合起来,而不是进行两个独立的过程。

可分卷积

在可分离卷积中,我们可以将核操作分成多个步骤。让我们将一个卷积表示为 y = conv(x,k) 其中 y 为输出图像, x 为输入图像, k 为内核。简单。接下来,我们假设 k 可以通过: k = k1.dot(k2) 来计算。这将使它成为一个可分离的卷积,因为我们可以通过对 k1 和 k2 进行 2 次 1D 卷积来得到相同的结果,而不是对 k 进行 2D 卷积。

Sobel X and Y filters

以图像处理中常用的 Sobel 核为例。通过将 vector [1,0,-1]和[1,2,1].T 相乘,可以得到相同的内核。在执行相同的操作时,这将需要 6 个而不是 9 个参数。上面的例子显示了所谓的空间可分卷积,据我所知,它没有用于深度学习。

编辑:实际上,人们可以通过堆叠 1xN 和 Nx1 内核层来创建非常类似于空间可分离卷积的东西。这是最近在一个叫做EffNet的架构中使用的,显示出有希望的结果。

在神经网络中,我们通常使用一种叫做**深度方向可分离卷积的东西。**这将在保持通道分离的同时执行空间卷积,然后执行深度卷积。在我看来,用一个例子最能理解。

假设我们在 16 个输入通道和 32 个输出通道上有一个 3×3 卷积层。具体发生的情况是,32 个 3×3 内核遍历 16 个通道中的每一个,从而产生 512(16×32)个特征图。接下来,我们通过将每个输入通道相加来合并 1 个特征图。因为我们可以这样做 32 次,我们得到了我们想要的 32 个输出通道。

对于同一个例子中的深度方向可分离卷积,我们遍历 16 个通道,每个通道具有 1 个 3×3 内核,给我们 16 个特征图。现在,在合并任何东西之前,我们用 32 个 1x1 卷积遍历这 16 个特征图,然后开始将它们加在一起。这导致 656 (16x3x3 + 16x32x1x1)个参数,而不是上面的 4608 (16x32x3x3)个参数。

该示例是深度方向可分离卷积的具体实现,其中所谓的深度乘数是 1。这是迄今为止此类层最常见的设置。

我们这样做是因为假设空间和深度信息可以分离。从例外模型的表现来看,这个理论似乎是可行的。深度方向可分离卷积也用于移动设备,因为它们有效地使用参数。

有问题吗?

这就结束了我们通过不同类型的回旋的小旅行。我希望这有助于对这件事有一个简要的了解。如果你还有任何问题,请发表评论,并查看GitHub 页面获取更多卷积动画。

市场组合建模中交互效应的类型

原文:https://towardsdatascience.com/types-of-interaction-effects-in-market-mix-modeling-mmm-95247f3de36e?source=collection_archive---------6-----------------------

Source: Pixabay

在这篇文章中,我想谈谈在市场组合模型中变量之间的各种类型的相互影响。

这篇文章是我在 MMM 上写的系列文章的延续。关于 MMM 的前三篇文章可以在这里、这里和这里找到

那么,回归中的交互作用效应是什么呢?

交互效应是两个或多个自变量对至少一个因变量的同时效应,其中它们的联合效应显著大于(或显著小于)各部分的总和。它有助于理解两个或多个自变量如何协同工作来影响因变量。

首先理解两个组成部分很重要——主效应和交互效应。

主要效果:

主效应是单个自变量对因变量的影响——忽略所有其他自变量的影响。

交互效果:

如上所述,两个或多个自变量对至少一个因变量的同时效应,其中它们的联合效应明显大于(或明显小于)各部分的总和。

我将把这篇文章限制在讨论两个变量之间的相互作用。

交互效果可以在两者之间:

I. 分类变量

二。 连续变量

三。 一个分类变量和一个连续变量

对于每一种情况,解释都会略有不同。

1。分类变量之间:

想象有人在努力减肥。减肥可能是锻炼或遵循饮食计划的结果,也可能是两者协同作用的结果。

以上数字表示以千克为单位的重量损失。

以上结果说明了什么?

结果表明,单独锻炼比节食计划更有效,体重减轻了 5 公斤

**二。**与锻炼和节食计划同时进行的情况(你的节食计划不起作用)相比,只有锻炼才能减轻更多体重

以上结果说明了什么?

这表明,当运动和饮食计划一起实施时,体重下降更高。所以,我们可以说,锻炼和饮食计划之间存在着相互作用。

**2。**连续变量间的

让我们来看一个显示主效应和交互效应分量的回归方程。

Y =β0+β1 * X1+β2 * X2+β3 * X1 x2

上述等式解释如下:

i. β1 是当 X2 等于 0 时 X1 对 Y 的影响,即当 X2 等于 0 时,X1 增加一个单位导致 Y 增加β1 个单位。

二。类似地,当 X1 等于 0 时,β2 是 X2 对 Y 的影响,即当 X1 等于 0 时,X2 增加一个单位导致 Y 增加β2 个单位。

三。在 X1 和 X2 都不为零的情况下,X1 对 Y 的影响取决于 X2,而 X2 对 Y 的影响取决于 X1。

为了更清楚,让我们用另一种格式重写上面的等式。

Y =β0+(β1+β3 * X2)X1+β2 * X2

=>Y =β0+β1 * X1+(β2+β3 * X1)X2

=> (β1 + β3 X2)是 X1 对 Y 的影响,它取决于 X2 的值*

=> (β2 + β3 X1)是 X2 对 Y 的影响,它取决于 X1 的值*

请注意,本文是针对用于市场组合建模的输入/变量而写的。上述概念是 MMM 的一种可能情况,其中输入值可能为零。

对于输入变量不能为零的情况,采取一些其他措施。一个例子可以是一个模型,其中一个人的体重被认为是一个回归变量。一个人的体重不能为零:)

3。 一个连续变量和一个分类变量

一个分类变量和一个连续变量之间的相互作用类似于两个连续变量。

让我们回到我们的回归方程:

Y =β0+β1 * X1+β2 * X2+β3 * X1 x2

其中 X1 是分类变量,比如说(女性= 1,男性= 0)

X2 =连续变量

  • 当 X1 = 0 时,Y = β0 + β2X2*

= > X2 增加一个单位将导致男性 Y 增加β2 个单位

  • *当 X1 = 1 时,Y = β0 + β1 + (β2 + β3)X2

= >女性在 X2 增加一个单位将导致 Y 增加β2 + β3 个单位

X2 对 Y 的影响女性高于男性(请参考下图 1)

Figure 1

MMM 中交互的解释:

1。两个分类变量:

让我们来看两个分类变量——季节性和一些产品的推出。

假设季节性和产品投放都与销售有积极的关系。季节性和以个人身份推出产品会带来销售。如果他们之间有互动效应,这可能会增加销售额。

Y = β0 + β1季节性+β2 产品投放+ β3季节性产品投放

=>Y =β0+β1+β2+β3

其中季节性和产品投放= 1

如果没有相互作用,Y = β0 + β1 + β2

2。两个连续变量:

MMM 中两个连续变量之间相互作用的例子可以是电视广告和数字广告一起对销售的影响。

因此,当存在交互项时,电视广告对销售的影响取决于数字广告,而数字广告对销售的影响取决于电视广告。

Y = β0 + β1电视广告+β2 数字广告+ β3电视广告数字广告- >正向互动术语

如果交互项为正,那么这两个变量的联合效应是协同的,因为它会导致额外的销售。建议这两种类型的广告应该同时进行,以获得更高的销售额。

Y = β0 + β1电视广告+β2 数字广告- β3电视广告数字广告- >负面互动术语

如果交互项是负的,那么交互组件会拿走一部分销售额,从而降低总销售额。在这种情况下,建议不要同时开展这两项活动,因为这会影响销售。(您的活动在客户中制造混乱:P)

请注意,这两种投入的主要影响是积极的,但综合影响具有负的β值,导致总销售额减少。

3。一个连续变量和一个分类变量

其中 X1 是分类变量,比如季节性(如果有季节性,则为 1,否则为 0)

X2 =连续变量:电视广告

Y =销售额

销售受到季节性和电视广告的影响,当它们一起作用时。

Y =β0+β1 季节性+ β2电视广告+ β3电视广告季节性**

在这种情况下,当季节性因素存在时,则:

Y =β0+β1+β2 电视广告+ β3电视广告

*=>Y =β0+β1+(β2+β3)电视广告

电视和季节性之间的相互作用导致了额外的销售。

这是一篇关于变量间交互作用的简介。互动效应本身就是一个巨大的话题。还有更多微妙之处。

请继续关注 MMM 上的更多文章…..

参考:

** [## 相互影响

对于不知情的人来说,调查似乎是一种容易设计和进行的研究,但是当学生和…

methods.sagepub.com](http://methods.sagepub.com/reference/encyclopedia-of-survey-research-methods/n226.xml)

如果你喜欢我的文章,给它一些掌声,或者更好地与你的朋友或同事分享。

页(page 的缩写)最近,很多人问我是否做市场组合建模/营销分析方面的咨询。

答案是肯定的。您可以将您的咨询问题发布到https://www.arymalabs.com/

你也可以在 LinkedIn 上联系我

【www.ridhimakumar.com】版权所有 2018 版权所有 版权所有。**

你应该知道的机器学习算法的类型

原文:https://towardsdatascience.com/types-of-machine-learning-algorithms-you-should-know-953a08248861?source=collection_archive---------0-----------------------

应我的朋友 Richaldo 的要求,在这篇文章中,我将解释机器学习算法的类型以及何时应该使用它们。我特别认为,了解机器学习算法的类型就像了解人工智能的全貌,以及该领域正在做的所有事情的目标是什么,并让你处于更好的位置来分解一个真正的问题并设计一个机器学习系统。

本帖中经常使用的术语:

  • 标记数据:由一组训练示例组成的数据,其中每个示例是由输入和期望输出值组成的(也称为监控信号、标签等
  • **分类:**目标是预测离散值,例如{1,0}、{True,False}、{spam,not spam}。
  • **回归:**目标是预测连续值,例如房价。

机器学习算法的类型

如何定义机器学习算法的类型有一些变化,但通常它们可以根据它们的目的分成几类,主要类别如下:

  • 监督学习
  • 无监督学习
  • 半监督学习
  • 强化学习

监督学习

  • 我喜欢用函数逼近的概念来考虑监督学习,基本上我们训练一个算法,在过程的最后,我们选择最好地描述输入数据的函数,对于给定的 X,它对 y (X → y)做出最好的估计。大多数时候,我们无法找出总是做出正确预测的真正函数,其他原因是算法依赖于人类关于计算机应该如何学习的假设,这种假设引入了偏差,偏差是我将在另一篇文章中解释的主题。
  • 在这里,人类专家充当教师,我们向计算机提供包含输入/预测的训练数据,我们向它显示正确的答案(输出),计算机应该能够从这些数据中学习模式。
  • 监督学习算法试图对目标预测输出和输入特征之间的关系和依赖性进行建模,这样我们就可以根据它从以前的数据集中学习到的那些关系来预测新数据的输出值。

起草

  • 预测模型
  • 我们已经标记了数据
  • 监督学习问题的主要类型包括回归和分类问题

常用算法列表

  • 最近邻
  • 朴素贝叶斯
  • 决策树
  • 线性回归
  • 支持向量机(SVM)
  • 神经网络

无监督学习

  • 用未标记的数据训练计算机。
  • 这里根本没有老师,实际上计算机在学习了数据模式后可能会教你新的东西,这些算法在人类专家不知道在数据中寻找什么的情况下特别有用。
  • 是机器学习算法家族,主要用于模式检测描述性建模。然而,这里没有输出类别或标签,算法可以基于它们来尝试对关系进行建模。这些算法尝试对输入数据使用技术来挖掘规则检测模式,以及汇总和分组数据点,这些数据点有助于获得有意义的见解并向用户更好地描述数据。

起草

  • 描述性模型
  • 无监督学习算法的主要类型包括聚类算法和关联规则学习算法。

常用算法列表

  • k-均值聚类,关联规则

半监督学习

在前两种类型中,要么数据集中的所有观察值都没有标签,要么所有观察值都有标签。半监督学习介于这两者之间。在许多实际情况下,标记的成本相当高,因为这需要熟练的人类专家来做。因此,在大多数观察值中没有标签但在少数观察值中存在标签的情况下,半监督算法是建模的最佳候选。这些方法利用了这样的思想,即使未标记数据的组成员是未知的,该数据也携带关于组参数的重要信息。

强化学习

方法的目的是利用从与环境的相互作用中收集的观察结果来采取行动,使回报最大化或风险最小化。强化学习算法(称为代理)以迭代的方式不断地从环境中学习。在这个过程中,代理从它的环境经验中学习,直到它探索所有可能的状态。

R 强化学习是机器学习的一种,因此也是人工智能的一个分支。它允许机器和软件代理自动确定特定上下文中的理想行为,以最大化其性能。需要简单的奖励反馈让代理学习它的行为;这就是所谓的强化信号。

这里有许多不同的算法来解决这个问题。事实上,强化学习是由特定类型的问题定义的,其所有解决方案都被归类为强化学习算法。在这个问题中,一个代理应该根据他当前的状态来决定最佳的行动。当这个步骤被重复时,这个问题被称为马尔可夫决策过程

为了产生智能程序(也称为代理),强化学习经历以下步骤:

  1. 代理观察输入状态。
  2. 决策功能用于使代理执行一个动作。
  3. 行动完成后,行动者从环境中获得奖励或强化。
  4. 存储关于奖励的状态-动作对信息。

常用算法列表

  • q 学习
  • 时差
  • 深层敌对网络

使用案例:

强化学习算法的一些应用是计算机玩的棋盘游戏(象棋、围棋)、机器人手和无人驾驶汽车。

最终注释

有可能使用不同的标准来分类机器学习算法的类型,但我认为使用学习任务是很好的,以可视化 ML 的大画面,我相信根据你的问题和你手中的数据,你可以很容易地决定你将使用监督,无监督或强化学习。在接下来的文章中,我会给出更多关于每种机器学习算法的例子。

下面这张来自 en.proft.me 的图片或许能帮到你。

进一步阅读

  • 机器学习算法之旅
  • 机器学习算法精要(附 Python 和 R 代码)
  • 有监督和无监督的学习算法有什么区别?
  • (这个很好玩,解释得很好)

让我知道你对此的想法,如果你有你想看的主题的建议,请联系我们。

最后做的事

如果你喜欢这些作品,请留下你的掌声👏推荐这篇文章,让其他人也能看到。

优步司机调度优化

原文:https://towardsdatascience.com/uber-driver-schedule-optimization-62879ea41658?source=collection_archive---------5-----------------------

这个模型实现和图形可以在我的 Github 库中找到。

此外,非常感谢我的团队成员 Deep Prasad、Emily Xu 和 Sharlene Peng 为这个项目做出的贡献。

第 1 部分:导言

优步的关键价值主张之一是为他们的司机合作伙伴提供调度灵活性。根据 Beneson Strategy Group 的一份报告,73%的司机更喜欢有一份可以让他们选择时间表的工作。司机可以利用这种灵活性,在可用时间内最大化他们的预期收入。为此,优步提供了客户需求热图,使司机能够瞄准高需求区域,提供更高的出行概率,从而获得更高的预期收入。

然而,没有现成的方法来确定从特定位置开始的行程是否值得为该行程花费时间。例如,由于交通而花费较长时间但需求较高的行程可能会导致总行程较少,价值较低。另一方面,需求较少但持续快速的旅行可能更有价值。因此,平衡某个位置的需求和从该位置出发的行程所需时间最符合驾驶员的利益。

为了解决这一缺口,我们试图使用混合整数规划(MIP)创建一个调度优化模型。

第 2 部分:数据收集

两个数据集用于确定需求行程持续时间。因为优步的需求数据不可用,所以 DC 出租车载客数据被用作需求的替代数据。持续时间由优步运动数据集确定。

DC 出租车数据-需求

数据集来自 DC 开放数据中心。它描述了以坐标表示的特定位置的单个出租车行程。从 1 月到 3 月,该数据集包含 10,843 个不同位置的总共 5,546,786 次拾取。

为了将数据离散化并缩小问题的规模,我们需要将皮卡分类到高需求区域。首先,计算每个位置的取货数量。然后,为了定义区域,我们选择了提货次数最多的前 100 个位置(见图 1–1 ),因为它们占提货总数的 30%。MATLAB 的 kmeans 函数用于将计数聚类成 5 个区域质心(见图 1–2)。基于到其他四个区域的最小欧几里德距离计算每个区域的半径。

Table 1: High-Demand Region Parameters

Figure 1–1: Taxicab Pickups in D.C.

Figure 1–2: High Demand Pickup Regions in D.C.

由于我们只比较区域内的行程,因此接货计数被过滤为只包括从五个区域之一始发且目的地与始发地在同一区域内的行程。然后对一天中的时间、一周中的日期和地区的计数进行平均和汇总。下面是一个经过清理的离散化数据集的示例。

Table 2: Sample of Demand Data (cleaned) used for Model

优步移动数据—行程持续时间

该数据集来自优步的“优步运动”倡议(见附录 A)。它描述了每个始发地-目的地区域对的平均、最小和最大行程持续时间。优步运动的区域小于之前确定的五个高需求区域。为了使这两个数据集具有可比性,对起点-目的地对进行了过滤,以仅包括完全落在五个区域之一内的区域,并且这些区域的目的地与起点在同一区域内(见图 2)。然后计算五个区域中每个区域的平均、最小和最大旅行持续时间。与需求数据类似,这些值是按一天中的时间、一周中的日期和地区聚合的。数据集的样本可以在下面找到。

Figure 2: High Demand regions over-laid over Uber Regions

Table: Sample of Trip Duration Data (cleaned) used for the model

第 3 部分:方法

使用需求和行程持续时间数据,开发了一个混合整数规划模型来为驾驶员找到最佳驾驶计划。MIP 是线性优化程序,一旦得到一个解,其中一些变量可以是整数,而另一些则不可以。

最著名的 MIP 和我们的类似:T2 背包问题。在我们的例子中,背包的容量代表了优步司机为他们的日程安排分配的“总时间”。我们希望最大化预期收入。开发了以下 MIP:

目标函数

该模型的目标函数是使司机在一周的工作时间内获得的收入最大化。这是通过最大化每个推荐区域 j 和时间段 I 的预期收入之和来实现的。预期收入项 R_的计算公式如下:

其中我们假设新出行的概率均匀分布在 0.5 和 1 之间,因为这 5 个区域是基于高需求选择的。基于这一假设,可以使用需求来分配概率(见附录 B)。

通过使用每组区域 j 和时间段 I 中可能的最小行程次数,找到了最坏情况下给定时间的行程次数。因为时间段被细分为 2 小时时间段,所以最小行程次数可以近似为:

决策变量和参数

模型中的决策变量为X_{ij},其中 I 和 j 分别表示对应的时间和区域。X_{ij}是布尔变量,其中 1 表示选择了时间 I 的区域 j。模型中使用了以下参数:

  • R_ —时间 I 期间驾驶员在区域 j 可获得的预期收入
  • _ —布尔变量,用于指示驱动程序在块 I 期间是否可用
  • B_ —布尔变量,表示驱动器是否能够在区域 j 中工作
  • T_ —驾驶员一周可以工作的最大小时数

限制

优步因其日程安排的灵活性而具有吸引力。优步司机可以随时随地工作。为了准确地模拟灵活性,MIP 受到以下限制:

  • 约束条件 1 和 2 确保生成的最佳排班不包括驾驶员不愿意工作的区域或他们不可用的时间。
  • 在约束 1 中,A _ =表示驾驶员可以在时间段 I 驾驶,否则为 0。
  • 在约束 2 中,B _ =表示驾驶员愿意在区域 j 中驾驶,否则为 0。
  • 常数 Tmax 确保排班的总小时数不会超过驾驶员每周愿意工作的最大小时数。
  • 约束条件 4 确保每个时间段只推荐一个区域。
  • 约束 5 确保决策变量 X_和参数 A_和 B_是二进制的。

MATLAB 实现

为了实际实现该模型,在 MATLAB 中编写了一个中央程序,该程序准备 MIP 并使用 intlinprog 函数求解它。中央程序需要 6 个参数,每个参数对应于上面列出的决策变量。该问题必须为 intlinprog 公式化,它解决以下形式的问题:

代码可以在 Launch_IP.m 和 Solve_IP.m 中找到

MATLAB:数据提取方法

首先,从Taxi Pickup DataUber Movement Data提取的两个数据集在工作日、小时和地区上被连接。数据集的每一行代表给定地区在给定工作日给定小时的交通状况。使用readtable()函数提取所需的子集数据。

MATLAB:约束

使用这些数据,通过分三步构建 A 和 b 矩阵,为 intlinprog 制定了约束条件。第一步创建维度为1 x n的向量 A1,b1,表示优步司机愿意工作的小时数。第二步构建矩阵 A2、b2,确保不会同时推荐两个区域。最后,A1 被附加到 A2,b1 被附加到 b2,以形成最终的矩阵 A 和 b。

第二个约束要求推荐的区域在驾驶员愿意前往的区域内。如果驾驶员不愿意在特定区域驾驶,则在创建约束矩阵之前,该区域的所有持续时间、交通和约束参数将被移除。因此,没有必要将区域偏好纳入约束矩阵。该模型还假设从一个区域到下一个区域的时间可以忽略不计。在时间段i期间,驾驶员可能预期在区域 B,但是对于时间段i+1,驾驶员在 12 英里之外的区域 C。在区域之间旅行的时间成本可以在未来的迭代中实现。

MATLAB:目标函数

为了表示目标函数,建立两个向量并相乘。第一个向量表示在时间 I 期间在当前区域获得客户的概率,第二个向量表示时间段i中的估计行程数。使用以下代码行找到最终的目标函数:

f = transpose(P_new_customer.*Min_Trips).*avg_revenue_trip;

其中avg_revenue_trip根据 2014 年优步研究得出的每小时收入中值和每小时出行信息,约为 12 美元。

现在,使用适当的公式,可以通过intlinprog()用构建的 A、b 和 f 向量找到最优解。上限和下限分别设置为 1 和 0。

第 4 部分:结果

该模型能够在给定一个驾驶员的指定参数的情况下生成周计划。例如:

Model Inputs — Driver’s Availability

Model Outputs — Ranked Recommendation to the Driver

为了评估模型性能,考虑了两个指标:模型性能优化。具体来说,该团队想知道当最大工作时间(Tmax)、时间段和区域的数量增加时,收入和计算时间会受到怎样的影响。

模型性能

为了确保稳定的结果,该模型对于每个实例运行 500 次,并且记录平均目标值和计算时间。为避免偏差,每个实例的时间段和区域都是随机选择的。发现计算时间随着时间段数量的增加而增加,但随着最大小时数的增加而减少(见附录 C)。

最佳性

随着可用时间段的数量在 1-42 之间变化,最佳收入在 450-545 美元/周之间变化(见图 3)。可用时间段数量的增加代表了驾驶员对我们定义的时间段的调度灵活性的增加。这种正相关关系表明,司机的时间安排越灵活,他们期望获得的收入就越多

Figure 3: Optimal Revenue/Week Increases as Driver Availability Increases

只有当包含多个区域时,可用区域数量的增加才会导致收入的增加,这表明更多的可用区域不会对收入产生重大影响(参见附录 C)。

第五部分:讨论

随着可用时间段数量的增加,收入增加有两个潜在的原因。

首先,是“偶然收入”。这意味着收入的增加是由于服务时间的多样性增加,平均而言,在更多的高收入产生时间内驾驶的结果。

或者,人们可以简单地赚更多的钱,因为他们开车更频繁了。为了确定原因,团队绘制了每周最大工作时间增加时的收入图(见图 4)。增加最大工作时间似乎显著增加了司机的收入,这表明一个人驾驶的时间段对收入的影响远不如他们驾驶的频率大。

此外,通过比较预期收益和实际收益,验证了模型的有效性。根据众包信息,一名优步司机每周工作 30 小时,每周收入约为 772 美元。根据我们的模型,最佳最坏情况下的预期收入约为 1900 美元。这明显更高,表明我们的模型是对当前驾驶员驾驶模式的显著改进。

延长

该模型的结果有直观的意义,并显示了更广泛的应用潜力。可以将该模型推广到任何城市,而不仅仅是华盛顿。该团队还希望将“竞争”组件纳入该模型。如果几个司机同时被推荐到同一个地区,竞争将会增加,每个司机得到一次旅行的可能性会降低。根据团队建立的公式,这明显降低了预期收入,并且会将最佳解决方案错误地呈现为“最佳”。一个更先进的模型将能够平衡它在给定地区和时间给出的建议数量,并“重新安排”司机,以平衡某个地区有建议的司机数量。

第六部分:结论

基于 MIP 模型的结果和解释,该团队能够宣称它在预期收入方面为优步驱动程序带来了有意义的价值。模型规定的时间段数与司机的预期收入之间存在正相关关系。为了增加他们的收入,司机应该在尽可能多的时间段可用。现在,司机通过做出数据驱动的决策,而不是使用试探法来选择“最佳”位置为客户服务,从而比其他司机更胜一筹。有了模型规定的可行和方便的时间表,司机们现在可以把他们的工作想象成一个具有竞争优势的有利可图的行业。

第 7 部分:参考

1优步新闻编辑室,“BSG 报告:驱动者路线图”。【在线】。可用:https://news room . Uber . com/WP-content/uploads/2015/01/BSG _ 优步 _Report.pdf 。[访问时间:2017 年 4 月 16 日]。

2Opendata.dc.gov,“出租车旅行”。【在线】。可用:【http://opendata.dc.gov/datasets?q=taxi】T2。[访问时间:2017 年 4 月 16 日]。

3Movement.uber.com,“优步运动:让我们找到更聪明的前进方式”,2017 年。【在线】。可用:【https://movement.uber.com/cities】T4。[访问时间:2017 年 4 月 16 日]。

[4] J. Hall 和 A. Krueger,“优步在美国的司机伙伴的劳动力市场分析”,2017 年。【在线】。可用:https://time dot com . files . WordPress . com/2015/01/Uber _ driver-partners _ hall _ kreuger _ 2015 . pdf。[访问时间:2017 年 4 月 16 日]。

5我和优步一起开车,《家——我和优步一起开车》,2017。【在线】。可用:http://www.idrivewithuber.com。[访问时间:2017 年 4 月 16 日]。

第八部分问答

为什么是 matlab?

更多的是个人喜好。Matlab 在解决优化问题方面非常专业(也很快),就像这种情况下的 MIP 模型,我熟悉它的语法。Python 确实有几个 MIP 的库,但是我不熟悉。项目中的数据处理和分析主要是用 Python 实现的。从技术上讲,用 Python 可以完成从处理到优化的整个循环。

如果所有的司机都遵循“最优解”,会发生什么

随着越来越多的司机采用这种“工具”,竞争优势将逐渐消失。在一个边缘案例中,如果我们达到了一个均衡,在这个均衡中,所有需求水平相同的区域的拥挤状态都是相同的,那么这个工具将变得无用。然而,这在现实中永远不会发生,至少现在是这样,所以总有一些改进的空间。

这只是概念层面。我希望看到我们能够在现实中实现这种智能和优化的资源配置。

附录

附录 A

以下是团队访问优步旅行持续时间数据时必须使用的优步移动接口。因为界面限制团队必须手动选择时间段和位置,所以团队必须缩小所选位置的范围。

附录 B

以下是在 MATLAB 中实现的公式,用于计算新行程的概率:

  • P_和 P_是用于计算新出行概率的均匀分布的下限和上限(在我们的例子中,为 0.5 和 1)
  • D_和 D_是该区域和时间段的最大和最小拾取计数。

附录 C

以下是补充图表,描述了给定变化参数的计算时间和目标函数的分析。

Increase in revenue with more regions leveling off after two regions

Increasing computation time with more time blocks

Decreasing computation time with higher T_

Decreasing computation time with more regions

优步地图技术讲座

原文:https://towardsdatascience.com/uber-maps-tech-talk-8df91c300f80?source=collection_archive---------5-----------------------

Pic Credit

除非你是出于某种神秘或其他原因远离科技生活的人,否则你一定非常习惯我所说的地图对话——“你能分享位置吗?”,“地图显示路上交通繁忙!”等等。数字和网络地图服务是一个随着时间和技术不断发展和完善的领域。虽然其中一个原因是技术和计算的进步,但另一个主要原因是这是一个非常具有挑战性且尚未解决的问题。这就是有趣的地方,也是这个优步地图技术演讲非常有趣的地方。

在我们今天进行的两次信息丰富的谈话之前,有一个关于优步·班加罗工程团队中从事技术工作的女性的视频,还有一个为答对的人准备的奖品。如果你想知道,不,我没有赢过!首先发言的是地图团队的产品经理 Ankit。在几个月前的一次早期演讲中,演讲者解释了用户打开优步应用程序到旅程结束之间发生的事件和操作的数量。定位骑手和驾驶员并提供准确的导航路线对于平稳的骑行非常重要。Ankit 带我们经历了每一步,从估计用户位置开始,搜索地点和地址,计算费用和预计到达时间。当用户打开应用程序时,首先需要的是他/她的位置。这涉及到许多需要考虑的特征,比如用户是在室内还是室外,用户是否在地面以上的某个建筑中,或者其他类似的场景。这是通过使用 GPS、位置预测模型和 WiFi 指纹识别来实现的。所有这些都是为了让那个小蓝点出现在优步地图的正确位置上!

为了便于搜索放置地点或地址,应该考虑许多因素。该地图可以使用用户的历史数据(如果有的话),显示具有准确位置的热门地点,显示附近的优步游乐设施的快照等。当涉及到 Uber Eats 时,还有其他不同的情况需要考虑。下一步是票价计算,必须非常准确。估计行程时间、行程距离、通行费的存在、当前用户位置周围优步乘车的供应以及当前乘车的需求都是估计费用的决定因素。如果这听起来很复杂,那么想想不同类型的乘车会有什么不同——UberGo、UberPool 和最近的 ExpressPool。虽然 UberPool 和 ExpressPool 都允许拼车,但 ExpressPool 从最近的上车点提供乘车服务,乘客可以步行到该地点。这不仅有助于骑车人到达一个可以乘坐的地方,而且也更便宜。

Pic Credit

每一步都建立在前一步的基础上,并增加了一些复杂性。ETA 预测是下一步,对于不同的乘坐模式是不同的。对于 UberGo/UberPool,只有一个司机到达骑手的预计到达时间。在快速拼车的情况下,还应考虑骑车人到达上车点所需的时间。ETA 计算几乎没有挑战。如果交通发生不可预见的变化怎么办?还是突然的路障?如果司机的网络不稳定怎么办?前两个导致 ETA 的重新计算。为了处理不稳定的网络,缓存的路径在驾驶员端被重用。因此,即使司机失去连接,也有办法让地图在没有连接的情况下工作。一旦驾驶开始,后台会不断优化路线,帮助驾驶员选择最佳路线到达目的地。骑手和所选路线的历史路线记录都用于此目的。在结束演讲之前,Ankit 透露了优步的多式联运计划,该计划适应使用不同模式的乘坐,不仅包括四轮车,还包括自行车、滑板车等。(以防你不知道,优步正在投资滑板车租赁初创公司 Lime,这家公司也有谷歌的支持)

"在座有多少人研究过地图?"Gaurang Khetan 开始讲话时问道。很少有人举手。因此,如果你想做一些有挑战性的、有趣的、对流行产品有直接影响的事情,那么地图就是你的了。是什么使它成为如此困难和具有挑战性的问题?地图和收集的数据一样好,好的数据很难得到。有不同的来源可以获取开发地图所需的数据,其中包括多家供应商。随着物理世界的不断变化,地图需要不断更新和改进。世界上不同的国家有不同的分配地址的惯例和结构。此外,很难衡量地图和路线的正确性。跟随数字地图时迷路并不罕见。除了所有这些原因,用于最佳路线和基于地理的搜索的算法需要非常快速、高效和可扩展。

地图数据来自不同的图层、不同的来源,包括多种类型,如道路网络、商业地点、地址、物理空间(如商场和建筑)以及自然特征(如湖泊)。数据量不仅巨大,而且非常多样化。这使得使用地图进行全球展示成为一个永无止境的过程。另一个问题是,“我们如何为一个没有地图数据的国家或地方建立地图数据?”你应该花几分钟思考一下,然后自己回答。邮政数据、政府数据、GPS 跟踪、多个供应商、手动驾驶和路线、卫星视图、众包等是收集/创建地图数据的一些方式。多少数据才够?随着城市化的发展和技术的扩展,城市的位置必须被很好地绘制,路线必须被完全理解,对吗?虽然这在某种程度上可能是真的,但有一个问题是城市地区特有的——城市峡谷。

Pic Credit

在市区或高楼林立的地方,卫星信号在直接到达 GPS 接收器之前可能会受到阻碍。如果有高层建筑在卫星的视线范围内,就会发生这种情况。简而言之,GPS 使用许多围绕地球轨道运行的卫星(30 颗或更多),并传输 GPS 接收器用于位置识别的信号。这些信号会被传播路径上的建筑物阻挡或反射。当这种情况发生时,会导致位置信息出错。这种误差从几米到 50 米或更大不等。上面的图像就是这样一个例子。

Pic Credit

为了克服这个问题,优步地图使用信噪比(SNR)。如果卫星的 SNR 值较低,这意味着没有到相应卫星的直接视线,并且位置信息会有一些误差。当它很高时,必须有一个清晰的卫星视线,因此位置信息将是准确的。在上图中,我们可以看到左侧的点在卫星 C 和 D 的视线范围内,但不在卫星 B 的视线范围内。同样,右侧的点在卫星 B 和 C 的直接视线范围内,但不在卫星 D 的视线范围内。此信息非常有用,同样可用于确定该位置位于道路的左侧还是右侧。

很明显,在地图方面,有太多的东西需要了解、学习、尝试和改进,而这正是优步正在做的事情。它不仅仅使用谷歌地图和 GPS 提供的原始信息。地图是优步大学的一个活跃的研究领域,他们正在不断完善它。作为一个例子来了解优步如何使位置信息更好,见下面的原始 GPS 提供的位置信息(红色的)和优步的改进 GPS(蓝色)的比较。虽然改进后的 GPS 提供了更好的导航,但原始的 GPS 却无处不在。

这是我今年参加的第三次优步科技讲座,这些讲座非常有趣。虽然众所周知,地图和图表不容易解决问题,而且还在不断改进,但了解这么多关于一个非常依赖这些领域的公司目前如何在这些领域工作和研究的信息真的很好。会谈结束后,我们还愉快地进行了交流。演讲者和其他几个目前在优步工作的人加入了我们,帮助我们解答问题和疑惑。感谢优步组织了这次技术讲座。

顺便说一句,他们的办公室很酷!!

这是我写的关于我参加的第一次优步科技演讲的博客的链接

如果你喜欢到目前为止在这篇文章中读到的内容,并且想了解优步发生的一切,我推荐你查看这个来自优步的博客,并且在 Twitter 上关注 @ubereng ,他们在 Twitter 上发布了关于他们最近的研究工作和开源工具的消息。

感谢阅读!!!

连接:LinkedInTwitter和我的 博客

优步的自主车祸调查

原文:https://towardsdatascience.com/ubers-autonomous-car-accident-investigation-57fcc88cb6e7?source=collection_archive---------7-----------------------

3 月 19 日,一个故事震惊了自动驾驶汽车行业,当时优步的一辆自动驾驶汽车在亚利桑那州坦佩撞倒了一名女子。这是被自动驾驶汽车撞上后的第一起死亡事件。这严重地对自动驾驶汽车提供的安全功能的所有说法产生了严重的怀疑。3 月 23 日,Tempe 警方发布了一段事故视频,这让许多事情都成了问题。完整视频可以在 youtube 这里观看。

Image Source (https://www.aol.com/article/news/2018/03/19/woman-dies-in-arizona-after-being-hit-by-uber-self-driving-car/23389700/)

分析 Dashcam 视频

完整视频可点击查看。(来源-美国广播公司行动新闻)。让我们看一下从仪表板上捕捉到的第一张图像,以分析我们获得的所有信息。

5 seconds before collision.

这里有几点需要注意-:
1。车道线清晰可见。
2。远处的路上有车,还有一些建筑物的灯光。
3。路上有路灯!
4。用肉眼,除了远处的汽车什么也看不见。

撇开这些细节-
1。汽车以每小时 38 英里的速度行驶,限速 45 英里。( 来源 ) 2。汽车在近光灯上行驶。

2 seconds before the collision

跳跃到 0.07,碰撞前 2 秒,可以观察到在左侧和右侧,我们有路灯,所以有足够的光线,但在左侧也有道路的黑色部分。

Left Street Light Passes by in the next frame of the same second

我们仍然处于第七秒,仍然没有任何行人的迹象,看着左边的路灯在这一帧中经过。

还在第 7 秒,两个灯都过去了。现在,这是我们第一次看到行人的脚步。

碰撞前 1 秒,从仪表板摄像头可以清楚地看到行人或有障碍物。

嗯,我们在第八秒,现在我们也可以看到行人和自行车的下半部分。

现在,这个女人和她的自行车清晰可见。但是那辆车减速了,甚至试图减速了吗?不要!再次需要注意的重要一点是,这位女士穿着黑色衬衫/夹克。但是自行车或者那个女人的白鞋子呢?

我有意跳过了第 9 帧的图像。即使在第 9 秒,赛车也没有减速!那就奇怪了!!

相机不是问题

确实,在撞击前 50 到 60 帧的时候,有人观察到了这个女人,但是机器仍然无法捕捉和减速!但这里的重点不是关于相机,它很暗,相机可能会错过这一点,而且上半部分是黑色的,也可能会错过这一点。自行车甚至完全看不见。现在主要问题来了。激光雷达怎么了?激光雷达是自动驾驶汽车使用的最昂贵的设备之一,它没有反应!!任何人都可以争辩雷达可能会错过一些信息,但激光雷达不会。激光雷达把那个女人当成噪音了吗?嗯,看起来只有这个,如果是这样,我们肯定有一个用例要处理。这里还有一点需要思考,那就是这个女人甚至一秒钟都没有意识到车的存在!

激光雷达没有工作,好吧,我们对雷达没有期望,但是它也没有工作。即使发现了自行车,照相机也坏了。这是不可接受的,需要进行详细的调查,需要了解激光雷达把这个女人当成了什么,为什么相机的输入被丢弃了。所有传感器和技术的融合失败了 3 秒钟,这是非常令人惊讶的!!还有,视频素材不够!

谁有错的问题仍然存在。**司机有错吗?**从内饰视图中可以清楚地看到,在碰撞发生前,驾驶员正在向下看。在任何这种情况下控制汽车是她的责任,但我相信即使是一个正常的司机也无法避免事故,这就是我们制造自动驾驶汽车的确切原因,以避免司机的错误。现场非常黑暗,不幸的是,这个女人在错误的时间出现在了错误的地点。如果她能从一个街灯足够亮的地方穿过去,她可能会得救。但是现在问题来了,我们有分析过的录像,但是谁有错呢?优步,女人,技术?

好吧,现在有一件事非常清楚,自动驾驶汽车行业需要严格的测试来重新赢得人们的信任。此外,需要像我们在空难调查中那样对此类事件进行详细的调查,并且应该在各个参与者之间分享,以提高这个行业的安全标准。

请随意分享你的观点。

Ubuntu +深度学习软件安装指南

原文:https://towardsdatascience.com/ubuntu-deep-learning-software-installation-guide-fdae09f79903?source=collection_archive---------0-----------------------

我最近在报读 Udacity 的自动驾驶汽车工程师 Nanodegree 后,造了一台深度学习机器。你可以在这里阅读我的构建:花 800 美元构建一个深度学习平台。在这篇文章中,我将描述从一个干净的构建到训练深度神经网络的必要步骤。有很多好的安装指南——特别是来自 floydhub 的这个,大部分内容都是基于它——但是我发现自己不得不挖掘许多不同的资源来正确安装所有的东西。本文的目标是将所有必要的资源整合到一个地方。

系统检查

即使在安装操作系统之前,您也应该执行一些基本的检查,以确保您的系统正常启动和运行。为此,我建议遵循 Paul 的硬件 YouTube 频道中的关于新 PC 构建的前 5 件事。他继续安装 Windows,但视频的前半部分适用于任何机器,不管是什么操作系统。

人的本质

首先下载 Ubuntu 16.04.2 LTS ,Ubuntu 最新的长期支持版本。然后,用 Ubuntu ISO 创建一个可启动的 u 盘。如果你在 macOS 上,你可以遵循 Ubuntu 官方说明这里,或者如果你在 Windows 上,你可以遵循这里。一旦你把 Ubuntu ISO 加载到你的 u 盘上,把它插入你的新版本并启动机器。要安装 Ubuntu,你需要进入启动菜单,对我来说是 F11 键,然后选择从 u 盘启动。从那里,您可以简单地按照屏幕上的安装说明。你也可以参考 Ubuntu 的社区 wiki 快速指南:从 USB 记忆棒安装 Ubuntu了解更多细节。

基础

从终端运行以下命令来更新软件包并安装一些基本软件:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential cmake g++ gfortran git vim pkg-config python-dev software-properties-common wget
sudo apt-get autoremove
sudo rm -rf /var/lib/apt/lists/*

Nvidia 驱动程序

您需要根据您的 GPU 型号下载正确的驱动程序,您可以使用以下命令进行检查:

lspci | grep -i nvidia

查看专有 GPU 驱动程序 PPA 库,找到您的 GPU 的当前版本。在撰写本文时,GeForce 10 系列的最新版本是 381.22,但我选择了 375.66,这是当前的长期分支版本。使用以下命令安装驱动程序:

sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt-get update
sudo apt-get install nvidia-375

然后重新启动计算机:

sudo shutdown -r now

要再次检查驱动程序是否已正确安装:

cat /proc/driver/nvidia/version

库达

从 Nvidia 的网站下载 CUDA 8.0 工具包。转到下载目录(或者您选择保存它的地方)并安装 CUDA:

sudo dpkg -i cuda-repo-ubuntu1604*amd64.deb
sudo apt-get update
sudo apt-get install cuda

将 CUDA 添加到环境变量:

echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc

检查是否安装了正确版本的 CUDA:

nvcc -V

重新启动计算机:

sudo shutdown -r now

cuDNN

从 Nvidia 的网站下载 cuDNN 库。在下载 cuDNN 之前,您需要首先注册 Nvidia 的开发者计划。他们说这可能需要几天的时间,但是我几乎立刻就获得了访问权限。在撰写本文时,cuDNN v5.1 是 TensorFlow 官方支持的版本,所以除非你知道 v6.0 受支持,否则不要发布(他们目前正在开发)。下载后,转到下载目录提取并复制文件:

tar xvf cudnn*.tgz
cd cuda
sudo cp -P */*.h /usr/local/cuda/include/
sudo cp -P */libcudnn* /usr/local/cuda/lib64/
sudo chmod a+r /usr/local/cuda/lib64/libcudnn*

Anaconda +包

从 Continuum 站点下载 Anaconda 安装程序。我选择了 Python 2.7 版本,但是您可以选择任何您想要的版本作为您的默认 Python:

bash Anaconda2-4.4.0-Linux-x86_64.sh

当安装程序询问您是否想将 Anaconda 添加到您的路径中时,回答“是”(除非您不想将它作为您的默认 Python)。一旦安装了 Anaconda,就可以用所有必要的深度学习库创建一个新的 conda 环境。我将使用 Udacity 的初学者工具包作为一个例子,因为这是我在许多项目中使用的。从CarND-term 1-Starter-Kit下载(或复制粘贴)environment-gpu.yml 文件。您可以在文件的顶部随意更改环境的名称。从保存环境-gpu.yml 文件的目录中:

conda env create **-**f environment-gpu**.**yml

要激活您的新环境:

source activate carnd-term1

现在,您可以通过运行 TensorFlow 的内置 MNIST 示例模型(不再适用于 TensorFlow 版本≥ 1.0)进行测试,以确保一切正常工作。请注意,以下命令将在首次运行时自动下载 12 MB MNIST 数据集:

python -m tensorflow.models.image.mnist.convolutional

如果在这一点上一切正常,那么恭喜你——你现在已经准备好对热狗进行分类了!

http://www.foodandwine.com/news/silicon-valleys-hot-dog-identifying-app-very-real

UCSF 科学家利用人工智能发现创伤性脑损伤的特征

原文:https://towardsdatascience.com/ucsf-scientists-use-artificial-intelligence-to-uncover-hallmarks-of-traumatic-brain-injury-a672ae75704a?source=collection_archive---------5-----------------------

我们在 UCSF 大学的长期合作者几周前刚刚发表了一篇论文,题为“使用 PLOS 一号中的拓扑数据分析揭示创伤性脑损伤(TBI)中的精确表型-生物标记关联”。UCSF 也发布了一份新闻稿。这是我们与 UCSF 合作的第二份出版物(以前的《自然》论文、快公司文章和我们的以前的博客)。这项研究得到了美国国立卫生研究院——国家神经疾病和中风研究所的资助。这些分析可能为 TBI 患者的未来临床试验中的患者分层和治疗计划提供一种可靠的方法。我已经在另一个博客中写了这项研究。

创伤性脑损伤是一种复杂的疾病,通常根据临床体征和症状来描述。最近的成像和分子生物标记创新为改善护理提供了机会,结合了病理解剖和分子机制。用于 TBI 诊断和患者分层的不同数据是一个挑战。来自扎克伯格旧金山总医院创伤中心、匹兹堡大学医学中心和德克萨斯州奥斯汀大学医学中心 Brackenridge 的急性创伤性脑损伤患者参与了这项研究。创伤性脑损伤的转化研究和临床知识(TRACK-TBI)试点多中心研究招募了 586 名急性 TBI 患者,并收集了研究人群的不同公共数据元素(TBI-CDEs),包括影像学、遗传学和临床结果。这些 CDEs 包含 944 个变量,包括人口统计学、临床表现、影像学和心理测试。

该论文阐述了机器智能(MI)如何揭示患者结果中的数据驱动模式,以识别潜在的恢复生物标志物,这可以使用更传统的单变量统计测试方法,显著预测 TBI 后患者结果的恢复。MI 算法在多维空间中组织并绘制了 TBI 患者的数据,确定了轻度 TBI 患者的一个子集,该子集具有与损伤后 3 个月和 6 个月的不利结果相关的特定多变量表型。进一步的分析显示,该患者亚组具有较高的创伤后应激障碍(PTSD)发生率,并且富含几种与细胞对应激和 DNA 损伤的反应以及纹状体多巴胺加工相关的独特遗传多态性。最后,MI 确定了一个独特的诊断亚组,该亚组由轻度 TBI 后出现不良结果的患者组成,这些患者可通过特定基因多态性的存在进行显著预测。

如果你想合作,请联系我们在 collaborators@ayasdi.com

Udacity 无人驾驶汽车纳米度项目 10 —模型预测控制

原文:https://towardsdatascience.com/udacity-self-driving-car-nanodegree-project-10-model-predictive-control-e9b4195d3f9?source=collection_archive---------3-----------------------

Udacity 自动驾驶汽车工程师纳米学位项目的第十个项目,也是第二学期的期末项目,题为“模型预测控制”(MPC)。MPC 将 PID 控制的概念提升到无数个层次,随之而来的是无数倍的复杂性。不过,Udacity 将大部分复杂性卸载到了 IPOPT 和 CPPAD 包中。

像 PID 控制和行为克隆项目一样,这个项目的目标是在 Udacity 提供的模拟器中导航一条轨道。我很高兴看到他们从“湖”赛道上获得了一些额外的里程(明白吗?).这三个项目都需要我们的代码通过 websocket 与模拟器通信,根据它提供的数据向模拟器发送转向和油门命令。在行为克隆中,它提供相机馈送,在 PID 控制中,它提供跨轨道误差(CTE,大约是从轨道中心线的距离),这次它提供遥测(位置、速度、方向)和未来一段轨道的几个航路点。这个项目的奖金挑战原来是强制性的(什么?!):一旦我们让我们的控制器工作,我们必须在发送控制命令之前投入 100 毫秒的延迟,以模拟我们在现实世界中可能遇到的延迟类型。

首先要做的是对提供的路点拟合一条曲线,最好是在它们已经从轨迹坐标转换到车辆视点之后,以简化未来的计算。我称之为最佳拟合曲线。然后,IPOPT 和 CPPAD 软件包可用于计算最佳轨迹及其相关的驱动命令,以便以最佳拟合最小化误差。你可能会想,“那么,为什么不遵循最合适的呢?”当然,这就是我们在 PID 控制中所做的事情,但现在我们知道接下来会发生什么,可以更聪明地规划我们的控制。当你开车转弯时,你并不完全是九十度,对吗?或许更像这样?

Image credit: Udacity

MPC 可以考虑车辆的运动模型,在给定一组约束的情况下,根据车辆运动的限制以及定义我们希望车辆如何移动的成本组合(如保持接近最佳拟合和所需方向,或防止车辆过快猛打方向盘),规划出有意义的路径。

优化只考虑短时间内的航路点,因为这是我们真正需要计划的(就我们的执行器控制而言)。我们可以调整优化器在其计划中使用的离散时间点的数量,以及它们之间的时间间隔,以便它可以在合理的时间内计算出最佳计划(我们当然希望它足够快,以实时控制汽车)。优化器需要一个巨大的一维向量,其中包括计划中每个时间步的状态变量和约束,以及总成本函数——坦率地说,不是特别直观,但易于管理。

由于未来时间步长的变量取决于先前的时间步长,因此它们的约束利用了车辆的运动学模型。运动学模型包括车辆的 x 和 y 坐标、方位角(psi)和速度,以及跨轨迹误差和 psi 误差(epsi)。执行器输出只是加速度和 delta(转向角)。该模型将前一时间步的状态和动作结合起来,根据以下公式计算当前时间步的状态:

经过一些调试和调整成本函数,我的车在赛道上行驶。是时候通过增加延迟来彻底摧毁它了——这就是所发生的事情。我处理它的方法是双重的(不仅仅是限制速度):最初的运动学方程依赖于前一个时间步的驱动,但是有 100 毫秒的延迟(恰好是我的时间步间隔),驱动在另一个时间步之后应用,所以我改变了方程来说明这一点。(注意:我的项目评审员建议了一个更简单的解决方案——在运行 MPC 求解器方法之前,将汽车的当前状态预测到未来 100 毫秒。例如,按照现在的情况,传递给解算器的我的汽车的 x 和 y 位置是0,0,但是 100 毫秒后它应该是不同的。)此外,除了课程中建议的成本函数,我还加入了一个惩罚速度和转向组合的成本,这导致了更多的可控转弯。

下面是一段轻松愉快的视频回顾:

这个项目的源代码可以在我的 GitHub 上找到

原载于 2017 年 6 月 30 日【http://jeremyshannon.com/2017/06/30/udacity-sdcnd-mpc.html】。**

Udacity 无人驾驶汽车纳米学位项目 4 —高级车道发现

原文:https://towardsdatascience.com/udacity-self-driving-car-nanodegree-project-4-advanced-lane-finding-f4492136a19d?source=collection_archive---------2-----------------------

欢迎来到“妈妈报告”(嗨妈妈!);如果技术术语和晦涩难懂的语言更符合你的风格,那么 请点击这里 ,否则请尽情享受吧!

Udacity 自动驾驶汽车工程师 Nanodegree 第一学期的第四个项目建立在第一个项目的之上,超过了第二个项目和第三个项目。虽然这看起来很明显,因为它们都涉及到寻找车道线,但这背后的原因是项目 2 和项目 3 向我们介绍了深度学习的新奇之处,几乎可以为我们编写代码,而项目 1 和项目 4 依赖于更传统的计算机视觉技术来非常明确地了解我们如何从输入到输出。这几乎让人失望——就像用键盘换铅笔一样——但是人们会说:(我听起来像总统吗?)公司仍然依赖这些技术,所以它绝对值得学习(并且仍然有趣和具有挑战性), OpenCV 库是承担所有重担的人。

"所以让我们拿个仪表盘找些车道!"你是说?好吧,等一下,特克斯。你不能随便就开始找车道。首先,你用的摄像机?它扭曲了图像。你可能看不出来,但这是真的!看:

幸运的是,这可以通过几张棋盘照片和 OpenCV 函数findChessboardCornerscalibrateCamera来纠正(对于单个相机/镜头)。看看这个:

我知道——对我来说它看起来也几乎一样,但失真在图像的角落最明显(看看底部汽车引擎盖形状的差异)。

现在我们可以开始有趣的事情了。下一步是应用透视变换来获得前方车道的鸟瞰图。它看起来是这样的:

我可能做了不必要的努力来使我的透视变换恰到好处(使直线在最终的鸟瞰图中完全垂直),但是因为变换是根据相同的规则反向的,所以最终可能没什么关系。

接下来,我探索了一些不同的颜色转换和渐变阈值,试图隔离车道线,并生成一个二进制图像,其中车道线处为 1(白色),其他地方为 0(黑色)。这无疑是整个过程中最微妙的部分,对光线条件和褪色非常敏感(更不用说那些该死的白色汽车了!)在路上。我不会用细节来烦你;我只想说这是我在这个项目上花了大部分时间的地方。最后,我结合了一个在 Lab 色彩空间的 B 通道上提取黄线的阈值和一个在 HLS 色彩空间的 L 通道上提取白色的阈值。这是每一个的样子:

这是它们在几幅测试图像上的组合:

不算太寒酸!

现在,聪明的一点是:搜索整个图像来识别哪些像素属于左车道和右车道是不必要的(并且计算量很大),因此我们计算了二进制图像下半部分的直方图,如下所示:

左半部分和右半部分的峰值为我们提供了车道线开始位置的良好估计,因此我们可以从底部开始搜索小窗口,并基本上沿着车道线一直到顶部,直到识别出每条线中的所有像素。然后可以将多项式曲线应用于识别的像素,瞧!

不仅如此,使用前一帧的拟合并在附近搜索,可以更容易地在视频的连续帧中找到像素,如下所示:

它只是在多项式线和多边形中着色以填充它们之间的通道,应用反向透视变换,并将结果与原始图像相结合。我们还做了一些简单的计算和转换,以确定道路的曲率半径和汽车离车道中心的距离。这是最终的结果:

这是我应用于下面链接的视频的管道,带有一点平滑(整合来自过去几帧的信息)和健全性检查以拒绝异常值(例如忽略不在特定距离内的拟合)。

该视频可爱地展示了图像处理管道中的步骤:

这里有一个链接到我的视频结果,这里有一个奖励视频,其中有一些额外的诊断信息,在这里你可以看到算法与困难的照明和路面条件进行斗争(在某些情况下会崩溃)。

再说一遍,如果你感兴趣的是技术类的东西, 去这里

最初发表于 ..//2017/03/03/uda city-SD CND-advanced-lane-finding . html2017 年 3 月 3 日。

Tableau 认证终极指南

原文:https://towardsdatascience.com/ultimate-guide-to-getting-certified-in-tableau-5bd2df7d0c7d?source=collection_archive---------3-----------------------

作为一个 tableau 的忠实支持者,一个认为 tableau 是商业智能和可视化领域最好的产品的人,我很自然地想办法提高我的 Tableau 知识,这样我就可以随时成为任何 Tableau 相关查询的联系人。在提高知识的同时,你会有一个两难的时刻,如果你现在就去争取一个更公开的认可,而不仅仅局限于你的“工作认可”,或者你应该坚持只与工作相关的认可。

虽然工作认可总是好的,并且是我们非常努力工作的事情,但获得证书使我们能够在社区中被听到,并有助于围绕数据科学、分析和 BI 进行建设性的讨论。从对整体形象的增值角度来看,证书并不是普遍得到认可的,因为如果你与 10 位经理谈论“他们在审查/选择求职面试简历时是否重视证书”,很肯定你会得到 5 个肯定,5 个否定。因此,学生和入门级的专业人士经常处于进退两难的境地,但考虑到我对画面的热爱,我不在其中😊。

自从我加入锡拉丘兹大学的 iSchool 以来,我一直在考虑获得 tableau 的认证,以及大多数招聘职位如何要求一个人知道至少一种标准的 BI 工具,无论是 Tableau、Microstrategy、PowerBI 还是其他工具。BI 工具上的所有这些招聘信息、讲座和博客点燃了我继续学习的好奇心,我决定要在 Tableau 获得认证。我在 2016 年 9 月决定了这一点,但由于时间表和事件的顺序,我未能将此事置于其他承诺之上。但最后,我在去年(2017 年)感恩节假期后恢复活力后做了这件事,并预订了日期。如果你已经犹豫了一段时间,不知道这样做的价值以及你是否会有时间,你应该只预订考试的日期。如果你不预订日期,你永远不会有时间!简单。

是什么启发我写了一篇关于 Tableau 证书的博客?

互联网上有大量的博客和资源,经过上个月的搜索,我觉得,我拥有的资源帮助我在考试中获得了超过 90%的分数。可以肯定的是,下面的资源不会让你获得 Tableau 认证,但也会帮助你成长为 Tableau 开发人员。

在我们深入研究计划以及如何从可用的免费/付费资源中学习之前,让我们先为从未听说过 Tableau 认证的人谈谈内务管理。

这里我们讨论的是 Tableau 桌面认证,请注意,Tableau 也是 Tableau 服务器认证,但这是另一天。

即使在 Tableau 桌面认证套件中,我们也根据您对该工具的理解和专业水平提供了几个选项。

1) Tableau 桌面合格助理(TDQA)

  • 推荐给具有至少 5 个月使用该工具的实践经验的人,以及了解 SQL 基础知识并理解数据库、连接和标准数据分析术语的人(即使您以前没有 Tableau 的经验,但愿意学习,您也可以获得认证)。
  • 费用:250 美元(不幸的是,没有学生折扣)
  • 时间限制:2 小时(额外 30 分钟用于设置和调查)
  • 问题数量:36
  • 问题的划分:70 次动手/30 次基于工具本身的理论
  • 及格分数:75%(注:每道题根据难度高低权重不同,动手更有价值)
  • Tableau 考试指南:下载 Tableau 考试指南

2) Tableau 桌面认证专家:

  • 推荐给有丰富 Tableau 桌面经验的人。建议有 9 个月以上的经验。与 TDQA 不同,该证书包括动手操作、书面回答和在 Tableau 桌面中构建/保存解决方案
  • 成本:600 美元(同样没有折扣)
  • 时间限制:3 小时(同样,额外的 30-45 分钟用于设置和调查)
  • 通过和评分:根据详细的评分标准手动评分

备考:

该博客安全地假设您从未使用过 Tableau 或者对该工具的访问权限有限。如果您是一名学生,并且没有访问该工具的权限, tableau 为学生提供一年的免费桌面工具访问权限。对于非学生和专业人士, tableau 提供 14 天的试用期这可能不够。但在博文的最后,我会分享免费获得 6 个月 Tableau 桌面访问的方法。继续读!

开始准备:

建议您做的第一件事是浏览 Tableau 桌面证书指南中的每个单词。pdf 做得非常好,列出了证书的知识,考试中测量的详细技能,并为您提供了样本问题和解决方案,以验证您对所要求技能的理解。对于该指南对于掌握证书的重要性,我怎么强调都不为过。实际上,在我准备的时候,我每周都会浏览 pdf 文档,并在我有绝对信心的技能和仍然需要改进的技能上打勾。一旦你复习完考试指南,就该记下你缺乏必要知识的地方,并开始复习。

我已经尝试将资源分为初级高级级别,以便在正确的时间访问正确的资源。

初学者资源:

  1. Tableau 学习 : 话不多说至于 Tableau 官网的免费培训对我备考有多大帮助。如果你看过考试指南,你会知道技能测试部分已经被分成数据连接,分别组织&简化数据 Tableau Learning 以类似的方式很好地组织了他们的培训。浏览 Tableau Desktop 下的所有视频两次,是的,两次,因为仅仅浏览一次是不够的,当你像我一样重新观看时,你会在观看时学到更多的技巧和诀窍,并提高你对该工具的理解。

**费用:**免费

2)【Tableau 10 A-Z 初学者】Kirill Eramenko**:**Kirill Eramenko 的初学者课程不是很适合专注于 Tableau 证书,如 Tableau Learning 和 Lukas Halim 的初学者 Tableau(描述如下),但该课程很好地介绍了 Tableau 10 的所有功能,该课程最好的部分是它很实用。一旦你完成了这个课程,你将从一个专业人士的角度学习 tableau,而不是作为一个仅仅是为了获得认证而学习 tableau 的学生。

通常需要 199.99 美元,但你总能在 Udemy online 上获得 90-95 折的优惠券,其中之一就是“JNY1202”

3)Lukas Halim**:**与 Kirill 的课程不同,本课程是专门为获得 Tableau 桌面认证而设计的。视频讲座充其量也就相当一般,我不会责怪 Lukas,因为课程的主要重点是让学生获得认证,而不是成为 Tableau 专家。本课程的好处是它非常紧密地遵循考试指南中的“技能衡量”部分,这允许您遵循考试的结构,并对所问的技能/问题更加自信。

课程中最精彩的部分?

Tableau 桌面资格助理考试的小测验和两个完整长度的模拟测试。我将在高级部分谈论考试,因为如果你还不熟悉这个工具本身,谈论模拟考试是没有意义的。

**费用:**与上面的建议类似,你可以用“JNY1202”这样的代码花 10-12 美元就能进入课程

  1. 安迪是数据学校的主教练,负责在 tableau 和 alteryx 上培训超过 1000 名个人。他是 Tableau 禅师,也是一个了不起的老师。在这段视频中,Andy 和他的 tableau/data school 学生团队分享了他们参加 Tableau QA 考试的经历,并单独谈论了技能部分,分享了一些如何快速学习这些技能的技巧&以及在考试中会遇到什么。我不得不说,这是一个相当不错的长达一小时的视频。

**花费:**你 1 个小时的时间

  1. Tableau 知识库 : 虽然没有遵循这些建议的特定格式,但我过去常常只是将“衡量技能”中的一行复制粘贴到谷歌上,然后阅读 Tableau 知识库上的文章。考虑到考试包含 30%的理论问题/权重,我们可以使用互联网搜索答案,阅读 Tableau 知识库是一个很好的培养习惯。

成本:免费

初学者部分到此为止。如果你遵循先完成 Tableau 学习,然后转到 Kirill 的 Tableau 10 A-Z,然后转到 Lukas Halim 的课程的模式,你现在应该足够自信,能够尝试 Tableau QA 考试指南中 50-60%以上的问题。

高级资源:

一旦您尝试了 Tableau QA 指南中的问题,就该进入高级部分了,这些部分将涵盖细节层次计算、集合/组、分析窗格等高级主题:

  1. Tableau 10 基里尔·叶列缅科 : 我非常喜欢基里尔的教学方式和他亲自动手的方法,即使是最简单的概念。在本高级培训中,Kirill 将带您浏览 5 个仪表板,涵盖一些非常高级的内容,如详细程度计算、高级计算(如字符串处理、数据处理、高级连接、数据混合)、仪表板操作、集合和组!同样,与 Kirill 之前的课程一样,他不会带着让您获得认证的心态教授课程,他会从专业分析师的角度教授,以及分析师将如何处理最终利益相关方提出的数据问题。一个一定要看的视频课程。

成本:$ 10–12

2)Coursera 的数据可视化与 Tableau 交流: 杜克大学的这门课程是我最喜欢的在线学习 Tableau 的课程之一。本课程最精彩的部分是,教师使用的数据集都是经过深思熟虑的,并且是实际操作的。数据集包括 H1B 工作签证申请数据和由 Dognition 提供的真实商业数据集,Dognition 是一家狗训练公司,它很乐意向学生提供关于他们公司的数据。

通过注册该课程,您还可以免费使用**tableau 6 个月,**即使您没有注册他们的付费证书选项。如果你因为没有 tableau 访问权限而坚持自己,那就去做吧

费用:免费,如果你需要完成证书

3)Simplilearn 的模拟测试:在你完成了上面链接的高级视频课程后,你现在已经准备好测试你的知识并了解你的弱点在哪里。如果你在网上搜索 tableau 考试的模拟试题,你会感到失望。在你准备期末考试之前,没有很多资源可以测试你的知识。Simplilearn 提供 2 个模拟测试样本,在您提交个人详细信息后,测试 1 即可公开获取,而如果您需要访问测试 2,则必须注册 Simplilearn 提供的 Tableau 课程的免费试用。当您尝试本模拟测试中的问题时,您会慢慢意识到这些问题的水平比考试指南低一个等级。真正的考试符合考试指南的水平,但由于没有太多的模拟考试,任何可以测试你的知识的考试都更有价值。如果你在这些测试中得分在 90%以上,不要太高兴,真正的模拟测试如下所述。

**费用:**免费或 7 天免费试用

  1. 学习 Tableau 实践考试 1:Tableau 桌面合格协理考试的事实上的实践考试。一旦你完成了所有的课程链接,Lukas Halim 的课程测试和 Simplilearn 的练习测试,并复习了测试之后,是时候进行真正的测试了!如果我说这个测试不值得,那我就是在撒谎。这是最接近 Tableau 的考试(包括练习 2,如下所述)。如果你真的对认证很认真的话,这是必须的。Lukas 做了一项了不起的工作,他真的提供了能很好地引起考试共鸣的数据集和问题。它的挑战性足以让你思考,不像 Simplilearn 测试,但也足够简单,让你对自己的准备感觉良好。卢卡斯创造了这些测试。

这项测试的另一个出色之处是 Lukas 为所有问题提供了一个出色的解决方案,而 simplilearn 没有做到这一点。这些解决方案指南帮助你了解错误的解决方案,并帮助你以更好的方式学习

**费用:**包含在您购买的 Lukas Halim 课程中,如果您没有兴趣购买课程,Lukas 还有独立测试包(比课程贵)。LearningTableau.com 有详细报道

  1. 高级概念:

如果我必须根据不同的难度等级来评价 tableau 考试,我会说 25%的问题是高级概念,我会在下面列出。这些概念是上述课程的一部分,但是单个概念的博客/视频可以让你更加关注它们,从而对它们更加好奇。你不仅要为考试准备这些高级概念,而且作为一个 tableau 的重度用户,我个人也在日常的 tableau 工作中使用一些概念。

a.**细节层次计算:**这是考试中最重要的概念之一。你不会得到超过 2-3 个关于这个概念的问题,但是考虑到它的用例以及 LOD 的强大,当然建议你尽可能多的了解它们。如果你浏览下面的链接,你会获得足够的关于 LOD 及其用例的知识。在考试中,您可能会遇到关于群组分析(或每个群组贡献了多少收入/销售额)、客户订单频率、客户获取的问题。

这里有一个提示,它将在考试中帮助你:只要学习固定 LOD,甚至不用担心包含或排除 LOD,包含和排除能做的,固定也能做。所以要成为固定 LOD 的专家。这里有一些关于它们的好资源

  1. **Top N/Nested N/Nested 排序:**另一个重要的概念,你可以很容易地想到关于 Top N/Nested N 的几个问题。这并不难,但如果没有给予适当的尊重,就很容易被忽略。以下资源将帮助您理解它。

c.**表计算:**大多数 tableau 新用户都知道计算字段,如 sum、average、datediff、datepart 等,但 tableau 中计算的另一个重要方面是表计算。这里有一些关于它们的好资源:

d.**参数及其用例:**虽然您不会被要求“专门”创建一个参数来解决任何问题,但它是您希望添加到 tableau 目录中的一个特性。最终利益相关者喜欢摆弄数据和控制数据点/参数的能力。tableau 中的参数赋予了他们这种超能力。

(我几乎每隔一周就重温一次这个视频,以获得如何在我的仪表板中使用参数的想法,它太棒了!只需将它加入书签以备将来使用)

e.**分析窗格:**分析窗格覆盖了考试总分数的 15%以上,是失分是犯罪的部分之一。如果你知道均值、中位数、众数、标准差、回归是什么意思,这里应该不会失分。一些好的资源:

f.**其他重要概念:**虽然我没有任何推荐的概念列表资源,但上面的课程很好地涵盖了它们:

  • 集合、组和创建组合集合
  • 高级过滤
  • 数据混合
  • 如何利用交叉表
  • 数据透视表
  • 拆分,自定义拆分
  • 连接计算
  • 绿色药丸和蓝色药丸的区别
  1. 学习表格练习测试 2 :已经学得够多了,该准备考试了。你怎么知道你是否准备好考试了呢?通过尝试卢卡斯·哈利姆的模拟测试 2。这两个测试都是最接近真实的测试。如果你直接从 udemy 上购买课程,你可以直接自动参加这两项考试,总共可以节省 20 美元。当尝试这个测试时,确保尝试复制真实的考试环境,这基本上意味着在两个小时内进行测试,没有手机,没有干扰。只有你和练习测试可以访问互联网,但没有电子邮件和聊天应用程序。一旦你完成了,即使你的分数低于 75%也不要担心,我有朋友在第二次测试中的分数低于 50%,但却通过了考试。只要确保你把事情放在你的下巴上,并仔细阅读解决方案指南。你现在准备好了!及时行乐!

杂项提示:

  • 该考试是监考考试,您可以在方便的时候进行,这意味着您可以在任何地方进行考试,唯一的问题是它将被监考。
  • 考试将在安装了相关数据文件和 tableau 桌面的虚拟机中进行。请务必查看数据文件。
  • 另一个非常重要的提示是,我一直给与我一起学习的其他人,总是用你的问题编号来重命名你的工作表。不要把它放在第一页、第二页……当到了复习的时候,你会浪费时间去找问题的工作表。
  • 在开始解决问题之前,在您的工作簿中添加一个仪表板,并在视图中拖动一个文本元素,开始记录需要检查的问题/要点,稍后再回来。
  • 一开始的问题让我很惊讶。这些问题的难度让我大吃一惊,我花了将近 20 分钟才解决了 3 个问题。所以,如果你也遇到了这种情况,不要担心,在最初的困难之后,问题会变得很简单,很容易解决。
  • 即使你对理论问题 100%有信心,也不要在没有搜索的情况下给它打分。提问的方式会利用你的疏忽,这样你就会失分。
  • 仪表板问题很简单,但问题的微小细节很容易被忽略。小心点。
  • 当你在 chrome 和 tableau 之间切换时,利用分屏可以节省一些时间。chrome 考试标签是移动自适应的,所以如果你调整考试标签的大小,你仍然可以阅读较小的 chrome 标签中的所有文本,而无需滚动。这给了我很大的帮助,也让我在回答问题的时候可以多次阅读问题。

继续你的学习:

考完了吗?已经认证了?恭喜你。你做到了。但是下一步,如果你想继续学习 Tableau 并从这一点开始成长。以下资源对我很有帮助,我很确定你也能从中学到很多。

  • tableau 大会直播:#Data17 即 Tableau 大会是 Tableau 每年举办的最大的数据大会之一。如果你是一名学生,参加会议的费用会很高,但是如果你能接触到会议上讨论的内容,如果你能接触到会议上教授的实践练习册,会怎么样呢?
  • 是啊。你可以!前往 tclive.tableau.com向最优秀的人学习!每年他们都会用最新的#数据视频和 handson 工作簿更新内容。
  • #改头换面星期一:需要一些不断的灵感和数据来挑战自己?网络上每周都有一些非常好的社交项目,其中之一是安迪·克里贝尔和伊娃·默里的#改头换面星期一,请访问#改头换面星期一,了解更多关于社区仪表盘的信息,让你大吃一惊!
  • 即社会公益:类似于#改头换面星期一,但具有独特的挑战。点击了解更多信息
  • Tableau Tips 周二:每周一篇关于一些高级 Tableau 概念的博客文章,由 Andy Kriebel 亲自解释!他们的一些令人惊叹的博客帖子包括 KPI 和迷你图,创建棒棒糖图表

这应该足以满足你的好奇心,以了解更多关于 Tableau。如果你觉得这篇博文足够有价值,点击分享按钮,或者在 Medium 上阅读时鼓掌,或者在 LinkedIn 上添加我,让我们在这里创建一个#数据社区,互相学习。

原载于 2018 年 10 月 1 日www.linkedin.com

CTR 预测的不确定性:一个阐明所有不确定性的模型

原文:https://towardsdatascience.com/uncertainty-for-ctr-prediction-one-model-to-clarify-them-all-8cb0aa5ed2?source=collection_archive---------21-----------------------

在本系列的第一篇文章的中,我们讨论了会影响模型的三种不确定性——数据不确定性、模型不确定性和测量不确定性。在的第二篇文章中,我们具体讨论了处理模型不确定性的各种方法。然后,在我们的第三篇文章中,我们展示了如何利用模型的不确定性来鼓励在推荐系统中探索新项目。

如果我们可以使用一个统一的模型,以一种有原则的方式处理所有三种类型的不确定性,这不是很好吗?在这篇文章中,我们将向你展示我们在 Taboola 是如何实现一个神经网络来估计一个物品与用户相关的概率,以及这个预测的不确定性。

让我们跳到深水处

一张图胜过千言万语,不是吗?一张包含一千个神经元的图片?…

无论如何,这是我们使用的模型。该模型由几个模块组成。我们将解释每个人的目标,然后画面会变得更清晰…

项目模块

该模型试图预测一个项目被点击的概率,即 CTR(点击率)。为此,我们有一个模块,它获取项目的特征作为输入,如标题和缩略图,并输出一个密集的表示——如果你愿意,也可以是一个数字向量。

一旦模型被训练,这个向量将包含从项目中提取的重要信息。

上下文模块

我们说过模型预测了一个项目被点击的概率,对吗?但是这个项目是在什么样的背景下展示的呢?

上下文可能意味着很多事情——出版商、用户、一天中的时间等等。该模块获取上下文的特征作为输入。然后它输出上下文的密集表示。

融合模块

因此,我们从项目和上下文中提取了信息。当然,这两者之间有一些互动。例如,与金融出版商相比,体育出版商中关于足球的项目可能具有更高的点击率。

这个模块将两种表示融合成一种,类似于协同过滤。

估计模块

最后,我们有一个模块,其目标是预测 CTR。此外,它还估计了 CTR 估计的不确定性。

我猜你对这个模块是如何工作的不太确定,所以让我们来解释一下。

我们将带您了解我们提到的三种不确定性,并向您展示我们的模型是如何处理每一种不确定性的。首先,让我们解决数据的不确定性。

资料不确定

让我们用一些在回归任务上训练的通用神经网络。一个常见的损失函数是 MSE——均方误差。我们喜欢这种损失,因为它是直观的,对不对?您希望最小化误差…但事实证明,当您最小化 MSE 时,您隐含地最大化了数据的似然性-假设标签正态分布,具有固定的标准偏差𝝈.这个𝝈是数据中固有的噪声。

我们可以做的一件事是通过引入一个新的节点,我们称之为𝝈.,显式地最大化可能性将其插入似然方程并让梯度传播使得该节点能够学习输出数据噪声。

我们没有取得任何不同,对吗?我们得到了与最初基于 MSE 的模型相同的结果。但是,现在我们可以引入从最后一层到𝝈:的链路

现在我们开始有趣的事情了!𝝈现在是输入的函数。这意味着模型可以学习将不同级别的数据不确定性与不同的输入关联起来。

我们可以让这个模型更加强大。我们可以估计高斯分布的混合物,而不是估计高斯分布。我们加入的高斯函数越多,模型的容量就越大——也更容易过度拟合,所以要小心。

这种架构被称为 MDN——混合密度网络。它是由主教等人于 1994 年引进的。以下是它捕捉到的一个例子:

我们有两组类似的项目——一组是关于购物的,另一组是关于运动的。

事实证明,购物项目往往有更多的可变点击率——可能是由于趋势。事实上,如果我们要求模型估计每组中一个项目的不确定性(图中的虚线),我们得到的购物不确定性比运动更高。

所以数据不确定性已经过去了。下一步是什么?

测量不确定度

这个有点复杂。在的第一篇文章中,我们解释了有时候测量会有噪音。这可能会导致有噪声的要素甚至有噪声的标注。在我们的例子中,我们的标签 y 是一个项目的经验性点击率——到目前为止它被点击的次数除以它被显示的次数。

假设一个物品的真实 CTR 是 y* —也就是说,没有测量噪声。如果我们在上下文中无限次显示该项目,这将是 CTR。但是时间是有限的(至少我们有的时间是有限的),所以我们只展示了有限的次数。我们测量了一个观察到的 CTR y。这个 y 有测量噪声——我们用𝜺.表示

接下来,我们假设𝜺呈正态分布,标准偏差为𝝈𝜺。r 的𝝈𝜺函数——我们展示物品的次数。r 越大,𝝈𝜺越小,这使得 y 更类似于 y*。

在一天结束时,在我们把你从数学细节中解救出来(你可以在我们的论文中找到)之后,我们得到这个可能性等式:

这与混合高斯分布的 MDN 架构中的可能性相同,但有一点不同,误差项分为两部分:

  • 数据不确定性(𝝈i)
  • 测量不确定度(𝝈𝜺)

既然模型能够用不同的术语解释每个不确定性,数据不确定性就不会被测量不确定性所污染。

除了能够以更好的方式解释数据,这允许我们在训练过程中使用更多的数据。这是因为在这项工作之前,我们过滤掉了太多噪音的数据。

最后但并不是最不重要的

在前一篇文章中,我们讨论了如何处理模型不确定性。我们描述的方法之一是在推理时使用 dropout。

能够估计模型的不确定性使我们能够更好地理解模型由于缺乏数据而不知道的东西。所以让我们来测试一下吧!

让我们看看独特的标题是否与高不确定性有关。我们将把训练集中的每个标题映射到一个密集表示(例如,平均 word2vec 嵌入),并期望该模型对唯一标题不太确定,唯一标题是映射到嵌入空间的稀疏区域的标题。

为了测试它,我们通过计算 KDE(核密度估计)来计算稀疏和密集区域。这是一种估计我们空间的 PDF(概率密度函数)的方法。接下来,我们要求模型估计与每个标题相关的不确定性。事实证明,该模型在稀疏区域确实具有更高的不确定性!

很好…如果我们向模型显示更多稀疏区域的标题,会发生什么?会不会对这些区域比较确定?让我们来测试一下!

我们取了一堆类似的关于汽车的标题,把它们从训练集中去掉了。实际上,它改变了他们在空间中的区域,从密集变为稀疏。接下来,我们估计了这些标题的模型不确定性。不出所料,不确定性很高。

最后,我们只将其中一个标题添加到训练集中,并重新训练该模型。令我们满意的是,现在所有这些项目的不确定性都降低了。整洁!

正如我们在看到的关于勘探开发的帖子,我们可以鼓励对这些稀疏地区的勘探。这样做之后,不确定性就会降低。这将导致该地区勘探的自然衰退。

最后的想法

在这篇文章中,我们详细阐述了如何使用一个统一的模型,以一种原则性的方式对所有三种类型的不确定性——数据、模型和测量——进行建模。

我们鼓励你思考如何在你的应用中使用不确定性!即使你不需要在你的预测中明确地模拟不确定性,你也可能从在训练过程中使用它中受益——如果你的模型能够更好地理解数据是如何产生的,以及不确定性如何影响游戏,它可能会有所改进。

这是与我们在今年 KDD 会议的一个研讨会上提交的论文相关的系列文章的第四篇: 深度密度网络和推荐系统中的不确定性

第一篇帖子可以在 这里找到
第二个帖子可以在这里找到

第三个帖子可以在这里找到*
。***

原载于engineering.taboola.com由我和 Inbar Naor 。

深度学习和神经网络中的不确定性?我没有那种感觉!

原文:https://towardsdatascience.com/uncertainty-in-deep-learning-and-neural-network-i-do-not-feel-that-way-f11ceca4341a?source=collection_archive---------1-----------------------

注意:这是 2014 年 6 月 5 日星期四的一篇旧博客文章

您可能知道,神经网络最近经常出现在新闻中,有许多成功的故事。

神经网络现在是最先进的算法,可以理解复杂的感官数据,如图像、视频、语音、音频、声音、音乐等。

神经网络最近更名为深度学习(DL)或深度神经网络。

2012 年,他们在一个行业标准图像数据集中超过任何其他算法 10%以上,成为新闻:

http://image-net.org/challenges/LSVRC/2012/results.html

他们在语音识别方面也有类似的提高,提高了 20%:

http://www . nytimes . com/2012/11/24/science/scientists-see-advances-in-deep-learning-a-part-of-artificial-intelligence . html?_r=0

和许多其他任务中。最近在熟悉面孔识别中达到人类表现的水平:

https://www.facebook.com/publications/546316888800776/

然而,行业和投资者都很谨慎。

他们经常看到新算法来来去去,几乎是年年如此。

他们说:“为什么一家初创公司要做深度学习或神经网络?当一个更好的算法出现并把你从平板电脑上抢走时,会发生什么?”

这是一个合理的怀疑,但是我确信我们不应该再为此担心了。

神经网络已经存在很多年了。

这有三个强有力的理由:

1.神经网络非常优越:

2012 年,深度神经网络算法被证明是理解复杂感官数据的最佳算法 10–20%,而不是每年 1–2%的典型改进。

这是复杂数据中算法性能的大差异。在我的职业生涯中,我从未见过如此大的进步。

想象一下,一名 100 米短跑运动员用 7.5 秒跑完,比其他人快了整整 2 秒,而以前的典型记录通常只比他快 0.1 秒。你不会感到惊讶吗?“几乎不真实!”

2.神经网络将在多项任务中达到人类水平的性能:

人脑是一个巨大的神经网络。深度学习提供了受生物神经系统(如人脑)启发的大型神经网络模型。

人脑是已知宇宙中复杂感官数据的最佳“处理器”。我们可以理解图像、视频、声音,就像今天没有电脑能理解的那样!

随着数据集和网络拓扑结构的改善,人脑模型,如深度学习中使用的人工神经网络,可以扩展到人类的表现。上面提到的脸书·迪普法斯就是一个例子。

随着我们加深对大脑神经拓扑的了解,并改进人工神经网络模型,我们可以在更多的任务中达到人类的表现。现在这种情况正在发生:每隔几个月,我就会有一个新的结果。

3.神经网络可以扩展:

我们在过去已经看到许多算法不能扩展到感官数据的复杂性。他们可以做得很好几年,然后他们在新一波“新”算法下消失了。虽然这已经发生了,但神经网络持续不断地进化,有时在聚光灯之外,持续了 60 多年。我们将这一进展归功于许多聪明的同事和研究人员。

但是将神经网络与其他技术区分开来的一个区别是,它们是一个非常可扩展的模型。他们理解数据的能力可以随着模型的大小以及可用于训练这些模型的数据而增长。通过添加神经元层、不同的连接和连接拓扑、空间和时间形式的更多输入数据,模型可以提供不断增强的能力,以理解它们接受训练的复杂数据和同类的新数据。

底线:

深度学习和神经网络将继续存在。至少 10 年,或者只要我们在理解原始感官数据方面达到人类的表现水平。

如果您想投资并推动技术的未来,这就是您想要的!

你为什么要相信我?“这只是你的看法!”,”“你到底是谁?"

我是教授、发明家、工程师和科学家。我希望我的工作能改变世界。因为我的研究成功,我见到了美国总统奥巴马。我教授大学水平的计算神经科学、微芯片设计、计算机架构、机器和深度学习等等。

我在神经形态系统的设计方面有 20 多年的经验。我在模拟微芯片、数字微芯片、计算机代码和理论中看到过神经网络。我见过许多人工神经系统的例子,不管是在硬件领域还是软件领域,都有成功的例子,也有失败的例子。我自己设计了许多系统,以第一人称测试代码和算法,而不仅仅是通过其他人的工作。

我的目标是用我的科技知识帮助人类。这就是现在的方法,用深度神经网络!

我不喜欢算法,我喜欢可行的和可扩展的。深度神经网络现在可以工作和扩展。

我见过很多事情,我有经验把我的一生花在对整个人类的重要目标上。如果我不是非常相信神经网络的力量和潜力,我不会在这个领域工作。

现在相信我或者让时间说服你,代价是失去一个大好机会。

在你们做出决定的同时,我和我的所有同事将每天继续推动技术的发展,打破阻碍当前计算机理解图像、视频、语音、音频和任何复杂感官数据的障碍。

这是我们的选择,我们的命运。

这是不可避免的。

欢迎评论!

发布于 2014 年 6 月 5 日,星期四

关于作者

我在硬件和软件方面都有将近 20 年的神经网络经验(一个罕见的组合)。在这里看关于我:传媒、网页、学者、 LinkedIn 等等…

揭示 Python 中树集合的结构

原文:https://towardsdatascience.com/uncover-the-structure-of-tree-ensembles-in-python-a01f72ea54a2?source=collection_archive---------6-----------------------

Photo by Ghost Presenter on Unsplash

集成方法将多个基本估计量结合起来,以产生更稳健的模型,更好地概括新数据。 BaggingBoosting 是集成方法的两个主要类别,它们的区别在于它们组合来自基础估计量的预测的方式。

Bagging 方法独立地建立估计量,然后平均它们的预测值。通过在构建每个基础估计量的方式中引入随机性,他们旨在减少最终模型的方差。换句话说,减少过度拟合。

Boosting 方法在序列中建立基本估计量,其中每个后续估计量从其前一个估计量的错误中学习。与减少方差相反,这些方法的目标是减少所得估计量的偏差。

每一类都包含几个算法。在这里,我们将看看两个广泛应用的算法,每个类别一个;随机森林作为装袋的例子 Ada Boost 作为 boosting 方法的例子,用决策树作为基本估计器。我们将在分类的上下文中讨论这些方法,尽管这两种方法也在回归任务中使用。

这篇文章的目的是展示如何通过可视化的树来挖掘集合的几个潜在估计量。

随机森林

随机森林,顾名思义,是一种建立在决策树上的装袋方法。每棵树都在数据的引导样本上进行训练,并且可以选择使用原始输入特征的子集。这两个随机因素确保了每棵树都是不同的。如果我们假设每棵树都超过了部分数据,我们期望它们的平均值会减少这种影响。

控制随机森林结构的主要参数是估计器的数量( n_estimators ),即构建的决策树的总数和用于在每个节点选择分裂的输入属性的最大数量( max_features )。

一般来说,估计量越大,结果越好。然而,大量的估计器也导致长的训练时间。也很有可能在一定数量的估计量之后,精确度的增加将趋于平稳。人们应该在准确性和性能之间寻求平衡。交叉验证是一种可以用来调整这些参数的原则性方法。

一旦选择了 n_estimators= N ,就以上述方式构建了 N 个决策树,并且通过对这些预测进行平均来获得最终预测。为了深入了解每个单独的预测,我们可以将构建的每个树可视化。

在这篇文章中,我们展示了如何在 Jupyter 笔记本中绘制决策树。这里,我们将更进一步,看看如何绘制一个系综的所有 N 棵树。

下面是为 sklearn 葡萄酒数据集训练随机森林分类器的脚本。

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine# load dataset
data = load_wine()# feature matrix
X = data.data# target vector
y = data.target# class labels
labels = data.feature_namesestimator = RandomForestClassifier().fit(X, y)

分类器对象有一个属性 estimators_ ,它是一个由 N 棵决策树组成的列表。这个列表的长度给出了树的数量。

print(“Number of trees “ + str(len(trees)))Number of trees 50

如果我们打印 trees 对象,我们将得到每个估计量的摘要。

display(estimator.estimators_)

Sample of estimators_

我们可以遍历列表中的每个元素,得到每棵树的节点数。

print("Number of nodes per tree is ")

i_tree = 0
for tree_in_forest in trees:
print(tree_in_forest.tree_.node_count)
i_tree += 1Number of nodes per tree is 
23
23
9
19
27
27
21
23
21
25

现在,如果我们迭代 trees 对象,我们可以使用 export_graphviz 函数来绘制每棵树。因为树的数量通常很大,所以在笔记本中画出每一棵树并不方便。相反,我们可以将每个文件保存在工作目录中的. dot 文件中。如果您还想将每个文件保存为. png 格式,请使用 check_call 功能。

from sklearn.tree import export_graphviz
from subprocess import check_callcnt = 1
for item in trees:
     export_graphviz(item, out_file=str(cnt)+’_tree.dot’,feature_names= labels, class_names=labels, rounded=True, precision=4, node_ids=True, proportion=True
, filled=True)

     check_call([‘dot’,’-Tpng’,str(cnt)+’_tree.dot’,’-o’,str(cnt)+’_tree.png’]) cnt += 1

一旦迭代完成,我们将在我们的目录中得到一个文件编号列表。

List of files in directory

下面是两种经过训练的树。

Two of the Decision Trees of the trained Random Forest model

我们可以看到,每棵树可以有不同的深度,以及不同的节点结构和分裂。这正是在不同的数据子集上构建每棵树,并基于特征子集进行分割的结果。在这一点上,我们应该提到,bagging 方法通常在复杂的底层模型(即深树)中工作得更好,它们减少了过拟合效应。

Ada 增强

与 bagging 相反,boosting 方法的原理是训练一系列“弱”学习器,例如深度小的决策树。在每次迭代中,通过为数据的每个实例分配权重来构建树。首先,给定 k 个训练样本,每个训练样本被赋予等于 1/k 的权重。在每次迭代中,没有被正确分类的样本得到更高的权重,迫使模型在这些情况下更好地训练。最后,通过加权多数投票将预测结合起来。

Ada Boost 的主要参数是 base_estimatorn _ estimator。估计量的数量相当于随机森林所描述的参数。基本估计量是基础模型的模型类型。在 sklearn learn 中,默认的基础估计器是决策树桩(具有 max_depth = 1 的决策树)。

与 RandomForestClassifier 类似,AdaBoostClassifier 也有一个 estimators_ 属性。因此,我们可以训练一个 AdaBoost 分类器,并以上述方式绘制所有的树。

from sklearn.ensemble import AdaBoostClassifierestimator = AdaBoostClassifier().fit(X, y)

trees = estimator.estimators_

print("Number of trees " + str(len(trees)))Number of trees 50

sklearn 中 AdaBoost 的默认估计数是 50。使用与上面完全相同的循环,我们可以得到 50 棵决策树中每一棵的图像。

Three first Decision Trees of the trained AdaBoost model

有前三个决策树,每个在顶部节点有不同的分割。这一次,不同的分裂是由于每个样本在每次迭代中得到的不同权重。每棵树都专注于正确预测前一棵树未能正确分类的内容。

在本文中,我们看到了一种可以应用于 bagging 和 boosting 两个分类器家族的方法,以便可视化底层模型,这些模型的投票构成了我们模型的最终预测。通过这种可视化,我们展示了如何通过装袋中的随机化和 boosting 中的权重分配从相同的原始数据和输入要素构建 N 个不同的树。再一次,我发现这是一个实用的方法,可以更好地理解集合方法在幕后是如何工作的,并且在我们的项目中使用这种模型时,可以减少黑箱。

使用数据科学揭示 AirBnB 评论中的隐藏趋势

原文:https://towardsdatascience.com/uncovering-hidden-trends-in-airbnb-reviews-11eb924f2fec?source=collection_archive---------9-----------------------

欢迎来到词汇世界

在做情感挖掘的研究时,我熟悉了主观词汇的重要概念。词典的应用是情感分析的两种主要方法之一。它包括从文本中出现的单词或短语的语义方向计算情感。

R 中可用的词典:

qdap 的极性()函数:使用来自 hash _ 情操 _ 刘虎(IL @CHI 极性(+/-)词研究的 U)的词典

  • NRC —根据 8 种情绪的单词,如“愤怒”或“喜悦”以及阳性/阴性
  • —标记为肯定或否定的词
  • AFINN —得分从-5 到 5 的单词

省力原则 使有限的词库变得有用。

您可以根据自己的需要随时修改词典!

1.定义业务问题

这是我最喜欢的,也是任何项目成功的最重要的一步:问正确的问题。一些领域的理解或与领域专家的交流确实有助于定义一个合适的问题陈述。

你应该很清楚自己的数据,并且有充分的理由去挖掘情感,而不仅仅是因为这听起来很酷!;)

例如,通常在调查中,消费者被要求在一定范围内对产品进行评级。在这种情况下,一个有序的评级足以确定消费者对产品的情绪,这里的情绪分析就有点过了。如果你想** 知道消费者喜欢或不喜欢产品的什么, 使用开放式问题,并使用回答提取有意义的见解。**

在这个博客中,我们将找出哪些住房属性(例如,餐馆、地铁站附近、卫生、安全等。)根据总体客户评价带来良好的租赁体验。

2.识别文本来源

从任何网站获取顾客评论的流行方式之一是通过网络搜集。用 R 或者 Python 都可以。我会在我的下一篇博客中保留这个话题。目前,我选择了一个数据集,其中有 1000 条关于波士顿 AirBnB 租赁的用户评论。****

*# Upload dataset in R (available as .rds file)* 
> bos_reviews <- readRDS("bos_reviews.rds", refhook = NULL)

3.组织和清理文本

在这一步,我们将使用两种不同的词汇( PolarityBING )来确定所收集的房屋评论的情感得分。

基于简单 Qdap 的极性评分

从进行情绪分析开始是一种合理的方法,因为它让您熟悉数据,并帮助您设定期望,以更好地解决业务问题。为此,来自 qdap 封装的极性功能非常有用。它允许我们将文本分为正面或负面。

*# Check out the boston reviews polarity overall polarity score* > bos_pol <- polarity(bos_reviews)  
> bos_pol all total.sentences total.words ave.polarity sd.polarity stan.mean.polarity all 1000 70481 0.902 0.502 1.799 *# Summary for all reviews* 
> summary(bos_pol$all$polarity) 
   Min. 1st Qu. Median  Mean  3rd Qu.  Max.   NA's 
-0.9712 0.6047  0.8921 0.9022 1.2063  3.7510   1 *# Kernel density plot of polarity score for all reviews* 
> ggplot(bos_pol$all, aes(x = polarity, y = ..density..)) + theme_gdocs() + geom_histogram(binwidth = 0.25, fill = "#bada55", colour = "grey60") + geom_density(size = 0.75)

The above graph shows that the median polarity score is greater than zero, i.e., the reviews tend to be positive. Notice that the reviews do not center on zero: this is known as grade inflation. There are two possible causes for this. First, social norms may lead respondents to be pleasant instead of neutral. The second reason could be **feature-based sentiment,where an author may write, “the bed was comfortable and nice, but the kitchen was dirty and gross” and the sentiment encompasses multiple “features” simultaneously, thereby skewing the average score.

TidyText 的必应词典

在这里,我们将直接从名为“comments”的 review 列创建 word data。

> library(tidytext) 
> library(tidyr) 
> library(dplyr) *# Use unnest_tokens to make text lowercase & tokenize reviews into single words.* 
> tidy_reviews <- bos_reviews %>% unnest_tokens(word, comments) *# Group by and mutate to capture original word order within each group of a corpus.* 
> tidy_reviews <- tidy_reviews %>% group_by(id) %>% mutate(original_word_order = seq_along(word)) *# Quick review* 
> tidy_reviews 
A tibble: 70,834 x 3 
Groups: id [1,000] 
id               word         original_word_order 
1 1               my                  1 
2 1            daughter               2 
3 1              and                  3 
4 1               i                   4 
5 1              had                  5 
6 1               a                   6 
7 1           wonderful               7 
8 1             stay                  8 
9 1             with                  9 
10 1            maura                 10 # ... with 70,824 more rows 
*# Load stopwords lexicon* 
> data("stop_words") *# Perform anti-join to remove stopwords* 
> tidy_reviews_without_stopwords <- tidy_reviews %>% anti_join(stop_words) *# Getting the correct lexicon* > bing <- get_sentiments(lexicon = "bing") *# Calculating polarity for each review* > pos_neg <- tidy_reviews_without_stopwords %>% inner_join(bing) %>% count(sentiment) %>% spread(sentiment, n, fill = 0) %>% mutate(polarity = positive - negative) *# Checking outcome* 
> summary(pos_neg) 
    id              negative         positive         polarity 
Min. : 1.0       Min. : 0.0000      Min. : 0.00     Min. :-11.000 
1st Qu.: 253.0   1st Qu.: 0.0000    1st Qu.: 3.00   1st Qu.: 2.000 Median : 498.0   Median : 0.0000    Median : 4.00   Median : 4.000 Mean : 500.4     Mean : 0.6139      Mean : 4.97     Mean : 4.356 
3rd Qu.: 748.0   3rd Qu.: 1.0000    3rd Qu.: 7.00   3rd Qu.: 6.000 Max. :1000.0     Max. :14.0000      Max. :28.00     Max. : 26.000 *# Kernel density plot of Tidy Sentiment score for all reviews* 
> ggplot(pos_neg, aes(x = polarity, y = ..density..)) + geom_histogram(binwidth = 0.25, fill = "#bada55", colour = "grey60") + geom_density(size = 0.75)

Based on the polarity distribution for both Qdap’s polarity score and TidyText’s BING, we can say that the comments are tending towards positive.

4.创建基于极性的语料库

在极性检查之后,我们需要创建一个大的文本集,用于下一步的特征提取。

a .根据步骤 2 中计算出的极性得分,将所有 1,000 条意见分为正面和负面意见。

*# Add polarity column to the reviews*
> bos_reviews_with_pol <- bos_reviews %>% mutate(polarity = bos_pol$all$polarity)

*# Subset positive comments based on polarity score*
> pos_comments <- bos_reviews_with_pol %>% filter(polarity > 0) %>% pull(comments)

*# Subset negative comments based on polarity score*
> neg_comments <- bos_reviews_with_pol %>% filter(polarity < 0) %>% pull(comments)

b .将正面和负面评论折叠成两个较大的文档。

*# Paste and collapse the positive comments* 
> pos_terms <- paste(pos_comments, collapse = " ") *# Paste and collapse the negative comments * 
> neg_terms <- paste(neg_comments, collapse = " ") *# Concatenate the positive and negative terms* 
> all_terms <- c(pos_terms, neg_terms)

c .创建词频逆文档频率(TFIDF)加权词频文档矩阵(TDM)。

这里,不是计算单词在语料库中的频率,而是对过度使用的术语惩罚 TDM 中的值,这有助于减少无信息的单词。

*# Pipe a VectorSource Corpus* 
> all_corpus <- all_terms %>% VectorSource() %>% VCorpus() *# Simple TFIDF TDM* 
> all_tdm <- TermDocumentMatrix(all_corpus, control = list( weighting = weightTfIdf, removePunctuation = TRUE, stopwords = stopwords(kind = "en"))) *# Examine the TDM * 
> all_tdm <> Non-/sparse entries: 4348/5582 Sparsity: 56% Maximal term length: 372 Weighting: term frequency - inverse document frequency (normalized) (tf-idf) *# Matrix* 
> all_tdm_m <- as.matrix(all_tdm) *# Column names* 
> colnames(all_tdm_m) <- c("positive", "negative")

5.提取特征

在这一步中,我们将从 TDM 中提取关键的住房特征,从而得出正面和负面的评价。

*# Top positive words* 
> order_by_pos <- order(all_tdm_m[, 1], decreasing = TRUE) *# Review top 10 positive words* 
> all_tdm_m[order_by_pos, ] %>% head(n = 10) DocsTerms       positive     negative 
walk           0.004565669       0 
definitely     0.004180255       0 
staying        0.003735547       0 
city           0.003290839       0 
wonderful      0.003112956       0 
restaurants    0.003053661       0 
highly         0.002964720       0 
station        0.002697895       0 
enjoyed        0.002431070       0 
subway         0.002401423       0 *# Top negative words* 
> order_by_neg <- order(all_tdm_m[, 2], decreasing = TRUE) *# Review top 10 negative words* 
> all_tdm_m[order_by_neg, ] %>% head(n = 10) DocsTerms       positive      negative 
condition           0        0.002162942 
demand              0        0.001441961 
disappointed        0        0.001441961 
dumpsters           0        0.001441961 
hygiene             0        0.001441961 
inform              0        0.001441961 
nasty               0        0.001441961 
safety              0        0.001441961 
shouldve            0        0.001441961 
sounds              0        0.001441961

6.分析特征

让我们比较一下通过 WordClouds 获得正面和负面评价的房屋特征。

a .对比云

> comparison.cloud(all_tdm_m, max.words = 20, colors = c("darkblue","darkred"))

b .缩放后的对比云

通过这种可视化,我们将在执行语料库子集之前,通过将评论分数调整回零,修复等级膨胀对租赁评论极性分数的影响。这意味着一些先前的正面评论可能会成为负面子部分的一部分,反之亦然,因为平均值变为零。

*# Scale/center & append* 
> bos_reviews$scaled_polarity <- scale(bos_pol$all$polarity) *# Subset positive comments* 
> pos_comments <- subset(bos_reviews$comments, bos_reviews$scaled_polarity > 0) *# Subset negative comments* 
> neg_comments <- subset(bos_reviews$comments, bos_reviews$scaled_polarity < 0) *# Paste and collapse the positive comments* 
> pos_terms <- paste(pos_comments, collapse = " ") *# Paste and collapse the negative comments* 
> neg_terms <- paste(neg_comments, collapse = " ") *# Organize* 
> all_terms<- c(pos_terms, neg_terms) *# VCorpus* 
> all_corpus <- VCorpus(VectorSource(all_terms)) *# TDM* 
> all_tdm <- TermDocumentMatrix( all_corpus, control = list( weighting = weightTfIdf, removePunctuation = TRUE, stopwords = stopwords(kind = "en"))) # Column names 
> all_tdm_m <- as.matrix(all_tdm) 
> colnames(all_tdm_m) <- c("positive", "negative") # Comparison cloud 
> comparison.cloud(all_tdm_m, max.words = 100, colors = c("darkblue", "darkred"))

除了上面的分析,我还想评估一个作者在写正面评论和负面评论时付出的努力之间的相关性。这是通过绘制正面和负面评论的字数来完成的。

*# Create effort* 
> effort <- tidy_reviews_without_stopwords %>% count(id) *# Inner join* 
> pos_neg_with_effort <- inner_join(pos_neg, effort) *# Review* 
> pos_neg_with_effort  
A tibble: 953 x 5 Groups: id [?] 
id      negative     positive      polarity     n 
1 1         0            4             4        26 
2 2         0            3             3        27 
3 3         0            3             3        16 
4 4         0            6             6        32 
5 5         0            2             2         8 
6 6         0            3             3        21 
7 7         0            5             5        18 
8 8         0            2             2        10 
9 9         0            4             4        12 
10 10       1           15            14        46 
*# ... with 943 more rows * *# Add pol* 
> pos_neg_pol <- pos_neg_with_effort %>% mutate(pol = ifelse(polarity >= 0, "Positive", "Negative")) *# Plot* 
> ggplot(pos_neg_pol, aes(polarity,n, color = pol)) + geom_point(alpha = 0.25) + geom_smooth (method = "lm", se = FALSE) + ggtitle("Relationship between word effort & polarity")

7.得出结论

不足为奇的是,顶级正面词汇包括:

  • 步行
  • 装备精良
  • 饭店
  • 地铁

相比之下,最负面的术语包括:****

  • 自动过账
  • 垃圾箱
  • 肮脏的
  • 卫生
  • 安全
  • 声音

同样,可以看出作者会花更多的精力来写一篇更强有力的正面或负面评论。这话多么真实啊!

我确信,有了更大的数据集,我们可以挖掘出比这个小案例研究更深刻的见解。

非常感谢您的阅读!

我写这篇博客的目的是与所有有志成为数据科学家的人分享情绪分析的基本概念,但我们不能就此止步!我想我已经准备好为我的作品集做一个更精细的情感挖掘项目了,:D,你呢?

请在下面的评论中分享你的想法/反馈。

也可以在 Linkedin 上和我联系。

继续编码。干杯!

(首发@www.datacritics.com)

揭开 Airbnb 高收入的秘密

原文:https://towardsdatascience.com/uncovering-the-secrets-to-higher-airbnb-revenues-6dbf178942af?source=collection_archive---------8-----------------------

使用数据分析和机器学习来揭示波士顿和西雅图 Airbnb 成功上市背后的秘密

介绍

Airbnb 是全球最受欢迎的短期租赁在线房源服务之一。虽然建立 Airbnb 业务相对容易,但在这一行取得成功可能很难。如果你正在考虑进入波士顿和西雅图的 Airbnb 业务,这篇文章就是为你而写的。

我们将探索 Airbnb 在这些城市是否确实是一项可行的业务,并应用数据分析和机器学习来确定策略,以帮助您获得超越竞争对手的优势。

将调查以下问题:

  • Airbnb 主机的收入有多少?
  • 出租什么类型的房产最好?
  • 什么时候是最好的租赁时间?
  • 哪些区域最适合出租?
  • 为了吸引更多的注意,你应该在列表名称中写些什么?

我们还将分享一些额外的技巧,帮助你成为一名成功的 Airbnb 房东,敬请关注。

数据

为了回答这些问题,我们将使用 Kaggle 提供的 Airbnb 数据集来处理波士顿和 T2 的数据。这些数据集提供的信息包括两个城市的房源详情、客户评论和房源安排。

假设

虽然两个数据集都没有提供预订的详细信息,但我们可以根据他们在该时间段内收到的评论数量来估计每个酒店的预订数量。然后,我们可以用以下公式推断每项资产的收入:

评论数量 x 列表价格 x 最短停留时间

这是对收入的保守估计,因为酒店的预订量很可能会超过点评量。此外,客人还可能会停留超过规定的最低住宿天数。

事不宜迟,我们开始吧!

s

2015 年波士顿的平均主机收入为 7200 美元,而西雅图为 4700 美元

2015 年,波士顿 Airbnb 主机的平均估计收入为 7200 美元。在一年中有 90 多天在网上登记房产的活跃房东中,平均年收入增长到了 9000 美元左右。

虽然 2015 年波士顿 Airbnb 主机的平均收入相对较高,但收入差距普遍存在。50%的活跃主机收入低于 3,900 美元,而前四分之一的活跃主机平均收入超过 9,800 美元。

波士顿的顶级 Airbnb 主机在 2015 年获得了超过 371,000 美元的收入!事实上,4 个票房收入最高的主机在那一年获得了至少 10 万美元的收入。

在西雅图,2015 年 Airbnb 主机的平均收入估计为 4700 美元,而一个活跃的主机收入超过 4900 美元。

和波士顿的情况一样,西雅图也存在收入差距。50%的活跃主机收入不到 2,400 美元,而前 25%的活跃主机平均收入超过 5,800 美元。同时,西雅图的顶级主持人获得了超过 27 万美元的收入。

在波士顿,你应该租出整个公寓或房子,而在西雅图,能容纳 4 个人的公寓最好

在波士顿出租整个公寓或房子可能会带来不错的收入。预计整套公寓的年收入为 6100 美元,整栋房子的年收入为 6700 美元。

这不仅远高于波士顿 Airbnb 房源的平均收入(4600 美元),公寓和房屋也是波士顿房源的最大组成部分。因此,对这类房产的需求相对健康。

虽然可能有其他类型的财产(床和早餐,阁楼等。)产生了更高的收入,它们在波士顿上市公司中所占的比例较小,因此更有可能服务于较小的利基市场。

Average annual revenues of Airbnb listings in Boston in 2015

Number of listings by property type in Boston in 2015

此外,能容纳更多客人的酒店也更有可能在波士顿创造更高的收入。事实上,容纳 4 位客人的酒店的平均收入几乎是容纳 3 位客人的酒店的两倍。2015 年,可容纳 6 名客人的房源收入最高。但是这些房源比较稀缺,所以这个细分市场可能不会很大。

Mean Revenues vs Number of Guests in Boston in 2015

列表的收入会有很大的不同,就像主机的收入一样。2015 年,波士顿 50%的房源收入低于 2300 美元,而前 25%的房源收入超过 5520 美元。

如果你正在西雅图寻找一个完美的 Airbnb 房源,那就看看能容纳 4 人的公寓吧。2015 年有 336 处此类房产上市,平均年收入为 4500 美元。

相比之下,2015 年西雅图 Airbnb 房源的平均收入为 3400 美元。

Average annual revenues of Airbnb listings in Seattle in 2015

Number of listings by property type in Seattle in 2015

出租整艘船估计每年可以获得 9000 美元的收入,远远超过其他任何财产。然而,这个数字应该谨慎对待,因为 2015 年只有两个这样的财产被列入名单。

如果你出租整栋房子或公寓,这是西雅图最常见的房源,你可以合理地预计分别获得 4500 美元和 4000 美元。

在西雅图,能容纳更多客人的酒店也在 2015 年创造了更高的收入。同样,理想的客人数量似乎是 4 个,因为这些酒店产生了相对较高的收入,同时仍然服务于相当大的市场。

Mean Revenues vs Number of Guests in Boston in 2015

有两间卧室的房源也获得了相对较高的收入,同时仍然迎合了一个大市场。拥有超过 2 间卧室的影响通常可以忽略不计。当我们考虑到超过 4 间卧室的房源的较小市场规模时,这一点尤其正确。

Mean Revenues vs Number of Bedrooms in Boston in 2015

收入差距在西雅图也确实存在。50%的房产在 2015 年收入低于 1800 美元,而前 25%的房产收入超过 4500 美元。

八月和九月是波士顿最好的租房时间。虽然八月是西雅图最好的月份

8 月和 9 月是波士顿 Airbnb 房产最好的月份。这几个月的收入最高也就不足为奇了,因为这段时间天气通常很好,游客可以欣赏波士顿令人惊叹的秋色。

在西雅图,八月是出租房产的最佳月份,而七月和九月也是有利可图的选择。

在这两个城市,总收入多年来一直大幅上升,这表明在可预见的未来,对 Airbnb 房产的需求可能会增长。

灯塔山和后湾是波士顿表现最好的社区,而第一山是西雅图最好的社区

在波士顿,Beacon Hill 在 2015 年创造了所有社区中最高的收入,平均每份房源约 7400 美元。Back Bay 是第二好的社区,总收入超过 6900 美元。

就可用房源总数而言,这两个社区都位列前五名。这是 Airbnb 认可的波士顿 25 个社区中的一个。

注意:在地图上,每个邻近区域都用一个圆圈表示,圆圈的颜色反映了邻近区域中某个列表的平均收入。每个圆圈的大小对应附近的房源数量,圆圈越大,房源越多。

This map depicts the average revenue in each neighborhood in Boston during 2015.

在西雅图的所有社区中,第一山的收入最高,2015 年平均每家上市公司的收入超过 5900 美元。然而,值得注意的是,与贝尔敦和百老汇等社区相比,该地区的房源数量明显较低。

中央商务区和史蒂文斯是 2015 年票房收入第二高的社区。2015 年,这两个社区的 Airbnb 房源收入约为 4500 美元。

This map depicts the average revenue in each neighborhood in Seattle during 2015.

在你的刊登名称中提及热门地点

潜在客户在寻找公寓时首先看到的往往是房源名称和房源图片。因此,你的上市名称吸引读者的注意力是至关重要的。

Most popular words used in the names for Boston listings ranked in the top 10% of revenue generated

上面显示的是收入排名前 10%的波士顿上市公司名称中最常用的词的词云。相比之下,下面的单词云描述了收入排名后 30%的列表中最常见的单词。

注意:单词在云中的大小与其在列表中出现的频率相对应,使用频率越高的单词出现得越大。

Most popular words used in the names for Boston listings ranked in the bottom 30% of revenue generated

通过比较,我们立即注意到,像 South EndBack BayBeacon Hill 这样的社区经常出现在高收入的列表中。另一方面,这些社区在低收入的列表中很少被提及。因此,如果你的房产位于上述社区附近,一定要在你的房源名称中突出显示。

单词 studio 在表现最好的列表中出现过多,而单词 room 在表现较差的列表中出现过多。在波士顿,出租工作室单元似乎比出租房间更有利可图,尽管人们必须记住,出租房间可能比工作室单元产生更低的运营成本。

有趣的是,虽然像漂亮宽敞这样的词在这两种房源中都很常见,但顶级房源更有可能使用现代这个词来描述它们的房产,而收入较低的房源更倾向于使用舒适这个词。这可能是波士顿游客更喜欢现代装饰的一个标志。

下面显示的是收入排名前 10%的西雅图列表名称中最常用的词。

Most popular words used in the names for Seattle listings ranked in the top 10% of revenue generated

相比之下,收入排名在后 30%的列表中使用频率最高的词。

Most popular words used in the names for Seattle listings ranked in the bottom 30% of revenue generated

两者之间最明显的区别是,顶级上市公司的名字中经常有西雅图 T21 这个词,而收入较低的上市公司很少提到它。另一方面,与顶级房源相比,低收入房源更有可能使用房间*、舒适现代等词语。*

私人、市中心、巴拉德国会山也更频繁地出现在顶级列表中,这表明这些属性很受欢迎。巴拉德和国会山都是西雅图的街区,很可能这两个地方都非常受游客欢迎。

有趣的是,视图在任一类型的列表中都有很好的表现。大多数游客可能是因为西雅图的壮观景色而来到这里的。

与波士顿相反,工作室单元的吸引力较低,这表明在西雅图拥有工作室单元没有任何优势。

从这一点可以得出一个重要的结论,即地名在列表名称中非常重要。房产的位置可能是 Airbnb 客户最重要的考虑因素之一。如果您的酒店位于任何热门地点附近,请确保在您的列表名称中突出显示这些地点的名称。

另一个关键要点是中的单词 room。在这两个城市,房源名称几乎总是与较低的收入联系在一起。

如果到目前为止你喜欢这篇文章,这里有一些额外的见解可以帮助你的 Airbnb 之旅。

Airbnb 超级房东在波士顿和西雅图挣得更多。在这两个城市,被认可为 Airbnb 超级房东可能会带来更高的收入。成为一名超级房东的要求如下:获得 4.8+的综合评分,在 24 小时内回复至少 90%的预订请求,每年至少接待 10 次住宿,并尊重每一次预订。

**波士顿偏好温和或严格的取消政策。**在波士顿,具有适度或严格取消政策的酒店往往能获得更高的收入。2015 年,实行中度或严格取消政策的酒店的收入中值为 2600 美元。相比之下,采用灵活或超严格 30 取消政策的酒店的收入中位数为 1300 美元。

**在波士顿,顾客更喜欢物有所值的房产。**波士顿 Airbnb 的顾客主要关心的是让他们的钱花得值。因此,在波士顿,价值评估得分较高的酒店往往表现更好。

在西雅图,顾客更喜欢干净的酒店。在西雅图,清洁度评分较高的酒店往往会获得略高的收入。西雅图的 Airbnb 客户肯定对清洁有强烈的偏好,所以要注意这一点。

**更高的清洁费不会影响波士顿的收入。**事实上,清洁费较高的房源往往比波士顿的其他房源表现更好。因此,如果你需要的话,不要害怕要求更高的清洁费,特别是如果你的地方为需要清洁的客人提供了很多额外的补贴。

在整篇文章中,我们看到了许多帮助你建立完美 Airbnb 房源的技巧和策略。现在,我们将总结一下这篇文章的主要发现。

波士顿 Airbnb 主机的关键见解概述

  • 2015 年,波士顿 Airbnb 的平均收入为 7200 美元
  • 租一整栋公寓可能会带来稳定的收入
  • 可容纳 4 位客人的酒店似乎是最佳选择
  • 八月和九月是出租房产的最佳时间
  • Beacon Hill 和 Back Bay 通常是建立 Airbnb 的最佳社区
  • 在你的列表名称中提及热门地点,如南端后湾比肯山可能会吸引浏览者的注意
  • 工作室单位在波士顿是首选。
  • 作为 Airbnb 超级房东,你会赚得更多
  • 具有适度或严格取消政策的酒店通常表现更好
  • 顾客更喜欢物有所值的房产
  • 更高的清洁费不会影响收入

西雅图 AIrbnb 房东的关键见解概述

  • 2015 年,西雅图 Airbnb 的平均收入为 4700 美元
  • 租一整栋公寓来接待 4 个客人可能会带来稳定的收入
  • 有两间卧室的房产是最好的选择
  • 八月是出租房产的最佳月份。七月和九月也是不错的选择
  • 第一山是出租房产的最佳街区,其次是中央商务区和史蒂文斯
  • 在你的列表名称中提到 private、downtown、BallardCapitol Hill 可能会吸引更多的兴趣
  • 作为 Airbnb 超级房东,你会赚得更多
  • 顾客更喜欢干净的房产

感谢您阅读这篇文章!我希望你喜欢它!

这个分析的代码可以在这里找到。

欠采样:不平衡数据的性能助推器

原文:https://towardsdatascience.com/under-sampling-a-performance-booster-on-imbalanced-data-a79ff1559fab?source=collection_archive---------11-----------------------

在某些情况下,用于开发机器学习/深度学习模型的数据集通常是不平衡的。在这里,不均衡是指阶级分布的高度不平等或不均衡。不平衡数据的一个例子如下(图 1):

Fig 1. Binary Imbalanced Data

这里,标签 0 包含 24,720 个实例,而标签 1 仅包含 7841 个实例。这是一个二进制(因为有 2 个标签,0 和 1)不平衡数据的例子。通过对多数类(标签 0)进行欠采样,并使其接近标签 1,可以在很大程度上减少这种不平衡。其中一个著名的欠采样算法是基于聚类质心的多数欠采样技术(CCMUT) 。除此之外,我在之前的文章《 基于扩展聚类质心的多数欠采样技术(E-CCMUT) 》中介绍了基于扩展聚类质心的多数欠采样技术(E-CCMUT) 。在这之后的下一篇文章中,我一定会讨论 E-CCMUT 对 CCMUT 的改进。至于现在,在本文中,我将展示一个在 UCI 成人数据集上的实验,并从统计上证明欠采样可以获得更好的结果,并在不平衡数据集中充当性能助推器。

实验

“从人口普查数据预测一个人的收入水平是否大于 50k 美元”。

数据集

来自 UCI(加州大学欧文分校)的成人数据集用于预测模型开发。数据集包含 48,842 个实例和 14 个属性/特征

数据预处理

  1. 对分类特征进行标签编码(参见表 1)
  2. 特征选择通过使用额外的树分类器训练整个数据集并使用每个特征的特征重要性分数来完成,特征种族本国被丢弃。(参见表 1)
  3. 对分类特征进行一键编码,其中假设二进制值为 0/1,特征的每个类别成为特征本身。

Table 1

数据不平衡消除

数据的不平衡性质如图 1 所示。它包含 24,720 个‘0’标记的(多数)实例和 7841 个‘1’标记的(少数)实例。使用基于聚类质心的多数欠采样技术(CCMUT)来消除这种数据不平衡,其中多数类(标签 0)欠采样 68%。图 2 显示了 68%欠采样后数据失衡的减少。

Fig 2. Reduction in Data Imbalance after 68% Under-sampling

洗牌和拆分

结果数据集包含 7911 个“0”标记的实例和 7841 个“1”标记的实例。整个数据集以一致的方式进行混洗,并且 80–20 分割(80%训练集和 20%验证集)。

学习算法

在训练集上使用梯度提升分类器作为学习算法。分类器通过网格搜索进行调整,以获得最佳的超参数集。

网格搜索后得到 200 个估计量和最大深度为 4 的最优超参数。图 3 显示了基于平均分数的模型的网格搜索调整的总结。

Fig 3. Grid-Search Summary on Mean Score

结果:

使用度量、训练准确度、验证准确度、召回率、精确度、F1 分数、受试者操作者特征曲线下面积(图 4 所示的 AUROC)和混淆矩阵(图 5 所示)来分析模型性能。

Fig 4. ROC Curve showing Area Under the Curve

Fig 5. Normalized Confusion Matrix

表 2 中列出了训练准确度、验证准确度、召回率、精确度和 F1 分数。

与最先进技术的对比

到目前为止, Chakrabarty 等人【1】名为“ 一种成年人普查收入水平预测的统计方法 ”的研究论文是最先进的模型。表 2 给出了与最先进水平的比较。

Table 2

结论

从上述演示实验的统计结果来看,很明显,如果所使用的数据中存在类别不平衡,欠采样可以证明是非常强大的性能助推器。

参考文献

1 Chakrabarty,Navoneel 和 Sanket Biswas。"成人人口普查收入水平预测的统计方法." arXiv 预印本 arXiv:1810.10076 (2018)。

在分析项目的掩护下

原文:https://towardsdatascience.com/under-the-hood-of-an-analytics-project-1cc2348a5411?source=collection_archive---------11-----------------------

Photo by Markus Spiske on Unsplash

新数据项目早期阶段的演练

几周前,我写了一篇文章深入 NHL 的详细拍摄,如何转化为篮板,以及这两个事件如何影响比赛的结果。

在你现在正在阅读的文章中,我想从不同的角度来看同样的分析。我希望它能帮助潜在的/新的数据科学家了解如何开始构建自己的项目,并让我的想法更加清晰。

找到正确的问题

找到正确的问题通常是开始一个新的数据科学项目的最困难的部分,尤其是当这个问题没有提供给你的时候。很难找到动力去完成一个没有真正目的的项目,花时间定义你在做什么是至关重要的。

我喜欢散步,思考数据集,用它可以实现什么,我可以回答什么样的问题。通过这个项目,我可以访问过去 4 年中每场 NHL 比赛的详细数据,我想建立一个预测比赛结果的系统。

下面 Vox 的视频总结了这样做的动机。NHL 的结果被认为很大程度上是运气的结果。在运气-技能连续体中,曲棍球被归类为最“随机”的运动之一。我有疑问,我想深入了解一下。

深入研究

随着我更多地思考如何解决这个问题,我意识到我想要建立的系统会有多复杂。一开始,我不知道哪些数据与获胜相关,更重要的是,似乎其他人也不知道。显然已经对游戏的各个方面进行了研究,但我找不到我想做的事情的完美起点。

为了解决这个问题,我会从更简单的问题开始,然后建立一个最终模型。我预计这个项目将花费数百个小时,随着时间的推移,可能会增加到数千个小时——但你需要从某个地方开始。我决定在一系列我称之为“深度潜水”的游戏中系统地移动游戏的各个部分。这些深入的研究将建立在我对该领域的整体理解上,但也会产生我可以在最终模型中使用的特性。

所以我建立了一个灵活的计划来一次解决这些问题。我不知道我会在每个部分花多长时间——这个选择可以让我决定是否在必要时进一步追求一个想法。我要挖掘的一些数据不可避免地会相当不直观,可能会鼓励更多的探索。

经过一些初步的探索性挖掘,我采用了以下策略:

逐一深入以下类别,在数据中寻找有意义的相关性

  • 射击
  • 惩罚
  • 失误
  • 守门
  • 主客场优势

然后,我会把我发现的见解构建到预测系统中。

在我分析的早期,很明显这将是一项艰巨的任务。我全神贯注于拍摄统计数据,亲眼目睹了为什么许多统计学家把这么多事情归结于偶然。然而,我也发现了一些我以前不知道的有趣信息(也找不到任何其他信息)。

最重要的是,我开始对游戏的一个非常具体的部分有了感觉。这让我相信,可以建立许多可以预测整个季节的特征,但这些相同的统计数据充满了嘈杂的异常值。我一直怀疑 NHL 是一个非常基于动力的游戏,一支球队如何在长期的基础上行动是他们成功的预测,行为比进球或射门等个人数据更重要。这篇文章的一个重要观点可以在下面的三张图中得到解释。

首先,我们发现什么是反弹。

其次,我们查看出现的次数来衡量重要性。

最后,我们查看了过去 4 年中的所有团队,以了解这些信息如何预测结果。

我们的结论。

“从分析的数据来看,更高的篮板球率实际上并不意味着更高的胜率。事实上,较高的反弹率与较低的胜场数相关联!

我们还发现,篮板率越高,投篮次数越少,投篮次数越多,胜率越高。”

代码走查

为了更好地介绍这个过程,并让您了解我是如何实现这一目标的,我提供了一些感兴趣的人来浏览代码。首先,你可以在这里得到原始数据。我们不会使用所有的数据集,我们主要关注的是详细的数据。

我们的第一步是加载比赛数据,提取进球和射门,创建标识射手和守门员的列,并缩放 x 和 y 位置,以便我们可以在我在 Plotly 上制作的曲棍球图上显示我们的射门分析。

然后,我们编写一个函数,它接受 shooting_df 函数的输出,并添加一些我们需要的数据。我们将添加球队名称,构建数据集,以便我们可以分析主场/客场,而不是输赢。

现在,我们将构建将在最终分析中使用的数据集。我想确定什么是反弹,这样我就可以利用这些信息来确定好的拍摄位置。由于没有明确的定义,我需要自己分析。

我对数据集中的独特游戏进行循环,并按时间顺序对每个游戏进行排序。然后,我可以在数据集上逐个镜头地迭代,并构建镜头之间的时间、这些镜头的结果以及反弹的位置。然后,我们添加一些必要的列,允许我们以几种不同的方式切割数据进行分析,特别是添加一个“for”列,以便我们可以查看整个赛季的球队。

为了更好地理解什么是反弹,我们需要按时间步长汇总我们的反弹数据框架。与此同时,我为 Plotly 图表添加了几个文本列,我们将使用它们来更好地了解篮板的影响和得分率。

这让我们可以创建我们在上面看到的前两个图,让我们知道什么是反弹。

知道了 3 秒以内的投篮命中率会有大幅上升,我按照前一次投篮在那个时间段内的任何一次投篮对篮板进行了分类。它让我们很好地了解了反弹的整体影响。

和下面的图表。

虽然抢篮板的投篮只占所有投篮的 5%,但他们占所有进球的 15%以上。

我也想知道高质量的照片是否有某种模式。在溜冰场制作热图的代码很长——所以我不会全部嵌入这里,但你可以在这个链接找到它。

概括地说,我们经历了以下过程:

  1. 我们创造了各种情节性的形状,产生了一个空的曲棍球场作为情节。X 和 Y 轴用于模拟竞技场的一半。
  2. 我们创建了一组盒子,将半溜冰场分成 625 个大小相等的盒子(25 x 25)。
  3. 我们从数据中选取一个子集,使其符合上一步中为盒子创建的 x-y 坐标。然后我们根据需要(射门、进球或进球率)给它上色
  4. 我们在每个框的中心产生一个数据点来提供鼠标悬停信息。

结果如下(互动版此处)

为了更好地理解拍摄地点,我回顾了这个图的一些变化。没有什么非显而易见的东西跳出来,但它给出了一些创建一个功能的想法,该功能涉及到在一些进一步的分析中使用这些框来产生镜头质量度量。从像这样的噪声数据到预测特征可能涉及几个阶段。

为了更好地理解拍摄地点,我回顾了这个情节的一些变化。没有什么非显而易见的东西跳出来,但它给出了一些创建一个功能的想法,该功能涉及到在一些进一步的分析中使用这些框来产生镜头质量度量。从像这样的噪声数据到预测特征可以包括几个阶段。

然后,我们有一个相对较长的代码片段来生成我们在原始文章中看到的 Plotly 图表。

我们取三个 x-y 对。

  1. 反弹率与获胜次数
  2. 反弹率与投篮次数
  3. 击球次数与获胜次数

我们在这里发现了一些非直觉的信息,这让我相信曲棍球的特征在一段时间内比一场比赛更相关。我们还发现了一些可能会引导我们找到另一组特征的东西。也许我们需要根据球队的类型和守门员的质量来调整射门次数或篮板比例?

仅仅是开始

这只是这种分析的开始。我们甚至还没有触及这个复杂游戏的表面,但是我们已经发现了一些潜在的有价值的特性,并且获得了一些领域知识。

我希望这篇文章对新的数据科学家有所帮助,让他们了解探索性数据分析有多重要,并正确看待项目设计。

一键外卖 —玩长游戏,找到错综复杂的细节,然后开始建模。您将最终得到一个好得多的模型,并获得无价的领域知识,在您前进的过程中帮助您。

最初发表于Jesse Moore . ca

在神经网络前向传播——可怕的矩阵乘法的掩护下

原文:https://towardsdatascience.com/under-the-hood-of-neural-network-forward-propagation-the-dreaded-matrix-multiplication-a5360b33426?source=collection_archive---------0-----------------------

简介

这篇文章的动机是我正在构建的神经网络中的一个令人沮丧的错误,它最终迫使我进入引擎盖下,真正理解神经网络核心的线性代数。我发现我做得很好,只是确保我相乘的两个矩阵的内部维度匹配,当错误发生时,我会在这里转置一个矩阵,在那里转置一个矩阵,直到事情解决,但这掩盖了我并不真正理解矩阵乘法如何工作的每一步的事实。

我们将介绍使用前向传播来计算一个相当简单的神经网络的成本函数的每个步骤。哦,如果你想知道我的矩阵乘法无知导致的错误,那就是我把我的偏差单位(1 的向量)作为一列添加了,而它应该是一行。我这样做是因为在这一步之前,我并没有真正理解矩阵乘法的全部输出,所以没有意识到我必须做出改变。首先,我将解释神经网络正向传播中发生的高级背景,然后我们将更仔细地看一个具体的例子,用索引值和代码来保持事情的清晰。

因此,神经网络在模拟复杂关系方面是不可思议的。我们只讨论网络的前馈传播部分。现在,神经网络的输入单元可以是任何东西。例如,它们可以是代表一串手写数字的 20 像素乘 20 像素图像的灰度强度(在 0 和 1 之间)。在这种情况下,您将有 400 个输入单元。这里我们有 2 个输入单元,加上+1 个偏置单元(关于为什么要有偏置单元的精彩解释,请点击这里)。正向传播实质上是从一个示例(比如一个手写数字的图像)中提取每个输入,然后将输入值乘以单元/节点之间每个连接的权重(见图 5),然后将所有连接的所有乘积加到正在计算激活的节点上,取总和(z)并通过 sigmoid 函数进行计算(见下文)。

Figure 1: Sigmoid Function

这样你就可以激活隐藏层的每一个单元。然后你做同样的事情来计算下一层,但是这次你使用隐藏层的激活作为“输入”值。你将所有的 a 激活(即隐藏层)单元乘以第二组权重θ2,将连接到单个最终输出单元的每个乘积求和,并将该乘积通过 sigmoid 函数,从而得到最终输出激活 a。g(z)是 sigmoid 函数,z 是 x 输入(或隐藏层中的激活)和权重θ(在图 5 的正常神经网络图中由单个箭头表示)的乘积。

Figure 2: Hypothesis Function, using the Sigmoid Function.

一旦你有了所有这些,你想计算网络的成本(图 4)。对于给定的示例,您的成本函数本质上是计算输出假设 h(x)和实际 y 值之间的成本/差异。因此,在我一直使用的例子中,y 是输入所代表的实际数字的值。如果通过网络有一个“4”馈送的图像,则 y 是值“4”。因为有多个输出单元,所以成本函数将输出 h(x)与列向量进行比较,其中第 4 行是 1,其余都是 0。这意味着表示“4”的输出单元输出为真,其余都为假。对于 1、2 或 n 的输出,请参见下文。

Figure 3: Our example data y values represented as logical TRUE/FALSE column vectors.

Figure 4: The Multi-Class Logistic Regression Cost Function

上面成本函数 J(theta)中的两个适马用于合计通过网络输入的每个示例(m)和每个输出类(K)的成本。现在,你可以通过单独进行每个计算来做到这一点,但事实证明,人类定义矩阵乘法的方式非常适合同时进行所有这些正向传播计算。我们在数值计算方面的朋友已经优化了矩阵乘法函数,这样神经网络就可以极其高效地输出假设。编写我们的代码,以便我们同时进行所有的计算,而不是对所有的输入示例进行 for 循环,这是一个称为向量化代码的过程。这在神经网络中非常重要,因为它们在计算上已经足够昂贵,我们不需要任何 for 循环来进一步降低我们的速度。

我们的网络示例

在我们的网络中,我们将有四个类,1、2、3、4,我们将完成这个计算的每一步。我们将假设网络已经被训练,并且我们已经通过反向传播训练了我们的θ参数/权重。这将是一个 3 层网络(有两个输入单元,2 个隐藏层单元和 4 个输出单元)。网络和参数(也称为权重)可以表示如下。

Figure 5: Our Neural Network, with indexed weights.

在我们走得更远之前,如果你不知道矩阵乘法是如何工作的,那就去看看可汗学院花 7 分钟,然后做一两个例子,确保你对它是如何工作的有直觉。在前进之前知道这一点是很重要的。

让我们从所有的数据开始。我们的 3 个示例数据和相应的 y 输出值。这些数据不代表任何东西,它们只是显示我们将要进行的计算的数字:

Figure 6: Our data.

当然,正如我提到的,由于有 4 个输出单元,我们的数据必须表示为三个示例输出的逻辑向量矩阵。我在 MATLAB 中工作,把我们的 y 向量变成一个逻辑向量矩阵:

yv=[1:4] == y;   %creating logical vectors of y values

Figure 7: Matrix of Example Output y data turned into logical vectors.

另外,注意我们的 X 数据没有足够的特性。在我们图 5 的神经网络中,当我们计算权重/参数和输入值的乘积时,我们有虚线偏置单元 x(0)。这意味着我们需要将偏差单位添加到数据中。这意味着我们在矩阵的开头添加了一列:

X = [ones(m,1),X];

Figure 8: Data with bias added. Bias represented by dotted-line unit/node in Neural Net Figure 5

数据 X 被定义为第一个输入层 a 的第一个激活值,所以如果你在代码中看到 a(第 3 行),它只是指初始输入数据。网络中每个连接/箭头的权重或参数如下:

Figure 9: First set of weights/parameters for our neural network with indices that match those on the arrows of the Figure 5 Neural Network diagram.

下面是我们将用于计算物流成本函数的完整代码,我们已经处理了第 2 行和第 9 行,但我们将在代码的其余部分慢慢分解矩阵乘法和重要的矩阵操作:

1:  m = size(X, 1);
2:  X = [ones(m,1),X]; 
3:  a1 = X;
4:  z2 = Theta1*a1';
5:  a2 = sigmoid(z2);
6:  a2 = [ones(1,m);a2];
7:  z3 = Theta2*a2;
8:  a3 = sigmoid(z3);
9:  yv=[1:4] == y;
10: J = (1/m) * (sum(-yv’ .* log(a3) — ((1 — yv’) .* log(1 — a3))));
11: J = sum(J);

让我们执行正向传播的第一步,上面代码中的第 4 行。将每个示例的输入值乘以它们相应的权重。我总是想象输入值沿着我们网络中的箭头流动(图 5 ),被击中/乘以权重,然后在激活单元/节点等待其他箭头进行乘法。然后,特定单元的整个激活值首先由这些箭头的总和(输入 x 重量)组成,然后该总和通过 sigmoid 函数传递(参见上面的图 1)。

所以这里很容易犯你的第一个矩阵乘法错误。因为我们的偏置单位加到 X(这里也称为 a1)的数据是 3×3 矩阵,而θ1 是 2×3 矩阵。简单地将这两个矩阵相乘是很容易的,因为θ:2×3 和 X:3×3 的两个内部维度是相同的,所以 viola 应该正确工作,并给出我们的 2×3 合成矩阵?不对!

z2 = Theta1 * a1;      %WRONG! THIS DOESN'T GIVE US WHAT WE WANT

虽然运行这个计算将输出一个我们期望的和下一步需要的正确维数的矩阵,但是所有计算的值都将是错误的,因此从现在开始所有的计算都将是错误的。此外,由于不存在计算机错误,即使您注意到了,也很难解释为什么您的网络成本函数会计算错误的成本。记住,当你做矩阵乘法时,得到的矩阵的每个元素 ab 都是第一个矩阵的行 a 乘以第二个矩阵的列 b 的点积和。如果我们使用上面的代码来计算上面的 z,那么得到的矩阵中的第一个元素将由我们的第一行 Theta 的[0.1 0.3]相乘得到。0.5]有一整列偏置单位,[1.000;1.000;1.000],对我们没用。这意味着我们需要转置示例输入数据的矩阵,以便矩阵将每个θ与每个输入正确相乘:

z2 = Theta1*a1';

其矩阵乘法如下:

Figure 10: The indexed symbolic representation of the matrix multiplication. The resultant elements in the columns each representing a single example, and the rows being the different activation units in the hidden layer. 2 hidden layers results in two values (or rows) per example.

然后,我们对上述 z 矩阵中的 6 个元素分别应用 sigmoid 函数:

a2 = sigmoid(z2);

对于三个示例中的每一个,这仅仅给出了两个隐藏单元的隐藏层激活值的 2×3 矩阵:

Figure 11: The activation values of the hidden units.

因为这是作为矩阵乘法完成的,所以我们能够一次性计算隐藏层的激活值,而不是在所有示例中使用 for 循环,这在处理较大的数据集时会变得非常昂贵。更不用说还需要反向传播。

现在我们在第二层中有了激活单元的值,这些值作为下一层也是最后一层,即输出层的输入。对于图 5 中第二层和第三层之间的每个箭头,该层具有一组新的权重/参数θ2,我们将做与上面相同的事情。将激活值(输入)乘以连接到每个激活节点的权重,分别对连接到每个激活节点的乘积求和,然后通过 sigmoid 函数对每个激活节点求和,得到最终输出。上述 a 作为我们的输入数据,我们的权重/参数如下:

Figure 12: Theta2 weights/parameters with indices. Each row represents a different output unit with the weights contributing to each output unit across each column.

我们想做以下计算:

z3 = Theta2*a2;

但在此之前,我们必须再次将偏差单位添加到我们的数据中,在这种情况下,隐藏层激活 a。如果您在图 5 中再次注意到,隐藏层中的虚线圆圈 a(0),偏差单位仅在我们进行下一次计算时添加。因此,我们将它添加到上面图 11 所示的激活矩阵中。

这是我介绍我的 bug 的地方,这也是我写这篇文章的动机。为了向前传播激活值,我们将θ中的一行的每个元素与 a 中的一列的每个元素相乘,并且这些乘积的总和将给出结果 z 矩阵的单个元素。通常数据的组织方式是将偏差单位作为一列添加,但是如果你这样做了(我愚蠢地这样做了),这将会给我们错误的结果。所以我们将偏差单位作为一行添加到。

a2 = [ones(1,m);a2];

Figure 13: Adding the bias row to the a² activations.

在我们运行矩阵乘法来计算 z 之前,请注意,在 z 之前,您必须转置输入数据 a,使其正确“排列”,矩阵乘法才能产生我们想要的计算结果。这里,我们的矩阵按照我们想要的方式排列,所以没有 a 矩阵的转置。这是另一个常见的错误,如果你不理解其核心的计算,这是很容易做到的(我过去对此非常内疚)。现在,我们可以在 4x3 和 3x3 矩阵上运行矩阵乘法,从而为 3 个示例中的每一个生成 4x3 输出假设矩阵:

z3 = Theta2*a2;

Figure 14: The indexed symbolic representation of the matrix multiplication. The resultant elements in the columns each representing a single example, and the rows being the different activation units of the output layer, with four output units. In a classification problem this would mean four classes/categories. Also notice the [m] superscript index on all the a’s in each element is the example number.

然后,我们对 z 矩阵中的 12 个元素逐一应用 sigmoid 函数:

a3 = sigmoid(z3);

这就为我们提供了每个输出单元/类的输出层激活的 4x3 矩阵(也称为假设):

Figure 15: The activation values for each of the output units of the network, for each example. If you were doing a for loop over all your examples, this would be a column vector rather than a matrix.

从这里开始,你只是在计算成本函数。唯一要注意的是,你必须转置 y 向量的矩阵,以确保你在成本函数中进行的元素操作与每个示例和输出单元正确对齐。

Figure 16: Transpose of the logical y vectors matrix.

然后,我们将它们放在一起计算成本函数:

Figure 4: The Multi-Class Logistic Regression Cost Function

J = (1/m) * (sum(-yv’ .* log(a3) — ((1 — yv’) .* log(1 — a3))));
J = sum(J);

这就给出了我们的成本,注意,所有类和所有例子的总和都是双倍的。这就是所有的人。矩阵乘法可以使代码非常简洁高效,不需要 for 循环来减慢速度,但是您必须知道矩阵乘法中发生了什么,以便您可以适当地调整矩阵,无论是乘法的顺序、必要时的转置,还是将偏差单位添加到矩阵的正确区域。一旦你把它分解了,掌握起来就更直观了,我强烈建议你自己慢慢地看一遍这个例子,如果你还是不确定,它总是归结到一些非常简单的基础上。

我希望这有助于理解向前传播所需的线性代数。此外,这是我的第一个帖子,也是我的第一个技术帖子,所以任何反馈,问题,评论等,都非常感谢。

在神经网络的保护下。第 1 部分:完全连接。

原文:https://towardsdatascience.com/under-the-hood-of-neural-networks-part-1-fully-connected-5223b7f78528?source=collection_archive---------0-----------------------

深度学习进展很快,快得令人难以置信。拥有如此大的 AI 开发人员社区的原因之一是我们有许多非常方便的库,如 TensorFlow、PyTorch、Caffe 等。正因为如此,通常实现一个神经网络不需要任何该领域的高深知识,这是非常酷的!然而,随着任务复杂性的增加,了解内部实际发生的事情会非常有用。这些知识可以帮助您选择激活函数、权重初始化、理解高级概念等等。所以在这组文章中,我将解释不同类型的神经网络的推理和训练过程背后的数学原理。

这篇文章我将致力于最基本类型的神经网络:全连接网络。尽管纯全连接网络是最简单的网络类型,但理解它们的工作原理是有用的,原因有二。首先,与其他类型的网络相比,它更容易理解后面的数学。第二,全连接层仍然存在于大多数模型中。

在这里,我将解释任何监督神经网络中的两个主要过程:全连接网络中的前向和后向传递。这篇文章的重点将放在称为反向传播的概念上,它成为现代人工智能的主力。

前进传球

前向传递基本上是一组将网络输入转换到输出空间的操作。在推理阶段,神经网络仅依赖于正向传递。让我们考虑一个具有两个隐藏层的简单神经网络,它试图将二进制数(这里是十进制 3)分类为偶数或奇数:

这里我们假设除了最后几层的神经元,每个神经元都使用 ReLU 激活函数(最后一层使用 softmax )。激活函数用于将非线性引入系统,这允许学习复杂的函数。让我们记下在第一个隐藏层中进行的计算:

神经元 1(顶部):

神经元 2(底部):

将它改写成矩阵形式,我们将得到:

现在,如果我们将输入表示为矩阵 I(在我们的情况下,它是一个向量,但是如果我们使用批量输入,我们将使它的大小为样本数乘以输入数),神经元权重为 W,偏差为 B,我们将得到:

其可以被概括为全连接神经网络的任何层:

其中 i —是层数, F —是给定层的激活函数。将此公式应用于网络的每一层,我们将实现正向传递,并最终获得网络输出。您的结果应该如下所示:

偶数道次

如果我们做所有的计算,我们最终会得到一个输出,这个输出实际上是不正确的(因为 0.56 > 0.44 我们输出的是偶数作为结果)。知道了这一点,我们想更新神经元的权重和偏差,这样我们就能得到正确的结果。这正是反向传播发挥作用的地方。反向传播是一种计算关于每个网络变量(神经元权重和偏差)的误差梯度的算法。这些梯度随后用于优化算法,如梯度下降,相应地更新它们。权重和偏差更新的过程称为反向传递。

为了开始计算误差梯度,首先,我们必须计算误差(即损耗)本身。我们将使用标准分类损失—交叉熵。然而,损失函数可以是任何可微分的数学表达式。回归问题的标准选择是均方根误差(RMSE)。交叉熵损失如下所示:

其中 M 是类的数量, p 是网络输出的向量, y 是真实标签的向量。对于我们的情况,我们得到:

现在,为了找到每个变量的误差梯度,我们将集中使用链式法则:

因此,从最后一层开始,对损失相对于神经元权重进行偏导数,我们得到:

了解在 softmax 激活和交叉吸附丢失的情况下我们拥有的事实(你可以自己推导出来作为一个很好的练习):

现在我们可以找到最后一层的梯度为:

继续第 2 层:

第一层:

对偏差遵循相同的程序:

现在我们可以跟踪一个常见的模式,它可以概括为:

这是反向传播算法的矩阵方程。有了这些等式,我们就可以计算每个权重/偏差的误差梯度。为了减少误差,我们需要在与梯度相反的方向上更新我们的权重/偏差。这种思想用于梯度下降算法,定义如下:

其中 x 是任何可训练变量(W 或 B), t 是当前时间步长(算法迭代),而 α 是学习率。现在,设置 α = 0.1(您可以选择不同的,但请记住,小值假设较长的训练过程,而高值导致不稳定的训练过程)并使用上面的梯度计算公式,我们可以计算梯度下降算法的一次迭代。您应该获得以下重量更新:

应用此更改并执行向前传递:

我们可以看到,我们的网络性能有所提高,与上例相比,现在奇数输出的值有所提高。对不同的例子(或一批样本)多次运行梯度下降算法,最终将得到一个经过适当训练的神经网络。

摘要

在这篇文章中,我解释了全连接神经网络训练过程的主要部分:向前和向后传球。尽管给出的概念很简单,但对反向传播的理解是建立鲁棒神经模型的一个基本步骤。我希望你从这篇文章中获得的知识能帮助你在训练过程中避免陷阱!

如果你觉得这篇文章有用,别忘了鼓掌,敬请关注!在下一篇文章中,我将解释递归网络的数学原理。

请在下面的评论中留下你的反馈/想法/建议/修正!

感谢阅读!

在神经网络的保护下。第二部分:经常性。

原文:https://towardsdatascience.com/under-the-hood-of-neural-networks-part-2-recurrent-af091247ba78?source=collection_archive---------5-----------------------

在本系列的第 1 部分中,我们已经研究了前馈全连接网络的前向和后向通路。尽管前馈网络很普遍,并且在现实世界中有很多应用,但是它们有一个主要的局限性。前馈网络不能处理顺序数据。这意味着它们不能处理不同大小的输入,也不能存储以前状态的信息(内存)。因此,在本文中,我们将讨论允许克服命名限制的递归神经网络(RNNs)。

前进传球

从技术上讲,循环网络可以表示为用状态变量和循环回路扩展的前馈网络。因此,在数学上,RNNs 的输入序列的每个元素被处理如下:

其中 It 为时步 t (输入序列的第 t 个元素)的输入, st 为时步 t 的隐藏状态, yt 为时步 t 的输出, fsfo 为各层的激活函数。从等式中我们可以看出,递归网络的状态基本上是隐含层的输出。网络的 r ecurrence 通过在时间步长 t 的计算中出现 t-1 项来解释。因此递归网络的每次计算都依赖于先前的状态和输入。

随着递归网络在各种现实世界问题中的应用,我们可以看到 RNN 架构的不同变体,这些变体不会显著改变背后的数学。这种应用和相应模型的例子可以是:(a)语言翻译,(b)视频分类,(c)图像字幕,(d)自动完成系统。

(a) RNN for translation

(b) RNN for video classification

(c ) RNN for image captioning

(d) RNN for the autocomplete system

由于情况(a)的训练过程的数学推导可以容易地应用于其余情况,我们将考虑一个序列遍历网络的简单例子。假设我们有一个数字序列(用二进制表示)1,3,5,在将它们逐个输入我们的网络后,我们希望得到 5,3,1 作为输出。首先让我们随机初始化变量:

**注:**这里为了计算简单,我们将状态大小设为 2,然而状态变量通常是高维变量。

由于输出端可以有多个 1,我们将使用 sigmoid 激活函数( fo ),而 fs 将使用 tanh

现在,已经初始化了变量,我们可以使用上面介绍的等式来计算网络的正向传递。结果我们会得到:

示意性地,我们的网络看起来像:

偶数道次

与前馈相比,递归网络的第一个不同之处在于,我们也可以将序列作为输出。因此,损耗表示为每个输出端的损耗之和(或它们的平均值)。因此:

其中θ可以由任何可训练变量表示。

这里我们将再次使用交叉衰减(在第 1 部分中介绍)。在这种情况下,我们向前传球的损失是 3.30 。在激活功能之前,损失相对于 o 的导数为:

由于 WoBo 不依赖于之前的时间步,没有循环回路,我们将从它们开始推导:

继续处理其余变量:

注: tanh 激活函数的衍生物:

现在我们有了计算梯度和应用梯度下降算法的所有方程(在第 1 部分中讨论)。让我们从分别计算每个输出的梯度开始,我们将从时间步骤 4 的输出开始:

对时间步骤 5 和 6 的输出执行相同的计算,我们将得到:

有了所有需要的梯度,我们可以将总损失的最终梯度计算为每个单独损失的梯度之和:

在应用学习率为 0.5 的梯度下降算法后,我们将得到新的变量:

现在,更新的网络将导致以下正向传递:

新的总损失等于 1.36

总结

在本文中,我介绍了递归神经网络 (RNNs),并推导了训练过程所需的基本方程。这种类型的网络对于序列处理任务特别有用。

尽管反向传递后的训练损失显著减少,但这种网络的训练过程仍然是棘手的。首先,应该增加状态的维度。更重要的是,经典(或香草)rnn 很难记住旧的状态。为了解决这个问题,存在许多解决方案。其中最著名的可能是:

  1. 在状态之间添加剩余连接(使得每个状态不仅依赖于前一个状态,也依赖于 t-2 或 t-3 状态)
  2. 使用长短期记忆( LSTM )细胞,这需要单独一篇文章来描述。

在下一部分中,我将描述卷积神经网络,它成为了现代深度学习和计算机视觉领域的重要组成部分。

如果你觉得这篇文章有用,别忘了鼓掌,关注我,看更多这样的帖子!

请在下面的评论中分享你对未来帖子的反馈和想法!

感谢阅读!

了解如何通过 doc2vec 将您的段落转换为 vector

原文:https://towardsdatascience.com/understand-how-to-transfer-your-paragraph-to-vector-by-doc2vec-1e225ccf102?source=collection_archive---------7-----------------------

“person holding camera lens” by Paul Skorupskas on Unsplash

在之前的故事中,提到的 word2vec 是 Mikolov 等人(2013)介绍的。Mikolov 和 Le 发表了句子/文档向量转换。这是嵌入技术的又一个突破,我们可以用向量来表示一个句子或文档。米科洛夫等人称之为“段落向量”。

看完这篇文章,你会明白:

  • 段落向量设计
  • 体系结构
  • 履行
  • 拿走

段落向量设计

doc2vec 的设计基于 word2vec。如果你不熟悉 word2vec(即 skip-gram 和 CBOW),你可以看看这个的故事。Doc2vec 还使用无监督学习方法来学习文档表示。每个文档的文本(即单词)输入可以是多种多样的,而输出是固定长度的向量。

段落向量和单词向量被初始化。段落向量在所有文档中是唯一,而单词向量在所有文档中是共享的,从而可以从不同的文档中学习单词向量。

在训练阶段,单词向量将被训练,而段落将被丢弃。在预测阶段(即在线预测),段落向量将被随机初始化,并通过词向量来计算。

体系结构

学习单词向量有两种算法。这两种方法都是受学习单词向量的启发,单词向量是 skip-gram 和连续词袋(CBOW)

分布式段落向量记忆模型(PV-DM)

段落向量和单词向量都是随机初始化的。每个段落向量被分配给单个文档,而单词向量在所有文档之间共享。平均或连接段落向量和单词向量,并传递到随机梯度下降,梯度通过反向传播获得。

Architecture of PV-DM (Mikolov et al., 2014)

这种方法类似于 word2vec 中的连续词包(CBOW)方法。

【分布式文字包版本段落矢量(PV-DBOW)

另一种方法走的是不同的路。它不是预测下一个单词,而是使用段落向量对文档中的整个单词进行分类。在训练过程中,对单词列表进行采样,然后形成分类器,对单词是否属于文档进行分类,从而学习单词向量。

Architecture of PV-DBOW (Mikolov et al., 2014)

这种方法类似于 word2vec 中的跳格法。

履行

首先,我们需要传递训练数据来构建词汇,并调用训练阶段来计算单词向量。

doc2vec_embs = Doc2VecEmbeddings()
x_train_tokens = doc2vec_embs.build_vocab(documents=x_train)
doc2vec_embs.train(x_train_tokens)

之后,我们可以通过提供训练数据和测试数据对其进行编码。

x_train_t = doc2vec_embs.encode(documents=x_train)
x_test_t = doc2vec_embs.encode(documents=x_test)

最后,我们可以将向量传递给分类器

from sklearn.linear_model import LogisticRegressionmodel = LogisticRegression(solver='newton-cg', max_iter=1000)
model.fit(x_train_t, y_train)y_pred = model.predict(x_test_t)from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_reportprint('Accuracy:%.2f%%' % (accuracy_score(y_test, y_pred)*100))
print('Classification Report:')
print(classification_report(y_test, y_pred))

结果

Accuracy: 52.8%
Average Precision: 0.66
Average Recall: 0.53
Average f1: 0.5

拿走

要访问所有代码,你可以访问我的 github repo。

  • 与 word2vec 不同,doc2vec 动态计算句子/文档向量。换句话说,在预测时间内得到矢量需要时间。
  • 根据 Mikolov 等人的实验, PV-DM 始终优于 PV-DBOW
  • 在 PV-DM 方法中,串联方式通常比求和/平均方式更好

参考

米克洛夫·托马斯,来自英国。2014.句子和文档的分布式表示

gensim 中的 doc 2 vec

理解文本摘要并在 python 中创建自己的摘要器

原文:https://towardsdatascience.com/understand-text-summarization-and-create-your-own-summarizer-in-python-b26a9f09fc70?source=collection_archive---------1-----------------------

文本摘要介绍

我们都与使用文本摘要的应用程序进行交互。这些应用程序中有许多是针对发布每日新闻、娱乐、体育文章的平台的。在我们忙碌的时间表中,我们更喜欢在决定阅读整篇文章之前先阅读那些文章的摘要。阅读摘要有助于我们确定感兴趣的领域,给出故事的简要背景。

摘要可以被定义为在保留关键信息和整体含义的同时产生一个简洁流畅的摘要的任务。

冲击

摘要系统通常有额外的证据,它们可以用来指定文档中最重要的主题。例如,当总结博客时,博客帖子后面的讨论或评论是很好的信息来源,可以确定博客的哪些部分是重要的和有趣的。

在科学论文摘要中,有大量的信息,如引用的论文和会议信息,可以用来识别原始论文中的重要句子。

文本摘要的工作原理

通常有两种类型的摘要,抽象的提取的摘要。

  1. **抽象概括:**抽象方法基于语义理解选择单词,即使那些单词没有出现在源文档中。它旨在以新的方式生产重要的材料。他们使用先进的自然语言技术解释和检查文本,以便生成新的更短的文本,传达原始文本中最重要的信息。

它可以与人类阅读文本或博客文章,然后用自己的话总结的方式相关联。

输入文档→理解上下文→语义→创建自己的摘要。

**2。提取摘要:**提取方法试图通过选择保留最重要观点的单词子集来总结文章。

这种方法对句子的重要部分进行加权,并用其形成摘要。使用不同的算法和技术来定义句子的权重,并基于它们之间的重要性和相似性来进一步对它们进行排序。

输入文档→句子相似度→句子权重→选择等级较高的句子。

有限的研究可用于抽象概括,因为与提取方法相比,它需要对文本有更深的理解。

与自动抽象摘要相比,纯粹的提取摘要经常给出更好的结果。这是因为抽象摘要方法处理诸如语义表示、
推理和自然语言生成之类的问题,这比诸如句子提取之类的数据驱动方法相对困难。

有许多技术可以用来生成摘要。为了简单起见,我将使用一种 无监督学习 方法来寻找句子的相似性并对它们进行排序。这样做的一个好处是,在项目中使用它之前,您不需要训练和构建模型。

理解余弦相似性对于充分利用你将要看到的代码是有好处的。余弦相似度是内积空间的两个非零向量之间的相似度,度量它们之间角度的余弦。因为我们将把我们的句子表示为向量束,所以我们可以用它来寻找句子之间的相似性。它测量矢量之间角度的余弦值。如果句子相似,角度将为 0

到现在都好..? 希望如此:)

接下来,下面是我们生成总结文本的代码流:-

输入文章→拆分成句子→去除停用词→建立相似度矩阵→基于矩阵生成排名→挑选前 N 个句子进行汇总。

让我们创建这些方法。

1.导入所有必需的库

from nltk.corpus import stopwords
from nltk.cluster.util import cosine_distance
import numpy as np
import networkx as nx

2.生成干净的句子

**def read_article(file_name):**
    file = open(file_name, "r")
    filedata = file.readlines()
    article = filedata[0].split(". ")
    sentences = [] for sentence in article:
     print(sentence)
     sentences.append(sentence.replace("[^a-zA-Z]", " ").split(" "))
     sentences.pop() 

    return sentences

3。相似性矩阵

这就是我们将使用余弦相似度来寻找句子间相似度的地方。

**def build_similarity_matrix(sentences, stop_words):**
    # Create an empty similarity matrix
    similarity_matrix = np.zeros((len(sentences), len(sentences)))

    for idx1 in range(len(sentences)):
        for idx2 in range(len(sentences)):
            if idx1 == idx2: #ignore if both are same sentences
                continue 
            similarity_matrix[idx1][idx2] = sentence_similarity(sentences[idx1], sentences[idx2], stop_words)return similarity_matrix

4.生成汇总方法

方法将继续调用所有其他帮助函数,以保持我们的摘要管道运行。确保看一下下面代码中的所有# Steps

**def generate_summary(file_name, top_n=5):**
    stop_words = stopwords.words('english')
    summarize_text = [] **# Step 1 - Read text and tokenize**
    sentences =  read_article(file_name) **# Step 2 - Generate Similary Martix across sentences**
    sentence_similarity_martix = build_similarity_matrix(sentences, stop_words) **# Step 3 - Rank sentences in similarity martix**
    sentence_similarity_graph = nx.from_numpy_array(sentence_similarity_martix)
    scores = nx.pagerank(sentence_similarity_graph) **# Step 4 - Sort the rank and pick top sentences**
    ranked_sentence = sorted(((scores[i],s) for i,s in enumerate(sentences)), reverse=True)    
    print("Indexes of top ranked_sentence order are ", ranked_sentence)for i in range(top_n):
      summarize_text.append(" ".join(ranked_sentence[i][1])) **# Step 5 - Offcourse, output the summarize texr**
    print("Summarize Text: \n", ". ".join(summarize_text))

所有放在一起,这里是完整的代码。

让我们看看它的运行情况。

一篇名为 的文章的全文微软推出智能云中心,提升学生在人工智能&云技术 方面的技能

In an attempt to build an AI-ready workforce, Microsoft announced Intelligent Cloud Hub which has been launched to empower the next generation of students with AI-ready skills. Envisioned as a three-year collaborative program, Intelligent Cloud Hub will support around 100 institutions with AI infrastructure, course content and curriculum, developer support, development tools and give students access to cloud and AI services. As part of the program, the Redmond giant which wants to expand its reach and is planning to build a strong developer ecosystem in India with the program will set up the core AI infrastructure and IoT Hub for the selected campuses. The company will provide AI development tools and Azure AI services such as Microsoft Cognitive Services, Bot Services and Azure Machine Learning.According to Manish Prakash, Country General Manager-PS, Health and Education, Microsoft India, said, "With AI being the defining technology of our time, it is transforming lives and industry and the jobs of tomorrow will require a different skillset. This will require more collaborations and training and working with AI. That’s why it has become more critical than ever for educational institutions to integrate new cloud and AI technologies. The program is an attempt to ramp up the institutional set-up and build capabilities among the educators to educate the workforce of tomorrow." The program aims to build up the cognitive skills and in-depth understanding of developing intelligent cloud connected solutions for applications across industry. Earlier in April this year, the company announced Microsoft Professional Program In AI as a learning track open to the public. The program was developed to provide job ready skills to programmers who wanted to hone their skills in AI and data science with a series of online courses which featured hands-on labs and expert instructors as well. This program also included developer-focused AI school that provided a bunch of assets to help build AI skills.

(来源:analyticsindiamag.com)

而用2**行作为输入的概括文本是

*Envisioned as a three-year collaborative program, Intelligent Cloud Hub will support around 100 institutions with AI infrastructure, course content and curriculum, developer support, development tools and give students access to cloud and AI services. The company will provide AI development tools and Azure AI services such as Microsoft Cognitive Services, Bot Services and Azure Machine Learning. According to Manish Prakash, Country General Manager-PS, Health and Education, Microsoft India, said, "With AI being the defining technology of our time, it is transforming lives and industry and the jobs of tomorrow will require a different skillset.*

如你所见,它做得很好。您可以进一步定制它,以减少到数字到字符而不是行。

重要的是要理解我们已经使用了 textrank 作为对句子进行排序的方法。TextRank 不依赖于任何以前的训练数据,可以处理任何任意文本。TextRank 是 NLP 的一个通用的基于图的排序算法。

有许多先进的技术可用于文本摘要。如果你是新手,你可以从一篇名为文本摘要技术:简要调查的有趣的研究论文开始

自然语言生成技术现状调查:核心任务、应用和评估是一篇更加详细的研究论文,您可以浏览一下以获得更好的理解。

希望这已经给了你一个文本摘要的简要概述和总结文本的代码示例演示。你可以从上面的研究论文入手,获取解决这个问题的高级知识和方法。

*这里显示的代码在我的GitHub**上有。*可以下载玩玩。

你可以在 Medium 、 Twitter 和 LinkedIn 上关注我,有任何问题,请发邮件给我(praveend806 [at] gmail [dot] com)。

理解这 4 个高级概念,听起来像机器学习大师

原文:https://towardsdatascience.com/understand-these-4-advanced-concepts-to-sound-like-a-machine-learning-master-d32843840b52?source=collection_archive---------3-----------------------

这是我一年前写的关于机器学习的一些基本概念的文章的续篇。有时候续集比《终结者 2》或《卡恩之怒》更好,但除非你看过第一部,否则你无法欣赏它们。去读那个帖子然后回来。我会等…

机器学习中有许多概念,理解这些概念对于掌握知识非常重要。更重要的是,如果你要实现人工智能,销售人工智能,集成人工智能,或者写关于人工智能的文章,你可能想要温习这些核心的,但先进的概念,以便有一个良好的,强大的基础来开始。

看完这篇文章后,你的 M 机器 I 智慧 L 收入 Q uotient(或 MILQ )将会大幅增加。你准备好了吗?

精确度和召回率

什么是活基督的精确和回忆?!有时当你读到精确和回忆时,它们听起来完全一样;“精确是你正确的频率,回忆是你正确的频率” —例如。Welp,它们实际上是不同的,不幸的是,对于理解为什么机器学习模型对用例有效或无效是重要的。

这可能是我解释这种差异的第三种最佳方式:

比方说,你试图记住一些事情,比如你一生中见过多少把蓝色雨伞。回忆描述了你有多擅长每次看到蓝色雨伞就回忆起来,代价是也会误认一些紫色雨伞的记忆。假设你在生活中看到了 10 把蓝色的雨伞,你把这 10 把雨伞都记住了。但是,你也错误地记住了另外 5 次,事实上它们是紫色的伞(但是你记得它们是蓝色的)。你的回忆是 100%,因为你每次都记得。恭喜你这个怪人!

现在精度将描述你的记忆中有多少是正确的。在上面这个奇怪的例子中,15 次记忆中,只有 10 次是正确的。因此,你的精度约为 66%。

那么哪个更重要呢?这取决于你的用例。如果你正在使用计算机视觉或深度学习从痣的照片中识别癌症,那么尽可能减少你告诉病人他们没有癌症的次数(假阴性),甚至冒着增加告诉人们他们没有癌症的可能性(假阳性)的风险。

关键是你不能两者兼得,总有的权衡。这取决于哪个对你的用例更重要;冒着得到一些假阳性的风险得到每一个真阳性?或者冒着得到更多假阴性的风险,确保尽可能多的结果是真阳性。

明白了吗?如果你仍然困惑,不要担心,它很复杂,很难记住。但是我要继续前进…好吗?

识别与检测

当你应用机器学习时,你会有一些非常酷的工具,比如人脸识别和商标检测*。还可以有人脸检测和 logo 识别。搞什么鬼。为什么?*

让我通过提供每种类型的一些例子来解释这个概念:

人脸识别-输入是一张人脸的图像,机器学习模型识别这个人,并向您返回这个人的名字。

人脸检测-输入是人脸图像,模型会返回一个包围它找到的人脸的边界框。它告诉你脸在哪里,但不告诉你是谁。

图像识别—输入是一幅图像,输出(可能)是描述该图像的多个标签,如雾天、汽车、单色、建筑、风景等。

对象检测—输入是特定图像(如徽标)和要在其上进行检测的一般图像,输出是图像中特定图像(或徽标)出现的每个位置周围的边界框。

这有助于解释差异吗?没有吗?太好了——我们势如破竹,继续前进…

分类

很多好的机器学习实现实际上都是分类器。一篇文章是假新闻还是真新闻,这是一片叶子、一片棕榈叶、一片枫叶还是毒橡树的图像,这句话是不是一个连续的句子,等等。

每堂课就像一个选择或者一个标签。你训练一个机器学习模型,把一些输入数据(比如一张照片或一篇新闻)放到一个类中。有些模型可以给你几个类作为结果,有些一次只能做一个类。

要知道的关键是,当你训练一个分类器时,你必须遵循一些基本规则,否则它不会很好地工作(像我的语法检查器)。

  1. 你的训练数据必须 平衡 。这意味着你必须有和你的狗一样多的猫的照片。如果你尝试训练一个类不均匀的模型,自然会变得更偏向于实例较多的类。
  2. 这个模型不会仅仅指出哪些例子是错误的。你的训练数据必须非常干净。如果你的猫文件夹里有一些狗的例子,那么你真的是在欺骗自己。去把那些照片移到狗文件夹里。

深度学习

深度学习听起来很牛逼吧?还有什么比常规学习更好的呢?我知道..深度学习。好吧,事实证明深度学习很棒,但它有一个问题。首先,让我试着解释一下什么是深度学习。

大多数深度学习模型都是基于人工神经网络的。神经网络本质上是一层又一层的节点,这些节点以某种该死的神奇方式相互连接。当你的输入层和输出层之间有超过 1 或 2 层时,你就有了一个很深的网络!真正酷的是,当你训练网络时,它以某种方式弄清楚如何组织自己来识别人脸(例如)。它可能会将第一层分配给像素分组,第二层分配给边缘检测,第三层分配给鼻子理解,等等……但它会自己找出答案。太神奇了。

但这并不是一切。一个安全的经验法则是,当你听到深度学习时,它意味着 GPU。而 GPU 又很贵。所以你真的需要考虑你的用例。例如,有一个很棒的人脸检测器,而没有使用深度学习。这是一个计算机视觉过滤器,有大约 97%的准确率。这种人脸检测还有深度学习版。精确度逐渐提高,但这是以巨大的性能成本为代价的。你需要 GPU!而计算机视觉版本可以在单个 CPU 上超快运行。

所以,这又是一个权衡。

好了,你的机器学习硕士课程到此结束。

再见

理解这 5 个基本概念,让自己听起来像机器学习专家

原文:https://towardsdatascience.com/understand-these-5-basic-concepts-to-sound-like-a-machine-learning-expert-6221ec0fe960?source=collection_archive---------0-----------------------

https://cdn2.hubspot.net/hub/395829/file-2619018693-jpg/TheEvolutionofForecasting-03-15ENJPG.jpg

亚伦·爱戴是 机器盒子 的联合创始人——这是一家机器学习初创公司,旨在让用机器学习来建造东西变得容易。

大多数人似乎都对机器学习感到有点害怕或困惑。这是什么?它要去哪里?现在能给我一些钱吗?

所有有效的问题。事实是,你已经训练机器学习模型多年了,可能还没有意识到这一点。你用 iPhone 还是苹果照片?或者脸书怎么样?你知道它是如何向你展示一组面孔并让你识别它们的吗?嗯,通过标记这些照片,你正在训练一个面部识别模型来识别新面孔。恭喜你,你现在可以说你有训练机器学习模型的经验了!但在此之前,请阅读这些机器学习基础知识,这样你就可以准确地回答任何后续问题。

1)机器学习的好处是可以预测

如果你只是在图片中标记你朋友的脸,你就不是在使用机器学习模型。如果你上传一张新照片,突然它告诉你每个人是谁,那么你正在用机器学习气体做饭。机器学习的全部意义在于根据模式和其他训练它的因素来预测事物。它可以是任何东西;基于邮政编码和卧室数量的房价,基于一年中的时间和天气的航班延误可能性,图片中物体或人物的标记等。

2)机器学习需要训练

你必须告诉机器学习模型它试图预测什么。想想人类的孩子是如何学习的。他们第一次看到香蕉时,不知道那是什么。然后你告诉他们这是一根香蕉。下一次他们看到一个(不是你训练他们吃的那个,因为你已经吃过了),他们会认出那是一个香蕉。机器学习以类似的方式工作。你给它看尽可能多的香蕉图片,告诉它这是一只香蕉,然后用一只没有被训练过的香蕉图片来测试它。这有点过于简化了,因为我省略了你必须告诉它什么不是香蕉的部分,并向它展示不同种类的香蕉,不同的颜色,不同视角和角度的图片等等。

3) 80%的准确率被认为是成功的

在技术上,我们还没有达到机器学习平台在识别图片中的香蕉时达到 100%准确率的地步。但是没关系。事实证明,人类也不是 100%准确。行业内的潜规则是,80%准确率的模型就是成功的。如果你想一想在你的收藏中正确识别 800,000 张图片是多么有用,尽管可能没有正确识别 200,000 张图片,你仍然节省了自己 80%的时间。从价值的角度来看,这是巨大的。如果我能挥动魔杖,让你的生产率提高那么多,你会给我很多钱。嗯,事实证明我可以,使用机器学习,所以请寄支票或现金。

2018 年更新:80%法则现在更像 90%法则了。

4)机器学习不同于人工智能、深度学习或神经网络

人们倾向于随便使用这些术语。要想听起来像专家,就要学会区别。

AI——人工智能只是指在完成特定任务方面与人类一样好(或更好)的计算机。它也可能意味着一个可以根据大量输入做出决定的机器人,就像终结者或 C3PO 一样。这是一个非常宽泛的术语,不是很有用。

机器学习是一种实现人工智能的方法。这意味着根据分析数据集的训练对某件事做出预测。有许多不同的方式,一个 ML 平台可以实现训练集来预测事情。

NL-神经网络是机器学习模型可以预测事物的方式之一。神经网络的工作有点像你的大脑,通过大量的训练来调整自己,以理解香蕉应该是什么样子的。你创建了一层层的节点,这些节点变得非常深。

5)在人工智能拥有自我意识之前,我们还有一段路要走

( https://xkcd.com/1319/))

我现在还不担心机器人会接管地球。主要是因为如果你曾经建立过一个机器学习模型,你就会知道它有多依赖你这个人来告诉它该做什么。即使你给它明确的指示,它通常也会出错。你必须对这些系统如此明确,以至于它突然变得有知觉的可能性微乎其微。即使是一个简单的网页,显示一个带有单词的框,也需要你准确地告诉它这个框出现在哪里,它是什么形状,它是什么颜色,如何在不同的浏览器上工作,如何在不同的设备上正确显示等等。等等。等等。

即使是非常深的神经网络接管世界,将我们变成电池,也有很多障碍,主要是因为没有人告诉它这样做(希望如此)。

用交互代码理解 Numpy 和 Tensorflow 中的 2D 展开卷积运算

原文:https://towardsdatascience.com/understanding-2d-dilated-convolution-operation-with-examples-in-numpy-and-tensorflow-with-d376b3972b25?source=collection_archive---------1-----------------------

Image from Pixabay

所以从这篇论文来看。用膨胀卷积进行多尺度上下文聚合,我被介绍到膨胀卷积运算。而且说实话只是用修改过的核,准确的说是更宽的核进行卷积运算。然而,为了充分理解一些事情,我需要实施它,因此有了这个帖子。

卷积 vs 扩张卷积(理论)

Image from paper

红线→ “熟悉的”离散卷积(在我们的例子中是正常的 2D 卷积)运算和扩张卷积之间的关系

我们熟悉的离散卷积就是 1-膨胀卷积 。因此,仅仅从这个陈述中,我们已经可以看出,当 1 的值增加到 2 时,这不是我们都喜欢的“熟悉的”卷积运算。而这一点,可以通过图片看得很清楚。

蓝色书写→ 膨胀因子为 1、2、4。(或 1-扩张卷积、2-扩张卷积和 4-扩张卷积)

那么这些扩张因子是什么呢?这可以用另一个图像来解释。(其实是同一个图像 lol)

蓝色数字 →应用于内核的膨胀因子

所以上图并不是膨胀卷积的最佳表现,但你可以大致了解这个膨胀因子是什么。并且随着膨胀因子的增加,原始核元素之间的空间变得越来越宽。现在让我们来看例子。

实验设置

红框 →原矩阵
蓝框 →我们要用的内核

因此,我们将使用蓝框核对红框矩阵执行多重卷积运算。但是,有三点需要注意。

  1. 在 Tensorflow 中有两种方法来执行扩张卷积,或者通过基本的 tf.nn.conv2d() (通过设置扩张的)或者通过 tf.nn.atrous_conv2d()
  2. 然而,似乎这两个操作都没有翻转内核。所以他们正在执行互相关(如果我错了请纠正我),所以我们将手动翻转内核,如下所示。(红线)

3.如上所述,所有的 Tensorflow 操作将使用原始(3*3)内核,同时改变膨胀因子,而对于 Numpy,我们将为每个膨胀率生成特定内核。

例 1-扩张因子 1

我们已经知道,如果我们将膨胀因子设置为 1,它就像我们学会的卷积运算一样。所以这个例子没有什么特别的。现在让我们看一下代码。

红线 →注意我们正在对 Numpy
进行“熟悉的”卷积运算,黄线 →张量流的膨胀因子

示例 2 -扩张因子 2

红框 →为 Numpy 生成膨胀因子为 2 的内核

现在,由于膨胀因子已经增加到 2,我们将为 Numpy 生成一个新内核。

红线 →注意我们正在对 Numpy
黄线 →张量流的膨胀因子进行“熟悉的”卷积运算

示例 3 —扩张因子 3

红框 →为 Numpy 生成膨胀系数为 3 的内核

现在,由于膨胀因子已经增加到 3,我们将为 Numpy 生成一个新内核。

红线 →注意我们正在对 Numpy
进行“熟悉的”卷积运算,黄线 →张量流的膨胀因子

例 4—扩张因子 4

红框 →为 Numpy 生成膨胀系数为 4 的内核

现在,由于膨胀因子已经增加到 4,我们将为 Numpy 生成一个新内核。

红线 →注意我们正在对 Numpy
黄线 →张量流的膨胀因子进行“熟悉的”卷积运算

交互代码

我为了交互代码搬到了 Google Colab!所以你需要一个谷歌帐户来查看代码,你也不能在谷歌实验室运行只读脚本,所以在你的操场上做一个副本。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!

注意安装在 Google Collab 上的 Tensorflow 版本似乎不支持膨胀因子大于 2 的膨胀卷积,(仅适用于 tf.nn.conv2d())它会给出以下错误。所以我已经把 tf.nn.cond2d()注释掉了。

要访问代码,请点击此处。

最后的话

一个惊人的事实是:对扩张卷积运算进行反向传播只是转置卷积运算。

如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有写作的列表,请点击这里查看我的网站。

同时,在我的推特这里关注我,访问我的网站,或者我的 Youtube 频道了解更多内容。如果你感兴趣,我还在这里做了解耦神经网络的比较。

参考

  1. 膨胀卷积和克罗内克因子卷积。(2016).推论。检索于 2018 年 3 月 12 日,来自http://www . inference . VC/expanded-convolutions-and-kronecker-factorisation/
  2. 卷积运算教程—no 1 . 0 . 0 文档。(2018).Deeplearning.net。检索于 2018 年 3 月 12 日,来自http://deep learning . net/software/the ano/tutorial/conv _ 算术. html
  3. tf.nn.atrous_conv2d | TensorFlow。(2018).张量流。检索于 2018 年 3 月 12 日,来自https://www . tensor flow . org/API _ docs/python/TF/nn/atrous _ conv 2d
  4. SciPy . signal . convolved 2d—SciPy v 1 . 0 . 0 参考指南。(2018).Docs.scipy.org。检索于 2018 年 3 月 12 日,来自https://docs . scipy . org/doc/scipy/reference/generated/scipy . signal . convolved . html
  5. 数组,I. (2018)。NumPy 数组的就地类型转换。Stackoverflow.com。检索于 2018 年 3 月 12 日,来自https://stack overflow . com/questions/4389517/in-place-type-conversion-of-a-numpy-array
  6. TF . nn . conv 2d _ back prop _ filter | tensor flow。(2018).张量流。检索于 2018 年 3 月 12 日,来自https://www . tensor flow . org/API _ docs/python/TF/nn/conv2d _ back prop _ filter
  7. tf.nn.conv2d | TensorFlow。(2018).张量流。检索于 2018 年 3 月 12 日,来自https://www.tensorflow.org/api_docs/python/tf/nn/conv2d
  8. “扩张卷积和卷积+步幅有什么区别?——Quora”。2018.Quora.Com。2018 年 3 月 12 日访问。https://www . quora . com/What-is-difference-of-expanded-convolution-and-convolution+stride。
  9. 于,冯,科尔敦,伏(2015)。基于扩张卷积的多尺度上下文聚合。 arXiv 预印本 arXiv:1511.07122
  10. 理解多层 CNN 转置卷积的反向传播。(2018).中等。检索于 2018 年 3 月 12 日,来自https://medium . com/swlh/only-numpy-understanding-back-propagation-for-transpose-convolution-in-multi-layer-CNN-with-c0a 07d 191981

理解黑盒

原文:https://towardsdatascience.com/understanding-a-black-box-896df6b82c6e?source=collection_archive---------7-----------------------

模型可解释性方法的概述…以及为什么它很重要。

在我们深入研究一些流行且相当强大的方法来打开黑盒机器学习模型(如深度学习模型)之前,让我们首先明确一下为什么它如此重要。

你看,有许多领域将受益于可理解的模型,如自动驾驶汽车,或广告定位,甚至有更多的领域需要这种可解释性,如信誉分配,银行,医疗保健,人力资源。能够审计这些关键领域的模型是非常重要的。

理解一个模型的最重要的特征让我们深入了解它的内部工作,并给出改进它的性能和消除偏差的方向。

除此之外,有时它有助于调试模型(经常发生)。然而,与预测一起提供解释的最重要的原因是,可解释的 ML 模型对于获得最终用户的信任是必要的(以医疗应用为例)。

我希望现在你也相信可理解的机器学习是非常重要的,所以让我们深入到具体的例子中来解决这个问题。

简单方法

人们能想到的最简单的方法是稍微改变输入数据,以观察底层黑盒是如何反应的。对于视觉数据,使用部分遮挡的图像是最简单的方法。对于文本——替换单词,对于数字/分类数据——改变变量。就这么简单!

这种方法的最大好处是——它是模型不可知的,您甚至可以检查其他人的模型,而无需直接访问它。

即使听起来很容易,好处也是巨大的。我多次使用这种方法来调试机器学习即服务解决方案和在我自己的机器上训练的神经网络,发现训练的模型选择不相关的特征来决定图像的类别,从而节省了工作时间。真正的 80/20 法则在起作用。

GradCAM

梯度加权类激活图——一种更高级更专业的方法。这种方法的限制是您需要访问模型的内部,并且它应该可以处理图像。为了让您对该方法有一个简单的直觉,给定一个数据样本(图像),它将输出图像区域的热图,其中神经网络具有最多和最大的激活,因此图像中的特征与该类的相关性最大。

从本质上讲,与之前的模型相比,您对该模型的重要特性有了更细粒度的理解。

这里是 GradCAM 可解释性方法的一个很好的演示。
要了解 GradCAM 如何工作,请查看“Grad-CAM:通过基于梯度的定位从深度网络进行可视化解释”的论文。

石灰

也许你听说过这个。如果没有,首先看看这个简短的介绍。

2016 年发表《我为什么要相信你?:解释任何分类器的预测”的论文,该论文介绍了 LIME —局部可解释的模型不可知解释。让我们从名字中推导出它的功能!

局部可解释性*——*你要知道机器学习模型的复杂度越高,模型的可解释性越差。也就是说,逻辑回归和决策树比随机森林和神经网络更容易解释。LIME 方法的假设是,像随机森林或神经网络这样的非线性复杂模型可以是线性的,并且在局部是简单的,即在整个决策边界的小块上。回想一下,我们说过简单的模型是可以解释的。

模型无关 这部分比较容易。LIME 对被解释的模型没有任何假设。

关于 LIME 最好的事情是它也可以作为 PyPI 包使用。你已经准备好出发了!要了解更多信息,这里是他们的 GitHub repo 基准和一些教程笔记本,这里是他们论文的链接。仅供参考,LIME 也被 Fast Forward Labs(现在是 Cloudera 的一部分)用于演示模型可解释性的重要性。

SHAP

SHapley 附加解释 —一种理解黑盒模型的最新解决方案。在某种程度上,它非常类似于石灰。两者都是强大的统一解决方案,与模型无关,并且相对容易上手。

但是 SHAP 的特别之处在于它内部使用石灰。事实上,SHAP 背后有太多的可解释模型,它选择最适合手头问题的模型,用正确的工具给你所需的解释。

此外,如果我们分解这个解决方案的能力,我们实际上发现,SHAP 用 Shapley 值解释了任何机器学习模型的输出。这意味着 SHAP 为每个预测的每个特征分配一个值(即特征属性);该值越高,该特征对特定预测的贡献就越大。这也意味着这些值的总和应该接近原始模型预测。

检查他们的 GitHub repo ,就像 LIME 一样,他们有一些教程,也可以通过 pip 安装 SHAP。此外,要了解更多细节,请查看他们的压印线预打印纸。

最终注释

机器学习模型的可解释性和可解释性是人工智能社区的一个热门话题,具有巨大的影响。为了让人工智能产品和服务进入新的高度监管的市场,必须了解这些新算法是如何做出决策的。

此外,知道机器学习模型的原因在调试它,甚至改进它方面提供了突出的优势。

在设计深度学习/机器学习系统时,最好考虑到可解释性,这样总是很容易检查模型,并在关键情况下抑制其决策。

如果你已经做到了,谢谢你!我鼓励你在这个新领域进行自己的研究,并在评论区与我们分享你的发现。

另外,如果你喜欢这篇文章,别忘了鼓掌😏或者关注我,获取更多关于机器学习和深度学习的各种主题的文章。

P.S .抱歉,这次没有 Colab 笔记本,因为已经有很多关于这个主题的非常好的教程让你开始。

通过食物理解机器学习的工作流程

原文:https://towardsdatascience.com/understanding-a-machine-learning-workflow-through-food-690ddad7803?source=collection_archive---------18-----------------------

Photo by Cel Lisboa on Unsplash

穿越美食?!

是的,没错,通过美食!:-)

想象一下,你点了一份披萨,过了一会儿,那份好吃的热的美味的披萨就送到了你家。

你有没有想过让这样一个比萨饼送到你家背后的工作流程?我的意思是,完整的工作流程,从播种番茄种子到骑自行车的人在你家门口嗡嗡作响!事实证明,机器学习工作流程并无太大不同。****

真的!我们去看看吧!

这篇文章的灵感来自于谷歌首席决策科学家 Cassie Kozyrkov 在柏林举行的 Data Natives 会议上的一次演讲。

Photo by SwapnIl Dwivedi on Unsplash

1.播种

农民播下种子,这些种子会成长为我们比萨饼的配料,就像西红柿一样。

这相当于数据生成过程**,可以是用户动作,例如触发传感器的运动、热量或噪声。**

Photo by no one cares on Unsplash

2.收获

然后是收获的时候,也就是蔬菜或水果成熟的时候。

这相当于数据收集**,意味着浏览器或传感器会将用户动作或触发传感器的事件转化为实际数据。**

Photo by Matthew T Rader on Unsplash

3.运送

收获后,产品必须运输到目的地,用作我们披萨的配料。

这相当于将数据接收到一个存储库中,稍后将从那里获取数据,比如数据库或数据湖。

Photo by Nicolas Gras on Unsplash

4.选择器具和器皿

对于每一种配料**,都有最合适的器具来处理。如果需要切片,使用。如果需要搅拌,一把勺子。同样的道理也适用于器具:如果你需要烘烤,使用烤箱。如果需要,一个。你也可以使用更复杂的设备,如微波炉,有更多的设置选项。**

有时候,使用更简单的设备甚至会更好——你见过餐馆做广告说“微波披萨”吗?!我没有!****

在机器学习中,器具是预处理数据的技术,而器具算法,就像线性回归随机森林。还可以用一个微波,我是说深度学习。可用的不同选项是超参数。在简单的电器里只有几个,我是说算法。但是在一个复杂的世界里还有很多很多。此外,无法保证复杂的算法会带来更好的性能(或者你更喜欢微波披萨?!).所以,明智地选择你的算法。****

Photo by S O C I A L . C U T on Unsplash

5.选择食谱

光有食材和器具是不够的。你还需要一份食谱**,里面有你准备菜肴需要遵循的所有步骤。**

这是你的型号**。而没有,你的型号不是跟你的算法一样。该模型包括您的算法所需的所有前置 -后置--加工。并且,说到预处理 …**

Photo by Caroline Attwood on Unsplash

6.准备配料

我敢打赌,大多数食谱中的第一个说明是这样的:“切这个”,“削那个”等等。他们不会告诉你去蔬菜,因为这是理所当然的——没人想吃的蔬菜,对吧?

数据也是如此。没人想要脏数据。你要清理它,也就是处理缺失值离群值**。然后你要切片,我的意思是预处理,就像编码分类变量()成数值( 01 )。**

没人喜欢那部分。数据科学家和厨师都不是(我猜)。

Photo by Bonnie Kittle on Unsplash

7.特殊准备

有时候,你可以用你的配料获得创意**,以获得更好的口味更精致的 呈现。**

你可以将牛排风干以获得不同的味道,或者将胡萝卜雕刻成玫瑰的形状,然后放在你的盘子上:-)。

这是特色工程**!这是一个重要的步骤,如果用一种巧妙的方式,可能会大大提高你的模型的性能。**

几乎每个数据科学家都喜欢这一部分。我猜厨师也喜欢它。

Photo by Clem Onojeghuo on Unsplash

8.烹饪

最基本的一步——没有真正的烹饪**,就没有菜肴。很明显。你把准备好的配料放入器具,调整热度,等一会儿再检查。**

这是你模型的训练**。您将数据输入到您的算法,调整其超参数并等待一段时间,然后再次检查。**

Photo by Icons8 team on Unsplash

9.品尝

即使你严格按照菜谱做,你也不能保证一切都是正确的。那么,你怎么知道你是否做对了呢?你尝尝吧!如果不好吃,可以多加尝试修复。您也可以改变温度。但是你继续做饭!

不幸的是,有时你的披萨会被烧焦,或者不管你怎么做都难以下咽。你把它扔进垃圾桶,从错误中吸取教训,重新开始。

但愿,坚持和一点点运气能做出美味** 披萨 😃**

品鉴就是评价。你需要评估你的模型,检查它是否运行良好。如果没有,您可能需要添加更多功能。您也可以更改一个超参数。但是你要坚持训练!

不幸的是,有时你的模型不会收敛到一个解决方案,或者做出可怕的预测,不管你做什么来试图挽救它。你抛弃了你的模型,从你的错误中吸取教训,重新开始。

希望,坚持和一点点运气会产生一个高性能模型** 😃**

Photo by Kai Pilger on Unsplash

10.递送

从厨师的角度来看,他/她的工作已经完成了。他/她做了美味的比萨饼。句号。

但是如果比萨饼没有很好地送到顾客手中,及时送到顾客手中,比萨饼店就会倒闭,厨师也会失业。

比萨饼做好之后,必须立即包装好以保温,并小心地处理好,以免在送到饥饿的顾客手中时看起来湿漉漉的。如果骑车人没有到达他/她的目的地,在路上丢失了比萨饼或者把它摇得面目全非,所有的烹饪努力都是徒劳的。

交付就是部署。不是披萨,而是预测。预测就像披萨一样,必须包装**,不是装在盒子里,而是作为数据产品,这样才能送到热切的顾客手中。如果管道出现故障、中途断裂或以任何方式修改预测,所有的模型训练和评估都是徒劳的。**

就是这样!机器学习就像烹饪食物——过程中有几个人参与,需要付出很多努力**,但最后的结果却可以好吃!**

只有几个要点:

  • 如果食材坏的**,那就要坏了——没有菜谱能搞定 当然,没有器具,也没有;**
  • 如果你是厨师**,千万不要忘记,不送,烹饪就毫无意义,因为永远不会有人品尝你的美味;**
  • 如果你是一个餐馆老板**,不要试图把电器强加给你的厨师——有时候 微波炉 并不是最好的选择——如果他/她把所有的时间花在洗碗切片 配料上,你会得到一个非常不开心的厨师…**

我不知道你怎么样,但是我现在想要订购一个比萨饼!:-)

如果你有什么想法、评论或者问题,请在下方留言或者联系我 推特

了解用于移动应用程序开发的人工智能和 ML

原文:https://towardsdatascience.com/understanding-ai-and-ml-for-mobile-app-development-d07a3788d508?source=collection_archive---------7-----------------------

Photo by Rock'n Roll Monkey on Unsplah

上次我发表了这篇博客,其中我解释了 AI 和 ML 的一个应用——“视觉”,还简要解释了在移动开发中使用 ML kit,这是谷歌提供的云平台,用于集成 Android 和 iOS 应用中的 ML 功能。这篇文章是那篇文章的前传,在这篇文章中,我将解释人工智能和机器学习的基础知识。我将阐明什么是不同类型的机器学习,以及当我们看到谷歌照片应用程序检测我们的面部时,或者当 Gmail 建议我们用完整的句子作为回复时,这一切是如何发生的。

AI vs ML

人工智能和 ML 是计算机科学的一个分支,一个单独的博客无法对这些主题做出公正的评价,我也不自称是这些领域的专家,但是为了我们在移动应用程序中开始使用 ML 的目标,我们必须对这些术语有一些基本的理解。

人工智能被定义为——机器或计算机对人类行为的模仿。人工智能研究的是科学的一个分支,其目标是使机器或计算机表现出与人类同等水平的智力、聪明、表达能力和艺术特征。人工智能的水平和应用各不相同。现在,例如,如果有一个假设的人形机器人可以洗碗、洗车和做饭,我们将把它称为人工智能的产品,但也将是一个能够理解语音并识别语音语气是愤怒、羡慕还是高兴的软件。人工智能是巨大的,涉及许多方面——有帮助收集、分类和处理数据的数据科学,有帮助理解和应用智能特征的算法,还有机器学习。ML 是人工智能的一部分,它实现了学习和训练能够做出决策的程序的目标。这些程序被输入了大量的数据,使用算法来处理这些数据,并根据这些数据进行训练,这样当它得到一个新的输入时,它就能够做出决定。

Cat or Dog — Using neural network for vision

人工智能在最近几年变得越来越热门,但它不是新概念,自 70 年代以来就一直存在。但直到现在,由于高处理能力、硬件和所需的大量数据的可用性,它才变得切实可行地用于解决问题。为了训练模型并给出可靠的输出,ML 需要处理的数据项不是几千而是几百万。

ML 解释道

ML 可以分为三种方式:

  1. 监督学习——我们向 ML 算法输入大量数据,这些数据被标记,即标有结果。该数据具有附在条目上的段或标签。在这种类型的学习中,我们教系统如何根据我们已经输入的数据来识别新的输入。
  2. 无监督学习——数据没有被标记或分类。在这种情况下,系统不知道成功或失败终点,因为它没有任何可用的指导。在这种情况下,系统会尝试对可用数据进行分类,并用给定的信息创建模式,并存储这些模式。现在,当一个新的输入到达时,它会尝试将输入与存储的模式进行匹配,并将选择的模式分配给它。
  3. 强化学习——这是一种无监督学习。在这种学习中,输入数据也没有标记。当获得成功时,它被反馈给系统以指示推断成功。这改善了未来的结果。

理解 ML 需要我们经历以下术语:

  • 数据
  • 模型
  • 培养
  • 决定
  • 经验

ML 程序被输入大量的数据训练它。从训练中,它学习问题的规则,并积累经验。有了经验,当新问题出现时,它就有能力做出决定。此外,在处理新的数据和问题陈述时,它使适应新的情况。所以和人类一样,它“边工作边学习”。例如,如果我们必须使用机器学习来创建一个国际象棋解算器,我们将不会编写大量的 if/else 来对每一步做出决定,而是我们将为 ML 程序提供一些非常基本的规则以及大量以前的国际象棋游戏数据。有了这些数据,它将学习并最终能够决定下一步该做什么。

创建“模型”

创建和训练模型是创建您的 ML 系统的非常重要的部分。模型是预处理数据和选定算法的集合,这些算法对数据进行处理以推断输出。创建模型是一个复杂的过程,本质上是迭代的。对于我们的用例,我们从一些基本规则和选择的算法开始,并开始向我们的系统提供大量的使用数据。这些数据是我们以前在系统中收集的条目。例如,在银行欺诈检测系统的情况下,数据将是所有用户的信用和借记交易的历史。使用这些数据,我们首先创建不同的“候选模型”,然后在新的数据集上使用和尝试这些模型,并观察它们的性能。在成功率的基础上,选择和部署最佳的模型来提供新的用例。有了新的输入数据,选定的模型做出决策,并在此过程中收集更多的经验,使自己适应不断扩展的用例。

Training and using ML model

Creating ML model — iterative nature of the process

ML 的应用

  • 图像处理——这是最典型的 ML 用例。在这个 ML 中,算法被用于检测给定图像中的各种对象。这属于“监督学习”,其中 ML 系统被输入大量包含不同对象的标记图像。因此,ML 模型被训练来识别对象。谷歌助手和谷歌照片就是很好的例子。AWS Rekognition 和 Firebase ML kit 为此功能提供了 API。
  • 自然语言处理和语音识别——自然语言处理和语音识别是 ML 的另一个非常著名且不断发展的用例。检测书面文本并推断其脚本和含义是非常有用的。有各种解决方案可用于集成这一点,包括 Google Cloud ML 和 AWS 的不同产品——Amazon transcripte、Translate 和 Lex。
  • 诊断学——医学诊断学是人工智能和人工智能领域的一个衍生因素。医疗部门和人工智能科学家开发了一些系统,可以使用细胞视觉和包括病历在内的其他数据来检测癌症和其他疾病的可能性。
  • 预测—使用历史数据 ML 模型可以推断未来事件,如商业欺诈检测、客户行为预测或自然事件预测。

First painting created by an AI program

如何在应用中使用人工智能/人工智能——何去何从

有几个方向可供选择,这取决于开发人员想要多少功能、灵活性,以及他们的用例有多具体。我们可以从谷歌云或 AWS 平台的现成、完全成熟的人工智能产品中进行选择,也可以部署我们自己的定制模型。

ML 框架

  • TensorFlow/Keras 模型——Tensor Flow 是谷歌的开源机器学习框架。张量流是一个通用的 ML 框架,涵盖了广泛的用例。这是最广泛用于开发和部署 ML 模型。Keras 是一个高级 Python API,用于构建和训练深度学习模型。它是独立开发的,但在谷歌收购后,现在是张量流的一部分。
  • 来自脸书的 PyTorch 这个来自脸书的库是基于 Python 的深度学习库。这主要用于像自然语言处理这样的应用。这也是开源的。PyTorch 的主要优势在于它利用 GPU 的能力来解决复杂的数学问题。它被深度学习研究人员用作首选库。它可以说是早期著名的 Python 数学库的高级版本,是 numPy,但它更好更快,因为它使用了 GPU。
  • Google Cloud ML/Cloud Vision——Google Cloud Vision 框架是 Google ML 产品的一部分,专门处理计算机视觉或“图像分析”。在这种情况下,有几种功能可用于图像分析,如文本检测、人脸检测、内容调节等。

Google Cloud Vision home

Cloud vision API demo

  • Firebase ML kit with tensor flow Lite—Firebase ML kit 是 Cloud Vision API 的新成员,主要面向移动开发者。ML 工具包提供易于使用的云 API 的图像处理,如文本检测,人脸检测,条形码扫描,对象检测和标志检测。它提供了在设备上或云处理的选项。
  • AWS 套件——AWS 还提供了大量现成的 ML 特性。这些功能包括图像分析(AWS Rekognition)、语音转文本(AWS Transcribe)、翻译(AWS Translate)、聊天机器人(AWS Lex)、文本转语音(AWS Polly)和许多其他功能。在这些 AWS 中,Rekognition 涵盖了与图像分析相关的最广泛的使用案例,如文本和对象识别、人脸检测和识别等。

AWS rekognition

  • OpenCV —这是迄今为止最著名的计算机视觉和机器学习库,它非常强大,易于使用,并且是开源的。它适用于包括 Android 在内的不同平台。这个库非常容易使用,开发人员正在使用它来制作非常酷的计算机视觉相关应用程序,如检测人脸或特定对象,并在此基础上做出决定。
  • kag gel——对于人工智能开发人员来说,这是一个非常有用的地方,可以为他们的特定用例获取数据集/模型。拥有超过 10,000 个数据集,以满足不同的需求和领域。例如,如果你想创建一个实时微笑检测器,你会想检查一个检测到的脸是否在微笑。您需要一个成熟的数据集来创建和准备您的模型。你会从卡格尔那里得到这个。Kaggle 于 2017 年被谷歌收购。

Kaggle datasets (www.kaggle.com)

TL;灾难恢复—如果您的需求属于图像分析、文本或识别或视频分析等一般使用情形,那么您可以使用 AWS 或 Google Cloud 提供的现成解决方案。如果您需要对现有模型进行一些调整,或者您想要部署现有模型,您可以使用 TensorFlow/Keras,如果您想要用自己的定制解决方案解决一个新问题,您可以使用 PyTorch 或 TF 创建和训练您的模型,并使用任何云解决方案部署它。Kaggel 是一个非常好的存储库,可以存储大量用例的数据。

了解和优化 gan(回到基本原则)

原文:https://towardsdatascience.com/understanding-and-optimizing-gans-going-back-to-first-principles-e5df8835ae18?source=collection_archive---------0-----------------------

Fig 1. Improvement of fake image generation of faces over training using basic GAN algorithm

自从 Ian Goodfellow 首次提出生成性对抗网络(GANs)架构以来,围绕该架构的宣传一直在增长,并且大量的进步和应用每天都变得越来越令人着迷。但是对于任何想开始使用 GANs 的人来说,想知道从哪里开始是相当棘手的。不要惊慌。这篇文章将指导你。

和许多事情一样,完全理解一个概念的最好方法是触及根本。抓住首要原则。对于甘斯来说,这里是原文->(https://arxiv.org/abs/1406.2661)。要理解这类论文,有两种方法,理论的和实践的。我通常更喜欢后者,但如果你喜欢深入研究数学,这里的是我的好友 Sameera 的一篇很棒的帖子,从理论上分解了整个算法。与此同时,本帖将使用 Keras 以最纯粹的形式呈现该算法的简单实现。让我们开始吧。

在 GAN 的基础设置中有两个模型,即生成器和鉴别器,其中生成器不断地与鉴别器竞争,鉴别器是正在学习区分模型分布(例如生成的假图像)和数据分布(例如真实图像)的对手。这个概念被一个伪造者对警察的场景形象化了,在这个场景中,生成模型被认为是伪造者生成假币,而鉴别模型被认为是警察试图检测假币。这个想法是,随着彼此之间的不断竞争,伪造者和警察都在彼此的角色中改进,但最终伪造者达到了生产与真钞难以区分的假钞的阶段。简单。现在让我们把它写成代码。

本文提供的示例脚本用于生成虚假的人脸图像。我们试图用该算法实现的最终结果如图 1 所示。

建立发电机模型

因此,发电机模型应该吸收一些噪声,并输出一个令人满意的图像。这里我们使用 Keras 序列模型以及密集和批量标准化层。使用的激活函数是 Leaky Relu。请参考下面的代码片段。发电机模型可以分为几个模块。由密集层->活化->批量归一化组成的一个块。添加了三个这样的块,最后一个块将像素转换成我们期望输出的图像的形状。该模型的输入将是形状为(100)的噪声向量,并且该模型在最后被返回。注意每个密集层中的节点是如何随着模型的进展而增加的。

建立鉴别器模型

鉴别器接收一个图像输入,将其展平并通过两个密集->激活模块,最终输出一个介于 1 和 0 之间的标量。输出 1 应该表示输入图像是真实的,否则为 0。就这么简单。参考下面的代码。

注意:-
你可以在以后修改这些模型,增加更多的模块,更多的批量标准层,不同的激活等等。根据这个例子,这些模型足以理解 GANs 背后的概念。

发现损失并训练

我们计算三个损失,在本例中全部使用二元交叉熵来训练两个模型。

首先是鉴别器。它被训练成两种方式,如下面的代码所示。首先为真实图像(数组“img”)输出 1,然后为生成的图像(数组“gen_img”)输出 0。随着训练的进行,鉴别器在这项任务上有所提高。但是我们的最终目标在理论上达到了,此时鉴别器对两种类型的输入都输出 0.5(即,不确定是假还是真)。

接下来是训练发电机,这是一个棘手的问题。为了做到这一点,我们首先公式化一个给定发电机输出的鉴别器的组合模型。记住!理想情况下,我们希望这个值为 1,这意味着鉴别器将生成的假图像识别为真实图像。所以我们针对 1 训练组合模型的输出。参见下面的代码。

现在我们来玩吧!这是代码的要点,可以简单地理解 GANs 的工作方式。

完整代码可以在我的 GitHub 上 这里 找到。您可以参考所有用于导入 RGB 图像、初始化模型并将结果记录在代码中的附加代码。还要注意,在训练期间,小批量被设置为 Hi32 图像,以便能够在 CPU 上运行。
此外,示例中使用的真实图像是来自 CelebA 数据集的 5000 幅图像。这是一个开源的数据集,我已经把它上传到我的 Floydhub 上以便于下载,你可以在这里找到
***

有许多方法可以优化代码以获得更好的结果,并了解算法的不同组件如何影响结果的效率。观察结果,同时调整不同的组件,如优化器,激活器,规格化,损失计算器,超参数等,是增强你对算法理解的最好方法。我选择改变优化。

因此,我以 32 个为一批,训练了 5000 个纪元,用三种优化算法进行了测试。使用 Keras,这个过程就像导入和替换优化器函数的名称一样简单。所有 Keras 内置的优化器都可以在这里找到。
还绘制了每种情况下的损失,以了解模型的行为。

  1. 使用 SGD(随机梯度下降优化器)。输出和损耗变化分别如图 2 和图 3 所示。

Fig 2. Output of the GAN using SGD as the optimizer

Fig 3. Plot showing the variation of losses while training the GAN using SGD

注释——虽然收敛有噪声,但我们可以看到,发生器损耗随着时间的推移而下降,这意味着鉴别器倾向于将假图像检测为真图像。

2.使用 RMSProp 优化器。输出和损耗变化分别如图 4 和图 5 所示。

Fig 4. Output of the GAN using RMSProp as the optimizer

损失:

Fig 5. Plot showing the variation of losses while training the GAN using RMSProp

注释—这里我们还可以看到发电机损耗在下降,这是一件好事。令人惊讶的是,真实图像上的鉴别器损耗增加了,这非常有趣。

3.使用亚当优化器。输出和损耗变化分别如图 6 和图 7 所示。

Fig 6. Output of the GAN using Adam as the optimizer

Fig 7. Plot showing the variation of losses while training the GAN using Adam

注释 adam 优化器产生了迄今为止最好的结果。请注意鉴别器对假图像的损失如何保持较大的值,这意味着鉴别器倾向于将假图像检测为真图像。

评论

我希望这篇文章从实用的角度传达了对 GANs 内部工作的基本看法,以理解和了解如何改进基本模型。在不同的应用程序上,开源社区中有许多 GANs 的实现,对基本原则有一个良好的理解将极大地帮助你理解这些进步。此外,GANs 对于深度学习来说相对较新,有许多研究途径对任何感兴趣的人开放。

所以你可以探索无限的可能性!

了解和可视化 DenseNets

原文:https://towardsdatascience.com/understanding-and-visualizing-densenets-7f688092391a?source=collection_archive---------1-----------------------

这篇文章可以在 PDF 这里下载。

这是关于 CNN 架构的系列教程的一部分。

主要目的是深入了解 DenseNet,并深入研究针对 ImageNet 数据集的 DenseNet-121。

  • 对于适用于 CIFAR10 的 DenseNets,这里还有另外一个教程。

索引

  • 背景
  • 动机
  • DenseNets 解决什么问题?
  • 体系结构
  • 摘要

背景

密集连接的卷积网络1,DenseNets,是继续增加深度卷积网络的下一步。

我们已经看到我们是如何从 5 层的 LeNet 发展到 19 层的 VGG 和超过 100 层甚至 1000 层的 ResNets。

动机

当 CNN 更深入时,问题就出现了。这是因为 路径 对于从输入层直到输出层的信息(对于反方向的渐变) 变得如此之大 ,以至于它们可以在到达另一边之前 消失

DenseNets 简化了其他架构中引入的层之间的连接模式:

  • 高速公路网2
  • 剩余网络3
  • 分形网络[4]

作者解决了确保最大信息(和梯度)流的问题。为此,他们只需将每一层直接相互连接。

DenseNets 没有从极深或极宽的架构中汲取代表力量,而是通过功能重用来挖掘网络的潜力。

DenseNets 解决什么问题?

反直觉地,通过这种方式连接,densentes比等效的传统 CNN 需要更少的参数 ,因为不需要学习冗余的特征映射 。

此外,ResNets 的一些变体已经证明许多层几乎不起作用,并且可以被丢弃。事实上,ResNets 的参数数量很大,因为每一层都有其要学习的权重。相反, DenseNets 图层很窄 (例如 12 个滤镜),它们只是 增加了一小组新的特征贴图

非常深的网络的另一个问题是训练的问题,因为提到了信息流和梯度。DenseNets 解决了这个问题,因为 每一层都可以从损失函数 和原始输入图像直接访问梯度。

结构

Figure 1. DenseNet with 5 layers with expansion of 4. 1

传统的前馈神经网络在应用操作 的 组合后,将该层的输出连接到下一层。

我们已经看到,通常这个组合包括一个卷积运算或池层、一个批处理规范化和一个激活函数。

这个等式是:

ResNets 扩展了这种行为,包括跳过连接,将该等式重新表述为:

DenseNets 与 ResNets 的第一个区别就在这里。 DenseNets 不将该层的输出特征图与输入特征图相加,而是将它们连接起来

因此,该等式再次变形为:

我们在 ResNets 上的工作面临着同样的问题,当它们的尺寸不同时,这种特征地图的分组就不能完成。不管分组是相加还是串联。因此,和我们用于 ResNets 的方法一样,DenseNets 被分成 DenseBlocks,其中特征映射的尺寸在一个块内保持不变,但是过滤器的数量在它们之间变化。它们之间的这些层被称为 过渡层 ,并负责应用批量归一化、1x1 卷积和 2x2 合并层的下采样。

现在我们可以开始讨论增长率了。由于我们正在连接特征图,该信道维度在每一层都在增加。如果我们使 H_l 每次产生 k 个特征图,那么我们可以对第 l 层进行推广:

这个超参数 k 就是增长率。增长率决定了每层网络中增加的信息量。为什么

我们可以把特征图看作是网络的信息。 每一层都可以访问其前面的特征图 ,因此,对 集合知识 。然后,每一层都向这一集体知识添加新的信息,具体表现为信息的 k 特征图

DenseNets-B

DenseNets-B 只是常规 DenseNets,它利用 1x1 卷积来减少 3x3 卷积之前的特征映射大小,并提高计算效率。B 出现在瓶颈层之后,你已经熟悉这个名字了,来自ResNets的工作。

丹麦-公元前

DenseNets-C 是 DenseNets-B 的另一个小增量步骤,用于我们想要 减少输出特征映射 的情况。 ***压缩因子(θ)**决定了这个减少量。我们将拥有 thetam,而不是某一层的 m 个特征地图。当然,在范围[0–1]内。所以当θ= 1时,DenseNets 将保持不变,否则将是 DenseNets-B。

为了与resnet 上的工作保持一致,我们将详细讨论 ImageNet 数据集上的案例。然而,CIFAR-10 或 SVHN 的结构更简单,因为输入量更小。

Figure 2. Sizes of outputs and convolutional kernels for different DenseNets 1 architectures on ImageNet.

正如您从之前关于其他体系结构的工作中了解到的,我更喜欢观察模型中的卷实际上是如何改变其大小的。这种方式更容易理解特定模型的机制,能够根据我们的特定需求对其进行调整。我将尝试遵循接近于 PyTorch 官方实现的符号,以便于稍后在 PyTorch 上实现它。

密集和过渡块

然而,由于 DenseNets 上的高密度连接,可视化变得比 VGG 和雷斯内特更复杂一些。图 3 显示了 DenseNet-121 架构的一个非常简单的方案,这将是我们在这项工作中重点关注的 DenseNet。这是因为它是在 ImageNet 数据集上设计的最简单的 DenseNet。

我们可以在 DenseNet-121 上比较图 3 和图 2。每个体积下的尺寸代表宽度和深度的大小,而顶部的数字代表特征地图的尺寸。我介绍了它们是如何派生出来的,以帮助我们更好地理解即将到来的步骤。

Figure 3. Another look at Dense-121. Dx: Dense Block x. Tx: Transition Block x.

您可能想知道整个 DenseNet 的旁路连接在哪里,您问对了!然而,我只是想先画一个最简单的方案,以便更深入地了解 DenseNet 的整个结构。但是出于好奇,您可以注意到计算每个新卷的特征映射的加法的第一个数字是如何与前一卷的特征映射维度相匹配的。这将解释旁路连接,因为它确切地意味着我们正在将串联(串联意味着添加维度,但不是添加值!)新信息到上一卷,也就是被重用的

请注意, 32 正是我们在本节开始时提到的增长率。那么,从上图我们能得到什么呢?

—每个密集块之后的体积增加了增长率乘以该密集块内的密集层数

在图 4 中,我们现在更深入地了解了每个块中实际发生的事情。

Figure 4. One level deeper look at DenseNet-121. Dense Block and Transition Block. DLx: Dense Layer x

致密层

现在,我们可以理解上面的说法了。每一层都在前一卷的基础上增加了 32 张新的特征地图。这就是我们在 6 层之后从 64 到 256 的原因。此外,过渡块执行 128 个滤波器的 1x1 卷积。随后是步长为 2 的 2×2 池,导致将体积的大小和特征图的数量对半分割。我们可以从这种模式观察中得出新的结论。

—致密块内的体积保持不变—

—在每个过渡块之后,体积和特征图减半—

不过,我们还可以再深入一层!我们需要了解每个密集块中的每个密集层内部发生了什么,因为这还不是小事。让我们一起去看全图吧!

Figure 5. 2 level deep. Full schematic representation of ResNet-121

在表示第一个密集块中的第一个密集层的新的更深层次中,我们可以看到添加 32 倍层数的行为实际上是如何实现的。我们执行作者建议的 128 个滤波器的 1×1 卷积,以减小*特征图的大小,并执行更昂贵的 3×3 卷积(记得包括填充以确保尺寸保持不变),具有选择的 32 个增长率特征图。

然后,在向网络的公共知识添加新信息的动作中,输入量和两个操作的结果(对于每个密集块内的每个密集层是相同的)被连接。

引用的作品

1 G .黄,z .刘,l .范德马腾,“密集连接卷积网络”,2018 .

2 R. Kumar,K. Gredd 和 J. Schmidhuber,“高速公路网络”,2015 年。

3何国光,张,任,孙健,“深度残差学习在图像识别中的应用”,2015 .

[4] G. Larsson,M. Maire 和 G. Shakhnarovich,“FractalNet:无残差的超深度神经网络”,2017 年。

理解和可视化资源

原文:https://towardsdatascience.com/understanding-and-visualizing-resnets-442284831be8?source=collection_archive---------1-----------------------

这篇文章可以在 PDF 这里下载。

这是关于 CNN 架构的系列教程的一部分。

主要目的是深入了解 ResNet,并深入研究 ResNet34 for ImageNet 数据集。

  • 对于应用于 CIFAR10 的 ResNets,这里还有另外一个教程。
  • 还有 PyTorch 实现详细教程这里。

索引

  • 背景
  • 动机
  • ResNets 解决什么问题?
  • 体系结构
  • 摘要

背景

研究人员观察到,当涉及到卷积神经网络时,肯定“*越深越好”*是有意义的。这是有意义的,因为模型应该更有能力(它们适应任何空间增加的灵活性,因为它们有更大的参数空间来探索)。然而,已经注意到,在一定深度之后,性能会下降。

这是 VGG 的瓶颈之一。他们不能达到预期的深度,因为他们开始失去归纳能力。

动机

由于神经网络是良好的函数逼近器,它们应该能够容易地求解识别函数,其中函数的输出成为输入本身。

按照同样的逻辑,如果我们绕过模型第一层的输入,作为模型最后一层的输出,网络应该能够预测它之前学习的函数和添加的输入。

直觉告诉我们,学习 f(x) = 0 对网络来说一定很容易。

ResNets 解决什么问题?

ResNets 解决的问题之一就是著名的已知 消失渐变 。这是因为当网络太深时,在链规则的几次应用之后,计算损失函数的梯度容易收缩到零。这导致权重永远不会更新其值,因此没有学习被执行。

有了 ResNets,渐变可以直接通过跳过连接从后面的层向后流到初始过滤器

体系结构

Figure 1. ResNet 34 from original paper 1

由于 ResNet 可以具有可变的大小,这取决于模型的每一层有多大,以及它有多少层,我们将遵循作者在论文1 — ResNet 34 中描述的,以便解释这些网络之后的结构。

如果你看了一下这篇论文,你可能会看到一些如下的图表,你很难理解。让我们通过研究每一步的细节来描绘这些数字。

在这里,我们可以看到 ResNet(右边的那个)由一个卷积和合并步骤(在 orange 上)组成,后面是 4 层类似的行为。

每一层都遵循相同的模式。它们分别与固定的特征映射维度(F) [64,128,256,512]执行 3×3 卷积,每两次卷积绕过输入。此外,宽度(W)和高度(H)尺寸在整个层中保持不变。

虚线在那里,正是因为输入体积的维度发生了变化(当然是因为卷积而减少)。注意,层与层之间的这种减少是通过在每层的第一个回旋处将步幅从 1 增加到 2 来实现的;而不是像我们习惯看到的下采样器那样通过汇集操作。

在该表中,总结了每一层的输出大小以及该结构中每一点的卷积核的维数。

Figure 2. Sizes of outputs and convolutional kernels for ResNet 34

但这是不可见的。我们想要图像!一张图片胜过千言万语!

图 3 是我更喜欢看到卷积模型的方式,从这里我将解释每一层。

我更喜欢观察通过模型的体积是如何改变它们的大小的。这种方式更容易理解特定模型的机制,能够根据我们的特定需求进行调整——我们将看到仅仅改变数据集如何迫使改变整个模型的架构。此外,我将尝试遵循接近于 PyTorch 官方实现的符号,以便稍后在 PyTorch 上实现它时更容易。

例如,论文中的 ResNet 主要针对 ImageNet 数据集进行解释。但是我第一次想用 ResNets 的集合做实验时,我不得不在 CIFAR10 上做。显然,由于 CIFAR10 输入图像是(32x32)而不是(224x224),因此需要修改 ResNets 的结构。如果您想控制应用到您的 ResNet 的修改,您需要了解细节。这另一个教程是当前应用于 CIFAR10 的一个简化版。

所以,我们一层一层来!

Figure 3. Another look at ResNet 34

卷积 1

在进入公共层行为之前,ResNet 上的第一步是一个块(此处称为 Conv1 ),由卷积+批处理规范化+最大池操作组成。

如果你不记得卷积和池操作是如何执行的,快速看一下我画的这个图来解释它们,因为我在这里重用了它们的一部分。

首先有一个卷积运算。在图 1 中,我们可以看到他们使用的内核大小为 7,特征映射大小为 64。您需要推断它们在每个维度上用零填充了 3 次——并在 PyTorch 文档中进行检查。考虑到这一点,从图 4 中可以看出,该操作的输出大小将是一个(112x122)卷。由于(64 个中的)每个卷积滤波器在输出音量中提供一个通道,因此我们最终得到(112x112x64)的输出音量——注意,为了简化说明,这不包括批次维度。

Figure 4. Conv1 — Convolution

下一步是批处理规范化,这是一个基于元素的操作,因此不会改变卷的大小。最后,我们有一个跨度为 2 的(3x3)最大池操作。我们还可以推断,他们首先填充输入体积,因此最终体积具有所需的尺寸。

Figure 5. Conv1 — Max Pooling

ResNet 层

所以,我们来解释一下这个重复的名字,block。一个 ResNet 的每一层都由几个块组成。这是因为当 ResNets 更深入时,它们通常通过增加块内的操作数量来实现,但总层数保持不变,即 4 层。 这里的运算是指对一个输入进行卷积、批量归一化和 ReLU 激活,除了最后一个没有 ReLU 的块的运算。

因此,在 PyTorch 实现中,他们区分包含 2 个操作的块基本块和包含 3 个操作的块瓶颈块。注意,通常这些操作中的每一个都被称为层,但是我们已经为一组块使用了层。

我们现在面临一个基本问题。输入音量是 Conv1 的最后一个输出音量。让我们看看图 6,看看这个模块内部发生了什么。

第一区

1 卷积

我们正在复制纸上每一层的简化操作。

Figure 6. Layer 1, block 1, operation 1

我们现在可以仔细检查我们使用的[3x3,64]内核和输出大小为[56x56]的论文中的表格。我们可以看到,正如我们前面提到的,在一个数据块中,卷的大小是如何保持不变的。这是因为使用了填充= 1,并且跨距也是 1。让我们看看这如何扩展到整个块,以覆盖表中出现的 2 [3x3,64]。

Figure 7. Layer 1, block 1

相同的过程可以扩展到整个层,如图 8 所示。现在, 我们可以完整的读取 表格的整个单元格了(只是重述一下我们在 Conv2_x 层的 34 层 ResNet 中。

我们可以看到如何在层 中使用***【3x 3,64】x 3 次。***

Figure 8. Layer 1

模式

下一步是从整个块升级到整个层。在图 1 中,我们可以看到这些层是如何通过颜色区分的。但是,如果我们观察每一层的第一个操作,我们会发现第一层使用的步幅是 2,而不是其他层使用的 1。

这意味着通过网络的音量的 下采样是通过增加步幅来实现的,而不是像通常的 CNN 那样的汇集操作 。事实上,在我们的 Conv1 层中只执行了一次最大池化操作,在 ResNet 的末尾,就在图 1 中完全连接的密集层之前,执行了一次平均池化操作。

我们还可以看到 ResNet 层上的另一个重复图案,点层代表维度的变化。这和我们刚才说的一致。每一层的第一个操作是减少维度,因此我们还需要调整通过跳过连接的卷的大小,这样我们就可以像图 7 中那样添加它们。

这种跳过连接上的差异在文中被称为 恒等式快捷方式投影快捷方式 。恒等快捷方式是我们已经讨论过的,简单地绕过加法运算符的输入量。投影快捷方式执行卷积运算,以确保此加法运算中的体积大小相同。从纸上我们可以看到 匹配 输出尺寸有两种选择。或者 填充输入音量 或者执行 1x1 卷积 。这里显示了第二个选项。

Figure 9. Layer2, Block 1, operation 1

图 9 显示了通过将跨距增加到 2 来执行的下采样。滤波器的数量被加倍,以试图保持每个操作的时间复杂度( 5664 = 28128 )。另外,请注意,由于卷被修改,现在无法执行添加操作。在捷径中,我们需要应用一种下采样策略。1x1 卷积方法如图 10 所示。

Figure 10. Projection Shortcut

最终的图片如图 11 所示,其中每个线程的 2 个输出卷大小相同,可以相加。

Figure 11. Layer 2, Block 1

在图 12 中,我们可以看到整个第二层的全局情况。下面的第 3 层和第 4 层的行为完全相同,只是改变了引入体积的尺寸。

Figure 12.Layer 2

摘要

遵循作者建立的解释规则的结果产生了如图 2 所示的以下结构:

Table 1. ResNets architectures for ImageNet

文献学

1何国光,张,任,孙,“深度残差学习在图像识别中的应用”,,2016。

理解和可视化 SE-net

原文:https://towardsdatascience.com/understanding-and-visualizing-se-nets-1544aff0fc68?source=collection_archive---------8-----------------------

这篇文章可以在 PDF 这里下载。

这是 CNN 架构系列文章的一部分。

主要目的是提供理解 SE-Nets 的洞察力。

指数

(1)有哪些创新点?

  • 新数据块与新网络
  • 解决什么问题?
  • 什么是 SE 块?

(2)结构

  • 转换
  • 挤压
  • 激发,兴奋
  • 缩放比例

(3)SE 模块的应用

(4)结果和结论

(5)全球图景

有哪些创新?

新块而不是新网络

首先,本文作者并没有试图通过开发一种新颖的 CNN 架构来提高经典计算机视觉竞赛的艺术水平。然而,非常有趣的是,作者创建了一个可以与现有模型一起使用的模块来增强它们的性能

这个新的模块在完成两个主要操作后被命名为 SE 模块:挤压和激励

动机——这些积木解决了什么问题?

作者声称卷积的输出导致与滤波器捕获的空间相关性纠缠的信道依赖性。哇,这听起来太疯狂了!但是不要担心,在一些想象之后,这变得非常简单。

那么作者想用这些积木做什么来解决这个问题呢?

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

他们的目标是通过利用选通网络对通道相互依赖性进行显式建模来提高网络的灵敏度,选通网络出现在 se 模块中

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

那么什么是 SE 块呢?

简而言之,SE 模块是通道关系中的轻量级门控机制。

简而言之,网络现在能够学习如何理解在卷积运算【1】之后提取的所有特征图的堆栈中的每个特征图的重要性,并且在将卷传递到下一层之前重新校准该输出以反映该重要性。

所有这些都将在结构部分详细介绍,所以如果您现在没有看到某些内容,也不必担心!

但是等一下,为了学习,我们需要更多的参数,对吗?

没错。门控机制或门控网络只不过是完全连接的层。这种技术在注意机制中被大量使用。我强烈推荐这篇文章来更好地理解注意力机制和门控网络。

结构

让我们首先来看看图 1 中的图。我们可以称这个图为简化图,因为我们总是想要更多的细节!

Figure 1. The SE Block from the paper.

它显示了所提供的插图,我在上面分离了它的三个主要部分。重要的是要看到,挤压和激励步骤只发生在中间模块,而第一个和最后一个模块执行不同的操作。

在一次展示详细的图片之前,让我们一部分一部分地阐述它。

1 —转换

该转换简单地对应于将要实现 SE 模块的网络在其自然方案中执行的操作。例如,如果你在一个 ResNet 内的一个块中, F tr 项将对应于整个残差块的处理(卷积、批量归一化、ReLU…)。因此:

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

SE 块应用于变换操作的输出体,通过校准提取的特征来丰富它。

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

因此,如果 ResNet 在某个点将输出卷 X,则 SE 块丰富它包含的信息,并传递到下一层,成为 X`。(不能包含上面带~的 X)。

为了简化可视化,让我们假设变换是一个简单的卷积运算。我们已经在之前的文章中描述了卷积运算,但是,让我们试着稍微详细一点,以便更好地理解接下来会发生什么。

我之所以声称这第一步很重要,是因为作者构建 se 块的动机就在于此。

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

对于常规卷积层,是一组滤波器**被学习来表达沿着输入通道的局部空间连通性模式* X 因此卷积滤波器是局部感受域 内的 通道方式信息的组合。*

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

如果我们看一下对应于图 2 的符号,我们有:

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

他们所说的 局部感受野 恰恰是每个通道 2 的空间Vc,s 在每个过滤器c .

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

为什么信息是渠道方面的?

嗯,请注意滤波器 V 1 的标记 V 1,s 将仅在输入音量 X s 的通道 s 上卷积。

Figure 2. Step1: Transformation

我们也可以按通道来表示卷积运算,以进行双重检查:

在体积 X 中卷积 1 个单个滤波器 Vc 的结果在单个特征图上, U c:

换句话说,一个滤波器在体积 X 上的卷积是输入体积 X s 的每个通道与其在滤波器 V c,s 中的对应通道的所有通道卷积的总和

2 —挤压

挤压步骤可能是最简单的一步。它基本上在每个通道上执行平均汇集,以创建一个 1x1 压缩的卷 U 表示。****

Figure 3. Squeezing

3 —激发

这是 SE 模块整个成功的关键部分,所以请注意。这确实是一个文字游戏,我们将使用一个使用门控网络的注意力机制: )

作者引入了一个称为缩减比** r 的新参数,在 sigmoid 激活的选通网络之前,引入第一个具有 ReLU 激活的全连接(FC)层。**

这样做的原因是引入一个瓶颈,它允许我们在引入新的非线性的同时降低维度。

此外,我们可以更好地控制模型的复杂性和辅助网络的泛化性能。

具有两个 FC 层将导致具有两个权重矩阵,这两个权重矩阵将由网络在训练期间以端到端的方式学习(所有权重矩阵都与卷积核一起反向传播)。

该函数的数学表达式得出:

我们已经让我们的压缩特征地图兴奋了!

看看这些激励只不过是一对经过训练的神经网络,以便在训练过程中更好地校准这些激励。

3.规模

最后一步,缩放,确实是重新缩放操作。我们将赋予压缩矢量其原始形状,保持在激发步骤中获得的信息。

Figure 5. Rescaling

在数学上,缩放是通过输入体积上的每个通道与激活的 1x1 压缩向量上的相应通道的简单标量积来实现的。

对于 1 个频道:

作者讨论:

激活充当适应于输入特定描述符 z 的通道权重。

硒块的应用

如作为创新之一介绍的,SE 块不是新的神经网络架构。它试图通过使现有模型对渠道关系更加敏感来改进现有模型。

Figure 6. SE block applied to Inception (left) and ResNets (right) modules

图 6 显示了如何在卷积层的输出音量之后应用相同的 SE 块,以在将其移动到下一层之前丰富其表示。在这种情况下,显示了 Inception 和 ResNets 模块。

结果和结论

结果证实,在最先进的网络中引入 SE 块提高了它们在不同计算机视觉应用中的性能:图像网络分类、场景分类(Places365-Challenge 数据集)和对象检测(COCO 数据集)。这些结果太宽泛了,不包括在这个总结中,我建议在原始论文中查看它们。

****折减系数的经验研究值带来了一个有趣的观察结果。事实证明,16 是一个很好的值,超过这个值,性能不会随着模型容量的增加而单调地提高。

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

SE 块可能会过度拟合通道相关性

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

最后,作者在每个阶段(或层)对 50 个均匀采样的通道执行平均激活,其中为 5 个显著不同的类别引入了 SE 块。已经观察到,跨不同类别的分布在较低层中几乎相同,而每个通道的值在更大深度处变得更加类别特定。****

全球图片

将所有东西放回一起,SE 块: )

理解并使用 R 编写您的第一个文本挖掘脚本

原文:https://towardsdatascience.com/understanding-and-writing-your-first-text-mining-script-with-r-c74a7efbe30f?source=collection_archive---------3-----------------------

介绍

数据科学变得流行的原因之一是因为它能够在瞬间或仅仅一个查询中揭示大量数据集的信息。

仔细想想,每天我们以文本的形式给出了多少信息?所有这些信息包含了我们的情感、我们的观点、我们的计划、建议、我们最喜欢的短语等等。

然而,揭示其中的每一个看起来就像是大海捞针,直到我们使用像文本挖掘/分析这样的技术。

文本挖掘考虑了信息检索、词频分析和研究以及模式识别,以帮助可视化和预测分析。

在本文中,我们将经历数据集为进一步分析做准备的主要步骤。我们将使用 R 编写脚本,代码将在 R studio 中编写。

为了实现我们的目标,我们将使用一个名为“tm”的 R 包。这个软件包支持所有的文本挖掘功能,如加载数据,清理数据和建立一个术语矩阵。它在 CRAN 上有售。

让我们首先在我们的工作空间中安装并加载这个包。

#downloading and installing the package from CRAN
install.packages("tm")#loading tm
library(tm)

加载数据

要挖掘的文本可以从不同的源格式加载到 R 中。它可以来自文本文件(。txt)、pdf(。pdf)、csv 文件(。csv) e.t.c,但不管源格式如何,要在 tm 包中使用它,就要把它变成一个“语料库”。

语料库被定义为“书面文本的集合,尤其是特定作者的全部作品或关于特定主题的写作主体”。

tm 包使用 Corpus()函数创建一个语料库。

#loading a text file from local computer
newdata<- readlines(filepath)#Load data as corpus
#VectorSource() creates character vectorsmydata <- Corpus(VectorSource(newdata))

参考本指南了解更多关于导入文件到 r。

正在清理数据。

一旦我们成功地将数据加载到工作空间中,就该清理这些数据了。我们在这一步的目标是从数据文件中创建独立的术语(单词),然后才能开始计算它们出现的频率。

因为 R 是区分大小写的,我们应该首先将整个文本转换成小写,以避免认为相同的单词“write”和“Write”不同。

我们将删除:网址,表情符号,非英语单词,标点符号,数字,空白和停用词。

停用词:tm 包中常用的英文单词如“a”、“is”、“The”都称为停用词。为了使结果更准确,必须去掉这些词。也可以创建自己的自定义停用词。

# convert to lower case
mydata <- tm_map(mydata, content_transformer(tolower))#remove ������ what would be emojis
mydata<-tm_map(mydata, content_transformer(gsub), pattern="\\W",replace=" ")# remove URLs
removeURL <- function(x) gsub("http[^[:space:]]*", "", x)
mydata <- tm_map(mydata, content_transformer(removeURL)
)
# remove anything other than English letters or space
removeNumPunct <- function(x) gsub("[^[:alpha:][:space:]]*", "", x)
mydata <- tm_map(mydata, content_transformer(removeNumPunct))# remove stopwords
mydata <- tm_map(mydata, removeWords, stopwords("english"))#u can create custom stop words using the code below.
#myStopwords <- c(setdiff(stopwords('english'), c("r", "big")),"use", "see", "used", "via", "amp")
#mydata <- tm_map(mydata, removeWords, myStopwords)# remove extra whitespace
mydata <- tm_map(mydata, stripWhitespace)# Remove numbers
mydata <- tm_map(mydata, removeNumbers)# Remove punctuations
mydata <- tm_map(mydata, removePunctuation)

词干

词干提取是将相似来源的单词聚集成一个单词的过程,例如“通信”、“交流”、“沟通”。词干分析通过删除后缀和将单词简化为基本形式来帮助我们提高挖掘文本的准确性。我们将使用雪球图书馆。

library(SnowballC)mydata <- tm_map(mydata, stemDocument)

构建术语矩阵并揭示词频

在清理过程之后,我们剩下的是存在于整个文档中的独立术语。这些都存储在一个矩阵中,显示它们的每一次出现。这个矩阵记录了术语在我们的干净数据集中出现的次数,因此被称为术语矩阵

#create a term matrix and store it as dtm
dtm <- TermDocumentMatrix(mydata)

词频:词在数据集中出现的次数。使用术语矩阵中出现的汇编,词频将向我们指示从数据集中最频繁使用的词到最少使用的词。

结论

我们刚刚写了一个基本的文本挖掘脚本,然而这只是文本挖掘的开始。获取原始格式的文本并将其清理到这一点的能力将为我们提供方向,如构建单词云、情感分析构建模型。

保留这个脚本,因为当我们开始进行情感分析时,它会派上用场。

有任何问题都可以联系我> @lornamariak 。

使用 Valenbisi(瓦伦西亚自行车共享系统)了解 ARIMA 车型

原文:https://towardsdatascience.com/understanding-arima-models-using-valenbisi-valencias-bike-share-system-dcbe13b3e8a?source=collection_archive---------8-----------------------

我杰出的同事 Nicole Eickhoff 和我一起去西班牙,我们希望在那里见到数据科学家。因为我们会在那里参加 Fallas,一个为期一个月的社区和传统庆祝活动,我们收集了 Valenbisi 在 Crida Fallas 前一周的数据。Crida Fallas 是为期一个月的活动的第一天。我们想看看瀑布如何影响自行车共享活动。在这里,我详细介绍了我们在 2018 年 3 月 13 日星期二与巴伦西亚大数据会议上介绍和讨论的项目。

As part of the celebration of Fallas, each neighborhood in Valencia creates fantastic street light displays.

在这篇博客中,我简要描述了我使用刮刀收集数据、进行 ARIMA 分析、仔细考虑结果以及提出构建模型的后续步骤的过程,该模型可以预测瓦伦西亚每个 Valenbisi 站的自行车和码头可用性。关于这些的更深入的报道,请继续关注这个博客和我的 Github 上的 Jupyter 笔记本中提供的链接。

收集数据

Nicole 于 2018 年 2 月 16 日请求 Valenbisi 的 API 密钥访问。在发现 API 只提供两年前的数据后,她向我寻求建议。鉴于网站提供了一个实时下载的 CSV 文件,而且当时它的使用条款中也没有禁止抓取,我知道我们可以制作一个抓取器并尝试一下。除了 python 库‘requests’之外,我只用了很少的东西就能构建一个 scraper,并在去西班牙之前的 10 天里,在一个 AWS web 实例上托管它。

这里有一个链接指向我的 Github 托管的 Jupyter 笔记本,在那里我浏览了我在 AWS 上托管的 scraper 的主干。

我每 15 分钟收集实时数据 1001 次。csv 包括“自行车可用”、“加油站空闲”、“总计、 XY 的信息。

这是 10 天多一点的数据。这使得我们无法观察一年中的季节,而只能观察一周中的季节。由于我们的数据如此之少,这将是一个大规模的例子,可能会更直观地解释。我们将能够关注每周和每小时的趋势。

我们的数据不包括关于哪个活动是重新平衡工作的信息。

我们的数据不包括具体的乘坐数据,这使得这些数据不适合网络分析。

x 和 Y 是 UTF 坐标,可以使用 UTM 图书馆转换成经度和纬度坐标。西班牙的国家代码是“30”和“S”,如下例所示。

[Input]: **import** **utm** utm.to_latlon(725755.944, 4372972.613, 30, 'S')[Output]:
(39.47674728414135, -0.37534073558984327)

并且使用散景,我能够绘制出每个 Valenbisi 站(蓝色)和为第一天安排的主要活动的每个位置(红色),开始为期一个月的活动:Crida Fallas。2018 年 2 月 25 日。

#Plaza Ayuntamiento @39.4697661,-0.4113992
#圣胡安德尔医院教堂@39.4743981,-0.3814647
#托雷斯·德洛斯·塞拉诺斯@39.4791963,-0.378187

探索性数据分析

首先,我们预计 Crida Fallas 周围的整个系统会出现“尖峰”或一些不规则行为。以下所有车站所有可用自行车的图表显示,还有其他冲击发生,不一定与坠落有关。竖线表示 Crida Fallas,2018 年 2 月 25 日。

We presented to Valencia’s Big Data Meetup. Suggestions for such frequent and unrelated-to-commute-times plummets were system power outages. For this analysis, I retained all datapoints.

接下来,我绘制了三个单独的 Valenbisi 站。也许靠近 Crida Fallas 活动与车站受到的影响有关。首先,我们来看看位于 Crida 活动地点附近或地图上红点附近的车站是什么样的。

Wow, we see a big spike for Crida Fallas, and another later in the week! This station is, as we expected, very close to the city center, the Ayuntamiento. Over all, apparent return to normal behavior after Crida Fallas seems to happen pretty quickly.

对位于市中心附近的车站 Ayuntamiento 的视觉观察。

  1. Crida Fallas 期间可用自行车的大高峰
  2. 本周晚些时候又一次飙升
  3. 总的来说,在 Crida Fallas 之后,相对较快地恢复到“正常”行为

现在,以下车站更靠近巴伦西亚的城市边界。

I see very little recognizable pattern here. Whatever occurred on February 25th looks as if it could have occured any day for this station.

对位于城市西南边界的车站的视觉观察:

  1. 这里几乎没有可辨认的图案。
  2. 无论这个站在 2 月 25 日表现出什么样的行为,看起来都像是发生在其他任何一天。

位于城市边缘附近的一个站的视觉观察。

  1. 没有查一下这个车站附近有什么(也许是医院?),很明显这里的自行车是用来通勤的。
  2. 我们看到,Crida 不仅在当天影响该站,而且在行为恢复“正常”的前一天和后两天也影响该站。

我们看到,无论我们提出什么样的解决方案,都需要适用于具有多种不同行为的电视台。出于我们的目的,让我们对所有数据进行 ARIMA 分析。我选择首先查看所有数据来开始分析,因为它在 Crida Fallas 附近没有表现出不稳定的行为,并且将是 ARIMA 建模的一个很好的学习示例。 ARIMA 模型依赖于这样一种假设,即自行车站点最近所处的州会影响未来可用自行车/码头的数量。此外,ARIMA 模型可以捕捉我们的时间序列数据中的季节关系。

ARIMA 分析

  1. 将时间序列分解为趋势、季节性和残差
  2. 平稳性检验(迪基-富勒检验)
  3. 创建 ARIMA 模型
  4. 结果解释

1.分解

视觉观察:

  1. 在 10 天的过程中,我们看到了一个略微向上的趋势。这种上升趋势仅涉及 100 辆自行车。
  2. 在季节分解中,我们观察到重复。试图解释每个裂缝是徒劳的,但这个特征中的重复模式表明了一种日常行为模式。(我们有 10 天,可以数 10 次重复。)
  3. 我们的残差图显示,正如预期的那样:6 次暴跌中只有 5 次出现了重大暴跌,这 6 次暴跌被巴伦西亚 Meetup 观众认为是“可能的断电”。

2.我们的数据是静态的吗?——扩展的迪基-富勒测试

首先,我测试我们的数据是平稳的。重要的是,你的时间序列在预测之前是平稳的,否则你的模型将是一个糟糕的预测器,因为 ARIMA 依赖于平稳性的假设。

An example of non-stationary data, stationized. Provided by https://www.itl.nist.gov/div898/handbook/pmc/section4/pmc442.htm

这可以是它自己的博客帖子,非常有趣。更定量的解释,我推荐这个来源。

出于我们谈话的目的,重要的是要知道,在进行 Dickey-Fuller 检验时,我们是在进行假设检验:

H0:数据是非平稳的

H1:数据是静止的

我使用下面的代码对数据执行 Dickey-Fuller 测试。它是作为我的数据科学训练营的学习练习提供的:

输出:

Our p-value is definitely below .05, meaning we can reject the null hypothesis; our data is stationary!

我们将stats models . TSA . stat tools . ad fuller用于以下输入:

  • maxlag : None (因为我们指定 autolag =‘AIC’,所以在我们的例子中不会用到它。)
  • 回归:‘c’:仅常量(默认)
  • 自动标记:‘AIC’:如果‘AIC’(默认)或‘BIC’,那么选择标记的数量以最小化相应的信息标准。这将选择具有最佳 AIC 分数的模型。

更多关于 AIC 和 BIC 的信息:

AIC 是一个常数加上数据的未知真实似然函数和模型的拟合似然函数之间的相对距离的估计值,因此 AIC 越小,模型越接近真实值。

BIC 是在特定的贝叶斯设置下,对模型为真的后验概率的函数的估计,因此较低的 BIC 意味着模型被认为更有可能是真实的模型。

……尽管存在各种微妙的理论差异,但它们在实践中的唯一区别是处罚的大小;BIC 对模型复杂性的惩罚更重。他们应该不同意的唯一方式是当 AIC 选择一个比 BIC 更大的模型

我们的 Dickey-Fuller 检验的 p 值肯定低于 0.05,这意味着我们可以拒绝零假设。我们的数据是稳定的,因此可以插入 ARIMA 模型。

3.ARIMA 模型

现在开始在这个博客中,你会发现与我们瓦伦西亚大数据会议演示的原始对话有偏差。我希望这篇博客能推动关于方法论的进一步讨论,以及我在 ARIMA 模型和我的数据中遇到的一些不确定性。我对如何提高我的理解和我的模型的谈话和对话持开放态度。

我发现 ARIMA 模型相当不确定,原因如下:

  • 在我们的 statsmodels SARIMAX 模型中使用的发现季节性指标的经验方法( ACF/PACF 图)并没有产生一个有效的模型。(详见 github。)
  • (在我运行的多个模型中)预测最好的模型是一个几乎没有统计显著滞后变量的模型。

这是我看到的最适合预测的模型的代码。你可以在我的 Github 上找到(几乎)我所有的其他模型。

mod = sm.tsa.statespace.SARIMAX(df[0:960].available, 
                                trend='n', 
                                order=(1,0,1), 
                                seasonal_order=(4,0,7,24), 
                                enforce_stationarity =False, 
                                enforce_invertibility = False)results = mod.fit()
results.summary()

Wow, why does a model with nearly no significant lags produce the best predictions? Perhaps it’s not so bad. Discussion below.

With no other independent variables besides its own behavior, our ARIMA model can predict pretty well, I’d say.

提醒一下:我们只有 10 天的数据,每小时 4 个点的数据。这使得我们无法测试年度季节性关系。出于我们的目的,我打算说一个赛季持续 6 个小时。这意味着每天有四个季节。这应该包括高峰时间、中午和晚上。最直观的是,这使得数据点/季节变量的数量 m = 4*6 = 24。

选择我的(pdq)(PDQ)m 价值观的动机:

非季节性的,对模型当前状态最有影响的滞后是在它之前的滞后期间发生的。p =1,q = 1,(以及 d = 0,因为我们的数据是平稳的)。

p,季节性 AR 订单。我怀疑日期之间有季节性,所以我想看看前一天发生了什么。(24 个数据点的 4 个滞后)

d,季节性差异为 0,因为我们的数据是稳定的。

q,季节移动平均订单。现在我承认,乍一看这似乎是最不直观的。我通过反复试验发现了它,但是如果我们考虑 7 个 24 点的滞后,意味着 42 小时之前,它似乎是可预测性最好的;不到两整天。如果你把一周看成 168 个小时,这些数字会清晰地分开:168/42 = 4。这表明一周有 4 个不同的行为时间。我们希望我们的模型相应地使用 1/4 周作为它的移动平均窗口。

请随意参考我的 github 查看(几乎)我尝试过的所有机型,并在评论中留下任何对机型参数改进的建议。

4.结果解释:

首先,我要承认,虽然存在极少数具有统计显著性的滞后,但移除一个因其 p>|z|值而被认为在统计上无关紧要的变量会对模型的预测能力产生不利影响。 ARIMA(1,0,0)(4,0,7,24),绿色=预测,蓝色=实际。

An example of what happens when you remove the ma.L1 with p>|z| value .993. ARIMA(1,0,0)(4,0,7,24).

ARIMA(1,0,1)(4,0,7,24)模型确实有整体最低的 AIC 和 BIC 分数*。这些指标不是对模型质量的评分,而是提供了与其他模型进行比较的手段;越低越好。

其次,我想深入了解 Statespace 模型结果提供的一些其他结果:

进行 Ljung-Box (Q) 测试以确认残差是独立的。这意味着我们的误差彼此不相关,我们已经成功地用我们的模型解释了数据中的模式。

我们对 Ljung-Box 进行的假设检验如下:

H0: 数据是独立分布的(即样本总体的相关性为 0,因此数据中任何观察到的相关性都是由抽样过程的随机性造成的)。

H1: 数据不是独立分布的;它们表现出序列相关性。

Ljung-Box(Q)给出的测试统计量遵循 X 分布,具有( h-p-q) 个自由度,其中 h 为测试滞后的数量。

如果 p 值(Prob(Q)) 大于 0.05,那么我们不能拒绝零假设;残差是独立的,这表明模型为数据提供了足够的拟合。我们看到我们的问题(Q)是. 62。太好了。因此,尽管没有很多统计上显著的滞后变量,我们的模型已经设法解释了足够多的方差,即残差是随机的。

**异方差:**线性回归的一个假设是残差不存在异方差。这意味着残差的方差不应随着响应变量的拟合值而增加;我们更喜欢我们的残差是同伦的。

H0: 残差的方差是常数;没有异性。

H1: 异方差存在。

这里我们不能在 95%的置信水平上拒绝零假设,因为我们的 p 值是 0.07。我们可以假设残差中的同质性。好吧,还不错。我们的模型设法通过的另一个测试。

Jarque-Bera 和峰度度量是关于正态性的。我们的数据不是正态分布的,所以现在我将跳过这些度量。

可能的后续步骤

  1. 扩大规模,这意味着收集更长时间的数据,并将模型应用于各个站点。考虑一个递归神经网络来模拟时间序列排序。
  2. 考虑一个泊松点过程模型来预测可用自行车和码头开放,使用建立时间优先级。shift() 像这样的 DSSG 项目做了。
  3. 请求关于再平衡工作的数据。
  4. 考虑主要城市活动的特征工程附加变量以及与特定活动的距离。
  5. 考虑对受影响的自行车站进行冲击建模。

#数据假期

这是我和妮可为我们的西班牙之行准备的两个演示文稿之一。它被分享给了巴伦西亚数据科学会议。

我们的另一项工作是在巴伦西亚大学商学院的本科生市场营销课上进行的 CRM 数据研讨会。请关注妮可即将发表的关于此事的博客。

数据源:

http://www . Valencia . es/ayuntamiento/datosabiertos . NSF/resultadoCapas/95d 6756 f 6861 f 9 FDC 1257 c 70003 e 4 FBD?open document&lang = 1&nivel = 2&seccion = 1&BD Origen =&idapoyo = 22 ADF 97 C1 FD 223 b5 c 1257 c 55003 BD 01 f

Github 资源库:

[## nmolivo/巴伦西亚-数据-项目

巴伦西亚-数据-项目-数据炸弹

github.com](https://github.com/nmolivo/valencia-data-projects/tree/master/valenbisi)

附加资源:
https://www . data camp . com/courses/introduction-to-time-series-analysis-in-python

理解 AUC - ROC 曲线

原文:https://towardsdatascience.com/understanding-auc-roc-curve-68b2303cc9c5?source=collection_archive---------0-----------------------

Understanding AUC - ROC Curve [Image 1] (Image courtesy: My Photoshopped Collection)

在机器学习中,性能测量是一项基本任务。所以当涉及到分类问题时,我们可以依靠 AUC - ROC 曲线。当我们需要检查或可视化多类分类问题的性能时,我们使用 AUC ( 曲线下的面积 ) ROC ( 接收器操作特性)曲线。它是检验任何分类模型性能的最重要的评价指标之一。也可以写成 AUROC(接收器工作特性下的区域)

注:为了更好的理解,我建议你看一下我写的关于混淆矩阵的文章。

本博客旨在回答以下问题:

1.什么是 AUC - ROC 曲线?

2.定义 AUC 和 ROC 曲线中使用的术语。

3.如何推测模型的性能?

4.敏感性、特异性、FPR 和阈值之间的关系。

5.多类模型如何使用 AUC - ROC 曲线?

什么是 AUC - ROC 曲线?

AUC - ROC 曲线是在各种阈值设置下对分类问题的性能测量。ROC 是概率曲线,AUC 代表可分性的程度或度量。它告诉我们这个模型在多大程度上能够区分不同的类。AUC 越高,模型预测 0 类为 0 和 1 类为 1 的能力越强。以此类推,AUC 越高,模型在区分患病和未患病患者方面就越好。

用 TPR 对 FPR 绘制 ROC 曲线,其中 TPR 在 y 轴上,FPR 在 x 轴上。

AUC - ROC Curve [Image 2] (Image courtesy: My Photoshopped Collection)

定义 AUC 和 ROC 曲线中使用的术语。

TPR(真阳性率)/召回/灵敏度

Image 3

特异性

Image 4

定期用量法(Fixed Period Requirements)

Image 5

如何推测车型的性能?

一个优秀的模型具有接近 1 的 AUC,这意味着它具有良好的可分性度量。差模型的 AUC 接近 0,这意味着它具有最差的可分性度量。事实上,这意味着它在往复结果。它预测 0 是 1,1 是 0。当 AUC 为 0.5 时,这意味着该模型没有任何类别分离能力。

我们来解读一下上面的说法。

我们知道,ROC 是一条概率曲线。让我们画出这些概率的分布:

注:红色分布曲线为阳性类别(患病患者),绿色分布曲线为阴性类别(未患病患者)。

[Image 6 and 7] (Image courtesy: My Photoshopped Collection)

这是一种理想的情况。当两条曲线完全不重叠时,意味着模型具有理想的可分性度量。它完全能够区分积极类和消极类。

[Image 8 and 9] (Image courtesy: My Photoshopped Collection)

当两个分布重叠时,我们引入类型 1 和类型 2 误差。根据阈值,我们可以最小化或最大化它们。当 AUC 为 0.7 时,这意味着模型有 70%的机会能够区分正类和负类。

[Image 10 and 11] (Image courtesy: My Photoshopped Collection)

这是最坏的情况。当 AUC 约为 0.5 时,该模型没有区分阳性类别和阴性类别的区分能力。

[Image 12 and 13] (Image courtesy: My Photoshopped Collection)

当 AUC 大约为 0 时,模型实际上是在往复类。这意味着模型将一个负类预测为正类,反之亦然。

灵敏度、特异性、FPR 和阈值之间的关系。

灵敏度和特异性是成反比的。所以当我们提高敏感度时,特异性就会降低,反之亦然。

Specificity⬇️的 Sensitivity⬆️和 Specificity⬆️的 Sensitivity⬇️

当我们降低阈值时,我们得到更多的正值,从而增加了灵敏度,降低了特异性。

类似地,当我们增加阈值时,我们得到更多的负值,因此我们得到更高的特异性和更低的敏感性。

正如我们所知,FPR 是 1 -特异性。因此,当我们提高 TPR 时,FPR 也会提高,反之亦然。

FPR⬆️的 TPR⬆️和 FPR⬇️的 TPR⬇️

多类模型如何使用 AUC ROC 曲线?

在一个多类模型中,我们可以使用一个对所有方法为 N 个类绘制 N 个 AUC ROC 曲线。例如,如果您有三个名为 X,Y,Z类,您将有一个针对 X 和 Z 分类的 ROC,另一个针对 Y 和 Z 分类的 ROC,以及针对 Y 和 X 分类的第三个 ROC

感谢阅读。

我希望我已经让你对什么是 AUC - ROC 曲线有了一些了解。如果你喜欢这篇文章,给这篇文章一些掌声会对你有所帮助👏。我随时欢迎你的问题和建议。你可以在脸书、推特、Linkedin 上分享这个,这样有需要的人可能会偶然发现这个。

您可以通过以下方式联系到我:

领英:https://www.linkedin.com/in/narkhedesarang/

推特:https://twitter.com/narkhede_sarang

github:https://github.com/TheSarang

用 Python 理解基本的机器学习——感知器和人工神经元

原文:https://towardsdatascience.com/understanding-basic-machine-learning-with-python-perceptrons-and-artificial-neurons-dfae8fe61700?source=collection_archive---------4-----------------------

基本功能的完整代码演练

如果你正在学习机器学习,很可能你的目标是应用前沿算法和“深度学习”来创建强大的应用程序。随着直观的 API 的广泛使用,这是可以实现的,只需要对正在发生的事情或深层底层实际上是如何工作的理解很少。

然而,在做这件事之前,浅显的架构基础知识和对底层的洞察是有益的。如果没有这一点,构建偏离盲目跟随教程的模型将变得困难(猴子见猴子做综合症)。

在这篇文章中,我们将讨论人工神经元和分类的起点,包括感知器和 Adaline 模型。对于每个模型,我们将讨论主要组件,然后将它们组合成完整的 Python 类实现。

Image 1. Neuron Cell, taken from Pixabay.

感知器模型

机器学习最根本的起点是人工神经元。第一个简化的脑细胞模型发表于 1943 年,被称为麦卡洛克-皮茨(MCP) 神经元。本质上,这是一个具有二进制输出(“0”或“1”)的基本逻辑门。如果到达神经元的输入的总和超过给定的阈值,则产生“1 ”,其中每个输入乘以相应的权重系数以产生这个总和。因此,神经元的放电很大程度上取决于输入集和相应的权重系数值。

弗兰克·罗森布拉特在 MCP 神经元的基本概念发表后不久就采用了这一概念,并提出了**感知器规则算法。**该允许自动学习神经元模型的最佳权重系数。通过这样的模型,我们可以预测给定的输入是属于一个类还是另一个类(二元分类)。

Figure 1. Simplified Perceptron Model. Diagram by Author.

感知器模型可能有任意数量的输入,也称为特征。因为我们通常有多个特征,所以用向量和矩阵来表示我们的输入和权重是有帮助的。不要混淆输入样本和输入特征;每个数据样本都有许多特征, n,,这些特征通过我们的模型输入,一次处理一个(按顺序)。例如,如果我们有 100 个汽车数据样本,其中每个样本都有 m 个特征(代表最高速度、bhp、成本等)。),那么数据的每个样本 x 将具有一个 m 个特征的向量。每个输入特征都有一个相应的权重,经过训练后,权重将根据我们训练的数据进行优化。

Figure 2. Vectors for our input features and weights.

对于每个数据样本,我们的输入特征和权重作为一个加权和在感知器中被接受,这就是通常所说的网络输入函数, z *。*对上面的 xw 使用向量的好处是,我们可以使用线性代数来简洁地表示它,就像这样:

Figure 3. Perceptron Net Input Function.

我们转置权重向量 w ,然后与我们的输入向量x相乘,这形成了我们需要的和。还应注意,我们还使用了一个偏差项来允许我们的感知器模型中有一个阈值,它等于我们向量中的第一个权重项。为了方便起见,输入矩阵中的第一个 x 项总是设置为 1。这意味着我们需要在输入向量中加入偏差项,然后再将它放入模型中。

如果你对这种数学符号完全陌生,我强烈推荐一些线性代数入门。几乎你在进一步的机器学习中所涉及的所有内容都将大量基于线性代数。

在净输入求和之后,我们的值被传递给感知器阈值,或决策函数。在这种情况下,该功能是一个单位步进功能。如果输入高于给定值,则输出“1”,否则输出“0”。

那么我们的感知机实际上是如何从一组数据中学习的呢?整个感知器过程如下:

  • 将重量参数初始化为初始值(通常是小的随机值,而不是零)。
  • 从每个训练样本输入的给定特征预测二进制输出。
  • 通过感知器学习规则更新权重。

Figure 4. Model for the Perceptron, including weight optimisation using the error. Diagram by Author.

感知器的成本函数非常简单,被称为**感知器学习规则。**每次训练迭代后,我们的权重向量中的每个权重都会有一个小的变化,如下所示:

Figure 5. Perceptron Learning Rule for updating of weights.

:=符号意味着我们同时更新权重向量中的所有权重,而不是迭代地更新。因此,进行输出预测,然后更新所有权重参数,作为一个训练周期的一部分。上面的 alpha 项也等于学习率,它决定了我们的模型在每个训练周期中学习的速度。

假设我们用于训练的数据是线性可分的,如果经过足够的训练周期(时期),感知器会将权重更新为最佳值。

Python 中的感知器

我们将从用 Python 编写感知器的每个组件开始,然后在最后将它们组合成一个更大的感知器类。对于这个基本模型,我们唯一需要的 Python 包是 numpymatplotlib

抽样资料

为此,我们将生成一个简单的数据集,其中包含两个不同的输出类,供我们的感知器进行训练。注意:该随机训练数据是通过随机函数生成的,并不完全可复制。

为了帮助理解我们正在努力做的事情,可视化我们的数据是有帮助的。在这种情况下,我们的输入样本只有两个特征,因此使用散点图来可视化我们的数据很容易。下面显示了数据生成,然后绘制成散点图。

Figure 6. Sample code for generating bird data and plotting on a scatter graph.

Figure 7. Visualisation of our generated data.

初始权重的生成

我们希望将我们的权重初始化为小的随机数字,而不是将它们初始化为零。我们需要这样做,否则我们的学习率将会降低训练过程中对分类结果的影响。这背后的理由将不被涵盖,然而,这是因为学习率只影响权重向量的规模,而不是方向,如果权重初始化为零。

这些权重可以以不同的方式生成。使用 numpy.random 的一个例子是:

向 X 添加偏差项

对于偏置项,我们只需在输入数据 x 中添加一列 1,在 numpy 中,这可以通过使用onehstack numpy 函数来实现。

加权求和函数(净输入)

如上所述,由于我们对每个样本的输入特征及其相关权重使用向量,因此我们可以非常容易地计算净输入和。在 Python 中使用带有 numpy 的矢量化,根据我们是否向训练数据添加了 1 的偏差列,网络输入函数变为:

Figure 8. Implementing the net input sum in numpy.

预测用单位阶跃函数

如果我们的净输入总和大于或等于零,我们希望返回 1,否则返回 0。

Figure 9. Implementing the step input function in numpy.

感知器学习规则

使用之前在图 6 中定义的学习规则,我们可以执行一个完整的训练周期。这包括遍历所有训练样本,并根据感知器学习规则更新权重,如下所示:

Figure 10. Perceptron training cycle implementation.

把所有的放在一起

有了使用 numpy 形成的感知器的基本组件,我们可以将它们拼凑在一起,实现一个完整的感知器二进制分类器。使用分类器,我们可以在训练周期中可视化我们的错误,并且(希望如此!)随着权重的优化,错误数量会随着时间的推移而减少。

Figure 11. Code for a Perceptron class in Python for binary classification.

Figure 12. Visualisation of the errors and decision boundaries made by our Perceptron classifier.

从误差与训练周期(时期)的关系图中可以看出,我们得到的误差数量随着时间的推移而减少。大约 7 个周期后,我们的模型将错误数量减少到零。我们的感知器分类器训练后做出的决策边界如右图所示,有效地区分了金雕和角枭。我们可以通过使用一组新输入 x 调用分类器预测函数,使用我们训练的模型对新数据进行预测。

感知器的一个问题是,如果所提供的数据是完全线性可分的,它们只会正确地优化权重。对于上面使用的数据,它是线性可分的。然而,如果我们使用更现实的数据,这些数据通常不能用直线分开,那么我们的感知器分类器将永远不会停止优化权重,并将不断出现错误。这是一个巨大的缺点,也是不使用感知机的原因之一。然而,它们确实是对基本神经元和更复杂模型的良好介绍。

Adaline——自适应线性神经元

对原始感知器模型的改进是 Adaline,它增加了一个用于优化权重的线性激活函数。通过这种添加,使用连续成本函数而不是单位步长。Adaline 很重要,因为它为更高级的机器学习模型奠定了基础。

Figure 13. Model for Adaline, which includes the additional activation function. Diagram by Author.

正如您在上面看到的,单位步骤仍然存在,但是它仅用于模型末尾的输出分类(“1”或“0”)。线性激活模型的连续输出值用于成本(或目标)函数。这表明我们的算法在我们的训练数据上做得有多差(或多好),并且可以通过众所周知的算法(如梯度下降)将其最小化。

价值函数

在这种情况下,我们将使用误差平方和作为我们的成本函数,可以这样实现:

Figure 14. Sum of Squared Errors implementation in Python.

梯度下降

为了应用梯度下降,我们需要确定成本函数相对于每个权重的偏导数。利用微分,我们发现这个偏导数等于:

Figure 15. Partial derivative of our cost function with respect to each weight.

为了优化我们的权重,我们希望以我们的学习速率参数所选择的速率,在梯度的相反方向上迈出一步。这背后的逻辑是最小化成本并最终达到全局最小值。因此,对于每次重量优化,我们需要应用:

Figure 16. Optimisation updates for our weights in the Adaline model.

我们可以将权重优化步骤和成本计算步骤合并到一个训练周期代码片段中,如下所示:

Figure 17. One training cycle for our Adaline model.

特征标准化

除了激活功能和梯度下降优化,我们还将通过 F 功能标准化增强我们模型的性能。这是机器学习中的一种常见做法,对于给定数量的时期,这种做法使优化过程更快、更有效。为此,我们将从训练数据中的每个相关特征值中减去每个特征的平均值,然后将特征值除以它们各自的标准偏差。

Figure 18. Feature standardisation in Python.

把所有的放在一起

有了 Adaline 模型的附加组件,我们就可以用 Python 生成一个最终的实现,就像我们用感知器一样。这个 Adaline 实现如下所示:

Figure 19. Adaline Classifier implemented in Python.

从下图中的基本 Adaline 示例中,我们可以看到为我们的模型设置超参数是多么重要;如果我们选择 0.1 的学习率,成本趋于无穷大并且不收敛,而如果我们选择 0.001 的学习率,我们的模型成功地收敛到成本函数的全局最小值。迭代的次数也很重要,应该足够高以充分降低成本。机器学习模型的这些可调方面被称为超参数,这些优化对于我们创建的任何模型都是一个重要方面。

Figure 20. Comparison of different choices of learning rate for our Adaline classifier.

进一步改进和结束语

有很多方法可以进一步改进这个模型,包括随机梯度下降,它可以更频繁地优化,而不是像上述模型那样使用整批训练数据。我们还可以将它扩展到不仅仅是二元分类,使用一元对多元分类。

此外,还有比 Adaline 好得多的分类器可用。Adaline 是一个起点,可以用作理解更复杂的分类模型(如逻辑回归和神经网络)的基础。

在这篇文章中,我们研究了基本神经元的特性,然后使用 Python 和 numpy 构建了一个基本的 Rosenblatt 感知器模型。然后,我们构建了一个工作 Adaline 分类器,它通过激活函数和优化成本函数,在许多方面改进了感知器。在此期间,我们还应用了一些有价值的特征处理,包括标准化以使梯度下降更快更有效。

虽然这些模型不能替代通过 Sci-kit Learn 和其他软件包获得的专业构建和优化的模型,但它们应该能够让人们了解基本分类器的工作原理。我希望我们遵循的过程有助于您理解基本的机器学习分类,并为您提供使用 Python 实现这些模型的洞察力。

通过超级马里奥了解机器学习的基础

原文:https://towardsdatascience.com/understanding-basics-of-machine-learning-through-super-mario-5ed93c7d587d?source=collection_archive---------3-----------------------

Super Mario Land for gameboy

有很多关于神经网络和机器学习的文章,因为这个主题在过去几年里非常受欢迎。这个领域似乎非常难以接近和理解,许多人可能认为必须是数学家或统计学家才能掌握机器学习的概念。然而,机器学习和神经网络的基本概念不一定像人们想象的那样复杂。

本文的目的是通过一个任何人都能理解的简单例子来解释机器学习如何工作的高级概念。希望它能给你兴趣和信心,让你继续阅读和学习更多关于这个主题的知识,打破让它看起来如此不可接近的令人生畏的障碍。

强化学习

机器学习程序与常规程序的不同之处在于,程序员没有明确定义逻辑。程序员创造了一个程序,它有能力自学如何成功地完成手头的任务。我要举的例子很可能会被认为是一个强化学习的机器学习程序。这个程序接受输入,做出自己的决定并产生一个输出,然后从输出产生的回报中学习,一遍又一遍地重复整个过程。这听起来可能很抽象,但这和我们人类学习如何做事的方式非常相似。下面我将把它分解成人类能够理解的步骤。还有什么比超级马里奥更好的表达方式呢?

要开始我们的思维实验,你必须想象你对电脑游戏完全陌生。你甚至从未听说过它们,更不用说以前玩过了。然后有人给你一个超级马里奥的游戏。

投入

你看着屏幕,看到简单的 2D 风景。这被认为是您的输入;你开始看这个小图形,这是马里奥,然后是风景中的所有其他物体。

输出

你有四种可能的方式与游戏互动。你可以左,右,蹲,跳。这些是你的输出。您可以根据输入来决定应该选择哪个输出。

报酬

你目前不知道游戏中有什么潜在的奖励,但是很快你就会亲身体验到。每个输出的奖励在游戏中会有所不同。如果你只是向左或向右走,回报是相当低的。如果你走进一枚硬币,奖励会稍微高一点。如果你跳进一个神秘的盒子,奖励会更高。然而,如果你被敌人击中,你的奖励是负的——不用说,负奖励更像是一种惩罚。

你学习如何玩超级马里奥

完全新手如何玩游戏,你开始按下右箭头。马里奥向右移动,你会得到奖励。然而,当你继续按右箭头时,马里奥最终击中了一个古姆巴,在这个古姆巴上你得到了死亡的奖励!

Mario got rewarded by death for hitting the Goomba

别担心,你可以重新开始。这一次,当你记录向你走来的古姆巴的输入时,你尝试其他的输出来获得不同的回报。经过几次尝试后,你意识到在那次遭遇中获得最高奖励的输出是跳到古姆巴上面,或者跳过它。你现在开始学习如何玩超级马里奥。

Mario is rewarded by staying alive for jumping over the Goomba

这就是强化学习的概念在现实生活中的工作方式。机器学习程序一开始是一张白纸,对它应该做的任务一无所知。然后,它接受一个输入,即它所处的环境,并开始试图找出哪个输出给它最高的回报。这个概念非常符合人类如何通过试错来学习做新的事情。我们尝试一种方式,然后是不同的方式,直到我们得到我们想要或期望的回报。

但是每个人都已经知道如何玩超级马里奥了…

的确,没有人真的需要学习如何玩超级马里奥,因为它是一个非常直观的游戏。甚至小孩子也能成功地玩这个游戏。

这样做的原因是,我们在游戏中加入了以前的经验,因此可以更好地掌握游戏规则,更快地获得更高的奖励。在机器学习中,这将被视为训练

培养

如前所述,每当机器学习程序开始试图找出如何成功完成一项任务时,它都会从头开始。因此,给程序一些训练数据是很重要的,这样它就有了一些开始的基础,这样它就不会一遍又一遍地犯小错误,直到它最终知道任务是什么。

当然,如果有足够的时间,机器学习算法将能够训练自己成功完成给定的任务。这可能需要很长时间,因此为您的程序提供高质量的训练数据以获得更准确的结果是非常重要的。

结论

他们从这篇阅读中得到的关键是理解机器学习算法如何比程序性程序更类似于人类如何学习完成任务。在过程程序中,决策是通过条件语句硬编码到程序中的。例如,这将是程序员识别超级马里奥游戏中的威胁,并输入如下语句:如果检测到威胁,则执行该特定动作,否则继续执行。这种过程方法和机器学习方法之间的主要区别是,最终,计算机程序有自主权做出自己的决定。理解这一点很重要,因为机器学习程序可以用于其他类似的任务,而不必重新编程。我们的示例程序可以在学习玩超级马里奥后很好地学习如何玩任何其他游戏,并且成功率很高,并且玩的游戏越多,玩的游戏越好。这种行为非常类似于一个人在玩不同的游戏时会变得越来越好,尽管每个游戏并不完全相同。我们利用以前的经验学得更快。

这篇文章只是对一个更深入的主题的一个非常简短的概述。如果你对深入研究人工智能和机器学习感兴趣,我会推荐这个文章系列。

如果你喜欢这篇文章,请鼓掌和评论!

使用交互代码的 Numpy 和 Tensorflow 中的示例了解批处理规范化

原文:https://towardsdatascience.com/understanding-batch-normalization-with-examples-in-numpy-and-tensorflow-with-interactive-code-7f59bb126642?source=collection_archive---------1-----------------------

Gif from here

所以今天我就来探讨一下批量规格化( 批量规格化:通过减少内部协变 ShiftbySergey io FFE,以及Christian Szegedy)。然而,为了加强我对数据预处理的理解,我将讨论 3 种情况,

案例 1 — 归一化:全数据(Numpy)
案例 2 — 标准化:全数据(Numpy)
案例 3 — 批量归一化:小批量(Numpy / Tensorflow)

本帖不涉及反向传播!

实验设置

这个实验的设置非常简单。为了模拟真实世界的用例,让我们从随机正态分布创建一个 32*32 的图像,并添加一些噪声。以上是我们的形象看起来像。

红框 →(图像数量,图像宽度,图像高度,通道数量)现在我们将使用 32*32 灰度图像。
左图 →我们图像数据的直方图

正如你在上面看到的,我们的图像平均值为 26,方差为 306。在左边,我们可以看到图像数据的直方图。

情况 1:归一化—全部数据

对于我们的第一个例子,让我们对整个数据集进行归一化。视觉上我们看不出有什么不同。

然而,一旦我们绘制直方图或查看平均值和标准差,我们可以清楚地看到我们的数据在 0 和 1 的范围内。

案例 2:标准化—全部数据

同样,视觉上我看不出彼此有什么太大的不同。

然而,当我们看到直方图的轴时,我们可以清楚地看到,我们的数据的平均值已经移动到 0(几乎),方差为 1。

标准化/规范化方程

Image from this website

左→ 标准化方程
→标准化方程

以防万一,如果有人想知道,让我们回顾一下标准化和规范化两种情况下的等式。请注意 μ 是平均值, σ 是标准差。

批量归一化方程

红框→ 标准化方程
蓝线→ 将要学习的参数

现在我们已经讨论了标准化和规范化,我们可以看到,批量标准化的等式与规范化的过程完全相同。唯一的区别是伽玛和贝塔项,用蓝色下划线标出。我们可以将这些项想象成权重,我们将从地面真实数据中计算误差,并使用反向传播来学习这些参数。

但是有一点我希望注意!如果我们把 gamma(谢谢 洛阳方 纠正我 ) 设为 1,beta 设为 0 整个过程只是标准化而已。对于 Tensorflow 的实现,我们将滥用该属性。

案例三:批量归一化——纯实现

红线 →小批量,从我们的图像数据
中取出前 10 张图像,蓝框 →数据标准化

这里有一点需要注意,对于批量标准化,我们将从测试数据中提取前 10 幅图像,并应用批量标准化。

同样,我们可以看到均值在 0 左右,方差为 1。现在让我们看看 tensorflow 的实现。

案例三:批量归一化—张量流

红线 → Mini Batch,来自我们图像数据
的前 10 张图像蓝线→ Offset (Beta)为 0,Scale (Gamma)为 1

还是那句话,视觉上,我们看不出任何区别。

但是,如果我们看一下数据的平均值和方差,我们可以看到这与应用标准化完全相同。

交互代码(谷歌 Collab/ Replit/微软 Azure 笔记本)

对于谷歌 Colab,你需要一个谷歌帐户来查看代码,而且你不能在谷歌 Colab 中运行只读脚本,所以在你的操场上做一个副本。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!

要访问 Google Colab 上的代码,请点击此处。
要访问 Repl it 上的代码,请点击这里。
要访问 Microsoft Azure 笔记本上的代码,请单击此处。

遗言

最近 Face book AI 研究组发布了群组规范化。( 分组规格化n by吴雨欣 ,以及 明凯何 )我会尽量涵盖这一点。

如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有写作的列表,请在这里查看我的网站。

同时,在我的 twitter 这里关注我,并访问我的网站,或我的 Youtube 频道了解更多内容。如果你感兴趣,我还在这里做了解耦神经网络的比较。

参考

  1. CS231n 冬季:第五讲:神经网络第二部分。(2018).YouTube。检索于 2018 年 3 月 19 日,来自https://www.youtube.com/watch?v=gYpoJMlgyXA&feature = youtu . be&list = plkt 2 usq 6 rbvctenobvg 1 tpcc 7 aoqi 31 ALC&t = 3078
  2. thorey,C. (2016 年)。流过批量归一化的渐变是什么样子的?。cthorey . github . io . 2018 年 3 月 19 日检索,来自http://cthorey.github.io/backpropagation/
  3. 推导批量范数反投影方程。(2018).chrisyeh 96 . github . io . 2018 年 3 月 19 日检索,来自https://chrisyeh 96 . github . io/2017/08/28/derivating-batch norm-back prop . html
  4. 推导批次标准化的后向传递的梯度。(2018).kevinzakka . github . io . 2018 年 3 月 19 日检索,来自https://kevinzakka . github . io/2016/09/14/batch _ normalization/
  5. 克拉泽特,F. (2018)。了解反向传递批处理规范化层。krat zert . github . io . 2018 年 3 月 19 日检索,来自https://krat zert . github . io/2016/02/12/understanding-the gradient-flow-through-the-batch-normalization-layer . html
  6. (2018).Arxiv.org。检索于 2018 年 3 月 19 日,来自https://arxiv.org/pdf/1502.03167.pdf
  7. NumPy . histogram—NumPy 1.13 版手册。(2018).Docs.scipy.org。检索于 2018 年 3 月 19 日,来自https://docs . scipy . org/doc/numpy-1 . 13 . 0/reference/generated/numpy . histogram . html
  8. NumPy . random . Weibull—NumPy v 1.13 手册。(2018).Docs.scipy.org。检索于 2018 年 3 月 19 日,来自https://docs . scipy . org/doc/numpy-1 . 13 . 0/reference/generated/numpy . random . Weibull . html # numpy . random . Weibull
  9. numpy.var — NumPy v1.14 手册。(2018).Docs.scipy.org。检索于 2018 年 3 月 26 日,来自https://docs . scipy . org/doc/numpy/reference/generated/numpy . var . html
  10. 数据?,H. (2018)。如何用 Python 中的 Matplotlib 绘制一个带有数据列表的直方图?。Stackoverflow.com。检索于 2018 年 3 月 26 日,来自https://stack overflow . com/questions/33203645/how-to-plot-a-histogram-using-matplotlib-in-python-with-a-list-of-data
  11. numpy.random.randn — NumPy v1.14 手册。(2018).Docs.scipy.org。检索于 2018 年 3 月 27 日,来自https://docs . scipy . org/doc/numpy/reference/generated/numpy . random . randn . html
  12. 吴,杨,何,王(2018)。群体规范化。Arxiv.org。检索于 2018 年 3 月 27 日,来自 https://arxiv.org/abs/1803.08494
  13. 标准化与规范化|数据挖掘博客—【www.dataminingblog.com 。(2007).Dataminingblog.com。检索于 2018 年 3 月 27 日,来自http://www . dataminingblog . com/standardization-vs-normalization/
  14. 约夫和塞格迪(2015 年)。批量标准化:通过减少内部协变量转移加速深度网络训练。Arxiv.org。检索于 2018 年 3 月 27 日,来自https://arxiv.org/abs/1502.03167
  15. 正态分布。(2018).Mathsisfun.com。检索于 2018 年 3 月 27 日,来自https://www . mathsisfun . com/data/standard-normal-distribution . html

理解 PyTorch 中的双向 RNN

原文:https://towardsdatascience.com/understanding-bidirectional-rnn-in-pytorch-5bd25a5dd66?source=collection_archive---------2-----------------------

快速回顾

Fig 1: General Structure of Bidirectional Recurrent Neural Networks. Source: colah’s blog

双向递归神经网络(RNN)实际上只是将两个独立的递归神经网络放在一起。对于一个网络,输入序列以正常的时间顺序馈送,而对于另一个网络,输入序列以相反的时间顺序馈送。两个网络的输出通常在每个时间步被连接,尽管还有其他选择,例如求和。

这种结构允许网络在每个时间步都具有关于序列的前向和后向信息。这个概念似乎很简单。但是当实际实现一个利用双向结构的神经网络时,就出现了混淆…

困惑

第一个困惑是关于将双向 RNN 的输出转发到密集神经网络的方式。对于普通的 RNNs,我们可以只转发最后一个时间步的输出,下面的图片是我通过谷歌找到的,展示了双向 RNN 的类似技术。

Fig 2: A confusing formulation. Image Source

但是等等…如果我们选择最后一个时间步的输出,反向 RNN 只会看到最后一个输入(图中的 x_3)。它几乎不会提供任何预测能力。

第二个困惑是关于返回隐藏状态。在 seq2seq 模型中,我们需要编码器的隐藏状态来初始化解码器的隐藏状态。直观地说,如果我们只能在一个时间步选择隐藏状态(如 PyTorch ),我们会选择 RNN 刚刚消耗完序列中最后一个输入的状态。但是如果返回时间步长 n (最后一个)的隐藏状态,和以前一样,我们将得到反转 RNN 的隐藏状态,只看到一步输入。

查看 Keras 实现

Keras 为双向 rnn 提供了一个包装器。如果您查看 wrappers.py 中的第 292 行:

[## fchollet/keras

用于 Python 的深度学习库。在 TensorFlow、Theano 或 CNTK 上运行。

github.com](https://github.com/fchollet/keras/blob/4edd0379e14c7b502b3c81c95c7319b5df2af65c/keras/layers/wrappers.py#L292)

你会发现,默认情况下,反向 RNN 的输出按时间步长向后排序( n…1 )。当return_sequences为真(默认为假)时,Keras 将反转它。因此,如果我们采用一个时间步长输出,Keras 将在正常 RNN 的时间步长 n 采用一个,在反向 RNN 的时间步长 1 采用一个。这很好地证实了图 2 显示了有缺陷的结构。

在 PyTorch 中它是如何工作的

随着第一个困惑的解决。我们现在感兴趣的是如何在 PyTorch 中正确使用双向 rnn:

上面的笔记本回答了我们遇到的两个困惑(假设batch_first为假):

  1. 我们要取output[-1, :, :hidden_size](正常的 RNN)和output[0, :, hidden_size:](反向的 RNN),把它们串联起来,把结果反馈给后续的密集神经网络。
  2. 返回的隐藏状态是消耗完整个序列后的状态。它们可以被安全地传递给解码器。

(边注)batch_first为假时 PyTorch 中 GRU 的输出形状:

输出(序列长度,批次,隐藏尺寸*数量方向)

h_n (层数*方向数,批次,隐藏大小)

LSTM 的方法类似,但是返回一个附加的单元格状态变量,形状与 h_n. 相同

理解二元交叉熵/对数损失:一个直观的解释

原文:https://towardsdatascience.com/understanding-binary-cross-entropy-log-loss-a-visual-explanation-a3ac6025181a?source=collection_archive---------0-----------------------

Photo by G. Crescoli on Unsplash

介绍

如果你正在训练一个二进制分类器,很可能你正在使用二进制交叉熵 / 对数损失作为你的损失函数。

有没有想过用这个损失函数到底是什么意思?问题是,考虑到今天的库和框架的易用性,很容易忽略所使用的损失函数的真正含义。

动机

我在寻找一篇博客文章,以一种视觉上清晰简洁的方式解释二元交叉熵 / 日志损失背后的概念,这样我就可以在数据科学务虚会上向我的学生展示它。因为我找不到任何适合我的目的的,所以我自己承担了写它的任务:-)

一个简单的分类问题

让我们从 10 个随机点开始:

x = [-2.2, -1.4, -0.8, 0.2, 0.4, 0.8, 1.2, 2.2, 2.9, 4.6]

这是我们唯一的特色 : x

Figure 0: the feature

现在,让我们给我们的点分配一些颜色:红色绿色。这些是我们的标签

Figure 1: the data

所以,我们的分类问题非常简单:给定我们的特征x,我们需要预测它的标签** : 红色或者绿色。**

既然这是一个二元分类,我们也可以把这个问题提出来:“点是绿色的”或者更好一点,“点是绿色的的概率是多少”?理想情况下,绿点的概率为 1.0 (绿色),而红点的概率为 0.0 (绿色)。

在此设置中,绿点属于正类 ( ,为绿色),而红点属于负类 ( ,为非绿色)。

如果我们拟合一个模型来执行这个分类,它将预测我们每一个点都是绿色的概率。给定我们所知道的点的颜色,我们如何评估预测的概率有多好(或多差)?这就是损失函数的全部目的!对于不良预测,它应该返回高值,对于良好预测,它应该返回低值

对于像我们的例子一样的二元分类,典型的损失函数二元交叉熵 / 对数损失

损失函数:二元交叉熵/对数损失

如果你查找这个损失函数,你会发现:

Binary Cross-Entropy / Log Loss

其中 y 为的标号(对于 绿色点为 1 ,对于 红色点为0****)p(y)为所有 N 点为绿色的预测概率。

阅读这个公式,它告诉你,对于每一个绿色点( y=1 ),它将 log(p(y)) 加到损失上,即它是绿色的的 log 概率。反之,它为每个红色点( y=0 )加上 log(1-p(y)) ,即它为红色log 概率。当然,不一定很难,但也没有那么直观…

况且跟这一切有什么关系?为什么我们首先采用概率对数?这些都是有效的问题,我希望在下面的“展示数学”部分回答它们。

但是,在进入更多公式之前,让我给你看一个上面公式的可视化表示

计算损失——可视化方法

首先,让我们分门别类,,如下图:

Figure 2: splitting the data!

现在,让我们训练一个逻辑回归来对我们的点进行分类。拟合回归是一条s 形曲线,代表对于任何给定的x点为绿色的概率。看起来是这样的:

Figure 3: fitting a Logistic Regression

那么,对于所有属于正类 ( 绿)的点,我们的分类器给出的预测概率是多少?这些是下的绿色条s 形曲线,在 x 坐标处对应的点。

Figure 4: probabilities of classifying points in the POSITIVE class correctly

好的,到目前为止,一切顺利!负类中的点呢?记住, 下的绿色条s 形曲线代表给定点为绿色的概率。那么,给定点的概率是多少?上方的**红色条s 形曲线*,当然:-)***

Figure 5: probabilities of classifying points in the NEGATIVE class correctly

将所有这些放在一起,我们最终会得到这样的结果:

Figure 6: all probabilities put together!

条形代表与每个点的相应真实类别相关的预测概率

好了,我们有了预测的概率…是时候通过计算二元交叉熵* / 日志损失来评估**了!*

这些概率就是我们所需要的全部,所以,让我们去掉 x并使棒条彼此相邻:

Figure 7: probabilities of all points

嗯,挂杆已经没有多大意义了,所以让我们重新定位它们:

Figure 8: probabilities of all points — much better 😃

因为我们试图计算一个损失,我们需要惩罚坏的预测,对吗?如果真类关联的概率1.0 ,我们需要它的损失。反之,如果那个概率是 ,比如说 0.01 ,我们需要它的损失巨大

事实证明,采用概率的*(负)对数非常适合我们的目的(由于 0.0 和 1.0 之间的值的对数是负的,我们采用负对数来获得损失的正值)。***

实际上,我们使用 log 的原因来自于交叉熵的定义,请查看下面的“展示数学”部分了解更多细节。

下面的图给了我们一个清晰的画面——随着真实等级预测概率变得更接近零,损失呈指数增长:

Figure 9: Log Loss for different probabilities

很公平!让我们取概率的(负)对数——这些是每个点对应的损失

最后,我们计算所有这些损失的平均值。

Figure 10: finally, the loss!

瞧!我们已经成功计算出这个玩具例子的二元交叉熵 / 对数损失是 0.3329!

给我看看代码

如果您想再次检查我们找到的值,只需运行下面的代码并自己查看:-)

给我看看数学(真的?!)

玩笑归玩笑,这篇文章不是旨在非常数学化…但是对于那些想要理解对数在所有这些中的作用的读者,我们开始吧:-)

如果你想更深入地了解信息论,包括所有这些概念——熵、交叉熵以及更多更多——请查看克里斯·奥拉的 帖子 查看,它非常详细!

分配

先说我们的积分分布。由于 y 代表我们点的(我们有 3 个红点7 个绿点,这就是它的分布,姑且称之为 q(y) ,看起来像是:

Figure 11: q(y), the distribution of our points

是与给定分布 q(y) 相关的不确定性的度量。

如果我们所有的点都是绿色会怎么样?不确定性会是什么样的分布?对吧?毕竟,一个点的颜色是毫无疑问的:它总是绿色!所以,熵为零

另一方面,如果我们确切地知道一半的点绿色的另一半是红色会怎么样?这是最糟糕的情况,对吗?我们在猜测一个点的颜色上绝对没有优势:这完全是随机的!在这种情况下,熵由下面的公式给出(我们有两类(颜色)——红色或绿色——因此, 2 ):

Entropy for a half-half distribution

对于在之间的每隔一种情况,我们可以计算分布熵,就像我们的 q(y) 一样,使用下面的公式,其中 C 是类的数量:

Entropy

所以,如果我们知道一个随机变量的真实分布,我们就可以计算出它的。但是,如果是这样的话,为什么首先要费心训练一个分类器?毕竟,我们知道真实的分布…

但是,如果我们呢?我们能否尝试用一些其他分布来近似真实分布,比如说 p(y) ?我们当然可以!:-)

交叉熵

让我们假设我们的 跟随这个其他分布 p(y) 。但是我们知道他们是从 ( 未知)分布 q(y) 实际上来的对吧?

如果我们像这样计算,我们实际上是在计算两个分布之间的交叉熵:

Cross-Entropy

如果我们奇迹般地将与* p(y) q(y) 完美匹配,那么交叉熵 的计算值也将与匹配。*

因为这很可能永远不会发生,交叉熵的值将大于对真实分布计算的熵

Cross-Entropy minus Entropy

原来,交叉熵之间的差异有一个名字…

库尔贝克-莱布勒散度

Kullback-Leibler 散度,或简称为“ KL 散度 ,是两个分布之间相异度的度量:

KL Divergence

这意味着,p(y)越接近 q(y) ,越低散度,因此,交叉熵,将是。

所以,我们需要找一个好的 p(y) 来用……但是,这是我们分类器应该做的,不是吗?!的确如此!它寻找最可能的 p(y) ,也就是最小化交叉熵的那个。

损失函数

在其训练期间,分类器使用其训练集中的 N 个点中的每一个来计算交叉熵损失,有效地拟合分布 p(y) !由于每个点的概率是 1/N,交叉熵由下式给出:

Cross-Entropy —point by point

还记得上面的图 6 到 10 吗?我们需要在与每个点的真实类别相关联的概率之上计算交叉熵。这意味着使用绿色条用于正级 ( y=1 )中的点,使用红色悬挂用于负级 ( y=0 )中的点,或者从数学上来说:**

Mathematical expression corresponding to Figure 10 😃

最后一步是计算两个类别中所有点的平均值正值负值:

Binary Cross-Entropy — computed over positive and negative classes

最后,通过一点点操作,我们可以从正类或负类中取任意一点,在相同的公式下:

Binary Cross-Entropy — the usual formula

瞧吧!我们回到了原始公式用于二元交叉熵/对数损失 😃

最后的想法

我真心希望这篇文章能够在一个经常被认为是理所当然的概念上闪耀一些新的光芒,这个概念就是二元交叉熵作为损失函数。此外,我也希望它能向你展示一点点机器学习信息论是如何联系在一起的。

2022 年 7 月 10 日更新:我刚刚在 YouTube 上发布了一个视频,里面有这篇文章的动画版本——来看看吧!

Understanding Binary Cross-Entropy / Log Loss in 5 Minutes!

如果你有什么想法、意见或问题,欢迎在下方留言评论或联系我 推特

如何理解您的聚类结果

原文:https://towardsdatascience.com/understanding-clustering-cf0117148ef4?source=collection_archive---------3-----------------------

我正与全球许多客户合作实施各种数据科学项目。有时,客户希望进行群集,而我试图避免这种情况。我遵循一个简单的经验法则:

如果你能被监督,那就去被监督。

原因很简单。每个分析都有超参数。这些都需要确定。在有监督的情况下,优化什么是相当直接的:商业价值。在无人监督的情况下,你常常很难找到正确的衡量标准。当然,有很多方法可以衡量你的聚类质量,比如戴维斯-波尔丁指数或者轮廓系数。但是它们与我的业务目标不一致,因此不好。

原来很多分割问题都可以转化为分类问题。这样做总是更可取的。只有在极少数情况下你不能。在这种情况下,您需要使结果易于理解,以符合您的业务目标。以下是我让聚类结果易于解释的技巧。

技巧 1——把它变成一个特征选择问题

通常在数据分析中,您需要能够将业务问题映射到方法。在您的案例中,问题是:*什么最能描述 cluster_0?*或者换句话说:【cluster _ 0 与其他所有产品的区别是什么?这其实可以解释为一个特征选择问题。您想知道哪些特征具有区分聚类的能力。我建议以一对一的方式来做这件事,因为这回答了直接的问题。

Data on two dimensions grouped. A feature selection technique would identify that both dimensions are important to distinguish the classes.

通常的特征选择技术,如包装器或过滤器方法,提供了一系列特征及其重要性。那已经相当不错了!

在众所周知的泰坦尼克号数据集上,我们可以得到“年龄、性别和乘客级别”作为最重要的属性。这使得我们可以将 cluster_0 重命名为:“年龄-性别-乘客级别”。这里的问题是,虽然你发现了重要的因素,但你没有指明方向。这是一群老人吗?或者说是年轻女性?我们可以通过查看质心坐标来更深入地挖掘,并将它们放入透视图中。但是有一个更简单的方法:决策树!

诀窍 2——决策树!

决策树是最容易理解的机器学习模型之一。通常它们用于解决分类问题。我们将使用它们来首先区分我们的 cluster_0 和所有其他聚类。

The Decision Tree can distinguish between the classes and also tell you on the exact values to look at.

第二步是分析决策树分支。所有预测我们的 cluster_0 的分支都可以作为描述。我们可以得到像这样的分支:

年龄< 20,乘客阶级=第一,性别=女。

这很好地描述了我们 cluster_0!

你也可以看看我们的描述有多精确,通过看树的训练精度。你需要平衡结果的质量和可解释性。您可以通过使用修剪来实现这一点。我建议在树的深处进行硬切割。根据我的经验,最多 4 到 5 次就能得到好的结果。人类经常高估他们解释模型的能力。对于决策树,他们通常把所有割的重要性等同起来,而他们需要在上下文和层次结构中进行解释。

理解编译器——面向人类(第 2 版)

原文:https://towardsdatascience.com/understanding-compilers-for-humans-version-2-157f0edb02dd?source=collection_archive---------6-----------------------

编程语言如何工作

从内部理解你的编译器可以让你有效地使用它。在这个按时间顺序排列的大纲中,浏览编程语言和编译器是如何工作的。许多链接、示例代码和图表有助于您的理解。

作者说明

*理解编译器——人类版(第 2 版)*是我第二篇关于 Medium 的文章的后续,有超过 21,000 的浏览量。我很高兴我能对人们的教育产生积极的影响,并且我很高兴能根据我从最初的文章中得到的信息给带来一个完整的重写。

[## 理解编译器——为了人类

你是否点击了绿色的运行按钮,但并不真正知道引擎下面发生了什么?你想知道一个…

medium.com](https://medium.com/@CanHasCommunism/understanding-compilers-for-humans-ba970e045877)

我选择了铁锈作为这部作品的主要语言。它冗长、高效、现代,而且从设计上看,对于编译器来说非常简单。我喜欢使用它。【https://www.rust-lang.org/

这篇文章的目的是保持读者的注意力,而不是有 20 页令人麻木的阅读。文本中有许多链接,将引导您找到更深入了解您感兴趣的主题的资源。大多数链接会将你引向维基百科。

欢迎在底部的评论区提出任何问题或建议。感谢您的关注,希望您喜欢。

介绍

什么是编译器

总之,你所谓的编程语言实际上只是一种叫做编译器的软件,它可以读取文本文件,对其进行大量处理,并生成二进制文件。由于计算机只能读取 1 和 0,而人类比二进制写得更好,编译器被设计成将人类可读的文本转换成计算机可读的机器码。

编译器可以是将一种文本翻译成另一种文本的任何程序。例如,这里有一个用 Rust 编写的编译器,它把 0 变成 1,把 1 变成 0:

While this compiler doesn’t read a file, doesn’t generate an AST, and doesn’t produce binary, it is still considered a compiler for the simple reason that it translates an input.

编译器做什么

简而言之,编译器获取源代码并生成二进制代码。因为从复杂的、人类可读的代码直接转换成 1 和 0 是相当复杂的,所以编译器在程序运行之前有几个处理步骤要做:

  1. 读取你给它的源代码的单个字符。
  2. 将字符分类为单词、数字、符号和运算符。
  3. 获取排序后的字符,通过将它们与模式进行匹配来确定它们试图执行的操作,并生成操作树。
  4. 迭代上一步中在树中进行的每个操作,并生成等效的二进制文件。

虽然我说编译器立即从操作树进入二进制,但它实际上生成汇编代码,然后汇编/编译成二进制。汇编就像一个更高级的、人类可读的二进制文件。更多了解什么是 这里是

什么是口译员

解释器很像编译器,因为它们阅读并处理语言。不过,解释器跳过代码生成,执行 AST 实时 。对解释器来说,最大的好处是在调试期间开始运行程序所花费的时间。编译器在程序执行前可能要花几秒到几分钟的时间来编译程序,而解释器不编译就立即开始执行。解释器最大的缺点是它需要安装在用户的计算机上,然后程序才能执行。

本文主要指的是编译器,但是应该清楚它们之间的区别以及编译器之间的关系。

1.词汇分析

第一步是一个字符一个字符地分割输入。这一步被称为词法分析,或标记化。主要的想法是,我们将字符组合在一起,形成我们的单词、标识符、符号等等。词法分析大多不处理像求解2+2这样的逻辑问题——它只会说有三个记号:一个数字:2,一个加号,然后是另一个数字:2

假设您正在编写一个类似于12+3的字符串:它将读取字符12+3。我们有各自独立的角色,但我们必须把它们组合在一起;分词器的主要任务之一。例如,我们将12作为单独的字母,但是我们需要将它们放在一起,并作为单个整数进行解析。+也需要被识别为加号,而不是它的文字字符值——字符代码43。

如果您可以看到代码,并以这种方式使其更有意义,那么下面的 Rust tokenizer 可以将数字分组为 32 位整数,并将加号作为TokenPlus

[## 铁锈操场

play.rust-lang.org](https://play.rust-lang.org/?gist=070c3b6b985098a306c62881d7f2f82c&version=stable&mode=debug&edition=2015)

您可以点击 Rust Playground 左上角的“运行”按钮,在您的浏览器中编译并执行代码。

在编程语言的编译器中,词法分析器可能需要几种不同类型的标记。例如:符号、数字、标识符、字符串、运算符等。知道需要从源代码中提取哪种单独的标记完全取决于语言本身。

Example of C source code that has been lexically analyzed, and its tokens printed.

2.从语法上分析

解析器确实是语法的核心。**解析器获取由词法分析器生成的标记,尝试查看它们是否符合特定的模式,然后将这些模式与像调用函数、调用变量或数学运算这样的表达式相关联。**解析器是真正定义语言语法的东西。

int a = 3a: int = 3的区别在于解析器。解析器决定语法应该是什么样子。它确保括号和花括号是平衡的,每个语句都以分号结束,并且每个函数都有一个名称。当标记不符合预期模式时,解析器知道什么时候事情没有按照正确的顺序进行。

你可以编写几种不同类型的 解析器 。其中最常见的是自上而下,递归下降解析器。递归下降解析是最容易使用和理解的解析之一。我创建的所有解析器例子都是基于递归下降的。

解析器解析的语法可以用语法来概括。像 EBNF 这样的语法可以描述像12+3这样的简单数学运算的解析器:

EBNF grammar for simple addition and subtraction expressions.

记住语法文件是 而不是 解析器,而是解析器工作的概要。你可以围绕这样的语法构建一个解析器。它将由人类使用,比直接查看解析器的代码更容易阅读和理解。

该语法的解析器将是expr解析器,因为它是基本上所有内容都与之相关的顶级项目。唯一有效的输入必须是任何数字,加或减,任何数字。expr期待一个additive_expr,这是大加减法出现的地方。additive_expr先预计一个term(一个数字),然后加减,再一个term

Example AST generated for parsing 12+3.

*解析器在解析时生成的树称为 抽象语法树 **,简称 AST。*AST 包含所有的操作。解析器不计算操作,它只是按照正确的顺序收集它们。

我添加了之前的 lexer 代码,这样它就能匹配我们的语法,并能生成如图所示的 ASTs。我用注释// BEGIN PARSER //// END PARSER //标记了新解析器代码的开头和结尾。

*[## 铁锈操场

play.rust-lang.org](https://play.rust-lang.org/?gist=205deadb23dbc814912185cec8148fcf&version=stable&mode=debug&edition=2015)*

我们实际上可以走得更远。比方说,我们希望支持没有运算的数字输入,或者添加乘法和除法,甚至添加优先级。通过快速修改语法文件,并在解析器代码中反映出来,这一切都是可能的。

The new grammar.

*[## 铁锈操场

play.rust-lang.org](https://play.rust-lang.org/?gist=1587a5dd6109f70cafe68818a8c1a883&version=nightly&mode=debug&edition=2018)*

Scanner (a.k.a. lexer) and parser example for C. Starting from the sequence of characters "if(net>0.0)total+=net*(1.0+tax/100.0);", the scanner composes a sequence of tokens, and categorizes each of them, e.g. as identifier, reserved word, number literal, or operator. The latter sequence is transformed by the parser into a syntax tree, which is then treated by the remaining compiler phases. The scanner and parser handles the regular and properly context-free parts of the grammar for C, respectively. Credit: Jochen Burghardt. Original.

3.生成代码

代码生成器接受一个 AST 并发出代码或汇编中的等价代码。代码生成器必须以递归下降的顺序遍历 AST 中的每一项——很像解析器的工作方式——然后发出等价的代码。

* [## 编译器资源管理器- Rust (rustc 1.29.0)

pub fn main(){ let a = 10 * 3;}

godbolt.org](https://godbolt.org/z/K8416_)

如果打开上面的链接,可以看到左边的示例代码生成的程序集。汇编代码的第 3 行和第 4 行显示了编译器在 AST 中遇到常量时是如何为它们生成代码的。

god bolt 编译器资源管理器是一款优秀的工具,允许你用高级编程语言编写代码,并查看其生成的汇编代码。您可以用它来看看应该生成什么样的代码,但是不要忘记在您的语言的编译器中添加优化标志,看看它有多聪明。( *-O* 为铁锈)

如果您对编译器如何将局部变量保存到 ASM 的内存中感兴趣,本文(“代码生成”一节)将详细解释堆栈。大多数情况下,当变量不在本地时,高级编译器会在堆上为变量分配内存,并将它们存储在堆上,而不是堆栈上。你可以在这个 StackOverflow 回答中阅读更多关于存储变量的内容。

因为组装是一个完全不同的复杂的主题,所以我不会详细讨论它。我只想强调代码生成器的重要性和作用。此外,代码生成器不仅仅可以生成汇编。 Haxe 编译器有一个 后端 可以生成超过六种不同的编程语言;包括 C++、Java 和 Python。

后端指编译器的代码生成器或评估器;因此,前端是词法分析器和语法分析器。还有一个中间端,它主要与优化和 IRs 有关,这将在本节后面解释。后端大多与前端无关,只关心自己收到的 AST。这意味着一个人可以为几个不同的前端或语言重用同一个后端。臭名昭著的 GNU 编译器合集 就是如此。

我没有比我的 C 编译器后端更好的代码生成器的例子了;你可以在这里找到

生成汇编后,它将被写入一个新的汇编文件(.s.asm)。然后,该文件将通过汇编器传递,汇编器是用于汇编的编译器,它将生成等价的二进制文件。然后,二进制代码将被写入一个名为目标文件的新文件中(.o)。

目标文件是机器代码,但不可执行。为了使它们成为可执行的,目标文件需要被链接在一起。链接器获取这个通用机器码,并使其成为可执行文件,一个共享库,或者一个静态库。更多关于联系人 这里

链接程序是根据操作系统而变化的实用程序。一个单独的第三方链接器应该能够编译后端生成的目标代码。在制作编译器时,应该不需要创建自己的链接器。

*一个编译器可能有一个中间表示,或者 IR。**IR 是为了优化或翻译成另一种语言而无损地表示原始指令。*IR 不是原始源代码;IR 是为了在代码中找到潜在的优化而进行的无损简化。循环展开和矢量化使用 IR 完成。更多与 IR 相关的优化示例可以在本 PDF 中找到。

结论

当你理解了编译器,你就能更有效地使用你的编程语言。也许有一天你会对制作自己的编程语言感兴趣?我希望这对你有帮助。

资源和延伸阅读

  • http://craftinginterpreters.com/—指导你用 C 和 Java 创建一个解释器。
  • https://norasandler.com/2017/11/29/Write-a-Compiler.html——可能是对我最有益的“编写编译器”教程。
  • 我的 C 编译器和科学计算器解析器可以在这里和这里找到。
  • 另一种类型的解析器的例子,称为优先攀爬解析器,可以在这里找到。致谢:韦斯利·诺里斯。*

理解合成模式产生网络(上)

原文:https://towardsdatascience.com/understanding-compositional-pattern-producing-networks-810f6bef1b88?source=collection_archive---------4-----------------------

全面解释 CPPNs 背后的理论

3

在过去的两年里,我一直在研究复合模式产生网络(CPPN),这是一种在1中提出的扩充拓扑神经网络。然而,在我的整个研究中,我总是对 CPPNs 背后的一些概念和理论感到困惑,我努力理解它们是如何工作的。虽然网上有一些 CPPN 的开源版本,但在我的研究中,我想为定制目的构建自己的实现,这比我最初预期的要复杂得多。因此,我想对 CPPN 背后的理论以及如何实现它们进行全面的解释,以便像我一样与 CPPN 斗争的每个人都可以获得这样的资源。这篇文章将分成两个独立的部分。您现在正在阅读的第一部分将关注 CPPN 背后的理论以及它们是如何在科学研究中使用的,而第二部分将关注用 Python 实际实现 CPPN。

这是什么鬼东西?CPPNs 理论

在1中提出,CPPNs 是对以前提出的神经网络的扩展,称为 NEAT 2。这些类型的神经网络非常相似,所以我将概述 NEAT 背后的一些理论,然后快速说明 CPPNs 的不同之处(别担心,它们几乎是相同的)。首先,NEAT 是一个用遗传算法进化的扩充拓扑神经网络。对这意味着什么的解释可以分成两个相关的概念:进化/遗传算法和扩充拓扑网络。

遗传算法

进化/遗传算法(GA)用于训练和优化神经网络的参数,类似于反向传播或爬山。然而,GA 不是使用导数来总是朝着改善损失的方向调整网络的权重,而是通过计算机版本的自然选择来找到最优的权重集,从达尔文主义和适者生存中汲取灵感。通过创建一个巨大的可能权重矩阵“群体”(通常约 25–100,但这可以变化),g a 可以评估群体中每个“个体”的损失,每个个体由一个唯一的权重矩阵表示。使用该信息,最佳权重矩阵然后被变异,彼此交叉,并被选择以前进到下一个“代”。通过在选择过程的许多代或迭代中重复该过程,GA 可以创建最小化损失的权重矩阵的最终群体,从而产生许多可能的性能最优的权重矩阵。

变异是通过随机扰动单个网络的权重来执行的,而交叉是通过将一个网络的权重与另一个网络的权重部分交换来执行的。这些概念对我来说总是有点困惑,所以这里是两组权重交叉和变异的直观表示:

Crossing Over Weight Matrices (found at https://github.com/lagodiuk/evo-neural-network-agents)

从上图中可以看出,在交叉过程中,很大一部分权重在权重矩阵之间交换,从而产生两个不同于原始“父”权重集的“子”权重集。在变异过程中,一些权重在随机方向上被扰动,以使“子”权重集与原始权重集略有不同。

这种变异、交叉和选择生存的最佳权重矩阵的过程重复许多代,直到你剩下最佳权重矩阵的最终群体。使用这种方法,只有最好的解决方案才能进入下一代,以便进一步变异、交叉和探索。因此,随着时间的推移,使用达尔文的适者生存原则来优化种群。如果你很好奇,想了解更多关于 GA 的知识,我鼓励你查看这个链接,它比我在这里给出的解释要深入得多。

扩充拓扑神经网络

通常,遗传算法在一组结构相同的网络上工作。扩充拓扑神经网络也利用 GA,但是它们允许 GA 在进化期间操纵神经网络的结构(不仅仅是权重),从而允许找到神经网络的最佳结构/拓扑。在进化之初,所有神经网络都是用完全连接到输出的输入来初始化的,没有隐藏节点——这是一个非常简单的最小结构。然而,随着拓扑的增加,随着神经网络的权重“进化”,网络的结构同时被优化——这在典型的 GA 优化中不会发生。为了探索可能的网络拓扑,当允许扩充拓扑时,GA 通过添加隐藏节点、添加更多的连接、甚至删除群体中某些拓扑内的现有连接来增加网络的复杂性。因此,虽然网络在进化之初结构简单,但它们的拓扑结构会进化到产生更高的性能,从而允许训练创建更复杂的网络结构。扩充拓扑的概念是 NEAT/CPPN 背后的核心思想,在我看来,这也是模型如此强大的原因。下图直观地展示了在进化过程中拓扑突变是如何应用于网络的:

Mutating Neural Network Structure 2

在上图中,一个现有的连接被拆分为两个新的连接,并且在这两个连接之间添加了一个节点。除了这种类型的拓扑突变(称为节点突变),NEAT 还有向网络中添加连接的拓扑突变(连接添加突变)和从网络中删除连接的拓扑突变(连接删除突变)。这种拓扑扩充导致最终的网络群体在结构上非常多样化,但都完成类似的任务-群体中的每个网络可能具有不同的拓扑,以不同的方式解决问题。

CPPN 和 NEAT 的区别?

既然您对 NEAT 有了很高的理解,您可能会好奇为什么我要写一个与标题中提到的(CPPN)完全不同的网络类型,但是这两者之间的区别非常简单。CPPN 允许每个节点包含从可能的激活功能列表中选择的唯一激活功能,而不是在每个节点中使用相同的激活功能。该激活列表可能包括 sin、cos、tanh、sigmoid、relu 或您可能想要包括的任何其他激活函数。允许神经网络包含许多不同的激活函数,反过来,允许它对展示所有这些不同激活的属性的函数进行建模,并创建模式化的、对称的和独特的输出。由于 CPPN 能够创建如此复杂和有趣的几何图形,因此它的目的是生成各种 2D 和 3D 形状。CPPN 的输入是像素的 x 和 y(甚至可能是 z)位置,它输出该输入位置的像素值(在[0,1]或[白色、黑色]之间)。对 2D 或 3D 空间内的每个可能的像素位置重复这种激活,以产生完整的输出形状。下图显示了 CPPN 的典型激活:

2D CPPN Activation 1

在该图像中,可以观察到像素的 x 和 y 位置被输入到 CPPN 中,并且在该 x 和 y 位置的像素的强度值被输出。CPPN 中的每个节点都包含一个独特的激活函数,该函数根据输入值以不同方式影响输出值。通过对 2D 或 3D 空间内的每个像素位置执行 CPPN 的激活,可以创建有趣的结构和图案,如下所示:

CPPN Black and White Output 1

CPPN Color Output (found on picbreeder.com)

从上面的输出中可以看出,CPPN 产生规则和对称形状的能力非常适合于发展类似艺术品、活生物体和许多其他有趣几何形状的结构。在我看来,这样的应用和能力非常有趣,这也是为什么我觉得研究 CPPNs 如此有趣。

演进中的 CPPNs 的细节

在进化开始时,cppn 的群体以不包含隐藏节点的简单结构初始化,但是,由于 cppn 的扩充拓扑特征,随着进化的继续和拓扑突变的应用,群体变得越来越复杂。在每一代中,额外的节点和连接被添加到网络结构中,从而产生越来越复杂且更适于解决预期问题的网络。然而,认识到群体中的所有网络不会同时突变是非常重要的,因此,每个网络可能具有与群体中其他 CPPNs 不同的拓扑结构。网络拓扑之间缺乏一致性使得 cppn 的发展变得有些独特和困难,因此我认为有必要解释一些 cppn 通常如何发展以及如何处理这种缺乏结构一致性的细节。

历史标记

每次一个新的连接被添加到 CPPN 的拓扑结构中,它都会被赋予一个“历史标记”或“创新号”,这只是一个特定连接所特有的整数。添加到群体中每个 CPPN 的每个连接都被赋予一个唯一的历史标记。随着连接在整个进化过程中的增加,全局计数器被维护并递增,使得分配的每个历史标记都是唯一的。这样的历史标记允许你理解人口中每个联系的历史和血统。此外,当结构在进化过程中相互交叉时,人们可以使用历史标记来观察哪些连接具有相似的进化血统。通过对添加的连接执行这种简单的簿记,进化 CPPNs 的几个方面被大大简化。在下图中,你可以观察到一个连接列表及其对应的创新编号(创新编号和历史标记是一回事!).

List of Connections 2

请注意,上图中的每个连接都被分配了一个创新号,并且每个连接的创新号都是唯一的。这允许您确定群体中的哪些网络共享共同的连接,从而从相同的结构中派生出来。

cppn 的交叉

如前所述,用遗传算法进化神经网络的一部分涉及交叉——在网络之间交换权重值以创建新的网络。对于遗传算法神经网络的典型进化,交叉是非常简单的。下图显示了相同拓扑网络之间常见的交叉类型:

Different Types of Crossover

对于扩充拓扑 CPPNs 的发展,由于两个网络之间的权重数目可能不相同,交叉变得稍微复杂。然而,创新数字的使用大大简化了这一过程。不是试图找到一种特殊的方法来决定哪些权重相互交叉,而是只交叉具有相同创新数的权重。因此,可以简单地通过在两个网络之间找到具有相等新息数的连接并交换它们的权重来执行交叉,从而产生 CPPNs 之间的伪一致交叉。

通过物种形成保护多样性

随着拓扑突变(新的连接和节点)被添加到群体中的 CPPNs 的拓扑中,这种突变通常会导致适应度的初始下降。这种适应度的降低是由这样的事实引起的,即在初始化时放入网络的新权重是随机的,并且尽管拓扑变化可以提供更优的结构,但是在网络实现其全部潜力之前必须训练这样的权重。网络中的这种新的随机权重通常会导致网络的适应性最初下降,然后在权重被训练后提高。如果我们不保护这样的网络不被选择,允许它们有时间训练并实现它们的最大适应度,它们将被 GA 立即从种群中淘汰,这将阻止 CPPNs 探索更复杂的结构。幸运的是,这样的新结构可以通过一个叫做“物种形成”的重要概念得以保存。

就个人而言,物种形成是我在研究 cppn 时最难理解的概念,但没有它,cppn 就无法有效进化。物种形成背后的基本概念是,当被选择用于下一代时,cppn 应该只与具有相似拓扑结构的 cppn 竞争。这样,如果通过变异创建了具有新的更复杂拓扑的网络,它将不必与已经达到其最大适应度的不太复杂的拓扑竞争,从而给更复杂的网络时间来训练和提高其适应度。拓扑的相似性通过比较网络之间的新息数来评估——如果网络有许多具有相同新息数的连接,则它们更相似,反之亦然。使用这样的信息,当执行选择时,基于新息数距离度量,CPPNs 被分成几个“种类”,或者具有相似拓扑的不同组。一旦这些物种形成,对每个物种分别进行选择,允许 CPPNs 只与它们物种的其他成员竞争。这种方法允许具有新的不同结构的 CPPNs 存在足够长的时间用于训练和优化,以发现这种拓扑是否是最佳的。

CPPN 演进总结

如果你理解了发展 cppn 的所有这些特殊细节,你就对 cppn 背后的理论有了很好的理解,并且可能理解使用 cppn 发表的大多数论文和项目。我相信这张图很好地总结了这些细节:

Evolution Details 2

如上图所示,要进化的 CPPNs 的群体从最低限度开始——完全连接,在任何结构中都没有隐藏节点。随着进化的进行,拓扑和重量突变被应用于 CPPNs,这允许它们生长,在结构上变得更复杂,并优化它们的参数。当新的连接被添加到 CPPNs 中时,它们每个都被赋予一个唯一的历史标记(或创新号),允许识别相似的连接。然后,这些历史标记可以用于创建不同网络拓扑之间的距离/相似性度量,这允许基于它们的网络结构将 CPPNs 分成不同的物种。通过对每个物种分别进行选择,允许新的 CPPN 拓扑在选择和进化中存活足够长的时间,以探索它们的能力,从而允许找到并优化最佳网络结构。

涉及 CPPN 的项目/研究示例

既然你已经理解了 cppn 是如何工作的,以及它们能做的很酷的事情,那么看看一些用 cppn 完成的研究项目可能会有所帮助,其中一些项目在计算进化领域相当有影响力。

pic breader 网站

在研究 CPPNs 时面临的最初问题之一是,在许多情况下,很难确定某个网络的适合度。每个 CPPN 输出一个独特的形状或图像,给这样的输出分配一个适合度是非常主观的——用户必须根据他们的偏好来确定适合度。Picbreeder.com 是一个作为研究项目开发的网站,完全基于用户的偏好,大规模地众包 CPPNs 的演变。使用 CPPNs 编码许多不同的图像,该网站允许用户选择他们喜欢的图像,并通过不断选择图像的变异版本来进一步进化它们。进化甚至可以在以后由不同的用户在相同的图像上继续。这样一个平台允许 CPPNs 完全基于主观用户输入,进化了令人难以置信的多代,这导致了各种有趣输出的集体创造。以下是网站上一些图片的例子:

Top Images on picbreeder.com

正如上面所看到的,一些非常有趣和令人印象深刻的图像是通过这样的合作进化创造出来的。此外,这项研究中的进化结果有效地证明了 CPPNs 的许多有价值的特性,使它们变得有用和有趣。例如,考虑下面一组也是使用 picbreeder 开发的图像:

Living Organism Images from picbreeder.com

从上面的图像中可以清楚地看到,CPPNs 可以产生类似于活生物体的对称和规则的几何形状,这是它们产生的主要动机之一。因此,picbreeder.com 进化的结果巩固了 CPPNs 在实现这一目的方面的有效性。

软体机器人进化

已经发表了许多论文来探索具有图像的 CPPNs 的 2D 应用,但是我发现许多最有趣的应用涉及 3D 形状的产生。CPPNs 最突出的 3D 应用之一是研究由 CPPNs 间接编码以实现最大行驶距离的软机器人的进化。现在,你可能在想“等等,到底什么是软体机器人”,所以这里有一张本文中软体机器人的快速图片:

Soft Robot Example 3

在这项研究中,软机器人是通过向 3D 空间添加材料来创建的,这些材料可以以不同的方式扩展和收缩(因此是“软”机器人),这使得机器人像生命体一样移动。这些软机器人是通过用不同类型的体素(3D 像素)填充 3D 空间(或者没有体素/空白空间)来创建结构而创建的。每种类型的体素(由不同的颜色表示)不同地收缩或松弛,从而当配对在一起时,体素的运动可以产生结构的整体运动。这种结构是通过查询输出空间中每个可能的体素位置处的 CPPN 以产生每个体素的类型和存在的输出来创建的。在这项研究中,该模型还使用距空间中心的距离(d)作为输入,但我发现对位置输入值进行归一化可以减少网络中的参数数量,并且表现类似。如果您仍然有一点困惑,这里是 CPPNs 如何在这个项目中用于创建软机器人输出的可视化:

Creating a Soft Robot with CPPN 3

每个结构都通过模拟来评估,模拟确定了每个软机器人在给定时间内移动的距离。这项研究成功地进化出了能够移动最大距离的 CPPNs,有趣的是,这些进化的结构中有许多在移动中类似于活的有机体(如果你感兴趣,请查看这个视频)。).此外,当这个问题试图只使用软机器人的直接编码(直接存储结构中每个体素的值)并用 GA 进化时,它根本不起作用,从而证明了 CPPNs 在创建逼真的功能性生物方面的有用性和有效性。以下是这项研究中进化出的一些最好的软体机器人的图片:

Set of Results from Soft Robot Evolution 3

其他论文/研究

有很多论文探讨了 CPPNs 的有效性和功能,但是写这些文章可能会花费很长时间(我相信您已经厌倦了阅读)。因此,以下是我在研究过程中发现的一些关于 CPPNs 的有用且有趣的额外论文:

  1. 上传任何物体并进化它:将复杂的几何图案注入 CPPNs 以进一步进化
  2. 在一个开放的、互动的进化系统中,管道化和可进化性的出现
  3. 受发育生物学启发,用生殖编码进化三维物体

结论

非常感谢你的阅读!我希望您现在对 CPPNs 以及如何使用它们有了更好的理解。如果你很好奇,想了解更多关于 CPPN 的知识,我真的鼓励你访问 NEAT 的网页,它是由 NEAT 的创建者创建的,允许研究人员分享关于 NEAT 的想法和方法(记住,NEAT 几乎与 CPPN 相同,所以大多数想法/技巧都适用于两者!).此外,请随时在 LinkedIn上联系我或者在 GitHub 上关注我。

引文

1 K. O .斯坦利一种新的发展抽象。遗传编程和进化机器,2007。

2 K. O .斯坦利和 r .米库拉宁。通过扩充拓扑进化神经网络。进化计算,2002。

3 Cheney,n .,MacCurdy,r .,Clune,j .和 Lipson,h.《解开束缚的进化:用多种材料和强大的生成编码进化出柔软的机器人》。遗传和进化计算会议论文集。纽约计算机学会,2013 年。

理解混淆矩阵

原文:https://towardsdatascience.com/understanding-confusion-matrix-a9ad42dcfd62?source=collection_archive---------0-----------------------

Understanding Confusion Matrix [Image 1] (Image courtesy: My Photoshopped Collection)

当我们得到数据后,经过数据清理、预处理和争论,我们做的第一步是把它输入到一个优秀的模型中,当然,得到概率输出。但是坚持住!我们到底如何衡量我们模型的有效性。效果越好,性能越好,这正是我们想要的。这也是混淆矩阵引人注目的地方。混淆矩阵是机器学习分类的性能度量。

本博客旨在回答以下问题:

  1. 混淆矩阵是什么,为什么需要它?
  2. 如何计算二类分类问题的混淆矩阵?

今天我们就来一劳永逸的了解一下混淆矩阵。

什么是混淆矩阵,为什么你需要它?

嗯,这是对机器学习分类问题的性能测量,其中输出可以是两个或更多个类。这是一个包含预测值和实际值的 4 种不同组合的表格。

Confusion Matrix [Image 2] (Image courtesy: My Photoshopped Collection)

它对测量召回率、精确度、特异性、准确性以及最重要的 AUC-ROC 曲线非常有用。

我们从怀孕类比的角度来理解 TP,FP,FN,TN。

Confusion Matrix [Image 3] (Image courtesy: My Photoshopped Collection)

真阳性:

解读:你预测的是正的,这是真的。

你预言一个女人怀孕了,她真的怀孕了。

真否定:

解读:你预测的是负数,这是真的。

你预言一个男人不会怀孕,他实际上也没有。

假阳性:(1 型错误)

解读:你预测的是正的,是假的。

你预言一个男人怀孕了,但他实际上没有。

假阴性:(2 型错误)

解读:你预测的是负数,这是假的。

你预测一个女人不会怀孕,但她确实怀孕了。

请记住,我们将预测值描述为正和负,将实际值描述为真和假。

Actual vs Predicted values [Image 4] (Image courtesy: My Photoshopped Collection)

如何计算二类分类问题的混淆矩阵?

让我们通过数学来理解混淆矩阵。

Confusion Matrix [Image 5 and 6] (Image 5 courtesy: My Photoshopped Collection) (Image 6 courtesy: I can not find the source. If you know please comment. I will provide appropriate citations. 😄)

召回

Recall [Image 7] (Image courtesy: My Photoshopped Collection)

上面的等式可以解释为,从所有的正类中,我们正确预测了多少。

召回率要尽可能高。

精度

Precision [Image 8] (Image courtesy: My Photoshopped Collection)

上面的等式可以解释为,从我们预测为正的所有类中,有多少实际上是正的。

精度要尽可能高。

精度

从所有的类(正类和负类)中,我们正确预测了多少。在这种情况下,它将是 4/7。

精确度应该尽可能高。

F-measure

F1 Score [Image 9] (Image courtesy: My Photoshopped Collection)

低精度和高召回率的两个模型很难比较,反之亦然。所以为了使它们具有可比性,我们使用 F-Score。F-score 有助于同时衡量查全率和查准率。它用调和平均值代替算术平均值,更多地惩罚极值。

我希望我已经让你对混淆矩阵有了一些基本的了解。如果你喜欢这篇文章,给这篇文章一些掌声会对你有所帮助👏。我随时欢迎你的问题和建议。你可以在脸书、推特、Linkedin 上分享这个,这样有需要的人可能会偶然发现这个。

您可以通过以下方式联系到我:

领英:https://www.linkedin.com/in/narkhedesarang/

推特:【https://twitter.com/narkhede_sarang

github:【https://github.com/TheSarang

感谢阅读!

理解卷积神经网络

原文:https://towardsdatascience.com/understanding-convolutional-neural-networks-221930904a8e?source=collection_archive---------3-----------------------

在这篇博文中,我们将探索(或至少尝试)卷积神经网络背后的直觉,卷积神经网络是机器视觉和图像识别中最重要的深度学习技术之一。我们还将通过一个例子来使用卷积神经网络识别不同的形状。

一些背景

随着人工智能的突破继续吸引着普通公众,诸如*、【人工智能】、、【机器学习】、、【深度学习】、等术语已经被互换使用。为了更好地了解人工智能在未来几年的发展方向,理解每个术语之间的差异绝对是值得的。*

The concentric circles of Artificial Intelligence

我们可以将这三个术语视为同心圆,人工智能包含机器学习,机器学习包含深度学习。我们可以更深入地研究人工智能的历史以及这一进步是如何产生的——但是关于这个话题已经讨论了很多。

简而言之,人工智能是计算机系统的发展,它执行通常保留给人类认知的任务。例如,尽管是一个硬编码系统,但计算器是一种人工智能。用于开发这种系统的技术是这些同心圆的关键。

机器学习围绕着创建可以从大型数据集学习有用模式的系统,并因此提供有用的见解。机器学习本身分为三个主要类别——第一个是监督学习,它需要创建理解一组数据点*(上下文)和标签(结果)之间关系的系统,从而提供未标记数据点的结果。此类系统的示例包括对贷款申请是否会导致违约进行分类的系统、预测未来股票价格的系统等。或者,无监督学习正在构建能够简单地基于相似特征或特性从数据集中识别有意义模式的系统。例如,根据相似的购物行为对客户进行聚类。最后,强化学习是机器学习的一个分支,它试图将智能代理置于一个定义明确的环境中,有一组可能的动作和一个目标函数(奖励)要最大化。我们可以想到自动驾驶汽车(代理)行驶在高速公路上(环境)其唯一的目标是不发生事故(奖励)*例如。

最后,深度学习是一种在机器学习中使用的技术,它利用大量数据和多层神经网络*(可以在这里找到神经网络的优秀遍历*),以便理解数据集内的模式。最近人工智能在计算机视觉和语音识别等方面的突破几乎都回到了深度学习研究,更重要的是计算能力的商品化(一篇关于计算能力在人工智能研究中的使用的有趣博客文章可以在这里找到*)*。**

直观地说,把机器学习想象成对孩子大脑建模的尝试。儿童从他人的动作中学习(监督学习)试图辨别世界上不同物体之间的相似性,例如将形状相似的乐高积木组合在一起(无监督学习)并在没有直接输入的情况下导航困难的环境,例如攀登架(强化学习)。深度学习是机器学习中的一种技术,是人工智能最近突破的根源。

什么是卷积神经网络?

在深度学习中,出现了大量的架构和技术,可以实现许多用例,其中主要是卷积神经网络。卷积神经网络的灵感来自于对哺乳动物视觉皮层的研究,以及它们如何使用大脑中神经元的分层结构来感知世界。把这个视觉皮层模型想象成专门设计来识别不同形状的神经元群。每组神经元在看到一个物体时都会放电,并相互交流,以形成对感知物体的整体理解。

Different groups of neurons in the brain learn to recognize different groups of characteristics given an input stimulus

该系统可以被解释为神经元的分级集群,其检测输入刺激的低级特征,并在该分级结构中相互通信,以开发对象的高级检测。
将层次结构想象成如下:

  • 第一个聚类作为识别低级特征的结构(即面部轮廓)
  • 第二类是识别颜色和形状的结构(肤色或颌线)
  • 第三个是识别细节的结构(耳朵、鼻子和眼睛……)
  • 最终聚类从整体上识别整个对象(脸部和附在脸部的人)

简单来说,给定一个物体的景象,该系统有不同组的神经元,它们针对该物体的不同方面激活,并相互通信以形成大画面。

Yann LeCun 从视觉皮层的分层模型中获得灵感,开发了卷积神经网络,包含以下内容:

  • 本地连接:每一层(或集群)共享一个连接,在那里它们将学习到的特性从一个集群转移到另一个集群。
  • 分层:在不同的层(或集群)之间有一个明显的层次——这类似于说从低级特征(即耳朵、眼睛)到高级特征(面部、所讨论的人等等)的学习中有一个层次。**
  • 空间不变性:输入的移动会导致输出的同等移动——无论我们如何改变输入图像,模型都应该相应地适应和移动其输出。(人类有能力识别一个物体,即使它在各种情况下颠倒或移动)

因此,卷积神经网络架构对应于类似这样的内容:

A typical Convolutional Neural Network Architecture

  • 其中 4D 矩阵形式的输入数据包括样本数(图像数)、每个样本的高度*(每个图像的高度)、每个样本的宽度(每个图像的宽度)、通道数(这里的通道数指的是每个图像的颜色规格——彩色图像对应于红色(R)、绿色(G)和蓝色(B)像素, 因此,每幅图像都有 3 个通道——把它想象成三个相互叠加的二维矩阵,每个矩阵对应于 RGB 像素的强度,而一幅灰色图像只有 1 个通道)*。 在我们的例子中,我们将只使用灰色图像。**
  • 我们的输入数据将被连接到一个隐藏的卷积层,该层在我们的图像上应用了许多任意尺寸的任意过滤器(通常是 3×3 或 5×5)。把滤镜想象成一个尺寸为 3 x 3 (或者 5 x 5) 的小手电筒,它试图理解我们的输入图像,并绘制出特征图。从特征图中,算法可以理解我们的数据中的局部特征*(眼睛、耳朵等),而不管其位置(平移不变性)*。我们可以看到卷积运算在这里有很大的显示:**

A convolution trying to capture low level features in a picture of buildings

  • 池化是一种子采样操作,通过应用任意大小的窗口(这被称为步幅)来减少提取的特征图的维度,并根据用户的指定提取窗口的总和、最大值或平均值。在这种情况下,我们将使用最大池,对于特征图中的每个 2 x 2 窗口,我们提取最高值。这项技术帮助我们在保留信息的同时降低维度。我们可以看看下面这个操作:

  • 最后,产生 Softmax 输出的传统全连接层接收卷积和 max 池层的学习表示,并输出预测。简而言之,全连接层是神经网络中的一层,它包含当观察到某个模式时会“点亮”的节点。卷积神经网络的更详细的分解及其背后的数学可以在这里找到。

直观地说,卷积神经网络接受图像作为输入,试图破译图像的不同小特征(局部连接)而不管它们的位置(空间不变性)使用一系列数学运算(分层,汇集),以便理解正在发生的事情的全貌。这些数学运算将图像建模为一系列数字,每个数字代表像素密度*(图片上特定位置的颜色强度)。***

一个工作实例

这里可以找到一个更详细的笔记本,上面有所有的实用功能和结果。

我们的数据集是一组几何形状(三角形、圆形和矩形),可以放置在 72 x 72 的网格中的任何位置。这些图片只有一个通道,因为它们是灰度级的。我们可以在下面看到这些图像的例子:**

**

Random triangles, circles and rectangles that can have any position in the grid — utility functions on how to produce them can be found in the github link above.**

我们将使用 python 上的 Keras 包(Keras 实现卷积神经网络的详细文档可以在这里找到)来开发一个卷积神经网络,它将能够以高达 98%的准确度对每个形状进行分类。

最终,卷积神经网络代表了图像识别的一个重大突破。自动驾驶汽车、面部识别系统和医疗诊断是卷积神经网络能够实现的几个用例。然而,值得注意的是,随着新技术的出现,仍然有增长的空间。

使用 Excel 了解神经网络

原文:https://towardsdatascience.com/understanding-convolutions-using-excel-886ca0a964b7?source=collection_archive---------1-----------------------

熟悉深度学习的 TL: DR 方法

为了简化卷积神经网络的概念,我将尝试解释在开发您的深度学习模型时会发生什么。要了解更多信息,我建议在网上搜索,因为这里有大量的信息(比如这个视频)。这个解释来源于 fast.ai 库。

这张简单神经网络的图片基本上代表了这个例子中发生的事情。

Simple Neural Network

输入层

7 号图像数据来自 MNIST 数据库,我们假设您使用预训练模型进行分类。

You can see the 7 by the larger numbers in the data

隐藏层 1

隐藏图层是对输入进行转换,以便从输出图层的数据中识别更复杂的要素,从而做出更好的评估。

两个过滤器将代表不同的形状-第一个过滤器设计用于检测水平边缘,第二个过滤器检测垂直边缘。这个 3x3 滤波器被称为卷积核。针对输入中的水平边缘激活滤波器 1。Conv1 显示了对输入的 3x3 部分进行处理并乘以卷积内核后两者的激活情况。下面的一张图给了你一个更好的想法。

*虽然这在 2d 数组中表示,但它们应该作为张量堆叠在一起。其中每个矩阵代表张量中的一个切片。这些本质上都是正在发生的行操作(线性代数)。

=SUM(F11:H13*$AD$11:$AF$13)是发生的卷积。

该求和将导致输入中特定 3×3 点的激活数为 3。

This this would represent a single layer.

激活功能

接下来,我们使用非线性单元,通过使用 RELU 作为我们的激活函数来消除负面影响。接下来我们可以看到底片在下一张图中消失了。

隐藏第二层

接下来,我们做另一个卷积。Conv2 将是下一个隐藏层。这将对 Conv1 中的两个矩阵进行加权,取其和积。这里的卷积核将表示一个 2X3X3 张量。

使用 RELU 后,我们现在已经创建了我们的第二层。

Layer 1 and 2

最大池化

通过只取 Conv2 中 2x2 部分的最大值,Max pooling 将达到高度和宽度分辨率的一半。在 Maxpool 矩阵中,我们可以看到 Conv2 的 2x2 部分的最大值,即 33。池的计算速度比卷积快。同样,它给了你一些平移不变性。

输出层

接下来,我们通过在 Maxpool 中获取所有激活并给它们一个权重来构建我们的全连接层。这是通过做一个矩阵乘积来实现的。在 excel 中,我们将获取激活和权重的和积。因此,与之前解析卷积层中的每个部分不同,全连接层(密集层)将对卷积层提取并由最大池层缩减采样的特征执行分类。

这个例子只代表一个类,也就是一个数字。我们还得把剩下的数字分类。

了解 Scikit 中的数据科学分类指标-了解 Python

原文:https://towardsdatascience.com/understanding-data-science-classification-metrics-in-scikit-learn-in-python-3bc336865019?source=collection_archive---------0-----------------------

在本教程中,我们将浏览 Python 的 scikit 中的一些分类指标——从头开始学习并编写我们自己的函数,以理解其中一些函数背后的数学原理。

数据科学中预测建模的一个主要领域是分类。分类包括试图预测总体中某个特定样本来自哪个类别。例如,如果我们试图预测某个特定的患者是否会再次住院,两个可能的类别是住院(阳性)和未住院(阴性)。然后,分类模型会尝试预测每个患者是否会住院。换句话说,分类只是试图预测来自总体的特定样本应该放在哪个桶中(预测正对预测负),如下所示。

当您训练您的分类预测模型时,您会想要评估它有多好。有趣的是,有许多不同的方法来评估性能。大多数使用 Python 进行预测建模的数据科学家都使用名为 scikit-learn 的 Python 包。Scikit-learn 包含许多用于分析模型性能的内置函数。在本教程中,我们将遍历其中一些指标,并从头开始编写我们自己的函数,以理解其中一些指标背后的数学原理。如果你更喜欢阅读性能指标,请点击这里查看我在的上一篇文章。

本教程将涵盖来自sklearn.metrics的以下指标:

  • 困惑 _ 矩阵
  • 准确性 _ 得分
  • 回忆 _ 分数
  • 精度分数
  • f1 _ 分数
  • roc _ 曲线
  • roc_auc_score

G 开始了

关于样本数据集和 jupyter 笔记本,请访问我的 github 这里。假设有两个类,我们将从头开始编写自己的函数。请注意,您需要填写标记为# your code here的部分

让我们加载一个样本数据集,它具有实际标签(actual_label)和两个模型的预测概率(model_RF 和 model_LR)。这里的概率是第一类的概率。

import pandas as pd
df = pd.read_csv('data.csv')
df.head()

在大多数数据科学项目中,您将定义一个阈值来定义哪些预测概率被标记为预测正与预测负。现在让我们假设阈值是 0.5。让我们添加两个额外的列,将概率转换为预测标签。

thresh = 0.5
df['predicted_RF'] = (df.model_RF >= 0.5).astype('int')
df['predicted_LR'] = (df.model_LR >= 0.5).astype('int')
df.head()

困惑 _ 矩阵

给定一个实际标签和一个预测标签,我们可以做的第一件事是将样本分成 4 个桶:

  • 真正值-实际值= 1,预测值= 1
  • 假阳性-实际= 0,预测= 1
  • 假阴性-实际= 1,预测= 0
  • 真负值-实际值= 0,预测值= 0

这些桶可以用下面的图像表示(原始源https://en . Wikipedia . org/wiki/Precision _ and _ recall #/media/File:Precision recall . SVG),我们将在下面的许多计算中引用这个图像。

这些存储桶也可以使用如下所示的混淆矩阵来显示:

我们可以从 scikit-learn 获得混淆矩阵(作为 2x2 数组),它将实际标签和预测标签作为输入

from sklearn.metrics import confusion_matrixconfusion_matrix(df.actual_label.values, df.predicted_RF.values)

其中有 5047 个真阳性,2360 个假阳性,2832 个假阴性和 5519 个真阴性。让我们定义自己的函数来验证confusion_matrix。注意,第一个我填了,另外 3 个你需要填。

def find_TP(y_true, y_pred):
    # counts the number of true positives (y_true = 1, y_pred = 1)
    return sum((y_true == 1) & (y_pred == 1))
def find_FN(y_true, y_pred):
    # counts the number of false negatives (y_true = 1, y_pred = 0)
    return # your code here
def find_FP(y_true, y_pred):
    # counts the number of false positives (y_true = 0, y_pred = 1)
    return # your code here
def find_TN(y_true, y_pred):
    # counts the number of true negatives (y_true = 0, y_pred = 0)
    return # your code here

您可以检查您的结果是否与

print('TP:',find_TP(df.actual_label.values, df.predicted_RF.values))
print('FN:',find_FN(df.actual_label.values, df.predicted_RF.values))
print('FP:',find_FP(df.actual_label.values, df.predicted_RF.values))
print('TN:',find_TN(df.actual_label.values, df.predicted_RF.values))

让我们写一个函数来计算这四个参数,然后再写一个函数来复制confusion_matrix

import numpy as np
def find_conf_matrix_values(y_true,y_pred):
    # calculate TP, FN, FP, TN
    TP = find_TP(y_true,y_pred)
    FN = find_FN(y_true,y_pred)
    FP = find_FP(y_true,y_pred)
    TN = find_TN(y_true,y_pred)
    return TP,FN,FP,TN
def my_confusion_matrix(y_true, y_pred):
    TP,FN,FP,TN = find_conf_matrix_values(y_true,y_pred)
    return np.array([[TN,FP],[FN,TP]])

检查您的结果是否与匹配

my_confusion_matrix(df.actual_label.values, df.predicted_RF.values)

不要手动比较,让我们使用 Python 的内置assert 和 numpy 的array_equal 函数来验证我们的函数工作正常

assert  np.array_equal(my_confusion_matrix(df.actual_label.values, df.predicted_RF.values), confusion_matrix(df.actual_label.values, df.predicted_RF.values) ), 'my_confusion_matrix() is not correct for RF'assert  np.array_equal(my_confusion_matrix(df.actual_label.values, df.predicted_LR.values),confusion_matrix(df.actual_label.values, df.predicted_LR.values) ), 'my_confusion_matrix() is not correct for LR'

给定这四个桶(TP,FP,FN,TN),我们可以计算许多其他性能指标。

准确性 _ 得分

最常见的分类指标是准确度,即预测正确的样本比例,如下所示:

我们可以从 scikit-learn 获得准确度分数,它将实际标签和预测标签作为输入

from sklearn.metrics import accuracy_scoreaccuracy_score(df.actual_label.values, df.predicted_RF.values)

你的答案应该是 0。38660 . 68868686861

使用上面的公式,定义你自己的复制accuracy_score的函数。

def my_accuracy_score(y_true, y_pred):
    # calculates the fraction of samples predicted correctly
    TP,FN,FP,TN = find_conf_matrix_values(y_true,y_pred)  
    return # your code hereassert my_accuracy_score(df.actual_label.values, df.predicted_RF.values) == accuracy_score(df.actual_label.values, df.predicted_RF.values), 'my_accuracy_score failed on RF'
assert my_accuracy_score(df.actual_label.values, df.predicted_LR.values) == accuracy_score(df.actual_label.values, df.predicted_LR.values), 'my_accuracy_score failed on LR'
print('Accuracy RF: %.3f'%(my_accuracy_score(df.actual_label.values, df.predicted_RF.values)))
print('Accuracy LR: %.3f'%(my_accuracy_score(df.actual_label.values, df.predicted_LR.values)))

使用精确度作为性能度量,RF 模型比 LR 模型(0.62)更精确(0.67)。那么我们是否应该就此打住,说 RF 模型是最好的模型呢?不要!准确性并不总是评估分类模型的最佳指标。例如,假设我们试图预测一件 100 次中只有 1 次发生的事情。我们可以建立一个模型,通过说事件从未发生,获得 99%的准确性。然而,我们抓住了 0%我们关心的事件。这里的 0%度量是另一个称为召回的性能度量。

回忆 _ 分数

回忆(也称为敏感度)是您正确预测的阳性事件的比例,如下所示:

我们可以从 scikit-learn 获得准确度分数,它将实际标签和预测标签作为输入

from sklearn.metrics import recall_scorerecall_score(df.actual_label.values, df.predicted_RF.values)

使用上面的公式定义您自己的复制recall_score的函数。

def my_recall_score(y_true, y_pred):
    # calculates the fraction of positive samples predicted correctly
    TP,FN,FP,TN = find_conf_matrix_values(y_true,y_pred)  
    return # your code hereassert my_recall_score(df.actual_label.values, df.predicted_RF.values) == recall_score(df.actual_label.values, df.predicted_RF.values), 'my_accuracy_score failed on RF'
assert my_recall_score(df.actual_label.values, df.predicted_LR.values) == recall_score(df.actual_label.values, df.predicted_LR.values), 'my_accuracy_score failed on LR'
print('Recall RF: %.3f'%(my_recall_score(df.actual_label.values, df.predicted_RF.values)))
print('Recall LR: %.3f'%(my_recall_score(df.actual_label.values, df.predicted_LR.values)))

提高召回率的一种方法是通过降低预测阳性的阈值来增加您定义为预测阳性的样本数量。不幸的是,这也会增加误报的数量。另一个称为精度的性能指标考虑到了这一点。

精度分数

精度是预测的阳性事件中实际为阳性的部分,如下所示:

我们可以从 scikit-learn 获得准确度分数,它将实际标签和预测标签作为输入

from sklearn.metrics import precision_scoreprecision_score(df.actual_label.values, df.predicted_RF.values)

使用上面的公式,定义您自己的复制precision_score的函数。

def my_precision_score(y_true, y_pred):
    # calculates the fraction of predicted positives samples that are actually positive
    TP,FN,FP,TN = find_conf_matrix_values(y_true,y_pred)  
    return # your code hereassert my_precision_score(df.actual_label.values, df.predicted_RF.values) == precision_score(df.actual_label.values, df.predicted_RF.values), 'my_accuracy_score failed on RF'
assert my_precision_score(df.actual_label.values, df.predicted_LR.values) == precision_score(df.actual_label.values, df.predicted_LR.values), 'my_accuracy_score failed on LR'
print('Precision RF: %.3f'%(my_precision_score(df.actual_label.values, df.predicted_RF.values)))
print('Precision LR: %.3f'%(my_precision_score(df.actual_label.values, df.predicted_LR.values)))

在这种情况下,看起来 RF 模型在召回率和精确度上都更好。但是,如果一个模型更擅长回忆,而另一个模型更擅长精确,你会怎么做。一些数据科学家使用的一种方法叫做 F1 分数。

f1 _ 分数

f1 分数是召回率和精确度的调和平均值,分数越高,模型越好。f1 分数使用以下公式计算:

我们可以从 scikit-learn 获得 f1 分数,它将实际标签和预测标签作为输入

from sklearn.metrics import f1_scoref1_score(df.actual_label.values, df.predicted_RF.values)

使用上面的公式,定义您自己的复制f1_score的函数。

def my_f1_score(y_true, y_pred):
    # calculates the F1 score
    recall = my_recall_score(y_true,y_pred)  
    precision = my_precision_score(y_true,y_pred)  
    return # your code hereassert my_f1_score(df.actual_label.values, df.predicted_RF.values) == f1_score(df.actual_label.values, df.predicted_RF.values), 'my_accuracy_score failed on RF'
assert my_f1_score(df.actual_label.values, df.predicted_LR.values) == f1_score(df.actual_label.values, df.predicted_LR.values), 'my_accuracy_score failed on LR'
print('F1 RF: %.3f'%(my_f1_score(df.actual_label.values, df.predicted_RF.values)))
print('F1 LR: %.3f'%(my_f1_score(df.actual_label.values, df.predicted_LR.values)))

到目前为止,我们假设我们定义了 0.5 的阈值来选择哪些样本被预测为阳性。如果我们改变这个阈值,性能指标将会改变。如下图所示:

print('scores with threshold = 0.5')
print('Accuracy RF: %.3f'%(my_accuracy_score(df.actual_label.values, df.predicted_RF.values)))
print('Recall RF: %.3f'%(my_recall_score(df.actual_label.values, df.predicted_RF.values)))
print('Precision RF: %.3f'%(my_precision_score(df.actual_label.values, df.predicted_RF.values)))
print('F1 RF: %.3f'%(my_f1_score(df.actual_label.values, df.predicted_RF.values)))
print(' ')
print('scores with threshold = 0.25')
print('Accuracy RF: %.3f'%(my_accuracy_score(df.actual_label.values, (df.model_RF >= 0.25).astype('int').values)))
print('Recall RF: %.3f'%(my_recall_score(df.actual_label.values, (df.model_RF >= 0.25).astype('int').values)))
print('Precision RF: %.3f'%(my_precision_score(df.actual_label.values, (df.model_RF >= 0.25).astype('int').values)))
print('F1 RF: %.3f'%(my_f1_score(df.actual_label.values, (df.model_RF >= 0.25).astype('int').values)))

如果我们没有选择阈值,我们如何评估一个模型?一种非常常用的方法是使用受试者工作特性(ROC)曲线。

roc 曲线和 roc AUC 分数

ROC 曲线非常有助于理解真阳性率和假阳性率之间的平衡。Sci-kit learn 内置了 ROC 曲线和分析这些曲线的功能。这些函数(roc_curveroc_auc_score)的输入是实际标签和预测概率(不是预测标签)。roc_curveroc_auc_score都是复杂的函数,所以我们不会让你从头开始写这些函数。相反,我们将向您展示如何使用 sci-kit learn 的功能,并解释其中的关键点。让我们从使用roc_curve制作 ROC 图开始。

from sklearn.metrics import roc_curvefpr_RF, tpr_RF, thresholds_RF = roc_curve(df.actual_label.values, df.model_RF.values)
fpr_LR, tpr_LR, thresholds_LR = roc_curve(df.actual_label.values, df.model_LR.values)

roc_curve函数返回三个列表:

  • 阈值=按降序排列的所有唯一预测概率
  • fpr =每个阈值的假阳性率(FP / (FP + TN))
  • tpr =每个阈值的真实阳性率(TP / (TP + FN))

我们可以为每个模型绘制 ROC 曲线,如下所示。

import matplotlib.pyplot as pltplt.plot(fpr_RF, tpr_RF,'r-',label = 'RF')
plt.plot(fpr_LR,tpr_LR,'b-', label= 'LR')
plt.plot([0,1],[0,1],'k-',label='random')
plt.plot([0,0,1,1],[0,1,1,1],'g-',label='perfect')
plt.legend()
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.show()

从这个图中我们可以观察到一些东西:

  • 随机猜测标签的模型将导致黑线,并且您希望有一个在这条黑线上方有曲线的模型
  • 离黑线越远的 ROC 越好,所以 RF(红色)比 LR(蓝色)好看
  • 虽然不能直接看到,但高阈值会在左下角产生一个点,低阈值会在右上角产生一个点。这意味着,随着门槛的降低,你会以更高的 FPR 为代价获得更高的 TPR

为了分析性能,我们将使用曲线下面积指标。

from sklearn.metrics import roc_auc_scoreauc_RF = roc_auc_score(df.actual_label.values, df.model_RF.values)
auc_LR = roc_auc_score(df.actual_label.values, df.model_LR.values)print('AUC RF:%.3f'% auc_RF)
print('AUC LR:%.3f'% auc_LR)

如您所见,RF 模型的曲线下面积(AUC = 0.738)优于 LR (AUC = 0.666)。当我绘制 ROC 曲线时,我喜欢将 AUC 添加到图例中,如下所示。

import matplotlib.pyplot as plt
plt.plot(fpr_RF, tpr_RF,'r-',label = 'RF AUC: %.3f'%auc_RF)
plt.plot(fpr_LR,tpr_LR,'b-', label= 'LR AUC: %.3f'%auc_LR)
plt.plot([0,1],[0,1],'k-',label='random')
plt.plot([0,0,1,1],[0,1,1,1],'g-',label='perfect')
plt.legend()
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.show()

总体而言,在这个玩具示例中,RF 型号在所有性能指标上都胜出。

结论

在预测分析中,在两个模型之间做出决定时,选择一个性能指标非常重要。正如您在这里看到的,有许多选项可供选择(准确度、召回率、精确度、f1 分数、AUC 等)。最终,您应该使用最适合当前业务问题的性能指标。许多数据科学家更喜欢使用 AUC 来分析每个模型的性能,因为它不需要选择阈值,有助于平衡真阳性率和假阳性率。

如果您对如何改进本教程有任何建议,请留下您的评论。

理解描述性统计

原文:https://towardsdatascience.com/understanding-descriptive-statistics-c9c2b0641291?source=collection_archive---------0-----------------------

Descriptive Statistics [Image 1] (Image courtesy: My Photoshopped Collection)

统计学是数学的一个分支,处理数据的收集、解释、组织和解释。

最初,当我们获得数据时,我们不是应用花哨的算法并做出一些预测,而是首先尝试通过应用统计技术来阅读和理解数据。通过这样做,我们能够了解数据的分布类型。

本博客旨在回答以下问题:

1.什么是描述性统计?

2.描述性统计的类型?

3.集中趋势的度量(平均值、中值、众数)

4.扩散/分散的度量(标准偏差、平均偏差、方差、百分位数、四分位数、四分位数间距)

5.什么是偏斜度?

6.什么是峰度?

7.什么是相关性?

今天,让我们一劳永逸地了解一下描述性统计。我们开始吧,

什么是描述性 S 统计学?

描述性统计包括总结和组织数据,以便于理解。与推断统计学不同,描述统计学试图描述数据,但并不试图从样本中推断出总体。这里,我们通常描述样本中的数据。这通常意味着描述统计学不同于推断统计学,它不是在概率论的基础上发展起来的。

描述性统计的类型?

描述性统计分为两类。集中趋势的度量和可变性(传播)的度量。

集中趋势的度量

集中趋势是指有一个数字可以最好地概括整个测量集合,这个数字在某种程度上是集合的“中心”。

平均值/平均值

平均值是数据的中心趋势,即一个数字,整个数据围绕这个数字展开。在某种程度上,它是一个单一的数字,可以估计整个数据集的价值。

让我们计算有 8 个整数的数据集的平均值。

Image 2

中位数

中位数是将数据分成两个相等部分的值,即当数据按升序或降序排列时,其右侧的项数与左侧的项数相同。

注意:如果你按降序排列数据,不会影响中位数,但 IQR 会是负数。我们将在本博客稍后讨论 IQR。

如果项数是奇数,中值将是中间项

如果若干项是偶数,则中值将是中间两项的平均值。

Image 3

中位数是 59,它将一组数字分成相等的两部分。由于集合中有偶数,所以答案是中间数 51 和 67 的平均值。

注:当值为等差数列时(连续项之间的差为常数。这是 2 英镑。),则中值总是等于平均值

Image 4

这 5 个数字的平均数是 6,所以是中位数。

模式

众数是在数据集中出现次数最多的词,即出现频率最高的词。

Image 5

在这个数据集中,模式是 67,因为它比其余的值多,即两倍。

但是可能有一个数据集根本没有模式,因为所有的值都出现相同的次数。如果两个值同时出现并且多于其余的值,则数据集为双峰。如果三个值同时出现并且多于其余值,则数据集为三模态,对于 n 个模式,数据集为多模态

扩散/分散的度量

分布的度量指的是数据内部的可变性。

标准偏差

标准差是每个数量和平均值之间的平均距离的度量。也就是说,数据是如何从平均值展开的。低标准偏差表示数据点倾向于接近数据集的平均值,而高标准偏差表示数据点分布在更宽的值范围内。

有些情况下,我们必须在样本或总体标准差之间做出选择。

当我们被要求找出人口的某一部分,人口的一部分的标准差时;然后我们用样本标准差。

Image 6

其中 x̅是样本的平均值。

但是当我们必须处理整个人口时,我们使用人口标准差。

Image 7

其中是总体均值。

虽然样本是总体的一部分,但它们的标准差公式应该是相同的,但事实并非如此。要了解更多信息,请参考此链接

众所周知,在描述统计学中,我们通常处理样本中的数据,而不是总体中的数据。因此,如果我们使用以前的数据集,并替换示例公式中的值,

Image 8

答案是 29.62。

平均偏差/平均绝对偏差

它是一组值中每个值之间的绝对差值的平均值,也是该组中所有值的平均值。

Mean Deviation [Image 9] (Image courtesy: My Photoshopped Collection)

所以如果我们使用之前的数据集,并替换这些值,

Image 10

答案是 23.75。

差异

方差是每个数量和平均值之间平均距离的平方。也就是说它是标准差的平方。

Image 11

答案是 877.34。

范围

范围是描述统计学中最简单的技术之一。它是最低值和最高值之差。

Image 12

范围是 99–12 = 87

百分位数

百分位数是一种表示数据集中数值位置的方法。要计算百分位数,数据集中的值应该始终按升序排列。

Image 13

中位数 59 在 8 个值中有 4 个值比它本身小。也可以这么说:在数据集中,59 是第 50 百分位,因为总项的 50%小于 59。一般情况下,如果 k第 n 个百分位,则暗示总项数的 n% 小于 k

四分位数

在统计和概率中,四分位数是将数据分成四个部分的值,前提是数据按升序排序。

Quartiles [Image 14] (Image courtesy: https://statsmethods.wordpress.com/2013/05/09/iqr/)

有三个四分位值。第一个四分位值在 25 个百分点。第二个四分位数是 50 个百分点,第三个四分位数是 75 个百分点。第二个四分位数(Q2)是整个数据的中位数。第一个四分位数(Q1)是数据上半部分的中位数。第三个四分位数(Q3)是数据下半部分的中间值。

所以在这里,通过类比,

Q2 = 67:是整个数据的 50%并且是中间值。

Q1 = 41:是数据的 25 个百分点。

Q3 = 85:是日期的 75%。

四分位距(IQR) = Q3 - Q1 = 85 - 41 = 44

**注:**如果按降序排列数据,IQR 将为 -44 。大小相同,只是符号不同。如果你的数据是降序排列的,那么负 IQR 是可以的。只是我们从较大的值中否定较小的值,我们更喜欢升序排列(Q3 - Q1)。

偏斜度

偏斜度是实值随机变量关于其均值的概率分布的不对称性的度量。偏斜值可以是正的或负的,也可以是未定义的。

在完美的正态分布中,曲线两边的尾部是彼此的镜像。

当分布向左倾斜时,曲线左侧的尾部比右侧的尾部长,并且平均值小于众数。这种情况也叫负偏度。

当分布向右倾斜时,曲线右侧的尾部比左侧的尾部长,均值大于众数。这种情况也叫正偏度。

Skewness [Image 16] (Image courtesy: https://www.safaribooksonline.com/library/view/clojure-for-data/9781784397180/ch01s13.html)

偏度系数如何确定?

要计算样本的偏态系数,有两种方法:

1]皮尔逊第一偏度系数(众数偏度)

Image 17

2]皮尔逊第二偏度系数(中位数偏度)

Image 18

释义

  • 偏斜的方向由符号给出。零表示完全没有偏斜。
  • 负值意味着分布是负偏态的。正值意味着分布是正偏的。
  • 该系数将样本分布与正态分布进行比较。该值越大,分布与正态分布的差异就越大。

示例问题:使用皮尔逊系数#1 和#2 来找出具有以下特征的数据的偏斜度:

  • 平均值= 50。
  • 中位数= 56。
  • 模式= 60。
  • 标准偏差= 8.5。

皮尔逊第一偏度系数:-1.17。

皮尔逊第二偏度系数:-2.117。

:皮尔逊的第一个偏度系数使用了模式。因此,如果值的频率非常低,那么它不会给出集中趋势的稳定度量。例如,这两组数据中的模式都是 9:

1, 2, 3, 4, 4, 5, 6, 7, 8, 9.

在第一组数据中,该模式只出现了两次。因此,使用皮尔逊的第一偏斜系数并不是一个好主意。但是在第二盘,

1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 12, 12, 13.

模式 4 出现 8 次。因此,皮尔逊的第二偏度系数将可能给你一个合理的结果。

峭度

峰度测量的确切解释过去一直有争议,但现在已经确定了。是关于离群值的存在。峰度是数据相对于正态分布是重尾(大量异常值)还是轻尾(缺少异常值)的度量。

Kurtosis [Image 19] (Image courtesy: https://mvpprograms.com/help/mvpstats/distributions/SkewnessKurtosis)

峰度有三种类型

中层大气

中间峭度是具有与正态分布峭度相似的峭度的分布,正态分布峭度为零。

薄谷开来

分布是峰度大于中峰度分布的分布。这种分布的尾部又厚又重。如果分布曲线比中峰曲线更尖,则称之为细峰曲线。

鸭嘴兽

分布是峰度小于中峰度分布的分布。这种分布的尾部更薄。如果一条分布曲线的峰值小于一条中 kurtic 曲线,则称之为 Platykurtic 曲线。

偏度和峰度之间的主要差异在于,偏度指的是对称程度,而峰度指的是分布中异常值的存在程度。****

相互关系

相关性是一种统计技术,可以显示变量对是否相关以及相关程度如何。

Correlation [Image 20] (Image courtesy: http://www.statisticshowto.com/what-is-correlation/)

相关的主要结果称为相关系数(或“r”)。范围从-1.0 到+1.0。r 越接近+1 或-1,这两个变量的关系就越密切。

如果 r 接近 0,说明变量之间没有关系。如果 r 为正,这意味着随着一个变量变大,另一个也变大。如果 r 为负,这意味着一个变大,另一个变小(通常称为“逆”相关)。

我希望我已经让你对什么是描述性统计有了一些了解。这是一些基本统计技术的基本运行,可以帮助您从长远角度理解数据科学。

感谢阅读。

如果你喜欢这篇文章,给这篇文章一些掌声会对你有所帮助👏。我随时欢迎你的问题和建议。你可以在脸书、推特、Linkedin 上分享这个,这样有需要的人可能会偶然发现这个。

您可以通过以下方式联系到我:

领英:https://www.linkedin.com/in/narkhedesarang/

推特:【https://twitter.com/narkhede_sarang

github:【https://github.com/TheSarang

了解数据科学中的开发工具

原文:https://towardsdatascience.com/understanding-devsecops-in-data-science-93b695a0d8ab?source=collection_archive---------16-----------------------

一些软件开发方法已经重新定义了产品到达市场的方式和速度。DevOps 就是一个例子。

它将软件开发与信息技术相结合,注重高速度和比过去方法更短的开发生命周期。此外,那些坚持 DevOps 方法的人提供了频繁的特性和修复。

DevOps vs. DevSecOps

DevSecOps 是一种类似于 DevOps 的方法,因为它们都在一个敏捷的框架内,将项目分成更小的块。

然而,DevSecOps 将安全性融入了开发过程的每一步。它需要开发和安全部门之间的持续沟通——这两个部门通常直到后期才进行沟通。

值得注意的是,DevOps 和 DevSecOps 团队经常将自动化集成到他们的实践中。通过这种方式以及其他方式,这些方法的相似之处要多于不同之处。

DevSecOps 只是优先考虑安全性,这是一个开发人员可能了解有限的因素,除非问题导致 bug,否则不会过分关注。

一些分析师认为,比较 DevOps 和 DecSecOps 是没有用的,因为它们并不矛盾。相反,DevSecOps 代表了 DevOps 的进步。

DevOps 和 DevSecOps 的循环

在 DevOps 团队中工作的人通常首先建立工作流,然后确保存在持续的反馈循环,最后,保持实验文化。相比之下,DevSecOps 团队总是将安全性放在心上。

例如,DevSecOps 专业人员将确定最紧迫的安全挑战,并为其建立工作流。

接下来,团队针对已知的安全风险实现防御机制,并应用自动化对其进行测试。即时反馈循环向需要此类信息并能据此采取行动的人员提供有关已知漏洞和攻击的详细信息。然后,组织中的开发过程和对安全性的承诺变得更强。

真正过渡到发展合作需要一个组织的文化转变。但是,一旦发生了,就值了。强调安全性不会阻碍创新,相反,它可以通过降低在开发过程的后期修复漏洞的可能性来加速创新。

美国国土安全部对 DevSecOps 表现出兴趣

在讨论了 DevOps 和 DevSecOps 的异同之后,下一个相关主题是 DevSecOps 如何应用于数据科学。2017 年夏天,有消息称,美国国土安全部在向潜在供应商发出信息请求(RFI)文件时,发现了 DevSecOps。

RFI 是实体评估潜在供应商能力的标准化方法。具体来说,RFI 涉及可能用于美国公民和移民服务的技术,并希望了解供应商如何将 DevSecOps 原则应用于大数据、分析和机器学习。

几年前,美国公民和移民服务局采用了敏捷方法,但对其实践的调查显示,该组织在使用敏捷开发电子移民系统时忽略了关键组件,如频繁测试。尽管如此,该组织知道 DevSecOps 并希望将其应用于数据科学的事实似乎很有希望。

对于数据科学家来说,DevSecOps 并不是一个巨大的飞跃

对于为什么数据科学家应该在他们的工作中采用 DevOps 原则,已经有很多争论。例如,如果他们不断测试他们的算法的有效性,他们可能会得到更可靠的结果。此外,他们可以采用越来越一致的流程,帮助他们节省时间。

由于 DevSecOps 越来越受欢迎,对它的需求也越来越大,公司提供专门的项目,给人们所需的基础知识,让他们熟悉 DevSecOps ,并开始在他们的职业生涯中使用它。例如,参与者可能会了解安全性如何与 DevOps 实践共存,以及为什么更严格的安全性与更大的 DevOps 文化相一致。

因此,如果数据科学家已经熟悉 DevOps,或者至少出于工作目的有兴趣了解更多关于它的知识,那么了解 DevSecOps 以及它如何应用于数据科学并不困难。

大多数数据科学家已经习惯了使用自动化

如前所述,自动化是 DevSecOps 的重要组成部分。自动化也是方法学的最佳实践。此外,数据科学家通常在理解大量数据包含的内容时运行自动化脚本,或者在监督质量保证时运行。

对于负责检测欺诈或恐怖主义企图的项目的数据科学家来说,自动化通常是这些安全相关目标的一部分。

众所周知,大多数数据科学家在工作中都会在一定程度上使用自动化。此外,他们应该始终关注安全性,即使他们不是 DevSecOps 团队的正式成员。这些特征使数据科学家做好了充分准备,可以正式过渡到以 DevSecOps 为中心的角色。

DevSecOps 符合当今对数据的重视

互联网用户知道,如果他们不同意放弃自己的一些细节和隐私,他们就无法使用社交媒体网站或在网上做任何事情。只要公司负责任地处理和分享数据,大多数人都可以接受。

但是,可以理解的是,与脸书等网站相关的数据泄露让用户感到不安。他们对一个网站或公司有一定程度的信任,并最终意识到这种信任可能是不值得的。

不幸的是,在其他公司之前挖掘数据并使用相关见解开发最想要的功能的竞赛可能会危及安全。

通过应用 DevSecOps 原则,数据科学家可以帮助在那些通常快速行动以跟上技术发展的公司促进隐私和安全。

数据科学家需要了解 DevSecOps

对 DevSecOps 的概述将阐明为什么数据科学家理解这种方法并意识到它所包含的内容是至关重要的。

不管他们如何处理数据,DevSecOps 原则很可能适用于他们的技术。

图像由 Rawpixel

用人工智能理解事件

原文:https://towardsdatascience.com/understanding-events-with-artificial-intelligence-12e1ec3c5c9?source=collection_archive---------0-----------------------

我们遇到了很多客户需求,归结起来就是使用人工智能来理解事件。有些系统需要将事件分类,有些需要监听特定的事件,有些需要预测事件。这些要求通常包括给一个事件分配一个分数,然后根据分配的分数对所有事件进行排名。

Events can be analyzed in a lot of ways, including sequence, location, numerical, categorical, image, text, and relationship data.

这些事件可以是谷歌日历事件、医疗警报、约会网站上的日期,或者在 GenRush 的情况下,事件可以根据现实世界中的事件为一家公司指明新的潜在客户。

这些事件理解问题是隐藏在“事件”一词复杂性背后的经典分类和回归需求。对于序列预测,我们使用 LSTM/GRU/RNN ,有时也使用 DNN(例如,当事件序列形成一种模式时,你可以用图表表示/查看)。但是在本文中,让我们把重点放在事件处理的非顺序和非位置部分。让我们更详细地看看如何将一个事件转化为一组人工智能可以使用的功能。

因此,我们有很多事件,我们希望人工智能在特定事件发生时通知人类用户。我们立即发现一个经典的假阳性对假阴性的难题出现了。我在医院/ 医疗通知系统中见过很多这样的例子,当时我正和 Mathieu Lemay 一起研究医疗设备。如果人工智能经常错误地通知(假阳性),那么用户将忽略这些通知。然而,如果系统错过了关键事件,那么用户会认为人工智能没有注意,这是正确的。

让我们更深入一层,讨论 AI 可以观察到的“事件”的一些特征,以便做出通知决策。模型观察物体的特征是为了理解它。我们在机器学习领域所做的工作是识别特征,并以它“喜欢”的方式将其暴露给机器学习模型。想想这种事件到特征的映射,比如一个女孩的照片?)以身高和罩杯大小为模特“特征”的杂志。就像 pinup 模型一样,我们需要一些方法来比较和对比事件。把每个事件想象成一张棒球卡,里面有一堆可处理的信息。事件可以包含以下类型的信息:序列、位置、数字、分类、图像、文本和关系。

我们决定不考虑序列数据(例如,事件之前发生了什么,事件之后发生了什么),所以让我们来谈谈这些其他事件特征。对于 GenRush ,我们从一个 Google API 获取位置数据,该 API 将地址转换成经度和纬度。我在过去的文章中提到过这类事情,也有更详细的描述。这就是通常所说的地理信息系统。位置数据可用于分类和回归,但我们不要关注这一方面,因为像序列数据一样,利用这些数据有很多注意事项。数字数据是作为一个数字有意义的东西,你可以安全地与其他数字进行比较。数字事件数据的一个例子是称为“容量”的字段。事件的容量是一个可以比较的东西。例如,门牌号不是数字。这是一个数字,但是布罗德维尔大街 888 号的房子并不比 900 号的房子小。门牌号、邮政编码和国家都是分类数据的例子。也许可以用偶数/奇数来确定房子的朝向,但作为数字是没有用的。为了避免数据集中出现大量频率为 1 的类别,这些数据需要按照频率进行组织,并进行二进制化。低频分类特征并不能真正告诉你事件,所以我们可以放心地把这些东西扔到“其他”桶里。事件中的图像数据可以是与谷歌日历事件列表相关联的一组图片。我们有一些很酷的基于 CNN 的技术来将这些数据压缩成固定大小的向量,但这超出了本文的范围。文本数据通常是事件描述的主体,但也可以包括与事件相关的元数据中的文本,例如社交媒体帖子和事件响应。我们使用单词嵌入模型来更好地理解文本的意思。关于事件的关系数据是从一个知识图中提取的,该知识图是根据爬虫可以看到的关系构建的。更具体地说,我们可以设置一个爬虫来构建所有事件的所有参与者的图,其中图中的每个节点(即顶点)是一个电子邮件地址或一个事件,而弧(即边)将一个电子邮件地址连接到一个事件。因此,参加同一事件的三个人(电子邮件)可以被拉入图中的一个关系中。这个简单的图表告诉你谁和谁一起参加活动。它有各种对事件分类有用的信息,比如有多少人参加了一个事件,一起参加事件的人群是什么,谁参加了很多事件,等等。基数是一个重要的分类特征,因为当我们想要通过将事件标记为“小”或“大”来理解它们时,知道有多少人参加真的很有帮助。我知道。似乎显而易见。但是后退一步,想想我们从一个简单的“事件”项目中提取了多少特征。

既然我们已经展示了这些特征,让我们缩小一下,看看一个事件是如何变成带有伪代码的特征向量的:

下面是 keras 中用于分类特征向量(x)和伴随的基本事实数据(y)的简单 DNN:

现在有一些棘手的问题,我们没有进入这里,像建立知识图,并行运行几个模型(CNN 与 DNN),建立一个通知框架与 AWS SES/SNS,建立二进制地图等。但是,我希望您能从本文中很好地理解如何构建一个事件分类器,首先是一个特征提取函数,然后是一个对特征向量进行分类的 DNN。

所以你有它。事件可以变成人工智能可以理解的特征。

我紧接着一些好消息写这篇文章。我们最近在深度学习人工智能方面的工作获得了两个奖项!首先是视觉深度学习推荐系统的最佳论文奖。更重要的是,我们还因为一篇无人监督的深度学习论文获得了顶级论文奖;我在上一篇文章中讨论过的那个。欢乐时光!

Awards! Booyah Lemay Solutions. More on battle cries here.

We got the best paper award for this paper. It sure was an uphill climb.

我在一个不安全的 98db听 Avicii 的歌,还在爬山,并在两个明天到期的不同项目上埋头苦干。我为什么要告诉你这些?我想告诉你我的感受。就在此时此地 2017 年 10 月 8 日。在赎罪日禁食 25 小时后,上周末休息了 3 天,我回到了工作中,凌晨 2 点起床,和一个新客户计划下一件大事。为什么?我超级上进。

正如所料,我们正在发展以跟上项目的增长。新文章(和一些后期工作产品)滞后的原因是我们在过去一个月的工作节奏,加上繁重的旅行和 T2 的假期。我们有 11 个正在进行的项目。在过去的一年中,我们通常在任何时候都是 5。感谢上帝 JIRA 和懈怠。

我们现在有 6 名工程忍者。我们有一名博士和一名博士候选人,一名硕士和硕士候选人,一名高级开发人员和一名 MBA。都是工科本科生。为什么这么多高等教育?嗯,这种机器学习的东西很难,我们需要重量级人物。我自己也做得太多了。是时候下放更多权力了。

在试图保持这篇文章的概括性的同时,我开始深入细节。太深?我愿意接受一些建设性的批评。如果你喜欢这篇关于人工智能的文章,那么请尝试一下拍手工具。轻点那个。跟着我们走。去吧。我也很高兴在评论中听到你的反馈。你怎么想呢?

编码快乐!

-丹尼尔
丹尼尔@lemay.ai ←打个招呼。
LEMAY . AI
1(855)LEMAY-AI

您可能喜欢的其他文章:

  • 人工智能和不良数据
  • 人工智能:超参数
  • 人工智能:让你的用户给你的数据贴上标签

理解演变的政策梯度

原文:https://towardsdatascience.com/understanding-evolved-policy-gradients-cbc2d6b974a1?source=collection_archive---------8-----------------------

Learning to hop backwards with EPG.

我在发射台工作。AI 。我们有两周一次的内部阅读小组,主要关注机器学习领域的最新研究论文。最近,我们研究了一种新的深度强化学习(RL)算法,称为进化策略梯度 (EPG)。

这东西很酷!

论文来源于 OpenAI 。他们作出了值得称赞的努力,使他们的工作为公众所了解;他们的博客文章提供了比研究论文更“柔和”的阅读,OpenAI 也发布了与每篇论文相关的代码(这里是 EPG 代码库和博客文章)。

尽管他们尽了最大努力直观地解释这项工作,但我发现他们关于 EPG 的文章有点晦涩。我很想了解它,但我找不到任何关于它的有帮助的第三方解释。这就是为什么我决定钻研报纸,写下这篇文章:提供一个直观的解释,说明 EPG 正在发生什么。

政策梯度

要理解 EPG,首先必须理解政策梯度。我对 PG 的第一个“啊哈”时刻来自于阅读 Andrej Karpathy 的 Pong from Pixels 帖子。

如果你理解反向传播是一种在监督环境下训练神经网络的方法,PG 的基础是同一概念的简单扩展。

在 RL 问题中,策略是将输入状态映射到输出动作的任何函数。PG 的想法是训练神经网络使用反向传播来学习一个好的策略函数。实现这一点的一个聪明的方法是以受监督的方式使用选定的操作作为目标值。

A diagram stolen from Andrej Karpathy’s PG blog post. The green values represent the selected action, and loss is computed between the policy output and these values.

举例来说,假设我们的网络需要在三个动作中选择一个;它接受一些状态输入并产生一些 softmax 输出,如下所示:

Some example softmax output from a neural network choosing one of three actions.

我们可以简单地通过获取这个输出的 argmax 来选择一个动作。

A one-hot encoded representation of the selected action from the above output. (In practice, actions are usually sampled from the distribution provided by the softmax output.)

然后,我们可以使用简单的损失函数(如二进制交叉熵)来计算我们的神经网络相对于这个选定的动作向量的“损失”。

Computing binary cross-entropy loss for this example, taken from this post by Manish Chablani.

如果我们使用标准的 SGD,我们可以更新我们的神经网络,在给定相同输入状态的情况下,给出更接近于所选动作的输出。这就像说“表现得更像那样!”类似地,我们可以朝相反的方向迈出一步(类似于“梯度上升”,只是上坡而不是下坡),这就像说“不要那样做!”

这就是 PG 背后的基本思想,而且出奇的简单。所有基于 PG 的 RL 算法背后的艰难工作是弄清楚如何使用 PG:什么时候我们希望鼓励我们的策略重复一个动作?我们什么时候要劝阻?由于奖励很少,这个问题并不简单。

设计损失函数

其他 PG 方法通常通过使用预期回报函数并将预期回报与观察到的回报进行比较而成功,观察到的回报使用一些折扣因子“分布”在许多时间步骤上。这本质上是一种处理稀疏回报问题的启发式方法。

这里的推理是,导致一些观察到的奖励的决策可以被认为是“好的”,因此是鼓励的。当由于行动而观察到的回报比预期的要好时,我们应该鼓励我们的政策朝着那个方向发展。折扣奖励概念是将这种推理应用于 RL 算法的一种方式。

控制策略参数步长变得非常重要。以一种有原则的方式做到这一点是近似策略优化 (PPO)方法背后的新颖之处。这里,基于更新前后策略参数之间的 KL 偏差的惩罚被用于控制步长。

所有这些工作都可以被看作是设计一个 PG 损失函数,这个函数依赖于观察到的回报——一个优化政策的能力以最大化回报的合理要求。

为什么不学习一个损失函数?

RL 硬。PPO 在各种任务中表现相对较好。

这很好,但 EPG 的基本想法是:让我们使用机器学习来学习损失函数,而不是自己设计一个。也许这种方法可以给我们一个更通用的 RL 算法。

退一步,思考整个问题。我们需要哪些信息来学习一个好的政策?

首先,给定一个状态的“正确选择”不仅取决于当前状态,还取决于状态的最近历史。这也取决于我们最近的决策历史。我们能为 PG 设计一个考虑所有这些信息的损失函数吗?

对 EPG 来说,这就是他们正在试图做的。最终的损失函数可能如下所示:

EPG loss function architecture… quite a lot going on. The grey stuff is the loss function.

这里有很多事情要做,但主要的想法是,可以建立一个神经网络,它可以获取您想要的所有信息(包括您的策略网络输出和您选择的操作),并输出一个值(图像顶部的绿色立方体)。)我们可以将该值称为损失,并训练我们的策略网络使其最小化。

这种特殊的架构使用跨越时间的卷积。这个时间维度让我们称这些层为“时间卷积”,但它们的工作方式就像我们所了解和喜爱的卷积层一样。

最难的部分

这是一个伟大的想法,但有一个问题:我们如何为我们的损失函数网络学习良好的权重?

做这件事没有直接的方法。我们不能在这里捏造政策梯度之类的东西。

这就是进化策略派上用场的地方。

进化策略

EPG 的“进化”部分来自于使用 es 来学习损失函数网络的良好参数。

这种特殊的优化算法在这里非常有用,因为它给了我们一种不用任何梯度概念就能更新权重的方法。ES 的基本思想是这样的:通过向每个参数添加随机噪声来更新权重。如果事情变得更好,坚持这些改变。如果事情变得更糟,那就是朝着错误的方向迈出了一步(也是有用的信息。)

因此,我们创造了一个新的问题(学习一些疯狂复杂但潜在有用的损失函数的参数)和一个潜在的解决方案(应用专家系统)。这篇论文的大部分都在描述这些人是如何着手做这件事的。

开始工作

ES 包含了大量的尝试和错误。为了在合理的时间内收敛,我们需要并行化学习过程。

我们可以通过同时进行许多试验来做到这一点。这些试验中的每一个都是由一个工人(所谓的论文)或一个线程执行的。

一系列任务

A visualization of one family of tasks. The family is “learn to move the ant to a target location.” A task in this family is “learn to move the ant to location [10, 5]”.

EPG 试图解决一系列的任务。这是通过从家庭中抽取个体任务来实现的。如上图所示,任务家族的一个例子是“引导蚂蚁到达指定的目标位置”这个家族的任务是“引导蚂蚁到坐标[10,5]。”

每个工人得到从问题任务族中抽取的任务。这意味着在我们的例子中,一个工蚁会花时间学习如何让蚂蚁到达目标位置[10,5],而另一个工蚁会花时间让蚂蚁到达目标位置[5,10]。每个工人都将经历多次重复相同的任务,通过最小化新的损失函数来学习策略。

经过这么多时间步骤,我们可以看看每个工人通过这个过程积累的总回报。

尝试许多损失函数

每个工人也得到一些我们目前正在研究的损失函数的变体。我说的变体指的是“我们学习到的损失函数的最新、最好的版本——加上一些随机噪声。”

所以,每个工人都有任务和损失函数。我们可以在许多时间步之后挑选出总报酬最高的员工,并假设其损失函数的变体比其他一些更好,然后朝着用于创建该变体的随机生成噪声的方向迈出一步。

这种方法的一个问题是,一个工人可能比另一个工人有更容易的任务。例如,一个工人的任务可能是将蚂蚁引导到坐标[1,1],而另一个工人必须一直到达10,15。第一个工人的样本任务更容易,所以我们不能完全确信分配给它的策略是我们观察到的更高回报的原因。

为了解决这个问题,作者给许多工人分配了相同的损失函数变量;每个工人都有不同的任务;他们使用相同的损失函数变量来计算所有工人的平均报酬。

我们在每次试验结束时得到的结果是一组候选损失函数,以及关于它们在一系列任务中的相对表现的一些想法。我们可以使用该信息来更新损失函数参数。

奖励在哪里?

关于 EPG 的一个有趣的事情是,在一些实验中,该算法能够在不直接观察任何回报的情况下学习好的政策。关于什么构成“好”行为的所有信息都编码在损失函数中,损失函数不需要(但可以)包括观察到的奖励。

有希望的结果?

A pretrained EPG does well in “out-of-distribution” tasks at test-time; good test-time validation in RL problems is an important outstanding problem that EPG may solve.

《EPG》的作者对他们的结果持乐观态度,这种方法当然很有趣。中的工作包含了许多来自最近深度 RL 研究的有趣想法。

也许最重要的结果是 EPG 训练的损失函数在“非分布”任务中表现良好的能力。在我们之前看到的蚂蚁例子中,只使用位于蚂蚁初始位置右侧的目标来训练 EPG 损失函数。同一个损失函数能够训练一个策略,在测试时间引导蚂蚁到达蚂蚁初始位置左侧的目标。****

然而,该算法面临一些实际挑战,大多与需要繁重的计算资源(许多 CPU 核心)和相对较差的数据效率(需要许多许多尝试来学习一个好的损失函数)有关。)损失函数更新必须顺序执行,这就限制了该方法现有的并行处理量。

依我拙见,这篇论文之所以重要,不是因为它的直接结果,而是因为它介绍了一种应用 PG 方法的完全不同的方法。这只是如何着手学习损失函数的一个例子,但是可能有完全不同的方法来做同样的事情。也许学习 PG 损失函数的不同技术比这好得多。但是,据我所知,这是第一次尝试直接学习 PG 损失函数;避开损失函数设计问题可能为 PG 方法开辟一条有前途的新途径。

连续数字数据

原文:https://towardsdatascience.com/understanding-feature-engineering-part-1-continuous-numeric-data-da4e47099a7b?source=collection_archive---------0-----------------------

了解特征工程(第一部分)

处理连续数值数据的策略

Source: https://pixabay.com

介绍

“有钱能使鬼推磨”是你无论选择同意还是不同意都无法忽视的东西。在今天的数字革命时代,更贴切的说法应该是“数据让世界运转”。事实上,数据已经成为企业、公司和组织的一级资产,无论其规模大小。任何智能系统,无论有多复杂,都需要由数据驱动。在任何智能系统的核心,我们都有一个或多个基于机器学习、深度学习或统计方法的算法,这些算法消耗这些数据来收集知识,并在一段时间内提供智能见解。算法本身相当幼稚,无法在原始数据上开箱即用。因此,从原始数据中设计有意义的特征是最重要的,这些特征可以被这些算法理解和消费。

机器学习管道的温和更新

任何智能系统基本上都由一个端到端的管道组成,从接收原始数据开始,利用数据处理技术从这些数据中获取、处理和设计有意义的特征和属性。然后,我们通常利用统计模型或机器学习模型等技术对这些功能进行建模,然后根据手头要解决的问题,在必要时部署该模型以供将来使用。基于 CRISP-DM 行业标准流程模型的典型标准机器学习流水线如下图所示。

A standard machine learning pipeline (source: Practical Machine Learning with Python, Apress/Springer)

接受原始数据并直接在这些数据上构建模型是有勇无谋的,因为我们不会获得预期的结果或性能,而且算法也不够智能,无法从原始数据中自动提取有意义的特征(现在有一些自动化的特征提取技术,在某种程度上可以通过深度学习方法来实现,但稍后会有更多内容!).

如上图所示,我们的主要关注领域属于数据准备方面,在经过必要的争论和预处理后,我们使用各种方法从原始数据中提取有意义的属性或特征。

动机

特征工程是构建任何智能系统的基本部分。即使你有很多更新的方法,如深度学习和元启发式方法,它们有助于自动机器学习,但每个问题都是特定领域的,更好的功能(适合该问题)通常是系统性能的决定因素。特征工程是一门艺术,也是一门科学,这就是为什么数据科学家经常在建模前的数据准备阶段花费 70%的时间。让我们来看看数据科学领域几位知名人士对特性工程的一些引用。

“想出新功能既困难又耗时,需要专业知识。‘应用机器学习’基本上是特征工程。”

——吴恩达教授。

这基本上强化了我们之前提到的数据科学家花费近 80%的时间在工程特性上,这是一个困难且耗时的过程,需要领域知识和数学计算。

“特征工程是将原始数据转换为特征的过程,这些特征能够更好地代表潜在问题预测模型,从而提高模型对不可见数据的准确性

杰森·布朗利博士

这给了我们一个关于特征工程的想法,即把数据转换成特征作为机器学习模型的输入的过程,这样高质量的特征有助于提高整体模型性能。特性也非常依赖于潜在的问题。因此,即使机器学习任务在不同的场景中可能是相同的,例如将电子邮件分类为垃圾邮件和非垃圾邮件,或者将手写数字分类,但在每个场景中提取的特征将彼此非常不同。

来自华盛顿大学的 Pedro Domingos 教授在他题为的论文中告诉了我们以下内容。

“最终,一些机器学习项目会成功,一些会失败。有什么区别?最重要的因素无疑是所使用的功能。”

佩德罗·多明戈斯教授

最后一句引语是著名的 Kaggler,Xavier Conort 说的,这句话应该会激发你对特征工程的兴趣。你们大多数人都已经知道,现实世界中棘手的机器学习问题经常会定期发布在 Kaggle 上,而 ka ggle 通常对所有人开放。

“我们使用的算法对 Kagglers 来说非常标准。…我们将大部分精力花在了功能工程上。…我们还非常小心地放弃了可能会让我们面临过度适应模型的风险的功能。”

—泽维尔·康纳特

了解功能

一个 特征 通常是在 原始数据 之上的特定表示,原始数据是一个单独的、可测量的属性,通常由数据集中的一列来描述。考虑一个普通的二维数据集,每个观察由一个描述,每个特征由一个描述,这将具有一个观察的特定值。

A generic dataset snapshot

因此,就像上图中的例子一样,每行通常表示一个特征向量,所有观测值的整个特征集形成一个二维特征矩阵,也称为特征集。这类似于表示二维数据的数据框或电子表格。通常,机器学习算法处理这些数字矩阵或张量,因此大多数特征工程技术处理将原始数据转换成这些算法容易理解的一些数字表示。

基于数据集,要素可以分为两种主要类型。固有的 原始特征 直接从数据集中获得,无需额外的数据处理或工程。 衍生特征 通常是从特征工程中获得的,我们从现有的数据属性中提取特征。一个简单的例子是从包含“出生日期”的雇员数据集中创建一个新特征“年龄”,只需从当前日期中减去他们的出生日期。**

数据有多种类型和格式,包括结构化和非结构化数据。在本文中,我们将讨论处理结构化连续数字数据的各种特征工程策略。所有这些例子都是我最近的一本书 【用 Python 进行实用机器学习】 的一部分,你可以在 GitHub 上访问本文中使用的相关数据集和代码。我还要感谢加布里埃尔·莫雷拉,他给了我一些关于特征工程技术的很好的建议。

数字数据的特征工程

数字数据通常以描述观察、记录或测量的标量值的形式表示数据。这里,数值数据是指 连续数据 ,而不是通常表示为分类数据的离散数据。数字数据也可以表示为值的向量,其中向量中的每个值或实体可以表示一个特定的特征。对于连续数值数据,整数和浮点数是最常见和最广泛使用的数值数据类型。即使数字数据可以直接输入到机器学习模型中,在建立模型之前,您仍然需要设计与场景、问题和领域相关的特征。因此,对特征工程的需求仍然存在。让我们利用 python,看看对数字数据进行要素工程的一些策略。我们首先加载以下必要的依赖项(通常在 Jupyter 笔记本中)。

**import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as spstats%matplotlib inline**

原始度量

正如我们前面提到的,原始数字数据通常可以根据上下文和数据格式直接输入到机器学习模型中。原始测量通常直接使用数字变量作为特征来表示,无需任何形式的转换或工程。通常,这些特征可以指示值或计数。让我们加载我们的一个数据集, 神奇宝贝数据集 也可以在 Kaggle 上找到。

**poke_df = pd.read_csv('datasets/Pokemon.csv', encoding='utf-8') poke_df.head()**

Snapshot of our Pokemon dataset

神奇宝贝是一个巨大的媒体专营权,围绕着虚拟人物称为神奇宝贝,代表口袋妖怪。简而言之,你可以把它们想象成拥有超能力的虚构动物!该数据集由这些字符组成,每个字符有不同的统计数据。

数值

如果仔细观察上图中的数据框快照,您会发现有几个属性表示可以直接使用的数字原始值。下面的代码片段重点描述了其中的一些特性。

**poke_df[['HP', 'Attack', 'Defense']].head()**

Features with (continuous) numeric data

因此,您可以直接将这些属性用作上述数据框中描述的要素。这些包括每个神奇宝贝的生命值,攻击和防御统计。事实上,我们也可以计算这些领域的一些基本统计措施。

**poke_df[['HP', 'Attack', 'Defense']].describe()**

Basic descriptive statistics on numeric features

有了这个,你就可以很好地了解计数、平均值、标准差和四分位数等统计指标。

计数

另一种形式的原始测量包括表示特定属性的频率、计数或出现的特征。让我们来看一个来自 百万首歌曲数据集 的数据样本,它描述了不同用户听过的歌曲的数量或频率。

**popsong_df = pd.read_csv('datasets/song_views.csv', 
                          encoding='utf-8')
popsong_df.head(10)**

Song listen counts as a numeric feature

从上面的快照可以明显看出,listen_count字段可以直接用作基于频率\计数的数字特征。

二值化

通常,原始频率或计数可能与基于正在解决的问题建立模型无关。例如,如果我正在为歌曲推荐构建一个推荐系统,我只想知道一个人是否对某首特定的歌曲感兴趣或听过。这不需要知道一首歌被听了多少次,因为我更关心他/她听过的各种歌曲。在这种情况下,与基于计数的特征相反,二进制特征是优选的。我们可以如下二进制化我们的listen_count字段。

**watched = np.array(popsong_df['listen_count']) 
watched[watched >= 1] = 1
popsong_df['watched'] = watched**

你也可以使用scikit-learn's模块中的Binarizer类代替numpy数组来执行同样的任务。

**from sklearn.preprocessing import Binarizerbn = Binarizer(threshold=0.9)
pd_watched = bn.transform([popsong_df['listen_count']])[0]
popsong_df['pd_watched'] = pd_watched
popsong_df.head(11)**

Binarizing song counts

从上面的快照中可以清楚地看到,这两种方法产生了相同的结果。因此,我们得到一个二进制化的特征,该特征指示该歌曲是否被每个用户收听过,该特征然后可以被进一步用于相关的模型中。

舍入

通常,当处理像比例或百分比这样的连续数字属性时,我们可能不需要精度很高的原始值。因此,将这些高精度百分比四舍五入成数字整数通常是有意义的。然后,这些整数可以直接用作原始值,甚至用作分类(基于离散类)特征。让我们尝试将这个概念应用到一个虚拟数据集中,描述商店商品及其受欢迎程度。

**items_popularity = pd.read_csv('datasets/item_popularity.csv',  
                               encoding='utf-8')items_popularity['popularity_scale_10'] = np.array(
                   np.round((items_popularity['pop_percent'] * 10)),  
                   dtype='int')
items_popularity['popularity_scale_100'] = np.array(
                  np.round((items_popularity['pop_percent'] * 100)),    
                  dtype='int')
items_popularity**

Rounding popularity to different scales

根据上面的输出,你可以猜到我们尝试了两种形式的舍入。这些特征以1–101–100两种尺度描述了物品的流行程度。根据场景和问题,您可以将这些值用作数字特征或分类特征。

相互作用

监督机器学习模型通常试图将输出响应(离散类或连续值)建模为输入特征变量的函数。例如,一个简单的线性回归方程可以描述为

其中输入特征由变量描述

具有由表示的权重或系数

而目标分别是预测 y 的反应*.*****

在这种情况下,这个简单的线性模型描述了输出和输入之间的关系,完全基于单独的输入特征。

然而,通常在一些真实的场景中,尝试捕获这些特征变量之间的交互作为输入特征集的一部分是有意义的。具有相互作用特征的上述线性回归公式的扩展的简单描述是

其中由表示的特征

表示交互特征。现在让我们尝试在我们的神奇宝贝数据集上设计一些交互功能。

**atk_def = poke_df[['Attack', 'Defense']]
atk_def.head()**

从输出数据帧中,我们可以看到我们有两个数值(连续)特征,AttackDefence。我们现在将通过利用scikit-learn来构建二级特性。

**from sklearn.preprocessing import PolynomialFeaturespf = PolynomialFeatures(degree=2, interaction_only=False,  
                        include_bias=False)
res = pf.fit_transform(atk_def)
res **Output
------**array([[    49.,     49.,   2401.,   2401.,   2401.],
       [    62.,     63.,   3844.,   3906.,   3969.],
       [    82.,     83.,   6724.,   6806.,   6889.],
       ..., 
       [   110.,     60.,  12100.,   6600.,   3600.],
       [   160.,     60.,  25600.,   9600.,   3600.],
       [   110.,    120.,  12100.,  13200.,  14400.]])**

上面的特征矩阵描述了总共五个特征,包括新的交互特征。我们可以在上面的矩阵中看到每个特征的程度如下。

**pd.DataFrame(pf.powers_, columns=['Attack_degree',  
                                  'Defense_degree'])**

查看这个输出,我们现在知道每个特性实际上代表了这里描述的度数。有了这些知识,我们现在可以为每个特性指定一个名称,如下所示。这只是为了便于理解,您应该用更好、更容易访问和简单的名称来命名您的功能。

**intr_features = pd.DataFrame(res, columns=['Attack', 'Defense',  
                                           'Attack^2', 
                                           'Attack x Defense',  
                                           'Defense^2'])
intr_features.head(5)**

Numeric features with their interactions

因此,上述数据框代表了我们的原始特征及其交互特征。

扔掉

使用原始连续数字要素的问题在于,这些要素中的值分布通常会有偏差。这意味着有些值会经常出现,而有些值会很少出现。除此之外,还有另一个问题是这些特征中的任何一个的值的变化范围。例如,特定音乐视频的浏览量可能异常之大( Despacito 我们正看着你呢!)有些可能真的很小。直接使用这些功能会导致许多问题,并对模型产生负面影响。因此,有策略来处理这一点,其中包括宁滨和转换。

宁滨,也称为量化,用于将连续的数字特征转换为离散的数字特征(类别)。这些离散值或数字可以被认为是类别或箱,原始的连续数值被装入或分组到这些类别或箱中。每个箱代表一个特定的强度等级,因此一个特定范围的连续数值落入其中。宁滨数据的具体策略包括固定宽度和自适应宁滨。让我们使用从 2016 FreeCodeCamp 开发者\编码者调查 中提取的数据集中的一个子集,该调查讨论了与编码者和软件开发者有关的各种属性。

**fcc_survey_df = pd.read_csv('datasets/fcc_2016_coder_survey_subset.csv', 
encoding='utf-8')fcc_survey_df[['ID.x', 'EmploymentField', 'Age', 'Income']].head()**

Sample attributes from the FCC coder survey dataset

ID.x变量基本上是每个参加调查的编码人员/开发人员的唯一标识符,其他字段是不言自明的。

固定宽度宁滨

顾名思义,在固定宽度宁滨中,我们为每个条柱提供特定的固定宽度,通常由分析数据的用户预先定义。每个 bin 都有一个预先确定的值范围,应该根据一些领域知识、规则或约束条件将这些值分配给该 bin。基于舍入的宁滨是其中一种方法,您可以使用我们之前讨论过的舍入运算来对原始值进行装箱。

现在让我们考虑编码器调查数据集中的Age特征,并看看它的分布。

**fig, ax = plt.subplots()
fcc_survey_df['Age'].hist(color='#A9C5D3', edgecolor='black',  
                          grid=False)
ax.set_title('Developer Age Histogram', fontsize=12)
ax.set_xlabel('Age', fontsize=12)
ax.set_ylabel('Frequency', fontsize=12)**

Histogram depicting developer age distribution

上面描述开发人员年龄的直方图如预期的那样稍微偏右(年龄较小的开发人员)。我们现在将根据以下方案将这些原始年龄值分配到特定的容器中

**Age Range: Bin
---------------
 0 -  9  : 0
10 - 19  : 1
20 - 29  : 2
30 - 39  : 3
40 - 49  : 4
50 - 59  : 5
60 - 69  : 6
  ... and so on**

使用我们在前面的舍入部分学到的知识,我们可以很容易地做到这一点,我们通过将底值除以 10 来舍入这些原始年龄值。

**fcc_survey_df['Age_bin_round'] = np.array(np.floor(
                              np.array(fcc_survey_df['Age']) / 10.))fcc_survey_df[['ID.x', 'Age', 'Age_bin_round']].iloc[1071:1076]**

Binning by rounding

您可以看到,每个年龄的对应箱都是基于舍入进行分配的。但是如果我们需要更多的灵活性呢?如果我们想根据自己的规则\逻辑来决定和固定框的宽度,该怎么办?基于定制范围的宁滨将帮助我们实现这一目标。让我们使用下面的方案为宁滨开发者年龄定义一些定制的年龄范围。

**Age Range : Bin
---------------
 0 -  15  : 1
16 -  30  : 2
31 -  45  : 3
46 -  60  : 4
61 -  75  : 5
75 - 100  : 6**

基于这个定制的宁滨方案,我们现在将为每个开发者年龄值标记容器,并且我们将存储容器范围以及相应的标签。

**bin_ranges = [0, 15, 30, 45, 60, 75, 100]
bin_names = [1, 2, 3, 4, 5, 6]fcc_survey_df['Age_bin_custom_range'] = pd.cut(
                                           np.array(
                                              fcc_survey_df['Age']), 
                                              bins=bin_ranges)
fcc_survey_df['Age_bin_custom_label'] = pd.cut(
                                           np.array(
                                              fcc_survey_df['Age']), 
                                              bins=bin_ranges,            
                                              labels=bin_names)
# view the binned features 
fcc_survey_df[['ID.x', 'Age', 'Age_bin_round', 
               'Age_bin_custom_range',   
               'Age_bin_custom_label']].iloc[10a71:1076]**

Custom binning scheme for developer ages

自适应宁滨

使用固定宽度宁滨的缺点是,由于我们手动决定面元范围,我们可能最终得到不规则的面元,这些面元根据落入每个面元的数据点或值的数量而不一致。有些箱子可能人口稠密,有些可能人口稀少,甚至是空的!在这些让数据自己说话的场景中,自适应宁滨是一种更安全的策略!没错,我们使用数据分布本身来决定我们的 bin 范围。

基于分位数的宁滨是用于自适应宁滨的一个好策略。分位数是特定的值或分界点,有助于将特定数值字段的连续值分布划分为离散的连续箱或区间。因此, q 分位数有助于将一个数值属性划分为 q 个相等的分区。分位数的常见例子包括:被称为中值2 分位数,它将数据分布分成两个相等的二进制;被称为四分位数4 分位数,它将数据分成 4 个相等的二进制;以及被称为十分位数10 分位数,它创建了 10 个相等宽度的二进制。现在让我们看看 developer Income字段的数据分布。

**fig, ax = plt.subplots()
fcc_survey_df['Income'].hist(bins=30, color='#A9C5D3', 
                             edgecolor='black', grid=False)
ax.set_title('Developer Income Histogram', fontsize=12)
ax.set_xlabel('Developer Income', fontsize=12)
ax.set_ylabel('Frequency', fontsize=12)**

Histogram depicting developer income distribution

上面的分布描述了收入的一个右偏,较少的开发者赚更多的钱,反之亦然。让我们采用基于四分位数的自适应宁滨方案。我们可以如下容易地得到四分位数。

**quantile_list = [0, .25, .5, .75, 1.]
quantiles = fcc_survey_df['Income'].quantile(quantile_list)
quantiles **Output
------** 0.00      6000.0
0.25     20000.0
0.50     37000.0
0.75     60000.0
1.00    200000.0
Name: Income, dtype: float64**

现在让我们在原始分布直方图中可视化这些分位数!

**fig, ax = plt.subplots()
fcc_survey_df['Income'].hist(bins=30, color='#A9C5D3', 
                             edgecolor='black', grid=False)for quantile in quantiles:
    qvl = plt.axvline(quantile, color='r')
ax.legend([qvl], ['Quantiles'], fontsize=10)ax.set_title('Developer Income Histogram with Quantiles', 
             fontsize=12)
ax.set_xlabel('Developer Income', fontsize=12)
ax.set_ylabel('Frequency', fontsize=12)**

Histogram depicting developer income distribution with quartile values

上面分布中的红线描绘了四分位值和我们的潜在仓。现在,让我们利用这一知识来构建基于四分位数的宁滨方案。

**quantile_labels = ['0-25Q', '25-50Q', '50-75Q', '75-100Q']
fcc_survey_df['Income_quantile_range'] = pd.qcut(
                                            fcc_survey_df['Income'], 
                                            q=quantile_list)
fcc_survey_df['Income_quantile_label'] = pd.qcut(
                                            fcc_survey_df['Income'], 
                                            q=quantile_list,       
                                            labels=quantile_labels)

fcc_survey_df[['ID.x', 'Age', 'Income', 'Income_quantile_range', 
               'Income_quantile_label']].iloc[4:9]**

Quantile based bin ranges and labels for developer incomes

这应该让你对基于分位数的自适应宁滨的工作原理有一个很好的了解。这里需要记住的重要一点是,宁滨的结果会导致离散值分类特征,在将分类数据用于任何模型之前,您可能需要对分类数据进行额外的特征工程步骤。我们将在下一部分讨论分类数据的特征工程策略!

统计变换

我们在前面简单地讨论了偏斜数据分布的不利影响。现在,让我们通过利用统计或数学变换来看看特征工程的不同策略。我们将研究对数变换以及 Box-Cox 变换。这两个转换函数都属于幂转换函数族,通常用于创建单调的数据转换。它们的主要意义在于,它们有助于稳定方差,紧密遵循正态分布,并使数据独立于基于其分布的均值

对数变换

对数变换属于幂变换函数族。该函数在数学上可以表示为

**其读作 x对数到底数 b 等于y。这可以转化为

其指示基底 b 必须提升到什么功率才能得到 x 。自然对数用 b=e 其中 e = 2.71828 俗称欧拉数。也可以使用十进制中普遍使用的基数 b =10。

对数变换在应用于偏斜分布时非常有用,因为它们倾向于扩展较低幅度范围内的值,并倾向于压缩或减少较高幅度范围内的值。这往往会使偏态分布尽可能接近正态分布。让我们在我们之前使用的开发人员Income特性上使用 log transform。

**fcc_survey_df['Income_log'] = np.log((1+ fcc_survey_df['Income']))
fcc_survey_df[['ID.x', 'Age', 'Income', 'Income_log']].iloc[4:9]**

Log transform on developer income

Income_log字段描述了对数变换后的变换特征。现在让我们来看看这个变换域上的数据分布。

**income_log_mean = np.round(np.mean(fcc_survey_df['Income_log']), 2)fig, ax = plt.subplots()
fcc_survey_df['Income_log'].hist(bins=30, color='#A9C5D3', 
                                 edgecolor='black', grid=False)
plt.axvline(income_log_mean, color='r')
ax.set_title('Developer Income Histogram after Log Transform', 
             fontsize=12)
ax.set_xlabel('Developer Income (log scale)', fontsize=12)
ax.set_ylabel('Frequency', fontsize=12)
ax.text(11.5, 450, r'$\mu$='+str(income_log_mean), fontsize=10)**

Histogram depicting developer income distribution after log transform

根据上面的图,我们可以清楚地看到,与原始数据的偏态分布相比,该分布更像正态分布或高斯分布。

博克斯-考克斯变换

Box-Cox 变换是属于幂变换函数族的另一个流行函数。该函数有一个先决条件,即要转换的数值必须是正的(类似于 log transform 所期望的)。如果它们是负的,使用常量值进行移位会有所帮助。数学上,Box-Cox 变换函数可以表示如下。

使得所得的变换输出 y 是输入 x 和变换参数λ的函数,使得当λ = 0 时,所得的变换是我们先前讨论的自然对数变换。λ的最佳值通常使用最大似然或对数似然估计来确定。现在让我们将 Box-Cox 变换应用于我们的开发者收入特性。首先,我们通过移除非空值从数据分布中获得最佳λ值,如下所示。

**income = np.array(fcc_survey_df['Income'])
income_clean = income[~np.isnan(income)]
l, opt_lambda = spstats.boxcox(income_clean)
print('Optimal lambda value:', opt_lambda) **Output
------**
Optimal lambda value: 0.117991239456**

现在我们已经获得了最佳λ值,让我们对λ的两个值使用 Box-Cox 变换,使得λ = 0 和λ = λ(最佳),并变换开发者Income特征。

**fcc_survey_df['Income_boxcox_lambda_0'] = spstats.boxcox(
                                        (1+fcc_survey_df['Income']), 
                                          lmbda=0)
fcc_survey_df['Income_boxcox_lambda_opt'] = spstats.boxcox(
                                            fcc_survey_df['Income'], 
                                              lmbda=opt_lambda)

fcc_survey_df[['ID.x', 'Age', 'Income', 'Income_log', 
               'Income_boxcox_lambda_0',       
               'Income_boxcox_lambda_opt']].iloc[4:9]**

Developer income distribution after Box-Cox transform

上述数据框中描述了变换后的要素。正如我们所料,Income_logIncome_boxcox_lamba_0具有相同的值。让我们看看用最优λ变换后的变换后的Income特征的分布。

**income_boxcox_mean = np.round(
                      np.mean(
                       fcc_survey_df['Income_boxcox_lambda_opt']),2)fig, ax = plt.subplots()
fcc_survey_df['Income_boxcox_lambda_opt'].hist(bins=30, 
                     color='#A9C5D3', edgecolor='black', grid=False)
plt.axvline(income_boxcox_mean, color='r')
ax.set_title('Developer Income Histogram after Box–Cox Transform', 
             fontsize=12)
ax.set_xlabel('Developer Income (Box–Cox transform)', fontsize=12)
ax.set_ylabel('Frequency', fontsize=12)
ax.text(24, 450, r'$\mu$='+str(income_boxcox_mean), fontsize=10)**

Histogram depicting developer income distribution after Box-Cox transform

该分布看起来更正常——类似于我们在对数变换后获得的分布。

结论

特征工程是机器学习和数据科学的一个非常重要的方面,永远不应该被忽视。虽然我们有像深度学习这样的自动化功能工程方法,以及像 AutoML 这样的自动化机器学习框架(它仍然强调它需要好的功能才能很好地工作!).特征工程一直存在,甚至一些自动化方法通常需要基于数据类型、领域和要解决的问题的特定工程特征。

在本文中,我们研究了对连续数字数据进行特征工程的流行策略。在下一部分中,我们将研究处理离散、分类数据的流行策略,然后在以后的文章中讨论非结构化数据类型。敬请期待!

本文使用的所有代码和数据集都可以从我的 GitHub 访问

该代码也可作为 Jupyter 笔记本

分类数据

原文:https://towardsdatascience.com/understanding-feature-engineering-part-2-categorical-data-f54324193e63?source=collection_archive---------0-----------------------

了解特征工程(第二部分)

处理离散分类数据的策略

Source: https://pixabay.com

介绍

我们在本系列的前一篇文章中介绍了处理结构化连续数字数据的各种特征工程策略。在本文中,我们将关注另一种类型的结构化数据,这种数据本质上是离散的,通常被称为分类数据。处理数字数据通常比分类数据更容易,因为我们不必处理与任何分类类型的数据属性中的每个类别值相关的额外的复杂语义。我们将使用实践方法来讨论处理分类数据的几种编码方案,以及处理大规模特征爆炸的几种流行技术,通常称为 【维数灾难】

动机

我相信到现在你一定意识到特征工程的动机和重要性,我们在本系列的 【第一部分】 中做了同样详细的强调。如果有必要的话,一定要检查一下,快速复习一下。简而言之,机器学习算法不能直接处理分类数据,在开始对数据建模之前,您需要对这些数据进行一些工程和转换。

理解分类数据

在深入特性工程策略之前,让我们先了解一下分类数据表示。通常,任何本质上是分类的数据属性都表示属于特定有限类别集的离散值。在由模型预测的属性或变量(通常称为响应变量)的上下文中,这些通常也称为类或标签。这些离散值本质上可以是文本或数字(甚至是像图像这样的非结构化数据!).分类数据有两大类,名义数据和序数数据。

在任何名义分类数据属性中,该属性的值之间没有排序的概念。考虑一个简单的天气类别示例,如下图所示。我们可以看到,在这个特定的场景中,我们有六个主要的类别或种类,没有任何顺序的概念或概念(多风并不总是发生在晴朗之前,也不小于或大于晴朗*)。*

Weather as a categorical attribute

类似地,电影、音乐和视频游戏类型、国家名称、食物和烹饪类型是其他名义分类属性的例子。

有序分类属性在其值中具有某种意义或顺序概念。例如,请看下图中的衬衫尺寸。很明显,当考虑衬衫时,顺序或者在这种情况下的‘size’很重要( S 小于 M ,M 小于 L 等等)。

Shirt size as an ordinal categorical attribute

鞋号、教育水平和就业角色是有序分类属性的一些其他示例。对分类数据有了一个很好的概念,现在让我们看看一些特征工程策略。

分类数据的特征工程

虽然在各种机器学习框架中已经取得了很多进步,以接受复杂的分类数据类型,如文本标签。典型地,特征工程中的任何标准工作流程都涉及将这些分类值的某种形式的 转换 为数字标签,然后对这些值应用某种 编码方案 。开始之前,我们把必要的必需品都装了起来。

*import pandas as pd
import numpy as np*

转换名义属性

名义属性由离散的分类值组成,它们之间没有概念或顺序感。这里的想法是将这些属性转换成更具代表性的数字格式,以便下游代码和管道能够轻松理解。让我们来看一个关于视频游戏销售的新数据集。这个数据集也可以在以及我的GitHub资源库中找到。

*****vg_df = pd.read_csv('datasets/vgsales.csv', encoding='utf-8')
vg_df[['Name', 'Platform', 'Year', 'Genre', 'Publisher']].iloc[1:7]*****

Dataset for video game sales

让我们关注上面数据框中描述的视频游戏Genre属性。很明显,这是一个名词性的范畴属性,就像PublisherPlatform一样。我们可以很容易地得到独特的视频游戏类型列表如下。

*****genres = np.unique(vg_df['Genre'])
genres**Output
------**
array(['Action', 'Adventure', 'Fighting', 'Misc', 'Platform',  
       'Puzzle', 'Racing', 'Role-Playing', 'Shooter', 'Simulation',  
       'Sports', 'Strategy'], dtype=object)*****

这告诉我们,我们有 12 种不同的视频游戏类型。我们现在可以生成一个标签编码方案,通过利用scikit-learn将每个类别映射到一个数值。

*****from sklearn.preprocessing import LabelEncodergle = LabelEncoder()
genre_labels = gle.fit_transform(vg_df['Genre'])
genre_mappings = {index: label for index, label in 
                  enumerate(gle.classes_)}
genre_mappings **Output
------** {0: 'Action', 1: 'Adventure', 2: 'Fighting', 3: 'Misc',
 4: 'Platform', 5: 'Puzzle', 6: 'Racing', 7: 'Role-Playing',
 8: 'Shooter', 9: 'Simulation', 10: 'Sports', 11: 'Strategy'}*****

因此,在LabelEncoder对象gle的帮助下,生成了一个映射方案,其中每个流派值被映射到一个数字。转换后的标签存储在genre_labels值中,我们可以将该值写回到我们的数据框中。

*****vg_df['GenreLabel'] = genre_labels
vg_df[['Name', 'Platform', 'Year', 'Genre', 'GenreLabel']].iloc[1:7]*****

Video game genres with their encoded labels

如果您计划将这些标签用作预测的响应变量,则可以直接使用这些标签,尤其是在像scikit-learn这样的框架中,但是如前所述,在将它们用作特性之前,我们需要对它们进行额外的编码。

转换序数属性

序数属性是在值之间有顺序感的分类属性。让我们考虑一下我们的 神奇宝贝数据集 ,我们在本系列的 第 1 部分 中使用过。让我们更具体地关注一下Generation属性。

*****poke_df = pd.read_csv('datasets/Pokemon.csv', encoding='utf-8')
poke_df = poke_df.sample(random_state=1, 
                         frac=1).reset_index(drop=True)np.unique(poke_df['Generation'])**Output
------**
array(['Gen 1', 'Gen 2', 'Gen 3', 'Gen 4', 'Gen 5', 'Gen 6'], 
         dtype=object)*****

根据上面的输出,我们可以看到总共有 6 代,每个神奇宝贝通常都属于基于视频游戏的特定一代(当它们被发布时),电视连续剧也遵循类似的时间线。这个属性通常是顺序的(领域知识在这里是必要的),因为大多数属于第 1 代的神奇宝贝在视频游戏和电视节目中比第 2 代更早出现,等等。粉丝们可以看看下图,记住每一代流行的一些神奇宝贝(粉丝们的看法可能会有所不同!).

Popular Pokémon based on generation and type (source: https://www.reddit.com/r/pokemon/comments/2s2upx/heres_my_favorite_pokemon_by_type_and_gen_chart)

因此他们有一种秩序感。一般来说,没有通用的模块或函数来根据订单自动将这些特征映射和转换成数字表示。因此,我们可以使用自定义编码\映射方案。

*****gen_ord_map = {'Gen 1': 1, 'Gen 2': 2, 'Gen 3': 3, 
               'Gen 4': 4, 'Gen 5': 5, 'Gen 6': 6}poke_df['GenerationLabel'] = poke_df['Generation'].map(gen_ord_map)
poke_df[['Name', 'Generation', 'GenerationLabel']].iloc[4:10]*****

Pokémon generation encoding

从上面的代码中可以明显看出,pandas中的map(…)函数在转换这个顺序特性时很有帮助。

编码分类属性

如果您还记得我们之前提到的内容,分类数据的特征工程通常包括我们在上一节中描述的转换过程和强制编码过程,在该过程中,我们应用特定的编码方案为特定分类属性中的每个类别\值创建虚拟变量或特征。

您可能想知道,我们在前面的部分中刚刚将类别转换为数字标签,现在我们究竟为什么需要它呢?原因很简单。考虑到视频游戏流派,如果我们直接将GenreLabel属性作为机器学习模型中的一个特征,它会认为它是一个连续的数字特征,认为值 10 ( 体育)大于 6 ( 赛车),但这是没有意义的,因为体育流派肯定不会大于或小于赛车,这些是本质上不同的值或类别,不能直接进行比较。因此,我们需要一个额外的编码方案层,其中为每个属性的所有不同类别中的每个唯一值或类别创建虚拟特征。

独热编码方案

考虑到我们具有带有 m 标签的任何分类属性的数字表示(转换后),一键编码方案将属性编码或转换为 m 二进制特征,其只能包含值 1 或 0。因此,分类特征中的每个观察结果都被转换成大小为 m 的向量,其中只有一个值为 1 (表示它是活动的)。让我们取一个描述两个感兴趣的属性的神奇宝贝数据集的子集。

*****poke_df[['Name', 'Generation', 'Legendary']].iloc[4:10]*****

Subset of our Pokémon dataset

感兴趣的属性是神奇宝贝Generation和它们的Legendary状态。第一步是这些属性转换成基于我们之前所学的数字表示。

*****from sklearn.preprocessing import OneHotEncoder, LabelEncoder# transform and map pokemon generations
gen_le = LabelEncoder()
gen_labels = gen_le.fit_transform(poke_df['Generation'])
poke_df['Gen_Label'] = gen_labels# transform and map pokemon legendary status
leg_le = LabelEncoder()
leg_labels = leg_le.fit_transform(poke_df['Legendary'])
poke_df['Lgnd_Label'] = leg_labelspoke_df_sub = poke_df[['Name', 'Generation', 'Gen_Label',  
                       'Legendary', 'Lgnd_Label']]
poke_df_sub.iloc[4:10]*****

Attributes with transformed (numeric) labels

特征Gen_LabelLgnd_Label现在描述了我们的分类特征的数字表示。现在让我们对这些特性应用一键编码方案。

*****# encode generation labels using one-hot encoding scheme
gen_ohe = OneHotEncoder()
gen_feature_arr = gen_ohe.fit_transform(
                              poke_df[['Gen_Label']]).toarray()
gen_feature_labels = list(gen_le.classes_)
gen_features = pd.DataFrame(gen_feature_arr, 
                            columns=gen_feature_labels)# encode legendary status labels using one-hot encoding scheme
leg_ohe = OneHotEncoder()
leg_feature_arr = leg_ohe.fit_transform(
                                poke_df[['Lgnd_Label']]).toarray()
leg_feature_labels = ['Legendary_'+str(cls_label) 
                           for cls_label in leg_le.classes_]
leg_features = pd.DataFrame(leg_feature_arr, 
                            columns=leg_feature_labels)*****

一般来说,你总是可以使用fit_transform(…)函数将两个特征编码在一起,方法是将两个特征的二维数组传递给它(查看文档!).但是我们分别对每个特性进行编码,以便于理解。除此之外,我们还可以创建单独的数据框,并对其进行相应的标注。现在让我们连接这些特征框架,看看最终的结果。

*****poke_df_ohe = pd.concat([poke_df_sub, gen_features, leg_features], axis=1)
columns = sum([['Name', 'Generation', 'Gen_Label'],   
               gen_feature_labels, ['Legendary', 'Lgnd_Label'], 
               leg_feature_labels], [])
poke_df_ohe[columns].iloc[4:10]*****

One-hot encoded features for Pokémon generation and legendary status

因此,您可以看到为Generation创建了 6 虚拟变量或二进制特征,为Legendary创建了 2 虚拟变量或二进制特征,因为它们分别是这些属性中不同类别的总数。类别的 活动 状态由这些虚拟变量之一的 1 值表示,从上述数据帧中可以明显看出。

假设您在训练数据上建立了这种编码方案,并建立了一些模型,现在您有一些新数据,这些数据必须在预测之前针对如下特征进行设计。

*****new_poke_df = pd.DataFrame([['PikaZoom', 'Gen 3', True], 
                           ['CharMyToast', 'Gen 4', False]],
                       columns=['Name', 'Generation', 'Legendary'])
new_poke_df*****

Sample new data

在这里,您可以通过对新数据调用先前构建的LabeLEncoderOneHotEncoder 对象的transform(…)函数来利用scikit-learn’s优秀的 API。记住我们的工作流程,首先我们做 转换

*****new_gen_labels = gen_le.transform(new_poke_df['Generation'])
new_poke_df['Gen_Label'] = new_gen_labelsnew_leg_labels = leg_le.transform(new_poke_df['Legendary'])
new_poke_df['Lgnd_Label'] = new_leg_labelsnew_poke_df[['Name', 'Generation', 'Gen_Label', 'Legendary', 
             'Lgnd_Label']]*****

Categorical attributes after transformation

一旦我们有了数字标签,现在让我们应用编码方案!

*****new_gen_feature_arr = gen_ohe.transform(new_poke_df[['Gen_Label']]).toarray()
new_gen_features = pd.DataFrame(new_gen_feature_arr, 
                                columns=gen_feature_labels)new_leg_feature_arr = leg_ohe.transform(new_poke_df[['Lgnd_Label']]).toarray()
new_leg_features = pd.DataFrame(new_leg_feature_arr, 
                                columns=leg_feature_labels)new_poke_ohe = pd.concat([new_poke_df, new_gen_features, new_leg_features], axis=1)
columns = sum([['Name', 'Generation', 'Gen_Label'], 
               gen_feature_labels,
               ['Legendary', 'Lgnd_Label'], leg_feature_labels], [])new_poke_ohe[columns]*****

Categorical attributes after one-hot encoding

因此,您可以看到,通过利用scikit-learn’s强大的 API,可以很容易地在新数据上应用这个方案。

您还可以通过利用pandas中的to_dummies(…)函数轻松应用一键编码方案。

*****gen_onehot_features = pd.get_dummies(poke_df['Generation'])
pd.concat([poke_df[['Name', 'Generation']], gen_onehot_features], 
           axis=1).iloc[4:10]*****

One-hot encoded features by leveraging pandas

上述数据框描述了应用于Generation属性的独热编码方案,其结果与之前的预期结果相同。

虚拟编码方案

伪编码方案类似于独热编码方案,除了在伪编码方案的情况下,当应用于具有 m 个不同标签的分类特征时,我们得到 m - 1 个二进制特征。因此,分类变量的每个值都被转换成大小为 m - 1 的向量。额外的特征被完全忽略,因此如果类别值的范围从 {0,1,…,m-1 }第 0 个m-1 个 特征列被丢弃,相应的类别值通常由全零的矢量 (0) 表示。让我们通过删除第一级二进制编码特征(Gen 1)来尝试在神奇宝贝Generation 上应用虚拟编码方案。

*****gen_dummy_features = pd.get_dummies(poke_df['Generation'], 
                                    drop_first=True)
pd.concat([poke_df[['Name', 'Generation']], gen_dummy_features], 
          axis=1).iloc[4:10]*****

Dummy coded features for Pokémon generation

如果你愿意,你也可以选择丢弃最后一级二进制编码特征(Gen 6)如下。

*****gen_onehot_features = pd.get_dummies(poke_df['Generation'])
gen_dummy_features = gen_onehot_features.iloc[:,:-1]
pd.concat([poke_df[['Name', 'Generation']], gen_dummy_features],  
          axis=1).iloc[4:10]*****

Dummy coded features for Pokémon generation

基于上面的描述,很清楚属于丢弃特征的类别被表示为零向量( 0) ,就像我们之前讨论的那样。

效果编码方案

效果编码方案实际上与虚拟编码方案非常相似,只是在编码过程中,虚拟编码方案中代表所有 0 的类别值的编码特征或特征向量在效果编码方案中被替换为 -1 。通过下面的例子,这将变得更加清楚。

*****gen_onehot_features = pd.get_dummies(poke_df['Generation'])
gen_effect_features = gen_onehot_features.iloc[:,:-1]
gen_effect_features.loc[np.all(gen_effect_features == 0, 
                               axis=1)] = -1.
pd.concat([poke_df[['Name', 'Generation']], gen_effect_features], 
          axis=1).iloc[4:10]*****

Effect coded features for Pokémon generation

上面的输出清楚地表明,与虚拟编码中的 0 相比,属于Generation 6 的神奇宝贝现在由值为-1 的向量表示。

面元计数方案

到目前为止,我们讨论的编码方案在一般分类数据上工作得很好,但是当任何特征中不同类别的数量变得非常大时,它们就开始产生问题。对任何一个绝对特征都必不可少的 m 不同的标签,你就得到 m 单独的特征。这很容易增加特征集的大小,从而导致诸如存储问题、关于时间、空间和内存的模型训练问题之类的问题。除此之外,我们还必须处理通常所说的 【维数灾难】等问题,在这些问题中,基本上有大量的特征和没有足够的代表性样本,模型性能开始受到影响,经常导致过度拟合。

因此,对于具有大量可能类别(如 IP 地址)的特征,我们需要寻找其他分类数据特征工程方案。容器计数方案对于处理具有许多类别的分类变量是一种有用的方案。在该方案中,我们使用基于概率的关于值和实际目标或响应值的统计信息,而不是使用实际标签值进行编码,我们的目标是在建模工作中预测这些信息。一个简单的例子是基于 IP 地址和 DDOS 攻击中使用的 IP 地址的历史数据;我们可以为由任何 IP 地址引起的 DDOS 攻击建立概率值。使用该信息,我们可以对输入特征进行编码,该输入特征描述了如果相同的 IP 地址在将来出现,导致 DDOS 攻击的概率值是多少。这个方案需要历史数据作为先决条件,是一个精心制作的方案。用一个完整的例子来描述这一点目前是困难的,但是你可以参考网上的一些资源。

特征散列方案

特征散列方案是另一种用于处理大规模分类特征的有用的特征工程方案。在该方案中,散列函数通常与预设的编码特征数量(作为预定义长度的向量)一起使用,使得特征的散列值被用作该预定义向量中的索引,并且值被相应地更新。由于哈希函数将大量值映射到一个有限的小值集,多个不同的值可能会创建相同的哈希,这称为冲突。通常,使用带符号的散列函数,使得从散列中获得的值的符号被用作存储在最终特征向量中适当索引处的值的符号。这将确保更少的冲突和由于冲突导致的更少的误差累积。

哈希方案适用于字符串、数字和其他结构,如向量。您可以将哈希输出视为一组有限的 b 二进制文件,这样,当哈希函数应用于相同的值\类别时,它们会根据哈希值被分配到 b 二进制文件中的相同二进制文件(或二进制文件的子集)。我们可以预先定义 b 的值,该值成为我们使用特征散列方案编码的每个分类属性的编码特征向量的最终大小。

因此,即使我们在一个特征中有超过 1000 个不同的类别,并且我们将 b=10 设置为最终的特征向量大小,如果我们使用一位热码编码方案,则输出特征集将仍然只有 10 个特征,而不是 1000 个二进制特征。让我们考虑一下视频游戏数据集中的Genre属性。

******unique_genres = np.unique(vg_df[['Genre']])
print("Total game genres:", len(unique_genres))
print(unique_genres)**Output
------**
Total game genres: 12
['Action' 'Adventure' 'Fighting' 'Misc' 'Platform' 'Puzzle' 'Racing'
 'Role-Playing' 'Shooter' 'Simulation' 'Sports' 'Strategy']******

我们可以看到一共有 12 种类型的电子游戏。如果我们在Genre 特性上使用一个独热编码方案,我们最终会有 12 个二进制特性。相反,我们现在将通过利用scikit-learn’s FeatureHasher类来使用一个特性散列方案,它使用一个带符号的 32 位版本的 Murmurhash3 散列函数。在这种情况下,我们将预先定义最终的特征向量大小为 6

******from sklearn.feature_extraction import FeatureHasherfh = FeatureHasher(n_features=6, input_type='string')
hashed_features = fh.fit_transform(vg_df['Genre'])
hashed_features = hashed_features.toarray()
pd.concat([vg_df[['Name', 'Genre']], pd.DataFrame(hashed_features)], 
          axis=1).iloc[1:7]******

Feature Hashing on the Genre attribute

基于上述输出,Genre 分类属性已经使用哈希方案编码成 6 特征,而不是 12 。我们还可以看到,行 16 表示相同流派的游戏, 平台 被正确地编码到相同的特征向量中。

结论

这些例子应该让您对离散、分类数据的特征工程的流行策略有一个很好的了解。如果你阅读了本系列的第一部分 ,你会发现与连续的数字数据相比,处理分类数据有点困难,但是绝对有趣!我们还讨论了一些使用特征工程来处理大特征空间的方法,但是你也应该记住还有其他的技术,包括 特征选择降维 方法来处理大特征空间。我们将在后面的文章中讨论其中的一些方法。

接下来是针对非结构化文本数据的特征工程策略。敬请期待!

要了解连续数值数据的特征工程策略,请查看本系列的第 1 部分****

本文中使用的所有代码和数据集都可以从我的 GitHub 中获得

该代码也可作为 Jupyter 笔记本

文本数据的传统方法

原文:https://towardsdatascience.com/understanding-feature-engineering-part-3-traditional-methods-for-text-data-f6f7d70acd41?source=collection_archive---------0-----------------------

了解特征工程(第三部分)

驯服非结构化文本数据的传统策略

介绍

在本系列*的前两部分中,我们已经介绍了处理结构化数据的各种特性工程策略。*检查第一部分:连续的数值数据第二部分:离散的分类数据复习。在本文中,我们将了解如何处理文本数据,这无疑是最丰富的非结构化数据来源之一。文本数据通常由能够代表自由流动文本的单词、句子甚至段落的文档组成。固有的非结构化(没有格式整齐的数据列!)和文本数据的噪声性质使得机器学习方法更难直接在原始文本数据上工作。因此,在本文中,我们将遵循动手实践的方法,探索一些最流行和最有效的从文本数据中提取有意义特征的策略。这些特征可以很容易地用于建立机器学习或深度学习模型。

动机

特征工程通常被认为是创造卓越和性能更好的机器学习模型的秘方。仅仅一个优秀的功能就可能成为你赢得挑战的入场券!对于非结构化的文本数据,特征工程的重要性甚至更加重要,因为我们需要将自由流动的文本转换为一些数字表示,然后机器学习算法可以理解这些数字表示。即使有了自动化特征工程能力的出现,在将它们作为黑盒模型应用之前,您仍然需要理解不同特征工程策略背后的核心概念。永远记住,“如果给你一盒修理房子的工具,你要知道什么时候用电钻,什么时候用锤子!”

理解文本数据

我敢肯定,在这种情况下,你们所有人对文本数据的组成都有一个大致的概念。请记住,您总是可以拥有结构化数据属性形式的文本数据,但是这些数据通常属于结构化分类数据的范畴。

在这个场景中,我们谈论的是单词、短语、句子和整个文档形式的自由流动的文本。本质上,我们有一些句法结构,像单词组成短语,短语组成句子,句子又组成段落。然而,文本文档没有固有的结构,因为您可能有各种各样的单词,这些单词可能在文档之间有所不同,并且与结构化数据集中固定数量的数据维度相比,每个句子的长度也是可变的。这篇文章本身就是一个完美的文本数据例子!

特征工程策略

让我们看看一些流行而有效的策略,用于处理文本数据并从中提取有意义的特征,这些策略可用于下游的机器学习系统。请注意,您可以在我的 GitHub 库 中访问本文中使用的所有代码,以供将来参考。我们将从加载一些基本的依赖项和设置开始。

*import pandas as pd
import numpy as np
import re
import nltk
import matplotlib.pyplot as pltpd.options.display.max_colwidth = 200
%matplotlib inline*

现在让我们来看一个样本文档集,我们将在本文中对其进行大部分分析。 语料库 通常是通常属于一个或多个主题的文本文档的集合。

Our sample text corpus

您可以看到,我们已经为我们的玩具语料库提取了几个属于不同类别的样本文本文档。在我们谈论特征工程之前,一如既往,我们需要做一些数据预处理或争论,以删除不必要的字符,符号和令牌。

文本预处理

可以有多种清理和预处理文本数据的方式。在下面的几个要点中,我们强调了自然语言处理(NLP)管道中大量使用的一些最重要的方法。

  • ***去除标签:*我们的文本往往包含 HTML 标签这样不必要的内容,在分析文本的时候并没有增加多少价值。BeautifulSoup 库在为此提供必要的函数方面做得非常出色。
  • 删除带重音的字符:在任何文本语料库中,尤其是在处理英语语言时,经常会遇到带重音的字符\字母。因此,我们需要确保这些字符被转换并标准化为 ASCII 字符。一个简单的例子就是将转换成再转换成 e
  • ***扩展缩写:*在英语中,缩写基本上是单词或音节的缩短版本。这些现有单词或短语的缩短版本是通过删除特定的字母和声音创建的。例如, 不要不要我要我要 。将每个缩写转换为其扩展的原始形式通常有助于文本标准化。
  • ***去除特殊字符:*通常为非字母数字字符的特殊字符和符号通常会增加非结构化文本中的额外噪声。更常见的是,简单的正则表达式(regexes)可以用来实现这一点。
  • 词干和词汇化:**词干通常是可能单词的基本形式,可以通过将词缀前缀后缀附加到词干来创建新单词。这就是所谓的变调。获得单词基本形式的反向过程被称为词干提取。一个简单的例子就是 手表 ES手表 ING手表 ED 这几个词。他们以词根词干 为基础形式。词汇化与词干化非常相似,我们移除词缀来获得单词的基本形式。然而,在这种情况下,基本形式被称为词根,而不是词干。区别在于词根总是字典上正确的单词(存在于字典中),但是词干可能不是这样。
  • 去除停用词:**意义不大或没有意义的词,尤其是在从文本中构建有意义的特征时,被称为停用词或停用词。如果你在语料库中做一个简单的术语或词频,这些通常是出现频率最高的词。像 aa等单词都被认为是停用词。没有通用的停用词表,但是我们使用来自nltk的标准英语停用词表。您也可以根据需要添加自己的特定领域的停用词。

除此之外,您还可以进行其他标准操作,如标记化、删除多余的空格、文本小写以及更高级的操作,如拼写纠正、语法错误纠正、删除重复字符等。如果你有兴趣,你可以从我最近的一本书中查阅 一个关于文本预处理 的样本笔记本。

由于本文的重点是特征工程,我们将构建一个简单的文本预处理程序,重点是删除文本语料库中的特殊字符、多余空格、数字、停用词和小写字母。

一旦我们准备好基本的预处理管道,让我们将同样的应用到我们的样本语料库。

***norm_corpus = normalize_corpus(corpus)
norm_corpus**Output
------** array(['sky blue beautiful', 'love blue beautiful sky',
       'quick brown fox jumps lazy dog',
       'kings breakfast sausages ham bacon eggs toast beans',
       'love green eggs ham sausages bacon',
       'brown fox quick blue dog lazy', 
       'sky blue sky beautiful today',
       'dog lazy brown fox quick'],
      dtype='<U51')***

上面的输出应该让您清楚地看到我们的每个样本文档在预处理后的样子。现在让我们来设计一些功能吧!

词汇袋模型

对于非结构化文本,这可能是最简单的向量空间表示模型。向量空间模型是一个简单的数学模型,将非结构化文本(或任何其他数据)表示为数字向量,这样向量的每个维度都是一个特定的特征\属性。单词袋模型将每个文本文档表示为数字向量,其中每个维度是来自语料库的特定单词,并且该值可以是它在文档中的频率、出现次数(用 1 或 0 表示)或者甚至是加权值。这个模型之所以叫这个名字,是因为每个文档都被字面上表示为它自己的单词的“包”,而不考虑单词顺序、序列和语法。

*****Output
------**
array([[0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0],
       [1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0],
       [1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
       [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1],
       [0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0]
      ], dtype=int64)***

因此,您可以看到我们的文档已经被转换成数字向量,这样,在上面的特征矩阵中,每个文档都由一个向量(行)表示。下面的代码将有助于用一种更容易理解的格式来表示这一点。

Our Bag of Words model based document feature vectors

这应该会让事情更清楚吧!您可以清楚地看到,特征向量中的每一列或每一个维度代表语料库中的一个单词,每一行代表我们的一个文档。任何单元格中的值表示该单词(由列表示)在特定文档(由行表示)中出现的次数。因此,如果文档集由跨越所有文档的 N 个 唯一单词组成,那么对于每个文档,我们将有一个 N 维 向量。

N 克模型袋

一个单词只是一个标记,通常被称为一元语法或一元语法。我们已经知道单词袋模型不考虑单词的顺序。但是如果我们也想考虑出现在序列中的短语或单词集合呢?N-grams 帮助我们实现了这一点。N 元语法基本上是来自文本文档的单词标记的集合,使得这些标记是连续的并且按顺序出现。二元语法表示 2 阶的 n 元语法(两个单词),三元语法表示 3 阶的 n 元语法(三个单词),依此类推。因此,N-gram 模型只是单词模型的扩展,所以我们也可以利用基于 N-gram 的特征。下面的例子描述了每个文档特征向量中基于二元语法的特征。

Bi-gram based feature vectors using the Bag of N-Grams Model

这为我们的文档提供了特征向量,其中每个特征由表示两个单词序列的二元语法组成,值表示该二元语法在我们的文档中出现的次数。

TF-IDF 模型

词袋模型在用于大型语料库时可能会出现一些潜在的问题。因为特征向量是基于绝对术语频率的,所以可能有一些术语在所有文档中频繁出现,并且这些术语可能会盖过特征集中的其他术语。TF-IDF 模型试图通过在其计算中使用一个缩放或归一化因子来解决这个问题。TF-IDF 代表词频-逆文档频率,它在
的计算中使用了两个度量的组合,即: 【词频】逆文档频率(idf) 。这项技术是为搜索引擎中的查询结果排序而开发的,现在它是信息检索和 NLP 领域中不可或缺的模型。

数学上,我们可以将 TF-IDF 定义为 tfidf = tf x idf ,可以进一步展开表示如下。

这里, tfidf(w,D) 是文档中单词 w 的 TF-IDF 得分。术语 tf(w,D) 表示单词 w 在文档 D 中的词频,可以从词袋模型中得到。术语 idf(w,D) 是术语 w 的逆文档频率,其可以计算为语料库 C 中的文档总数除以单词 w 的文档频率的对数变换,这基本上是单词 w 在语料库中的文档频率这个模型有多种变体,但最终都给出了非常相似的结果。现在让我们把它应用到我们的语料库中吧!

Our TF-IDF model based document feature vectors

我们的每个文本文档的基于 TF-IDF 的特征向量显示了与原始单词包模型值相比的缩放和归一化值。有兴趣的读者可能想深入了解这个模型内部工作原理的更多细节,可以参考第 181 页的 使用 Python 的文本分析(Springer \ ApressDipanjan Sarkar,2016)

文档相似度

文档相似性是使用基于距离或相似性的度量的过程,该度量可用于基于从文档中提取的特征(如单词袋或 tf-idf)来识别文本文档与任何其他文档的相似程度。

Are we similar?

因此,您可以看到,我们可以在上一节中设计的基于 tf-idf 的功能的基础上进行构建,并通过利用这些基于相似性的功能,使用它们来生成在搜索引擎、文档聚类和信息检索等领域中有用的新功能。

语料库中的成对文档相似性涉及计算语料库中每对文档的文档相似性。因此,如果在一个语料库中有 C 个文档,那么最终会得到一个 C x C 矩阵,使得每一行和每一列都代表一对文档的相似性得分,这分别代表该行和该列的索引。有几种用于计算文档相似性的相似性和距离度量。其中包括余弦距离/相似度、欧氏距离、曼哈顿距离、BM25 相似度、jaccard 距离等等。在我们的分析中,我们将使用可能是最流行和最广泛使用的相似性度量,
余弦相似性,并基于它们的 TF-IDF 特征向量来比较成对的文档相似性。

Pairwise document similarity matrix (cosine similarity)

余弦相似性基本上给出了一种度量,表示两个文本文档的特征向量表示之间的角度的余弦。文档之间的角度越小,它们就越接近和相似,如下图所示。

Cosine similarity depictions for text document feature vectors

仔细观察相似性矩阵清楚地告诉我们,文档(0、1 和 6)、(2、5 和 7)彼此非常相似,文档 3 和 4 彼此稍微相似,但是幅度不是很大,但是仍然比其他文档强。这一定表明这些相似的文件有一些相似的特征。这是一个分组或聚类的完美例子,可以通过无监督学习来解决,特别是当您处理数百万文本文档的庞大语料库时。

基于相似特征的文档聚类

聚类利用无监督学习将数据点(在这个场景中是文档)分组到组或聚类中。我们将在这里利用无监督的层次聚类算法,通过利用我们之前生成的文档相似性特征,尝试将来自我们的玩具语料库的相似文档分组在一起。有两种类型的层次聚类算法,即凝聚和分裂方法。我们将使用凝聚聚类算法,这是一种使用自下而上方法的分层聚类,即每个观察或文件从其自己的聚类开始,然后使用测量数据点之间距离的距离度量和链接合并标准将聚类连续合并在一起。下图显示了一个示例描述。

Agglomerative Hierarchical Clustering

关联标准的选择决定了合并策略。连锁标准的一些例子是沃德、完全连锁、平均连锁等。该标准对于在每个步骤中基于目标函数的最优值选择要合并的聚类对(最低步骤中的单个文档和较高步骤中的聚类)非常有用。我们选择沃德的最小方差方法作为我们的连锁标准,以最小化总的组内方差。因此,在每一步,我们找到合并后导致总的类内方差最小增加的那对类。因为我们已经有了相似性特征,所以让我们在样本文档上构建链接矩阵。

Linkage Matrix for our Corpus

如果仔细观察关联矩阵,您会发现关联矩阵的每一步(每一行)都告诉我们哪些数据点(或聚类)被合并在一起。如果你有 n 个数据点,那么链接矩阵, Z 将具有*(n-1)x4其中将告诉我们哪些聚类在步骤 i 被合并。每行有四个元素,前两个元素是数据点标识符或聚类标签(在矩阵的后面部分,一旦
多个数据点合并),第三个元素是前两个元素(数据点或聚类)之间的聚类距离,最后一个元素是合并完成后聚类中元素\数据点的总数。我们推荐你参考 scipy 文档 ,里面对此有详细解释。
*

现在让我们把这个矩阵想象成一个树状图,以便更好地理解这些元素!

Dendrogram visualizing our hierarchical clustering process

我们可以看到每个数据点如何开始作为一个单独的集群,并慢慢开始与其他数据点合并形成集群。从颜色和树状图的高度来看,如果您考虑大约 1.0 或更高的距离度量(由虚线表示),您可以看到该模型已经正确地识别了三个主要聚类。利用这个距离,我们得到我们的聚类标签。

Clustering our documents into groups with hierarchical clustering

因此,您可以清楚地看到,我们的算法已经根据分配给它们的聚类标签,在我们的文档中正确地识别了三个不同的类别。这将让您很好地了解如何利用我们的 TF-IDF 特性来构建我们的相似性特性,这反过来又有助于对我们的文档进行聚类。您实际上可以在将来使用这个管道来聚集您自己的文档!

主题模型

我们还可以使用一些摘要技术从文本文档中提取基于主题或概念的特征。主题模型的思想围绕着从表示为主题的文档语料库中提取关键主题或概念的过程。每个主题可以被表示为来自文档语料库的单词/术语的包或集合。总的来说,这些术语表示特定的主题、主题或概念,并且每个主题可以通过这些术语所传达的语义来容易地与其他主题区分开来。然而,基于这些数据,你经常会得到一些重叠的主题。这些概念可以从简单的事实和陈述到观点和展望。主题模型在总结大量文本文档以提取和描述关键概念时非常有用。它们还可用于从文本数据中提取特征,以捕捉数据中的潜在模式。

An example of topic models

主题建模有多种技术,其中大多数都涉及某种形式的矩阵分解。像潜在语义索引(LSI)这样的一些技术使用矩阵分解操作,更具体地说是奇异值分解。我们将使用另一种技术是潜在狄利克雷分配(LDA),它使用一种生成概率模型,其中每个文档由几个主题的组合组成,每个术语或单词可以分配给一个特定的主题。这类似于基于 pLSI 的模型(概率 LSI)。在 LDA 的情况下,每个潜在主题包含一个 Dirichlet 先验。

这项技术背后的数学是相当复杂的,所以我会尽量总结一下,而不会用很多细节来烦你。我推荐读者去看看克里斯汀·多伊格的这篇精彩的演讲。****

End-to-end LDA framework (courtesy of C. Doig, Introduction to Topic
Modeling in Python)

上图中的黑框表示核心算法,该算法利用前面提到的参数从 M 文档中提取 K 主题。下面的步骤简单地解释了算法在幕后发生了什么。

运行几次迭代后,我们应该为每个文档准备好主题混合,然后从指向该主题的术语中生成每个主题的成分。像gensimscikit-learn这样的框架使我们能够利用 LDA 模型来生成主题。

出于特征工程的目的(这也是本文的目的),您需要记住,当 LDA 应用于文档术语矩阵(TF-IDF 或单词包特征矩阵)时,它被分解为两个主要部分。

  • 文档-主题矩阵,这将是我们正在寻找的特征矩阵。
  • 一个主题术语矩阵,帮助我们在语料库中寻找潜在的主题。

让我们利用scikit-learn得到如下的文档-主题矩阵。

Document-Topic Matrix from our LDA Model

在上面的输出中,您可以清楚地看到哪些文档对三个主题中的哪一个贡献最大。您可以按如下方式查看主题及其主要组成部分。

******Topic 1
-------**
[('sky', 4.3324395825632624), ('blue', 3.3737531748317711), ('beautiful', 3.3323652405224857), ('today', 1.3325579841038182), ('love', 1.3304224288080069)]**Topic 2
-------**
[('bacon', 2.3326959484799978), ('eggs', 2.3326959484799978), ('ham', 2.3326959484799978), ('sausages', 2.3326959484799978), ('love', 1.335454457601996), ('beans', 1.3327735253784641), ('breakfast', 1.3327735253784641), ('kings', 1.3327735253784641), ('toast', 1.3327735253784641), ('green', 1.3325433207547732)]**Topic 3
-------** [('brown', 3.3323474595768783), ('dog', 3.3323474595768783), ('fox', 3.3323474595768783), ('lazy', 3.3323474595768783), ('quick', 3.3323474595768783), ('jumps', 1.3324193736202712), ('blue', 1.2919635624485213)]****

因此,你可以清楚地看到,这三个主题根据它们的构成术语彼此有很大的区别,第一个谈论天气,第二个谈论食物,最后一个谈论动物。选择主题建模的主题数量本身就是一个完整的主题(不是双关语!)是一门艺术,也是一门科学。有各种各样的方法和试探法来获得最佳的主题数量,但是由于这些技术的详细性质,我们在这里不讨论它们。

具有主题模型特征的文档聚类

我们使用基于特征的词袋模型,使用 LDA 建立基于特征的主题模型。我们现在实际上可以利用我们获得的文档术语矩阵,并使用无监督聚类算法来尝试对我们的文档进行分组,就像我们之前使用相似性特征所做的那样。

这一次,我们将使用一种非常流行的基于划分的聚类方法,K-means 聚类来根据这些文档的主题模型特征表示对它们进行聚类或分组。在 K-means 聚类中,我们有一个输入参数 k ,它指定了使用文档特征输出的聚类数。这种聚类方法是一种基于质心的聚类方法,它试图将这些文档聚类成等方差的聚类。它试图通过最小化类内平方和度量(也称为惯性)来创建这些类。有多种方法来选择 k 的最佳值,如使用误差平方和度量、轮廓系数和肘方法。

Clustering our documents into groups with K-means clustering

从上面的输出中我们可以看到,我们的文档被正确地分配到了正确的集群中!

高级策略的未来范围

我们在本文中没有涉及的是围绕文本数据的特征工程的几个高级策略,这些策略最近变得很突出。这包括利用基于深度学习的模型来获得单词嵌入。在本系列的下一部分中,我们将深入探讨这些模型,并通过详细的实践示例介绍流行的单词嵌入模型,如word 2 vecGloVe,敬请关注!

结论

这些例子应该让您对文本数据的特征工程的流行策略有一个很好的了解。请记住,这些是基于数学、信息检索和自然语言处理概念的传统策略。因此,随着时间的推移,这些经过试验和测试的方法在各种数据集和问题中被证明是成功的。接下来将是利用深度学习模型对文本数据进行特征工程的详细策略!

要阅读关于连续数值数据的特征工程策略,请查看本系列的第 1 部分的

要了解离散分类数据的特征工程策略,请查看本系列的 第 2 部分

本文中使用的所有代码和数据集都可以从我的 GitHub 中获得

该代码也可作为 Jupyter 笔记本

如果你对我的文章或数据科学有任何反馈、评论或有趣的见解要分享,请随时通过我的 LinkedIn 社交媒体频道联系我。

**** [## Dipanjan Sarkar | LinkedIn

查看 Dipanjan Sarkar 在世界最大的职业社区 LinkedIn 上的个人资料。Dipanjan 有 5 份工作列在…

www.linkedin.com](https://www.linkedin.com/in/dipanzan/)****

文本数据深度学习方法的直观实践方法— Word2Vec、GloVe 和 FastText

原文:https://towardsdatascience.com/understanding-feature-engineering-part-4-deep-learning-methods-for-text-data-96c44370bbfa?source=collection_archive---------0-----------------------

了解特征工程(第四部分)

驯服非结构化文本数据的更新、高级策略

介绍

处理非结构化文本数据非常困难,尤其是当你试图构建一个智能系统,像人类一样解释和理解自由流动的自然语言时。您需要能够处理嘈杂的、非结构化的文本数据,并将其转换为任何机器学习算法都可以理解的结构化、矢量化格式。来自自然语言处理、机器学习或深度学习的原理所有这些都属于人工智能的大伞下,是该行业的有效工具。基于我以前的帖子,这里要记住的重要一点是,任何机器学习算法都是基于统计学、数学和优化的原则。因此,他们还不够聪明,不能以原始的、自然的形式处理文本。我们在 第 3 部分:文本数据的传统方法 中介绍了一些从文本数据中提取有意义特征的传统策略。我鼓励你去看看同样的网站,做一个简短的复习。在本文中,我们将探讨更高级的特征工程策略,这些策略通常利用深度学习模型。更具体地说,我们将涵盖 Word2VecGloVeFastText 型号。

动机

我们已经多次讨论过,包括在我们之前的文章 中的 中,特征工程是创建更好的机器学习模型的秘方。永远记住,即使有了自动化特征工程能力的出现,你仍然需要理解应用这些技术背后的核心概念。否则,它们只是黑盒模型,你不知道如何针对你试图解决的问题进行调整和优化。

传统模式的缺点

用于文本数据的传统(基于计数的)特征工程策略涉及属于通常被称为单词袋模型的模型家族的模型。这包括术语频率、TF-IDF(术语频率-逆文档频率)、N 元语法等等。虽然它们是从文本中提取特征的有效方法,但由于模型的固有性质只是一个非结构化单词的包,我们会丢失每个文本文档中邻近单词周围的附加信息,如语义、结构、序列和上下文。这为我们探索更复杂的模型提供了足够的动力,这些模型可以捕捉这些信息,并为我们提供单词的向量表示特征,通常称为嵌入。

对单词嵌入的需求

虽然这确实有些道理,但是我们为什么要有足够的动力去学习和构建这些单词嵌入呢?关于语音或图像识别系统,所有信息已经以嵌入在高维数据集中的丰富密集特征向量的形式存在,如音频频谱图和图像像素强度。然而,当涉及到原始文本数据时,尤其是像单词包这样基于计数的模型,我们处理的是单个单词,这些单词可能有自己的标识符,并且没有捕获单词之间的语义关系。这导致文本数据的巨大稀疏词向量,因此,如果我们没有足够的数据,我们可能最终会得到糟糕的模型,甚至由于维数灾难而过度拟合数据。

Comparing feature representations for audio, image and text

为了克服基于词袋模型的特征丢失语义和特征稀疏的缺点,我们需要利用【VSMs】向量空间模型,在这个连续的向量空间中基于语义和上下文相似度嵌入词向量。事实上, 分布语义学 领域中的 分布假说 告诉我们,在同一语境中出现和使用的词在语义上彼此相似,具有相似的意义。简单来说,‘一言以蔽之’。其中一篇详细谈论这些语义词向量和各种类型的著名论文是‘不要算,预测!Baroni 等人对上下文计数与上下文预测语义向量的系统比较。我们不会深入探讨,但简而言之,有两种主要的上下文单词向量方法。等基于计数的方法 【潜在语义分析】(LSA)可用于计算单词与其相邻单词在语料库中出现频率的一些统计度量,然后根据这些度量为每个单词构建密集的单词向量。 预测方法基于神经网络的语言模型 尝试通过查看语料库中的单词序列从其相邻单词中预测单词,在此过程中,它学习分布式表示,给我们提供密集的单词嵌入。在本文中,我们将重点关注这些预测方法。

特征工程策略

让我们看看处理文本数据并从中提取有意义的特征的一些高级策略,这些策略可用于下游的机器学习系统。请注意,您可以在我的 GitHub 库中访问本文中使用的所有代码,以供将来参考。我们将从加载一些基本的依赖项和设置开始。

****import pandas as pd
import numpy as np
import re
import nltk
import matplotlib.pyplot as pltpd.options.display.max_colwidth = 200
%matplotlib inline****

我们现在将采用一些文档的语料库,我们将在其上执行所有的分析。对于其中一个语料库,我们将重用我们上一篇文章中的语料库, 第 3 部分:文本数据的传统方法 。为了便于理解,我们将代码描述如下。

Our sample text corpus

我们的玩具语料库由属于几个类别的文档组成。本文中我们将使用的另一个语料库是通过nltk中的corpus模块从 项目中免费获得的 钦定版圣经 。在下一节中,我们将很快加载它。在我们谈论特征工程之前,我们需要预处理和规范化这个文本。

文本预处理

可以有多种清理和预处理文本数据的方式。在自然语言处理(NLP)管道中大量使用的最重要的技术已经在本系列 第 3 部分【文本预处理】 部分中详细强调。由于本文的重点是功能工程,就像我们的上一篇文章一样,我们将重用我们简单的文本预处理程序,它专注于删除文本语料库中的特殊字符、额外空格、数字、停用词和小写字母。

一旦我们准备好了基本的预处理流水线,让我们首先把它应用到我们的玩具语料库中。

***norm_corpus = normalize_corpus(corpus)
norm_corpus**Output
------** array(['sky blue beautiful', 'love blue beautiful sky',
       'quick brown fox jumps lazy dog',
       'kings breakfast sausages ham bacon eggs toast beans',
       'love green eggs ham sausages bacon',
       'brown fox quick blue dog lazy', 
       'sky blue sky beautiful today',
       'dog lazy brown fox quick'],
      dtype='<U51')***

现在让我们使用nltk加载基于 钦定版圣经 的其他语料库,并对文本进行预处理。

下面的输出显示了我们的语料库中的总行数,以及预处理如何对文本内容进行处理。

*****Output
------**Total lines: 30103

Sample line: ['1', ':', '6', 'And', 'God', 'said', ',', 'Let', 'there', 'be', 'a', 'firmament', 'in', 'the', 'midst', 'of', 'the', 'waters', ',', 'and', 'let', 'it', 'divide', 'the', 'waters', 'from', 'the', 'waters', '.']

Processed line: god said let firmament midst waters let divide waters waters***

让我们看看现在流行的一些单词嵌入模型和来自我们语料库的工程特征!

Word2Vec 模型

该模型由谷歌在 2013 年创建,是一种基于预测性深度学习的模型,用于计算和生成高质量、分布式和连续的单词密集矢量表示,这些表示捕捉上下文和语义的相似性。本质上,这些是无监督的模型,可以接受大量文本语料库,创建可能单词的词汇表,并在表示该词汇表的向量空间中为每个单词生成密集的单词嵌入。通常你可以指定单词嵌入向量的大小,向量的总数实质上就是词汇量的大小。这使得这个密集向量空间的维数比使用传统单词袋模型构建的高维稀疏向量空间低得多。

Word2Vec 可以利用两种不同的模型架构来创建这些单词嵌入表示。这些包括:

  • 连续单词包(CBOW)模型
  • 跳格模型

最初由 Mikolov 等人介绍,我建议感兴趣的读者阅读围绕这些模型的原始论文,包括 Mikolov 等人的 【单词和短语的分布式表示及其组合性】和 Mikolov 等人的 【向量空间中单词表示的有效估计】,以获得一些很好的深入观点。

连续词汇袋模型

CBOW 模型架构试图基于源上下文单词(周围单词)来预测当前目标单词(中心单词)。考虑一个简单的句子, “敏捷的棕色狐狸跳过懒惰的狗” ,这可以是成对的 (context_window,target_word) 其中如果我们考虑大小为 2 的上下文窗口,我们有这样的例子: (【敏捷,狐狸】、棕色)、(【the,棕色)、敏捷)、(【the,狗】、 等等。因此,该模型试图基于context_window单词来预测target_word

The CBOW model architecture (Source: https://arxiv.org/pdf/1301.3781.pdf Mikolov el al.)

虽然 Word2Vec 系列模型是无监督的,但这意味着你可以给它一个没有额外标签或信息的语料库,它可以从语料库中构建密集的单词嵌入。但是一旦你有了这个语料库,你仍然需要利用一个监督的分类方法来得到这些嵌入。但是我们将从语料库本身中进行,没有任何辅助信息。我们现在可以将这个 CBOW 架构建模为深度学习分类模型,使得我们接受 上下文单词作为我们的输入,X 并且尝试预测 目标单词,Y 。事实上,构建这种架构比 skip-gram 模型更简单,在 skip-gram 模型中,我们试图从源目标单词预测一整串上下文单词。

实施连续单词袋(CBOW)模型

虽然使用像 gensim 这样的具有 Word2Vec 模型的健壮框架是很好的,但是让我们从头开始尝试实现它,以获得一些关于幕后真正工作方式的观点。我们将利用我们的 圣经语料库 中包含的norm_bible变量来训练我们的模型。实施将集中在四个部分

  • 建立语料库词汇
  • 构建一个 CBOW(上下文,目标)生成器
  • 构建 CBOW 模型架构
  • 训练模型
  • 获取单词嵌入

不要再拖延了,让我们开始吧!

建立语料库词汇

首先,我们将首先构建我们的语料库词汇,从我们的词汇中提取每个唯一的单词,并为其映射一个唯一的数字标识符。

*****Output
------**Vocabulary Size: 12425
Vocabulary Sample: [('perceived', 1460), ('flagon', 7287), ('gardener', 11641), ('named', 973), ('remain', 732), ('sticketh', 10622), ('abstinence', 11848), ('rufus', 8190), ('adversary', 2018), ('jehoiachin', 3189)]***

因此,您可以看到,我们已经在语料库中创建了独特单词的词汇表,以及将单词映射到其独特标识符的方法,反之亦然。如果需要,**PAD**术语通常用于将上下文单词填充到固定长度。

构建一个 CBOW(上下文,目标)生成器

我们需要由目标中心词和周围上下文词组成的词对。在我们的实现中,一个 目标单词 的长度为**1**,而 周围上下文 的长度为**2 x window_size**,其中我们在语料库中的目标单词前后取**window_size** 单词。通过下面的例子,这将变得更加清楚。

*****Context (X): ['old','testament','james','bible'] -> Target (Y): king
Context (X): ['first','book','called','genesis'] -> Target(Y): moses
Context(X):['beginning','god','heaven','earth'] -> Target(Y):created
Context (X):['earth','without','void','darkness'] -> Target(Y): form
Context (X): ['without','form','darkness','upon'] -> Target(Y): void
Context (X): ['form', 'void', 'upon', 'face'] -> Target(Y): darkness
Context (X): ['void', 'darkness', 'face', 'deep'] -> Target(Y): upon
Context (X): ['spirit', 'god', 'upon', 'face'] -> Target (Y): moved
Context (X): ['god', 'moved', 'face', 'waters'] -> Target (Y): upon
Context (X): ['god', 'said', 'light', 'light'] -> Target (Y): let
Context (X): ['god', 'saw', 'good', 'god'] -> Target (Y): light*****

前面的输出应该让您对 X 如何形成我们的上下文单词有了更多的了解,我们正试图根据这个上下文来预测目标中心单词 Y 。举个例子,如果原文是‘太初神造天地’,经过预处理,去掉停用词后就变成了‘太初神 造了 【天地’,对我们来说,我们要达到的是,给定【始、神、天、地】为语境,目标中心词是什么,这种情况下就是' 创造了'**

构建 CBOW 模型架构

我们现在利用tensorflow之上的keras来为 CBOW 模型构建我们的深度学习架构。为此,我们的输入将是传递到嵌入层的上下文单词(用随机权重初始化)。单词嵌入被传播到 lambda 层,在那里我们平均出单词嵌入 (因此称为 CBOW,因为我们在平均时并不真正考虑上下文单词中的顺序或序列) ,然后我们将这个平均的上下文嵌入传递到预测我们的目标单词的密集 softmax 层。我们将其与实际的目标单词进行匹配,通过利用categorical_crossentropy损失来计算损失,并在每个时期执行反向传播,以在该过程中更新嵌入层。下面的代码向我们展示了我们的模型架构。

CBOW model summary and architecture

如果你仍然难以可视化上述深度学习模型,我建议你通读我之前提到的论文。我将尝试用简单的术语来总结这个模型的核心概念。我们有尺寸为**(2 x window_size)**输入上下文单词 ,我们将把它们传递给尺寸为**(vocab_size x embed_size)**嵌入层 ,这将为这些上下文单词**(1 x embed_size for each word)**中的每一个给出 密集单词嵌入 。接下来,我们使用一个λ层*** 来平均这些嵌入,并得到一个 平均密集嵌入 **(1 x embed_size)**,它被发送到 密集 softmax 层 ,后者输出最可能的目标单词。我们将其与实际的目标单词进行比较,计算损失,反向传播误差以调整权重(在嵌入层中),并对多个时期的所有*(上下文,目标)对重复该过程。下图试图解释同样的情况。**

Visual depiction of the CBOW deep learning model

我们现在准备在我们的语料库上训练这个模型,使用我们的数据生成器输入 (上下文,目标单词) 对。

训练模型

在我们完整的语料库上运行模型需要相当多的时间,所以我只运行了 5 个时期。您可以利用下面的代码,并在必要时增加更多的历元。

***Epoch: 1 	Loss: 4257900.60084
Epoch: 2 	Loss: 4256209.59646
Epoch: 3 	Loss: 4247990.90456
Epoch: 4 	Loss: 4225663.18927
Epoch: 5 	Loss: 4104501.48929***

****注意:运行这个模型计算量很大,如果使用 GPU 进行训练,效果会更好。我在一个 AWS **p2.x**实例上用 Tesla K80 GPU 对其进行了训练,仅 5 个纪元就花了我将近 1.5 小时!

一旦这个模型被训练,相似的单词应该基于嵌入层具有相似的权重,并且我们可以测试出相同的权重。

获取单词嵌入

为了获得整个词汇表的单词嵌入,我们可以利用下面的代码从嵌入层中提取出相同的内容。我们不在位置 0 进行嵌入,因为它属于填充项**(PAD)**,而填充项并不是真正感兴趣的单词。

Word Embeddings for our vocabulary based on the CBOW model

因此,您可以清楚地看到,每个单词都有一个大小为**(1x100)**的密集嵌入,如前面的输出所示。让我们试着根据这些嵌入,为感兴趣的特定单词找出一些上下文相似的单词。为此,我们基于密集嵌入向量在我们的词汇表中的所有单词之间建立成对距离矩阵,然后基于最短(欧几里德)距离找出每个感兴趣单词的 n 个最近邻居。

*****(12424, 12424)****{'egypt': ['destroy', 'none', 'whole', 'jacob', 'sea'],
 'famine': ['wickedness', 'sore', 'countries', 'cease', 'portion'],
 'god': ['therefore', 'heard', 'may', 'behold', 'heaven'],
 'gospel': ['church', 'fowls', 'churches', 'preached', 'doctrine'],
 'jesus': ['law', 'heard', 'world', 'many', 'dead'],
 'john': ['dream', 'bones', 'held', 'present', 'alive'],
 'moses': ['pharaoh', 'gate', 'jews', 'departed', 'lifted'],
 'noah': ['abram', 'plagues', 'hananiah', 'korah', 'sarah']}*****

你可以清楚地看到,其中一些在上下文中有意义 【上帝,天堂】【福音,教会】*** 等等,而一些可能没有意义。训练更多的纪元通常会得到更好的结果。现在,我们将探讨 skip-gram 体系结构,与 CBOW 相比,它通常会给出更好的结果。***

跳格模型

跳格模型体系结构通常试图实现 CBOW 模型的反向操作。它试图在给定目标单词(中心单词)的情况下预测源上下文单词(周围的单词)。考虑到我们前面的简单句子, “敏捷的棕色狐狸跳过懒惰的狗”。 如果我们使用 CBOW 模型,我们得到成对的 (context_window,target_word) 其中如果我们考虑大小为 2 的上下文窗口,我们有类似于 ([quick,fox],brown),([the,brown),quick),([the,dog],lazy) 等例子。现在考虑到 skip-gram 模型的目的是从目标单词预测上下文,该模型通常反转上下文和目标,并试图从其目标单词预测每个上下文单词。于是任务就变成了预测上下文 【快,狐狸】 给定目标词 【布朗】【the,brown】给定目标词 【快】 等等。因此,该模型试图基于目标单词来预测上下文窗口单词。

The Skip-gram model architecture (Source: https://arxiv.org/pdf/1301.3781.pdf Mikolov el al.)

就像我们在 CBOW 模型中讨论的那样,我们现在需要将这种跳过语法的架构建模为深度学习分类模型,以便我们将目标单词作为我们的输入,并尝试预测上下文单词。这变得有点复杂,因为在我们的上下文中有多个单词。我们通过将每个 (目标,上下文 _ 单词)对 分解成 (目标,上下文)对 来进一步简化这一点,使得每个上下文仅由一个单词组成。因此,我们之前的数据集被转换成像 (棕色,快速),(棕色,狐狸),(快速,the),(快速,棕色) 这样的对。但是如何监督或训练模型知道什么是上下文相关的,什么不是?**

为此,我们喂我们的跳过图模型对 (X,Y) 其中 X 是我们的 输入Y是我们的 标签 。我们通过使用 [(目标,上下文),1] 对作为 实际输入样本 来做到这一点,其中 目标 是我们感兴趣的单词,而 上下文 是出现在目标单词附近的上下文单词,并且 正标签 1 指示这是上下文相关的对。我们还输入 [(目标,随机),0] 对作为 负输入样本 其中 目标 再次是我们感兴趣的单词,但是 随机 只是从我们的词汇表中随机选择的单词,与我们的目标单词没有上下文或关联。因此 否定标记 0 表示这是一个上下文不相关的对。我们这样做是为了让模型能够学习哪些词对是上下文相关的,哪些是不相关的,并为语义相似的词生成相似的嵌入。

实现跳格模型

现在,让我们从头开始尝试并实现这个模型,以获得一些关于幕后工作方式的视角,这样我们就可以将其与 CBOW 模型的实现进行比较。我们将像往常一样利用包含在**norm_bible**变量中的圣经语料库来训练我们的模型。实施将集中在五个部分

  • 建立语料库词汇
  • 构建一个 skip-gram [(目标,上下文),关联]生成器
  • 构建跳格模型架构
  • 训练模型
  • 获取单词嵌入

让我们开始构建我们的 skip-gram Word2Vec 模型吧!

建立语料库词汇

首先,我们将遵循构建语料库词汇的标准流程,从我们的词汇中提取每个唯一的单词,并分配一个唯一的标识符,类似于我们在 CBOW 模型中所做的。我们还维护将单词转换成它们的唯一标识符的映射,反之亦然。

***Vocabulary Size: 12425
Vocabulary Sample: [('perceived', 1460), ('flagon', 7287), ('gardener', 11641), ('named', 973), ('remain', 732), ('sticketh', 10622), ('abstinence', 11848), ('rufus', 8190), ('adversary', 2018), ('jehoiachin', 3189)]***

正如我们所希望的那样,语料库中的每个独特的单词现在都是我们词汇表的一部分,带有一个独特的数字标识符。

构建一个 skip-gram [(目标,上下文),相关性]生成器

现在是时候构建我们的跳格生成器了,它会像我们之前讨论的那样给我们一对单词和它们的相关性。幸运的是,keras有一个可以使用的漂亮的skipgrams实用程序,我们不必像在 CBOW 中那样手动实现这个生成器。

****注:功能[**skipgrams(…)**](https://keras.io/preprocessing/sequence/#skipgrams)出现在[**keras.preprocessing.sequence**](https://keras.io/preprocessing/sequence)

此函数将一系列单词索引(整数列表)转换为以下形式的单词元组:

-(字,字在同一个窗口),标签为 1(阳性样本)。

-(单词,从词汇表中随机抽取的单词),标签为 0(负样本)。

*****(james (1154), king (13)) -> 1
(king (13), james (1154)) -> 1
(james (1154), perform (1249)) -> 0
(bible (5766), dismissed (6274)) -> 0
(king (13), alter (5275)) -> 0
(james (1154), bible (5766)) -> 1
(king (13), bible (5766)) -> 1
(bible (5766), king (13)) -> 1
(king (13), compassion (1279)) -> 0
(james (1154), foreskins (4844)) -> 0*****

因此,您可以看到我们已经成功地生成了所需的跳转图,并且基于前面输出中的示例跳转图,您可以根据标签(0 或 1)清楚地看到什么是相关的,什么是不相关的。

构建跳格模型架构

我们现在在tensorflow的基础上利用keras来为跳格模型构建我们的深度学习架构。为此,我们的输入将是我们的目标单词和上下文或随机单词对。每一个都被传递给它自己的嵌入层(用随机权重初始化)。一旦我们获得了目标和上下文单词的单词嵌入,我们就把它传递给一个合并层,在那里我们计算这两个向量的点积。然后,我们将这个点积值传递给密集的 sigmoid 层,该层根据这对单词是上下文相关的还是只是随机单词来预测 1 或 0(Y’)。我们将其与实际的相关性标签( Y )进行匹配,通过利用mean_squared_error损失来计算损失,并在该过程中利用每个时期执行反向传播来更新嵌入层。下面的代码向我们展示了我们的模型架构。

Skip-gram model summary and architecture

理解上面的深度学习模型非常简单。不过,为了便于理解,我会尽量用简单的词语来概括这个模型的核心概念。对于每个训练示例,我们有一对输入单词,由具有唯一数字标识符的一个输入目标单词 和具有唯一数字标识符的一个上下文单词 组成。如果是 一个正例 这个词有上下文意义,是 一个上下文词 和我们的 标注 Y=1 ,否则如果是 一个负例 ,这个词没有上下文意义,只是 一个随机词 和我们的 标注 Y=0 我们将把它们中的每一个传递给它们自己的 嵌入层 ,大小为**(vocab_size x embed_size)**,这将为这两个单词**(1 x embed_size for each word)**中的每一个给我们 密集单词嵌入 。接下来我们使用一个 合并层 来计算这两个嵌入的 点积 并得到点积值。这然后被发送到 密集 s 形层 ,其输出 1 或 0。我们将其与实际标签 Y (1 或 0)进行比较,计算损失,反向传播误差以调整权重(在嵌入层中),并对多个时期的所有 【目标,上下文】 对重复该过程。下图试图解释同样的情况。

Visual depiction of the Skip-gram deep learning model

现在让我们开始用跳步图训练我们的模型。

训练模型

在我们的完整语料库上运行该模型需要相当多的时间,但比 CBOW 模型少。因此,我只运行了 5 个时期。您可以利用下面的代码,并在必要时增加更多的历元。

Epoch: 1 Loss: 4529.63803683
Epoch: 2 Loss: 3750.71884749
Epoch: 3 Loss: 3752.47489296
Epoch: 4 Loss: 3793.9177565
Epoch: 5 Loss: 3716.07605051

一旦这个模型被训练,相似的单词应该基于嵌入层具有相似的权重,并且我们可以测试出相同的权重。

获取单词嵌入

为了获得整个词汇表的单词嵌入,我们可以利用下面的代码从嵌入层中提取出相同的内容。请注意,我们只对目标单词嵌入层感兴趣,因此我们将从我们的**word_model**嵌入层中提取嵌入。我们不在位置 0 进行嵌入,因为词汇表中没有一个单词的数字标识符为 0,我们忽略它。

Word Embeddings for our vocabulary based on the Skip-gram model

因此,您可以清楚地看到,每个单词都有一个大小为**(1x100)**的密集嵌入,如前面的输出所示,类似于我们从 CBOW 模型中获得的结果。现在让我们对这些密集的嵌入向量应用欧几里德距离度量来为我们的词汇表中的每个单词生成成对的距离度量。然后,我们可以基于最短(欧几里德)距离找出每个感兴趣单词的 n 个最近邻,类似于我们在 CBOW 模型的嵌入中所做的。

(**12424, 12424)****{'egypt': ['pharaoh', 'mighty', 'houses', 'kept', 'possess'],
 'famine': ['rivers', 'foot', 'pestilence', 'wash', 'sabbaths'],
 'god': ['evil', 'iniquity', 'none', 'mighty', 'mercy'],
 'gospel': ['grace', 'shame', 'believed', 'verily', 'everlasting'],
 'jesus': ['christ', 'faith', 'disciples', 'dead', 'say'],
 'john': ['ghost', 'knew', 'peter', 'alone', 'master'],
 'moses': ['commanded', 'offerings', 'kept', 'presence', 'lamb'],
 'noah': ['flood', 'shem', 'peleg', 'abram', 'chose']}**

从结果中可以清楚地看到,对于每个感兴趣的单词,许多相似的单词是有意义的,并且我们已经获得了比 CBOW 模型更好的结果。让我们现在使用 t-SNE 来可视化这些单词嵌入,T11 代表t-分布式随机邻居嵌入 一种流行的降维技术来在较低维(例如 2-D)中可视化高维空间。

Visualizing skip-gram word2vec word embeddings using t-SNE

我用红色标记了一些圆圈,这些圆圈似乎显示了在向量空间中位置相近的上下文相似的不同单词。如果你发现任何其他有趣的模式,随时让我知道!

基于 Gensim 的鲁棒 Word2Vec 模型

虽然我们的实现足够好,但它们还没有优化到能在大型语料库上很好地工作。由雷迪姆·řehůřek 创建的[**gensim**](https://radimrehurek.com/gensim/)框架由 Word2Vec 模型的健壮、高效和可伸缩的实现组成。我们将在圣经语料库中利用同样的方法。在我们的工作流程中,我们将标记化我们的规范化语料库,然后关注 Word2Vec 模型中的以下四个参数来构建它。

  • **size** : 一词嵌入维度
  • **window** : 上下文窗口大小
  • **min_count** : 最小字数
  • **sample** : 常用词的下采样设置

在建立我们的模型之后,我们将使用我们感兴趣的单词来查看每个单词的顶部相似单词。

这里的相似词肯定与我们感兴趣的词更相关,这是预料之中的,因为我们对这个模型进行了更多次迭代,这一定产生了更好和更多的上下文嵌入。你注意到什么有趣的联想了吗?

Noah’s sons come up as the most contextually similar entities from our model!

在使用 t-SNE 将它们的维度减少到 2-D 空间之后,让我们也使用它们的嵌入向量来可视化感兴趣的单词和它们的相似单词。

Visualizing our word2vec word embeddings using t-SNE

我画的红圈指出了我发现的一些有趣的联想。根据我之前的描述,我们可以清楚地看到 诺亚 和他的儿子们根据我们模型中的单词 embeddings 彼此非常接近!

将 Word2Vec 特性应用于机器学习任务

如果你还记得阅读过上一篇文章 第三部分:文本数据的传统方法 你可能已经看到过我使用特性来完成一些实际的机器学习任务,比如聚类。让我们利用我们的其他顶级语料库,并尝试实现同样的目标。首先,我们将在语料库上构建一个简单的 Word2Vec 模型,并可视化嵌入。

Visualizing word2vec word embeddings on our toy corpus

请记住,我们的语料库非常小,因此要获得有意义的单词嵌入,并让模型获得更多的上下文和语义,更多的数据是有帮助的。那么在这个场景中嵌入的单词是什么呢?它通常是每个单词的密集向量,如以下单词 sky 的示例所示。

w2v_model.wv['sky']**Output
------**array([ 0.04576328,  0.02328374, -0.04483001,  0.0086611 ,  0.05173225, 0.00953358, -0.04087641, -0.00427487, -0.0456274 ,  0.02155695], dtype=float32)

现在,假设我们想从我们的玩具语料库中聚集八个文档,我们需要从每个文档中出现的每个单词中获得文档级嵌入。一种策略是平均文档中每个单词的单词嵌入量。这是一个非常有用的策略,你可以用它来解决你自己的问题。现在让我们将它应用到我们的语料库中,以获得每个文档的特征。

Document level embeddings

现在我们有了每个文档的特征,让我们使用 相似性传播 算法对这些文档进行聚类,这是一种基于数据点之间的*“消息传递”*概念的聚类算法,并且不需要将聚类的数量作为显式输入,而这是基于分区的聚类算法经常需要的。

Clusters assigned based on our document features from word2vec

我们可以看到,我们的算法已经根据 Word2Vec 特性将每个文档聚类到正确的组中。相当整洁!我们还可以通过使用 主成分分析(PCA) 来将特征维度降低到二维,然后将其可视化(通过对每个聚类进行颜色编码),来可视化每个文档在每个聚类中的位置。

Visualizing our document clusters

每一个簇中的文档看起来都是有序的,因为每个簇中的文档彼此靠近,而与其他簇相距较远。

手套模型

GloVe 模型代表全局向量,这是一种无监督的学习模型,可用于获得类似于 Word2Vec 的密集单词向量。然而,该技术是不同的,并且在聚集的全局单词-单词共现矩阵上执行训练,给我们一个具有有意义的子结构的向量空间。这种方法是由 Pennington 等人在斯坦福发明的,我推荐你阅读关于 GloVe 的原始论文,*‘GloVe:Global Vectors for Word Representation’*Pennington 等人的文章,这是一篇很好的阅读材料,可以让你对这个模型的工作原理有一些了解。

我们不会在这里过多地讨论该模型的实现细节,但是如果你对实际代码感兴趣,你可以查看官方的 页面 。我们将保持事情简单,并试图理解手套模型背后的基本概念。我们已经讨论了基于计数的矩阵分解方法,如 LSA 和预测方法,如 Word2Vec。这篇论文声称,目前,两个家庭都有明显的缺陷。像 LSA 这样的方法有效地利用了统计信息,但它们在单词类比任务上表现相对较差,比如我们如何找出语义相似的单词。像 skip-gram 这样的方法可能在类比任务上做得更好,但是它们在全局水平上很少利用语料库的统计数据。

GloVe 模型的基本方法是首先创建一个由(单词,上下文)对组成的巨大的单词-上下文共现矩阵,使得该矩阵中的每个元素表示单词与上下文(可以是单词序列)一起出现的频率。想法是应用矩阵分解来近似这个矩阵,如下图所示。

Conceptual model for the GloVe model’s implementation

考虑到***【WC】矩阵、 词-特征(WF) 矩阵和 特征-上下文(FC) 矩阵,我们尝试对**WC = WF x FC**进行因式分解,这样我们的目标是从FC 中重构 WC 为此,我们通常用一些随机权重初始化*【WF】FC ,并尝试将它们相乘以获得【WC’**(WC 的近似值),并测量它与 WC 的接近程度。我们多次使用【SGD】来最小化误差。最后, 单词特征矩阵(WF) 给出了每个单词的单词嵌入,其中 F 可以预设为特定的维数。需要记住的非常重要的一点是,Word2Vec 和 GloVe 模型在工作方式上非常相似。它们都旨在建立一个向量空间,其中每个单词的位置都受其相邻单词基于上下文和语义的影响。Word2Vec 从单词共现对的局部单个示例开始,GloVe 从语料库中所有单词的全局聚合共现统计开始。

将手套特征应用于机器学习任务

让我们尝试利用基于手套的嵌入来完成我们的文档聚类任务。非常流行的[**spacy**](https://spacy.io)框架具有基于不同语言模型利用手套嵌入的能力。你也可以获得预先训练好的单词向量,并根据需要使用gensimspacy加载它们。我们将首先安装 spacy 并使用 en_vectors_web_lg 模型,该模型由在普通爬行上训练的 300 维单词向量组成。

*# Use the following command to install spaCy
> pip install -U spacyOR> conda install -c conda-forge spacy# Download the following language model and store it in disk
[https://github.com/explosion/spacy-models/releases/tag/en_vectors_web_lg-2.0.0](https://github.com/explosion/spacy-models/releases/tag/en_vectors_web_lg-2.0.0)# Link the same to spacy 
> python -m spacy link ./spacymodels/en_vectors_web_lg-2.0.0/en_vectors_web_lg en_vecsLinking successful
    ./spacymodels/en_vectors_web_lg-2.0.0/en_vectors_web_lg --> ./Anaconda3/lib/site-packages/spacy/data/en_vecsYou can now load the model via spacy.load('en_vecs')*

spacy中也有自动安装模型的方法,如果需要,你可以查看他们的模型&语言页面了解更多信息。我有一些同样的问题,所以我不得不手动加载它们。我们现在将使用spacy加载我们的语言模型。

***Total word vectors: 1070971***

这验证了一切都在正常工作。现在,让我们在玩具语料库中获取每个单词的手套嵌入。

GloVe embeddings for words in our toy corpus

我们现在可以使用 t-SNE 来可视化这些嵌入,类似于我们使用 Word2Vec 嵌入所做的。

Visualizing GloVe word embeddings on our toy corpus

spacy的美妙之处在于,它会自动为你提供每个文档中单词的平均嵌入量,而不必像我们在 Word2Vec 中那样实现一个功能。我们将利用同样的方法为我们的语料库获取文档特征,并使用 k-means 聚类来对我们的文档进行聚类。

Clusters assigned based on our document features from GloVe

我们看到一致的集群,类似于我们从 Word2Vec 模型中获得的集群,这很好!GloVe 模型声称在许多情况下比 Word2Vec 模型表现更好,如下图所示,该图来自 Pennington 等人的原始论文。

GloVe vs Word2Vec performance (Source: https://nlp.stanford.edu/pubs/glove.pdf by Pennington et al.)

上述实验是通过在相同的 6B 令牌语料库(Wikipedia 2014 + Gigaword 5)上训练 300 维向量来完成的,该语料库具有相同的 40 万单词词汇和大小为 10 的对称上下文窗口,以防有人对细节感兴趣。

快速文本模型

脸书在 2016 年首次推出了 FastText 模型,作为普通 Word2Vec 模型的扩展和据称的改进。基于 Mikolov 等人的题为 “用子词信息丰富词向量”的原始论文,这是深入理解该模型如何工作的一篇好文章。总的来说,FastText 是一个用于学习单词表示以及执行健壮、快速和准确的文本分类的框架。该框架由脸书在 GitHub 上开源,并声称有如下内容。

  • 最近最先进的英语单词矢量。
  • 在维基百科上训练的 157 种语言的单词向量和爬行。
  • 用于语言识别和各种监督任务的模型。

虽然我还没有从零开始实现这个模型,但根据这篇研究论文,以下是我对这个模型如何工作的了解。一般而言,像 Word2Vec 模型这样的预测模型通常将每个单词视为不同的实体(例如 ,其中 ),并为该单词生成密集嵌入。然而,这对于具有大量词汇和许多在不同语料库中不经常出现的罕见单词的语言来说是一个严重的限制。Word2Vec 模型通常忽略每个单词的形态结构,并将单词视为单个实体。FastText 模型将每个单词视为一包字符 n 元语法。这在文中也称为子字模型。

我们在单词的开头和结尾加上特殊的边界符号 <> 。这使我们能够将前缀和后缀与其他字符序列区分开来。我们还将单词 w 本身包含在其 n-grams 的集合中,以学习每个单词的表示(除了它的字符 n-grams)。以单词 其中n = 3*(tri-grams)为例,将由字符 n-grams: < wh、whe、her、ere、re > 和特殊序列 <其中> 表示整个单词。注意顺序,对应字 <她> 不同于三字组 来自字 其中 。*

在实践中,本文推荐在抽取所有 n 元文法时,对于n≥3n≤6。这是一种非常简单的方法,可以考虑不同组的 n 元语法,例如取所有的前缀和后缀。我们通常将一个单词的向量表示(嵌入)与每个 n 元语法相关联。因此,我们可以用一个单词的 n 元文法的向量表示的和或者这些 n 元文法的嵌入的平均值来表示这个单词。因此,由于这种基于单词的字符利用单个单词的 n 元语法的效果,稀有单词有更高的机会获得良好的表示,因为它们的基于字符的 n 元语法应该出现在语料库的其他单词中。

将快速文本特征应用于机器学习任务

gensim包有很好的包装器,提供用户界面来利用gensim.models.fasttext模块下可用的 FastText 模型。让我们在圣经语料库 上再次应用这一点,看看我们感兴趣的单词和它们最相似的单词。

你可以在我们的 Word2Vec 模型的结果中看到很多相似之处,每个感兴趣的单词都有相关的相似单词。你注意到什么有趣的联系和相似之处了吗?

Moses, his brother Aaron and the Tabernacle of Moses

***注意:*运行该模型在计算上是昂贵的,并且与 skip-gram 模型相比通常花费更多的时间,因为它为每个单词考虑 n-grams。如果使用 GPU 或良好的 CPU 进行训练,效果会更好。我在 AWS ***p2.x***实例上对此进行了训练,花费了我大约 10 分钟的时间,相比之下,在常规系统上花费了 2-3 个小时。

现在让我们使用 主成分分析(PCA) 将单词嵌入维数降低到 2-D,然后将其可视化。

Visualizing FastTest word embeddings on our Bible corpus

我们可以看到很多有趣的图案!诺亚,他的儿子和爷爷玛士撒拉关系亲密。我们也看到摩西埃及联系在一起,在那里它忍受了圣经中的瘟疫,包括饥荒瘟疫*。同样耶稣和他的一些门徒彼此关系密切。*

要访问任何单词嵌入,您可以用如下单词索引模型。

***ft_model.wv['jesus']**array([-0.23493268,  0.14237943,  0.35635167,  0.34680951,    
        0.09342121,..., -0.15021783, -0.08518736, -0.28278247,   
       -0.19060139], dtype=float32)*

有了这些嵌入,我们可以执行一些有趣的自然语言任务。其中之一是找出不同单词(实体)之间的相似性。

*print(ft_model.wv.similarity(w1='god', w2='satan'))
print(ft_model.wv.similarity(w1='god', w2='jesus'))**Output
------**
0.333260876685
0.698824900473*

我们可以看到 【上帝】【耶稣】 更紧密地联系在一起,而不是基于我们圣经语料库中的文本 【撒旦】 。挺贴切的!

考虑到单词嵌入的存在,我们甚至可以从一堆单词中找出奇怪的单词,如下所示。

*st1 = "god jesus satan john"
print('Odd one out for [',st1, ']:',  
      ft_model.wv.doesnt_match(st1.split()))st2 = "john peter james judas"
print('Odd one out for [',st2, ']:', 
      ft_model.wv.doesnt_match(st2.split()))**Output
------**
**Odd one out for [ god jesus satan john ]: satan
Odd one out for [ john peter james judas ]: judas***

有趣的和相关的结果,在这两种情况下,对于其他单词中的奇数实体!

结论

这些例子应该让你对利用深度学习语言模型从文本数据中提取特征以及解决单词语义、上下文和数据稀疏性等问题的更新和有效的策略有一个很好的想法。接下来将详细介绍利用深度学习模型对图像数据进行特征工程的策略。敬请期待!

要了解连续数值数据的特征工程策略,请查看本系列的第 1 部分

要了解离散分类数据的特征工程策略,请查看本系列的第 2 部分****

要了解针对非结构化文本数据的传统特征工程策略,请查看本系列的第 3 部分****

本文中使用的所有代码和数据集都可以从我的 GitHub 中访问

该代码也可作为 Jupyter 笔记本

除非明确引用,否则架构图是我的版权。你可以随意使用它们,但是如果你想在自己的作品中使用它们,请记得注明出处。

如果你对我的文章或数据科学有任何反馈、评论或有趣的见解要分享,请随时通过我的 LinkedIn 社交媒体频道联系我。

***** [## Dipanjan Sarkar -数据科学家-英特尔公司| LinkedIn

查看 Dipanjan Sarkar 在世界最大的职业社区 LinkedIn 上的个人资料。Dipanjan 有 5 份工作列在…

www.linkedin.com](https://www.linkedin.com/in/dipanzan/)*****

用简单的步骤理解张量流程序。

原文:https://towardsdatascience.com/understanding-fundamentals-of-tensorflow-program-and-why-it-is-necessary-94cf5b60e255?source=collection_archive---------4-----------------------

ensorFlow 是一个库,可以应用于所有的机器学习算法,尤其是用神经网络进行深度学习。机器学习就是那些被编写来处理大型数据集以从中发现模式并提取信息的程序。它实际上从数据中学习,以做出准确或接近准确的预测,并更好地自我修正。就像我们希望有人做的那样。图像识别及其增强甚至识别是 ML 的一些应用。

自从我在 TF 上写了第一个故事后,我很高兴看到了可喜的变化。这个故事着重于理解 TensorFlow 程序的一些基础知识。我建议在你的机器上试试这段代码,看看它是如何工作的。

为了能够在不同的问题集上运行相同的模型,我们需要占位符和提要词典。随着我们的张量流程序变得越来越复杂,我们的可视化也需要跟上。回归试图对因果关系进行建模。原因是发生的独立变量,结果取决于原因。线性回归是一种直线回归,它是在对 X 导致 y 的回归进行建模时产生的。原因也称为解释变量

财富假说增加了预期寿命。

对于方程 Y=A+BX。为了找到最佳拟合,ML 算法将为 A 和 b 提供初始值。它将运行回归并找出 A 和 b 的这些值的误差。然后将这些误差反馈到输入中以获得 A 和 b 的新值。线性回归包括找到最佳拟合线

通过最小化最小平方误差来找到最佳拟合线。最佳拟合线是从底部连接到图中数据点的线的长度的平方和最小的线。

占位符

TensorFlow 中的占位符类似于变量,您可以使用 tf.placeholder 来声明它。您不必提供初始值,您可以在运行时使用 Session.run 中的 feed_dict 参数来指定它,而在 tf。变量,可以在声明它时提供初始值。

使用占位符的示例程序

import tensorflow as tf#setup placeholder using tf.placeholder
x = tf.placeholder(tf.int32, shape=[3],name='x')
'''it is of type integer and it has shape 3 meaning it is a 1D vector with 3 elements in it
we name it x. just create another placeholder y with same dimension. we treat the 
placeholders like we treate constants. '''
y = tf.placeholder(tf.int32, shape=[3],name='y')sum_x = tf.reduce_sum(x,name="sum_x")
prod_y = tf.reduce_prod(y,name="prod_y")
'''we dont know what values x and y holds till we run the graph'''
final_div = tf.div(sum_x,prod_y, nwe give fetches and feed_dict pass into every session.run commandame="final_div")final_mean = tf.reduce_mean([sum_x, prod_y], name="final_mean")sess = tf.Session()print ("sum(x): ", sess.run(sum_x, feed_dict={x: [100,200,300]}))
print ("prod(y): ", sess.run(prod_y, feed_dict={y: [1,2,3]}))writer = tf.summary.FileWriter('./tensorflow_example',sess.graph)writer.close()
sess.close()

取送字典

我们将 fetches 和 feed_dict 传递给每个 session.run 命令。获取参数指示我们想要计算什么,而提要字典为该计算指定占位符值

import tensorflow as tfW = tf.constant([10,100], name='const_W')#these placeholders can hold tensors of any shape
#we will feed these placeholders later
x = tf.placeholder(tf.int32, name='x')
b = tf.placeholder(tf.int32,name='b')#tf.multiply is simple multiplication and not matrix
Wx = tf.multiply(W,x, name="Wx")
y = tf.add(Wx,b,name='y')with tf.Session() as sess:
 '''all the code which require a session is writer here
 here Wx is the fetches parameter. fetches refers to the node of the graph we want to compute
 feed_dict is used to pass the values for the placeholders
 '''
 print( "Intermediate result Wx: ", sess.run(Wx, feed_dict={x: [3,33]}))
 print( "Final results y: ",sess.run(y, feed_dict={x:[5,50],b:[7,9]}))writer = tf.summary.FileWriter('./fetchesAndFeed',sess.graph)
writer.close()

变量

变量是允许你改变存储在那里的值的结构。监督学习算法在到达最终结论之前执行多次迭代,使用变量来存储随着模型收敛而变化的值。我们的目标是最小化回归线和数据集中的点之间的误差。所以我们在每次迭代中调整回归线来获得新的值。为了得到方程 y=A+Bx 的最佳拟合线,我们不断调整 A 和 b 的值。

变量是可变的张量值,在多次调用 sesssion.run()时保持不变。我用与上面相同的演示代码来解释这一点。

import tensorflow as tfW = tf.Variable([2.5,4.0],tf.float32, name='var_W')
#here W is a Variable
x = tf.placeholder(tf.float32, name='x')
b = tf.Variable([5.0,10.0],tf.float32, name='var_b')
#b is also a variable with initial value 5 and 10
y = W * x + b#initialize all variables defined
init = tf.global_variables_initializer()
#global_variable_initializer() will declare all the variable we have initilized
# use with statement to instantiate and assign a session
with tf.Session() as sess:
 sess.run(init)
 #this computation is required to initialize the variable
 print("Final result: Wx + b = ", sess.run(y,feed_dict={x:[10,100]}))
# changing values 
number = tf.Variable(2)
multiplier = tf.Variable(1)init = tf.global_variables_initializer()
result = number.assign(tf.multiply(number,multiplier))with tf.Session() as sess:
 sess.run(init)for i in range(10):
  print("Result number * multiplier = ",sess.run(result))
  print("Increment multiplier, new value = ",sess.run(multiplier.assign_add(1)))

一个 TensorFlow 程序的多个图形

我们可以在 TensorFlow 程序中显式创建尽可能多的图形。任何 TensorFlow 程序都有一个默认的图形,其中包含了您已经实例化的所有占位符和变量。但是我们可以通过使用 tf.graph()显式地实例化一个图来对图进行逻辑分段。下面的节目可能会解答你的一些疑惑。

import tensorflow as tfg1 = tf.Graph()
'''set g1 as default to add tensors to this graph using default methord'''
with g1.as_default():
 with tf.Session() as sess:
  A = tf.constant([5,7],tf.int32, name='A')
  x = tf.placeholder(tf.int32, name='x')
  b = tf.constant([3,4],tf.int32, name='b')y = A * x + bprint( sess.run(y, feed_dict={x: [10,100]}))
  '''to ensure all the tensors and computations are within the graph g1, we use assert'''
  assert y.graph is g1g2 = tf.Graph()with g2.as_default():
 with tf.Session() as sess:
  A = tf.constant([5,7],tf.int32, name='A')
  x = tf.placeholder(tf.int32, name='x')
  y = tf.pow(A,x,name='y')
  print( sess.run(y, feed_dict={x: [3,5]}))
  assert y.graph is g2'''same way you can access defaut graph '''
default_graph = tf.get_default_graph()
with tf.Session() as sess:
 A = tf.constant([5,7],tf.int32, name='A')
 x = tf.placeholder(tf.int32, name='x')
 y = A + x
 print(sess.run(y, feed_dict={x: [3,5]}))assert y.graph is default_graph

命名范围

TensorBoard 可能是最有用的调试工具,但是随着你的图表尺寸爆炸,你需要一些方法来获得更大的图片中的细节。现在使用 TensorFlow 运行下面的程序,并在 TensorBoard 中查看它的图形

import tensorflow as tfA = tf.constant([4], tf.int32, name='A')
B = tf.constant([4], tf.int32, name='B')
C = tf.constant([4], tf.int32, name='C')x = tf.placeholder(tf.int32, name='x')# y = Ax^2 + Bx + C
Ax2_1 = tf.multiply(A, tf.pow(x,2), name="Ax2_1")
Bx = tf.multiply(A,x, name="Bx")
y1 = tf.add_n([Ax2_1, Bx, C], name='y1')# y = Ax^2 + Bx^2
Ax2_2 = tf.multiply(A, tf.pow(x,2),name='Ax2_2')
Bx2 = tf.multiply(B, tf.pow(x,2),name='Bx2')
y2 = tf.add_n([Ax2_2,Bx2],name='y2')y = y1 + y2with tf.Session() as sess:
 print(sess.run(y, feed_dict={x:[10]}))writer = tf.summary.FileWriter('./named_scope',sess.graph)
 writer.close()

这张图表看起来真的很复杂!

现在我们可以使用命名作用域在 tensorboard 中组织事物。使用定义名称范围

with tf.name_scope("name the scope"):

并在这个范围内编写代码。上述程序可以使用如下所示的命名空间进行安排

import tensorflow as tfA = tf.constant([4], tf.int32, name='A')
B = tf.constant([4], tf.int32, name='B')
C = tf.constant([4], tf.int32, name='C')x = tf.placeholder(tf.int32, name='x')# y = Ax^2 + Bx + C
with tf.name_scope("Equation1"):
 Ax2_1 = tf.multiply(A, tf.pow(x,2), name="Ax2_1")
 Bx = tf.multiply(A,x, name="Bx")
 y1 = tf.add_n([Ax2_1, Bx, C], name='y1')# y = Ax^2 + Bx^2
with tf.name_scope("Equation2"):
 Ax2_2 = tf.multiply(A, tf.pow(x,2),name='Ax2_2')
 Bx2 = tf.multiply(B, tf.pow(x,2),name='Bx2')
 y2 = tf.add_n([Ax2_2,Bx2],name='y2')with tf.name_scope("final_sum"):
 y = y1 + y2with tf.Session() as sess:
 print(sess.run(y, feed_dict={x:[10]}))writer = tf.summary.FileWriter('./named_scope',sess.graph)
 writer.close()

将在接下来的故事中继续介绍图像识别。请分享帮助别人找到。欢迎发表评论。

了解谷歌分析报告

原文:https://towardsdatascience.com/understanding-google-analytics-reports-585a570bbee2?source=collection_archive---------4-----------------------

到现在为止,你应该已经完成了所有的艰苦工作,从而得到谷歌分析报告。这包括:

来自博客 1

  1. 提出一个测量计划
  2. 准备您的网站

来自博客 2

  1. 将谷歌分析代码添加到您的网站页面
  2. 让人们访问你的网站

现在,让我们深入研究 Google Analytics 报告,了解它们对于我们的目标和衡量计划的意义。请记住,有很多报告对小企业没什么帮助;因此,我们将只讨论重要的问题,以帮助您处理您的测量计划。

谷歌分析报告是什么意思

当你进入谷歌分析页面时,你会看到:

  1. 你在哪个账户?如果您想更改帐户,请单击下拉箭头并选择您想查看的网站数据。
  2. 报告导航
  3. 网页上的一些快速数据
  4. 你的网站上的一些实时数据(在这种情况下,我目前在我的网站上,所以它把我算作一个当前的访问者。)

让我们谈一谈我们在 3 中看到的数据。谷歌把这些数字放在一起,以帮助我们快速了解你的网站在过去七天里的情况。

在这个例子中,我在社交媒体数据上使用了 Kickass。

  • 用户—显示过去 7 天有 9 个用户。即 9 个人访问了该网站。
  • Sessions —显示过去 7 天内有 9 个会话。“会话”是指某人访问网站的每一次独特的时间。如果这个数字是 10 或更多,这意味着同一个人(在过去 7 天访问的 9 个人之一)访问您的网站不止一次。
  • 跳出率——这个数字指的是点击离开你的页面的用户的百分比。(我们将在本博客后面对此进行更深入的探讨)
  • 会话持续时间——人们在你的网站上花了多少时间。

现在,让我们仔细看看与您的小型企业相关的每个导航选项。这个博客不会详细讨论每一个导航选项,因为很多都不相关。

观众

“观众报告”部分深入介绍了访问我们网站的人的详细情况。为了给你一些不同的数据,我用 SonjaDewing.com 作为例子。

这里最重要的细节是:

概述:和你在家里看到的信息一样。不同的是,这里的图表向您展示了新访客与回头客的对比。这意味着人们在已经访问过网站之后会再回来——可能是阅读博客,找到你的联系信息,等等。

跳出率:这里我们再次得到跳出率的信息。跳出率基本上是指当人们访问网站时,他们没有找到足够有趣的东西让他们留在那里。发生这种情况的原因有很多,包括:

  • 他们是偶然进入你的网站的吗?
  • 你网站的某个地方有没有没有意义的参考(例如,一个关于回收的博客有一个关于动物收容所的网站链接,所以访问者不会发现它有用。)
  • 你的网站加载时间太长了吗?
  • 你的网站在用户的浏览器上工作吗?
  • 你的网站上有什么可以留住访客的内容吗(比如博客、活动日程等等)。)

跳出率有多重要?这取决于你网站的目标。如果你网站的目标是让人们注册你的时事通讯,用户可能会继续注册你的时事通讯,然后马上关闭网站。所以跳出率并不重要——只要你注册了时事通讯。

跳出率的理想目标是在 20–40%之间,平均值是 41–55%。

如果你想固定你的跳出率,在那些你能控制的事情上努力,比如:

  • 装载速度。如果用户必须等待一个网站加载,他们很可能会关闭它,去别的地方。在这种情况下,请缩小图像尺寸以提高加载速度。{链接到以前的带有大小调整器的 wordpress 插件},
  • 浏览器可以正确加载你的网站。用户来自各种浏览器,如 Chrome、Firefox 和 Internet Explorer。你有没有检查过你的网站在所有这些浏览器中看起来都是正确的?
  • 创造能让用户更长久停留的内容。这些内容可以是从博客到图片库的任何内容。

**技术/浏览器:**有趣的是,你可以向下滚动,点击“浏览器”,就可以快速看到人们浏览你的网站时使用的浏览器类型。当我们谈到跳出率时,这一点很重要。

如果 95%的用户都在使用 Chrome,一定要从 Chrome 上测试你的网站,以确保它看起来和工作正常。

地理/位置:受众也很重要。如果你关注的是你所在地区的受众,而人们从很远的地方来到你的网站,你可能想要创建更多关于你所在地区的内容,无论是博客还是你的联系页面上的更多信息。

如果你想更详细地了解这些信息,你可以点击地图上的蓝色区域,深入到各个州,等等。

如果你还没有使你的网站移动友好,这个信息是很重要的。如果你有很多人通过手机访问你的网站,你应该确保它适合移动环境。

用户流量 : 如果你想让用户去某个页面,非常重要。例如,这里我们看到有 4 个人直接进入了主页,只有 1 个人进入了“关于”页面。1 个人直接去了一篇关于马蹄湖的博文。

如果我想让人们停留在某个页面上,我会在我的主页上做些改变。即。放一个大链接到我的博客或其他页面信息。

获得物ˌ获得

人们是如何找到你的网站的?

概述:概述将展示人们如何找到你的网站。

有机发现意味着他们通过链接到你的网站的另一个网站、广告或在谷歌等浏览器上的搜索找到了你的网站。

直接搜索意味着他们知道你的网址并输入到他们的网址中。

这对你意味着什么?有有机的流量是很好的,特别是如果流量来自搜索——这意味着他们通过你的搜索引擎优化(SEO)找到你的信息。

Source/Medium :转到 Source/Medium 会告诉你那些有机搜索来自哪里。

其余的呢?事实上,对于小型企业的测量计划,您需要了解的并不多。

根据报告和你的计划改进你的网站

具体来说一下你的测量计划。

我在博客 1 中使用的例子

  1. 剧情小鸭。这家公司致力于帮助美国的作家更有创造力。

他们的网站业务目标是:

  • 通过在网站上分享有用的信息来提高品牌知名度,在年底前增加网站的流量。
  • 你可以看到有流量(最近 7 天 9)但跳出率很高。在这种情况下,这很可能是因为在这些博客中使用该网站作为例子。你不是网站的目标市场,所以你很快离开。
  • 我会做什么来修复高跳出率:1。开始为目标市场添加更多有帮助的博客。2.开始在社交媒体上分享这些博客来吸引访问者。3.探究跳出率高的任何其他原因(如上文跳出率中所述)。
  • 每次我对网站、博客等做出改变。我会回到这里,看看我的访问者数量是否上升,跳出率是否下降,并检查行为,看看观众/用户流是否去了我想要的地方。每次都做些小改动,看看你的数字是如何随着更新而变化的。
  • 到月底,通过 50 个新的电子邮件/时事通讯注册来提高品牌知名度。

这个数字你不需要从谷歌分析中得到,你可以从注册人数中看到。但是如果你没有从你的网站上直接获得任何注册,你会从你的时事通讯注册中知道,你会想要让你的注册页面容易被找到。

  1. 在社交媒体上表现出色。这家公司专注于向阿尔伯克基的小企业教授社交媒体。他们的网站业务目标:
  • 通过销售更多 9 月份下一场活动的门票来增加收入。
  • 收入数字将来自门票销售,但如果你得到了很多跳出率,这意味着没有人会花时间阅读你的活动。在这种情况下,我会围绕活动写一些博客(活动空间、活动主持人、从上次活动中吸取的教训、活动所在的城市等)。)这种方式增加了搜索引擎优化,让人们在网站上停留的时间更长一些。

创建自定义仪表板

如果你进入谷歌分析,只需要某些信息,创建一个仪表板会很有帮助。

谷歌已经有了一个入门仪表板,它非常有助于将所有东西放在一起。

  1. 点击定制
  2. 点击仪表板
  3. 点击创建

从上图可以看出,Google 给了你一个选项,让你从一个空白的仪表板开始,或者从一个初学者仪表板开始。Starter Dashboard 实际上非常有用。

  1. 点击启动仪表板
  2. 为您的新仪表板键入一个名称(我使用了快速查看)
  3. 点击创建仪表板

现在,您已经将数据分组到一个非常有用的页面上。要更改任何数据,请选择小部件上方的编辑按钮(小部件是页面上每个图形数据的引用)。要删除任何小部件,您可以选择每个图形右上角的关闭按钮。

在本例中,我将向下滚动并删除目标和收入的小部件,因为这些信息并不重要。

如果您想要添加新的小部件,请在页面的左上角选择+添加小部件。这将给出一个对话框,您可以在其中选择任何可用的小部件。然而,我不打算添加任何东西,因为这已经给了我需要一目了然的信息。

另外,那些我想添加的东西,比如有机/直接搜索,我不能添加到仪表板上。所以,我必须点击这些信息才能看到数据。

曾经有一种方法可以找到一份报告,并将其添加到您的仪表板上,但由于谷歌分析正在经历一些变化,目前还不可用。

这就是谷歌分析。当你了解这些报告时,事情就变得很简单了。留意那些数据,记得记录你做了什么。祝您的测量计划好运!

如果你喜欢这篇文章,请分享和推荐它,这样其他人就可以找到它!

在你走之前…

如果你喜欢这篇文章,你将会喜欢上《阿姆迪周刊》。这是我们免费的每周文摘。今天就订阅!

了解梯度增压机

原文:https://towardsdatascience.com/understanding-gradient-boosting-machines-9be756fe76ab?source=collection_archive---------1-----------------------

<​a href​=”https://www.freepik.com/free-vector/binary-code-netwrok-technology-concept-background_2395548.htm"​>Designed by Starline<​/a>

动机:

虽然 Kaggle 竞赛中大多数获胜的模型都是一些高级机器学习算法的组合,但通常是这种组合一部分的一个特定模型是梯度推进机器。举个例子,在这篇文章中,Allstate Claims Severity Kaggle 竞赛的获胜者 Alexey Noskov 将他在竞赛中的成功归功于 GBM 算法的另一个变种 XGBOOST。然而,尽管它大受欢迎,许多专业人士仍然使用这种算法作为一个黑箱。因此,本文的目的是为这种强大的机器学习技术奠定一个直观的框架。

什么是梯度推进?

先从了解 Boosting 开始吧!强化是一种将弱学习者转化为强学习者的方法。在 boosting 中,每个新树都适合原始数据集的修改版本。梯度推进算法(gbm)可以通过首先介绍 AdaBoost 算法来最容易地解释。AdaBoost 算法首先训练一个决策树,在该决策树中,每个观察值被赋予相同的权重。在评估第一棵树后,我们增加那些难以分类的观察值的权重,降低那些易于分类的观察值的权重。因此,第二棵树在这个加权数据上生长。这里,我们的想法是改进第一棵树的预测。因此,我们的新模型是树 1 +树 2 。然后,我们根据这个新的 2-树集成模型计算分类误差,并生长第三棵树来预测修正的残差。我们重复这个过程指定的迭代次数。后续的树帮助我们对之前的树没有很好分类的观察结果进行分类。因此,最终集合模型的预测是由先前树模型做出的预测的加权和。

梯度增强以渐进、累加和顺序的方式训练许多模型。AdaBoost 和梯度提升算法之间的主要区别在于这两种算法如何识别弱学习器(例如决策树)的缺点。虽然 AdaBoost 模型通过使用高权重数据点来识别缺点,但梯度增强通过使用损失函数中的梯度来执行相同的操作( y=ax+b+e,e 需要特别提及,因为它是误差项)。损失函数是一种衡量指标,它表明模型系数对基础数据的拟合程度。对损失函数的逻辑理解将取决于我们试图优化的内容。例如,如果我们试图通过使用回归来预测销售价格,那么损失函数将基于真实和预测的房价之间的误差。类似地,如果我们的目标是对信用违约进行分类,那么损失函数将是对我们的预测模型在对不良贷款进行分类方面有多好的一种衡量。使用梯度推进的最大动机之一是它允许优化用户指定的成本函数,而不是通常提供较少控制并且本质上不符合真实世界应用的损失函数。

在 R 中训练一个 GBM 模型

为了在 R 中训练一个 gbm 模型,首先必须安装并调用 gbm 库。gbm 函数要求您指定某些参数。您将从指定公式开始。这将包括你的反应和预测变量。接下来,您将指定响应变量的分布。如果没有指定,那么 gbm 将尝试猜测。一些常用的分布包括-“伯努利”(0–1 结果的逻辑回归)、“高斯”(平方误差)、“TD ist”(t 分布损失)和“泊松”(计数结果)。最后,我们将指定数据n.trees 参数(毕竟 gbm 是树的集合!)默认情况下,gbm 模型将假设 100 棵树,这可以很好地估计我们的 gbm 的性能。

在 Kaggle 的 Titanic 数据集上训练一个 gbm 模型:我使用了来自 Kaggle 的著名 Titanic 数据集来说明我们如何实现一个 gbm 模型。我首先使用 read.csv() 函数将 Titanic 数据加载到我的 R 控制台中。然后,使用 createDataPartition()函数将原始数据集划分为单独的训练集和测试集。这种必要的划分在后期阶段非常有用,可以评估模型在单独的维持数据集(测试数据)上的性能,并计算 AUC 值。以下屏幕显示 R 代码。

注意:考虑到原始数据集的规模较小,我将 750 个观察值分配给训练,将 141 个观察值分配给测试保持。此外,通过定义一个种子值,我确保了每次都生成相同的随机数集。这样做将消除建模结果的不确定性,并帮助人们准确评估模型的性能。

下一步是使用我们的训练保持来训练 gbm 模型。虽然所有其他参数都与上一节中讨论的完全相同,但是还指定了另外两个参数- 交互。深度收缩。交互深度指定每棵树的最大深度(即训练模型时允许的变量交互的最高级别)。收缩率被认为是学习率。它用于减少或缩小每个附加的适合的基础学习者(树)的影响。它减少了增量步骤的大小,从而降低了每次连续迭代的重要性。

注意:即使我们最初用 1000 棵树训练我们的模型,我们也可以基于“开箱”或“交叉验证”技术来修剪树的数量,以避免过度拟合。我们将在后面看到如何将它合并到我们的 gbm 模型中(参见“调优 gbm 模型和提前停止”一节)

了解 GBM 模型输出

当您打印 gbm 模型时,它会提醒您在执行过程中使用了多少树或迭代。使用其内部计算,如变量重要性,它还会指出是否有任何预测变量在模型中没有影响。

gbm 建模的一个重要特征是可变重要性。将汇总函数应用于 gbm 输出会生成一个变量重要性表和一个模型图。下表根据各个变量的相对影响对其进行了排名,相对影响是一种衡量标准,表明每个变量在模型训练中的相对重要性。在泰坦尼克号模型中,我们可以看到船舱和性别是迄今为止我们 gbm 模型中最重要的变量。

调整 gbm 模型并提前停止

超参数调整对于 gbm 建模尤其重要,因为它们容易过度拟合。为 gbm 和随机森林等算法调整迭代次数的特殊过程称为“提前停止”。早期停止通过在单独的测试数据集上监控模型的性能来执行模型优化,并且一旦测试数据的性能停止提高超过一定的迭代次数,就停止训练过程。

它通过尝试自动选择拐点来避免过度拟合,在该拐点处,测试数据集的性能开始下降,而随着模型开始过度拟合,训练数据集的性能继续提高。在 gbm 的背景下,早期停止可以基于袋外样本集(“OOB”)或交叉验证(“cv”)。如上所述,停止训练模型的理想时间是在验证误差由于过度拟合而开始增加之前,验证误差已经减少并开始稳定。

虽然其他提升算法(如*“xgboost”)允许用户指定一系列指标(如错误和日志损失),但“gbm”算法专门使用指标“错误”来评估和测量模型性能。为了在“gbm”中实现提前停止,在训练我们的模型时,我们首先必须指定一个名为“c . v folds”*的附加参数。其次,gbm 包附带了一个名为 gbm.perf() 的默认函数来确定最佳迭代次数。参数“方法”允许用户指定用于决定最佳树数的技术(“OOB”或“cv”)。

以下控制台屏幕显示按照“OOB”和“cv”方法的最佳树数。

此外,我们还将看到两个曲线图,表明基于各自使用的技术的最佳树木数量。左边的图表显示了测试(绿线)和训练数据集(黑线)的错误。蓝色虚线表示最佳迭代次数。人们还可以清楚地观察到,超过某个点(对于“cv”方法为 169 次迭代),测试数据上的误差似乎由于过度拟合而增加。因此,我们的模型将在给定的最佳迭代次数上停止训练过程。

使用 gbm 的预测

最后, predict.gbm() 函数允许从数据中生成预测。gbm 预测的一个重要特性是用户必须指定树的数量。由于预测函数中的“n . trees”没有默认值,建模者必须指定一个。由于我们已经通过执行提前停止计算出了最佳的树数量,我们将使用最佳值来指定“ n.trees ”参数。我使用了基于交叉验证技术的最佳解决方案,因为在大型数据集上,交叉验证通常优于 OOB 方法。用户可以在预测函数中指定的另一个参数是类型,它控制函数生成的输出类型。换句话说,类型指的是 gbm 进行预测的尺度。

总结和评估结果:

最后,任何建模工作最重要的部分是评估预测和衡量模型的性能。我首先创建了一个混淆矩阵。混淆矩阵是一个非常有用的工具,它将模型的实际值与预测值进行比较。它被称为混淆矩阵,因为它揭示了你的模型在两个类之间有多混乱。混淆矩阵的列是真实类别,而矩阵的行是预测类别。在你制作混淆矩阵之前,你需要在一个给定的阈值上“切割”你的预测概率,以将概率转化为类别预测。使用 ifelse() 函数可以很容易地做到这一点。在我们的例子中,概率大于 0.7 的病例被标记为 1,即可能存活,概率较小的病例被标记为 0。记得调用“*插入符号”*库来运行混淆矩阵。

运行最后一行将产生我们的混淆矩阵。

看到我们模型的准确性,我和你一样高兴!深入到混淆矩阵,我们观察到我们的模型完美地预测了 141 个观察值中的 118 个,给了我们 83.69%的准确率。我们的模型有 23 个错误。这 23 个病例被分为假阴性和假阳性,分别为 9 和 14。

ROC 和 AUC:基于真阳性和假阳性,我绘制了 ROC 曲线并计算了我们的 AUC 值。

根据定义,ROC 曲线越靠近网格的左上角越好。左上角对应的是真阳性率 1,假阳性率 0。这进一步意味着好的分类器在曲线下有更大的面积。显然,我们的模型的 AUC 为 0.8389。

最后备注:

我希望这篇文章能帮助你对梯度推进算法的工作原理有一个基本的了解。欢迎在 LinkedIn 上加我,我期待听到你的评论和反馈。此外,如果您有兴趣阅读更多关于这种强大的机器学习技术的信息,我将强烈推荐以下资源。

  1. 机器学习的梯度推进算法简介
  2. 一位 Kaggle 大师解释梯度推进
  3. 梯度提升的自定义损失函数
  4. 用 R 中基于树的模型进行机器学习

另外,我很高兴地分享我最近提交给泰坦尼克号卡格尔比赛的分数在前 20%。我最好的预测模型(准确率为 80%)是广义线性模型、梯度推进机器和随机森林算法的集合。我已经上传了我的代码到 GitHub,可以在:【https://lnkd.in/dfavxqh 访问

了解 GRU 网络

原文:https://towardsdatascience.com/understanding-gru-networks-2ef37df6c9be?source=collection_archive---------0-----------------------

https://pixabay.com

在本文中,我将尝试对一种真正令人着迷的神经网络类型给出一个相当简单易懂的解释。由 Cho 等人在 2014 年提出的 GRU(门控递归单元)旨在解决标准递归神经网络中的消失梯度问题。GRU 也可以被认为是 LSTM 的变体,因为两者设计相似,在某些情况下,产生同样优秀的结果。如果你不熟悉递归神经网络,我推荐阅读我的简介。为了更好地了解 LSTM,许多人推荐克里斯托弗·奥拉的文章。我还想补充一下这篇论文,它清楚地区分了 GRU 和 LSTM。

GRUs 是如何工作的?

如上所述,GRUs 是标准递归神经网络的改进版本。但是是什么让它们如此特别和有效呢?

为了解决标准 RNN 的消失梯度问题,GRU 使用所谓的更新门和复位门。基本上,这是决定什么信息应该被传递到输出的两个向量。它们的特别之处在于,它们可以被训练来保留很久以前的信息,而不会随着时间的推移而消失,也不会删除与预测无关的信息。

为了解释这一过程背后的数学原理,我们将考察以下递归神经网络中的一个单元:

Recurrent neural network with Gated Recurrent Unit

以下是那首单曲《GRU》的更详细版本:

Gated Recurrent Unit

首先,让我们介绍一下符号:

如果你不熟悉以上术语,我推荐你看这些关于“sigmoid”和“tanh”功能和“hada mard product”操作的教程。

#1.更新门

我们从使用以下公式计算时间步长 t 的更新门 z_t 开始:

x_t 插入网元时,乘以自身重量 W(z) 。对于 h_(t-1) 来说也是如此,它保存先前 t-1 单元的信息,并乘以其自身的权重 *U(z)。*将两个结果相加,并应用 sigmoid 激活函数将结果压缩在 0 和 1 之间。按照上面的模式,我们有:

**更新门帮助模型确定有多少过去的信息(来自以前的时间步骤)需要传递给未来。**这非常强大,因为模型可以决定复制过去的所有信息,并消除消失梯度问题的风险。稍后我们将看到更新门的用法。现在记住 z_t 的公式。

#2.复位门

本质上,这个门是用来从模型中决定有多少过去的信息要忘记。为了计算它,我们使用:

该公式与更新门的公式相同。区别在于重量和门的用途,稍后会看到。下图显示了重置门的位置:

像以前一样,我们插入 h_(t-1) —蓝线x_t —紫线,将它们与相应的权重相乘,将结果求和并应用 sigmoid 函数。

#3.当前存储内容

让我们看看这些门究竟会如何影响最终输出。首先,我们从复位门的使用开始。我们引入了一种新的存储内容,它将使用复位门来存储过去的相关信息。其计算方法如下:

  1. 将输入 x_t 乘以权重 W 并将 h_(t-1) 乘以权重 U.
  2. 计算复位门 r_t 和 *Uh_(t-1)之间的 Hadamard(逐元素)乘积。*这将决定从先前的时间步骤中删除什么。假设我们有一个情感分析问题,要从一个人写的评论中判断他对一本书的看法。正文以“这是一本奇幻的书,它阐释了……”开始,几段后以“我不太喜欢这本书,因为我认为它捕捉了太多的细节”结束。要确定这本书的总体满意度,我们只需要最后一部分的评论。在这种情况下,随着神经网络接近文本的结尾,它将学习将 r_t 向量赋值为接近 0,洗去过去,只关注最后的句子。
  3. 总结第一步和第二步的结果。
  4. 应用非线性激活功能 tanh

你可以清楚地看到这里的步骤:

我们对 h_(t-1) —蓝线r_t —橙线进行逐元素乘法,然后将结果—粉线与输入 x_t —紫线相加。最后用 tanh 产生h’_ t—亮绿线

#4.当前时间步的最终记忆

作为最后一步,网络需要计算 h_t —保存当前单元信息的向量,并将其传递给网络。为此,需要更新门。它决定了从当前内存内容中收集什么— h'_t ,从前面的步骤中收集什么— h_(t-1) 。这是按如下方式完成的:

  1. 对更新门 z_th_(t-1)应用逐元素乘法。
  2. (1-z_t)h'_t. 应用逐元素乘法
  3. 将步骤 1 和步骤 2 的结果相加。

让我们举一个关于书评的例子。这一次,最相关的信息被定位在正文的开头。该模型可以学习将向量 z_t 设置为接近 1,并保留大部分先前信息。由于 z_t 在这个时间步将接近于 1, 1-z_t 将接近于 0,这将忽略当前内容的大部分(在这种情况下是解释书籍情节的评论的最后部分),这与我们的预测无关。

下面是一个强调上述等式的例子:

接下来,您可以看到如何使用 z_t —绿线来计算 1-z_t ,它与h’_ t—亮绿线一起产生结果暗红线z_t 也与 h_(t-1) —蓝线一起用于逐元素乘法。最后, h_t —蓝线是对应于亮红线和暗红线的输出相加的结果。

现在,您可以看到 gru 如何使用它们的更新和重置门来存储和过滤信息。这消除了消失梯度问题,因为模型不是每次都洗去新的输入,而是保留相关信息,并将其传递给网络的下一个时间步骤。如果仔细训练,他们甚至可以在复杂的情况下表现得非常好。

我希望这篇文章能让你更好地理解这个被称为 GRU 的最先进的深度学习模型。

更多 AI 内容,关注我 LinkedIn 。

感谢您的阅读。如果你喜欢这篇文章,给它一些掌声👏。希望你有一个伟大的一天!

理解机器学习中的高维空间

原文:https://towardsdatascience.com/understanding-high-dimensional-spaces-in-machine-learning-4c5c38930b6a?source=collection_archive---------6-----------------------

机器学习的一个标志是处理来自各个领域的大量数据。不管这些数据是作为图像、视频、文本、语音还是纯数字来处理,它几乎总是存在于某个高维空间中。在本文中,我将展示数据是如何在更高维度中表示的,以及我们如何在它们之间进行插值。由于几乎不可能将这些抽象的空间形象化,我也将提供一些有用的类比来思考。

作为图像的空间坐标

我们可以给我们三维空间中的每一个点一个 (x,y,z) 坐标。由于这些点被表示为三个实数,我们说它属于集合ℝ。这些坐标通常没有什么意义,但是它们包含了有用的距离和大小的概念。

上面重要的事情是,当我们有三个实数值时,我们可以在我们的三维空间中表示它。现在让我们考虑一个图像。一幅图像就是一大堆像素,每个像素代表一个范围内的亮度。为了简单起见,让我们只考虑灰度图像,其中每个像素的亮度介于 0 和 1 之间。

低分辨率图像可能是 32 x 32 像素的缩略图。即使它在视觉上表现为一个正方形,你也可以想象把它拉伸成一条 1024 = 32 × 32 像素的线。**那么这有什么意义呢?**这个形象生活在什么空间?嗯,我们现在有 1024 个实数,所以它一定存在于 1024 维空间ℝ ⁰ ⁴.中

思考高维空间

在某种程度上,我们已经有了一种可视化 1024 维空间的方法:32 乘 32 的灰度图像!这可能看起来有点绕圈,但它在某些情况下是有效的。当我们在这个高维空间中移动时,图像中的像素强度会发生变化。但是这些变化中的大部分看起来不会有任何意义,而且大部分看起来都是无意义的。

作为人类,我们知道如何在图像之间进行解释和插值。如果我们想把一张图片从看起来像猫变成一只狗,我们知道如何将两张图片可视化并分离出关键的区别。如果我们在大脑中绘制所有图片的空间,猫和狗的图片会非常接近。我们已经学习了图像之间的联系,以及如何将相似的图像放在一起,不相似的图像放在远处。但是在高维空间里,每一个图像都混杂在一起,被嘈杂的、无意义的废话包围着。

像素空间和潜在空间

到目前为止,我们一直在讨论的高维表示通常被称为环境空间(在图像的情况下称为像素空间)。这就是我们在高维欧几里得空间中把长串数字看作向量的方式。

关于简单图像,最著名的例子是手写数字。这些是 28 乘 28 的灰度图像,每张图像都属于ℝ⁷⁸⁴.如果我们想从一个图像“移动”到另一个图像,那么我们需要理解每个数字的语义。

Interpolating between digits in pixel space.

像素空间内插

假设我们有两个坐标 p 和*q。*我们可以在像素空间中对它们进行插值,只需逐步将每个坐标从第一个坐标变为第二个坐标。比如我们想分两步从坐标(1,2)变到(5,12),那么我们可以考虑级数(1,2) → (3,7) → (5,12)。在每一步中,我们只需添加坐标之间的一半差异。

这种算法适用于任意数量的坐标,因此也适用于我们的手写数字图像。在上图中,我们以一个“5”开始,以一个“9”结束上面的进程显示了它们之间的四个步骤的插值。

潜在空间和插值

虽然我们可以通过图像的像素来表示图像,但是我们也可以通过图像的语义表示来对图像进行分类。我们知道 5 和 9 是什么样子,所以我们可以想象把所有相似的数字组合在一起。这个空间可能完全不同,可能只需要几个维度。这是许多降维方法的基础。

很多机器学习模型的目的就是学习这个潜在空间。在以后的文章中,我将讨论这些模型的架构如何隐含地决定潜在空间的维度。

一旦我们学习了潜在空间表示,我们就可以在潜在空间中进行插值,并在图像之间获得更平滑的过渡。考虑之前的两个相同的图像。下图显示了潜在空间的插值。

Interpolating between the same two digits in latent space.

结论

在许多方面,机器学习都是关于解释高维空间的。理解这些空间是如何被使用和转化的是一种有价值的技能,即使我们自己无法想象它们。由于机器学习的困难在于设计和理解将数据减少到低维潜在空间的模型,因此学习这些表示有很大的价值。

谢谢!

感谢您阅读这篇文章,我希望它是有用的。我计划写更多关于机器学习中的降维和潜在空间表示的文章,如果能听到您对您想看到的内容的反馈,那将是非常棒的!请随意在下面的回答中写下任何问题。

理解卷积神经网络(CNN)如何使用单词嵌入执行文本分类

原文:https://towardsdatascience.com/understanding-how-convolutional-neural-network-cnn-perform-text-classification-with-word-d2ee64b9dd0b?source=collection_archive---------2-----------------------

CNN 已经在各种文本分类任务中取得了成功。在1中,作者展示了一个简单的 CNN,具有很少的超参数调整和静态向量,在多个基准上取得了优异的结果——在 7 个任务中的 4 个上改进了现有技术。

然而,当学习将 CNN 应用于单词嵌入时,跟踪矩阵的维度可能会令人困惑。这篇短文的目的是简单地跟踪这些维度,并理解 CNN 是如何进行文本分类的。我们将在一个 7 个单词的句子上使用一层 CNN,单词嵌入为 5 维——这是一个帮助理解 CNN 的玩具示例。所有的例子都来自2。

设置

Above figure is from 2, with #hash-tags added to aid discussion. Quoting the original caption here, to be discussed later. “Figure 1: Illustration of a CNN architecture for sentence classification. We depict three filter region sizes: 2,3,4, each of which has 2 filters. Filters perform convolutions on the sentence matrix and generate (variable-length) feature maps; 1-max pooling is performed over each map, i.e., the largest number from each feature map is recorded. Thus, a univariate feature vector is generated from all six maps, and these 6 features are concatenated to form a feature vector for the penultimate layer. The final softmax later then receives this feature vector as input and uses it to classify the sentence; here we assume binary classification and hence depict two possible output states.”

#句子

例子是“我很喜欢这部电影!”,这里有 6 个单词,感叹号被当作一个单词来处理-一些研究人员以不同的方式处理,忽略感叹号-句子中总共有 7 个单词。作者选择 5 作为单词向量的维数。我们让 s 表示句子的长度,而 d 表示单词向量的维数,因此我们现在有一个形状为 s x d 的句子矩阵,即 7×5。

#过滤器

CNN 的一个令人满意的特性是它保持了计算机视觉中的 2D 空间方向。文字和图片一样,都是有方向性的。文本不是二维的,而是一维结构,其中单词序列很重要。我们还记得,示例中的所有单词都被一个 5 维的单词向量替换,因此我们固定过滤器的一个维度来匹配单词向量(5)并改变区域大小, h 。区域大小指的是要过滤的句子矩阵中代表单词的行数。

在图中,#filters 是过滤器的说明,而不是过滤器从句子矩阵中过滤出来的内容,下一段将使这种区别更加清楚。这里,作者选择使用 6 个过滤器——2 个互补的过滤器来考虑(2,3,4)个单词。

#功能地图

在本节中,我们将逐步介绍 CNN 如何执行卷积/过滤。为了清楚起见,我在句子矩阵和过滤器矩阵中填入了一些数字。

The action of the 2-word filter on the sentence matrix.

首先,由 2×5 黄色矩阵 w 表示的双字过滤器,覆盖在“I”和“like”的字向量上。接下来,它对其所有 2 x 5 元素执行元素式乘积,然后将它们相加并获得一个数字(0.6 x 0.2 + 0.5 x 0.1 + … + 0.1 x 0.1 = 0.51)。0.51 被记录为该滤波器输出序列的第一个元素 o 。然后,过滤器向下移动 1 个单词并覆盖单词向量“like”和“this ”,并执行相同的操作以获得 0.53。因此, o 将具有(sh+1 x 1)的形状,在本例中为(7–2+1 x 1)

为了获得特征图, c ,我们添加一个偏置项(一个标量,即形状 1×1)并应用一个激活函数(例如 ReLU )。这给了我们 c,o(sh+1 x 1)相同的形状。

# 1 最大

请注意, c 的维数取决于 sh ,换句话说,它会随着不同长度的句子和不同区域大小的过滤器而变化。为了解决这个问题,作者采用了 1-max 池函数,并从每个 c 向量中提取最大数。

#concat1max

在 1-max 池化之后,我们确定具有 6 个元素的固定长度向量(=过滤器数量=每个区域大小的过滤器数量(2) x 考虑的区域大小的数量(3))。这个固定长度的向量然后可以被馈送到 softmax(全连接)层以执行分类。作为学习的一部分,来自分类的误差然后被反向传播回以下参数:

  • 产生 ow 矩阵
  • 添加到 o 以产生 c 的偏置项
  • 单词向量(可选,使用验证性能来决定)

结论

这篇短文通过关注每个中间步骤中矩阵的维度,阐明了 CNN 在单词嵌入方面的工作。

参考文献

  1. 用于句子分类的卷积神经网络。2014;
  2. 用于句子分类的卷积神经网络的敏感性分析(和实践者指南)。arXiv 预印本 arXiv:151003820。2015;PMID: 463165

理解石灰如何解释预测

原文:https://towardsdatascience.com/understanding-how-lime-explains-predictions-d404e5d1829c?source=collection_archive---------3-----------------------

在最近的一篇文章中,我介绍了三种现有的方法来解释任何机器学习模型的个体预测。在这篇文章中,我将重点介绍其中的一种:局部可解释的模型不可知解释 ( LIME ),这是马尔科·图利奥·里贝罗、萨梅尔·辛格和卡洛斯·盖斯特林在 2016 年提出的一种方法。

在我看来,它的名字完美地概括了这种解释方法背后的三个基本思想:

  1. 模型不可知论。换句话说,与模型无关,这意味着 LIME 不会对其预测得到解释的模型做出任何假设。它将模型视为一个黑盒,因此它必须理解其行为的唯一方式是扰动输入,并观察预测如何变化。
  2. 可解释性。首先,解释必须易于用户理解,这对于模型所使用的特征空间来说不一定是正确的,因为它可能使用太多的输入变量(即使是线性模型,如果它具有成百上千个系数,也可能难以解释),或者它只是使用太复杂/非官方的变量(并且根据这些变量的解释将不会被人类解释)。出于这个原因,LIME 的解释使用了不同于原始特征空间的数据表示(称为可解释表示)。
  3. 地点。LIME 通过在我们想要解释的实例附近用可解释的模型(例如,具有几个非零系数的线性模型)来近似黑盒模型来产生解释。

总之,LIME 根据可解释模型的组成部分(例如,线性回归中的系数)生成对预测的解释,该模型类似于关注点附近的黑盒模型,并通过新的数据表示进行训练以确保可解释性。

可解释的表示

为了确保解释是可解释的,LIME 将可解释的表示与模型使用的原始特征空间区分开来。可解释的表示必须是人类可理解的,因此它的维度不一定与原始特征空间的维度相同。

p 为原始特征空间 X 的维数,设p’为可解释空间X’的维数。可解释输入通过映射函数hʸ: x’→x映射到原始输入,具体到我们要解释的实例 yX

不同类型的映射用于不同的输入空间:

  • 对于文本数据,可能的可解释表示是指示单词存在或不存在的二进制向量,尽管分类器可以使用更复杂和不可理解的特征,例如单词嵌入。形式上, X' ={0,1}ᵖ'≡ {0,1}× ⋅⋅⋅ × {0,1}其中 p' 是包含被解释的实例的单词数,映射函数将 1 或 0 的向量(分别是单词的存在或不存在)转换成模型使用的表示:如果它使用单词计数,映射将 1 映射到原始单词计数,0 映射到 0;但是如果模型使用单词嵌入,映射应该将任何用 1 和 0 的向量表示的句子转换成它的嵌入版本。
  • 对于图像,可能的可解释表示是指示一组连续相似像素(也称为超像素)的存在或不存在的二进制向量。形式上, X' ={0,1}ᵖ'其中 p' 是所考虑的超级像素的数量,通常通过图像分割算法如快速移动来获得。在这种情况下,映射函数将 1 映射为保留原始图像中的超像素,将 0 映射为灰化超像素(表示缺失)。

Original representation (left) and interpretable representation (right) of an image. Sets of contiguous similar pixels (delimited by yellow lines) are called super pixels. Each super pixel defines one interpretable feature. Source: https://www.oreilly.com/learning/introduction-to-local-interpretable-model-agnostic-explanations-lime

  • 对于表格数据(即矩阵),可解释的表示取决于特征的类型:分类、数值或混合数据。对于分类数据,x’={0,1}ᵖ,其中 p 是模型使用的特征的实际数量(即p’= p),并且映射函数将 1 映射到实例的原始类,将 0 映射到根据训练数据的分布采样的不同类。对于数值型数据, X'=X 和映射函数是恒等式。但是,我们可以将数字特征离散化,这样它们就可以被认为是分类特征。对于混合数据,可解释的表示将是由对应于分类特征的二元特征和对应于数值特征的数值特征(如果它们没有被离散化)组成的一个 p 维空间。根据解释变量的类型,映射函数的每个组成部分也根据前面的定义来定义。

位置

虽然一个简单的模型可能无法全局近似黑盒模型,但在我们想要解释的个体实例的邻域中近似它可能是可行的。换句话说,LIME 依赖于这样一个假设,即每个复杂的模型在局部尺度上都是线性的。

从形式上来说,我们需要一个权重函数 wʸ: X →ℝ⁺,它给最接近我们想要解释的实例的实例 zX 最大权重,给最远的实例最小权重。

保真度-可解释性权衡

Ribeiro 等人将解释定义为模型g:x’→ℝ,使得 gG ,其中 G 是一类“潜在的”可解释模型,也就是说,可以容易地用视觉或文本工件呈现给用户的模型,例如线性模型或决策树。注意 g 的定义域是可解释空间X’

假设𝔏 (f,g,wʸ) 是一个损失函数,它测量 g 在考虑权重 的情况下近似 f 的准确度。由于不是每个 gG 都足够简单到可以被解释,我们让ω(G)作为一个正则化项来度量解释 gG 的复杂度(与可解释性相反)。例如,对于线性模型,ω(g)可以是非零系数的数量,而对于决策树,ω(g)可以是树的深度。

方法

X =ℝᵖ为特征空间。设 y ∈ℝᵖ为被解释实例的原始表示,而y’x’为其可解释表示

同样,让ℝᵖ→ℝ成为被解释的模型。在分类中, f(x)x 属于某一类的概率(或二元指标)。对于多个类,LIME 分别解释每个类,因此 f(x) 是相关类的预测。在回归中, f(x) 是回归函数。

最后,让 g: X' → ℝ作为解释模型。设𝔏 (f,g,wʸ) 是一个损失函数,它测量 g 在由 定义的位置中逼近 f 的不忠实程度,设ω(g是解释的复杂度的度量 gG

为了确保可解释性和局部保真度,我们必须最小化𝔏( f,g,wʸ ,同时使ω(g)足够低,以便人类能够解释。因此,由石灰产生的解释ξ( y )由下式得到:

注意,该公式可用于不同的解释族 g、损失函数𝔏和正则化项ω。

实际上,LIME 用来产生解释的一般方法如下:

  1. 生成实例的可解释版本的 N 个“扰动”样本来解释y’。设{zᵢ'x’| I = 1,…,N}为这些观测值的集合。
  2. 通过映射函数恢复原始特征空间中的“扰动”观察值。设{zᵢhʸ(zᵢ')x| I = 1,…,N}为原表示中的集合。
  3. 让黑盒模型预测每一次“扰动”观察的结果。设{ f(zᵢ) ∈ℝ | i=1,…,N}为回答的集合。
  4. 计算每个“被扰乱”的观察的权重。设{ wʸ(zᵢ) ∈ℝ⁺ | i=1,…,N}为权的集合。
  5. 使用“扰动”样本及其响应的数据集{ (z'ᵢ,f(zᵢ))【∈x'×ℝ| I = 1,…,N}作为训练数据,求解上述方程。

请注意,复杂度不取决于训练集的大小(因为它产生对单个预测的解释),而是取决于计算预测的时间 f(z) 和样本数量 N

步骤 1 中描述的采样过程取决于可解释空间X’,因此根据输入数据的类型而不同(参见“可解释表示”一节)。对于解释空间由二值特征组成的文本数据或图像(即x’={0,1}ᵖ'),样本*zᵢ'x’是通过随机均匀抽取y’*的非零元素得到的,其中抽取的次数也是均匀抽样的。对于表格数据(即矩阵),步骤 1 取决于特征的类型,并且需要原始训练集。

对于文本数据,由于可解释空间是指示单词存在或不存在的二进制向量,因此该过程意味着从被解释的实例中随机移除单词。例如,如果我们试图解释文本分类器对句子“我讨厌这部电影”的预测,我们将扰动该句子,并得到对诸如“我讨厌电影”、“我这部电影”、“我电影”、“我讨厌”等句子的预测。请注意,如果分类器使用一些不可解释的表示,如单词嵌入,这仍然有效:在步骤 2 中,我们将使用单词嵌入来表示受干扰的句子,解释仍然是根据单词,如“仇恨”或“电影”。

对于图像,由于可解释空间是指示超像素的存在或不存在的二进制向量,所以该过程包括随机地使一些超像素变成灰色。换句话说,如果我们想要解释一幅图像的预测,我们将扰动该图像,并在具有一个或多个隐藏超像素的图像上获得预测。下图描述了这一过程:

Examples of perturbed instances of an image and their predictions. Source: https://www.oreilly.com/learning/introduction-to-local-interpretable-model-agnostic-explanations-lime

对于表格数据(即矩阵),分类特征和数值特征之间存在差异,但两种类型都依赖于训练集。对于分类特征(其可解释的表示是二进制的),扰动样本是通过根据训练分布进行采样,并在值与被解释的实例相同时生成为 1 的二进制特征而获得的。对于数字特征,通过从正态(0,1)分布采样并进行均值居中和缩放的逆运算(使用训练数据的均值和标准偏差)来扰乱正在解释的实例。

稀疏线性解释

Ribero 等人专注于他们所谓的稀疏线性解释,对应于解释族 G 的具体选择,损失函数𝔏和正则化项ω。这些选择没有明确的理由,但可以推断出一些可能的原因。它们是:

  • 作为解释族的线性模型类 Gg(z')=β⋅ z'

线性模型让我们通过检查系数的大小和符号来衡量每个特征在预测中的影响。因此,线性模型提供了解释变量和响应之间的定性理解,这使得它们成为适合作为解释模型的潜在可解释模型。

  • 定义在某个距离函数 D 上作为权函数的指数核。 wʸ(z)=e^{-D(y,z) /σ }

选择使用指数核是不合理的。使用的距离函数是文本数据的余弦相似性度量,以及图像和表格数据的欧几里德距离。然而,LIME 在 Python 和 R 中的实现接受用户选择的任何其他距离。最后,即使没有讨论内核宽度σ的选择,它默认为σ=3/4 \sqrt,其中 p 是特征的数量。

  • 加权最小二乘误差作为损失函数。

其中 *(z'ᵢ,f(zᵢ)*是“扰动”样本的数据集,其响应如上所述。二次损失函数通常比其他损失函数在数学上更容易处理,特别地,加权最小二乘问题具有封闭形式的解。

  • 将非零系数的数量限制为 K 作为正则项。

其中∥β∥₀=∑ⱼ|βⱼ|⁰是 L0“范数”(即β的非零项的数量)。正则化参数 K 对于解释任务至关重要,因为它确定了将呈现给用户的组件的数量。

注意,有两个超参数:用于解释的核宽度σ和特征数量 K

在前面的选择中,使用石灰进行解释所需的方程变为:

这个方程不能直接求解,因此他们通过首先使用特征选择技术选择 K 特征,然后通过加权最小二乘法估计系数来近似求解。

在原始论文中,作者使用 LASSO 产生的正则化路径(即 LASSO 作为收缩因子的函数估计的系数)选择 K 特征,然后通过加权最小二乘法估计系数。他们称这个过程为 K-LASSO。然而,LIME 的实现目前支持更多的特性选择算法来选择 K 特性。同样,所有特性都可以用于解释,但除非特性非常少,否则不推荐使用。

总的来说,LIME 用来近似前一个方程的解并产生对例如 y 解释的当前方法是:

  1. 生成实例的可解释版本的 N 个“扰动”样本以解释 y’。设{zᵢ'x’| I = 1,…,N}为这些观测值的集合。
  2. 通过映射函数恢复原始特征空间中的“扰动”观察值。设{zᵢ≡hʸ(zᵢ')x| I = 1,…,N}为原表示中的集合。
  3. 让黑盒模型预测每一次“扰动”观察的结果。设{ f(zᵢ) ∈ℝ | i=1,…,N}为响应集合,设ℨ={ *(z'ᵢ,f(zᵢ)x '*×ℝ| I = 1,…,N}为“扰动”样本及其响应的数据集。
  4. 计算每个“被扰乱”的观察的权重。设{ wʸ(zᵢ) ∈ℝ⁺ | i=1,…,N}为权的集合。
  5. 从扰动的数据集ℨ.中选择最能描述黑盒模型结果的 k 个特征
  6. 将加权线性回归模型(实际上,LIME 的当前实现是将正则化参数设置为 1 的加权岭回归)拟合到由步骤 5 中的 K 所选要素组成的要素缩减数据集。如果黑箱模型是回归量,线性模型会直接预测黑箱模型的输出。如果黑盒模型是分类器,线性模型将预测所选类别的概率。
  7. 从线性模型中提取系数,并用它们来解释黑盒模型的局部行为。

下图显示了此图像处理过程的一个示例。注意,除了黑盒模型(分类器或回归器) f 和解释 y (及其可解释表示y’)的实例之外,前面的过程需要预先设置样本数量 N ,核宽度σ和解释长度 K

Explaining the prediction of a classifier with LIME. Source: https://www.oreilly.com/learning/introduction-to-local-interpretable-model-agnostic-explanations-lime

在以后的文章中,我将解释如何使用 R 和 Python 解释带有 LIME 的 ML 模型的预测。

理解超参数及其优化技术

原文:https://towardsdatascience.com/understanding-hyperparameters-and-its-optimisation-techniques-f0debba07568?source=collection_archive---------3-----------------------

Figure 1: https://pixabay.com/en/thoughts-think-psyche-psychology-551263/

什么是超参数?
在统计学中,超参数是来自先验分布的参数;它在数据被观察到之前捕捉先验信念。

在任何机器学习算法中,这些参数都需要在训练模型之前进行初始化。

模型参数对超参数

模型参数 是分类器或其他 ML 模型在训练过程中将自行学习的训练数据的属性。举个例子,

  • 权重和偏差
  • 决策树中的分割点

Figure 2: Hyperparameters vs model parameters → Source

模型超参数 是管理整个训练过程的属性。以下是在训练模型之前通常配置的变量。

  • 学习率
  • 时代数
  • 隐藏层
  • 隐藏单元
  • 激活功能

为什么超参数必不可少?

超参数非常重要,因为它们直接控制训练算法的行为,并对正在训练的模型的性能产生重大影响。

“一个好的超参数选择,真的可以让一个算法大放异彩”。

选择合适的超参数在我们的神经网络体系结构的成功中起着至关重要的作用。因为它对学习模型有巨大的影响。例如,如果学习率太低,模型将错过数据中的重要模式。如果高,可能会有碰撞。

选择好的超参数有两个好处:

  • 有效地搜索可能的超参数空间
  • 易于管理超参数调整的大量实验。

超参数优化技术

机器学习中寻找最优超参数的过程称为超参数优化。

常见算法包括:

  • 网格搜索
  • 随机搜索
  • 贝叶斯优化

网格搜索

网格搜索是实现超参数的一种非常传统的技术。它强力破解所有组合。网格搜索需要创建两组超参数。

  1. 学习率
  2. 层数

网格搜索通过使用两组超参数(学习速率和层数)为所有组合训练算法,并使用“交叉验证技术测量性能。这种验证技术保证了我们的训练模型从数据集中获得了大多数模式。使用“ K 重交叉验证 进行验证的最佳方法之一,这有助于为模型的训练和验证提供充足的数据。

Figure 3: Grid Search → Source

网格搜索方法是一种使用起来更简单的算法,但是如果数据具有被称为 维数灾难 的高维空间,它就会受到影响。

随机搜索

随机对搜索空间进行采样,并根据指定的概率分布计算集合。例如,我们可以检查 1000 个随机参数,而不是试图检查所有 100,000 个样本。

Figure 4: Random Search → Source

然而,使用随机搜索算法的缺点是,它不使用来自先前实验的信息来选择下一组,并且也很难预测下一组实验。

贝叶斯优化

超参数设置使模型在验证集上的性能最大化。机器学习算法经常需要微调模型超参数。不幸的是,这种调整通常被称为“黑函数”,因为由于函数的导数未知,它不能被写入公式。

更吸引人的优化和微调超参数的方法是 通过使用贝叶斯优化算法启用自动模型调整方法。用于逼近目标函数的模型被称为代理模型。用于贝叶斯优化的流行代理模型是高斯过程(GP) 。贝叶斯优化通常通过假设从高斯过程(GP)中采样未知函数来工作,并在进行观察时保持该函数的后验分布。

执行贝叶斯优化时,必须做出两个主要选择。

  1. 选择先验函数,它将表达关于被优化函数的假设。为此,我们选择 高斯过程 先验
  2. 接下来,我们必须选择一个 采集函数 ,用于从模型后验构建一个效用函数,允许我们确定下一个要评估的点。

高斯过程

高斯过程定义了函数的先验分布,一旦我们看到一些数据,它可以转换成函数的后验分布。高斯过程使用协方差矩阵来确保值非常接近。协方差矩阵以及输出期望值的均值函数定义了高斯过程。

1.高斯过程将作为 的先验 用于贝叶斯推理
2。计算的后验概率在于它可以用来对看不见的测试用例进行预测。

Figure 5: Gaussian Process prior distribution → Source

Figure 6: Gaussian Process posterior distribution by applying covariance matrix → Source

采集功能

通过采集功能将采样数据引入搜索空间。这有助于最大化采集函数以确定下一个采样点。常见的采集功能有

  • 最大改善概率(MPI)
  • 预期改善
  • 置信上限(UCB)

预期改善(EI) 功能似乎是一个受欢迎的功能。它被定义为

EI(x)=𝔼[max{0,ƒ(x)−ƒ(x̂ )}]

其中ƒ(x̂)是超参数的当前最佳集合。最大化超参数将改善的性能。**

  1. 当损失的后验期望值 (x) 高于当前最佳值ƒ(x̂时,EI 为高)
  2. 当围绕点 x x 的不确定性σ( x )σ(x)高时,EI 高。

概要:

  • 超参数调谐是一门艺术,也就是我们常说的“黑函数”。选择合适的超参数将使算法发光并产生最大的精确度
  • 超参数优化技术大多使用任何一种优化算法
  1. 网格搜索
  2. 随机搜索
  3. 贝叶斯优化
  • 贝叶斯优化使用高斯过程(GP)函数来获得后验函数,以基于先验函数进行预测
  • 采集功能有助于最大化和确定下一个采样点。

理解机器学习中的 K-均值聚类

原文:https://towardsdatascience.com/understanding-k-means-clustering-in-machine-learning-6a6e67336aa1?source=collection_archive---------0-----------------------

K-means 聚类是最简单和最流行的无监督机器学习算法之一。

通常,无监督算法仅使用输入向量从数据集进行推断,而不参考已知或标记的结果。

AndreyBu 拥有超过 5 年的机器学习经验,目前正在向人们传授他的技能,他说“K-means 的目标很简单:将相似的数据点组合在一起,并发现潜在的模式。为了实现这个目标,K-means 在数据集中寻找固定数量( k )的聚类

聚类是指由于某些相似性而聚集在一起的数据点的集合。

您将定义一个目标数 k ,它指的是您在数据集中需要的质心数。质心是代表群集中心的虚拟或真实位置。

通过减少类内平方和,将每个数据点分配给每个类。

换句话说,K-means 算法识别 k 个质心,然后将每个数据点分配到最近的簇,同时保持质心尽可能小。

K-means 中的表示是指数据的平均值;也就是求质心。

K 均值算法的工作原理

为了处理学习数据,数据挖掘中的 K-means 算法从第一组随机选择的质心开始,这些质心用作每个聚类的起始点,然后执行迭代(重复)计算以优化质心的位置

当出现以下任一情况时,它会停止创建和优化集群:

  • 质心已经稳定,因为聚类成功,所以它们的值没有变化。
  • 已达到定义的迭代次数。

K-means 算法例题

让我们看看 K-means 机器学习算法如何使用 Python 编程语言工作的步骤。

我们将使用 Scikit-learn 库和一些随机数据来说明 K-means 聚类的简单解释。

步骤 1:导入库

import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom sklearn.cluster import KMeans%matplotlib inline

从上面的代码中可以看出,我们将在项目中导入以下库:

  • 熊猫用于阅读和书写电子表格
  • 用于执行有效计算的数字
  • 用于数据可视化的 Matplotlib

第二步:生成随机数据

下面是在二维空间中生成一些随机数据的代码:

X= -2 * np.random.rand(100,2)X1 = 1 + 2 * np.random.rand(50,2)X[50:100, :] = X1plt.scatter(X[ : , 0], X[ :, 1], s = 50, c = ‘b’)plt.show()

总共产生了 100 个数据点,并分成两组,每组 50 个点。

以下是数据在二维空间中的显示方式:

第三步:使用 Scikit-Learn

我们将使用 Scikit-learn 库中的一些可用函数来处理随机生成的数据。

代码如下:

from sklearn.cluster import KMeansKmean = KMeans(n_clusters=2)Kmean.fit(X)

在这种情况下,我们任意给 k (n_clusters)一个任意值 2。

下面是我们运行代码时得到的 K-means 参数的输出:

KMeans(algorithm=’auto’, copy_x=True, init=’k-means++’, max_iter=300
 n_clusters=2, n_init=10, n_jobs=1, precompute_distances=’auto’,
 random_state=None, tol=0.0001, verbose=0)

第四步:寻找质心

下面是查找聚类中心的代码:

Kmean.cluster_centers_

以下是质心值的结果:

array([[-0.94665068, -0.97138368],
 [ 2.01559419, 2.02597093]])

让我们显示集群质心(使用绿色和红色)。

plt.scatter(X[ : , 0], X[ : , 1], s =50, c=’b’)plt.scatter(-0.94665068, -0.97138368, s=200, c=’g’, marker=’s’)plt.scatter(2.01559419, 2.02597093, s=200, c=’r’, marker=’s’)plt.show()

以下是输出:

第五步:测试算法

下面是获取 K 均值聚类示例数据集的 labels 属性的代码;也就是说,如何将数据点分类到两个集群中。

Kmean.labels_

下面是运行上述 K-means 算法代码的结果:

array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

正如您在上面看到的,50 个数据点属于 0 簇,而其余的属于 1 簇。

例如,让我们使用下面的代码来预测数据点的聚类:

sample_test=np.array([-3.0,-3.0])second_test=sample_test.reshape(1, -1)Kmean.predict(second_test)

结果如下:

array([0])

显示测试数据点属于 0 (绿色质心)簇。

包装

以下是 Python 中完整的 K-means 聚类算法代码:

import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom sklearn.cluster import KMeans%matplotlib inlineX= -2 * np.random.rand(100,2)X1 = 1 + 2 * np.random.rand(50,2)X[50:100, :] = X1plt.scatter(X[ : , 0], X[ :, 1], s = 50, c = ‘b’)plt.show()from sklearn.cluster import KMeansKmean = KMeans(n_clusters=2)Kmean.fit(X)Kmean.cluster_centers_plt.scatter(X[ : , 0], X[ : , 1], s =50, c=’b’)plt.scatter(-0.94665068, -0.97138368, s=200, c=’g’, marker=’s’)plt.scatter(2.01559419, 2.02597093, s=200, c=’r’, marker=’s’)plt.show()Kmean.labels_sample_test=np.array([-3.0,-3.0])second_test=sample_test.reshape(1, -1)Kmean.predict(second_test)

k-均值聚类是一种广泛使用的数据聚类分析技术。

这很容易理解,尤其是如果你使用 K-means 聚类教程来加速你的学习。此外,它可以快速提供培训结果。

但是,它的性能通常不如其他复杂的聚类技术有竞争力,因为数据中的微小变化会导致很大的差异。

此外,聚类被假设为球形且大小均匀,这可能会降低 K-means 聚类 Python 结果的准确性。

在机器学习中使用 K-means 聚类有什么经验?

请在下面分享你的评论。

使用 Python 的多处理库理解 Lamport 时间戳

原文:https://towardsdatascience.com/understanding-lamport-timestamps-with-pythons-multiprocessing-library-12a6427881c6?source=collection_archive---------7-----------------------

每个使用分布式系统或来自这种系统的日志的人都直接或间接地遇到过 Lamport 时间戳。Lamport 时间戳用于在分布式系统中对事件进行(部分)排序。该算法基于事件的因果排序,是矢量时钟和间隔树时钟(ITC)等更高级时钟的基础。

在本文中,我们将首先简要介绍逻辑时钟的概念,解释为什么分布式系统中需要事件排序,并讨论一些替代方案。然后,我们将讨论 Lamport 时间戳的算法,并使用三个流程进行示例。接下来,我们将使用 Python 的多重处理库,用易于理解的代码实现这个例子。最重要的是,我们将用矢量时钟将代码转换成实现。

逻辑时钟

为了理解为什么需要逻辑时钟,理解什么是分布式系统是很重要的。分布式系统是一个系统,其组件(这里称为进程)位于不同的联网计算机上,然后这些计算机通过相互传递消息来协调它们的动作。

分布式系统的主要特性之一是它没有一个全局时钟。所有进程都有自己的本地时钟,但是由于时钟偏移和时钟漂移,它们没有直接的方法知道自己的时钟是否与系统中其他进程的本地时钟一致,这个问题有时被称为时钟同步的问题。

这个问题的解决方案包括使用中央时间服务器( Cristian 的算法)或称为逻辑时钟的机制。中央时间服务器的问题在于,它的误差取决于消息从进程到时间服务器的往返时间。

逻辑时钟基于捕捉过程的时间顺序和因果关系,并基于这些关系对事件进行排序。第一个实现,Lamport 时间戳,是由 Leslie Lamport 在 1978 年提出的,现在仍然是几乎所有逻辑时钟的基础。

Lamport 时间戳算法

Lamport 逻辑时钟是在每个进程中维护的递增计数器。从概念上讲,这个逻辑时钟可以被认为是一个只对在进程间移动的消息有意义的时钟。当一个进程接收到一条消息时,它会将其逻辑时钟与发送方重新同步(因果关系)。

Lamport 时间戳的算法可以通过一些规则来捕获:

  • 所有进程计数器都从值 0 开始。
  • 对于流程中的每个事件(内部事件、消息发送、消息接收),流程的计数器都会递增。
  • 当进程发送消息时,它会在消息中包含其(递增的)计数器值。
  • 在接收到消息时,接收方的计数器被更新为其当前计数器和接收到的消息中的时间戳中的较大者,然后递增 1。

查看这些规则,我们可以看到该算法将创建最小的开销,因为计数器仅由一个整数值组成,并且消息传递搭载在进程间消息上。

Lamport 时间戳的缺点之一是,它们只对事件进行部分排序(而不是全部排序)。偏序表示并非每对事件都需要具有可比性。如果两个事件不能比较,我们称这些事件为并发。Lamport 时间戳的问题在于,它们不能判断事件是否是并发的。矢量时钟解决了这个问题。

例子

如果上面的描述对你来说有点模糊,看看下面的例子。所有进程的内部计数器(时钟)都从零开始。对于由圆圈表示的每个事件,计数器增加 1。当进程接收到消息时,它将其计数器设置为其内部计数器和消息中包含的时间戳中的较大者。

Lamport Timestamps example

例如,考虑流程 2 中的第一个事件,它从流程 1 接收一条消息。进程 2 的本地计数器此时为 0,但增加到 1,因为接收消息是一个事件。消息中包含的时间戳将是 2:进程 1 的本地时间加 1 (1+1)。进程 1 在发送消息的同时也将自己的时钟加 1。

为了在进程 2 中设置新的时间,取接收到的时间戳和它自己的本地时间之间的最大值( max(2,1) )并加 1。这将产生一个值为 3 的新时间戳。这是有意义的,因为消息永远不会在发送之前或发送的同时被接收。

履行

我们的实现将运行三个独立的进程,它们可以通过消息相互通信。每个进程都有自己的内部计数器,它将随着每个事件而更新。我们的脚本将为每个事件打印一行,连同更新的内部计数器和运行进程的机器上的时间。

在开始之前,我们需要从标准模块中导入一些函数:多处理中的进程管道用一个脚本运行多个 Python 进程,从 os 中的 getpid 获取每个进程的进程 id,从 datetime 中的 datetime 获取当前时间。

如果你需要更多关于多处理库的信息,请阅读文档,观看这个很棒的教程系列或者看一看这个(免费的)网络研讨会。

from multiprocessing import Process, Pipe
from os import getpid
from datetime import datetime

然后我们创建一些辅助函数。第一个简单地打印本地 Lamport 时间戳和执行进程的机器上的实际时间。请注意,打印“实际”时间在真正的分布式系统中没有意义,因为本地时钟不会彼此同步。

def local_time(counter):
    return ' (LAMPORT_TIME={}, LOCAL_TIME={})'.format(counter,
                                                     datetime.now())

第二个是在流程收到消息时计算新时间戳。该函数取接收到的时间戳及其本地计数器中的最大值,并将其加 1。

def calc_recv_timestamp(recv_time_stamp, counter):
    return max(recv_time_stamp, counter) + 1

接下来,我们想为每个可能发生的事件创建一个函数。在我们的例子中,它们是三个事件:事件(任何本地事件)消息发送消息接收。为了使我们的代码易于阅读,事件函数将为事件发生的流程返回更新的时间戳

事件事件获取本地计数器和进程 id ( pid ),将计数器递增 1,打印一行以便我们知道事件发生了,并返回递增后的计数器。

def event(pid, counter):
    counter += 1
    print('Something happened in {} !'.\
          format(pid) + local_time(counter))
    return counter

send_message 事件也以 pid计数器作为输入,但是额外需要一个管道管道是多处理库中的一个对象,代表两个进程之间的双向连接。每个管道由两个连接对象组成,每个方向一个。要发送或接收消息,我们需要在这些连接对象上调用 sendrecv 函数。

如果你看一下我们的例子,你会发现我们只需要两个消息管道。一个在进程 1 和进程 2 之间,一个在进程 2 和进程 3 之间。因此,我们的示例将有四个连接对象: pipe12pipe21pipe23pipe32 (见下文)。

Example with two pipes

我们的 send_message 事件首先将计数器加 1,然后发送一个实际的消息(这里内容并不重要)及其增加的时间戳,并打印一个简短的语句,包括新的本地 Lamport 时间和机器上的实际时间。就像我们所有的事件函数一样,它返回新的本地时间戳。

def send_message(pipe, pid, counter):
    counter += 1
    pipe.send(('Empty shell', counter))
    print('Message sent from ' + str(pid) + local_time(counter))
    return counter

recv_message 事件采用与 send_message 相同的三个参数。它通过调用管道上的 recv 函数来接收实际消息和时间戳。然后,它使用我们之前创建的 calc_recv_timestamp 函数计算新的时间戳,并打印一行包括更新的计数器和机器上的实际时间。

def recv_message(pipe, pid, counter):
    message, timestamp = pipe.recv()
    counter = calc_recv_timestamp(timestamp, counter)
    print('Message received at ' + str(pid)  + local_time(counter))
    return counter

我们已经准备好开始创建我们的三个过程的定义。每个进程从获得其唯一的进程 id (这是在我们的机器上运行的进程的实际进程 id)和将自己的计数器设置为 0 开始。然后,根据我们前面的示例,通过调用不同的事件函数来更新计数器,并将返回值传递给计数器。

def process_one(pipe12):
    pid = getpid()
    counter = 0
    counter = event(pid, counter)
    counter = send_message(pipe12, pid, counter)
    counter  = event(pid, counter)
    counter = recv_message(pipe12, pid, counter)
    counter  = event(pid, counter)

def process_two(pipe21, pipe23):
    pid = getpid()
    counter = 0
    counter = recv_message(pipe21, pid, counter)
    counter = send_message(pipe21, pid, counter)
    counter = send_message(pipe23, pid, counter)
    counter = recv_message(pipe23, pid, counter)

def process_three(pipe32):
    pid = getpid()
    counter = 0
    counter = recv_message(pipe32, pid, counter)
    counter = send_message(pipe32, pid, counter)

请注意,到目前为止,如果您执行代码,什么也不会发生。这是因为实际上没有创建任何进程,更不用说启动了。在脚本的 main 部分,我们将创建成功运行脚本所需的两个管道( Pipe() )和三个进程( Process() )。要启动流程,我们需要在每个流程上调用 startjoin加入向我们保证所有流程将在退出前完成。

if __name__ == '__main__': oneandtwo, twoandone = Pipe()
    twoandthree, threeandtwo = Pipe()

    process1 = Process(target=process_one, 
                       args=(oneandtwo,))
    process2 = Process(target=process_two, 
                       args=(twoandone, twoandthree))
    process3 = Process(target=process_three, 
                       args=(threeandtwo,))

    process1.start()
    process2.start()
    process3.start()

    process1.join()
    process2.join()
    process3.join()

现在,尝试运行代码。如果一切正常,您将得到与下图非常相似的输出。请注意,每个进程都有自己唯一的进程 id(每次运行代码时,这些 id 都会改变):

  • 进程 1 的 id 为 16112
  • 进程 2 的 id 为 18968
  • 进程 3 的 id 为 9584

每个事件都打印了一行,包括事件的类型和更新的 Lamport 时间戳。花一分钟时间将时间戳与我们示例中的戳记进行比较,您会发现它们都彼此一致。您可以通过绘制时间线来测试新的示例,并相应地更改过程定义。

Script output with Lamport Timestamps

矢量时钟

如前所述,Lamport 时间戳有一个很大的缺点:它们不能告诉你两个事件何时并发。回到我们的例子,通过检查时间戳,我们可以得出结论,流程 1 中的事件 3 发生在流程 3 中的事件 8 之前,但这不一定是真的。

Compare event 3 in process 1 with event 8 in process 2

如果事件 3 需要几秒钟,这不会影响事件 8,因此事件 8 将在事件 3 之前执行。您可以通过在流程 1 中执行事件 3 之前添加一点延迟来轻松验证这一点。

from time import sleepdef process_one(pipe12):
    pid = getpid()
    counter = 0
    counter = event(pid, counter)
    counter = send_message(pipe12, pid, counter)
    sleep(3)
    counter  = event(pid, counter)
    counter = recv_message(pipe12, pid, counter)
    counter  = event(pid, counter)

请注意,我们的事件顺序发生了变化,而我们的时间戳保持不变。

Output with delay in process 15104

矢量时钟通过使用矢量计数器而不是整数计数器来解决这个问题。具有 N 个进程的系统的向量时钟是 N 个计数器的向量,每个进程一个计数器。向量计数器必须遵循以下更新规则:

  • 最初,所有的计数器都是零(在我们的例子中是*【0,0,0】*)
  • 每当一个进程经历一个事件,它就把自己在 vector 中的计数器加 1。
  • 每当一个进程发送一条消息时,它都会在消息中包含一个它自己的(递增的)向量的副本。
  • 每当一个进程接收到一条消息,它就将自己在向量中的计数器加 1,并通过取自己的向量计数器中的值和接收到的消息的向量中的值的最大值来更新其向量中的每个元素。

将向量时钟应用于我们之前的示例时,我们为每个事件获取一个向量,如下图所示。

Vector Clocks example

考虑我们之前的例子,我们比较了流程 1 中的第三个事件和流程 2 中的第四个事件。向量读作*【3,0,0】【2,4,2】*。对于在另一个事件之前发生的一个事件,其向量的所有元素需要小于或等于另一个向量中的匹配元素

这里显然有冲突( 3 > 2 和 0 < 4 ),因此我们可以断定这些事件是同时发生的,并没有相互影响。

要将我们的代码转换成矢量时钟,我们需要做一些最小的调整。最大的问题在于当我们收到一条消息时,我们如何计算新的计数器。因为我们将使用数组,所以我们需要为每个元素计算消息中的计数器和流程的计数器之间的最大值。

def calc_recv_timestamp(recv_time_stamp, counter):
    for id  in range(len(counter)):
        counter[id] = max(recv_time_stamp[id], counter[id])
    return counter

接下来,同样因为我们使用数组,我们需要替换

counter += 1

经过

counter[pid] += 1

在我们所有的活动中。

最后,我们希望通过用长度为 3 的向量替换初始计数器,并根据它在向量中的位置手动设置我们的流程 id,来更改我们的流程定义。对于过程一

pid = getpid()
counter = 0

应替换为

pid = 0
counter = [0,0,0]

如果您对所有进程进行相应的更改并运行您的代码,您将得到以下输出。将输出与我们的示例进行比较,得出结论,它工作正常。

Output of Vector Clocks script

一旦你正确理解了 Lamport 时间戳和向量时钟是如何工作的,看看其他一些逻辑时钟可能会很有趣,比如矩阵时钟版本向量间隔树时钟。或者,用于跟踪分布式系统中数据变化的其他机制,例如散列历史

—请随时在评论中或私信中向我指出任何不一致或错误。—

来源

Time, Clocks, and the Ordering of Events in a Distributed System, Leslie Lamport, 1978

[## 云计算概念,第 1 部分| Coursera

关于本课程:今天的云计算系统,无论是开源的还是在公司内部使用的,都是使用…

www.coursera.org](https://www.coursera.org/learn/cloud-computing) [## 偏序集-维基百科

在数学中,尤其是在序论中,偏序集(也称偏序集)形式化并概括了直觉…

en.wikipedia.org](https://en.wikipedia.org/wiki/Partially_ordered_set)

了解学习率及其如何提高深度学习的性能

原文:https://towardsdatascience.com/understanding-learning-rates-and-how-it-improves-performance-in-deep-learning-d0d4059c1c10?source=collection_archive---------0-----------------------

这篇文章试图记录我对以下主题的理解:

  • 学习率是多少?它的意义是什么?
  • 一个人如何系统地达到一个好的学习率?
  • 为什么我们在训练时要改变学习率?
  • 使用预训练模型时,我们如何处理学习率?

这篇文章的大部分内容是基于过去 fast.ai 研究员写的东西1、2、5和3。这是它的一个简明版本,以一种能让人快速得到材料实质的方式安排。请仔细阅读参考资料,了解更多细节。

首先,什么是学习率?

学习率是一个超参数,它控制我们根据损失梯度调整网络权重的程度。该值越低,我们沿下坡行驶的速度越慢。虽然在确保我们不会错过任何局部最小值方面,这可能是一个好主意(使用低学习率),但这也可能意味着我们将需要很长时间才能收敛——特别是如果我们被困在一个平坦区域。

下面的公式显示了这种关系。

new_weight = existing_weight — learning_rate * gradient

Gradient descent with small (top) and large (bottom) learning rates. Source: Andrew Ng’s Machine Learning course on Coursera

通常,学习速率是由用户天真地随机配置的。在最好的情况下,用户将利用过去的经验(或其他类型的学习材料)来获得在设置学习率时使用的最佳值的直觉。

因此,通常很难做到正确。下图展示了配置学习率时可能遇到的不同情况。

Effect of various learning rates on convergence (Img Credit: cs231n)

此外,学习率影响我们的模型能够多快收敛到局部最小值(也就是达到最佳精度)。因此,从一开始就把它做好意味着我们训练模型的时间会更少。

**Less training time, lesser money spent on GPU cloud compute. :)**

有没有更好的方法来确定学习率?

的第 3.3 节中,用于训练神经网络的循环学习率[4]les lie n . Smith 认为,可以通过最初以非常低的学习速率训练模型,并在每次迭代中增加学习速率(线性或指数)来估计良好的学习速率。

Learning rate increases after each mini-batch

如果我们记录每次迭代的学习,并绘制学习率(log)与损失的关系图;我们会看到,随着学习率的增加,会有一个点,损耗停止减少,开始增加。实际上,我们的学习率应该理想地在图表最低点的左边(如下图所示)。在这种情况下,0.001 到 0.01。

以上似乎有用。我该如何开始使用它?

目前,它作为 fast.ai 包中的一个函数受到支持,由杰瑞米·霍华德开发,作为一种抽象 pytorch 包的方法(很像 Keras 是 Tensorflow 的抽象)。

在训练神经网络之前,只需要键入以下命令就可以开始寻找最佳学习速率。

让它变得更好

在这个节骨眼上,我们已经讨论了学习率是什么,它的重要性,以及当我们开始训练我们的模型时,我们如何系统地得出一个最佳值。

接下来,我们将讨论如何使用学习率来提高模型的性能。

传统智慧

典型地,当一个人设置他们的学习速率并训练模型时,他将只等待学习速率随着时间的推移而降低,并等待模型最终收敛。

然而,随着梯度达到稳定水平,训练损失变得更难改善。在3中, Dauphin 等人认为最小化损失的困难来自鞍点而不是不良的局部最小值。

A saddle point in the error surface. A saddle point is a point where derivatives of the function become zero but the point is not a local extremum on all axes. (Img Credit: safaribooksonline)

那么,我们如何摆脱这种情况呢?

我们可以考虑几个选择。一般来说,引用1中的话,

…如果训练不再改善我们的损失,我们将根据某种循环函数 f 在每次迭代中改变学习率,而不是使用一个固定的学习率值并随时间减少。就迭代次数而言,每个周期具有固定的长度。这种方法让学习率在合理的边界值之间循环变化。这很有帮助,因为如果我们在鞍点上停滞不前,提高学习速率可以更快地穿越鞍点平台。

在2中,Leslie 提出了一种“三角形”方法,其中学习速率在每几次迭代后重新开始。

‘Triangular’ and ‘Triangular2’ methods for cycling learning rate proposed by Leslie N. Smith. On the left plot min and max lr are kept the same. On the right the difference is cut in half after each cycle.

另一种同样流行的方法叫做热重启随机梯度下降,由 Loshchilov&Hutter【6】提出。这种方法基本上使用余弦函数作为循环函数,并在每个循环中以最大值重新开始学习速率。“暖”位来自于当学习率重新启动时,并不是从零开始;而是根据模型在最后一步[7]中收敛的参数。

虽然有各种变化,下图展示了它的一种实现,其中每个周期都设置为相同的时间段。

SGDR plot, learning rate vs iteration.

因此,我们现在有了一种减少训练时间的方法,基本上就是周期性地绕着“山”跳(如下)。

Comparing fixed LR and Cyclic LR (img credit: https://arxiv.org/abs/1704.00109)

除了节省时间之外,研究还表明,使用这些方法可以在不调整和较少迭代的情况下提高分类精度。

迁移学习中的学习速率

在 fast.ai 课程中,非常强调在解决人工智能问题时利用预训练模型。例如,在解决图像分类问题时,学生将学习如何使用 VGG 或 Resnet50 等预训练模型,并将其连接到您想要预测的任何图像数据集。

为了总结如何在 fast.ai(该程序,不要与 fast.ai 包混淆)中建立模型,下面是我们通常会采取的几个步骤:

1.启用数据扩充,预计算=真

2。使用 **lr_find()** 找到损失仍在明显改善的最高学习率

3.从预计算的激活中训练最后一层,持续 1-2 个时期

4.在 cycle_len=1 的情况下,对最后一层进行 2–3 个历元的数据扩充训练(即 precompute=False)

5.解冻所有层

6。将前几层的学习速率设置为比下一个更高层低 3-10 倍

7。再次使用**lr_find()**

8.用 cycle_mult=2 训练整个网络,直到过度拟合

从上面的步骤中,我们注意到步骤 2、5 和 7 与学习速度有关。在这篇文章的前面部分,我们已经基本上涵盖了提到的步骤的第二项——在那里我们谈到了如何在训练模型之前获得最佳的学习率。

在接下来的部分中,我们回顾了如何通过使用 SGDR,我们能够减少训练时间,并通过不时地重新启动学习速率来避免梯度接近零的区域,从而提高精度。

在最后一节中,我们将讨论差分学习,以及当训练模型与预训练模型相关联时,如何使用差分学习来确定学习率。

什么是差异学习?

这是一种在训练期间为网络中的不同层设置不同学习速率的方法。这与人们通常配置学习速率的方式形成对比,后者是在训练期间在整个网络中使用相同的速率。

One reason why I just love Twitter — direct answer from the man himself.

写这篇文章的时候,Jeremy 和 Sebastian Ruder [9]发表了一篇论文,深入探讨了这个话题。所以我猜想差别学习率现在有了一个新名字——区别性微调 。:)

为了更清楚地说明这个概念,我们可以参考下图,其中一个预训练模型被分成 3 组,每组将配置一个递增的学习率值。

Sample CNN with differential learning rate. Image credit from 3

这种配置方法背后的直觉是,前几层通常会包含非常细粒度的数据细节,如线条和边缘,我们通常不希望对其进行太多更改,而是希望保留其信息。因此,没有必要大幅度改变它们的权重。

相比之下,在后面的图层中,如上面绿色的图层,我们可以获得数据的详细特征,如眼球、嘴或鼻子;我们不一定需要保留它们。

这与其他微调方法相比如何?

在[9]中,有人认为微调整个模型的成本太高,因为有些模型可能有 100 多个层。因此,人们通常做的是一次一层地微调模型。

然而,这引入了顺序要求,阻碍了并行性,并且需要多次通过数据集,导致对小数据集的过度拟合。

还证明了[9]中介绍的方法能够在各种 NLP 分类任务中提高准确性并降低错误率(如下)

Results taken from [9]

参考资料:

【1】用学习率改善我们的工作方式。

【2】循环学息术

【3】利用差异学习率进行迁移学习。

【4】莱斯利·n·史密斯。训练神经网络的循环学习率。

【5】估计深度神经网络的最优学习速率

【6】随机梯度下降带温重启

【7】2017 年深度学习优化亮点

8】第一课笔记本,fast.ai 第一部分 V2

【9】用于文本分类的微调语言模型

了解测量级别

原文:https://towardsdatascience.com/understanding-levels-of-measurement-97ecfe94c388?source=collection_archive---------21-----------------------

因此,我想成为一名数据炼金术士(更普遍的说法是数据科学家)。炼金术士是试图将金属物质转化为黄金的人。在我的情况下,唯一的区别是我的金属是数据,而我的黄金是我希望数据承认的令人瞠目结舌的洞察力!

所以,如果你还在读这篇文章,你可能是这个社区的一员,你可能知道统计学在我们的技能组合中占有重要地位。在这篇文章中,我将使用一个故事来阐述我对测量及其水平的理解。当然,它必须是一个故事,毕竟数据科学家是高超的故事讲述者!

Our Day Dreaming Friend, Bob..Yeah, of course, he has to look cute 😉

见见我的朋友,鲍勃。他是一个非常有创造力和想象力的学生,正在从事统计学方面的职业。一天,大学毕业后,他决定去一家比萨饼店吃午饭。那里有很多顾客,鲍勃不得不等着下订单。

鲍勃是一个想象力丰富、沉浸在自己世界里的男孩,他只是瞥了一眼菜单。他进入了自己的统计世界。他注意到比萨饼的类别是名义上的数据。名义数据通常被称为分类数据,因为它们只是将给定的数据放入定义的类别中。例如,比萨饼可以有蔬菜或非蔬菜配料。名义上的数据并不能说明顺序,我们无法仅仅通过所用的配料来描述“披萨的美味”程度。另一个最好的例子是一个人的性别,即男性、女性或变性人

鲍勃然后意识到比萨饼的尺寸是有序的类型。顾名思义,序数数据清楚地表明一个有意义的顺序。鲍勃可以在菜单上看到小号、中号和大号比萨饼,清楚地表明了等级的顺序。然而,顺序变量并不意味着两组值(区间)之间的差是相等的。这意味着我们不能说小号和中号披萨的区别等于中号和大号披萨的区别。

鲍勃的白日梦被服务员打断了,因为他要求鲍勃点菜。Bob 点了他最爱吃的芝士爆鸡烧烤披萨(啊,我都流口水了!)并在比萨饼店四处张望。

在他面前的桌子上,有一家人正在享用他们的比萨饼,一对父母和他们的婴儿在助步车里。这个婴儿的脚太小了,鲍勃确信他的鞋号肯定是零!然后他意识到鞋码是一个区间变量。找到了。一个区间变量在数值之间有一个确定的区间,但缺少一个零点。考虑鞋号,我们可以说鞋号 8 和鞋号 7 的差等于鞋号 2 和鞋号 3 的差。但不代表 6 码是 3 码的 2 倍。当我们说鞋码为零时,并不意味着没有鞋。但它却表示鞋号,也就是说,它是一个任意的零点。

Aww!

鲍勃的奶酪热比萨饼现在已经到了,他的思想现在只集中在比萨饼上。鲍勃狼吞虎咽地吃着比萨饼,吃完后,比萨饼店非常安静。令人惊讶的是,所有的顾客都不见了,包括他前面的那家人。只有服务员和他。

鲍勃很快就离开了这个地方。他的思绪回到了统计世界,他得出结论,一个比萨饼店的顾客数量是一个比率比例。一个秤是区间秤的老大哥。它有明确的间隔,也有一个真正的零点值。这意味着在 Bob 离开比萨店时,顾客为零,即真正没有顾客。而如果有 20 个客户,这实际上意味着现在客户数量的 20 倍。故事结束!

我希望我们的男孩鲍勃已经用他自己的方式帮助你理解了测量的水平。我试图用一个故事来给你最简单的解释。但是为什么要学习测量的级别呢?

了解测量水平有助于我们解释该变量的数据。例如,对于数据变量颜色,,你可以将红色编码为 0,蓝色编码为 1,绿色编码为 2。将分类数据编码成数字是优选的,因为计算机倾向于比字母更容易解释数字。此外,我们可以尽量减少数据输入时出错的机会。例如,输入数据的人会像写“红色”一样写“红色”。“r”和“r”对计算机的意义不同,因此会影响我们的分析。此外,如果我们知道数据是名义上的,我们永远不会平均它。为什么?

Encoding for the music genre

为了更好地理解,考虑上面的音乐流派编码。使用上面的编码,如果我们让六个人选择一种颜色,我们得到的假设数据如下图所示。

它说我们调查的平均反馈是 4。这显然是误导。因此,在分析变量之前,有必要了解变量的测量水平。那都是乡亲们!

唷!我终于在 Medium 上写了我的第一篇博客。请留下您的回复,朋友们!

位置敏感散列法

原文:https://towardsdatascience.com/understanding-locality-sensitive-hashing-49f6d1f6134?source=collection_archive---------0-----------------------

减少数据维数的有效方法

动机

寻找最近邻居的任务很常见。您可以考虑像查找重复或相似文档、音频/视频搜索这样的应用程序。虽然使用暴力来检查所有可能的组合会给你精确的最近邻,但它根本不可伸缩。完成这项任务的近似算法一直是积极研究的领域。虽然这些算法不能保证给你准确的答案,但通常它们会提供一个很好的近似值。这些算法速度更快,可伸缩性更强。

位置敏感散列(LSH)就是这样一种算法。LSH 有许多应用,包括:

  • 近似重复检测:LSH 通常用于对大量文档、网页和其他文件进行重复数据删除。
  • 全基因组关联研究:生物学家经常使用 LSH 在基因组数据库中识别相似的基因表达。
  • 大规模图片搜索:谷歌使用 LSH 和 PageRank 来构建他们的图片搜索技术。
  • 音频/视频指纹识别:在多媒体技术中,LSH 被广泛用作音频/视频数据的指纹识别技术。

在这篇博客中,我们将试图理解这种算法的工作原理。

大意

是指一族函数(称为 LSH 族)将数据点散列到桶中,使得彼此靠近的数据点大概率位于同一个桶中,而彼此远离的数据点很可能在不同的桶中。这使得识别具有不同相似度的观察结果变得更加容易。

查找相似的文档

让我们试着去理解我们如何利用 LSH 来解决一个实际问题。我们试图解决的问题是:

目标:您已经收到了大量的文档。您希望找到“近似重复”的配对。

在这个问题的背景下,我们可以将 LSH 算法分解为 3 个主要步骤:

  1. 皱缩
  2. 最小哈希
  3. 区分位置的散列法

暂时不要过多地解读这个数字。它只是给你一个流程的概念。我们将详细讨论每个步骤。

叠瓦作用

**在这一步中,我们将每个文档转换成一个长度为 k 的字符集(也称为 k-瓦片区或 k-grams)。关键思想是将我们集合中的每个文档表示为一组 k 瓦片区。

举个例子:你的一个文档(D):“纳达尔”。如果我们对 2-带状疱疹感兴趣,那么我们的集合:{Na,ad,da,al}。类似的 3-带状疱疹集:{Nad,ada,dal}。

  • 相似的文档更有可能共享更多的瓦片区
  • 在改变单词的文档中重新排序段落对带状疱疹没有太大影响
  • 实际中一般采用 8–10的 k 值。较小的值将导致出现在大多数文档中的许多带状疱疹(不利于区分文档

Jaccard 索引

我们以瓦片的形式表示每个文档。现在,我们需要一个度量来衡量文档之间的相似性。Jaccard Index 是一个很好的选择。文档 A & B 之间的 Jaccard 索引可以定义为:

它也被称为(IOU)。**

假设 A:“Nadal”和 B:“Nadia”,那么 2-带状疱疹表示将是:

A: {Na,ad,da,al}和 B: {Na,ad,di,ia}。

雅克卡指数= 2/6

更多数量的公共瓦片区将导致更大的 Jaccard 索引,因此文档更可能是相似的。

让我们讨论一下我们需要解决的两个大问题:

时间复杂度

现在你可能认为我们可以就此打住。但是如果考虑到可伸缩性,仅仅这样做是行不通的。对于 n 个文档的集合,需要做 n(n-1)/2 比较,基本上就是 O(n ) 。假设你有 100 万个文档,那么比较的数量将是 510(完全不可伸缩!).**

空间复杂性

文档矩阵是一个稀疏矩阵,按原样存储它将是一个很大的内存开销。解决这个问题的一种方法是散列法。

散列法

散列的思想是使用散列函数 H 将每个文档转换成一个小签名。 假设我们语料库中的一个文档用 d. 表示,那么:

  • H(d)是签名,它足够小,可以放在内存中
  • 如果相似度(d1,d2) 高,则 概率(H(d1)==H(d2))
  • 如果相似度(d1,d2) 低,则 概率(H(d1)==H(d2))

哈希函数的选择与我们使用的相似性度量紧密相关。对于 Jaccard 相似性,合适的散列函数是最小散列**。**

最小散列法

这是这个算法最关键也是最神奇的地方,所以请注意:

第一步:文档瓦片矩阵行索引随机排列 (π) 。**

**第二步:**哈希函数是 C 列值为 1 的第一行(按排列顺序)的索引。这样做几次(使用不同排列)来创建列的签名。

最小散列属性

签名的相似性是它们一致的最小散列函数(行)的分数。所以 C1 和 C3 的签名相似度是 2/3,因为第一行和第三行是相同的。

****

两个签名的预期相似性等于列的 Jaccard 相似性。签名越长,误差越小

在下面的例子中,你可以在某种程度上看到这一点。有所不同,因为我们只有长度为 3 的签名。但是如果增加长度,这两个相似点会更接近。

因此,使用最小散列法,我们通过消除稀疏性并同时保持相似性的,解决了空间复杂度的问题。在实际实施中,他们是一个创造指数排列的技巧,我不会覆盖,但你可以在 15:52 左右检查这个视频。 Min-hash 实现**

局部敏感散列法

目标:找到 Jaccard 相似度至少为 t 的文档

LSH 的总体思想是找到一种算法,使得如果我们输入两个文档的签名,它告诉我们这两个文档是否形成候选对,即它们的相似性大于阈值 t 。请记住,我们将签名的相似性作为原始文档之间 Jaccard 相似性的代理。

专门针对最小哈希签名矩阵:

  • 使用几个散列函数散列签名矩阵 M 的列
  • 如果对于至少一个散列函数的来说,两个文档散列到同一个桶中,我们可以将这两个文档作为候选对****

现在的问题是如何创建不同的散列函数。为此,我们进行波段划分。

波段划分

算法是这样的:

  • 将签名矩阵分成 b 个带,每个带有 r 行
  • 对于每个带,用 k 个桶将它在每列中的部分散列到一个散列表中
  • 候选列对是那些对于至少 1 个带散列到相同桶的列对
  • 调整 b 和 r 以捕捉最相似的对,但很少捕捉不相似的对

这里的考虑很少。理想情况下,对于每个波段,我们希望 k 等于一个列在一个波段内可以采用的所有可能的值组合。这将等同于身份匹配。但是这样,k 将是一个巨大的数字,在计算上是不可行的。举个例子:如果一个乐队有 5 行。现在,如果签名中的元素是 32 位整数,那么这种情况下的 k 将是(2 )⁵ ~ 1.4615016e+48。你可以看到这里有什么问题。通常 k 取 100 万左右。

其思想是,如果两个文档相似,那么它们将作为候选对出现在至少一个波段中。

选择 b & r

如果我们取 b 大,即更多数量的散列函数,那么我们减少 r,因为 b*r 是常数(签名矩阵中的行数)。直觉上,这意味着我们正在增加找到候选配对的可能性。这个案例相当于取了一个小 t(相似度阈值)

假设你的签名矩阵有 100 行。考虑两种情况:

b1 = 10 → r = 10

b2 = 20 → r = 5

在第二种情况下,两个文档在同一个桶中出现至少一次的可能性更大,因为它们有更多的机会(20 比 10)更少的签名元素被比较(5 比 10)。

更高的 b 意味着更低的相似性阈值(更高的假阳性),而更低的 b 意味着更高的相似性阈值(更高的假阴性)****

我们试着通过一个例子来理解这一点。

设置:

  • 100k 文档存储为长度为 100 的签名
  • 签名矩阵:100*100000
  • 签名的暴力比较将导致 100C2 比较= 50 亿(相当多!)
  • 让我们取 b = 20 → r = 5

相似度阈值(t) : 80%

我们希望 20 个波段中至少有一个波段的两个文档(D1 和 D2)具有 80%的相似性,在同一个桶中进行哈希运算。

P(D1 和 D2 在特定波段相同)= (0.8)⁵ = 0.328

P(D1 和 D2 在所有 20 个波段中不相似)=(1–0.328)^20 = 0.00035

这意味着在这种情况下,我们有大约 0.035%的机会出现 80%相似文档的假阴性。

我们还希望对于 20 个波段中的任何一个(阈值= 80%),具有 30%相似性的 2 个文档(D3 和 D4)不在同一个桶中被散列。

P(D3 和 D4 在特定波段中相同)= (0.3)⁵ = 0.00243

P(D3 和 D4 在 20 个波段中的至少一个波段中相似)= 1-(1–0.00243)^20 = 0.0474

这意味着在这种情况下,我们有大约 4.74%的机会在 30%的相似文档中出现误报。

所以我们可以看到,我们有一些假阳性和几个假阴性。这些比例将随着 b 和 r 选择而变化

我们在这里想要的是像下面这样的东西。如果我们有两个相似度大于阈值的文档,那么它们在至少一个波段中共享同一个桶的概率应该是 1,否则为 0。

最坏的情况是,如果我们有如下所示的签名矩阵中的 b =行数。

任何 b 和 r 的一般情况如下所示。

选择 b 和 r 以获得最佳的 S 曲线,即最小的假阴性和假阳性率

LSH 摘要

  • 调整 M,b,r 以获得几乎所有具有相似签名的文档对,但排除大多数没有相似签名的对
  • 在主存储器中检查候选对确实有相似的签名

结论

我希望你很好地理解这个强大的算法,以及它如何减少搜索时间。你可以想象 LSH 如何适用于几乎任何类型的数据,以及它在当今的大数据世界中有多大的相关性。

要阅读更多关于 LSH 的代码实现,请查看本文。https://santhoshhari.github.io/Locality-Sensitive-Hashing/

参考

  1. http://joyceho.github.io/cs584_s16/slides/lsh-11.pdf
  2. https://www.youtube.com/watch?v=96WOGPUgMfw
  3. **【https://eng.uber.com/lsh/ **
  4. https://medium . com/engineering-brainly/locality-sensitive-hashing-explained-304 EB 39291 E4
  5. http://www.mit.edu/~andoni/LSH/

理解逻辑回归

原文:https://towardsdatascience.com/understanding-logistic-regression-9b02c2aec102?source=collection_archive---------1-----------------------

逻辑回归是解决分类问题的基本和流行的算法之一。它被命名为“逻辑回归”,因为它的基本技术与线性回归完全相同。术语“逻辑”取自该分类方法中使用的逻辑函数

本博客旨在回答以下问题:

1.分类问题是什么?

2.为什么不用线性回归?

3.逻辑回归算法?

4.什么是决策边界?

5.如何检查模型性能?

今天,我们来一劳永逸地了解一下逻辑回归。我们开始吧,

什么是分类问题?

当自变量在本质上是连续的并且因变量是分类形式时,即在像正类和负类这样的类中,我们将该问题识别为分类问题。分类实例的实际例子是,将邮件分类为垃圾邮件或非垃圾邮件,将肿瘤分类为恶性或良性,并将交易分类为欺诈性或真实性。所有这些问题的答案都是分类形式的,即是或否。这就是为什么它们是两类分类问题。

[Image 1] (Image courtesy: My Photoshopped Collection)

虽然,有时我们会遇到两个以上的类,但这仍然是一个分类问题。这些类型的问题被称为多类分类问题。

为什么不用线性回归?

假设我们有肿瘤大小与其恶性程度的数据。由于这是一个分类问题,如果我们绘图,我们可以看到,所有的值将位于 01 。如果我们拟合最好的回归线,假设阈值为 0.5,我们可以做线相当合理的工作。

[Image 2] (Image courtesy: Andrew Ng provided image + Photoshopped)

我们可以确定 x 轴上的点,从该点开始,位于其左侧的所有值都被认为是负类,而位于其右侧的所有值都是正类。

[Image 3] (Image courtesy: Andrew Ng provided image + Photoshopped)

但是如果数据中有异常值呢?事情会变得相当混乱。例如,对于 0.5 的阈值,

[Image 4] (Image courtesy: Andrew Ng provided image + Photoshopped)

如果我们拟合最佳回归线,它仍然不足以决定我们可以区分阶级的任何点。它会把一些正面类的例子放到负面类里。绿色虚线(决策边界)将恶性肿瘤与良性肿瘤区分开来,但该线应该位于黄线处,黄线清楚地将阳性和阴性示例区分开来。因此,仅仅一个异常值就会扰乱整个线性回归预测。这就是逻辑回归发挥作用的地方。

逻辑回归算法

如前所述,为了处理异常值,逻辑回归使用 Sigmoid 函数。

解释逻辑回归可以从解释标准逻辑函数开始。逻辑函数是一个 Sigmoid 函数,它取 0 到 1 之间的任何实数值。它被定义为

而如果我们绘制它,图形会是 S 曲线,

[Image 5] (Image courtesy: https://openclassrooms.com/en/courses/6389626-train-a-supervised-machine-learning-model/6405876-understand-the-logistic-regression-algorithm)

让我们把 t 看作一元回归模型中的线性函数。

所以逻辑方程式会变成

现在,当逻辑回归模型遇到异常值时,它会处理它。

[Image 6] (Image courtesy: Andrew Ng provided image + Photoshopped)

但有时它会根据异常值的位置将其 y 轴向左或向右移动。

什么是决策边界?

决策边界有助于将概率分为正类和负类。

线性决策边界

[Image 7] (Image courtesy: Andrew Ng provided image + Photoshopped)

[Image 8] (Image courtesy: My Photoshopped Collection)

非线性决策边界

[Image 9] (Image courtesy: Andrew Ng provided image + Photoshopped)

[Image 10] (Image courtesy: My Photoshopped Collection)

如何检查绩效?

为了检查性能,我们可以使用混淆矩阵和 AUC - ROC 曲线。要知道它是什么,可以查看我关于混淆矩阵和 AUC - ROC 曲线的文章。

参考文献:

图片取自吴恩达球场并做了一些修改,以便于理解😁。

感谢阅读。

我希望我已经让你对什么是逻辑回归有了一些了解。如果你喜欢这篇文章,给这篇文章一些掌声会对你有所帮助👏。我随时欢迎你的问题和建议。你可以在脸书、推特、Linkedin 上分享这个,这样有需要的人可能会偶然发现这个。

您可以通过以下方式联系到我:

领英:https://www.linkedin.com/in/narkhedesarang/

推特:https://twitter.com/narkhede_sarang

github:https://github.com/TheSarang

用石灰理解模型预测

原文:https://towardsdatascience.com/understanding-model-predictions-with-lime-a582fdff3a3b?source=collection_archive---------1-----------------------

在我之前关于模型可解释性的帖子中,我概述了用于研究机器学习模型的常用技术。在这篇博文中,我将对石灰进行更详尽的解释。

LIME explaines of model predictions at the data sample level. It allows end-users to interpret these predictions and take actions based on them. Source

为什么理解可解释性方法是必要的?

如果您信任一种解释模型预测的技术,那么理解该技术的基本机制以及任何与之相关的潜在陷阱是非常重要的。可解释性技术不是防错的,如果对方法没有很好的理解,你很可能将你的假设建立在错误的基础上。

在下面这篇关于兰登森林重要性的博客文章中,做了一个类似但更彻底的调查。要素重要性通常用于确定哪些要素在模型预测中起重要作用。随机森林提供了一种现成的方法来确定数据集中最重要的要素,许多人依赖于这些要素的重要性,将它们解释为数据集的“基本事实解释”。

A decision or random forest consists of multiple decision trees. By investigating which features are used to construct the ‘best’ trees, it is possible to get an estimate of the feature importance. Source

作者研究了两个随机森林(RF)实现以及它们提供的特性重要性的标准度量。作者表明,与随机森林重要性相比,当变量强相关时,排列重要性提供了更稳健的估计。我强烈推荐阅读他们的博客文章,以全面了解这些发现。

石灰

LIME 是模型不可知的,这意味着它可以应用于任何机器学习模型。该技术试图通过干扰数据样本的输入和理解预测如何变化来理解模型。

LIME assumes a black box machine learning model and investigates the relationship between input and output, represented by the model.

特定于模型的方法旨在通过分析内部组件以及它们如何交互来理解黑模型机器学习模型。在深度学习模型中,例如,可以调查激活单元并将内部激活链接回输入。这需要对网络有透彻的了解,并且不能扩展到其他模型。

LIME 提供了本地模型的可解释性。LIME 通过调整特征值来修改单个数据样本,并观察对输出产生的影响。通常,这也与人类在观察模型输出时感兴趣的内容有关。最常见的问题可能是:为什么会做出这种预测,或者是哪些变量导致了这种预测?

其他模型可解释性技术仅从整个数据集的角度回答了上述问题。要素重要性在数据集层面上解释了哪些要素是重要的。它允许您验证假设以及模型是否过度适应噪声,但是很难诊断特定的模型预测。

LIME attempts to play the role of the ‘explainer’, explaining predictions for each data sample. Source

石灰背后的直觉

LIME 的一个关键要求是使用人类可以理解的可解释的输入表示。可解释表示的例子是例如 NLP 的弓形向量,或者计算机视觉的图像。另一方面,密集嵌入是不可解释的,应用石灰可能不会提高可解释性。

LIME 的输出是一个解释列表,反映了每个特征对数据样本预测的贡献。这提供了局部可解释性,并且还允许确定哪些特征变化将对预测产生最大影响。

An example of LIME applied to a classic classification problem. Source

一个解释是通过用一个可解释的模型局部地逼近底层模型而产生的。可解释的模型是例如具有强正则化的线性模型、决策树等。可解释的模型在原始实例的小扰动上被训练,并且应该仅提供良好的局部近似。“数据集”是通过例如向连续特征添加噪声、移除单词或隐藏图像的部分来创建的。通过仅局部地近似黑盒*(在数据样本的邻域中),任务被显著简化。*

潜在的陷阱

虽然酸橙的一般概念听起来很容易,但有几个潜在的缺点。

在当前的实现中,仅使用线性模型来近似局部行为。在某种程度上,当观察数据样本周围非常小的区域时,这种假设是正确的。然而,通过扩展这个区域,线性模型可能不足以解释原始模型的行为。对于那些需要复杂的、不可解释的模型的数据集,在局部区域会发生非线性。不能在这些场景中使用石灰是一个很大的缺陷。

A linear approximation of the local behaviour for two features is not a good representation and won’t capture the highly non-linear behaviour of the model.

其次,需要对数据执行的修改类型通常是特定于用例的。作者在他们的论文中给出了以下例子:
例如,预测棕褐色调图像复古的模型不能用超级像素的存在与否来解释。

通常,简单的扰动是不够的。理想情况下,扰动将由数据集中观察到的变化驱动。另一方面,手动控制扰动可能不是一个好主意,因为它很可能会在模型解释中引入偏差。

结论

LIME 是解释机器学习分类器(或模型)在做什么的一个很好的工具。它是模型不可知的,利用简单和可理解的想法,并且不需要很多努力来运行。和往常一样,即使使用 LIME,正确解释输出仍然很重要。

如果你对机器学习的可解释性有任何问题,我很乐意在评论中阅读。如果你想收到我博客上的更新,请在 Medium 或 Twitter 上关注我!

理解神经网络:什么,如何和为什么?

原文:https://towardsdatascience.com/understanding-neural-networks-what-how-and-why-18ec703ebd31?source=collection_archive---------1-----------------------

解开黑盒

N 就称为深度学习的机器学习子领域而言,神经网络是最强大和最广泛使用的算法之一。乍一看,神经网络似乎是一个黑盒;输入层将数据输入到“隐藏层中,变戏法之后,我们可以看到由输出层提供的信息。然而,理解隐藏层在做什么是神经网络实现和优化的关键步骤。

在我们理解神经网络的道路上,我们将回答三个问题:什么如何为什么

什么是神经网络?

我们将要考虑的神经网络被严格地称为人工神经网络,顾名思义,它是基于科学对人脑结构和功能的了解。

简而言之,神经网络被定义为一种计算系统,它由许多简单但高度互连的元素或节点组成,这些元素或节点被称为“神经元”,它们被组织成使用对外部输入的动态状态响应来处理信息的层。正如我们将在后面解释的那样,这种算法在寻找太复杂而无法手动提取和教会机器识别的模式方面非常有用。在这种结构的背景下,模式通过输入 被引入神经网络,该层对于输入数据中存在的每个分量具有一个神经元,并且被传送到网络中存在的一个或多个隐藏层;被称为“隐藏”仅仅是因为它们不构成输入或输出层。在隐藏层中,所有的处理实际上是通过一个连接系统发生的,该连接系统的特征是**(通常称为 W 和 b)* : 接收输入,神经元计算加权和,并根据结果加上偏差和预设的激活函数(最常见的是 sigmoid,ψ 即使它几乎不再被使用,并且有更好的像 ReLu ) 一样,它决定它是否应该被‘发射’或激活。 然后,神经元将信息向下游传输到其他连接的神经元,这个过程称为“前向传递”。在这个过程的最后,最后一个隐藏层被链接到输出层,它有一个神经元用于每个可能的期望输出。*

Basic structure of a 2-layer Neural Network. Wi: Weight of the corresponding connection. Note: The input layer is not included when counting the number of layers present in the network.

神经网络是如何工作的?

现在我们对神经网络的基本结构有了一个概念,我们将继续解释它是如何工作的。为了做到这一点,我们需要解释我们可以在网络中包含的不同类型的神经元。

我们要解释的第一类神经元是感知器* 。尽管今天它的使用已经衰退,但理解它们如何工作将为我们提供更多现代神经元如何运作的线索。*

感知器使用函数通过将二进制变量的向量映射到单个二进制输出来学习二进制分类器,并且它也可以用于监督学习。在这种情况下,感知器遵循以下步骤:

  1. 将所有的输入乘以它们的权重 w ,实数表示对应的输入对输出有多重要,
  2. 将它们加在一起称为 加权和:∑ wj xj
  3. 应用 激活函数 ,换句话说,确定加权和是否大于一个阈值,其中-阈值相当于偏差,并赋值 1 或更少,赋值 0 为输出**

我们也可以用下面的术语来写感知器函数:

Notes: b is the bias and is equivalent to -threshold, w.x is the dot product of w, a vector which component is the weights, and x, a vector consisting of the inputs.

这种算法的最大优点之一是我们可以改变权重和偏差来获得不同的决策模型。我们可以赋予这些输入更多的权重,这样如果它们是积极的,它将有利于我们期望的输出。此外,因为偏差可以理解为输出 1 的难易程度的度量,所以如果我们想使期望的输出更可能或更不可能发生,我们可以降低或提高它的值。如果我们注意公式,我们可以观察到一个大的正偏差会使输出 1 变得非常容易;然而,非常负的偏差将使输出 1 的任务变得非常不可能。

因此,感知器可以分析不同的证据或数据,并根据设定的偏好做出决定。事实上,有可能创建更复杂的网络,包括更多层的感知器,其中每一层都采用前一层的输出并对其进行加权,从而做出越来越复杂的决策。

**什么等一下:如果感知器可以很好地做出复杂的决定,为什么我们需要其他类型的神经元?包含感知器的网络的缺点之一是,即使只有一个感知器,权重或偏差的微小变化也会严重改变我们的输出,从 0 变为 1,反之亦然。我们真正想要的是能够通过引入权重或偏差的小修改来逐渐改变我们网络的行为。这就是一种更现代的神经元类型派上用场的地方(如今它的用途已被其他类型取代,如 Tanh 和最近的 ReLu): ***乙状结肠神经元。*sigmoid 神经元和感知器的主要区别在于,输入和输出可以是 0 到 1 之间的任何连续值。考虑到权重 w 和偏差 b,将 sigmoid 函数 应用于输入后,获得输出。为了更好地形象化,我们可以写下:

因此,输出的公式是:

如果我们对这个函数进行数学分析,我们可以制作函数 σ 的图表,如下所示,并得出结论:当 z 大且为正时,函数达到其最大渐近值 1;然而,如果 z 很大并且是负的,则函数达到其最小渐近值 0。这就是 sigmoid 函数变得非常有趣的地方,因为在 z 值适中的情况下,函数呈现出平滑且接近线性的形状。在此区间内,权重(δwj)或偏置(δbj)的微小变化将导致输出的微小变化;我们所期望的行为是对感知机的改进。

Shape of the sigmoid function used in sigmoid neurons to obtain small changes in the output making small changes in weights or bias. z=-∑wj xj-b

我们知道,函数的导数是值 y 相对于变量 x 的变化率的度量。在这种情况下,变量 y 是我们的输出,变量 x 是权重和偏差的函数。我们可以利用这一点,利用导数,特别是偏导数(相对于 w 和 b)来计算输出的变化。你可以阅读这篇文章来进行计算,但是在 sigmoid 函数的情况下,导数将被简化为计算:f(z)*(1-f(z))。

这是一个简单的代码,可用于模拟 sigmoid 函数:

我们刚刚解释了我们网络中每个神经元的功能,但是现在,我们可以检查它的其余部分是如何工作的。一种神经网络,其中一层的输出被用作下一层的输入,这种神经网络被称为前馈,特别是因为它不涉及环路,信息只向前传递,从不向后传递。

假设我们有一个训练集,我们想使用一个 3 层神经网络,其中我们也使用我们上面看到的 sigmoid 神经元来预测某个特征。以我们对神经网络结构的解释为例,权重和偏差需要首先分配给一层和下一层神经元之间的连接。通常,偏差和权重都是在突触矩阵中随机初始化的。如果我们用 python 对神经网络进行编码,我们可以使用 Numpy 函数np.random.random 生成一个高斯分布(其中均值等于 0,标准差等于 1 ),以便有一个开始学习的地方。

之后,我们将构建神经网络,从 前馈 步骤开始计算预测输出;换句话说,我们只需要构建网络中涉及的不同层:

  • layer0是输入层;我们的训练集读作一个矩阵(我们可以称之为 X)
  • layer1是通过应用激活函数 a’=σ(w . X+b)获得的,在我们的例子中,执行输入layer0和突触矩阵syn0之间的点乘
  • layer2layer1与其突触syn1点乘得到的输出层

我们还需要迭代训练集,让网络学习(我们将在后面看到)。为了做到这一点,我们将为 循环添加一个**

到目前为止,我们已经创建了神经网络的基本结构:不同的层,神经元之间连接的权重和偏差,以及 sigmoid 函数。但是这些都不能解释神经网络如何在预测数据集中的模式方面做得如此好。这是我们的最后一个问题。

为什么神经网络能够学习?

机器学习算法的主要优势在于它们每次在预测输出时都能够学习和改进。但这意味着他们可以学习吗?在神经网络的背景下,它意味着定义神经元之间连接的权重和偏差变得更加精确;最终,选择权重和偏差,使得网络的输出接近所有训练输入的真实值 y(x)。

那么,我们如何量化我们的预测与我们的真实值有多远,以便我们知道我们是否需要继续寻找更精确的参数?为此,我们需要计算一个误差,或者换句话说,定义一个 成本函数 (成本函数不是预测我们的网络的正确输出的误差;换句话说,就是预期输出和预测输出之间的差异)。在神经网络中,最常用的是二次成本函数,也称为均方误差,由以下公式定义:

w and b referred to all the weights and biases in the network, respectively. n is the total number of training inputs. a is the outputs when x is the input. ∑ is the sum over all training inputs.

该函数优于线性误差,因为在神经网络中,权重和偏差的微小变化不会产生正确输出数量的任何变化;因此,使用二次函数(其中大的差异对成本函数的影响大于小的差异)有助于找出如何修改这些参数。

另一方面,我们可以看到,对于所有训练输入,随着输出更接近真实值 y ,我们的成本函数变得更小。我们算法的主要目标是通过找到一组权重和偏差使其尽可能小来最小化这个成本函数。而实现这个目标的主要工具就是一种叫做 梯度下降 的算法。

那么,我们应该回答的下一个问题是,我们如何使成本函数最小化。从微积分中,我们知道一个函数可以有全局最大值和/或最小值,也就是函数达到它所能有的最大值或最小值的地方。我们也知道,得到那个点的一个方法是计算导数。然而,当我们有一个具有两个变量的函数时,很容易计算,但是在神经网络的情况下,它们包括许多变量,使得这种计算很难进行。

相反,让我们来看看下图中的随机函数:

我们可以看到这个函数有一个全局最小值。我们可以,如前所述,计算导数,来计算最小值在哪里,或者我们可以采取另一种方法。我们可以从一个随机点开始,尝试在箭头方向上做一个小的移动,从数学上来说,我们可以在 x 方向上移动δx,在 y 方向上移动δy,然后计算我们的函数δc 的变化,因为一个方向上的变化率是一个函数的导数,我们可以将函数的变化表示为:

这里,我们将从函数梯度的微积分中得到定义:

Gradient of a function: Vector with partial derivatives

现在,我们可以将函数中的变化重写为:

Gradient of C relates the change in function C to changes in (x,y)

现在,我们可以看到,当我们选择参数的某个变化时,成本函数会发生什么。我们选择向任何方向移动的量被称为学习速率,它定义了我们向全局最小值移动的速度。如果我们选择一个非常小的数字,我们将需要进行太多的移动来达到这一点;但是,如果我们选择了一个非常大的数字,我们就有可能过了这个点,永远也到不了。因此,挑战在于选择足够小的学习率。选择学习率后,我们可以更新我们的权重和偏差,并再次移动;我们在每次迭代中重复的过程。

因此,简而言之,梯度下降法的工作原理是重复计算梯度∇C,然后更新权重和偏差,并试图找到正确的值,从而最小化函数的成本。这就是神经网络学习的方式。

**有时,计算梯度可能非常复杂。然而,有一种叫做随机梯度下降的方法可以加速这种计算。这通过计算随机选择的训练输入的小样本的梯度来估计梯度∇C。然后,对这些小样本进行平均,以获得对真实梯度的良好估计,加速梯度下降,从而更快地学习。

**但是等一下?我们如何计算成本函数的梯度?这里是另一个算法进入的地方: 反向传播 。该算法的目标是计算成本函数相对于任何权重 w 和任何偏差 b 的偏导数;在实践中,这意味着从最后一层开始计算误差向量,然后将其传播回来以更新权重和偏差。我们需要返回的原因是,成本是我们网络输出的函数。我们需要计算几个计算和误差,其公式由反向传播算法给出:1)输出误差(δL)与梯度(▽C)对激活函数(σ′(z)的导数的逐元素(⦿)乘积相关, 2)一层的误差(ẟl ),根据与权重的转置矩阵(Wl+1)乘以下一层的误差(ẟl+1)和激活函数的导数的逐元素乘法相关的下一层的误差,3)成本相对于网络中任何偏差的变化率:这意味着 c 相对于任何偏差(∂C/∂bj)的偏导数等于误差ẟl, 4)成本相对于网络中任何权重的变化率:意味着 c 相对于任何权重的偏导数(∂C/∂wj)等于误差(ẟl)乘以神经元输入的激活。 这最后两个计算构成了成本函数的梯度。在这里,我们可以观察公式。

Four essential formulas given by backpropagation algorithms that are useful to implement neural networks

反向传播算法只为一个训练示例计算成本函数的梯度。因此,我们需要将反向传播与学习算法相结合,例如随机梯度下降,以便计算所有训练集的梯度。

现在,我们如何在 python 中将它应用到我们的神经网络中呢?。在这里,我们可以看到一步一步的计算:

让我们把一切都包起来…

现在,我们可以把所有这些公式和概念放在一个算法中,看看我们如何实现它:

  • 输入:我们输入一组训练样本,我们设置输入层对应的激活 a
  • 前馈:对于每一层,我们计算函数 z = w . a + b,即 a = σ(z)
  • 输出误差:我们使用上面引用的公式#1 计算输出误差。
  • 反向传播:现在我们反向传播误差;对于每一层,我们计算上面引用的公式#2。
  • 输出:我们使用公式#3 和#4 计算任何重量和偏差的梯度下降。

当然,神经网络可以有更多的概念、实现和改进,在过去的几年里,神经网络可以变得越来越广泛地使用和强大。但我希望这些信息能给你一点提示,告诉你什么是神经网络,它是如何工作的,以及如何使用梯度下降和反向传播来学习。

参考文献:

  • 神经网络和深度学习。迈克尔·尼尔森
  • 4 分钟构建一个神经网络。西拉伊·拉瓦尔

理解数字总和

原文:https://towardsdatascience.com/understanding-numpy-sum-1587eec69527?source=collection_archive---------2-----------------------

如果你不清楚 NumPy 是什么或者它是如何工作的,请先看看这篇文章。

[## Python 数据科学的第一步— NumPy

我读到过学习的最好方法是写博客。因为我学习数据科学已经有一段时间了…

towardsdatascience.com](/first-step-in-data-science-with-python-numpy-5e99d6821953)

在那篇介绍 NumPy 的文章中,我在 NumPy 数组上做了一个按行添加的操作。然后,帖子的一位读者回应说,我所做的是列方向的添加,而不是行方向的添加。事实上,当我学习它的时候,我同样觉得它不应该这样工作。这与它应该如何工作正好相反。所以,我看了一下文件,但是上面说

我们可以对数组的每一行求和,在这种情况下,我们沿着列或轴 1 进行操作

没用。我还是很困惑。我继续寻找,然后我发现了Aerin Kim的这篇文章,它改变了我看待 NumPy 数组求和的方式。所以以她的帖子为基础,这是我对 NumPy 数组和的看法。

如果你不清楚问题是什么,让我们正式定义它。

问题

我们有一个 5x5 NumPy 阵列,如下所示

a = array([[ 12., -22., -20., -19.,  -3.],
       [-23.,  21., -17., -11.,  -1.],
       [ -4.,  -5.,  16.,  -9., -14.],
       [-10.,  -6., -18.,  15.,  -8.],
       [-25.,  -2., -13.,  -7.,  24.]])

我们在上面的数组中使用

sum_matrix = a.sum(axis=1)

我们最终在sum_matrix中得到下面的数组

array([-52., -31., -16., -27., -23.])

如果axis=1指的是逐行相加,这似乎是正确的。没问题。除此之外,axis=0实际上应该是指行而不是axis=1。当我们看到 NumPy 数组是如何形成的时,这一点会更清楚。让我们取另一个 NumPy 数组。

arr = np.arange(12).reshape(4,3)

我们在arr得到的是

array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])

很明显,它是 4 行 3 列。因此,第一个轴axis=0应该表示行,第二个轴axis=1应该表示列。

如果你观察熊猫,这一点也会得到证实。让我们举一个数据帧的例子。

df = pd.DataFrame(data=np.arange(12).reshape(4,3),index=['row1','row2','row3','row4'],columns=['col1','col2','col3'])

df看起来是这样的

如果你现在做df.drop(labels=[‘row1’], axis=0),你会得到的回报是

如果你做了df.drop(labels=[‘col2’], axis=1),你会得到

显然,axis=0表示行,axis=1表示列。那么,为什么 NumPy sum 的做法不同呢?

解决办法

引用 Aerin Kim 在她的帖子中的话,她写道

的方式来理解 numpy 的 求和就是将 折叠 指定轴。所以当它折叠轴 0(行)时,它就变成了一行和一列的总和。

让我们看看这是什么意思。现在,它在 2D 可能会变得有点混乱,所以让我们首先在一个更高的维度上理解这一点,然后我们将逐步进入 2D;就像她在岗位上做的一样。

所以,我们来取一个形状为(4,3,2)的 3D 数组。

three_d_array = np.arange(24).reshape(4,3,2)

three_d_array现在变成等于

array([[[ 0,  1],
        [ 2,  3],
        [ 4,  5]],

       [[ 6,  7],
        [ 8,  9],
        [10, 11]],

       [[12, 13],
        [14, 15],
        [16, 17]],

       [[18, 19],
        [20, 21],
        [22, 23]]])

现在,让我们看看沿第一轴的元素,axis=0。沿着axis=0我们有 4 个元素。这些可以用three_d_array[0]three_d_array[1]three_d_array[2]three_d_array[3]查看

每一个都是形状为(3,2)的 2D 阵列。现在,如果我们把上面所有的 2D 阵列加起来,

three_d_array[0]+three_d_array[1]+three_d_array[2]+three_d_array[3]

在逐个元素相加之后,我们得到一个 3x2 的数组,如下所示:

array([[36, 40],
       [44, 48],
       [52, 56]])

这正是我们做three_d_array.sum(axis=0)时得到的结果。我们将带走axis=0的所有元素。然后我们一个元素一个元素地求和。最初,我们有一个 3D 形状数组(4,3,2)。求和之后,我们得到了一个形状为(3,2)的 2D 数组。于是,我们丢掉了第一轴4,保留了剩下的两根(3,2)。这可能就是 Kim 所说的“它会折叠轴”的意思。

现在,我们来看看axis=1。这次我们保持第一个轴不变,沿着第二个轴求和,axis=1。这里,我们有 12 个元素,从第一个轴 0 开始,每个轴上有 3 个元素。

加上所有这些,我们回到

类似地,我们为剩下的三个添加

将所有 4 个组合起来,我们得到一个如下所示的数组:

array([[ 6,  9],
       [24, 27],
       [42, 45],
       [60, 63]])

这正是我们做three_d_array.sum(axis=1)时得到的;沿着axis=1逐个元素执行加法。同样,和矩阵的形状是(4,2),这表明我们从原来的(4,3,2)中去掉了第二轴3

对于最后的轴 2,我们做同样的事情。这次我们有所有 24 个元素,我们通过保持前两个轴不变来沿着axis=2求和。这里,我们只看前 6 个元素。

这给了我们一行 sum 数组。我们对剩下的部分做同样的事情,最后我们得到了下面的数组,

array([[ 1,  5,  9],
       [13, 17, 21],
       [25, 29, 33],
       [37, 41, 45]])

这正是我们在three_d_array.sum(axis=2)上得到的。同样,求和数组的形状是(4,3),这里我们失去了最后一个轴2

最后,回到最初的问题

我们的阵列是

a = array([[ 12., -22., -20., -19.,  -3.],
       [-23.,  21., -17., -11.,  -1.],
       [ -4.,  -5.,  16.,  -9., -14.],
       [-10.,  -6., -18.,  15.,  -8.],
       [-25.,  -2., -13.,  -7.,  24.]])

现在,当我们沿着axis=0移动元素时,我们得到

一个元素一个元素地添加这些元素给我们

这相当于a.sum(axis=0)

类似地,当我们沿着axis=1提取元素时,

现在,如果我们分别对所有的a[0]s、所有的a[1]s、所有的a[2]s、所有的a[3]s和所有的a[4]s求和,我们得到

这就是我们用a.sum(axis=1)得到的。如果我们检查形状,我们得到(5,)。如果我们只看 2D 数组,这可能不清楚,但正如我们前面看到的,这只是折叠轴 1 并返回剩余轴 0 的形状。

现在,如果我们回头看看文档中的语句,“我们可以对数组的每一行求和,在这种情况下,我们沿着列或轴 1 操作”,我认为这更有意义。因此,尽管我们计算了每行的总和,但从技术上讲,这是一个列相加而不是行相加,因为 axis=0 是行,axis=1 是列。

为什么 NumPy 不像熊猫那样直截了当?嗯,老实说,我也不知道答案。但这就是饼干碎裂的方式。

理解神经网络中的目标函数。

原文:https://towardsdatascience.com/understanding-objective-functions-in-neural-networks-d217cb068138?source=collection_archive---------1-----------------------

这篇博文的目标读者是有机器学习经验的人,他们希望对用于训练神经网络的不同目标函数有更好的直觉。

介绍

我决定写这篇博客的原因有三点:

  • 博客帖子经常解释优化方法,如随机梯度下降或其变体,但很少花时间解释如何为神经网络构建目标函数。为什么均方误差(MSE)和交叉熵对数损失被用作 resp 的目标函数。回归分类?为什么添加一个正则化术语有意义?总的想法是,通过研究目标函数,人们可以了解为什么神经网络以它们的方式工作,或者为什么它们在其他情况下失败。

Cross entropy log loss between the ground truth p and network output q, used in classification problems.

Mean squared error between the ground truth y and network output y_tilde, used in regression problems.

  • 神经网络以提供糟糕的概率估计而闻名,并且它们受到反面例子的困扰。简而言之:神经网络往往高度自信,即使它们是错误的。当它们部署在现实生活场景中时(例如自动驾驶汽车),这可能是一个问题。自动驾驶汽车在 90 英里/小时的速度下做决定时应该是确定的。如果我们部署深度学习管道,我们应该知道它们的优势和劣势。
  • 我一直想知道神经网络如何从概率的角度进行解释,以及它们如何适应更广泛的机器学习模型框架。人们倾向于用概率来谈论网络输出。神经网络的概率解释和它们的目标函数之间有联系吗?

这篇博文的主要灵感来自于我和我的朋友布莱恩·特里普在剑桥大学计算和生物学习实验室所做的关于贝叶斯神经网络的工作。我强烈推荐任何人阅读布莱恩关于神经网络中变分推理的论文。

免责声明:在计算和生物学习实验室,贝叶斯机器学习技术被毫无歉意地作为未来的方向教授。因此,请注意这篇博文中的潜在偏见(😉).

监督机器学习

在有监督的机器学习问题中,我们经常考虑观察对( xy )的数据集 D ,并且我们尝试对以下分布建模:

例如,在图像分类中,x 代表图像,y 代表相应的图像标签。p(y|x,θ)表示给定图像 x 和由参数θ定义的模型的标签 y 的概率。

遵循这种方法的模型被称为判别模型。在判别或条件模型中,定义条件概率分布函数 p(y|x,θ)的参数是从训练数据中推断出来的。

基于观察数据 x(输入数据或特征值),模型输出概率分布,然后用于预测 y (类别或真实值)。不同的机器学习模型需要估计不同的参数。线性模型(例如,由一组等于特征数量的权重定义的逻辑回归)和非线性模型(例如,由每层的一组权重定义的神经网络)都可以用来近似条件概率分布。

对于典型的分类问题,这组可学习参数θ用于定义不同标签上从 x 到分类分布的映射。判别分类模型产生 N 个概率作为输出,N 等于类别的数量。每个 x 属于单个类别,但是模型不确定性通过输出类别上的分布来反映。通常,在做出决策时,会选择概率最大的类别。

In image classification, the network outputs a categorical distribution over image classes. The image above depicts the top 5 classes (classes with highest probability) for a test image.

注意,判别回归模型通常只输出一个预测值,而不是所有真实值的分布。这不同于鉴别分类模型,在鉴别分类模型中提供了所有可能类别的分布。这是否意味着歧视性模型在回归中会土崩瓦解?模型的输出不应该告诉我们哪些回归值比其他值更有可能吗?

虽然判别回归模型的单一输出是误导性的,但回归模型的输出实际上与众所周知的概率分布,即高斯分布有关。事实证明,判别回归模型的输出代表高斯分布的均值(高斯分布完全由均值和标准差定义)。有了这些信息,你就可以确定给定输入 x 的每个实值的可能性。

通常只对该分布的平均值进行建模,高斯的标准偏差要么不进行建模,要么被选择为在所有 x 上保持不变。在判别回归模型中,θ因此定义了从 x 到高斯均值的映射,y 从该高斯均值被采样。做决定时,几乎总是选择平均值。输出给定 x 的平均值和标准差的模型更能提供信息,因为该模型能够表达不确定的 x(通过增加标准差)。

A model needs to be uncertain in regions where there is no training data and certain in regions where it has training data. Such a model is displayed in the image above, from Yarin Gal’s blog post.

其他概率模型(如高斯过程)在建模回归问题中的不确定性方面做得更好,而判别回归模型在同时建模均值和标准差时往往过于自信。

高斯过程能够通过明确地模拟标准偏差来量化不确定性。高斯过程的唯一缺点是它们不能很好地适应大型数据集。在下图中,您可以看到 GP 模型在包含大量数据的区域周围具有较小的置信区间(由标准差确定)。在数据点很少的区域,置信区间明显变大。

A Gaussian Process model is certain at the data points, but uncertain at other places (image taken from Sklearn)

在训练数据集上训练判别模型,以便学习代表类或真实值的数据中的属性。如果模型能够将高概率分配给正确的样本类或接近测试数据集中真实值的平均值,则该模型表现良好。

与神经网络连接

当神经网络被训练用于分类或回归任务时,使用神经网络对前述分布(分类和高斯)的参数进行建模。

当我们试图确定神经网络*的参数 θ 的最大似然估计(MLE)时,这变得很清楚。*MLE 对应于找到使训练数据的似然性(或等效对数似然性)最大化的参数 θ 。更具体地,下面的表达式被最大化:

p(Y | X,θ)表示当用模型确定时,训练数据中真实标签的概率。如果 p(Y | X,θ)更接近 1,这意味着模型能够确定训练集中的正确标签/均值。给定训练数据( XY )由 N 个观察对组成,训练数据的可能性可以被重写为对数概率的和。

在分类和回归的情况下,p( y | x,θ ),单个对(x,y)的后验概率,可以重写为分类和高斯分布。在优化神经网络的情况下,目标是以这样的方式移动参数,即对于一组输入 X ,在输出(回归值或类)给出概率分布 Y 的正确参数。这通常通过梯度下降或其变体来实现。为了获得最大似然估计,目标是相对于真实输出优化模型输出:

  • 最大化分类分布的对数对应于最小化近似分布和真实分布之间的交叉熵。
  • 最大化高斯分布的对数对应于最小化近似平均值和真实平均值之间的均方误差。

因此,先前图像中的表达式可以被重写,并且分别导致交叉熵损失和均方误差,这是用于分类回归的神经网络的目标函数。

与更传统的概率模型相比,神经网络学习从输入到概率或均值的非线性函数很难解释。虽然这是神经网络的一个显著缺点,但神经网络能够建模的复杂函数的广度也带来了显著的优势。基于本节中的推导,很明显,在确定参数的 MLE 时出现的神经网络的目标函数可以用概率来解释。

神经网络的一个有趣的解释是它们与广义线性模型(线性回归、逻辑回归等)的关系。神经网络不是采用特征的线性组合(如 GLM 的方法),而是产生高度非线性的特征组合。

最大后验概率

但是,如果神经网络可以被解释为概率模型,为什么它们提供糟糕的概率估计,并遭受对立的例子?为什么他们需要这么多数据?

我喜欢把不同的模型(逻辑回归、神经网络……)看作是在不同的搜索空间中寻找好的函数逼近器。虽然拥有一个非常大的搜索空间意味着在建模后验概率时有很大的灵活性,但这也是有代价的。例如,神经网络被证明是通用函数逼近器。这意味着只要有足够的参数,它们就可以逼近任何函数(太棒了!).然而,为了确保函数在整个数据空间中得到很好的校准,需要指数级的大数据集(昂贵!).

重要的是要知道一个标准的神经网络通常使用最大似然优化。使用 MLE 的优化倾向于过度拟合训练数据,并且需要大量数据来获得适当的结果。机器学习的目标不是找到一个能很好地解释训练数据的模型。您宁愿尝试找到一个模型,该模型能够很好地概括看不见的数据,并且不确定数据是否与训练数据显著不同。

使用最大后验概率(MAP)方法是一种有效的替代方法,当概率模型遭受过拟合时,通常会探索这种方法。那么在神经网络的上下文中,MAP 对应于什么呢?它对目标函数有什么影响?

类似于 MLE,MAP 也可以被重写为神经网络环境中的目标函数。本质上,使用 MAP,您可以在假定 *θ 😗 的先验分布的同时,最大化给定数据的一组参数 θ 的概率

使用 MLE,只考虑公式的第一个元素(模型解释训练数据的能力)。对于 MAP,为了减少过拟合,模型满足先验假设(T4θ与先验的拟合程度)也很重要。

将平均值为 0 的高斯先验放在 θ 上对应于添加到目标的 L2 正则化(确保许多小权重),而将拉普拉斯先验放在 θ 上对应于添加到目标的 L1 正则化(确保许多值为 0 的权重)。

L1 regularisation on the left and L2 regularisation on the right.

完全贝叶斯方法

在 MLE 和 MAP 的情况下,使用单个模型(具有单组参数)。尤其是对于复杂的数据,例如图像,数据空间中的某些区域很可能没有被很好地覆盖。这些区域中模型的输出取决于模型和训练过程的随机初始化,导致对数据空间的未覆盖段中的点的概率估计较差。

尽管 MAP 确保模型不会在这些区域过度拟合,但它仍然会导致模型过于自信。在完全贝叶斯方法中,这通过在多个模型上平均来解决,从而产生更好的不确定性估计。目标不是单一的一组参数,而是对参数的分布进行建模。如果所有模型(不同的参数设置)在未覆盖的区域提供不同的估计,这表明该区域有很大的不确定性。通过对这些模型进行平均,最终结果是一个在这些区域不确定的模型。这正是我们想要的!

在下一篇博文中,我将讨论贝叶斯神经网络,以及它们如何试图解决传统神经网络的上述问题。贝叶斯神经网络(BNN 的)仍然是一项积极的研究工作,在训练它们时没有明确的赢家方法。

我强烈推荐 Yarin Gal 关于深度学习中的不确定性的博文!

PCA 和自动编码器:人人都能理解的算法

原文:https://towardsdatascience.com/understanding-pca-autoencoders-algorithms-everyone-can-understand-28ee89b570e2?source=collection_archive---------5-----------------------

本文的主要重点是为主成分分析(PCA)和 Autoencoder 数据转换技术提供直觉。我不打算深入研究支撑这些模型的数学理论,因为已经有太多的资源可用了。

Source: FK Films

简介:

自动编码器通过组合数据最重要的特征,将它们输入的数据映射到一个较低的维度空间。他们将原始数据编码成更紧凑的表示,并决定如何组合数据,因此在 Autoencoder 中有了 auto 。这些编码特征通常被称为潜在变量。

有几个原因可以说明这样做是有用的:

1.降维可以减少训练时间

2.使用潜在特征表示可以提高模型性能

像机器学习中的许多概念一样,自动编码器看起来很深奥。如果你不熟悉潜在变量,潜在变量本质上是一些数据的隐含特征。这是一个无法直接观察或测量的变量。例如,幸福是一个潜在的变量。我们必须使用类似问卷调查的方法来推断一个人的幸福程度。

像自动编码器模型一样,主成分分析(PCA)也被广泛用作降维技术。但是,PCA 算法映射输入数据的方式与自动编码器不同。

直觉:

假设你有一套很棒的跑车乐高玩具,想送给你的朋友作为生日礼物,但是你的盒子不够大,装不下所有的乐高玩具。你决定打包最重要的乐高零件——对汽车制造贡献最大的零件,而不是根本不送。所以,你扔掉一些琐碎的零件,如门把手和挡风玻璃雨刷,打包一些零件,如车轮和框架。然后,你把盒子寄给你的朋友。收到包裹后,你的朋友对没有说明的各种乐高积木感到困惑。尽管如此,他们还是组装了该套件,并且能够识别出这是一辆可驾驶的车辆。可能是沙滩车、赛车或轿车——他们不知道。

上面的类比是有损数据压缩算法的一个例子。数据的质量没有完全保持。这是一个有损算法,因为一些原始数据(即乐高积木)已经丢失。虽然使用 PCA &自动编码器进行维数缩减是有损耗的,但是这个例子并没有准确地描述这些算法——它描述了一个特征选择算法。特征选择算法丢弃数据的一些特征并保留显著特征。它们保留的特征通常是出于统计原因而选择的,例如属性和目标标签之间的相关性。

主成分分析:

假设一年过去了,你朋友的生日又快到了。你决定再给他们买一套乐高玩具汽车,因为他们去年告诉你他们有多爱他们的礼物。你也犯了一个大错,买了一个太小的盒子。这一次,你认为你可以更好地利用乐高,将它们系统地切割成更小的块。乐高积木的粒度更细,可以让你比上次装得更多。以前,收音机天线太高,放不进盒子里,但现在你把它切成三份,包括三份中的两份。当你的朋友收到邮寄的礼物时,他们会把某些零件粘在一起组装成汽车。他们能够将扰流器和一些轮毂盖粘合在一起,因此汽车更容易识别。接下来,我们将探索这个类比背后的数学概念。

LEGO klodser©2015 LEGO/Palle Peter SkovP 1

阐述:

PCA 的工作原理是将输入数据投影到数据协方差矩阵的特征向量上。协方差矩阵量化了数据的方差以及每个变量相对于另一个变量的变化程度。特征向量是通过线性变换保持其跨度的简单向量;也就是说,它们在变换前后指向相同的方向。协方差矩阵将原始基向量转换为每个变量之间的协方差方向。更简单地说,特征向量允许我们重新构建原始数据的方向,以便从不同的角度查看它,而无需实际转换数据。当我们将数据投影到这些向量上时,我们实质上是在提取每个变量中导致最大方差的分量。然后,我们可以使用协方差矩阵的特征值来选择主轴,因为它们反映了相应特征向量方向上的方差的大小。

Original Data (left) 1st Principal Component & Data (right)

这些投影产生一个新的空间,其中每个基向量包含最大的方差(即,在具有最大特征值的特征向量上的投影具有最大的方差,在第二特征向量上的投影具有第二大的方差,等等)。).这些新的基向量被称为主分量。我们希望主成分朝着最大方差的方向,因为属性值的方差越大,预测能力越强。例如,假设您试图预测一辆汽车的价格,给定两个属性:颜色和品牌。假设所有的车颜色都一样,但是其中有很多品牌。在这个例子中,根据颜色猜测汽车的价格是不可能的,因为颜色是一个零方差的特性。然而,如果我们考虑一个有更多变化的特征——品牌——我们将能够得出更好的价格估计,因为奥迪和法拉利的价格往往高于本田和丰田。PCA 产生的主要成分是输入变量的线性组合,就像胶合的乐高积木是原件的线性组合一样。这些主成分的线性性质也允许我们解释转换后的数据。

Data projected onto 1st principal component (Source: Author)

PCA 优点:

  • 降低维度
  • 可解释的
  • 快速运行时间

PCA 缺点:

  • 不能学习非线性特征表示

自动编码器:

Autoencoder Architecture

自动编码器的事情变得有点奇怪。你不再只是切割积木,而是开始融化、拉长和弯曲整个乐高积木,这样最终的积木代表了汽车最重要的特征,同时又符合盒子的限制。这样做不仅可以让你在盒子里放入更多的乐高积木,还可以让你定制积木。这很好,但是当包裹到达时,你的伙伴不知道如何处理它。对他们来说,它只是看起来像一堆随机操纵的乐高积木。事实上,这些零件是如此的不同,以至于你需要对几辆车重复这个过程无数次,以一种系统的方式将原始零件转化为可以由你的朋友组装到汽车上的零件。

阐述:

希望上面的类比有助于理解自动编码器如何类似于 PCA。在自动编码器的环境中,你是编码器,你的朋友是解码器。你的工作是以一种解码器可以解释的方式转换数据,然后以最小的误差重建。

自动编码器只是一个重新设计的前馈神经网络。我不打算在这里深究本质细节,但可以随意查看 Piotr Skalski 的伟大文章或深度学习书籍以获得对神经网络更全面的了解。

尽管它们能够学习复杂的特征表示,但自动编码器最大的缺陷在于它们的可解释性。就像你的朋友收到扭曲的乐高玩具时毫无头绪一样,我们也不可能想象和理解非视觉数据的潜在特征。接下来,我们将研究稀疏自动编码器。

自动编码器优点:

  • 能够学习非线性特征表示
  • 降低维度

自动编码器缺点:

  • 训练的计算成本很高
  • 无法解释的
  • 更复杂
  • 倾向于过度拟合,虽然这可以通过正则化来减轻

稀疏自动编码器:

Sparse Autoencoder Loss Function (Source: Andrew Ng)

认为人类没有充分利用大脑能力的观点是基于神经科学研究的误解,该研究表明大脑中最多有 1 %- 4%的神经元同时放电。人类大脑中神经元的稀疏放电可能有几个好的进化原因。如果所有神经元同时放电,我们能够“释放大脑的真正潜力”,它可能看起来像这个。我希望你喜欢这个题外话。回到神经网络。大脑中突触的稀疏性可能是稀疏自动编码器的灵感来源。整个神经网络中的隐藏神经元学习输入数据的分级特征表示。我们可以认为,当一个神经元看到它正在寻找的输入数据的特征时,它就“触发”了。传统的自动编码器依靠其欠完整架构(欠完整意味着隐藏层比输入层包含更少的单元)来强制学习潜在特征。稀疏自动编码器背后的想法是,我们可以通过与架构无关的约束(稀疏性约束)来迫使模型学习潜在的特征表示。

稀疏性约束是我们想要的平均隐藏层激活,并且通常是接近零的浮点值。稀疏约束超参数在上面的函数中用希腊字母 rho 表示。hat j 表示隐藏单元 j 的平均激活度。

我们使用 KL 散度对模型施加这种约束,并用β对这种施加进行加权。简而言之,KL 散度衡量两个分布的不相似性。将此项添加到我们的损失函数中激励模型优化参数,使得激活值的分布和稀疏参数的均匀分布之间的 KL 散度最小化。

将激活限制在接近零意味着神经元只会在优化准确性最关键的时候触发。KL 散度意味着神经元也会因为过于频繁的放电而受到惩罚。如果你有兴趣了解更多关于稀疏自动编码器的知识,我强烈推荐你阅读这篇文章。吴恩达的这些讲座(讲座 1 、讲座 2 )也是很好的资源,帮助我更好地理解支撑自动编码器的理论。

结论:

在整篇文章中,我们深入研究了 PCA 和自动编码器背后的概念。不幸的是,没有灵丹妙药。PCA 和自动编码器模型之间的决定是依情况而定的。在许多情况下,PCA 更优越——它更快,更容易解释,可以像自动编码器一样减少数据的维数。如果你能雇用 PCA,你应该。但是,如果您正在处理的数据需要高度非线性的特征表示来获得足够的性能或可视化,PCA 可能会有所不足。在这种情况下,训练自动编码器可能是值得的。再者,即使自动编码器产生的潜在特征提高了模型性能,这些特征的模糊性对知识发现构成了障碍。

感谢阅读!我希望你喜欢这篇文章,并获得一些有用的见解。如果你做了,请随意留下掌声!感谢建设性的反馈。

参考文献:

神经科学研究:https://www . science direct . com/science/article/pii/s 0960982203001350?通过%3Dihub

https://www . coursera . org/learn/neural-networks/lecture/JiT1i/from-PCA-to-auto encoders-5-mins

https://arxiv.org/pdf/1801.01586.pdf

其他图像来源:

自动编码器架构:

  • 基于稀疏过完备特征的高压缩测量值的轴承故障智能状态监测方法 ResearchGate 上的科学数字。可从:https://www . research gate . net/auto encoder-architecture _ fig 1 _ 318204554获取【2018 年 9 月 4 日】

另一篇值得一读的文章:https://Neptune . ai/blog/understanding-re presentation-learning-with-auto encoder-everything-you-Neptune-to-know-about-re presentation-and-feature-learning

用龙与地下城理解概率论

原文:https://towardsdatascience.com/understanding-probability-theory-with-dungeons-and-dragons-a36bc69aec88?source=collection_archive---------13-----------------------

第一章:独立事件&二项分布

http://strangerthings.wikia.com/wiki/Dungeons_%26_Dragons

概率论是一个丰富的数学分支,也与哲学、神学和逻辑交叉。概率论起源于 17 世纪,当时数学家帕斯卡和费马开始分析概率游戏的数学。帕斯卡和费马不仅对数学,而且对哲学和神学都有贡献。神学家和哲学专业的学生可能还记得帕斯卡的赌注,用简单的话来说,就是人类用自己的生命打赌上帝是否存在。因此,我们可以看到概率论的广泛影响。

我们可以认为概率论是一个涉及面很广的领域,但我相信只要给出有用的例子,它既直观又容易掌握。概率论也是数据科学不可或缺的一部分,了解这一领域的基础知识将为更高级的主题提供坚实的基础,如回归和贝叶斯分析。

最近几个月,我花时间阅读了各种关于概率论和统计学的书籍,包括库珀和韦克斯开创性的数据、模型和统计分析。鉴于这些文本通常是实验和分析的跳板,我觉得将 Cooper 和 Weekes 所涉及的一些公理转化为现实世界的例子可能会很有趣。鉴于更奇怪的东西暂时还不会回来,我想浏览一下概率论,用龙与地下城来比喻所讨论的各种公理

在这第一篇文章中,我将介绍概率论中独立和相关事件的含义,以及二项式分布,这是任何数据科学家工具箱中必不可少的一部分。

Image by Diacritica

独立和非独立事件;滚动一个二十面模具

在概率论中,我们有独立事件和非独立事件。Cooper 和 Weekes 将依赖事件定义为第一个事件的结果影响第二个事件的结果。因此,独立事件是指第一个事件的结果不会影响第二个事件。

一个独立事件的完美例子是两次掷骰子;事实上,这是概率论中的一个经典例子。在今天的帖子中,我们将对它进行一点 D&D 扭曲。

让我们想象一下,我们已经在每周一次的 D&D 游戏中安定下来。我们的地牢主人分发我们的骰子,我们看一看那个有二十面的骰子。我们可以注意到,如果我们掷两次,第一次的结果不会影响第二次的结果。不像我们在 D&D 的许多选择,我们的第一卷不会影响我们的下一卷。

不像地下城主,也不像那个当你的探险队询问桥边地精时一点帮助都没有的古怪村民,骰子不记得!

通过理解概率的数学,我们可以计算两个或更多独立事件的概率,因此可以连续两次掷出 20 个。找出这一点的乘法定理如下:

如果 A 和 B 是独立的,那么 p(A 和 B) = P(A) * P(B)

让我们想象一下,我们需要用 D&D 的招牌骰子让掷出两个二十个骰子。就其本身而言,20 卷的概率是 1/20。因此,p(A 和 B)的概率为:

1/20 * 1/20 = 0.0025

如您所见,这种情况发生的概率非常低!让我们希望我们不需要在我们的游戏中做两个 20 的卷。

https://www.flickr.com/photos/42405591@N02/11013366686

介绍二项式分布

这一切都很好;我们现在知道我们的掷骰子不会相互影响。然而,我们还想知道在游戏中达到一定数量的 x 次掷骰数( n )的可能性有多大。我们知道,我们在游戏中的表现取决于我们掷骰子的结果——正如任何以前玩过 D & D 的人一样,有时 6 和 8 之间的差异可能意味着一切。

让我们回到谈判桌前,赶上我们的进度。我们的冒险就要结束了,情况不妙。我们走投无路了——对我们这群勇敢的冒险家来说,情况看起来不妙。我们在游戏中还有四次机会。我们需要在其中的三个上得到 20!

在概率论的框架下;我们有 n 次试验,我们的目标是 x 次成功,或者 n = 4,x = 3。

有了概率论,就可以理解我们勇敢的冒险者接这个任务的可能性有多大,或者说我们的地下城主在这些掷骰子的时候有多残忍(剧透;相当残忍)。我们可以使用二项式分布来做到这一点,二项式分布“描述了随机变量 x 在 n 次实验中出现次数的概率分布”(Cooper & Weekes,1983)。

分布的方程式如下:

关于阶乘的一个注记(n!还有 x!)

如果你是第一次统计 n!看起来会很困惑。n!指阶乘,即 n 乘以一系列递减的自然数。所以如果 n = 4,那么 n!是:

4 * 3 * 2 * 1

回到二项式

在 R 中,我们可以使用二项式函数来找出 4 次掷骰中有 3 次成功的可能性,例如,我们将在 4 次中掷出 23 次。我们知道掷出 20 的概率是 1/20。我们将使用 R 的 dbinom 函数,它采用以下值:

##Sample values
dbinom(x, size, prob, log = FALSE)dbinom(3,4,(1/20))
= 0.000475

几率肯定对我们不利。这是一个残酷的地下城主!对于你们当中勇敢的人来说,这里有一个 R 版本的文本游戏,它要求你从四个骰子中掷出三个二十来拯救你的勇敢冒险者。被警告;你可能会死(没有骰子相关的双关语)。要玩这个游戏,只需将代码复制并粘贴到你的 R 控制台上,然后输入 startGame()

[## hollyemblem/DD-二项式

用 D&D 理解二项分布

github.com](https://github.com/hollyemblem/dd-binomial/blob/master/binomial-script.R)

重温我们的冒险

因此,我们已经了解了如何用概率论来理解用我们的骰子掷出两个 20 的机会,或者更广泛地说,乘法定理如何适用于独立事件。我们还学习了如何使用二项式分布来预测 n 次试验中的 x 次成功。我们也知道我们的地下城主有点刻薄,这不是什么好消息,但我们还是继续冒险!

掷骰子很有趣,但在我们的下一个游戏中,我们想改变一些事情。我们的地下城主承诺她会为我们的玩家准备一些新的角色表,但是,因为她有点刻薄,我们不能选择我们的新职业,相反,我们会从桌子上随机抽取一个。有 6 张,2 个德鲁伊,1 个野蛮人,1 个圣骑士,1 个术士和 1 个吟游诗人。我们需要计算出得到每个角色类别的概率。

在下一篇文章中,我们将着眼于相关事件和条件概率来帮助回答这个问题。我们可能还会问为什么我们的地下城主如此刻薄。

有用的资源

https://www . varsitytutors . com/hotmath/hotmath _ help/topics/binomial-probability

http://www . r-tutor . com/elementary-statistics/probability-distributions/binomial-distribution

https://stat . ethz . ch/R-manual/R-devel/library/stats/html/binomial . html

通过聚类分析了解卡纳塔克邦的初等教育质量

原文:https://towardsdatascience.com/understanding-quality-of-primary-education-in-karnataka-through-cluster-analysis-95afd7238399?source=collection_archive---------19-----------------------

tldr;为什么要进行这项研究,研究结果是什么?

新千年见证了小学入学率的大幅提升,从 2001 年的 79%上升到 2014 年的 93%。但正如我在之前的博客“通过数据可视化解读印度:印度教育系统”中所展示的,印度许多邦已经很低的学习水平在最近几年进一步下降。尽管本应影响学习成果的因素显示出有利的趋势,但还是发生了这种情况。私立学校在增加,辍学率很低并且保持稳定,一个班级的学生人数在下降,每个教师的学生人数也在下降。随着 2009 年《实时教育法》的通过,更多的资金以设施、学习材料等形式注入教育系统。那么,如何解释这种糟糕的学习状态呢?社会经济因素如成人文化程度、种姓制度是否在起作用?在本研究中,我使用聚类算法通过卡纳塔克邦的案例研究来挖掘潜在的原因。该算法创建了以小学学习成果为重点的学区群,并对每个学区群的特征进行了分析。

聚类分析产生 3 个聚类,标记为“第 1 层”、“第 2 层”和“第 3 层”。在各学区中,第 1 级的学习成果最高,第 3 级最低。每个组群的地区如下。

那么,区别特征是什么呢?请继续读下去…

来自 ASER、DISE 和 SocialCops 的数据

在我之前的博客文章中,我已经提到了 DISE 和阿瑟。概括地说,ASER(年度教育状况报告)是一项年度调查,旨在为印度每个地区和邦的儿童入学率和基本学习水平提供可靠的估计。这项调查由非政府组织 Pratham 与当地伙伴组织的志愿者合作进行。

DISE(地区教育信息系统)收集全国所有学校的入学率、基础设施、教师和其他可用设施的信息。该数据库由国立教育规划和管理大学开发和维护。

第三,其中一个参数,即 RTE 符合性分数,来自 socialcops.com 网站。这里提取了 DISE 数据库中的 RTE 值,并计算了一个综合分数,以评估每个区的 RTE 实施水平。想了解更多关于 RTE 的知识?参考这篇文章。

准备集群

数据分析参数有哪些?【2014 年收集了所有来源的数据。为什么是 2014 年?那一年来自所有三个来源的数据质量要好得多。例如,RTE 合规分数在随后几年无法在 socialcops.com 网站上获得。这项研究使用了卡纳塔克邦 26 个区的小学数据。Ramanagar、Yadgir、Chikkaballapur 和 Bangalore Urban 等地区不包括在内,因为 ASER 调查没有收集这些地区 2014 年的学习成果。这里使用了 18 个参数进行分析,包括社会经济特征、入学率、学校类型、教学媒介、学习水平。

**一如既往的 R:**R 依然是我的最爱。所有用于数据准备、模型建立和可视化的代码都是用 r 编写的。

**探索数据:**这里的分析单位是区。使用箱线图和汇总函数进行数据探索。箱线图检测了变量的异常值,如男女比例、教师的性别分布、非在校儿童、私立学校入学率和阅读水平。经过进一步检查,发现这些值是适当的,没有应用异常值处理。

**关于聚类分析的更多信息:**聚类分析是一种基于无监督学习的数据挖掘技术。无监督学习探索“未标记”或“未分类”的数据,以找到隐藏的模式。这里没有目标属性。聚类分析将描述相似特征的对象分组。由于观测值较少,这里选择凝聚层次聚类技术。在各种凝聚过程中,使用沃兹方法。这种方法会合并对象,从而尽可能降低簇内方差。

**缩放和加权:**每个变量使用不同的测量类型。在本研究使用的变量中,教师的男女比例和性别分布是比率,RTE 合规分数以 10 分制衡量,而其余变量是百分比。对于有效的聚类,将变量调整到一个共同的范围是非常重要的。这被称为“缩放”。应用基础包中的函数“scale ”,将所有值标准化为 z 分数。下一步是“称重”。因为我们希望基于它们的性能来区分集群,所以我们给学习结果变量增加了更多的权重。我们将结果值增加了三倍。

建立模型

**确定聚类数:**如何确定聚类数?为此,使用了肘法、剪影法和间隙统计法等方法。r 包 factoextra 用于确定给定聚类方法和数据可视化的最佳聚类数。

所以,在 2 和 3 之间很难抉择。为了收集更多关于区分因素的信息,我决定分成 3 组。

**计算距离矩阵:*凝聚式层次聚类算法以距离矩阵为输入。距离矩阵是显示对象对之间距离的表格。这里,r 包 factoextra 再次用于计算和可视化距离。*计算每个特征的一对区域之间的欧几里德距离。生成的热图如下,随着距离的增加,颜色从红色变为蓝色。

**算法:**在凝聚层次聚类中,每个对象被分配到自己的聚类中,然后算法迭代进行,在每个阶段加入两个最相似的聚类,继续进行,直到只有一个聚类。这里,来自集群包的 hclust 函数用于构建算法。被监护人的方法。“D2”用于在每次迭代中合并两个相似的聚类。该算法生成以下树状图。

使用 cutree 功能,在 3 处截取树状图,确定为最佳数量。

通过专题地图可视化集群

使用 sprgdal 、raster 和 tmap 软件包构建了一个显示学习成果的卡纳塔克邦专题地图。

我们来分析一下集群

学习成果不太令人满意

即使在这些地区中学习水平最高的一级地区,也只有四分之三的儿童(STD 3-5)能够阅读标准 1 课文,只有三分之二的儿童(STD 3-5)能够做减法。在占总区一半以上的三级区中,平均值分别下降到 50%和 30%。

第三级的更多地区

表现最差的第 3 层集群有 14 个区。这个数字比其他两个性能更高的集群加起来还要多。性能最高的集群,第 1 层只有 4 个地区。

区分集群的因素

**识字率:**与第二层相比,第一层的总体识字率和女性识字率至少高出 10%,第二层是表现第二好的组群。一级教育的总体识字率超过 80%,而女性识字率约为 75%。三级学校的整体识字率和女性识字率最低,分别徘徊在 70%和 60%左右。

**种姓分布:**在一级地区,在册种姓和在册部落的入学率较低,分别为 11%和 3%。对于二级和三级学校,在册种姓入学率超过 20%。在三级学校中,ST 的入学率最高,为 11%。

OBC 的入学率在一级区最高,为 77%,其次是二级区的 66%和三级区的 56%。

**在册种姓和在册部落教师:**在一级区,在册种姓和在册部落教师的比例较低。在册种姓教师占教师总数的 8%,而在册部落教师约占 3%。在二线和三线城市,在册种姓和在册部落教师的比例分别约为 15%和 5%。

**男教师:**在一级地区,男教师比女教师多 2:1。在第二级和第三级,男女教师人数相当。

**教学语言:**在一级区,五分之一的儿童以英语为教学语言,是三级区平均水平的两倍。在二级学校,15%的学生选择英语作为教学语言。

**私立学校入学率:**私立学校入学率在一级区很高,为 35%,其次是二级区的 26%和三级区的 22%

**失学儿童:**在三级区,失学儿童的比例很高,为 3%。在一级和二级地区,不到 1%的儿童失学。

**学生教室比率(SCR) > 30 和学生教师比率(PTR) > 30 的学校百分比:**学生教室比率> 30 和学生教师比率> 30 的学校百分比在三级区更多,分别为 22%和 13%。一级和二级地区的选择性接种率约为 10 %, PTR 约为 7%。

集群之间的相似性

儿童性别比例 : 各区儿童性别比例差异不大。每一级的平均男女比例都在 0 . 9 以上

RTE 得分:集群的平均 RTE 得分高于 8。

事实检验

每个聚类中的平均值可以显示在下表中。

结论

这项研究表明了影响学习成果的因素。一些积极影响学习成果的因素包括私立学校教育、英语作为教学媒介、整体和女性识字率、学生课堂比率和学生教师比率。这项研究还表明,即使在成绩最好的地区,学习成绩也达不到理想水平。所以,我们需要更多的数据来解释糟糕的学习状态。这可能包括学生和教师出勤率、教学质量、教师积极性水平、学生认知水平等方面的数据。这样的数据还不能从二手资料中获得,而且像教学质量、教师激励水平、学生认知水平等也很难量化。因此,任何深入研究这个问题的未来研究都需要收集原始数据。这既费时又费钱。但是我一定会继续努力…

想看看代码吗?参考我的 github 库。

理解随机变量

原文:https://towardsdatascience.com/understanding-random-variable-a618a2e99b93?source=collection_archive---------3-----------------------

随机变量在统计学和概率学中非常重要,如果有人想了解概率分布,这是必须的。随机变量经常与传统变量混淆。在这篇博文中,我们将看到什么是随机变量,以及为什么我们需要它们而不是传统变量。

Photo by Alois Komenda on Unsplash

在概率统计中,随机变量、随机数量或随机变量是一个变量,其可能值是随机现象的结果——维基百科

随机变量不同于我们传统的变量,就它所取的值而言。这是一个将随机过程的结果映射成数值的函数。

由于它具有随机性,所以取不同的值。

为什么是随机变量?

随机变量允许我们用数学的方式提问。

如果我们抛 5 枚硬币,想回答这样的问题:

1.恰好得到 3 个头的概率是多少?

2.少于 4 头的概率有多大?

3.得到 1 头以上的概率有多大?

那么我们一般的写法是:

p(当我们掷 5 次硬币时,恰好得到 3 个正面的概率)

p(当我们掷 5 次硬币时,得到少于 4 个正面的概率)

p(当我们掷 5 次硬币时,得到 1 个以上人头的概率)

但是,如果我们用随机变量来表示上述问题,那么我们会写:

1.P(X=3)

2.P(X <4)

3. P(X> 1)

正如我们在上面看到的,随机变量使我们的任务更容易量化任何随机过程的结果,应用数学和执行进一步的计算。

假设我们有一个投掷硬币的随机过程/实验。两种可能结果中的一种可能是正面或反面。所以这里我们用 X 来表示随机变量,它代表这个随机过程的结果。

因此我们可以写作

X= 1,如果结果是正面

X= 0,如果结果是尾巴

这里,随机变量 X 将随机过程(抛硬币)的结果映射为数值(1 和 0)。

用来表示头部和尾部的值可以是任何值,不一定是 1 和 0。

为了便于理解,我们使用了 1 和 0。

将数值分配给随机过程结果的其他方式可以是:

X= 100,如果结果是正面

X= 50,如果结果是尾巴

总结为三点

我们有一个实验(扔硬币)

我们给每个事件赋予价值

这组值是一个随机变量。

随机变量与代数中使用的传统变量有何不同?

假设代数中使用的变量为 x,y,z,这里 x 可以是手机的数量,y =人头数,z=学生数。变量不过是一个字母字符,代表一个未知数。

例如:

x + 5 = 10

x 是一个变量,它的值是未知的,我们试图找到它的值。

经过评估,x=5。

随机变量不同于代数中的变量,因为它有一组完整的值,并且可以随机取其中的任何一个。代数中使用的变量一次只能有一个值。

如果随机变量 X={0,1,2,3}

那么 X 可以是随机的 0、1、2 或 3,其中每一个可能具有不同的概率。

我们用大写字母表示随机变量,以避免与传统变量混淆。

随机变量可以是离散的,也可以是连续的。

如果一个变量可以取可数个不同的值,那么它就是一个离散随机变量

举个例子:在一个投掷 2 枚硬币的实验中,我们需要找出可能的人头数。

在这种情况下,X 是随机变量,它取的可能值是 0、1 和 2,这是离散的。

因此 X= {0,1,2}

如果一个随机变量在一个区间内取无穷多个值,则称其为连续的

例如:假设一个城市的温度介于 30⁰和 45⁰之间。温度可以取 30⁰到 45⁰.之间的任何值所以温度可能是 30.13⁰或 40.15⁰,也可能是 30.13⁰和 40.15⁰.当我们说温度是 38⁰时,意思是它在 37.5 到 38.5 之间。所以在连续的随机变量中没有精确的或离散的观测值。

这是对随机变量的简单介绍。

感谢阅读!!

了解剩余网络

原文:https://towardsdatascience.com/understanding-residual-networks-9add4b664b03?source=collection_archive---------1-----------------------

由于大型数据集和强大的 GPU 的可用性,图像识别近年来取得了进展,这使得非常深入的架构训练成为可能。Simonyan 等人,《VGG》的作者证明了通过简单地堆叠更多的层,我们可以提高精确度,在此之前,Yoshua Bengio 在他的专著《学习人工智能的深度架构》中对深度架构的有效性进行了令人信服的理论分析。
在以前的帖子中,我演示了如何将各种技术应用于卷积神经网络,包括批量标准化、丢弃和数据扩充。通过简单地叠加越来越多的卷积-批量归一化-relu 层,能建立更精确的系统吗?在某种程度上,精确度会提高,但是超过大约 25+层,精确度会下降。
明凯等人 2015 首次演示了深度问题,并提出了一个卓越的解决方案,此后允许训练超过 2000 层!越来越准确。在这篇文章中,我将解释他们的技术以及如何应用。
首先,由于渐变消失,许多层的精度下降,随着层深入,渐变变小,导致性能变差。这与过度拟合无关,因此,辍学者无法挽救它。微软亚洲研究院的何和他的同事设计的最终解决方案是引入剩余连接。这只是描述将先前层的输出连接到新层的输出的简单术语。
假设您有一个七层网络。在残差设置中,不仅要将第 1 层的输出传递到第 2 层,还要将第 1 层的输出加到第 2 层的输出上。
在标准网络中用***【f(x)*** 表示每一层 y = f(x)
然而,在残差网络中,
y = f(x)+x

Typical Structure of A Resnet Module

应用这一原理,作者赢得了 Imagenet 2015 ,并在所有标准计算机视觉基准测试中取得了新的最先进的结果。这个想法后来被扩展到深度学习的所有其他领域,包括语音和自然语言处理。

基础数学讲够了,让我们用代码来弄脏我们的手。

标准的两层模块如下

***def** Unit(x,filters):

    out = BatchNormalization()(x)
    out = Activation(**"relu"**)(out)
    out = Conv2D(filters=filters, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(out)

    out = BatchNormalization()(out)
    out = Activation(**"relu"**)(out)
    out = Conv2D(filters=filters, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(out)

    **return** out* 

概括地说,在这个模块中,我们传入一个输入 x,对它进行批处理规范化— relu- conv2d,然后输出通过同一个堆栈。

下面是一个 resnet 模块

***def** Unit(x,filters):
    res = x
    out = BatchNormalization()(x)
    out = Activation(**"relu"**)(out)
    out = Conv2D(filters=filters, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(out)

    out = BatchNormalization()(out)
    out = Activation(**"relu"**)(out)
    out = Conv2D(filters=filters, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(out)

    out = keras.layers.add([res,out])

    **return** out*

这看起来非常相似,但有一个主要区别,首先,我们存储一个对原始输入的引用“res ”,在通过 batchnorm-relu-conv 层后,我们将输出添加到残差中,为了清楚起见,这是在该行中完成的

*out = keras.layers.add([res,out])*

这部分对应方程 y = f(x) + x

因此,我们可以通过将许多模块堆叠在一起来构建一个 resnet。

在此之前,我们需要稍微修改一下代码来考虑池。

***def** Unit(x,filters,pool=**False**):
    res = x
    **if** pool:
        x = MaxPooling2D(pool_size=(2, 2))(x)
        res = Conv2D(filters=filters,kernel_size=[1,1],strides=(2,2),padding=**"same"**)(res)
    out = BatchNormalization()(x)
    out = Activation(**"relu"**)(out)
    out = Conv2D(filters=filters, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(out)

    out = BatchNormalization()(out)
    out = Activation(**"relu"**)(out)
    out = Conv2D(filters=filters, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(out)

    out = keras.layers.add([res,out])

    **return** out*

请注意上面的一些内容,当我们合并时,我们输出的维数将不再匹配我们残差的维数,因此,我们不仅将合并应用于输入,而且残差也将通过步长为 1×1 的 conv 变换,该变换将滤波器投影为与输出相同,并且步长为 2 将是维数的一半,就像最大合并一样。

解释完之后,我现在将给出完整的答案。

***def** Unit(x,filters,pool=**False**):
    res = x
    **if** pool:
        x = MaxPooling2D(pool_size=(2, 2))(x)
        res = Conv2D(filters=filters,kernel_size=[1,1],strides=(2,2),padding=**"same"**)(res)
    out = BatchNormalization()(x)
    out = Activation(**"relu"**)(out)
    out = Conv2D(filters=filters, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(out)

    out = BatchNormalization()(out)
    out = Activation(**"relu"**)(out)
    out = Conv2D(filters=filters, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(out)

    out = keras.layers.add([res,out])

    **return** out**def** MiniModel(input_shape):
    images = Input(input_shape)
    net = Conv2D(filters=32, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(images)
    net = Unit(net,32)
    net = Unit(net,32)
    net = Unit(net,32)

    net = Unit(net,64,pool=**True**)
    net = Unit(net,64)
    net = Unit(net,64)

    net = Unit(net,128,pool=**True**)
    net = Unit(net,128)
    net = Unit(net,128)

    net = Unit(net, 256,pool=**True**)
    net = Unit(net, 256)
    net = Unit(net, 256)

    net = BatchNormalization()(net)
    net = Activation(**"relu"**)(net)
    net = Dropout(0.25)(net)

    net = AveragePooling2D(pool_size=(4,4))(net)
    net = Flatten()(net)
    net = Dense(units=10,activation=**"softmax"**)(net)

    model = Model(inputs=images,outputs=net)

    **return** model*

这不包括训练代码,你可以看到,下面是训练代码,纪元设置为 50 个纪元。

你可以用谷歌实验室在 GPU 上免费运行这个

**#import needed classes* **import** keras
**from** keras.datasets **import** cifar10
**from** keras.layers **import** Dense,Conv2D,MaxPooling2D,Flatten,AveragePooling2D,Dropout,BatchNormalization,Activation
**from** keras.models **import** Model,Input
**from** keras.optimizers **import** Adam
**from** keras.callbacks **import** LearningRateScheduler
**from** keras.callbacks **import** ModelCheckpoint
**from** math **import** ceil
**import** os
**from** keras.preprocessing.image **import** ImageDataGenerator

**def** Unit(x,filters,pool=**False**):
    res = x
    **if** pool:
        x = MaxPooling2D(pool_size=(2, 2))(x)
        res = Conv2D(filters=filters,kernel_size=[1,1],strides=(2,2),padding=**"same"**)(res)
    out = BatchNormalization()(x)
    out = Activation(**"relu"**)(out)
    out = Conv2D(filters=filters, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(out)

    out = BatchNormalization()(out)
    out = Activation(**"relu"**)(out)
    out = Conv2D(filters=filters, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(out)

    out = keras.layers.add([res,out])

    **return** out

*#Define the model* **def** MiniModel(input_shape):
    images = Input(input_shape)
    net = Conv2D(filters=32, kernel_size=[3, 3], strides=[1, 1], padding=**"same"**)(images)
    net = Unit(net,32)
    net = Unit(net,32)
    net = Unit(net,32)

    net = Unit(net,64,pool=**True**)
    net = Unit(net,64)
    net = Unit(net,64)

    net = Unit(net,128,pool=**True**)
    net = Unit(net,128)
    net = Unit(net,128)

    net = Unit(net, 256,pool=**True**)
    net = Unit(net, 256)
    net = Unit(net, 256)

    net = BatchNormalization()(net)
    net = Activation(**"relu"**)(net)
    net = Dropout(0.25)(net)

    net = AveragePooling2D(pool_size=(4,4))(net)
    net = Flatten()(net)
    net = Dense(units=10,activation=**"softmax"**)(net)

    model = Model(inputs=images,outputs=net)

    **return** model

*#load the cifar10 dataset* (train_x, train_y) , (test_x, test_y) = cifar10.load_data()

*#normalize the data* train_x = train_x.astype(**'float32'**) / 255
test_x = test_x.astype(**'float32'**) / 255

*#Subtract the mean image from both train and test set* train_x = train_x - train_x.mean()
test_x = test_x - test_x.mean()

*#Divide by the standard deviation* train_x = train_x / train_x.std(axis=0)
test_x = test_x / test_x.std(axis=0)

datagen = ImageDataGenerator(rotation_range=10,
                             width_shift_range=5\. / 32,
                             height_shift_range=5\. / 32,
                             horizontal_flip=**True**)

*# Compute quantities required for featurewise normalization
# (std, mean, and principal components if ZCA whitening is applied).* datagen.fit(train_x)

*#Encode the labels to vectors* train_y = keras.utils.to_categorical(train_y,10)
test_y = keras.utils.to_categorical(test_y,10)

*#define a common unit* input_shape = (32,32,3)
model = MiniModel(input_shape)

*#Print a Summary of the model* model.summary()
*#Specify the training components* model.compile(optimizer=Adam(0.001),loss=**"categorical_crossentropy"**,metrics=[**"accuracy"**])

epochs = 50
steps_per_epoch = ceil(50000/128)

*# Fit the model on the batches generated by datagen.flow().* model.fit_generator(datagen.flow(train_x, train_y, batch_size=128),
                    validation_data=[test_x,test_y],
                    epochs=epochs,steps_per_epoch=steps_per_epoch, verbose=1, workers=4)

*#Evaluate the accuracy of the test dataset* accuracy = model.evaluate(x=test_x,y=test_y,batch_size=128)
model.save(**"cifar10model.h5"**)*

希望你喜欢这一点,未来的帖子将致力于通过宽度和深度轻松扩展剩余网络的方法,以及调整学习速度的方法。

玩得开心,别忘了留下一些掌声!

你可以随时在推特上通过 @johnolafenwa 联系我

了解 RMSprop —更快的神经网络学习

原文:https://towardsdatascience.com/understanding-rmsprop-faster-neural-network-learning-62e116fcf29a?source=collection_archive---------1-----------------------

免责声明:我假定关于神经网络优化算法的基础知识。特别是关于 SGD SGD 带动量 的知识,会对理解这篇帖子很有帮助。

一、简介

RMSprop—是为神经网络设计的未发布的优化算法,由 Geoff Hinton 在在线课程“用于机器学习的神经网络”【1】的第 6 讲中首次提出。RMSprop 属于自适应学习率方法领域,这种方法近年来越来越受欢迎,但也受到一些批评6。它因没有出版而出名,但却非常出名;大多数深度学习框架都包括开箱即用的实现。

有两种方法可以引入 RMSprop。首先,将它视为 rprop 算法对小批量学习的适应。这是开发这种算法的最初动机。另一种方法是看看它与 Adagrad2的相似之处,并将 RMSprop 视为应对其学习率急剧下降的一种方式。我将尝试触及这两点,这样就能更清楚为什么这个算法有效。

二。RPROP

让我们先来了解一下rprop——用于整批优化的算法。Rprop 3试图解决梯度幅度可能变化很大的问题。一些梯度可能很小,而另一些可能很大,这导致了非常困难的问题——试图为算法找到单一的全局学习速率。如果我们使用整批学习,我们可以通过只使用梯度的符号来处理这个问题。这样,我们可以保证所有权重更新的大小相同。这种调整对鞍点和平台有很大帮助,因为我们即使在很小的坡度下也能迈出足够大的步伐。请注意,我们不能仅仅通过提高学习率来做到这一点,因为我们在大梯度下采取的步骤会更大,这将导致发散。Rprop 结合了仅使用梯度符号的思想和为每个权重单独调整步长的思想。因此,我们不看梯度的大小,而是看为特定权重定义的步长。步长随着时间的推移而不断调整,这样我们就可以朝着我们需要的方向加速学习。为了调整某些权重的步长,使用以下算法:

  1. 首先,我们看看重量的最后两个梯度的符号。
  2. 如果它们具有相同的符号,这意味着我们正朝着正确的方向前进,并且应该将它加速一小部分,这意味着我们应该成倍地增加步长(例如,增加 1.2 倍)。如果它们不同,这意味着我们做了太大的步长并且跳过了局部最小值,因此我们应该成倍地减小步长(例如通过因子 0.5)。
  3. 然后,我们将步长限制在两个值之间。这些值实际上取决于您的应用程序和数据集,默认的好值是 50 和百万分之一,这是一个好的开始。
  4. 现在我们可以应用权重更新。

注意,作者定义了不同版本的 rprop 算法。为了让您熟悉它,我已经展示了最简单的一个。虽然我喜欢用等式正式定义优化算法,但这种算法最好通过代码来表达;因此,rprop 更新规则的最简单版本如下所示:

三。Rprop 至 RMSprop

当我们拥有非常大的数据集并且需要执行小批量权重更新时,Rprop 实际上不起作用。为什么它不适用于小批量?人们已经尝试过了,但是发现很难成功。它不起作用的原因是它违反了随机梯度下降背后的中心思想,即当我们有足够小的学习率时,它会在连续的小批量上平均梯度。考虑重量,九个小批量的梯度为 0.1,十分之一小批量的梯度为-0.9。我们想要的是这些梯度大致互相抵消,这样保持大致相同。但 rprop 不是这样。使用 rprop,我们将权重增加 9 次,只减少一次,因此权重会增加很多。

要结合 rprop 的稳定性(仅通过使用梯度的符号)、我们从小批量获得的效率以及对小批量求平均值(允许以正确的方式结合梯度),我们必须从不同的角度来看待 rprop。Rprop 相当于使用梯度,但也除以梯度的大小,因此无论特定梯度有多小,我们都会得到相同的幅度。小批量的问题是,我们每次除以不同的梯度,那么为什么不强制我们除以的数字对于相邻的小批量是相似的呢?RMSprop的中心思想是保持每个权重的平方梯度的移动平均值。然后我们将梯度除以均方根。这就是它被称为 RMSprop(均方根)的原因。使用数学等式,更新规则如下所示:

E[g] — moving average of squared gradients. dC/dw — gradient of the cost function with respect to the weight. n — learning rate. Beta — moving average parameter (good default value — 0.9)

从上面的等式可以看出,我们通过除以梯度的平方根来调整学习率,但是由于我们只有当前小批量的梯度估计值,因此我们需要使用它的移动平均值。您可以在项目中使用的移动平均参数的默认值是 0.9。对于大多数应用程序来说,它工作得非常好。在代码中,该算法可能如下所示:

四。与阿达格拉德相似。

Adagrad2是自适应学习速率算法,看起来很像 RMSprop。Adagrad 基于每个维度中的历史平方和添加元素式渐变缩放。这意味着我们保留了一个梯度平方和。然后我们通过除以总和来调整学习率。在代码中,我们可以这样表达它:

当我们有高条件数时,这个比例有什么作用?如果我们有两个坐标——一个总是有大的梯度,另一个有小的梯度,我们将通过相应的大或小的数字潜水,所以我们在小的方向上加速运动,在梯度大的方向上,我们将减速,因为我们除以某个大的数字。

培训过程中会发生什么?步数变得越来越小,因为我们在训练中不断更新增长的平方梯度。所以我们每次都除以较大的数。在凸优化中,这很有意义,因为当我们接近 minina 时,我们希望慢下来。在非凸的情况下,这是不好的,因为我们可以卡在鞍点。我们可以将 RMSprop 视为解决这一问题的算法。

使用 RMSprop,我们仍然保留平方梯度的估计值,但我们保留了它的移动平均值,而不是让该估计值在训练中不断累积。

动词 (verb 的缩写)结果

我为不同的优化算法找到了这些令人敬畏的可视化效果,展示了它们在不同情况下的表现。

Source: https://imgur.com/a/Hqolp#NKsFHJb

如你所见,在鞍点的情况下,RMSprop(黑线)直线下降,梯度有多小并不重要,RMSprop 缩放学习速率,因此算法通过鞍点的速度比大多数算法都快。

Source: https://imgur.com/a/Hqolp#NKsFHJb

在这种情况下,算法从初始梯度非常大的点开始。RMSprop(黑线)走的几乎是最优路径,而动量法超调很多。阿达格拉德在那一瞬间变得不稳定。

不及物动词结论(了解更多信息)

RMSprop 是一款优秀、快速且非常受欢迎的优化器。Andrej Karpathy的《机器学习趋势一瞥【4】显示,它是深度学习中使用的最流行的优化算法之一,其受欢迎程度仅次于 Adam【5】。如果你想了解更多关于深度学习中的优化,你应该查看以下一些来源:

  1. Sebastian Ruder 的博客有几篇关于深度学习优化趋势的文章。
  2. fast.ai 是一门很棒的关于深度学习的课程,他们通过最流行的优化算法,在 excel 表格上解释它们。
  3. 吴恩达在 coursera 上的深度学习专业的第二门课程也触及了流行的算法,以非常清晰的方式解释了它们。

七。参考

1 Geoffrey Hinton 用于机器学习的神经网络 nline 课程。https://www.coursera.org/learn/neural-networks/home/welcome

2阿达格勒:杜奇,j .,哈赞,e .,辛格,Y. (2011 年)。在线学习和随机优化的自适应次梯度方法。机器学习研究杂志,12,2121–2159。从 http://jmlr.org/papers/v12/duchi11a.html[取回](http://jmlr.org/papers/v12/duchi11a.html)

3克里斯蒂安·伊格尔和迈克尔·̈usken(2000 年)。改进 Rprop 学习算法。【http://citeseerx.ist.psu.edu/viewdoc/summary? doi=10.1.1.17.1332

[4]安德烈·卡帕西(2017)。机器学习趋势一瞥。https://medium . com/@ karpathy/a-peek-at-trends-in-machine-learning-ab8a 1085 a 106

5金马,D. P .,&巴,J. L. (2015 年)。亚当:一种随机优化方法。学习表征国际会议,1–13

6 Ashia C. Wilson 、Rebecca Roelofs 、Mitchell Stern 、Nati Srebro、Benjamin Recht(2017)机器学习中自适应梯度方法的边际价值。arXiv:1705.08292v2

了解设置 SettingWithCopyWarning

原文:https://towardsdatascience.com/understanding-settingwithcopywarning-7142952a01fa?source=collection_archive---------12-----------------------

Photo from Pixabay

是人们在学习熊猫时遇到的最常见的障碍之一。快速的网络搜索会发现大量的堆栈溢出问题、GitHub 问题和来自程序员的论坛帖子,他们试图理解这个警告在他们的特定情况下意味着什么。这并不奇怪,许多人都在为此挣扎;有很多方法来索引 pandas 数据结构,每种方法都有其独特的细微差别,甚至 pandas 本身也不能保证两行看起来相同的代码有一个单一的结果。

本指南解释了产生警告的原因,并向您展示了解决方法。它还包括引擎盖下的细节,让您更好地了解正在发生的事情,并提供了一些关于该主题的历史,让您了解为什么它都是这样工作的。

为了探究SettingWithCopyWarning,我们将使用《建模在线拍卖一书中易贝 3 天拍卖中销售的 Xboxes 价格的数据集。让我们来看看:

正如你所看到的,我们数据集的每一行都涉及到一次特定的易贝 Xbox 拍卖的单一出价。以下是对每列的简要描述:

  • auctionid —每个拍卖的唯一标识符。
  • bid —投标的价值。
  • bidtime —投标时拍卖的期限,以天为单位。
  • bidder —投标人的易贝用户名。
  • bidderrate -投标人的易贝用户评级。
  • openbid —卖家为拍卖设定的开价。
  • price —拍卖结束时胜出的出价。

什么是 SettingWithCopyWarning?

首先要明白的是SettingWithCopyWarning是一个警告,而不是一个错误。

虽然错误表明出现了问题,例如无效的语法或试图引用未定义的变量,但警告的作用是提醒程序员他们的代码存在潜在的错误或问题,而这些错误或问题在该语言中仍然是允许的操作。在这种情况下,警告很可能表示一个严重但不明显的错误。

SettingWithCopyWarning通知您您的操作可能没有按预期运行,您应该检查结果以确保没有出错。

如果您的代码仍然像预期的那样工作,忽略这个警告是很有诱惑力的。这是不好的做法,并且SettingWithCopyWarning不应该被忽略。在采取行动之前,花些时间去理解为什么你会得到警告。

为了理解SettingWithCopyWarning是关于什么的,理解 pandas 中的一些操作可以返回您的数据的视图,而其他操作将返回副本是有帮助的。

View vs copy

正如你在上面看到的,左边的视图df2只是原始视图df1的一个子集,而右边的副本创建了一个新的、唯一的对象df2

当我们试图进行更改时,这可能会导致问题:

Modifying a view vs modifying a copy

根据我们正在做的事情,我们可能想要修改原始的df1(左),或者我们可能想要只修改df2(右)。警告是让我们知道我们的代码可能做了一件事,而我们希望它做了另一件事。

稍后我们将深入探讨这个问题,但是现在让我们先来解决这个警告的两个主要原因以及如何修复它们。

链式分配

Pandas 在检测到一种叫做链式分配的东西时会发出警告。让我们定义几个我们将用来解释事情的术语:

  • 赋值——设置值的操作,例如data = pd.read_csv('xbox-3-day-auctions.csv')。通常称为
  • 访问—返回某个值的操作,例如下面的索引和链接示例。通常被称为 get
  • 索引—引用数据子集的任何分配或访问方法;比如data[1:5]
  • 链接——连续使用多个索引操作;比如data[1:5][1:3]

链式赋值是链接和赋值的组合。让我们快速看一个例子,它包含了我们之前加载的数据集。我们稍后将更详细地讨论这一点。为了这个例子,假设我们被告知用户'parakeet2004'的投标人评级不正确,我们必须更新它。让我们从当前值开始。

我们有三行来更新bidderrate字段;让我们继续做那件事。

哦不!我们神秘地发现了SettingWithCopyWarning

如果我们看一下,我们可以看到在这种情况下,值没有改变:

生成该警告是因为我们将两个索引操作链接在一起。这更容易发现,因为我们已经使用了两次方括号,但是如果我们使用其他访问方法,如.bidderrate.loc[].iloc[].ix[]等等,情况也是如此。我们的连锁经营包括:

  • data[data.bidder == 'parakeet2004']
  • ['bidderrate'] = 100

这两个连锁操作一个接一个地独立执行。第一个是访问方法(get 操作),它将返回一个包含所有行的DataFrame,其中bidder等于'parakeet2004'。第二个是赋值操作(set 操作),在这个新的DataFrame上调用。我们根本没有在原来的DataFrame上操作。

解决方案很简单:使用loc将链接的操作组合成一个操作,这样 pandas 可以确保原始的DataFrame被设置。熊猫将始终确保不被束缚的集合操作(如下所示)正常工作。

这是警告建议我们做的,并且在这种情况下非常有效。

隐藏链接

接下来是人们遇到的第二种最常见的方式SettingWithCopyWarning。让我们调查中标情况。我们将创建一个新的数据框架来处理它们,注意使用loc,现在我们已经学习了关于链式赋值的课程。

我们可能会用 winners 变量写几行后续代码。

一个偶然的机会,我们在DataFrame中遇到了另一个错误。这一次,标记为304的行中缺少了bidder值。

为了我们的例子,让我们说,我们知道这个投标人的真实用户名,并更新我们的数据。

又一个SettingWithCopyWarning!但是我们用了loc,怎么又出现这种情况了?为了进行研究,让我们看看代码的结果:

这次成功了,那我们为什么会收到警告呢?

链式索引既可以出现在两行中,也可以出现在一行中。因为winners是作为 get 操作(data.loc[data.bid == data.price])的输出创建的,所以它可能是原始DataFrame的副本,也可能不是,但是在我们检查之前没有办法知道!当我们索引winners时,我们实际上使用的是链式索引。

这意味着当我们试图修改winners时,我们可能也修改了data

在真正的代码库中,这些代码行可能相隔很远,因此追踪问题的根源可能更困难,但情况是一样的。

为了防止在这种情况下出现警告,解决方案是明确地告诉 pandas 在我们创建新的数据帧时制作一个副本:

就是这样!就这么简单。

诀窍是学会识别链式索引,并不惜一切代价避免它。如果你想改变原来的,使用单一的赋值操作。如果你想要一份拷贝,确保你强迫熊猫这么做。这将节省时间,并使您的代码滴水不漏。

还要注意的是,即使SettingWithCopyWarning只会在你设置的时候出现,也最好避免 gets 的链式索引。链式操作速度较慢,如果您决定稍后添加赋值操作,会导致问题。

处理设置 SettingWithCopyWarning 的提示和技巧

在我们下面做更深入的分析之前,让我们拿出显微镜,看看SettingWithCopyWarning的一些细微之处和本质细节。

关闭警告

首先,如果不讨论如何显式控制SettingWithCopy设置,这篇文章将是不完整的。熊猫mode.chained_assignment选项可以取其中一个值:

  • 'raise' —引发异常而不是警告。
  • 'warn' —生成警告(默认)。
  • None —完全关闭警告。

例如,让我们关闭警告:

因为这不会给我们任何警告,所以除非你完全明白自己在做什么,否则不推荐这样做。如果你感到一丝怀疑,这是不可取的。一些开发人员非常认真地对待SettingWithCopy,并选择将其提升为一个例外,就像这样:

如果您的团队中有一个没有经验的 pandas 开发人员,或者一个需要高度严谨性或完整性的确定性的项目,这可能会特别有用。

使用该设置的更精确的方法是使用上下文管理器。

如您所见,这种方法支持细粒度的警告抑制,而不是不加区别地影响整个环境。

is_copy 属性

另一个可以用来避免警告的技巧是修改熊猫用来解释SettingWithCopy场景的工具之一。每个DataFrame都有一个默认为Noneis_copy属性,但是如果是副本,则使用一个[weakref](https://docs.python.org/3/library/weakref.html)来引用源DataFrame。通过将is_copy设置为None,可以避免生成警告。

然而,请注意,这将而不是奇迹般地解决问题,但是它确实使 bug 检测变得非常困难。

单类型与多类型对象

值得强调的另一点是单数据类型和多数据类型对象之间的区别。如果一个DataFrame的所有列都是相同的数据类型,那么它就是单数据类型的;例如:

而如果DataFrame的列不都具有相同的数据类型,那么它就是多数据类型的,例如:

由于下面的历史部分解释的原因,在多数据类型对象上的索引器获取操作将总是返回一个副本。然而,主要为了提高效率,索引器对单数据类型对象的 get 操作几乎总是返回一个视图;这里需要注意的是,这取决于对象的内存布局,并且不能保证。

假阳性

假阳性,或无意中报告了连锁分配的情况,过去在早期版本的 pandas 中更常见,但后来基本上被消除了。为了完整起见,这里包括一些固定误报的例子是有用的。如果您在使用早期版本的 pandas 时遇到以下任何情况,那么可以安全地忽略或取消警告(或者通过升级来完全避免警告!)

使用用于的当前列的值向DataFrame添加新列会生成警告,但此问题已得到解决。

直到最近,当在一个DataFrame的片上使用apply方法设置时,一个假阳性也发生了,尽管这也已经被修复。

最后,直到版本 0.17.0,在[DataFrame.sample](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.sample.html)方法中有一个错误导致了虚假的SettingWithCopy警告。sample方法现在每次都返回一个副本。

深度链式赋值

让我们重新使用之前的例子,我们试图用'parakeet2004'bidder值更新data中每一行的bidderrate列。

pandas 用这个SettingWithCopyWarning真正告诉我们的是,我们代码的行为是不明确的,但是要理解为什么是这样以及警告的措辞,回顾一些概念将是有帮助的。

我们之前简单地讨论了视图和副本。有两种方法可以访问一个DataFrame的子集:要么在内存中创建一个对原始数据的引用(一个视图),要么将子集复制到一个新的、更小的DataFrame(一个副本)。视图是查看原始数据特定部分的一种方式,而副本是数据在内存中新位置的 T21 克隆。正如我们前面的图表所示,修改视图会修改原始变量,但修改副本不会。

由于我们将在后面讨论的原因,熊猫的“get”操作的输出不能保证。当您索引一个 pandas 数据结构时,可能会返回一个视图或一个副本,这意味着对一个DataFrame的 get 操作会返回一个新的DataFrame,其中可能包含:

  • 原始对象中数据的副本。
  • 对原始对象数据的引用,但不制作副本。

因为我们不知道会发生什么,每种可能性都有非常不同的行为,忽视警告是在玩火。

为了更清楚地说明视图、副本和这种模糊性,让我们创建一个简单的DataFrame并将其编入索引:

让我们将df1的子集分配给df2:

根据我们所了解的,我们知道df2可能是df1上的一个视图,或者是df1的一个子集的副本。

在我们着手解决这个问题之前,我们还需要再看一看链式索引。用'parakeet2004'扩展我们的例子,我们将两个索引操作链接在一起:

其中__intermediate__代表第一次调用的输出,对我们完全隐藏。请记住,如果我们使用属性访问,也会得到同样有问题的结果:

这同样适用于任何其他形式的链式调用**,因为我们正在生成这个中间对象**。

实际上,链式索引意味着不止一次调用__getitem____setitem__来完成一个操作。这些是特殊的 Python 方法,通过在实现它们的类的实例上使用方括号来调用,这是所谓的语法糖的一个例子。让我们看看 Python 解释器将在我们的例子中执行什么。

您可能已经意识到,SettingWithCopyWarning是这个链式__setitem__调用的结果。您可以自己尝试一下——上面几行的功能完全相同。为了清楚起见,请注意第二个__getitem__调用(针对bidder列)是嵌套的,根本不属于这里的链接问题。

一般来说,如前所述,pandas 不保证 get 操作将返回数据的视图还是副本。如果在我们的例子中返回一个视图,那么我们的链式赋值中的第二个表达式将是对原始对象的__setitem__调用。但是,如果返回一个副本,将被修改的是该副本——原始对象不会被修改。

这就是警告所说的“试图在数据帧的切片副本上设置值”的含义。由于没有对该副本的引用,它最终将被垃圾收集。SettingWithCopyWarning让我们知道 pandas 不能确定第一个__getitem__调用返回的是视图还是副本,因此不清楚赋值是否改变了原始对象。另一种思考熊猫为什么给我们这个警告的方式是因为“我们在修改原作吗?”是未知的。

我们确实想修改原始操作,警告建议的解决方案是使用loc将这两个独立的链式操作转换成一个赋值操作。这将从我们的代码中删除链式索引,我们将不再收到警告。我们的固定代码及其扩展版本将如下所示:

我们的 DataFrame 的loc属性保证是原始的DataFrame本身,但是具有扩展的索引功能。

假阴性

使用loc并不能解决我们的问题,因为使用loc的 get 操作仍然可以返回视图或副本。让我们快速检查一个有点复杂的例子。

这次我们抽出了两列,而不是一列。让我们尝试设置所有的bid值。

没有效果也没有警告!我们在一个切片的拷贝上设置了一个值,但熊猫没有检测到它—这是一个假阴性。仅仅因为我们使用了loc并不意味着我们可以再次开始使用链式赋值。GitHub 上有一个关于这个特殊 bug 的旧的未解决的问题。

正确的做法如下:

您可能想知道在实践中怎么可能有人会遇到这样的问题,但是当我们在下一节中将DataFrame查询的结果赋给变量时,这比您想象的要容易。

隐藏链接

让我们再来看看前面的隐藏链接示例,我们试图从我们的winners变量中标有304的行中设置bidder值。

即使我们使用了loc,我们还是得到了另一个SettingWithCopyWarning。这个问题非常令人困惑,因为警告信息似乎在建议我们做我们已经做过的事情。

但是想想winners这个变量。到底是什么?假设我们通过data.loc[data.bid == data.price]实例化了它,我们无法知道它是视图还是原始dataT5 的副本(因为 get 操作要么返回视图,要么返回副本)。将实例化与生成警告的代码行结合起来,可以清楚地看出我们的错误。

我们再次使用了链式赋值,但是这次它被分成了两行。思考这个问题的另一种方式是问这样一个问题“这是修改了一个还是两个东西?”在我们的例子中,答案是未知的:如果winners是一个副本,那么只有winners受到影响,但是如果它是一个视图,winnersdata都将显示更新的值。这种情况可能发生在脚本或代码库中相距很远的代码行之间,使得问题的根源很难追踪。

这里警告的目的是防止我们认为我们的代码会修改原来的DataFrame,而实际上它不会,或者我们正在修改一个副本而不是原来的。深入研究熊猫 GitHub repo 的老问题,你可以阅读开发者自己对此的解释。

我们如何解决这个问题在很大程度上取决于我们自己的意图。如果我们乐于使用原始数据的副本,解决方案就是简单地强迫熊猫制作一个副本。

另一方面,如果您要求更新原始的DataFrame,那么您应该使用原始的DataFrame,而不是实例化具有未知行为的其他变量。我们之前的代码会变成:

在更复杂的情况下,例如修改一个DataFrame的子集的子集,而不是使用链式索引,可以通过在原始DataFrame上的loc修改正在制作的切片。例如,您可以更改上面的新winner_mask变量,或者创建一个新变量来选择获胜者的子集,如下所示:

这种技术对于未来的代码库维护和扩展更加健壮。

历史

您可能想知道为什么不能通过显式地指定返回视图或副本的索引方法来完全避免整个SettingWithCopy问题,而不是制造我们发现自己所处的混乱局面。为了理解这一点,我们必须了解熊猫的过去。

pandas 用来确定它是返回一个视图还是一个副本的逻辑源于它对 NumPy 库的使用,这是 pandas 操作的基础。观点实际上是通过 NumPy 进入熊猫词典的。事实上,视图在 NumPy 中非常有用,因为它们是可预测地返回的。因为 NumPy 数组是单一类型的,pandas 试图通过使用最合适的数据类型来最小化空间和处理需求。因此,包含单个 dtype 的DataFrame的片可以作为单个 NumPy 数组上的视图返回,这是处理操作的高效方式。然而,在 NumPy 中,多数据类型片不能以同样的方式高效地存储。Pandas 将通用的索引功能与最有效地使用其 NumPy 内核的能力结合在一起。

最终,pandas 中的索引被设计成有用和通用的,其核心并不完全结合底层 NumPy 数组的功能。随着时间的推移,设计和功能的这些元素之间的相互作用导致了一组复杂的规则,这些规则决定了视图或副本是否可以被返回。有经验的 pandas 开发人员通常对 pandas 的行为感到满意,因为他们可以轻松地导航其索引行为。

不幸的是,对于库的新手来说,链式索引几乎是不可避免的,尽管这并不是想要的方法,因为 get 操作返回可索引的 pandas 对象。更进一步,用熊猫几年的核心开发者之一 Jeff Reback 的话说,“从语言的角度来说,直接检测链式索引根本不可能;必须推断出来”。

因此,该警告在 2013 年底的版本 0.13.0 中引入,作为许多开发人员遇到的链式分配的静默失败的解决方案。

在 0.12 版本之前,[ix](http://pandas.pydata.org/pandas-docs/version/0.19.2/generated/pandas.DataFrame.ix.html) 索引器是最流行的(在 pandas 命名法中,ixlociloc等“索引器”是简单的构造,允许对象像数组一样用方括号索引,但具有特殊的行为)。但是大约在这个时候,也就是 2013 年年中,熊猫项目开始获得动力,迎合新手用户变得越来越重要。从这个版本开始,lociloc索引器因其更清晰的本质和更容易解释的用法而更受青睐。

Google Trends: pandas

在推出之后,SettingWithCopyWarning一直在继续发展,几年来在许多 GitHub 问题上被热烈讨论,甚至现在还在更新,但是它还在这里,理解它对于成为熊猫专家仍然至关重要。

包扎

隐藏在SettingWithCopyWarning背后的复杂性是熊猫库中为数不多的粗糙边缘之一。它的根源深深植根于图书馆,不应该被忽视。用 Jeff Reback 自己的话来说,“就我所知,没有任何情况下你应该忽略这个警告。...如果你做某些类型的索引,它永远不会工作,其他的它会工作。你真是在玩火。”

幸运的是,解决这个警告只需要您识别链式赋值并修复它。如果说我们能从这一切中吸取什么的话,那就是。

原文 发表 data quest

了解 SSD 多盒—深度学习中的实时对象检测

原文:https://towardsdatascience.com/understanding-ssd-multibox-real-time-object-detection-in-deep-learning-495ef744fab?source=collection_archive---------0-----------------------

Example of end-to-end object detection (from Microsoft)

这篇文章旨在直观地解释固态硬盘多盒物体检测技术。我试图将数学最小化,而是慢慢地引导你理解这个架构的原则,包括解释多盒算法的作用。看完这篇文章后,我希望你对 SSD 有更好的了解,并亲自试用它!

自从 AlexNet 在 2012 ImageNet 大规模视觉识别挑战赛(ILSVRC)上席卷研究界以来,深度学习已经成为图像识别任务的首选方法,远远超过了文献中使用的更传统的计算机视觉方法。在计算机视觉领域,卷积神经网络擅长图像分类,它包括对图像进行分类,给定一组(例如猫、狗),并让网络确定图像中存在的最强的类。

Images of cats and dogs (from kaggle)

如今,深度学习网络在图像分类方面比人类更好,这表明了这项技术的强大。然而,我们人类在观察世界和与世界互动时,不仅仅是对图像进行分类。我们还定位分类我们视野内的每个元素。这些任务要复杂得多,机器仍然难以像人类一样完成。事实上,我认为当物体检测表现良好时,会使机器更接近真实场景的理解。

Does the image show cat, a dog, or do we have both? (from kaggle)

区域卷积神经网络(R-CNN)

几年前,通过利用 CNN 在计算机视觉中实现的一些飞跃,研究人员开发了 R-CNN 来处理对象检测、定位和分类的任务。概括地说,R-CNN 是一种特殊类型的 CNN,能够定位和检测图像中的对象:输出通常是一组与每个检测到的对象紧密匹配的边界框,以及每个检测到的对象的类输出。下图显示了典型的 R-CNN 的输出:

Example output of R-CNN

在这个领域有一个详尽的论文列表,对于任何渴望进一步探索的人,我建议从以下围绕该主题的论文“三部曲”开始:

  • 美国有线电视新闻网
  • 美国有线电视新闻网
  • 更快-R-CNN

正如你可能已经猜到的,接下来的每篇论文都提出了对 R-CNN 所做的开创性工作的改进,以开发更快的网络,目标是实现实时物体检测。通过这组工作展示的成就确实令人惊讶,然而这些架构中没有一个能够创建实时对象检测器。在不涉及太多细节的情况下,确定了上述网络的以下问题:

  • 训练数据既麻烦又耗时
  • 训练发生在多个阶段(例如,训练区域提议与分类器)
  • 推断 时间(即处理非训练数据时)网络太慢

幸运的是,在过去几年中,新的架构被创建来解决 R-CNN 及其后继者的瓶颈,实现实时对象检测。最著名的有 YOLO (你只看一次)和 SSD MultiBox(单发探测器)。在本帖中,我们将讨论 SSD,因为关于这种架构的报道似乎比 YOLO 少。此外,一旦你了解了固态硬盘,你应该会发现更容易掌握 YOLO。

单发多盒探测器

关于SSD:Single Shot multi box Detector(作者 C. Szegedy 等人)的论文于 2016 年 11 月底发布,并在对象检测任务的性能和精度方面创下新纪录,在标准数据集如 PascalVOC 和 COCO 上以每秒 59 帧的速度获得超过 74%的 mAP ( 均值 平均精度)。为了更好地理解 SSD,我们先来解释一下这种架构的名称来源:

  • **单镜头:**这意味着物体定位和分类的任务是在网络的单次 前向传递中完成的
  • 多框:这是 Szegedy 等人开发的一种包围盒回归技术的名字(我们将很快简要介绍)
  • **检测器:**网络是一个对象检测器,它也对那些检测到的对象进行分类

体系结构

Architecture of Single Shot MultiBox detector (input is 300x300x3)

从上图中可以看出,SSD 的架构建立在古老的 VGG-16 架构之上,但抛弃了完全连接的层。VGG-16 被用作基础网络的原因是它在高质量图像分类任务中的强大性能,以及它在解决转移学习有助于改善结果的问题中的受欢迎程度。取代原来的 VGG 全连接层,增加了一组辅助卷积层(从 conv6 开始),从而能够在多个尺度上提取特征,并逐渐减小每个后续层的输入大小。

VGG architecture (input is 224x224x3)

多框

SSD 的边界框回归技术受到 Szegedy 在多框上的工作的启发,这是一种快速类不可知边界框坐标提议的方法。有趣的是,在 MultiBox 上完成的工作中,使用了 Inception 风格的卷积网络。您在下面看到的 1x1 卷积有助于降维,因为维度的数量会减少(但“宽度”和“高度”将保持不变)。

Architecture of multi-scale convolutional prediction of the location and confidences of multibox

MultiBox 的损失功能还结合了进入 SSD 的两个关键组件:

  • 置信度损失:测量网络对计算边界框的对象的置信度。分类交叉熵用于计算这种损失。
  • **位置损失:**这度量了距离多远网络的预测边界框与训练集中的地面真实边界框有多远。这里使用的是 L2 规范。

在不深究数学的情况下(如果你很好奇,想要一个更精确的符号,请阅读这篇论文),损失的表达式是这样的,它衡量我们的预测“着陆”有多远:

多框 _ 损失=置信度 _ 损失+阿尔法位置 _ 损失*

α项帮助我们平衡位置损失的贡献。像通常在深度学习中一样,目标是找到最佳地减少损失函数的参数值,从而使我们的预测更接近地面事实。

多箱前科和欠条

围绕边界框生成的逻辑实际上比我前面所说的更复杂。但不要害怕:它仍然触手可及。

在 MultiBox 中,研究人员创建了我们所谓的 priors (或 fast-R-CNN 术语中的锚点),它们是预先计算好的固定大小的边界框,与原始地面真相框的分布紧密匹配。事实上,那些先验是以这样一种方式选择的,即它们的交集/并集比(又名 IoU,有时也称为 Jaccard index )大于 0.5。正如您可以从下图中推断的那样,IoU 为 0.5 仍然不够好,但它确实为边界框回归算法提供了一个强有力的起点-这是一个比用随机坐标开始预测好得多的策略!因此,多框以先验作为预测开始,并试图回归更接近真实边界框。

Diagram explaining IoU (from Wikipedia)

所得到的架构(再次检查上面的多盒架构图以供参考)每个特征地图单元包含 11 个先验(8×8、6×6、4×4、3×3、2×2)并且在 1×1 特征地图上只有一个先验,导致每幅图像总共有 1420 个先验,从而能够以多种比例稳健地覆盖输入图像,以检测各种大小的对象。

最后,MultiBox 仅保留使位置( LOC )和置信度( CONF )损失最小化的前 K 个预测。

固态硬盘的改进

回到 SSD,增加了一些调整,使这个网络更有能力定位和分类对象。

**固定先验:**与多框不同,每个特征映射单元都与一组不同尺寸和纵横比的默认边界框相关联。这些先验是手动(但仔细)选择的,而在 MultiBox 中,选择它们是因为它们相对于地面真值的 IoU 超过 0.5。这在理论上应该允许 SSD 针对任何类型的输入进行推广,而不需要针对前一代的预训练阶段。例如,假设我们已经为每个 b 默认边界框配置了 2 个对角相对的点 (x1,y1)(x2,y2) 以及 c 类进行分类,在给定大小为f =mn*的特征图上,SSD 将计算 f *

SSD default boxes at 8x8 and 4x4 feature maps

位置损失: SSD 使用平滑 L1 范数计算位置损失。虽然不像 L2 范数那样精确,但它仍然非常有效,并给 SSD 更多的操作空间,因为它不会试图在其边界框预测中做到“像素完美”(即,几个像素的差异对我们许多人来说很难察觉)。

分类: MultiBox 不执行对象分类,而 SSD 执行。因此,对于每个预测的边界框,为数据集中每个可能的类计算一组 c 类预测。

培训和运行固态硬盘

数据集

您将需要带有地面真实边界框和分配的类标签(每个边界框只有一个)的训练和测试数据集。Pascal VOC 和 COCO 数据集是一个很好的起点。

Images from Pascal VOC dataset

默认边界框

建议配置不同比例和长宽比的一组不同的默认边界框,以确保可以捕捉大多数对象。SSD 文件中每个要素地图像元大约有 6 个边界框。

特征地图

特征图(即卷积块的结果)是图像在不同比例下的主要特征的表示,因此在多个特征图上运行多框增加了任何物体(大的和小的)最终被检测、定位和适当分类的可能性。下图显示了网络如何通过其要素地图“看到”给定图像:

VGG Feature Map Visualisation (from Brown Uni)

硬负开采

在训练期间,由于大多数边界框将具有低 IoU,因此被解释为训练示例,我们可能会在训练集中以不成比例数量的负示例结束。因此,不要使用所有的负面预测,建议保持负面与正面的比例在 3:1 左右。之所以需要保留阴性样本,是因为网络也需要学习并被明确告知什么构成了不正确的检测。

Example of hard negative mining (from Jamie Kang blog)

数据扩充

SSD 的作者表示,与许多其他深度学习应用一样,数据增强对于教会网络变得对输入中的各种对象大小更加鲁棒至关重要。为此,他们使用不同 IoU 比率(例如,0.1、0.3、0.5 等)的原始图像的补丁来生成额外的训练示例。)和随机补丁。此外,每个图像还以 0.5 的概率随机水平翻转,从而确保潜在的对象以相似的可能性出现在左侧和右侧。

Example of horizontally flipped image (from Behavioural Cloning blog post)

非最大抑制(NMS)

假设在推理时间 SSD 的向前传递期间产生大量的盒子,通过应用被称为非最大值抑制的技术来修剪大部分边界盒子是必要的:置信损失阈值小于 ct (例如 0.01)并且 IoU 小于 lt (例如 0.45)的盒子被丢弃,并且仅顶部的 N 预测被保留。这确保了网络只保留最有可能的预测,而去除更嘈杂的预测。

NMS example (from DeepHub tweet)

固态硬盘的附加说明

SSD 文件提出了以下附加意见:

  • 默认框越多,检测就越准确,尽管对速度有影响
  • 由于检测机在多个分辨率的要素上运行,因此在多个图层上使用多盒子也能实现更好的检测
  • 80%的时间花在基本的 VGG-16 网络上:这意味着如果有更快和同样准确的网络,SSD 的性能可能会更好
  • SSD 混淆了具有相似类别的对象(例如动物)。这可能是因为多个类共享位置
  • SSD-500(使用 512x512 输入图像的最高分辨率变体)在 Pascal VOC2007 上实现了 76.8%的最佳 mAP,但以速度为代价,其帧速率降至 22 fps。因此,SSD-300 是一个更好的折衷方案,在 59 fps 时具有 74.3 的 mAP。
  • SSD 在较小的对象上产生较差的性能,因为它们可能不会出现在所有的要素地图上。提高输入图像分辨率可以缓解这个问题,但不能完全解决它

玩 SSD

网上有一些 SSD 的实现,包括来自本文作者的原始 Caffe 代码。在我的例子中,我选择了 Paul Balanç的 TensorFlow 实现,可以在 github 上获得。为了更好地理解所有东西是如何组合在一起的,阅读代码和文章是值得的。

我最近还决定重新实施一个使用传统计算机视觉技术的车辆检测项目,这次采用 SSD。我使用 SSD 输出的一个小 gif 显示它工作得非常好:

GIF of vehicle detection Using SSD

超越固态硬盘

这一领域的最新研究成果已经问世,我建议有兴趣在这一领域进一步拓展知识的人继续阅读以下两篇论文:

  • YOLO9000:更好更快更强(那是论文的题目;不开玩笑)
  • 屏蔽 R-CNN :像素级非常精确的实例分割

瞧啊。我们已经完成了单次多盒探测器的参观。我试图用简单的术语来解释这种技术背后的概念,尽我所能地理解它们,并用许多图片来进一步说明这些概念并促进您的理解。我真的建议你读读报纸(如果你像我一样反应迟钝的话,可能要读几遍)🙃),包括在这项技术的一些数学背后形成良好的直觉,以巩固你的理解。如果这篇文章的某些部分有助于你理解这篇文章,你可以随时查看。一路平安!

感谢你阅读这篇文章。希望你觉得有用。我现在正在建立一个新的创业公司,叫做 EnVsion !在 EnVsion,我们正在为 UX 的研究人员和产品团队创建一个中央存储库,以从他们的用户采访视频中挖掘见解。当然我们用人工智能来做这个。).

如果你是 UX 的研究人员或产品经理,对与用户和客户的视频通话感到不知所措,那么 EnVsion 就是为你准备的!

你也可以关注我的 推特

理解数据科学中的主观性

原文:https://towardsdatascience.com/understanding-subjectivity-in-data-science-70a25b2ea39f?source=collection_archive---------12-----------------------

在一个完美的世界中,数据科学家在检查发现时会将主观性从他们的结论中剔除。

然而,在人们意识到发生了什么之前,偏见就已经悄然而至。意识到可能的主观性允许研究人员在相对确信其尽可能客观之前,努力将其最小化,并且不发表他们的工作。

人类是会犯错的

一个常见的思路是,仅仅在研究中使用大数据工具就可以消除偏见。但是,尽管这些进步将众多信息流汇集在一起进行分析,但人类仍然在该过程的各个阶段参与收集数据——人类天生就是主观的。

2016 年 9 月的一项研究希望利用大数据建立一个影响全球文明的事件的综合集合。它发现美国和拉丁美洲的系统很少通过将它们注册为重要来复制相同的情况。

这是因为即使是最强大、最智能的大数据工具背后也有人,尤其是那些培训数据科学平台的人。由于人不是公正的存在,即使数据科学可以消除一些主观性,但人类天生就拥有它。

数据越多,找到支持材料就越容易

人们表现出确认偏差,这是一种倾向,即寻找支持某个观点的东西,而忽略冲突的信息。

数据科学的进步可能会恶化这一特征,因为它让个人能够访问大量数据,从而增加了他们找到支持他们观点的材料的可能性,只要他们足够努力地寻找。

如果发生这种情况,他们可能会发现将研究推向一个方向的信息,而忽略导致完全不同结论的相反发现。

主观数据是可变的

人们通过与他人交流获得主观数据。他们也可以通过基于通信做出假设和判断来收集信息。因此,数据的特征可能因人而异,甚至根据一个人在特定时刻的感受而变化。

相比之下,客观数据来自可验证的事实或事件,即使在多个来源之间也具有一致性。

主观数据包含个人解释的成分,而客观数据主要依赖于使用准确的细节来确认发生了什么或某人假设了什么。

主观性并不总是负面的。例如,某人可以主观地修改显示销售区域或类似信息的映射数据,以支持公司的需求,并使利益相关者更容易获得统计数据。

然而,使用映射数据来解释事物的人必须注意彻底解释变量,否则可能会使个人得出错误的结论。

例如,当收集的样本不能充分反映总体情况时,抽样偏差经常出现在研究中。

他们可以使用地图上的注释来阐明样本大小和用于收集信息的技术。这些额外的见解给人们提供了他们得出明智结论所需的知识。

主观性可能会忽视重要的现实

如前所述,人类倾向于关注支持他们信念的材料,而忽略不支持的材料。有时,这个问题意味着数据科学家没有注意到他们研究中隐藏的发现。

贫穷、服务不足的社区特别容易成为这个问题的受害者。例如,一个名为 Street Bump 的智能手机应用程序让波士顿居民在遇到坑洞时报告。这个想法是,来自应用程序的集体信息将让当地基础设施知道哪里存在最严重的问题,这个概念是有意义的。

然而,来自低收入社区的人怎么办?他们可能住在坑坑洼洼的地方,却买不起该应用程序所需的智能手机来简化报告过程。

大数据是在恶化种族偏见吗?

警察部门越来越依赖大数据来预测未来的犯罪,并找出如何在多个社区中最佳地分配警察。

然而,分析人士指出,种族偏见在执法部门非常普遍。研究表明,与非洲裔美国人和拉丁美洲人相比,警察不太可能阻止白人,即使这两个群体表现出相同的行为。

执法人员必须评估输入数据的所有特征,并确定输入数据的某些方面是否会教授算法来强调和延续种族偏见,而不是仅仅相信大数据的结果是准确的。

即使没有大数据平台,这样的事情也可能发生。例如,一个特定管辖区的官员可能会说,“我的经验告诉我,我因暴力犯罪而逮捕的非裔美国人比白种人多,”一个同事可能会说同样的话。

然而,仔细观察统计数据可以发现,非裔美国人在这些非法活动中只占一小部分,但官员们过于依赖个人经验,无法做出客观的结论。

努力减少有偏见的大数据

从科学家每天处理的信息数据中去除主观性是不可能的。

然而,一个负责任的数据科学家必须意识到这种偏见的存在,并有意识地尝试最小化它们,无论是通过检查数据中不太明显的方面,还是回答最重要的问题,“我是否忽略了什么?”

图像由 Rawpixel

支持向量机:完整理论

原文:https://towardsdatascience.com/understanding-support-vector-machine-part-1-lagrange-multipliers-5c24a52ffc5e?source=collection_archive---------0-----------------------

了解 SVM 系列:第一部分

在这篇文章中,我将介绍支持向量机分类器。这篇文章将是我将解释支持向量机(SVM)的系列文章的一部分,包括它背后所有必要的细节和数学。这很容易,相信我!没有任何延迟,让我们开始吧—

假设我们得到了蓝色星星和紫色心的这两个样本(只是为了示意性的表示,这里没有使用真实的数据),我们的工作是找出一条线来最好地分开它们。这里我们所说的最好是什么意思?

Figure 1: Samples in a 2D plane with some separation between them

我们来看下图。你能猜出哪条线能更好地分开这两个样本吗?

Figure 2: Lines (Hyperplanes?) that could potentially separate the two samples

是的,左边的红线比橙线好,因为,我们说红线在两组之间创造了'最宽的路'(边距)。见下图

Figure 3: Widest road approach for separating two groups

边界线(虚线)边缘的样本线,被称为'**支持向量'。**与右侧的样本相比,左侧有两个这样的样本(蓝色星星)。关于支持向量的几个要点是-

  1. 支持向量是最难分类的样本。
  2. 它们直接影响寻找决策边界(虚线)最佳位置的过程。
  3. 只有一个非常小的训练样本子集(支持向量)可以完全指定决策函数(一旦我们了解 SVM 背后的数学,我们将会看到更多细节)。
  4. 如果从数据集中移除支持向量,将有可能改变分割线 的位置(对于维数高于 2 的空间,该线称为超平面)。

我们已经认识到这是一个受约束的优化问题。优化 —因为,我们要找到支持向量分离最大的线约束— 因为,支持向量应该远离道路,而不是在道路上。我们将使用拉格朗日乘数来解决这个问题,所以让我们从一个非常简单的使用拉格朗日乘数的例子开始。

拉格朗日乘数:何时和如何使用

假设我们给定一个函数 f(x,y,z,…) ,我们想要找到它的极值,服从条件 *g(x,y,z,…)= k。*拉格朗日乘子中使用的思想是,目标函数 f 的梯度在一个最佳点上与约束 g 的梯度平行或反平行排列。在这种情况下,一个梯度应该是另一个梯度的倍数。让我们看一个例子——

使用拉格朗日乘数法,我们解决它如下

所以我们找到了函数的最大值和最小值,并且看到它有一个唯一的最小值,两个最大值和一个鞍点。如果我们画出这些函数 fg,,那么我们将更好地理解拉格朗日乘数的概念。

Figure 4: Visualizing Lagrange Multiplier Method

从上图我们可以清楚地体会到 约束函数 f 的极值,位于约束 g 的曲面上, 是一个单位半径的圆。这是一个必要条件。此外,函数和约束的切向量在每个极值处平行或反平行。用于这个情节的代码可以在我的 github 中找到。

我们现在准备深入 SVM 背后的数学,并成功地应用这一技术。

支持向量机的数学;

如果你忘记了问题陈述,让我再次提醒你。在图 1 中,我们要找到一条能最好地分离两个样品的线。我们考虑一个垂直于中线(红线)的向量(W)和一个未知样本,该样本可由向量 x. 表示

Figure 5: Determine on which side of the road a new sample X lies

为了确定未知样本 X 位于中线(红色实线)的哪一侧,我们首先取 X 沿中线垂线的投影,即 w 。如果这个投影大于某个数(称为偏差),那么我们说未知样本 X 在线的右侧。它通常被称为决策规则。让我们把它放进一个等式里

在这一点上,我们对数字 b 一无所知。我们对 w 也一无所知,只知道它垂直于中线。为了确定 wb ,我们现在考虑已知样本并坚持如下条件

因此,对于右边(左边)的已知样本,我们坚持判定规则(等式。1.4)大于(小于)或等于 1。对于边界线上的样本(支持向量),等号成立。接下来,我们的目标是用一个等式代替两个,为此,我们引入一个变量,它对右边的样本为正,对左边的样本为负。

随着这一新变量的引入,我们将把两个条件方程的 L.H.S .相乘。1.5)我们得到

我们将在这里强加的另一个条件(相当直观)是,对于槽(“支持向量”)上的样本,L.H.S 将正好为零。

*由于我们的主要目的是找到样本之间最宽的道路,*我们现在将继续定义两条平行线之间的距离(或道路的宽度)。

为此,我们首先在任一侧选择任意两个支持向量,并计算差向量

Figure 6: Difference of two support vectors

从上图可以了解到道路的宽度将是这个差向量与一个垂直于道路的单位向量的点积。

但是等等!我们已经定义了一个垂直于最佳直线的矢量,即 w. ,因此我们准备将道路的距离公式化为

我们能简化这个等式吗?让我们回头看看情商。1.8,看看能不能想出点什么。

使用 eq。1.8 并且利用 y 对于右边的样本为正,对于左边的样本为负的事实,我们可以将等式 1.9 简化为

因为我们想要最大化道路的宽度,我们现在的整个问题可以归结为一个非常重要的信息—

牢记我们之前的约束条件,即 eq。1.8.

因此,我们不再像以前那样凭直觉,现在我们可以从数学上理解,找到最佳线路确实是一个约束优化问题。

我们现在准备应用我们对拉格朗日方法的理解。

首先,取决于支持向量的数量,将有几个约束,因此包含乘数的约束项将是

我们想要最小化的拉格朗日量,可以写成

扩展表达式,

现在,在开始最小化之前,我们应该确定变量 w.r.t .,我们将对其进行拉格朗日微分,并将其设置为零。如果你记住了问题陈述,回到 eq。1.4.,我们看到向量 w 和偏差 b 是独立变量。因此

标量微分和往常一样,但矢量微分是在标量上执行的,首先是垂直矢量的大小,其次是支持矢量和法向矢量的点积。向量微分的后一项很容易解决,对第一项来说很直观,我想给你们一个提示

使用这个我们可以最终写出如下结果

到目前为止,上述结果在这篇文章中是最重要的,我们已经发现**法向量( w )是支持向量的线性组合。**我们将使用这个条件来得到我们的决策规则,但是让我们意识到我们已经减少了公式中的另一个问题,那就是——因为等式的条件。1.16.现在我们可以去掉 w 和 b,取而代之的是只用拉格朗日乘数。所以我们从等式中使用这些条件。1.16,并尽量简化 eq。1.13

让我们进一步简化这个表达式

最后,我们在文章末尾发现最大化将只取决于支持向量对的点积。多棒啊!!!!

一个更有趣的结果可以得到,一旦我们把 w 放回去,我们从等式。1.16.决策规则,即等式。1.4 我们得到

因此,新样本是否将位于道路右侧取决于支持向量和未知样本的点积(这里由向量 u 表示)。

本质上,与 SVM 相关的一切都依赖于样本的简单点积,这对我来说是令人兴奋的。希望它也能给你提供一些思考的素材。

让我们总结一下我们学到的最重要的两点

  1. 通过简单的直觉和严格的数学,我们知道 SVM 问题是约束最小化问题。
  2. 我们学习了求解约束优化问题的简单拉格朗日方法,并成功地应用于开发 SVM 算法。

下面是我下一篇关于 SVM 背后的数学以及使用 python 和 scikit-learn 的应用的文章的链接。

第二贴: 内核绝招&默塞尔定理

第三贴: 现实生活中 SVM 的例子

第四帖: 标图决定功能为

保持坚强!干杯!!

如果你对更深入的基础机器学习概念感兴趣,可以考虑加盟 Medium 使用 我的链接 。你不用额外付钱,但我会得到一点佣金。感谢大家!!

[## 通过我的推荐链接加入媒体

更多来自 Saptashwa(以及媒体上的所有其他作者)。你的会员费直接支持 Saptashwa 和其他作家…

medium.com](https://medium.com/@saptashwa/membership?source=publishing_settings-------------------------------------)

支持向量机:核技巧;默瑟定理

原文:https://towardsdatascience.com/understanding-support-vector-machine-part-2-kernel-trick-mercers-theorem-e1e6848c6c4d?source=collection_archive---------2-----------------------

了解 SVM 系列:第二部分

先决条件:1。关于支持向量机算法的知识,我在的上一篇文章中已经讨论过了。2.代数的一些基础知识。

在本系列的第一部分中,从支持向量的数学公式中,我们发现了 SVM 的两个重要概念,它们是

  • SVM 问题是一个约束最小化问题,我们已经学会了使用拉格朗日乘数法来处理这个问题。
  • 为了找到不同样本之间的最宽路径,我们只需要考虑支持向量和样本的点积。

在 SVM 的上一篇文章中,我举了一个简单的线性可分样本的例子来演示支持向量分类器。如果我们有一个如下的样本集,会发生什么?

Blue and Red samples all over the place !!!! At least it seems like (Source: Author)

该图使用sklearn.的内置make_circles 数据集生成

import numpy as np 
import sklearn 
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_circlesX,y = make_circles(90, factor=0.2, noise=0.1) 
#noise = standard deviation of Gaussian noise added in data. 
#factor = scale factor between the two circlesplt.scatter(X[:,0],X[:,1], c=y, s=50, cmap='seismic')
plt.show()

如你所知,在这个 2d 图中不可能画出一条线来区分蓝色样品和红色样品。我们还有可能应用 SVM 算法吗?

如果我们给这个 2d 空间一点震动,红色样本飞离平面,看起来与蓝色样本分离,会怎么样?看一看!

After ‘shaking’ the data samples now it seems there is a great possibility of classification! Find the code in my github (Source: Author)

看来摇动数据样本确实有效,现在我们可以很容易地画一个平面(而不是我们以前使用的线)来分类这些样本。那么在摇晃过程中到底发生了什么呢?

当我们没有如上例的线性可分训练数据集时(在现实生活中,大多数数据集都相当复杂),内核技巧就派上用场了。其思想是将非线性可分离数据集映射到一个更高维的空间,在那里我们可以找到一个可以分离样本的超平面。

因此,这一切都是为了找到将 2D 输入空间转换为 3D 输出空间的映射函数。或者是?内核技巧到底是什么?

从上一篇关于支持向量的帖子中,我们已经看到(请查看理解数学公式)最大化只取决于支持向量的点积,

不仅如此,由于决策规则还依赖于支持向量和新样本的点积

这意味着,如果我们使用映射函数将数据映射到更高维度的空间,那么,最大化和决策规则将取决于不同样本的映射函数的点积,如下所示

瞧啊。!如果我们有一个函数 K 定义如下

那么我们只需要知道 K 而不是映射函数本身。这个函数被称为核函数,它降低了寻找映射函数的复杂性。所以,核函数在变换空间定义了内积。

让我们看看一些最常用的内核函数

我已经使用径向基函数核绘制了图 2,其中从 2D 空间到 3D 空间的映射确实有助于我们分类。

除了这个预定义的内核,*哪些条件决定了哪些函数可以被认为是内核?这是由**默瑟定理给出的。第一个条件相当简单,即内核函数必须对称。**作为核函数是点积(内积)*的映射函数我们可以写成如下——

Mercer 定理给出了函数是核函数的充要条件。理解这个定理的一种方式是—

**换句话说,在有限输入空间中,如果核矩阵(也称为 Gram 矩阵)是正半定的那么,矩阵元素即函数 K 可以是核函数。**因此 Gram matrix 将学习算法所需的所有信息、数据点和映射函数合并成内积。

让我们看一个从核函数中找到映射函数的例子,这里我们将使用高斯核函数

调谐参数

既然我们已经讨论了非线性核,特别是高斯核(或 RBF 核),我将以对 SVM 中的一个调整参数—γ的直观理解来结束这篇文章。

观察 RBF 核,我们看到它取决于两点之间的欧几里德距离,即如果两个向量越近,则该项越小。由于方差总是正的,这意味着对于较近的向量,RBF 核比较远的向量分布更广。当 gamma 参数较高时,核函数值会较小,即使对于两个邻近的样本也是如此,这可能导致复杂的判定边界或引起过拟合。你可以在我的另一篇文章中读到更多。

Example of over-fitting and complex decision boundary with high values of gamma. Image Courtesy : [Chris Albon]

在结束讨论之前,让我们回顾一下到目前为止我们在本章中学到了什么

  1. 将数据点从低维空间映射到高维空间可以使得即使对于非线性数据样本也可以应用 SVM。
  2. 我们不需要知道映射函数本身,只要知道核函数即可; 内核绝招
  3. 函数被认为是核函数的条件;半正定格拉姆矩阵。
  4. 最常用的内核类型。
  5. 调节参数γ如何导致 RBF 核的过度拟合或偏差。

希望你喜欢这篇文章,在下一章,我们将看到一些使用 SVM 算法的机器学习例子。

SVM 算法背后的完整数学在这里讨论:

[## 支持向量机:完整理论

SVM 的决策规则

towardsdatascience.com](/understanding-support-vector-machine-part-1-lagrange-multipliers-5c24a52ffc5e)

关于绘制和理解支持向量机决策边界的更多信息,请查看这篇文章:

[## 用 Python 实现流水线中的主成分分析和 SVM

管道、网格搜索和等高线图

towardsdatascience.com](/visualizing-support-vector-machine-decision-boundary-69e7591dacea)

保持坚强!干杯!!

如果你对更深入的基础机器学习概念感兴趣,可以考虑加盟 Medium 使用 我的链接 。你不用额外付钱,但我会得到一点佣金。感谢大家!!

[## 每当 Saptashwa Bhattacharyya 发表文章时,收到一封电子邮件。

每当 Saptashwa Bhattacharyya 发表文章时,收到一封电子邮件。通过注册,您将创建一个中等帐户,如果您没有…

medium.com](https://medium.com/subscribe/@saptashwa?source=publishing_settings-------------------------------------)

参考资料:

  1. “统计学习的要素”;Hastie,t .等人;亚马逊链接
  2. ”内核的属性”;伯克利大学;pdf 。
  3. “内核”;麻省理工学院讲稿。

用 Dialogflow 理解基本的对话式人工智能概念

原文:https://towardsdatascience.com/understanding-the-basic-conversational-ai-concepts-with-dialogflow-b0604d957d5c?source=collection_archive---------8-----------------------

这是一个初学者指南,旨在理解围绕设计对话和使用 Google Dialogflow 实现对话的不同概念。其他对话式人工智能工具使用相同的概念,因此这些应该可以转移到任何平台。我使用过各种各样的机器人构建器,在我看来,Dialogflow 是最容易快速创建简单机器人或非程序员的工具。本概述涵盖了如何创建意图及其组成的不同部分,培训您的机器人,以及其他有助于使用 Dialogflow 的有用提示。

在将你的第一个机器人实现到 dialogflow 之前,最好先绘制出对话流,就像思维导图一样。当一些对话可能会很长并且很难跟上时,拥有这种观想将会派上用场。注意:下面的截图来自 Dialogflow,用例是针对内部业务流程助理的。

创作意图

意图用于定义当机器人获得用户的意图时,或者当您希望基于其他事件触发响应时,您希望机器人做出什么响应。基本上,如果一个用户说 X,我们希望我们的机器人用 y 来回应。

话语——或训练短语

这些是用户所说的被机器人理解为某种意图的短语。许多不同的短语可能实际上描述了该短语的同一个动机。例如:“我需要找人”,“我在找人帮忙…”和“你能帮我找一个人吗?”是指用户想要找到一个人的所有话语。最好在一个意图中有大约 10 个不同的短语,作为自然语言理解(NLU)引擎的良好基础。在此基础上,Dialogflow 可以自信地连接来自用户的新短语和最接近的意图。我们永远无法真正假设我们会知道我们的用户会为每一个意图说话的每一种方式,所以这就是利用谷歌的 NLU 功能真正帮助我们的地方。

此外,对于后续对话,你可能只需要非常简单的话语,如是或否,并将其与上下文相关联,但我们将在稍后讨论。

Example of training phrases in Dialogflow

实体

实体是用户输入的一部分,它描述了一些有用的信息,Dialogflow 可以从中提取并执行操作。例如,如果用户输入“我想找人帮我修车”,其意图将是找人,主题的实体将被选择为汽车。要定义一个新的实体,您需要在 Dialogflow 中的 entity 部分定义一组在一个实体中具有相同目的的相关信息。

还有一些系统定义的实体,比如位置、日期、数字等等,您可以加以利用。

Entities in the definition screen and when they are being picked up inside user phrases

响应—标准

这些是当一个意图匹配时,您的 bot 服务将发送回用户的响应。以某种方式确认响应中的意图是很好的,比如“好的,所以你想找到一个人……”,这样用户就可以看到机器人确实理解他们所说的话。如果你想每次都给人一种稍微不同的体验,你可以给一个意图添加不同的回答,dialogflow 会随机选择一个。如果您希望在同一个输出中显示多个单独的消息,可以通过添加文本响应模块来实现。

响应——特定于渠道的丰富消息

要利用通道独特的消息传递功能,您可以通过选择+图标并选择您喜欢的通道,在响应部分添加该功能。您还可以选择让这些特定于通道的响应取代标准响应,或者将其添加到总输出中。特定于渠道的响应通常包括易于使用的富 UI 消息类型,包括按钮、卡片和图像等元素。例如在 Slack 中,我经常使用快速回复给用户一个选项列表和卡片来显示图片和/或链接。这些使得用户的体验更加容易。

An example of a rich UI element, Quick Replies, and the slack tab in responses

如果你想跨频道做任何丰富的 UI,或者做任何更加定制化的事情,那么你必须利用定制有效载荷响应选项,或者在实现中对它进行编码。您可以在 dialogflow 文档中了解更多信息。

这些丰富的 UI 元素在 slack 中是什么样子的:

参数

参数与用户输入中的实体相关联,可用于在履行中执行某些动作或用于响应。通过在参数部分中定义一个实体,意味着它们可以在该意图中用作变量。您还可以将一个参数设置为强制参数,机器人会询问后续问题,直到给出合适的答案。如果查找一个人的意图需要一个主题参数,对话流将询问“你到底要找谁?”所以它能给出一个合适的答案。您可以通过勾选该字段将参数设置为强制参数;如果你这样做,你还需要写下必要的跟进问题。

Parameters in the intent window

**注意:**有一个已知的问题是,如果用户不理解后续问题,并且回答与所需实体不匹配的响应,那么机器人会无休止地循环相同的问题。所以如果你要用这个,最好把问题弄清楚。

您可以通过编写$和参数名在响应中使用该参数

Calling a parameter in a response

实体和参数是一回事吗??为什么两者都有?参数与实体值相关联,但是有时您可能希望跟踪意图对话中的多个参数,并且所有这些参数可能是一个实体的不同情况。例如,在两个意图中,您可能希望找出某件事情的开始日期和结束日期,这将是两个不同的参数,都对应于一个“日期”实体。

语境——进行更长的对话

上下文用于跟踪用户在对话中的位置。它们代表当前状态。要使一个意图跟随另一个意图,可以从第一个意图创建一个输出上下文,并将相同的上下文放在第二个意图的输入上下文字段中。您可以同时使用多个上下文。每个上下文旁边的数字对应于您希望上下文持续的响应数量,这是可以更改的。如果您想让上下文在某个意图之后不再继续,您可以将它放在传出上下文中,并将数字设置为 0。

上下文还保存在该上下文中定义的参数,所以您可以在以后再次使用它们,但是我还没有对此进行过实验。

An example of an output context

事件

当您希望机器人在没有用户输入但发生特定事件时被触发时,例如,如果您希望机器人在某人第一次开始聊天时或可能在每天中午 12 点时说些什么,则可以使用这些。

命名意图

最佳实践是描述用户的意图。可以用空格。名称越明显越好,因为各种后端用户可能需要解释这些意图的内容。

例如,如果用户想为某个主题找到合适的人,名称可以是“查找一个人”

如果在较长的对话中有后续意图,最好在命名约定中表明这一点(我建议不要使用实际的“后续”意图,因为它们不灵活),所以如果你在较长的对话中,你可以做类似“餐厅->预订->确认”的事情。使用像“Q1”、“Q2”这样的系统…..对于机器人的工程师来说,一系列问题可能是有意义的,但当涉及到与其他管理员一起训练机器人时,就很难理解其中的内容了。

履行

当你想要一个引发某种行动的意图时,就使用满足感。例如,如果你想将对话输入到外部数据库,调用外部服务来查找某个位置的天气,执行一些计算,给某人发送电子邮件,在预订系统中检查可用性,或者只是搜索随机的 GIF。实现在每个意图中被打开。您可以在 dialogflow 内部对此进行编码,也可以将您的 bot 连接到另一个名为 webhook 的服务,该服务可以处理该操作。这更复杂,通常需要开发来创建适当的动作。我只是在一些基本的方面使用了满足感。

示例:我希望多个 intent 共享一个响应,因此创建了一个函数来保存共享部分,并使用一个命令来调用在 intent 中管理的初始响应。

Fulfilment code example

要了解更多关于如何编写代码实现的信息,文档中有很多相关内容,还有很多例子可以下载。对于非开发人员来说,过多地涉及履行确实意味着 bot 变得更难管理。

最佳实践意图包括

为了机器人的可用性,包含一些标准响应总是好的。

介绍或欢迎——回答你好或任何其他问候,它应该给出机器人做什么的概述,可能还有一些示例问题。这也可以由一个事件触发,比如当你打开一个聊天。

  • 默认的后退意图或不理解-当没有其他意图匹配时,此意图匹配,并且应该给用户一些关于接下来要问什么的指导。
  • 与人交谈——一些用户可能会对机器人的回答感到失望,可能会要求与真人交谈。有这个选择总是好的。你也许不能马上把他们和聊天中的人联系起来,但即使是一些联系方式也是值得的。
  • 错误的答案——如果用户说机器人给了他们错误的答案,那么最好提出反馈,并给用户其他联系方式。

在某个意图或对话的一部分之后包含一组常用选项也是很好的,这样可以将用户引导到机器人可以协助的方向。例如,在预订了一家餐馆之后,用户接下来可能要做的就是想出如何到达那里,或者将预订添加到您的日历中。

知识库

知识库是从电子表格中制作 FAQ 类型列表的简单方法。这是 Dialogflow 的一个非常新的功能,所以不要期望能够通过这种方式上传你所有的意图,最好保持非常简单的问答回复。在 CSV 电子表格中,第一列是用户输入,第二列是响应。它为列表中的每个条目都创建了一个单独的意图。由于每个条目只有一个用户短语,所以它们不是很强大,但是对于 FAQ 列表来说很有用。例如,对于一个内部业务聊天机器人,我使用知识库上传一个业务缩写和术语列表。

您也可以将知识库连接到 FAQ 格式的网页,但是我认为这只是扫描页面一次,而不是实时连接,因此如果您稍后更改网页,知识库将不会保持最新。

您可以管理如何在 dialogflow 的知识库部分实际显示响应。

训练

我们在这里讨论的训练是你训练机器人,并有效地让它变得更聪明。在培训窗口中,您可以看到对话日志。打开对话会显示每个用户输入和 dialogflow 触发的匹配意图,您可以选择确认 dialogflow 给出了正确的答案(在您进行确认之前,机器人不会将这些新的话语提交到内存中,即机器人无法自行学习),将其更改为另一个意图,或者将其添加到默认的回退意图(如果它超出了机器人的知识范围)。这就是为什么给意图一个容易理解的名字是好的;如果其他团队成员正在训练不是他们自己创建意图的机器人,那么他们可以很容易地找到匹配的那个。通过批准对话,您有效地将任何新的用户短语添加到您已经确认正确匹配的意图中。

example training conversation log

训练有点有限,如果你想在对话中准确地看到机器人的响应,并按日期或频道过滤,那么你可以在 Dialogflow 的历史部分中完成这一操作。

集成

Dialogflow 可以很容易地将 bot 服务连接到多个频道:slack、facebook、kik 等。完全完成连接通常需要几个步骤,其中大部分都在通道端。连接 slack 需要创建一个应用程序,然后在相关字段中插入一些 URL。这种设置通常不需要编码。所有这些联系都有很好的记录。

Integrations available from Dialogflow, plus of course google assistant actions.

如果您想要连接到这些简单集成之外的自定义接口,那么这需要一些额外的工作来连接到您可以在 bot 的设置中找到的 dialogflow API 端点。我找不到关于这方面的很好的文档,但这确实取决于您选择使用的 UI。

闲聊

闲聊是对机器人个性的一个有趣的小补充。这给非常简单的流行输入,如“怎么了”或“我恨你”,添加了大量预先制造的意图,dialogflow 机器人会用一组随机答案来响应它们。你可以打开它,也可以选择自定义一些答案。第一个“你是谁?”可能是一个很好的更新。

分析

简而言之,你可以看到你的机器人获得了多少流量,你可以看到最匹配的意图列表和一些基本的对话旅程。这让你很好地了解人们是否在使用这个机器人,他们什么时候使用它最多,以及他们真正使用它的目的是什么。然而,直到你有一个大的用户群,这不是很强大。

你也可以将你的机器人连接到另一个谷歌平台——https://chatbase.com

向后端添加用户

你可以在 dailogflow 的设置->共享部分进行设置。最好用谷歌邮箱添加用户。在 bot 设置中添加该地址,确保保存。您可以授予用户“审阅者”角色(可以查看所有内容,但不能进行修改),或者授予用户“开发人员”角色(可以更新除管理设置之外的所有内容)。

一旦你设置好了,他们就可以在 https://console.dialogflow.com 找到机器人

如果你想改变机器人的所有者或添加一名管理员,那么你必须在谷歌云中这样做。这是说明。

https://dialogflow.com/docs/concepts/sharing#gcpconsole

更多资源

文档中的更多帮助

https://dialogflow.com/docs

希望这对您有所帮助!如果你需要更多的机器人帮助,请联系我们。

nicholaspollard.com

理解偏差-方差权衡

原文:https://towardsdatascience.com/understanding-the-bias-variance-tradeoff-165e6942b229?source=collection_archive---------0-----------------------

每当我们讨论模型预测时,理解预测误差(偏差和方差)是很重要的。在模型最小化偏差和方差的能力之间有一个权衡。正确理解这些误差不仅有助于我们建立准确的模型,而且有助于我们避免过拟合和欠拟合的错误。

所以让我们从基础开始,看看它们如何对我们的机器学习模型产生影响。

什么是偏见?

偏差是我们模型的平均预测值和我们试图预测的正确值之间的差异。具有高偏差的模型很少关注训练数据,并且过度简化了模型。它总是导致训练和测试数据的高误差。

什么是方差?

方差是给定数据点或值的模型预测的可变性,它告诉我们数据的分布。高方差模型非常重视训练数据,不会对以前没有见过的数据进行归纳。结果,这样的模型在训练数据上表现得非常好,但是在测试数据上有很高的错误率。

数学上

假设我们试图预测的变量为 Y,其他协变量为 x。我们假设两者之间存在这样的关系

Y=f(X) + e

其中 e 是误差项,正态分布,均值为 0。

我们将使用线性回归或任何其他建模技术来制作 f(X)的模型 f^(X。

所以 x 点的期望平方误差是

Err(x)可以进一步分解为

Err(x)是偏差、方差和不可约误差之和。

不可约误差是不能通过创建好的模型来减少的误差。这是对我们数据中噪声量的一种度量。在这里,重要的是要明白,无论我们的模型做得多好,我们的数据都会有一定数量的噪声或不可减少的误差,这些是无法消除的。

使用靶心图的偏差和方差

在上图中,目标的中心是一个完美预测正确值的模型。随着我们远离靶心,我们的预测变得越来越糟糕。我们可以重复我们的建模过程,以获得对目标的单独命中。

在监督学习中,欠拟合发生在模型无法捕捉数据的底层模式时。这些模型通常具有高偏差和低方差。当我们只有很少的数据来建立一个精确的模型时,或者当我们试图用非线性数据建立一个线性模型时,就会发生这种情况。此外,这种模型非常简单,可以捕捉数据中的复杂模式,如线性和逻辑回归。

在监督学习中,当我们的模型捕捉到数据中的噪声和潜在模式时,过拟合就会发生。当我们在嘈杂的数据集上训练我们的模型时,就会发生这种情况。这些模型具有低偏差和高方差。这些模型像决策树一样非常复杂,容易过度拟合。

为什么是偏差方差权衡?

如果我们的模型太简单,参数很少,那么它可能会有高偏差和低方差。另一方面,如果我们的模型有大量的参数,那么它将有高方差和低偏差。因此,我们需要在不过度拟合和欠拟合数据的情况下找到正确/良好的平衡。

这种复杂性的权衡就是为什么在偏差和方差之间存在权衡。一个算法不能同时更复杂和更不复杂。

总误差

为了建立一个好的模型,我们需要在偏差和方差之间找到一个好的平衡,使总误差最小化。

偏差和方差的最佳平衡不会使模型过拟合或欠拟合。

因此,理解偏差和方差对于理解预测模型的行为至关重要。

感谢您的阅读!

理解层次聚类技术的概念

原文:https://towardsdatascience.com/understanding-the-concept-of-hierarchical-clustering-technique-c6e8243758ec?source=collection_archive---------0-----------------------

层次聚类技术是机器学习**中流行的聚类技术之一。**在我们试图理解层次聚类技术的概念之前让我们先了解一下聚类…

什么是聚类??

聚类基本上是一种对相似数据点进行分组的技术,使得同一组中的点比其他组中的点更加相似。一组相似的数据点被称为簇。

聚类和分类/回归模型的区别:

在分类和回归模型中,我们得到一个数据集(D ),其中包含数据点(Xi)和类别标签(易)。其中,Yi 属于分类模型的{0,1}或{0,1,2,…,n ), Yi 属于回归模型的真实值。

说到聚类,我们得到的数据集只包含数据点(Xi)。这里我们没有提供的类标签(Yi)。

现在,让我们回到最初的主题,即层次聚类技术。

这里有一个小礼物,特别送给我的读者,作为善意的表示:)亚马逊音乐无限免费3 个月:【https://amzn.to/2ZBlWI7】(注册支持)感谢。

层次聚类技术:

层次聚类是一种流行且易于理解的聚类技术。这种聚类技术分为两种类型:

  1. 结块的
  2. 分裂的

点击此处申领免费麦当劳礼品卡

****凝聚层次聚类技术:在该技术中,最初每个数据点被认为是一个单独的聚类。在每次迭代中,相似的聚类与其他聚类合并,直到形成一个聚类或 K 个聚类。

凝聚的基本算法是简单明了的。

  • 计算邻近矩阵
  • 让每个数据点成为一个集群
  • 重复:合并两个最近的聚类并更新邻近矩阵
  • 直到只剩下一个集群

关键操作是计算两个聚类的接近度

为了更好地理解,让我们看一个凝聚层次聚类技术的图示。假设我们有六个数据点{A,B,C,D,E,F}。

  • 步骤 1:在初始步骤中,我们计算各个点的接近度,并将所有六个数据点视为独立的聚类,如下图所示。

Agglomerative Hierarchical Clustering Technique

  • 步骤 2:在步骤 2 中,相似的聚类被合并在一起并形成单个聚类。让我们考虑 B、C 和 D、E 是在第二步中合并的相似集群。现在,我们剩下四个集群,分别是 A,BC,DE,f。
  • 步骤 3:我们再次计算新聚类的接近度,并合并相似的聚类以形成新的聚类 A、BC、DEF。
  • 步骤 4:计算新群的接近度。聚类 DEF 和 BC 是相似的,并且合并在一起以形成新的聚类。我们现在剩下两个星团 A,BCDEF。
  • 第 5 步:最后,所有的集群合并在一起,形成一个单一的集群。

可以使用树状图来可视化分层聚类技术。****

****树状图是一个树形图,记录了合并或拆分的顺序。

****

Dendrogram representation

**2。分裂式 **层次聚类技术:由于分裂式层次聚类技术在现实世界中使用不多,我就简单介绍一下分裂式层次聚类技术。

简单来说,我们可以说分裂式层次聚类与凝聚式层次聚类正好相反。在分裂层次聚类中,我们将所有数据点视为单个聚类,并且在每次迭代中,我们从聚类中分离不相似的数据点。每个被分离的数据点被认为是一个单独的聚类。最终,我们会剩下 n 个集群。

由于我们将单个聚类分成 n 个聚类,因此称之为分裂式** 层次聚类。**

因此,我们已经讨论了两种类型的层次聚类技术。

但是等等!!我们还剩下层次聚类的重要部分**。**

“我们如何计算两个聚类之间的相似度???"

计算两个聚类之间的相似性对于合并或划分聚类是重要的。有一些方法可用于计算两个聚类之间的相似性:

  • 马克斯(男子名ˌ等于 Maximilian)
  • 群体平均值
  • 质心之间的距离
  • 沃德方法
  • MIN: 也称为单链算法可以定义为两个聚类 C1 和 C2 的相似度等于点 Pi 和 Pj 之间的相似度的最小值使得 Pi 属于 C1,Pj 属于 C2。****

从数学上讲,这可以写成:

Sim(C1,C2) = Min Sim(Pi,Pj)使得 Pi ∈ C1 & Pj ∈ C2

简而言之,选取两个最近的点,使得一个点位于聚类 1 中,另一个点位于聚类 2 中,并获取它们的相似性,将其声明为两个聚类之间的相似性。

敏的优点:

  • 只要两个簇之间的间隙不小,这种方法就可以分离非椭圆形状。

************

Original data vs Clustered data using MIN approach****

MIN 的缺点:

  • 如果聚类之间存在噪声,最小方法不能正确地分离聚类。

************

Original data vs Clustered data using MIN approach****

  • MAX: 也称为完全联动算法,这与 MIN 方法正好相反。两个群集 C1 和 C2 的相似性等于点 Pi 和 Pj 之间的相似性的最大值,使得 Pi 属于 C1,Pj 属于 C2。****

从数学上讲,这可以写成:

Sim(C1,C2) = Max Sim(Pi,Pj)使得 Pi ∈ C1 & Pj ∈ C2

简而言之,选取两个最远的点,使得一个点位于聚类 1 中,另一个点位于聚类 2 中,并获取它们的相似性,将其声明为两个聚类之间的相似性。

MAX 的优点:

  • 如果聚类之间存在噪声,最大值方法在分离聚类方面表现良好。

************

Original data vs Clustered data using MAX approach****

Max 的缺点:

  • Max 方法偏向球状星团。
  • 最大值方法倾向于打破大的集群。

************

Original data vs Clustered data using MAX approach****

  • ****组平均:取所有的点对,计算它们的相似度,并计算相似度的平均值。

从数学上讲,这可以写成:

sim(C1,C2) = ∑ sim(Pi,Pj)/|C1||C2|*

其中,π∈C1 & Pj∈C2

组平均的优点:

  • 如果聚类之间存在噪声,则组平均方法在分离聚类方面表现良好。

组平均的缺点:

  • 群平均法偏向球状星团。
  • ****质心距离:计算两个聚类 C1 & C2 的质心,将两个质心之间的相似度作为两个聚类之间的相似度。这是现实世界中不太流行的技术。

  • ****沃德方法:除了沃德方法计算距离 Pi 和 PJ 的平方和之外,这种计算两个聚类之间相似性的方法与组平均完全相同。

从数学上讲,这可以写成:

sim(C1,C2) = ∑ (dist(Pi,Pj)) /|C1||C2|*

沃德方法的优点:

  • 如果聚类之间存在噪声,Ward 的方法在分离聚类方面也做得很好。

沃德方法的缺点:

  • 沃德的方法也偏向球状星团。

层次聚类技术的空间和时间复杂度:

****空间复杂度:当数据点的数量很大时,层次聚类技术所需的空间非常大,因为我们需要将相似性矩阵存储在 RAM 中。空间复杂度是 n 的平方的数量级。

空间复杂度= O(n)其中 n 是数据点的数量。

****时间复杂度:由于我们要进行 n 次迭代,并且在每次迭代中,我们需要更新相似度矩阵和恢复矩阵,所以时间复杂度也很高。时间复杂度是 n 的立方的数量级。

时间复杂度= O(n)其中 n 是数据点的数量。

层次聚类技术的局限性:

  1. 分层聚类没有数学目标。
  2. 所有计算聚类之间相似度的方法都有其自身的缺点。
  3. 层次聚类的高空间和时间复杂度。因此,当我们有大量数据时,不能使用这种聚类算法。

相关文章:K 近邻入门

**** [## 机器学习:K 近邻入门。

我们将在本文中了解到:

medium.com](https://medium.com/datadriveninvestor/machine-learning-getting-started-with-k-nearest-neighbours-6851280d4c93)

参考文献:

  1. https://cs . wmich . edu/alfuqaha/summer 14/cs 6530/lectures/clustering analysis . pdf
  2. www.appliedaicourse.com
  3. https://en.wikipedia.org/wiki/Hierarchical_clustering

****

理解疾病周期:斯坦福大学使用 TDA 的突破性研究

原文:https://towardsdatascience.com/understanding-the-disease-cycle-groundbreaking-research-from-stanford-using-tda-81cfb595d605?source=collection_archive---------2-----------------------

这篇原创的博客于 2017 年首次出现在 Ayasdi 网站上。

我们合作项目的最大回报之一就是看到开创性的工作使用我们的软件发表。史丹福微生物学,特别是大卫·施奈德博士和他的实验室似乎每年都达到这个地位。

也就是说,他们最近从 DARPA 获得了 600 万美元的资助,以继续他们在理解疾病康复方面的开创性工作。他们的工作如此重要,以至于在 PLOS 的两家独立的报纸上发表。两篇论文都展示了我们的底层技术拓扑数据分析(TDA) 如何被用于绘制宿主循环通过疾病空间的方式。

这项工作是使用我们的平台的无监督学习能力进行的,并通过使用横截面数据的疾病地图的可视化来区分。

目前,当动物/人类从疾病中康复时,没有/几乎没有收集到数据,因此潜在的商业影响是显著的,并且将因疾病指征而异。

Schneider 实验室使用 TDA 对数据进行聚类,而没有强加连接结构,例如层次模式或最小分支树。拓扑网络提供了一个健康空间的惊人表示,类似于疾病地图,其中网络的不同区域对应于疾病的不同部分:舒适、疾病和康复。事实上,老鼠和人类的数据集形成了这些优雅的、定义清晰的循环结构。

施尼德博士的团队绘制了寄生虫、红细胞、粒细胞或网织红细胞等参数的强度——发现小鼠和人类感染在许多方面是共线的,具有相同的事件顺序。TDA 图被用来将活的和死的老鼠分成两条不同的路径,然后确定两组之间基因表达的差异。研究人员证明,红细胞和网织红细胞在存活和死亡小鼠中的表现不同,因为它们通过疾病空间的路径不同。

一个有趣的因素是,TDA 是在这种情况下唯一可行的技术。

TDA 制作的图形更明显是循环的,因为拓扑网络拉近了间隙。他们将被感染的宿主穿越的“疾病空间”可视化,并确定了感染过程的不同状态。弹性系统不适合用树来描述,用环来描述更好——但是环避开了大多数分析方法。

另一方面,TDA 对数据的“形状”很敏感,不会任意线性化一个循环,然后强迫它适应一棵树。相反,这种分析只是将相关的数据点聚集起来,用网络图上的节点表示,图形的形状揭示了时间点之间的联系。在弹性系统的情况下,如从感染中恢复的主机,此图形成一个循环。

下面是每篇论文的作者摘要和实际论文的链接。

通过绘制疾病空间图跟踪对感染的抵御能力

“当我们生病时,我们渴望康复;因此,医学的一个主要目标是促进复原力——宿主在感染后恢复健康的能力。虽然在实验室中,我们可以通过对接种时间和剂量的精确了解来研究对感染的反应,但诊所中的病人却没有这些信息。这就产生了一个问题,因为我们不容易区分处于感染早期阶段的患者和在感染后期出现的更具疾病耐受性的患者,前者将发展为严重疾病。这两类患者之间的区别很重要,因为对疾病耐受性较差的患者需要更积极的治疗方案。为了确定患者在感染时间线上的位置,我们绘制了“疾病地图”,通过“疾病空间”追踪患者的路线。“我们选择在病人生病和康复时产生循环图的症状。通过使用小鼠-疟疾模型,我们证明了弹性较低的个体在这个空间中走更宽的回路,这表示感染时间更长,症状更严重。我们发现这种循环行为也适用于人类,并表明携带镰状细胞特征的人对疟疾感染更有抵抗力。”

描述疾病耐受性需要多少个参数?

“这是一个直观的假设,即感染期间症状的严重程度必须与病原体载量相关联。然而,解释健康如何随病原体负荷变化的剂量-反应关系是非线性的,可以描述为“疾病耐受曲线”;这种关系随着宿主或病原体的遗传特性以及环境条件而变化。我们研究了这条曲线形状的变化可以告诉我们免疫反应的潜在回路。使用一个模型系统,我们用细菌病原体单核细胞增生李斯特氏菌感染果蝇,我们观察到一个 S 形的疾病耐受曲线。这种类型的曲线可以用标准方式用三个或四个参数来描述,这使我们能够开发一个简单的数学模型来解释随着免疫反应的变化,曲线预计会如何改变形状。在观察了由于宿主和病原体遗传变异导致的曲线形状变化后,我们得出结论,李斯特菌感染造成的损害不是由过度旺盛的免疫反应造成的,而是由病原体更直接地造成的。”

要成为合作者,请发电子邮件给我们,姓名为collaborations@ayasdi.com。

理解内核技巧。

原文:https://towardsdatascience.com/understanding-the-kernel-trick-e0bc6112ef78?source=collection_archive---------0-----------------------

我观察到,就像我一样,我们中的许多人试图学习支持向量机,发现很难理解内核的智慧。这花了我相当多的时间和资源,但我终于渡过了这条河,我打算帮助你们也这样做。这中间可能看起来很混乱,但是只要有一点耐心和坚持,我很确定你最终会有一个好主意。那么,让我们现在就开始吧!

对于那些不熟悉 SVM 的人,这里有一个简短的介绍。在数据分类问题中,SVM 可以用来为线性可分的数据集提供最大的分离间隔。也就是说,在可以被选择来分离用于分类的数据集的所有可能的决策边界中,它从两个类中选择离所述决策边界最近的点最远的决策边界。这应该有点令人困惑,所以这里有一个图来帮助你得到一个直觉。

这里有两个班级,红色和蓝色。中间的线是决策边界。突出显示的点是支持向量。所有这些点和直线之间的距离是所有可能的决策边界中的最大值,因此这是最佳值。

现在这样不好吗?它是,除了这是适用的事实;以它的原始形式;仅适用于线性可分数据。如果不是呢?输入内核。这个想法是,我们的数据,在我们的 n 维空间中是不可线性分离的,在一个更高维的空间中可能是可线性分离的。为了理解内核是如何工作的,一些数学知识是必要的,所以做好准备!

比方说决策边界。即,分离类的超平面具有由向量 w 给出的权重(系数)。这是我们需要找到的。我们试图最大化从这个 w 向量到最近点(支持向量)的距离,所以这现在成为我们的约束。省去了后面的一些数学知识,我要请你们在这里假定,为了解决这个问题,我们解决了以下问题

我会给你一个简单的解释这个看起来可怕但本质简单的等式。l 是我们训练数据中数据点的数量。y 表示数据点的输出,为了方便起见,我们表示为+1 或-1。x 是每个训练示例中的特征向量。α现在……嗯,α是拉格朗日常数。为了对此进行简要概述,拉格朗日乘数用于包含解决最小化或最大化问题的约束,从而使我们在达到我们的解决方案时不必担心它们。
无论如何,当最小化 W(alpha)[作为 alpha 的函数的权重向量]时,我们看到术语 x*x(转置)。也就是说,我们不需要确切的数据点,只需要它们的内积来计算我们的决策边界。有什么大不了的,对吧?那么如果是这样呢?这有什么帮助?
这意味着,如果我们想要将现有数据转换为更高维度的数据,这在许多情况下有助于我们更好地分类(参见下图中的示例),我们不需要计算数据的精确转换,我们只需要高维度空间中数据的内积。这在不可线性分离的数据集中非常有效!

得到高维空间的内积比得到高维空间的实际点要容易得多。通过简单地使用‘d’的指数将我们的数据映射到‘d’维空间的多项式核对于我们的解决方案是有效的。高斯核,在数学上,将我们的数据映射到一个无限维的空间(是的,我没有拼错)。这些只是众多可用内核中的一部分。通过这种方式,我们甚至不需要访问高维空间就可以得到我们的解。

当然,这里涉及的数学和逻辑比我在这里解释的要多得多,但是我希望我已经能够给你一个关于内核技巧的像样的直觉。快乐学习!

在神经网络的上下文中理解 L 正则化的缩放

原文:https://towardsdatascience.com/understanding-the-scaling-of-l%C2%B2-regularization-in-the-context-of-neural-networks-e3d25f8b50db?source=collection_archive---------4-----------------------

你是否曾经看到过神经网络成本函数的 L 正则化项,并想知道为什么它同时被 2 和 m 缩放?

Equation 1: An L2-regularized version of the cost function used in SGD for NN

您可能在众多使用它来正则化神经网络模型的论文中遇到过它,或者在学习关于神经网络主题的课程时遇到过它。令人惊讶的是,当 L 正则化的概念在这种情况下出现时,该术语通常与这些因素一起引入,而没有进一步的解释。

我最近在学习 改进深度神经网络 课程(吴恩达/ deeplearning.ai 在 Coursera 的优秀深度学习专业化中的第二门课程)时再次遇到了这个术语,其中确实没有对这些比例因子做出解释,所以我开始在互联网上搜索。下面的帖子总结了我在搜索过程中所学到的东西。

提醒:神经网络中梯度下降的 L 正则化

只是为了确保我们都在同一页上,这里有一个在神经网络的随机梯度下降背景下什么是 L 正则化的简要回顾。

通常在机器学习中,当我们拟合我们的模型时,我们在解空间中搜索最合适的解;在神经网络的上下文中,解空间可以被认为是我们的网络可以表示的所有函数的空间(或者更准确地说,接近任何期望的程度)。我们知道这个空间的大小取决于(至少)网络的深度和使用的激活函数。我们还知道,使用“挤压” 函数,至少有一个隐藏层后跟一个激活层,这个空间非常大,并且它随着网络的深度呈指数增长(参见 通用近似定理 )。

当我们使用随机梯度下降 (SGD)来使我们的网络参数适合手头的学习问题时,我们在算法的每次迭代中,在解空间中朝着损失函数J(θ;x,y) 相对于网络的参数 θ 。由于深度神经网络的解空间非常丰富,这种学习方法可能会过度适应我们的训练数据。如果不使用应对措施,这种过度拟合可能会导致显著的泛化误差和对看不见的数据(或模型开发环境中的测试数据)的不良性能。那些反措施被称为正则化技术。

Figure 1: An unregularized model can overfit to noise/outliers in the training data

“正则化是我们对学习算法进行的任何修改,旨在减少其泛化误差,而不是训练误差。”伊恩·古德菲勒

在迭代学习算法的一般情况下,有几种正则化技术,如早期停止,特别是神经网络,如辍学。统计学和机器学习中的一种常见方法是在损失函数中添加一个正则项,这意味着将模型复杂性的一种度量纳入到要最小化的函数中。这种方法既不是迭代学习算法也不是神经网络所独有的,它将众多学习算法的共同形式化为优化问题。

现在,我们不再只是在解决方案空间中搜索训练集损失最小的解决方案,而是考虑解决方案的简单性。这增加了选择更简单且因此更通用的解决方案的机会,同时保持训练数据的低误差。用 Tim Roughgarden 的话说,我们变得*“偏向于更简单的模型,因为它们捕捉的是更基本的东西,而不是特定数据集的一些工件”*。

Figure 2: Applying regularization can help prevent overfitting on the training data

现在我们已经讨论了泛化错误和正则化,让我们回到 L 正则化。这种技术在统计学中也被称为 吉洪诺夫正则化岭回归,是一种通过添加复杂性表示项来正则化成本函数的特定方式。在神经网络中的 L 正则化的情况下,该术语简单地是网络的隐藏层的权重矩阵的平方欧几里德范数 (或者在多个隐藏层的情况下,包括输出层,是所有这种平方范数的总和)。添加附加参数 λ ,以允许控制正则化的强度。

添加 L 项通常会导致整个模型的权重更小。其他类型的基于项的正则化可能具有不同的效果;例如, L 正则化导致更稀疏的解,其中更多的参数将以零值结束。

具有 L 和 L 的正则化也有一个漂亮的概率解释:它相当于在权重矩阵的分布上添加一个先验W;这将优化问题从执行 最大似然估计 (MLE) 转换为执行 最大后验概率 (MAP) 估计;即从使用频率主义推理移动到贝叶斯推理。Brian Keng 的一篇伟大的文章中可以找到对这一解释的全面概述。

回到 L 正则化,我们得到一个形式的项

Equation 2 : Adding L² regularization to a cost function

其中∨≈∨是 L 范数。这确实是我们在经典 吉洪诺夫正则化 中遇到的形式。

那么被 m2 的划分又是从何而来呢?此处将该项减半似乎特别多余,因为它只增加了除以一个常数,因此如果我们也像通常所做的那样搜索超参数(如 λ )的最佳值,则没有任何意义。事实上,在经典机器学习中,没有这两个因素也会遇到相同的正则化项。

一个可能的答案是,L 正则化可能是通过引入相关但不相同的概念权重衰减而进入深度学习领域的。

重量衰减

权重衰减的想法很简单:为了防止过度拟合,每当我们用相对于 w 的梯度 ∇J 更新权重 w 时,我们还要从中减去λw。这使得重量趋向于衰减为零,因此得名。

这其实是深度学习历史上相当早期的概念。Nowlan 和 hint on 1992 年的一篇论文 通过软权重共享 简化神经网络,不经意地引用了 Plaut、Nowlan 和 hint on 1986 年 6 月的一篇论文 通过反向传播 进行学习的实验。因为那里引用的几篇论文似乎都没有使用这个概念,这实际上可能是在神经网络的上下文中引入这个概念的地方。甚至汉森&普拉特(1988) 似乎也在脚注中暗示,他们当时找不到发表的论文来引用这个概念。

Equation 3: Weight decay for neural networks

当从这个角度看正则化时,常见形式开始变得清晰。为了将这一项添加到权重更新中,我们“劫持”了成本函数 J ,并且添加了一项,该项在被导出时将产生这个期望的-λ∙w;要加的项当然是 -0.5 λ∙w 。对 J -0.5 λ∙w 求导,将得到∇j-λ∙w,这就是我们的目标。

Equation 4 : L² regularization from a weight decay perspective

Plaut 等人已经在上述论文中指出了这种与 L 范数的关系:

“看待术语 h∙w 的一种方式是将其视为 0.5 h∙w 的导数,因此我们可以将学习过程视为最小化 E (误差)和最小化权重的平方和之间的折衷。”

事实上,L 正则化和权重衰减正则化对于标准随机梯度下降是等价的(当通过学习率重新调整时)。对于所有基于梯度的学习算法来说,这并不一定是真的,最近显示对于自适应梯度算法来说,例如 Adam 。

为什么要除以 m?

所以,我们仍然有被 m 分割的问题。毕竟,适当的超参数优化也应该能够处理规模的变化(至少在理论上)。

选项 1:批量梯度下降的副作用

让我们从重量衰减的角度来看这个问题。在梯度下降 (SGD)的随机变量中,我们每次在单个训练样本上评估损失函数的梯度(关于参数 θ )。如果我们认为权重衰减是在每个示例级别中引入的(如最初那样),我们自然会得到,当梯度下降的单次迭代在整个训练集上被形式化时,导致算法有时被称为批量梯度下降, 1/m 的比例因子(被引入以使成本函数在不同大小的数据集之间具有可比性)自动应用于权重衰减项。

选项 2:重新调整单个示例的权重

我在一个由用户 grez 验证的关于交叉的答案中遇到的第二种方式是,这种缩放确保正则化项对损失函数的影响大致对应于单个训练示例。这确保了正则化的实际效果不会随着数据量的增加而爆炸——这可能解释了为什么当 SGD 用于神经网络时,这个比例因子开始具体出现,神经网络在大数据时代再次出现。

从单个例子的角度考虑这个术语,考虑没有这种缩放的正则化术语:在学习算法解决的一些第一批问题中,一个术语可能具有 1000 个例子的权重,在大数据集时代,突然在算法的每次迭代中获得与 10,000,000 个例子相同的权重。从信息论的角度来看,这个论点在某种程度上是有道理的;这是很多与我们之前提到的假设相关的信息,更简单的模型捕捉一些基本的东西,当训练集变得非常大时,这可能成为太强的假设。

选项 3:训练集代表性

我还想就这个问题提出一个统计学的观点。我们可以把我们的训练集想象成未知复杂性的未知分布的样本。然而,无论这种看不见的分布有多复杂,随着我们的训练集的增长,它成为这种看不见的源分布的代表性样本的概率也在增长,这总是事实。因此,它也更能代表未来未知数据(或测试集)的任何足够大的样本。简而言之,训练集越有代表性,需要做的过度拟合就越少。

在这个意义上,随着例子数量的增加,缩小正则化项编码了这样一个概念,即我们拥有的数据越多,在查看任何特定的 SGD 步骤时,我们可能需要的正则化就越少;毕竟,当损失项应该随着 m 增长而保持不变时,网络的权重也应该增长,使得正则化项本身相对于原始损失项收缩。

最近的一篇论文(以及的后续论文)提出,如果引入足够的数据扩充,权重衰减和丢失对于目标识别 NNs 来说可能不是必要的,这或许可以被视为支持这一概念,即我们拥有的数据越多,需要的正则化就越少。

选项 4:使 λ可比

最后一个很好的动机是:当 m 改变时,通过希望减轻改变 λ 的需要,这种缩放使得 λ 本身在不同大小的数据集之间具有可比性。这使得 λ 成为针对特定学习问题的特定模型所需的实际正则化程度的更具代表性的估计值。

选项 5:经验值

无论你觉得哪个直观的理由令人满意,至少对于使用 ReLU 作为激活函数的前馈网络来说,通过 1/m 缩放正则项的经验值在下面的笔记本中由前述的grez:
https://github . com/grez 911/machine-learning/blob/master/L2 . ipynb优雅地展示

最后的话

就是这样!我希望你喜欢这个小而重要的数学术语。如果你对这些比例术语的形成原因和方式有任何更正、补充或其他想法,请在评论中告诉我,或者通过我在个人网站上链接的任何方式联系我。:)

脚注:

  1. 在这种情况下,“挤压”函数是任何非常数、有界且连续的函数,因此是满足通用逼近定理条件的函数,而不是通常称为“挤压函数”的任何特定函数,如 sigmoid 函数。
  2. 欧几里德范数是一般的p-范数(又名lᵖ-范数)当 p=2 时的情况;L-定额。因此,取名为 L 正规化。

Python 的 Lambda 表达式、映射和过滤器

原文:https://towardsdatascience.com/understanding-the-use-of-lambda-expressions-map-and-filter-in-python-5e03e4b18d09?source=collection_archive---------8-----------------------

函数式编程值得吗?

Welcome to the Functional Church, where laziness is not a sin. Source: Pixabay

Python 的 Lambda 表达式,使用 lambda 运算符,是颇有争议的。有人说它们笨重,有人说它们优雅。

作为一个喜欢函数式编程范例的人,我喜欢不时地在我的代码中加入一些表达式,只要是少量的。
然而,我确实看到了如何将一个有点长的关键字放在一行的中间,并在假设它不会在程序的其余部分中使用的情况下匿名定义一个函数,这可能最终会成为一个问题。

但是,不要急于求成,让我们从定义相关术语开始:

Lambdas are Anonymous. They never forgive, they never forget. Expect them. Source: Pixabay

什么是 Lambda 表达式?

表达式是一个函数的匿名内联声明,通常作为参数传递。它可以做常规函数能做的任何事情,除了它不能在定义它的行之外被调用,因为它是匿名的:它没有名字。

上面的代码片段显示了使用一个定期定义的函数(或强制定义的,对于那些在角落里感觉被我的命令式特权谈话歧视的功能人员来说)、一个由 lambda 定义并分配给变量的函数(这是可以做到的,但通常被视为一种不好的做法)和一个对 lambda 函数的内联调用之间的比较(我甚至不需要告诉你为什么这不应该做得太多)。

这三段代码最终返回相同的值,但是每一段在作用域和内存方面都有不同的效果:两段代码为程序的其余部分定义了一个可调用的对象,而最后一段代码创建了一个不会在任何其他行中调用的匿名函数。

如果你还不能流利地理解列表,这里有一个常规的、命令式的 for 循环示例:

你可能会同意 map 比常规的 for-loops 不那么笨拙,占用的空间也更少,但是可能比 List Comprehensions 稍欠直观。

我们已经谈论了太多的批评(代码更难阅读,一个笨拙的关键字),让我们谈谈实际的一面。

映射和过滤:利用 lambda 表达式

下面我们再介绍两个 Python 的原生关键词:贴图滤镜。

对于不熟悉函数式编程的人来说,map 函数是一个高阶函数,即至少接受一个函数作为输入,或者产生一个函数作为输出。

在它的正式定义中,它的参数是一个函数和一个序列(任何可迭代对象),它的输出是另一个序列,包含将给定函数应用于所提供序列中每个元素的结果,顺序相同。

听起来熟悉吗?那是因为在一个列表上调用一个函数的映射几乎等同于使用一个列表理解!不过,这种说法有一些注意事项,我会尽快解决。

以下等价关系几乎成立:

注意,在最后两行中,我传递了三次和三次函数作为参数,这要感谢 map 是一个高阶函数。

如果你迭代这五个变量中的每一个,它们都会产生相同的值。然而在 Python 3+中,在打印它们时,你会看到一些是列表,而另一些是地图对象。没错,在一个列表上应用映射会返回一个生成器!这基本上意味着它将生成一个延迟求值的序列,可以迭代,并且必须转换到一个列表中才能切片或索引。另一方面,在 Python 2.7 中, map 返回一个普通的列表

这就是图和图产生协同作用的地方:就像用图和 T21 写一条线一样流畅,如果你能即时发明你的小功能,它会变得更加流畅。一旦你掌握了它,你将开始考虑映射,并欣赏这个特性。但是请注意,如果地图无人看管,不可读的代码会很快溃烂。

作为补充,我还将向您介绍滤镜。在序列中调用过滤器与在列表理解的末尾添加一个 if 是一样的,除了它留下了功能性的余味。以下代码片段是等效的:

映射一样,过滤器返回一个生成器(在这种情况下是一个过滤器对象),但是将它转换成一个列表表明它相当于在一个列表理解中使用一个*。*

地图比列表理解更快吗?滤镜呢?

我运行了几个基准测试,比较普通的 for-loops ,List Comprehensions 和 map 。我不确定结果会是什么,但是有一些关于它们的理论。

以下是我在进行实验之前定义的一些东西:

这是我运行的基准测试的代码:

我比较了一个使用追加调用的常规命令式列表声明,一个使用列表理解,最后一个调用映射。

在 Python 2.7 中,我的结果如下:

  • 列表 a 为 6.00 秒
  • 名单 b 为 4.12 秒
  • 列表 c 的 3.53 秒(使用映射的列表)

关于 Python 2.7 中的优化 map 用了什么,我其实不知道也没有什么理论,但是出来的速度比列表理解还快!因此,在后者的清晰度和前者的速度之间做出选择时,需要做出权衡。需要注意的是,我多次运行这个实验,并且得到了一致的结果。

在 Python 3 中,我得到了令人惊讶的结果:map测试用了不到一毫秒,而 list comprehension 测试用了 5 秒!这时,我记得将结果转换成一个列表以使操场公平,因为生成器当然会加载得更快,这要感谢不必初始化它的值。这些是结果:**

  • 列表 a 为 7.08 秒
  • 列表 b 为 5.1 秒
  • 列表 c 为 5.1 秒

我不得不多次运行这个程序来检查,但是它们基本上花费相同的时间。很明显,他们都在做非常相似的事情,于是他们之间的选择就变成了清晰和懒惰是否有用。

综上所述, lambdas 可能很笨重,但是它们也为你的代码增加了很多表达能力。 Filtermap 对某些人来说可以是优雅的,但在性能方面不会给表格增加很多(并且被一些人视为不如 List Comprehensions 那么 Pythonic 化)。

我个人的观点是,我喜欢 Python 有这些特性,因为它们让一些代码行更漂亮,但通常不像列表理解那样喜欢它们。如果没有尾部调用消除和其他优化,除了风格和懒惰(好的那种)之外,要举出在 Python 中使用函数式编程的好理由可能有点困难(尽管我们实际上可以从在 Haskell 中使用函数式编程中获得很多好处)!)。

你的观点是什么?你还想让我讨论其他功能性话题吗?我不提你生气吗?你希望 Python 中引入哪些其他功能性的东西?哪些是你不喜欢的?我相信你对此有自己的看法,我也很想了解更多。我也很想知道是否有一些非平凡的例子,在这些例子中, map 实际上比 List Comprehensions 更快,但我没有看到它们。

这是我对 Python 中函数式编程特性的介绍,我希望您发现它很有用,或者至少在阅读它的过程中获得了一些乐趣。

你可以在我的 个人网站 中看到我正在做的事情以及我最近的文章和笔记。

通过可视化了解您的卷积网络

原文:https://towardsdatascience.com/understanding-your-convolution-network-with-visualizations-a4883441533b?source=collection_archive---------1-----------------------

Convolution layer outputs from InceptionV3 model pre-trained on Imagenet

自从卷积神经网络出现以来,计算机视觉领域已经取得了巨大的进步。在过去的几年里,这一领域令人难以置信的研究速度,加上网上大量图像数据库的开放可用性,给了我们令人难以置信的结果。大型卷积神经网络的兴起始于 2012 年的 AlexNet ,由 Alex KrizhevskyIlya SutskeverGeoffrey Hinton 创建,是当年 ImageNet 大规模视觉识别挑战赛的获奖作品。从那以后,这个领域的研究人员再也没有回头看,计算机视觉各个领域的结果就是一个明显的证明。从手机中的人脸识别到驾驶汽车,CNN 的巨大力量正被用来解决许多现实世界的问题。

但是,尽管大型数据库和预先训练的 CNN 模型广泛可用,但有时很难理解你的大型模型到底在学习什么以及如何学习,特别是对于没有机器学习所需背景的人来说。虽然,阅读基础统计和概率有助于克服一些障碍,但当涉及到调试大型卷积架构(如 Inception 模型)时,许多人会上当。大多数人的目标只是使用预先训练好的模型来进行一些图像分类或任何其他相关的问题,以得到最终的结果。他们最不关心网络的内部工作,这实际上可以告诉他们很多关于他们的网络如何学习和学习什么,以及调试它的故障。

最近偶然看到这本Fran ois Chollet(Twitter)用 Python 深度学习的超棒的书。如果你正开始你的深度学习之旅,这本书是一个瑰宝。它使用 Keras,这是一个优秀的深度学习库,运行在 TensorFlow,MXNET 和 Theano 上,解释了深度学习的基础知识以及前沿和最新的事情和结果。在我阅读这本书学到的许多新东西中,真正激发我兴趣的是可视化如何用于学习 conv 网。在这篇博客中,我总结了我学到的三种技术以及我复制它们的结果。

Eenter 可视化

可视化机器学习模型的输出是一种很好的方式来查看它的进展情况,无论是基于树的模型还是大型神经网络。在训练深度网络时,大多数人只关心训练误差(精度)和验证误差(精度)。虽然判断这两个因素确实可以让我们了解我们的网络在每个时代的表现,但当涉及到像 Inception 这样的深度 CNN 网络时,我们可以看到更多信息,从而了解网络架构。

在这篇文章中,我将演示几种可视化模型输出的方法(中间层和最终层),这可以帮助你更深入地了解模型的工作。我训练了 Keras 中的 InceptionV3 模型(在 ImageNet 上进行了预训练),训练了 Kaggle 上的花卉识别数据集。如果你不熟悉 Inception 模型,我建议你先浏览一下 Inception 架构 的原始论文,然后再浏览一下 InceptionV3 论文 以了解这些架构背后的理论。

我对模型进行了 10 个时期的训练,批次大小为 32,每个图像的大小调整为(299,299,3)的形状,这是预训练的 InceptionV3 模型所需要的。我的模型能够达到 0.3195 的训练损失和 0.6377 的验证损失。我使用 Keras 内置的 ImageDataGenerator 模块来扩充图像,这样模型就不会过拟合得太快。可以看看我的 github 库 上的代码。

可视化中间层激活

为了理解我们的深度 CNN 模型如何能够对输入图像进行分类,我们需要理解我们的模型如何通过查看其中间层的输出来查看输入图像。通过这样做,我们能够更多地了解这些层的工作原理。

例如,当提供来自测试集的花的图像时,以下是训练的 InceptionV3 模型的一些中间卷积及其相应激活层的输出。

Original Image

Filters from layers First, Fourth and Ninth convolution layers in InceptionV3

Filters from ReLU activation layers respective to First, Fourth and Ninth convolution layers in InceptionV3

上图显示了分别来自 InceptionV3 网络的几个中间卷积和 ReLU 层的滤波器。我通过在一个测试图像上运行训练好的模型来捕获这些图像。

如果你看看不同的图像从卷积层过滤器,很清楚地看到不同的过滤器在不同的层是如何试图突出或激活图像的不同部分。一些过滤器充当边缘检测器,其他的检测花的特定区域,如其中心部分,还有一些充当背景检测器。在起始层中更容易看到卷积层的这种行为,因为随着你越深入,卷积核捕获的模式变得越来越稀疏,所以可能这种模式甚至可能不存在于你的图像中,因此它不会被捕获。

进入相应卷积层的 Relu(校正线性单位)激活,它们所做的就是将 ReLU 函数应用于每个像素ReLU(z) = max(0, z),如下图所示。因此,基本上,在每个像素上,激活函数要么为所有负值设置 0,要么在像素值大于 0 时设置像素值本身。

ReLU function

通过以这种方式可视化来自不同卷积层的输出,您将注意到的最重要的事情是,网络中较深的层可视化更多训练数据特定特征,而较早的层倾向于可视化一般模式,如边缘、纹理、背景等。当您使用迁移学习时,这些知识非常重要,通过迁移学习,您可以在完全不同的数据集上训练预训练网络(在不同的数据集上进行预训练,如本例中的 ImageNet)的某个部分。总的想法是冻结早期层的权重,因为它们无论如何都会学习一般特征,并且只训练更深层的权重,因为这些层实际上识别你的对象。

可视化 Convnet 滤波器

了解卷积网络在图像中寻找什么的另一种方法是可视化卷积图层过滤器。通过显示网络层过滤器,您可以了解每个过滤器将响应的模式。这可以通过对 convnet 的值运行梯度下降来实现,以便从空白输入图像开始最大化特定滤波器的响应。

以下是我在 Flowers 数据集上训练的 InceptionV3 模型中的一些模式。

Filters from third convolution layer in InceptionV3

Filters from eight convolution layer in InceptionV3

Filters from fortieth convolution layer in InceptionV3

仔细观察这些来自不同卷积层的滤波器图像后,就可以清楚地看到不同的层实际上试图从提供给它们的图像数据中学习什么。在起始层的过滤器中发现的图案似乎非常基本,由线条和其他基本形状组成,这告诉我们早期的层了解图像中的基本特征,如边缘、颜色等。但是,随着你向网络的更深处移动,模式变得更加复杂,这表明更深的层实际上正在学习更抽象的信息,这有助于这些层概括关于类而不是特定图像的信息。这就是为什么在前面的部分中,我们在更深的层中看到一些空的过滤器激活,因为该特定过滤器没有为该图像激活,换句话说,该图像没有过滤器感兴趣的信息。

可视化课程激活热图

预测图像的类别标签时,有时您的模型会为您的类别预测错误的标签,即正确标签的概率不是最大的。在这种情况下,如果你能想象出你的 convnet 在看图像的哪一部分并推断出类别标签,这将会很有帮助。

这种技术的一般类别称为类激活图 (CAM)可视化。使用 CAM 的技术之一是在输入图像上产生类激活的热图。类别激活热图是与特定输出类别相关联的分数的 2D 网格,针对输入图像的每个位置计算,指示每个位置相对于该输出类别有多重要。

在上面的图片中,你可以看到这种技术是如何工作的。从左开始,首先是输入图像,然后是 InceptionV3 架构中最后一个混合层的激活热图,最后我将热图叠加在输入图像上。因此,基本上,热图试图告诉我们的是图像中的位置,这些位置对于特定图层将其分类为目标类非常重要,在本例中是雏菊****。

在第一幅图像中,很明显网络在分类花方面没有问题,因为在整个图像中没有其他对象。在下一幅图像中,网络无法将图像分类为**雏菊,**但是如果你看一下激活图的热图,很明显网络正在图像的正确部分寻找花朵。与第三个图像的情况类似,网络能够突出显示图像的左下部分,小雏菊花位于该部分。因此,很明显,虽然网络不能正确地对第二和第三幅图像进行正确分类,但做出这一决定的原因不是网络的不正确,而是两幅图像中的其他对象占据了图像的较大部分。

对于网络中的不同层,激活热图可能会有所不同,因为所有层都以不同的方式查看输入图像,从而基于其过滤器创建图像的独特抽象。在这个例子中,我将重点放在模型的最后一层,因为类预测标签将在很大程度上依赖于它。但是比较不同层的激活热图是一个很好的实验。

结论

在这篇文章中,我描述了三种不同的方法来可视化你的深层卷积网络。正如前面所解释的,这样的可视化可以帮助我们理解黑盒技术的工作,更好地像神经网络一样,这对于调试任何错误或网络的整体性能都是有用的。

Tensorflow 的不公平反向传播

原文:https://towardsdatascience.com/unfair-back-propagation-with-tensorflow-manual-back-propagation-with-tf-c166115988fd?source=collection_archive---------9-----------------------

GIF from this website

我一直在思考反向传播,在传统的神经网络中,我们似乎总是线性地执行前馈操作和反向传播。(1:1 的比例)但是我对自己说,我们真的不需要这么做。所以我想做些实验。

案例 a)反向传播(无数据增强)
案例 b)反向传播(数据增强)
案例 c)不公平的后支撑(从后面)(无数据增强)
案例 d)不公平的后支撑(从后面)(数据增强)
案例 e)不公平的后支撑(从前面)(无数据增强)
案例 f)不公平的后支撑(从前面)(数据增强)

请注意,这个帖子是为了好玩,也是为了表达我的创意。因此不是面向性能的。

网络架构/数据集/典型反向传播

红色方块 →输入图像批次
黑色方块 →有/无均值合并的卷积层
橙色方块 →用于分类的 Softmax 层
橙色箭头 →前馈操作方向
紫色箭头 →反向传播方向。

如上所述,我们将使用我的旧帖子“全卷积网”中的基本网络,这是一个仅由卷积运算组成的 9 层网络。此外,我们将使用 CIFAR 10 数据集。

不公平反向传播

现在为了解释不公平反向传播的概念,让我们首先假设我们刚刚完成了前馈操作(如上所示)。通过查看粉色箭头,我们已经可以知道我们已经反向传播到第 9 层。

现在,我们可以再次执行前馈操作来获得另一轮分类,而不是继续反向传播到第八层等等。(但是这次第 9 层已经更新了一次它的权重。)

我们可以再次重复这个过程,但是这次我们也要更新第 8 层的权重。

我们可以一次又一次地遵循这个概念。直到我们到达第一层,完成整个反向传播。总之,我们对网络的开始层不公平,因为后面的部分会更新更多。我们也可以在 GIF 格式中看到不同。

最后,我们可以把对网络开始部分不公平的概念反过来,对网络的后面部分不公平。(换句话说,我们网络的开始部分比后面部分更新得更多。)

结果:情况 a)反向传播(无数据增加)(50 个时期)

左图 →一段时间内测试图像的精度/成本
右图 →一段时间内列车图像的精度/成本

如上所述,网络测试图像的准确率已经开始停滞在 83%左右。然而,这里要注意的是,网络需要 13 个历元才能使测试图像的准确率达到 80%以上。

训练图像的最终准确率为 98 %,而测试图像的准确率为 83 %,这表明网络正遭受过拟合。

左图 →训练后权重直方图
右图 →训练前权重直方图

如上所示,所有的权重范围都从-0.1/0.1 增加到-0.5/0.5。

结果:情况 b)反向传播(数据扩充)(10 个时期)

左侧图像 →一段时间内测试图像的精度/成本
右侧图像 →一段时间内训练图像的精度/成本

现在,由于我们执行了数据扩充,我们可以清楚地观察到训练图像的准确性下降(因为数据中有更多的差异。).

如上所示,在训练 10 个时期后,网络最终达到了 79%的准确率(在测试图像上)。值得庆幸的是,网络并没有过度拟合。

左图 →训练后权重直方图
右图 →训练前权重直方图

就像我们没有执行数据扩充的情况一样,权重的范围也增加了。

结果:案例 c)不公平的后道具(从后面) (无数据增强)(10 个历元)

左侧图像 →一段时间内测试图像的精度/成本
右侧图像 →一段时间内列车图像的精度/成本

与用普通(典型)反向传播方法训练的网络相比,该网络表现得更好。在测试图像上完成训练的准确率约为 82 %,在训练图像上完成训练的准确率约为 89%。表明仍然存在过度拟合,但是与情况 a)相比没有那么多。

观察到不公平反向传播似乎具有某种正则化效应的事实是相当令人惊讶的。

左图 →训练后权重直方图
右图 →训练前权重直方图

到目前为止,最有趣的观察是权重的直方图。如上所述,当我们将注意力集中到网络最终层生成的直方图时,我们可以观察到直方图偏向一侧。(-左侧范围为-0.5,而右侧没有 0.5。)表明分布的对称性有些受阻。中间层的直方图也是如此。

结果:案例 d)不公平背道具(从后面) (数据增强)(10 Epoch)

左图 →一段时间内测试图像的精度/成本
右图 →一段时间内列车图像的精度/成本

同样,当我们执行数据扩充时,我们可以观察到训练图像的准确性下降。

并且当比较来自情况 b)的结果(10 个历元的正常反向支持)时,我们可以观察到训练图像上的准确度彼此相似(49%)的事实。然而,不管是什么原因,由不公平反向支持训练的网络在测试图像上具有更高的准确性。

左图 →训练后权重直方图
右图 →训练前权重直方图

与情况 c)不同,我们可以观察到这种情况下权重分布的一些对称性。

结果:情况 e)不公平的后道具(来自前方) (无数据增强)(10 个历元)

左侧图像 →一段时间内测试图像的精度/成本
右侧图像 →一段时间内训练图像的精度/成本

最后,我想看看,当我们对网络的后半部分不公平时,是否有区别。从表面上看,对我们网络的开始部分不公平比后面部分不公平要好。

我这么说的一个原因是因为测试图像的最终准确性。我们可以观察到在训练图像上的准确性是相似的,但是该网络在测试图像上具有较低的准确性。

左图 →训练后权重直方图
右图 →训练前权重直方图

有趣的是,不管我们对网络的开始部分还是后面部分不公平,权重的分布似乎是相似的。

结果:案例 f)不公平的后道具(来自正面) (数据增强)(10 个历元)

左侧图像 →一段时间内测试图像的精度/成本
右侧图像 →一段时间内列车图像的精度/成本

最后,我在训练来自案例 e 的相同网络时执行了数据扩充。

如上所述,这里也可以观察到精度没有提高。

左图 →训练后权重直方图
右图 →训练前权重直方图

重量分布也有类似的结果。在普通的 CNN 中,我们知道后面的层捕捉更高级的特征。我怀疑网络更努力训练比较好?捕捉更高层次的特征。

交互代码

对于 Google Colab,你需要一个 Google 帐户来查看代码,而且你不能在 Google Colab 中运行只读脚本,所以在你的操场上复制一份。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!同样为了透明,我在 github 上上传了所有的训练日志。

要访问案例 a 的代码,请点击此处,要查看日志,请点击此处。
访问案例 b 的代码请点击此处,日志的请点击此处。
要访问案例 c 的代码,请点击此处,要查看日志,请点击此处。
要访问案例 d 的代码,请点击此处,要查看日志,请点击此处。
要访问案例 e 的代码,请点击此处,要查看日志,请点击此处。
要访问案例 f 的代码,请点击此处,要查看日志,请点击此处。

最后的话

关于我为什么发这篇博文,我其实有更深层次的原因,很快就会揭晓。这种不成比例的反向传播的想法真的让我很感兴趣。

如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你希望看到我所有写作的列表,请在这里查看我的网站。

同时,在我的 twitter 上关注我这里,访问我的网站,或者我的 Youtube 频道了解更多内容。我还实现了广残网,请点击这里查看博文 t。

参考

  1. tf.cond |张量流。(2018).张量流。检索于 2018 年 6 月 17 日,来自https://www.tensorflow.org/api_docs/python/tf/cond
  2. TensorFlow?,H. (2018)。如何在 TensorFlow 中打印一个张量对象的值?。堆栈溢出。检索于 2018 年 6 月 17 日,来自https://stack overflow . com/questions/33633370/how-to-print-the-value-of-a-tensor-object-in-tensor flow
  3. 数学|张量流。(2018).张量流。检索于 2018 年 6 月 17 日,来自https://www.tensorflow.org/api_guides/python/math_ops
  4. tf.floormod | TensorFlow。(2018).张量流。检索于 2018 年 6 月 17 日,来自https://www.tensorflow.org/api_docs/python/tf/floormod
  5. tf.cond |张量流。(2018).张量流。检索于 2018 年 6 月 17 日,来自https://www.tensorflow.org/api_docs/python/tf/cond
  6. 使用 tf。TensorFlow 中的 print()—走向数据科学。(2018).走向数据科学。检索于 2018 年 6 月 17 日,来自https://towards data science . com/using-TF-print-in-tensor flow-aa 26 E1 cf F11 e
  7. Tensorflow?,H. (2018)。如何在 Tensorflow 中给 tf.cond 内部的函数传递参数?。堆栈溢出。检索于 2018 年 6 月 17 日,来自https://stack overflow . com/questions/38697045/how-to-pass-parameters-to-functions-inside-TF-cond-in-tensor flow
  8. TensorFlow?,H. (2018)。如何在 TensorFlow 中打印一个张量对象的值?。堆栈溢出。检索于 2018 年 6 月 17 日,来自https://stack overflow . com/questions/33633370/how-to-print-the-value-of-a-tensor-object-in-tensor flow
  9. 规范化的方向保持亚当,从亚当到 SGD 的转换,和内斯特罗夫动量亚当与…(2018).走向数据科学。检索于 2018 年 6 月 17 日,来自https://towards data science . com/normalized-direction-preserving-Adam-switching-from-Adam-to-SGD-and-nesterov-momentum-Adam-with-460 be 5 ddf 686
  10. 谷歌合作实验室。(2018).Colab.research.google.com。检索于 2018 年 6 月 17 日,来自https://colab . research . Google . com/drive/1 okr 4 jfqbmoq 8 q 4 ctzdjmp 8 jqea 4 xdqbk
  11. 反向传播|杰出的数学和科学维基。(2018).Brilliant.org。检索于 2018 年 6 月 17 日,来自https://brilliant.org/wiki/backpropagation/
  12. tf.while_loop,I. (2018)。tf.while_loop 中是否可以定义多个条件。堆栈溢出。检索于 2018 年 6 月 17 日,来自https://stack overflow . com/questions/45595419/is-possible-have-multiple-conditions-defined-in-TF-while-loop
  13. Python,E. (2018)。Python 中每 N 次迭代执行一次语句。堆栈溢出。检索于 2018 年 6 月 17 日,来自https://stack overflow . com/questions/5628055/execute-statement-every-n-iterations-in-python
  14. 示例:基础— imgaug 0.2.5 文档。(2018).img aug . readthe docs . io . 2018 年 6 月 18 日检索,来自http://img aug . readthe docs . io/en/latest/source/examples _ basics . html
  15. CIFAR-10 和 CIFAR-100 数据集。(2018).Cs.toronto.edu。检索于 2018 年 6 月 19 日,来自https://www.cs.toronto.edu/~kriz/cifar.html
  16. [ ICLR 2015 ]追求简单:具有交互码的全卷积网。(2018).走向数据科学。检索于 2018 年 6 月 19 日,来自https://towards data science . com/iclr-2015-forwards-for-simplicity-the-all-convolutional-net-with-interactive-code-manual-b 4976 e 206760

从头开始展开朴素贝叶斯!

原文:https://towardsdatascience.com/unfolding-na%C3%AFve-bayes-from-scratch-2e86dcae4b01?source=collection_archive---------3-----------------------

对于 ML 初学者

Photo by Jukan Tateisi on Unsplash

从头开始展开朴素贝叶斯!Take-1🎬

W **无论你是机器学习的初学者,还是你一直在努力理解超级自然的 机器学习算法,但你仍然觉得点与点之间没有某种联系,这篇文章绝对适合你!

这篇博文的目的

我试图让事情简单明了。唯一的目的是深入和清楚地理解一个众所周知的文本分类 ML 算法(朴素贝叶斯)的工作原理,而不是陷入在 ML 算法的解释中经常使用的莫名其妙的数学术语!

谁是目标受众?

任何人从零开始寻找对 ML 算法的深入而易懂的解释

本教程的成果

一个完整清晰的朴素贝叶斯 ML 算法的图片,所有神秘的数学都被揭开了神秘的面纱,在你的 ML 旅程中向前迈出了具体的一步!

定义路线图…..🚵

**里程碑# 1 😗* 简单介绍一下朴素贝叶斯算法

**里程碑# 2 😗* 朴素贝叶斯模型的训练阶段

**重大里程碑# 3 😗* 测试阶段——预测开始发挥作用了!

**里程碑# 4 😗* 深入挖掘概率的数学

**里程碑# 5 😗* 避免下溢错误的常见陷阱!

**里程碑# 6 😗* 结束语……

简单介绍一下朴素贝叶斯算法

朴素贝叶斯是最常见的 ML 算法之一,常用于文本分类。如果你刚刚步入 ML,它是最容易开始的分类算法之一。朴素贝叶斯是一种概率分类算法,因为它使用概率来进行分类预测。

因此,如果你期待着在机器学习的旅程中向前迈出一步,朴素贝叶斯分类器绝对是你的下一站!

达到里程碑# 1👍

朴素贝叶斯模型的训练阶段

比方说,有一篇餐厅评论,“非常好的食物和服务!!!",你想预测这个给定的评论是暗示积极的还是消极的情绪。要做到这一点,我们首先需要在相关的带标签的训练数据集上训练一个模型(这实质上意味着确定每个类别的字数),然后这个模型本身将能够自动地将这样的评论分类到它被训练所针对的给定情感之一中。假设给你一个看起来像下面的训练数据集(一个评论及其相应的情绪):

Labelled Training Dataset

快速补充说明:朴素贝叶斯分类器是一种监督机器学习算法

那么我们如何开始呢?

步骤# 1:数据预处理

作为预处理阶段的一部分(这篇文章中没有详细介绍),训练语料库/训练数据集中的所有单词都被转换成小写和**,除了像标点符号这样的字母之外的一切都从训练示例中排除**。

**一个小提示:**一个常见的缺陷是没有以与训练数据集预处理 相同的方式预处理测试数据,而是将测试示例直接输入到训练好的模型中。结果, 训练好的模型在给定的测试示例 上表现很差,而在该测试示例上它应该表现得很好!

Preprocessed Training Dataset

第二步:训练你的朴素贝叶斯模型

只需简单地制作两个单词包(BoW),每个类别一个,每个包将简单地包含单词及其对应的计数。所有属于“正面”情感/标签的单词将被归入一个 BoW,所有属于“负面”情感的单词将有它们自己的 BoW。训练集中的每个句子都被拆分成单词(基于作为标记符/分隔符的空间),这是如何简单地构造单词计数对的,如下所示:

BoW for Both categories

我们已经完成了朴素贝叶斯模型的训练!

达到里程碑# 2👍

在进入第三个里程碑之前,喝杯咖啡或者舒展一下肌肉

Photo by Rumman Amin on Unsplash

注意:我们即将开始朴素贝叶斯模型最重要的部分,即使用上述训练好的模型来预测餐馆评论。我现在觉得这有点长,但完全值得,因为我们将讨论每一个细节,最终结果是零歧义!

测试阶段——预测开始发挥作用了!

考虑现在你的模型被给予一个餐馆评论, “非常好的食物和服务!!!" ,它需要归类到它所属的特定类别。正面评价还是负面评价?我们需要找到这个给定的评论属于每个类别的概率,然后我们会根据这个测试示例能够为哪个特定类别获得更多的概率,给它分配一个正面或负面的标签。

找到给定测试示例的概率

步骤# 1:测试示例的预处理

以与预处理训练示例相同的方式预处理测试示例,即,将示例更改为小写,并排除除字母/字母表之外的所有内容。

Preprocessed Test Example

步骤 2:预处理测试示例的标记化

将测试示例标记化,即将其拆分为单个单词。

Tokenized Preprocessed Example

快速边注 :你一定已经熟悉机器学习中的术语 特征 。在这里,在朴素贝叶斯中,的每一类训练数据集的词汇中的每个词构成了一个分类特征 。这意味着每一类的所有唯一单词(即词汇/vocab)基本上是该特定类的一组特征。为什么我们需要“计数”?因为我们需要分类词特征的数字表示,因为朴素贝叶斯模型/算法需要数字特征来找出概率分数!****

步骤 3:使用概率来预测标记化测试示例的标签

寻找概率的不那么吓人的数学形式

Probability of a Given Test Example i of belonging to class c

  • = 测试示例= “非常好的食物和服务!!!"
  • 中的总字数 i = 5,所以j****(表示特征号 ) 的值从 1 到 5 不等。就这么简单!**

让我们将上面的场景映射到给定的测试示例中,这样会更清楚!

让我们开始计算这些产品术语的值

第一步:求 c 类 p 项的值

Simply the Fraction of Each Category/Class in the Training Set

p of class c for Positive & Negative categories

步骤# 2:求项的值:乘积(c 类中测试词 j 的 p)

在我们开始推断特定类别中测试词【j】c的概率之前,让我们快速熟悉一些简单的符号,这些符号在这篇博客文章的不太远的行中使用:

Understanding Notations — e, i & j

由于目前我们的测试集中只有一个例子(为了便于理解),所以 i = 1。

快速补充说明 :在 测试时间/预测时间期间,我们将测试示例的每个单词映射到在训练阶段 发现的计数。因此,在这种情况下,我们在这个给定的测试示例中总共寻找 5 个单词计数。

Photo by Jared Brashier on Unsplash

只是一个让你无法入睡的随机事件!

求 c 类中测试词“j”的概率

在我们开始计算的乘积** ( p 中的一个测试字 j 中的类 c )之前,我们显然首先需要确定 p 中的一个测试字jc有两种方法可以做到这一点,如下所述— 几分钟后,我们将发现哪一种方法应该被真正遵循,而不是被实际使用……

让我们首先尝试使用方法 1 来寻找概率:

现在我们可以将单个单词的概率相乘(如上所述)以找到该项的数值:
乘积(测试单词
*【j】*c)

The Common Pitfall of Zero Probabilities!

到目前为止,我们已经有了两个术语的数值,即类 c产品(测试字*【j】和类 c 中的 p 因此,我们可以将这两项相乘,以确定这两个类别的p*(I属于类别 c )。下面演示了这一点:****

The Common Pitfall of Zero Probabilities!

p(I属于类 c )对于两个类别来说都是零!!!但显然测试示例“非常好的食物和服务!!!"属于正班!很明显,这是因为类中测试词
【j】乘积 ( p )对于两个类别来说都是零,而这又是因为中的几个词(以橙色突出显示)从未在我们的训练数据集中出现过,因此它们的概率为零!很明显是他们造成了所有的破坏!
******

那么这是否意味着无论何时出现在测试示例中但从未出现在训练数据集中的单词总是会导致这种破坏?在这种情况下,我们训练过的模型将永远无法预测正确的情绪?它只会随机选择积极或消极的类别,因为两者都有相同的零概率和预测错误?答案是否定的!这就是第二种方法(编号 2)发挥作用的地方,事实上这是一个数学公式,它实际上用于推导(I属于类 c )。但是在我们继续第二种方法之前,我们应该先熟悉一下它的数学原理!**

所以现在在添加了为 1 的伪计数* 之后,从未出现在训练数据集中的测试字的概率 p 将永远不会为零,因此**,** 项乘积(p【j】在类【c】)中的数值永远不会以零结束,这又意味着
p 所以一切都很好,不会再有零概率的破坏了!
*

所以方法 2 的分子项将增加 1,因为我们已经为词汇表中的每个单词增加了 1,所以它变成了 :

类似地,分母变成:

于是完整的公式:

Probabilities of Positive & Negative Class

Photo by Greg Rakozy on Unsplash

你快到了!

现在用第二种方法计算概率:

Handling of Zero Probabilities : These act like failsafe probabilities !

**********

现在作为测试例子的概率,“非常好的食物和服务!!!"与负面类别(即 7.74E-09)相比,正面类别(即 9.33E-09)更多,因此我们可以将其预测为正面情绪!这就是我们如何简单地预测一个测试/看不见的例子的标签

里程碑# 3 达成!!👍 👍 👍

只剩最后几笔润色了!

快速补充说明: 像所有其他机器学习算法一样,朴素贝叶斯也需要一个验证集来评估训练模型的有效性。但是,因为这篇文章旨在关注算法的见解,所以我故意避开它,直接跳到测试部分

深入挖掘概率数学

现在,您已经对训练朴素贝叶斯模型所需的概率计算建立了基本的理解,然后使用它来预测给定测试句子的概率,我现在将更深入地挖掘概率细节。
在计算上一节中给定测试句子的概率时,我们只执行了给定的概率公式来进行测试时的预测:

解码上面的数学方程式:

" | " =指已经给定的状态和/或一些过滤标准

=类/类别

" x " =测试示例/测试句子

p(c | x)****=给定测试示例 x ,它属于类 c 的概率是多少。这也被称为后验概率。这是为每个给定培训类的给定测试示例 x 找到的条件概率。**

p(x|c) = 给定类 c ,实例 x 属于类 c概率是多少。这也被称为可能性,因为它暗示了示例 x 属于类 c 的可能性有多大。这也是条件概率,因为我们正在从类的全部实例中寻找的概率,也就是说,在寻找 x 的概率时,我们已经将的搜索空间限制/调节到类 c 。我们使用在训练阶段确定的字数来计算这个概率。******

Here j represents a class and krepresents a feature******

由于我们有两个类,我们在上面的计算部分隐式地使用了这个公式两次。还记得在类p中找到一个测试字jc*的数值吗?*****

****p =这暗示了类 c概率。这也被称为先验概率/无条件概率。这是无条件概率。我们在前面的概率计算部分已经计算过了(在步骤# 1 中,寻找类 c 的 term : p 的值)

【p(x)=这也被称为 归一化常数以便概率p(c | x)确实落在范围【0,1】内。所以如果去掉这个,概率p(c | x)不一定落在[0,1]的范围内。直观地说,这意味着在任何情况下或不管其类别标签是正还是负,实例 x 的概率。
这也反映在全概率定理中,全概率定理用于
计算 p(x)
**

Total Probability Theorem

这意味着,如果我们有两个阶级,那么我们将有两个术语,所以在我们的积极和消极情绪的特殊情况下:

Total Probability Theorem for Two Classes

我们在上面的计算中使用它了吗?不,我们没有。为什么???因为我们正在比较正类和负类的概率,并且因为分母保持不变,所以在这种特殊情况下,省略相同的分母不会影响我们训练好的模型的预测。这两个类只是相互抵消。因此,虽然我们可以包括它,但没有这样做的逻辑理由。**但是同样由于我们已经消除了归一化常数,概率 p(c|x)不一定落在【0,1】T5 的范围内**

达到里程碑# 4👍

避免下溢错误的常见陷阱!

  • 如果你注意到的话,单词概率的数值(即类别【c中的一个测试单词**【j】)非常小。因此,将所有这些微小的概率相乘以找到乘积**(p【j】【c】)将产生甚至更小的数值,这经常导致下溢,这显然意味着对于给定的测试句子,训练的模型将无法预测其类别/情感。因此,为了避免这种下溢误差,我们采用如下数学对数的帮助:**

Avoiding the Underflow Error

  • 所以现在,我们将简单地把它们相加,而不是把微小的单个单词的概率相乘。为什么只有日志?为什么不是其他功能?因为 log 单调增加或减少,这意味着它不会影响概率的顺序。较小的概率在应用对数后仍然会保持较小,反之亦然。因此,假设测试单词“是”比测试单词“快乐”具有更小的概率,因此在通过 log 之后,虽然增加了它们的大小,但是“是”仍然具有比“快乐”更小的概率。因此,在不影响我们的训练模型的预测的情况下,我们可以有效地避免下溢误差的常见陷阱。

达到里程碑# 5👍

结束语……

  • 尽管我们生活在一个 API 的时代,几乎很少从头开始编码。但是深入理解算法理论对于正确理解机器学习算法实际上是如何工作的极其重要。只有关键的理解才能区分真正的数据科学家和天真的数据科学家,以及在训练一个真正优秀的模型时真正重要的东西。因此,在转向 API 之前,我个人认为,一个真正的数据科学家应该从头开始编写代码,以真正看到数字背后以及某个特定算法优于其他算法的原因。
  • 朴素贝叶斯模型最好的特点之一是,你可以通过简单地用新词汇更新它来提高它的准确性,而不是总是重新训练它。你只需要添加单词到词汇表中,并相应地更新单词数。就是这样!

Photo by Benjamin Davies on Unsplash

终于来了!终于!达到里程碑# 6😤 😤 😤

这篇博文到此结束&你已经在你的 ML 之旅中向前迈进了一步!😄

即将发布的帖子将包括:

  • 从头开始展开朴素贝叶斯!Take-2🎬用 Python 从头开始实现朴素贝叶斯
  • 从头开始展开朴素贝叶斯!Take-3🎬使用 scikit-learn 实现朴素贝叶斯( Python 的 机器学习的圣杯! )

敬请期待!📻

如果您有任何想法、意见或问题,欢迎在下面评论或联系📞跟我上 LinkedIn

内容许可—一些注意事项…

再用

图表和文本根据媒体的服务条款获得许可,即作者拥有其创作并在媒体上发布的内容的权利。"未经您的许可(或合理使用许可),其他人不得复制、分发或执行您的作品."

这篇博文中包含的来自其他来源的图片不属于本许可证的范围,可以通过标题“图片作者…”中的注释来识别。所有此类图片均取自 Unsplash ,可免费使用,无需获得摄影师或 Unsplash 的许可或提供其信用。详细的许可条款可以参考这里的。

引文 出于署名目的,本作品被引为

*****Aisha Javed, “Unfolding Naïve Bayes from Scratch !”, Towards Data Science, 2018*****

BibTeX 引文

*****@ARTICLE {javed2018a,
    author  = "Javed, Aisha",
    title   = "Unfolding Naïve Bayes from Scratch !",
    journal = "Towards Data Science",
    year    = "2018",
    note    = "https://towardsdatascience.com/unfolding-na%C3%AFve-bayes-from-scratch-2e86dcae4b01"
    doi     =  "2e86dcae4b01"
}*****

意外后果和古德哈特定律

原文:https://towardsdatascience.com/unintended-consequences-and-goodharts-law-68d60a94705c?source=collection_archive---------3-----------------------

使用正确指标的重要性

为了增加收入,一个客户服务呼叫中心的经理制定了一项新政策:不再按小时计酬,而是根据每个员工打电话的次数来支付报酬。在第一周之后,这个实验似乎取得了巨大的成功:呼叫中心每天处理的电话数量增加了一倍!只要员工的业绩良好,这位经理就不会费心去听他们的谈话,他对此非常满意。然而,当老板来访时,她坚持要出去到楼层,当她这样做时,她和经理都被他们听到的震惊了:员工拿起电话,发出一系列一个词的回答,不等再见就砰地放下电话。难怪通话完成数翻倍了!无意中,通过只根据通话量来判断绩效,这位经理已经激励员工重视速度而不是礼貌。不知不觉中,他陷入了古德哈特定律。

古德哈特定律简单表述为:“当一个度量成为目标时,它就不再是一个好的度量。”换句话说,当我们设定一个特定的目标时,人们会倾向于不顾后果地优化这个目标。当一种情况的其他同等重要的方面被忽视时,这就导致了问题。我们的呼叫中心经理认为增加处理的电话数量是一个很好的目标,他的员工尽职尽责地努力增加电话数量。然而,通过只选择一个标准来衡量成功,他鼓励员工以数量的名义牺牲礼貌。人们会对激励做出反应,我们的自然倾向是最大化评判我们的标准。

Goodhart’s Law Explained (Source)

一旦我们意识到古德哈特定律,我们就可以在生活中的许多领域最小化它的影响。在学校,我们有一个目标:最大化我们的分数。这种对一个数字的关注可能不利于实际的学习。高中就像是一长串为考试而记忆的内容,然后很快就忘得一干二净,这样我就可以为下一次考试在脑子里塞满信息,而不用考虑我是否真的知道这些概念。考虑到学校衡量成功的方式,这种策略非常有效,但我怀疑这是否是获得良好教育的最佳方法。我们看到古德哈特定律有害影响的另一个领域是在学术界,这里强调出版,用短语“出版或灭亡”来表示。发表通常依赖于在研究中获得积极的结果,这导致了被称为“p-hacking”的技术,其中研究人员操纵或子集化实验结果以实现统计显著性。当一个数字被用来衡量成功时,记忆而不是学习内容和 p-hacking 都是意想不到的后果。

从数据科学的角度来看,古德哈特定律的应用提醒我们需要适当的指标。当我们设计机器学习模型或对网站的界面进行更改时,我们需要一种方法来确定我们的解决方案是否有效。通常,我们会使用一个统计量,例如回归的均方误差或分类问题的 F1 分数。如果我们意识到只使用单一的衡量标准可能会有不利的后果,我们可能会再次思考如何对成功进行分类。就像呼叫中心经理根据处理的呼叫数量和客户满意度来判断员工绩效会更好一样,我们可以通过考虑几个因素来创建更好的模型。除了只通过准确性来评估机器学习方法,我们还可以考虑可解释性,以便创建可理解的模型。

虽然大多数人希望听到一个数字来总结一个分析,但在大多数情况下,我们最好报告多个度量(带有不确定性区间)。有时候,一个设计良好的指标可以鼓励我们想要的行为,例如增加退休储蓄率,但是,重要的是要记住,人们会试图最大化我们选择的任何衡量标准。如果我们最终以牺牲其他同等重要的因素为代价来实现一个目标,那么我们的解决方案可能对情况没有帮助。解决问题的第一步——数据科学或其他——是确定衡量成功的正确方法。当我们希望客观地找到最佳解决方案时,我们应该回忆一下古德哈特定律的概念,并认识到最佳评估通常是一组测量值,而不是使用单个数字。通过选择多个指标,我们可以设计出一个解决方案,而不会出现针对狭窄目标进行优化时出现的意外后果。

一如既往,我欢迎反馈和建设性的批评。可以通过推特 @koehrsen_will 联系到我。

数据科学的单元测试和日志记录

原文:https://towardsdatascience.com/unit-testing-and-logging-for-data-science-d7fb8fd5d217?source=collection_archive---------3-----------------------

Laufen Castle & Rhein Falls, Schaffhausen, Switzerland.

在我们的行业中,数据科学家的职责包括各种任务。通常,它从数据库查询开始,以完成的模型结束,事实上,这是许多公司的规范,它允许数据科学家专注于只存在于他们专业领域的任务;这是可以理解的,因为研究比其他任务更昂贵。然而,在许多资源匮乏的公司,数据科学家工作的端到端定义包括创建简单的 API、单元测试和日志记录。

在本教程中,我将创建输入输出单元测试、一个日志记录类和一个 API 合适的部署。为此,我们将创建一个使用 MNIST 数据集的监督分类器。请注意,单元测试和记录器的 python 代码是由科里·斯查费在这里和在这里提供的。

我们的 logger 是一个 decorator,它是一个具有日志功能的函数,使用“@my_function”语法包装其他函数。这个想法是使用一个通用的包装器,在我们的例子中:

  1. 每次执行函数时,为每个函数创建一个文件日志,其中每行包含函数的参数。
  2. 报告运行该函数所花费的时间。

我们将“@ my _ logger”&“@ my _ timer”添加到我们想要记录的每个函数中,并知道它们的运行时间。请记住,您可以脱机查看这些日志文件,如果出现错误,您可以相应地调试代码。

以下函数下载 MNIST 数据集,使用 MinMaxScaler 归一化数据,并将原始数据拆分为训练和测试数据集。

作为数据科学家,我们的任务之一是创建一个可以在以后的生产中使用的类。因此,我以一种非常熟悉的方式设计了‘the algorithm’类,你会注意到该类遵循 sklearn 的函数结构,即我们有众所周知的‘fit’和‘predict’函数(以及 init )。这些函数将在生产过程中使用,以使用训练集和测试集初始化类,使用训练集(即 fit())训练模型,以及使用测试集(即 predict())进行测试。为了简化,我特意使用了一个简单的训练测试分割。本教程的主要目的是解释单元测试和日志记录是如何工作的,而不是进行交叉验证、网格搜索或其他机器学习方法。最后用“@ my _ logger”&“@ my _ timer”修饰每个函数。

在我们创建单元测试之前,我们需要一些基于数据集的输入和输出示例。首先,我们下载 MNIST 数据集,我们将其分割为 60K & 10K,我们创建一个“算法”类变量并执行 fit(),我们观察训练精度和产生的混淆矩阵。就输入和输出而言,精确度数字和混淆矩阵是唯一的,并且如果我们的模型中有任何变化,包括输入、分割比、随机种子等,精确度数字和混淆矩阵也会变化。因此,在运行模型之后,我们保存单元测试的输出,我们的想法是,如果“算法”类或伴随的函数中有什么变化或中断,输出将会不匹配,测试将会失败。我们对类的 predict()函数做同样的事情,并保存最终的测试准确度和混淆矩阵。

以下是运行上述算法时的输出:

我们的单元测试类“TestInput”继承自“unittest”。' TestCase ',这允许我们使用几个已知的函数如' setUpClass,tearDownClass,setUp,tearDown ',前两个是先执行后执行,后两个是在每个测试函数之前执行。在“设置”功能中,我们下载数据,分割数据,并保存训练和测试精度以及混淆矩阵。这些变量将使我们能够创建两个使用 fit()和 predict()的测试,使用一个众所周知的输入,最后将结果输出与预期输出进行比较。

为此,我们创建了“test_fit()”和“test_predict()”。在每个函数中,我们使用“assertEqual”将使用 fit()或 predict()时的结果输出与预期的输出变量进行比较。预期输出是训练和测试阶段的准确度和混淆矩阵图。如果这些输入输出单元测试失败,这意味着我们的算法有一个关键的变化。最后,我们执行我们的单元测试,如下面的输出所示,你可以看到两个测试都通过了。

请注意,在这里有额外的断言可用于单元测试。

Ori Cohen 拥有计算机科学博士学位,并在机器学习、脑机接口和神经生物学领域完成了博士学位。

通用语言模型来增强您的 NLP 模型

原文:https://towardsdatascience.com/universal-language-model-to-boost-your-nlp-models-d59469dcbd64?source=collection_archive---------7-----------------------

来自 fast.ai 的人们已经因其前沿的深度学习课程而闻名,他们才刚刚开始。昨天,他们发表了他们对各种 NLP 问题的预训练语言模型的研究。这项研究非常棒。看看这些结果:

Taken from https://arxiv.org/abs/1801.06146

蓝线表示仅针对该任务训练的新模型,橙色表示针对该任务微调的预训练语言模型,绿色表示针对该任务数据集微调为 LM,然后针对其目标微调的预训练模型。最后一个选项比第一个选项取得了更好的结果,但数据量却少了 100 倍!

基本上,他们的方法允许使用预训练的 LMs,并使用更少的数据获得更好的结果。这和 ResNets 在 ImageNet 上的预训练在计算机视觉上做的差不多。他们已经发布了所有的源代码,并在 WikiText 103 上预先训练了 LM(103 百万字),所以可以在你的研究/项目中随意使用它。

它是如何工作的

简而言之,食谱如下:

  1. 在大型数据集上训练 LM 或下载预先训练的 LM。
  2. 在你的数据上微调这个 LM。
  3. 加几层,微调一下,解决手头的任务。
  4. 干得好!你可能刚刚取得了 SOTA 的成绩。现在,您可以选择另一个问题并返回到步骤 2。

现在让我们更仔细地看看每一步。

  1. 只是一个三层 LSTM,具有精心调整的丢弃参数,如本文中描述的(AWD-LSTM)在 WikiText 103(28,595 篇预处理的维基百科文章和 1.03 亿字)上训练。
  2. 根据上一步的数据对语言模型进行微调。一般来说,当模型忘记了它以前学过的东西时,就会产生一个问题。为了解决这个问题,作者提出了两种技术:区别微调(从最后一层到第一层,以某个因子减少每个先前层的学习速率,在这个特定情况下为 2.6)和倾斜三角形学习速率(在迭代的第一~10%线性增加 LR,然后线性减少它)。
  3. 最后,添加一些完全连接的层,并为该任务训练模型。为了避免灾难性的遗忘这一步,作者建议逐步解冻(首先冻结所有预先训练的权重,并在每个时期后解冻一层,从最后到第一)。此外,对于分类任务,他们将大文档分成几批,并用最后一批的隐藏状态初始化模型。
  4. 他们已经报告了 6 项任务的 SOTA 结果,并且正在进行中。

这真是太棒了。相对于 CV,NLP 中的分类相当困难,但是现在我们可以用几百个例子训练一个好的模型。这种方法不仅适用于分类,而且适用于几乎所有类型的 NLP 问题。我想这项研究将会产生和几年前单词向量一样大的影响。看到最终能用它解决多少任务,我真的很激动。

通用风格转移

原文:https://towardsdatascience.com/universal-style-transfer-b26ba6760040?source=collection_archive---------8-----------------------

Fig. 0

NIPS 2017 上的一篇有趣的论文是这样的:通过特征转换进行通用风格转换 0。有一堆基于神经网络的风格转换技术,特别是在艺术风格的神经算法【1】之后。所有现有技术都有以下主要问题之一:

  1. 在推理过程中效率不高:上面提到的1就是一个例子。
  2. 风格特定的网络。这方面的一个例子是论文实时风格转换和超分辨率的感知损失【2】。
  3. 就输出质量而言,泛化能力差:这方面的一个例子是论文使用实例规范化的实时任意样式传输 3

正在讨论的文件声称要解决上述问题。这篇博客是对这篇论文的评论。假设对深度学习和线性代数有一些基本的了解。作者的代码库可以在这里找到。

在一些地方(图 9、10 和 12 ),我用图像来表现数学。这主要是因为 medium 蹩脚的数学支持。我使用https://latexbase.com/在 latex 上生成数学,然后拍摄他们的快照。(我知道,很痛苦)

问题(万一从上面还没看清楚):给定一个有一定内容在里面的图像(称之为内容图像)和另一个嵌入了一定风格的图像(想想一幅名画的图像。让我们称这种样式为图像)。目标是构建一个新的图像,它具有内容图像的内容和样式图像的样式。如下图所示。

Fig. 1 Content Image + Style Image = Stylized Content Image [4]

这篇论文的卖点是“免学习”。现有的基于前馈的技术需要在预定义的风格上进行训练,然后针对新的风格进行微调。然而,本文提出了一种在训练阶段完全独立于风格的方法,使其成为一种“免学习”的方法。请注意,3本质上与本文更接近,但依赖于训练时的样式图像(但可以很好地推广到任意样式图像)。

在本文中,风格转换问题被表述为两个过程的组合,即使用白化和颜色变换的图像重建和特征变换(WCT)。

图像重建

经典的编码器-解码器机制是这样一种机制,其中图像被馈送到编码器网络,编码器网络对图像进行编码以形成表示,并被传递到解码器,解码器试图重建原始输入图像。该文件使用了一个轻微的修改,这为图像重建。

Fig. 2 A classic Encoder-Decoder Network(just a reference not used in paper) 5

作为第一步,他们在 Imagenet 图像分类任务上训练 VGG-19(此后称为 VGG)。这被用作编码器。下一步,固定编码器,训练解码器来重建图像。看起来如下所示:

Fig. 3 Encoder-Decoder for reconstruction 0

上图中看到的 Relu_X_1 和 DecoderX 有些清晰:它们训练不止一个解码器进行重建。事实上,他们训练 5 个解码器进行重建。我们很快就会看到原因。但是,这里的“X”是指 VGG 网络中的层数。X = 1,2,3,4,5 是本文中使用的值。VGG 编码器部分结束于层 Relu_X_1,并且解码器(DecoderX)被构造成与该编码器对称。他们使用像素重构损失和特征损失的组合,如下所示。

Fig.4 Loss function for Decoder Reconstruction

像素重构是重构输出(I_o)和输入图像(I_i)的简单 L2 范数。特征损失是重建的输出和输入图像的 Relu_X_1 特征的 L2 范数。这里φ代表提取 Relu_X_1 特征的 VGG-19 编码器。λ是损失的加权系数。编码器和解码器现在已被训练和固定。请注意,我们在整个培训过程中从未使用任何风格图像。

格式化

Fig. 5 Single level Stylization 0

上面的图像代表单级风格化。这包括作为编码器(VGG Relu_X_1)的输入的内容图像(C)和样式图像(S)。请注意,这些输入是相互独立地传入的(每个输入都独立地通过 VGG)。编码器的输出被发送到白化和着色变换模块(我们将在下一节中看到更多细节),然后其输出被传递到解码器(Recons DecoderX)以获得最终的风格化输出。下图显示了 X=1、2、3、4 和 5 时的风格化输出。较低层(1 等。)捕获像样式颜色这样的特征,而更高层(比如说,5 层)捕获样式结构。

Fig.6 Stylized outputs for each of the layers/decoders 0

作者继续使用所有层的特征,而不是只坚持一层。这导致了如下所示的体系结构。

Fig. 7 Multi level stylization 0

我们从内容和风格图像开始,将它们提供给 VGG,Relu_5_1 特征被提取并发送到 WCT,然后解码。解码器 5 的输出与样式图像一起被馈送到 VGG,并且 Relu_4_1 被提取,并且该过程继续,直到我们从解码器 1 获得输出。下图显示了这种多级推理的结果。I_5 实际上是第一级的输出(如上图),I_1 是解码器 1 的输出(最终输出)。绝对比单级风格化好看。

Fig. 8 Multi level stylization outputs at various levels 0

增白和颜色变换(WCT)

在上一节中,我们把 WCT 看作一个黑盒。让我们深入研究一下,了解它到底在做什么。请记住,在模型训练中,我们从未使用过任何样式图像。我们的编码器是经过 Imagenet 训练的 VGG,解码器经过训练,可以在编码器的不同特征级别进行重构(Relu_ X _1)。WCT 做了一些很酷的数学运算,在从风格图像中转移风格特征的同时仍然保留内容方面起到了核心作用。

让我们将 WCT 视为解除输入图像的当前样式的关联并将样式图像的样式与输入图像相关联的过程。第一步是美白。

我们知道 WCT 模块的输入是编码器模块的输出(Relu_X_1)。Relu_X_1 的形状为 C x H x W ,其中 C 为通道数, H 为高度, W 为特征图的宽度。这是假设单个输入图像。我们对这些特征图进行矢量化,从而得到长度为 H x WC 个向量。设 f_c 为形状的矢量化特征图[ C,(H_c x W_c)], 其中 H_cW_c 分别为内容图像在某一 Relu_X_1 处的特征图的高度和宽度。同样,设 f_s 为形状[ C,(H_s x W_s) 的矢量化特征图,其中 H_sW_s 分别为特征图在某一 Relu_X_1 处因风格图像而产生的高度和宽度。

白化变换:

我们的目标是找到 *f_c,我们称之为 f_ct 的变换,使得 f_ct 的协方差矩阵是一个单位矩阵,即f _ CT x(f _ CT . transpose)= I .*这保证了特征图没有相关性。更正式地说,

*f_ct = W x f_c,*其中 W 是变换矩阵。一个很常见的选择 W 是 Y 的平方根倒数,其中 Y 是协方差矩阵 *f_c x (f_c.transpose)。*在更好的表述中:

Fig. 9

小注意:根据协方差矩阵的定义,为了使Y =**f _ c x(f _ c . transpose),我们需要从 f_c 中减去平均值 m_c(每通道平均值)。上面的 f_c 实际上代表的是减法后的值。

可以看到 Y 是实值对称矩阵。因此,我们可以对这个矩阵进行特征分解,最终的 f_ct 如下所示:

Fig. 10

很容易验证新 f_ct 的协方差矩阵是一个单位矩阵(不相关特征)。你可以把这当成一个练习:)

Fig. 11 Inverting whitened Relu_4_1 features 0

以上是增白过程的实验验证。基本上,他们运行的模型只有美白块(没有着色块)。您可以看到,最终的构造保留了内容(金门),但删除了任何与样式相关的信息。

着色变换:

这是白化变换的一种逆运算。记住,通过白化,我们有效地将特征从它们的风格中分离出来。现在,我们将通过变换白化结果(等式 1)来将这些与样式图像的样式相关联。

我们的目标是找到 f_ct 的一个变换,让我们称之为 f_cst ,使得 f_cst 的协方差矩阵等于 f_s 的协方差矩阵。记住 f_s 是由于风格图像的矢量化特征图。再小提一下,mean m_s 是从 f_s 中减去的(原因同上)。更正式地说:

Fig. 12

用上面的 f_cst 的值很容易验证(2)

我试图简要地解释这篇论文的要点。如果你觉得有趣,那就去读报纸吧。该文件有更多的训练细节和其他功能,如用户控制和纹理合成。您也可以在这里试用代码:6

如果你喜欢这篇文章,那就来吧,伸出你的手,给我一些👏 😃

参考文献:

[4]:https://research . Google blog . com/2016/02/exploring-intersection-of-art-and . html

释放流程挖掘的价值

原文:https://towardsdatascience.com/unleash-the-value-of-process-mining-4e3b5af4e9d8?source=collection_archive---------1-----------------------

Looking for an easy way to analyze complex processes?

(公民)数据科学家的强大能力

关于;在…各处 ;大约

这篇文章的目的是向读者介绍流程挖掘,一种创新的分析方法以客观和详尽的方式了解任何流程。它当然涵盖了的关键概念和定义,以及的好处,技术的要求,以及的成功标准,希望能给你灵感将这些技术应用到你自己的职业现实中。

让我们一起来了解一下这个复杂过程探索的迷人创新解决方案吧!

内容

  • 什么是流程挖掘?
  • 利益
  • 它是如何工作的?
  • 流程挖掘如何大幅提升流程发现?
  • 关于所需数据的一句话
  • 成功标准
  • 结论

什么是流程挖掘?

大多数组织创建业务流程,这些流程有时难以控制和理解。然而,在采取任何改进措施之前,理解这些流程是绝对必要的。

流程挖掘是一门由强大的分析技术支持的学科,这使得容易快速获得完整的目标图,从而控制持续改进。这是通过分析 IT 系统中的大量可用数据实现的。主要是执行哪些活动、何时执行以及由谁执行。

从这个意义上说,流程挖掘位于业务流程管理和数据挖掘的交叉点。

流程挖掘是一个非常有价值的洞察生成解决方案:你有没有问过自己,在一个特定的流程中到底发生了什么,观察到了与最初设计流程的哪些偏差,瓶颈在哪里,如何优化流程?如果是这样,那么您应该明确地将流程挖掘作为您团队工具箱的一部分。

由于流程挖掘工具使用起来非常直观,并且高度可视化,我建议您在深入了解更多细节之前,先看一下下面的视频,以展示流程挖掘在银行流程中的强大功能。这个视频是由 Fluxicon 创作的。

Process mining applied to the banking industry (ILLUSTRATIVE)

利益

使用流程挖掘为企业主和组织提供了几个好处。我们在下面列出了最重要的几个:

  • 了解流程实际上是如何执行的。

大多数时候,企业主从理论角度非常了解他们的流程:应该发生什么,什么时候,谁应该做什么,在什么条件下。

然而,他们通常没有办法调查在整个流程生命周期中到底发生了什么。传统的报告、商业智能(BI)和统计工具很难揭示大的和非常详细的情况。这种从大画面到细节的来回导航实际上是理解真实生活情况的最有效的方式。流程挖掘解决方案,如 Disco 侧重于使其易于消化和利用。

There are often disconnects between ideal (well understood) and real (unknown) situations (ILLUSTRATIVE)

  • 通过了解流程中的实际流量、频率和延迟来改进流程

IT 系统日志跟踪大量有用的信息,使得计算从流程中的一个步骤切换到另一个步骤的路径和交付时间变得可行。人们可以利用这些有价值的信息来检测瓶颈、突出次效率、揭示最频繁的路径等。

  • 通过提高员工的生产力来节约成本

加快调查时间,让您的分析师腾出时间来改进流程,而不是分析现状。通过关注棘手问题来减少总体流程时间。

  • 协调不同地区的流程通过了解人们如何以不同的方式工作,了解最佳实践并调整流程。

Reveal local specificities, slicing and dicing at your convenience in the process across any dimension of analysis — contributor, entity, product, etc. (ILLUSTRATIVE)

  • 提高审计质量和效率。

以高效的方式进行审计,利用数据科学,避免基于观点的讨论(数据是不可知的!).

  • 通过对比旧流程和新流程,验证已实施的流程变更是否达到预期效果

想观察过程中任何变化的影响吗?进行前/后分析,量化您对新流程的影响和附加值!

它是如何工作的?

流程挖掘的一大优势是以不可知的方式分析任何流程。这要归功于数据,即在 IT 系统中执行的任何操作的足迹,并记录在其日志中。

为了理解这是如何工作的,让我们考虑一个由 5 个活动 A、B、C、D、E 组成的过程,并分析 3 个过去的项目如何通过这个过程来帮助了解它。

在下面的动画中,您可以观察到一些案例经历了不同的活动,或者经历了相同的活动但顺序不同**。其他一些循环相同的活动。**

流程挖掘包括基于历史数据分析所有可能的模式,并为调查创建高度可视化的流程图

From IT System log to an exhaustive, fact-based understanding of your process (ILLUSTRATIVE)

过程挖掘如何极大地提高过程发现练习?

过程挖掘的价值是双重的:产生有价值的洞察力以改进当前的过程,以及加速洞察力产生的时间,从而提高团队的生产力。让我们比较并强调这些优势:

没有流程挖掘

传统的流程发现方式是通过研讨会和访谈手动进行。****

1.耗时 : 对于做访谈和流程映射的人来说。如果他们能更快地完成工作,他们就能做更多的项目,从而为他们的组织交付更多的价值。

2.绑定资源:它将人们(受访者)从生产工作中绑定到讨论当前事情是如何完成的,只是为了理解“现状”流程。

3.主观结果:基于人们对流程的看法,而不一定基于流程的实际情况。

4.政治僵局风险:可能有不同意见无法解决(政治僵局)。在参与的人不能对“现状”过程和过程中的问题达成一致意见的情况下,项目失败的风险很高,并且根本没有进行过程改进。

5.不完整的图片:你得到的只是一个样本视图,而不是完整的图片。通过要求人们拼出过程,手动图片将永远不会完整。

6.测量成本高:人工跟踪测量成本高,有偏差,而且只能提供样本数据。这是关于使用秒表测量过程步骤以收集客观证据的实践:(1)做这种手工工作非常耗时,(2)被观察的人的行为与正常情况不同,以及(3)只能获得有限的样本(例如,在几周内追踪 30 个案例)。

7.难以复制:因为流程诊断和信息收集的成本太高,不容易重复。

使用流程挖掘

任何过程改进项目的起点都是所谓的“现状”过程分析,在该过程分析中,绘制出过程的当前状态和所有缺陷,并确定改进机会。流程挖掘通过限制人员访谈和从 IT 系统的现有数据中提取必要的信息,大大降低了理解当前流程的成本

有了流程挖掘,前面提到的棘手问题得以解决:

1.时间高效:分析师花在访谈和研讨会上的时间更少。相反,“原样”流程是根据组织中的 IT 数据自动重建的。

2.释放资源:研讨会可以更有成效,因为真正的“原样”流程已经可以作为一个起点。

3.客观结果:数据为诊断和改进决策提供事实依据。

4.摆脱政治僵局:就过程现实而言,没有发表意见的余地。

5.完整画面:所有异常都随正常流程带入画面。例如,可以分析过去一年的所有流程变化和实际延迟,以获得完整的画面。

6.测量成本更低:流程步骤之间的实际持续时间和延迟可以针对数千个事务进行测量。

关于所需数据的一句话

对于所有的数据驱动技术,为了能够从过程挖掘中充分受益,数据准备起着重要的作用。

在这一节中,我将向读者简要介绍数据需求,包括创建一个可以输入到流程挖掘工具中的事件日志**。**

先决条件

任何过程分析都需要哪些关键要素?实际上只需要 3 条主要信息:

  • 活动(流程步骤):组成流程的几个步骤。
  • Case ID :通过流程的任何物品的唯一标识符。
  • 时间戳(用于性能评估):每个项目到达和离开任何活动的标志。

可选

对于更高级的分析,我强烈建议您用附加(可选)信息来补充这些先决条件,例如资源**、国家部门等。参与其中。**

利用这些额外的数据将能够进行更高级、更详细的调查(地域特殊性、根据产品类别而区别对待的产品等。)

Process Mining tools can ingest information once prepared in this simple template (event log) (ILLUSTRATIVE)

成功标准

有兴趣启动流程挖掘计划吗?在开始之前,提醒一下流程挖掘是一门学科**(不仅仅是一种工具),它需要人们需要学习的技能(例如,如何检测数据质量问题,如何解释结果,等等。)并且过程挖掘只是与领域专家讨论的起点(所以目的不是自动生成确定的答案并停止与人交谈,而是开始在不同的层面上与他们交谈)。**

确保从一开始就确定成功的标准。

  1. 关注商业价值:从有效性(客户体验和收入)、效率(成本)和风险(可靠性)三个方面定义商业价值。确定您想要深入了解流程的哪些方面。这种洞察力有助于哪种业务驱动力?更好的客户体验、降低成本、降低风险?
  2. 从小处着手,大处着眼:将业务驱动因素与特定的业务领域联系起来。选择一个起点和终点都明确的过程。这一过程的每一个管理者都将从有助于降低成本或提高效率的见解中受益。当你考虑可能的使用案例和应用可能性时,也要确保传达流程挖掘不是什么。通过指出清晰的界限,你可以管理对它的期望。
  3. 工作假设驱动且周期短:将主要业务驱动因素分成子假设,您可以通过流程挖掘分析来确认或否定这些子假设。例如:有一种直觉,认为某个特定的服务流程耗时太长。这个过程需要多长时间?它与预期偏离了多少?导致这一过程延迟的瓶颈在哪里?此外,您还可以指出流程中延迟的确切位置。让您的业务利益相关者从一个洞察到另一个洞察。刺激他们提问。探索,分析,创新。时间盒中间结果和项目。第一个项目的八周通常是一个很好的目标。
  4. 事实不会说谎:流程挖掘允许你根据事实而不是主观意见来分析流程。公开透明地谈论你使用的数据和从分析中得出的事实。这可能是对抗性的,对一些人来说甚至是不受欢迎的。组建一个有能力处理阻力的变革管理团队。过程挖掘可以是这一真相发现的完美助手。总是使用来自业务流程领域和 IT 领域的专家来对数据和分析进行完整性检查。使用流程挖掘作为建设性的起点,提出正确的问题,避免过快的判断。

结论

几年前,我跟随流程采矿大师 Wil van der Aalst 的在线课程发现了流程采矿,这真的让我大开眼界。它的好处数不胜数,绝对应该成为任何数据科学家的工具箱的一部分!

我很高兴收到任何类型的反馈,所以请随时发表评论并分享您的观点(意见、用例等)。)在这个能力上。

Struggling with your processes? No need to get your hands dirty anymore! Take full benefit of process mining!

来源

  • 流程挖掘:数据科学在行动 | Wil van der Aalst |埃因霍温理工大学| Coursera。
  • 实践中的流程挖掘 |由 active Fluxicon 的团队编写的综合性在线书籍。
  • Fluxicon 网站 |一家通过 Disco 实现流程挖掘“企业就绪”的创新公司。
  • Fluxicon 博客也充满了很棒的技术指导和用例。
  • ProM 网站 | ProM 是一个开源的可扩展框架,支持多种流程挖掘技术。
  • Celonis 网站 | Celonis 是一家技术公司,提供致力于流程挖掘的软件和咨询服务。
  • R 中的业务流程分析 | bupaR 是一个开源套件,用于处理和分析 R 中的业务流程数据,由比利时 Hasselt 大学的业务信息学研究小组开发。

注意

这篇文章主要基于我作为一个数据科学家爱好者的观点和详细的高质量 Fluxicon 文档。一个伟大的有价值的资源,对于任何有兴趣在理解基础理论上更进一步的人来说!

从机器学习中释放商业价值:模型可解释性

原文:https://towardsdatascience.com/unlocking-business-value-from-machine-learning-model-interpretability-c08100b788c8?source=collection_archive---------6-----------------------

为什么越花哨越好

这是人工智能革命。如果你的公司没有挖掘数据,把它塞进神经网络,并推销其先进的人工智能能力,你已经落后了…对不对?不完全是。

就像明星球员会成为糟糕的教练一样,在高抽象层次上做出复杂决策的模型也是有代价的,他们不容易解释他们的推理。这是一个直接的(有时是昂贵的)权衡。

机器学习也有类似的范式。模型越强大,就越难解释其内部运作。当然,你可能会从神经网络中得到更准确的答案,但是它如何得出那个答案可能完全是个谜。当试图找出哪里出了问题或者如何改进时,这可能是一个问题。

现代营销巩固了“深度学习神经网络”作为科技领域最性感的四个词短语的竞争者。但是,数据科学家知道,越花哨并不总是意味着越好。

如果我告诉你 真正的商业价值 不一定与你的模型的“复杂程度”相关联呢?

模型可解释性

可解释性用于寻求对输入和输出之间复杂本质的理解。

Model Explainability vs. Power. Credit: iapp

让我们举一个简单的例子:预测 年家庭支出 。利用一个神经网络,我可以得到这个国家每一个人手里的每一美元的完美预测。那太好了,但是如果我想知道投入是如何促成那笔支出的呢?

一般的狗贵多少?一般的孩子?收入增加?这些因素肯定会增加支出,但是在高层决策中,每个因素增加多少可能是一个谜。

由于神经网络如何将输入转化为输出的复杂、抽象的本质,试图理解它是没有希望的。

Deep Learning interpreting inputs

相反,一个简单的线性回归可能会得到这些答案。虽然不太准确,但肯定会更容易理解。

Linear Regression interpreting inputs

你是选择线性回归、神经网络,还是任何介于两者之间的方式,可能在很大程度上取决于你的目标——是使用还是理解机器。换句话说,你需要一个好球员还是一个好教练?

商业价值

归根结底,什么对你的企业更有价值:最大化绩效指标还是理解投入产出关系?

问问你自己:

  • 我的客户需要了解机器的决定吗?

比如以“我不知道,机器刚这么说”为由拒绝贷款申请,就是不够好。改变生活的决定应该被清楚地传达,而且决定应该是公平的。

这是从可解释性中释放价值的基础**——被告知的客户是信任你的客户。**

最后一件事

还有一点值得一提:明确输入的重要性。

选择正确的输入对于建立一个可解释的模型至关重要。只有当你的输入一开始就有意义时,直观的输入-输出解释才是可能的。例如,考虑以下两个特征:

显然,第一个特征更容易理解:“每多生一个孩子,一个家庭平均每年将多支出 10,000 美元”,而“收入的平方根每增加 1,000 美元,平均每年支出就会增加 0.25 美元”。

尽管第二种方法可能有助于建立更准确的模型,但直觉上它毫无意义。输入是直观的,这一点至关重要——我们的客户和我们的决策可能会依赖于此。

结论

今天深度学习的爆发是很牛逼的,但我们不应该忘记基本面。

大多数商学院统计学课程关注线性和逻辑回归是有原因的。清晰的理解导致良好的决策、有效的沟通和信任你的客户。

最后,我想这是一种“嘿,有时客户也需要知道发生了什么”的冗长说法

揭开 PCA 背后的数学面纱

原文:https://towardsdatascience.com/unmasking-the-math-behind-pca-a1d003ba4adb?source=collection_archive---------8-----------------------

大量的特性可能是一件好事,也可能是一件坏事,这取决于具体的实例。这种情况经常发生,以至于相当多的可用特性是相关的,因此是多余的。更大维度的数据更难可视化。这就是降维技术派上用场的地方。PCA 可能是最常用的降维技术。它不会消除特征,而是从现有的低维特征中形成新的特征。为了真正理解这种算法,有必要掌握一些统计概念,这反过来又涉及到一些数学。但是,如果数学不是你的强项,也不要担心,因为我会尽量把它变得简单。因此,让我们更深入地探讨一下。

协方差

我们需要理解的第一项是协方差。协方差是两个变量之间的度量。它给出了一个维度的变化如何影响另一个维度的变化的度量。听起来真的很熟悉相关性,除了它不是。

标准差或方差是单变量分析的一种度量,其中这些度量的值给出了组成员对组均值的净偏差。这两个措施在一个维度上起作用。协方差在两个维度上起作用。

协方差是一种度量,用于找出维度相对于平均值的变化程度。总是在两个维度之间衡量。协方差的公式如下

协方差值可以是负数、零或正数。零协方差表示两个维度相互独立。正协方差表示两个维度一起增加和减少,而负协方差表示一个维度增加,另一个维度减少。

特征向量

特征向量是满足以下方程的任何向量:

Av = λv

其中 A 为(n×n)方阵,v 为特征向量,λ为特征值。

在这里你可以观察到,当特征向量 v 用矩阵 A 变换时,向量 v 只按因子λ缩放,也就是说,它改变了它的大小。它不会改变方向。

特征向量使理解线性变换变得容易。它们是线性变换简单地通过“拉伸/压缩”作用的方向。也就是说,v 和 Av 会在同一直线上,Av 只是将 v 拉伸或压缩一个因子λ,这个因子叫做特征值。

协方差矩阵的特征向量对应于最大特征值,如果它在数据中的方向(因为我没有更好的术语)具有最大方差。

PCA 的步骤

1)用平均值减去数据的每个变量。
将此存储在变量 roadjustdata
假设数据有 m 个实例和 n 个变量,得到的矩阵将是一个(m,n)形矩阵。

2)计算可用数据的协方差矩阵。

3)计算协方差矩阵的特征向量和特征值。
对于 PCA 来说,重要的是特征向量是单位特征向量。
特征向量帮助我们得到表征数据的线条。

The red dots represent the data points while the dotted lines represent the eigenvectors.

4)具有最高特征值的特征向量是数据的主成分。
一般来说,一旦找到特征向量,就把特征值从最高到最低排序。相应的特征向量按照分量的重要性顺序给出分量。

5)获取转换后的数据。
创建一个名为 FeatureVector 的新矢量,如下所示:

If you’ve chosen the first k principal components, then those eigenvectors are placed in columns in this matrix

这个矩阵将是(n,k)
的形状,其中 k 是你选择包括的主成分的数量。
现在,转换后的数据将是
transformed data = RowAdjustData * feature vector
,并且这个结果矩阵的大小将是(m,k)。注意,实际数据的形状是(m,n)。其中,k(我们选择的组件数)将小于 n,这就是降维的执行方式。

具有特征向量单元将是有用的,因为值将在变换时被放大或缩小。

在上图的例子中,我们简单地选择对应于正斜率虚线的特征向量,从而消除了一个维度。

拆包(** PCA)

原文:https://towardsdatascience.com/unpacking-pca-b5ea8bec6aa5?source=collection_archive---------11-----------------------

降维技术的一种实用实现

尽管互联网上有大量的 PCA(主成分分析)资源,但只有忍者才能在一定的合理时间内抓住整个想法,更不用说在你知道实际发生了什么的同时将想法具体化为代码。话虽如此,我们还是非常喜欢像专业人员一样应用 PCA 和解决真实案例的感觉。

在这篇文章中,我将尝试并清楚地说明人们可能会感到困惑的想法,我认为像我这样的新手会陷入其中并坚持几个小时。

事不宜迟,让我们直接进入正题。

首先,主成分分析是一种降维方法,更简单地说,是将多个特征(变量)归纳为较少特征的方法。假设,我们需要将新看到的动物分类为'或',我们将测量动物的特征,如'身高和'体重。我们也可以根据更多的特征对这种看不见的动物进行分类(颜色’、形状’、敏捷’…等等。)

但是,问题是,我们不能将它们归类为超过三个特征(维度),这对我们来说是视觉上无法解释的。另一个原因是,有些特征用起来不太重要,或者更糟的是,如果它们是随机数据或错误,有些可能是噪音,这两种情况都会干扰我们的预测。

简而言之,一个特征'体重'可能无法有效区分''和'',因此我们应该从数据中去掉'体重'。通过去掉大部分不重要的特征,我们可以节省计算成本。想象一下,我们的数据有 100 x 100 个特征,比如图像或遗传信息,尽可能地降低维度会好得多。

我们可以通过使用 PCA 来实现这些愿望。

PCA describe multiple variable with fewer Principal Components

最好是实现一下,以获得一个整体的想法。让我们从制作 5 *10 矩阵开始,并采取步骤的过程。

Matrix X

列是变量(特征),行是样本(比如“猫”或“狗”)。

我们想对这个矩阵做的是得到特征值和特征向量,它们变成了描述样本的新变量(主成分)。设矩阵***【x】*n p 大小,则 p p 协方差矩阵其中【c=xᵀx/n.】**协方差矩阵是埃尔米特矩阵和半正定矩阵,利用 谱定理 让我们得到一个协方差矩阵和特征值。但在此之前,不要忘记从同一列中减去每列的平均值。

我们设置'row var = False ',这样关系就转置了:每一列代表一个变量,而行包含观测值。然后,我们得到 w 中的特征值和 v 中的特征向量。

Means of each columns

*10 10 Covariance Matrix

*此时,特征向量是 10 10 的矩阵。为了执行从 10 个变量到 2 个变量的降维,我们需要截断矩阵。

然后,我们要将(主轴上的投影 X)原始的 10 10 样本变换到新的空间(二维空间),我们使用等式=XV。*

*10 2 Eigenvectors (Principal components)

*我们得到了矩阵 5 2 矩阵 T ,投影到 2 个主成分上。我们最后用两个变量来描述每个样本。

*有趣的部分应该是可视化这些转换后的样本数据。让我们使用更大的数据。从定义 200 2 矩阵 X 开始。

(在这种情况下,特征值是 2,因此我们实际上不需要将其截断为 2)

最后剧情。让我们不要忘记设置 轴‘相等’,这样我们可以看到主分量的正交性。否则,我们将得到一个不垂直的特征向量。

Original sample plot(Fig. left) and plot eigenvectors(Fig. right)

让我们也绘制转换后的样本。因为我们的样本已经是二维的,我没有必要截断它们,但是,让我们采取降维过程的步骤。

最后剧情。

正如我们所看到的,两个主分量是正交的,因为它们被 PCA 去相关,所以变量是相互独立的。

Fig. 1: Plot transformed sample data

样本数据也沿着两个主轴进行变换(不相关/旋转)。

Fig.2: Uncorrelated sample data

为了更好地理解术语 【不相关/旋转】 ,让我们看一下图 1,并与图 2 进行比较。分散的数据实际上是完全相同的数据,但是,我们对它们进行了去相关(旋转),从而使两个变量(轴)相互独立(图 2)。

*为什么我们要用特征分解(或者为了效率用奇异值分解),用一些最大的特征值和对应的特征向量?这是因为 PCA 的目的是降低维数,但同时又尽可能用较少的变量描述样本。换句话说,我们想要在每个样本中变化的变量,而不想要在样本中相同的变量。我们可以通过使用更大的特征值或更大的方差来实现这个想法。根据信息论的观点,最大方差对应于具有最大熵的维度,因此,最大方差编码了最多的信息。然而,特征分解是昂贵的。假设,我们有图像样本,比如说 100 100 像素,这意味着它有 10000 个变量。它的协方差矩阵 C 将是 10000 * 10000 维。因此,我们通常更喜欢 SVD(奇异值分解)来将维度大小降低到样本大小,而不是可变大小。让我们试一试,用奇异值分解绘制样本。

SVD 将协方差矩阵 C *,wherec=xxᵀ/n***,分解成其中 S 是一个含有奇异值的(矩形)对角矩阵**【sᵢ***, U 是一个酉矩阵,而就奇异值***【sᵢ】而言,我们可以用【λᵢ=【sᵢ2)/n】,其中 n 是样本量,**【λᵢ】是特征值。

从这个结果中,我们通过 SVD 和本征分解看到完全相同的主分量。

让我们也确定特征向量是相互正交的。一个正交矩阵 Q 定义为 QᵀQ=QQᵀ=I ,其中 I 为一个单位矩阵。我们从奇异值分解得到了特征向量*【vᵀ】*现在如下图。

Vᵀ*** (Eigenvectors)***

V.dot(V.T)的结果是一个单位矩阵。

Identity matrix

在许多数学概念的理论中,例如偏最小二乘法,向量正交的概念经常出现。以这种方式检查它对于确保我们在正确的轨道上是有用的。

PCA with SVD

人们可能想观察每个点离中心有多远。其中一个方法是画一个等概率图,或者误差日蚀图。这对于查看两个组中间的样本特别有帮助,例如,我们可以将它用于 K-means 聚类。

我们从导入模块开始。然后,我们想用奇异值分解原始样本的协方差矩阵。

酉矩阵 U_ 用于旋转样本数据,现在我们分别使用U _【0】U _【1】,余弦,正弦,这样我们就可以得到正切来计算角度。

Equiprobability: ecliptic error circle

角度是从 x 轴。当坐标轴由标准差定义时,日食由方程定义,(x/σ₁)【+(y/σ₂)= s**,其中 σ₁ 为 x 轴的标准差, σ₂ 为 y 轴的标准差, s 为样本的方差。**

The angle between X and PC1

x=2σ₁√s 表示一个标准差。我们在上面的代码中绘制了三次。第三个圆圈包含图像上的大部分样本数据,因为它应该是 99.7%的置信区间。

我们可以使用 Scikit-learn 进行 PCA。让我们再看一遍同一个样本。像往常一样从样本数据开始。

*定义 200 2 矩阵 X ,为了剧情的缘故,我们使用两个组件。

剩下的过程和以前一样。

PCA with Scikit-learn version

结果是一样的。从代码中可以看出,我们可以通过 【分量 _ 获取最大特征向量,通过 解释 _ 方差 _ 获取特征值。

explained_variance_

让我们来看看 讲解 _ 方差 _

主成分解释了样本数据的 97.6%[0.7625315/(0.7625315+0.0184779)],第二主成分解释了剩余部分。这意味着我们几乎可以不用第二主成分来描述原始数据。Scikit-learn 已经计算了解释方差比率,因此我们可以使用 viaexplained _ variance _ ratio _

*为了更好地理解,让我们使用 1797 64 矩阵数字数据,并将这些维度从 64 减少到 10。

现在,我们可以看到这 10 个新组件可以在多大程度上描述原始样本数据。

Accuracy vs. number of components

事实证明,它描述了 7273%的样本,而不是使用确保 100%准确性的 64 个维度。请注意,在左图中,第一个成分是指数 0,这就是为什么该图从 1415%的方差开始。

假设需要多少元件才能达到 90%的精度呢?我们可以先清空 PCA 函数并绘制图形。

我们认为 20 个左右的成分对于 90%的方差来说就足够了。更简单的方法是将数字直接添加到函数中,例如,pca = PCA(.9)

为了进一步理解,让我们将转换后的样本数据转化为原始数据,并对它们应用热图。我们应该观察到,组件的数量越多,它创建的样本数据就越精确。

显然,原始数据比具有两个主成分的反演数据具有更多的特征。使用四十个主成分,我们可以更精确地反演转换后的数据。

我们实际上可以显示目前为止我们正在处理的数字数据。

Digits from original sample

让我们使这些数字图像更粗糙,或者更准确地说,一旦执行降维并将数字图像反转到原始大小。

Reconstructed digits images

我们也可以将 PCA 应用于特征脸,因为它的特征只有亮度,就像上面的数字图像一样。在重建原始数据方面,我们采取了与数字重建略有不同的步骤。因为我们首先需要一张平均脸。在转换数据后,我们添加平均脸。假设我们想要一个反转的人脸图像 XX 描述为x =μ+w** v+w****₂***** v*****

Full dimension(Fig. above) and 100 dimensions(Fig. below)

*正如我们之前讨论的,当维数很大时,SVD 表现良好。例如,这些图像是 62 47 = 2914 尺寸。如果我们使用本征分解,我们需要计算相关矩阵的 2914 2914 维。相反,奇异值分解可以通过样本大小样本大小来计算。

*主成分由 XV=US 给出。我们把维度从 500 降低到 100,现在 我们的 就是一个 500 100 的矩阵。

为了与原始人脸图像进行比较,我们要将 投影为 ,并将其逆投影为 X 。我们应用方程*【x=usvᵀ】,得到 500 * 2914 矩阵×19**。***

最后绘制图像。

Reconstructed face images with SVD(Fig. below)

得到的图像不像先前的 scikit-learn 方法那样模糊。似乎是更好的方法,我们使用的数据越少,构建的图像越清晰。这是因为样品的噪音更少,机器使用的过滤器更少。这将导致它自己对新图像的预测较低,这是机器以前从未见过的。

组成这些脸的特征向量称为特征脸,每个特征脸都是唯一的。让我们来看看他们是什么样子的,以及这些人脸图像的平均脸是什么样子的。

The average face(Fig. left), and the first five(most biggest) Eigenfaces(Fig. right group)

平均人脸是人脸图像的基础。

最后,这里是奇异值分解处理特征脸的概述。

SVD overview

参考

** [## 奇异值分解与主成分分析的关系。如何用 SVD 进行 PCA?

主成分分析(PCA)通常通过协方差矩阵的特征分解来解释。然而…

stats.stackexchange.com](https://stats.stackexchange.com/questions/134282/relationship-between-svd-and-pca-how-to-use-svd-to-perform-pca/) [## 理解主成分分析、特征向量和特征值

在今天的模式识别课上,我的教授谈到了 PCA,特征向量&特征值。我得到了…

stats.stackexchange.com](https://stats.stackexchange.com/questions/2691/making-sense-of-principal-component-analysis-eigenvectors-eigenvalues) [## 主成分分析的一站式商店

在我用于研究生统计理论课的教科书的开始,作者(乔治·卡塞拉和罗杰…

towardsdatascience.com](/a-one-stop-shop-for-principal-component-analysis-5582fb7e0a9c) [## 如何画出代表协方差矩阵的误差椭圆?

在这篇文章中,我将展示如何为 2D 正态分布数据绘制一个误差椭圆,也称为置信椭圆…

www.visiondummy.com](http://www.visiondummy.com/2014/04/draw-error-ellipse-representing-covariance-matrix/) [## 用于特征选择的主成分分析(PCA)及其一些缺陷

数据科学中的一个典型方法是我所说的宇宙特征化。我的意思是我们提取…

jotterbach.github.io](http://jotterbach.github.io/content/posts/pca/2016-03-24-Principal_Component_Analysis/) [## eigen faces-scholar pedia

特征脸可以被认为是表征人脸图像之间的全局变化的一组特征。然后…

www.scholarpedia.org](http://www.scholarpedia.org/article/Eigenfaces#fig:PIE.jpg) [## 基于主成分分析的特征提取——假人的计算机视觉

在这篇文章中,我们讨论如何主成分分析(PCA)的工作,以及它如何可以被用来作为一个维度…

www.visiondummy.com](http://www.visiondummy.com/2014/05/feature-extraction-using-pca/)**

解开政策梯度并加强

原文:https://towardsdatascience.com/unravel-policy-gradients-and-reinforce-5de9d0a8ab3?source=collection_archive---------10-----------------------

这一次,我们将让自己忙于另一个强化学习算法家族,称为基于策略的方法。如果你还记得,当谈到无模型强化学习时,有两组主要的技术。

我们分析了前两篇文章中的第一部分,其中我们谈到了 Q 学习和深度 Q 网络以及对基本模型的不同改进,如双深度 Q 网络和优先重放。看看这里的和这里的和。

让我们快速回放一下。请记住,我们将问题构建为马尔可夫决策过程,我们的目标是找到最佳策略,这是从状态到行动的映射。换句话说,我们想知道在给定的状态下,具有最大期望回报的行为是什么。在基于价值的方法中,我们通过寻找或近似价值函数来实现,然后提取策略。如果我们完全抛弃价值部分,直接找到策略会怎么样。这就是基于策略的方法的作用。

不要误解我。Q-learning 和 Deep Q 网络都很棒,它们在很多应用程序中使用,但是基于策略的方法提供了一些不同的优势:

  • 它们更容易收敛到局部或全局最大值,并且不会出现振荡
  • 它们在高维或连续空间中非常有效
  • 他们可以学习随机策略(随机策略给出动作的概率分布,而不是确定性动作。他们在随机环境中使用,他们将随机环境建模为部分可观测的马尔可夫决策过程,在这种情况下,我们无法确定每个行动的结果)

等一下。我讲了收敛,局部最大值,连续空间,随机性。这里发生了什么事?

嗯,问题是基于策略的强化学习是一个优化问题。但是这是什么意思呢?

我们有一个带有一些参数θ的策略(π),它输出动作的概率分布。我们想找到产生最佳政策的最佳θ。但是我们如何评价一项政策的好坏呢?我们使用一个政策目标函数 J(θ),它通常是期望的累积报酬。此外,无论我们有间断的还是连续的环境,目标函数都是不同的。

所以我们在这里,手里拿着一个优化问题。我们所要做的就是找到使 J(θ)最大化的参数θ,这样我们就有了最优策略。

第一种方法是使用强力技术并检查整个策略空间。嗯,不太好。

第二种方法是在策略空间或其子集中使用直接搜索。这里我们引入术语**策略搜索。**事实上,我们可以使用两种算法。让我们称他们为:

  • 无梯度
  • 基于梯度的

想一想你曾经用来解决优化任务的任何算法,它不使用导数。这是一个无梯度的方法,其中大部分可以用于我们的情况。一些例子包括:

  • 爬山是一种随机迭代的局部搜索
  • 单纯形:一种流行的线性规划算法(如果你喜欢线性代数,就去看看他)
  • 模拟退火,根据某种概率在不同状态间移动。
  • 模拟物理进化过程的进化算法。它们从一个以基因组表示的随机状态开始,通过交叉、突变和物理选择找到最强的一代(或最大值)。整个“适者生存”的概念包含在一个算法中。

第二类方法使用梯度下降或者更准确地说是梯度上升。

在(普通)梯度下降中,我们:

  1. 初始化参数θ
  2. 生成下一集
  3. 获得长期奖励
  4. 基于所有时间步长的奖励更新 theta
  5. 重复

但是有一个小问题。我们能以解析形式计算梯度θ吗?因为如果我们做不到,整个过程都会被扔进垃圾桶。事实证明,我们可以用一点小技巧。我们必须假设策略在非零的时候是可微的,并使用对数。此外,我们将状态-动作轨迹(τ)定义为状态、动作和回报的序列:τ = (s0,a0,r0,s1,a1,r1…,st,at,rt)。

我想今天的数学到此为止。当然,结果是,我们有了解析形式的梯度,现在可以应用我们的算法了。

到目前为止所描述的算法(略有不同)被称为加强蒙特卡洛政策梯度。与普通政策梯度的不同之处在于,我们去掉了对回报的预期,因为这不太实际。相反,我们使用随机梯度下降来更新θ。我们从期望值中抽取来计算该集的奖励,然后更新该集每一步的参数。这是一个非常简单的算法。

好了,让我们把那些事情都简化一下。你可以这样想政策梯度:

对于我们获得积极奖励的每一集,该算法将增加未来这些行为的概率。同样,对于负面奖励,算法会降低行动的概率。因此,随着时间的推移,导致负面结果的行为将慢慢被过滤掉,而那些有正面结果的行为将变得越来越有可能。就是这样。如果要从整篇文章中记住一件事,就是这件事。这就是政策梯度的本质。每次唯一改变的是我们如何计算奖励,我们选择什么策略(软最大,高斯等..)以及我们如何更新参数。

现在我们继续。

如前所述,增强是一种随机梯度下降算法。考虑到这一点,我想到了一个问题。为什么不使用神经网络来近似策略并更新 theta?

答对了。!

是时候将神经网络引入等式了:

当然,我们可以使用几乎任何机器学习模型来逼近策略函数(π),但我们使用诸如卷积网络之类的神经网络,因为我们喜欢深度学习。一个著名的例子是一个代理,它学习使用策略梯度和神经网络来玩 Pong 游戏。在该示例中,网络接收来自游戏的输入帧,并输出上升或下降的概率。

T3【http://karpathy.github.io/2016/05/31/rl/】T5

我们将尝试使用 OpenAI 的健身房环境做类似的事情。

你可以看到这不是小事。我们定义神经网络模型、蒙特卡罗抽样、训练过程,然后让代理通过与环境交互来学习,并在每集结束时更新权重。

但是政策梯度有其自身的缺点。最重要的是,它们具有很高的方差,并且很难稳定模型参数。

你想知道我们如何解决这个问题吗?保持联系…

(提示:它的演员兼评论家模型)

如果您有任何想法、评论、问题或者您只想了解我的最新内容,请随时在LinkedinTwitterinsta gramGithub或在我的

要阅读完整的深度强化学习课程,学习所有你需要了解的人工智能知识,去 这里

原载于 2018 年 11 月 1 日sergioskar . github . io

解开贝叶斯黑魔法:非贝叶斯主义者实施贝叶斯回归

原文:https://towardsdatascience.com/unraveling-bayesian-dark-magic-non-bayesianist-implementing-bayesian-regression-e4336ef32e61?source=collection_archive---------2-----------------------

首先,我是一个深度学习的人,直到最近我都很满意这一点。但我最近成了一个恶性小样本高维问题的受害者!所以我不得不把我的头转向擅长从小的学习的算法,并告诉我“我对那次学习有多有信心”。

这对我来说是一个相当突然的变化。因为我已经远离贝叶斯“东西”太久了。但是现在是改变的时候了。所以我不得不(几乎)从头开始学习。我被诸如先验、后验概率、 KL-DivergenceEvidence Lower BOund (ELBO) 之类的术语轰炸着(希望有一天我会再写一篇关于后两者的帖子!).然后我意识到“嘿,这和 frequentist 类型的算法没什么不同”。所以是时候解开结构化知识这个大球了,希望不要掉进兔子洞。

让我简单介绍一下将要发生的事情。所以我们要从一个频率主义类型的回归例子开始。然后,我们将会看到为什么我们可能想要用更有前途的技术来解决我们的例子,比如贝叶斯线性回归(显然是不确定性信息)。在那之后,我们将陈述贝叶斯规则,随后是关于我们如何能够采用贝叶斯规则来为给定的数据找到一个好的模型的快速注释。有了这个我们就可以定义先验、似然和后验项(我的意思是定义。不了解)。然后,我们将沿着一条漫长的道路(很长,但很有启发性)讨论这些术语。当我们讨论这些术语时,我们将看到我们在示例中得到的结果,以建立一些上下文。最后,我们将通过比较我们开始时(之前)和我们发现的最佳(之后)来做一个快速评估。

我们要解决的问题:Y= β1 X + β0 + ε

线性回归的第一个假设是,我们假设数据具有以下形式。

从这种模型生成的数据如下所示。

普通最小二乘(OLS)线性回归

假设我们得到了这个数据集,我们需要拟合一条线。我们通过将问题公式化如下来做到这一点。

我们的目标是找到β1 和β0,使数据的 RMSE(均方根误差)最小。从数学上来说,

首先让我们用线性回归拟合一条简单的直线。

A line fit to data with OLS linear regression

那么,这个结果说明了什么?

看起来还不错。事实上几乎是正确的。但是对于有限的数据区域,我真的可以依靠线性回归给出的答案吗?我不这么认为。我想要一个基本上说,

嘿,我之前看过很多这方面的数据,所以我对自己的预测还是蛮有信心的。

或者

嗯,这一点在我没有看到太多数据的地方。答案大概是这样,但我不太确定。

类似这样的。

Fitting lines with Bayesian linear regression. The red dashed line represent the mean line where the red solid lines on both sides represent the 95% confidence interval

你可以看到,在没有数据的地方,置信界限是如何增加的(因此答案的不确定性增加了)。但是线性回归给不了你这个。这就是为什么我们需要贝叶斯线性回归。那么,我们如何使用高级的“贝叶斯”疗法来解决这个问题呢?

重要的事情先来!所有贝叶斯“东西”的圣杯

贝叶斯规则

给定事件 B 发生的事件 A 发生的概率(——你感兴趣但不知道的事情)由给定事件 A 发生的事件 B 发生的概率(可能性)乘以 A 发生的概率()给出。

贝叶斯定理和这个问题有什么关系?

很好,我们已经听过无数次了!我想知道的是这和机器学习有什么关系。为此,设 A 为学习模型的参数(即β0 和β1),用θ表示, B 为你的数据, D 。现在让我们解释一下贝叶斯规则中的每个实体。

通过求解这个问题,我们将得到给定数据下θ (β0 和β1)中所有参数的联合分布。这正是我们所需要的。换句话说,P(θ|D)将告诉我们给定数据β0=0.5,β1=2.0,概率为 0.5,β0=1.5,β1=3.0,概率为 0.1。所以我们知道β0=1.5 β1=3.0 并不完全脱离这个世界(这是我们实际上在 frequentist 方法中假设的)!这叫做后验分布。

我们通过计算来计算

  • P(D|θ):如果我们的模型中有参数θ,我们有多大可能看到想要的数据
  • P(θ):我们对参数θ可能位于何处的先验信念。这越接近真实的后验概率,你就能越快越好地找到正确的后验概率
  • P(D):这是一个常数值,代表观察数据的概率

先验 P(θ):我们对什么样的参数的信念?

我们需要从一些参数值开始,对吗?在贝叶斯设置中,你不用一个值来指定事物,而是用分布来表示(例如高斯/正态分布)。在我们的例子中,我们可能会说,

用概率分布指定参数

嘿,我相信参数β0 可以用一个均值为 0,标准差为 3 的正态来表示。也就是说,

类似地,你说对于β1,

如果我们对β的许多值进行采样,我们就更接近真正的正态分布。如您所见,对于β0 和β1,许多值在接近 0 时被采样,但是与β0 相比,β1 更受挤压(与β1 相比,在 0 附近不太集中)

Priors we chose for β0 and β1

为什么是正态分布?

你会问为什么我们使用正态分布?正态分布具有非常好的分析特性。这样,我们就有了后验分布的均值和方差的解析解。关于解析后验解的更多细节。

为什么一个好的先验(P(θ))如此重要?

因为你的后路取决于此。也就是说,关闭你的前部到后部,你会更快到达真正的后部。要知道为什么,假设你的先验和后验是相同的,那么当你从先验采样时,你实际上是从后验采样(这是我们需要的)。

现在开始下一个重要的部分。看到数据的可能性。

可能性 P(D|θ):对于给定的θ,看到数据的可能性有多大

对于给定的一组参数,我们如何计算数据的似然性?换句话说,我们想要计算,

P(Y|X,θ)

下面,我们将做一步一步的探索,找到一个方程,我们可以计算这个实体的值。

计算可能性:P(Y|X,θ)

1.根据单个数据样本(Y 和 X)编写数据集(Y,X)

现在让我们试着为上面的项建立一个方程。

这是真的,因为假设,

  • 【数据点(,易)是独立同分布的

2.用 x,β1,β0 和ε来写 y

现在让我们回忆一下我们的数据是什么样的,

我们可以把这个方程代入似然方程,

3.使用条件变量隔离ε

我们给出了所有的 x,β1,β0,所以我们可以把它们从等式中去掉,

这样考虑这个变换,如果我需要 P(A+B|B)这和 P(A|B)是一样的,因为我们知道 B 是“给定”。换句话说,P(B|B) = 1,所以我们可以从 P(A+B|B)的顶部去掉 B,而 P(A|B)不受伤害。

4.假设:噪声与数据无关

现在我们开始下一个重要的假设,

  • 噪声与数据无关

这给了我们,

5.使用 PDF 的写入概率

记住我们的噪声是正态分布的,我们可以得到正态 as 的概率密度函数(PDF ),

6.假设:零均值恒定方差噪声

在线性回归中,我们对其中的噪声成分做了两个重要的假设。也就是说,它是正态分布,

  • 这是零均值
  • 它有一个恒定的方差

有了这两个假设,将噪声值代入我们得到的方程,

我们已经有了,

7.最终似然方程

所以让我们把它插上电源,

是的,都完成了!这是一个简单的变换系列,加上一些假设,以达到某种可计算的可能性函数。

使符号更简单

为了使事情更简单,从这一点开始,我们说,

这样一来,

直觉:如果 y=β1 x,似然如何寻找β1?

在我们的例子中有两个参数。所以为了简单起见,暂时忘掉β0。假设 y 和 x 是根据下式生成的

现在,我们通过尝试一系列不同的β1 值来进行近似,这将产生一个新的 y

对于β1 值的范围。可能性 P(y|x,β1)如下所示。

你可以看到接近 4 我们有很高的可能性看到数据。这正是我们所需要的。

更多直觉:我们前面例子的可能性

您可以将其推广到任意数量的β值(在我们的示例中是β1 和β0 值)。这是我们在例子中得到的图表。

上面的图表说明了什么?

上图显示,当β0 接近-2.5,β1 接近 1.5 时,我们最有可能看到数据 X,y。还要注意,β1 的可能性是一个很大的峰值,而β0 的分布更广。现在,作为一个练习,思考这对于每个变量对模型准确性的影响意味着什么。

希望这足够澄清事情。让我们继续到后面

后验 P(θ | D):我们最终需要什么?

后验概率是给定观察数据时参数(即β0 和β1)的概率密度函数。快速回忆一下,这是我们想要的最终结果(贝叶斯规则的左侧)。为了计算这个我们需要计算 P(Y|X, β1,β0 )P( β1,β0 )P(X,Y) 放在一起产生,

现在实体 P(X,Y)将是常数。因为无论我们对模型做了什么,无论我们有什么数据都会在那里。所以不会变。所以我要用一个常数 Z 来替换 P(X,Y),我们稍后会讨论如何计算这个 Z。

换句话说,

后验只是一个加权的先验,其中权重是对于给定的先验值看到数据的可能性

所以有两种方法可以解决这个问题。

  • 得到后验概率的解析解
  • 通过对许多β1 和β0 进行采样来求解该方程,然后近似后验概率

我们将使用取样。因为我们想通过更多的实践来学习

我们感兴趣的是后验概率和先验概率的表现。所以用解析解得到答案对我们来说就是作弊。让我们通过抽样来计算。

因此,我们将制定上述方程,以适应采样。

然后,我们通过从β0 和β1 各自的先验中提取 15000 个不同的值来近似完整的后验概率,并计算这些β0 和β1 组合的可能性。更具体地说,对于我们的例子,

所以我们解决了,

我们有后路。因为数据是独立的,β1 和β0 是独立的,所以我们可以把上面的实体写成,

通过赋予我们讨论过的符号简化,我们得到,

证据(Z=P(D)):使后验和达到 1

Z = P(D) = P(X,Y)

P(D) —这有时被称为证据,表示看到数据的概率。由...给出,

我们如何计算 Z?

我们如何能近似这一点?我们只是得到β1 和β0 样本的所有不同组合的 P(D|β1,β0)P(β1,β0)的总和(即贝叶斯规则的顶部)。我们取样越多,观察数据的概率就越真实,P(D)就越大。更具体地说,我们可以通过下式计算 Z,

这没有什么可怕的,这只是将 P 的顶部(β1(i),β0(i)|xj,yj)一遍又一遍地相加,得到我们对不同的β1 和β0 采样的总次数。Z 的存在使得后验概率下的面积加起来等于 1(你知道,因为这是一个概率分布)

对于我们的例子,先验、似然、后验结合在一起

下面我们把先验的、可能性的和后验的都放在一个地方来说明看起来如何。

图表显示了什么?

我可以做两个重要的观察。

  • 你可以看到,由于我们的先验稍微偏离了真实的后验概率,这种可能性实际上将后验概率从先验概率中抽离出来。如果先验越来越接近真正的后验,你会看到这种拉力在减弱
  • 下一个观察是,参数β1 似乎比β0 更敏感。否则,β1 的变化比β0 的变化更能影响结果的准确性。

最后,我们做一个比较,看看从先验分布(只有前 500 个样本)和后验分布采样的线的差异。我将让你来判断哪个更好。

如何获得新数据点的答案?

这很简单,因为我们有了β1 和β0 的后验分布。你只需从后验样本中抽取不同的β1 和β0,并得到这些β1 和β0 中每一个的值***【y】(即y =β1 x+β0***) 。有了这组 y 对于 x 的潜在候选,就可以计算出 y 的均值和 y 的标准差。

Jupyter 笔记本可在此处获得:

https://github . com/thushv 89/exercises _ thushv _ dot _ com/blob/master/Bayesian _ linear _ regression . ipynb

结束语

所以这有点长,但希望能揭开贝叶斯方法的一些“黑暗秘密”。通过一个示例任务,我们理解了贝叶斯线性回归是如何工作的;Y= β1 X + β0 + ε。

我们首先看到频率主义者的方法解决了问题,但是忽略了一些关键信息;答案的不确定性。然而,我们看到贝叶斯方法不仅会给出最有可能的答案,还会告诉我们这个答案的不确定性。

通过摘要的数据挖掘对代谢组学的当前和潜在趋势进行无监督分析

原文:https://towardsdatascience.com/unsupervised-analysis-of-current-and-potential-trends-in-metabolomics-through-data-mining-of-ee26acbd10a0?source=collection_archive---------8-----------------------

在短短几秒钟内不断更新有趣趋势的信息,这不是很酷吗?这是可能的,如果你挖掘文章摘要。

一个科学领域的进步取决于其从业者的自我评价。研究人员探索书目,以探索研究领域和相关领域的新兴模式。有了这些信息,他们可以研究现场社区感兴趣的新想法。

随着科学领域的蓬勃发展,在研究过程中获得新的见解需要更高的复杂性。因此,研究人员需要缩小他们的专业领域,以便为他们合作的跨学科团队贡献比较优势。

不幸的是,这种专业化可能意味着对相关领域发生的有趣趋势的认知度较低,而这些趋势可能有助于科学领域的进一步发展。油田可能越来越多地被封闭在筒仓中,其中一些程序是默认执行的,而不适应其他油田已经普遍存在的改进。

评论和会议是跟上新的有趣发展的有效手段。尽管如此,它们需要时间和认知投资,这些投资可以更好地用于继续推进项目。如果有某种方法能够以一种更自动和更容易解释的方式意识到新的有趣模式,那将是非常有益的。

Google Trends 支持调查和比较质谱和核磁共振等概念中的时间模式:

Google Trends

(试着在图片上找到圣诞节和暑假。)

尽管如此,Google Trends 只能处理单个概念,而不能处理关联概念。例如,“血液代谢组学”不能与“尿液代谢组学”相比,因为“血液代谢组学”和“尿液代谢组学”不是代谢组学研究中通常使用的概念。此外,对于谷歌趋势,我们需要在分析之前识别有趣的概念。但是,我们如何分析那些我们甚至不知道分析起来有意思的东西呢?

如果我们首先收集尽可能多的感兴趣领域的文本信息,就有可能对趋势进行“无监督分析”。有了这些信息,我们就可以分析一个词在一段时间内的使用次数,以及各种因素对其使用的影响。例如,合乎逻辑的是,使用核磁共振(nmr)作为分析平台的代谢组学文章比使用质谱(MS)作为分析平台的代谢组学文章更多地使用“NMR”一词。

通过在其搜索引擎中寻找具有例如“nmr 代谢组学”或“ms 代谢组学”的文章,然后导出找到的文章的摘要,可以从 Pubmed 数据库中提取文本信息。然后,R 包'记号赋予器'能够将导出的摘要组织成可以分析的单词列表。

核磁共振和质谱文章中最典型的词是哪些?

不出所料,排名大多被各分析平台的特定术语和代谢物占据。还可以找到一些专注于具体分析平台的研究中心。有趣的是,鱼似乎更容易被核磁共振分析而不是质谱分析。

这些信息可能很奇怪,并会产生一些转发,但可能不会有太大的成效。更有趣的可能是分析例如相对于前几年,哪些词在 2016 年的代谢组学中增加最多:

我们将永远拥有巴黎,“代谢组学”。我不会过度分析结果,因为科学产出可能有不规则的模式。尽管如此,2016 年似乎有相当多的新兴代谢组学文章来自非西方国家。对“1H”和“13C”的兴趣似乎也在下降,这可能是因为核磁共振的相关性在下降。

我还发现新出现的对利益冲突的担忧很有意思。尽管如此,这可能与《代谢组学》杂志最近提交的稿件中这一部分的要求相混淆。

(是的,在最差的排名中也有几个著名的名字……)

如果你需要写一篇代谢组学综述,或者你只是想在下一次会议上成为代谢组学的潮人/酷猎人/潮流引领者/什么的,与 2016 年相比,你可能对 2017 年代谢组学中正在流行或正在流行的词语更感兴趣:

很高兴看到指纹降低了它的相关性。跳上剖析的潮流;)

现在我们来分析一下相关领域有意思的趋势。如前所述,当试图在一个科学领域取得进展时,开发新方法的典型方式是试图从其他领域获取想法。代谢组学与蛋白质组学的联系比与其他组学的联系更紧密,蛋白质组学产生的年度研究产出比代谢组学大得多。因此,分析代谢组学中尚未探索的蛋白质组学的可能趋势是一个好主意。下面是蛋白质组学 2017 年和 2016 年的单词对比结果:

您是否发现了您尚未意识到的与代谢组学相关的感兴趣的领域或研究中心?

最后,我们可以分析代谢组学中多元分析的可能趋势。与前几年的文章相比,我们使用多元分析分析了 2016 年代谢组学文章中的趋势词,结果如下:

很明显,这里有一个混淆因素:与代谢组学中的多变量分析相比,该排名提供了代谢组学中更多的关于单词趋势的信息。像“代谢组学”或“代谢组学”这样的词,在多变量分析中没有相关性,是减少最多的词。

纠正这种混杂因素影响的一种方法是,通过分析 2016 年代谢组学中增加的词时计算的比率,将计算的比率“归一化”。例如,“代谢组学”的标准化是这样工作的:

  • 在代谢组学多元分析中的趋势词分析中有 0.318 的比值。
  • 在代谢组学趋势词分析中有 0.303 的比值。
  • 在代谢组学的多变量分析中,单词的趋势重要性的归一化比率是 0.318/0.303=1.049。那么 2016 年‘代谢组学’在代谢组学多元分析中的重要性并没有发生有意义的变化。

修正后的排名给出了以下结果:

这里出现了一些有趣的词语。例如,“茶”、“酒”和“脑脊液”在多变量分析中似乎没有取得类似于其他研究矩阵中所示的进展。是因为这些矩阵的多元分析没有提供有意义的优势吗?或者,是否有可能尝试整合多变量技术来提高相关研究中获得的洞察力?

这些例子仅仅给出了在几秒钟内探索代谢组学(或任何其他科学领域)和可以利用的相关领域的当前趋势的无限可能性的不足直觉。如果有一些“参数调整”来过滤我们分析中不感兴趣的词,或者过滤来自旧文章或低引用计数/影响因子期刊的文章的摘要,那么可以开发更高质量的分析。此外,如果进行多年分析,以避免从任意模式得出错误结论,分析可能会得到改善。

无监督学习和数据聚类

原文:https://towardsdatascience.com/unsupervised-learning-and-data-clustering-eeecb78b422a?source=collection_archive---------0-----------------------

涉及机器学习的任务可能不是线性的,但它有许多众所周知的步骤:

  • 问题定义。
  • 数据准备。
  • 学习一个底层模型。
  • 通过定量和定性评估改进基础模型。
  • 展示模型。

解决新问题的一个好方法是以最好的方式识别和定义问题,并学习从数据中获取有意义信息的模型。虽然模式识别和机器学习中的问题可以有各种类型,但它们可以大致分为三类:

  • 监督学习:
    由“教师”给系统提供示例输入及其期望输出,目标是学习将输入映射到输出的一般规则。
  • 无监督学习:
    没有给学习算法贴标签,让它自己在输入中寻找结构。无监督学习本身可以是一个目标(发现数据中的隐藏模式),也可以是达到目的的一种手段(特征学习)。
  • 强化学习:
    一个系统与一个动态环境进行交互,在这个环境中它必须执行某个目标(比如驾驶车辆或者与对手进行游戏)。当系统导航其问题空间时,系统被提供奖励和惩罚方面的反馈。

介于监督学习和无监督学习之间的是半监督学习,其中教师给出一个不完整的训练信号:一个训练集,其中丢失了一些(通常是许多)目标输出。在这篇博文中,我们将重点讨论无监督学习和数据聚类。

无监督学习

在一些模式识别问题中,训练数据由一组输入向量 x 组成,没有任何相应的目标值。这种无监督学习问题的目标可能是发现数据中的相似示例组,这被称为聚类,或者确定数据如何在空间中分布,被称为密度估计。更简单地说,对于 n 采样空间 x1 到 xn,没有为每个样本提供真实的类标签,因此称为无师学习

无监督学习的问题:

  • 与监督学习任务相比,无监督学习更难..
  • 既然没有答案标签,我们如何知道结果是否有意义?
  • 让专家看看结果(外部评估)
  • 定义聚类的目标函数(内部评估)

尽管存在这些问题,为什么还需要无监督学习?

  • 标注大型数据集的成本非常高,因此我们只能手动标注几个例子。示例:语音识别
  • 可能有这样的情况,我们不知道数据被分成多少/什么类。示例:数据挖掘
  • 在设计分类器之前,我们可能希望使用聚类来深入了解数据的结构。

无监督学习可以进一步分为两类:

  • 参数无监督学习 在这种情况下,我们假设数据的参数分布。它假设样本数据来自一个总体,该总体遵循基于一组固定参数的概率分布。从理论上讲,在一个正态分布族中,所有成员都具有相同的形状,并且通过均值和标准差被参数化。这意味着如果你知道均值和标准差,并且分布是正态的,你就知道任何未来观察的概率。参数无监督学习涉及高斯混合模型的构建和使用期望最大化算法来预测所讨论的样本的类别。这种情况比标准的监督学习困难得多,因为没有可用的答案标签,因此没有正确的准确性测量来检查结果。
  • 非参数无监督学习 在无监督学习的非参数化版本中,数据被分组到聚类中,其中每个聚类(希望)表示数据中存在的类别和类的一些信息。这种方法通常用于建模和分析小样本数据。与参数模型不同,非参数模型不需要建模者对总体的分布做出任何假设,因此有时被称为无分布方法。

什么是聚类?

聚类可以被认为是最重要的无监督学习问题;因此,和其他这类问题一样,它处理的是在一组未标记的数据中找到一个结构。聚类的一个宽泛定义可以是“将对象组织成其成员在某些方面相似的组的过程”。因此,群集是它们之间“相似”并且与属于其他群集的对象“不相似”的对象的集合。

基于距离的聚类。

给定一组点,利用点之间的距离的概念,将这些点分组为一些,使得

  • 内部(集群内)距离应该很小,即集群成员彼此接近/相似。
  • 外部(集群内)距离应该很大,即不同集群的成员不相似。

聚类的目标

聚类的目标是确定一组未标记数据的内部分组。但是如何决定什么是好的集群呢?可以看出,不存在独立于聚类最终目标的绝对“最佳”标准。因此,应该由用户来提供这个标准,以使聚类的结果符合他们的需要。

在上图中,我们如何知道什么是最佳的集群解决方案?

为了找到特定的聚类解决方案,我们需要定义聚类的相似性度量。

邻近度

对于聚类,我们需要为两个数据点定义一个接近度。这里的接近度是指样本彼此之间的相似/不相似程度。

  • 相似性度量 S(xi,xk):大如果 xi,xk 是相似的
  • 相异(或距离)测度 D(xi,xk):小若 xi,xk 相似

有多种相似性度量可以使用。

  • 向量:余弦距离

  • 集合:Jaccard 距离

  • 点:欧几里德距离
    q=2

一个“好的”邻近度测量非常依赖于应用。在问题的“自然”变换下,聚类应该是不变的。此外,在进行聚类时,不建议对来自多个分布的数据进行标准化。

聚类算法

聚类算法可以分类如下:

  • 排他聚类
  • 重叠聚类
  • 分层聚类
  • 概率聚类

在第一种情况下,数据以排他的方式分组,因此如果某个数据点属于某个确定的群,那么它不能被包括在另一个群中。下图显示了一个简单的例子,其中点的分离是通过二维平面上的直线实现的。

相反,第二种类型,即重叠聚类,使用模糊集对数据进行聚类,使得每个点可能属于两个或更多个具有不同隶属度的聚类。在这种情况下,数据将与适当的成员资格值相关联。

分层聚类算法基于两个最近的聚类之间的联合。起始条件是通过将每个数据点设置为一个簇来实现的。经过几次迭代后,它到达最终想要的簇。

最后,最后一种聚类使用完全概率的方法。

在这篇博客中,我们将讨论四种最常用的聚类算法:

  • k 均值
  • 模糊 K-均值
  • 分层聚类
  • 高斯混合

这些算法都属于上面列出的聚类类型之一。而 K-means 是一种排他聚类算法,模糊 K-means 是一种重叠聚类算法,层次聚类是明显的,最后混合高斯是一种概率聚类算法。我们将在下面的段落中讨论每种聚类方法。

K 均值聚类

K-means 是最简单的无监督学习算法之一,它解决了众所周知的聚类问题。该过程遵循一种简单且容易的方式,通过先验固定的一定数量的聚类(假设 k 个聚类)来对给定数据集进行分类。主要思想是定义 k 个中心,每个聚类一个。这些质心应该以一种巧妙的方式放置,因为不同的位置会导致不同的结果。因此,更好的选择是将它们放置在尽可能远离彼此的地方。下一步是获取属于给定数据集的每个点,并将其与最近的质心相关联。当没有点悬而未决时,第一步完成,早期分组完成。在这一点上,我们需要重新计算 k 个新的质心作为上一步得到的聚类的重心。在我们有了这 k 个新质心之后,必须在相同的数据集点和最近的新质心之间进行新的绑定。已经生成了一个循环。作为这个循环的结果,我们可能会注意到 k 个质心一步一步地改变它们的位置,直到不再发生变化。换句话说,质心不再移动。

最后,该算法旨在最小化目标函数,在这种情况下是平方误差函数。目标函数

在哪里

是数据点 xi 和聚类中心 cj 之间的选定距离度量,是 n 个数据点距它们各自聚类中心的距离的指示符。

该算法由以下步骤组成:

  • 设 X = {x1,x2,x3,…..,xn}是数据点的集合,V = {v1,v2,…。,vc}是中心的集合。
  • 随机选择‘c’个聚类中心。
  • 计算每个数据点和聚类中心之间的距离。
  • 将数据点分配到所有聚类中心中距离聚类中心最小的聚类中心。
  • 使用重新计算新的聚类中心

其中,“ci”代表第 I 个聚类中数据点的数量。

  • 重新计算每个数据点与新获得的聚类中心之间的距离。
  • 如果没有数据点被重新分配,则停止,否则从步骤 3 开始重复。

虽然可以证明该过程将总是终止,但是 k-means 算法不一定找到对应于全局目标函数最小值的最优配置。该算法对初始随机选择的聚类中心也非常敏感。可以多次运行 k-means 算法来减少这种影响。

K-means 是一种简单的算法,已经被应用于许多问题领域。正如我们将要看到的,使用模糊特征向量是一个很好的扩展候选。

k-means 过程可以被视为用于将 n 个样本划分成 k 个聚类的贪婪算法,以便最小化到聚类中心的平方距离之和。它确实有一些弱点:

  • 未指定初始化方法的方式。一种流行的开始方式是随机选择 k 个样本。
  • 可能发生的情况是,最接近于 m i 的样本集是空的,使得 m i 不能被更新。这是一个需要在实现过程中处理的问题,但通常会被忽略。
  • 结果取决于 k 的值,并且没有描述最佳“k”的最佳方式。

最后一个问题特别麻烦,因为我们通常无法知道存在多少个集群。在上面显示的示例中,应用于相同数据的相同算法产生了以下 3 均值聚类。它比 2 均值聚类更好还是更差?

不幸的是,对于任何给定的数据集,没有找到最佳聚类数的通用理论解决方案。一种简单的方法是比较不同 k 类的多次运行的结果,并根据给定的标准选择最佳的一个,但我们需要小心,因为根据定义,增加 k 会导致更小的误差函数值,但也会增加过拟合的风险。

模糊 K 均值聚类

在模糊聚类中,每个点都有属于每个聚类的概率,而不是像传统的 k-means 那样完全属于一个聚类。模糊 k-means 特别试图通过用概率代替距离来处理点在中心之间或不明确的问题,概率当然可以是距离的某个函数,例如具有相对于距离倒数的概率。模糊 k-means 使用基于这些概率的加权质心。初始化、迭代和终止的过程与 k-means 中使用的过程相同。产生的聚类最好作为概率分布来分析,而不是标签的硬分配。应该认识到,如果数据点最接近质心,则 k-均值是模糊 k-均值的特殊情况,此时使用的概率函数简单地为 1,否则为 0。

模糊 k 均值算法如下:

  • 假设固定数量的集群 K.
  • **初始化:**随机初始化与聚类相关的 k-means μk 并计算每个数据点 Xi 是给定聚类 KP(PointXiHasLabelK | Xi,K)成员的概率。
  • **迭代:**给定所有数据点的隶属概率,重新计算聚类的质心作为加权质心 Xi :

  • 终止:迭代直至收敛或达到用户指定的迭代次数(迭代可能陷入局部最大值或最小值)

为了更好地理解,我们可以考虑这个简单的一维例子。给定一个数据集,假设把它表示为分布在一个轴上。下图显示了这一点:

看这幅图,我们可以在两个数据集中附近识别出两个集群。我们将用‘A’和‘B’来指代它们。在本教程中展示的第一种方法 k-means 算法——中,我们将每个数据点与一个特定的质心相关联;因此,这个隶属函数看起来像这样:

相反,在模糊 k-means 方法中,相同的给定数据点不仅仅属于明确定义的聚类,而是可以放在中间。在这种情况下,隶属函数遵循更平滑的线,以指示每个数据点可以属于具有不同隶属度的几个聚类。

在上图中,显示为红色标记点的数据点更属于 B 类,而不是 A 类。“m”的值 0.2 表示这种数据点对 A 的隶属度。

层次聚类算法

给定一组要聚类的 N 个项目和一个 N*N 距离(或相似性)矩阵,分层聚类的基本过程如下:

  • 首先将每个项目分配到一个分类中,这样,如果您有 N 个项目,那么现在您有 N 个分类,每个分类只包含一个项目。让聚类之间的距离(相似性)与它们包含的项目之间的距离(相似性)相同。
  • 找到最接近(最相似)的一对聚类,并将它们合并成一个聚类,这样现在就少了一个聚类。
  • 计算新分类和每个旧分类之间的距离(相似性)。
  • 重复第 2 步和第 3 步,直到所有项目都聚集成一个大小为 n 的簇。

聚类为高斯分布的混合体

还有另一种处理聚类问题的方法:基于模型的方法,该方法包括对聚类使用某些模型,并试图优化数据和模型之间的拟合。

在实践中,每个聚类都可以用参数分布来表示,如高斯分布。因此,整个数据集由这些分布的混合建模。
具有高可能性的混合模型往往具有以下特征:

  • 成分分布具有高“峰值”(一个聚类中的数据是紧密的);
  • 混合模型很好地“覆盖”了数据(数据中的主要模式由成分分布捕获)。

基于模型的集群的主要优势:

  • 可用的经过充分研究的统计推断技术;
  • 选择组件分布的灵活性;
  • 获得每个聚类的密度估计;
  • “软”分类是可用的。

高斯混合 这种最广泛使用的聚类方法是基于学习一个高斯混合:

混合模型是 k 个分量分布的混合,共同构成混合分布 f ( x ):

αk 表示第k 个分量在构造 f(x) 中的贡献。在实践中,经常使用参数分布(例如高斯分布),因为已经做了大量工作来了解它们的行为。如果你用每一个 fk ( x )代替一个高斯模型,你会得到一个众所周知的高斯混合模型(GMM)。

EM 算法

期望最大化假设您的数据由多个多元正态分布组成(注意,这是一个非常强的假设,尤其是当您固定了聚类数的时候!).换句话说,EM 是一种当模型中的一些变量不可观察时(即当你有潜在变量时)最大化似然函数的算法。你可能会问,如果我们只是想最大化一个功能,为什么不利用现有的机制来最大化一个功能呢?如果你试图通过求导并把它们设为 0 来最大化,你会发现在很多情况下,一阶条件没有解。这是一个先有鸡还是先有蛋的问题,为了求解模型参数,你需要知道未观测数据的分布;但是你的未观测数据的分布是你的模型参数的函数。

期望最大化试图通过反复猜测未观察数据的分布来解决这个问题,然后通过最大化实际似然函数的下限来估计模型参数,并重复直到收敛:

期望值最大化算法

  • 从猜测模型参数值开始
  • E-step :对于每个有缺失值的数据点,使用你的模型方程求解缺失数据的分布,给出你当前对模型参数的猜测和观测数据(注意你是在求解每个缺失值的分布,而不是期望值)。现在我们有了每个缺失值的分布,我们可以计算关于未观察变量的似然函数的期望值。如果我们对模型参数的猜测是正确的,这个预期的可能性将是我们观察到的数据的实际可能性;如果参数不正确,它将只是一个下限。
  • M 步:现在我们已经得到了一个不含未观测变量的期望似然函数,最大化这个函数,就像你在完全观测情况下所做的那样,从而得到你的模型参数的新估计。
  • 重复直到收敛。

与聚类相关的问题

集群有许多问题。其中包括:

  • 由于时间复杂性,处理大量维度和大量数据项可能会有问题;
  • 该方法的有效性取决于“距离”的定义(对于基于距离的聚类)。如果一个明显的距离度量不存在,我们必须“定义”它,这并不总是容易的,尤其是在多维空间中;
  • 聚类算法的结果(在许多情况下可以是任意的)可以以不同的方式解释。

可能的应用

聚类算法可以应用于许多领域,例如:

  • 营销:给定一个包含客户属性和过去购买记录的大型客户数据数据库,找到具有相似行为的客户群;
  • 生物学:根据植物和动物的特征对它们进行分类;
  • 保险:识别平均索赔成本高的汽车保险保单持有人群体;识别欺诈;
  • 地震研究:对观测到的地震震中进行聚类,识别危险区域;
  • 环球网:文档分类;聚集网络日志数据以发现相似访问模式的组。