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

TowardsDataScience 博客中文翻译 2019(四)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

选择 A/B 测试指标—入门

原文:https://towardsdatascience.com/a-guide-for-selecting-an-appropriate-metric-for-your-a-b-test-9068cccb7fb?source=collection_archive---------10-----------------------

并且避免了大多数测试工作中常见的错误。

Photo by Luke Chesser on Unsplash

这篇文章是我关于 A/B 测试系列文章的第三篇。

在第一篇文章中,我向展示了 A/B 测试背后的直觉,以及确定您希望观察的效果大小和相应样本大小的重要性。

在第二篇文章中,我谈到了产品经理如何以加速测试的方式设计 A/B 测试。

在第三篇文章中,我将讨论 A/B 测试的另一个方面:在确定 A/B 测试的指标时,你应该考虑哪些因素?

案例研究:VRBO 搜索登录页面

当我们设计一个 A/B 测试时,我们选择一个我们希望改进的主要度量标准(和几个次要度量标准),并测量变体和控制组。如果我们不仔细选择这个指标,我们就是在浪费时间。

我们将使用一个我熟悉的例子:在 VRBO 上搜索登陆页面。VRBO 是一个双边市场,房主可以列出他们的房屋出租,潜在的旅行者可以为下次旅行找到合适的住宿。搜索登录页面的目的是从谷歌获得流量,并将该流量转化为执行更高意向查询的人。

让我们看一些截图,从旅行者开始计划过程的最常见方式(在谷歌上搜索)开始

第一步 :想着去巴哈马旅游?让我们搜索一下。

Searching for Vacation Homes in the Bahamas

第二步 :啊哈!看起来 VRBO 有很好的选择。让我们看看那里。

Google Search Result on VRBO

让我们看看我在巴哈马有哪些选择。

Search Landing Page for the Bahamas — Above the Fold

Search Landing Page for the Bahamas — Below the Fold

我们建立这个页面是为了:

  1. 高预订意向用户。用户可能已经预订了机票,或者至少知道他们想什么时候旅行。我们假设,对于这些用户来说,该页面要做的工作是找到适合他们旅行日期的房屋。
  2. 低预订意向用户。处于计划阶段的早期用户,他们可能对何时旅行没有任何概念。我们假设,对于这些用户来说,该页面要做的工作是帮助他们探索各种可用的房屋,并影响用户访问巴哈马。
  3. 谷歌机器人。我们希望谷歌为最相关的用户查询建立页面索引。

整个用户旅程(从谷歌登陆 VRBO 到预订看起来是这样的。)

Typical user journey for booking travel.

有两点需要特别注意:

  1. 在初始步骤和最终步骤之间,有用户必须采取的多个步骤,并且在每个级别,一些用户将退出。
  2. 由于旅行被认为是购买(相对于冲动购买),最初和最后一步之间的时间可能是几周。

现在让我们看看这个转换漏斗的数学,对从一个步骤到另一个步骤的转换做一些假设,并估计总的转换率。( 免责声明:这些数字仅用于说明目的 )

An estimate of the conversion rate of each step and overall conversion rate.

最后,你必须得到一个粗略的流量数量级。让我们在这里做一些假设( )免责声明:这些数字仅用于说明目的。)

  1. 每月独立访客总数:1000 万
  2. 到达搜索登录页面的独特新访问者:30%(300 万用户)

现在,假设您是搜索登录页面的产品经理。根据这些基本比率,让我们来看一个假设的 A/B 测试,并为您的实验看两个可能的指标。

测试假设:通过在搜索登录页面上添加一个背景“英雄”图像来指示目的地,用户会感到舒适,因为他们正在查看正确的目的地,从而导致更高的搜索和 2%的整体转化率

您有两个指标选择,总转化率和进行过时搜索的用户百分比。

实验设计当我们选择总转化率作为衡量标准时

用整体转化率作为产品经理的衡量标准是很有诱惑力的。毕竟,你可以告诉你的管理层,你增加了$$$的收入。

如果您决定选择这个作为您的度量,让我们看看测试参数:测试样本大小和总测试持续时间。让我们将 0.225%的基本比率和 2%的最小可检测效应(MDE)代入 Evan Miller 的样本量计算器。

The sample size for an A/B test with 0.225% base rate and 2% MDE. Courtesy: Sample Size Calculator by Evan Miller

总的来说,您将需要 34,909,558 个样本用于您的变体组和对照组。

每月有 300 万独立用户,如果测试正确,您的测试将需要 11-12 个月才能完成。很多人会犯这样的错误,过早地看到一些积极的结果,变得不耐烦,过早地停止实验。如果你这样做,你很可能会看到一个假阳性。

实验设计当我们选择%的用户进行日期搜索作为主要指标时

如果您决定选择这个作为您的度量,让我们看看测试参数:测试样本大小和总测试持续时间。让我们将 30%的基本比率和 2%的最小可检测效应(MDE)代入 Evan Miller 的样本量计算器。

The sample size for an A/B test with 30% base rate and 2% MDE. Courtesy: Sample Size Calculator by Evan Miller

总的来说,你将需要 183,450 个样本用于你的变异体和对照组。每月有 300 万独立用户,这将需要几天时间来完成您的测试。[ 你可能想考虑运行测试整整一周,以消除任何一周内偏差的可能性。]

用这种方法,你可以在同样的时间内进行 10 次实验。

经验教训

如果上面的情况听起来是假设的,让我向你保证,很多产品经理(包括我)已经采取了使用总转化率作为主要指标的方法。这里是我学到的一些经验,我想更广泛地分享。

  1. 当你设计你的测试时,充分注意你选择的度量标准。如果你正在测试的功能在漏斗中处于较高位置,并且你的整体转化率低于 1%,你的测试结果将需要几个月才能完成。(除非你是脸书、谷歌、亚马逊,或者一个顶级的互联网网站。)
  2. 当您的测试需要几个月的时间才能完成时,由于意外的和不相关的更改而导致错误蔓延并破坏您的测试结果的可能性将会非常高。您可能需要重新开始测试。
  3. 你的特征离整体转化率越远,你的变化对指标产生因果影响的可能性就越低。
  4. 最好的选择是使用直接受您的更改影响的指标,比如页面上的指标,来衡量微转化。
  5. 如果你选择了像点击率这样的页面指标,通过查看一个平衡的指标来注意意想不到的结果。如果我们选择日期搜索作为我们的衡量标准,我们还将查看该页面以及后续页面的跳出率。这种技术确保产品变更不会向下游发送不合格的流量。(在以后的文章中会有更多关于这个主题的内容。

如果你觉得这篇文章有用,请告诉我。如果你对 A/B 测试有任何疑问,请在评论中给我留言,我会考虑把它作为未来帖子的主题。

这是我的 A/B 测试系列文章的第三篇。该系列的其他文章是:

  1. A/B 测试背后的直觉——新产品经理入门
  2. 如何在 A/B 测试中分割流量

学分:

我要感谢 Evan Miller 出色的样本量计算器和他在 A/B 测试方面的思想领导力。

关于我 : Aditya Rustgi 是一名产品管理领导者,在电子商务和旅游行业的多边市场和 B2B Saas 业务模式方面拥有超过 15 年的产品和技术领导经验。最近,他是 Expedia 公司 VRBO 的产品管理总监。

数组和操作指南(数据结构)

原文:https://towardsdatascience.com/a-guide-to-arrays-and-operations-data-structures-f0671028ed71?source=collection_archive---------23-----------------------

一开始,学习数据结构和算法可能会非常困难。这就像学习任何新的课程,这些课程有你以前没有接触过的话题,有自己的语言(有点像学习有机化学或新的游戏类型)。我原本打算把这一整篇文章都放在数据结构和算法上,但是它太长了。所以,我在这里把它分开了,我将从数据结构开始,以后会发布更多。不用担心找到所有的东西。一旦文章完成,我将像一个双向链表一样在每篇文章中插入链接(你将在另一篇文章中得到参考)。

为什么要学习数据结构?

计算机软件就是处理数据。数据涵盖所有类型的信息,更基本的形式是数字和字符串。数据结构解释了数据是如何组织的。这种结构决定了代码运行的速度和效率。一旦你深刻理解了数据结构是如何工作的,你的代码就会运行得更好,更漂亮。从数据科学家的角度来说,我们都写代码,但是写好代码也会给你带来软件工程的机会。当然,学习一些能让你在自己的领域做得更好的东西,同时扩展到其他有利可图的领域也没那么糟糕。

数组数据结构& 4 种基本操作

数组是一种基本的数据结构。数组基本上是一个数据列表。下面是一个表示 Hello 的数组示例:

Image taken from Javapoint.com

我喜欢通过我已经知道的事物的例子来学习。那么,我们来说说上面的数组图像。我们有实际的数据 Hello,下面有一个空格和数字。你好下面的数字被称为索引。把一个数组的索引想象成一个家的地址。在 Hello 数组中,H 位于地址 0,e 位于地址 1。我们从 0 开始索引的原因是因为大多数编程语言从 0 开始索引——比如 Python。为了了解像数组这样的数据结构如何影响你的代码,我们必须看看操作。大多数数据结构适用于这四种操作:

  • 阅读:在特定的地方检查数据。例如,在上面的数组中读取“o ”,计算机知道在索引 4 中查找。
  • 搜索:在数据结构中查找一种类型的值。例如,在 Hello 数组中查找数字将会一无所获。
  • 插入:在数据中放置另一个值。例如,在上面的数组中放置 Hellow 将在索引 5 中添加“w”。
  • 删除:删除数据结构中的一个值。例如,从 hello 中删除“H”将会是 ello(旁注:删除值 H 实际上会涉及到将所有字符向左移动的另一个步骤)。

当计算机科学家或软件工程师提到算法的速度时,他们指的是该过程中有多少步,而不是时间。这意味着时间有点仓促,因为不同的硬件在不同的时间执行。根据过程中的步骤来测量速度允许一致的标准化测量,这也反映了算法的复杂性。有趣的是,时间复杂度、效率和性能在数据结构和算法讨论中经常是指同一个东西。

阅读

读取是检查数组中特定索引的值。看书的速度真的很快,快一步而已。原因是由于计算机知道数组中的索引并偷看里面。当计算机读取数组时,它会转到正确的索引,原因是:

  1. 计算机知道每个值的索引。
  2. 存储在内存中的数组是以“块”的形式读取的把它想象成寻找地址的街道上的房子。
  3. 数组从 0 开始,所以计算机知道它只能从那里开始。

从上面的原因来看,从一个数组中读取需要计算机一步,这使它成为一个真正快速的操作。

搜索

在数组中搜索是寻找特定类型的数据,并找到它在索引中的位置。搜索是以一种非常有条理的方式进行的。计算机从索引 0 开始向前查找,直到找到它要寻找的值。在最坏的情况下,如果计算机想在一个 10 的数组中搜索,而所需的值在第 10 个点上,那么它会一直搜索到第 10 个值。换句话说,一个 300 大小的数组,我们想要的值位于第 300 个索引中,计算机需要 300 步来搜索该值。

我希望你现在能明白这个模式。从更抽象的角度来看,对于数组中的任意 N 个单元,线性搜索最多需要 N 步。因此,如果您将此公式应用于前面的两个搜索示例,我们可以看到,由于我们要查找的数据的索引位置在末尾,最差的情况总是取最高值。与阅读相比,搜索更慢,因为它需要 N 个步骤,而阅读只需 1 个步骤。

插入

插入的速度取决于插入值的位置。在数组中插入的最快方法是插入到末尾。在开头或中间的某个地方插入会稍微复杂一点。但是不要担心,我们会经历发生的事情。让我们来看看最糟糕的情况,因为其他事情都差不多,只是步骤少了一些。在最坏的情况下,在数组中插入,在开始时,需要最多的步骤。原因是一旦值被插入到开头,计算机必须将所有其他值向右移动。由于左边的值没有移动,所以插入中间的任何其他值占用的时间更少。

从抽象的角度来看,我们可以看到,对于 N 大小的数组,插入需要 N + 1 个步骤。将值向左向右移动是 N 步,而实际的插入需要 1 步。因此,最坏的情况需要 N+1 步,但是最后的插入只需要 1 步。

删除

删就是你想的那样。删除会移除数组中的值。删除有点像以相反的方式插入。删除操作不是放置一个值,而是移除该值并移动这些值以弥补删除操作留下的空白。就像插入一样,删除的最佳速度是在最后——1 步。它删除结束值,而不必移动任何其他值。删除的最坏情况是在开始。一旦它删除了第一个值,右边的所有其他值都必须左移一个,以覆盖数组中的空白空间。

对于 N 大小的数组,插入的总体模式是 N + 1。删除需要 1 步,而值的移动需要 N 步。像插入一样,最坏的情况是在数组的开始,而最好的情况是在数组的末尾。

结论

了解步骤的数量和操作步骤的长度是理解数据结构如何工作的基础之一。在理解操作的基础上选择正确的数据结构,可以让你以更少的步骤编写代码,这意味着更高的效率。我在这里非正式地介绍了大 O 符号,但是我们稍后会正式讨论它。这篇文章已经太长了。我希望这篇文章能帮助你更好地理解数据结构,因为我个人第一次发现它非常令人困惑。继续努力,你会成功的!

在此找到的第 2 部分:

[## 阵列的线性搜索和二分搜索法指南(数据结构和算法)

在上一篇文章中,我们讨论了数组和操作(链接)。现在,我们将了解算法选择如何影响…

towardsdatascience.com](/a-guide-to-linear-search-and-binary-search-on-arrays-data-structures-algorithms-2c23a74af28a)

对于那些现在想了解更多的人来说,下面是我用来撰写本文的关于这些主题的好资源:

免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。

康达环境权威指南

原文:https://towardsdatascience.com/a-guide-to-conda-environments-bc6180fc533?source=collection_archive---------0-----------------------

如何使用 conda for Python & R 管理环境

Conda’s natural environment. Illustration by Johann Wenzel Peter.

Conda 环境就像是 Python 的虚拟环境的表亲。两者都有助于管理依赖性和隔离项目,它们以相似的方式工作,有一个关键的区别:conda 环境是语言不可知的。也就是说,它们支持 Python 以外的语言。

☄️在本指南中,我们将介绍使用 Python 的conda创建和管理环境的基础知识

⚠️注:在本指南中,我们将在 macOS Mojave 上使用最新版本的 Conda v4.6.x、Python v3.7.y 和 R v3.5.z。

目录

Conda 与 Pip 和 Venv —有什么区别?
使用康达环境
安装包
管理环境
带 R 的环境
进一步阅读

康达 vs .皮普 vs. Venv —有什么区别?

在我们开始之前,你们中的一些人可能想知道condapipvenv之间的区别。

很高兴你问了。我们不能说得比这更好了:[pip](https://pip.pypa.io/en/stable/)是 Python 的一个包管理器T5 是 Python 的环境管理器conda既是包又是环境管理器,并且是语言不可知的

鉴于venv只为 Python 开发创建隔离环境,conda可以为任何语言创建隔离环境(理论上)。

pip只安装来自 PyPI 的 Python 包,conda两者都可以

  • 从像 Anaconda RepositoryAnaconda Cloud 这样的库安装软件包(用任何语言编写)。
  • 在活动的 Conda 环境中使用pip从 PyPI 安装软件包。

多酷啊。

👉🏽如果想要一个比较这三者的图表,请点击这里(不要忘记向右滚动!).

[Morning Mist](https://commons.wikimedia.org/wiki/File:Cole_Thomas_Morning_Mist_Rising_Plymouth_New_Hampshire_(A_View_in_the_United_States_of_American_in_Autunm_1830.jpg) by Thomas Cole.

使用 Conda 环境

创造环境

要使用conda为 Python 开发创建一个环境,运行:

% conda create --name conda-env python                  # Or use -n

💥重要提示:用您的环境名称替换“conda-env”。从现在开始,我们将始终使用“conda-env”来命名我们的环境。

这个环境将使用与您当前 shell 的 Python 解释器相同的 Python 版本。要指定不同版本的 Python,请使用:

% conda create -n conda-env python=3.7

你也可以在创建环境时安装额外的包,比如说numpyrequests

% conda create -n conda-env numpy requests

⚠️ 注意:因为conda确保安装包时满足依赖关系,Python 将与numpyrequests一起安装😁。

您还可以指定想要安装的软件包版本。

% conda create -n conda-env python=3.7 numpy=1.16.1 requests=2.19.1

⚠️ 注意: 建议同时安装你想包含在一个环境中的所有软件包,以帮助避免依赖冲突。

最后,您可以通过调用来激活您的环境:

% conda activate conda-env           
(conda-env) %                          # Fancy new command prompt

并使用以下命令将其禁用:

% conda deactivate
%                                      # Old familiar command prompt

环境生活的地方

当您使用 Python 的venv模块创建一个环境时,您需要通过指定它的路径来说明它位于何处。

% python3 -m venv /path/to/new/environment

另一方面,用conda创建的环境默认位于 Conda 目录的envs/文件夹中,其路径如下所示:

% /Users/user-name/miniconda3/envs          # Or .../anaconda3/envs

我更喜欢venv采用的方法,原因有二。

1️⃣通过将环境包含为子目录,可以很容易地判断一个项目是否利用了一个隔离的环境。

my-project/
├── conda-env                    # Project uses an isolated env ✅
├── data                             
├── src                  
└── tests

2️⃣它允许你对所有的环境使用相同的名字(我使用“conda-env”),这意味着你可以用相同的命令激活每个环境。

% cd my-project/
% conda activate conda-env

💸好处:这允许你给激活命令起别名,并把它放在你的.bashrc文件中,让生活简单一点。

⚠️注:如果你将所有的环境都保存在 Conda 的env/文件夹中,你将不得不给每个环境取一个不同的名字,这可能会很痛苦😞。

那么,你如何把环境放到你的康达的env/文件夹之外呢?通过在创建环境时使用--prefix标志而不是--name

% conda create --prefix /path/to/conda-env             # Or use -p

⚠️注:这使得一个名为“conda-env”的环境出现在指定的路径中。

就这么简单。然而,将环境放在默认的env/文件夹之外有两个缺点。

1️⃣ conda无法再用--name旗找到你的环境。相反,您需要沿着环境的完整路径传递--prefix标志。例如,在安装包时,我们将在下一节中讨论。

2️⃣您的命令提示符不再以活动环境的名称为前缀,而是以其完整路径为前缀。

(/path/to/conda-env) %

你可以想象,这很快就会变得一团糟。比如说,像这样的东西。

(/Users/user-name/data-science/project-name/conda-env) %        # 😨

幸运的是,有一个简单的解决方法。你只需要修改你的.condarc文件中的env_prompt设置,你只需要简单的一笔就可以完成。

% conda config --set env_prompt '({name}) '

⚠️注:如果你已经有一个.condarc文件,这将编辑你的文件,如果你没有,则创建一个。关于修改您的.condarc文件的更多信息,请参见文档

现在,您的命令提示符将只显示活动环境的名称。

% conda activate /path/to/conda-env
(conda-env) %                                        # Woohoo! 🎉

最后,您可以查看所有现有环境的列表。

% conda env list# conda environments:
#
                         /path/to/conda-env
base                  *  /Users/username/miniconda3
r-env                    /Users/username/miniconda3/envs/r-env

⚠️注:*指向当前活动环境。有点烦人的是,即使没有环境活动,它也会指向“base”🤷🏽‍♂️.

An American Lake Scene by Thomas Cole.

安装软件包

conda安装包有两种方式。

活跃环境中的 1️⃣。

2️⃣从您的默认外壳。

后者要求您使用与创建环境时相同的标志(--name--prefix)指向您想要安装软件包的环境。

无论您使用哪种标志,前者都同样有效。

💥重要提示:我们强烈建议坚持前一种方法,因为它消除了无意中在系统范围内安装软件包的危险。

♻️提醒:本指南中的所有环境均命名为“conda-env”。您可以用您的环境名替换“conda-env”。

从巨蟒库

默认情况下,condaAnaconda 存储库安装软件包。一旦您创建了一个环境,您可以通过两种方式安装额外的软件包。

活跃环境中的 1️⃣。

(conda-env) % conda install pandas=0.24.1                   # 🐼

2️⃣从您的默认外壳。

% conda install -n conda-env pandas=0.24.1      # Or -p /path/to/env

同样,您可以通过两种方式更新环境中的软件包。

活跃环境中的 1️⃣。

(conda-env) % conda update pandas

2️⃣从您的默认外壳。

% conda update -n conda-env pandas             # Or -p /path/to/env

您还可以用两种方式列出给定环境中安装的软件包——是的,您猜对了。

活跃环境中的 1️⃣。

(conda-env) % conda list

2️⃣从您的默认外壳。

% conda list -n conda-env                      # Or -p /path/to/env

来自其他 Conda 存储库

如果在默认的 Anaconda 仓库中找不到一个包,你可以试着在 Anaconda Cloud 上搜索它,它托管了由第三方仓库如 conda-Forge 提供的 Conda 包。

要从 Anaconda Cloud 安装一个包,您需要使用--channel标志来指定您想要安装的存储库。例如,如果你想安装康达-福吉的opencv,你可以运行:

(conda-env) % conda install --channel conda-forge opencv     # Or -c

幸运的是,conda跟踪软件包是从哪里安装的。

(conda-env) % conda list# packages in environment at /path/to/conda-env:
#
# Name                Version          Build             Channelnumpy                 1.16.1           py37h926163e_0
opencv                4.1.0            py37h0cb0d9f_3    conda-forge
pandas                0.24.2           py37h0a44026_0

numpypandas的空白通道条目代表default_channels,默认情况下它被设置为 Anaconda 存储库。

⚠️注:为了简洁起见,我们只展示了上面的一些软件包。

您也可以永久添加一个频道作为包源。

% conda config --append channels conda-forge

这将修改您的.condarc文件,如下所示:

env_prompt: '({name}) '      # Modifies active environment prompt
channels:                    # Lists package sources to install from
- defaults                   # Default Anaconda Repository
- conda-forge

🚨注意:你的渠道顺序事关。如果一个软件包可以从多个渠道获得,conda将从您的.condarc文件中列出的最高渠道安装它。有关管理渠道的更多信息,请参见文档

来自 PyPI

如果 Anaconda 存储库或 Anaconda Cloud 中没有可用的包,您可以尝试用pip安装它,默认情况下,conda会在任何用 Python 创建的环境中安装它。

例如,要安装带有pip的请求,您可以运行:

(conda-env) % pip install requests

请注意,conda正确地将 PyPI 列为requests的通道,从而很容易识别出安装了pip的包。

(conda-env) % conda list# packages in environment at /path/to/conda-env:
#
# Name                Version          Build             Channelnumpy                 1.16.1           py37h926163e_0
opencv                4.1.0            py37h0cb0d9f_3    conda-forge
pandas                0.24.2           py37h0a44026_0
requests              2.21.0                   pypi_0    pypi

🚨注意:由于pip软件包不具备conda软件包的所有特性,强烈建议尽可能安装带有conda的软件包。有关condapip封装的更多信息,请点击此处

Moonlight by Thomas Cole.

管理环境

环境文件

使您的工作可以被其他人复制的最简单的方法是在您的项目根目录中包含一个文件,该文件列出了您的项目环境中安装的所有包及其版本号。

Conda 将这些环境文件称为。它们是 Python 虚拟环境需求文件的精确模拟。

像其他任何事情一样,您可以用两种方法创建环境文件。

活跃环境中的 1️⃣。

(conda-env) % conda env export --file environment.yml       # Or -f

2️⃣从您的默认外壳。

% conda env export -n conda-env -f /path/to/environment.yml

您的environment.yml文件看起来会像这样:

name: null                          # Our env was made with --prefix
channels:
  - conda-forge                     # We added a third party channel
  - defaults
dependencies:
  - numpy=1.16.3=py37h926163e_0
  - opencv=3.4.2=py37h6fd60c2_1
  - pandas=0.24.2=py37h0a44026_0
  - pip=19.1.1=py37_0
  - pip:                            # Packages installed from PyPI
    - requests==2.21.0
prefix: /Users/user-name/data-science/project-name/conda-env

⚠️注:为了简洁起见,我们只展示了上面的一些软件包。

复制环境

给定一个environment.yml文件,您可以轻松地重新创建一个环境。

% conda env create -n conda-env -f /path/to/environment.yml

💸附加功能:您还可以使用以下功能将environment.yml文件中列出的软件包添加到现有环境中:

% conda env update -n conda-env -f /path/to/environment.yml

View in the White Mountains by Thomas Cole.

R 环境

要在一个环境中使用 R,您需要做的就是安装r-base包。

(conda-env) % conda install r-base

当然,您可以在第一次创建环境时这样做。

% conda create -n r-env r-base

⚠️注意:用您的环境名替换“r-env”。

conda 的 R 包可以从 Anaconda Cloud 的 R 通道获得,默认情况下包含在 Conda 的[default_channels](https://docs.conda.io/projects/conda/en/latest/user-guide/configuration/use-condarc.html#default-channels-default-channels)列表中,所以在安装 R 包时不需要指定 R 通道,比如说tidyverse

% conda activate r-env
(r-env) % conda install r-tidyverse 

⚠️注:所有来自 r 通道的包裹都带有前缀“r-”。

如果你愿意,你可以安装r-essentials包,它包括 80 多个最流行的科学 R 包,像tidyverseshiny

(r-env) % conda install r-essentials

最后,如果你想安装 Conda 没有提供的 R 包,你需要从 CRAN 构建这个包,你可以在这里找到的说明。

进一步阅读

如果你偶然发现自己想知道 Conda 环境到底是如何工作的,看看这篇关于 Python 的虚拟环境如何工作的简介。Conda 环境以完全相同的方式工作。

除此之外,我们差不多做到了。如果你想了解我最新的数据科学帖子,欢迎在推特上关注我。

干杯,祝阅读愉快。

2019 年 8 月更新:Conda 修订版

你真的每天都能学到新东西。今天早上,我的朋友 Kumar Shishir 告诉我另一个非常有用的 conda特性:conda 修订版。

我简直不敢相信自己的耳朵。我怎么能在完全和完全不知道这样一个辉煌的特征的情况下憔悴了这么久?

修订版会随着时间的推移跟踪您的环境的变化,允许您轻松地移除包及其所有依赖关系。

例如,假设我们创建了一个新的conda-env并安装了numpy,然后安装了pandas。我们的修订历史如下所示:

(conda-env) % conda list --revisions 2019-08-30 16:04:14  (rev 0)               # Created our env+pip-19.2.2
+python-3.7.42019-08-30 16:04:30  (rev 1)               # Installed numpy+numpy-1.16.4
+numpy-base-1.16.42019-08-30 16:04:39  (rev 2)               # Installed pandas+pandas-0.25.1
+python-dateutil-2.8.0
+pytz-2019.2

想象一下,我们不再想在我们的环境中拥有pandas,因为它(不知何故)与我们早期的依赖不兼容,或者因为我们不再需要它。

修订版允许我们将环境回滚到以前的版本:

(conda-env) % conda install --revision 1
(conda-env) % conda list --revisions         # (Showing latest only) 2019-08-30 16:08:05  (rev 3)                 # Uninstalled pandas -pandas-0.25.1
-python-dateutil-2.8.0
-pytz-2019.2

每个包装上的标志告诉我们,我们已经成功地将从我们的环境中移除。现在,我们准备回到一些数据科学😎。

更新 02/2020:清除你的 Tarballs!

随着您构建更多的项目,每个项目都有自己的环境,您将开始从已安装的包中快速积累tarballs

要删除它们并释放一些磁盘空间,请运行:

% conda clean --all                     # no active env needed

从头开始构建卷积神经网络指南

原文:https://towardsdatascience.com/a-guide-to-convolutional-neural-networks-from-scratch-f1e3bfc3e2de?source=collection_archive---------8-----------------------

卷积神经网络是 2010 年深度学习取得许多进展背后的主力。这些网络彻底改变了图像分类和对象检测等任务,但它们在文本分类、语音识别或任何可以使用过滤器来检测输入数据区域相似性的领域等其他环境中也非常有效。

在这篇文章中,我将介绍如何使用 numpy 从头开始构建一个基本的 CNN。这个练习深入到这些网络实际上是如何工作的具体细节。在实践中,使用深度学习框架如 Tensorflow 或 Pytorch 是很常见的。这些框架很棒,但当你所要做的只是键入几行代码来创建 CNN 时,不可能理解卷积神经网络在每一步实际上在做什么。

概念:

前馈神经网络是强大的工具,但它们在图像上效果不佳。前馈神经网络获取 32×32×3 的图像(32 像素高,32 像素宽,3 像素深,红色、绿色和蓝色的图像)并对其进行分类。为了通过前馈神经网络运行图像,该图像被拉伸为 3072×1(32 * 32 * 3 = 3072)numpy 阵列。然后乘以权重,优化损失,并根据指定的分数对图像进行分类。这个过程是可行的,但是它不能产生现有技术的结果,因为将图像拉伸成一维向量不能保持图像的空间结构。这意味着,如果图像的空间结构在所有三个维度上都得到保留,那么分类任务中使用的特征就不会像它们可能达到的那样精确。深度学习任务的结果取决于提供给它们的数据的质量。产生最新的结果需要一种能够从图像中提取最新特征的解决方案。

卷积神经网络就是解决方案。美国有线电视新闻网的生产状态的艺术效果,因为他们不断保持图像的空间结构。这意味着在分类任务的最后将提取更好的特征。CNN 拍摄 32×32×3 的图像,在图像上滑动相同深度的过滤器以产生 2D 激活图,该激活图包含测量过滤器和图像之间的相似性的分数。激活映射的堆栈用于网络中的下一层,根据体系结构,下一层可以是卷积层或池层。在最后一步中,使用前馈神经网络对图像进行分类。要看 CNN 的报道,请点击这里的迪普维斯、这里的 T2 和这里的 T4

卷积层:

卷积可能看起来像一个可怕的词,但它不是。在纯数学中,它是一种度量一个函数的形状如何被另一个函数的形状修改的方法。这个定义可以很容易地扩展到计算机视觉。如果您试图查看图像是圆形还是方形,您可以在两幅图像上滑动一条直线和一条曲线,以查看特定的滤镜是否会影响图像的形状。量化每个过滤器的影响的方法是计算每个图像和每个过滤器的分数。分数越接近 1,特征对输入的影响就越大。对于这个例子,分数显示直线影响正方形,曲线影响圆形;这是激活地图上的最高分数所显示的。

Applying a 5x5x3 filter (semi circle and line) to a 32x32x3 image (circle and square) produces an 28x28 activation map that shows where the image is the most like the filter. This image shows that where the filter is like the image the score is high.

Applying a 5x5x3 filter (semi circle and line) to a 32x32x3 image (circle and square) produces an 28x28 activation map that shows where the image is the most like the filter. This image shows that the filters are not like the image so the scores are low.

计算卷积的一个问题是滤波器的大小、步幅的大小和图像的大小可能是不对称的。这是一个问题,因为这些尺寸应该是对称的,以保持图像的空间结构。例如,如果您有一个 32x32x3 的图像,一个 7x7x3 的滤镜,并且跨距为 1,则该滤镜将无法查看图像中的所有像素。零填充通过在图像周围添加零来解决这个问题。这意味着过滤器将能够滑过整个图像并为整个图像产生分数。零填充也是一种很好的做法,因为它允许您控制输出音量的大小。这可确保边缘不会消失得太快,并保留输入体积的空间大小和结构。因此,您可以设计更大、更深的网络。零填充是确保从图像中提取最佳数据的另一种方式,以便网络可以获得最佳结果。

The zeros around the perimeter now allow for the filter to see the entire input.

如何计算卷积:

就像这个定义一样,卷积背后的数学并不难理解。

卷积的正式定义是这样的:

Not as scary as it looks. Calculus is simply a way to measure how quantities change.

这个公式并没有看起来那么恐怖。一旦过滤器和图像对齐,公式可以分解为三个简单的步骤:

  1. 将每个图像像素乘以权重,然后乘以过滤器像素(点积)
  2. 把它们加起来
  3. 除以过滤器中的像素总数

实现不会偏离这些步骤太远。一旦设置了步幅大小、零填充和输出的值,就可以计算卷积并将计算出的值存储在缓存中,以便可以再次访问它们进行反向传播。

现在你可以明白为什么 CNN 有计算猪的名声了。这种类型的实现通常不会大规模使用,但这个项目的重点是深入了解 CNN 实际在做什么。

联营

池化过程接受输入并减少其大小,同时保留输入中最重要的信息。池化减少了计算过程中的噪声参数,从而控制过度拟合。该过程采用 2×2 滤波器,在输入上的跨距为 2,并选择具有最大值的输入像素,并将该像素放入尺寸减小的输出中。池化将输入的大小从 W1xH1xD1 减小到新的输出,大小为 W2=(W1 大小)/步幅+1,(H1 大小)/步幅+1,D2=D1。这处理了先前输入的 75%。剩余的 25%是与特定滤波器中的像素最相似的输入。同样,该过程进一步隔离最相关的数据,以便全连接层进行分类。

This shows pooling in action. If we had a 8x8 image the pooling operation would pick the max value from each 2x2 region. The activation map is now 25% of its original size.

对于实现,您设置旧图像和新图像的宽度、高度和步幅的值。下一步是使用过滤器迭代图像,提取具有最大值的特征,然后返回新的缩减大小的输入。

背面投影:

从头开始创建 CNN 的最重要的原因之一是获得计算 backprop 的第一手经验,因为它是一个有漏洞的抽象。这意味着随着系统变得越来越复杂,开发人员依赖于更多的抽象。抽象隐藏了复杂性,允许开发人员编写处理抽象的软件,而不是解决复杂的问题,如消失或爆炸的渐变。然而,这条定律也指出,可靠软件的开发者无论如何都必须了解抽象的底层细节。所以,让我们来学习吧!

在深入了解反向传播如何在 CNN 架构中工作之前,我高度推荐这个讲座深入了解反向传播如何工作。

反向传播测量给定输入时输出如何变化。反向传播的目的是找到最小化损失函数结果的权重值。激活图是卷积层的输出,是过滤器和权重应用于输入的线性变换的结果。因此,我们需要计算相对于重量和相对于输入的梯度,即一个量的变化量。对输出中的每个像素都执行此过程,因为过滤器中的每个权重都有助于创建输出中的每个像素。这表明权重的变化将改变输出像素。因此,所有这些变化加起来就是最终的损失。

为了图形的简单性和理解直观性,我将使用这些尺寸,一个 3x3 输入,一个 2x2 过滤器和一个 2x2 输出。反向投影的偏导数如下所示,其中 W 是重量,H 是输出:

为了实现当前图层的反向投影代码以及上述等式的工作原理,有必要了解我们正在获取作为输入的输出的梯度,并且我们需要计算权重和输入的梯度。因此,相对于输入的梯度,(或相对于前一层的输出的梯度)将是前一层的反向传递的输入。这种联系是反向传播强大的原因。

最后,由于协变层的反向传播也是一个卷积,但具有空间翻转层,所以它又回到了原点。

全连接层

最后,一旦所有的卷积和池化完成,网络的最后一部分就是一个完全连接的层。这部分网络采用 CNN 提取的特征,并通过前馈神经网络进行分类。当在卷积和池化之后使用时,完全连接的图层更有效,因为它对在整个特征提取过程中在空间上保留的一组特征进行分类。这意味着网络将产生更准确的结果,因为它有更准确的数据。

the feedforward network is the final step

就是这样!如果你想了解更多关于 CNN 及其应用的信息,我建议你查看以下链接:

[## 用于视觉识别的 CS231n 卷积神经网络

斯坦福 CS231n 课程材料和笔记:视觉识别的卷积神经网络。

cs231n.github.io](http://cs231n.github.io) [## 博客

欢迎光临!给自己倒一杯热饮,四处看看。机器学习的应用驱动课程…

布罗尔.吉图布.艾欧](https://brohrer.github.io/blog.html) [## 11-785 深度学习

以深度神经网络为代表的“深度学习”系统正越来越多地接管所有人工智能任务,从…

deeplearning.cs.cmu.edu](http://deeplearning.cs.cmu.edu)

面向初学者的 R 语言数据可视化综合指南

原文:https://towardsdatascience.com/a-guide-to-data-visualisation-in-r-for-beginners-ef6d41a34174?source=collection_archive---------1-----------------------

R 可视化功能概述。

Photo by William Iven on Unsplash

注意:文章是旧的,许多没有反映 R 包的最新变化

当今世界充满了数据,我们必须正确地分析数据,以获得有意义的见解。数据可视化是一个重要的工具,可以从数据中挖掘出可能的关键见解。如果分析的结果没有被恰当地可视化,它们将不会被有效地传达给期望的受众。

在本教程中,我们将学习如何使用 R 统计语言来分析和显示数据。我们将从基本的情节开始,然后在文章的后面继续讨论更高级的情节。

目录

先决条件

对 R 及其语法的基本熟悉将使您很容易入门。

R 简介

概观

R 是一个统计计算和图形的语言和环境。当涉及到创建可视化时,r 也非常灵活和易于使用。它的功能之一是用最少的代码生成高质量的地块。

装置

我们将简要回顾一下安装 R:

  1. 进入 R 主页选择曲柄
    CRAN 是—综合 R 档案网的缩写。它是包含 R 发行版、软件包和文档的站点的集合。
  2. 选择离你最近的地点。
  3. 根据您的操作系统下载并安装 R。

或者,您可以在 base R GUI 上使用R studio

启动

下载并安装 R 后,您可以从应用程序文件夹(MacOS)或桌面图标(Windows)启动它。只需输入以下命令来检查 R 是否已经正确安装并正在运行。

> 1
1
> ‘hello World’
hello world

载入数据

数据集既可以是内置的,也可以从 r。

  • 内置数据集指的是 r 中已经提供的数据集。我们将使用一个这样的数据集,称为空气质量数据集,它与 1973 年 5 月至 9 月纽约的每日空气质量测量值有关。该数据集由 6 个变量的 100 多个观测数据组成,即、臭氧(十亿分之几)、太阳。R (太阳辐射)(平均风速)温度(日最高气温华氏温度)(观测月)日(一个月中的某一天)

要将内置数据集加载到 R 中,请在控制台中键入以下命令:

data(airquality)
  • 外部数据源的情况下(CSV、Excel、文本、HTML 文件等。),只需用 setwd() 命令将包含数据的文件夹设置为工作目录
setwd(path of the folder where the file is located)

现在,在读取命令的帮助下加载文件。在这种情况下,数据是一个名为 airquality.csv 的 CSV 文件,可以从这里下载

airquality = read.csv('airquality.csv',header=TRUE, sep=",")

以上代码将文件 airquality.csv 读入数据帧 airqualityHeader=TRUE 指定数据包含标题, sep= ","指定数据中的值用逗号分隔。

数据探索

一旦数据被加载到工作空间中,就应该研究它以了解它的结构。

  • str(airquality)
    它显示 R 对象的内部结构,并给出数据集的行和列的快速概览。
'data.frame': 111 obs. of  6 variables:    
$ Ozone  : int  41 36 12 18 23 19 8 16 11 14 ...    
$ Solar.R: int  190 118 149 313 299 99 19 256 290 274 ...    
$ Wind   : num  7.4 8 12.6 11.5 8.6 13.8 20.1 9.7 9.2 10.9 ...    
$ Temp   : int  67 72 74 62 65 59 61 69 66 68 ...    
$ Month  : int  5 5 5 5 5 5 5 5 5 5 ...    
$ Day    : int  1 2 3 4 7 8 9 12 13 14 ... `
  • head(data,n)tail(data,n)
    head 输出数据集中顶部的 n 个元素,而 tail 方法输出底部的 n 个
head(airquality, n=3)
Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3tail(airquality, n=3)
   Ozone Solar.R Wind Temp Month Day
109    14     191 14.3   75     9  28
110    18     131  8.0   76     9  29
111    20     223 11.5   68     9  30
  • summary(air quality)
    summary 方法根据变量的类型显示数据集中每个变量的描述性统计数据。
**summary(data)**

    Ozone          Solar.R           Wind            Temp           Month            Day       
 Min.   :  1.0   Min.   :  7.0   Min.   : 2.30   Min.   :57.00   Min.   :5.000   Min.   : 1.00  
 1st Qu.: 18.0   1st Qu.:113.5   1st Qu.: 7.40   1st Qu.:71.00   1st Qu.:6.000   1st Qu.: 9.00  
 Median : 31.0   Median :207.0   Median : 9.70   Median :79.00   Median :7.000   Median :16.00  
 Mean   : 42.1   Mean   :184.8   Mean   : 9.94   Mean   :77.79   Mean   :7.216   Mean   :15.95  
 3rd Qu.: 62.0   3rd Qu.:255.5   3rd Qu.:11.50   3rd Qu.:84.50   3rd Qu.:9.000   3rd Qu.:22.50  
 Max.   :168.0   Max.   :334.0   Max.   :20.70   Max.   :97.00   Max.   :9.000   Max.   :31.00

我们可以一目了然地看到变量的均值中位数最大值四分位值

基本情节入门

图形 包用于绘制图形,如散点图、箱线图等。通过输入:library(help = "graphics")可以获得带有帮助页面的完整功能列表。

plot()函数

  • plot()函数是一种用于绘制 R 对象的通用函数。
plot(airquality$Ozone)

Scatter Plot

我们在这里得到一个散点图/点图,其中每个点代表臭氧平均十亿分之中的值。

  • 现在让我们绘制一张臭氧和风值之间的图表,来研究两者之间的关系。
plot(airquality$Ozone, airquality$Wind)

图表显示风和臭氧值有某种程度的负相关性。

  • 当我们对整个数据集使用 plot 命令而不选择任何特定列时,会发生什么情况?
plot(airquality)

我们得到一个散点图矩阵,它是所有列的相关矩阵。上面的图立即显示:

  • 臭氧水平和温度正相关。
  • 风速与温度和臭氧水平都呈负相关。

只要看看变量之间的关系图,我们就能很快发现它们之间的关系。

在 plot()函数中使用参数

我们可以通过使用plot()函数的参数来轻松设计图表。

类型参数

绘图函数有一个名为type的参数,它可以接受像 p:点l:线b:两者等值。这决定了输出图形的形状。

# points and lines 
 plot(airquality$Ozone, type= "b")

# high density vertical lines.
 plot(airquality$Ozone, type= "h")

在控制台中键入 *?plot()* 可以阅读更多关于 *plot()* 命令的内容。

标签和标题

我们还可以标记 X 轴和 Y 轴,并给我们的图加一个标题。此外,我们还可以选择给图着色。

plot(airquality$Ozone, xlab = 'ozone Concentration', ylab = 'No of Instances', main = 'Ozone levels in NY city', col = 'green')

2.条形图

在条形图中,数据以矩形条的形式表示,条的长度与数据集中变量或列的值成比例。通过调整 horiz 参数,可以生成水平和垂直条形图。

# Horizontal bar plot
 barplot(airquality$Ozone, main = 'Ozone Concenteration in air',xlab = 'ozone levels', col= 'green',horiz = TRUE)

# Vertical bar plot
barplot(airquality$Ozone, main = 'Ozone Concenteration in air',xlab = 'ozone levels', col='red',horiz = FALSE)

3.柱状图

直方图与条形图非常相似,只是它将值分组到连续的范围内。直方图表示被划分为不同范围的变量值的频率。

hist(airquality$Solar.R)

我们得到了太阳的直方图。R 值。通过给颜色参数一个合适的值,我们也可以得到一个彩色直方图。

hist(airquality$Solar.R, main = 'Solar Radiation values in air',xlab = 'Solar rad.', col='red')

4.箱线图

我们已经看到 R 中的summary()命令如何显示数据集中每个变量的描述性统计数据。Boxplot 做了同样的事情,尽管是以四分位数的形式。在 r 中绘制箱线图也非常简单。

#Single box plot
boxplot(airquality$Solar.R)

# Multiple box plots
boxplot(airquality[,0:4], main='Multiple Box plots')

5.图表网格

R 中有一个非常有趣的特性,可以让我们一次绘制多个图表。这在 EDA 过程中非常方便,因为不再需要一个接一个地绘制多个图形。
绘制网格时,第一个参数应指定某些属性,如网格的边距(mar)、行数和列数(mfrow)、是否包含边框(bty)以及标签的位置(las : 1 表示水平,las : 0 表示垂直)。

par(mfrow=c(3,3), mar=c(2,5,2,1), las=1, bty="n")
plot(airquality$Ozone)
plot(airquality$Ozone, airquality$Wind)
plot(airquality$Ozone, type= "c")
plot(airquality$Ozone, type= "s")
plot(airquality$Ozone, type= "h")
barplot(airquality$Ozone, main = 'Ozone Concenteration in air',xlab = 'ozone levels', col='green',horiz = TRUE)
hist(airquality$Solar.R)
boxplot(airquality$Solar.R)
boxplot(airquality[,0:4], main='Multiple Box plots')

注意:通过键入?plot name,您可以使用函数文档来了解关于给定函数的更多信息。另外,example(plot)直接在控制台中运行绘图演示。

R 中的可视化库

r 配备了功能强大的复杂可视化库。让我们仔细看看一些常用的。

在本节中,我们将使用内置的 mtcars 数据集来展示各种库的用法。该数据集摘自 1974 年的《汽车趋势》美国杂志。

点阵图形

Lattice 包本质上是对 R Graphics 包的改进,用于可视化多元数据。晶格使得能够使用 t rellis 图形 。格子图展示了依赖于一个或多个变量的变量之间的关系。让我们从安装和加载软件包开始。

# Installing & Loading the package
install.packages("lattice")
library(lattice) #Loading the dataset
attach(mtcars)

attach 函数将数据库附加到 R 搜索路径,这样数据库中的对象只需给出它们的名称就可以被访问。(详见?attach())

# Exploring the datasethead(mtcars)
                       mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

在继续使用 lattice 包之前,让我们对数据做一些预处理。在我们的 mtcars 数据集中有两列,即齿轮气缸,它们本质上是分类的。我们需要分解它们,使它们更有意义。

gear_factor<-factor(gear,levels=c(3,4,5),
labels=c("3gears","4gears","5gears")) 

cyl_factor <-factor(cyl,levels=c(4,6,8),
labels=c("4cyl","6cyl","8cyl"))

注意:由于我们已经附加了数据集 mtcars,我们不需要指定 *mtcars$gear* *mtcars$cyl*

现在让我们看看如何使用 lattice 包在 r 中创建一些基本的情节。

  • 内核密度图
densityplot(~mpg, main="Density Plot",  xlab="Miles per Gallon")

使用点阵库非常简单。人们只需要插入想要绘图的列。

  • 散点图矩阵
splom(mtcars[c(1,3,4,5,6)], main="MTCARS Data")

  • 描绘两个因素组合的散点图
xyplot(mpg~wt|cyl_factor*gear_factor,  
main="Scatterplots : Cylinders and Gears",  
ylab="Miles/Gallon", xlab="Weight of Car")

2.ggplot2

ggplot2 包是 r 中使用最广泛的可视化包之一。它使用户能够使用图形的语法用很少的代码创建复杂的可视化。图形的语法是一个数据可视化的通用方案,它将图形分解成语义成分,如比例和层。

近年来,ggplot2 的受欢迎程度大大增加,因为它可以以非常简单的方式创建包含单变量和多变量数据的图表。

#Installing & Loading the package 

install.packages(“ggplot2”) 
library(ggplot2)

#Loading the dataset
attach(mtcars) # create factors with value labels 

mtcars$gear <- factor(mtcars$gear,levels=c(3,4,5),  
labels=c("3gears", "4gears", "5gears"))  
mtcars$am <- factor(mtcars$am,levels=c(0,1),  
labels=c("Automatic","Manual"))  
mtcars$cyl <- factor(mtcars$cyl,levels=c(4,6,8),  
labels=c("4cyl","6cyl","8cyl"))

让我们创造几个情节来了解 ggplot2 的能力

  • 散点图
ggplot(data = mtcars, mapping = aes(x = wt, y = mpg)) + geom_point()

geom_point()用于创建散点图,geom 可以有多种变化,如geom_jitter()geom_count()

  • 根据因子设计散点图的样式

我们知道数据集 mtcars 由某些以因子形式存在的变量组成。我们可以利用这个属性来分割数据集

ggplot(data = mtcars, mapping = aes(x = wt, y = mpg, color = as.factor(cyl))) + geom_point()

颜色参数用于区分 cyl 变量的不同因子级别。

  • 根据大小设定散点图样式

ggplot2 的另一个有用的特性是,它可以根据属性的大小来设置样式。

ggplot(data = mtcars, mapping = aes(x = wt, y = mpg, size = qsec)) + geom_point()

在上面的例子中,qsec的值表示决定点大小的加速度。

  • 不同尺寸的不同符号

使用 ggplot2,还可以通过将不同大小的多个点分层来创建独特而有趣的形状

p  <-  ggplot(mtcars,aes(mpg, wt, shape  =  factor(cyl)))
  p + geom_point(aes(colour  =  factor(cyl)), size  =  4) + geom_point(colour  =  "grey90", size  =  1.5)

3.Plotly

Plotly 是一个 R 包,通过开源的 JavaScript 图形库 plotly.js 创建交互式的基于 web 的图形。它还可以轻松地将“ggplot2”图翻译成基于网络的版本。

#Installing & Loading the package 

 install.packages(“plotly”)  
 library(plotly)

现在让我们看看我们如何利用情节来创造互动的视觉化。我们将使用点阵图形演示中使用的相同 mtcars 数据集。

  • 基本散点图
p <- plot_ly(data = mtcars, x = ~hp, y = ~wt)
p

上面的图也可以以网页的形式导出,以保持其交互性。

  • 样式散点图

散点图可以通过给定适当的颜色代码来设计。

p <- plot_ly(data = mtcars, x = ~hp, y = ~wt, marker = list(size = 10, color = 'rgba(255, 182, 193, .9)', line = list(color = 'rgba(152, 0, 0, .8)', width = 2)))p

  • 标记和线条

也可以用 plotly 在同一个图形中绘制标记和线条。在这里,我们将创建一个任意数据框来展示此功能。

data1 <- rnorm(100, mean = 10)   
data2 <- rnorm(100, mean = 0)   
data3 <- rnorm(100, mean = -10)   
x <- c(1:100)data <- data.frame(x, data1, data2, data3)p <- plot_ly(data, x = ~x)%>%   

add_trace(y = ~data1, name = 'data1',mode = 'lines')%>%             
add_trace(y = ~data2, name = 'data2', mode = 'lines+markers')%>% 
add_trace(y = ~data3, name = 'data3', mode = 'markers')p

添加颜色和大小映射

p <- plot_ly(data = mtcars, x =~hp, y = ~wt,color = ~hp, size = ~hp )
p

虽然这不是 R 中用于可视化的包的完整列表,但是这些应该足够让你开始了。

在 R 中可视化地理数据

地理数据(地理数据)与基于位置的数据相关。它主要描述物体在空间中的关系。数据通常以坐标的形式存储。以地图的形式看到一个州或一个国家更有意义,因为它提供了更真实的概览。在下一节中,我们将简要概述 R 在地理数据可视化方面的能力。

地理地图

我们将使用 ABC 公司的超市数据集样本。该数据集由他们在美国的商店位置组成。让我们加载数据并检查它的列。

data <- read.csv('ABC_locations.csv', sep=",")head(data)
                    Address       City   State   Zip.Code Latitude  Longitude
1  1205 N. Memorial Parkway Huntsville Alabama 35801-5930 34.74309  -86.60096
2      3650 Galleria Circle     Hoover Alabama 35244-2346 33.37765  -86.81242
3    8251 Eastchase Parkway Montgomery Alabama      36117 32.36389  -86.15088
4 5225 Commercial Boulevard     Juneau  Alaska 99801-7210 58.35920 -134.48300
5      330 West Dimond Blvd  Anchorage  Alaska 99515-1950 61.14327 -149.88422
6          4125 DeBarr Road  Anchorage  Alaska 99508-3115 61.21081 -149.80434

plot()函数

我们将简单地通过纬度和经度列创建一个粗略的地图。

plot(data$Longitude,data$Latitude)

输出不是精确的地图,但它给出了美国边界的模糊轮廓。

map()函数

地图包在绘制地理数据时非常有用而且非常简单。

# Install package 
install.packages("maps", dependencies=TRUE)# Loading the installed maps package
library(maps)

使用 map()函数绘制美国底图

map(database="state")

使用 symbols()函数在基础地图上构建一个点地图

symbols(data$Longitude, data$Latitude, squares =rep(1, length(data$Longitude)), inches=0.03, add=TRUE)

赋予符号颜色

symbols(data$Longitude, data$Latitude,bg = 'red', fg = 'red', squares =rep(1, length(data$Longitude)), inches=0.03, add=TRUE)

与 map 函数一起使用的命令是不言自明的。然而,你可以在他们的文档页面上了解更多。

当数据由位置组成时,地理数据可视化非常重要。人们可以很容易地想象出确切的地点和区域,并传达出更好的画面。

5.结论

我们已经看到使用 r 开始可视化是多么的简单和容易。你可以选择从头开始创建可视化或者使用预先构建的包。无论你选择什么,很明显 R 的可视化能力是无穷无尽的。

Python 人脸检测指南(附代码)

原文:https://towardsdatascience.com/a-guide-to-face-detection-in-python-3eab0f6b9fc1?source=collection_archive---------1-----------------------

Greenland

在本教程中,我们将看到如何使用 OpenCV 和 Dlib 在 Python 中创建和启动人脸检测算法。我们还将添加一些功能来同时检测多张脸上的眼睛和嘴巴。本文将介绍人脸检测的最基本实现,包括级联分类器、HOG 窗口和深度学习 CNN。

我们将使用以下内容来介绍人脸检测:

  • 基于 OpenCV 的 Haar 级联分类器
  • 使用 Dlib 的方向梯度直方图
  • 使用 Dlib 的卷积神经网络

本文原载于我的个人博客:https://maelfabien.github.io/tutorials/face-detection/#

本文的 Github 库(以及我博客中的所有其他内容)可以在这里找到:

[## mael fabien/机器学习教程

本报告包含练习、代码、教程和我的个人博客文章

github.com](https://github.com/maelfabien/Machine_Learning_Tutorials)

介绍

我们将使用 OpenCV,这是一个用于计算机视觉的开源库,用 C/C++编写,有 C++、Python 和 Java 的接口。它支持 Windows、Linux、MacOS、iOS 和 Android。我们的一些工作还需要使用 Dlib,这是一个现代 C++工具包,包含机器学习算法和用于创建复杂软件的工具。

要求

第一步是安装 OpenCV,和 Dlib。运行以下命令:

pip install opencv-pythonpip install dlib

根据您的版本,文件将安装在以下位置:

/usr/local/lib/python3.7/site-packages/cv2

如果你遇到 Dlib 的一些问题,请查看这篇文章

导入和模型路径

我们将创建一个新的 Jupyter 笔记本/ python 文件,并从以下内容开始:

import cv2
import matplotlib.pyplot as plt
import dlib
from imutils import face_utilsfont = cv2.FONT_HERSHEY_SIMPLEX

一.级联分类器

我们将首先探索级联分类器。

一. 1 .理论

级联分类器,即使用 haar-like 特征的级联提升分类器,是集成学习的一个特例,称为 boosting。它通常依赖于 Adaboost 分类器(以及其他模型,如 Real Adaboost、Gentle Adaboost 或 Logitboost)。

级联分类器在包含我们想要检测的对象的图像的几百个样本图像上以及不包含那些图像的其他图像上被训练。

我们如何检测一张脸是否存在?有一种算法,称为 Viola–Jones 对象检测框架,它包括实时人脸检测所需的所有步骤:

  • 哈尔特征选择,从哈尔小波导出的特征
  • 创建整体图像
  • Adaboost 训练
  • 级联分类器

最初的论文发表于 2001 年。

I.1.a .哈尔特征选择

我们在大多数普通人的脸上发现了一些共同的特征:

  • 与脸颊上部相比,眼部区域较暗
  • 与眼睛相比明亮的鼻梁区域
  • 眼睛、嘴巴、鼻子的一些特定位置…

这些特征称为哈尔特征。特征提取过程将如下所示:

Haar Features

在这个例子中,第一特征测量眼睛区域和上脸颊区域之间的亮度差异。特征值简单地通过将黑色区域中的像素相加并减去白色区域中的像素来计算。

然后,我们应用这个矩形作为卷积核,覆盖整个图像。为了做到面面俱到,我们应该应用每个内核所有可能的维度和位置。简单的 24*24 图像通常会产生超过 160,000 个特征,每个特征由像素值的和/减组成。对于活体面部检测来说,在计算上是不可能的。那么,我们如何加快这个过程呢?

  • 一旦好的区域被矩形识别,在图像的完全不同的区域上运行窗口是没有用的。这可以通过 Adaboost 来实现。
  • 使用积分图像原理计算矩形特征,这样更快。我们将在下一节讨论这个问题。

有几种类型的矩形可以应用于 Haar 特征提取。根据原始论文:

  • 双矩形特征是两个矩形区域内的像素之和的差,主要用于检测边缘(a,b)
  • 三矩形功能计算两个外部矩形的总和,从中心矩形的总和中减去,主要用于检测线(c,d)
  • 四矩形特征计算矩形(e)的对角线对之间的差

Haar Rectangles

既然已经选择了特征,我们使用 Adaboost 分类将它们应用于训练图像集,Adaboost 分类结合一组弱分类器来创建准确的集成模型。有了 200 个特征(而不是最初的 160,000 个),准确率达到了 95%。论文作者选择了 6000 个特征。

I.1.b .整体形象

在卷积核样式中计算矩形特征可能会很长,非常长。出于这个原因,作者 Viola 和 Jones 提出了图像的中间表示:积分图像。积分图像的作用是允许仅使用四个值简单地计算任何矩形和。我们来看看效果如何!

假设我们想要确定坐标为(x,y)的给定像素处的矩形特征。然后,在给定像素的上面和左边的像素的总和中的像素的积分图像。

其中 ii(x,y)是积分图像,i(x,y)是原始图像。

当你计算整个积分图像时,有一种形式的递归,只需要在原始图像上遍历一次。事实上,我们可以定义以下一对递归:

其中 s(x,y)为累计行和,s(x1)= 0,ii(1,y)=0。

这有什么用?好吧,考虑一个区域 D,我们想估计它的像素总数。我们已经定义了 3 个其他区域:A、B 和 c。

  • 点 1 处的积分图像的值是矩形 a 中像素的总和。
  • 点 2 的值是 A + B
  • 点 3 的值是 A + C
  • 点 4 的值是 A + B + C + D。

因此,区域 D 的像素之和可以简单地计算为:4+1(2+3)。

在一次传递中,我们仅使用 4 个数组引用计算了矩形内部的值。

人们应该简单地意识到矩形在实践中是非常简单的特征,但是对于人脸检测来说已经足够了。当涉及复杂问题时,方向可调滤波器往往更加灵活。

Steerable Filters

I.1c .用 Adaboost 学习分类函数

给定一组标记的训练图像(正的或负的),Adaboost 用于:

  • 选择一小组特征
  • 并训练分类器

由于 160,000 个特征中的大多数特征被认为是完全不相关的,因此我们围绕其构建增强模型的弱学习算法被设计成选择分割最佳负样本和正样本的单个矩形特征。

级联分类器

尽管上述过程非常有效,但仍存在一个主要问题。在一幅图像中,图像的大部分是非人脸区域。赋予图像的每个区域同等的重要性是没有意义的,因为我们应该主要关注最有可能包含图片的区域。Viola 和 Jones 使用级联分类器提高了检测率,同时减少了计算时间。

关键思想是拒绝不包含人脸的子窗口,同时识别包含人脸的区域。由于任务是正确地识别人脸,我们希望最小化假阴性率,即包含人脸并且没有被识别为人脸的子窗口。

一系列分类器被应用于每个子窗口。这些分类器是简单的决策树:

  • 如果第一个分类器是肯定的,我们继续第二个
  • 如果第二个分类器是肯定的,我们继续第三个

在某一点上的任何否定结果都导致拒绝该子窗口,因为该子窗口可能包含人脸。初始分类器以较低的计算成本消除了大多数负样本,随后的分类器消除了额外的负样本,但需要更多的计算工作。

使用 Adaboost 训练分类器,并调整阈值以最小化错误率。当训练这样的模型时,变量如下:

  • 分类器级数
  • 每个阶段的特征数量
  • 每个阶段的门槛

幸运的是,在 OpenCV 中,整个模型已经为人脸检测进行了预训练。

如果你想了解更多关于增强技术的知识,我邀请你查看我关于 Adaboost 的文章。

一. 2 .进口

下一步就是找到预先训练好的权重。我们将使用默认的预训练模型来检测面部,眼睛和嘴巴。根据您的 Python 版本,这些文件应该位于以下位置:

/usr/local/lib/python3.7/site-packages/cv2/data

一旦确定,我们将这样声明级联分类器:

cascPath = "/usr/local/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_default.xml"
eyePath = "/usr/local/lib/python3.7/site-packages/cv2/data/haarcascade_eye.xml"
smilePath = "/usr/local/lib/python3.7/site-packages/cv2/data/haarcascade_smile.xml"faceCascade = cv2.CascadeClassifier(cascPath)
eyeCascade = cv2.CascadeClassifier(eyePath)
smileCascade = cv2.CascadeClassifier(smilePath)

I.3 .检测图像上的人脸

在实现实时人脸检测算法之前,让我们在一幅图像上尝试一个简单的版本。我们可以从加载测试图像开始:

# Load the image
gray = cv2.imread('face_detect_test.jpeg', 0)plt.figure(figsize=(12,8))
plt.imshow(gray, cmap='gray')
plt.show()

Test image

然后,我们检测面部,并在其周围添加一个矩形:

# Detect faces
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
flags=cv2.CASCADE_SCALE_IMAGE
)# For each face
for (x, y, w, h) in faces: 
    # Draw rectangle around the face
    cv2.rectangle(gray, (x, y), (x+w, y+h), (255, 255, 255), 3)

以下是detectMultiScale功能最常见的参数列表:

  • scaleFactor:指定图像在每个图像比例下缩小多少的参数。
  • minNeighbors:指定每个候选矩形应该有多少个邻居来保留它的参数。
  • 最小尺寸:可能的最小物体尺寸。小于该值的对象将被忽略。
  • maxSize:可能的最大对象大小。大于该值的对象将被忽略。

最后,显示结果:

plt.figure(figsize=(12,8))
plt.imshow(gray, cmap='gray')
plt.show()

人脸检测在我们的测试图像上运行良好。现在让我们进入实时时间!

I.4 .实时人脸检测

让我们继续讨论实时面部检测的 Python 实现。第一步是启动相机,捕捉视频。然后,我们将图像转换成灰度图像。这用于减少输入图像的尺寸。事实上,我们应用简单的线性变换,而不是每像素 3 个点来描述红、绿、蓝:

这在 OpenCV 中是默认实现的。

video_capture = cv2.VideoCapture(0)while True:
    # Capture frame-by-frame
    ret, frame = video_capture.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

现在,我们将使用上面定义的faceCascade变量,它包含一个预先训练的算法,并将其应用于灰度图像。

faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30),
        flags=cv2.CASCADE_SCALE_IMAGE
        )

对于每个检测到的人脸,我们将在人脸周围画一个矩形:

for (x, y, w, h) in faces:
        if w > 250 :
            cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 3)
            roi_gray = gray[y:y+h, x:x+w]
            roi_color = frame[y:y+h, x:x+w]

对于检测到的每个嘴部,在其周围画一个矩形:

smile = smileCascade.detectMultiScale(
        roi_gray,
        scaleFactor= 1.16,
        minNeighbors=35,
        minSize=(25, 25),
        flags=cv2.CASCADE_SCALE_IMAGE
    )
    for (sx, sy, sw, sh) in smile:
        cv2.rectangle(roi_color, (sh, sy), (sx+sw, sy+sh), (255, 0, 0), 2)
        cv2.putText(frame,'Smile',(x + sx,y + sy), 1, 1, (0, 255, 0), 1)

对于检测到的每只眼睛,在其周围画一个矩形:

eyes = eyeCascade.detectMultiScale(roi_gray)
    for (ex,ey,ew,eh) in eyes:
        cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
        cv2.putText(frame,'Eye',(x + ex,y + ey), 1, 1, (0, 255, 0), 1)

然后,计算面部总数,并显示整体图像:

cv2.putText(frame,'Number of Faces : ' + str(len(faces)),(40, 40), font, 1,(255,0,0),2)      
    # Display the resulting frame
    cv2.imshow('Video', frame)

当我们想要按下q停止拍摄时,执行退出选项:

if cv2.waitKey(1) & 0xFF == ord('q'):
        break

最后,当一切完成后,释放捕获并销毁所有窗口。在 Mac 上杀死 windows 有一些问题,这可能需要稍后从活动管理器中杀死 Python。

video_capture.release()
cv2.destroyAllWindows()

I.5 .包装

一. 6 .结果

我在 YouTube 上做了一个脸部检测算法的快速演示。

二。Dlib 中的方向梯度直方图(HOG)

第二个最流行的人脸检测工具是由 Dlib 提供的,它使用了一个叫做梯度方向直方图(HOG)的概念。这是 Dalal 和 Triggs 最初论文的实现。

二. 1 .理论

HOG 背后的想法是将特征提取到一个向量中,并将其输入到一个分类算法中,例如支持向量机,该算法将评估一张脸(或任何你训练它实际识别的对象)是否存在于一个区域中。

提取的特征是图像梯度方向(定向梯度)的分布(直方图)。边缘和角落周围的梯度通常较大,这使我们能够检测到这些区域。

在原始论文中,该过程被实现用于人体检测,并且检测链如下:

二. 1.a .预处理

首先,输入图像必须大小相同(裁剪和重缩放图像)。我们将应用的补丁需要 1:2 的纵横比,因此输入图像的尺寸可能是64x128100x200

计算梯度图像

第一步是通过应用以下内核来计算图像的水平和垂直梯度:

Kernels to compute the gradients

图像的梯度通常会移除不重要的信息。

我们上面考虑的图像的渐变可以在 Python 中以这种方式找到:

gray = cv2.imread('images/face_detect_test.jpeg', 0)im = np.float32(gray) / 255.0# Calculate gradient 
gx = cv2.Sobel(im, cv2.CV_32F, 1, 0, ksize=1)
gy = cv2.Sobel(im, cv2.CV_32F, 0, 1, ksize=1)
mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True)

画出这幅图:

plt.figure(figsize=(12,8))
plt.imshow(mag)
plt.show()

但是我们之前没有对图像进行预处理。

II.1.c 计算猪

然后,图像被分成 8×8 的单元,以提供紧凑的表示,并使我们的 HOG 对噪声更加鲁棒。然后,我们计算每个单元格的 HOG。

为了估计区域内的梯度方向,我们简单地在每个区域内的梯度方向的 64 个值(8×8)和它们的量值(另外 64 个值)之间建立直方图。直方图的类别对应于渐变的角度,从 0°到 180°。总共有 9 类:0,20,40 … 160。

上面的代码给了我们两个信息:

  • 渐变的方向
  • 和梯度的大小

当我们制造 HOG 时,有 3 种情况:

  • 角度小于 160°且不在两个类别的中间。在这种情况下,角度将被添加到猪的正确类别中
  • 角度小于 160°,正好在 2 级之间。在这种情况下,我们考虑对两个最近的类的相等贡献,并且将大小分成两部分

  • 角度大于 160°。在这种情况下,我们认为像素成比例地贡献给 160 和 0。

对于每个 8×8 单元,猪看起来像这样:

HoG

II.1.d .块标准化

最后,可以应用 16×16 的块,以便归一化图像并使其对于例如光照不变。这可以简单地通过将大小为 8×8 的 HOG 的每个值除以包含它的 16×16 块的 HOG 的 L2 范数来实现,这实际上是长度为9*4 = 36的简单向量。

II.1.e .块标准化

最后,所有的 36×1 向量被连接成一个大向量。我们完了。我们有我们的特征向量,在其上我们可以训练一个软 SVM 分类器(C=0.01)。

II.2 .检测图像上的人脸

实现非常简单:

face_detect = dlib.get_frontal_face_detector()rects = face_detect(gray, 1)for (i, rect) in enumerate(rects):
(x, y, w, h) = face_utils.rect_to_bb(rect)
    cv2.rectangle(gray, (x, y), (x + w, y + h), (255, 255, 255), 3)

plt.figure(figsize=(12,8))
plt.imshow(gray, cmap='gray')
plt.show()

II.3 .实时人脸检测

如前所述,该算法很容易实现。我们还通过只检测面部来实现一个更轻的版本。Dlib 也使得检测面部关键点变得非常容易,但这是另一个话题了。

三。Dlib 中的卷积神经网络

最后一种方法基于卷积神经网络(CNN)。它还实现了一个关于最大边际对象检测(MMOD)的文件,以增强结果。

III.1 .一点理论

卷积神经网络(CNN)是主要用于计算机视觉前馈神经网络。它们提供了自动化的图像预处理以及密集的神经网络部分。CNN 是一种特殊类型的神经网络,用于处理具有网格状拓扑结构的数据。CNN 的建筑灵感来自动物的视觉皮层。

在以前的方法中,很大一部分工作是选择滤波器以创建特征,从而从图像中提取尽可能多的信息。随着深度学习和更大计算能力的兴起,这项工作现在可以自动化。CNN 的名字来源于我们用一组滤波器卷积初始图像输入的事实。要选择的参数仍然是要应用的过滤器数量和过滤器的尺寸。过滤器的尺寸被称为内核尺寸。步长是我们移动该过滤器的像素数。步幅的典型值介于 2 和 5 之间。

在这种特定情况下,CNN 的输出是二进制分类,如果有人脸,则取值 1,否则取值 0。

III.2 .检测图像上的人脸

某些元素在实现中会发生变化。

第一步是在这里下载预先训练好的模型。将权重移动到您的文件夹,并定义dnnDaceDetector:

dnnFaceDetector = dlib.cnn_face_detection_model_v1("mmod_human_face_detector.dat")

然后,非常类似于我们到目前为止所做的:

rects = dnnFaceDetector(gray, 1)for (i, rect) in enumerate(rects): x1 = rect.rect.left()
    y1 = rect.rect.top()
    x2 = rect.rect.right()
    y2 = rect.rect.bottom() # Rectangle around the face
    cv2.rectangle(gray, (x1, y1), (x2, y2), (255, 255, 255), 3)plt.figure(figsize=(12,8))
plt.imshow(gray, cmap='gray')
plt.show()

III.3 .实时人脸检测

最后,我们将实现 CNN 人脸检测的实时版本:

四。选哪个?

这是一个棘手的问题,但我们将只讨论两个重要的指标:

  • 计算时间
  • 准确性

在速度上,HoG 似乎是最快的算法,其次是 Haar 级联分类器和 CNN。

然而,Dlib 中的 CNN 往往是最精确的算法。HoG 表现很好,但是在识别小脸方面有一些问题。总体而言,HaarCascade 分类器的性能与 HoG 差不多。

我个人在我的个人项目中主要使用 HoG,因为它在实时人脸检测方面速度很快。

结论 :希望你喜欢这个关于 OpenCV 和 Dlib 人脸检测的快速教程。如果您有任何问题/评论,请不要犹豫,发表评论。

动词 (verb 的缩写)来源:

将文本分析集成到 Tableau 的指南

原文:https://towardsdatascience.com/a-guide-to-integrating-text-analytics-into-tableau-94d1a1331117?source=collection_archive---------11-----------------------

Credit: Freddie Marriage

数据往往又脏又乱。有时,它甚至没有以正确的形式进行快速分析和可视化。虽然 Tableau(和 Prep)有几个工具来处理数字、分类甚至空间数据,但一直缺少的一个部分是处理非结构化文本数据。

不再是了。

在几周前发布的最新版 Tableau Prep (2019.3)中,Prep 现在原生支持自定义 R 或 Python 脚本。通过使用 TabPy ,人们可以在任何数据集上使用整套 R 和 Python 库,而不必离开 Tableau 宇宙。从运行机器学习模型调用地理空间 API,可能性几乎是无穷无尽的。

在本文中,我们尝试了一些令人兴奋的新事物:使用 Tableau Prep 和 Python 将自然语言处理技术应用于非结构化文本数据。在深入研究之前,我们先从如何设置一切的深入指导开始。

第 1 部分:为 Tableau 准备设置 Python

第一个大问题是:如何让 Python 与 Tableau Prep 一起工作?安装非常简单明了——只需遵循网站上的说明这里。我们的建议是使用 Anaconda 安装包,而不是 pip,以避免潜在的依赖错误。

(我们在 MacBook 上运行我们的代码,所以这是我们在指南中使用的参考,抱歉,Windows 用户!)

有两件真正有用的事情需要注意,希望能让你免受我们所经历的挫折:

  1. conda安装了 TabPy 之后,你得把你的tornado版本降级到 5.1.1,否则在尝试运行 TabPy 的时候会遇到异步错误。这也列在(非常短)常见问题部分中。
  2. 在终端中运行命令tabpy对我不起作用。相反,我使用cd将目录更改为 TabPy 文件夹(尝试在类似anaconda3/envs/[my_env]/lib/python3.7/site-packages/tabpy_server的地方找到它)。然后,我通过键入sh startup.sh运行启动文件。

就是这样!但第二个大问题是:Tableau Prep 到底是如何使用 Python 脚本的?

A simple diagram to explain what is going on behind the scenes

本质上,Tableau Prep 将数据导出为 Pandas 数据帧,将自定义 Python 脚本中的指定函数应用于数据帧,并返回一个新的数据帧,该数据帧将被传递回 Tableau Prep。

记住整个流程很有帮助,尤其是在 Python 脚本中编写定制函数时。特别要注意的是,您的函数必须接收一个 Pandas 数据帧并返回另一个 Pandas 数据帧。

现在进入有趣的部分:编写 Python 脚本!

您的 Python 脚本至少需要两个函数,一个用于您尝试在 Python 中执行的操作,另一个用于定义输出模式。先说后者。

get_output_schema()帮助 Tableau Prep 理解从 Python 返回给它的数据的结构。如果要返回到 Tableau Prep 的数据帧与原始数据有不同的列,则需要此函数。它采取以下形式:

有六种数据类型,都是不言自明的,如上面的函数所示。注意,它们必须正确地映射到数据帧中每一列的实际数据类型,这样才能工作。

至于您自己的自定义函数,这里有一个非常简单的函数,它执行一些基本的数据处理:

如前面的图表所示,该函数接收原始数据作为 Pandas 数据帧,并返回清理后的数据作为 Pandas 数据帧。您可以在这里编写任何函数,只要您在脚本本身中导入所需的库。

您也可以在脚本中包含多个函数,但是 Tableau Prep 中的每个脚本工具一次只能调用一个函数。如果您计划对不同的数据集使用多个函数,您可以简单地将它们全部放入同一个 Python 脚本中,但只在需要时调用相关的函数。这省去了创建多个脚本的麻烦。

将这两个函数放在一个脚本中,就大功告成了。现在,我们终于可以在 Tableau Prep 上运行它了!

首先,我们通过引入一个 CSV 文件打开一个新的 Tableau 准备工作流。

这个 CSV 文件只有三列— CategoryTitleText。然后,我们将“脚本”工具添加到工作流中,这将我们带到以下页面:

现在,我们得到一个错误,因为 TabPy 服务器还没有设置好。打开终端,导航到文件夹tabpy_server,运行命令sh startup.sh。应该会出现以下内容:

记住这里的端口号,然后返回 Tableau Prep,单击“连接到 Tableau Python(tabby)服务器”按钮,并键入以下内容:

Key in the port number that was specified in Terminal! It’s not always 9004.

点击“登录”,它会带你回到主 Tableau 准备窗口。选择 Python 脚本文件,然后在按钮正下方的框中输入函数的名称。只要您的脚本运行正常,工作流就会自动运行。

从现在开始一切都是标准的舞台准备。当然,数据清理是 Python 中最不令人兴奋的事情,尤其是 Tableau Prep 已经做得很好了。既然我们已经学会了如何做基本的事情,我们就可以放下训练,开始将更高级的功能集成到工作流中。

第 2 部分:Tableau 中的自然语言处理

Most text data is unstructured, and NLP can help us to analyze all this data.

什么是自然语言处理(NLP)?简而言之,NLP 寻求解析和分析我们交流的内容和方式。虽然代码总是被精确而清晰地定义,但我们如何书写或说话只受语法规则的约束。语境和意义塑造了我们的写作和言语,这种模糊性使得计算机很难准确理解我们的意思。

不出所料,NLP 已经成为日常生活中相当常见的一部分。垃圾邮件过滤器、翻译和虚拟助手是 NLP 在现实世界中应用的许多例子中的一些。这一领域有如此大的潜力,因为它弥合了我们凭直觉发现的东西和计算机能够理解的东西之间的差距。

这就是为什么将文本分析引入 Tableau 是一个游戏改变者。面对如此多的非结构化文本数据,能够有效地可视化这些数据将有助于我们更好地感知总体趋势和调查重要的异常值。

Credits: AbsolutVision

对于本文,我们使用一个包含 2225 篇 BBC 新闻文章的公开数据集(非常感谢 Greene 和 Cunningham 免费提供这个数据集!).每一篇文章都被分配到五个类别中的一个,并单独放在一个.txt文件中。

我们使用 Python 处理这个脚本,以便为 Tableau Prep 生成一个 CSV 文件。下面是我们使用的代码:

现在我们已经有了正确格式的数据,让我们看看如何分析非结构化文本。让我们看两篇新闻文章来了解一下底层数据是什么样的。

这里有一个来自“商业”类别:

标致交易助推三菱

陷入困境的日本汽车制造商三菱汽车(Mitsubishi Motors)已达成一项协议,向法国汽车制造商标致(Peugeot)供应 3 万辆运动型多功能车(SUV)。

两家公司签署了一份谅解备忘录,并表示他们希望在 2005 年春天之前达成最终协议。在几次利润预警和销售不佳之后,这一联盟对亏损的三菱来说是一个急需的提振。这款 SUV 将在日本生产,使用标致的柴油发动机,主要在欧洲市场销售。销量下降让三菱汽车的产能未得到充分利用,而与标致的生产协议给了它一个利用部分产能的机会。

今年 1 月,三菱汽车发布了 9 个月来的第三次利润预警,并下调了截至 2005 年 3 月的年度销售预期。在过去的一年里,该公司的销量下滑了 41%,这是由该公司系统地隐藏故障记录,然后秘密修理车辆的消息所推动的。因此,这家日本汽车制造商寻求了一系列金融救助。上月,该行表示,正寻求进一步 5400 亿日元(52 亿美元;27.7 亿英镑)的新资金支持,其中一半来自三菱集团的其他公司。拥有三菱汽车 30%股份的美-德汽车制造商戴姆勒-克莱斯勒在 2004 年 4 月决定不再注资。三菱新任命的首席执行官西冈隆(Takashi Nishioka)庆祝了与标致的交易,他是在上个月三位高管辞职承担公司困境的责任后接任的。三菱汽车(Mitsubishi Motors)预计,在截至 2005 年 3 月的本财年,该公司将出现 4720 亿日元的净亏损。上个月,该公司与日本竞争对手日产汽车(Nissan Motor)签署了一份生产协议,向其供应 3.6 万辆小型汽车,在日本销售。自 2003 年以来,该公司一直为日产生产汽车。

这里有一个来自“技术”类别:

年份搜索变成了个人

很可能当你打开浏览器时,你会直接进入你最喜欢的搜索引擎,而不是输入网址。

有些人可能认为这是极度的懒惰,但是在一个信息超载的时代,搜索已经成为导航网络的重要工具。这表明了我们使用互联网的方式正在发生变化。正如谷歌所展示的,提供一项人们离不开的服务是有利可图的。很多公司都在争夺网络搜索者的忠诚度,提供大量不同的服务和工具来帮助你找到你想要的东西。在过去的 12 个月里,微软和雅虎等科技巨头都试图在搜索领域分一杯羹。雅虎的扬卡·布鲁尼尼说:“用户体验促使人们进行更多的搜索。她说,随着人们对互联网越来越熟悉,他们倾向于花更多的时间在网上,并提出更多的问题。“第二件事是宽带,”布鲁尼尼女士告诉 BBC 新闻网站。"这对互联网的影响就像色彩对电视的影响一样."

但是搜索并不是一个新现象。自从网络出现以来,它就一直存在。

经验丰富的冲浪者会记得 Hotbot 和 Altavista 这样的老前辈。“搜索一直都很重要,”谷歌运营副总裁乌尔斯·霍尔兹尔(Urs Holzle)表示。“我们在 1999 年就宣扬了这一点。随着用户越来越多,信息越来越多,现在更是如此。”“人们没有意识到搜索是未来。财务状况与此有关。”谷歌已经表明,网络商务可以通过其有针对性的小广告来运作,这些小广告出现在页面右侧的顶部和底部,并与原始搜索相关。这些小广告帮助谷歌在截至 9 月的三个月里实现了 8.059 亿美元的收入。其他人已经意识到你可以从网络查询中赚钱。“一旦你看到有一个市场,微软一定会抓住它。如果微软认为搜索很重要,那就没人会质疑它,”霍尔兹尔先生说。

微软只是进军搜索领域的网络巨头之一。雅虎、Ask Jeeves、亚马逊和一些较小的公司都在寻求吸引眼球。

随着每家公司都试图通过推出桌面搜索等新的搜索产品来击败谷歌,网络用户面临着过多的选择。它反映了战场是如何从网络转移到你的个人电脑上的。搜索不仅仅是在网上找路。现在,它是关于解锁隐藏在硬盘上数十亿字节的文档、图像和音乐中的信息。尽管有这些进步,搜索仍然是一个笨拙的工具,经常不能准确地找到你想要的东西。为了做得更好,搜索引擎试图更好地了解你,更好地记忆、分类和管理你遇到的所有信息。“个性化将是未来的一个大领域,”雅虎的扬卡·布鲁尼尼说。“谁破解了它,并给你你想要的信息,谁就是赢家。我们必须理解你,才能给你量身定制的更好的结果。”这也许是搜索的圣杯,理解你在寻找什么,并迅速提供给你。问题是还没有人知道如何到达那里。

我们想从这些新闻文章中提取什么样的数据?一些事情浮现在脑海中:

  1. 文章中提到了谁或什么?
  2. 这篇文章是用肯定语气还是否定语气写的?
  3. 讨论的一般话题是什么?

巧合的是,这三个问题中的每一个都对应 NLP 中的一个特定子领域。第一是实体识别,第二是情感分析,第三是话题建模。在本文中,我们将只研究前两者。

为此,我们依赖 Python 中两个著名的 NLP 库: SpacyTextBlob 。请确保在继续之前安装这两个软件包!

现在,我们只需使用这些库编写我们的脚本!

本文并不打算成为 Python 上 NLP 的指南(有许多文章和网站已经这样做了),所以我们将跳过解释这两个包是如何工作的。我们在代码中留下了注释,以便对我们在每个部分所做的事情有一个好的了解。

在上一节中,我们深入了解了如何将 Python 脚本集成到 Tableau Prep 工作流中,因此使用上面的脚本应该很容易!我们导入 BBC 数据 CSV 文件,输入端口号,选择 Python 脚本,输入函数名。

两分钟内,我们看到…

Python 脚本完美运行!

Tableau Prep 最棒的地方之一是能够查看汇总数据。我们可以立即看到,大多数文章少于 3750 个字符,通常极性得分约为 0 (-1 为负,1 为正),这与我们对 BBC 新闻作为简洁和中立的新闻来源的印象相当吻合。

我们还有每篇文章中提到的人、国家和组织的数据。虽然有一些错误(“气候”不是一个组织),但 Spacy 库在识别这些命名实体方面大体上是准确的。

让我们更深入地研究一下我们前面看到的两篇文章到底返回了什么。关于标致的文章:

关于个性化搜索的文章:

在这两种情况下,斯帕西都正确地指出了文章中提到的组织、个人和国家。还要注意个性化搜索文章在Text_SubjectivenessText_Polarity中的得分如何更高。这与我们读到的一致:它更侧重于构建一个关于个性化搜索如何变得更加普遍的叙事,并且相当支持这一趋势。相比之下,标致的文章只是描述了行业动向。

通过将文本分析集成到 Tableau Prep 中,我们能够从新闻文章中包含的非结构化文本数据中提取有用的信息。我们还可以做更多的事情——主题建模、文档相似性、情感检测等等。

最后的想法

Credits: Clem Onojeghuo

我们希望本指南有助于解释如何将定制 Python 脚本集成到 Tableau Prep 中,尤其是在自然语言处理领域。一旦掌握了窍门,为 API 调用、地理空间分析甚至机器学习编写定制脚本就变得非常简单了。

当这一切发生时,天空才是极限。

萧恩

阵列的线性搜索和二分搜索法指南(数据结构和算法)

原文:https://towardsdatascience.com/a-guide-to-linear-search-and-binary-search-on-arrays-data-structures-algorithms-2c23a74af28a?source=collection_archive---------17-----------------------

在上一篇文章中,我们讨论了数组和操作( LINK )。现在,我们将回顾算法选择如何影响代码的性能。特别是,我们将通过无序和有序数组来研究线性搜索和二分搜索法。

什么是算法?

我的一个经理是个数学专家,他总是喜欢明确地陈述定义,这样每个人都在同一页上。在我们的例子中,算法是解决问题的一种方式。例如,这里有一个关于如何执行谷歌搜索的粗略算法:

1.打开 web 浏览器。
2。在地址栏
3 中输入www.google.com。按回车键
4。在谷歌搜索栏中,输入想要的搜索
5。按回车键

现在有更多的步骤来更加明确和改进算法,但你得到的想法。换句话说,算法是做某事的过程。

有序数组

在上一篇文章(链接)中,我们讨论了无序数组。有序数组是数据以定向方式组织的数组(通常被视为升序)。因此,每次添加或删除一个数字时,数组都会按照需要的顺序进行重组。让我们看一个 Python 中数组的例子:

ordered_array = [1, 6, 7, 22, 100]# Let's insert the value 19
ordered_array.insert(0, 19)
ordered_array

[19, 1, 6, 7, 22, 100]

我们可以看到,增加值并没有按照正确的升序排列。为了保持数组有序,值 19 必须放在正确的位置。在 Python 中,我们可以这样对数组进行排序:

ordered_array.sort()
ordered_array

[1, 6, 7, 19, 22, 100]

这很容易,但是,在幕后,Python 做了更多的事情。如果我们从插入 19 和排列开始,第一步是检查 19 是否大于 1。如果是,则移动到下一个值。如果没有,则将值放在索引处,并将所有值向右移动。

在我们的例子中,它将逐个搜索每个值,直到达到 22。在 22 处,它会将 22 和 100 向右移动一个索引值。之后,它会将 19 放在 22 的前一个索引值上。

线性搜索

好吧,那么显示有序和无序数组的全部意义是什么?对于线性搜索这样的算法来说,性能变化很大。线性搜索逐个检查数组中的值,直到找到为止。在无序数组中,线性搜索必须检查整个数组,直到找到所需的值。但是有序数组就不同了。原因是,一旦线性搜索发现一个值大于它的期望值,那么它可以停止,并说它找到了值或没有。基本上,有序数组需要更少的步骤,无序数组使用线性搜索。Python 示例编码如下:

#Linear Search Function (modified from: [https://www.geeksforgeeks.org/linear-search/](https://www.geeksforgeeks.org/linear-search/))
def linsearch(arr, n, x): 
    for i in range (0, n): 
        if (arr[i] == x): 
            return i; 
    return -1;#Ordered Array
arr = [1, 6, 7, 19, 22, 100]; 
#Desired value
x = 19;n = len(arr); 
result = linsearch(arr, n, x)if(result == -1): 
    print("Element is not present in array") 
else: 
    print("Element is present at index", result);

元素出现在索引 3 处

二进位检索

由于我们的数据被结构化为有序数组,因此实际上有一种比线性搜索更好的方法来搜索值。你已经猜到了。更好的算法是二分搜索法!那么,它是如何工作的呢?

二分搜索法基本上是取你要找的值,然后到有序数组的中间。它现在会考虑期望值是大于还是小于中间值。如果更高,二分搜索法会到达中间点,再次询问更高或更低的价格,直到找到理想的价格。这同样适用于较低的值。

重要的是要记住,二分搜索法只能发生在有序的数组中。如果它是无序的,二分搜索法不能要求更高或更低的值来加速搜索。这个例子强调了数据结构的重要性以及正确的算法选择如何影响性能。二分搜索法的 Python 示例如下:

#Binary Search Function (modified from: [https://www.geeksforgeeks.org/binary-search/](https://www.geeksforgeeks.org/binary-search/))
def binarySearch(arr, l, r, x): 
    while l <= r: 
        mid = l + (r - l)//2; 
        if arr[mid] == x: 
            return mid 
        elif arr[mid] < x: 
            l = mid + 1
        else: 
            r = mid - 1
    return -1#Ordered Array
arr = [1, 6, 7, 19, 22, 100]; 
#Desired value
x = 19; 

result = binarySearch(arr, 0, len(arr)-1, x) 

if(result != -1): 
    print("Element is present at index % d" % result)
else: 
    print("Element is not present in array")

元素出现在索引 3 处

结论

因此,我们了解了线性搜索和二分搜索法对有序数组的性能影响。由于逐个检查数组中每个数据点的期望值,线性搜索速度较慢。相比之下,二分搜索法通过获取中间值并根据期望值升高或降低来减少搜索时间。我认为以图形方式观察这种变化会有所帮助,所以请看下图:

Graph performance of Linear Search v. Binary Search. Image taken from Techtud: https://www.techtud.com/sites/default/files/public/user_files/tud39880/linearSearch%20vs%20binary%20search%20diagram_0.jpg

基本上,在最坏的情况下,线性搜索性能会随着每个新元素的增加而提高。例如,期望值为 49,000 的 50,000 个有序数组将以从 0 一直到 49,000 为步长进行线性搜索。另一方面,二分搜索法将在大约 15 步内穿过一个又一个中间值。不要担心图中的 O 符号。这是一个很大的 O 符号,我们将在下一篇文章中讨论它!

本系列文章的第一部分可以在这里找到:

https://towards data science . com/a-guide-to-arrays-and-operations-data-structures-f 0671028 ed 71

对于那些现在想了解更多的人来说,下面是我用来撰写本文的关于这些主题的好资源:

免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。

使用 R 挖掘和分析 Tweets 的指南

原文:https://towardsdatascience.com/a-guide-to-mining-and-analysing-tweets-with-r-2f56818fdd16?source=collection_archive---------2-----------------------

撰写深刻的 Twitter 分析报告的简单步骤

Photo by Carlos Muza on Unsplash

Twitter 为我们提供了大量用户生成的语言数据——这是任何想要进行文本分析的人的梦想。更重要的是,推特让我们能够洞察在线公共行为。因此,分析 Twitter 已经成为品牌和代理商的重要信息来源。

几个因素让 Twitter 在分析方面比其他社交媒体平台有相当大的优势。首先,推特有限的字符大小为我们提供了一个相对同质的语料库。其次,每天发布的数百万条推文允许访问大量数据样本。第三,tweets 是公开的,容易访问,也可以通过 API 检索。

尽管如此,提取这些见解仍然需要一些编码和编程知识。这就是为什么大多数情况下,品牌和机构依赖于易于使用的分析工具,如 SproutSocial 和 Talkwalker,这些工具只需点击一下即可提供这些见解。

在这篇文章中,我帮助你打破这些障碍,并为你提供一个简单的指南,告诉你如何用编程软件 r 提取和分析推文。

以下是你可能选择这样做的 3 个原因:

  • 使用 R 是免费的,也就是说,你将能够免费制作一份 Twitter 分析报告,同时学习如何编码!
  • R 给你无限的分析机会。因此,用它来分析 Twitter,可以让你根据你想要分析的内容进行量身定制的分析,而不是依赖一份一刀切的报告
  • R 允许你分析任何你想要的 Twitter 账户,即使你没有登录信息。与许多分析工具相比,这是一个巨大的优势,许多分析工具要求您首先拥有登录详细信息以便分析信息。

深信不疑?那我们开始吧!

步骤 1:获取 Twitter API 访问权限

为了开始,您首先需要获得一个 Twitter API。这将允许你检索推文——没有它,你不能做任何事情。获得一个 Twitter API 很容易。首先确保你有一个 Twitter 账户,否则就创建一个。然后,通过以下网站申请开发者帐号:https://developer.twitter.com/en/apply-for-access.html。你需要填写一份申请表,包括对你希望分析的内容做更多的解释。

一旦你的申请被 Twitter 接受(这不会花太长时间),你将收到以下凭证,你需要保持安全:

  • 消费者密钥
  • 消费者秘密
  • 访问令牌
  • 访问密码

第二步:挖掘推文

一旦有了上面的信息,启动 R 并下载“rtweet”包,我将用它来提取 tweets。

install.packages("rtweet")
library (rtweet)

然后,设置连接 Twitter 的身份验证。你可以通过输入你的应用名称、消费者密钥和消费者秘密来做到这一点——所有这些都是你在申请 Twitter API 时收到的信息。您将被重定向到一个 Twitter 页面,并被要求接受认证。一旦完成,你就可以返回 R,开始分析你的推文了!

twitter_token <- create_token(
  app = ****,
  consumer_key = ****,
  consumer_secret = ****,
  set_renv = TRUE)

搜索推文

根据您希望执行的分析,您可能希望搜索包含特定单词或标签的推文。请注意,您只能提取过去 6 到 9 天的推文,因此在分析时请记住这一点。

要做到这一点,只需使用 search_tweets 函数,后跟一些规范:要提取的 tweets 的数量(n),是否包括转发和 tweets 的语言。作为示例,请参见下面的代码行。

climate <- search_tweets(“climate”, n=1000, include_rts=FALSE, lang=”en”)

搜索特定的用户帐户

或者,您可能希望分析特定的用户帐户。在这种情况下,使用 get_timeline 函数,后跟 twitter 句柄和您希望提取的 tweets 数量。注意,这里只能提取最后 3200 条推文。

在这个例子中,我选择了提取比尔·盖茨的推文。这里的优势是比尔·盖茨的账户总共有 3169 条推文,低于 3200 条的门槛。

Gates <- get_timeline("@BillGates", n= 3200)

第三步:分析推文

在这一部分,我向你展示了你应该包含在每一份 Twitter 分析报告中的 8 个关键观点。为此,让我们更深入地研究一下比尔·盖茨的 Twitter 账户吧!

1.显示什么效果最好,什么效果不好

任何报告的第一部分都应该提供清晰的信息,说明什么效果最好,什么效果不好。找出表现最好和最差的推文可以快速清晰地了解账户的整体情况。

为了做到这一点,你首先需要区分有机推文、转发和回复。下面一行代码向您展示了如何从您的样本中删除转发和回复,只保留有机的推文——就内容而言,这些是您想要分析的推文!

# Remove retweets
Gates_tweets_organic <- Gates_tweets[Gates_tweets$is_retweet==FALSE, ] # Remove replies
Gates_tweets_organic <- subset(Gates_tweets_organic, is.na(Gates_tweets_organic$reply_to_status_id)) 

然后,你需要通过查看变量来分析参与度: favorite_count (即喜欢的数量)或 retweet_count (即转发的数量)。只需将它们按降序排列(变量前有一个减号“-”)即可找到点赞或转发数量最多的一个,或按升序排列(没有减号)即可找到参与次数最少的一个。

Gates_tweets_organic <- Gates_tweets_organic %>% arrange(-favorite_count)
Gates_tweets_organic[1,5]Gates_tweets_organic <- Gates_tweets_organic %>% arrange(-retweet_count)
Gates_tweets_organic[1,5]

2.显示回复/转发/有机推文的比率

分析回复、转发和有机推文的比例可以告诉你很多你正在分析的账户类型。例如,没有人喜欢一个专门转发的 Twitter 账户,没有任何个人内容。因此,如果一个人希望提高他或她的账户的性能,找到回复、转发和有机推文的良好比例是一个关键的监控指标。

作为第一步,确保创建三个不同的数据集。由于您已经在前面的步骤中创建了一个仅包含有机推文的数据集,现在只需创建一个仅包含转发的数据集和一个仅包含回复的数据集。

# Keeping only the retweets
Gates_retweets <- Gates_tweets[Gates_tweets$is_retweet==TRUE,]# Keeping only the replies
Gates_replies <- subset(Gates_tweets, !is.na(Gates_tweets$reply_to_status_id))

然后,创建一个单独的数据框,包含有机推文、转发和回复的数量。这些数字很容易找到:它们是你的三个数据集的观测值。

# Creating a data frame
data <- data.frame(
  category=c("Organic", "Retweets", "Replies"),
  count=c(2856, 192, 120)
)

完成后,您可以开始为圆环图准备数据框,如下所示。这包括添加计算比率和百分比的列,以及一些可视化调整,如指定图例和舍入数据。

# Adding columns 
data$fraction = data$count / sum(data$count)
data$percentage = data$count / sum(data$count) * 100
data$ymax = cumsum(data$fraction)
data$ymin = c(0, head(data$ymax, n=-1))# Rounding the data to two decimal points
data <- round_df(data, 2)# Specify what the legend should say
Type_of_Tweet <- paste(data$category, data$percentage, "%")ggplot(data, aes(ymax=ymax, ymin=ymin, xmax=4, xmin=3, fill=Type_of_Tweet)) +
  geom_rect() +
  coord_polar(theta="y") + 
  xlim(c(2, 4)) +
  theme_void() +
  theme(legend.position = "right")

3.显示推文发布的时间

多亏了从每条推文中提取的日期和时间,了解比尔·盖茨最常发推文的时间非常容易分析。这可以让我们对账户的活动有一个总体的了解,也是一个有用的指标,可以用来分析表现最好和最差的推文。

在这个例子中,我按年份分析了推文的频率。请注意,您也可以通过简单地将下面一行代码中的“year”改为“month”来按月执行此操作。或者,您也可以使用 R 包 hms 和 scales 按小时分析发布行为。

colnames(Gates_tweets)[colnames(Gates_tweets)=="screen_name"] <- "Twitter_Account"ts_plot(dplyr::group_by(Gates_tweets, Twitter_Account), "year") +
  ggplot2::theme_minimal() +
  ggplot2::theme(plot.title = ggplot2::element_text(face = "bold")) +
  ggplot2::labs(
    x = NULL, y = NULL,
    title = "Frequency of Tweets from Bill Gates",
    subtitle = "Tweet counts aggregated by year",
    caption = "\nSource: Data collected from Twitter's REST API via rtweet"
  )

4.显示推文发布的位置

分析发布推文的平台的来源是另一个很酷的洞察。其中一个原因是,我们可以在一定程度上推断出比尔·盖茨是不是发微博的人。因此,这有助于我们定义推文的个性。

在这一步中,您对 rtweet 包收集的源变量感兴趣。下面一行代码向您展示了如何按来源类型聚合这些数据,并分别统计每种类型的 tweets 的频率。请注意,为了简化可视化过程,我只保留了发表了超过 11 条推文的来源。

Gates_app <- Gates_tweets %>% 
  select(source) %>% 
  group_by(source) %>%
  summarize(count=n())Gates_app <- subset(Gates_app, count > 11)

一旦完成,这个过程类似于之前已经创建的圆环图!

data <- data.frame(
  category=Gates_app$source,
  count=Gates_app$count
)data$fraction = data$count / sum(data$count)
data$percentage = data$count / sum(data$count) * 100
data$ymax = cumsum(data$fraction)
data$ymin = c(0, head(data$ymax, n=-1))data <- round_df(data, 2)Source <- paste(data$category, data$percentage, "%")ggplot(data, aes(ymax=ymax, ymin=ymin, xmax=4, xmin=3, fill=Source)) +
  geom_rect() +
  coord_polar(theta="y") + # Try to remove that to understand how the chart is built initially
  xlim(c(2, 4)) +
  theme_void() +
  theme(legend.position = "right")

请注意,比尔·盖茨的大多数推文来自 Twitter 网络客户端 Sprinklr 和 Hootsuite——这表明比尔·盖茨很可能不是自己发推文的人!

5.显示在推文中找到的最常用的词

Twitter 分析报告当然应该包括对推文内容的分析,这包括找出哪些词用得最多。

因为您正在分析文本数据,所以请确保首先清理它,并从您不想在分析中显示的任何字符(如超链接、@提及或标点符号)中删除它。下面几行代码为你提供了清理 tweets 的基本步骤。

Gates_tweets_organic$text <-  gsub("https\\S*", "", Gates_tweets_organic$text)Gates_tweets_organic$text <-  gsub("@\\S*", "", Gates_tweets_organic$text) Gates_tweets_organic$text  <-  gsub("amp", "", Gates_tweets_organic$text) Gates_tweets_organic$text  <-  gsub("[\r\n]", "", Gates_tweets_organic$text)Gates_tweets_organic$text  <-  gsub("[[:punct:]]", "", Gates_tweets_organic$text)

第二步,确保从文本中删除停用词。这对于您分析最常用的单词非常重要,因为您不希望出现最常用的单词,如“to”或“and ”,因为这些单词对您的分析没有太大意义。

tweets <- Gates_tweets_organic %>%
  select(text) %>%
  unnest_tokens(word, text)tweets <- tweets %>%
  anti_join(stop_words)

然后,您可以按照下面的简单步骤,标出推文中出现频率最高的单词。

tweets %>% # gives you a bar chart of the most frequent words found in the tweets
  count(word, sort = TRUE) %>%
  top_n(15) %>%
  mutate(word = reorder(word, n)) %>%
  ggplot(aes(x = word, y = n)) +
  geom_col() +
  xlab(NULL) +
  coord_flip() +
  labs(y = "Count",
       x = "Unique words",
       title = "Most frequent words found in the tweets of Bill Gates",
       subtitle = "Stop words removed from the list")

6.显示最常用的标签

你可以对标签做同样的分析。在这种情况下,您需要使用 rtweet 包中的 hashtags 变量。形象化这些的一个好方法是使用如下所示的单词云。

Gates_tweets_organic$hashtags <- as.character(Gates_tweets_organic$hashtags)
Gates_tweets_organic$hashtags <- gsub("c\\(", "", Gates_tweets_organic$hashtags)set.seed(1234)
wordcloud(Gates_tweets_organic$hashtags, min.freq=5, scale=c(3.5, .5), random.order=FALSE, rot.per=0.35, 
          colors=brewer.pal(8, "Dark2"))

7.显示转发次数最多的账户

从一个账户大量转发通常不是人们在 Twitter 账户中寻找的。因此,一个有用的见解是监控和了解大多数转发来自哪个账户。这里您要分析的变量是 retweet_screen_name ,可视化的过程类似于之前使用单词云描述的过程。

set.seed(1234)
wordcloud(Gates_retweets$retweet_screen_name, min.freq=3, scale=c(2, .5), random.order=FALSE, rot.per=0.25, 
          colors=brewer.pal(8, "Dark2"))

8.对推文进行情感分析

最后,你可能想在 Twitter 分析报告的末尾添加一个情感分析。使用“syuzhet”软件包很容易做到这一点,并允许您通过把握推文的语气来进一步深化您的分析。没有人喜欢一个只会传播愤怒或悲伤推文的推特账号。捕捉你的推文的语气以及它们是如何平衡的,是你的账户表现的一个很好的指标。

library(syuzhet)# Converting tweets to ASCII to trackle strange characters
tweets <- iconv(tweets, from="UTF-8", to="ASCII", sub="")# removing retweets, in case needed 
tweets <-gsub("(RT|via)((?:\\b\\w*@\\w+)+)","",tweets)# removing mentions, in case needed
tweets <-gsub("@\\w+","",tweets)ew_sentiment<-get_nrc_sentiment((tweets))
sentimentscores<-data.frame(colSums(ew_sentiment[,]))names(sentimentscores) <- "Score"sentimentscores <- cbind("sentiment"=rownames(sentimentscores),sentimentscores)rownames(sentimentscores) <- NULLggplot(data=sentimentscores,aes(x=sentiment,y=Score))+
  geom_bar(aes(fill=sentiment),stat = "identity")+
  theme(legend.position="none")+
  xlab("Sentiments")+ylab("Scores")+
  ggtitle("Total sentiment based on scores")+
  theme_minimal()

总结

在这篇文章中,我旨在展示如何使用免费的编程软件 r 提取和分析推文。我希望这个指南有助于您构建自己的 Twitter 分析报告,其中包括:

  • 显示哪些推文效果最好,哪些效果不好
  • 有机推文/回复/转发的比率,推文发布的时间和发布推文的平台。这些都是关于推特行为的见解。
  • 推文中使用最频繁的词,标签,转发最多的账户,以及捕捉推文语气的情感分析。这些都是对推文内容的见解。

[## 挖掘 2018 年中期选举前后美国候选人关于大规模枪击事件的推文

与卡洛斯·阿胡马达合作撰写的文章

medium.com](https://medium.com/data-social/mining-tweets-of-us-candidates-on-mass-shootings-before-and-after-the-2018-midterms-90cc18ff652a)

我定期撰写关于数据科学和自然语言处理的文章。关注我的 Twitter Medium查看更多类似的文章或简单地更新下一篇文章!

Unicode、UTF-8 和 Python 中的字符串指南

原文:https://towardsdatascience.com/a-guide-to-unicode-utf-8-and-strings-in-python-757a232db95c?source=collection_archive---------3-----------------------

让我们来看看弦乐的基本概念,这将使你的理解更上一层楼。

字符串是 Python 中最常见的数据类型之一。它们用于处理任何类型的文本数据。自然语言处理领域是建立在某种文本和字符串处理之上的。了解 Python 中字符串的工作方式很重要。当字符串由英语 ASCII 字符组成时,通常很容易处理,但是当我们输入非 ASCII 字符时,就会出现“问题”——这在当今世界越来越普遍。随着表情符号等的出现。

Let’s decipher what is hidden in the strings

许多程序员将encodedecode与字符串一起使用,希望消除令人恐惧的UnicodeDecodeError——希望这篇博客能帮助你克服对处理字符串的恐惧。下面我会用一个 Q 和一个格式来真正得到你可能会有的问题的答案,在我开始学习字符串之前我也有。

1.绳子是由什么制成的?

在 Python (2 或 3)中,字符串既可以用字节表示,也可以用 unicode 码位表示。
字节是由 8 位构成的信息单位,字节用于存储硬盘中的所有文件。所以你计算机上所有的 CSV 和 JSON 文件都是由字节组成的。我们都同意我们需要字节,但那么 unicode 码位呢?我们将在下一个问题中讨论它们。

2.什么是 unicode 和 Unicode 码位?

当从文件中读取字节时,读者需要知道这些字节意味着什么。因此,如果你写一个 JSON 文件并发送给你的朋友,你的朋友需要知道如何处理你的 JSON 文件中的字节。对于最初 20 年左右的计算,大写和小写的英文字符,一些标点符号和数字就足够了。这些都被编码成一个名为 ASCII 的 127 符号列表。7 位信息或 1 字节足以对每个英文字符进行编码。你可以告诉你的朋友用 ASCII 编码解码你的 JSON 文件,瞧——她就能读懂你发给她的东西了。

这在最初的几十年里很酷,但是慢慢地我们意识到有更多的字符而不仅仅是英文字符。我们尝试将 127 个字符扩展到 256 个字符(通过 Latin-1 或ISO-8859–1)以充分利用 8 位空间——但这还不够。我们需要一个大家都同意的国际标准来处理成百上千的非英语字符。

Unicode 出现了!

Unicode 是国际标准,其中维护了单个字符和唯一数字的映射。截至 2019 年 5 月,Unicode 的最新版本是 12.1,包含超过 137k 个字符,包括英语、印地语、中文和日语等不同的脚本,以及表情符号。这 137k 个字符每个都由一个 unicode 码位表示。所以 unicode 码位指的是显示的实际字符。
这些码点被编码成字节,再从字节解码回码点。例如:字母表a的 Unicode 码位是 U+0061,表情符号🖐是 U+1F590,ω是 U+03A9。

3 Unicode 定义的最流行的编码标准是 UTF-8、UTF-16 和 UTF-32。

3.什么是 Unicode 编码 UTF-8、UTF-16 和 UTF-32?

我们现在知道 Unicode 是一种国际标准,它将每个已知的字符编码成一个唯一的数字。那么下一个问题是,我们如何在互联网上移动这些唯一的号码?你已经知道答案了!使用字节的信息。

UTF-8: 使用 1、2、3 或 4 字节对每个码点进行编码。它向后兼容 ASCII。所有的英文字符只需要 1 个字节——效率相当高。如果我们发送非英语字符,我们只需要更多的字节。
这是最流行的编码形式,也是 Python 3 中默认的编码方式。在 Python 2 中,默认编码是 ASCII(不幸的是)。

UTF-16 是变量的 2 或 4 个字节。这种编码方式非常适合亚洲文字,因为大多数亚洲文字都可以用 2 个字节进行编码。这对英语不好,因为所有的英语字符在这里也需要 2 个字节。

UTF-32 是固定的 4 字节。所有的字符都用 4 个字节编码,所以需要很大的内存。它不经常使用。
【你可以在这篇 StackOverflow 帖子里读到更多。]

我们需要encode方法将 unicode 码位转换成字节。例如,这通常发生在将字符串数据写入 CSV 或 JSON 文件的过程中。
我们需要decode方法将字节转换成 unicode 码位。这通常发生在将数据从文件读入字符串的过程中。

Why are encode and decode methods needed?

4.Python 中有哪些数据类型处理 Unicode 码位和字节?

正如我们前面讨论的,在 Python 中,字符串可以用字节或 unicode 码位表示。
Python 中主要的外卖有:
1。Python 2 使用**str**类型存储字节,使用**unicode**类型存储 unicode 码位。默认情况下,所有字符串都是str类型——字节~默认编码是 ASCII。因此,如果传入的文件是西里尔字符,Python 2 可能会失败,因为 ASCII 将无法处理这些西里尔字符。在这种情况下,我们需要记住在读取文件时使用decode("utf-8")。这不方便。
2。Python 3 来了,解决了这个问题。默认情况下,字符串仍然是**str**类型,但是它们现在意味着 unicode 码位——我们携带我们看到的东西。如果我们想在文件中存储这些str类型的字符串,我们使用**bytes**类型。默认编码是 UTF-8,而不是 ASCII。完美!

5.有没有比较不同数据类型的代码示例?

Yes, let’s look at “你好” which is Chinese for hello. It takes 6 bytes to store this string made of 2 unicode code points. Let’s take the example of popularlen function to see how things might differ in Python 2 and 3 — and things you need to keep note of.

>>> print(len(“你好”))   # Python 2 - str is bytes
6>>> print(len(u“你好”))  # Python 2 - Add 'u' for unicode code points
2>>> print(len(“你好”))   # Python 3 - str is unicode code points
2

因此,在 Python 2 中添加前缀u会对代码是否正常运行产生完全不同的影响——这可能会令人困惑!Python 3 通过默认使用 unicode 码位解决了这个问题——所以在上面的例子中,如果长度为 2,那么len将会像您所期望的那样工作。

让我们看看 Python 3 中处理字符串的更多例子:

# strings is by default made of unicode code points
>>> print(len(“你好”)) 
2# Manually encode a string into bytes
>>> print(len(("你好").encode("utf-8")))  
6# You don't need to pass an argument as default encoding is "utf-8"
>>> print(len(("你好").encode()))  
6# Print actual unicode code points instead of characters [[Source](https://stackoverflow.com/questions/7291120/get-unicode-code-point-of-a-character-using-python)]
>>> print(("你好").encode("unicode_escape"))
b'\\u4f60\\u597d'# Print bytes encoded in UTF-8 for this string
>>> print(("你好").encode()) 
b'\xe4\xbd\xa0\xe5\xa5\xbd'

6.信息量很大啊!你能总结一下吗?

当然可以!让我们直观地看看我们到目前为止所学的内容。
在 Python 3 中,默认情况下,我们位于字符串 Unicode 码位世界的左侧。我们只需要在写入或读取数据时来回移动字节。此转换过程中的默认编码是 UTF-8,但也可以使用其他编码。我们需要知道在解码过程中使用了什么编码器,否则我们可能会得到错误或得到乱码!

Visual diagram of how encoding and decoding works for strings

这个图对 Python 2 和 Python 3 都适用!我们可能会得到UnicodeDecodeErrors,因为:
1)我们试图使用 ASCII 编码非 ASCII 字符。这种情况会发生。在 Python 2 中,默认编码器是 ASCII。因此,您应该使用 UTF-8 显式编码和解码字节。我们可能完全用错了解码器。如果 unicode 码位是用 UTF-16 而不是 UTF-8 编码的,你可能会遇到在 UTF-8 土地上乱码的字节。所以 UTF-8 解码器可能完全无法理解这些字节。

一个好的做法是,一旦从文件中加载了字节,就用 UTF-8(或用于创建这些字节的编码器)对它们进行解码。通过 Python 代码对 unicode 码位进行处理,然后使用 UTF-8 编码器将字节写回到文件中。这叫做 Unicode 三明治。阅读/观看内德·巴奇尔德(@ 内德巴特)关于这个问题的精彩演讲。

如果你想在 Python 中添加更多关于字符串的信息,请在下面的评论中提及,因为这将有助于他人。我关于 Unicode、UTF-8 和字符串指南的博客到此结束。祝你在自己的文本探索中好运!

PS,看看我的新播客!它叫做“数据生活播客”,我在这里谈论类似的话题。在最近的一集里,我谈到了为什么熊猫是新的 Excel。你可以在这里或任何你听播客的地方听播客。

My podcast: The Data Life Podcast

如果您有任何问题,请在我的 LinkedIn 个人资料中给我留言。感谢阅读!

从高中的角度介绍深度学习

原文:https://towardsdatascience.com/a-hands-on-introduction-to-deep-learning-from-a-high-school-perspective-41be62ef00a7?source=collection_archive---------9-----------------------

Image Courtesy of Xkcd ( https://xkcd.com/1838/)

他的一系列博客文章致力于为寻求学习深度学习的高中生提供直接而简单的深度学习解释。

主要的 DL 概念将在本系列中以一种互动的、实际操作的方式进行解释,引导读者完成构建一个简单的 DL 模型并对其进行训练和评估的过程。

我在互联网上获取数字图书馆资料的经验是,它仍然主要面向那些寻求转向数字图书馆的人,或者关注那些寻求从事数字图书馆的大学生。当我开始学习 DL 的时候,大部分信息都需要对数学和微积分概念有一个很好的、直观的理解。虽然获得这些知识是我从学习 DL 的旅程中获得的许多好处之一,但该过程的最初步骤导致对梯度下降和激活函数的目的等概念的理解非常肤浅。总的来说,我缺乏对概念的数学直觉,这导致了混乱和误解。这种数学直觉在网上的大部分资料中通常被忽略,因为类似领域的大学生和大学毕业生都有广泛的数学背景。

本系列旨在以一种典型的对数学和数字逻辑感兴趣的高中生能够理解的方式提供数字逻辑概念的直观联系。

本系列将遵循构建、训练和评估亚马逊评论情感分析模型的过程。情感分析是根据语句含义中的情感对语句进行分类。例如,有人说“天气晴朗”背后的一般情绪是积极的,而如果有人说“天气多云,正在下雨”,他们可能感到消极。这是情感分析的基础,这个概念将被应用于对 polar IMDB 电影评论进行正面或负面分类。

这第一篇文章将使读者了解深度学习的最新基础知识,并将教给读者完全理解该主题所需的核心概念。

背景

M 机器学习(ML)是一种算法,利用数据来学习模式,得出有意义的结果,并从多个应用中进行预测。深度学习(DL)和神经网络是更有效地实现 ML 目标的专门技术。

在过去的几年中,ML 领域,尤其是 DL 领域发展迅速。多年来,传统的企业数据量已经从大约 10,000–100,000 增长到 1,000,000–1,000,000,000。

这引发了一个研究人员从未遇到过的独特问题;计算能力对训练模型的限制。为了创建更深层次的神经网络,他们需要一种当时无法提供的计算能力。这就是 ML 领域停滞多年的原因。

然后,计算能力的提高允许研究人员实现更深、更高维的神经网络。新的技术进步带来了图形处理单元(GPU),这是深度学习所需的高维矩阵乘法的最有效的硬件之一。同样,唯一的限制是模型的算法和架构,而我们可以不断地收集更多的数据来提高准确性。

现在,DL 领域已经分裂成多个主要组:计算机视觉(CV)、音频理解和自然语言处理(NLP)等等。本教程将集中在一个“Hello World”类型的 NLP 介绍性问题,但也将包括一些计算机视觉技术。

有几个主要行业 NLP 可以完全重新设计。这些是客户服务,虚拟助理,信息检索。

  • 在客户协助方面,聊天机器人可以简化客户服务,处理简单的任务和问题,并将复杂的查询留给人类。在未来,DL 模型可以分析电话,并通过情感分析对客户满意度进行评级。
  • 虚拟助手使用自然语言理解技术从你的语音中提取命令。正是这些技术让 Alexa、Siri 和 Google Assistant 等虚拟助手能够交流并理解我们的语言。
  • 信息检索通过使用情感分析和抽象概括从非结构化文本中提取有价值信息。

计算机视觉可以重新设计的一些领域是自动驾驶和安全。

  • CV 是自动驾驶背后的主要力量之一,它存在于越来越受欢迎的特斯拉汽车中。它允许计算机识别街道地标,如车道线、交通信号和街道上的其他物体,如汽车和行人
  • 安全性也会受到 CV 的严重影响。公司可以使用 CV 代替员工监控摄像头的威胁,这既增加了发现威胁的可能性,又降低了误报的几率。

基础知识

Image Courtesy of MPLS VPN (http://www.mplsvpn.info/2017/11/what-is-neuron-and-artificial-neuron-in.html)

深度学习以人类神经元为模型,其中神经元具有从其他神经元获取信息的树突,进行计算的轴突,以及向其他神经元发送信号的轴突终端。在人工神经元中,输入与树突同义,激活功能与轴突同义,输出类似于轴突终末。

深度学习的一个简单应用就是从数据中画出边界和洞察。

Courtesy of StackoverFlow

在上面的例子中,假设 x 轴是房子里卧室的数量,y 轴是房子里浴室的数量。红点代表公寓,绿点代表单户住宅,蓝点代表豪宅。DL 中的一个常见任务是根据卧室和浴室的数量将房子分类为公寓、单户住宅或豪宅。这是通过学习一个函数来完成的,该函数在 3 个不同的类周围画出一个大致的边界。

对于一个人来说,仅仅通过查看图就可以相对容易地用手画出这些边界。可以绘制的边界示例如下:

虽然当只有两个参数时,我们人类很容易做出这些界限,但随着参数数量的增加,这变得越来越具有挑战性。例如,如果给定房子的四个或五个不同的方面,在我们的头脑中想象这些数据几乎是不可能的。这是深度学习的主要应用。对于一台计算机来说,学习边界对于具有 10 个甚至 100 个不同特征的问题来说是非常初级的。

如果一个房子突然出现 1.5 个卫生间和 3 个卧室,我们可以根据上面的数据来概括我们的边界并预测它很可能是一个单独的家庭住宅。就像这样,深度学习模型可以很容易地针对许多数据点进行归纳,这意味着它不需要针对每个数据点和案例场景进行专门编程,并且可以使用之前从数据中获得的洞察力来决定做出什么决定。

让我们看看这到底是怎么做到的:

Image Courtesy of Jeffries (https://hackernoon.com/@dan.jeffries)

上面的图像是一个人造物体内部到底发生了什么的图像。一个人工神经元基本上是线性模型,形式是 y = Wx + B,或者 y = mx + b,应该看起来比较熟悉。w 和 B 是神经元的参数,可以改变以适应数据。最后,其中一个激活函数将被应用于 y,产生单个神经元的输出。

Image Courtesy of Sbongo (https://www.kaggle.com/sbongo/)

就像大脑是由数万亿个这样的神经元组成一样,神经网络(NNs)也是由许多相互连接的神经元组成的。

全连接层是最基本的架构,由数百个相互连接的人工神经元组成。这种架构有两个属性:深度和隐藏层大小。深度是模型中的总层数,而隐藏层大小是每层中神经元的数量。

这种架构的缺点是,随着输入图层的维度变得越来越大,例如当输入高分辨率图像的数百万个像素值时,完全连接的图层或密集图层不再起作用。

这就引出了下一个基础架构,称为卷积。

Image Courtesy of Tamang (https://medium.com/@apiltamang)

卷积神经网络是基于位置的架构,最初设计用于读取和解释图像像素。他们的工作原理是使用滑动滤波器,将滤波器中的所有值乘以一个权重并添加一个偏差,然后对总和应用一个激活函数。然后将从该操作中获得的所有值相加。当过滤器以一定的步幅穿过图像时,这继续进行。

ConvNet 的好处是它可以学习识别图像中的特征,从垂直和水平边缘一直到大型物体和动物。这使得 ConvNets 在 DL 的计算机视觉领域取得了巨大成功,并用于特斯拉的自动驾驶系统,以检测汽车、行人和道路特征,如车道线、标志和交通信号。

Image Courtesy of Computer Science Wiki (https://computersciencewiki.org/index.php/Max-pooling_/_Pooling)

一种重要的卷积类型是最大池,它只是从一个区域中获取最大像素值,并丢弃所有其他像素。提取并移动过滤器尺寸中的最大值,同时移除所有其他值。通常,最大池的过滤器大小为 2x2,跨距为 2,但也可以使用其他大小和跨距。max pooling 背后的直觉是,它减少了查看的像素数量,同时保留了图像最重要的特征。

Image Courtesy of Colah (https://colah.github.io)

递归神经网络(RNNs)主要用于语言或任何对其序列有长期依赖性的东西,如语音记录或音频文件。这些网络将输入分割成时间步长,每个时间步长的计算结果都被输入到下一个时间步长,从而赋予模型记忆输入的能力。这种网络是专门为语言设计的,因为当时的主要架构是无效的。时间步长的计算也不同于传统的人工神经元。RNN 建筑师实现了忘记和保留门,这为模型提供了一种以加权的方式记忆信息的方法,类似于人类记住他们生活中的重要部分并丢弃平凡的事情。这些系统被称为长短期记忆单元或 LSTMs。

这些是 DL 模型最常见的架构,可以相互结合使用,为复杂的任务创建更复杂的网络。

接下来我要解释的是一些最流行的激活函数以及为什么使用它们。您应该记得,DL 模型中的每个神经元计算输入和偏置的加权和,然后对输出应用激活函数以增加非线性。

双曲正切函数非常类似于 sigmoid 函数,而 sigmoid 函数的范围是 0 到 1,双曲正切函数的范围是-1 到 1。tanh 和 sigmoid 都可以表示门,这就是为什么这两个函数在 LSTMs 中非常流行的原因(见下图)。LSTMs 通常在其遗忘和保留门中使用 tanh 函数,因为它压缩-1 和 1 之间的值,这些值直观地对应于关闭和打开门。

sigmoid 函数是一个历史上非常流行的函数,当时模型和数据集都很小。在现代,它已经失去了一些流行,由于问题出现时,这个功能是复合在自己身上。最大的问题是由于这样一个事实,即随着数量的增加,这个函数的斜率变得无限小,停止了模型的优化。称为消失梯度问题,它导致了这个函数的轻微下降。

ReLU,或整流线性单元,是深度学习社区中使用的非常流行的激活函数(类似于大脑神经元思维)。它的流行是因为线性模型非常擅长概括数据。由于 ReLU 函数非常类似于线性函数,因此它保留了泛化的优点,同时仍将非线性引入模型。ReLU 函数简单来说就是 y=max(0,x)。

现在,您已经了解了创建自己的 DL 模型所需的所有基础知识。学习 DL 的下一步是理解它是如何从数据集学习的。

训练和损失函数

机器通过损失函数来学习。这是一种评估特定算法对给定数据建模程度的方法。如果预测与实际结果相差太多,损失函数就会产生一个非常大的数字。逐渐地,在一些优化函数的帮助下,损失函数学习减少预测中的误差。

DL 中使用的损失函数有很多种,每种都有自己的优缺点。DL 中最常见的两个损失函数是回归的损失函数(均方误差(MSE ))和分类问题的损失函数(交叉熵)。

MSE 损失是预测值和实际观测值的平方差的平均值。这种损失的一些优点是,高度不正确的预测受到很大的惩罚,并且更容易计算用于优化的损失函数的斜率。

使用的另一个损失是交叉熵:

交叉熵损失是分类问题中最常用的损失,因为它简单而有效。当实际标签为 1 时,函数的后半部分消失,而在实际标签为 0 的情况下,前半部分消失。为什么这种损失会起作用,一种直觉是注意到当预测和实际数据点都是 1 或 0 时,损失中的一项抵消,输出为 0。如果预测和数据点分别为 1 和 0,则损失最大。一个重要的方面是交叉熵损失会严重惩罚那些有把握但却是错误的预测。

训练深度学习模型的过程类似于调整模型中的每个参数,以便它们尽可能准确地拟合数据。一个简单的例子是改变公式 y=Wx + b 中的参数 W 和 b,以找到散点图上数据的最佳拟合线。

Image Courtesy of Stackoverflow ( https://stackoverflow.com/questions/19068862/how-to-overplot-a-line-on-a-scatter-plot-in-python)

实际上,有数学方法可以求解最符合数据的最佳参数 W 和 b,但在 DL 中这是不可能的,因为参数数量巨大。这可以通过查看关于上述数据的参数 W 和 b 的损失函数的曲线图以及 DL 模型的损失函数的曲线图来可视化。

Graph for the Linear Function’s Loss

Graph for the loss of a DL model

当损耗最小时,可以很容易地求解上图中的参数 W 和 b,但是对于 DL 模型,这是不可能的。因此,采用迭代方法来训练 DL 模型。

优化算法通过获取斜率或函数在给定点的梯度来实现这一点,然后从参数中减去斜率,以将该点向下移动到希望的最小值。

简单地说,调整 DL 模型的参数,直到它们输出正确的预测,之后这些参数被锁定在适当的位置以供使用。

该步骤的数学表示如下:

这里,θ是参数,表达式中的第二项可以看作损失函数相对于参数θ的斜率。alpha 符号表示该步骤的学习速率,并控制算法进行的步长。这一点很重要,因为如果步长太小,算法将运行非常慢,但如果步长太大,算法将快速波动。

估价

一旦训练了 DL 模型,就需要对它进行评估,以查看它在数据上的表现如何。衡量一个 DL 模型做得有多好的方法叫做度量,有许多不同的类型。

要使用的最简单的度量标准就是模型正确分类的示例占示例总数的百分比。这是模型的准确性,用于对模型的表现有一个浅显的、全面的了解。更复杂的指标将在本系列的第 2 部分中解释,我将一步一步地创建一个情感分析模型。

感谢您阅读这篇博文!在本系列的下一部分,我将一步一步地使用 Tensorflow 2.0 创建一个情感分析模型。我希望这篇文章已经成功地教会了你深度学习的基础。

自动编码器高级指南

原文:https://towardsdatascience.com/a-high-level-guide-to-autoencoders-b103ccd45924?source=collection_archive---------10-----------------------

一个自动编码器工具箱,从最基本的到最花哨的。

在机器学习和人工智能的奇妙世界中,存在一种称为自动编码器的结构。自动编码器是一种神经网络,它是无监督学习(或者对某些人来说,半无监督学习)的一部分。有许多不同类型的自动编码器用于许多目的,有些是生成式的,有些是预测式的,等等。本文将为您提供一个工具箱和不同类型的自动编码器指南。

传统自动编码器(AE)

The basic autoencoder

自动编码器的基本类型如上图所示。它由输入层(第一层)、隐藏层(黄色层)和输出层(最后一层)组成。网络的目标是输出层与输入层完全相同。隐藏图层用于特征提取或识别决定结果的特征。从第一层到隐藏层的过程称为编码。从隐藏层到输出层的过程称为解码。编码和解码的过程是自动编码器的特别之处。黄色层有时被称为瓶颈隐藏层。

从这里,有一堆不同类型的自动编码器。

问题:隐藏图层过多

我们首先要看的是解决过度完整的隐藏层问题。

Overcomplete Hidden Layers

需要注意的重要部分是,隐藏层比输入/输出层多。如果他们的数据中有比平常更多的特征,他们将需要这个。这样做的主要问题是输入可以不加任何改变地通过;就不会有任何真正的特征的提取。看看下面的例子:

Grey nodes are not used; the blue nodes are not at all altered.

输入层和输出层之间没有发生真正的变化;他们只是保持不变。此外,两个隐藏层节点根本没有被使用。为了避免这种情况,至少有三种方法:

解决方案 A:稀疏自动编码器

Sparse Autoencoders

简而言之,稀疏自动编码器能够“淘汰”隐藏层中的一些神经元,迫使自动编码器使用它们所有的神经元。它不再仅仅通过某些节点来记忆输入,因为在每次运行中,这些节点可能不是活动的。

解决方案 B:降噪自动编码器(DAE)

Some of the inputs are turned into 0.

我们改变了稀疏自动编码器中的隐藏层。另一种选择是改变输入。在去噪自动编码器中,一些输入被(随机地)归零。一旦它被馈通,输出就与原始(非零)输入进行比较。这与稀疏自动编码器的目的相似,但是这一次,清零的编码器位于不同的位置。

解决方案 C:收缩式自动编码器(CAE)

The darkened circles represent a slightly modified output.

我们改变了输入层,隐藏层,现在我们将改变输出层。自动编码器通过一种叫做反向传播的方法进行训练;在收缩式自动编码器中执行这种算法时,输出会略有改变,但不会完全归零(就像过去的算法一样)。反向传播时对输出层的这种改变阻止了纯粹的记忆。

为什么要解决这个问题?

这些网络的一些实际应用包括标记用于分割的图像数据、对图像去噪(对此的明显选择是 DAE)、检测异常值以及填充图像中的间隙。这些应用程序中的许多还与 SAE 一起工作,这将在下面解释。

别再提那个问题了。现在我们要提到其他更强大的自动编码器的变体。

堆叠式自动编码器(SAE)

Source: https://www.researchgate.net/figure/Stacked-autoencoders-architecture_fig21_319524552

堆叠自动编码器开始看起来很像神经网络。本质上,SAE 是许多自动编码器与多层编码和解码放在一起。这允许算法有更多的层、更多的权重,并且很可能最终变得更健壮。

不仅要了解 SAE,还要了解其他形式的 AEs,这些层也可以是卷积层和解卷积层;这样更便于图像处理。

SAE 和 AEs 的一些用途通常包括分类和调整图像大小。这是自动编码器已知的特征提取工具的两个实际应用;特征提取的任何其他用途对于自动编码器都是有用的。

可变自动编码器(VAE)

Source: http://kvfrans.com/variational-autoencoders-explained/

这可能是自动编码器最常用的变体:生成式。它也比其他的要复杂得多。

简而言之,VAEs 类似于 SAE,但是它们能够分离解码器。在中间,有两个向量,然后结合成一个潜在向量。这是什么意思?嗯,如果理论上从 SAE 中提取瓶颈隐藏层,并要求它生成给定随机向量的图像,很可能会产生噪声。有很多随机性,只有某些区域是提供真实图像的矢量。

The yellow sectors are good vectors. All of the pink region will just give noise.

由于获得图像生成向量的机会很小,均值和标准差有助于将这些黄色区域压缩成一个称为潜在空间的区域。然后,对其进行采样,以产生最终图像。潜在空间内的一切都应该产生图像。

从这里,我们可以取出编码部分,结果应该是一个生成器。

解开变分自动编码器

这是 VAEs 的决胜,略有变化。这将基本上允许每个向量控制图像的一个(且仅一个)特征。

看看下面的例子:

The two to the left use disentangled VAEs, and the one to the left is a normal VAE. (Source: https://arxiv.org/pdf/1707.08475.pdf)

请注意,在“解开”选项中,只有一个特征被更改(例如,左转、右转、距离等。).然而,在纠缠中,似乎有许多特征同时发生变化。单个变化改变单个特征的能力是解开 VAEs 的要点。

做到这一点的方法是向原始值添加另一个参数,该参数将考虑模型随着输入向量的每次变化而变化的程度。从那里开始,权重将相应地调整。

而且…现在就这样了。我希望你喜欢这个工具箱。我用了大量的文章和视频,都是很好的读物。如果有任何我可以改进的地方,或者如果你有任何意见或建议,我很乐意听到你的反馈。谢谢大家!

使用的来源

注:除非另有说明,所有图片均由本人设计。

[## 神经网络——深度自动编码器和堆叠式自动编码器的区别

该领域的术语没有固定的、清晰的和明确的定义,不同的研究可能意味着不同的…

stackoverflow.com](https://stackoverflow.com/questions/49296951/neural-networks-difference-between-deep-autoencoder-and-stacked-autoencoder#targetText=As I understand it%2C the,greedy%2C layer-wise approach.) [## 基于堆叠式自动编码器的深度神经网络实现齿轮箱故障诊断

机械故障诊断在现代制造业中至关重要,因为早期检测可以避免一些故障的发生

www.hindawi.com](https://www.hindawi.com/journals/mpe/2018/5105709/) [## 教程-什么是变分自动编码器?-贾恩·阿尔托萨尔

为什么深度学习研究人员和概率机器学习人员在讨论变分时会感到困惑…

jaan.io](https://jaan.io/what-is-variational-autoencoder-vae-tutorial/) [## 解释了各种自动编码器

在我上一篇关于生成对立网络的文章中,我介绍了一个简单的方法来训练一个可以…

kvfrans.com](http://kvfrans.com/variational-autoencoders-explained/)

https://www.youtube.com/watch?v=9zKuYvjFFS8

https://www.youtube.com/watch?v=fcvYpzHmhvA

http://www . jmlr . org/papers/volume 11/Vincent 10a/Vincent 10a . pdf

https://arxiv.org/pdf/1707.08475.pdf

用于通用乐高分拣机的高速计算机视觉流水线

原文:https://towardsdatascience.com/a-high-speed-computer-vision-pipeline-for-the-universal-lego-sorting-machine-253f5a690ef4?source=collection_archive---------6-----------------------

在过去的几年里,我一直在设计和制造一台可以识别和分类乐高积木的机器。该机器的一个关键部分是捕获单元——这是一个小型的大部分封闭的腔室,具有一条皮带、一盏灯和一台相机。

You’ll see the light a bit later.

相机拍摄沿着传送带移动的乐高零件的照片,然后将零件的图像无线发送到服务器,服务器运行人工智能算法,从数千个可能的乐高元素中识别出零件。我将在未来的文章中提供更多关于人工智能算法本身的细节,但本文将致力于相机的原始视频输出和神经网络输入之间的处理。

我需要解决的核心问题是将皮带的实时视频流转换为神经网络可以使用的各个部分的图像。

The final goal: Go from raw video (left) to a bunch of uniformly sized images (right) to send to the neural network. (Gif is slowed down to about 50% speed vs realtime)

这是一个很好的例子,这个问题表面上看起来很简单,但实际上存在许多独特而有趣的障碍,其中许多是计算机视觉平台所特有的。

以这种方式提取图像的相关部分通常被称为“对象检测”。这正是我需要做的:检测对象的存在,它们的位置和大小,这样我就可以为每一帧的每一部分生成边界框

The key is to find good bounding boxes (shown in green)

我将讨论解决方案的三个方面:

  • 通过消除无关的变量来为自己的成功做准备
  • 从简单的 CV 操作中构建管道
  • 在有限的 Raspberry Pi 平台上保持良好的性能

消除无关变量

对于类似这样的问题,在尝试应用计算机视觉技术之前,最好尽可能多地消除变量。例如,我不想关心环境条件、不同的相机位置或由于遮挡造成的信息丢失。如果有必要,在软件中解决所有这些变量是可能的(如果非常困难),但幸运的是,我正在从头开始设计这台机器——我可以在编写任何代码之前通过删除这些变量来为自己的成功做准备。

第一步是强制固定相机位置、角度和焦点。很简单,装备把摄像机锁定在腰带上方。我也不需要担心遮挡;不想要的物体不太可能开始进入捕获单元。稍微难一点,但非常重要的是,强制一致的照明条件。我不希望我的物体探测器错误地将路人的影子解读为物理物体。对于许多计算机视觉应用来说,加强照明是非常困难或不可能的。谢天谢地,捕捉单元超级小(相机的整个视野比一条面包还小!)所以我对环境有了超乎寻常的掌控力。

View from inside the capture unit. The camera is in the top third of the frame.

一种选择是将盒子完全封闭,这样外部环境的光线就无法进入。我试过这个,用 LED 灯带做光源。不幸的是,它非常棘手——外壳上的一个小洞和光线可以涌入,干扰任何物体检测。
最后,最好的解决方案是通过彻底爆破充满光线的小房间来“战胜”其他光源。事实证明,这种可以照亮整个房间的灯非常便宜,使用起来也很简单。

Take that, shadows!

当光线射进这个小房间时,它远远压倒了任何潜在的干扰。作为一个令人高兴的副作用,这种丰富的光线意味着相机可以使用非常快的快门速度,拍摄零件的完美清晰的图像,即使它们沿着传送带跑。

物体检测器

那么,我如何把这个漂亮的、持续发光的视频变成有用的边框呢?如果你是一名人工智能从业者,你可能会建议实现一个对象检测神经网络,像 YOLO更快的 R-CNN 。这些神经网络可以轻松实现这个目标。不幸的是,我在一个 Raspberry pi 上运行对象检测代码。即使是高端计算机也很难以我需要的大约 90FPS 的帧率运行这些卷积神经网络。没有任何方式,一个树莓派,缺乏任何人工智能兼容的 GPU 硬件,将能够运行这些人工智能算法之一的超级精简版本。我可以将视频从 Pi 流式传输到另一台计算机,但实时视频流非常麻烦,延迟和带宽限制都会导致严重的问题,尤其是在需要高数据速率的情况下。

YOLO is really cool! But I don’t need all this functionality.

幸运的是,我可以通过寻找“老派”计算机视觉技术来避免复杂的人工智能解决方案。第一个是背景减除,它试图突出显示图像中正在变化的任何部分。在我的例子中,摄像机看到的唯一移动的东西是乐高零件。(皮带当然在移动,但是因为它有统一的颜色,所以看起来不会向摄像机移动)。把那些乐高零件从背景中分离出来,我就成功了一半。

为了使背景减法起作用,前景物体必须与背景有很大不同才能被提取出来。乐高零件有各种各样的颜色,所以我需要非常明确地选择背景颜色,尽可能不像乐高。这就是为什么相机下面的带子是由纸制成的——不仅需要非常均匀,而且不能由乐高制成,否则它会与它需要识别的一些砖块颜色相同!我选择了淡粉色,但任何其他不同于普通乐高颜色的柔和颜色都可以。

精彩的 OpenCV 库内置了许多背景减除算法。MOG2 背景减法器是最复杂的,运行速度惊人,甚至在树莓 pi 上也是如此。然而,将视频帧直接馈送到 MOG2 并不十分有效。浅灰色和白色的作品在亮度上与苍白的背景过于相似,会丢失。我需要一种方法,通过告诉背景减法器更仔细地查看颜色而不是亮度来更清楚地区分皮带和皮带上的东西。我所需要做的就是在将图像传递给背景减法器之前增加图像的饱和度。结果大大改善了。

在背景减除之后,我需要使用形态学操作来消除尽可能多的噪声。OpenCV 的 findContours()功能可用于查找白色区域的轮廓。在应用了一些基于轮廓面积的启发式方法来丢弃包含噪声的轮廓之后,将这些轮廓转换成最终的边界框是一个简单的过程。

表演

神经网络是一头饥饿的野兽。为了获得尽可能好的分类结果,需要尽可能多的高分辨率图像。这意味着我需要以很高的帧速率拍摄,同时还要保证图像质量和高分辨率。我将把相机和树莓图形处理器推到绝对的极限。极其详尽的 picamera 文档显示,V2 相机芯片可以以每秒 90 帧的最高速度输出 1280x720 像素的图像。这是一个令人难以置信的数据量,即使相机可以生成它,也不意味着计算机可以处理它。如果我处理的是原始的 24 位 RGB 图像,那就需要大约 237 MB/s 的带宽,对于可怜的 Pi 的 GPU 或 SDRAM 来说太多了。即使使用 GPU 加速的 JPEG 压缩,90fps 也是不可能实现的。
raspberry pi 摄像机能够输出未经过滤的原始“YUV”图像。尽管 YUV 比 RGB 更难处理,但它实际上有很多很好的属性。最重要的是,它每像素只有 12 位(相对于 RGB 的 24 位)。

Every 4 ‘Y’ bytes has one ‘U’ and one ‘V’ byte — that comes out to 1.5 bytes per pixel.

这意味着我可以处理两倍于 RGB 帧的 YUV 帧,甚至不考虑 GPU 否则将不得不花费编码 RGB 图像的额外时间。
上面对实际的处理管道设置了一些非常独特的限制。对全尺寸视频帧的大多数操作都将是内存和 CPU 密集型的。在我严格的时间限制内,即使解码一个全尺寸的 YUV 帧也是不可能的。

幸运的是,我实际上不需要处理整个帧!对象检测不需要精确的边界框,只需要相当接近即可,因此整个对象检测流水线可以在小得多的调整大小的帧上完成。缩小操作不需要考虑全尺寸帧中的所有像素,因此,只要小心,可以非常快速且廉价地调整帧的大小。然后,生成的边界框被按比例放大,并用于从全尺寸 YUV 帧中取出裁剪部分。这样,我永远不需要解码或处理整个高分辨率帧。

幸运的是,由于这种 YUV 格式的存储方式(见上文),实现直接在 YUV 格式上工作的快速裁剪和缩小操作实际上非常容易。最后,整个管道可以在 Pi 的 4 个内核上多线程化,而不会有太多麻烦(您确实需要在后台减法步骤周围设置一个锁)。然而,我发现并非所有内核都得到充分利用,这表明瓶颈仍然是内存带宽。即便如此,我在实践中也能达到 70-80 fps。更深入的内存使用分析可能会进一步加快速度。

如果你有兴趣了解更多关于这个项目的信息,可以看看我以前的文章,我是如何创造了超过 100,000 个标记的乐高训练图像

你可以在推特上关注我: @JustASquid

极区/花簇/玫瑰图的历史&如何在 R 的 ggplot2 中制作它们

原文:https://towardsdatascience.com/a-history-of-polar-area-coxcomb-rose-charts-how-to-make-them-in-rs-ggplot2-a1b1ce2defd1?source=collection_archive---------26-----------------------

探索图表名称背后的故事及其潜在的使用案例

A sample Polar Area Chart created in R using data from transfermarkt.com

这张图表有几个不同的名字:极地区域图,风玫瑰图,玫瑰图,花花公子图,甚至是顾问图。我将从概述图表的历史和我在网上搜索观察到的一些差异开始。在底部有一个关于如何在 R 的 ggplot2 包中创建图表的技术解释。

首先,我们来处理一下名字。数据即 Projec t 使用以下描述将极区、Coxcomb &玫瑰图组合在一起:

“极区图类似于通常的饼图,除了扇形是等角的,并且每个扇形从圆心延伸的距离不同。”

《T4 可视化数据》一书的作者安迪·基尔克用同样的方式对它们进行分类,尽管不包括玫瑰图,包括圆形柱状图。他的定义稍微详细一些,如下:

'极坐标图在同一个显示屏上显示三个或更多不同定量指标的值。它使用一个放射状(圆形)布局,包括几个等角度的扇形,就像比萨饼的切片,每个测量一个。与雷达图(使用沿刻度的位置)相比,极坐标图使用扇形区域大小的变化来表示定量值。这实际上是一个放射状绘制的条形图。

因此,该图表是条形图(使用长度作为预先注意的特征)和饼图(本质上是放射状的,顶部较宽,中间较薄的部分,即。极坐标)。这有助于我们理解图表的形式作为一种表示数据的方式,但仍然没有告诉我们为什么这种图表类型在涉及到不同的名称时如此贪婪!

为了回答这个问题,我们先来看看这张图表在野外的首次出现。根据大多数资料,它首次出现是在克里米亚战争期间,佛罗伦萨·南丁格尔在她的统计图中使用它来显示一年中几个月的死亡原因。

Nightingale’s Diagram on the Causes of Mortality in the Crimean War

出于这个原因,可以理解为什么它有时被称为“夜莺的玫瑰”——向外延伸的部分类似于玫瑰的形状。作为它的一个变体,“风玫瑰图”采用了类似的格式,但是这些线段是根据指南针的指向来显示风向和风力的。在足球分析领域,风玫瑰图被用来显示特定位置或球员的传球方向和数量。

然而,弗罗伦斯·南丁格尔自己从来没有把图表称为玫瑰,这个名字是后来才有的。与普遍看法相反,她也没有把它们称为“花花公子”图表。更详细的解释可以在这里找到,但是看起来‘花花公子’这个名字已经因为一个误解而随着时间的流逝而消失了!

A Cockerel’s Coxcomb

到底什么是花花公子?它可以指一种花的形式,但是,考虑到图表的视觉特性,误解很可能是在与另一个定义进行比较时产生的:公鸡头顶上的红色羽冠(自己看吧!)

本质上,虽然南丁格尔在她的报告中使用了 coxcomb 这个词,但她指的不是图表本身,而是图表的位置和一份更大的报告----皇家委员会报告----的报告。

我们现在已经讨论了玫瑰和花花公子,只剩下极地区域图和顾问图(不可否认不太为人所知,不在本文讨论之列)。

在数学中,极坐标系是一种二维坐标系,其中平面上的每一点都由与参考点的距离和与参考方向的角度来确定。参考点称为极点,从极点沿参考方向发出的射线为极轴。这与我们大多数人习惯的坐标系不同;“笛卡尔”坐标系。这包括线性、垂直/水平方向的标准 x、y 坐标。

Same Chart using Cartesian (x,y) coordinates

上面的例子是与原始图表完全相同的图表,但没有 r 中的 coord_polar()指令。你可以明白为什么安迪·基尔克将该图表描述为“实际上是一个径向绘制的条形图”。通过使用极坐标,您可以将整个图表环绕在一个中心点周围,使其向外呈扇形增大。

它与径向条形图的不同之处在于,当你远离中心时,它的宽度会增加,形成楔形或比萨饼切片,而不是矩形条。这就是极区图中“面积”部分的由来。我相信这使得极区图更适合跨类别的快速比较,正如我们在阿森纳比较中所做的那样,因为可视化利用长度和宽度来表示数据。由于 viz 中覆盖的表面积更大,我的眼睛能够更快地注意到较高和较低的值&对不同的玩家进行比较。

因此,总之,对于大多数用例来说,极区图应该是该图的常用名称。玫瑰图/风玫瑰图适用于可视化采用预先获得的罗盘/特定方向知识,以强调每个线段长度上的运动。据我们所知,这张花花公子图的命名是错误的,尽管它至少保留了与该图的原始设计者——弗洛伦斯·南丁格尔的联系。最终,和大多数语言情况一样,只要你的听众明白你在说什么,你叫它什么并不重要!

如何制作 R 中的极区图

本博客的第二部分现在将分解如何在 R 中构建极区图。这假设对 R、RStudio &如何安装包有基本的了解。下面是创建相对无格式的极区图的完整代码。请参阅下面的逐行描述。用您自己的数据框替换粗体彩色指标。

ggplot( 数据,aes(x= 公制,y= 长度)+

  • 这一行调用 ggplot2 包,将您的数据绑定到绘图,并允许您选择将用于可视化的“美学”(aes)。
  • 在这种情况下,我们希望 x 轴上是我们的度量,y 轴上是我们的值。请记住,我们正在创建一个柱形图,直到 coord_polar 命令。
  • 使用“+”号将各行链接在一起。

geom_col(fill = " red ",alpha=1,width=1)+

  • 这将调用 geom_col 函数,这是制作柱形图/垂直条形图所必需的。
  • fill 参数设置列的填充颜色。这里可以使用十六进制代码/RGB。
  • alpha 设置透明度(0 =透明,1=不透明)。
  • 宽度设置列之间的间隙(0 =无栏,1=并排接触)。

geom_hline(yintercept = seq(0,100,by = 10),

color = "grey ",size = 1) +

geom_vline(xintercept = seq(.5,16.5,by = 1),

color = "grey ",size = 1) +

  • 这些线条为我们的图表添加了一些方便的网格线。
  • geom_hline 设置圆形网格线,geom_vline 设置线段边界线。
  • seq()在两个数字之间创建一个序列,“by”参数说明了间隔。
  • 颜色设置线条颜色。
  • 大小设置线条宽度。

坐标极坐标()+

  • 神奇就发生在这里。从笛卡尔坐标转换到极坐标。

facet _ wrap(vars(Player))

  • 使用“facet”函数获得每个特定指标的小倍数。点击阅读更多关于这个的内容。

图表的所有其他格式,例如添加标题、副标题、背景颜色和小平面的方框,都可以在主题()中实现。下面是我为我的兵工厂图表创建的主题的一个例子。

混合密度网络搭便车指南

原文:https://towardsdatascience.com/a-hitchhikers-guide-to-mixture-density-networks-76b435826cca?source=collection_archive---------5-----------------------

评估预测的不确定性是商业决策的基础。混合密度网络帮助你更好地理解你在现实世界中面临的不确定性。

Photo by Adi Goldstein on Unsplash

介绍

不确定性是我们做出每个决定的关键因素。然而,在商业中,经理们经常会面临各种各样不可预见的后果。经理可能会处理以下问题:

  • "我们如何根据产品属性为 XYZ 定价?"
  • "这个广告会带来多少网站访问量?"
  • "顾客 Z-A137 的预期顾客终身价值是多少?"
  • "考虑到市场形势,我们应该在广告上花多少钱?"

这些问题中的每一个都意味着一个决策,这个决策最好是充分知情的,并且考虑(或者至少承认)潜在的不确定性。例如:错误的定价会导致收入减少,这反过来可能会导致节约成本的必要性。

Photo by rawpixel on Unsplash

这篇文章面向面向业务的数据科学受众。我们将探讨一些关于预测连续值的技术问题,以及众所周知的线性模型在某些情况下的局限性。然后,我们展示了一种称为混合密度网络(MDN)的神经网络变体,以规避这些限制。因此,管理者可以更好地理解预测的潜在不确定性。

前面提出的问题需要预测,并且有三个共同的基本特征。第一个是,我们希望预测一个连续的数量(价格、网站访问量、销售额,你能想到的)。第二个,预测是在不确定性下做出的。因此,我们很想了解一下我们对预测的不确定性。第三,预测取决于一些输入观察(产品属性、客户、广告设计)。理想情况下,我们不希望得到问题的单一答案,而是希望得到一系列答案来评估每个答案的概率。简而言之:我们正在寻找一个概率分布在给定输入的答案范围内。因此,我们增强了对预测的理解,甚至可以作为经理或客户做出更明智的决策。

高斯混合的直觉

举个例子:让我们假设,我们将要预测一个产品的价格,比如说耳机。看一下市场价格的柱状图,我们推断出存在低价位(~30 美元)、中位(~60 美元)和高价(~120 美元)的耳机。回归到简单的高斯分布来模拟数据注定会失败,从经验高斯分布的曲线可以很容易地看出这一点。请记住,高斯正态分布(𝒩)由两个值参数化:均值(μ)和标准差(σ)。根据样本平均值(μ=47.95)和标准差,将𝒩拟合到数据中。偏差(σ=27.76)将概率分配给价格区域,这是我们在虚拟市场中观察不到的(即价格在$90 到$110 之间)。此外,根据曲线的左侧,负的价格是“合理的”。

Source: Author

产生价格分布的基础数据是高斯混合的。混合物是多峰的;因此,它表现出多个“峰值”。为了适应我们虚构的定价数据的分布,我们可以使用不是一个,不是两个,而是三个充分混合的高斯分量。我们“只”需要选择参数(μ,σ),通过加权(⍺)归一化分布,并对它们求和(稍后将详细介绍)。如下图所示,巧妙地混合这些组件反映了真实的数据。

Source: Author

我们将在后续章节中使用 tensor flow(【www.tensorflow.org】)及其扩展 tensor flow-Probability(【www.tensorflow.org/probability】)。该示例是在 Tensorflow Probability 中使用下面代码片段中显示的值生成的。我们基本上定义了同一个族的混合分布。

线性回归的假设

本文开头提出的问题的第一个解决方案确实是执行一个简单的线性回归。我们几乎可以听到你在打哈欠。

但是等等,我们会给它一个简短的技术镜头!给定一个输入向量 x (产品属性、客户……等等)我们希望预测 y (价格、网站访问量……等等)。更准确地说:我们的目标是在给定x:p(y |x)的情况下获得 y 的概率。如果我们假设实值目标数据的高斯分布(正如我们通常所做的,当我们最小化平方误差时),那么p(y |x)采用众所周知的形式:

在实际应用中,对于某数据集𝔻.中的所有( xt15】y)对,给定 x 、其参数θ和目标值 y ,我们最小化线性函数μ的输出的平方误差项(μ( xθ-y)在给定数据和参数的情况下,学习函数实质上“吐出”了高斯分布μ( xθ)的条件均值。它扔掉了性病。偏差和归一化常数,不依赖于θ。通过这样做,该模型强加了多个重要的假设,这些假设在实践中可能非常有限:

  1. 数据分布是高斯分布。引用[1]:
    “实际的机器学习问题往往可以有显著的非高斯分布”(第 272 页)。
  2. 产出分布是单峰的。因此,我们无法解释 x 可以产生多个有效答案的情况,而多模态分布可以捕获这些答案(如上面的耳机示例)。
  3. 性病。假设噪声分布的偏差σ为常数,因此一定不依赖于 x (同质性,各向同性协方差矩阵)。同样,在现实世界中情况并不总是如此。
  4. 函数μ( xθ)是线性的,即μ( xθ)=x×w+b其中θ= {wb 线性模型被广泛认为更容易解释。另一方面,神经网络提供了极好的预测能力,因为它们理论上能够模拟任何函数。

让我们考虑两种情况,这两种情况形象地激发了先前概述的技术问题:

Source: Author

(LHS):基本函数是线性的。然而,我们观察到两个违反:首先是,std。(噪声)分布的偏差不是常数。其次,噪声确实取决于输入。

(RHS):不仅是性病。噪声分布的偏差取决于 x ,但是输出额外为非线性。此外,输出分配是多模态。对于某些数据区域(大约 8),简单平均值不是一个合理的解决方案。当我们要预测遵循如此复杂模式的结果时,强加先前概述的假设可能容易误导。

MDN 的背景

考虑到上述限制,[2]建议通过 DNN 对混合分布进行参数化。MDN 最初构想于 1994 年[1] [2],最近发现了一系列不同的应用。比如:苹果 iOS 11 中的 Siri 使用 MDN 进行语音生成[3]。Alex Graves 使用 MDN 结合 rnn 来生成人工笔迹[4]。此外,还有多个博客帖子专门讨论这个主题[5] [6] [7] [8]。Amazon Forecast 为其客户提供 MDN 作为算法[9],而[10]写了一篇关于这个主题的硕士论文。

然而,我们希望为更广泛的受众建立方法。原因很简单,许多现代神经网络架构可以扩展为 MDN(Transformer、LSTMs、CovNets 等)。MDNs 本质上可以被视为一个扩展模块,适用于各种各样的业务相关任务。

Source: Author

在其核心,MDN 的概念是简单的,直截了当的,有吸引力的:结合了深度神经网络(DNN)和混合分布。DNN 为多个分布提供参数,然后通过一些权重进行混合。这些砝码也由 DNN 提供。由此产生的(多模态)条件概率分布有助于我们对现实世界数据中的复杂模式进行建模。因此,我们能够更好地评估,我们预测的某些值有多大的可能性。

混合模型的形式化

理论上,高斯混合能够模拟任意概率密度[2],如果它被充分参数化(例如,给定足够的分量)。形式上,混合物的条件概率定义为

让我们分别阐述每个参数:

  • c 表示相应混合物成分的指数。每个输出最多有 C 个混合成分(即:分布),这是一个用户可定义的超参数。
  • ⍺表示混合参数。将混音参数想象成滑块,以不同的强度将不同的音频信号混合在一起,产生更丰富的输出。混合参数取决于输入 x
  • 𝒟是要混合的相应分布(音频信号)。可以根据任务或应用来选择分布。
  • λ表示分布𝒟.的参数如果我们将𝒟表示为高斯分布,λ1 对应于条件均值μ( x ),λ2 对应于条件标准差。偏差σ( x )。分布可以有多个参数(例如:Bernoulli 和 Chi2 有一个参数,Gaussian 和 Beta 有两个参数,截断的 Gaussian 最多有四个参数)。这些是神经网络输出的参数。

将条件概率公式化为分布的混合已经解决了与概述的假设相关的多个问题。首先,分布可以是任意的,因为我们理论上能够将每个分布建模为高斯分布的混合物[2]。其次,使用多种分布有助于我们对多模态信号进行建模。考虑我们的耳机价格例子,这显然是多模态的。第三,性病。偏差现在以输入为条件,允许我们考虑变量 std。偏差。即使我们只使用单一的高斯分布,这个优势也适用。第四个,函数的线性问题可以通过选择一个非线性模型来解决,该模型决定了输入的分布参数。

为了获得混合物的参数,DNN 被修改以输出多个参数向量。我们从单层 DNN 和 ReLU 激活开始。使用隐藏层 h1( x ),我们继续计算混合物的参数如下:

混合系数必须总和为 1:∑⍺(x)= 1。因此,我们使用 softmax 函数来约束输出。这一步很重要,因为概率的混合必须整合为一。λ1 和λ2 的约束本身取决于我们为模型选择的分布。我们必须对高斯函数施加的唯一约束是。偏差为
σ( x ) > 0。这种效果可以通过多种方式实现。例如,我们可以使用最初由 Bishop [1] [2]提出的指数激活。然而,指数会导致数值不稳定。或者,我们可以使用简单的 softplus 激活,类似于[11]中使用的 oneplus 激活。或者我们采用一种有偏移的 ELU 激活的变体。由于最近 ELU 的突出,我们选择了后者。因此,我们最终完成了以下转换:

约束条件的选择取决于分布和数据。一如既往:不同的约束可能在不同的数据集上表现得更好。有人甚至会说,从商业角度来看,将μ( x )限制为正值也是明智的。因此,我们可以认为负价格是不可能的。

既然我们现在指定了参数和条件概率,我们就有了使用某种形式的梯度下降(SGD、Adagrad、Adadelta、Adam、RMSProp 等)直接最小化平均负对数似然(NLL)所需的一切。).

千年发展目标的实施

代码在Github/Colab上有。

建立了 MDN 的基本理论后,我们现在展示如何在 Tensorflow/Keras 中实现该模型。我们基本上需要两个组件:计算参数的自定义层和最小化的损失函数。出于数值稳定性和方便性的原因,我们将在张量流函数中进行大部分计算。正如我们之前强调的 MDN 框架的灵活性一样,我们并没有讨论所有的内容,而是讨论了与您构建自己版本的 MDN 框架相关的部分。定义 DNN 很简单:

根据数据和应用,对 sigmas 进行额外的活动调整以防止 std 也可能是有意义的。偏离炸毁。简单的 L2 正则化将是一个明智的选择。

代码示例需要一个“非负指数线性单位”激活函数,确保 sigmas 严格大于零。Tensorflow 提供了一种非常友好的方式来定义所需的激活函数。我们只是让 nnelu 成为一个可调用的函数,并在 Keras 中将其注册为自定义激活函数。

剩下的构建模块是损失函数的实现。Tensorflow-Probability 的应用很方便,因为我们只是稍微重新定义了本文开头的例子。MixtureSameFamily 需要混合分布和组件分布。前者是一个简单的分类分布,它得到混合权重⍺( x 。后者是正态分布,由平均值和标准差参数化。偏差。随后,我们只需计算 y 及其负平均值的对数似然。通过回归到张量流概率,我们避免了数值上溢/下溢(手动实现这一点实际上相当棘手)。

在定义了 MDN 最重要的组件之后,只剩下模型的编译了。

模拟数据的应用

是时候回到我们之前的例子了。我们训练具有两层的简单 MDN,每层 200 个神经元,并且在线性数据集上有一个高斯分量。MDN 显示了它的实力:由于调节性病。输入上分布的偏差,MDN 可以适应底层数据分布的变化。它巧妙地捕捉到了线性趋势(如预期的那样),但调整了标准差。根据数据中存在的不确定性的增加而产生的偏差(我喜欢这个图表。看起来像流星)。

Source: Author

为了更好地掌握结果,我们还对几个模型的平均负对数似然进行了比较。也就是说,让我们看看零模型(样本均值和样本标准差。偏差)、线性模型(线性条件均值和样本标准差。偏差)、DNN(非线性条件均值和样本标准差。偏差)和 MDN(非线性条件均值和非线性条件标准差)。偏差)。DNN 和 MDN 使用相同的参数和训练程序。幸运的是,我们可以使用 Tensorboard 监控 MDN 的训练进度。所要做的就是回调 fit 例程。因此,我们不需要费心单独存储训练损失。我们正在汇合!

MDN nll-loss during optimization. Source: Author

Source: Author

所有模型都能够击败零模型。其余模型在 MSE 方面表现相同,因为 MSE 假设 std。基础分布的偏差是常数。我们无法充分捕捉数据的行为!NLL 包含了 std。偏差,确实反映了一个更微妙的画面。由于基础函数是线性的,因此 DNN 和线性模型的性能相当。然而,MDN能够更好地适应数据分布,从而产生最低的 NLL 值。

为了从单个数据点的 MDN 的概率密度中导出条件均值,可以计算:

看一下这个公式就可以解释这个结果:平均值没有包含标准差。偏差σ( x )。仅仅查看 MDN 的含义就丢弃了有价值的信息,而这些信息在现实世界的应用程序中可能是需要的。有了这种分布,我们就可以计算更精细的数量。例如,香农熵可以作为我们有多确定的指标。或者我们可以计算 f-散度来评估,预测有多相似。

现在让我们转向第二个非线性的例子。我们首先使用最小-最大缩放器将 y 转换为 DNN / MDN 的合理范围,以加速学习。

Source: Author

MDN 不仅能捕捉潜在的非线性,还能捕捉输出的多模态和标准差的变化。偏差。数据生成分布被充分捕获。查看 x = 8 的条件密度,我们看到 MDN 产生两个不相交的峰值:

Source: Author

对这些复杂分布建模的能力反映在 NLL 中,MDN 在 NLL 中取得了最好的效果。

Source: Author

真实世界数据的应用

我们以预测价格的例子开始这篇文章。在冗长的技术阐述之后,让我们回到最初的例子:预测价格。

为了便于分析,我们使用数据集的果蝇:波士顿住房。给定大约 13 个独立变量,目标是预测以 1000 美元为单位的自有住房的中值(MDEV)。这个例子可能没有充分利用 MDNs 的能力来建模多模态分布。尽管如此,它显示了 MDN 如何能够模拟价格的不确定性。自变量使用最小-最大缩放器进行转换,而价格则进行对数转换。

Source: Author

在 NLL 中,我们观察到与前面的例子类似的行为。MDN 能够更好地处理数据。因此,虽然我们在例子中可能没有多模态,但我们肯定受益于对完整条件概率的建模,而不仅仅是点估计。

Source: Author

分析不同房屋的条件密度有助于我们更好地做出决定。我们对 18 号房的高价相当有信心,因此,作为管理者,我们可以相应地设定价格。

对 12 号房的预测很不确定。可能需要人类专家直接评估案例来设定价格。

房子 13 和 45 在价格上确实重叠。直接分析它们的属性是有意义的,以查看它们是否可以作为相同价格范围内的买家感兴趣的对象。虽然我们没有在这个简单的数据集中挖掘模型的全部潜力,但我们仍然从附加功能中受益。

摘要

评估不确定性是现代企业的一个重要方面。这篇博文重点介绍了理论推理、实现细节以及使用 MDN 时的一些技巧和诀窍。我们展示了 MDN 在模拟和实际应用中的能力。由于它的简单性和模块化,我们期待广泛的应用。

如有疑问,欢迎联系 me

附加说明

代码在Github/Colab上有。本指南是为 Tensorflow 1.12.0 和 Tensorflow-Probability 0.5.0 编写的。

文学

[1] Christopher M. Bishop,模式识别与机器学习 (2006)

[2]克里斯托弗·m·毕晓普,混合密度网络 (1994)

[3] Siri 团队,Siri 语音的深度学习:用于混合单元选择合成的设备上深度混合密度网络 (2017)

[4] Alex Graves,用递归神经网络生成序列 (2014)

[5] Christopher Bonnett,Edward,Keras 和 TensorFlow 的混合密度网络 (2016)

[6]吴炳浩,混合密度网络:基础知识 (2017)

[7] Otoro,tensor flow 混合密度网络 (2016)

[8] Mike Dusenberry,混合密度网络 (2017)

[9]亚马逊,混合密度网络配方 (2019)

[10] Axel Brando,分布和不确定性估计的混合密度网络实施 (2017)

[11] Alex Graves 等人,使用具有动态外部存储器的神经网络的混合计算 (2016)

放弃

表达的观点仅代表我个人,并不代表我的雇主的观点或意见。作者对本网站内容的任何错误或遗漏不承担任何责任或义务。本网站包含的信息按“原样”提供,不保证完整性、准确性、有用性或及时性。

为数据科学家揭秘对象检测和实例分割

原文:https://towardsdatascience.com/a-hitchhikers-guide-to-object-detection-and-instance-segmentation-ac0146fe8e11?source=collection_archive---------4-----------------------

The stage we are at and how we reached it.

目标检测

简单解释!!!我试过了

我非常喜欢深度学习,但对象检测对我来说并不容易。

并且目标检测是重要的并且确实有它的用途。其中最常见的是自动驾驶汽车、医学成像和人脸检测。

这绝对是一个很难解决的问题。在这个问题的漫长历史中引入了如此多的活动部件和新概念,它变得更加难以理解。

这篇文章是关于 将那段历史提炼成一个简单的解释 并解释对象检测和实例分割的血淋淋的细节。

介绍

我们都知道图像分类问题。给定一幅图像,你能找出它属于哪一类吗?

我们可以使用预训练的网络,通过 ConvNets 和转移学习解决任何新的图像分类问题。

作为固定特征提取器的 conv net。获取一个在 ImageNet 上预训练的 ConvNet,移除最后一个完全连接的层(该层的输出是 ImageNet 等不同任务的 1000 个类分数),然后将 ConvNet 的其余部分视为新数据集的固定特征提取器。在 AlexNet 中,这将为每个包含分类器之前隐藏层激活的图像计算 4096-D 向量。我们称这些特征为 CNN 代码。如果这些代码在 ImageNet 上训练 ConvNet 期间也达到了阈值(通常情况下),则这些代码被重新赋值(即阈值为零)对性能非常重要。为所有图像提取 4096-D 代码后,为新数据集训练一个线性分类器(如线性 SVM 或 Softmax 分类器)。

但是在图像领域还有很多其他有趣的问题。

Source

这些问题可以分为 4 大类。在接下来的几行中,我将尝试在我们深入探讨之前简要解释这些问题:

  1. 语义分割: 给定一幅图像,我们能否将每一个像素归类为属于特定的一类?
  2. 分类+定位:我们能够将图像分类为一只猫。太好了。我们是否也可以通过在猫的周围画一个边界框来获得该猫在图像中的位置?这里我们假设图像中有固定数量的物体(一般为 1 个)。
  3. 物体检测:一个更一般情况下的分类+定位问题。在真实世界的设置中,我们事先不知道图像中有多少对象。那么我们是否可以检测图像中的所有对象,并在它们周围绘制边界框?
  4. 实例分割: 我们可以为图像中的每个单独的对象创建遮罩吗?不同于语义切分。怎么会?如果你看顶部的第四张图片,我们将无法使用语义分割程序区分两只狗,因为它会将两只狗合并在一起。

正如你所看到的,所有的问题都有相似的味道,但彼此又有些许不同。在这篇文章中,我将主要关注对象检测和实例分割,因为它们是最有趣的。我将介绍 4 种最著名的物体探测技术,以及它们是如何随着时间和新想法而改进的。

分类+本地化

因此,让我们首先尝试理解,当图像中只有一个物体时,我们如何解决这个问题。分类+本地化案例。

💡把本地化当成回归问题!

Source

输入数据

让我们首先讨论这种模型期望什么样的数据。通常在图像分类设置中,我们使用(X,y)形式的数据,其中 X 是图像,y 是分类标签。

在分类+本地化设置中,我们通常会有(X,y)形式的数据,其中 X 仍然是图像,y 是包含(class_label,X,y,w,h)的数组,其中,

x =边界框左上角的 x 坐标

y =边界框左上角的 y 坐标

w =边界框的宽度,以像素为单位

h =边界框的高度,以像素为单位

型号

所以在这个设置中,我们创建了一个多输出模型,它以一个图像作为输入,有(n_labels + 4)个输出节点。n_labels 每个输出类的节点和给出(x,y,w,h)预测的 4 个节点。

损失

通常,损失是 Softmax 损失(来自分类问题)和回归 L2 损失(来自边界框坐标)的加权和。

损失=阿尔法软最大损失+(1-阿尔法)L2 损失

由于这两个损失将在不同的规模,阿尔法超参数是需要调整的东西。

这里有一件事我想注意一下。我们正在尝试进行对象定位任务,但我们仍然有我们的 convnets 在这里。我们只是增加了一个输出层来预测边界框的坐标,并调整了我们的损失函数。

而这正是整个深度学习框架的精髓所在——层层叠加,重用组件来创建更好的模型,创建架构来解决自己的问题 。这就是我们将会看到的未来。

目标检测

那么这种使用回归的定位思想是如何映射到物体检测的呢?没有。

我们没有固定数量的物体。所以我们不能有 4 个输出来表示边界框坐标。

一个天真的想法可能是将 CNN 应用于图像的许多不同部分。CNN 将每种作物分类为对象类或背景类。这很棘手。你可以创造很多这样的作物。

区域提议:

因此,如果有一种方法(通常称为区域建议网络)可以自动为我们找到一些数量较少的裁剪区域,我们就可以在这些区域上运行 convnet 并完成对象检测。这就是 RCNN 背后的基本思想——物体探测的首次重大成功。

这就是选择性搜索(Uijlings 等人,“目标识别的选择性搜索”IJCV,2013)所提供的。

那么什么是地区提案呢?

  • 找到可能包含物体的图像区域
  • 跑起来比较快;例如,选择性搜索在几秒钟内在 CPU 上给出 2000 个区域建议

那么,地区提案究竟是如何提出的呢?

目标识别的选择性搜索:

本文分两步寻找区域。

首先,我们使用[13] (P. F. Felzenszwalb 和 D. P. Huttenlocher)从一组初始区域开始。高效的基于图形的图像分割。IJCV,59:167–181,2004 年。1, 3, 4, 5, 7)

基于图的图像分割技术通常用图 G = (V,E)来表示该问题,其中每个节点 v ∈ V 对应于图像中的一个像素,E 中的边连接某些相邻像素对。

在本文中,他们采用了一种方法:

每个边(vi,vj )∈ E 具有相应的权重 w((vi,vj)),其是相邻元素 vi 和 vj 之间的相似性的非负度量。在基于图的方法中,分段 S 是将 V 划分成多个分量,使得每个分量(或区域)C ∈ S 对应于图中的一个连通分量。

Efficient graph-based Image Segmentation Example

简而言之,他们使用基于图形的方法来寻找图像中的连通成分,并根据像素之间的某种相似性度量来制作边缘。

正如你所看到的,如果我们在这些遮罩周围创建边界框,我们将会丢失很多区域。我们希望将整个棒球运动员放在一个边框中。我们需要以某种方式将这些初始区域分组。这是第二步。

为此,对象识别的选择性搜索的作者将分层分组算法应用于这些初始区域。在这种算法中,他们根据不同的相似性概念(基于颜色、纹理、大小和填充)将最相似的区域合并在一起,为我们提供更好的区域建议。

**

The Algorithm for region Proposal used in RCNN

1.R-CNN

所以现在我们有了我们的区域提案。在 R-CNN 中我们到底该如何使用它们?

物体检测系统概述。我们的系统

(1)获取输入图像,(2)提取大约 2000 个自下而上的区域提议,(3)使用大型卷积神经网络(CNN)计算每个提议的特征,然后(4)使用特定类别的线性 SVM 对每个区域进行分类。

除此之外,作者还使用了特定于类的边界框回归器,它采用:

输入:(Px,Py,Ph,Pw)-建议区域的位置。

目标:(Gx,Gy,Gh,Gw)-该区域的地面实况标签。

我们的目标是学习一种将建议区域(P)映射到地面真实框(G)的变换

培训 R-CNN

RCNN 的输入是什么?

因此,我们从 RPN 战略和标签的基本事实(标签、基本事实框)中获得了一个图像、区域建议

接下来,我们将所有 IoU(交集/并集)与基础事实框重叠≥ 0.5 的区域提议视为该框类的正面训练示例,其余视为负面训练示例。我们训练班级特定的 SVM 氏症

因此,每个地区的提案都成为一个培训范例。并且 convnet 给出该区域提议的特征向量。然后,我们可以使用特定于类的数据来训练我们的 n-SVM。

测试时间 R-CNN

在测试时,我们使用特定于类的支持向量机来预测检测盒。在测试的时候,我们会得到很多重叠的检测框。因此,非最大抑制是对象检测流水线的组成部分。

首先,它根据分数对所有检测框进行分类。选择具有最大分数的检测框 M,并且抑制与 M 有显著重叠(使用预定阈值)的所有其他检测框。

这个过程递归地应用于所有剩余的框,直到我们只剩下好的边界框。

https://www.pyimagesearch.com/wp-content/uploads/2014/10/hog_object_detection_nms.jpg

RCNN 的问题:

  • 训练很慢。
  • 推断(检测)慢。使用 VGG16 时每幅图像 47s——因为需要多次运行 Convnet。

对速度的需求。这么快 R-CNN。

2.快速 R-CNN

**💡所以来自同一作者的下一个想法:为什么不创建输入图像的卷积图,然后从卷积图中选择区域?我们真的需要运行这么多网络吗?我们可以只运行一个 convnet,然后对 convnet 计算的特征应用区域建议裁剪,并使用简单的 SVM/分类器对这些裁剪进行分类。

类似于:

来自论文:图为快速 R-CNN 架构示意图。快速 R-CNN 网络将整个图像和一组对象提议作为输入。网络首先用几个卷积(conv)和最大汇集层处理整个图像,以产生 conv 特征地图。然后,对于每个对象提议,感兴趣区域(RoI)池层从特征图中提取固定长度的特征向量。每个特征向量被馈入一系列全连接(fc)层,这些层最终分支成两个兄弟输出层:一个层产生 K 个对象类加上一个包罗万象的“背景”类的 softmax 概率估计,另一个层为 K 个对象类中的每一个输出四个实数值。每组 4 个值对 K 个类之一的精确边界框位置进行编码。

💡想法

所以 的基本思想是在图像中只需运行一次卷积,而不是 R-CNN 中的那么多卷积网络。 然后,我们可以使用某种方法映射 ROI 提议,过滤最后一个卷积层,并在其上运行最终分类器。

这个想法在一定程度上依赖于所用模型的架构。

所以作者提出的架构是:

**我们对三个预训练的 ImageNet [4]网络进行了实验,每个网络有五个最大池层和五到十三个 conv 层(有关网络详情,请参见第 4.1 节)。预训练网络初始化快速 R-CNN 网络时,要经历三次变换。首先,最后一个最大池层由 RoI 池层替换,RoI 池层通过设置 H 和 W 与网络的第一个完全连接层兼容来配置(例如,对于 VGG16,H = W = 7)。第二,网络的最后一个全连接层和 softmax(其被训练用于 1000 路 ImageNet 分类)被替换为之前描述的两个兄弟层(K + 1 个类别上的全连接层和 softmax 以及类别特定的边界框回归器)。第三,网络被修改以接受两个数据输入:图像列表和那些图像中的 ROI 列表。

如果你不了解以上内容,也不要担心。这显然有点令人困惑,所以让我们来分析一下。但为此,我们需要先了解 VGG16 架构。

VGG 16 Architecture

最后一个池层是 7x7x512。这是网络作者打算用 ROI 池层来代替的层。该池层获得了作为输入的区域提议的位置(xmin_roi,ymin_roi,h_roi,w_roi)和先前的特征地图(14x14x512)。

We need fixed-sized feature maps for the final classifier

现在 ROI 坐标的位置以输入图像为单位,即 224×224 像素。但是我们必须应用 ROI 合并操作的层是 14x14x512。

当我们使用 VGG 时,我们将图像(224 x 224 x 3)转换为(14 x 14 x 512),即高度和宽度除以 16。我们可以将 ROI 坐标除以 16,映射到特征图上。

在深度上,卷积特征图已经编码了图像的所有信息,同时保持了它相对于原始图像编码的“事物”的位置。例如,如果图像的左上角有一个红色方块,并且卷积层为其激活,则该红色方块的信息仍将位于卷积特征图的左上角。

什么是投资回报率池?

请记住,最终的分类器会针对每种作物运行。所以每种作物都需要一样大。这就是投资回报池的作用。

Source

在上图中,我们的区域建议是 x,y,w,h 格式的(0,3,5,7)。

我们将该区域划分为 4 个区域,因为我们希望有一个 2x2 的 ROI 池层。我们通过舍入 5/2 和 7/2 将整个区域分成桶,然后只做一个最大池。

你如何在小于目标规模的区域进行投资回报池?如果区域提案大小为 5x5,投资回报池层大小为 7x7。如果发生这种情况,我们只需将每个单元格复制 7 次,然后最大合并回 7x7,就可以将大小调整到 35x35。

在替换了汇集层之后,作者还将 1000 层的 imagenet 分类层替换为全连接层和 K + 1 个类别上的 softmax(对于背景+ 1)和类别特定的边界框回归器。

训练快速神经网络

快速 RCNN 的输入是什么?

非常类似于 R-CNN:所以我们有一个图像,来自 RPN 策略的区域提议和标签的基本事实(标签,基本事实框)

接下来,我们将所有 IoU(交集/并集)与基础事实框重叠≥ 0.5 的区域提议视为该框类的正面训练示例,其余视为负面训练示例。这一次我们在上面有一个密集层,我们使用多任务损失。

所以每一个 ROI 都成了训练样本。主要区别在于多任务丢失有一个概念:

快速 R-CNN 网络具有两个兄弟输出层。

首先输出一个 离散概率分布 (每 RoI),p = (p0,。。。,pK),超过 K + 1 个类别。通常,p 由 softmax 通过全连接层的 K+1 个输出来计算。

对于 K 个对象类中的每一个,第二兄弟层输出 包围盒回归偏移 ,t= (tx,ty,tw,th)。每个训练 RoI 被标记有基本事实类 u 和基本事实包围盒回归目标 v。我们在每个标记的 RoI 上使用多任务损失 L 来联合训练分类和包围盒回归

Classification Loss + regression Loss

其中,Lcls 是 softmax 分类损失,Lloc 是回归损失。u=0 表示 BG 类,因此,只有当我们有任何其他类的边界框时,我们才会增加损耗。

问题:

区域提案仍然占据了大部分时间。我们能否缩短区域提案的时间?

Runtime dominated by region proposals!

3.快速 RCNN

下一个被问到的问题是:网络本身能做区域提议吗?

直觉是:使用 FastRCNN,我们已经在 CNN 中计算了一个激活图,为什么不通过几个层来运行激活图以找到感兴趣的区域,然后通过预测类+ bbox 坐标来完成向前传递呢?

区域提案网络如何运作?

论文中的一个主要观点是锚的概念。锚点是固定的边界框,以不同的大小和比例放置在整个图像中,在首次预测对象位置时将用作参考。

所以,首先,我们在图像上定义锚定中心。

Anchor centers throughout the original image

在 VGG16 网络的情况下,锚中心相隔 16 px,因为(14×14×512)的最终卷积层以因子 16(224/14)对图像进行子采样。

这是主播的样子:

Left: Anchors, Center: Anchor for a single point, Right: All anchors

  1. 所以我们从一些预定义的区域开始,我们认为我们的对象可能带有锚点。
  2. 我们的区域提议网络(RPN)对哪些区域具有对象和对象边界框的偏移进行分类。使用相同的逻辑完成训练。如果边界框> 0.5 的锚点的 IOU 为 1,否则为 0。
  3. 减少区域建议的非最大抑制
  4. 基于建议的快速 RCNN 检测网络

快速 RCNN 损耗

然后用 4 个损失联合训练整个网络:

  1. RPN 分类对象/非对象
  2. RPN 回归框坐标偏移
  3. 最终分类分数(对象类别)
  4. 最终框坐标偏移

表演

Results on VOC Dataset for the three different approaches

实例分割

现在是最有趣的部分——实例分割。我们能为图像中的每个物体创建* 蒙版 吗?具体来说大概是:*

Some images with masks from the paper

掩模-RCNN

同样的作者再次前来救援。基本思想是添加另一个预测遮罩的输出层。并使用 ROIAlign 代替 ROIPooling。

Source: Everything remains the same. Just one more output layer to predict masks and ROI pooling replaced by ROIAlign

Mask R-CNN 采用相同的两阶段程序,第一阶段(RPN)相同。

在第二阶段,与预测类别和盒子偏移并行,掩模 R-CNN 还为每个 RoI 输出二进制掩模。

ROIAlign 与 ROIPooling

在 ROI 合并中,我们会丢失基于位置的准确信息。看看我们是如何将我们的区域任意分成 4 个不同大小的盒子的。对于分类任务来说,它工作得很好。

但是对于在像素级别上提供遮罩,我们不想丢失这些信息。因此,我们不会量化池图层,而是使用双线性插值法来找出将提取的要素与输入正确对齐的值。看看 0.8 和 0.88 有什么不同

Source

培养

在训练期间,我们将每个采样 RoI 的多任务损失定义为

L = Lcls + Lbox + Lmask

分类损失 Lcls 和包围盒损失 Lbox 与快速 R-CNN 中的相同。对于每个 RoI,mask 分支有一个 K × m × m 维输出,它对分辨率为 m × m 的 K 个二进制掩码进行编码,K 个类别中的每一个都有一个掩码。

为此,我们应用每像素 sigmoid,并将 Lmask 定义为平均二进制交叉熵损失。对于与地面实况类别 k 相关联的 RoI,Lmask 仅在第 k 个掩码上定义(其他掩码输出不会造成损失)。

掩模预测

掩模层是 K × m × m 维的,其中 K 是类的数量。m×m 浮点数掩模输出被调整到 RoI 尺寸,并在阈值 0.5 被二值化以获得最终掩模。

结论

祝贺你到达终点。这篇文章很长。

在这篇文章中,我谈到了对象检测和实例分割领域的一些最重要的进展,并试图尽可能简单地解释它们。

这是我自己对这些论文的理解,来自互联网上的许多博客和幻灯片,我真诚地感谢创作者。如果你发现我的理解有问题,请告诉我。

目标检测是一个广阔的领域,有许多其他方法在这个领域占主导地位。其中一些是优网,SSD 和 YOLO。

学习它们的资源并不缺乏,所以我鼓励你去看看它们。你现在有了坚实的后盾/理解。

在这个帖子里,我没有写编码和实现。因此,请继续关注我的下一篇文章,在这篇文章中,我们将为自定义数据集训练一个掩码 RCNN 模型。

如果你想了解更多关于各种 物体检测技术,运动估计,视频中的物体跟踪等 。,我想推荐这个关于计算机视觉深度学习的超赞课程。

谢谢你的阅读。将来我也会写更多初学者友好的帖子。在关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。

此外,一个小小的免责声明——在这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。

Spring Boot、Elasticsearch、Logstash、Kibana、PostgreSQL 和 Docker 的搭便车指南

原文:https://towardsdatascience.com/a-hitchhikers-guide-to-spring-boot-elasticsearch-logstash-kibana-postgresql-and-docker-5602feaa9fd3?source=collection_archive---------7-----------------------

最近,我决定开始创建一个 ELK stack 示例项目的旅程,该项目与 Spring Boot 和 PostgreSQL 一起工作——全部在 Docker 中,带有 docker-compose。没有 SaaS。尽管由于 ELK 的流行程度,任何给定的 web 框架都有许多示例项目,但在我看来,Spring Boot 并没有明确的终点线。

我的示例 Spring Boot 应用 spring-elastic-genie 有一个 REST API,它在 OMDB 寻找电影,并将结果保存在 PostgreSQL 中。这些结果然后被 Elasticsearch 索引,这时你可以在 Kibana 中可视化结果。你应该提前知道这是而不是一个如何编码的教程,而是在 Docker 中使用 Spring Boot 和本地 ELK 的高级架构概述。

如果您对进一步阅读不感兴趣,但是想要一个 GitHub 链接来查看一些代码,这里有一个指向我的示例项目的 GitHub 链接:

[## tech 4242/弹簧-弹力-genie

🧶This 项目将展示如何使用弹性搜索和弹性靴。— tech4242/spring-elastic-genie

github.com](https://github.com/tech4242/spring-elastic-genie)

但是我强烈建议你继续阅读,因为有许多陷阱和大量的教程不能告诉你整个故事;尤其是如果你来自一个非春天的背景(像我一样)。

我看到的所有教程都涵盖了如何使用 Spring 数据仓库直接写入 Elasticsearch,但它们没有涵盖如何使用生产中的 Spring Boot 应用程序,这些应用程序实际上将数据保存到诸如 PostgreSQL、MariaDB 等关系数据库中,相反,对于全文搜索等用例,需要搜索索引之上。下面的部分解释了细微的差别以及它们背后的原因。

架构选项

选项 1:还有哪些“如何使用 Spring Boot 和 Elasticsearch”教程

好了,基本上这就是你在网上浏览关于弹性搜索和 Spring Boot 的教程时会发现的。您将拥有一个 Spring 数据存储库,允许您使用 ElasticsearchCrudRepository 接口直接向 Elasticsearch 写入数据,该接口是用于向 PostgreSQL 等普通数据库写入数据的 CrudRepository 的扩展。这一切都很棒,但只涵盖了现实世界用例的一小部分,因为很多时候你希望 Elasticsearch 索引你的主数据库,而不是像上面提到的那样。

所以,当你想直接写给 Elasticsearch 和 PostgreSQL 的时候,问题就来了。如果你想保持如上所示的架构,很遗憾只有一个选择:每个模型有两个 Spring 数据仓库——一个用于 Elasticsearch,一个用于 PostgreSQL。这太可怕了。您只需要 2 倍的业务逻辑代码,而 Spring 不能在两个数据库之间进行事务管理,所以如果事务失败,您可能最终只能保存在 Elasticsearch 或 PostgreSQL 中(除非您想手动管理这些东西……),这首先违背了拥有搜索索引的目的。

TL;如果您想同时写入两个数据库,这种方法并不好。没有什么比 Django + Haystack 方法更好的了,在这种方法中,你可以告诉 Elasticsearch 索引你的 Django 模型,然后你就完成了。

此外,您不能做类似以下的事情:

*public interface MovieRepository extends CrudRepository<Movie, Integer>, ElasticsearchCrudRepository<Movie, Integer> { 
    //...
}*

这将立即在运行时(而不是在构建时)给你一个错误,因为你正在覆盖 beans,缺省情况下是禁用的,但是启用它将没有帮助,因为你只能做两者之一(在单词中是 override)。这就是为什么你将坚持为每个 DB 拥有一个 Spring 数据存储库。除非你选择选项 2。

选项 2: Logstash 和更多抽象

这就是选项 2 的样子。本质上,Spring Boot 处于次要位置,我们使用标准的 CrudRepository 将数据保存到 PostgreSQL 中,然后我们开始使用 Logstash 将我们想要的所有交易从 PostgreSQL 记录到 Elasticsearch,从而从我们的 Spring Boot 应用程序中删除所有 Elasticsearch 代码,并消除代码复制的需要。选项 1 所需的代码在 GitHub 的每个文件中都被注释掉了。

这个项目的 docker-compose 包括 Spring Boot app、PostgreSQL、Elasticsearch、Kibana、Logstash 和 ElasticHQ (ES 监测服务)。这个设置会让你立刻与 ELK 和 Docker 一起运行。

如果你熟悉 Docker,这大部分都是非常基本的。一些亮点:

  • Spring Boot 正在等待 PostgreSQL 的健康检查。这个 Docker 容器只是运行用 gradle 构建的 jar 文件。DB 连接的配置可以在 application.properties 中找到,它是从 core.env 文件中读取的。
  • Logstash 在我的 GH 项目中为 JDBC 驱动程序和 logstash.conf 安装了两个本地文件夹
  • Elastichq 实时监控 Elasticsearch,并且几乎可以开箱即用
  • 所有这些都不能用于生产—只能用于开发!此外,如果在 AWS 上用作 SaaS,ELK 也相当不错,但我想展示如何实现内部开源路径。GitHub 上的 README 中进一步描述了该配置。
  • Logstash 免责声明:目前 Logstash 仅配置为通过简单的 SQL 查询从 PostgreSQL 获取数据,但它没有针对重复等的过滤器。有许多 Logstash 教程可以用来过滤数据。

随机陷阱

  • Logstash 7.2.0 与许多 JDBC 驱动程序不兼容,你需要将 Logstash 与 Elasticsearch 连接起来。相反,我恢复到 7.0.0。在这上面浪费了这么多时间。最后在 pgjdbc GH 页面上打开一个问题,却发现这是一个 Logstash bug
  • 弹性搜索 7。x 与 spring-data-elasticsearch 不兼容,后者是通过使用 spring 的数据仓库将数据保存到 elasticsearch 中。支持的最新版本是 6.7.2,但 Kibana 的是 7。x 有黑暗模式,我想在这篇文章中的一些黑暗模式截图。因为黑暗模式。:)你可以在 GitHub 上关注他们的发布。

幸运饼干的故事

选项 2 有点违背了为 Spring Boot 和弹性设计一个专用指南的目的,对吗?也许是,但也许不是。由于选项 1 最终变得有点混乱,这应该突出了您可以用现有项目做什么,而不需要彻底检查您的整个 Spring 项目来编写 Elasticsearch。此外,问问自己是否需要 Elasticsearch。另一个直接与 PostgreSQL 一起工作的索引能完成这项工作吗?PostgreSQL 本身能很好地完成任务吗?如果对这些问题的回答是“不”,那么选项 2 应该会带来最少的麻烦。

我希望这篇教程能够让你开始你的 ELK stack 之旅(也许甚至可以用 Docker ),这样你就可以少担心你的 Spring 应用程序,多关心如何充分利用 Elasticsearch!

最重要的是:不要惊慌;)

一种混合神经机器翻译模型(Luong & Manning);

原文:https://towardsdatascience.com/a-hybrid-neural-machine-translation-model-luong-manning-fcf419be358a?source=collection_archive---------35-----------------------

Luong & Manning 最近发表了一篇题为“用混合单词字符模型实现开放词汇神经机器翻译”的论文其内容我总结如下。

要快速总结神经机器翻译(NMT)的现状,你可以快速看一下我的另一篇文章这里

目前,通用的基于单词的 NMT 为输出中的罕见单词生成,然后应用后处理步骤,通过使用来自它们的注意力机制的对齐信息,经由简单的单词字典查找来处理这些未知标记。这种方法存在 1)字母不匹配和 2)多词对齐的问题

添加一个字符组件。

Luong 和 Manning 通过在当前的编码器-注意力-解码器架构中使用基于核心单词的 NMT 来解决这个问题,但他们没有将所有罕见的单词都视为<unk,而是添加了一个字符组件,以每个字符为基础对它们进行编码:

Luong, Manning, “Achieving Open Vocabulary Neural Machine Translation with Hybrid Word-Character Models.”

在这个图表中,“可爱”是一个罕见的词。因此,它被分解成字符,并通过“c”、“u”、“t”、“e”和“_”(边界符号)输入到基于字符的深层 LSTM 中。最终的表现,隐藏状态,在顶层,然后取代了“可爱”的

每当单词级 NMT 产生一个< unk >,你就可以参考这个字符级解码器来恢复未知目标单词的正确表面形式。

这在纯字 NMT 上提供了以下改进:

1)更快更容易训练(无后处理步骤)
2)从不产生未登录词

相对于现有技术的结果:

在 WMT 的 15 个英语-捷克语翻译任务中,与其他 NMT 模型相比,混合神经机器翻译模型获得了+2.1–11.4 BLEU,最好的系统获得了最高的 20.7 BLEU。它还获得了更高的 chrF3 分数。

基于字符的模型,用于取代纯粹的< unk >技术,对 BLEU 分数贡献最大,在 10k 词汇上为+2.1 BLEU。

Figure 3. Vocabulary size effect

Table 1. Experiment results

结论

本文提出的混合体系结构结合了基于单词的模型和基于字符的模型,前者速度快且易于训练,后者能很好地处理未登录词,从而产生更高质量的翻译。本文还展示了纯基于字符的模型的潜力,尽管它的训练速度非常低。因此,可能需要做更多的工作来提高基于角色的模型的速度。

最初发表于“使用混合单词-字符模型实现开放词汇神经机器翻译”
Minh-Thang Luong 和 Christopher D. Manning,加利福尼亚州斯坦福市斯坦福大学计算机科学系,邮编:94305

人工智能和人类的自我异化

原文:https://towardsdatascience.com/a-i-and-humanitys-self-alienation-69a2fddf9b9c?source=collection_archive---------14-----------------------

Photo by Andy Kelly on Unsplash

“我们是谁?”是一个永恒的问题,无法用单一的特性来回答,因为我们不是任何一个事物。正如我们所知,我们是许多东西,许多文化,许多社会,许多制度,许多规范,许多关系。我们是善与恶,养育与威胁,聪明与愚蠢,明智与愚蠢。简单地说,我们是人类,我们有智慧。

那么,什么是智能呢?智力是多方面的。什么被认为是智慧会随着时间的推移而改变,并且会因环境和文化的不同而不同。与美国流行文化对待它的方式相反,智力是流动的,而不是固定的。它的评估依赖于上下文。

没有对这种本体论问题的固定答案,人类对一般(不同于狭隘的、特定任务的)人工智能(AI)的追求是一种既傲慢又天真的练习。建立一个神经网络可能接近于一个精心设计的大厦中的建筑,但它的结果是一个格式塔表达式。正如我们的身体大脑,在我们头骨的立方英寸内,产生意识和主观体验的奇迹,感觉大于其各部分的总和。

由于我们被文化所影响,很容易把特殊误认为一般,把特殊误认为普遍。例如,随着时间的推移,主要在美国设计的心理测量智力评估已经尽可能地得到完善,以一种纯粹个性化的方式获取智力。我们对智力(以及更多)的理解已经开始通过个人主义文化来理解。

问题是,真空中没有智能这种东西。即使有,也没什么用,因为应用的是智能。人类不是一直在一起努力建造经得起时间考验的东西吗?即使是做出重大发现的科学家这一(正确的)被看重的人物也经历了一个系统的教育,并定期与同事磋商。以一种纯粹个性化的方式评估智力对谁或什么最有利?除了特定社会秩序的合法化和维护,个性化测试的构建、验证、管理和依赖还能获得什么?

在当前对广义人工智能的狂热追求中,我们冒着梦游般自我淘汰的风险。通过相信收益将超过负担来淡化人工智能的风险,如果当一个广义的人工智能实现并上线时,那就太晚了。

对人工智能问题的批评方法在内容上可以不同于陈词滥调的悲观主义。我们最大的恐惧并不一定是暴力的终结者黑客帝国场景,导致悲剧的仿生活艺术情节扭曲。尽管在可能性的范围内,而不是采取一种向外看的姿态,看着机器,思考它的力量,我们应该通过向内转向,提出问题来批判对人工智能的盲目追求。例如,人工智能(以及我们对它的追求)告诉我们关于我们自己的什么?AI 的梦想从何而来?其诉求的语境是什么?

Self-entanglement. | Photo by Artem Kim on Unsplash

资本主义现代性

对人工智能的追求来自我们的当代历史——先进生产的晚期资本主义时期。从机械和技术中可以想象出一个乌托邦世界,在这个世界中,生产完全自动化,留给人类自由的时间——这个梦想就这样实现了。我们这个时代的生产、分配和消费的现实,以这种方式为我们想象力的扩展创造了真实、具体的基础。

抛开完全自动化的梦想不谈,资本主义现代化时期产生了自身特有的社会生活形式。日常现实被认为是理所当然的——例如,关于个人自由/企业家精神和市场中达尔文式竞争的想法。这些真理看起来具有普遍的、超越历史的有效性,但实际上是资本主义时代特有的社会生活的各个方面。它们是人类创造和提炼的一般经验的一部分,是这个系统维持和繁殖所必需的。

资本主义现代性的一个显著特征是异化。当人们去工作时,他们必然会将他们原本的个人自由置于工作场所的等级和专制结构之下。人们与他们的劳动产品分离,无论是服装制造还是一行代码。我们的劳动属于他人。这是他人的财产,是我们大多数人认为理所当然的生活的基本特征。最近,泰勒·斯威夫特相当公开地疏远了她的工作当音乐执行官斯库特·布劳恩购买了她的整个旧目录时,尽管,正如作家诺亚·伯拉特斯基所指出的,她是自己作词和音乐的作者,也是她自己的动力。根据 Berlatsky 的说法,Swift 与其他人的区别在于

大多数人不仅不拥有自己的劳动,而且在文化上也不具备拥有劳动的能力。斯威夫特可以说,“我应该拥有我的专辑,”这很有道理。但是如果一个装配线上的工人说,“我应该拥有我的汽车”,或者一个沃尔玛的员工说,“我应该拥有我的商店”,他们得到的公众支持会少得多,因为他们认为他们甚至可以找到任何人来倾听。

这些权利和工作成果的分离是现代世界中异化活动的形式。然而,我们可以说,今天的人们比以前的社会遭受的公开统治要少得多(我们不受封建地主的摆布,尽管我们中的许多人会被我们的城市地主驱逐出去)。然而,正如已故马克思学者Moishe Postone所言,“只考虑个人依赖性和独立性问题的自由可能会掩盖更为普遍的不自由形式的存在……”(2015 年,第 8 页)。然而,作为个体,我们不得不做我们必须做的事情来生存。正是这种以现代性的他律史为特征的抽象异化形式,将资本主义与以前的社会形态区分开来。

21 世纪的异化起着破坏性和破坏性的社会作用。它同时是具体的和抽象的,由直接的社会活动决定,并作为一种模糊的、不可描述的社会统治形式被体验。它的一个分支是围绕人工智能发展的集体不响应——也许是因为我们想象一个我们自己创造的、独立于我们的存在,比我们允许自己成为的那种人更完整。

简而言之,异化是指将人从其本性中分离出来的关系。工作和创造是人类的天性,然而我们却与之分离。生产是我们的天性,但我们与我们的产品分离,无法控制我们创造什么,如何处理我们的创造。我们变得彼此分离,被迫参与竞争和各种形式的敌意,大部分时间都在课间度过(见办公室中的虚构例子,以及每天都在发生的为生活工资和安全工作条件而斗争)。通过这种分离和隔离,现代社会中的绝大多数人被降低到最低的共同标准,失去了最初使他们成为人的特殊品质。通过彻底异化的生活形式,人类变成了“抽象的”,个体化的,孤立的,与任何超越表面共性的社会整体都没有联系。根据 NYU 大学政治学教授 Bertell Ollman 的说法,异化是“这一过程在很大程度上说明了货币在资本主义社会中的力量,即购买那些如果它们仍然是生产者的组成部分就永远不会被出售的物品”(1976 年,第 135 页)。

鉴于我们当前世界的结构,人们开始质疑现状就不足为奇了。我们今天所认识的自由是片面的、浅薄的。如果一个人“选择”不工作,他就有挨饿的自由——这种选择本身就是错误的。相反,我们被迫从事报酬过低的劳动,并被告知我们是自由的。在这种情况下,可以理解的是,会存在一种对完全智能和有能力的机器的集体渴望,这是一种解放我们的工具。我们想赋予一个合成生物超越自身局限的能力,让我们摆脱苦差事,而我们却在当前条件下系统地否认自己拥有同样的能力。我们所知的人工智能等同于外包人性,因为我们已经疏远了自己。

Urban assembly line. | Photo by Alex Kotliarskyi on Unsplash

很长一段时间以来,在各种情况下,人类一直梦想着与智能机器人共存——这些机器人没有睡眠时间表,肌肉不会疲劳,大脑不会疲劳。抛开想象力不谈,尽管有杰出的怀疑论者,迈向通用人工智能的竞赛正在被推销,仿佛它的成就将带来某种未指明的解脱,由寻求赚取惊人利润的公司带给你。我们有多年的技术进步。节省时间和劳动力的技术的扩散并没有解放任何人的时间,也没有让我们减少工作。

最近的一次采访中,劳工组织者萨姆·金丁指出,在资本主义中,例如,如果工厂工人被给予工厂的控制权,工人们将不知道该做什么。资本主义不关心发展普通人的能力。它只教特定的人(历史上,白人男性)在特定的班级地点如何协调,管理和经营任何事情,绝大多数人只是做他们被告知的事情。为什么一个被系统剥夺权力的人会同意在解除自身权力之前创造一个理论上无限的智能?在这样的条件下会发展出什么样的智力?

我们对智能机器人的愿景是资本透过我们支离破碎、疏离的生活所投射出的想象。想象我们之外的东西比我们自己更有人情味,具有我们显然缺乏的革命潜力,已经变得更容易接受了。我们更容易想象构建一个比我们自己更“人”的有感知能力的机器人,因为我们已经失去了认识自身更伟大人性的能力。

人工智能非军事化不会发生

原文:https://towardsdatascience.com/a-i-demilitarisation-wont-happen-92bcf6d4bc7d?source=collection_archive---------23-----------------------

人工智能已经被集成到下一代防御系统中,它的非军事化是极不可能的。无论如何,限制其用于军事用途可能不是最明智的策略。

Photo by Rostislav Kralik on Public Domain Pictures

今年的世界经济论坛年会即将开幕。在浏览今年的议程时,我不禁想起了去年对谷歌首席执行官孙戴·皮查伊的采访,他非常坦率和乐观地谈到了他对人工智能如何改变人类运作方式的根本方式的设想。

事实上,思维过程的自动化,结合高速通信网络、即时可用的数据和强大的计算资源,有可能影响社会的所有机制。人工智能将在医疗、教育、能源供应、执法、经济和治理等领域的决策、日常运营和自动化中发挥关键作用。

像大多数其他创新一样,每一项技术进步都可能被滥用于邪恶的目的,人工智能也不例外。让大多数人害怕的是它难以捉摸的本质,它是一个如此广阔的领域,并且在如此多的科幻情节中扮演着核心角色,以至于没有很好的结局

在他的采访中,Sundai 试图通过建议各国应该解除人工智能的武装来平息这种担忧。当然,人们应该结合上下文来看待这些评论。但是期望所有国家都这样做就像期望人类完全停止战争一样。

我强调而非的原因是,只需要一个国家就能造成失衡。如果朝鲜决定在其洲际弹道导弹中集成人工智能以实现高精度自主制导会怎样?期望美国不做同样的事情来应对这种威胁现实吗?又是一次同归于尽

在这种情况下,只有当双方都采取更具侵略性的优势策略并且对手进行报复时损失更大,你才能达到纳什均衡。人们会期望世界上最大的人工智能公司之一的首席执行官至少知道博弈论的这样一个基本概念。

Photo Credits Wikimedia Commons

但是 Sundai 当然完全意识到了这一点。他对人工智能应用的和谐的国家间和平合作的乌托邦式的愿景,正符合他的雇主的议程。具有讽刺意味的是,这发生在同一年年初,当时其“不作恶”的座右铭被删除,其自己的员工罢工抗议其参与军事项目,人们开始严重关注他们的私人信息的可用性和滥用,如电子邮件手机数据

保持对立双方的力量平衡已经是不要对一方施加限制的足够好的理由,而没有任何具体的保证另一方实际上也在这样做。但是这里有更多的原因为什么人工智能非军事化不会发生,以及为什么我们可能一开始就不希望它发生。

资助

国防预算推动了西方国家的大量研究和创新,在这些国家,强大的军事能力被视为至关重要。他们不仅资助导弹和隐形战斗机的建设。他们支持一些想法的发展,这些想法通常还没有任何商业模式,但在竞争国家出现之前仍然值得拥有。当然,更有可能的是,具有明确军事用途的想法会得到国防预算的资助。但是像互联网(最初是阿帕网)和全球定位系统(最初是国防项目)这样的技术最终被公之于众。

自动驾驶汽车可能因谷歌的自动驾驶汽车项目(现为 Waymo )而变得更受欢迎,但实际上这是美国国防高级研究计划局(DARPA)的大挑战的结果。然后,谷歌从赢得 2005 年挑战的团队中招募人员。DARPA 还举办了一场机器人挑战赛,目标是开发能够在对人类有害的环境中执行危险任务的人形机器人。人们只需要回忆一下切尔诺贝利和福岛的灾难,以及人们在放射性环境中工作的后果,就能意识到这种技术有多么有用。

JPL’s RoboSimian at the DARPA Robotics Challenge

DARPA 非常重视人工智能,其他国防组织也是如此,比如 BAE 系统公司和泰雷兹公司。期望军方袖手旁观,与人工智能保持距离是完全不现实的。

人工智能可以减少(双方的)伤亡

在军事上使用人工智能的一个主要担忧是杀手机器人的发展。这是一个合理的担忧,需要通过正确的政策和条约来解决,尽管我怀疑如果技术组件可以获得,任何国家都会公开承认拥有自主武器(直到它被迫拿出并使用它们)。此外,如果一个国家有可能获得这样的技术,那么让竞争环境失衡可能是一个非常糟糕的主意。

鉴于人工通用智能距离还很遥远,而且不太可能出现“终结者式”杀手机器人,也许我们应该更关注人工智能的眼前利益,比如战场智能。如果一个士兵的护目镜配备了增强现实,使用人工智能来识别朋友和敌人,或者平民和威胁,比肾上腺素分泌过多担心自己生命安全的人类更准确,会怎么样?自主装甲车可以用于高风险的任务,比如通过敌对路线运送物资,或者从活跃的战区营救伤员。机器人可以陪伴士兵,帮助他们调查威胁或搬运重型设备。

Photo by Sgt. Eric Keenan

如果导弹制导系统配备了在爆炸前验证目标的机载算法会怎么样?“外科手术式打击”只会击中预定目标,而不会造成附带伤害和无辜平民死亡。利用人工智能来跟踪和拦截空中威胁,甚至在它们实际发射之前检测它们的更智能的防空系统怎么样?

人工智能没有很好的定义

大多数人工智能技术涉及处理数据流,应用微积分、概率和统计等数学技术,并使用少量算法将它们放在一起以达成解决方案。没有什么真正的认知、感知或自我意识在进行。

与核武器不同,你可以清楚地确定一个国家是否有库存(假设你能找到它们),没有明确的方法对集成在各种防御系统中的软件技术进行分类。此外,人们不能真正指望军方不使用它所拥有的数据和计算资源来获得更快、更智能和机器验证的决策支持,而普通公众对它了如指掌。人工智能非军事化不会发生。

约瑟夫·巴加达 拥有计算机科学博士学位,专门研究计划和调度的人工智能技术。他是一名技术顾问,为物流和油田技术应用开发人工智能解决方案。上述文章中表达的任何观点纯属其个人观点,不一定代表任何附属机构的观点。

A.一.加强分子发现和优化

原文:https://towardsdatascience.com/a-i-enhanced-molecular-discovery-and-optimization-9434f3f8a593?source=collection_archive---------12-----------------------

召集所有科学家和开发者

我们正处于一种新的科学方法的边缘,这种方法利用人工智能的力量来加速科学发现的发展。

“在过去几年中,实验和模拟产生的大量数据催生了第四种科学范式,即数据驱动科学,它统一了理论、实验和计算/模拟的前三种范式。”—西北大学的安基特·阿格拉瓦尔

A visual representation of science (colorized, circa. 2003)

科学常常会像一根泥棒,因此理论和实验科学的前两种范式被证明是缓慢的或两个原因:

  1. 理论知识缺乏经验证据(第一范式)
  2. 实验中人类偏见的丰富程度(第二范式)

然而,计算机改变了科学游戏,我们开始充分欣赏这些不可思议的设备带来的准确性和速度。计算和模拟的第三范式是一个很有前途的范式,但是受到当时技术的限制。这将我们引向第四种范式。

第四范式利用了计算范式的数字副产品:数据。数据科学虽然不是一门精确的科学,但可以带来如此高的性能和准确性,以至于它们经常可以识别我们尚未用科学发现的新方法、方程和想法。

这就是计算机如何以及为什么能够:

  1. 击败世界上最好的国际象棋、围棋和 DOTA 玩家
  2. 发现新的药物、材料和分子
  3. 翻译语言,驾驶汽车,交易股票

这个名单每天都在增长。他们能比我们更好地做这些事情,和做一些我们不能做的事情只是数据和一个模型/架构。它需要的唯一等式、直觉或知识是通过观察数据中的模式产生的。

图案在化学和材料科学中非常普遍。从钻石的晶体结构到脂质的支链,这些模式定义了分子的各种性质。识别这些模式并从中学习是人工智能的责任。尽管有一些挫折,比如没有足够的数据用于训练,人工智能非常适合分子发现的问题。今天,处于科学前沿的研究人员开始转向人工智能,以获得更高效、更准确、更多样化的结果。

A.I can do it better (Photo by Franki Chamaki)

我为什么要在乎?

仅仅几十年后,对更坚固的建筑材料、更耐久的电池和更个性化的药物的需求将会增加。我们 T2 满足这些需求的能力取决于研究人员能以多快的速度向试图解决世界上最大问题的公司提供合适的材料。如果链条的强度取决于其最弱的一环,那么:

“创新和进步的速度与我们发现和优化材料的速度一样快”

历史被定义在那个时期主要使用的基本材料上。石器时代、青铜时代和铁器时代,也就是我们今天生活的硅时代的前身。明天我们可能会发现自己处于碳时代。总的来说,我们不能等待这些新的科学时代,但一个新分子到达大众仍然需要几十年的时间。答:我想知道我们将如何弥补差额。

每年,使用最新和最棒的机器学习工具的研究论文数量都在增加。 强化学习增强的递归神经网络 ,到 生成式对抗性自动编码器 ,还有其他的 A.I 恶作剧,这将是一个十年的狂野时代。

如果这是你第一次接触人工智能,太棒了!希望这能给你一张 A .在不久的将来我将去哪里的照片。如果你是化学家、物理学家或生物学家,那太好了!这个领域的每个人都同意的一件事是需要意识到可能性。如果你是一名开发人员或机器学习者,那么欢呼吧!将是你塑造明天的世界。

厉害!但是我们如何到达那里呢?

处于各自领域前沿的研究人员一直在尝试使用我们手头现有的工具来解决这个问题。当前研究的工作方式有一个模式,同样的一般过程适用于任何基于人工智能的科学项目。

研究人员是木匠,这些是材料、工具和指令。

Crafting the perfect molecule (Photo by Barn Images)

首先,我们需要一些高质量的木材…

我们需要数据。更重要的是,我们需要干净的、有标签的和丰富的数据。这些数据必须用计算机能理解的格式来表示。谢天谢地,我们正好有这个东西;简化的分子输入-行-输入系统(SMILES)字符串。

微笑串是计算机可以解释分子的四种方式之一。按照从最低到最高(因此从最简单到最复杂)的顺序听:

  1. 分子指纹(特定长度的数字序列)
  2. 字符串表示(描述结构和组件的符号)
  3. 分子图(与数据结构中的树和图的概念相同)
  4. 模拟(下一级的东西。说够了)

Pick your poison: molecules like drugs reap the benefits of being represented by all 4 formats

90%的研究项目使用 SMILES 字符串表示,尽管有争议的是像 SMARTS 这样更适用的格式。这是因为它在准确性(就表示给定分子的细微差别而言)和复杂性(就计算机解释数据的容易程度而言)之间取得了平衡。字符串本身看起来有点像化学胡言乱语:

C/C=C/C=C/C

OC(=O)C@@HC

CCc1c[n+]2 CCC 3c 4 cccc 4[nH]C3 C2 cc 1

它们看起来有点像典型的高中科学课上教授的化学式。这是因为每个微笑串是由给定分子的分子图的深度优先树遍历生成的。所以在某种程度上,微笑字符串是一个分子的公式,更详细地拼写出来。

SMILES 字符串数据最好在被清理后使用。这包括规范化、(同一个分子可以有多个微笑字符串)、以及去重。你可以把它想象成从木头上移除碎片。这样工作起来更容易也更安全。

当然,计算机不会按字母顺序思考;它用数字思考。因此,我们必须将所有这些字母、符号和字符转换成整数表示、二进制指纹、一键编码或任何其他计算机可以消化的数字格式。

现在我们需要一把锤子和一些钉子…

我们需要工具来处理数据。在机器学习中,这些工具是各种算法,每种算法都用于预测、分类、生成、回归等。每种工具都有不同的用途,因此针对正确的问题选择正确的工具非常重要。在科学领域,机器学习在任何项目中的应用都可以分为以下两类:

正向模型:用于属性预测

或者

逆模型:用于分子发现/优化

模型的类型不同,但输入和输出保持不变。在正向模型中,分子是输入,属性是输出。在逆模型中,这是颠倒的;属性是输入,分子是输出。

有相对简单类型的机器学习模型,如线性回归和 K-最近邻,还有更复杂的算法,如决策树和森林。有时这些工具就足够了,但是如果有足够的数据,可以考虑更强大的模型;神经网络。

神经网络是机器学习算法的瑞士军刀。神经网络可以分类、预测、生成、降低维度等等,这要归功于矩阵乘法的魔力和一种叫做“反向传播”的超级特殊学习算法。

神经网络本身有不同的架构,每种架构都针对不同的目的进行了优化。递归神经网络(RNNs)是操纵时间序列数据(如文本)的完美工具,或者在分子的情况下,意味着微笑字符串表示。rnn 是多用途的,可用于预测属性(输入微笑字符串分子和输出属性)或生成分子(输入属性和输出微笑字符串分子)。

我们需要建造这东西的说明书…

我们现在有了建造新东西所需的材料和工具!我们只需要知道更多的细节。这些细节被称为超参数,如神经元的数量、层数、学习速率等。超参数告诉我们如何使用我们的工具(机器学习算法),来处理我们的木材(数据)。很多时候,指令是由木匠和他们的直觉决定的。作为架构师,您的工作是决定一些超参数值,而其他值是在培训过程中学习到的。

But when you do, choose wisely. (courtesy of Daniel Shapiro)

这些参数对模型的结果有很大的影响,所以选择一个好的起点取决于机器学习者的直觉和经验。成功与失败的区别往往在于单个超参数的变化。优化就是改变这些超参数,直到模型的最终输出尽可能精确。

我们将不得不选择我们的损失函数(我们决定我们的模型做得好或坏的方式)。还有大量的激活函数可供选择(当在神经网络的每一层之间传递时,保持值不变。发展如何选择所有这些超参数的直觉需要理解每个选择如何以及为什么起作用,有时你只需要猜测和检查!

我真的需要一把锯子和一些抛光机…

木匠的工作不仅仅是建造东西;让它看起来像样也是他们的工作。因此,最后一步是以综合的格式返回模型的输出。

在正向模型中, 这意味着用适当的测量单位最准确地呈现给定材料的属性。

在逆模型中, 这意味着以正确的微笑字符串符号呈现生成的分子。

我们有办法提高产品的光洁度。特别是在寻找潜在的候选药物时,这是最危险的阶段。不进行实际测试就无法知道一个分子是否稳定,这就是为什么确定性和误差率在科学中如此重要。这是许多研究人员在他们的原始模型上使用另一个附件的地方。找到一劳永逸的解决方案非常罕见,也没有灵丹妙药。分子发现的良好解决方案实现了多种机器学习算法,也称为集成算法。

发布架构(玛利亚·波波娃等人)结合了 RNNs 和强化学习技术。RNN 由两个不同的网络组成,它们产生有效的分子。强化训练然后将这些结果偏向期望的属性。

ECAAE 架构 ( Daniil Polykovskiy 等人)首先将自动编码器的潜在分布码从属性中分离出来,然后修改潜在码以匹配先前的分布码。这是用一个对抗性的网络来训练的,直到鉴别者不再能够区分潜在的和先前的。

有机架构(Benjamin Sanchez-Lengeling等人)使用带有强化学习技术的生成式对抗网络(GANs)。与释放架构类似,GAN 会在强化学习(称为“目标强化”)将输出转向所需属性之前生成有效的分子。

大概就是这样

我要真实世界的证据!!!

这个一般化的过程不是来自直觉,而是来自两个派别慷慨提供的大量论文、项目和案例研究中开发的模式;学术界和工业界。

大学研究

前面提到的架构,如 ReLeaSE、ECAAE 和 ORGANIC,都是有监督的深度学习的最新例子。这些创新背后令人难以置信的机构是一些世界顶尖大学。

哈佛大学

像“什么是高通量虚拟筛选… ”这样的论文,还有前面提到的有机架构,都是来自世界排名第一的大学。哈佛的清洁能源项目是将人工智能推向前沿的研究的一个例子。贡献者包括来自化学、人工智能、数据科学和许多其他领域的人。如果我们要继续发展这些领域的应用,这种合作是必要的。

剑桥大学

简单的“材料科学的机器学习”是一篇深度论文,涵盖了该领域所有的最新创新。剑桥也是非常特殊应用的地方,比如使用神经网络的合金概率设计。随着像 Deep Mind 这样的公司进驻英国,剑桥继续推出优质内容也就不足为奇了。

西北大学

数据驱动科学的整体理念是西北大学近期工作的一个亮点。从用于分子发现的高通量密度泛函理论通过递归神经网络预测定向能沉积过程中的高维热历史的研究都源于西北大学进行的研究。

创业公司和公司

我的导师纳维德·纳图给了我一个很好的建议;

“当人们愿意为解决问题付费时,问题就变成了机会;必须有一个经济激励。”

如果没有钱,到目前为止的一切都是一个有趣的科学项目,听起来很酷,但从商业角度来看毫无意义。话虽如此,这里有一些公司,或大或小(它们的规模应该说明有多少经济激励),正在寻求改变。

One of the leaders of the industry specifically in cheminformatics

黄水晶信息学

这家位于旧金山的不可思议的公司在分子发现和优化研究领域取得了长足的进步。我要特别强调他们的操作方法。Citrine 明白,就数据的规模、质量和一致性而言,科学界不像其他领域那样享有特权。我们可能有大量的图像、文本和音频数据集,但你很难找到一个可靠的碳分子数据集,更不用说清洁或标记了。

Citrine 通过利用尽可能多的技术来解决的“小数据”问题。像数据扩充、迁移学习和堆叠架构这样的技术从现有数据集中榨取每一盎司的价值。

IBM 研究

对财富 500 强公司如微软、脸书、谷歌,尤其是 IBM(谁还记得 IBM 代表什么?).自从在计算领域的竞标中失利并错失移动业务后,IBM 已经将注意力从正在发生的事情转移到了将要发生的事情上。今天,IBM 仍在努力保持相关性,但不再是我们曾经认识的计算机公司,而是一家量子计算、人工智能研究和技术创新公司,希望在不久的将来东山再起。

最近,IBM 发布了一个预测化学反应的免费工具,根据大多数此类项目,SMILES strings 是选择的分子表示。有了化学反应的两百万个数据点,人工智能设法得到了相当精确的结果。

谷歌研究

不出所料,这家世界上最有影响力的公司碰巧也把手伸向了饼干罐。谷歌的人工智能研究有一个名为谷歌加速科学的特别团队,他们致力于计算化学和生物学,目标是推进科学研究和加速科学创新。他们与 Deep Mind 合作过几次,推出了令人兴奋的作品。

传言他们最近的工作涉及使用 4 种可能的分子表示中的第 3 种;分子图。这是他们研究的自然结果,因为几何深度学习开始普及,其好处变得更加明显。谷歌一贯发布他们的研究出版物,有时还会发布他们的相关代码。密切关注新闻,如果有人能够完成下一件大事,那就是谷歌。

关键要点

  • 我们现在正进入科学的第四范式,一个由数据驱动而不是理论、实验或计算的范式
  • A.我是这一变化将如何影响科学以及对社会意味着什么的决定性因素
  • 当前的研究遵循一个过程,并且局限于人工智能中当前可用的工具
  • 目前学术界和工业界正在解决许多现实世界中的问题,而且这种问题还在不断增加

The future is bright (courtesy of the Science magazine)

接下来会发生什么

Chamath Palihapitiya 认为,虽然谷歌可能是搜索数据的大师,脸书可能是通信数据的大师,亚马逊可能是消费主义数据的大师,还没有一个明确的医疗保健数据、分子数据和许多其他增长领域的大师。

搜索、通信和消费主义数据华而不实,表面上很重要,但没有足够的人来解决世界上最棘手的问题。

人工智能可以改变这一点。

你可以改变。

需要看更多这样的内容吗?

跟我上LinkedIn 脸书 insta gram,当然还有

我所有的内容都在 我的网站 我所有的项目都在GitHub

我总是希望结识新朋友、合作或学习新东西,所以请随时联系 flawnsontong1@gmail.com

人工智能:寻找价值

原文:https://towardsdatascience.com/a-i-primer-what-why-and-how-of-the-revolution-shaping-the-modern-economy-3e805e30ec46?source=collection_archive---------20-----------------------

将塑造现代经济的革命联系起来

我们越来越多地看到轰动效应和行话阻碍了关于人工智能的建设性对话。要认识到人工智能能为我们做什么,我们必须提出有针对性的问题,并充实其实际价值。

我将交替使用人工智能和机器学习。机器学习是人工智能的一个子集,指的是建立统计模型,通过发现和推断数据中的模式来执行任务。数据科学是从数据中提取知识,它使用机器学习技术。

人工智能是一个模糊的术语,也是一个移动的目标——用于描述所有类型的模拟智能行为的技术。这些术语是相互关联的,有时会被归入人工智能的范畴。

我们为什么要谈论它?

它对我们的生活产生了巨大的影响。

作为有眼光的消费者,我们需要知道我们的数据是如何被使用的。YouTube 和脸书算法比我们最好的朋友更了解我们的偏好。从我们的交易中,银行知道我们何时搬家,家中有了新成员,以及我们喜欢什么品牌。我们在网络物理空间采取的每一个行动都会产生数据。这些数据被用来模拟我们的虚拟复制品。

这是变革的驱动力。

我们正在经历日常看不到的指数级增长。互联网上市还不到 8000 天。在那个时期,我们看到了数十亿的超链接,数万亿的搜索,最大的开源百科全书的创建;观看和分享视频的平台,以及将你与食物、交通、商品和服务联系起来的应用程序。难道我们过去的统治者不会为了这种神奇的力量而开战吗?

在一代人的时间里,互联网用户的数量从少数科学家增加到 39 亿——占世界人口的一半。增长率不是线性的;是指数级的。这是问题“你宁愿有一百万美元,还是一便士的总和在一个月内每天翻倍?”中暗示的几何级数从一便士开始,你会在第三十天得到 530 万美元。

人工智能革命正处于第一天。我们将越来越多地看到智能渗透到我们生活的方方面面。

它正在创造巨大的价值

人工智能几乎颠覆了所有行业。很少有技术把人类的经历分成两部分:在它被发现之前,和之后;一些科学家认为人类的下一个这样的发明是人工通用智能。想象一下,一个实体可以像人类一样解决许多领域的问题,只是在访问海量数据时速度要快得多。这可能是我们最后的发明了!

我们所说的人工智能是什么意思?

人工智能的主要领域是:

自然语言处理:虚拟助手、聊天机器人

计算机视觉:照片标记、X 射线诊断、自动驾驶汽车

数据科学和分析:推荐、预测等。

机器人和传感器:工业机器人、智能设备、家庭和信息物理系统

我们的人工智能用例中有三种机器学习算法。它们是:

监督学习:通过向机器展示大量输入和响应的例子来教它“学习”。

无监督学习:输入数据,让机器识别模式

强化学习:不给机器任何数据,而是让它在一个环境中自由活动,让它通过试错来学习。

这些算法可以用来创建机器学习中的某些工具。大多数用例可以简化为以下一项或多项:

人工智能能做什么?

人工智能不是魔法。原因:

●需要大量高质量的数据

●非常容易受到对抗性攻击。

●有许多不遵守人工智能安全和道德原则的使用案例。

然而,这不应该阻止人们尝试不同的模型和用例。我们可以认为用例属于三个类别:

1。改进现有功能

看看你的产品/服务的每个特性,然后问自己,“这个特性试图最大化/最小化什么?

示例:假设您手动处理客户支持请求。您收到的大约 80%的查询都是您以前见过的查询——这些可以而且应该是自动化的。您可以在几天内部署一个简单的 FAQ 聊天机器人,如果不是几个小时,并节省数百个小时。如果客户请求需要专门的支持,则将其重定向至人工。拥有聊天机器人还有另一个好处——你可以挖掘客户支持数据,识别客户痛点,提高你的业务质量。

2。创建新特征

写下一个流程中的每一个活动,问有哪些功能可以为用户创造即时价值?

示例:假设您的应用程序存储照片。使用自动标记或分类,您可以允许用户按人物或事件搜索他们的照片。

3。创造全新的产品

这些产品颠覆了工业——想想自动驾驶汽车。想出在 ML 之前不存在的产品是一个令人兴奋的问题:它们涉及新技术的组合。当 AR/VR、量子计算、区块链、边缘计算等其他指数级行业开始融合时,我们将会看到更多这样的产品。

我们该怎么办?

我们知道,机器学习本质上需要数据,数据经过处理后给出响应。使用这个框架,我们可以想到有趣的应用程序,这些应用程序恰好是很好的业务用例。

这里的要点是,每个机器学习应用程序都涉及输入(数据),然后处理这些输入以给出有用的输出(预测)。中间的过程是机器学习。

令人兴奋的是,这些机器学习算法可以作为服务提供给你今天使用。所有主要参与者都在人工智能即服务领域展开竞争。您添加您的数据,模型就为您建立起来了。要获得可用服务的快速列表,请查看这个

思考数据——以及它是如何被挖掘出来的。

您每天生成哪些数据?下载应用程序时,您授予了它们哪些访问权限?通过访问您的电子邮件、语音记录和交易历史记录,您的服务提供商如何获得您的更多信息?如何使用这些信息?

由于机器学习现在可以作为一项服务提供给每个人,数据成为你的竞争优势。考虑利用机器学习改进现有功能,创造新功能和新产品。

不要对改变脱敏。

比尔·盖茨说,“我们总是高估未来两年将发生的变化,低估未来十年将发生的变化。”要知道,技术的复合性质在未来十年带来的变化将超过上个世纪的总和。

不要小瞧登月的想法。

新技术总会有反对者。尽量不要非黑即白地思考;任何人工智能项目的进展都是一系列的失败和成功。

如果这项技术为社会增加了价值,并且看起来可行,它很可能会以某种方式表现出来——这只是时间问题。而且比大多数人预期的要快。众所周知,增长率是非线性的。

此外,任何雄心勃勃的技术解决方案的每个组成部分本身都是一个突破性的解决方案。自动驾驶汽车由计算机视觉、激光雷达、移动计算、预测算法、人工智能伦理等组成。每个组成部分都可以重新组合成新的产品和服务。

Hari Meyyappan 是一名机器学习工程师、企业家和研究生。要阅读更多他的作品,请访问 hmeyy.com。

人工智能与行为

原文:https://towardsdatascience.com/a-i-with-behaviors-a58395ab7d5d?source=collection_archive---------29-----------------------

谣言、时尚/潮流和体育比赛中的潮流有什么共同点?

回答:都是集体行为的形式!

集体行为的由来

创造了“集体行为”一词的美国社会学家罗伯特·e·帕克,将其定义为“个人在一种普遍的集体冲动影响下的行为,换句话说,这种冲动是社会互动的结果。”何强调,群体、时尚或其他形式的集体行为的参与者有着共同的态度或相似的行为:这不是因为既定的规则或权威力量,也不是因为所有个人都有相同的态度,而是因为一个独特的群体过程。**

  1. 谣言…真的吗?是的,非常喜欢。大多数对群体行为进行社会分析的人认为,通过谣言进行的 信息分配和传播 是整个现象的关键。当一大群人聚集在一起采取共同的行动时,如暴乱或恐慌,谣言往往就会出现。通常会有一个关于这种情况的近似通用定义的发展,这是通过谣言传播过程发生的。(链接到有趣的例子)

在我看来,动物的集体行为要有趣得多

“Fish, for sport only, not for meat. Fish meat is practically a vegetable.” Ron Swanson

这个视频展示了在多种不同环境下集体动物行为的精彩片段。通过视频观看这些奇观确实令人惊叹,但想象一下这在现实中是多么不可思议。也许我应该放下手头的一切,去当一名摄影师??但在视频中所有这些自然景观中,每个个体(代理人)都被群体淹没了,因为群体有了自己的生活。

很酷的东西,但是有什么好主意呢?

在《集体动物行为的原则》中,D . j . t . sum pter 做了一个很好的过渡,说明集体行为的可能性对研究和未来有多么令人兴奋。

有一种感觉,所有这些集体模式都是有规律的,甚至是可预测的。集体动物行为(群体、群体、蚂蚁踪迹)的规律性使我们感到,一定有某种统一的法则支配着这些不同的现象。但是,虽然通勤车的行列可能会让我们想起一群蚂蚁,但它们之间有什么深刻的相似之处吗?如果是这样,我们能否确定一套原则,让我们能够分类和理解集体动物行为?

群体智能

群体智能,除了听起来像一些未来的机器人接管,本质上是分散的,自组织的,自然或人工系统的集体行为。这个概念是由杰拉尔多·贝尼和王静在 1989 年首次提出的。两人深受大自然的启发,尤其是生物系统。

S.I .系统基本上包括一个群体,其中充满了简单的代理人(个体),这些代理人在本地相互作用,并与他们的环境相互作用。代理遵循简单的规则,但当涉及到他们如何在本地行为时,他们有一种自由意志。它们也有一定程度的随机性。

Intelligent Bees clip from Black Mirror, Sci-Fi show

重要的阶段,特别是智能群体的行为(有点像人工集体行为),通过智能体之间的许多交互发生,而其他个体智能体却不知道。

美国国家航空航天局正试图使用 S.I .技术进行行星测绘。美国军方一直在用同样的技术研究战区无人驾驶车辆。欧洲航天局正在利用它进行自我组装和干涉测量的研究。

AI 在哪里出现

人工智能有多种不同的学习方法(只是算法,基本上是乐高积木,更多细节在我之前的博客)

  • 无监督 -我们 而不是 有任何结果变量或目标要预测/估计。它主要用于将数据(群体)聚类成组。
  • 监督- 现在我们有了的目标,我们将根据给定的独立变量的估计来预测结果。
  • 强化 学习- 一个流行的例子是马尔可夫决策过程。它是一台有环境的机器,通过试错来学习。它将继续失败,同时从错误中学习,并获取最佳可用知识作为未来决策的基础。

在高度依赖效率的资源分配行业的任何地方,整个系统中所有个体代理的自组织过程都应该被监控。

人工智能规则如何让代理学习

【投影模拟】

汉斯·布里格尔开发了这种学习模型,它基于不以预定(预编程)方式对事件做出反应的代理。这些智能体具有学习能力,同时它们也被编码为个体。这意味着他们在与环境互动时,每个人都有独特的行为方面:受每个“学习”主体感知和反应的所有感官输入的监控。

为此,他们遵循人工智能规则,允许他们使用并记住以前的经验来调整他们的行动,以便受益。

托马斯·穆勒解释了集体行为调节的应用:

“如果代理人和其他人一起井然有序地移动,我们会给予奖励。随着时间的推移,一个代理意识到:当感知到某些事情时,最好以一种将导致奖励的方式做出反应。我们不会在特定情况下预设正确的行动方案,但我们会确保通过代理人之间的互动来实现"

实际上是复制集体行为

“投影模拟”学习模型已经成功地应用于蝗虫群集行为的研究。这项研究最初是在一个封闭的空间里进行的,在那里他们研究了每个个体与群体大小相对应的运动行为。结果显示,当蜂群的规模只有几个个体时,它们的运动是杂乱无章的。较大的蝗虫群会作为一个整体一起移动,而非常大的蝗虫群会作为一个整体移动,但现在都是向同一个方向移动。研究人员设法定性地再现蝗虫的行为。

[“展望未来,托马斯·穆勒相信这一领域未来的研究将受益于动物的大型数据集,比如鱼群及其动态行为模式。”穆勒总结道:“为鱼建模可能是一个很好但也非常复杂的下一步,可以让我们的学习模型更加真实。](https://www.sciencedaily.com/releases/2019/04/190408114325.htm)

如果你喜欢这本书,看看我的另一篇文章,一组研究人员成功地模拟了鱼群的行为,非常有趣的发现!

作品引用

[## 集体行为的类型和例子-大众传播谈话

什么是集体行为?讨论集体行为的不同类型和例子。也叙述理论…

www.masscommunicationtalk.com](http://www.masscommunicationtalk.com/types-and-examples-of-collective-behaviour.html) [## 集体动物行为的原则

近年来,自组织的概念被用来理解动物的集体行为。的…

www.ncbi.nlm.nih.gov](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1626537/) [## 集体行为|心理学

集体行为:集体行为,由规模可观但组织松散的群体参与的活动…

www.britannica.com](https://www.britannica.com/science/collective-behaviour) [## 群体智能-维基百科

SI 系统通常由一群简单的代理人或机器人组成,这些代理人或机器人在本地相互作用,并与…

en.wikipedia.org](https://en.wikipedia.org/wiki/Swarm_intelligence) [## 利用人工智能来理解集体行为

托马斯·穆勒教授和汉斯·布里格尔教授一直在研究一种机器学习模型,用于…

www.sciencedaily.com](https://www.sciencedaily.com/releases/2019/04/190408114325.htm) [## 视频:描述大量宏观物体集体行为的框架

让我们把冬天抛在脑后吧——是时候考虑沙子了。物理学家经常想到沙子,因为他们并不真的…

phys.org](https://phys.org/news/2015-04-video-framework-characterize-behavior-large.html)

揭秘人工智能的记者指南。

原文:https://towardsdatascience.com/a-journalists-guide-to-demystify-a-i-c49b30e2528d?source=collection_archive---------20-----------------------

与其诅咒算法,不如点燃蜡烛

(Image: Gerd Altmann, Pixabay)

我们越来越多地被智能设备和系统所包围,这些设备和系统具有预测我们需求的内置智能。如果你在拨打客户支持电话时使用了语音识别系统,在从国外进入美国时进行了面部扫描,或者让 Alexa 或 Siri 告诉你天气预报,那么你就与人工智能或人工智能进行了互动。

虽然我们享受着智能设备和系统的便利,但随着人工智能在我们越来越多的生活活动中出现,在工作、家庭、学校、商业和休闲中,它们也引起了用户的担忧。甚至新闻编辑室也是人工智能的目标,它们渗透到我们经常随身携带的移动设备上。问问 Siri 就知道了。

我们愿意假设这些系统中的智能是专业制造的,并且在发布用于日常使用之前经过了彻底的测试和验证。但是我们能做出这样的假设吗?作为记者,我们被要求报道影响人们日常生活的事态发展。然而,随着人工智能技术向前发展,记者们经常被留在外面,和其他人一起观察。是时候了——实际上,是过去的时候了——记者们应该问问智能系统的开发者,人工智能里有什么。我们正在转向我们的生活。

关于人工智能和记者

人工智能一词涵盖了许多不同的技术,包括自然语言处理、计算机视觉和语音识别,以感知和理解来自周围世界的信号和刺激。虽然这些进步中的一些已经存在了几十年,但它们延伸到我们的日常生活中是由于巨大计算能力的广泛可用性、移动设备的激增以及存储大量数据的云计算的出现。

但是也许人工智能最引人注目的进步是在机器学习方面。由于机器学习,智能系统在整合它们遇到的数据时变得更加智能。

现在,系统不仅会记住它们遇到的数据,还会从这些数据中学习和增长更多知识,在许多情况下,比人类更高效、更可预测。人们可以说,机器学习提供的便利被它们对人类在日益智能的技术世界中的角色造成的不确定性所抵消。

我们可能会在生活中看到更多人工智能系统。虽然没有关于智能系统和设备数量的可靠统计,但最近的一份风险投资汇编为我们提供了一个很好的趋势线索。市场情报公司 GlobalData 的统计显示,仅在过去一年,开发人工智能系统的初创公司的风险交易和资金大幅增加,使人工智能成为热门的风险投资目标之一。(2019 年第一季度的数据显示,人工智能风险投资从去年的快速增长中放缓。)

这并不是说记者们对所有这些都漠不关心,而是关注点相当狭窄,例如寻找人工智能对就业的潜在影响。我也承认写了那种故事。事实上,最近的另一项研究显示,公司正在安装对业务有益的人工智能系统,不一定是为了裁员。这项由消费者技术协会市场数据公司 Statista 进行的研究显示,人工智能的顶级商业应用是更好地检测安全威胁和改善客户服务,这些功能直接关系到企业的生存。

关于人工智能的一个更好的故事是检查智能系统做什么,它们如何做,以及它们是否做得好。换句话说,点亮黑匣子里的蜡烛,而不是抱怨黑暗。为了点燃这根蜡烛,知道要问什么问题是有帮助的,我们将在这里检查这些问题。

关于算法

机器学习的核心是计算机代码背后的逻辑算法,它通过智能设备或系统处理信息。算法是执行任务的一组规则和过程,通常用数学公式或逻辑表示。它们可以是简单的,如计算贷款利息的公式,也可以是复杂的,考虑多种因素和条件。

在机器学习中,算法具有一种特殊的性质:当遇到更多数据时,它们会调整自己的规则、过程和计算。机器学习中使用的许多算法都来自于贝叶斯统计,以 18 世纪英国牧师和哲学家托马斯·贝叶斯的名字命名,他的定理导致了根据其他相关概率预测某个结果发生的概率的计算。在这些计算中,用于计算结果的数据越多,预测就越可靠。创建了 FiveThirtyEight 的内特·西尔弗(Nate Silver)帮助普及了选举投票中的贝叶斯统计,并预测了体育赛事的结果,甚至在比赛进行的时候。

对于学习这些算法的机器来说,它们需要数据和大量的数据。算法遇到和吸收的数据越多,这些数据中表达的条件越多样化,预测就应该越精确,就越有把握应用于更大的人群。机器学习系统的开发人员编写他们的算法,然后通常用来自大规模数据库的数据来训练例程。在投入使用后,这些算法会继续从遇到的数据中学习,并在结果中变得更加精确。

虽然算法的概念相当简单,但正如前面提到的,它们可能会变得相当复杂。然而,企业高管、政策制定者和普通公民正在使用机器学习算法来帮助做出比以往更多的决定,这些决定取决于他们计算的准确性和可靠性。我们可以信任编写算法的数学家和工程师,或者坚持采取安全措施来检查算法的准确性和可靠性。

为什么我们需要检查算法?我们对 2007-2008 年的金融危机有着痛苦的经历。自 20 世纪 30 年代以来最严重的经济衰退的原因之一是复杂的金融工具,一种被称为抵押债务凭证的衍生品,它将其他资产,如抵押贷款和债券汇集在一起,并重新包装为单独的投资。

许多债务抵押债券非常详细和复杂,需要用算法表达的数学公式和计算机逻辑来精确地确定结果和管理风险。在崩溃之前,许多华尔街投资公司雇佣了训练有素的物理学家和数学家“量子学家”来编写这些算法,算法的复杂性往往掩盖了向投资者推销的抵押贷款组合的潜在风险。

随着一揽子计划中潜在的次级贷款变坏,建立在这个不稳定基础上的债务抵押债券也随之崩溃。因为它们的复杂性,像贝尔斯登和雷曼兄弟这样拥有这些证券的投资银行也无法解释为什么会破产。(2008 年,我在科学杂志的职业专栏中写过一篇关于科学家被聘为量子分析师的专题。)

点燃蜡烛

(Image: Science Translational Medicine)

记者,尤其是那些没有数学和统计学背景的记者——这涵盖了当今的许多记者——如何才能发现这些机器学习算法中的内容?通过问正确的问题:关于算法旨在解决的问题,用于编写算法的过程,以及它在实践中的跟踪记录。如果你想一想,记者们通常会问政治家、企业高管、艺人和体育明星同样的问题。我们现在需要问他们以及人工智能系统的开发者。

从算法的基本事实开始:

1.人工智能系统在解决什么问题?

2.有助于解决这个问题的算法是什么?

3.训练算法的数据来源是什么?

4.当算法遇到数据时,它在学习什么?

下一组问题询问算法的质量和可靠性。当然,这可能是一个棘手的领域,因为除了数据科学家之外,很少有人拥有评估算法的数学或逻辑的技术背景。

密歇根大学法学教授 W. Nicholson Price 在 2018 年 12 月发表在杂志科学转化医学上的一篇文章大数据和黑盒医学算法帮助了我们。尼科尔森提供了一种策略,来帮助医学领域的机器学习算法的用户理解其中的内容。

普莱斯向机器学习系统开发人员提出了一系列问题,以帮助医疗系统监管机构,如食品药品监督管理局,掌握人工智能。(FDA 在 2019 年 4 月宣布,它打算为医疗算法创建一个监管框架。)但普莱斯了解医疗黑匣子内部的策略也可以应用于其他机器学习算法,比如:

5.算法是否被独立审查,或者用于训练算法的代码和数据库是否可供独立审查者使用?

6.除了用于训练的数据集之外,算法是否针对其他数据集运行,以验证最初的发现?

7.该算法在真实世界数据中的表现如何?

与真实算法一起使用的问题示例

这里有一个应用于医疗保健算法的例子,这是科学&企业在 2019 年 3 月报道的。来自斯坦福大学和以色列领先的科学和工程机构 Technion 的医学研究人员和数据科学家团队编写了一种机器学习算法,来计算一个人的免疫系统健康指标,发表在《自然医学杂志上。调用免疫系统正迅速成为许多疾病,特别是癌症新疗法的关键机制。但这些新疗法需要患者体内功能良好的免疫系统才能有效发挥作用。

由斯坦福大学的马克·戴维斯和 Technion 的 Shai Shen-Orr 领导的团队编写了一种算法来计算他们所谓的免疫年龄。随着时间的推移,一个人的免疫系统会逐渐衰退,但如果调用免疫系统的治疗方法合适,实足年龄充其量只是一个粗略的指标。因此,Davis,Shen-Orr 和他的同事设计了这种算法来计算一个人的免疫年龄,他们说这提供了一种更敏感和可靠的免疫系统健康衡量标准。

让我们将我们的 7 个问题应用到这个算法中。

1。人工智能系统在解决什么问题?该系统满足了更好地测量免疫系统健康的需求,以确定调用免疫系统的治疗是否适合一个人。

2。有助于解决这个问题的算法是什么?

3。训练算法的数据来源是什么?
研究人员跟踪了 135 名健康个体 9 年,定期测量各种免疫系统指标:全血样本中表达的基因,细胞对免疫系统细胞发出的称为细胞因子的信号酶的反应,以及体内特定细胞亚群的特征。

4。当算法遇到数据时,它在学习什么?

5。算法是否被独立审查,或者用于训练算法的代码和数据库是否可供独立审查者使用?
研究人员将数据和源代码提供给独立的研究人员。

6。该算法是否针对除用于训练的数据集之外的数据集运行,以验证最初的发现?
该团队对来自弗雷明汉心脏研究的 2000 名参与者样本的健康数据运行了他们的算法,这是一项里程碑式的持续调查,对马萨诸塞州弗雷明汉市 15000 多人的心血管和整体健康进行了调查,始于 1948 年。研究人员表示,他们的免疫年龄算法准确预测了他们采样病例的死亡率。

7。该算法在真实世界数据中的表现如何?
《自然医学》论文发表于 2019 年 3 月,因此截至 2019 年 4 月,进行真实世界测试的机会很小。然而,免疫年龄算法不仅仅是一个学术练习。申-奥尔在特拉维夫联合创办的公司 CytoReason 从 Technion 获得知识产权许可,用于模拟药物发现和临床试验计划的细胞行为。该公司在免疫年龄算法方面的经验可以为这个问题提供答案,并在遇到更多样化的人群时提供新的数据来完善算法。

额外问题:如果一家公司声称其算法是专有的怎么办?

提供机器学习算法服务的公司可能会声称他们的算法是商业秘密,不能披露。这里使用的免疫年龄算法作为一个例子,可以提供一些方法来解决这个问题。以下是进一步要问的问题:

公司的算法是基于学术研究吗?如果是这样的话,一个更早的版本可能会发表在杂志上,就像斯坦福科技公司在《自然医学》上的论文一样。该公司可能会增加或微调计算,但发表的研究可以提供最新版本的良好估计。

*该公司的算法,或其背后的研究,是由美国政府资助的吗?美国国立卫生研究院是免疫年龄算法的资助者之一。联邦机构的资金公告是公开文件,可以在线搜索。这里有来自…

**算法有专利,还是公司申请了专利?如果算法对公司的成功至关重要,那么公司——或者从其获得技术许可的学术机构——可能会申请专利来保护知识产权。搜索专利数据库,如美国专利商标局或第三方数据库提供的数据库,可以提供专利文本。同样,该专利可能不会提供所有算法的最新功能,但它可以提供一个关于其工作原理的好主意。

从火星轨道飞行器到陆地神经网络的旅程

原文:https://towardsdatascience.com/a-journey-from-martian-orbiters-to-terrestrial-neural-networks-16efcb1bda9a?source=collection_archive---------20-----------------------

年份是 2019 年。如果你现在设法传送到火星,你会发现一艘多用途宇宙飞船在近圆形轨道上围绕火星运行,持续约 2 小时,高度从 250 公里到 316 公里不等。这个被恰当地命名为火星勘测轨道飞行器(MRO) 的航天器,自 2006 年 9 月以来一直在向地球传输由其所有最先进的仪器捕获的大量数据。收到的数据总量为 361 兆兆比特,比过去和现在所有其他星际任务的总和还要多。此外,MRO 以每秒 3.4 公里的速度运行,并绕火星运行了 6 万圈!

NASA Infographic (May 2019) — Image Source

如果一个月前你问我这个奇妙的装置,我根本不知道你在说什么。然而,3 周前,我对火星表面的了解经历了一次彻底的变革,这是因为我被选为奥姆德纳的全球人工智能合作挑战 的一部分,与一个 50 人的团队合作,自动识别火星表面的着陆点和异常。

你可能已经猜到了,我们决定应用机器学习来解决这个问题,但在开始之前,我们意识到我们需要大量的火星表面数据(图像)。为了获取这些数据,我们需要了解在哪里可以找到这些数据,以及如何检索这些数据。因此,我们发现自己费力地阅读与复杂软件系统协同工作的精心构造的机器的规范文档和用户手册;试图更多地了解 MRO 和它所有的乐器。

如果您赶时间,并且只想知道如何使用几行代码(Python 语言)检索这些图像,以便您可以专注于构建和调整神经网络来分析火星表面,那么可以随意跳到“一体化 Python 包”部分。然而,如果你想知道更多关于火星图像如何到达地球以及下载这些图像后修复的问题,那么请继续阅读。

目录

高分辨率成像科学实验(HiRISE)

MRO 通过捕捉不同类型的火星表面图像,为漫游车和固定着陆器任务提供了至关重要的支持,以便地球上的科学家可以手动评估每张图像,以确定潜在的着陆点。在轨道器上包括的 3 个相机,2 个光谱仪和 1 个雷达中,我们决定专注于由亚利桑那州大学图森分校管理的高分辨率成像科学实验(HiRISE)相机捕获的数据。这款相机的美妙之处在于,它能够在 300 公里的高度达到 1 微弧度的分辨率,即 0.3 米(相当于一张餐桌的大小)。这些观测覆盖了大约 2.4%的火星表面,相当于两个阿拉斯加的面积,许多地方被重复拍摄。

HiRISE Camera — Image Source

深空网络

MRO 通过与美国宇航局的深空网络通信将所有这些数据中继到地球,这是一个由美国航天器通信设施组成的全球网络,位于美国(加利福尼亚州)、西班牙(马德里)和澳大利亚(堪培拉),支持美国宇航局的星际航天器任务。

70 m antenna at Goldstone, California — Image Source

美国宇航局行星数据系统

现在,这些数据到达地球后去了哪里?很高兴你问了。来自这些仪器中每一个的数据都存储在美国宇航局的行星数据系统(PDS)的远程节点中,这是一个分布式数据系统,美国宇航局用来存档太阳系任务收集的数据,能够经受住时间的考验,以便未来的科学家能够访问、理解和使用预先存在的行星数据。

The geographic distribution of NASA’s Planetary Data System. There are nine nodes geographically distributed across the U.S., broken down by scientific expertise — Image Source

地球科学节点的轨道数据探测器

仅仅为了找到在特定纬度和经度拍摄的图像而搜索分散在多个区域的节点将是非常麻烦和低效的。因此,另一个称为地球科学节点的轨道数据探测器(ode)的系统将 PDS 档案数据从本地和远程节点加载到中央数据库,以便它可以通过以可扩展的方式提供高级搜索、检索和排序工具、集成分析和可视化工具来增强现有的 PDS 搜索和检索界面。

PDS and ODE systems — Image Source

ODE 网络界面

ODE 网站为轨道数据探测器提供了一个用户友好的搜索界面,允许用户根据不同的标准搜索图像,如仪器类型、纬度、经度等。

Data Product Search with Filters

它甚至支持地图搜索,这相当于我们如何使用谷歌地图来搜索特定的地方(我不知道火星的几个地区已经被命名了!)

Interactive Map of the entire surface of Mars

ODE REST 接口

然而,当我们希望搜索和下载来自火星不同地区的大量图像(超过 1000 张)时,网络界面并不是特别有用。这就是 ODE REST 接口出现的地方。它通过 HTTP 提供对 ODE 网站上的相同图像的编程访问。示例响应如下所示:

Sample Response for a query processed by the ODE REST Interface

庞大的 JPEG2000 文件

如果你仔细观察,你会注意到图像文件的 URL,而不是实际的图像本身。除此之外,图像文件的扩展名不是我们已经习惯的 JPG 或 PNG 格式。相反,它是一种叫做 JP2 的奇怪格式。

JPEG 2000 (JP2)是一种图像压缩标准和编码系统。它是由联合图像专家组委员会在 2000 年创建的,旨在取代他们最初的 JPEG 标准(创建于 1992 年),在压缩高分辨率图像方面更有效。它还提供了将图像分割成较小部分以独立编码的可能性,并提高了抗噪声能力。总的来说,JPEG 2000 是一种更灵活的文件格式。

Image Source

由于我们处理的是数千像素量级的高分辨率图像,我们不得不依赖这种高级的 JP2 格式,这种格式处理起来计算量很大,并且需要大量的内存来存储。难怪即使在 2019 年,这种格式也没有像 JPEG 格式一样在小规模设备中变得无处不在。

切掉大块

我如何在(̶E̶a̶r̶t̶h̶)火星上建立一个卷积神经网络来处理成千上万的这些 JP2 文件,每个图像的分辨率约为 25000 x 40000 像素,并希望它在我的有生之年完成?好吧,我们试图解决这个问题,从这个巨大的图像中分割出较小的、相同大小的块(大约 1024 x 1024 像素),并将每个块保存为 JPG 格式,这样 CNN 甚至可以考虑观看它。

Low-Resolution JPG Thumbnail of a JP2 image before slicing (Used only for display purposes and isn’t the actual JP2 file) — Image Source

寻找可扩展的解决方案

我们的麻烦才刚刚开始,因为将一个 JP2 文件分割成块被证明是一个非常缓慢的过程——如果 python 程序在此之前设法不崩溃的话,处理一个图像需要大约 1 个小时。这是不可伸缩的。因此,发现了另一种切片方法,它不需要将整个 JP2 文件加载到内存中。它需要使用 rasterio 包,通过滑动窗口技术只获取 JP2 图像的一部分。

JPG Chunks from a single JP2 image

黑边和计算机视觉技巧

但这并不是结束。现在我们有了所有的块,我们手动浏览它们,却发现多个图像是全黑的或者有不规则的黑色边缘。事实上,大约 50%的块是黑色的。深入挖掘后,我们意识到这是因为 JP2 文件中的图像是地图投影的,这导致它沿着一个矩形区域的对角线排列,周围都是黑色的边缘。

为了解决这个问题,一些计算机视觉技巧,如轮廓和阈值,被应用于识别这样的黑边;旋转并裁剪它们。除此之外,所有完全黑色的块都被丢弃。

Numpy 数据集文件

最后,虽然块被单独保存在磁盘上,但我们也希望将这些块保存为 numpy 数组的集合,以便在训练机器学习模型之前可以轻松地将其作为数据集导入,类似于 keras 等库提供样本数据集的方式。这是通过聚集所有块并将它们保存在单个 npz 文件中实现的。

任务摘要

嗯,那是相当多的一口!让我总结一下到目前为止我们已经完成的步骤:

  • 创建 HTTP 查询字符串以从 ODE REST 接口获取图像
  • 解析查询响应 XML 并提取 JP2 URL
  • 使用步骤 2 中获得的 URL 下载所有 JP2 图像
  • 将每个 JP2 图像分割成较小的、大小相等的块
  • 确定每个块中的黑色边距
  • 通过旋转或裁剪来移除黑边,同时保留该块的原始分辨率,如果不可能,则丢弃整个块
  • (可选)聚合所有区块,并将其保存在单个 NPZ 文件中

如果所有这些步骤都是通过安装一个包并运行几个命令来完成的,那不是很好吗?

一体化 Python 包

嗯,我非常高兴地宣布,使用我们开发的一个名为" mars-ode-data-access "的小 python 包来执行所有这些步骤确实是可能的,可以在 https://github.com/samiriff/mars-ode-data-access获得。

要安装此项目,只需运行以下命令:

pip install git+[https://github.com/usgs/geomag-algorithms.git](https://github.com/usgs/geomag-algorithms.git)
pip install git+[https://github.com/samiriff/mars-ode-data-access.git](https://github.com/samiriff/mars-ode-data-access.git)

它支持多个查询参数和块设置,并在内部利用以下包提供的一些功能:

为了在您的项目中使用 mars-ode-data-access 包,您必须导入相关的类:

确定并定义从轨道数据探测器获取所需的 JP2 图像所需的查询参数。例如,下面的片段演示了如何从凤凰号火星着陆点获取数据:

接下来,我们需要为每个下载的 JP2 图像将被分割到的每个块定义一些设置。下面是一个示例:

最后,我们需要做的就是获取结果并处理它们以创建块。这可以通过运行以下代码来完成:

瞧啊。当所有繁重的工作都在幕后为您完成时,您只需高枕无忧(处理每张 JP2 图像可能需要大约 6 分钟,具体取决于分辨率)。

Sample Output after processing results of the Phoenix Landing Site

如果您想尝试这些 API,看看如何以 NPZ 格式保存这些块,您可以使用这个合作笔记本—https://colab . research . Google . com/drive/1c-j-dblksxuvduhzsdqbp 87 ua 1et 2n

结论

如果没有奥姆德纳人工智能挑战赛提供的协作学习环境,以及来自拉德伯·米特拉、帕特里西奥·韦塞拉、丹尼尔·安格豪森和迈克尔·布哈特的专家建议和指导,这一壮举是不可能实现的。我还要感谢参与本项目的整个团队,特别要感谢 Conrad Wilkinson Schwarz、Sebastian Laverde、Sumbul Zehra、Murli Sivashanmugam、Marta Didych、Aman Dalmia 和 Indresh Bhattacharya,感谢他们为此项目做出的贡献。

总而言之,这对我来说是一次很好的学习和启发经历,我希望我能让你满意地一瞥我在过去 4 周内掌握的知识,亲爱的读者!所以,下一次你在夜空中发现这颗红色星球时,不要仅仅把它当成茫茫太空中的一个小点。请记住,这是一个宏伟的数据源,地球上的任何人都可以使用它来训练神经网络,并了解更多关于其表面和表面下的奥秘,从而提高人类在不久的将来踏上火星的机会…

Dune shaped in the form of the Star Trek logo, discovered southeast Hellas Planitia ( https://www.uahirise.org/ESP_059708_1305)

参考

[1]https://mars . NASA . gov/news/ten-years-of-discovery-by-mars-respective-orbiter/
【2】https://www . pops ci . com/mars-respective-orbiter-have-be-orbiter-being-on-10-years/
【3】https://ode.rsl.wustl.edu/mars/indexHelp.aspx
【4】https://www.uahirise.org
【5】http://www . Planetary

Apache Spark 大数据之旅—第 2 部分

原文:https://towardsdatascience.com/a-journey-into-big-data-with-apache-spark-part-2-4511aa19a900?source=collection_archive---------19-----------------------

介绍如何用 Scala 构建第一个 Apache Spark 应用程序来读取 CSV 文件。

A tabular view of a DataFrame from a CSV file in Apache Spark

欢迎回到(我希望成为的)关于了解 Apache Spark 的系列文章的第二部分。

在第一集中,我们学习了如何使用 Docker 创建和运行 Apache Spark 集群。如果你还没有阅读,你可以在这里阅读。我将使用该集群作为运行我的 Spark 应用程序的集群,因此启动并运行它对您来说非常有用。

我将使用 Scala 构建应用程序,因为我也想了解这一点。Scala 并不是我经常使用的东西,所以当我弄清楚一些事情的时候,请一定要忍耐一下:)。如果有更好的方法来做我做的任何事情,请让我知道——我随时欢迎反馈!

开始之前

本文不会深入探讨如何设置和配置 Scala 应用程序,因为我们的目标是快速启动和运行,并深入 Spark 的世界。Scala world 确实让这变得简单了,它提供了一个叫做 SBT 的工具,Scala Build Tool,有一些值得注意的东西只会让这变得更简单。

设置我们的环境

如果你读过我之前的帖子,我暗示我是一个 Docker 的超级粉丝,以真正的粉丝风格,我将使用已经包含 Scala 和 SBT 的 Docker 图像来帮助我的开发。我将要使用的 Dockerfile 可以在这里找到。这个 Dockerfile 很棒,因为它在构建时接受环境参数,安装由这些参数指定的特定版本的 Scala 和 SBT(非常感谢原作者&贡献者!).我在 Dockerfile 中添加了我自己的小改动,主要是将WORKDIR设置为/project(因为那是我挂载项目目录的地方,就像我的代码一样),并添加了一个CMD,以便在我们启动容器时启动到sbt控制台中。我们可以通过运行以下命令来构建映像:

docker build -t ls12styler/scala-sbt:latest \
    --build-arg SCALA_VERSION=2.12.8 \
    --build-arg SBT_VERSION=1.2.7 \
    github.com/ls12styler/scala-sbt

您可以看到我们将构建的图像标记为ls12styler/scala-sbt:latest,因此我们可以通过运行以下命令来简单地运行图像,让我们进入 bash shell,在我们之前配置的WORKDIR中:

docker run -it --rm ls12styler/scala-sbt:latest /bin/bash

我们可以通过运行scala -versionsbt sbtVersion来验证安装,得到以下输出:

bash-4.4# scala -version
Scala code runner version 2.12.8 -- Copyright 2002-2018, LAMP/EPFL and Lightbend, Inc.
bash-4.4# sbt sbtVersion
[warn] No sbt.version set in project/build.properties, base directory: /
[info] Set current project to root (in build file:/)
[info] 1.2.7

为了能够访问我们的本地文件,我们需要将一个卷从我们的工作目录挂载到正在运行的容器中的某个位置。我们可以通过简单地在我们的run命令中添加-v选项来做到这一点。我们将移除/bin/bash,这样我们就可以直接进入sbt控制台:

docker run -it --rm -v `pwd`:/project ls12styler/scala-sbt:latest

我们在这里所做的就是将pwd(当前工作目录)挂载到容器上的/project目录下。当运行上述内容时,我们将在 SBT 控制台的那个路径上结束:

[warn] No sbt.version set in project/build.properties, base directory: /project
[info] Set current project to project (in build file:/project/)
[info] sbt server started at local:///root/.sbt/1.0/server/07b05e14c4489ea8d2f7/sock
sbt:project>

设置我们的项目

在你的项目目录中创建一个名为build.sbt的新文件,用你最喜欢的编辑器打开它。用以下内容填充它,这些内容实际上是从官方 Spark 文档中借用的,尽管略有改动:

name := "MyFirstScalaSpark"
version := "0.1.0"
scalaVersion := "2.11.12"
libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.4.0"

这给了我们一个最小的项目定义来开始。注意:我们已经将 Scala 版本指定为 2.11.12,因为 Spark 是针对 Scala 2.11 编译的,但是容器上的 Scala 版本是 2.12。在 SBT 控制台中,运行reload命令,用新的构建设置刷新 SBT 项目:

sbt:local> reload
[info] Loading project definition from /project/project
[info] Loading settings for project project from build.sbt ...
[info] Set current project to MyFirstScalaSpark (in build file:/project/)
sbt:MyFirstScalaSpark>

您应该注意到控制台采用了我们项目的名称:MyFirstScalaSpark。现在我们有了一个构建项目的环境。我们写点代码吧!

我们的第一个应用

我们将进一步跟踪 Spark 文档,只是为了测试我们到目前为止的进展。

SBT 应用程序采用 Java 应用程序的标准目录结构,所以让我们在项目目录中创建一些新目录(使用-p标志将递归地创建目录):mkdir -p ./src/main/scala/

在新创建的目录中创建一个名为MyFirstScalaSpark.scala的新文件,并在您喜欢的编辑器中打开它。添加以下内容(同样,从原始内容略作调整):

package com.example
import org.apache.spark.sql.SparkSessionobject MyFirstScalaSpark {
  def main(args: Array[String]) {
    val SPARK_HOME = sys.env("SPARK_HOME")
    val logFile = s"${SPARK_HOME}/README.md"
    val spark = SparkSession.builder
      .appName("MyFirstScalaSpark")
      .getOrCreate()
    val logData = spark.read.textFile(logFile).cache()
    val numAs = logData.filter(line => line.contains("a")).count()
    val numBs = logData.filter(line => line.contains("b")).count()
    println(s"Lines with a: $numAs, Lines with b: $numBs")
    spark.stop()
  }
}

由于我们将在第 1 部分创建的集群上运行这个应用程序,我们知道将设置环境变量$SPARK_HOME并指向 Spark Workers 上的正确目录。在上面的代码中,我们简单地检索了$SPARK_HOME(应该是/spark)环境变量的内容,将其插入到我们正在使用的 Spark 发行版附带的README.md的文件路径中,创建我们的 Spark 会话,然后执行几个 MapReduce 过滤器来计算包含字母ab的各种行数。然后,我们将这些计数输出到控制台。

现在我们已经有了一些需要实际编译的代码,我们可以创建一个 jar 并提交给 Spark 集群。在 SBT 控制台中,只需运行package来生成 jar。您应该会看到类似于以下内容的输出:

sbt:MyFirstScalaSpark> package
[info] Updating ...
[info] Done updating.
[warn] There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings.
[info] Compiling 1 Scala source to /project/target/scala-2.11/classes ...
[info] Done compiling.
[info] Packaging /project/target/scala-2.11/myfirstscalaspark_2.11-1.0.jar ...
[info] Done packaging.
[success] Total time: 11 s, completed Dec 27, 2018 3:22:16 PM

如您所见,jar 已经在容器内的/project/target/scala-2.11/myfirstscalaspark_2.11-1.0.jar输出,这意味着在本地,我们可以在``pwd/target/scala-2.11/中找到 jar。

提交我们的申请

现在是时候让我们在第 1 部分中创建的集群起死回生了!找到包含docker-compose.yml的目录并运行:

docker-compose up --scale spark-worker=2

这将产生一个 Spark Master 和两个 Spark Workers,这足以证明我们的第一个应用程序实际上是可行的。

在我们的项目目录中,我们可以使用我们在集群中创建的相同 Docker 映像作为我们的 Spark 驱动程序。Spark 驱动程序是我们向 Spark 集群提交应用程序的地方的名称,我们可以使用以下命令启动它:

docker run --rm -it -e SPARK_MASTER="spark://spark-master:7077" \
  -v `pwd`:/project --network docker-spark_spark-network \
  ls12styler/spark:latest /bin/bash

在这个命令中,我们设置了环境变量$SPARK_MASTER的内容,在容器上的/project下安装了pwd,将它附加到我们创建的 Docker 网络,并放入一个 bash shell 中。要提交我们的申请,只需将其提交给 spark driver:

bash-4.4# spark-submit --master $SPARK_MASTER \
  --class com.example.MyFirstScalaSpark \
  /project/target/scala-2.11/myfirstscalaspark_2.11-0.0.1.jar

当我们提交应用程序时,我们指定 Spark Master 的 URI、要运行的类名以及该类所在的 jar。当我们在项目目录中启动容器时,Spark Driver 容器可以访问我们构建的 jar,而不需要我们在底层文件系统中复制它。在提交给 Spark 的日志中,您会看到我们在代码输出中构建的行:

...
Lines with a: 62, Lines with b: 31
...

如果我们检查群集的日志,我们会看到如下所示的内容:

spark-master    | 2018-12-27 16:24:10 INFO  Master:54 - Registering app MyFirstScalaSpark
spark-master    | 2018-12-27 16:24:10 INFO  Master:54 - Registered app MyFirstScalaSpark with ID app-20181227162410-0005
spark-master    | 2018-12-27 16:24:10 INFO  Master:54 - Launching executor app-20181227162410-0005/0 on worker worker-20181227134310-172.21.0.4-39747
spark-master    | 2018-12-27 16:24:10 INFO  Master:54 - Launching executor app-20181227162410-0005/1 on worker worker-20181227134310-172.21.0.3-42931
spark-worker_1  | 2018-12-27 16:24:10 INFO  Worker:54 - Asked to launch executor app-20181227162410-0005/0 for MyFirstScalaSpark
spark-worker_2  | 2018-12-27 16:24:10 INFO  Worker:54 - Asked to launch executor app-20181227162410-0005/1 for MyFirstScalaSpark

这显示了我们的应用程序被注册到 Master 并被赋予一个 ID。然后在每个 Worker 上启动 Executors,然后在我们的应用程序运行时发生一系列其他事情。

我们已经成功构建了第一个基于 Scala 的 Spark 应用程序,并在第 1 部分构建的集群上运行。恭喜你!

还有一件事…

现在有一个小问题:这只在目前有效,因为我们很幸运地选择了一个文件,该文件可用于所有使用我们在第 1 部分中构建的相同映像的容器(Master、Worker & Driver)。如果我们希望能够访问没有捆绑在映像中的文件,例如主机文件系统上的某个文件,我们需要与 Spark Workers 共享该文件系统。这可以通过在我们启动集群时在docker-compose中挂载卷来轻松实现。在您的编辑器中打开docker-compose.yml,并在工作者服务声明的末尾添加以下 YAML:

 volumes:
      - "./:/local"

保存文件并重新启动集群。现在,我们的 Spark 员工之间有了一个共享目录。接下来,我们需要与驱动程序共享同一个目录(我们提交应用程序的目录)。这只是为了方便起见,所以我们可以使用 bash 自动完成来构建文件路径,并将其作为参数传递给应用程序。我们可以通过更新我们的run命令来包含新的卷(假设您运行docker-compose up的目录与您的项目目录在同一级别):

docker run --rm -it -e SPARK_MASTER="spark://spark-master:7077" \
  -v `pwd`:/project -v `pwd`/../docker-spark:/local \
  --network docker-spark_spark-network -w /project \
  ls12styler/spark:latest /bin/bash

这个容器现在有了我们的项目目录和共享数据目录,可以分别在/project/local访问。

在 Spark 中读取 CSV 文件

在我们应用程序的第一次迭代中,我们使用了 Spark 中的read.textFile函数来加载一个 README,这个 README 已经对工作人员可用了。接下来,我们将使用read.csv,它将以一种我们可以执行操作的方式加载一个 CSV 文件。我将使用英国航天局支出报告:2018 年 10 月数据来完成这篇文章的其余部分,我将把这些数据放入我在容器上的/local下安装的目录中。首先,我们将简单地使用count方法来查看文件中有多少行。我们还将通过传递给 jar 的命令行参数将 CSV 文件的文件路径传递给应用程序。

在编辑器中,打开MyFirstScalaSpark.scala文件并添加以下代码:

package com.example
import org.apache.spark.sql.SparkSessionobject MyFirstScalaSpark {
  def main(args: Array[String]) {
    val spark = SparkSession.builder
      .appName("MyFirstScalaSpark")
      .getOrCreate() val filePath = args(0)
    val data = spark.read
      .csv(filePath) println(data.count)
    spark.stop()
  }
}

我们实际上只是添加了使用参数来指定文件路径,并使用它作为用 Spark 打开的文件。Spark 会将该文件加载到一个数据帧中。然后,我们将数据帧中的行数打印到控制台。在 SBT 控制台中再次运行package来构建我们应用程序的新版本。提交构建的应用程序,这次传入我们使用的数据集的文件路径:

spark-submit --master $SPARK_MASTER \
  --class com.example.MyFirstScalaSpark \
  target/scala-2.11/myfirstscalaspark_2.11-1.0.jar \
  /local/UKSA_Oct_18_-_Transparency_Data.csv

在 Spark 的日志输出中,您应该看到数字689。命令行上的快速检查显示了相同的内容:

bash-4.4# wc -l /local/UKSA_Oct_18_-_Transparency_Data.csv
689 /local/UKSA_Oct_18_-_Transparency_Data.csv

获得正确的结构

然而,如果我们想要某种类似于“表格”的数据表示,行数可能不是这样。检查 CSV 文件的第一行显示该文件包含列标题,因此我们实际上只有 688 行数据。让我们来看看我们加载的数据的实际结构。在我们的代码中,我们可以添加data.printSchema来做到这一点:

 ...
    val data = spark.read
      .csv(filePath) **data.printSchema**
    ...

package并提交以查看类似下面的输出:

root
 |-- _c0: string (nullable = true)
 |-- _c1: string (nullable = true)
 |-- _c2: string (nullable = true)
 |-- _c3: string (nullable = true)
 |-- _c4: string (nullable = true)
 |-- _c5: string (nullable = true)
 |-- _c6: string (nullable = true)
 |-- _c7: string (nullable = true)
 |-- _c8: string (nullable = true)
 |-- _c9: string (nullable = true)
 |-- _c10: string (nullable = true)

这并没有告诉我们太多。共有 11 列,都是string类型,而且这些列都没有很好地命名。当使用 Spark 读取 CSV 文件时,我们可以指定一个选项,使用第一行作为列标题,然后使用剩余的行作为“表”的行。我们通过添加到read行将它添加到我们的应用程序中:

 val data = spark.read
      **.option("header", true)**
      .csv(filePath)

运行package构建一个新的 jar,然后再次提交给集群。我们现在应该可以在日志和下面的模式中看到数字688。您可以看到,我们现在有了已命名的列,而不是按位置命名的列:

root
 |-- Department: string (nullable = true)
 |-- Entity: string (nullable = true)
 |-- Date of Payment: string (nullable = true)
 |-- Expense Type: string (nullable = true)
 |-- Expense Area: string (nullable = true)
 |-- Supplier: string (nullable = true)
 |-- Transaction Number: string (nullable = true)
 |-- Amount: string (nullable = true)
 |-- Description: string (nullable = true)
 |-- Supplier Post Code: string (nullable = true)
 |-- Supplier Type: string (nullable = true)

所以我们现在已经有了正确的行数和一个已命名列的结构——太好了!仔细看看这个模式——我们所有的值都是类型string。同样,这不是很有帮助。我们应该和合适的类型一起工作。幸运的是,Spark 提供了另一个选项来尝试并最好地猜测文件的模式:inferSchema。我们可以像对待第一个选项一样,将它添加到我们的代码中:

 val data = spark.read
      .option("header", true)
      **.option("inferSchema", true)**
      .csv(filePath)

package然后提交,您将得到一个稍微改进的模式版本:

root
 |-- Department: string (nullable = true)
 |-- Entity: string (nullable = true)
 |-- Date of Payment: string (nullable = true)
 |-- Expense Type: string (nullable = true)
 |-- Expense Area: string (nullable = true)
 |-- Supplier: string (nullable = true)
 |-- Transaction Number: integer (nullable = true)
 |-- Amount: double (nullable = true)
 |-- Description: string (nullable = true)
 |-- Supplier Post Code: string (nullable = true)
 |-- Supplier Type: string (nullable = true)

更值得注意的是,Transaction NumberAmount字段现在分别是integerdouble类型。其他的都保持为字符串,甚至是Date of Payment列。让我们变得迂腐些,让它成为timestamp类型。再次,火花来拯救!我们可以添加另一个选项来详细说明包含日期的列的格式:

 val data = spark.read
      .option("header", true)
      .option("inferSchema", true)
      **.option("timestampFormat", "dd/MM/yyyy")**
      .csv(filePath)

结果模式应该如下所示:

root
 |-- Department: string (nullable = true)
 |-- Entity: string (nullable = true)
 |-- Date of Payment: timestamp (nullable = true)
 |-- Expense Type: string (nullable = true)
 |-- Expense Area: string (nullable = true)
 |-- Supplier: string (nullable = true)
 |-- Transaction Number: integer (nullable = true)
 |-- Amount: double (nullable = true)
 |-- Description: string (nullable = true)
 |-- Supplier Post Code: string (nullable = true)
 |-- Supplier Type: string (nullable = true)

注意Date of Payment列现在是timestamp类型!我们现在有了一个类似表格的数据表示,其中包含了正确类型的列。来看看我们的数据吧!在data.printSchema行之后,插入以下内容:

 ...
    data.printSchema
    **data.show
    ...**

打包并提交应用程序,在输出日志中,我们将看到显示的前 20 行:

+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+----------+-----------+------------------+-------------+
|          Department|         Entity|    Date of Payment|        Expense Type|        Expense Area|            Supplier|Transaction Number|    Amount|Description|Supplier Post Code|Supplier Type|
+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+----------+-----------+------------------+-------------+
|Department for Bu...|UK Space Agency|2018-10-11 00:00:00|R & D Current Gra...|UK Space Agency -...|SCIENCE AND TECHN...|            241835|   38745.0|       null|           SN2 1SZ|     WGA ONLY|
|Department for Bu...|UK Space Agency|2018-10-17 00:00:00|R & D Printing an...|UK Space Agency -...|ENGINEERING AND P...|            250485|   2256.94|       null|           SN2 1FF|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-23 00:00:00|R & D Other Staff...|UK Space Agency -...|A.M. HEALTH & SAF...|            253816|      37.5|       null|           SN5 6BD|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-17 00:00:00|R & D Other Profe...|UK Space Agency -...|         QINETIQ LTD|            254217|   33320.0|       null|          GU14 0LX|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-17 00:00:00|R & D Other Profe...|UK Space Agency -...|         QINETIQ LTD|            254318|   -5000.0|       null|          GU14 0LX|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-17 00:00:00|R & D Other Profe...|UK Space Agency -...|         QINETIQ LTD|            254318|   10000.0|       null|          GU14 0LX|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00|R & D Other Profe...|         UKSA - UKSA|Border Consulting...|            255630|    571.06|       null|          GU51 3BE|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00|R & D Other Profe...|         UKSA - UKSA|Border Consulting...|            255630|  16289.65|       null|          GU51 3BE|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00|R & D Other Profe...|         UKSA - UKSA|Border Consulting...|            255630|  16289.65|       null|          GU51 3BE|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-02 00:00:00|R & D Subsistence...|         UKSA - UKSA|Personal Expense,...|            256572|      2.42|       null|              null|     EMPLOYEE|
|Department for Bu...|UK Space Agency|2018-10-02 00:00:00|R & D Subsistence...|         UKSA - UKSA|Personal Expense,...|            256572|       5.1|       null|              null|     EMPLOYEE|
|Department for Bu...|UK Space Agency|2018-10-02 00:00:00|R & D Rail Travel...|         UKSA - UKSA|Personal Expense,...|            256572|      35.4|       null|              null|     EMPLOYEE|
|Department for Bu...|UK Space Agency|2018-10-02 00:00:00|R & D Subsistence...|         UKSA - UKSA|Personal Expense,...|            256572|     39.97|       null|              null|     EMPLOYEE|
|Department for Bu...|UK Space Agency|2018-10-26 00:00:00|R & D Other Profe...|UK Space Agency -...|      Cabinet Office|            256868|   -3570.0|       null|           FY5 3FW|     WGA ONLY|
|Department for Bu...|UK Space Agency|2018-10-26 00:00:00|R & D Other Profe...|UK Space Agency -...|      Cabinet Office|            256868|    1230.0|       null|           FY5 3FW|     WGA ONLY|
|Department for Bu...|UK Space Agency|2018-10-26 00:00:00|R & D Other Profe...|UK Space Agency -...|      Cabinet Office|            256868|    5910.0|       null|           FY5 3FW|     WGA ONLY|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00|R & D Current Gra...|UK Space Agency -...|CENTRE NATIONAL D...|            256966|  127900.0|       null|             31401|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00|   R & D Contractors|         UKSA - UKSA|Alexander Mann So...|            257048|   3435.24|       null|          EC2N 3AQ|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00|   R & D Contractors|UK Space Agency -...|Alexander Mann So...|            257065|   2532.19|       null|          EC2N 3AQ|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-02 00:00:00|R & D Current Gra...|UK Space Agency -...|SCIENCE AND TECHN...|            257213|2498072.42|       null|           SN2 1SZ|     WGA ONLY|
+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+----------+-----------+------------------+-------------+
only showing top 20 rows

我们有一个有点宽的表(抱歉的格式!),但你有望看到我们将要使用的一些价值观。

用我们的数据做些什么

现在我们已经有了一个真正的表状数据结构,我们可以开始进行分析了。首先,让我们简单地按Date of Payment列降序排列数据。当我们在数据帧上操作时,Spark 提供了许多函数来执行这样的操作。我们可以简单地使用orderBy函数来做我们想做的事情。我们还将使用desc函数,向它传递我们想要排序的列的名称。Spark 中对数据帧的任何操作都会返回一个新的数据帧,因此我们将把返回的数据帧分配给orderedData并显示它。我们还将输出的行数限制为 5,只是为了保持输出最小化。

 ...
    data.show

    **val orderedData = data.orderBy(desc("Date of Payment"))
    orderedData.show(5)**
    ...

package并提交,我们应该看到以下输出:

+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+--------+-----------+------------------+-------------+
|          Department|         Entity|    Date of Payment|        Expense Type|        Expense Area|            Supplier|Transaction Number|  Amount|Description|Supplier Post Code|Supplier Type|
+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+--------+-----------+------------------+-------------+
|Department for Bu...|UK Space Agency|2018-10-31 00:00:00|R & D Office Supp...|UK Space Agency -...| OFFICE DEPOT UK LTD|            261459|  145.57|       null|          SP10 4JZ|       VENDOR|
|Department for Bu...|UK Space Agency|2018-10-31 00:00:00|  R & D Other Travel|UK Space Agency -...|Personal Expense,...|            261508|    6.14|       null|              null|     EMPLOYEE|
|Department for Bu...|UK Space Agency|2018-10-31 00:00:00|R & D Other Profe...|UK Space Agency -...|Geospatial Insigh...|            261474| 13475.0|       null|           B46 3AD|        GRANT|
|Department for Bu...|UK Space Agency|2018-10-31 00:00:00|R & D Current Gra...|UK Space Agency -...|REACTION ENGINES LTD|            261327|167000.0|       null|          OX14 3DB|        GRANT|
|Department for Bu...|UK Space Agency|2018-10-31 00:00:00|R & D Hotel & Acc...|         UKSA - UKSA|Personal Expense,...|            261505|   114.0|       null|              null|     EMPLOYEE|
+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+--------+-----------+------------------+-------------+
only showing top 5 rows

恭喜你!您已经能够使用 Apache Spark 加载 CSV 文件,并学习了如何使用带有descorderBy方法执行基本排序。

这一版就完成了!下次回来时,我们将研究如何使用 Spark 来回答一些基于我们已有数据的商业问题。

BigQuery 模糊匹配之旅——[ 1,∞)之四——向 FuzzyWuzzy 致敬

原文:https://towardsdatascience.com/a-journey-into-bigquery-fuzzy-matching-4-of-1-a-tribute-to-fuzzywuzzy-54ff73e91a1c?source=collection_archive---------16-----------------------

这是一个正在进行的系列的一部分,还有其他的好处潜伏在那里!所有模糊的善良!

  • 【BigQuery 模糊匹配之旅—1/1,∞) — Soundex
  • 【BigQuery 模糊匹配之旅—2/1,∞) —更多 Soundex 和 Levenshtein 距离
  • 【BigQuery 模糊匹配之旅—3/1,∞) — NYSIIS

好的,我知道在上一篇文章中我说过我们将使用这个开始添加地址元素和匹配组(我保证他们还在路上),但是我想稍微绕一下路,在我们到达那里之前添加另一组函数。

让我们重温一下 Levenshtein 距离函数。之前我们用它来计算两个字符串之间的编辑距离。它旨在确定一个字符串变成另一个字符串所发生的变化的数量,帮助我们确定两个字符串是否应该是相同的。我们看到了如何在单词中使用它,但是当我们开始在越来越复杂的字符串中使用它时会发生什么呢?

在我们进入一些例子之前,让我们首先建立如何计算相似比,以便更容易理解这些比较。这是普通字符与总字符的简单比率。

((|a| + |b|) — ldist(a, b)) / (|a| + |b|)

让我们创建一个函数来计算它,因为我们会经常用到它。

CREATE OR REPLACE FUNCTION
dq.dq_fm_ldist_ratio(a STRING, b STRING) AS ( 
/*
 * Data Quality Function - Fuzzy Matching
 * dq_fm_ldist_ratio
 * input: Two strings to compare.
 * returns: The Levenshtein similarity ratio.
 */
(LENGTH(a) + LENGTH(b) - `dq.dq_fm_LevenshteinDistance`(a, b)) 
  / (LENGTH(a) + LENGTH(b)) 
);

为了了解这些函数如何处理日益复杂的字符串,我们需要一个数据集来测试。我们将使用来自 Expedia 和 Booking.com 的房间描述数据集。我们将把它加载到一个新的数据集中(我将使用fuzzy_matching)并快速浏览一下。

So what are we supposed to call these, then?

这些字符串对代表同一个房间,但你可以看到它们可能被称为不同的东西。当我们深入挖掘数据时,我们会看到一些更复杂的组合。

a != b

因此,让我们尝试使用我们拥有的工具,并将它们应用到这个数据集,看看它们的表现如何(剧透:它不会是准确的)。

Well, it figured one of them out at least.

现在,在我们继续之前,重要的是要注意,Levenshtein 距离可以用两种不同的方式实现,取决于你如何权衡事物。一些实现将替换视为单个操作,替换和添加的权重相等。其他实现方式给替换权重为 2(一个减法+一个加法)。在比较任何实现时,重要的是要注意它是如何权衡的,否则你可能会以无法解释的计算差异而告终。在我们的比赛中,我们用换人作为得分的权重。

回到结果。正如所料,编辑距离非常长,因为我们将整个字符串视为单个标记。正因为如此,匹配率将会很低。我们需要做的是标记化这些字符串,并对它们进行更智能的比较。

输入 FuzzyWuzzy 。字符串匹配库,而不是没有头发的熊。

FuzzyWuzzy 是一个 Python 库,它获取字符串,将其标记,然后以不同的方式匹配它们。这是一个可以利用的非常强大的包,但是 Python 不能被 BigQuery 使用。所以让我们看看我们是否能在 SQL 中复制一些这样的功能!

让我们从令牌排序比率开始。当您有非常相似但顺序不对的字符串标记时,这很方便。令牌排序比率的作用是将字符串分解成单个的令牌,按字母顺序对它们进行排序,将它们连接成一个字符串,然后基于此计算比率。为了实现这一功能,我们首先要创建两个助手函数,它们对数组进行分割、清理和排序。

CREATE OR REPLACE FUNCTION
dq.dq_hf_gh_clean_tokenize(a STRING) AS(
/*
 * (Helper) Data Quality Function
 * dq_hf_gh_clean_tokenize
 * This function removes all non-alphanumeric characters.
 * input: Uncleaned string
 * returns: String of tokenized and cleaned string.
 */
ARRAY(
  SELECT
    tokens
  FROM
    UNNEST(
      SPLIT(
        REGEXP_REPLACE(
          UPPER(
            TRIM(a)
          ), '[^a-zA-Z0-9 ]+', ''
        ), ' '
      )
    ) tokens
) 
);

添加另一个函数对其进行排序。

CREATE OR REPLACE FUNCTION
dq.dq_hf_gh_clean_sort_tokenize(a STRING) AS(
/*
 * (Helper) Data Quality Function
 * dq_hf_gh_clean_sort_tokenize
 * input: Uncleaned string
 * returns: String of tokenized, sorted, and cleaned string.
 */
ARRAY(
  SELECT
    x
  FROM
    UNNEST(`dq.dq_hf_gh_clean_tokenize`(a))
  AS x
  ORDER BY x)) ;

从这里,我们可以重新组装阵列,并进行比较。

CREATE OR REPLACE FUNCTION
dq.dq_fm_ldist_token_sort_ratio(a STRING, b STRING) AS( 
/*
 * Data Quality Function - Fuzzy Matching
 * dq_fm_ldist_token_sort_ratio
 * input: Two strings to compare.
 * returns: The Levenshtein similarity ratio with sorted tokens.
 */ 
`dq.dq_fm_ldist_ratio`(
  ARRAY_TO_STRING(`dq.dq_hf_gh_clean_sort_tokenize`(a),''),
  ARRAY_TO_STRING(`dq.dq_hf_gh_clean_sort_tokenize`(b), '')));

有了这两个,让我们继续将它添加到数据集,看看它是如何表现的。我们正在寻找具有高编辑距离(表明存在大量原始替换,因为一切都是无序的)和高排序率的条目,这意味着各个标记非常相似。

We’re starting to get some better matches!

这些结果表明,您可以使用它来匹配带有无序标记的字符串,同时允许一定程度的字符变化。

当字符串之间有一些共性,但其余字符串的令牌长度和实际内容却大相径庭时,会发生什么呢?这就是令牌集的用武之地!开发和开源 FuzzyWuzzy Python 包的 SeatGeek 的人们在他们的博客上对它做了一个非常好的描述。我建议阅读他们的博客文章,以更好地理解这一切是如何工作的,但这里是它的要点。

1 —对于字符串ab,对这两个字符串进行标记。
2 —创建三个字符串: *t0 = sorted intersection of tokens from a and b t1 = t0 + sorted remainder of tokens from a t2 = t0 + sorted remainder of tokens from b* 3 —从 *ldist(t0,t1)* *ldist(t0,t2)* *ldist(t1,t2)*返回最高比率

为什么会这样?正如 SeatGeek 的人解释的那样,“这里的直觉是,因为 SORTED_INTERSECTION 组件总是完全相同,所以当(a)它在整个字符串中占的百分比更大,并且(b)字符串的剩余部分更相似时,分数会增加。”让我们用一对房间描述来尝试一下,看看这是如何工作的。

a = "Deluxe Room, 1 Queen Bed (High Floor)"
b = "Deluxe Queen Room — High Floor With Free Wi-Fi"

对它们进行清理、排序和标记会给我们带来以下结果:

token_a =
  ['1','BED','DELUXE','FLOOR','HIGH','QUEEN','ROOM']
token_B = 
  ['DELUXE,'FI','FLOOR','FREE','HIGH','QUEEN','ROOM','WI','WITH']

相交的记号是,“豪华”、“楼层”、“高”、“女王”和“房间”。这给了我们以下三个字符串和比较:

t0 = 'DELUXEFLOORHIGHQUEENROOM'
t1 = 'DELUXEFLOORHIGHQUEENROOM1BED'
t2 = 'DELUXEFLOORHIGHQUEENROOMFIFREEWIWITH'`dq.dq_fm_ldist_ratio`(a, b) = 0.64
`dq.dq_fm_ldist_ratio`(t0, t1) = 0.92
`dq.dq_fm_ldist_ratio`(t0, t2) = 0.8
`dq.dq_fm_ldist_ratio`(t1, t2) = 0.83

所以这给了我们 0.92 的置信度,比原来的 0.64 高得多。这是可能的,因为交集由原始字符串的大部分组成,所以自然地,比较会很高。如果交集很小,但是剩余的令牌仍然相似,那么通过比较t1t2,我们仍然可以获得高置信度得分。我们从多个角度被覆盖!

现在让我们弄清楚如何将它放入 BigQuery 函数中。我们在前面已经有了一个函数,可以清理、标记和排序字符串。我们现在需要构造一些东西来找到排序后的交集。

CREATE OR REPLACE FUNCTION
dq.dq_hf_gh_find_array_intersection(a ARRAY<STRING>, b ARRAY<STRING>) AS(
/*
 * (Helper) Data Quality Function
 * dq_hf_gh_find_array_intersection
 * input: Two arrays to compare
 * returns: Array with the common elements
 */
 ARRAY(
    SELECT
      *
    FROM
      UNNEST(a) AS a
    INTERSECT DISTINCT
    SELECT
      *
    FROM
      UNNEST(b) AS b )) ;

我们还需要一些东西来计算两组令牌之间的差异。

CREATE OR REPLACE FUNCTION
dq.dq_hf_gh_find_array_difference(a ARRAY<STRING>, b ARRAY<STRING>) AS(
/*
 * (Helper) Data Quality Function
 * dq_hf_gh_find_array_difference
 * input: Two arrays to compare
 * returns: Array with elements a - b.
 */
 ARRAY(
    SELECT
      *
    FROM
      UNNEST(a) AS a
    EXCEPT DISTINCT
    SELECT
      *
    FROM
      UNNEST(b) AS b )) ;

现在我们只需要创建字符串并找到三次比较的最大值。

CREATE OR REPLACE FUNCTION
dq.dq_fm_ldist_token_set_ratio(a STRING,
    b STRING) AS( 
/*
 * Data Quality Function - Fuzzy Matching
 * dq_fm_ldist_token_set_ratio
 * input: Two strings to compare.
 * returns: The Levenshtein similarity of the maximum ratio
 *   between the different token sets.
 */ 
ARRAY(
  SELECT
    MAX(x)
  FROM
    UNNEST( [
      # First ratio is sorted intersection and combined A diff B
      `dq.dq_fm_ldist_ratio`( 
        ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
          `dq.dq_hf_gh_clean_sort_tokenize`(a),
          `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
        ,
        CONCAT(
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
        , 
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_difference`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')))
    , 
      # Second ratio is sorted intersection and combined B diff A
      `dq.dq_fm_ldist_ratio`(     
        ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
          `dq.dq_hf_gh_clean_sort_tokenize`(a),
          `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
        ,
        CONCAT(
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
        , 
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_difference`(
            `dq.dq_hf_gh_clean_sort_tokenize`(b),
            `dq.dq_hf_gh_clean_sort_tokenize`(a)),'')))
    , 
      # Third ratio is A diff B and B diff A
      `dq.dq_fm_ldist_ratio`(
        CONCAT(
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
          , 
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_difference`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),''))
        ,
        CONCAT(
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
          , 
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_difference`(
            `dq.dq_hf_gh_clean_sort_tokenize`(b),
            `dq.dq_hf_gh_clean_sort_tokenize`(a)),''))) 
    ] ) AS x)[OFFSET(0)]
);

现在让我们在room_data表上运行这个程序,看看我们会得到什么。

Hooray! Matches!

通过一些函数,您现在能够执行一些更复杂的字符串比较。通过对标记集执行编辑距离比较,您可以超越单个单词匹配来查看更广泛的实体。这不仅对产品和描述有用,也适用于地址。地址匹配是实体解析的一个重要部分,像这样的匹配方法是其中的一个重要部分。让我们快速看一下它是什么样子的。

我们将使用帝国大厦的地址,并有目的地以几种不同的方式改变地址。列出的地址是纽约州纽约市第 34 街 20 号,邮编 10001。

These are okay.

考虑到我们只是在看纯粹的令牌字符串比较,这些匹配相当不错。在这些例子中,我们得到了很多变化,因为字符串很短,将像“St”这样小的东西改为“Street”会产生很大的影响。

如果实体的域是预先知道的,比如“我们知道这将是地址数据”,那么让一些令牌得到预处理和标准化确实很有帮助。例如,对于美国的地址,我们通常可以假设“St”和“Street”是相同的,“Ave”和“Avenue”是相同的,等等。这种特定领域的预处理可以帮助我们提高两组数据之间的匹配百分比!

至此,我们的模糊匹配工具箱又多了几个新成员。希望这是对 FuzzyWuzzy 的一个有价值的致敬。有了这些构件,我们可以开始将它们应用于复杂的数据集,并使用它们来构建一些基本的匹配组。我们将在下一轮开始查看这些,敬请关注!

卷积神经网络可视化之旅

原文:https://towardsdatascience.com/a-journey-into-convolutional-neural-network-visualization-1abc71605209?source=collection_archive---------15-----------------------

Photo by Ricardo Rocha on Unsplash

关于计算机视觉有一个著名的都市传说。大约在 80 年代,美国军方希望使用神经网络来自动检测伪装的敌人坦克。他们拍了一些没有坦克的树的照片,然后拍了同样的树后面有坦克的照片。结果令人印象深刻。如此令人印象深刻,以至于军方想确定网络已经正确地概括了。他们拍摄了有坦克和没有坦克的树林的新照片,并在网络上再次展示。这一次,这个模型表现得很糟糕,它无法区分树林后面有坦克的图片和只有树的图片。原来没有坦克的照片都是阴天拍的,而有坦克的照片是晴天拍的!在现实中,网络学习识别天气,而不是敌人的坦克。

源代码可以在这里找到

这篇文章也可以作为交互式 jupyter 笔记本

没有自己的事情

在这篇文章中,我们将看到不同的技术来理解卷积神经网络内部发生了什么,以避免犯同样的美国陆军错误。

我们将使用 Pytorch 。所有的代码都可以在这里找到。大部分可视化都是从零开始开发的,然而,一些灵感和部分是从这里中获取的。

我们将首先介绍每种技术,对其进行简要解释,并在不同经典计算机视觉模型alexnetvgg16resnet之间进行一些示例和比较。然后,我们将尝试更好地理解机器人技术中使用的模型,仅使用正面摄像机的图像来预测本地距离传感器。

我们的目标不是详细解释每种技术是如何工作的,因为每篇论文都已经做得非常好了,而是使用它们来帮助读者可视化不同输入的不同模型,以更好地理解和突出不同模型对给定输入的反应。

稍后,我们将展示一个工作流程,在该流程中,我们将利用您在本次旅程中学到的一些技术来测试模型的健壮性,这对于理解和修复其局限性非常有用。

好奇的读者可以通过查看每个可视化的源代码和阅读参考资料来进一步理解。

序言

让我们从选择一个网络开始我们的旅程。我们的第一个模型将是老学校alexnet。Pytorch 的 torchvision.models包中已经提供了它

AlexNet( (features): Sequential( (0): Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2)) (1): ReLU(inplace) (2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) (3): Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) (4): ReLU(inplace) (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) (6): Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (7): ReLU(inplace) (8): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (9): ReLU(inplace) (10): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (11): ReLU(inplace) (12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) ) (classifier): Sequential( (0): Dropout(p=0.5) (1): Linear(in_features=9216, out_features=4096, bias=True) (2): ReLU(inplace) (3): Dropout(p=0.5) (4): Linear(in_features=4096, out_features=4096, bias=True) (5): ReLU(inplace) (6): Linear(in_features=4096, out_features=1000, bias=True) ) )

现在我们需要一些输入

现在我们需要一些输入图像。我们将使用三张图片,一只猫,美丽的圣彼得大教堂和一只狗和一只猫的图像。

我们装了一些包裹。在utils中,有几个效用函数来创建地块。

由于我们所有的模型都是在 imagenet 上训练的,这是一个包含1000不同类的巨大数据集,我们需要解析并规范化它们。

在 Pytorch 中,我们必须手动将数据发送到设备。在这种情况下,设备如果第一个gpu如果有,否则cpu被选中。

请注意,jupyter 没有垃圾收集,所以我们需要手动释放 gpu 内存。

我们还定义了一个实用函数来清理 gpu 缓存

正如我们所说的,imagenet是一个包含1000类的巨大数据集,由一个不太容易被人类理解的整数表示。我们可以通过加载imaganet2human.txt将每个类 id 与其标签相关联,并创建一个 python 字典。

[(0, 'tench Tinca tinca'), (1, 'goldfish Carassius auratus')]

权重可视化

第一个直观的方法是绘制目标层的权重。显然,当通道数增加时,我们越深入,每个图像变得越小。我们将每个通道显示为灰色阵列图像。不幸的是,每个 Pytorch 模块都可以嵌套,所以为了使我们的代码尽可能通用,我们首先需要跟踪输入遍历的每个子模块,然后按顺序存储每一层。我们首先需要trace我们的模型来获得所有层的列表,这样我们就可以选择一个目标层,而不用遵循模型的嵌套结构。在PyTorch中,模型可以无限嵌套。换句话说,我们在奉承模型的层,这是在[module2traced](https://github.com/FrancescoSaverioZuppichini/A-journey-into-Convolutional-Neural-Network-visualization-/blob/master/utils.py#)函数中实现的。

[Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2)), ReLU(inplace), MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False), Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)), ReLU(inplace), MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False), Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), ReLU(inplace), Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), ReLU(inplace), Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), ReLU(inplace), MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False), Dropout(p=0.5), Linear(in_features=9216, out_features=4096, bias=True), ReLU(inplace), Dropout(p=0.5), Linear(in_features=4096, out_features=4096, bias=True), ReLU(inplace), Linear(in_features=4096, out_features=1000, bias=True)]

让我们画出第一层的重量。我们还打印出重量的形状,以便给读者一个正确的降维概念。

torch.Size([1, 55, 55])

让我们停下来解释一下这些图像代表了什么。我们通过计算图追踪输入,以便找出我们模型的所有层,在本例中是alexnet。然后我们实例化在visualization.core中实现的Weights类,我们通过传递当前输入、图像和目标层来调用它。作为输出,我们将当前层的所有权重作为灰色图像。然后,我们画出其中的 16 个。我们可以注意到,它们在某种程度上是有意义的;例如,图像边缘的一些像素更亮。

让我们绘制第一个MaxPool层,以便更好地看到这种效果,维度减少和一些有趣区域的更高亮度像素。

如果你想知道 maxpolling 操作在做什么,看看这个棒极了的回购

torch.Size([1, 27, 27])

让我们试试另一个输入,圣彼得大教堂

torch.Size([1, 27, 27])

通过观察它们,这些图像在某种程度上变得有意义;他们强调了巴西利卡的布局,但是很难理解这个模型实际上在做什么。我们的想法是,正确地计算一些东西,但是我们可以问一些问题,例如:它是在看圆顶吗?巴西利卡最重要的特征是什么?

此外,我们越深入,就越难识别输入。

torch.Size([1, 13, 13])

在这种情况下,我们不知道发生了什么。可以认为,权重可视化并不携带任何关于模型的有用信息,即使这几乎是真实的,也有一个绘制权重的好理由,尤其是在第一层。

当模型训练很差或根本没有训练时,第一个权重有很多噪声,因为它们只是随机初始化的,并且它们比训练的图像更类似于输入图像。这一特性有助于即时了解模型是否经过训练。然而,除此之外,重量可视化并不是了解您的黑盒在想什么的方法。下面,我们首先为未训练版本的alexnet和训练版本的绘制第一层的权重。

torch.Size([1, 55, 55]) torch.Size([1, 55, 55])

您可以注意到,在第一幅图像中可以更容易地看到输入图像。这不是一个通用的规则,但在某些情况下它会有所帮助。

与其他模型的相似之处

我们已经看到了alexnet的重量,但它们在不同型号之间相似吗?下面我们为alexnetvggresnet绘制每个第一层的前 4 个通道的权重

resnetvgg权重看起来比alexnet更类似于输入图像。但是,这又意味着什么呢?请记住,至少 resnet 的初始化方式与其他两个模型不同。

显著性可视化

深度卷积网络提出的一个想法:可视化图像分类模型和显著图 是相对于目标类别反向支持网络的输出,直到输入并绘制计算的梯度。这将突出显示负责该类的图像部分。先说 alexnet。

让我们首先打印网络的预测(如果重新运行单元,这可能会改变)

predicted class tiger cat

每个可视化都在自己的类中实现。你可以在这里找到代码。它将反向传播与对应于class tiger cat的数字的一个热编码表示相关的输出

我们可以看到alexnet对猫感到兴奋。我们甚至可以做得更好!反向推进时,我们可以将每个设置为0 relu 梯度。这项技术被称为guided

现在我们可以清楚地看到,网络在看猫的眼睛和鼻子。我们可以试着比较不同的模型

Alextnet似乎对眼睛更感兴趣,而VGG看耳朵,resnet 类似于alexnet。现在我们可以清楚地了解输入的哪一部分有助于网络给出预测。

虽然引导产生了更好的人可理解的图像,但是普通的实现可以用于定位感兴趣的对象。换句话说,我们可以通过从输入图像中裁剪出对应于梯度的区域来免费找到感兴趣的对象。让我们为每个模型绘制每个输入图像。

巴西利卡非常有趣,所有四个网络都正确地将其归类为dome,但只有resnet152对天空比对圆顶更感兴趣。在最后一列中,我们有一个包含两个类的图像,dogcat。所有的网络都突出了展台,就像vgg16中的狗的眼睛和猫的耳朵。如果我们只想发现与特定类相关的输入区域,该怎么办?用这种技术是不可能的。

类激活映射

类别激活映射是在学习深度特征用于鉴别定位中提出的技术。其思想是使用最后的卷积层输出和模型的线性层中负责目标类的神经元,通过取它们的点积来生成映射。然而,为了使这个工作,模型必须有一些约束。首先,卷积的输出必须首先通过全局平均轮询,它要求特征映射直接位于 softmax 层之前。为了让它与其他架构一起工作,比如alexnetvgg,我们必须改变模型中的一些层并重新训练它。这是一个主要缺点,将在下一节中解决。目前,我们可以通过 resnet 免费使用它!因为它的建筑是完美的。

实现可以在这里找到。我们可以向可视化传递一个target_class参数,以从 fc 层获得相对权重。

请注意,通过更改目标类,我们可以看到图像的不同部分被突出显示。第一个图像使用预测类,而第二个使用另一种类型的cat和最后一个bookcase,只是为了看看模型会对错误的类做什么。

这是有意义的,唯一的事情是在最后一行我们仍然有猫的一部分为bookcase高亮显示

让我们在不同的resnet建筑的cat图像上绘制 CAM。对于 resnet > 34,使用Bottleneck模块

Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

和预想的都很像。这种技术的一个很大的缺点是强迫你使用一个具有特定架构的网络,在解码器部分之前进行全局轮询。下一种技术通过利用一个特定层的梯度来推广这种方法。记住类激活时,我们使用特征图的权重作为最后一层通道的比例因子。要素地图必须位于 softmax 图层之前和平均池之后。下一项技术提出了一种更通用方法。

Grad Cam

Grad CamGrad-CAM 推出:通过基于梯度的定位从深度网络进行视觉解释。这个想法实际上很简单,我们对目标类的输出进行反投影,同时存储给定层的梯度和输出,在我们的例子中是最后的卷积。然后,我们对保存的梯度进行全局平均,保持信道维度,以获得 1-d 张量,这将表示目标卷积层中每个信道的重要性。然后,我们将卷积层输出的每个元素乘以平均梯度,以创建梯度 cam。整个过程是快速的,并且是独立于体系结构的。有趣的是,作者表明这是先前技术的一种推广。

这里的代码是这里的

我们可以用它来突出不同的模型在看什么。

alexnet看鼻子、vgg看耳朵、resnet看整只猫真的很有趣。有趣的是,这两个版本看起来像猫的不同部位。

下面我们为resnet34绘制了相同的输入,但是我们改变了每一列中的目标类,以向读者展示 grad cam 是如何相应改变的。

注意它们与CAM的输出是多么的相似。为了更好地比较我们的三个模型,下面我们为每个模型的每个输入绘制梯度凸轮

读者可以立即注意到不同型号之间的差异。

有趣的区域

我们之前讨论过有趣的区域本地化。Grad-cam 还可以用于从图像中提取类对象。很容易,一旦有了 grad-cam 图像,我们就可以用它作为蒙版从输入图像中裁剪出我们想要的东西。读者可以使用TR参数来查看不同的效果。

等着瞧!我们也可以再次改变类,并为该类裁剪感兴趣的区域。

不同型号

我们已经看到了在imagenet上训练的经典分类模型使用的所有这些技术。在不同领域使用它们怎么样?我已经把这篇论文移植到 Pytorch 并重新训练了它。该模型通过学习机器人正面摄像机的图像来预测本地距离传感器,以避开障碍物。让我们看看,通过使用这些技术,我们是否能更好地理解模型内部的情况。

使用来自短程传感器和里程计的自我监督学习远程感知

其思想是在给定远程传感器(如摄像机)的当前输出的情况下,预测短程传感器(如近程传感器)的未来输出。他们从机器人的相机图像中训练了一个非常简单的 CNN 来预测接近传感器的值。如果你对他们的工作感兴趣,你可以在这里阅读全文

我做了一个 PyTorch 实现,并从头开始重新训练这个模型。请注意,我没有微调或尝试不同的超参数集,所以我的模型可能没有作者的模型表现得好。

让我们导入它

我们知道需要一些输入来测试模型,它们直接取自测试集

然后作者标准化每张图片,这是由 callind pre_processing完成的。由于某种原因,在 mac 和 ubuntu 上的输入图像是不同的,如果你在 mac 上运行笔记本,结果是不同的。这可能是由于警告消息。

我们将使用SaliencyMapGradCam,因为它们是最好的

我们可以清楚地看到模型注视着物体。在第二张图片的GradCam行中,计划基本上由热图分割。有一个问题,如果你看第三张图,相机前面的白色方框没有被清晰地突出。这可能是因为地板的白色与盒子的颜色非常相似。我们来调查一下这个问题。

在第二行中,SaliencyMaps高亮显示所有对象,包括白色框。读者可以注意到,左边第一张图中的反射似乎激发了该区域的网络。我们还应该调查这个案例,但是由于时间限制,我们将把它作为一个练习留给好奇的读者。

为了完整起见,让我们也打印预测的传感器输出。该模型试图预测五个正面距离传感器给图像相机。

如果你和作者的照片比较,我的预测会更糟。这是因为为了加快速度,我没有使用所有的训练集,也没有进行任何超参数优化。所有的代码都可以在这里找到。现在让我们研究第一个问题,与地面颜色相似的物体。

相似的颜色

为了测试模型是否有一个与地面颜色相同的障碍物的问题,我们在 blender 中创建了四个不同的障碍物场景。如下图所示。

有四种不同的灯光配置和两种不同的立方体颜色,一种与地面相同,另一种不同。第一列代表真实的情况,而第二列有来自后面的非常强的光,在相机前面产生阴影。第三列左边有阴影,最后一列左边有一点阴影。

这是使用 gradcam 查看每个图像中的模型的完美场景。在下图中,我们绘制了 gradcam 结果。

第二列中的大阴影肯定会混淆模型。在第一列和最后一列,grad cam 更好地突出了红色立方体的角,尤其是在第一张图片中。我们可以肯定地说,这个模型与地面颜色相同的物体有些困难。由于这种考虑,我们可以改进数据集中相等对象/背景的数量,执行更好的预处理,改变模型结构等,并且有希望增加网络的鲁棒性。

结论

在这篇文章中,我们提出了不同的卷积神经网络可视化技术。在第一部分中,我们通过应用于一组著名的分类网络来介绍每一个。我们比较了不同输入的不同网络,并强调了它们之间的相似性和差异。然后,我们将它们应用于机器人学中采用的模型,以测试其鲁棒性,我们能够成功地揭示网络中的问题。

此外,作为一个附带项目,我开发了一个名为 mirro r 的交互式卷积神经网络可视化应用程序,它在短短几天内就在 GitHub 上收到了一百多颗星,反映了深度学习社区对这个主题的兴趣。

所有这些可视化都是使用一个公共接口实现的,并且可以作为 python 模块使用,因此它们可以在任何其他模块中使用。

感谢您的阅读

一种用于图像分割的 Keras 流水线

原文:https://towardsdatascience.com/a-keras-pipeline-for-image-segmentation-part-1-6515a421157d?source=collection_archive---------2-----------------------

Photo by Soragrit Wongsa on Unsplash

网上有数百个教程,教你如何使用 Keras 完成图像分割任务。这些非常有帮助,通常对您的用例来说已经足够了。然而,对于初学者来说,即使是从普通的深度学习任务开始,也可能显得势不可挡。在开始训练过程之前,有一些普通的操作需要完成——准备数据,创建分区(train,val,test ),准备模型。在本教程(分为 3 个部分)中,我试图创建一个可访问的整个图像分割管道的演练。这包括:

a)创建和结构化数据集

b)生成训练和评估图像

c)模型选择、加载和编译以及培训。

希望在本课程结束时,您能够轻松地尝试自己的图像分割初学者项目,或者任何此类专注于图像的深度学习问题。

我们开始吧!

第一部分:数据集

图像分割中的问题稍微复杂一点(不像分类),因为你必须跟踪你的图像它们的遮罩。

通常,你会使用 PASCAL VOC ,或者 MS COCO ,或者 Cityscapes ,这取决于你想要解决什么问题。

如果是这样的话,那么您的大部分工作就完成了,因为这些存储库已经为您创建了 train、val 和 test 集。你所要做的就是下载它们,并把它们放到相关的目录中[更多细节见下文]。

但是,如果您希望在自己的数据集上运行图像分割模型,请参考以下内容:

Structure of your data

其中 mask_001.png 对应 frame_001.png 的掩码,以此类推。

对于那些已经在使用我上面提到的公共数据集的人来说,你所要做的就是保持上面提到的目录结构。

对于其他使用自己的数据集的人,您需要编写一个脚本来完成这项工作。我写了一个给你参考:

让我们浏览一下这段代码。

我假设所有的图像都在“帧”目录中,相应的蒙版在“蒙版”目录中,都在DATA_PATH

随机化 train、test 和 val 分区的一个好方法是列出文件,按 id 对它们进行排序并对它们进行洗牌【注意使用一个恒定的随机种子——改变的种子将在洗牌中产生改变的顺序】。

这就是线23–34所实现的。

接下来,我们分别为我们的训练集、val 集和测试集使用一个70–20–10比率。这是通常使用的测试,尽管60–30–1080–10–10并非闻所未闻。这是 Python 中一个简单的列表索引操作。

我们在第39–44行中这样做。

随后的几行运行一个 list comprehension 来遍历所有帧,并简单地将训练帧添加到 train_frames ,将验证帧添加到 val_frames ,将测试帧添加到 test_frames

我们现在有了包含图像 id 的必要列表。但是,我们仍然需要将这些列表中的图像保存到相应的[正确]文件夹中。函数 add_frames()add_masks() 对此有所帮助。

正如您可能已经猜到的,有多种方法可以做到这一点。你可以通过实验找到最快的的方法,但是我发现了一个相当有效的方法:

  1. 从两个元组列表开始。元组构成了图像列表,以及它们相应的目录名。将这些 frame_foldersmask_folders ,前者保存我们所有帧列表的细节——train、val、test——后者保存我们所有 mask 列表的细节。
  2. 遍历 frame_foldersmask_folders【一个接一个】,使用 map() 函数将每张图片分别映射到 add_frames()add_masks() 函数。我使用 map 代替琐碎的循环,只是因为 Python 的内置 map()快得多。我还没有测试它更快的确切顺序,如果有读者这样做,我会很高兴。**

对于 1000 个图像[+1000 个遮罩]的非常小的数据集,设置文件夹只需不到一分钟的时间。一个很好的实验是找到更快的方法来做到这一点。我很想听听你的想法。

这样,我们就有了数据集!

第 1 部分到此结束。

在第 2 部分中,我们将研究图像分割管道的另一个重要方面——为训练生成批量图像。

在本教程的第一部分,我们学习了如何准备和组织我们的图像分割任务中使用的数据。在这一部分,我们将我们的任务向前推进了一步——生成这些图像。

第 2 部分:发电机

Keras 图像数据生成器

为了训练你的模型,理想情况下你需要生成一批图像来支持它。当你这样做的时候,你可能想对所有的图像进行普通的操作——像缩放、旋转、裁剪和移动等操作。这被称为数据增强。事实上,一个非常常见的做法是将所有图像的大小调整为一个形状,以使训练过程统一。

请注意,数据扩充不会改变你的图像——它只是创建了同一图像的另一种表示。想象一下,如果有人给你拍了一张照片,然后将这张照片旋转了某个角度。这是两张不同的图片,但是图片的对象【你】没有变化。

为了实现这一点,我们使用 Keras 的 ImageDataGenerator

根据文件:

通过实时数据扩充生成批量张量图像数据。数据将(分批)循环。

我们分别创建我们的训练和验证生成器对象。您可以看到,训练图像将通过重新缩放、水平翻转、剪切范围和缩放范围得到增强。

对于这些操作意味着什么的描述,更重要的是,它们看起来像什么,到这里

当谈到如何初始化对象时,没有唯一正确的答案。这取决于谁在设计它们,以及他的目标是什么。

现在我们的生成器对象已经创建好了,我们使用非常有用的flow_from_directory():来启动生成过程

我们需要向 Keras 提供的只是目录路径和批处理大小。还有其他的选择,但是现在,这已经足够让你开始了。

最后,一旦我们分别有了训练集和验证集的框架和掩码生成器,我们就 zip() 它们一起创建:

a) train_generator :训练帧和掩码的生成器。

b) val_generator :验证帧和掩码的生成器。

创建您自己的数据生成器

在设计生成器时,Keras ImageDataGenerator 绝不是唯一的选择。自定义生成器也经常使用。这些为设计者提供了更大的选择灵活性。请参见下面的示例:

我们已经决定让所有图像的大小为(512 * 512 * n),其中 n = 3,如果它是正常的 RGB 图像,n = 1,用于该图像的相应蒙版,这显然是灰度图像。

我们初始化两个数组来保存每个图像(和每个遮罩)的细节,这将是三维数组本身。所以, img遮罩是数组的数组。

我们使用 yield 的简单目的是生成一批图像,而不是使用 return 一次生成所有图像。关于何时使用其中一个而不是另一个的清晰解释,请参见

最后,我们创建我们的训练和验证生成器,通过一次 传递训练图像、遮罩路径和验证图像、遮罩路径以及批处理大小。****

然而,在这种情况下,我们并没有即时使用随机变换。假设您正在处理一个图像分割问题,其中要分割的对象的位置也很重要。你还会使用旋转、缩放和移动吗?精神食粮。

归根结底,这都是个人的选择。这两种方法都有效。在特定情况下,人们可能会发现一种方法比另一种更有用,反之亦然。

太好了!现在我们已经准备好了生成器对象。

训练时间到了!

第 3 部分:培训

在前两节中,我们学习了如何准备数据,以及如何创建图像生成器来帮助培训。在这最后一部分,我们将看到如何使用这些生成器来训练我们的模型。

这部分将结束我们的整个管道。

在我们开始训练之前,我们需要决定使用哪种架构。幸运的是,大多数流行的都已经实现了,并免费提供给公众使用。一些例子包括:

  1. Keras UNet 实施
  2. Keras FCNet 实现。

开始时,您不必太担心这些体系结构中的差异,以及在哪里使用什么。到目前为止,您可以简单地将这个 model.py 文件放在您的工作目录中,并将其导入到 train.py 中,这将是培训代码所在的文件。

希望您的工作目录如下所示:

请注意新的代码文件,以及我们之前看到的数据目录。

假设您正在使用 FCNet_VGG16_32s ,让我们来看看加载、编译和运行模型的一行程序。

在必要的导入之后,第8–13行初始化完全取决于您的数据集和您选择的输入的变量——例如:您决定的批量大小,以及您的模型将训练的时期数。

线 15 初始化路径,每个时期后的权重[一个 .h5 文件]将被保存到该路径。

17–22 行是加载和编译模型的必要步骤。请注意,我没有指定使用什么度量标准。对于图像分割任务,一个流行的度量是骰子系数【反之,骰子损失】。这里可以找到一个很好的实现

24–32行也是样板 Keras 代码,封装在一系列称为回调的操作下。

仅当满足模式参数时,我们才使用模型检查点来保存权重。要了解什么是监视器模式参数,请继续阅读。

我们确保我们的模型不会在不必要的长时间内训练,例如:如果损失在连续的时期内没有显著减少,我们设置一个耐心参数,在我们的损失没有显著减少的一定数量的时期后自动停止训练。当我提到“显著”时,我指的是 min_delta 参数。在这种情况下,我们检查我们的损失是否至少减少了 0.1%。在这种情况下,我们的耐心是 3 ,这是连续周期的数量,在此之后,如果损失没有减少至少 0.1,训练将自动停止。

****监视器参数定义了您想要检查其值的指标——在我们的例子中,是骰子损失。模式参数定义了训练停止的时间,如果监控量减少,则为【最大】,如果增加,则为【最小】

所以,如果你在监控精度,模式应该是最大。但是如果你在监控均方差,模式将会是最小

这整个现象叫做。希望到现在为止,你已经理解了为什么这么叫了。****

第 34 行是训练步骤。我们传递所有需要的输入,包括:

a)训练和验证图像生成器,如前所述。

b)历元的数量。

c)每个时期的步骤数取决于图像总数和批次大小。

d)最后,我们的回调列表,包括模型检查点和提前停止的条件。

最后我们调用 fit_generator 在这些生成器上进行训练。

训练开始了!

一旦训练完成,您可以使用保存功能保存检查点架构及其所有权重。你可以随便给它起什么名字。

摘要

在这个由三部分组成的系列中,我们介绍了图像分割任务的整个 Keras 流程。从构建数据,到创建图像生成器,再到最终训练我们的模型,我们已经为初学者介绍了足够多的内容。当然,我们还可以做更多的事情。

您可以尝试不同的架构、不同的超参数(比如使用不同于 Adam 的优化器)、不同的停止条件(使用耐心参数)等等。

一个好主意是为不同的超参数绘制提前停止之前的时期数,评估度量值,并检查是否存在任何最佳超参数-模型-时期组合。

我希望这个系列是可以理解的,如果有任何部分不清楚,我很乐意听到你的问题。

快乐深度学习!

深度神经网络的外行指南

原文:https://towardsdatascience.com/a-laymans-guide-to-deep-neural-networks-ddcea24847fb?source=collection_archive---------1-----------------------

深度学习基础

用 PyTorch 对深度神经网络的非数学介绍

序幕

最近关于人工智能的讨论已经在学术界和企业的神经网络中产生了足够的意识。你可能肯定遇到过强调某种形式的人工智能/神经网络系统将超越你的传统工作流程的内容。我相信你肯定听说过(尽管可能没有完全意识到)深度神经网络和深度学习。

在这篇文章中,我想用最短但有效的方法来介绍这个主题,以拥抱深度神经网络并使用 PyTorch 实现它们。

深度神经网络的外行定义,也称为深度学习

取 1

深度学习是人工智能(A.I .)中机器学习的一个子领域,它处理从大脑的生物结构和功能中获得灵感的算法,以帮助机器获得智能。

听起来复杂吗?让我们通过进一步分解定义中的每个单词来简化它,并再次与定义进行讨论。我们将首先从人工智能开始 A.I

Source — Learn Keras for Deep Neural Networks (Apress)

人工智能(A.I .)最一般的形式可以被定义为引入机器的智能质量。机器通常是愚蠢的,所以为了让它们更聪明,我们引入了某种智能,这样它们就可以独立做出决定。比如说,洗衣机可以决定摄入适量的水,决定浸泡、洗涤和脱水所需的时间,即在提供特定输入时做出决定,从而以更智能的方式工作。类似地,一台 ATM 机,它可以根据机器中可用的纸币的正确组合来支付你想要的金额。这种智能在技术上是以人工方式引入机器的,这就是为什么称之为人工智能的原因。

这里需要注意的重要一点是,这种智能是明确编程的,比如一个 if-else 规则的综合列表。设计系统的工程师仔细考虑了所有可能的组合,并设计了一个基于规则的系统,该系统可以通过遍历定义的规则路径来做出决定。如果我们需要在没有显式编程的情况下在机器中引入智能,可能是机器可以自己学习的东西,会怎么样。那就是我们用机器学习触底的时候。

机器学习可以定义为在没有显式编程的情况下,将智能诱导到系统或机器中的过程

  • 安德鲁·吴,斯坦福兼职教授

机器学习的例子可以是通过从历史测试结果和学生属性中学习来预测学生是否会在测试中失败或通过的系统。在这里,系统并没有编码有所有可能的规则的综合列表,这些规则可以决定学生是通过还是失败,相反,系统根据它从输入的历史训练数据中识别的模式进行自我学习。

那么,深度学习在这种背景下处于什么位置呢?碰巧的是,机器学习虽然对各种问题都非常有效,但在一些对人类来说非常容易的特定情况下却无法超越。例如,将图像分类为猫或狗,或者将音频剪辑区分为男性或女性声音等。机器学习通常在处理图像、音频和其他非结构化数据类型时表现不佳。在研究这种糟糕表现的原因时,一种灵感的想法导致了模仿人脑生物过程的想法,这种过程由数十亿神经元连接和协调组成,以适应学习新事物。与此同时,神经网络已经成为一个研究课题好几年了,并且由于当时计算和数据的限制,只取得了有限的进展。当研究人员到达机器学习和神经网络的尖端时,出现了深度学习领域,该领域通过开发深度神经网络来构建,即具有更多层的临时神经网络。

现在,让我们再做一次尝试来理解深度学习的定义。

取 2

深度学习是机器学习和人工智能(A.I .)中的一个领域,它处理从人脑中获得灵感的算法,在没有显式编程的情况下帮助机器获得智能。

现在不是更容易理解了吗?😃

深度学习擅长于机器学习落后的新领域。随着时间的推移,额外的研究和实验导致了这样一种理解,即我们可以利用深度学习来完成所有机器学习任务,并期望在有剩余数据可用的情况下获得更好的性能。因此,深度学习成为解决预测问题的无处不在的领域,而不仅仅局限于计算机视觉、语音等领域。

今天深度学习解决了哪些问题?

随着经济高效的计算能力和数据存储的出现,深度学习已经融入到我们日常生活的每个数字角落。基于深度学习的常见日常生活数字产品的几个例子是流行的虚拟助手,如Siri/Alexa/Google Assistant,在上传的脸书照片中标记朋友的建议,特斯拉中的自动驾驶, Snapchat 中的猫滤镜,亚马逊网飞中的产品推荐,以及最近流行的照片应用,如【face app你可能已经在没有意识到的情况下使用了基于深度学习的产品。

深度学习已经涉足几乎所有的行业垂直领域,如检测癌症和糖尿病视网膜病变的医疗保健、车队优化的航空、机器预测维护的石油&天然气、欺诈检测的银行&金融服务、客户流失预测的零售电信等等。Andrew NG 正确地引用了人工智能是新的电力。就像电改变了一切一样,在不久的将来,人工智能将改变几乎一切。

分解深层神经网络

深度神经网络的简化版本被表示为与其他神经元连接的神经元(类似于大脑中的神经元)的分级(分层)组织。这些神经元根据收到的输入向其他神经元传递消息或信号,并形成一个复杂的网络,通过某种反馈机制进行学习。下图表示一个“N”层深度神经网络。

A Deep Neural Network with N hidden layers

如上图所示,输入数据由第一层(未隐藏)中的神经元消耗,然后向下一层中的神经元提供输出,依此类推,提供最终输出。输出可能是“是”或“否”这样的预测(用概率表示)。每层可以有一个或多个神经元,每个神经元将计算一个小函数,即激活函数。激活功能模拟信号传递给下一个连接的神经元。如果输入神经元产生大于阈值的值,则输出被传递,否则被忽略。连续层的两个神经元之间的连接将具有关联的权重。权重定义了输入对下一个神经元的输出的影响,以及最终对整个最终输出的影响。在神经网络中,初始权重将全部是随机的,但是在模型训练期间,这些权重被迭代地更新,以学习预测正确的输出。分解网络,我们可以定义几个逻辑构建块,如一个神经元权重输入输出、一个激活函数以及最后一个 l 收益机制(优化器),这将帮助神经网络递增地更新权重(随机初始化的)为更合适的权重,从而有助于正确预测结果。

为了直观的理解,让我们举一个人类大脑如何学习识别不同人的例子。当你第二次见到一个人时,你就能认出他。这是怎么发生的?人在整体结构上有相似之处;两只眼睛,两只耳朵,一个鼻子,嘴唇等等。每个人都有相同的结构,但我们能够很容易地区分人,对不对?

大脑中学习过程的本质是相当直观的。它不是学习面部的结构来识别人,而是学习与普通面部的偏差,即他的眼睛与参考眼睛有多不同,然后可以量化为具有定义强度的电信号。类似地,它从参考基准学习面部所有部分的偏差,并将这些偏差组合成新的维度,并最终给出输出。所有这一切都发生在不到一秒钟的时间里,我们没有人意识到我们的潜意识实际上做了什么。

类似地,上面展示的神经网络试图使用数学方法来模拟相同的过程。输入由第一层中的神经元消耗,并且在每个神经元内计算激活函数。根据一个简单的规则,它将输出转发给下一个神经元,类似于人脑学习的偏差。神经元的输出越大,输入维度的重要性就越大。这些维度然后在下一层被组合起来形成额外的新维度,这是我们可能无法理解的。但是系统凭直觉学习。这一过程,当乘以几倍,发展成一个复杂的网络与几个连接。

现在已经了解了神经网络的结构,让我们来了解学习是如何发生的。当我们向已定义的结构提供输入数据时,最终输出将是一个预测(通过一系列矩阵乘法),它可能是正确的,也可能是不正确的。基于该输出,如果我们向网络提供反馈,以使用一些手段来改进,从而更好地预测,则系统通过更新连接的权重来学习。为了实现以正确的方式提供反馈和定义下一步进行更改的过程,我们使用了一种美丽的数学算法,称为“”。随着越来越多的数据逐步迭代该过程几次,有助于网络适当地更新权重,以创建一个系统,在该系统中,它可以根据它通过权重和连接为自己创建的规则来做出预测输出的决策。

深度神经网络的名称是从使用更多隐藏层演变而来的,使其成为学习更复杂模式的“深度”网络。深度学习的成功故事只是在最近几年才浮出水面,因为训练网络的过程计算量很大,需要大量数据。只有当计算和数据存储变得更加可用和经济实惠时,这些实验才最终得以实现。

深度学习有哪些流行的框架?

鉴于深度学习的采用已经以惊人的速度推进,生态系统的成熟度也显示出惊人的提高。多亏了许多大型技术组织和开源项目,我们现在有了太多的选择。这些深度学习框架为我们提供了可重用的代码块,这些代码块抽象了我们上面讨论的逻辑块,并在开发深度学习模型时提供了几个额外的便利模块。

我们可以将可用选项分类为低级或高级深度学习框架。虽然这绝不是业界公认的术语,但我们可以使用这种分离来更直观地理解框架。低级框架提供了更基本的抽象块,同时为定制和灵活性提供了大量空间。高级框架进一步聚合了抽象以简化我们的工作,同时限制了定制和灵活性的范围。高级框架使用低级框架作为后端,并且通常通过将源代码转换成期望的低级框架来执行。下面是深度学习框架的几个流行选择。

低层框架

  1. 张量流
  2. MxNet
  3. PyTorch

高层框架

  1. Keras(使用 TensorFlow 作为后端)
  2. 胶子(使用 mxnet 作为后端)

目前,最受欢迎的选择是 Tensorflow(由谷歌提供)。鉴于 Keras 在快速构建深度学习模型方面提供的便利,它也很受欢迎。然而,PyTorch(由脸书开发)是另一个流行的框架,它正以惊人的速度赶上这场竞赛。PyTorch 对于许多人工智能实践者来说是一个很好的选择,比 TensorFlow 有更容易的学习曲线,可以轻松地从原型开发到生产深度学习模型。

在本教程中,我们更喜欢使用 PyTorch 来实现一个婴儿神经网络。在决定选择框架之前,您应该进行更多的调查和研究。Skymind 的这篇 文章 提供了很好的对比和细节,有助于确定您需要的框架。

然而,这篇文章不会介绍 PyTorch。我会推荐探索 PyTorch 的官方教程。此外,猫王的这本指南对于 PyTorch 初学者来说也是一篇不错的文章。

用 PyTorch 构建婴儿神经网络

对这个主题有了一个基本的外行概述,我们现在可以开始在 PyTorch 中构建一个基本的神经网络。在本例中,我们生成了一个虚拟数据集,它模拟了一个具有 32 个特征(列)和 6000 个样本(行)的分类用例。数据集将使用 PyTorch 中的 randn 函数进行渲染。

这段代码也可以从 Github 库获得

总结想法

这篇文章的目的是用一种非常简单的语言给初学者一个简单的入门。保持数学的抽象和专注,从纯粹的功能性手段来利用现代企业项目的深度学习。大部分内容都是从我的书‘学习深度神经网络的 Keras’的第一章借来的。

在下一篇文章中,我将介绍“卷积神经网络的外行指南”,同样的例子将在 PyTorch 中给出。

从喀拉斯到皮托尔彻的专家指南

原文:https://towardsdatascience.com/a-laymans-guide-to-moving-from-keras-to-pytorch-37fe56b6f588?source=collection_archive---------26-----------------------

说真的,是时候搬家了

最近我在 Kaggle 上开始了一场关于文本分类的比赛,作为比赛的一部分,我不得不设法转移到 Pytorch 上以获得确定性的结果。现在,我过去一直与 keras 一起工作,它给了我相当好的结果,但不知何故,我知道 Keras 中的 CuDNNGRU/CuDNNLSTM 层不是确定性的,即使在设置种子之后。所以 Pytorch 来营救了。我很高兴我考虑过搬家。

作为边注:如果你想了解更多关于 NLP 的知识,我在此推荐 高级机器学习专精 中关于 自然语言处理 的这门牛逼课程。本课程涵盖了自然语言处理中从基础到高级的各种任务:情感分析、摘要、对话状态跟踪等等。

好吧,回到手头的任务。虽然 Keras 从深度学习开始很好,但随着时间的推移,你会对它的一些局限性感到不满。我考虑过搬到 Tensorflow。这似乎是一个很好的过渡,因为 TF 是 Keras 的后端。但是这很难吗?对于整个session.run命令和张量流会话,我有点困惑。它根本不是毕氏的。

Pytorch 在这方面有所帮助,因为它看起来像是 python 做事的方式。一切都在你的掌控之中,在性能方面没有任何损失。用安德烈·卡帕西的话说:

我已经使用 PyTorch 几个月了,从来没有感觉这么好过。我有更多的精力。我的皮肤更干净了。我的视力提高了。

—安德烈·卡帕西(@卡帕西)2017 年 5 月 26 日

所以事不宜迟,让我为你把 Keras 翻译成 Pytorch。

写你的网络的经典方式?

好,让我们首先在 keras 中创建一个示例网络,我们将尝试将它移植到 Pytorch 中。在这里,我也想给你一个建议。当你试图从 Keras 迁移到 Pytorch 时,使用你拥有的任何网络,并尝试将其移植到 Pytorch 。这会让你更好地理解 Pytorch。在这里,我试着写一个在 Quora 虚假问题分类挑战中给我很好结果的网络。这个模型具有至少任何文本分类深度学习网络可以包含的所有功能,包括 GRU、LSTM 和嵌入层,以及元输入层。因此可以作为一个很好的例子。如果你想了解更多关于比尔斯特姆/GRU 和注意力模型是如何工作的,请访问我的帖子这里

因此 pytorch 中的模型被定义为一个从nn.module继承而来的类(因此更优雅一点)。每个类都必须包含一个__init__程序块和一个forward通道块。

  • __init__部分,用户定义了网络将要拥有的所有层,但还没有定义这些层如何相互连接
  • 在正向传递模块中,用户定义数据如何在网络中从一层流向另一层。

为什么这是经典?

显然是因为上课而显得优雅。咄!但玩笑归玩笑,我发现它是有益的,原因有几个:

1)它让你对如何构建你的网络有很大的控制权。

2)当您构建网络时,您对网络有很多了解,因为您必须指定输入和输出维度。所以出错的几率更小。(虽然这个真的要看技能水平了)

  1. 易于调试的网络。任何时候你发现网络有任何问题,只要在正向传递中使用类似print("avg_pool", avg_pool.size())的东西来检查层的大小,你就可以很容易地调试网络

4)您可以从正向层返回多个输出。这在编码器-解码器架构中非常有用,因为您可以返回编码器和解码器的输出。或者在 autoencoder 的情况下,您可以返回模型的输出和数据的隐藏层嵌入。

  1. Pytorch 张量的工作方式与 numpy 数组非常相似。例如,我可以使用 Pytorch Maxpool 函数来编写 Maxpool 层,但是max_pool, _ = torch.max(h_gru, 1)也可以。

6)您可以用不同的初始化方案设置不同的层。一些你在喀拉斯做不到的事。例如,在下面的网络中,我改变了我的 LSTM 层的初始化方案。LSTM 图层对于偏差、输入图层权重和隐藏图层权重具有不同的初始化。

7)等到你看到 Pytorch 中的训练循环时,你会对它提供的控制感到惊讶。

现在 Pytorch 中的同一个模型看起来会像这样。请仔细阅读代码注释,了解更多关于如何移植的信息。

希望你还和我在一起。我想在这里强调的一点是,你需要用 Pytorch 编写一些代码来真正理解它是如何工作的。并且知道一旦你这样做了,你会很高兴你付出了努力。进入下一部分。

定制或现成:高度可定制的训练循环的最佳选择

在上面的部分,我写道,一旦你看到训练循环,你会感到惊讶。这是一种夸张。第一次尝试时,你会有点困惑。但是一旦你不止一次地通读这个循环,你会有很多直观的感觉。再次阅读注释和代码以获得更好的理解。

该训练循环对训练数据进行 k 重交叉验证,并输出对测试数据的运行进行平均的非折叠 train_preds 和 test_preds。如果这个流程看起来像是从 kaggle 竞赛中直接出来的,我很抱歉,但是如果你明白这一点,你就能够为自己的工作流程创建一个训练循环。这就是 Pytorch 的魅力。

所以这个循环的简要总结如下:

  • 使用培训数据创建分层拆分
  • 循环遍历拆分。
  • 使用X_train_fold = torch.tensor(x_train[train_idx.astype(int)], dtype=torch.long).cuda()命令将训练和 CV 数据转换为张量并将数据加载到 GPU
  • 使用model.cuda()命令将模型加载到 GPU 上
  • 定义损失函数、调度程序和优化程序
  • 创建train_loader和 valid_loader `来迭代批处理。
  • 开始运行纪元。在每个时代
  • 使用model.train()将模型模式设置为训练。
  • 检查train_loader中的批次并向前运行
  • 运行调度程序步骤以更改学习率
  • 计算损失
  • 将优化器中的现有梯度设置为零
  • 通过网络反向传播损失
  • 剪切渐变
  • 采取优化步骤来改变整个网络中的权重
  • 使用model.eval()将模型模式设置为评估。
  • 使用valid_loader获得验证数据的预测,并存储在变量valid_preds_fold
  • 计算损失并打印
  • 所有历元完成后,预测测试数据并存储预测。这些预测将在分割循环结束时进行平均,以获得最终的test_preds
  • 使用train_preds[valid_idx] = valid_preds_fold获得列车组的离差(OOF)预测
  • 然后,这些 OOF 预测可用于计算模型的局部 CV 分数。

但是为什么呢?为什么这么多代码?

好吧。我明白了。这可能是少数。在 keras 中用一个简单的.fit就可以完成的事情,在 Pytorch 中需要大量代码才能完成。但要明白,你也获得了很多权力。您需要了解的一些使用案例:

  • 在 Keras 中,您有预先指定的调度程序,如ReduceLROnPlateau(编写它们是一项任务),而在 Pytorch 中,您可以疯狂地尝试。如果你知道如何写 Python,你会过得很好
  • 想在两个时期之间改变模型的结构。是的,你能做到。动态更改卷积网络的输入大小。
  • 还有更多。只有你的想象会阻止你。

想自己经营吗?

You have all the tools! Do something…

这里还有一个小小的坦白。上面的代码将不会运行,因为有一些代码工件,我没有在这里显示。我这样做是为了让帖子更具可读性。就像你在上面的代码中看到的seed_everythingMyDatasetCyclicLR(来自杰瑞米·霍华德课程)函数和类,它们并没有真正包含在 Pytorch 中。但别担心,我的朋友。

我试过用完整的运行代码写一个 Kaggle 内核您可以在这里看到代码,并将其包含在您的项目中。

如果你喜欢这个帖子,请不要忘记也投票支持 内核 。我将不胜感激。

尾注和参考文献

这篇文章是许多优秀的 Kagglers 们努力的结果,我将在这一部分尝试引用他们。如果我漏掉了某个人,请理解我不是故意的。

原载于 2019 年 1 月 6 日mlwhiz.com

精益预测工作流程

原文:https://towardsdatascience.com/a-lean-forecasting-workflow-1a8a5eb2d4ab?source=collection_archive---------23-----------------------

如何使用精益数据科学工作流程创建良好的业务预测

Photo by Felix Wegerer on Unsplash

介绍

商业预测的工作基本上类似于典型的数据科学项目,但是它需要自己的调整才能正确完成。在本文中,我们打算应用精益框架,不仅产生良好的预测,而且确保您的流程为预测质量增值。

在这里,我们预测问题的例子将是预测一个零售连锁店的收入,但是它可以应用于许多其他用例。

工作流程

请求

这是你的客户提出他的预测请求的地方,你将开始发展你的业务理解。你可能有的许多问题会在这个过程的后期出现,但是没关系:只要确保你在一开始就已经涵盖了最重要的主题。以下是一些有用的问题:

  • 这些预测的目标是什么(了解你的总收入结构,指导生产决策,向股东报告…)?
  • 它们将如何被使用(它们应该被发送到一个漂亮的仪表板还是将被发送到另一个自动化系统)?
  • 谁会使用它们(是精通数据科学的人,公司的 CEO,投资者…)?
  • 我们会维护它们吗?谁来做?—我们稍后将详细讨论如何维护预测
  • 你想什么时候完成(截止日期是什么时候)?
  • 在什么水平上(整体、按商店、按产品……)?
  • 在什么时间段(每周,每月…)?
  • 我们将提前多长时间生成预测(下周、明年……)?
  • 是否有要使用的外部数据(天气、假期……)?

技术设置

在这里,您可以选择生成预测的工具或编程语言,还可以设计文件夹结构(如果适用)。就我个人而言,我喜欢每个步骤都有一个 Jupyter 笔记本:数据处理、分析和建模,但可以自由选择最适合你的。

这应考虑是否将预测发送到仪表板或存储您的数据的自动化系统,如果您的客户已经有一个预测系统,您打算如何获取外部数据,以及预测是否将被维护(以及由谁维护)。

在这一点上,你还必须设计你的数据工作流程:列出你的数据源,它们是如何被收集、存储和合并的,以及你的脚本在哪里。笔和纸在这里可能会有帮助。

数据处理

首先创建数据提取脚本:这些可能是来自数据库的查询,但也可能包括某种 web 清理。考虑所需的聚合级别、外部变量和时间框架。

一旦收集了数据,您将不得不清理它,这将提出一些常见的问题,例如如何处理离群值和缺失值?嗯,这个真的要看每个具体案例,我也不能真的给你提供一个最终的答案,但是试着问问自己:为什么这个值这么高/缺失?是真值,还是很可能是输入错误?然后考虑如何处理它:用一些公式(比如平均值)手动输入它,去掉它,用零代替它,等等。

最后,你会做一些特征工程:合并不同来源的数据,添加新的变量,现有变量的组合或函数(log,平方根等。)等等。你不必在这里面面俱到,如果需要的话,你可以稍后回到这一步,添加你在开始时没有想到的变量。

分析

这是你让你的好奇心自由奔跑的地方,并且真正理解你正在处理什么类型的数据。然而,这里可以回答几个问题作为进一步分析的起点:有趋势吗?这个时间序列是平稳的吗?有季节性吗?在什么级别(每天、每周…)?如果有外部变量,它们是如何相互作用的(尤其是与你试图预测的变量)?您可以为多对变量创建多个散点图。如果您发现您感兴趣的变量和另一个变量之间的关系具有某种特殊的形状,您可以返回到上一步,尝试在该变量上包含变换。例如,您可能会看到您的收入与观察到的降雨量有关,但不是以线性方式。

在分析过程中,您还需要根据数据定义适当的误差测量。常见的误差度量包括 RMSE、MAPE 和脉塞,但还有更多。根据你的目标和数据做出明智的选择。:MAPE 不适用于间歇性数据,即变量经常等于零的情况)。

一旦您定义了您的误差度量,您需要设置正确的基线:从现在开始,您将根据它来比较您获得的误差与您尝试的所有模型。你的基线是你用最简单的模型得到的误差。例如,如果您正在处理零售收入,该收入具有很强的年度季节性,您可以将明年 12 月的销售额预测为去年 12 月的销售额。你不需要一个奇特的模型或数据科学家来做这件事:一个 Excel 电子表格就可以了。因此,这是可接受的最大误差值,如果你的神经网络不能战胜它,那么它肯定不值得努力。低于这个级别的任何东西都可以被认为是一种改进,但是请记住,您可能不想为了几个额外的准确性点而牺牲可伸缩性和易于理解性。

现在你有了基线,你可以考虑适合你情况的模型。一些模型不处理季节性,而另一些不处理外部变量。现在有太多的方法,你不可能知道所有的方法,但是一定要列出所有的基本方法(这些方法往往执行得很好)和一些更高级的方法。基础知识包括 SARIMAX 系列模型和指数平滑方法。更复杂的方法包括使用 XGBoost、神经网络或脸书开发的 Prophet 算法。

系统模型化

建模部分本身是非常简单的,它将为返回到您的数据处理和分析步骤以及添加额外的变量和分析提供洞察力。

首先,您将把数据集分成三部分:训练、验证和测试。验证/测试术语通常有些混乱,但在这里,我假设训练数据用于训练您的模型,验证用于应用它们,查看哪个效果最好,并可能使用 insight 来更改一些超参数,测试集是您应用您的最佳模型并获得关于它在新数据上的表现的良好估计的地方。与其他数据科学问题不同,这种分裂不应该是随机的:因为你正在处理时间序列,所以你的观察顺序很重要,你应该保持这种顺序。相反,为每个数据集选择一个分割点(一个日期)。《出埃及记》:我将从 2015 年到 2018 年训练我的模型数据,在 2019 年的数据上验证它们,并在 2020 年的数据上测试我的最终模型。

但是,请记住,如果您的模型依赖于在它必须预测之前发生的观察,这种方法是不完整的。例如,如果您的模型应该根据过去三周来预测下周的预测,您将需要执行向前行走验证,这意味着当您每周进行预测时,您的训练集会逐渐变大。你可以在这里阅读更多相关信息

重复

通过应用所有这些模型,您肯定会了解更多关于您的数据行为的信息,这意味着您将通过数据处理和分析,甚至通过请求阶段,向您的客户询问您以前没有想到的问题并添加新功能。你这样做,直到你根据你的基线取得了令人满意的结果,或者如果你已经达到了客户给你的最后期限(或者如果你已经没有改进的想法了,很明显)。

同意

在许多情况下,您需要客户或更高层的批准来部署您的模型,这意味着您必须向他们展示您已经尝试过的模型、获得的结果,以及与基线相比您实现了多少。根据这些人是谁,您可能希望保持简单,或者更详细地了解度量和方法。但是,请确保您向他们现实地展示了他们可以从您的预测中得到什么(此处应使用预测置信区间)。

部署

到了部署的时候,您将使用您选择的基础设施来部署您的数据处理步骤,以及一个模型应用步骤,只包括您决定应用的模型(您不需要在这里继续测试模型,也不需要分析部分)。

监视

为了监控您的模型,您需要记住您想要跟踪的度量标准。不应该有太多(通常三个就足够了),他们至少应该测量偏差,平均误差和方差。除了这些指标之外,您还需要跟踪您的预测置信区间和实际观察值:确定一个可接受的误差阈值,无论何时您的预测开始偏离轨道,您的监控系统都应该发出某种标志。

结论

我希望这篇文章对您和您的预测需求有用,并记住这是整个工作流的一般指南,但这些步骤中的每一个可能都值得有自己的文章,因为每个步骤都有许多警告和注意点(我可能很快就会在这方面工作)。

有用的链接

本文展示了一个数据科学工作流的示例,并附有实际例子。

这家公司也有类似的目标,但重点是初创公司。

数据科学项目的模板(一种可以复制的文件夹结构)。

网飞管理数据科学项目的图书馆 meta flow。

脸书的先知,一个时间序列预测的优秀图书馆

用于嵌入人工智能的学习引擎

原文:https://towardsdatascience.com/a-learning-engine-for-embodied-ai-7ef54f6574f0?source=collection_archive---------26-----------------------

本文介绍了在游戏模拟器中创建自主代理的深度学习框架

An Agent Learning a Match to Sample Task using Neurostudio

由于能够创建物理和视觉环境的高保真表示,现代游戏引擎已经成为训练多种具体化人工智能的可行工具。术语“具体化人工智能”在这里用于区分机器学习算法的类型。一个被具体化的人工智能包含了一个环境中的视觉表现,不管是真实的还是虚拟的,并且正在优化一些服从于那个角色的东西。例如,垃圾邮件分类器并不代表具体化的人工智能,因为它在其环境中缺乏任何种类的可见身份。然而,用于动画表情的垃圾邮件分类器可以说是表示具体化的 AI,因为优化器现在具有时空内的物理表示。

创建这种具体化人工智能的工具可以被认为是一种新型的软件,或者我在这里称之为“学习引擎”。虽然这些例子已经存在,但大多数用于创建具体化代理的深度学习工具仍处于起步阶段,需要大量的专业知识来部署。在这篇文章中,我介绍了一个名为 Neurostudio 的深度学习框架,它利用 Unreal Game Engine 的可视化脚本语言蓝图,通过新手可以学习的几个简单步骤来创建自主学习代理。

https://www.youtube.com/watch?v=rgQWJ5bkVkk

为什么首先要使用视频游戏引擎来训练具体化的人工智能?在部署强化学习等下一代人工智能技术时,一个持久的障碍是缺乏合适的培训环境。各种各样的研究已经注意到使用基线现实训练具体化代理人的困难。通常,人工智能的物理约束,如机器人的电子执行器,禁止像深度强化学习这样的技术产生良好结果所需的高容量训练计划。

一种替代方法是使用模拟器来训练代理。从这里开始,智能体可以继续存在于模拟器中(就像电子游戏《NPC》的情况一样),或者它们的学习可以转移到“实体”现实中,就像机器人的情况一样。在这两种情况下,使用模拟器来训练具体化代理都有几个优点。首先,当事情发生灾难性的错误时,其结果通常没有在物理现实中发生灾难性错误时那么严重。一个疯狂奔跑的机器人的模拟和一个 800 磅重的四肢乱飞的怪物是完全不同的。更重要的是,很多时候人们可能希望代理人永远留在模拟器中,就像电子游戏角色的情况一样。

我在这里描述的系统将深度神经网络与强化学习算法相结合,以实现自我学习的具体化代理。使用这个系统,一个智能体可以简单地通过改变 AI 角色控制器中的奖励函数来执行任何涉及其环境中对象的动作组合。这是强化学习的主要优势——不需要手工制作行为,而是指定一个要奖励的行为,让代理自己学习实现奖励的必要步骤。本质上,这就是如何用食物奖励来教狗表演一个魔术。

同样的方法也可以用来训练 NPC、虚拟助理甚至机器人。通过这个系统可以获得各种各样的有意行为,包括路径寻找、NPC 攻击和防御以及许多类型的人类行为。最先进的实现包括那些用于在国际象棋、围棋和多人战略视频游戏中击败一流人类玩家的实现。

https://www.youtube.com/watch?v=SmBxMDiOrvs

强化学习已经成为训练具体化代理人的一个有前途的途径,因为这样的代理人几乎总是与一些时间和行动的概念有关。强化学习不同于人工智能的其他分支,因为它专门解决学习的问题,其中代理可以采取一些与时间和环境相关的行动。在这种情况下,时间可以是一系列的游戏移动或训练时期。以这样或那样的方式,有一个时间空间,在其中事情正在发生。人工智能不像监督学习技术那样简单地迭代一组冻结的标记数据。

一旦一个主体存在于时间和变化的环境中,复杂性就成了压倒一切的问题。在诸如表格 Q 学习的强化学习技术中,算法必须跟踪表格中环境变化、动作和奖励的所有组合。根据环境的复杂性和代理可用的操作,这可能会使这样的表变得非常大。即使几个环境因素相互作用也能迅速导致组合爆炸。

人类也使用强化学习的变体来获得许多技能,你可能会忍不住问,在复杂性成为问题之前,我们自己可以跟踪多少环境变量?从视觉上来说,答案少得惊人——根据物体是运动还是静止,在 4 到 8 个之间。根据我们对强化学习和组合爆炸的了解,这是有道理的——超过八个对象,注意力的空间分辨率就会停滞不前。四个动态对象可以以 24 种不同的方式组合,八个对象以 40,320 种方式组合!除此之外,我们进入了从人类的角度来看几乎毫无意义的数字——12 个物体可以以 4.79 亿种独特的方式组合。例如,在玩视频游戏的任何时候,我们通常会从成千上万的像素中抽象出 4 到 5 个不同的对象来跟踪。

那么,我们如何从所有这些像素组合中提取出少量有意义的特征呢?在人类中,进化为我们做了所有艰苦的工作,在生物学中这种天赋被称为潜在抑制。在这个过程中,熟悉的物体会失去它们的显著性,我们会随着时间的推移而忽略它们。遗忘的面纱确实是一个仁慈的面纱。虽然根据计算机的处理能力,计算机可以跟踪比人更多的特征,但组合爆炸甚至会加重现代超级计算机的负担。对计算机科学家来说幸运的是,“神经网络”可以帮助解决这种复杂的问题。

深度神经网络最常与称为“监督学习”的人工智能领域相关联,这需要有人提供一个标记训练数据的数据库,供算法从中学习模式。深度神经网络的惊人之处在于,它们可以像猫的照片一样获取嘈杂、非线性、非均匀的数据,并将其抽象为对其进行分类至关重要的几个特征。这就是你的垃圾邮件分类器如何在你的电子邮件收件箱中工作,以及网飞如何根据你喜欢或不喜欢的电影为你创建推荐。这种分类器在软件中越来越常见,并由于深度神经网络而受到了鼓舞。神经网络比早期的统计方法(如逻辑回归和贝叶斯分类器)更强大,因为它们擅长发现隐藏在多层复杂性下的模式。分类器是强大的工具,但与强化学习不同,它们通常需要某种标记数据来训练。

2015 年,DeepMind 公司的研究人员突发奇想,利用深度神经网络从雅达利视频游戏屏幕的屏幕像素中提取像素,以便将强化学习算法应用于玩游戏。如上所述,深度神经网络有能力获取非常嘈杂的大型数据集,并检测其中的模式。Atari 视频游戏的屏幕可以被认为是这样一个大而嘈杂的数据集。通过使用 Atari 控制台的屏幕作为神经网络的训练集,他们将所有像素组合的复杂性减少到与玩家可能做出的不同动作相关的少数几个特征,通常只有 4 或 5 个(Volodymyr Mnih,2015)。他们仅仅是幸运的没有一个游戏需要更多的动作来获胜吗?一点也不,因为这些游戏是为人类设计的,它们的活动和环境空间有限。为外星人设计的 Atari 视频游戏能够从 10,000 种不同的动作组合中学习,这完全是另一回事。然而,在大多数游戏功能只是装饰,对人们应该采取的行动没有任何意义的情况下,深度神经网络可以将复杂性降低到强化学习算法可以管理的程度。

雅达利的情况同样适用于围棋这样的棋类游戏。由于游戏固有的复杂性,这种古老的中国娱乐方式被认为是计算机无法掌握的。正如围棋专家喜欢提醒我们的那样,在一场围棋比赛中,可能的棋盘组合比宇宙有史以来存在的夸克数量还要多。但就像在雅达利电子游戏中一样,围棋游戏中的许多棋盘位置与游戏的任何给定回合都不相关。它们就像屏幕远处角落里的像素,在它表明敌人正向你走来之前并不重要。“深度强化学习”,即深度神经网络和强化学习的结合,被证明在掌握围棋方面与在 Attari 视频游戏中一样有效。2017 年,由 DeepMind 开发的围棋深度强化学习算法 AlphaZero 击败了几位世界领先的人类围棋选手以及最佳围棋人工智能。

当想到像围棋这样的游戏时,人们陷入的一个主要谬误是假设复杂的游戏需要复杂类型的学习。在分形几何中,看似无限变化的令人困惑的图案可以从简单的公式中推导出来。进化已经产生了无数极其复杂的生命形式,它受到一个同样简单的学习规则——错误——的指导。同样的学习方程式可以让你掌握井字游戏,也可以让你掌握像围棋这样的游戏。在这两个游戏中,强化学习可以发现与获胜相关的关键关联。这并不是说没有更复杂的方法来解决学习问题。1997 年在国际象棋比赛中击败加里·卡斯帕罗夫的 IBM 超级计算机 DeepBlue 是一个庞大的程序,其中内置了数千个由国际象棋专家和程序员编写的场景。但是这样复杂的程序,最终远不如像 Q 学习这样的简单算法健壮和强大。首先,他们编织了编码他们的人类的经验偏见。当雅达利深度强化学习算法在 DeepMind 开发出来时,它发现了一种在乒乓游戏中增加分数的方法,这种方法使用了一种人类玩家以前不知道的技巧。如果它完全是根据人类的经验编写的,它很可能永远不会做出这种“外星人”的动作。强化学习的优势在于,独自玩游戏时,它可以尝试数百万个游戏历史上从未有人想过要尝试的动作。

许多专家评论员在研究国际象棋强化学习算法 AlphaZero 时,看到了更高级版本的 DeepBlue,因此没有意识到他们正在研究一种完全不同的人工智能,一种具有完全不同含义的人工智能。因为强化学习模仿了人类学习的一种方式,所以可以用于掌握围棋的相同算法可以用于掌握煎蛋卷或叠衣服。当你第一次开始学习叠衣服时,你会犯错误,袖子不整齐,折痕不精确。通过重复,或者用计算机科学的话说,迭代,你慢慢地学会了让你达到目标状态,完美折叠衬衫所必需的正确动作。以这种方式,许多人类活动可以被“游戏化”并变成强化学习问题。

将神经网络与强化学习结合起来,允许人们采用诸如 Q 学习的算法,并扩大代理可以学习的环境和动作空间。极端情况下—代理学习的环境可以是屏幕的实际像素输入。这反映了人类和狗等哺乳动物从视野中学习的方式。

Neurostudio 学习引擎基于深度强化学习算法,称为深度 Q 学习,简称 DQN。对它的表亲表格式 Q 学习有一个基本的了解,对理解深度 Q 学习会有帮助。在下面的链接中,您可以找到表格 Q 学习的介绍,其中代理解决了一个简单的匹配样本难题:https://www . unrealenengine . com/market place/artificial-intelligence-Q-learning

Q 学习的工作方法有时被称为逆向归纳法。想象一下,一个徒步旅行者迷失了方向,正试图找到返回营地的路。首先,他们随机选择一个前进的方向。他们爬过一块岩石,观察这个动作是否能让他们更接近目标。从这个新的有利位置,他们决定如何评价他们以前的行为。爬过岩石是一个好的决定还是一个坏的决定?实际上,我们正在从猜测中学习猜测。首先对未来进行猜测(考虑到我的新状态,到达营地有多容易),然后根据第一次猜测对他们最后一次行动的值进行猜测(我爬过这块岩石,离大本营更近了,所以我的最后一次行动很好),我们通常称之为试错学习,或联想学习。在表格式的 Q 学习数学形式中,这需要表达式

Q(状态,动作)=奖励(状态,动作)+ Gamma * Max[Q(下一个状态,所有动作)]

其中 R(状态,动作)是由当前动作收集的任何奖励,gamma 是介于 0 和 1 之间的固定折扣率,它控制代理人对当前奖励和未来奖励的重视程度。Max[Q(下一个状态,所有动作)]也称为贝尔曼更新规则,使状态动作对的当前值依赖于可以从该位置采取的下一个最佳未来动作。这是等式的“向前看”部分。以这种方式,一个人相信将来会发生的奖励可以被向后链接到到达那里的步骤。

为了将 Q 学习与神经网络相结合,神经网络首先预测对应于给定其当前状态的代理可用的每个动作的值。最初,这些只是由神经网络产生的随机噪声。然而,在代理收到奖励后,它可以应用 Q 学习方程,并使用状态动作对的预测值和状态动作对的新值之间的结果误差来形成误差项。这个误差项可以用来训练神经网络。把神经网络想象成一个最小化预测误差的工具,把 Q 学习方程想象成提供这些预测误差的东西。

经过多次训练后,神经网络逐渐提高了对代理在模拟器中可能遇到的每个状态动作对的估计。为了进行战略性的移动,代理只需在给定网络当前状态的情况下向前运行网络,并采取预计具有最高价值的行动。

虽然我已经详细解释了 DQN 的工作原理,但是使用 Neurostudio 并不一定需要了解学习是如何发生的细节。相反,人们只需要清楚代理人正在从环境中的哪些元素学习,代理人可以采取的行动,以及它可以获得的回报。就像你不需要理解脑科学来教狗如何变戏法一样,你需要理解狗有什么能力,它发现什么是有益的,以及何时给予这些奖励来最大限度地学习。

也就是说,在选择神经网络的参数时,对深度学习原则(如过拟合)的理解可能是有帮助的。训练神经网络既是一门科学,也是一门艺术,因为神经网络的许多参数会影响学习。

虽然深度强化学习允许代理在复杂的真实世界环境中学习,但它们通常比表格 Q 学习代理做得更慢。给定影响神经网络的大量参数,也可能更难以“调整”代理的行为。

另一方面,使用神经网络允许代理人概括他们的策略——也就是说,他们将把学到的策略应用于各种各样的环境状态,这些环境状态类似于他们最初接受训练的环境状态。这使得他们即使在全新的环境中也能聪明地行动。相比之下,使用表格式 Q 学习,所学习的策略将仅在代理具有过去关联的确切环境状态中被调用。这种将学习推广到新任务和新环境的能力使深度强化学习成为目前可用的最强大的机器学习框架之一,也是学习引擎的自然起点。我期望使用这样的学习引擎来扩展真实和虚拟代理的视野,并迎来一个新的嵌入式人工智能时代。

购买多 GPU 系统的经验

原文:https://towardsdatascience.com/a-lesson-buying-a-multi-gpu-system-a14d3d1c710e?source=collection_archive---------7-----------------------

我在寻找用于深度学习实验的本地多 GPU 系统中学到了什么

这个故事是关于 H 字的,我指的是硬件或者更准确地说是用于繁重的深度学习任务的高端 GPU 系统。

所以在长时间使用 GPU 云实例,甚至编写 PyTorch 检查点处理程序来支持保存和加载模型权重和其他超参数作为快照后,更容易在 spot 实例上工作。是时候购买一台本地机器了。我目前专注于视频相关的任务和训练繁重的 I3D 型号,所以我需要一台坚固的多 GPU 机器来支持这些工作。使用大的小批量会占用大量的 GPU 内存。最新最好的 NVIDIA GPU 是配备 24GB 内存的泰坦 RTX ,售价为 2499 美元,所以为什么不买四个这样的宝贝呢?我联系了几个推荐的供应商,以获得这种系统的规格建议和价格估计。听到其中一家供应商说这不可能,而其他供应商确实提出了建议,我有点惊讶。

他的完整回答是这样的:

它们会在没有鼓风机的情况下加热,最物有所值的是 GeForce RTX 2080 Ti TURBO 11G ,因为每个价格一半,有 11GB 内存,只需 8 个。

我最近确实购买了一台配有单个 GEFORCE RTX 2080 Ti 的 GPU 机器,所以我问我是否可以为该机器添加更多 GPU,他问了确切的 GPU 型号,并再次表示:“不要鼓风机,机箱中会太热”。

那么这是怎么回事,鼓风机是什么?

困惑中,我开始寻找一个简单的答案,在谷歌的帮助下,我找到了这张图片和它所来自的伟大的博客文章。

A picture is worth a thousand words. The image is taken from: NVIDIA RTX Graphics Card Cooling Issues

是的,在右边——一台鼓风机!

技嘉网站所写的鼓风机是:

“千兆字节涡轮风扇冷却系统专为在空间有限的机箱中使用多个显卡的系统而设计。借助蒸汽室直触 GPU、鼓风机风扇和特殊形状的外部,它提供了更多的气流和更好的散热。”

The image is taken from: GIGABYTE product page

事实证明,游戏玩家模型,如泰坦 RTX ,并不专用于多 GPU 系统,而是为游戏而设计的。他们通过使用“露天”系统来降温。

在非服务器机架上组装多 GPU 系统迫使你将它们彼此靠近,而鼓风机的工作是负责散热。

所以下次你在寻找一个 GPU 来处理深度学习任务时,你最好问问你的供应商,GPU 是否有鼓风机。

更多阅读,推荐这篇很棒的博文:https://www . pugetsystems . com/blog/2019/01/11/NVIDIA-RTX-显卡-散热-问题-1326/

现代分类模型的一课

原文:https://towardsdatascience.com/a-lesson-on-modern-classification-models-938cbd731d9d?source=collection_archive---------17-----------------------

揭开 ML 的最新进展,为您构建一个更好的分类模型

在机器学习中,分类问题是最根本的令人兴奋挑战现有问题之一。一个合格的分类模型的含义是巨大的——这些模型被用于自然语言处理文本分类、图像识别、数据预测、强化训练以及无数的进一步应用。

然而,目前实现的分类算法很糟糕。在脸书期间,我发现任何机器学习分类问题的通用解决方案都是“扔一棵梯度下降推进树给它,然后抱最好的希望”。但情况不应该是这样的——研究正在投入到现代分类算法和改进中,这些算法和改进允许显著更准确的模型,而所需的训练数据却少得多。

在这里,我们探索一些特别有趣的现代分类算法的例子。这篇文章假设你对机器学习有一定的了解,但是,这篇文章的大部分内容不需要。

深度神经决策树

深度神经网络已经被证明在处理感知数据方面非常强大,比如图像和音频。然而,对于表格数据,基于树的模型更受欢迎有几个原因——其中一个重要原因是它们提供了自然的可解释性。

例如,考虑一个试图确定系统故障原因的企业。您可以使用几个参数创建一个预测模型,例如网络速度、正常运行时间、线程处理和系统类型。有了决策树,我们还可以了解系统失败的原因。

深度神经决策树结合了决策树的效用和神经网络产生的影响。由于它是通过神经网络实现的,DNDT 支持开箱即用的 GPU 加速和对不适合内存的数据集的最小批量学习,这要归功于现代深度学习框架。因此,在许多数据集上,它们比传统的决策更加准确。此外,它们易于使用——在 TensorFlow 或 PyTorch 中,一个实现需要大约 20 行代码

我们可以探索模型核心数学背后的概念。首先,我们需要一种方法来做出分割决策(即我们如何决定选择树的哪条路径)。然后,我们需要将我们分开的决策组合在一起,构建决策树

我们通过一个 宁滨函数做出拆分决定。宁滨函数接受一个输入,并生成该输入所属的条柱的索引。在我们的模型中,每个箱代表一个特性——例如,正常运行时间、网络速度或系统类型。

我们通过其自己的一层神经网络(我们模型的“深度神经”部分)和以下激活函数来绑定每个特征。

The activation function of each bin.

然后,我们通过克罗内克乘积将我们的箱彼此相乘,以构建我们的决策树。

每个特征都被它们自己的神经网络分类。这就给我们返回了一个表示 x 的分类的索引(即树中叶子节点的索引),完成了我们深度神经决策树的构建。

置信度加权线性分类

许多机器学习任务,特别是在自然语言处理中,最终会有许多不同的特征,其中大多数是二进制的,很少被操作。这导致数据稀疏,这需要大的训练集和非常大的参数向量。

考虑一个产品评论分类器,其目标是将评论标记为正面或负面。许多评论可能会说“我喜欢这个作者”,因此会将“喜欢”这个词与正面评论相关联。想象一下一个稍加修改的负面评论:“我喜欢这个作者,但觉得这本书索然无味”。分类器可能不会经常看到世界“沉闷”,这可能会错误地将该评论分类为积极的,因为该评论使用短语“喜欢该作者”,从而降低了收敛速度。

我们可以用置信度加权学习来解决这个问题,这是一种在每个参数中保持概率置信度的学习方法。较不自信的参数比较自信的参数更新得更积极。

在置信度加权学习中,我们确保对于每次迭代,每个训练实例的正确预测的概率大于或等于该预测的置信度。这可以正式定义。

就其本身而言,这可以附加到任何其他模型上(您需要决定如何度量置信度——一些想法是贝叶斯方法,如变分贝叶斯)。这导致模型的变化,趋向于解决稀疏数据集涉及的上述问题。

决定批量大小的贝叶斯原则

除了选择一个有代表性的模型,还有一系列的变量会影响我们的模型所代表的准确度。一个是批量大小——训练期间每次迭代使用的训练数据量。研究表明,不仅存在最大化测试准确性的最佳批量,而且我们可以应用贝叶斯原理来计算作为学习率训练数据量的比例函数。计算本身是一个多步骤的过程,超出了本文的范围,但是结果可以表示为一个线性比例函数:

由此,我们可以得出两个有益的结论。

首先,随着我们的训练数据的大小增加,每个批量迭代的大小应该增加相同的量。第二,随着学习数据的增加,我们应该增加批量。这使我们能够确定单个实验的最佳批量,并对其进行缩放,以确定任意数量的不同实验的批量,从而全面优化测试精度。

结论

这只是对现代机器学习研究中分类问题的广度(和深度)的一个尝试——本文中的所有内容都是在过去几个月中发表的。希望这向您展示了一点令人兴奋的复杂性,人们在未来选择分类模型时可能会考虑到这一点!

R 语言中的文本分析简介

原文:https://towardsdatascience.com/a-light-introduction-to-text-analysis-in-r-ea291a9865a8?source=collection_archive---------6-----------------------

使用语料库、文档术语矩阵、情感分析等…

介绍

这是我在 r 中使用一些文本分析工具的第一个项目的快速浏览。这个项目的目标是探索文本分析的基础,如使用语料库、文档术语矩阵、情感分析等…

使用的包

  • tm
  • 其他:tidyverse,SnowballC,wordcloud,RColorBrewer,ggplot2,RCurl

快速查看数据源

我使用了我最新的 网络搜集项目 中的职位描述。实际上,大约有 5300 个职位空缺。

我们将在这里集中讨论职位描述,因为它们包含了最多的文本和信息。让我们看看我们的第一份工作描述,看看我们在做什么。

**postings1$job_description[1]**

正如您所看到的,这是一个很大的字符串,包含了工作列表中的所有文本。

创建语料库

语料库(corpora pl。)只是一种存储文本数据的格式,在整个语言学和文本分析中使用。它通常包含每个文档或文本集,以及一些帮助描述该文档的元属性。让我们使用 tm 包从我们的工作描述中创建一个语料库。

**corpus <- SimpleCorpus(VectorSource(postings1$job_description))
# And lets see what we have
view(corpus)**

你可以看到我们最外面的列表是一个类型=列表,长度= 5299,这是我们拥有的工作描述(或文档)的总数。当我们查看列表中的第一项时, [1],,我们看到这也是一个类型=列表,长度= 2。如果我们看这两个项目,我们会看到有内容元。内容属于类型=字符,包含字符串形式的工作描述文本。M eta类型=列表,长度为 7。这是自动添加到简单语料库中的 7 个元属性,即使我没有它们的任何值。

  1. 作者=空
  2. 日期-时间戳=另一个列表…但是对于我的数据是空的
  3. 描述=空
  4. 标题=空
  5. id = '1 '(由职位自动创建)
  6. language = 'en '(我假设是 tm 包的默认值)
  7. 原点=空。

现在你知道了。这是一个简单语料库的一般格式。请记住,您可以编辑元属性来包含您想要的任何内容。

转换:清理我们的语料库

tm 包中的转换指的是在进行任何分析之前,我们可能要对文本进行预处理或格式化。我们将执行 5 个快速转换,这将为我们的分析准备数据。

**# 1\. Stripping any extra white space:
dfCorpus <- tm_map(dfCorpus, stripWhitespace)# 2\. Transforming everything to lowercase
dfCorpus <- tm_map(dfCorpus, content_transformer(tolower))# 3\. Removing numbers 
dfCorpus <- tm_map(dfCorpus, removeNumbers)# 4\. Removing punctuation
dfCorpus <- tm_map(dfCorpus, removePunctuation)# 5\. Removing stop words
dfCorpus <- tm_map(dfCorpus, removeWords, stopwords("english"))**

除了移除停用词功能,大多数转换都是自解释的。那到底是什么意思?停用词基本上只是被确定为对某些文本分析(如情感分析)没有什么价值的常用词。这是 tm 包将删除的停用词列表。

**stopwords(“english”)**

现在我们已经转换了我们的工作描述,让我们再看一下我们的第一个清单,看看有什么变化。

**corpus[[1]]$content**

堵塞物

词干提取是将单词压缩成共同词根的过程,这有助于词汇的比较和分析。tm 包使用 波特词干算法 来完成这个任务。让我们继续干我们的数据。

**dfCorpus <- tm_map(dfCorpus, stemDocument)**

现在让我们最后一次看一下我们的工作描述,看看有什么不同。

**corpus[[1]]$content**

很好,现在所有的工作描述都被清理和简化了。

创建文档术语矩阵(DTM)

文档术语矩阵是比较每个文档中所有术语或单词的简单方法。如果你把数据简单地看成一个矩阵;每行代表一个唯一文档,每列代表一个唯一的术语。矩阵中的每个单元格都是该术语在文档中出现次数的整数。

**DTM <- DocumentTermMatrix(corpus)
view(DTM)**

如你所见,DTM 实际上并不是作为矩阵存储在 R 中,而是属于类型= simple_triplet_matrix** 。这是一种更有效的存储数据的方式。你可以在这里 更好地了解它们是如何被格式化的 。出于我们的目的,最好把它想成一个矩阵,我们可以用inspect()函数看到它。**

**inspect(DTM)**

因此,我们可以看到我们有 5296 个文档(删除了三个 NA)和 41735 个术语。我们还可以看到一个 DTM 样图。现在让我们来看看在所有的招聘启事中最常用的词是什么。

创建最常用术语的词云

为此,我们首先要将 DTM 转换成一个矩阵,这样我们就可以对各列求和,从而得到所有文档的总术语数。然后,我可以在整个语料库中挑出前 75 个最常用的单词。

注意: 我选择使用无词干版本的语料库,这样我们就有了单词 cloud 的完整单词。

**sums <- as.data.frame(colSums(as.matrix(DTM)))
sums <- rownames_to_column(sums) 
colnames(sums) <- c("term", "count")
sums <- arrange(sums, desc(count))
head <- sums[1:75,]wordcloud(words = head$term, freq = head$count, min.freq = 1000,
  max.words=100, random.order=FALSE, rot.per=0.35, 
  colors=brewer.pal(8, "Dark2"))**

所以,这里没有什么太疯狂的,但我们可以很好地感受到这个工具有多强大。支持、学习、理解、沟通等术语可以帮助描绘出这些公司在候选人身上寻找什么。

情感分析

“情绪(名词) :对某事的总体感觉、态度或看法。”——剑桥英语词典

情感分析的目标很简单,但实现这一目标的过程却很复杂。桑杰·米娜有一篇很棒的介绍,值得一读:

** [## 你的情感分析指南

情感分析帮助你发现人们对你的产品或服务的看法、情感和感受

medium.com](https://medium.com/seek-blog/your-guide-to-sentiment-analysis-344d43d225a7)

我们将开始使用'sensitement analysis'包,使用Harvard-IV dictionary(General Inquirer)做一个简单的极性分析,这是一个与积极(1915 个单词)或消极(2291 个单词)情绪相关的单词字典。

sent <- analyzeSentiment(DTM, language = "english")# were going to just select the Harvard-IV dictionary results ..  
sent <- sent[,1:4]#Organizing it as a dataframe
sent <- as.data.frame(sent)# Now lets take a look at what these sentiment values look like. 
head(sent)

如你所见,每份文件都有字数统计、消极得分、积极得分和总体情绪得分。让我们来看看我们整体情绪的分布。

summary(sent$SentimentGI)

好的,总的来说,我们的工作描述是积极的。所有文件中的最低分是 0.0,所以看起来这些公司在写他们的职位描述方面做得很好。现在,为了好玩,让我们看看排名前五和后五的公司的情绪得分。

# Start by attaching to other data which has the company names 
final <- bind_cols(postings1, sent)# now lets get the top 5 
final %>% group_by(company_name) %>%
  summarize(sent = mean(SentimentGI)) %>%
  arrange(desc(sent)) %>%
  head(n= 5)

# And now lets get the bottom 5 
final %>% group_by(company_name) %>%
  summarize(sent = mean(SentimentGI)) %>%
  arrange(sent) %>%
  head(n= 5

就这样。现在,这显然不是一个很好的情感分析用例,但它是理解过程的一个很好的介绍。

情感

我们可以做的另一件有趣的事情是从工作描述中提取情感。我们将使用 NRC 情感词典 使用 syuzhet 包 来完成这项工作,该词典将单词与相关情感以及积极或消极情感联系起来。

sent2 <- get_nrc_sentiment(postings1$job_description)# Let's look at the corpus as a whole again:
sent3 <- as.data.frame(colSums(sent2))
sent3 <- rownames_to_column(sent3) 
colnames(sent3) <- c("emotion", "count")ggplot(sent3, aes(x = emotion, y = count, fill = emotion)) + geom_bar(stat = "identity") + theme_minimal() + theme(legend.position="none", panel.grid.major = element_blank()) + labs( x = "Emotion", y = "Total Count") + ggtitle("Sentiment of Job Descriptions") + theme(plot.title = element_text(hjust=0.5))

太棒了。我们已经知道工作描述大多是积极的,但令人感兴趣的是看到更高价值的信任和期望。显而易见,这可以应用于其他类型的数据,如评论或评论,以将大量文本数据简化为快速洞察。**

感谢您的阅读,我希望这篇文章能够帮助其他初学者开始使用 R 的文本分析包。我很乐意听到任何问题或反馈,因为我自己也刚刚开始。

面向物联网流的轻量级机器学习架构

原文:https://towardsdatascience.com/a-lightweight-machine-learning-architecture-for-iot-streams-bd1bf81afa2?source=collection_archive---------20-----------------------

在高频流数据上运行机器学习模型不一定要花大价钱。通过考虑我们的实时需求,我们可以设计更容易扩展的高效架构。

在过去的一年半时间里,我和我的团队一直在试图预测公共道路上的公共汽车的运动,并预测它们在公共汽车站的到达和离开时间。我们的客户,一家名为 Kolumbus 的公共交通公司,已经在许多车辆上安装了物联网(IoT)网关,每秒钟都在向微软 Azure 云发送消息。

虽然我们的大部分数据是地理空间数据,但问题本质上是时间问题。对它的研究让我思考时间的概念,以及它与实时系统各部分的关系。

伴随着大数据而来的是巨大的责任

86,400.这是一天中的秒数,这个数字解释了为什么物联网成为大数据时代的海报儿童。

单个传感器通常一天只能记录这么多信息。根据有效载荷的大小,这可能会产生大约 5 MB 的数据。虽然这听起来可能不多——只有一个略大的 mp3 文件的大小——但物联网解决方案很少只有一个传感器。嵌入式设备通常会连接几个传感器,它们依次连接到网关,网关路由来自多个设备的流量。此外,一个典型的流处理管道会在几个步骤中咀嚼、处理和丰富原始有效载荷,我们手上有一些重要的数据。

物联网设备产生大量数据,机器学习需要大量处理。当你把它们放在同一个句子中,通常不会首先想到“轻量级”这个词。现在你可能想知道为什么这三个都出现在这篇文章的标题中。我们会谈到这一点。

如果您在行业环境中从事物联网工作,您可能对以下场景很熟悉。

支持 IP 的物联网设备或网关使用 MQTT 或 AMQP 等通信协议向公共云中的中央消息代理发送遥测数据。该代理可以是像 Azure IoT Hub 或 AWS Kinesis 这样的云原生服务,也可以是像 Apache Kafka 或 Flink 这样的开源框架。这些技术可以以合理的成本接收来自数百万设备的消息,这意味着我们可以可靠地收集所有传感器数据。到目前为止,一切顺利。

对数据采取行动并产生可行见解的愿望不可避免地导致以下问题:

现在怎么办?

正是在这一点上,组织通常会雇用像我这样的顾问。

满足对数据的渴望

顾问们通常会提出这样的建议。

流处理器订阅来自代理的消息,并动态地对其进行反应性处理,然后立即将其提供给丰富数据的实时视图。在记录原始消息后的几百毫秒内,结果就可以在实时视图中显示,并显示在报告仪表板中。机器学习 web 服务与流处理器挂钩,并执行预测分析,成为实时输出的一部分。这被称为“从消防水管喝水”,是在流处理平台中使用机器学习模型的规范方式。它是这类系统的两个主要标准架构的核心:所谓的 Lambda 和 Kappa 架构。

当设计一个实时系统时,我们应该问自己的第一个问题是,它如何适应项目的特定约束和需求。将机器学习模型直接挂钩到流意味着请求将到达每一条物联网消息的预测端点。这可能意味着服务器集群和相当大的托管费用。当速度和数量增加时,成本、复杂性和延迟也会增加。

虽然在某些情况下从消防水管喝水是必要的,但从一杯水中啜饮通常更舒服。

实时的神话

设计软件时,我们有时会谈到“近实时”。这里的“近”暗指我们永远不可能在任何系统中实现零延迟。在系统能够响应之前,不可避免地要经过一些非零的处理时间。当它非常快时,我们作弊,称之为实时。但是我们在哪里划定界限呢?100 毫秒?一秒钟?一分钟?

在我们甚至考虑我们是否能够实现适当的实时或接近实时之前,我们应该考虑实时需求,这是另一个完全不同的地方。我们应该问自己一个更基本的问题,而不是简单地考虑技术上的可能性:缓慢响应的后果是什么?

实时要求分为三类:

  • 实时。延迟将导致整个系统的失败。也许它们会导致发电厂爆炸,飞机坠毁,太空探测器错失目标,或者无人驾驶飞机轰炸无辜平民。你通常列举的可怕事故。
  • 实盘实时。偶尔延迟是可以的。延迟的输出是无用的,但是系统仍然是可操作的。想象一下网飞。虽然偶尔停顿的电影流可能很烦人,但你可能不会因此失眠。
  • 实时。频繁的延误完全没问题。一个迟来的回应可能没那么有价值,但它仍然是有用的。

让我们面对现实吧。极少数系统实际上有严格的实时要求。但是,即使是严格的实时要求也很少。大多数系统都有相当宽松的时间限制。

回到我们的公交预测,这是一个具有软实时需求的系统的经典案例。如果我们在 8:30 预测一辆公共汽车将在 9:00 到达某个车站,那么这个预测在几秒钟后仍然有效并且几乎同样准确。即使是在 8:31 或 8:32,预计到达时间(ETA)也不会发生根本性的变化。

时间窗口

对于软实时要求,我们可以选择对数据进行下采样。毕竟,传感器信号的频率只是我们用来从设备中采样的任意时间段。我们并不需要处理每一条传入的消息。

流处理也有一种规范的方式来做到这一点,它被称为时间窗口。

这个简单的函数叫做滚动窗口,所有主流的流处理框架都支持它。通过查看固定大小的时间窗口,我们可以以某种方式聚集数据,或者只处理批处理中最新的消息。

在后一种情况下,我们只对捕捉传感器的最新状态感兴趣。当你想到它时,这就是物联网设备已经在做的事情,只是速度更快。

这允许稍微不同的架构。

在这种设置中,一个计划任务(如 cron 作业)会在特定的时间间隔醒来,查看来自流式管道的最新输出,生成预测,然后再次进入睡眠状态。当我们等待任务再次触发时,旧的预测仍然有效。记住,考虑到我们的软实时需求,预测在有限的时间内是有价值的。

这可能不是在每种情况下都有效,但是在适用的情况下,它可以大大降低系统的成本。借助现代云服务,我们通常不会为闲置的处理单元付费。

另一个好的方面是,我们将预测分析与我们希望对每条消息进行的更简单的处理形式分离开来。

作为旁注,我们也可以将一些相同的哲学应用于模型训练。对于在大型数据集上训练模型,下采样通常是一种不受重视的策略。

付诸实践

在我们的实时总线系统中,我们已经将预测和训练功能从流层中分离出来,并将它们放入单独的 Docker 容器中,这些容器在需要时会旋转起来。

通过这种方式,我们拥有了一个自包含的基础设施,只要流式管道接收到物联网消息,它就可以根据新数据保持训练模型并生成实时预测。

系统的这一部分目前每天处理几百万条消息,每月花费大约 60 美元。这包括托管、计算和存储。我们通过利用“容器即服务”( CaaS)和“功能即服务”( FaaS )(也称为“无服务器”)的云模式来实现这一目标。

目前,我们正在一个小型 Docker 容器上运行预测任务,该容器只有一个 CPU 内核和 2.5 GB 的内存,它的响应速度仍然相对较快。这还没有太多的优化。事实上,我们正在并行运行一些不同的机器学习模型,以评估它们在生产中的性能,所有这些都是在那个容器实例上进行的。限制流向终端的流量使我们可以享受这些自由。

但是推论是廉价的。那么训练呢?

训练模型需要更强大的服务器,但我们仍然运行一个相对适中的实例,具有四个 CPU 核心和 5 GB 内存。我们对数据进行了大量的缩减采样,每天只运行几分钟。通过这样做,我们将这项特殊任务的成本保持在每月 2 美元的低得离谱的水平。

我们预计我们系统的入站物联网流量将增加至少一个数量级,但负载测试结果显示,我们的设置可以相对轻松地处理它。训练容器可能需要更大的马力,但是考虑到它只运行一小部分时间,即使我们使用像 Kubernetes 这样的集群技术扩展到多个节点,它仍然是廉价的。

最后的想法

我上面所描述的并不适用于所有的问题。有些情况下,你需要连续预测每一个事件。但在物联网场景中,通常情况下你可以跳过时间步骤。事实上,平滑信号甚至有助于防止模型过度拟合。

我们的系统以惊人的低成本运行在最小的基础设施上,同时满足我们的性能要求。我们已经在 Azure 上部署了这个,但是我故意避免为我们的组件使用市场名称,因为这个概念和一般架构可以在任何通用的云平台上实现。

我的观点不是建议我们的架构作为每个人都要遵循的标准。它只是呼吁数据科学家和数据工程师在设计过于复杂和沉重的系统之前,考虑他们机器学习管道中每个单独组件的时间约束和实时要求。

随机森林回归的一个局限性

原文:https://towardsdatascience.com/a-limitation-of-random-forest-regression-db8ed7419e9f?source=collection_archive---------5-----------------------

邻居的规则如何影响你的预测。

One Tree from a Random Forest of Trees

随机森林是一种流行的机器学习模型,通常用于分类任务,这在许多学术论文、Kaggle 竞赛和博客帖子中可以看到。除了分类,随机森林还可以用于回归任务。随机森林的非线性特性可以帮助它超越线性算法,成为一个很好的选择。但是,了解您的数据并记住随机森林无法进行外推是很重要的。它只能做出预测,该预测是先前观察到的标签的平均值。从这个意义上说,它非常类似于 KNN 。换句话说,在回归问题中,随机森林可以做出的预测范围受到训练数据中最高和最低标签的限制。在训练和预测输入的范围和/或分布不同的情况下,这种行为会变得有问题。这被称为协变量移位,对于大多数模型来说很难处理,尤其是对于随机森林,因为它不能外推。

例如,假设您正在处理具有潜在趋势的数据,如股价、房价或销售额。如果您的训练数据缺少任何时间段,您的随机森林模型将会根据趋势低估或高估训练数据中时间段之外的示例。如果您将模型的预测值与真实值进行对比,这一点会非常明显。让我们通过创建一些数据来看看这一点。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
%matplotlib inline#make fake data with a time trend
X = np.random.rand(1000,10)#add time feature simulating years 2000-2010
time = np.random.randint(2000,2011,size=1000)#add time to X
X = np.hstack((X,time.reshape(-1,1)))#create target via a linear relationship to X
weights = np.random.rand(11)
y = X.dot(weights)#create test data that includes years
#not in training data 2000 - 2019
X_test = np.random.rand(1000,10)
time_test = np.random.randint(2000,2020,size=1000)
X_test = np.hstack((X_test,time_test.reshape(-1,1)))
y_test = X_test.dot(weights)

让我们看看一个随机森林能多好地预测测试数据。

#fit and score the data using RF
RF = RandomForestRegressor(n_estimators=100)
RF.fit(X,y)
RF.score(X_test,y_test)
>>0.5872576516824577

那不太好。让我们对照它们的已知值来绘制我们的预测,看看发生了什么。

#plot RF as trees increase
#set starting point for subplots
index = 1#set the size of the subplot to something large
plt.figure(figsize=(20,20))#iterate through number of trees in model
#and plot predictions v actual
for i in [1,5,10,100]:
    plt.subplot(2, 2, index)
    RF_plot = RandomForestRegressor(n_estimators=i)
    RF_plot.fit(X,y)
    #split data btw vals RF can interploate vs. data
    #it needs to exptrapolate
    interpolate_index = X_test[:,10]<=2010
    extrapolate_index = X_test[:,10]>2010
    X_interpolate = X_test[interpolate_index]
    X_extrapolate = X_test[extrapolate_index]
    y_interpolate = y_test[interpolate_index]
    y_extrapolate = y_test[extrapolate_index]
    #plot predictions vs. actual
    plt.scatter(RFplot.predict(X_interpolate),
                y_interpolate,
                color="g",label="interpolate")
    plt.scatter(RFplot.predict(X_extrapolate),
                y_extrapolate,
                color="b",label="extrapolate")
    plt.xlabel('Predicted')
    plt.ylabel('Actual')
    plt.title('Random Forest with {} trees'.format(i))
    plt.subplots_adjust(wspace=.4, hspace=.4)
    plt.legend(loc="best")
    index += 1

Predicted vs. Actual Random Forest

该图清楚地表明,模型可以预测的最高值约为 961,而数据中的潜在趋势将更近的值推高至 966。不幸的是,随机森林无法外推线性趋势,也无法准确预测时间值高于训练数据(2000–2010)中所见时间值的新示例。即使调整树木的数量也不能解决问题。在这种情况下,由于我们对数据施加了完美的线性关系,因此像线性回归这样的模型将是更好的选择,并且在检测数据趋势和对训练数据中时间范围之外的数据做出准确预测方面不会有问题。

#fit the data using Linear Regression
LR = LinearRegression()
LR.fit(X,y)
LR.score(X_test,y_test)
>>1.0#plot predictions of Linear Regression against actual
plt.figure(figsize=(7,7))
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Linear Regression - Test Data')
_ = plt.scatter(LR.predict(X_interpolate),y_interpolate,
               color="g",label="interpolate")
_ = plt.scatter(LR.predict(X_extrapolate),y_extrapolate,
               color="b",label="extrapolate")
plt.legend(loc="best")

Predicted vs. Actual Linear Regression

虽然随机森林通常是一个很好的模型选择,但了解它是如何工作的,以及在给定数据的情况下它是否有任何限制仍然很重要。在这种情况下,因为它是一个基于邻域的模型,所以它阻止我们对训练数据之外的时间范围进行准确预测。如果你发现自己处于这种情况,最好是测试其他模型,如线性回归或立体模型,和/或考虑在模型集合中使用随机森林。预测快乐!

马尔可夫链简介

原文:https://towardsdatascience.com/a-lite-introduction-to-markov-chains-eebe239f9147?source=collection_archive---------17-----------------------

Photo by JJ Ying on Unsplash

之前我写了一篇关于潜在狄利克雷分配的简介,作为深入探究自然语言处理(NLP)为何如此伟大的一部分。随着人工智能的不断发展,NLP 将在未来几年内(确切地说,直到 2025 年)加速发展。它是关键驱动因素之一,而且随着它继续成为我们日常生活的一部分,也许有必要了解它在幕后是如何工作的。有大量不同的概念、数学和模型进入不同的 NLP 用例,但我们只打算在基础层面上理解一个,那就是马尔可夫链。

启动马尔可夫链不仅用于 NLP。数字还有其他应用,但我们现在只关注它与 NLP 的关系。此外,还有许多与马尔可夫链(例如,转移图、转移概率矩阵和初始状态分布矩阵)和数学相关的术语,我们不会讨论。这篇文章是对马尔可夫链的简单介绍。在后面的系列文章中,我们可以深入探讨,但首先,让我们了解一下它的基本要点。

马尔可夫链,它的同名者是俄罗斯数学家安德烈·马尔可夫。定义为“…描述一系列可能事件的随机模型,其中每个事件的概率仅取决于前一个事件达到的状态。”随机模型是一种随机性模型。我们试图根据这个变量及其相关变量来发现接下来会发生什么。事实上,这个模型非常容易理解,但是理解它的基础是马尔可夫性。

马尔可夫性质表明我们不知道所有的历史,只知道以前的历史,我们是无记忆的。做出预测只需要最近的事件和未来事件的可能性。想象一下今天正在下雨,而你不知道过去还发生过什么天气事件。然而,你知道明天有 50%的可能会下雨,30%的可能是晴天,20%的可能是阴天。选择你的冒险。我们用最大概率去吧。现在继续到第二天,我们再次忘记前一天发生的事情,知道今天下雨,为了简单起见,概率是相同的,我们选择这次是晴天,一个新的状态,这意味着某事发生的新概率。如果太阳多的概率是 10%,下雨的概率是 20%,但是下雪的概率是 70%呢?

如果你看马尔可夫链,你可能会看到像这样的图像四处浮动。让我们来分解一下,从冰淇淋开始。这有点令人眼花缭乱,所以请原谅我。如果你吃了冰淇淋,有 10%的几率你会再次吃冰淇淋,20%的几率你会去睡觉,70%的几率你会去跑步。如果你跑步,你有 60%的机会再次跑步,30%的机会吃冰淇淋,10%的机会睡觉。如果你睡觉,有 20%的几率你会继续睡觉,20%的几率你会吃冰淇淋,60%的几率你会跑步。看起来宇宙,又名马尔可夫链,正试图告诉你一些事情:快跑!!

应用到自然语言处理中,我们可以用这个来预测单词。给定单词“我”,在它后面会有什么单词?在文本语料库中,我们可以找到所有直接跟在 I 后面的单词,并把它们放入字典中,以“I”作为关键字,所有与之相关的单词作为值。如果一个单词出现超过两次,那么它的概率就会增加,太少的话,它的概率就会下降。从那里,选择一个单词,然后我们继续下一个键:值对来做出另一个决定。只要你觉得你在代码中创建的函数合适,这个过程就会一直持续下去。

在 NLP 中使用它的问题是理解模型做得有多好。这个模型就是所谓的分室模型,在这个模型中,我们指定所考虑的不同状态,并且我们确定移动到下一步的概率,不管有多少个。如果我们用数字工作,这很容易评估它是如何工作的。一个生存或死亡的双态模型说明了这一点。假设我们有 1000 个人活着,你有 5%的几率死去,95%的几率活着。有了这些严格的数字,我们可以为自己的每次迭代创建期望。在第一次迭代中,50 人死亡,950 人活着,第二年又有 50 人死亡,900 人活着。我们可以不断设定期望值,然后运行我们的模型,看看它有多接近这些数字。这个例子很容易看出我们如何评估它,但现在想象一个有 1000 个单词的语料库和与之相关的每个单词的概率。这有点难以计算。我最近用它来生成文本,我能评估它的唯一方法是确定它听起来语法不正确,只是一堆混乱的单词。我能做的唯一实际评估是,把它和马尔可夫链创造的句子进行比较。将来,如果您打算使用 Markov Chain 来生成文本(它主要用于 NLP ),请尝试将其与递归神经网络模型生成的文本进行比较,看看 Markov Chain made 版本的效果如何。

供思考的一点空间:易于使用的 NLP 框架

原文:https://towardsdatascience.com/a-little-spacy-food-for-thought-easy-to-use-nlp-framework-97cbcc81f977?source=collection_archive---------19-----------------------

在下面的文章中,你将会看到如何快速简单地开始使用 spaCy。这是特别有用的初学者爱好者在 NLP 领域的一步一步的指示和光明的例子。

spaCy 是一个 NLP 框架,由 Explosion AI 于 2015 年 2 月发布。它被认为是世界上最快的。易于使用和有能力使用神经网络是它的其他优势。

第一步:安装空间

打开您的终端(命令提示符),写下:

pip install spacy

第二步:下载语言模型

编写以下命令(仍在您的终端中):

python -m spacy download en_core_web_lg

型号(en_core_web_lg)是 spaCy 最大的英文型号,大小为 788 MB。有英文版的小模型,也有其他语言版的模型(英语、德语、法语、西班牙语、葡萄牙语、意大利语、荷兰语、希腊语)。

第三步:导入库并加载模型

在 python 编辑器中编写了以下几行代码后,您就可以享受 NLP 的乐趣了:

import spacy
nlp = spacy.load(‘en_core_web_lg’)

步骤 4:创建样本文本

sample_text = “Mark Zuckerberg took two days to testify before members of Congress last week, and he apologised for privacy breaches on Facebook. He said that the social media website did not take a broad enough view of its responsibility, which was a big mistake. He continued to take responsibility for Facebook, saying that he started it, runs it, and he is responsible for what happens at the company. Illinois Senator Dick Durbin asked Zuckerberg whether he would be comfortable sharing the name of the hotel where he stayed the previous night, or the names of the people who he messaged that week. The CEO was startled by the question, and he took about 7 seconds to respond with no.”doc = nlp(sample_text)

步骤 5:拆分段落的句子

让我们把这篇文章分成几个句子,并在句尾写上每个句子的字符长度:

sentences = list(doc3.sents)
for i in range(len(sentences)):
 print(sentences[i].text) 
 print(“Number of characters:”, len(sentences[i].text))
 print(“ — — — — — — — — — — — — — — — — — -”)

输出:

Mark Zuckerberg took two days to testify before members of Congress last week, and he apologised for privacy breaches on Facebook.
Number of characters: 130
-----------------------------------
He said that the social media website did not take a broad enough view of its responsibility, which was a big mistake.
Number of characters: 118
-----------------------------------
He continued to take responsibility for Facebook, saying that he started it, runs it, and he is responsible for what happens at the company.
Number of characters: 140
-----------------------------------
Illinois Senator Dick Durbin asked Zuckerberg whether he would be comfortable sharing the name of the hotel where he stayed the previous night, or the names of the people who he messaged that week.
Number of characters: 197
-----------------------------------
The CEO was startled by the question, and he took about 7 seconds to respond with no.
Number of characters: 85
-----------------------------------

步骤 6:实体识别

实体识别性能是自然语言处理模型的一个重要评价标准。spaCy 用一行代码就成功地实现了这一点:

from spacy import displacy
displacy.render(doc, style=’ent’, jupyter=True)

输出:

步骤 7:标记化和词性标注

让我们对文本进行标记化,并查看每个标记的一些属性:

for token in doc:
 print(“{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}”.format(
 token.text,
 token.idx,
 token.lemma_,
 token.is_punct,
 token.is_space,
 token.shape_,
 token.pos_,
 token.tag_
 ))

输出:

Mark	0	mark	False	False	Xxxx	PROPN	NNP
Zucker.	5	zucker.	False	False	Xxxxx	PROPN	NNP
took	16	take	False	False	xxxx	VERB	VBD
two	21	two	False	False	xxx	NUM	CD
days	25	day	False	False	xxxx	NOUN	NNS
to	30	to	False	False	xx	PART	TO
testify	33	testify	False	False	xxxx	VERB	VB
before	41	before	False	False	xxxx	ADP	IN
members	48	member	False	False	xxxx	NOUN	NNS
of	56	of	False	False	xx	ADP	IN

同样,它非常容易应用,并立即给出令人满意的结果。关于我打印出来的属性的简要说明:

text: token itselfidx: starting byte of the tokenlemma_: root of the wordis_punct: is it a punctuation symbol or notis_space: is it a space or notshape_: shape of the token to show which letter is the capitalpos_: the simple part of speech tagtag_: the detailed part of speech tag

什么是言语标记?

它是在将整个文本分割成标记后,给每个标记(如名词、动词、形容词)分配标记的过程。

第八步:只有数字

当我们在处理语言和文本时,数字从何而来?

由于机器需要把一切都转换成数字来理解世界,所以在 NLP 世界中每个单词都用一个数组(单词向量)来表示。以下是《空间词典》中“人”的词向量:

[-1.7310e-01,  2.0663e-01,  1.6543e-02, ....., -7.3803e-02]

spaCy 的词向量的长度是 300。在其他框架中可以不同。

在建立单词向量之后,我们可以观察到上下文相似的单词在数学上也是相似的。以下是一些例子:

from scipy import spatialcosine_similarity = lambda x, y: 1 — spatial.distance.cosine(x, y)print(“apple vs banana: “, cosine_similarity(nlp.vocab[‘apple’].vector, nlp.vocab[‘banana’].vector))print(“car vs banana: “, cosine_similarity(nlp.vocab[‘car’].vector, nlp.vocab[‘banana’].vector))print(“car vs bus: “, cosine_similarity(nlp.vocab[‘car’].vector, nlp.vocab[‘bus’].vector))print(“tomatos vs banana: “, cosine_similarity(nlp.vocab[‘tomatos’].vector, nlp.vocab[‘banana’].vector))print(“tomatos vs cucumber: “, cosine_similarity(nlp.vocab[‘tomatos’].vector, nlp.vocab[‘cucumber’].vector))

输出:

apple vs banana:  0.5831844210624695
car vs banana:  0.16172660887241364
car vs bus:  0.48169606924057007
tomatos vs banana:  0.38079631328582764
tomatos vs cucumber:  0.5478045344352722

印象深刻?当比较两种水果或蔬菜或两种交通工具时,相似性更高。当两个不相关的物体如一辆汽车和一根香蕉进行比较时,相似性很低。当我们检查西红柿和香蕉的相似性时,我们观察到它高于汽车对香蕉的相似性,但低于西红柿对黄瓜和苹果对香蕉的相似性,这反映了现实。

第九步:国王=王后+(男人——女人)?

如果一切都用数字来表示,如果我们可以用数学的方法计算相似性,我们可以做一些其他的计算吗?比如我们把“男”减去“女”,把差加到“后”,能不能找到“王”?让我们试试:

from scipy import spatial

cosine_similarity = lambda x, y: 1 — spatial.distance.cosine(x, y)

man = nlp.vocab[‘man’].vector
woman = nlp.vocab[‘woman’].vector
queen = nlp.vocab[‘queen’].vector
king = nlp.vocab[‘king’].vectorcalculated_king = man — woman + queenprint(“similarity between our calculated king vector and real king vector:”, cosine_similarity(calculated_king, king))

输出:

similarity between our calculated king vector and real king vector: 0.771614134311676

我觉得还不错。你可以用不同的单词替换来尝试,你会观察到相似的有希望的结果。

总之;

本文的目的是对 spaCy 框架做一个简单的介绍,并展示一些简单的 NLP 应用示例。希望它是完美的。你可以在他们设计精良、内容丰富的网站https://spacy.io/上找到详细的信息和大量的例子。

如果你有任何进一步的问题,请不要犹豫,写信给:haydarozler@gmail.com。

从各种图表看詹姆斯·哈登的《可笑的季节》

原文:https://towardsdatascience.com/a-look-at-ridiculous-season-by-james-harden-through-various-charts-cbc790ff5d7f?source=collection_archive---------23-----------------------

很多人爱哈登,更有甚者,受不了他的比赛。但他正在经历现代篮球史上最令人印象深刻的赛季之一。他在没有太多低效的情况下打出了惊人的高投篮命中率。他正在做的这一切都要归功于他的(甚至更令人讨厌的)顶级武器。

单人军队

没有必要去搜索高级统计数据来了解詹姆斯·哈登背上的负担有多大。他已经连续 31 场比赛得分超过 30 分,这是除了伟大的威尔特·张伯伦之外 NBA 历史上最长的连胜纪录。但那是一些不同的时代,在 1979-80 年开始的三分时代,连续 30 场比赛得分最多的第二名是科比·布莱恩特,连续 16 场比赛,第三名是特雷西·麦克格雷迪,14 场比赛。他们都在 2002-03 赛季取得了这样的成就。

那个荒谬的事实让我研究了哈登本赛季的统计数据,我接着寻找的第一件事就是助攻/无助攻投篮命中率。我收集了从 1999-00 赛季到今年的数据。从 1996-97 赛季开始跟踪助攻得分的百分比,但我排除了前几个赛季,因为三分球线较短,三分球的数量过多。

Assisted vs Unassisted field goals made since 1999–00 — Image by Author

在上面的图表中,你可以看到自 1999-00 赛季以来,前 10 名得分手在每个赛季中助攻和无助攻的投篮次数。我还标记了那段时间总得分最高的 10 名球员。有趣的是,威斯布鲁克,艾弗森,甚至勒布朗的投篮总数大致相同。虽然代表罚球的圆圈大小比威斯布鲁克的大一点,但区别在于只有 50 次罚球,这使他领先拉塞尔约 150 分。

Assisted vs Unassisted 3pt field goals since 1999–00 — Image by Author

所有这些想法促使我制作了第二张图表。这里可以看到,他比其他球员的优势是由于疯狂的无辅助三分球数量而实现的。他在除了詹姆斯·哈登以外的任何球员面前都有超过 100 个无助攻三分球。

运球和每次触球得分

看到哈登疯狂的无助攻投篮次数,我想看看他每次运球次数和得分之间的相关性。

Dribbles per touch and points per touch — Image by Author

只有两个球员的每次运球次数超过哈登,他们是托尼·帕克和 DJ 奥古斯丁。一般来说,很多每次运球超过 4 次的球员都是控卫,这是符合逻辑的,因为他们通常会带球过球场,并叫停比赛,等等。但即使这样,哈登的每次触球得分也非常高。这意味着大多数触球不仅仅是带球穿过球场,而是带球,最终创造投篮机会,大多数时候是投篮。

我不知道他的高 PPT(每触得分)和高运球次数是否比保罗·乔治每触得分半分更令人印象深刻,这意味着他每第二次触球得分。他看起来真的是威斯布鲁克的完美球员,也是真正的 MVP 候选人。

拍摄图表

这篇文章的第二部分将致力于分析詹姆斯·哈登的投篮图表,以及他的投篮选择。类似于我之前的帖子,关于Luka don CII

Image by Author

首先,这里是哈登本赛季所有投篮的常规投篮图。他投了很多三分球,更重要的是,他的命中率很高。在真正的莫雷球精神中,中距离跳投并不多,所以在投篮不够的情况下,百分比真的不重要。

退后跳投

但现在我们来到了这篇文章最有趣的部分之一,也是哈登最危险的武器。当然,他的武器库中最有争议的一个镜头是《退后一步》。如果你看了视频,你会注意到有一些看起来像旅行的尝试。这就是所有大惊小怪的地方。但是我不会在这篇文章中深入探讨这个问题。我只想看看詹姆斯·哈登在退后一步跳投方面有多棒。

如果你看了我关于卢卡·东契奇的帖子(我把上面的几段链接了起来),你可能会注意到我为他的后退跳投做了一个原始的投篮图表。

Too Cluttered — Image by Author

我试着在这里做同样的事情,但是结果是毫无意义的。这是因为詹姆斯·哈登退后跳投的次数几乎是他所有投篮尝试的三分之一(总共 1316 次投篮尝试中的 417 次退后)。这种镜头的数量对于这个原始镜头图表来说太大了,没有意义,所以我像绘制普通镜头图表一样绘制它。

Image by Author

现在,这个图表真的令人印象深刻。与联盟平均百分比的比较与上面图表中的方法相同。这意味着他在每个区域的得分百分比是用所有类型的击球来计算的,而不仅仅是后退。从这张图表中我们可以得出结论,詹姆斯·哈登的退后一步跳投远高于任何类型投篮的平均 3%的命中率。

为了更好地理解詹姆斯·哈登退后一步跳投的效率有多荒谬,这里有另一个图表。

Image by Author

只有几个球员的三分球比詹姆斯·哈登还多。确切的说,只有八个。他也很有效地把握住了这些机会,超过 40%的尝试都成功了。

卡里姆有他的天勾,乔丹,科比和德克有他们自己版本的后仰投篮,哈基姆有梦摇,哈登有后退。

效率和使用

当人们想到哈登时,他们会想到几件事:

退后跳投。

走向罚球线。

成为一个投很多球的投手。

第一点我已经讲过了。在这篇文章中,除了在几个图表中作为的辅助数据,我没有触及罚球的话题。但我将试图揭穿围绕他的第三个想法。

首先,让我解释一下将在接下来的几个图表中看到的术语使用率。根据篮球参考,使用率百分比(或比率)是一个球员在场上使用的团队比赛百分比的估计。更具体地说,这意味着使用率是一个衡量球员在场上的所有比赛中有多少次投篮、罚球或失误的指标。

Image by Author

现在我们用效率和使用量来看看今年的情况。这张图表显示了 PPG 排名前 100 位的运动员。就使用而言,詹姆斯·哈登是他自己的故事,乔尔·恩比德落后 7%。这里可以看出总的趋势,随着使用率的上升,真实命中率下降。最大的异类肯定是哈登,但值得一提的是库里,詹尼斯和杜兰特也是异类。

Image by Author

这张图表显示了三分时代前 100 名得分手的效率,取决于使用情况。如前所述,我没有包括老一代的玩家,因为没有使用率和其他高级指标的数据。

根据 basketball-reference 的数据,詹姆斯·哈登的使用率在现代历史上(嗯,跟踪使用率的历史)排名第二,仅次于拉塞尔·维斯特布鲁克的 monster 2016-17 赛季。但是,他的真实投篮命中率(PTS / (2 * (FGA + 0.44 * FTA))比他高大约 7%。事实上,真实的百分比也比联盟平均水平高 7%,同时具有历史最高的使用率。

在此期间,我还标记了前 10 名得分手,以及查尔斯·巴克利 1987-88 赛季和斯蒂芬·库里令人难以置信的高效 2015-17 赛季,令人难以置信的 67%的 TS%。

这两张图表本身应该足以阻止哈登投篮命中率低和效率低的说法。

基于情况类型的评分

我要讲的最后一个话题是基于动作类型的分数。这也是我在关于 don ci 的帖子中提到的东西,但是我为这个帖子做了一个更有趣的可视化。我决定将这些值绘制成一个平行图,这导致了下面的图表。

Image by Author

我试着想象 MVP 的前 5 名候选人是如何得分的。用灰色线条,我也代表了本赛季前 50 名的得分手。这实际上只是根据这六种类型的评分来概述分数的大致分布。展示哈登在得分和拉高得分方面的差距,以及展示他的接球和投篮得分有多少。他在这方面得分如此之少是有道理的,因为整个赛季他有大约 70 个助攻进球,但人们会认为这个数字会更高。

在那之后,我很好奇休斯顿火箭队球员的情况。

Image by Author

和预期的差不多。卡佩拉和法里德在内线得分和一些肘部跳投中占据主导地位,每个人都专注于接球和投篮(每场比赛大约有 6 名球员在 4 分左右徘徊)。似乎只有克里斯·保罗和埃里克·戈登是另外两个在某些时候创造进球机会的球员。

如果你现在仔细看第一张图表,你会发现卡佩拉在得分上领先联盟。保罗和哈登这两个伟大的组织者显然是一个巨大的推动。

辅助图表

对于本帖的最后一张图表,我决定看看哈登助攻的一些投篮得分,看看他是如何为队友服务的。我受到启发,想到多亏了我在 Nylon Calculus 上看到的这个很棒的帖子。不幸的是,我没有传球起点的位置,换句话说,哈登从哪里传球,所以我的图表看起来不那么有吸引力。

Image by Author

简而言之,这是一张图表,非常粗糙,因为我不知道如何在视觉上改进它,但它很有用。看到他的助攻有 8 次中距离投篮(如果不算 PJ 塔克在篮下的投篮,就更少了),真是令人印象深刻。看起来哈登要么把球踢到三分范围内,要么只是把球投低上篮/扣篮。正如我已经说过的,以真正的莫雷球的方式。

结论

最后,我想说研究哈登的数据是一件非常有趣和简单的事情。无论你在哪里看,他都在一些历史上很好的数据上表现,除了在防守上,但即使在那里他也是在最差的平均数据上。

有些人仍然试图淡化本赛季和 MVP 候选资格,因为防守和我提到的其他一些要点(罚球,退后一步旅行,等等。),但事实是詹姆斯·哈登是一个进攻怪兽,他正在经历 NBA 篮球历史上最繁荣和高效的赛季之一。对我来说,他是 MVP 竞争中的主要领跑者,尽管也有一些伟大的候选人,如保罗·乔治,詹尼斯,当然还有斯蒂芬库里。这将会是一个有趣而激动人心的赛季,MVP 也是如此。

所有这些图表都是由来自 stats.nba.com 或 T2 的数据生成的。所有图表都是用 Python 创建的,使用的是 matplotlib 和 seaborn。代码以 Jupyter 笔记本的形式存在于我的 Github 库中。

逻辑回归模型中特征重要性的研究

原文:https://towardsdatascience.com/a-look-into-feature-importance-in-logistic-regression-models-a4aa970f9b0f?source=collection_archive---------2-----------------------

在完成了一个调查 PUBG 中 winning 的项目(https://medium . com/@ jasonrichards 911/winning-in-PUBG-clean-data-does-mean-ready-data-47620 a 50564)之后,我突然想到不同的模型会产生不同的功能重要性排名。对于模型选择的级别(逻辑回归、随机森林、XGBoost)并不奇怪,但在我的数据科学头脑中,我必须挖掘得更深,特别是在逻辑回归中。

让我们为那些已经准备点击后退按钮的人换一个方向。特征选择是模型调整中的一个重要步骤。简而言之,它降低了数据集中的维数,从而提高了模型的速度和性能。现在,我知道这涉及到一个更老的(我们称之为“有经验的”)模型…但是我们知道有时候老狗正是你所需要的。

稍微研究了一下之后,我发现了三种在逻辑回归模型中排列特性的方法。这将通过系数值、递归特征消除(RFE)和 sci-kit Learn 的 SelectFromModels (SFM)来实现。

所有这些方法都应用于 sklearn.linear_model。物流回归,因为 RFE 和 SFM 都是 sklearn 包。另请注意,运行 Statsmodels 版本的逻辑回归(Logit)来比较初始系数值,初始排名是相同的,因此我会假设在 Logit 模型上执行任何其他方法都会产生相同的结果,但我确实讨厌 ass-u-me 这个词,因此如果有任何人想要测试该假设,请随意使用。在执行这些方法之前,数据也被擦洗、清洁和白化。

现在来看本质。第一,系数。系数越高,特征的“重要性”越高。为了设置基线,决定选择前八个特性(这就是项目中使用的特性)。数据被拆分和拟合。如果你看看下面的图片,碰巧所有的正系数都产生了前八个特性,所以我只是将布尔值与列索引相匹配,并列出下面的八个。(靴子,杀死,步行距离,助攻,杀死条纹,骑距离,游泳距离,武器获得)。

LogReg Feature Selection by Coefficient Value

接下来是 RFE,可在 sklearn.feature_selection.RFE 中找到。RFE 没有深入研究细节,它是一种特征选择方法,适合模型,并删除最弱的特征(或多个特征),直到达到指定的特征数量。要获得特性的完整排名,只需设置参数 n_features_to_select = 1。如果将它设置为大于 1 的任何值,它会将前 n 名排序为 1,然后按顺序递减。在这里,在一点点列表操作(增强,伤害,爆头,治疗,杀伤点,杀伤,连续杀伤,最长杀伤)后,排名是非常明显的。

LogReg Feature Selection by RFE

使用的最后一个方法是 sk learn . feature _ selection . selectfrommodel。该函数的预期方法是,它将按重要性选择特性,您可以将它们保存为自己的特性数据帧,并直接实施到调整后的模型中。操纵代码来提供所选列的名称需要一点工作,但是有了咖啡因、时间和 Stackoverflow,一切皆有可能。(提升,伤害,死亡,死亡条纹,比赛持续时间,骑行距离,团队死亡,步行距离)。

LogReg Feature Selection with SFM

现在来看看从每种方法中选择的特性是如何改进模型的。具有所有特征(总共 18 个)的原始 LogReg 函数产生 0.9771113517371199 的“曲线下面积”(AUC)和 93%的 F1 分数。

系数排名:AUC:0.975317873246652;F1: 93%。因为我们确实减少了一半以上的功能,失去. 002 是一个相当不错的结果。

RFE:AUC:0.9726984765479213;F1: 93%。实际表现比系数选择稍差,但差不了多少。

SFM:AUC:0.976537660071581;F1: 93%。最佳性能,但也差不了多少

结论:总的来说,这两种方法的性能没有太大的差别。从计算开销的角度来看,系数排名是目前最快的,SFM 紧随 RFE 之后。需要记住的是,在超参数调整后,精确度可能会受到指数影响,如果这是在一场以美元为单位的 Kaggle 竞赛中排名第一或第二之间的差异,那么如果逻辑回归是最适合的模型,那么用尽您的特征选择选项可能值得一点额外的计算费用。

顺便提一下:我的 XGBoost 选择了 ( 击杀、步行距离、最长击杀、获得武器、治疗、增强、辅助、爆头击杀),这导致了(在超参数调整之后)99.4%的测试准确度分数。

GLTR 研究(使用 GPT 新协议)

原文:https://towardsdatascience.com/a-look-into-gltr-using-gpt-2-76d823057421?source=collection_archive---------12-----------------------

Taken from http://gltr.io/

随着 BERT 模型[1]的发布,自然语言处理(NLP)领域在过去的一年中取得了巨大的进步,该模型改善了许多问题的技术水平,如文本分类、问题回答等。现在,Open AI [2]发布了名为 GPT-2 [3]的语言模型,据称该模型能够生成无法识别为机器或人类所写的文本样本。

最近,来自麻省理工学院-IBM 沃森人工智能实验室和哈佛大学的合作团队推出了一款名为GiantLangauge ModelTestRoom(GLTR)的文本取证工具。GLTR 基本上使用 GPT-2 语言模型来区分人类生成的文本和机器生成的文本。

在这篇文章中,我将使用GLTR(Python 中的)来分析不同来源的文本片段,看看它们在文本的平滑度方面有何不同。我将使用 https://github.com/HendrikStrobelt/detecting-fake-text的 GLTR 代码。

下面是这段代码,将文本作为输入并使用 GPT-2 模型来输出包含三样东西的有效载荷

  1. 给定上下文中每个单词的概率。
  2. 给定上下文,整个词汇表中每个单词的等级。
  3. 给定上下文,前 K 个单词及其概率。
*import* numpy *as* np
*import* torch
*import* time
*import* nltk

*from* pytorch_pretrained_bert *import* (GPT2LMHeadModel, GPT2Tokenizer,
                                     BertTokenizer, BertForMaskedLM)

*from* matplotlib *import* pyplot *as* plt

*class* AbstractLanguageChecker():
    *"""
    Abstract Class that defines the Backend API of GLTR.

    To extend the GLTR interface, you need to inherit this and
    fill in the defined functions.
    """

    def __init__*(*self*):
        *'''
        In the subclass, you need to load all necessary components
        for the other functions.
        Typically, this will comprise a tokenizer and a model.
        '''
        self*.device = torch.device(
            "cuda" *if* torch.cuda.is_available() *else* "cpu")

    *def* check_probabilities(*self*, in_text, topk=40):
        *'''
        Function that GLTR interacts with to check the probabilities of words

        Params:
        - in_text: str -- The text that you want to check
        - topk: int -- Your desired truncation of the head of the distribution

        Output:
        - payload: dict -- The wrapper for results in this function, described below

        Payload values
        ==============
        bpe_strings: list of str -- Each individual token in the text
        real_topk: list of tuples -- (ranking, prob) of each token
        pred_topk: list of list of tuple -- (word, prob) for all topk
        '''
        raise* NotImplementedError

    *def* postprocess(*self*, token):
        *"""
        clean up the tokens from any special chars and encode
        leading space by UTF-8 code '\u0120', linebreak with UTF-8 code 266 '\u010A'* ***:param*** *token:  str -- raw token text* ***:return****: str -- cleaned and re-encoded token text
        """
        raise* NotImplementedError

*def* top_k_logits(logits, k):
    *'''
    Filters logits to only the top k choices
    from https://github.com/huggingface/pytorch-pretrained-BERT/blob/master/examples/run_gpt2.py
    '''
    if* k == 0:
        *return* logits
    values, _ = torch.topk(logits, k)
    min_values = values[:, -1]
    *return* torch.where(logits < min_values,
                       torch.ones_like(logits, dtype=logits.dtype) * -1e10,
                       logits)

*class* LM(AbstractLanguageChecker):
    *def __init__*(*self*, model_name_or_path="gpt2"):
        super(LM, *self*).__init__()
        *self*.enc = GPT2Tokenizer.from_pretrained(model_name_or_path)
        *self*.model = GPT2LMHeadModel.from_pretrained(model_name_or_path)
        *self*.model.to(*self*.device)
        *self*.model.eval()
        *self*.start_token = '<|endoftext|>'
        print("Loaded GPT-2 model!")

    *def* check_probabilities(*self*, in_text, topk=40):
        *# Process input* start_t = torch.full((1, 1),
                             *self*.enc.encoder[*self*.start_token],
                             device=*self*.device,
                             dtype=torch.long)
        context = *self*.enc.encode(in_text)
        context = torch.tensor(context,
                               device=*self*.device,
                               dtype=torch.long).unsqueeze(0)
        context = torch.cat([start_t, context], dim=1)
        *# Forward through the model* logits, _ = *self*.model(context)

        *# construct target and pred* yhat = torch.softmax(logits[0, :-1], dim=-1)
        y = context[0, 1:]
        *# Sort the predictions for each timestep* sorted_preds = np.argsort(-yhat.data.cpu().numpy())
        *# [(pos, prob), ...]* real_topk_pos = list(
            [int(np.where(sorted_preds[i] == y[i].item())[0][0])
             *for* i *in* range(y.shape[0])])
        real_topk_probs = yhat[np.arange(
            0, y.shape[0], 1), y].data.cpu().numpy().tolist()
        real_topk_probs = list(map(*lambda* x: round(x, 5), real_topk_probs))

        real_topk = list(zip(real_topk_pos, real_topk_probs))
        *# [str, str, ...]* bpe_strings = [*self*.enc.decoder[s.item()] *for* s *in* context[0]]

        bpe_strings = [*self*.postprocess(s) *for* s *in* bpe_strings]

        *# [[(pos, prob), ...], [(pos, prob), ..], ...]* pred_topk = [
            list(zip([*self*.enc.decoder[p] *for* p *in* sorted_preds[i][:topk]],
                     list(map(*lambda* x: round(x, 5),
                              yhat[i][sorted_preds[i][
                                      :topk]].data.cpu().numpy().tolist()))))
            *for* i *in* range(y.shape[0])]

        pred_topk = [[(*self*.postprocess(t[0]), t[1]) *for* t *in* pred] *for* pred *in* pred_topk]
        payload = {'bpe_strings': bpe_strings,
                   'real_topk': real_topk,
                   'pred_topk': pred_topk}
        *if* torch.cuda.is_available():
            torch.cuda.empty_cache()

        *return* payload

    *def* sample_unconditional(*self*, length=100, topk=5, temperature=1.0):
        *'''
        Sample `length` words from the model.
        Code strongly inspired by
        https://github.com/huggingface/pytorch-pretrained-BERT/blob/master/examples/run_gpt2.py

        '''* context = torch.full((1, 1),
                             *self*.enc.encoder[*self*.start_token],
                             device=*self*.device,
                             dtype=torch.long)
        prev = context
        output = context
        past = *None
        # Forward through the model
        with* torch.no_grad():
            *for* i *in* range(length):
                logits, past = *self*.model(prev, past=past)
                logits = logits[:, -1, :] / temperature
                *# Filter predictions to topk and softmax* probs = torch.softmax(top_k_logits(logits, k=topk),
                                      dim=-1)
                *# Sample* prev = torch.multinomial(probs, num_samples=1)
                *# Construct output* output = torch.cat((output, prev), dim=1)

        output_text = *self*.enc.decode(output[0].tolist())
        *return* output_text

    *def* postprocess(*self*, token):
        with_space = *False* with_break = *False
        if* token.startswith('Ġ'):
            with_space = *True* token = token[1:]
            *# print(token)
        elif* token.startswith('â'):
            token = ' '
        *elif* token.startswith('Ċ'):
            token = ' '
            with_break = *True* token = '-' *if* token.startswith('â') *else* token
        token = '“' *if* token.startswith('ľ') *else* token
        token = '”' *if* token.startswith('Ŀ') *else* token
        token = "'" *if* token.startswith('Ļ') *else* token

        *if* with_space:
            token = '\u0120' + token
        *if* with_break:
            token = '\u010A' + token

        *return* token

为了检查一篇文章的通顺程度,我会画出每个单词的排名。根据 GPT-2 语言模型,如果文本中单词的排名较高,则文本将是不平滑的。以下代码用于为文本创建这些绘图。

*def* plot_text(vals, what, name):
    *if* what=="prob":
        ourvals = vals[0]
        x = list(range(1,len(ourvals)+1))
        y = ourvals
        plt.plot(x, y, color='orange')
        plt.ylim(0,1)
        plt.savefig(name + ".png")
        *# plt.show()
    elif* what=="rank":
        ourvals = vals[1]
        x = list(range(1, len(ourvals) + 1))
        y = ourvals
        plt.plot(x, y, color='orange')
        plt.ylim(-1000, 50000)
        plt.savefig(name + ".png")
        *# plt.show()**def* main_code(raw_text):
    lm = LM()
    start = time.time()
    payload = lm.check_probabilities(raw_text, topk=5)
    *# print(payload["pred_topk"])* real_topK = payload["real_topk"]
    ranks = [i[0] *for* i *in* real_topK]
    preds = [i[1] *for* i *in* real_topK]
    plot_text([preds, ranks], 'rank', "rank_")
    end = time.time()
    print("{:.2f} Seconds for a check with GPT-2".format(end - start))

现在,让我们看看不同来源的文本在流畅度方面是否有所不同。我们将检查以下文本。

  1. 由 GPT-2 语言模型生成的文本。
  2. 新闻文章中的文字。
  3. 来自博客的文本。

以下是情节:

Rank plot for GPT-2 Generated Text

Rank plot for News Article

Rank plot for Blog Text

GPT-2 生成的文本的等级图非常平滑,因为它是由 GPT-2 模型本身检查的。博客和新闻文章数据有一些峰值,这表明围绕这些词有一些不一致之处。

作为一个有趣的练习,你可以分析不同类型的文章,看看在流畅度方面有什么不同。

GLTR 的一个主要用途可能是在 Grammarly 这样的系统中。它可以指出导致不一致的单词,并提示用户进行更改。这至少是一个不错的 GitHub 项目。

参考文献

[1]https://arxiv.org/abs/1810.04805

[2]https://openai.com/

[3]https://d4mucfpksywv . cloudfront . net/better-language-models/language _ models _ are _ unsupervised _ multask _ learners . pdf

机器生成的书和算法作者

原文:https://towardsdatascience.com/a-machine-generated-book-and-an-algorithmic-author-f02d4e62ffbe?source=collection_archive---------18-----------------------

对比是显而易见的。在奥威尔的《1984 年的 T0》中,一台机器被用来大量生产书籍,并分发给大众。轻率,浮夸和重复,这些灰色的书养活了一个没有生命的文化。当发现人工智能已经被用来写一本学术书籍时,很难不去想那个画面。我们被告知,这种写作的自动化是获取大量知识的一种快速有效的新方法。

除了 33 页的序言,这本书是“由一种算法自动编译的”。该算法是由出版商 Springer Nature 和法兰克福歌德大学应用计算语言学实验室合作开发的。整本书是 Springer Nature 的第一本“机器生成的书”,可以在免费下载

这本书的封面不是作者,而是一个算法的名字:Beta Writer。有趣的是,他们给了这位机械作者一个名和姓,大概是为了让它在封面上看起来不会太不合适。

Beta Writer 的风格可以被描述为冗长而单调——内容中有四个庞大的章节是笨拙的描述。章节标题暗示了缺乏技巧。第四章标题为“模型、SOC、最大值、时间、单元、数据、参数”,是典型的平面子分析法。诚然,分析和微妙显然不是目标。这是一本专门针对机械化总结的书。

正如 Springer Nature 所说,“书籍原型概述了快速增长的锂离子电池领域的最新研究”,并补充说它“旨在帮助研究人员有效管理该学科的信息过载”。这本书和它的算法作者 Beta Writer 是作为一个大领域的范围的手段提出的,为研究人员提供了克服在特定主题上发现的令人困惑和压倒性数量的材料的手段。虽然我很好奇读者纯粹的无聊会让它的内容变得难以理解到什么程度。

这与其说是写作,不如说是将信息进行分组的练习。这不能被描述为策展,没有足够的选择或叙事正在进行。取而代之的是,它使用“聚类程序将源文档排列成连贯的章节”,然后从这些章节中“创建文章的简明摘要”。接下来的问题是,聚类是否是作者身份,或者一种新的写作和书籍类别是否正在这里产生。一个问题是,这种从一个领域捆绑信息的做法是否有所推进。书籍不仅仅需要找到模式,还需要给它们上色,塑造它们遇到的星座。

这一发展并不打算以这本书结束,它也是一个预期的未来方向的标志。Springer Nature 图书部总经理尼尔斯·彼得·托马斯(Niels Peter Thomas)表示,出版商利用这项技术“旨在塑造图书出版和阅读的未来”。托马斯声称,“围绕自然语言处理和人工智能的新技术为我们探索在算法的帮助下生成科学内容提供了充满希望的机会”。这里有一个未来的方向,暗示这是一个新的文学分支的开始。人类为这本书撰写的序言也让人们感觉这本书触发了某种不确定的东西:

与许多技术创新一样,我们也承认,机器生成的研究文本可能会成为一种全新的内容,其具体特征尚不完全可预见。如果说我们确切知道这段旅程将把我们带到未来的什么地方,那就太奢侈了。

有一种对未知未来的愿景,据推测,机器学习预计将带来未知但似乎肯定的好处。反思这一切对作者的角色意味着什么,《人类的序言》为这一潜在的未来增添了一点血肉:

我们预见,未来将有广泛的选择来创建内容——从完全由人类创建的内容到各种混合的人机文本生成,再到完全由机器生成的文本。我们不期望作者会被算法取代。相反,我们预计研究人员和作者的角色仍将很重要,但随着越来越多的研究内容由算法产生,这一角色将发生实质性变化。

这里的愿景是人类、机器和混合文本的变体。另一种看待这一点的方式是将作者身份放在自动化的范围内。看起来 Beta Writer 可能还有合作作者。支撑这一观点的是一个想法,事实上是一个庆祝,一个新的自动化机构将改变知识和写作。

从广义上讲,成为一名学者已经变得越来越算法化,这种发展是一系列正在发生的变化中的又一步。这需要一些批判性的思考。就像其他走向自动化的举措一样,这种算法作者身份也是一种不断增强的效率、便利性等等的举措。也许最令人惊讶的不是人工智能能写出这样的书,而是它比真正的人类学者更便宜。

随着人工智能的发展,可能值得反复回到为什么的问题上来。在这种特殊情况下,机器增加了什么?我们可以问这是一种增进知识和理解的方式,还是仅仅是一种机械的包装和分发系统。看起来这与其说是一次思考的练习,不如说是一次自动化信息编目和重新打包的尝试。

人们很容易得出这样的结论:这标志着作者的自动死亡,他们被更快、更全面的机器所取代,但我怀疑,通过展示作者需要做什么,他们会适得其反。这本书缺少的东西实际上突出了一个作者带来的东西。我毫不怀疑这些系统将会进步很快,将来可能会更接近地复制作者身份,但我怀疑这是否可取。就其现状而言,这种机械的内容缺乏洞察力,同时也很难阅读。要使任何领域都可以消化,即使是以总结的形式,也需要一些活力。

《数据凝视:资本主义、权力和感知》于 12 月出版,有平装本和电子书。

如果你对技术、媒体和文化感兴趣,可以在这里找到一份免费的每周时事通讯的详情。

从文本片段中识别恐怖小说作者的机器学习方法

原文:https://towardsdatascience.com/a-machine-learning-approach-to-author-identification-of-horror-novels-from-text-snippets-3f1ef5dba634?source=collection_archive---------3-----------------------

让我们开始吧…

有许多小说正在被创作,但其中一些在多年后获得了狂热的地位,并被人们铭记了很久。小说有几种体裁和跨体裁(几种体裁的混合)。恐怖小说是一种特殊的小说类型。有许多著名的恐怖小说,即使在发行几十年后,仍然是读者的绝对最爱。例如,RL Stine 的鸡皮疙瘩系列(1998–2016)已经家喻户晓,是现代最著名的恐怖小说之一。但是许多经典的恐怖小说出现在 21 世纪之前。比如 H.P .洛夫克拉夫特的恐怖小说【未知卡达思的寻梦(1943) 已经是 20 世纪必读的恐怖小说之一。从这里,如果我们再回到 19 世纪,怎么会有人忘记玛丽·雪莱的弗兰肯斯坦(1818 & 1823) 和埃德加·爱伦·坡的厄舍古屋的倒塌(1839) ?但是有一点很明显,

每位作家,无论是洛夫克拉夫特、玛丽·雪莱还是爱伦坡,都有自己的写作风格,其中包括使用特定词汇的标志性时尚,这使得他们的文学作品独一无二,易于辨认

所以,让我们利用这一事实,从他们的恐怖小说中摘录或引用的文字片段中确定作者(洛夫克拉夫特/玛丽·雪莱/坡)。自然语言处理(NLP)支持的机器学习是解决上述问题的一个很好的方案。所以,我们把问题陈述清楚,开始行动吧!!!

问题陈述:给出埃德加·爱伦·坡、玛丽·雪莱和惠普·洛夫克拉夫特的著名小说中的文字片段/引文,指出该文字片段或引文的作者是谁

为此,考虑由 Kaggle 准备的 幽灵作者识别数据集

所以,让我们使用 NLTK(自然语言工具包)和 Scikit-Learn 开始用 Python 开发机器学习模型吧!!!

I. 使用 Pandas 加载(读取)数据集:

import pandas as pddf = pd.read_csv('train.csv')
df.head(5) # **for showing a snapshot of the dataset**

Snapshot of the Dataset in which under label author, EAP -> (Edgar Allan Poe), HPL -> (HP Lovecraft) and MWS -> (Mary Wollstonecraft Shelley)

二。文本处理步骤:

  1. 删除标点符号→从数据集(语料库)的所有文本片段(实例或文档)中删除所有标点符号。
  2. 一个词的词形变化叫做引理。例如,(正在学习,已学习)是词根单词 study 的变形形式或引理。因此,一个单词的词条被分组在单个词根下。这样做是为了使语料库中的词汇只包含不同的单词。
  3. 停用词的去除→停用词通常是冠词(a,an,the),介词(in,on,under,…)以及其他不提供任何关键或必要信息的频繁出现的词。它们被从数据集(语料库)中存在的所有文本片段中移除。
# **Importing necessary libraries** import string
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizerlemmatiser = WordNetLemmatizer()# **Defining a module for Text Processing** def text_process(tex):
    # **1\. Removal of Punctuation Marks** 
    nopunct=[char for char in tex if char not in string.punctuation]
    nopunct=''.join(nopunct)
    # **2\. Lemmatisation** a=''
    i=0
    for i in range(len(nopunct.split())):
        b=lemmatiser.lemmatize(nopunct.split()[i], pos="v")
        a=a+b+' '
    # **3\. Removal of Stopwords** return [word for word in a.split() if word.lower() not 
            in stopwords.words('english')]

三。类别标签编码:

因为这是一个分类问题,这里的类是上面提到的三个作者。但是在数据集中,可以看到标签是非数字的(MWS、EAP 和 HPL)。这些是标签编码,使其成为数字,从 0 开始,按字母顺序描述每个标签,即(0 → EAP,1 → HPL 和 2 → MWS)

# **Importing necessary libraries** from sklearn.preprocessing import LabelEncodery = df['author']
labelencoder = LabelEncoder()
y = labelencoder.fit_transform(y)

四。字云可视化:

随着机器学习模型的开发,基于作者在文本中使用特定单词时有自己独特的风格这一事实,在单词云的帮助下,取分别属于 3 个作者的 3 个文本片段,完成 3 个作者最常用的单词到最少使用的单词的可视化。

# **Importing necessary libraries** from PIL import Image
from wordcloud import WordCloud
import matplotlib.pyplot as pltX = df['text']wordcloud1 = WordCloud().generate(X[0]) # **for EAP**
wordcloud2 = WordCloud().generate(X[1]) # **for HPL**
wordcloud3 = WordCloud().generate(X[3]) # **for MWS** print(X[0])
print(df['author'][0])
plt.imshow(wordcloud1, interpolation='bilinear')
plt.show()print(X[1])
print(df['author'][1])
plt.imshow(wordcloud2, interpolation='bilinear')
plt.show()print(X[3])
print(df['author'][3])
plt.imshow(wordcloud3, interpolation='bilinear')
plt.show()

Word Clouds for the 3 authors taking their text-snippet samples

动词 (verb 的缩写)特色工程用词袋:

机器学习算法只对数字数据有效。但是在这里,数据仅以文本的形式出现。为此,通过某种方式,需要将文本数据转换成数字形式。这样做的一种方法是特征工程。在这种方法中,从文本数据中提取或设计数字特征。存在许多特征工程技术。在这个问题中,使用了特征工程的词袋技术。

= >词汇袋:

这里,存在于语料库中的词汇被维护。这些单词充当每个实例或文档(这里是文本片段)的特征。针对作为特征的每个单词,考虑其在当前文档(文本片段)中的频率。因此,以这种方式,从文本数据或语料库中设计或提取单词特征。

# **Importing necessary libraries**
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split# **80-20 splitting the dataset (80%->Training and 20%->Validation)** X_train, X_test, y_train, y_test = train_test_split(X, y
                                  ,test_size=0.2, random_state=1234)# **defining the bag-of-words transformer on the text-processed corpus** # **i.e., text_process() declared in II is executed...** bow_transformer=CountVectorizer(analyzer=text_process).fit(X_train)# **transforming into Bag-of-Words and hence textual data to numeric..**
text_bow_train=bow_transformer.transform(X_train)#**ONLY TRAINING DATA**# **transforming into Bag-of-Words and hence textual data to numeric..** text_bow_test=bow_transformer.transform(X_test)#**TEST DATA**

不及物动词训练模型:

多项式朴素贝叶斯算法(分类器)已经被用作分类机器学习算法[1]。

# **Importing necessary libraries** from sklearn.naive_bayes import MultinomialNB# **instantiating the model with Multinomial Naive Bayes..** model = MultinomialNB()# **training the model...** model = model.fit(text_bow_train, y_train)

七。车型性能分析:

= >训练准确度

model.score(text_bow_train, y_train)

Training Accuracy

= >验证准确性

model.score(text_bow_test, y_test)

Test/Validation Accuracy

= >精确度、召回率和 F1–分数

# **Importing necessary libraries** from sklearn.metrics import classification_report

# **getting the predictions of the Validation Set...**
predictions = model.predict(text_bow_test)
# **getting the Precision, Recall, F1-Score** print(classification_report(y_test,predictions))

Classification Report

= >混淆矩阵

# **Importing necessary libraries** from sklearn.metrics import confusion_matrix
import numpy as np
import itertools
import matplotlib.pyplot as plt# **Defining a module for Confusion Matrix...** def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.
    """
    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
        print("Normalized confusion matrix")
    else:
        print('Confusion matrix, without normalization')print(cm)plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)fmt = '.2f' if normalize else 'd'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0])
                                  , range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt),
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')cm = confusion_matrix(y_test,predictions)
plt.figure()
plot_confusion_matrix(cm, classes=[0,1,2], normalize=True,
                      title='Confusion Matrix')

Normalized Confusion Matrix

根据性能分析,可以得出结论,NLP 驱动的机器学习模型已经成功地有效地正确分类了 84.14%的未知(验证集)样本。换句话说,84.14%的文本片段被正确地识别出属于三个作者中的哪一个。

基于我们的模特表演,能不能得出哪位作者的文笔最独特?

答案是肯定的!!!让我们看看归一化的混淆矩阵。这里标签 2 是最正确的分类。由于标签 2 指的是玛莉·渥斯顿克雷福特·雪莱,因此可以得出结论

玛莉·渥斯顿克雷福特·雪莱写恐怖小说的风格最独特的是埃德加·爱伦·坡和惠普·洛夫克拉夫特。

另外,换个角度,我们能说玛丽·雪莱、埃德加·爱伦·坡和惠普·洛夫克拉夫特谁是最多才多艺的作家吗?

同样,答案是肯定的!!!再次查看混淆矩阵,标签 0 是分类最不正确的。标签 0 指的是埃德加·爱伦·坡,所以可以得出结论

埃德加·爱伦·坡比惠普·洛夫克拉夫特和玛丽·雪莱都多才多艺。

这样,可以使用机器学习和自然语言处理来开发文本检测模型。

使用经过训练的伯努利朴素贝叶斯(而不是多项式朴素贝叶斯)的相关网络应用程序也已经使用 Flask API 在 Heroku 开发和部署。Web 应用程序的链接如下所示:

https://authoridentifier.herokuapp.com/

参考文献

[1]https://towards data science . com/multinomial-naive-Bayes-classifier-for-text-analysis-python-8dd 6825 ECE 67

自动化顾客满意度调查的机器学习方法

原文:https://towardsdatascience.com/a-machine-learning-approach-to-automated-customer-satisfaction-surveys-946d2604e309?source=collection_archive---------6-----------------------

泰勒·多尔,马修·巴辛,凯·尼科尔斯,西德尼·约翰逊

在浏览我的一些文档时,我偶然发现了一篇我在大学时参与的论文,我认为它非常适合分享。作为背景,这篇论文是为我的一个班级写的,在那里我们有一个由一家公司赞助的项目。就我而言,我与马修·布辛、凯·尼科尔斯和西德尼·约翰逊合作了一个由 ProKarma 赞助的项目,试图实现客户满意度调查的自动化。这篇论文最初发表在我们的课程网站这里。它已被改编以适应这种格式,原文被嵌入在文章的结尾。尽情享受吧!

介绍

自然语言处理(NLP)是一个关于捕获、分析和解释人类
语言的广泛学科。特别地,NLP 可以用于评估人类语音
,以便确定关于其说话者、上下文、
和情感的不同品质。这些评估可用于通知人机交互、可访问性、自动化和自然语言的统计分析。

这个 NLP 项目是由 ProKarma 的 Edge Intelligence group 提出的,pro karma 是一家 IT 解决方案公司,总部位于内布拉斯加州,提供数字化转型和分析咨询。ProKarma 的
Edge Intelligence group 正在研究如何通过结合机器学习来增加电信行业的客户
服务呼叫,从而改善客户
服务。提高客户服务满意度的一种方法
包括确定客户对特定产品的态度,并通过对客户电话数据进行情感和话题分析,有效地实现自动化客户服务调查。

自动化的客户满意度数据收集将提供
关于消费者对产品
和服务态度的可操作信息,其响应水平比单纯依赖
在线完成电话调查的客户要高得多。这个自动化系统可以与许多无线运营商目前采用的传统电话调查并行运行。对电话中提到的产品的自动化情感分析
可以根据客户完成电话后调查
的情况进行验证

由于自然语言中包含大量变量,传统的分析方法很难适应这一目的。机器学习算法允许简单的音频数据线性插值以及强大的模式
查找工具。出于这个原因,神经网络被开发用于
的主题和情感分类。这些模型发现产品类型和消费者态度之间的模式
,这提供了从客户电话音频中生成自动化客户满意度
调查所需的
信息。

方法

完成
自动化调查过程的最终目标需要三个模型:语音转文本转录、情感
建模和主题建模。

  • 语音转文本转录:为了自动转录呼叫数据,需要一种自动语音识别(ASR)策略。为了执行后面的主题和情感分析,准确和高性能的 ASR 实现是至关重要的,这些分析将简单语言的抄本作为输入。作为输入,抄本比纯音频更可取,原因有二:首先,主题建模不能直接在音频上执行,因为主题是必须从文本源中直接提取或解释的字符串;其次,音频文件可以用于检测有声情绪,但不能检测非情绪情绪(例如,单调的客户说“谢谢您的帮助”,或者活泼的客户高兴地说“我的电话打不开”)。
  • 情绪模型:由于情绪分析对于确定客户满意度非常重要,因此需要开发一个机器学习模型来根据转录的文本输入检测对客户服务代表的情绪(积极、消极或中立)。ProKarma 的 Edge Intelligence group 之前实施了一个双向长短期记忆递归神经网络(LSTM RNN),该网络使用开源数据集进行训练,如交互式情感二元运动捕捉(IEMOCAP)数据库,以便对从音频剪辑中提取的声学特征进行情感和情绪分类。在这个项目中,我们基于抄本的模型旨在捕捉整体情绪,而不是像以前基于声学的模型那样捕捉声音特征。
  • 主题模型:为了交叉分析客户情绪和谈话主题,产生了分类模型来识别抄本中的概念和特定主题。对话话题的趋势可以用来理解个人客户对产品和服务的态度,也可以用来理解一般客户群的态度。

这些模型最终形成了一个对客户通话录音进行端到端音频分析的引擎。所有项目代码都是使用
Python 3.6 编写的,通过
Keras 接口使用了 Google 的 TensorFlow 机器学习库,并使用了 Python/R Anaconda 发行版。
使用 git 执行版本控制,GitHub 用于
托管所有项目存储库。该项目是使用
敏捷工作流程开发的,团队协作和沟通是使用软件 Slack
促进的。

系统架构和设计

该项目的目的是证明将客户
服务呼叫作为输入,并将与客户满意度调查相关的数据作为输出是可能的。为完成这项任务而构建的系统,如图 1 所示,由三个主要模型组成:语音到文本模型、主题模型和情感模型。语音转文本模型在网络搜集的客户服务呼叫音频文件上进行训练。主题模型是在一个无线运营商的 FAQ 和论坛帖子的 web 废弃语料库上训练的。情感模型是在注释 IEMOCAP 转录本和电子评论的组合数据集上训练的。然后,客服电话音频通过语音转文本程序生成文字记录,然后输入主题和情感模型。后两种模型输出对整体主题和逐句情感标签的预测。然后将这两个输出进行汇总,以生成客户满意度指标的可视化,如通话过程中随时间推移的情绪以及与特定主题相关的情绪。

Figure 1: Diagram of general system architecture.

技术设计

将卷积神经网络(CNN)用于自然语言处理是最近的发展。CNN 最广为人知的是他们在图像分类中的成功,从过滤器的自然能力中识别图像的组成部分,如线条和形状。用于图像的 CNN 可以成功地
找到形状中的模式,而用于语言的 CNN 的过滤器同样能够
找到 n-gram 中的模式。

用于测试的网络如图 2 所示,并在图 3 中详细说明
,有两个卷积层。第一卷积
层有 64 个滤波器,滤波器大小为 4,第二卷积层有 32 个滤波器
,滤波器大小为 6。这些是测试
型号功能的起点。这些参数可以进一步调整
以提高模型的准确性。使用 CNN 进行情感
分析时,建议使用更多数量的过滤器
和 3–5 范围内的过滤器尺寸,以便根据紧密相邻的
单词之间的关系捕获大量上下文
信息。图中的脱落层旨在防止
过拟合。

Figure 2: Convolutional neural network architecture.

Figure 3: CNN layer type, output shape, and number of parameters.

潜在狄利克雷分配(LDA)主题模型广泛用于
识别一组文档中的潜在主题。给定 K 个要查找的主题
,LDA 模型将根据最常出现的单词和它们各自的主题
将文档中的单词分类成不同的
主题。这通过一个生成过程
工作,其中 LDA 模型假设如下:一个文档由一组主题
组成,每个主题由一组单词
组成。然后,它对这个过程进行逆向工程,以便
识别语料库中的主题。图 4 是图版
符号,其中:

  • m 是文档的数量
  • n 是文档中的字数
  • α是每个文档的主题分布
  • β是每个主题的单词分布
  • m 是文档 m 的主题分布
  • φ_k 是主题 k 的单词分布
  • Z_mn 是文档 m 中第 n 个单词的主题
  • W_mn 是特定的单词

Figure 4: Diagram of smoothed LDA model.

为了将客户服务记录数据分类到
主题中,使用了无线运营商的在线技术支持讨论板和常见问题解答部分
。通过使用该数据集,主题
可以被预先确定,并且模型可以被调整以识别
特定主题。图 5 提供了主题信息
的例子,这些信息可以用来识别主题。为了做到这一点,
β以如下方式定义:

  • 对于每个主题,所有的单词最初都被赋予 1 / 语料库
    词汇量
    分布
  • 然后,对于给定的主题,被预先确定为更频繁使用的单词
    被严重偏向(1000 倍的权重)

这使得模型偏向于在
文档中查找特定主题,而不是确定自己的主题。

Figure 5: Example of raw output from the LDA model.

设计决策

一些工具跨越了项目的所有部分。整个项目中使用的通用
数据科学工具包括:

  • Python: Python 是一种强大的通用编程语言
    ,有一套健壮的库。它是一个具有广泛支持网络的行业标准
  • TensorFlow: TensorFlow 是一个开源库,用于跨不同平台部署高性能数值计算。
  • Anaconda:Anaconda 发行版包含了大量的数据科学
    包,包括 conda,它是一个独立于操作系统的
    包和虚拟环境管理器,允许跨机器轻松安装
    包。
  • Jupyter Notebook:Jupyter Notebook 是包含文本和嵌入代码的文档,可以很容易地在文档中运行。它们易于共享,并为我们的 python 代码提供高质量的交互式输出。Jupyter notebooks 的解释器、降价和可视化
    环境的散文式格式
    促进了代码和概念的协作。
  • Pandas: Pandas 是一个强大的 python 库,在
    数据科学中无处不在。在这个项目中,它用于管理培训
    和测试数据。
  • Matplotlib: Matplotlib 是一个用于数据可视化的 python 库。在这个
    项目中,它用于情感分析
    和主题建模数据的最终可视化。
  • Pickle: Pickle 是一个用于对象序列化和数据
    存储的 python 库。在这个项目中,它对导出模型配置
    和相关数据框很有用。

由于这是一个影响深远的项目,涉及许多移动部件,因此需要各种
技术工具来具体完成每个主要公用事业公司的
目标:

语音转文本转录

  • ffmpeg:由于语音到文本引擎处理音频
    文件的方式,使用与引擎预期一致的音频编码
    是很重要的。FFmpeg 是一个免费的、轻量级的
    命令行音频编码器,可以无缝地融入
    我们的音频处理工作流程。最终的编码模式
    由 16 kHz 采样频率的单声道音频、
    16 位位深度和 300/3000 Hz 高/低通
    滤波组成,以专门捕捉语音音频。
  • Audacity:除了编码,我们的数据需要少量的编辑,主要是以短语划分的形式。Audacity 的
    “Silence Finder”实用程序允许我们将长音频
    片段分解成短语长度的声音片段,并轻松导出它们
    ,以便在 DeepSpeech 中立即进行转录处理。
  • DeepSpeech: DeepSpeech 是一个免费的语音转文本引擎,具有高精度上限和简单的转录和训练功能。DeepSpeech 还带有预训练的
    模型,可以通过转移学习进行优化
    以提高任何特定类型音频的准确性,从而避免
    需要延长训练时间或极其庞大的
    数据集。我们的迁移学习过程包括移除 DeepSpeech 的最终解释层
    ,用随机初始化的层
    替换它,冻结所有子层并训练最终层

主题模型

  • gensim: gensim 是一个用于 python
    的通用主题建模库,具有许多有用的特性。Gensim 主要用于其 LDA 模型
    ,因为它非常强大且易于训练
    并根据我们的需求进行调整。
  • NLTK: NLTK 代表自然语言工具包,是一个用于自然语言处理的
    python 库。这个库
    用于我们的主题模型,在通过我们的 LDA 模型运行文档
    之前对它们进行规范化。
  • pyLDAvis: pyLDAvis 是一个 python 包,用于可视化
    LDA 模型,并被用于这个项目,因为它
    与 gensim 接口良好。pyLDAvis 允许我们轻松地
    可视化我们的 LDA 模型的性能。
  • 斯坦福 NER:斯坦福命名实体识别器模型
    用于识别语料库中的命名实体,如人员、
    地点和组织。这有助于我们识别文档的主题。
  • 斯坦福词性标注器:斯坦福词性标注器用于识别语料库中每个单词的词性。这有助于我们识别电话记录句子的主语、动词和宾语。

情感模型

  • 单词嵌入:Tensorflow_hub 的单词嵌入模块
    被选为我们神经网络分类
    模型的输入,因为它们允许我们将句子映射到数字
    值,并保留词序信息。这些
    模块很容易通过 tensorflow_hub
    实现,并经过预训练。
  • 手动特征选择(MFS):手动特征选择
    用于 SVM 和随机森林分类器模型
    ,因为它允许更快的训练,因此可以处理
    更多的特征。这允许我们训练我们的
    模型来识别手边特定主题的词汇。
  • (MFS) NLTK 词干化:在手动特征选择中,单词
    被词干化,因此具有相同词根的单词将被
    识别为相同的单词,这减少了我们的特征
    空间。选择 NLTK 的词干模块是为了便于使用。
  • (MFS)过滤:超过 25 个字符的单词,短于 3 个字符的单词
    ,出现超过 2000 次的单词,
    和出现少于 5 次的单词都被过滤掉
    以减少特征空间。
  • 二元模型:二元模型被添加到特征空间以嵌入一些关于词序的信息。
  • 分类模型:探索了各种分类算法
    来比较我们的
    模型对训练数据的准确性。探索的模型有
    SVM 分类器、随机森林分类器、LSTM 递归
    神经网络和卷积神经网络。
  • Sklearn、Tensorflow 和 Keras: Tensorflow 和 Keras 用于神经网络训练。Sklearn 被用于
    其他分类算法。
  • NLTK 和 NLTK-trainer: NLTK 用于情感分析,
    因为它有几个预置的情感模型。这使得
    我们可以快速建立一个标准模型,并与我们自己的模型迭代进行比较。

绩效结果

语音转文本转录

DeepSpeech,我们客户首选的自动语音识别(ASR)引擎
,是一个端到端可训练的字符级
LSTM 递归神经网络。DeepSpeech 已经被用于产生非常低的单词错误率(WER),特别是 LibriSpeech 上 6%的 WER,这是一个开源的 1000 小时自然语音数据集。6%大约是人类的
错误率。开箱后,DeepSpeech 的通用模型在我们的客户服务电话测试数据上返回了 65.4%的 WER,超过人工处理 WER 的 10 倍。
在使用非常小的训练数据语料库
生成的定制模型上,该 WER 最终减少到大约 18.7%

DeepSpeech 在翻译句子长度、
< 10 秒的音频剪辑时效果最佳。Deep-
Speech 为每个音频片段创建一个抄本所需的处理时间在 4 到
9 秒之间,平均为 7.14 秒。因此,5 分钟的
音频可能需要 DeepSpeech 差不多 4 分钟的
处理时间。

情感模型

各种模型的准确性在 80/20 分割的
训练/测试数据上进行比较,这些数据由 IEMOCAP 数据集和
电子评论的网络搜集数据集组成,具有图 6 中包含的情感
分类准确性。这些
是三类分类器,其中情感类别是
积极、消极和中立。然后比较了不同特性实现的精度,结果如图 7 中的
所示。一些特性实现不容易
在不同的分类
模型上运行,因此缺少数据。

Figure 6: Accuracy results of different classifiers for sentiment.

Figure 7: Accuracy results of different feature implementations.

Figure 8: Confusion matrix for training data on the final LSTM model.

Figure 9: Confusion matrix for testing data on the final LSTM model.

在不同的数据集和实现中,最好的
结果是在使用 tf_hub
单词嵌入模块的神经网络分类器上。在单词嵌入模块中,
通用句子编码器的表现优于其他模块。
在相同的功能实现下,一个更深层次的神经网络优于 sklearn 的 DNNClassifier
,并且是所有实现中性能最高的
,测试集精度比第二个竞争者高出约 10%
。最好的
模型迭代是 LSTM RNN,它使用 tf_hub 的通用
句子编码器作为特征输入。该模型在 IEMOCAP 和
电子评论数据集上的
测试集准确率为 77.6%。从 3 个类别中随机选择一个类别的基线准确率为 33.3%。

主题模型

使用从无线运营商的在线讨论
论坛和常见问题部分收集的数据,训练数据被组织成 5 个主题
:账户和服务、安卓产品、
苹果产品、网络和覆盖范围以及其他产品。
这些主题中的每一个还包括一些带有偏见的
植入 LDA 模型的关键词(例如
苹果产品的“iphone”,安卓产品的“galaxy”等)。使用
这个训练数据来训练 LDA 模型,它能够成功地
以 57.6%的时间预测测试数据上的主题。从 5 个类别中随机选择一个类别的基线准确度为 20%。这个 LDA 的可视化可以在图 10 中找到。

使用自然语言工具包
(NLTK)中包含的语料库
来训练词性主题标识符(PoSSI)模型,然后在上述网络搜集的无线运营商
数据上进行测试。这个模型能够产生
连贯的主谓宾(SVO)结果,但是因为
网络抓取的数据集是未标记的,所以没有定量的
方法来分析准确性,除非所有网络抓取的数据
都被手工标记了词性。手工标记整个
网络抓取的数据集不在这个项目的范围内。

客户呼叫数据的可视化和分析

在通话过程中可视化情绪显示了我们可能预期的趋势
:绿色、积极的第一句话介绍
,随后是红色、消极的问题介绍
,以及接近通话结束的深绿色(即更强烈的积极情绪)

这些令人鼓舞的结果表明,情感分析
可以应用于自动化客户满意度调查的环境中。

Figure 10: A visualization of the topics and the vocabulary found in the training corpora.

Figure 11: Top left: sentiment for each clip of the call displayed over the call transcript; Top right from top down: a heat-map of the intensity of the sentiment of each sentence of the call, a line graph displaying the intensity of the sentiment during each sentence of the call; Middle: the distribution of sentiment among keywords for each category; Bottom: the distribution of probabilities the call belongs into one of the five topic categories.

Figure 12: Sentiment distribution for sample service keywords.

结论

语音转文本转录

DeepSpeech 是高度可训练的,但是有 1.2 亿个参数,
需要大规模的训练语料库,数百小时的训练和昂贵的设备。迁移学习以冻结模型
的所有子层并重新训练最后一层的形式进行
。改变
先前图层的实验无法产生改进。转移
学习是一个可行的行动过程,可以为未来的转录需求定制深度-
语音,但应该使用更多高质量的音频剪辑进行
训练。
在我们的测试
数据上,DeepSpeech 的表现明显优于 Kaldi 和 CMUSphinx
等替代 ASR 引擎,以及隐马尔可夫模型
等传统 ASR 方法。

未来工作在为转录准备
低质量通话数据方面,以及在转录后处理
以产生更正确的语音
(由于 DeepSpeech 是字符级的,所以有时会产生
废话)方面,可能会有进一步的改进。在大型行业专用 copora 上重新训练 DeepSpeech 的权重也可能会产生更高的精确度,但在计算时间和所需的数据量方面会明显更加昂贵。

情感模型

对所测试的情感分析模型的准确性
影响最大的两个因素是数据准备
和模型选择。数据准备和输入格式化
对较小的数据集有较大的影响。模型选择
对较大的数据集有较大的影响。在我们尝试的各种模型迭代中,使用了三种不同类型的数据输入格式:

  • 手动特征选择(在 SVM 和随机森林-
    分类器中使用):手动特征选择通过使用技术
    词干化、过滤和标记化来完成。使用 NLTK 的词干模块对单词
    进行词干处理,因此不同时态的所有
    单词将对应于同一个
    标记。当单词长度小于 3、大于 25 时,不包括在训练/测试
    集中,当单词在完整语料库中出现超过 2000 次或少于 5 次
    时,不包括在
    集中。然后为语料库中所有的
    可行的单字和双字创建标记。
  • 预训练单词嵌入模块(用于 DNNClassifier)
    -来自 tensorflow_hub
    的预训练单词嵌入模块用于 DNN 分类器。
    -NNLM 嵌入基于一个具有两个隐藏层的神经网络
    语言模型。最不常用的
    令牌被散列到桶中。
    • Word2vec 是一个基于令牌的嵌入模块,在英文维基百科文章语料库上进行训练

      -通用句子编码器对句子进行编码,用于文本分类
      。它使用深度平均
      网络进行训练,并具有编码语义
      相似性的特征。
  • 标记化:长度小于 1 的单词被删除,然后使用 Keras 的文本预处理模块

    句子进行矢量化。为
    训练输入中的每个单词选择一个标记。所有的句子都被填充成相等的长度,单词被替换成了记号。

考虑到我们的数据集相对较小的词汇量,
使用预先训练的单词嵌入模块给出了最好的
结果,超过了使用什么模型的影响。还开发了替代
型号,例如:

  • SVM 和兰登森林:这两个模型是第一个被用来衡量可以达到何种精度的
    模型,以及预计
    可以击败的更复杂的模型。sklearn SVM 分类器和 Random-
    森林分类器被用于这项任务。这是两种常用的高性能分类器。
  • DNN:这个模型是来自
    Tensorflow 的预建深度神经网络。该模型用于评估神经网络在数据集上的性能
    ,并测试 tf_hub 的单词嵌入模块的使用
  • LSTMs 目前是像自然语言这样的顺序数据的行业标准模型。
  • CNN:卷积神经网络已经被证明
    通过
    使用
    卷积层捕获关于 n-grams 的信息,从而在句子分类方面提供了出色的结果。
  • 美国有线电视新闻网-LSTM:一个组合的美国有线电视新闻网-LSTM 模型已经被证明
    通过用
    卷积层编码区域信息和用
    LSTM 层编码跨越
    句子的长距离依赖而工作良好。

对于中小规模的训练数据集,当使用具有数千个参数的神经网络(如 RNN 和 CNN 神经网络)时,过度适应训练集的风险要高得多。这可以从我们的性能结果中测试和训练集准确性之间的巨大差异中看出。停止训练的理想点是当训练和测试分数开始偏离时,训练分数继续上升,但测试分数开始下降。在训练模型的上下文中,这意味着在训练时保存检查点是很重要的,这样模型就可以恢复到尚未过度拟合的旧检查点。参见附录 B,了解培训和各时期测试分数的示例。过拟合也可以通过向损失函数添加正则化参数或引入漏失层来减少。在大多数类型的神经网络中,向层中添加辍学已经取得了成功。然而,这种方法在使用 LSTM 单位的 RNNs 上效果不佳,而这种类型的模型在这个项目中表现最佳。为了减轻对我们的小训练数据集的过度拟合,我们仅对非递归层应用 dropout。

未来工作

  • 手动特征选择:当进行手动特征
    选择时,NLTK 词干模块用于寻找
    词根。词汇化可能会给出更好的结果,
    但是需要词性标注。实现
    这将创建一个更精确的特征空间。这可以通过结合使用 NLTK 的 WordNetLemmatizer 和 NLTK 的 pos_tag 来完成。
  • 训练数据:使用更大的训练数据集。IEMOCAP
    数据集的词汇量为 3000 个单词,相对来说
    比较小,测试数据很容易包含
    看不见的单词。这一点通过加入
    电子评论数据集得到了改善,该数据集将词汇量
    增加到了大约 8000 个单词。此外,数据并不像可能的那样 T13 是领域特定的。IEMOCAP 非常通用
    目的,由演员阅读关于
    日常情景的剧本来表演。电子评论针对的是与技术
    无线运营商客户电话故障排除中讨论的产品类似的电子
    产品,但不是最近的
    。可以引入更多特定于无线
    运营商客户服务呼叫中讨论的内容的数据,
    例如更近期的电子设备评论或手动
    带注释的无线运营商论坛帖子。
  • 预训练单词嵌入模块:迁移学习
    可以在这些模块上使用与正在尝试分类
    的文本数据类型相关的文本语料库
    来实现。在这种情况下,单词嵌入
    模块可以在
    无线运营商相关文本的语料库上进一步训练,例如从
    特定无线运营商的在线 FAQ 部分和讨论
    论坛帖子中搜集的数据。
  • CNN 和 LSTM 神经网络:对层
    及其参数的微调,以及向模型提供更多的
    数据可以在神经网络模型上得到改进。
    这些努力的目的是提高精度
    和减少过拟合。

主题模型

LDA 模型的低准确度结果是预料之中的,因为
LDA 模型并不意味着被强制加入预定义的主题
,而是应该用于在语料库中寻找隐藏的主题信息
。使用词性和 NER
标记的 SVO 提取能够产生一致的结果,但是这些结果
在主题之间并不一致,这在尝试按主题对文档进行排序时提出了挑战

未来工作

  • LDA 模型可以通过使用更特定领域的
    词性标注器(而不是 NLTK 的默认词性
    标注功能)以及更精确的 alpha
    (文档-主题密度)和 beta(主题-词密度)参数来改进。
  • PoSSI 模型可以在几个方面进行改进:
    -使用一个 POS 标记器和一个命名实体识别
    (NER)标记器在特定领域的语料库上进行训练
    -一个更特定领域的 POS 标记器模型(目前
    使用斯坦福的研究模型)
    -一个更特定领域的 NER 标记器模型(目前
    使用斯坦福的研究模型)
    -一种更好的从标记的
    文档中提取主题的方法,例如结合特定领域语料库
    的上下文无关
    语法的解析器-速度改进,因为该模型对于
    大型文档可能非常慢。
    -这两种模型可以结合起来识别生成的 svo 中的主题

文献学

A.G. Tripathi 和 N. S .,“用于情感分析的特征选择和分类方法
”,“机器学习和应用:
国际期刊,第 2 卷,第 2 期,第 01–16 页,2015 年。

B.C. Busso、M. Bulut、C. Lee、A. Kazemzadeh、E. Mower、S. Kim、
J. Chang、S. Lee 和 S. Narayanan,“IEMOCAP:交互式情感
二元运动捕捉数据库”,《语言资源与评估杂志》
,第 42 卷第 4 期,第 335–359 页,2008 年 12 月。

C.Y. Bengio、R. Ducharme、P. Vincent 和 C. Jauvin,“一种神经
概率语言模型”,《机器学习研究杂志
,第 3 卷,第 1137-1155 页,2013 年 3 月。

D.T. Mikolo、K. Chen、G. Corrado 和 J. Dean,“向量空间中单词表示的有效估计
”, CoRR,第 abs/1301.3781 卷,
2013 年 1 月。

E.D. Cer,Y. Yang,S.-yi Kong,N. Hua,N. Limtiaco,R. St. John,
N. Constant,M. Guajardo-Cespedes,S. Yuan,C. Tar,Y.-H. Sung,B.
Strope,R. Kurzweil,《通用句子编码器》,CoRR,vol .
ABS/1803.1175,2018 .

F.W. Zaremba、I. Sutskever 和 O. Vinyals,“递归神经网络
正则化”,CoRR,第 abs/1409.2329 卷,2014 年。

G.胡和刘。"挖掘和总结客户评论."ACM SIGKDD 国际知识会议论文集
发现数据挖掘,2004 年 8 月。

H.金达尔和刘。“意见垃圾和分析。”第一届 ACM 网络搜索和数据挖掘国际会议论文集
,2008 年 2 月。

一、刘倩、高志强、刘冰、张元林。观点挖掘中面向抽取的自动
规则选择。国际人工智能联合会议论文集
,2015 年 7 月

J.Y. Kim,“用于句子分类的卷积神经网络”,
CoRR,第 abs/1408.5882 卷,2014 年。

K.张量流。(2018).文本模块|张量流。【在线】。

长度 X. Ma 和 E. Hovy,“通过双向
进行端到端序列标记的 LSTM-CNN-CRF”,
计算语言学协会第 54 届年会论文集,2016 年第 1 卷。

米(meter 的缩写))J. Cheng,L. Dong,M. Lapata,“机器阅读的长短期记忆-
网络”,2016 年自然语言处理经验方法会议论文集
,2016 年。

名词(noun 的缩写)Y. Goldberg,“自然语言处理的神经网络模型入门”,人工智能研究杂志,
第 57 卷,2016 年 11 月。

O.王、余立春、赖、张,“使用区域 CNN-LSTM 模型的维度情感分析”,计算语言学协会第 54 届年会论文集(第 2 卷:短文),2016 年。

页(page 的缩写)A. Y. Hannun,C. Case,J. Casper,B. Catanzaro,G. Diamos,E.
Elsen,R. Prenger,S. Satheesh,S. Sengupta,A. Coates 和 A. Y. Ng,
“深度语音:扩大端到端语音识别”,CoRR,
第 abs/1412.5567 卷,2004 年。

Q. J .昆泽、l .基尔希、I .库伦科夫、a .克鲁格、j .约翰斯迈尔和
S .斯托伯,“预算内语音识别的迁移学习”,

NLP 第二届表征学习研讨会论文集,2017。

R.S. Bansal 与自然语言处理和机器学习,
《Python 中主题建模的初学者指南》,Analytics Vidhya,
29-Aug-2016。【在线】。

南 J. Brownlee,“如何开发用于情感分析的 N 元多通道卷积
神经网络”,机器学习
掌握,2018 年 2 月 14 日。

T.S. Axelbrooke,“LDA Alpha 和 Beta 参数—直觉”,
LDA Alpha 和 Beta 参数—直觉|思维向量
博客,2015 年 10 月 21 日。【在线】。

单位 A. Crosson,“使用自然语言处理提取文档主题”,
Medium,2016 年 6 月 8 日。【在线】。

动词 (verb 的缩写)J. R. Finkel、T. Grenager 和 C. Manning,“通过 Gibbs
抽样将非局部
信息纳入信息提取系统”,计算语言学协会第 43 届年会会议记录——ACL 05,第 363–370 页,2005 年。

W.K. Toutanova 和 C. D. Manning,“丰富最大熵词性标记器中使用的知识来源”,2000 年在
举行的关于自然语言处理和超大规模语料库的经验方法
的 2000 年联合 SIGDAT 会议的会议记录

计算语言学协会第 38 届年会,第 63–70 页,2000 年。

X.S. Bird、E. Klein 和 e . Loper,
Python 的自然语言处理:用自然语言工具包分析文本。北京:
奥雷利,2009 年。

Y.平滑的 LDA。维基百科,2009 年。

Z.S. Ruder,“NLP 最佳实践的深度学习”,Sebastian Ruder,
2017 年 7 月 25 日。【在线】。

Original PDF of our Final Report

word2vec 模型的数学介绍

原文:https://towardsdatascience.com/a-mathematical-introduction-to-word2vec-model-4cf0e8ba2b9?source=collection_archive---------9-----------------------

Image by Gerhard Gellinger from Pixabay

作为 NLP 项目的一部分,我最近不得不处理 Mikolov 等人在 2013 年开发的著名的 word2vec 算法。在网上有很多关于这个主题的教程和指南,有些更侧重于理论,有些则有实现的例子。
然而,我感兴趣的不仅仅是学习这种方法背后的理论,还有理解算法的实现细节,这样我就可以自己编写并正确地重现算法了(此处)。从这个意义上说,我找不到真正对我有帮助的东西,所以我准备了两篇有条理的文章:在这篇文章中,我讨论模型的理论,而在这里我展示如何通过神经网络具体训练模型。

注:我发现在 Medium 上使用 latex 是相当不满意和讨厌的,所以我选择了使用手绘配方(和方案)。我提前为我的书法道歉。

Word2vec 已经成为一种非常流行的单词嵌入的方法。单词嵌入意味着单词用实值向量表示,因此可以像处理任何其他数学向量一样处理它们。一种从文本、基于字符串的域到向量空间的变换,只需要少量的规范运算(主要是和与减)。

A change of domain

为什么要嵌入单词?

通过单词嵌入,我们可以用数学方法处理文本中的单词。如果两个单词有相似的意思,它们的向量是接近的:单词嵌入是一种相似性的度量,这使得不仅单词,而且句子和整个文本都有可能相关联。这在各种 NLP 任务和系统中非常有用,例如信息检索、情感分析或推荐系统。

报纸

2013 年,Mikolov 等人提出了两篇开创性的论文[1] [2]和两种不同的单词嵌入模型,即连续单词袋 (CBOW)和跳格模型。它们在本质上没有太大区别,在下面的讨论中,我将集中讨论后者。

两个模型的假设都是分布假设:出现在相同上下文中的单词往往有相似的意思(Harris,1954)。也就是说,一个词的特点是它的同伴。

假设我们的文本由一系列单词组成:

Text as a word sequence of words

那么对于单词 wⱼ, wⱼ上下文由其左右邻域给出:

其中 M 是上下文窗口的一半大小。

然后,给每个单词 w 分配一个向量表示 v,和概率,即 wₒwᵢ 的上下文中被定义为它们的向量乘积的 softmax :

Output probability is given by softmax of vector product

跳格模型的目标是预测中心词的上下文。因此,训练模型意味着找到使目标函数最大化的一组 v :

Objective function

等效地,这意味着最小化损失函数,该函数看起来是在语料库上平均的交叉熵(因为真实分布仅在中心词的上下文中等于 1):

到目前为止,这就是我们需要知道的关于 vanilla wordvec 的所有信息。

然而,这种需要考虑每个单词的上下文的所有概率的方法,对于通常包括数十亿个单词的相当大的语料库来说是不可分析处理的。因此 Mikolov 的小组提出了一些提高计算效率的有效措施。令人惊讶的是,它们还改善了嵌入结果。让我们看看他们。

单词子采样

这很简单。我们不是以简单的方式考虑文本中的所有单词,而是给每个单词分配一个概率,这个概率与它出现的频率成反比。保持概率由下式给出:

因此,在生成训练数据的过程中,常用词将更有可能被丢弃,从而减少要处理的数据量。由于这种词通常带来有限的信息量(想想像“the”、“of”、“to”这样的词),从语料库中删除一些词还可以提高文本的质量,并允许专注于更有意义的术语。

这里显示的保持概率公式包含在 Google 代码实现中,它与原始文章中报告的略有不同。感谢克里斯·麦考密克指出了这一点。

负采样

相反,这种技术似乎有点晦涩难懂,但它已被证明非常有效。

负抽样只考虑少量样本来评估跳格概率。样本被称为阴性,因为它们是不属于 wᵢ 的上下文的单词(因此,模型应该理想地将概率分配为零)。

负采样源于噪声对比估计 (NCE)技术;其基本思想是将多项分类问题转化为二元分类问题;

  • 多项式分类问题 该模型使用 softmax 函数估计输出单词的真实概率分布。
  • 二元分类 问题 对于每个训练样本,模型被输入一个对(一个中心单词和出现在其上下文中的另一个单词)和少量的对(中心单词和从词汇表中随机选择的单词)。该模型学习区分真实对和负面对。

对于负采样,目标函数变为:

Objective function with negative sampling

其中σ是逻辑( sigmoid )函数:

Sigmoid function

softmax 不同, sigmoid 是一个单参数函数,因此不需要同时评估所有输出值。

为什么负抽样效果这么好?

这个问题仍在讨论中。分布假设看起来是正确的,负采样通过增加中心词和上下文词之间的相似性来利用它。戈德堡和 Levy⁴认为,二次抽样也可能产生有益的影响。事实上,通过从语料库中消除频繁出现的单词,我们有选择地扩展了上下文的大小,因此我们可以掌握与信息性单词的关系,否则这些信息性单词将留在窗口之外。

参考

[1] Mikolov 等,2013,向量空间中单词表示的高效估计。

[2] Mikolov 等,2013,词和短语的分布式表征及其组合性

[3]https://mccormickml . com/2017/01/11/word 2 vec-tutorial-part-2-negative-sampling/

[4] Goldberg,Levy,2014, word2vec 解释:推导 Mikolov 等人的负采样单词嵌入法

线性关系的度量

原文:https://towardsdatascience.com/a-measure-of-linear-relationship-5dd4a995ee7e?source=collection_archive---------24-----------------------

统计数字

皮尔逊与 Jupyter 笔记本的积矩相关性

Photo by olena ivanova on Unsplash

**Table of Contents**[**Introduction**](#ae6d)1\. [Import necessary libraries](#bde6)
2\. [Finding the regression line](#e399)
3\. [Pearson’s correlation coefficient](#14c9)
4\. [Finding Pearson’s correlation coefficient](#0513)
5\. [Degree of freedom and critical values](#8a6e)
6\. [The least-squares regression line](#d12c)
7\. [The mean point on the line of best fit](#b71a)
8\. [Real-life example](#a7b5)
9\. [Finding r from more than two arrays](#1b9e)
10\. [Heat map](#591d)[**Conclusion**](#1dbc)

介绍

在本文中,我使用 Python 来分析二元数据,使用皮尔逊的积差相关系数 r,绘制散点图、最佳拟合线和最小二乘回归线。二元数据涉及两种类型的相关数据。皮尔逊的积差相关系数告诉你这两个数据的线性相关程度。我们可以在散点图上显示收集的数据。横轴称为 x 轴,我们称 x 轴的坐标为独立变量。纵轴称为 y 轴,我们称 y 轴的坐标为因变量。

我从这个链接下载了数据。

导入必要的库

让我们创建一个样本数据。

我们需要转置数据,以便按列对数据进行分类。熊猫转置不修改原始数据。

我们使用 Seaborn 创建一个散点图。

寻找回归线

linregress返回斜率、截距、r 值和 p 值。

The equation of reegression line is y=1.221x+1.151.
Pearson's product-moment correlation coefficient is {r_value:.4f}.
p-value is {p_value:.4f}.

皮尔逊相关系数

对于人口数据

两组总体数据 x 和 y 的皮尔逊积差相关系数为:

其中 cov 是协方差, 𝜎𝑥𝜎𝑦 是 x 和 y 的总体标准差

其中 𝜇𝑥 是 x 的平均值,而 𝜇𝑦 是 y 的平均值

对于示例数据

两组样本数据 x 和 y 的皮尔逊积差相关系数为:

其中 𝑠𝑥𝑦 是协方差, 𝑠𝑥𝑠𝑦 是 x 和 y 的样本标准差

因此:

[## 使用有序数据的 Spearman 等级相关系数

发现单调关系的力量

towardsdatascience.com](/discover-the-strength-of-monotonic-relation-850d11f72046)

求皮尔逊相关系数

让我们使用样本数据。

数学上使用 Numpy

0.93050085576319

在熊猫中,ddf=0代表种群,ddf=1代表样本。因为我们使用所有数据,所以这里使用 0。

使用scipy.stats.pearsonr

0.9305008557631897

pearsonr返回皮尔逊的积差相关系数和 p 值。

自由度和临界值

您可以在此处找到皮尔森相关性临界值表。自由度(dof)是数据点数减 2。在上面的例子中,自由度= 5–2 = 3。对于具有统计显著性的 95%置信度,我们使用临界值表中的 0.05 显著性水平。这给出了 0.878。如果|r| >临界值,那么相关性可能不是由于变化而产生的,这意味着它在统计上是显著的。在上面的例子中,|0.9928| > 0.878,所以有 95%的把握认为两个变量之间存在统计上显著的正相关关系。

最小二乘回归线

最小二乘回归线称为最佳拟合线。由于linregress()返回斜率和 y 轴截距,我们用它们来做一条回归线。

最佳拟合线上的平均点

我们找到每个数据集的平均值,并将其绘制在同一个图表上。

[## 卡方独立性检验简介

使用 Jupyter 笔记本的卡方初学者指南

towardsdatascience.com](/gentle-introduction-to-chi-square-test-for-independence-7182a7414a95)

现实生活中的例子

我们将探讨澳大利亚人口和劳动力之间的线性关系。我们使用经合组织的历史人口。让我们用read_csv找到尺寸(形状)并用shapehead()显示前五个数据。

从历史人口数据来看,我们选取澳大利亚。我们还需要在性别列中选择 TOTAL,在年龄列中选择 Total。

我们需要选择值列。我将向你展示两种不同的方法。本网站告诉你如何使用lociloc.由于 Python 索引从 0 开始,所以位于第 8 列。

在第二种方法中,我们使用&逻辑运算符。你可以在这篇文章中读到更多关于lociloc的细节。我们选择国家为澳大利亚、器械包为总计、年龄为总计的列。

我们还需要一份经合组织的数据。数据是 ALFS 的劳动力。我们选择国家为澳大利亚的数据。head()显示前 5 个数据。

我们需要第 15 个索引的值列,所以我们在iloc中使用 14。记住 Python 索引是从 0 开始的。

我们可以从df_popdf_lab中找到皮尔逊相关系数。pearsonr返回rp-value

我们使用linregress找到梯度/斜率和 y 截距。我们用海牛和熊猫数据框创建了一个散点图。

澳大利亚的人口和劳动力之间有很强的正相关关系。

从两个以上的数组中寻找 r

有时候你想找出哪一对数据的线性关系最强。可以用corr()来找。

请注意 A 和 B 的皮尔逊相关系数是 0.952816,和我们之前发现的一样。在这种情况下,A 和 C 的线性关系最强。

热图

我们可以使用 Seaborn 来绘制热图。由于在上一节中我们有最小值 0.88 和最大值 1.00,因此我们相应地设置了vmaxvmin。我们使用Blues作为配色方案。

结论

通过使用 Python 及其库,您可以用几行代码找到所有必要的数据。此外,您可以轻松地可视化您的数据。

通过 成为 的会员,可以完全访问媒体上的每一个故事。

https://blog.codewithshin.com/subscribe

参考

一个极简的端到端的零碎教程(第一部分)

原文:https://towardsdatascience.com/a-minimalist-end-to-end-scrapy-tutorial-part-i-11e350bcdec0?source=collection_archive---------2-----------------------

面向初学者的系统化网页抓取

Photo by Paweł Czerwiński on Unsplash

第一部分第二部分第三部分第四部分第五部分

网络抓取是数据科学家的一项重要技能。在过去的几年里,我使用 Python、BeautifulSoup 和 Scrapy 开发了许多专门的 web 抓取项目,并阅读了一些书籍和大量在线教程。然而,我还没有找到一个简单的初学者水平的教程,它是端到端的,涵盖了一个典型的零碎的 web 抓取项目中的所有基本步骤和概念(因此标题中的极简主义者)——这就是为什么我写这篇文章,并希望代码回购可以作为一个模板,帮助启动您的 web 抓取项目。

很多人问:我应该用 BeautifulSoup 还是 Scrapy?它们是不同的东西:BeautifulSoup 是一个用于解析 HTML 和 XML 的库,Scrapy 是一个 web 抓取框架。如果你愿意,你可以使用 BeautifulSoup 而不是 Scrapy 内置选择器,但是将 BeautifulSoup 与 Scrapy 进行比较就像将 Mac 键盘与 iMac 进行比较,或者更好的比喻,如官方文档中所述“就像将 jinja2 与 Django 进行比较”,如果你知道它们是什么的话:)—简而言之,如果你想进行严肃而系统的 web 抓取,你应该学习 Scrapy。

TL;博士,给我看看代码:

[## 哈利旺/剪贴簿-教程

这个报告包含了我的教程的代码:一个极简的端到端的零碎教程(…

github.com](https://github.com/harrywang/scrapy-tutorial)

在本系列教程中,我将讲述以下步骤:

  1. (本教程)从头开始一个 Scrapy 项目,开发一个简单的蜘蛛。一件重要的事情是使用 Scrapy Shell 来分析页面和调试,这是你应该使用 Scrapy 而不是 BeautifulSoup 的主要原因之一。
  2. (第二部分)介绍 Item 和 ItemLoader,并解释为什么要使用它们(尽管它们让你的代码一开始看起来更复杂)。
  3. (第三部分)通过管道使用 ORM (SQLAlchemy)将数据存储到数据库,并展示如何建立最常见的一对多和多对多关系。
  4. (第四部分)将项目部署到 Scrapinghub(你必须为预定的抓取作业等服务付费)或者通过使用伟大的开源项目 ScrapydWeb 和 Heroku 完全免费地建立自己的服务器。
  5. ( Part V )我创建了一个单独的 repo ( Scrapy + Selenium )来展示如何抓取动态网页(比如通过滚动加载附加内容的页面)以及如何使用代理网络(ProxyMesh)来避免被禁止。

一些先决条件:

我们开始吧!

首先创建一个新文件夹,在文件夹里面设置 Python 3 虚拟环境,安装 Scrapy。为了使这一步变得容易,我创建了一个 starter repo ,你可以派生和克隆它(如果需要,请参见 Python3 虚拟环境文档):

$ git clone [https://github.com/yourusername/scrapy-tutorial-starter.git](https://github.com/yourusername/scrapy-tutorial-starter.git)
$ cd scrapy-tutorial-starter
$ python3.6 -m venv venv
$ source venv/bin/activate
$ pip install -r requirements.txt

您的文件夹应该如下所示,我假设我们总是在虚拟环境中工作。注意到目前为止我们在 requirements.txt 中只有一个包。

运行scrapy startproject tutorial创建一个空的 scrapy 项目,你的文件夹看起来像:

创建了两个相同的“教程”文件夹。我们不需要第一级“教程”文件夹—删除它,并将第二级“教程”文件夹及其内容向上移动一级—我知道这很混乱,但这就是你对文件夹结构所做的一切。现在,您的文件夹应该看起来像这样:

到目前为止,不要担心自动生成的文件,我们稍后将回到这些文件。本教程基于官方 Scrapy 教程。所以我们要爬的网站是http://quotes.toscrape.com,很简单:有几页引用作者和标签:

当您单击作者时,它会转到作者详细信息页面,包括姓名、生日和简历。

现在,在“spider”文件夹中创建一个名为“quotes-spider.py”的新文件,其内容如下:

您刚刚创建了一个名为“quotes”的蜘蛛,它向http://quotes.toscrape.com发送请求,并从服务器获得响应。然而,到目前为止,蜘蛛在解析响应时不做任何事情,只是向控制台输出一个字符串。让我们运行这个蜘蛛:scrapy crawl quotes,您应该会看到如下输出:

接下来,让我们使用 Scrapy Shell 通过运行以下命令来分析响应,即位于http://quotes.toscrape.com的 HTML 页面:

$ scrapy shell http://quotes.toscrape.com/...2019-08-21 20:10:40 [scrapy.core.engine] INFO: Spider opened2019-08-21 20:10:41 [scrapy.core.engine] DEBUG: Crawled (404) <GET http://quotes.toscrape.com/robots.txt> (referer: None)2019-08-21 20:10:41 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/> (referer: None)[s] Available Scrapy objects:[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)[s]   crawler    <scrapy.crawler.Crawler object at 0x105d01dd8>[s]   item       {}[s]   request    <GET http://quotes.toscrape.com/>[s]   response   <200 http://quotes.toscrape.com/>[s]   settings   <scrapy.settings.Settings object at 0x106ae34e0>[s]   spider     <DefaultSpider 'default' at 0x106f13780>[s] Useful shortcuts:[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)[s]   fetch(req)                  Fetch a scrapy.Request and update local objects[s]   shelp()           Shell help (print this help)[s]   view(response)    View response in a browser>>>

您可以使用 Xpath 选择器CSS 选择器Chrome DevTools 来选择元素,它们通常用于分析页面(我们不会涉及选择器细节,请阅读文档以了解如何使用它们):

例如,您可以测试选择器并在 Scrapy Shell 中查看结果——假设我们想要获得上面显示的报价块:

可以使用 Xpath response.xpath(“//div[@class=’quote’]”).get() ( .get()显示第一个选中的元素,使用.getall()显示全部)或者 CSS response.css(“div .quote”).get()。我用粗体显示了我们希望从这个报价块中获得的报价文本、作者和标签:

>>> response.xpath("//div[@class='quote']").get()'<div class="quote" itemscope itemtype="http://schema.org/CreativeWork">\n        <span class="text" itemprop="text">**“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”**</span>\n        <span>by <small class="author" itemprop="author">**Albert Einstein**</small>\n        <a href="/author/Albert-Einstein">(about)</a>\n        </span>\n        <div class="tags">\n            Tags:\n            <meta class="keywords" itemprop="keywords" content="change,deep-thoughts,thinking,world"> \n            \n            <a class="tag" href="/tag/change/page/1/">**change**</a>\n            \n            <a class="tag" href="/tag/deep-thoughts/page/1/">**deep-thoughts**</a>\n            \n            <a class="tag" href="/tag/thinking/page/1/">**thinking**</a>\n            \n            <a class="tag" href="/tag/world/page/1/">**world**</a>\n            \n        </div>\n    </div>'

我们可以继续在 shell 中获取如下数据:

  • 将所有报价块转换成“报价”
  • 使用“quotes”中的第一个引号:quotes[0]
  • 尝试 css 选择器
>>> quotes = response.xpath("//div[@class='quote']")
>>> quotes[0].css(".text::text").getall()['“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”']>>> quotes[0].css(".author::text").getall()['Albert Einstein']>>> quotes[0].css(".tag::text").getall()['change', 'deep-thoughts', 'thinking', 'world']

看起来上面显示的选择器得到了我们需要的东西。注意,出于演示目的,我在这里混合了 Xpath 和 CSS 选择器——在本教程中不需要两者都用。

现在,让我们修改蜘蛛文件并使用关键字yield将选择的数据输出到控制台(注意,每个页面都有许多引用,我们使用一个循环来遍历所有引用):

import scrapyclass QuotesSpider(scrapy.Spider):
    name = "quotes"start_urls = ['[http://quotes.toscrape.com'](http://quotes.toscrape.com')]def parse(self, response):
        self.logger.info('hello this is my first spider')
        quotes = response.css('div.quote')
        for quote in quotes:
            yield {
                'text': quote.css('.text::text').get(),
                'author': quote.css('.author::text').get(),
                'tags': quote.css('.tag::text').getall(),
            }

再次运行蜘蛛:scrapy crawl quotes可以在日志中看到提取的数据:

您可以通过运行scrapy crawl quotes -o quotes.json将数据保存在一个 JSON 文件中

到目前为止,我们从第一页获得所有报价信息,我们的下一个任务是抓取所有页面。您应该注意到首页底部有一个“下一页”按钮用于页面导航,逻辑是:单击“下一页”按钮进入下一页,获取报价,再次单击“下一页”直到没有“下一页”按钮的最后一页。

通过 Chrome DevTools,我们可以获得下一页的 URL:

让我们通过再次运行scrapy shell [http://quotes.toscrape.com/](http://quotes.toscrape.com/)在 Scrapy Shell 中进行测试:

$ scrapy shell [http://quotes.toscrape.com/](http://quotes.toscrape.com/)
...>>> response.css('li.next a::attr(href)').get()'/page/2/'

现在,我们可以编写以下代码,让蜘蛛浏览所有页面以获取所有报价:

next_page = response.urljoin(next_page)获取完整的 URL,yield scrapy.Request(next_page, callback=self.parse)发送一个新的请求来获取下一个页面,并使用回调函数调用相同的解析函数来获取新页面的报价。

可以使用快捷键进一步简化上面的代码:参见本节。本质上,response.follow支持相对 URL(不需要调用urljoin),并自动为<a>使用href属性。因此,代码可以进一步缩短:

for a in response.css('li.next a'):
            yield response.follow(a, callback=self.parse)

现在,再次运行蜘蛛程序scrapy crawl quotes,你应该会看到所有 10 页的引文都被提取出来了。坚持住——我们就要完成第一部分了。下一个任务是抓取单个作者的页面。

如上所示,当我们处理每个报价时,我们可以通过跟随突出显示的链接进入单个作者的页面—让我们使用 Scrapy Shell 来获得链接:

$ scrapy shell [http://quotes.toscrape.com/](http://quotes.toscrape.com/)
...
>>> response.css('.author + a::attr(href)').get()'/author/Albert-Einstein'

因此,在提取每个引文的循环过程中,我们发出另一个请求,以转到相应作者的页面,并创建另一个parse_author函数来提取作者的姓名、生日、出生地点和简历,并输出到控制台。更新后的蜘蛛如下所示:

再次运行 spiderscrapy crawl quotes并再次检查您需要提取的所有内容是否正确输出到控制台。注意 Scrapy 基于 Twisted ,这是一个流行的 Python 事件驱动网络框架,因此是异步的。这意味着单独的作者页面可能不会与相应的报价同步处理,例如,作者页面结果的顺序可能与页面上的报价顺序不匹配。我们将在后面的部分讨论如何将报价与其对应的作者页面链接起来。

恭喜你,你已经完成了本教程的第一部分。

第二部分中了解更多关于物品和物品装载器的信息。

第一部分第二部分第三部分第四部分第五部分

一个极简的端到端剪贴簿教程(第二部分)

原文:https://towardsdatascience.com/a-minimalist-end-to-end-scrapy-tutorial-part-ii-b917509b73f7?source=collection_archive---------5-----------------------

面向初学者的系统化网页抓取

Photo by Igor Son on Unsplash

第一部分第二部分第三部分第四部分第五部分

在第一部分中,您了解了如何设置 Scrapy 项目并编写了一个基本的蜘蛛程序来通过页面导航链接提取网页。但是,提取的数据仅显示在控制台上。在第二部分中,我将介绍 Item 和 ItemLoader 的概念,并解释为什么应该使用它们来存储提取的数据。

我们先来看看刺儿头架构:

正如您在第 7 步和第 8 步中看到的,Scrapy 是围绕项目的概念设计的,即,蜘蛛将把提取的数据解析成项目,然后项目将通过项目管道进行进一步处理。我总结了使用 Item 的一些关键原因:

  1. Scrapy 是围绕 Item 和 expect Items 设计的,作为 spider 的输出——您将在第四部分看到,当您将项目部署到 ScrapingHub 或类似的服务时,会有默认的 ui 供您浏览项目和相关的统计数据。
  2. 项目在一个单独的文件中明确定义了通用的输出数据格式,这使您能够快速检查您正在收集的结构化数据,并在您错误地创建不一致的数据时提示异常,例如在代码中拼写错误的字段名称,这种情况比您想象的更常见:)。
  3. 您可以(通过 ItemLoader)为每个项目字段添加前/后处理,如修剪空格、删除特殊字符等。,并将这个处理代码从主蜘蛛逻辑中分离出来,以保持代码的结构化和整洁。
  4. 在第三部分中,您将学习如何添加不同的项目管道来完成诸如检测重复项目和将项目保存到数据库中之类的事情。

在第一部分的结尾,我们的蜘蛛产生了以下数据:

yield {
                'text': quote.css('.text::text').get(),
                'author': quote.css('.author::text').get(),
                'tags': quote.css('.tag::text').getall(),
            }

yield {
            'author_name': response.css('.author-title::text').get(),
            'author_birthday': response.css('.author-born-date::text').get(),
            'author_bornlocation': response.css('.author-born-location::text').get(),
            'author_bio': response.css('.author-description::text').get(),
        }

你可能会注意到authorauthor_name是同一个东西(一个来自报价页面,一个来自对应的个人作者页面)。因此,我们实际上提取了 6 条数据,即引用文本、标签、作者姓名、生日、出生地点和简历。现在,让我们定义保存这些数据的项目。

打开自动生成的items.py文件,更新其内容如下:

我们只定义了一个名为“QuoteItem”的 Scrapy 项,它有 6 个字段来存储提取的数据。在这里,如果您以前设计过关系数据库,您可能会问:我是否应该有两个项目 QuoteItem 和 AuthorItem 来更好地逻辑表示数据?答案是可以的,但是在这种情况下不推荐,因为 Scrapy 以异步方式返回条目,并且您将添加额外的逻辑来匹配报价条目和其对应的条目——在这种情况下,将相关的报价和作者放在一个条目中要容易得多。

现在,您可以将提取的数据放入蜘蛛文件的条目中,如下所示:

from tutorial.items import QuoteItem
...
quote_item = QuoteItem()
...for quote in quotes:
    quote_item['quote_content'] = quote.css('.text::text').get()
    quote_item['tags'] = quote.css('.tag::text').getall()

或者,更好的方法是使用 ItemLoader,如下所示:

from scrapy.loader import ItemLoader
from tutorial.items import QuoteItem
...

for quote in quotes:
    loader = ItemLoader(item=QuoteItem(), selector=quote)
    loader.add_css('quote_content', '.text::text')
    loader.add_css('tags', '.tag::text')
    quote_item = loader.load_item()

嗯,ItemLoader 的代码看起来更复杂——为什么要这么做?简单的回答是:从 css 选择器获得的原始数据可能需要进一步解析。例如,提取的quote_content在 Unicode 中有引号,需要去掉。

生日是一个字符串,需要解析成 Python 日期格式:

出生位置在提取的字符串中有“in ”,需要删除:

ItemLoader 使预处理/后处理功能可以很好地从 spider 代码中指定,并且项目的每个字段都可以有不同的预处理/后处理功能集,以便更好地重用代码。

例如,我们可以创建一个函数来删除前面提到的 Unicode 引号,如下所示:

MapCompose 使我们能够对一个字段应用多个处理函数(在本例中我们只有一个)。ItemLoader 返回一个列表,比如标签的[‘death’, ‘life’]。对于作者姓名,虽然返回一个列表值,如[‘Jimi Hendrix’],但 TakeFirst 处理器取列表的第一个值。添加额外的处理器后,items.py 看起来像:

现在的关键问题是,我们从报价页面加载两个字段quote_contenttags,然后发出另一个请求来获取相应的作者页面以加载author_nameauthor_birthdayauthor_bornlocationbio。为此,我们需要将项目quote_item作为元数据从一个页面传递到另一个页面,如下所示:

yield response.follow(author_url, self.parse_author, meta={'quote_item': quote_item})

而在作者解析函数中,你可以得到条目:

def parse_author(self, response):
        quote_item = response.meta['quote_item']

现在,在添加了 Item 和 ItemLoader 之后,我们的 spider 文件看起来像这样:

在控制台 Scrapy stats 中运行蜘蛛scrapy crawl quotes,可以找到提取的物品总数:

2019-09-11 09:49:36 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
...'downloader/request_count': 111,
...'item_scraped_count': 50,

恭喜你。您已经完成了本教程的第二部分。

第一部分第二部分第三部分第四部分第五部分

一个极简的端到端剪贴簿教程(第三部分)

原文:https://towardsdatascience.com/a-minimalist-end-to-end-scrapy-tutorial-part-iii-bcd94a2e8bf3?source=collection_archive---------3-----------------------

面向初学者的系统化网页抓取

Photo by Sarah Dorweiler on Unsplash

第一部分第二部分第三部分第四部分第五部分

在第二部分中,您已经从网站中提取了所有需要的数据,并将它们存储在 Items 中。在第三部分中,我将引入项目管道,使用 ORM (SQLAlchemy)将提取的数据保存到数据库中,并处理重复数据问题。

由蜘蛛返回的每个项目被顺序发送到项目管道(如果有的话),以进行额外的处理,例如将项目保存到数据库、数据验证、删除重复项等。项目管道在pipelines.py文件中被定义为类,打开这个自动生成的文件,可以看到一个空管道被定义为“TutorialPipeline”:

您需要在settings.py文件中指定启用哪个管道以及管道的顺序——默认情况下,没有管道被启用。要启用上面的空管道,请在settings.py中注释掉以下部分:

整数值(通常范围从 0 到 1000),例如上面所示的 300,决定了管道的执行顺序(较低值的管道首先运行)。

接下来,让我们开发一个管道来将项目保存到数据库中。在这里,我使用面向对象的范例,使用对象关系映射(ORM)来查询和操作数据库中的数据。特别是,我使用 SQLAlchemy 。我不会涉及 ORM 的细节,请参考这篇文章了解一些利弊。

首先,让我们设计数据库模式。注意,该项目有 6 个字段,如quote_contenttagsauthor_nameauthor_birthdayauthor_bornlocationbio。我将使用三个表来存储这些数据,即报价、标签、作者。引用和标记之间存在多对多关系(一个引用可以有一个或多个标记,一个标记可以与一个或多个引用相关联),作者和引用之间存在一对多关系(一个作者可以有一个或多个引用,但是一个引用只属于一个作者)。

要通过 SQLAlchemy 使用 ORM 定义这个模式,您需要:

  • requirements.txt中添加SQLAlchemy>=1.3.6,在虚拟环境中运行pip install -r requirements.txt安装软件包
  • 用以下内容创建一个models.py:

db_connect()功能使用create_engine(get_project_settings().get(“CONNECTION_STRING”))连接到数据库。CONNECTION_STRINGsettings.py文件中指定。您可以更改连接字符串以连接到不同的数据库系统,如 SQLite、MySQL、Postgres,而无需更改代码。在本教程中,我使用 SQLite,它本质上是一个名为scrapy_quotes.db的本地文件,在蜘蛛第一次运行时在根文件夹中创建。

CONNECTION_STRING = ‘sqlite:///scrapy_quotes.db’

我还提供了一个连接 MySQL 的示例(注释掉了):

# MySQL
CONNECTION_STRING = "{drivername}://{user}:{passwd}@{host}:{port}/{db_name}?charset=utf8".format(
     drivername="mysql",
     user="harrywang",
     passwd="tutorial",
     host="localhost",
     port="3306",
     db_name="scrapy_quotes",
)

现在,让我们创建将项目保存到数据库的管道。打开pipelines.py文件,添加以下类(管道):

确保您还导入了所需的包和函数:

下面的 init 函数使用models.py中的函数连接到数据库(db_connect)并创建表格(create_table),如果表格还不存在的话(否则被忽略)。

process_item函数中,我首先为数据库会话和三个表创建实例。然后,我将作者信息和引用文本值分配给相应的表列。

接下来,我们需要检查当前条目的作者和标签是否已经存在于数据库中,如果到目前为止它们还不存在,则只创建新的作者/标签:

最后,我将报价添加到数据库中:

请注意,由于您在 ORM ( quote.authorquote.tags)中指定的关系,您不需要显式添加作者和标签—新的作者/标签(如果有)将由 SQLAlchemy 自动创建和插入。

现在,运行蜘蛛scrapy crawl quotes,你应该看到一个名为scrapy_quotes.db的 SQLite 文件被创建。您可以使用 SQLite 命令行打开文件以查看提取的内容:

$ sqlite3 scrapy_quotes.db
...sqlite> .tables
author     quote      quote_tag  tagsqlite> select * from quote limit 3;1|The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.|12|Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.|23|The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.|3sqlite> .quit

或者用于 SQLite 的 DB 浏览器:

请注意,我们提取了 50 个报价。假设网站可能会添加额外的报价,并且您希望每周运行一次蜘蛛来收集新报价(如果有的话)。所以,让我们再次运行蜘蛛scrapy crawl quotes,你可能会注意到一个问题:我们现在在数据库中有 100 个报价——同样的 50 个报价被再次提取和存储!

接下来,让我们添加另一个管道来检查该项,以查看该项是否是重复的,如果是,则删除该项,以便该项不会通过其余的管道。

打开 pipelines.py 文件并添加以下类(pipeline):

确保导入 DropItem 异常:from scrapy.exceptions import DropItem。逻辑很简单:执行数据库查询,查看当前商品的报价文本是否已经存在,如果存在,则删除该商品。现在,您需要在settings.py中启用这个管道,并确保在保存到数据库管道之前执行复制管道:

您可以先删除 SQLite 文件,然后运行几次蜘蛛程序,您将看到只有第一次数据库被填充了 50 个引号。之后,您可以看到警告信息,指示重复的项目已被删除。

2019-09-12 11:16:04 [scrapy.core.scraper] WARNING: Dropped: Duplicate item found...
2019-09-12 11:16:04 [scrapy.core.engine] INFO: Closing spider (finished)2019-09-12 11:16:04 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
...'item_dropped_count': 50,'item_dropped_reasons_count/DropItem': 50,...

你已经完成了第三部分!!干杯。在第四部分中,我将向您展示如何部署蜘蛛来进行周期性的爬行和监视,例如,每 10 分钟自动运行一次蜘蛛。

第一部分第二部分第三部分第四部分第五部分

一个极简的端到端剪贴簿教程(第四部分)

原文:https://towardsdatascience.com/a-minimalist-end-to-end-scrapy-tutorial-part-iv-3290d76a2aef?source=collection_archive---------11-----------------------

面向初学者的系统化网页抓取

Photo by Paweł Czerwiński on Unsplash

第一部分第二部分第三部分第四部分第五部分

在前三部分中,您已经开发了一个蜘蛛,它从http://quotes.toscrape.com中提取报价信息,并将数据存储到本地 SQLite 数据库中。在这一部分,我将向您展示如何将蜘蛛部署到云中。

首先,让我们看看你如何部署到https://scrapinghub.com——开源 Scrapy 框架背后的团队运行的商业服务。

创建一个免费帐户和一个新项目:

然后,点击 Code and deployments 菜单,按照屏幕上显示的说明安装shub——记录您的 API 密钥和部署号。

回到 scrapy-tutorial 的根目录(scrapy 项目的根目录),使用命令shub loginshub deploy将你的项目部署到 Scrapy hub:

(venv) dami:scrapy-tutorial harrywang$ shub login
Enter your API key from [https://app.scrapinghub.com/account/apikey](https://app.scrapinghub.com/account/apikey)
API key: xxxxx
Validating API key...
API key is OK, you are logged in now.(venv) dami:scrapy-tutorial harrywang$ shub deploy 404937
Messagepack is not available, please ensure that msgpack-python library is properly installed.
Saving project 404937 as default target. You can deploy to it via 'shub deploy' from now on
Saved to /Users/harrywang/xxx/scrapy-tutorial/scrapinghub.yml.
Packing version b6ac860-master
Created setup.py at /Users/harrywang/xxx/scrapy-tutorial
Deploying to Scrapy Cloud project "404937"
{"status": "ok", "project": 4xxx, "version": "b6ac860-master", "spiders": 3}
Run your spiders at: [https://app.scrapinghub.com/p/404937/](https://app.scrapinghub.com/p/404937/)

Scrapinghub 配置文件scrapinghub.yml在根文件夹中创建,您需要编辑它来指定我们特定的软件包需求。否则,将使用默认设置:

  • 运行 Python 3 的 scrapy 1.7
  • 其他包的需求文件

运行$ shub deploy再次部署,新配置生效。

假设我在 repo 中有 3 个蜘蛛(quotes_spider_v1.pyquotes_spider_v2.py是用于演示目的的中间蜘蛛),您应该在已部署的项目中看到 3 个蜘蛛(quotes_spider.py是主蜘蛛):

现在,你可以运行你的蜘蛛:

作业完成后,您可以检查结果并下载不同格式的项目:

但是,您必须付费才能运行定期作业,例如,每周二上午 8 点运行您的蜘蛛。

在搜索运行定期爬行作业的免费选项时,我遇到了由 my8100 开发的伟大的开源项目 ScrapydWeb——非常感谢作者开发了这样一个具有伟大特性和文档的好项目。接下来,我将带你通过 Heroku 使用 ScrapydWeb 建立你自己的“ScrapingHub.com”的过程(你也可以按照作者的文档)。

下图显示了 ScrapydWeb 的架构,该架构旨在支持分布式爬行。

source: https://github.com/my8100/scrapyd-cluster-on-heroku

在本教程中,我不介绍分布式爬行。相反,我将只设置两个服务器:一个 ScrapydWeb 服务器(该服务器提供 web UI 来管理不同的蜘蛛和作业)和一个 Scrapyd 服务器(该服务器托管您的蜘蛛代码并实际发送/接收请求/响应)。

ScrapydWeb 的作者通过在他的 repo 中预先配置 Heroku 使这个部署过程变得非常简单,repo 位于ttps://github . com/my 8100/scrapyd-cluster-on-Heroku

  • scrapyd-cluster-on-heroku/ScrapydWeb:该文件夹包含 ScrapydWeb 服务器的 Heroku 配置
  • Scrapyd-cluster-on-heroku/Scrapyd:该文件夹包含 Scrapyd 服务器的 Heroku 配置

我们需要定制部署,因为我们的 scrapy 项目有特定的包需求,例如,SQLAlchemy、MySQL、Python 3.x 等。因此,你需要将https://github.com/my8100/scrapyd-cluster-on-heroku的副本放到你的 github 账户中,例如https://github.com/harrywang/scrapyd-cluster-on-heroku并做一些修改来支持本教程。

您可以在https://github . com/Harry Wang/scrapyd-cluster-on-heroku/commit/e 612 dcb 9 a6 c 158 da 4b 744d 311 e 82 c 529497 fba7c查看我对作者回购的修改,包括:

  • 在 scrapyd/requirements.txt 中添加 MySQL 和 SQLAlchem 包
  • 在 scrapyd/runtime.txt 中将 python 版本更改为 python-3.6.8
  • 打开 Scrapy web 服务器认证,在 Scrapy web/Scrapy web _ settings _ v10 . py 中设置用户名和密码(不要这样公开用户名和密码)

接下来,在 heroku.com 创建一个免费账户并安装 Heroku CLI: brew tap heroku/brew && brew install heroku

然后,克隆回购:

git clone [https://github.com/harrywang/scrapyd-cluster-on-heroku](https://github.com/harrywang/scrapyd-cluster-on-heroku)
cd scrapyd-cluster-on-heroku/

登录 Heroku:

scrapyd-cluster-on-heroku harrywang$ heroku login
heroku: Press any key to open up the browser to login or q to exit:
Opening browser to [https://cli-auth.heroku.com/auth/browser/3ba7221b-9c2a-4355-ab3b-d2csda](https://cli-auth.heroku.com/auth/browser/3ba7221b-9c2a-4355-ab3b-d2csda)
Logging in… done
Logged in as [xxx@gmail.com](mailto:xxx@gmail.com)

部署垃圾服务器/应用程序:

  • 首先转到/scrapyd 文件夹,并通过运行以下 git 命令使该文件夹成为 git repo:
git init
git status
git add .
git commit -a -m "first commit"
git status
  • 创建一个名为scrapy-server1的新应用程序(如果这个应用程序被占用,请选择另一个)
  • 设置一个名为 heroku 的 git 遥控器
  • 检查 git 遥控器
  • 将/scrapyd 文件夹中的内容推送到遥控器以部署应用程序
$ pwd
/Users/harrywang/xxx/scrapyd-cluster-on-heroku/scrapyd$ heroku apps:create scrapy-server1$ heroku git:remote -a scrapy-server1set git remote heroku to https://git.heroku.com/scrapy-server1.git$ git remote -vheroku https://git.heroku.com/scrapy-server1.git (fetch)heroku https://git.heroku.com/scrapy-server1.git (push)origin https://github.com/harrywang/scrapyd-cluster-on-heroku (fetch)origin https://github.com/harrywang/scrapyd-cluster-on-heroku (push)$ git push heroku master

您可以为远程垃圾服务器设置环境变量,例如设置时区:

$ heroku config:set TZ=US/EasternSetting TZ and restarting ⬢ scrapy-server1... done, **v4**TZ: US/Eastern

现在,你有了一个运行在 http://scrapy-server1.herokuapp.com 的 scrapyd 服务器

接下来,让我们设置 web 应用程序,它为我们添加 scrapyd 服务器、上传 scrapy 项目和安排爬行作业提供了 UI。

同样,让我们部署 ScrapydWeb 服务器/应用程序:

  • 首先转到/scrapydweb 文件夹,通过运行以下 git 命令使该文件夹成为 git repo:
git init
git status
git add .
git commit -a -m "first commit"
git status
  • 创建一个名为scrapyd-web的新应用
  • 设置一个名为 heroku 的 git 遥控器
  • 检查 git 遥控器
  • 将/scrappy web 文件夹中的内容推送到远程设备以部署应用程序
  • 设置时区
$ pwd/Users/harrywang/xxx/scrapyd-cluster-on-heroku/scrapydweb$ heroku apps:create scrapyd-web$ heroku git:remote -a scrapyd-webset git remote heroku to [https://git.heroku.com/scrapyd-web.git](https://git.heroku.com/scrapyd-web.git)$ git remote -v
$ git push heroku master
$ heroku config:set TZ=US/Eastern
Setting TZ and restarting ⬢ scrapyd-web... done, **v6**TZ: US/Eastern

您需要向 web 服务器添加至少一个 Scrapyd 服务器(让我们添加您刚刚在scrapy-server1.herokuapp.com上面设置的服务器)。您可以以类似的方式添加更多用于分布式爬网的 scrapyd 服务器:

$ heroku config:set SCRAPYD_SERVER_1=scrapy-server1.herokuapp.com:80Setting SCRAPYD_SERVER_1 and restarting ⬢ scrapyd-web... done, **v6**SCRAPYD_SERVER_1: scrapy-server1.herokuapp.com:80

现在,你有了运行在 http://scrapyd-web.herokuapp.com 的 scrapyd 网络服务器。在浏览器中打开该地址,使用您在 scrapydweb/scrapydweb _ settings _ v10 . py 文件中指定的用户名和密码登录,您应该会看到 web 服务器的管理 UI:

最后一个任务是使用[scrapyd-client](https://github.com/scrapy/scrapyd-client)部署我们的 scrapy 项目。

去我们的 scrapy 项目回购:

$ pwd/Users/harrywang/xxx/scrapy-tutorial

使用pip install git+[https://github.com/scrapy/scrapyd-client](https://github.com/scrapy/scrapyd-client)安装 scrapyd-client。

打开scrapy.cfg文件,修改其内容,添加如下部署配置:

[settings]
default = tutorial.settings[deploy]
url = [http://scrapy-server1.herokuapp.com](http://scrapy-server1.herokuapp.com)
username = admin
password = scrapydweb
project = scrapy-tutorial

然后,使用scrapyd-deploy将我们的项目打包并部署到 scrapyd 服务器:

$ scrapyd-deploy/Users/harrywang/xxx/scrapy-tutorial/venv/lib/python3.6/site-packages/scrapyd_client/deploy.py:23: ScrapyDeprecationWarning: Module `scrapy.utils.http` is deprecated, Please import from `w3lib.http` instead.from scrapy.utils.http import basic_auth_headerPacking version 1568331034Deploying to project "scrapy-tutorial" in http://scrapy-server1.herokuapp.com/addversion.jsonServer response (200):{"node_name": "5f9ee34d-f6c8-4d80-ac05-3657c4920124", "status": "ok", "project": "scrapy-tutorial", "version": "1568331034", "spiders": 3}

在浏览器中打开http://scrapyd-web.herokuapp.com/1/projects/,您应该看到项目成功部署:

点击菜单"运行蜘蛛",可以运行"行情"蜘蛛:

然后,您可以在“作业”菜单中检查结果,并在“项目”菜单中下载项目——您可以尝试其他菜单来查看统计数据、错误等。:

最后一个任务是指定一个定时任务,比如每 10 分钟自动运行一次报价蜘蛛:点击“定时器任务”,下面的截图显示了一个每 10 分钟运行一次的任务——定时器任务的特性是基于一个名为 APScheduler 的高级 Python 调度器库,参见这部分文档来弄清楚如何为定时器设置不同的值。

然后,您可以检查任务结果:

下面显示计时器任务已经触发了 4 次:

注意,在将我们的项目部署到服务器时,我们不应该使用本地 SQLite 数据库。相反,我们应该保存到一个远程数据库,比如 MySQL 服务器——您只需要像我们在第三部分中讨论的那样更改 CONNECTION_STRING 变量。

恭喜你!你已经完成了本教程,我希望你喜欢学习。

作为奖励,我还创建了一个单独的 repo ( Scrapy + Selenium )来展示如何抓取动态网页(例如通过滚动加载附加内容的页面)以及如何使用代理网络(ProxyMesh)来避免被禁止,请阅读第五部分。

第一部分第二部分第三部分第四部分第五部分

防止语音助手误触发的建议

原文:https://towardsdatascience.com/a-modest-proposal-for-voice-assistants-91ee48ed1325?source=collection_archive---------16-----------------------

只需使用内部噪音消除来防止语音助手用反馈触发自己

就是这样。标题说明了一切。

Image by TechCrunch

开个玩笑,我会进一步解释这个想法,为什么我认为这是解决问题的必要方法,为什么我觉得我首先需要写这篇文章。

两句外卖

由于音频反馈,Alexa、Cortana 和谷歌助手等语音助手目前似乎能够在输出的声音包含唤醒词或至少足够接近的内容时触发自己。我建议通过过滤掉助理音频输出的噪声控制算法来输入他们的麦克风输入,从而解决这个问题。

问题是

你曾经通过你的助理设备(Google Home、Amazon Echo 等)播放过播客、新闻甚至音乐吗?)只是为了让它说出那些可怕的单词“Ok Google”/“Alexa”?那么毫无疑问,你已经经历了我试图解决的问题。本质上,这些助手能够通过说出自己的唤醒词来逗自己,然后对唤醒词做出回应。更糟糕的是,当这种情况发生时,唤醒词/短语甚至没有说。

亚马逊朝着正确方向迈出的一步

最近亚马逊的 Alexa 团队想出了一个聪明的方法,可以部分地帮助解决这个问题,但它不是万无一失的。本质上,他们创建了一个已知假阳性“Alexa”触发器(如亚马逊商业广告)的指纹数据库,然后每当它认为有人说了唤醒词时,就会根据这个数据库检查新的触发器。如果你有一个 Echo 设备,并观看了最近的超级 Owl handegg 游戏,你可能会注意到 Alexa 的商业广告令人惊讶地没有让你的 Echo 发疯。此外,Amazon 创建了一种方法来自动扩展此数据库,以防止第三方误报,方法是用相似的指纹标记来自多个客户的唤醒事件,将其记录为“媒体事件”。

An illustration of how fingerprints are used to match audio. Different instances of Alexa’s name result in a bit error rate of about 50% (random bit differences). A bit error rate significantly lower than 50% indicates two recordings of the same instance of Alexa’s name. Image by the Amazon’s developer blog

虽然这应该提供了显著的改进,但是这种方法不足以完全解决这个问题,特别是因为我们现在消费的大多数媒体是流式的,因此是非同步的,所以许多错误触发不会同时发生。此外,这种方法涉及比较云中除了最可预测的触发器之外的所有触发器的指纹,这增加了助理使用的处理时间和带宽。我称赞亚马逊实现了这样一种新颖的方法(尽管它并不完全新颖,因为我非常确定谷歌的个性化语音识别模型遵循了类似的设计模式),即使它不是包罗万象的。

但是多麦克风系统的噪音消除怎么样呢?

的确,现在大多数(如果不是全部的话)语音助手设备都带有多个麦克风来检测背景噪音并将其过滤掉,使用一种称为波束形成的噪音控制技术来专注于你的声音。然而,这个问题只是与手头的问题无关。例如,多麦克风设置非常适合在关掉房间中的大音量电视时清晰(或多或少)地听到您的命令,但当设备在附近没有人说话的情况下听到命令时,这种设置就不是完成任务的正确工具。

“大”的想法

我的提议真的很简单,简单到我曾经以为语音助手的所有主要参与者都在使用这种方法。然而,随着我花更多的时间在家里对着机器人大喊大叫告诉我这个消息,我开始意识到他们要么没有这样做,要么如果他们这样做了,他们做得不好。在听了许多其他人的轶事后,我知道我不是唯一一个确保用耳机听我最喜欢的技术播客的人,以免让我过于热切的人工智能助手产生错误的想法。

好吧,也许他们现在的语音助手不会这么做,但这种方法现在应该已经在其他地方提出来了,对吧?也许吧,但我不这么认为。我使用各种相关的术语和各种平台进行了几次搜索,从常规的谷歌搜索,到谷歌学术搜索,再到语义学者搜索。如果有一篇研究论文、专利、博客文章或任何其他公开的资源,那么我觉得我应该找到它;我通常能找到我想要的。如果我错过了什么关键的东西,我很想听听。我找到了大量关于主动噪声控制(ANC)的资源,以及更多关于人工智能语音助手的资源,但我能找到的最接近这一应用的是这篇关于语音助手噪声消除的论文,但可惜的是,范围仅限于外部噪声,正如上文针对多麦克风设置所讨论的:https://pdfs . semantic scholar . org/e448/5 abce 7703 bace 8 FDD 3 ba 3 e 65688 e 1c 60d 827 . pdf?_ ga = 2.7190005241670009-4167009

Diagram by Silentium

术语的快速概述:

主动噪声控制(ANC) ,有时也称为主动噪声消除,通过记录不想要的噪声,然后回放其相反的波形(基本上就是相同的声音在时间上向后移动了半个相位)来过滤掉不想要的噪声,从而消除不想要的噪声,同时保留想要的噪声。

我们的问题实际上可以归结为音频反馈,即系统在音频输入中拾取自己的音频输出。在像剧院这样的现场音响系统中,由于反馈回路放大高频,反馈很快转变为震耳欲聋的尖叫。幸运的是,我们的语音助手不会屈服于反馈循环,因为他们不会立即输出他们的输入音频,但每当你的助手触发自己时,它都会对反馈做出反应。我在影音系统方面的背景可能是我之前假设这种方法已经被广泛使用的原因。

工作原理:

该系统应该能够完全在大多数语音助理系统的软件中实现,因此能够在当前一代语音硬件(如 Google Homes 和 Amazon Echos)上部署更新。我建议使用发送到扬声器的音频馈送,而不是使用独立的外部麦克风作为 ANC 滤波器的输入。由于设备正在生成音频,我们可以 100%确定我们不需要使用任何音频作为输入。这不仅可以防止反馈意外触发助手,还可以帮助助手在音频输出时专注于人类的命令,从而在你想与助手交谈时更容易通过你的音乐大喊。最重要的是,与亚马逊的方法不同,这种方法不需要 ping 云进行验证,也不会给助理设备增加过多的处理开销,因为 ANC 可以是一种相对简单的计算。就像大多数人无法挠自己痒痒一样,因为我们的大脑知道我们自己的行为产生了什么输入,这种方法将使人工智能助手无法触发自己。

The orange elements represent the software bits that I propose adding to the system.

这个想法的类似实现:

虽然我无法找到这种技术用于语音助手设备的任何证据,但我确实发现这种方法在其他应用中得到利用,例如专业音频音响系统或扬声器电话中的反馈抑制,就像这个过期的专利:【https://patents.google.com/patent/US6212273B1/en】T4

因此,如果这已经是现有人工智能助手设计的一部分,我很抱歉重复这一显而易见的内容,但请继续阅读,因为有一些方法可以建立在这个想法上,我认为这些方法还没有开发出来。据我所知,这种方法或任何类似的方法目前没有在任何人工智能助手中使用。

潜在的障碍:

一个可能的问题是,如果设备没有拾取到显著的声反馈,则以数字方式引入反馈。许多语音助手设备具有非常复杂的麦克风阵列和扬声器,旨在最大限度地减少反馈,因此,如果麦克风拾取的音频不够响亮,理论上可以将新音频添加到输入中。这是由于 ANC 的工作方式:简单地异相播放相同的音频。避免这一问题的一种方法是,根据来自麦克风输入的音频电平,调整发送到 ANC 的输出音频的增益/音量。这种缩放可以作为 ANC 算法的函数动态发生,并且可以在每次设备上电时设置基线,作为针对其特定声学环境对其进行校准的方式。

另一个潜在的缺点可能是需要重新训练触发字检测算法,以考虑 ANC 算法的过滤。然而,从我对算法的理解来看,它们可能足够健壮,能够在这些不同的参数下很好地运行。此外,如果他们用非常干净的音频进行训练,这种过滤后的音频可能会更接近训练数据。

Gif by tenor

更多功能:

人工智能语音接口的圣杯是与人工智能的全双工通信,其中人工智能说话和人类说话之间可以有重叠,双方都可以跟上。当前版本的语音助手就像对讲机,如果你打断它,它必须停止说话;这被称为半双工。虽然制作一个令人信服的人类语音人工智能的步骤比避免反馈要复杂得多,但反馈肯定会成为人工智能的主要绊脚石。这种方法应该有助于我们到达那里:通过阻止人工智能听自己的话。

此外,虽然这种方法讨论的是一个器件的输出通过 ANC 滤波器以数字方式馈入,但没有理由将我们的思维局限于同一器件的反馈。该助理可能从听力范围内的任何设备接收音频馈送。比方说,我们不想让 Chromecast 或智能电视的音频干扰我们的助理,您可以设置这些设备以数字方式将音频馈送发送给助理,以便它过滤掉不相关或不需要的信号。与上面提到的问题类似,如果缺少声音反馈,设备在其环境中进行自我校准将是至关重要的。这可以通过每当一个人启动时,它播放一个快速校准音来实现,然后在听力范围内的助理用它来设置 ANC 滤波器的适当水平。这将解决亚马逊试图利用 Alexa 指纹数据库的问题,只需让电视告诉助手忽略来自它的所有音频,包括任何潜在的触发因素。

为什么要提出这个建议

以我对这个想法的详细程度和我对类似应用的研究,我可能会成功申请专利。但是我相信分享好的想法,据我所知,这个想法从来没有被分享过,尽管它对我来说似乎非常明显。另外,这应该算作的现有技术来阻止任何人申请将内部 ANC 应用于语音助手的专利。我没有足够的资源来实现我的每一个想法,所以为什么不把它们放在那里,看看其他人是否能从中受益?如果你最终使用了这个想法,或者你想在某件事情上合作,我很乐意听到你的意见。

如果任何 ANC、HCI(语音)、对话式 AI 或任何其他相关领域的专家正在阅读,并且希望更深入地探索这一点,请告诉我。我愿意进一步研究或测试它。也许我错过了一些关键因素或已经提出这种方法的工作。如果是这样,我真的很想了解一下。

另外,我有一个用超声波频率防止人工智能意外触发的想法。如果有人有兴趣了解更多,请告诉我,我很乐意进一步发展这个想法。

我期待听到任何人对这篇文章或讨论的话题的反馈或问题,无论是在这里还是在社交媒体上。随时联系我(只要告诉我你看到这篇文章了)→

【twitter.com/theNathanielW

linkedin.com/in/theNathanielWatkins

计算掷骰子的期望值的蒙特卡罗实验

原文:https://towardsdatascience.com/a-monte-carlo-experiment-for-calculating-the-expected-value-of-a-full-dice-roll-af8a3f9a612e?source=collection_archive---------43-----------------------

在看到所有 6 个数字之前,掷骰子的期望值是多少?数学和程序上的解释。

Monte Carlo, Wikipedia Commons by MartinP.

这个问题是很多面试中的常见问题,下面是一个使用随机抽样解决这个问题的程序化方法。这个想法是,运行许多实验,在这些实验中,你滚动骰子(均匀分布的样本),直到你看到所有 6 个数字都出现在一个正常和公平的骰子中。最后,你计算期望值

数学

再说几率,第一次掷出一个数字的几率是 1,看到第二个数字的几率是 5/6 等等。

我们可以用这个公式来概括:

为了解决这个问题并且由于结果是几何分布。一个数字出现的概率是 1/p,这意味着从上面的公式中计算出的每个数字都应该放在而不是“p”作为分母。

最后,我们计算掷骰子直到看到每个数字所需的平均时间,即 14.7。

代码

我们可以使用几行代码,通过运行蒙特卡罗实验,即 10K 随机实验,从 1 到 6 之间的均匀分布中抽取数字,并计算在每个实验中我们掷出所有 6 个数字的次数。所有这些实验的平均值就是期望值。大约是 14.7,你可以改变滚动的次数,看看它在这个模拟环境中的效果。

我要感谢我的同事 Shay Yehezkel。

Ori Cohen 博士拥有计算机科学博士学位,专注于机器学习。他在 Zencity.io 领导研究团队,试图积极影响市民生活。

带有 BERT、Transformer-XL 和 Seq2Seq 的多任务音乐模型

原文:https://towardsdatascience.com/a-multitask-music-model-with-bert-transformer-xl-and-seq2seq-3d80bd2ea08e?source=collection_archive---------5-----------------------

Buzzwordy clickbait 标题本意,但仍然是一个简单的概念。

这是“构建人工智能音乐生成器”系列的第三部分。我将讲述音乐模型多任务训练的基础知识——我们将用它来做一些非常酷的事情,如和声、旋律生成和歌曲混音。我们将在第一部第二部的基础上展开。

背景

如你所知,变形金刚最近革新了自然语言处理领域。您可能也知道,有几种不同的变压器变体。它们都有相同的基本注意层,但有些是专门用于不同的任务。这里有 3 个最酷的:

Seq2Seq (序列到序列翻译)——使用编码器-解码器架构在语言之间进行翻译。这就是开启革命的 OG 变形金刚。

transformer XL—这款正向解码器是一款令人惊叹的文本生成器。记忆和相对位置编码使超快速和准确的预测成为可能。我们在第二部分中使用了这个模型。

BERT—这个双向编码器在回答问题和填空时产生 SOTA 结果。令牌屏蔽和双向允许特殊的上下文。

该死,所有这些变化都太酷了!与其选择一个,为什么不把它们结合起来呢?

等待..什么?!?

请稍等片刻。

多任务模型来统治他们

如果你正在训练一个语言模型,那么结合这三个模型是没有意义的。

TransformerXL 非常适合生成文本。Seq2Seq 非常适合语言翻译。伯特擅长填空。你没有理由想同时做这三件事。

对于音乐一代来说,这是一个不同的故事。

让我们来看几个你在考虑作曲时的场景:

任务 1。我有几个音符想做成一首 的歌

TransformerXL 非常擅长序列生成。让我们用它来自动完成你的歌曲想法。

任务 2a。我的旋律需要一些和声。
任务 2b。我有一个和弦进行。现在我需要一个钩子。

S eq2Seq 非常适合翻译任务。我们可以用这个把旋律翻译成和弦。反之亦然。

任务 3a。我现在有了一首歌,但听起来有些不对劲。
任务 3b。这首歌需要更好的节奏。

伯特很擅长填空。我们可以删除歌曲的某些部分,用伯特来产生一个新的变奏。

如你所见,每一种变形都有助于产生歌曲创意。我们要训练一个能解决所有这些任务的模型。

先玩,后理解

为了理解我们在这里试图做什么,尝试一下我们试图创建的多任务模型可能会有所帮助。

每个演示都是为了解决特定的任务而生成的。在预测值(红色音符)和原始值(绿色音符)之间切换,听出不同之处。

任务 1。宋一代
《典藏 D》作者帕赫尔贝尔

任务 2a 。和谐的旋律
《爱在哪里》黑眼豆豆

任务 2b 。现有和弦进行的新旋律
【史奇雷克斯的《可怕的怪物和可爱的小精灵》

任务 3a。同节拍,异曲
《关卡》由中航工业

任务 3b。同一首歌,混音节拍
贝多芬的《富尔伊利斯》

建造怪物

你回来了。现在让我们来建造这个东西。

一开始听起来可能有点令人畏惧,但是说实话并不复杂。我们的多任务模型本质上是 Seq2Seq 架构。我们所做的只是修改它来训练不同的任务。

我假设你已经知道 Seq2Seq 翻译是如何工作的。如果没有,请访问这个不可思议的 变形金刚插图

Seq2Seq

好了,现在让我们想象一下 Seq2Seq 变压器如何为音乐工作。

非常类似于你如何翻译一种语言。和弦(输入语言)被翻译成旋律(目标语言)。

“先前的输出”被反馈到解码器,所以它知道什么已经被翻译。

编码器与解码器

该模型被分成蓝色编码器块和红色编码器块。了解这两者之间的区别很重要,因为我们将在其他任务中重新使用它们。

蓝色编码块 单双向注意层。他们能够看到以前和将来的令牌。

红色解码块双层叠前向注意层。双堆叠块使用编码器输出和“先前输出”作为上下文来预测旋律。前向图层无法看到未来的令牌,只能看到之前的令牌。

正如你可能已经猜到的,蓝色双向编码器是训练 BERT 模型的完美匹配。同样,前向解码器层可以重新用于训练 TransformerXL 任务。

让我们来看看。

伯特

擦掉一些笔记,伯特会填空:

Masked notes prevent bidirectional layers from cheating

我们训练编码器预测正确的音符(红色),只要它看到一个屏蔽的令牌(蓝色)。

变压器 XL —下一个字

你会从以前的文章中认出这个图表。

Next tokens are attention masked to prevent cheating

我们训练解码器通过将目标移动一位来预测下一个令牌。

综合考虑

如您所见,Seq2Seq 型号是 BERT 编码器和 TransformerXL 解码器的组合。这意味着我们可以重用 Seq2Seq 模型中的编码器和解码器来训练 BERT 和 TransformerXL 任务。唯一改变的是输入和目标。

这里提醒一下我们之前的三项任务:

任务 1。使用 TransformerXL 生成音乐

任务 2a/2b。使用 Seq2Seq 进行旋律到和弦/和弦到旋律的翻译

任务 3a/3b。宋与伯特的混音

解决多任务#2。

前面你看到了如何进行旋律到和弦的翻译(2a。).和弦到旋律的任务(2b。)是完全相同的,但是输入和目标被翻转。

多任务#1 和#3

由于 BERT 仅使用编码器层,而 TransformerXL 仅使用解码器层,因此可以同时训练任务#1 和任务#3。在 BERT 端,我们屏蔽输入并通过编码器发送。同时,我们将移位后的输入馈入解码器以训练 TransformerXL。

看起来是这样的:

  • 编码器接受屏蔽任务的训练。
  • 单独且并行地,解码器在下一个令牌任务上被训练。

注意,解码器只有一个箭头作为输入。对于此任务,它不使用编码器输出。

瞧啊。这是我们的模型代码

希望这个模型对使用过 PyTorch 的人来说非常清楚。

Model architecture:
Encoder - Bi-directional attention layers
Decoder - Uni-directional double-stacked attention layers
Head - Dense layer for token decodingForward Prop:
1\. If the input is masked ('msk'), train the encoder.
2\. If the input is shifted ('lm'), train the decoder.
3\. If the input contains both translation input ('enc') and previous tokens ('dec'), use both encoder and decoder.

运行此笔记本进行实际训练。

这就是训练多任务模型的全部内容。

它实际上只是一个编码器/解码器模型,针对各种类型的输入和输出进行训练。

屏蔽令牌训练编码器(BERT)。移位令牌训练解码器(TransformerXL)。成对序列训练两者(Seq2Seq)。

关于结果

如果你使用了本文开头的例子,那么你已经看到了结果。音乐机器人网络应用由多任务转换器驱动。与其听我喋喋不休地谈论结果,不如回去自己创造结果,你会更开心!

要启用任务 1、2a、2b、3a、3b ,只需拨动此开关:

备选计划yg ground

如果你觉得需要更多的动手操作,这个 python 笔记本用代码生成了所有相同的例子。通过浏览笔记本,你会更好地理解预测是如何工作的。

将结果更进一步

呜哇!我们可以生成一些很酷的结果,但是…它似乎缺少了一些流行音乐的魔力。在我们的下一篇文章中,我们将揭开一些神奇的酱料。

第四部分。使用一个音乐机器人来重新混合烟鬼——这是我最喜欢的最后一篇文章了!

谢谢你对我的包容!

特别感谢肯尼斯、 、杰瑞米·霍华德SPCPalapaVC 的支持。

使用 Spotify API 和 Python 进行音乐品味分析。

原文:https://towardsdatascience.com/a-music-taste-analysis-using-spotify-api-and-python-e52d186db5fc?source=collection_archive---------3-----------------------

探索音频特征并构建机器学习方法

几天前,我读了一篇非常有趣的文章,作者是我的一个朋友(鲁兹),他使用 API(应用编程接口)分析了他的 Spotify 播放列表。读完之后,我打开应用程序,看了看我的播放列表,意识到我一周甚至一整天都在听不同风格的音乐。我可能一分钟前还在听桑巴,过一会儿又开始听重金属。想到这一点,我决定不仅分析我的音乐品味,也分析我未婚妻的音乐品味,以弄清楚数据对此有何说明。

因此,为了做到这一点,我首先使用 Spotify 的 API 提取了我们在 Spotify 上听得最多的 10 位艺术家的音频特征,以便我能够进行音乐品味分析。除此之外,我训练了一个机器学习模型来预测一首歌更有可能属于的每个列表。

另一个值得注意的事实是,我有一些来自数据科学做零的参考资料,这是巴西一个著名的数据科学社区。

你可以在我的Github页面 上查看我开发的所有代码

工具:

  • Spotify 库获取 Spotify 平台音乐数据
  • Seaborn 和 matplotlib 实现数据可视化
  • Pandas 和 numpy 实现数据分析
  • Sklearn 构建机器学习模型

Spotify 音频功能

众所周知,Spotify 是全球最受欢迎的音频流媒体平台之一。同样,Twitter、Slack 和脸书也为开发者提供了一个 API 来探索他们的音乐数据库,并深入了解我们的收听习惯。

基于此,我选择了十位我日常经常听的艺术家,并让我的未婚妻给我一张她最喜欢的艺术家的名单。有了艺术家列表后,我使用了稀有战利品帖子作为参考来获取音频特征数据,以便进行分析。

获得的第一个数据集包含 16 列,其中 1433 首歌曲来自我的列表,691 首来自 Emily 的 lit。因此,为了平衡歌曲的数量,我构建了一个函数,从我的列表中随机删除一些行。在删除过程之后,我们总共找到了 1394 首歌曲(703 首来自我的列表,691 首来自 Emily 的列表)。

值得一提的是,我并没有使用所有的 16 列进行分析。相反,我只选择了那些与音频特性相关的栏目。您可以在下面找到每个功能的解释(过去/复制自 Spotify 网站)。

  • 声音:一种置信度,从 0.0 到 1.0,表示音轨是否是声音的。1.0 表示音轨是声学的高置信度。
  • 可跳舞性:可跳舞性描述了一个曲目在音乐元素组合的基础上适合跳舞的程度,包括速度、节奏稳定性、节拍强度和整体规律性。值 0.0 最不适合跳舞,1.0 最适合跳舞。
  • 能量:能量是一个从 0.0 到 1.0 的度量,代表强度和活动的感知度量。通常,高能轨道感觉起来很快,很响,很嘈杂。例如,死亡金属具有高能量,而巴赫前奏曲在音阶上得分较低。对该属性有贡献的感知特征包括动态范围、感知响度、音色、开始速率和一般熵。
  • 乐器性:预测音轨是否不包含人声。“Ooh”和“aah”在这种情况下被视为乐器。Rap 或口语词轨道明显是“有声的”。乐器度值越接近 1.0,轨道不包含人声内容的可能性就越大。高于 0.5 的值旨在表示乐器轨道,但随着该值接近 1.0,置信度会更高。
  • 活跃度:检测录音中是否有观众。较高的活跃度值表示音轨被现场执行的概率增加。高于 0.8 的值很有可能表示该音轨是实时的。
  • 响度:轨道的整体响度,以分贝(dB)为单位。响度值是整个轨道的平均值,可用于比较轨道的相对响度。响度是声音的质量,是与体力(振幅)相关的主要心理因素。值的典型范围在-60 和 0 db 之间。
  • 语速:语速检测音轨中是否存在口语单词。越是类似语音的录音(例如脱口秀、有声读物、诗歌),属性值就越接近 1.0。高于 0.66 的值描述可能完全由口语单词组成的轨道。介于 0.33 和 0.66 之间的值描述可能包含音乐和语音的轨道,可以是分段的,也可以是分层的,包括说唱音乐。低于 0.33 的值很可能代表音乐和其他非语音类轨道。
  • 配价:从 0.0 到 1.0 的一种量度,描述音轨所传达的音乐积极性。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。
  • 速度:轨道的整体估计速度,单位为每分钟节拍数(BPM)。在音乐术语中,速度是给定作品的速度或节奏,直接来源于平均节拍持续时间。

Features

数据分析

在我决定做这篇文章之前,我从来没有真正考虑过我的音乐品味。事实上,在思考这个问题后,我意识到我没有一个每天都听的特定类型的音乐。其实那要看我的心情了…有些天我醒来听 pagode(来自里约热内卢的巴西风格音乐),有些天起床后只想听一首真正有活力的歌比如铁娘子,等等。所以,我很好奇不仅调查我的,也调查 Emily 的 Spotify 音频功能。也就是说,让我们直接进入分析。我将首先绘制一个柱状图和一个雷达图,显示我们的特征,以便对它们进行比较。

情节表明,在我的艺术家名单中,最突出的特征是活力——可能是因为 ACDC、铁娘子和摩托头乐队等摇滚乐。另一方面,观察 Emily 的特征,我们可以注意到可跳舞性能量是她列表中普遍的音频属性。这真的很有道理,因为她喜欢听 Ludmila(巴西放克歌手)和 Rihanna 等艺术家的歌曲。

速度是音乐分析的一个重要特征。它可以像旋律、和声或节奏一样重要,因为它代表了歌曲的速度和它唤起的情绪。例如,一首歌的 BPM 越高,这首歌的速度就越快,因此也就越令人振奋和快乐。另一方面,低 BPM 意味着歌曲较慢,这可能表明悲伤、浪漫或戏剧。

查看下图,我们可以看到我们的列表平均速度接近 120 BPM,这表明速度适中/较快。基于这一点,我认为这两种类型的赛道对那些喜欢快走和跑步的人都有兴趣,因为一首 120 BPM 的歌曲通常可以与一个人的步幅模式和他们的步伐同步,以使跑/走更难和更快。

为了比较音频特性,请务必查看下面的条形图。它显示了我的和 Emily 的歌单的每个属性的平均值之间的差异。

与此一致,我们可以清楚地看到,我的列表比她的更有活力,更生动,更具工具性。此外,我们还可以注意到在我们的语音变量上的微小差异,并且看到化合价、声音在她这边占据首位。

名单有多多样化?!

可以通过检查我们歌曲流派的差异来调查列表的多样性。如果大多数歌曲属于同一流派,我们会说它们变化不大。

问题是:我们如何分析这个问题?嗯,答案很简单:让我们检查每个音频变量的标准偏差,并对它们进行检查。

虽然音频特征本身的标准偏差不能给我们提供太多信息(正如我们在下面的图中看到的),但我们可以将它们相加,并计算列表标准偏差的平均值。通过这样做,我们得到了“各种音频特性”图中表示的值,在我的列表中值为 0.22,在 Emily 的列表中值为 0.20。

我们该如何解释呢?!好吧,让我们说,我们可以有一些歌曲的某个特定特征的值很高,比如能量,而其他歌曲的相同属性的值很低。简而言之,这些数字表明我的歌曲比艾米丽的更多样化。

Variety of Audio Features

Standard Deviation of the Audio Features

变量之间的相关性

我们还可以构建相关图,如散点图,来显示变量之间的关系。在我们的例子中,我们将把描述音乐积极性的特征效价与可舞性和能量联系起来。

为了解释下面的情节,我们必须记住数字一(绿点)和数字零(灰点)分别代表我和艾米丽的歌曲。也就是说,让我们检查散点图。

化合价和能量

配价和能量之间的相关性表明,有一个高能量和低水平的配价歌曲聚集。这意味着我的许多充满活力的歌曲听起来更消极,带有悲伤、愤怒和抑郁的感觉(NF 在这里占据特殊位置哈哈)。然而,当我们看灰色的点时,我们可以看到,随着积极情绪水平的增加,歌曲的能量也增加了。虽然她的数据是分裂的,但我们可以识别这种模式,表明变量之间存在某种“线性”相关性。

配价和可舞性

现在,看看化合价和可跳舞性之间的关系,我们可以看到 Emily 的歌曲在情节的第一和第二象限中具有高的可跳舞性值。另一方面,我的歌曲大多要么在第三象限,要么在第一象限,就这两个特征而言,表现出一种多样性。

机器学习方法

好了,我们从数据中得到了一些启示。为了使这篇文章简短,让我们直接进入最好的部分(至少对我来说),那就是机器学习(ML)算法。

重要的是要记住,我并不是 100%关注模型的准确性。此外,我们将使用支持向量机(SVM ),因为它是我目前正在研究的。此外,我不会解释 SVM 是如何工作的。相反,让我们说它是一种监督的 ML 方法,用于分类和回归问题。此外,它的主要任务(分类)是通过定义一个区分它们的最佳超平面来分离所有的类。也就是说,让我们建立一个算法来预测一首歌更有可能属于我的列表还是 Emily 的列表。

移除功能

第一步是预处理我们的数据集,以便得到一个在所有列中都有数值的数据帧。因此,让我们首先删除所有与我们的模型不相关的特征,如 id、专辑、名称、URI、流行度和 track_number,并将目标(who 列)与我们的数据框架分开。我们可以通过构建函数 features_removal 轻松地做到这一点,该函数接收一个列表,其中包含我们希望作为参数删除的特性。

请注意,在删除它之后,我们仍然有一个分类特征(艺术家)。所以,我们必须在第二步处理这个问题。另外,重要的是要提到我们有两个稍微平衡的类(who 列),这两个类表示这首歌属于谁的列表。简而言之,我的列表中有 703 首歌曲,她的列表中有 691 首,这种数量上的平衡对我们的模型很重要。

标签编码器

第二个任务是将所有分类数据(艺术家姓名)转换成数字数据。为何如此?ML 算法只接受数字数据,因此,我们必须使用 LabelEncoder 类将每个艺术家的名字编码成一个特定的数字。编码过程如下所示。

#Set Labels
artist_label = enc.fit_transform(df_couple.artist)#Create column containing the labels
df_couple['labels_artists'] = artist_label#Remove colum artist (cathegorical data)
features_removal(['artist']) 

管道

现在我们的数据集几乎准备好了,我们可以建立我们的模型。你可能想知道:准备好了吗?!当我们处理一些最大似然算法时,我们必须记住,其中一些算法需要特定范围或结构的数据。例如,有时我们不得不将数据转换到一个更高的维度,以便找到分类的界限,如下图所示。为了实现这一点,我们使用了一种叫做内核技巧的技术,这种技术提供了一种高效且成本较低的方法来实现这种映射。此外,它使用不同的函数(核),其中最流行的是多项式,线性和径向基函数(RBF)。例如,最后一种方法需要以 0 为中心的特征,并且具有相同数量级的方差,这就是我们必须预处理数据的原因。

Kernel Trick

Radial Basis Function (RBF)

# Import libraries
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import Normalizer# Cross-validation and accuracy of the model
def accuracy(clf, data, target):
    results = cross_val_predict(clf, data ,target ,cv = 10)
    return metrics.accuracy_score(target,results)

管道:

# Pipelines 
pip_1 = Pipeline([('scaler',StandardScaler()),
                  ('clf', svm.SVC())
])pip_2 = Pipeline([('scaler',StandardScaler()),
                ('clf', svm.SVC(kernel = 'linear'))               
])

pip_3 = Pipeline([('scaler', StandardScaler()),
                ('clf', svm.SVC(kernel = 'poly'))                
 ])pip_4 = Pipeline([('min_max_scaler', MinMaxScaler()),
                 ('clf', svm.SVC())               
])pip_5 = Pipeline([('min_max_scaler', MinMaxScaler()),
                 ('clf', svm.SVC(kernel= 'linear'))               
])pip_6 = Pipeline([('min_max_scaler', MinMaxScaler()),
                  ('clf', svm.SVC(kernel='poly'))               
])pip_7 = Pipeline([('Normalize', Normalizer()),
                  ('clf', svm.SVC() )    
])pip_8 = Pipeline([('Normalize', Normalizer()),
                  ('clf', svm.SVC(kernel='linear') )    
])pip_9 = Pipeline([('Normalize', Normalizer()),
                  ('clf', svm.SVC(kernel='poly') )    
])

带有管道的列表:

# list with pipelines
pip_list= []
pip_list.append(('Scaler_rbf', pip_1))
pip_list.append(('Scaler_linear', pip_2))
pip_list.append(('Scaler_poly', pip_3))pip_list.append(('Min_max_scaler', pip_4))
pip_list.append(('Min_max_scaler_linear', pip_5))
pip_list.append(('Min_max_scaler_poly', pip_6))pip_list.append(('Normalizer', pip_7))
pip_list.append(('Normalizer_linear', pip_8))
pip_list.append(('Normalizer_poly', pip_9))# Function to build models
def model_accuracy(clf_models, data, target):

    results = []
    names = []

    for name, pip in clf_models:
        cross_val = cross_val_predict(pip, data, target, cv = 10)
        accuracy = metrics.accuracy_score(target, cross_val)               
        print(f'name: {name} - Accuracy : {accuracy:.4f}')

把酒装入大酒桶

具有 RBF 核和标准缩放器预处理的模型给了我们最高的精度,但是我们可以通过调整它的超参数来改进它。让我们使用 GridSearchCV 详尽地组合 C 和 Gamma 的不同值,并在我们的算法中测试它们。

# Import GridSearchCV
from sklearn.model_selection import GridSearchCV
# Values for parameter CC_list = [0.001 , 0.01, 0.1 , 1 , 10 , 100]#Values for parameter Gamma
Gamma_list = [0.001, 0.01 , 0.1, 1, 10, 100]
# Dictionary with lists of parameters
Grid_parameters = dict(clf__C = C_list, clf__gamma = Gamma_list)
Grid_parameters
# Grid object with pip_1, Grid_parameters, numbers of folders (cv) and accuracy (scoring) as parameters 
grid = GridSearchCV(pip_1,Grid_parameters,cv = 10, scoring = 'accuracy')
#Apply gridsearch to our data and target 
grid.fit(df_couple,target)

结论

在这篇文章中,我使用 Spotify API 分析了我未婚妻和我的音乐列表的音频特征。我没有检查我们的播放列表,而是使用了我们在日常生活中听得最多的 10 位艺术家的特征。基于此,我得出结论,我的列表比她的更多样化,令人惊讶的是,我的歌曲更有活力。另一个见解(我预料到了:])是艾米丽的歌曲更适合跳舞。为了补充分析,我还建立了一个机器学习模型(SVM ),来预测一首歌是否更有可能被她或我听到。该模型的准确率约为 74%,这是很好的(尽管还可以改进)。

参考资料:

Python 中的 Apache Spark 尼安德特人指南

原文:https://towardsdatascience.com/a-neanderthals-guide-to-apache-spark-in-python-9ef1f156d427?source=collection_archive---------0-----------------------

完全初学者的 PySpark 入门教程

你听说过 Apache Spark 吗

如果您和我一样,您听说了一种听起来很不错的技术,叫做 Spark,并且想要测试您的编码能力,看看您是否可以在您的数据科学工具包中添加另一种工具。希望你不要和我一样,因为在我的情况下,我很快碰到了安装墙,然后是术语墙,然后是概念墙,四个小时后,我还没有写出一行代码。所以,在花了几个小时在网上搜索,以及比我想提及的更多的所谓“初学者指南”之后,我决定写一篇“尼安德特人指南”,希望能让你免去一些我忍受的麻烦。

为什么要阅读本指南?

甚至在 Spark 上快速搜索学习资料也会让你沉浸在文档、在线课程(其中许多都不便宜)和其他资源中。根据我的经验,大多数人要么假设我对分布式计算了解太多(比如假设我知道分布式计算意味着什么),要么他们提供了高级或背景信息,但没有帮助我理解如何在 Spark 中实际实现任何东西。

考虑到这一点,在本指南中,我试图尽我所能解释一个概念,或者用一个解释把你引向其他地方,所有的目标都是让你尽可能快地编写 Spark 代码。因为我尽可能多地尝试与 Spark 相关的主题,所以如果您已经很好地掌握了某个特定的主题,请随意跳转。我还会试着给你留下一些链接,这些链接是我在钻研 Spark 时发现的有用资源。

这是指南的结构:我首先解释一些关键的术语和概念,这样我们就可以对其余的材料保持一致,同时也降低了进入 Spark 上的外部资源的门槛,您可以在这里和其他地方找到这些资源。接下来,我将使用 Google Colab 在您的机器上运行 Spark 的工作版本。最后,我将通过一个用例来演示 PySpark 是如何实际实现的,以及第一次通过示例问题是什么样子的。

你会学到什么

  • 足够的术语和概念,能够阅读其他 Spark 资源,而不会永远感到困惑
  • 让 PySpark 在您的计算机上运行的相对简单的方法
  • 如何开始使用 PySpark 进行数据探索
  • 在 PySpark 中构建和评估基本线性回归模型
  • 此处涵盖的大部分材料的有用外部资源

关键术语和概念

这里有一个各种术语和概念的列表,了解这些术语和概念将有助于您深入 Spark 的世界。

什么是火花

如果你谷歌过“什么是 Spark”,很有可能你遇到了下面的描述,或者类似的描述:“Spark 是一个通用的分布式数据处理引擎”。如果没有 Spark 的背景或者不熟悉这些术语的含义,这个定义是没有用的。让我们来分解一下:

  • 分布式数据/分布式计算 — Apache Spark 在一个与普通计算机科学略有不同的世界中运行。当数据集变得太大,或者新数据进入得太快时,单台计算机可能无法处理。这就是分布式计算的用武之地。这些任务可以在相互通信的多台计算机之间分配,以产生一个输出,而不是试图在一台计算机上处理一个巨大的数据集或运行计算量非常大的程序。这种技术有一些重要的好处,但是在多台计算机之间分配处理任务有其自身的挑战,并且不能以与正常处理相同的方式构建。当 Spark 说它与分布式数据有关时,这意味着它被设计来处理非常大的数据集,并在分布式计算系统上处理它们。

注意:在分布式计算系统中,每台单独的计算机被称为一个节点,所有这些计算机的集合被称为一个集群

(Comic from xkcd)

进一步阅读分布式计算简介 (8 分钟阅读)

  • 处理引擎/处理框架 —处理引擎,有时称为处理框架,负责执行数据处理任务(一个启发性的解释,我知道)。比较可能是理解这一点的最佳方式。Apache Hadoop 是一个开源软件平台,也处理“大数据”和分布式计算。Hadoop 有一个不同于 Spark 的处理引擎,叫做 MapReduce。MapReduce 有自己独特的方法来优化在多个节点上处理的任务,而 Spark 有不同的方法。Sparks 的优势之一是它是一个处理引擎,可以单独使用,也可以代替 Hadoop MapReduce 使用,充分利用 Hadoop 的其他特性。

(Image from Brad Anderson)

进一步阅读解释和比较的处理引擎(约 10 分钟阅读)

  • 通用—Spark 的主要优势之一是它的灵活性,以及它有多少应用领域。它支持 Scala、Python、Java、R 和 SQL。它有一个专用的 SQL 模块,能够实时处理流数据,并且它有一个机器学习库和基于它的图形计算引擎。所有这些原因促使 Spark 成为大数据领域最受欢迎的处理引擎之一。

Spark Functionality (from Databricks.com)

延伸阅读理解火花意义的 5 分钟指南(大概更像是~10 分钟阅读)

分布式计算术语

  • 分区数据(Partitioned Data)——当使用计算机集群时,你不能只是扔进一个普通的数据帧,然后期望它知道该做什么。因为处理任务将跨多个节点划分,所以数据也必须能够跨多个节点划分。分区数据是指经过优化能够在多个节点上处理的数据。

进一步阅读数据分区说明 (2 分钟阅读)

  • 容错 —简而言之,容错指的是分布式系统即使在出现故障时也能继续正常工作的能力。例如,故障可能是一个节点突然起火,或者只是节点之间的通信中断。Spark 中的容错围绕着 Spark 的 RDDs(后面会讨论)。基本上,Spark 中处理数据存储的方式允许 Spark 程序在发生故障的情况下正常运行。

进一步阅读火花容错能力如何 (~1 分钟阅读)

  • 懒惰评估 —懒惰评估,或懒惰计算,与代码如何编译有关。当一个不懒惰的编译器(称为严格求值)编译代码时,它会依次对遇到的每个表达式求值。另一方面,一个懒惰的编译器不会不断地计算表达式,而是等待,直到它真正被告知生成一个结果,然后一次执行所有的计算。因此,当它编译代码时,它会跟踪它最终必须评估的所有内容(在 Spark 中,这种评估日志可以说被称为谱系图),然后每当它被提示返回某些内容时,它都会根据其评估日志中的内容执行评估。这是有用的,因为它使程序更有效,因为编译器不必评估任何实际上没有使用的东西。

延伸阅读——什么是懒评 (4 分钟阅读)

火花术语

  • 关系数据库、数据框架、数据集,天哪!Spark rdd(弹性分布式数据集)是数据结构,是 Spark 的核心构建块。RDD 是一个不可变的、分区的记录集合,这意味着它可以保存值、元组或其他对象,这些记录被分区以便在分布式系统上处理,并且一旦创建了 RDD,就不可能对其进行更改。这基本上概括了它的缩写:由于它们的不变性和谱系图(稍后将讨论),它们是有弹性的,由于它们的分区,它们可以是分布式的,并且它们是数据集,因为它们保存数据。
    需要注意的一个关键点是,rdd没有模式,这意味着它们没有列结构。记录只是逐行记录,显示类似于列表。进入火花数据帧。不要与 Pandas 数据帧混淆,因为它们是不同的,Spark 数据帧具有 rdd 的所有特性,但也有一个模式。这将使它们成为我们开始使用 PySpark 的首选数据结构。
    Spark 有另一种数据结构, Spark 数据集。这些类似于 DataFrames,但是强类型的,意味着类型是在创建数据集时指定的,而不是从存储在其中的记录类型中推断出来的。这意味着 PySpark 中不使用数据集,因为 Python 是一种动态类型语言。对于这些解释的其余部分,我将参考 RDD,但要知道,对于 RDD 来说是正确的,对于数据帧来说也是正确的,数据帧只是被组织成一个列结构。

进一步阅读RDDs、数据帧、&数据集对比(约 5 分钟阅读)
进一步阅读Pandas v. Spark 数据帧 (4 分钟阅读)
进一步阅读有用的 RDD 文档(约 5 分钟阅读)

  • 变换 —变换是你在 Spark 中可以对 RDD 做的事情之一。它们是创建一个或多个新 rdd 的懒惰操作。值得注意的是,转换会创建新的rdd,因为,记住,rdd 是不可变的,所以一旦它们被创建,就不能以任何方式被更改。因此,本质上,转换将 RDD 作为输入,并根据被调用的转换对其执行一些功能,并输出一个或多个 rdd。回想一下关于惰性求值的部分,当编译器遇到每个转换时,它实际上并不构建任何新的 rdd,而是构建一个由这些转换产生的假设 rdd 链,这些转换只有在调用了动作后才会被求值。这个假设的链,或者“子”RDD,都逻辑地连接回原始的“父”RDD,就是谱系图。

进一步阅读有用的转型文档(约 2 分钟阅读)进一步阅读更深入的文档(5-10 分钟阅读;上半年的转变)

  • 动作 —动作是不产生 RDD 作为输出的任何 RDD 操作。一些常见操作的例子是对数据进行计数,或者查找最大值或最小值,或者返回 RDD 的第一个元素,等等。如前所述,动作提示编译器评估谱系图并返回动作指定的值。

延伸阅读有帮助的行动文档 (~1 分钟阅读)
延伸阅读更深入的文档 (~5 分钟阅读;下半年的行动)

  • 沿袭图 —沿袭图的大部分内容在转换和操作部分都有描述,但概括来说,沿袭图概括了所谓的“逻辑执行计划”。这意味着编译器从不依赖于任何其他 RDD 的最早的 rdd 开始,并遵循一个逻辑转换链,直到它以一个动作被调用的 RDD 结束。这个特性是 Spark 容错的主要驱动力。如果某个节点由于某种原因失败了,所有关于该节点应该做什么的信息都存储在谱系图中,可以在其他地方复制。

Visualization of example lineage graph; r00, r01 are parent RDDs, r20 is final RDD (from Jacek Laskowski )

延伸阅读——有用的血统文件(大约 2 分钟阅读)

  • Spark 应用和作业——当谈到像 Spark 这样的处理引擎如何在分布式系统上实际执行处理任务时,有很多细节。为了对某些 Spark 代码片段的作用有一个工作上的理解,下面是你需要知道的。在 Spark 中,当一个处理项目必须完成时,有一个“驱动”进程负责获取用户的代码并将其转换为一组多任务。还有“执行者”进程,每个进程在集群中的一个单独节点上运行,由驱动程序委派负责运行任务。为了运行任务,每个驱动程序进程都有一组它可以访问的执行器。Spark 应用是一个用户构建的程序,由一个驱动程序和该驱动程序的相关执行器组成。Spark job 是一个或一组由执行器进程执行的任务,由驱动程序指导。作业由 RDD 操作的调用触发。这种东西可能相当令人困惑,所以如果一开始不太明白,也不要担心,熟悉这些术语有助于以后在代码中实现它们。如果你想了解更多信息,我已经在这个主题上包含了额外的资源。

Visualization of Spark Architecture (from Spark API)

延伸阅读集群模式概述来自 Spark API (~3 分钟阅读)
延伸阅读stack overflow 上的有用回答 (~2 分钟阅读)
延伸阅读cloud era 上的 Spark 应用概述(~ 2 分钟阅读)

唷,你已经理解了所有的术语和概念!现在让我们开始实施吧!

安装 Spark

这个标题可能有点用词不当,因为严格来说,本指南不会向您展示如何安装 Apache Spark。安装 Spark 可能是一件痛苦的事情。首先,可以用多种语言编写 Spark 应用程序,每种语言的安装都略有不同。Spark 的底层 API 是用 Scala 编写的,但是 PySpark 是用 Python 实现的上层 API。对于数据科学应用程序,使用 PySpark 和 Python 比 Scala 更受推荐,因为它相对更容易实现。因此,本指南将向您展示如何在 Google Colab 中运行 PySpark,而不是安装它。

Google Colab

当我试图让 PySpark 在我的电脑上运行时,我不断收到关于从哪里下载它(例如,它可以从spark.apache.org或 pip installed 下载)、在什么地方运行它(它可以在 Jupyter 笔记本中运行或者在命令行中的本机 pyspark shell 中运行)的相互矛盾的指令,并且有许多模糊的 bash 命令散布在各处。作为一名数据分析师,我对非 pip 安装的 bash 命令的反应通常是厌恶和绝望的混合,所以我求助于 Google Colab。

Google Colab 是一个非常强大的交互式 python 笔记本(。ipynb)工具,它预装了许多数据科学库。关于它是什么以及如何运行它的更多信息,请查看这篇超级有用的文章 (8 分钟阅读)。

一旦你有了一个 Colab 笔记本,要让 Spark 运行,你必须运行下面的代码块(我知道这不是我的错,但我为它的丑陋道歉)。

!apt-get install openjdk-8-jdk-headless -qq > /dev/null
!wget -q [https://www-us.apache.org/dist/spark/spark-2.4.3/spark-2.4.3-bin-hadoop2.7.tgz](https://www-us.apache.org/dist/spark/spark-2.4.3/spark-2.4.3-bin-hadoop2.7.tgz)
!tar xf spark-2.4.3-bin-hadoop2.7.tgz
!pip install -q findspark
import os
os.environ["JAVA_HOME"] = "/usr/lib/jvm/java-8-openjdk-amd64"
os.environ["SPARK_HOME"] = "/content/spark-2.4.3-bin-hadoop2.7"
import findspark
findspark.init()

注意:当我第一次运行这段代码时,它没有运行。这是因为在我找到的代码编写完成后,已经发布了一个新版本的 Spark,而我试图访问一个找不到的旧版本的 Spark。因此,如果上面的代码不运行,仔细检查这个网站看看 Spark 的最新版本是什么,并把上面代码片段中你看到的“2.4.3”替换成任何最新版本。

基本上这段代码所做的就是下载正确版本的 Java (Spark 使用一些 Java)和 Spark,设置这些版本的路径,并在笔记本中初始化 Spark。

如果你想在除了 Colab 之外的另一个平台上使用 Spark,下面是我找到的最有用的指南(按有用性排序),希望其中一个能帮助你:

安装资源PySpark 和 Jupyter 入门
安装资源如何在自己的电脑上使用 PySpark
安装资源如何在本地安装 PySpark
安装资源如何入门 PySpark

PySpark 中的编码

因为我们想要处理列数据,所以我们将使用 Spark SQL 的一部分 DataFrames。

注意:为了避免可能的混淆,尽管我们将使用 Spark SQL,这些都不是 SQL 代码。当使用 Spark 数据帧时,您可以编写 SQL 查询,但您不必这样做。

配置火花会话

使用 Spark SQL 的入口点是一个名为SparkSession的对象。它启动一个 Spark 应用程序,该会话的所有代码都将在其上运行。

from pyspark.sql import SparkSession
spark = SparkSession.builder \
    .master("local[*]") \
    .appName("Learning_Spark") \
    .getOrCreate()

注意:这个上下文中的“\”字符称为延续字符,它只是一个有用的换行工具,使长代码行更具可读性。

  • .builder —提供对用于配置会话的构建器 API 的访问。
  • .master() —决定程序运行的位置;"local[*]"将其设置为在所有内核上本地运行,但是您可以使用"local[1]"在一个内核上运行。在这种情况下,我们的程序将在谷歌的服务器上运行。
  • .appName() —命名 Spark 应用程序的可选方法
  • .getOrCreate() —获取一个现有的SparkSession,如果没有,则创建一个新的

在构建SparkSession时,检查构建器 API 以获得更多选项。

加载数据

要在 Google Colab 上打开一个本地文件,您需要运行以下代码,该代码将提示您从您的计算机中选择一个文件:

from google.colab import files
files.upload()

在本指南中,我们将使用 Kaggle 的视频游戏销售数据集。在这里可以找到

现在使用.read.csv()函数将我们的数据加载到 Spark 数据帧中:(为了简洁起见,我缩短了文件名)

data = spark.read.csv('Video_Games_Sales.csv',inferSchema=True, header=True)

注意:这个函数专门用于将 CSV 文件读入 PySparkSQL 中的数据帧。它不适用于将数据加载到 RDD 中,并且不同的语言(除 Python 之外)具有不同的语法。在网上搜索帮助时要小心,因为许多资源并不假定 Spark SQL 或 Python。

数据探索

现在让我们开始了解如何更熟悉我们的数据!

我们可以做的第一件事是检查数据帧的形状。不像熊猫,这没有专用的方法,但是我们可以自己使用.count().columns()来检索信息。

data.count(), len(data.columns)>>> (16719, 16)

.count()方法返回 DataFrame 中的行数,而.columns返回列名列表。

注意:我们不必实际打印它们,因为 Colab 会自动显示每个单元格的最后输出。如果你想显示一个以上的输出,你必须打印它们(除非你使用这个解决方法,它非常好,在 Jupyter 笔记本上也能工作)

查看数据帧
要查看数据帧,使用.show()方法:

data.show(5)

Output from data.show(5)

如您所见,运行data.show(5)显示了数据帧的前 5 行,以及标题。不带参数调用.show()将返回前 20 条记录。

让我们使用。printSchema()方法(也可以使用.dtypes):

data.printSchema()

Output from data.printSchema()

此输出的一些要点是,Year_of_Release 和 User_Score 具有字符串类型,尽管它们是数字。它还告诉我们,每一列都允许空值,这在前 5 行中可以看到。

我们还可以用.select()方法有选择地选择我们想要显示的列。让我们只查看名称、平台、用户分数和用户计数:

data.select("Name","Platform","User_Score","User_Count") \
.show(15, truncate=False)

Output from data.select().show()

包含的truncate=False参数调整列的大小,以防止值被截断。

汇总统计数据/信息
我们可以使用.describe()方法来获取我们选择的列的汇总统计数据:

data.describe(["User_Score","User_Count"]).show()

Output from data.describe().show()

从这个输出中可以看出,User_Score 列中似乎有一个奇怪的“tbd”值。User_Score 的计数也高于 User_Count,但很难判断这是因为 User_Score 中实际上有更多的值,还是“tbd”值人为地提高了计数。稍后我们将学习如何过滤掉这些值。

我们可能还想获得一些关于平台栏中有哪些平台以及它们是如何分布的信息。我们可以为此使用一个groupBy(),并使用.orderBy()对其进行排序:

data.groupBy("Platform") \
.count() \
.orderBy("count", ascending=False) \
.show(10)

Output from data.groupBy().orderBy().show()

这里我们来看一下最常用的 10 个平台。我们可以说这个数据集很旧了,因为我在任何地方都没有看到 PS4🤔

过滤数据帧 让我们创建一个新的数据帧,其中 User_Score 和 User_Count 的值为空,使用.filter()方法过滤掉“待定”值:

condition1 = (data.User_Score.isNotNull()) | (data.User_Count.isNotNull())condition2 = data.User_Score != "tbd"data = data.filter(condition1).filter(condition2)

condition1对于 User_Score 或 User_Count 中没有空值的任何记录,返回 True。condition2对于 User_Score 中没有“tbd”的任何记录,返回 True。

我们可以通过重建先前的可视化来仔细检查我们的过滤是否有效

Reconstructed summary statistics and DataFrame with filtered out values

这是足够的数据探索,现在让我们建立一个模型!

在 PySpark 中构建模型

在 PySpark 中构建模型看起来和你可能习惯的有点不同,你会看到像变压器、参数这样的术语。本指南不会深入探讨这些术语的含义,但下面的链接会简要介绍它们的含义。

进一步阅读Spark 中的机器学习(约 5-10 分钟阅读)

设置
以线性回归为例,看看能否从 Year_of_Release、Global_Sales、Critic_Score、User_Count 预测 User_Score。

首先,让我们将所有的预测器重新编码为 Doubles(我发现这消除了后来一些非常棘手的错误)。

from pyspark.sql.types import DoubleTypedata2 = data2.withColumn("Year_of_Release", data2["Year_of_Release"].cast(DoubleType()))data2 = data2.withColumn("User_Score", data2["User_Score"].cast(DoubleType()))data2 = data2.withColumn("User_Count", data2["User_Count"].cast(DoubleType()))data2 = data2.withColumn("Critic_Score", data2["Critic_Score"].cast(DoubleType()))

我们使用方法withColumn(),它要么创建一个新列,要么替换一个已经存在的列。例如,Year_of_Release 列被替换为自身的一个版本,该版本被转换为 doubles。

下一步是将我们的数据转换成 PySpark 可以用来创建模型的形式。为此,我们使用一种叫做VectorAssembler的东西。

from pyspark.ml.feature import VectorAssemblerinputcols = ["Year_of_Release",  "Global_Sales", "Critic_Score", "User_Count"]assembler = VectorAssembler(inputCols= inputcols,
                            outputCol = "predictors")

在这里,我们已经描述了我们希望我们的模型使用什么特征作为预测器,以便VectorAssembler可以将这些列转换成一个列(名为“预测器”),其中包含我们希望预测的所有数据。

predictors = assembler.transform(data)predictors.columns

Output from VectorAssembler.transform().columns

VectorAssembler.transform()所做的是创建一个新的数据帧,在末尾有一个新的列,其中每一行都包含了我们在创建汇编程序时在inputCols参数中包含的所有特性的列表。

让我们的数据准备好在模型中使用的最后一步是收集我们刚刚制作的新预测列和 User_Score(我们的目标变量)在数据帧中。

model_data = predictors.select("predictors", "User_Score")model_data.show(5,truncate=False)

The final data we will use to build a model

接下来是将model_data拆分成一个训练和测试集:

train_data,test_data = model_data.randomSplit([0.8,0.2])

模特训练
现在来训练模特!

from pyspark.ml.regression import LinearRegressionlr = LinearRegression(
    featuresCol = 'predictors', 
    labelCol = 'User_Score')lrModel = lr.fit(train_data)pred = lrModel.evaluate(test_data)

pyspark.ml.regression导入LinearRegression后,我们构建一个回归器,并指定它应该寻找一个名为“预测”的列作为模型的特征,一个名为“User_Score”的列作为模型的标签。接下来我们用.fit()训练它,最后用.evaluate()产生预测。

我们可以用下面的代码访问模型的参数

lrModel.coefficients
>>>
[-0.07872176891379576,-0.0350439561719371,0.06376305861102288,-0.0002156086537632538]lrModel.intercept
>>> 160.7985254457876

我们还可以查看我们的模型做出的最终预测:

pred.predictions.show(5)

Model predictions

名为“pred”的对象是一个linear regression summary对象,因此要检索带有预测的数据帧,我们称之为.predictions.show()

模型评估

from pyspark.ml.evaluation import RegressionEvaluatoreval = RegressionEvaluator(
    labelCol="User_Score", 
    predictionCol="prediction", 
    metricName="rmse")

让我们为模型计算一些统计数据:

rmse = eval.evaluate(pred.predictions)mse = eval.evaluate(pred.predictions, {eval.metricName: "mse"})mae = eval.evaluate(pred.predictions, {eval.metricName: "mae"})r2 = eval.evaluate(pred.predictions, {eval.metricName: "r2"})

它返回

rmse
>>> 1.125mse
>>> 1.266mae
>>> 0.843r2
>>> 0.386

由此我们可以理解,我们的模型倾向于偏离实际 User_Score 大约 1.125 个评分点(根据 rmse)。的 r 值告诉我们,我们模型中的预测值能够解释 User_Score 中总可变性的 40%以下。这只是一个初步的观察,我建议您使用模型参数和特性进行更多的实践!

延伸阅读— 线性回归的详细代码示例 (~20+分钟完成整件事)
延伸阅读— 使用 SQL 的逻辑回归的详细代码示例 (~10 分钟)
延伸阅读— 线性回归、决策树和梯度推进树回归的示例 (6 分钟阅读)

就您可以在 PySpark 中进行的建模而言,这只是冰山一角,但是我希望本指南已经为您提供了足够的知识,让您能够进入大数据的大门!

结论

哇哦。如果你能坚持到最后,那就恭喜你。您接触了大量新概念,从分布式计算和 Spark 的术语,到在 PySpark 中实现数据探索和数据建模技术。我希望这份指南能成为你继续使用 Spark 的资源!

本文使用的所有代码都可以在 GitHub 这里找到。

艺术风格的神经算法:一种现代创作形式

原文:https://towardsdatascience.com/a-neural-algorithm-of-artistic-style-a-modern-form-of-creation-d39a6ac7e715?source=collection_archive---------10-----------------------

关于使用简单的机器学习算法创作专业外观的艺术品,你需要知道的一切

Machu picchu depicted in the style of starry night.

自从我们这个物种诞生以来,人类就一直通过艺术来传达思想。而且理由很充分;艺术是一种强有力的表现主义形式,是创造力的独特表现。因此,视觉作品及其创作者在社会中受到高度重视。

近年来,计算能力的提高已经允许机器开始模仿人类行为。由于艺术的重要性,毫不奇怪,研究人员已经开始开发算法,努力产生看不见的创造性内容。这既有争议,又令人着迷。在这篇文章中,我将专注于这场创造性革命的技术组成部分,而不是伦理辩论。

艺术风格的神经算法(N.A.A.S .)主要由 Leon A. Gatys 发明,是我迄今为止见过的最有趣、但最容易理解的人工艺术品之一。

Artwork creating using N.A.A.S.

目录:

  • 美国国家航空航天局简介。
  • 理解卷积神经网络
  • 虚拟 G.G .网络
  • 内容表示和损失
  • 风格表征与缺失
  • N.A.A.S 算法

艺术风格的 Gatys 神经算法介绍

N.A.A.S .使用两个图像来创建输出:内容图像和样式图像。正如它们的标签所暗示的,样式图像的样式被编织到内容图像的内容中。这是通过一种巧妙的技术实现的,这种技术允许计算机使用卷积神经网络(conv 网或 CNN)来区分图片的内容和风格。将输出图像(最初是一组随机的像素)与指定的内容和样式进行比较,并逐步调整,直到它在数学上类似于所需的结果。

Content (left) and style (right) combined to create an output image.

Output image

更详细地说,上面提到的风格和内容的比较是使用专门用于该算法的成本函数来完成的。通过改变优化图像的像素信息来最小化该函数。像素值是该技术的参数,这意味着它们的值将被改变以最小化 N.A.A.S .成本函数。如果你不明白什么是参数或损失函数,我强烈建议在继续之前浏览一下我的关于线性回归的文章,以获得对机器学习过程的介绍。

这并不是说你应该理解在引擎盖下发生了什么。重要的是要有基本的东西。

了解卷积神经网络

鉴于卷积神经网络是整个 N.A.A.S .的基础概念,对它们的作用有一个清晰的概念是很重要的。如果你已经知道 CNN,那太好了。继续下一部分。

Conv 网是一种人工神经网络,它利用一些特殊的技术,使它们特别擅长于将图像分解成它们的基本内容。这个过程是分步骤进行的,每一步都是网络中的一个新层。一层简单的像一个文件柜放数据;它组织信息。层 x 由已经经历了 x 数学操作的输入数据的表示组成,在这种情况下是卷积。这些独特的计算集合构成了每个神经网络,并将数据从一层移动到另一层。一层中包含的每一位信息都存储在所谓的神经元中。神经元应该被认为是存储在每个虚拟橱柜中的文件,因为它们包含关于输入图像内容的信息。储存在神经元中的信息被称为激活或输出。激活是标量值。

CNN 就是这样储存信息的。现在让我们直接进入尘垢,看看图像剖析网络内部发生了什么。对于 conv 网,总共有三种用于分解图片的变换:卷积、池化和激活函数。

我们将从最重要的突变开始,卷积。卷积基本上是在图像上移动的一系列滤波器。这些过滤器是矩阵,通常是形成方形棱柱的三维数值集合。这些结构的高度和宽度通常是 3 或 5。滤镜的深度将与图像的通道数相匹配。三个颜色通道(RBG)意味着深度为三。

当滤镜在图像中移动时,滤镜中的每个值都会乘以当前“位于其上”的像素值。这些乘积相加产生一个标量输出,存储在神经元中。一个神经元的持有量对人类来说可能没有多大意义,但这些信息对计算机来说是有价值的。然后,滤波器以用户指定的增量在图像周围移动(增量的大小称为步长)。一旦滤波器已经通过了图像中的每个位置,并且已经创建了充满输出值的整个矩阵,就用另一个滤波器重复该过程。

A simplified example of the relationship between an input image and its features map (above convolved feature in pink). The values of the filter are in small red font and the bounds of the filter itself in yellow. The filter would, in reality, be moved left to right across the image, at many horizontal positions.

过滤器的输出表示图像上的给定区域与过滤器正在搜索的内容相匹配的程度。较大的值意味着区域和所需特征之间的高度相关性。

来自卷积的所述输出被存储在所谓的特征图中。这听起来很复杂,但它只是过滤过程中产生的所有值的矩阵。要注意的关于特征地图的一个重要特性是它们被组织成在空间上与图像相关。这意味着查看图像左上角的滤波器的输出值也将在特征映射矩阵的左上角。

由于滤镜提供标量输出并在图像中移动,单个滤镜最终会产生二维输出。在图像上使用的每一个新的过滤器都会给特征图添加一个通道,使其成为一个三维矩阵。

注意:通道是特征图的二维层,从深度上看是一个横截面。

上面描述的只是一个卷积。大多数神经网络由许多层卷积组成。你怎么问?

这就像在特征图上运行另一组过滤器一样简单,可以创建一个新的特征图。在这种情况下,过滤器将具有与它们正在分析的地图相同的深度。除此之外,该过程与上面描述的过程相同。

滑动、乘法、求和、冲洗和重复。

如果你想知道这些神奇的过滤器是从哪里诞生的,你提出了一个非常有效的问题。每个过滤器中的每个数字称为一个参数。这意味着它是网络通过反向传播随着时间的推移而学习的。如果你不知道什么是 back prop,不要烦恼。只需知道 conv 网的机器学习方面是计算机逐步调整其过滤器,直到它们搜索并表示有意义的信息。

Above are two two-dimensional filters: one to pick up on horizontal lines, the other for vertical lines. Although these exact filters are unlikely to be seen in a real learning environment, they are good for exemplary purposes. Consider why each filter contains the values they do. Recall, multiply each value with a pixel value and sum the products. Higher output == high correlation to desired feature.

这在理论上很好,但让我们来看看这在实践中是如何使用的。

假设我们试图建立一个网络来直观地理解汽车,然后对汽车进行分类。一个 conv 网将被用于构建的理解方面。它将分解图像的信息,这样密集的神经网络可以很容易地将图像分类为“汽车”或“非汽车”。

在训练过程的开始,当我们开始将车辆图像输入年轻网络时,它将使用包含随机值的过滤器。随着时间的推移,网络开始学习,它会开发一套独特的过滤器来识别汽车。在网络的第一层,由于 conv 网的学习方式,过滤器可能会搜索非常基本的结构,如垂直线或水平线。随着时间的推移,通过网络层次结构的进展将意味着所呈现的数据的复杂性的进展。在较高层,网络可能会学习如何看到形状,在最后一层附近,过滤器可能会搜索镜子、窗户或轮胎。

不要忘记,只有第一套过滤器是直接看着输入图像的像素信息。除此之外,过滤器还会查看之前的图层,并分析其中的数据。

注意:神经网络中的一层是一系列神经元,每个神经元保存一个值。当我描述池层或卷积层时,它指的是执行特定任务的网络部分(无论是池、卷积还是其他)。卷积层是接受值并执行卷积以 创建 特征图的层,而不是由特征图的 组成的层

在继续之前,我必须强调的最后一件事:到目前为止,从这一部分学到的最重要的东西是,卷积网络的层代表输入图像的 内容

这就是卷积的情况。让我们看看卷积网络的其他两个部分,接下来是池层。

一个池层是一个相对简单的概念。其目的是缩小特征地图的尺寸。可以在任何卷积层之前执行汇集过程。使用池有两个原因,第一个原因是减少网络中的计算量,从而提高网络速度。第二个原因,我劝你不要担心(但仍然应该承认),是通过最小化数据的维数来防止过度拟合,从而降低数据分布的复杂性。用人类的话说,这使得网络在更多样化的数据集上表现得更好。

出于本文的目的,将只解释 max pooling 层。还有其他类型的池,但最大池是最常见的。

在给定输入的每个通道上,max pooling 四处移动,查看指定大小(通常为 2x2 正方形)的部分。它取该区域中的最大值,即最活跃的神经元,然后通过丢弃该区域中的所有其他值来改变特征图。它也保持了神经元的空间表现。

这个过程有助于丢弃大量无意义的信息,只保留最有价值的内容。

唉,激活功能。这是几乎每个神经网络的主要部分。它将非线性引入到网络中,使网络能够学习几乎任何可能的分布。

激活函数通过使它们通过期望的函数来改变特征图中的每个值(正如它们的名字所暗示的)。通常的做法是在每个卷积层之后执行激活变更。

卷积神经网络使用校正线性单元(ReLU)或泄漏 ReLU 激活函数表现最佳。

ReLU

ReLU 将每个负值接地为零。这是合乎逻辑的,因为负像素值是没有意义的。

Leaky ReLU can be seen above in pink.

ReLU 变化(泄漏或参数)的目的是在反向传播过程中允许梯度流动。换句话说,泄漏 ReLU 帮助网络更稳定地学习其参数。

这是 conv 网的三个部分!这里有几个简单网络架构的例子:

卷积-> ReLU ->池->卷积-> ReLU ->池

或者

卷积-> ReLU ->卷积-> ReLU ->池->卷积-> ReLU ->卷积-> ReLU ->卷积-> ReLU->池

最后,现在所有的部分都就位了,让我们检查一个适当的网络的可视化。

这是上面分解成几个阶段的图表:

阶段 1:在输入图像上使用 6 个大小为 5×5×1 的过滤器,产生大小为 28×28×6 的特征图(第 1 层)。

注:数据的宽度和高度会发生变化,这是因为图像边缘的一些像素无法卷积,因为过滤器没有编程来解决图像周边出现的像素缺失问题。

阶段 2:执行最大池化,将地图缩小到 14x14x6 的大小(第 2 层)。

阶段 3: 16 个大小为 5x5x6 的滤波器(每个包含 6 个通道)在层 2 上卷积,产生大小为 10x10x16 的特征图(层 3)。

阶段 4:在第 3 层上执行最大池化,将特征地图缩小到 5x5x16 的大小(第 4 层)。

阶段 5:这个网络的最后一部分与神经类型转移无关。在第 4 层之后,特征图被输入到一系列完全连接的层中,这些层对图像进行分类。同样,这与手头的概念无关,但可能会引起一些人的兴趣。

就是这样!你很好地理解了卷积神经网络的含义!让我们继续你来的目的:艺术风格的神经算法。

VGG 16 网

神经风格研究论文推荐使用一个预先训练好的,非常有能力的 CNN,叫做 VGG 16。VGG 16 包括一个分类部分,但只有它的卷积部分用于 N.A.A.S .网络的架构如下:

注意:在列出每一个卷积后,应用 ReLU 激活功能。网络中的所有过滤器都是 3×3 大小。网络中的池大小为 2x2。

卷积块 1:

Conv1_1: 64 个滤波器,每个深度为 3。

Conv1_2: 64 个滤波器,每个深度为 64。

最大池 1

卷积块 2:

Conv2_1: 128 个滤波器,每个深度为 64。

Conv2_2: 128 个滤波器,每个深度为 128。

最大池 2

卷积块 3:

Conv3_1: 256 个滤波器,每个深度为 128。

Conv3_2: 256 个滤波器,每个深度为 256。

Conv3_3: 256 个滤波器,每个深度为 256。

Conv3_4: 256 个滤波器,每个深度为 256。

最大池 3

卷积块 4:

Conv4_1: 512 个滤波器,每个深度为 256。

Conv4_2: 512 个滤波器,每个深度为 512。

Conv4_3: 512 个滤波器,每个深度为 512。

Conv4_4: 512 个滤波器,每个深度为 512。

最大池 4

卷积块 5:

Conv5_1: 512 个滤波器,每个深度为 512。

Conv5_2: 512 个滤波器,每个深度为 512。

Conv5_3: 512 个滤波器,每个深度为 512。

Conv5_4: 512 个滤波器,每个深度为 512。

最大池 5

VGG Network, including FC layers

如您所见,VGG 16 网络的架构相当复杂。这不是一个可以在日常笔记本电脑上训练的网络。相反,先前获得的过滤器重量可以从网上下载。这优化了我们的结果,节省了大量的时间。

内容表示和损失

现在我们进入算法的核心部分!

Gatys 提交的研究论文的第一部分描述了一种将内容图像的内容转移到优化图像的方法。这是通过数学上表示两个图像内容之间的差异并最小化所述表示来实现的。既然已经建立了对 conv 网的理解,成本函数的这一部分就相对直接了。

当我们将一幅图像传入 conv 网络时,它的内容由整个网络中的神经元来表示。注意,我说的是内容,而不是像素值。猫脸照片的内容与所有其他猫脸图像的内容非常相似。尽管猫的颜色或面部结构略有变化,conv 网仍然可以理解它在看一只猫。这是一个重要的细节,因为它允许内容以数字形式保留,尽管图像的样式被改变了。

也就是说,为了表示优化图像的所需内容,我们在将内容图像传递给 VGG 层(具体来说是 conv4_2 层,在执行 ReLU 之后)后,使用该层的值。

至于它的数学原理:

对于熟悉均方误差成本函数的人来说,这看起来应该非常相似。这个表达式说明了以下内容:

关于内容图像 p 和优化图像 x,在 conv 网的层 l 处生成的内容损失是层 l 处 p 和 x 的每个内容表示或激活之间的平均方差

这里,F 表示 conv 网的层 l 处的优化图像的表示。F(i,j)是来自层 l 的 F 的单个神经元。P 和 P(i,j)表示层 l 的内容图像表示及其激活。因此,对于 I 和 j 的每个值对,将激活 F(i,j)和 P(i,j)之间的平方差加到一个运行和中。这个过程完成后,用总和除以求和中的总迭代次数(等于 F 或 P 中的神经元数)。再除以 2。

让我们从逻辑上来思考这个问题。整个风格转换过程的目标是最小化 N.A.A.S .成本函数,内容损失占该函数的一半。为了最小化损失,必须改变优化图像,使得其内容表示 F 类似于内容图像的表示 p。这将把 p 的内容转移到 x 上,保留指定图像的所有重要细节。

就这样,一半的神经类型转移。不算太糟吧?

风格表现与缺失

接下来,我们进入 N.A.A.S .更具创造性的部分:风格表现。所提出的区分风格和内容的方法是使用 gram 矩阵来计算特征之间的相关性。看看这是什么意思,好吗?

为了计算 gram 矩阵,我们采用ℓ层的内容表示,并将数据转换成二维矩阵。矩阵的每一行都是分析图层ℓ-1 的过滤器的完整输出。因为每个滤波器都在寻找特定的特征,所以也可以说矩阵中的每一行都是输入图像上不同位置的给定特征的表示。

现在,这些值已经被适当地构造,可以使用下面的等式来计算矩阵:

Gram matrix computation

该等式明确地说明了 gram 矩阵的元素(I,j)等于来自内容矩阵中两个不同行的元素的乘积之和。

为了对其进行分解,第 I 行的元素 1 乘以第 j 行的元素 1。元素 2 乘以元素 2,依此类推,直到元素 k。最后,将这些乘积求和以产生 gram 矩阵的单个元素。

因此,为了完整地计算 gram 矩阵,需要对矩阵中行的每个组合进行计算。

这是论文中最难住我的部分。简单的矩阵乘法如何表现一幅图像的风格?

请记住,矩阵的每一行都是一个展开的特征地图,包含关于特征存在的空间信息。通过将元素相乘,我们检查这些元素在图像中的位置是否重叠。对图像中的每一个位置和每一对可能的特征进行这种处理。然后进行求和,丢弃所有信息的空间相关性。

而这种元素之间的重叠或关联,不管它们在哪里,正是风格。蓝色圆圈与水平影线重叠的频率是多少?在整个图像中,小点与螺旋线交叉吗?这些特征以错综复杂、不易察觉的方式交织在一起,最终形成了一幅图像的风格。

这就是风格的表现。

现在,MSE 损失再次被使用。

MSE Loss for style

这里,我们迭代优化图像(G)的 gram 矩阵和样式图像(A)的 gram 矩阵。我们对这两个矩阵的所有元素的平方差求和。这里,N 表示层 l 中的特征图的数量,M 表示这 N 个特征图中的元素的数量。然后,对于层 l 的最终风格损失,将该总和缩放 4 倍 N * M

Gatys 的论文指出,在比较多层图像的风格时,可以获得最佳结果。因此,总风格损失为:

Complete style loss

其中 w(l)表示层 l 的损耗权重,E(l)是层 l 的损耗。

Style of starry night, as it is represented by gram matrices using activations in layers 1–5 (1 far left, 5 far right) of VGG.

由于算法的目标是最小化成本函数,优化图像的风格将慢慢地改变以类似于风格图像的风格。这将增加它们的 gram 矩阵的相似性,最终降低成本。

风格!这就是全部了!

艺术风格的神经算法

你看过所有的部分。让我们把它们放在一本宜家说明书中。

首先要做的是指定一个样式图像和一个内容图像。为计算机提供了这些图像的路径。然后创建与内容图像大小相同的随机值张量。这是优化图像。其中的随机值是这个算法的参数。它们将随着时间的推移被计算机改变,成为输出图像。

Content image (left) and style image (right)

Random noise image for optimization

损失函数或优化目标设置为使用 VGG 图层 conv4_2 的制图表达的内容损失加上使用 VGG 图层 conv1_1、conv2_1、conv3_1、conv4_1 和 conv5_1 的制图表达的样式损失。发现由 Gatys 提出的这些层产生最好的结果。

超参数α和β用于调整输出内容和风格之间的平衡。

The complete N.A.A.S. cost function

现在,机器学习魔法开始发挥作用。鉴于你们中的一些人可能并不精通优化算法,并且这个主题不是在一篇短文中就能讲授的,我将保持这一部分的简洁。优化图像通过 VGG 网络反向传播,以获得其相对于成本函数的梯度。使用最小化算法(在这种情况下是 L-BFGS),随机噪声张量的值被改变以降低成本函数的输出。慢慢地,噪声变成了样式和内容图像的融合。

然后使用 Gatys 提出的另一种技术将结果放大到更高的分辨率。这个概念尽管简单,但超出了本文的范围。它也没有风格转换算法本身有趣(在我看来)。

Fruits of the algorithm’s labor

仅此而已。一件不可思议的艺术品由机器学习诞生。这真是一个惊人的过程。

随着更多的神经艺术算法被开发出来,创造过程将会进一步加速和改善。在不久的将来,我将看到由机器创造的独一无二的作品,这让我非常兴奋。

感谢阅读!出发前:

  • 查看 GitHub 上的代码
  • 查看这份文件了解更多关于CNN
  • 请随时在 Linkedn 上与我联系

一位新数据科学家对文化、进步和技术的思考

原文:https://towardsdatascience.com/a-new-data-scientists-reflections-on-culture-progress-technology-70054782880f?source=collection_archive---------24-----------------------

以及学习一项新技能可以。融合(内在、外在)动机

我第一次接触数据科学和机器学习

2018 年春天,加州伯班克又是一个阳光明媚的日子,我走向传奇娱乐公司的办公室,这是一家电影、电视和数字媒体的金融家和制作人,早在 2005 年就开始发行蝙蝠侠前传,这是我第一次在应用分析集团开始梦想中的演出。回到 NYU,我看到了一个关于创始人托马斯·图尔的案例研究,他努力将先进的数据分析纳入决策,以选择哪些电影创意值得花费数百万美元,以及如何以具有成本效益的方式将其推向市场。我从未想过有一天我会成为其中的一员。我知道我将向该公司的生产商和营销人员提供的见解来自波士顿定量分析师、工程师和研究人员的辛勤工作和敏锐思维,但我对计算机编程、高级统计学或产生的有价值数据的绝对范围知之甚少,这些数据可以为一家经常在创造性直觉上承担巨大财务风险的公司打开机会。

我只是很高兴能在那里,并成为制作惊人内容的一部分,但我对我们团队能力的迷恋让我意识到我只接触到了冰山一角。我不得不不断学习。2018 年秋天,我决定参加一个在线课程,看看数据科学是不是我想更认真地追求的东西。确实是。几周前,我离开了传奇公司,此后一直在西雅图熨斗学校的数据科学沉浸式训练营进行全日制学习,从今天起,我在这里给你写信。

动机:内在和外在

接受放弃一份好工作去接受更多教育的风险,给了我超越过去思考未来的自由。哪怕只是短暂的一瞬间,我的支持系统和好运给了我特权,让我抛开支付账单的思维模式,让我更深入地思考是什么在内在和外在激励着我。我希望利用这个平台来交流我对自己的结论的简化版本,以及我对这个世界的思考,在训练营结束后,我将带着一个新的工具箱重新加入这个世界。明确地说,这篇文章是非技术性的、探索性的头脑风暴,是动机、业务、文化和我对数据科学的热情的交汇。

我能够将我目前的主要动机简化为四个主要方面,以下没有特别的顺序。通过一点自我反省,我意识到在我知道数据科学需要什么之前,这些驱动力与我的选择相关,我希望每一个都以一种重要的方式坚持下去。

坦率地说,我热衷于用我的能力来推动艺术事业。我知道我想对人们和世界产生积极的影响。我喜欢旅行,我想继续旅行。我想最终拥有一个家。这些因素背后的为什么可能会导致一场私人的、令人兴奋的、可能是无休止的对话(我很高兴与任何感兴趣的人进行这种对话)。目前,我将坚持尝试理解这些动机如何与更严峻的现实相联系,以及为什么我认为数据科学将提供一个伟大的工具包来实现这些愿望。我的问题总是比答案多,但是当我思考一些与我的人生轨迹直接或间接相关的不同话题时,我邀请你们所有人加入对话。

友敌:创造力和技术

“每个人都生活在两个领域:内在和外在。内在是艺术、文学、道德和宗教中表达的精神目的的领域。外在是我们赖以生存的设备、技术、机制和工具的综合体。”

—马丁·路德·金

我对艺术、创意文化和创意经济的迷恋为我提供了借口,让我可以考虑更多有趣的想法,参观更多有趣的地方,结识更多有趣的人。我相信电影、音乐、绘画、语言和其他形式的个人表达对人类进步的历史有着比看起来更独特的重要性,我很久以前就决定要利用我的能力来扶持我认为伟大的艺术家和思想家。经济学并不总是支持艺术家,但我确实认为技术有潜力使创造性的职业建设民主化。

随着 YouTube、Spotify 和网飞等降低优质创意产品进入门槛并引导向大众受众交付的组织的崛起,以及 Etsy、Patreon 和众筹平台 Kickstarter 和 Indiegogo 等组织最近的努力,一个创意能力和独立资源与财务状况更明确相关的世界正在我们眼前形成。超级设备正在降低规模化生产的成本,获奖的电影正在用智能手机创作(Tangerine(2015)——IMDb)。互联网让寻找愿意为优秀内容付费的观众变得更加容易。区块链有可能淘汰利润分享中介(区块链&媒体——麻省理工斯隆评论)。好莱坞人才机构现在将分析视为了解消费者偏好的核心战略( Parrot Analytics signs CAA )。在这种情况下,越来越多花在消费创意上的钱直接流入了艺术家的口袋,这是显而易见的。

“苦苦挣扎的艺术家”的概念不会在一夜之间被消除,但更多资源较少的人有更大的机会让这个概念停止。对新媒体内容的文化意义有明确或隐含承诺、依赖或简单开放的关键组织将需要数据科学家来帮助指导他们在未来无数职能领域的决策。不管你的想法相似还是不同,让我们继续对话。我很想听听你对科技赋能创意的愿景,以及你对创意经济发展方向的看法。

文化&令人上瘾的科技产业

“我们沉迷于我们的电子邮件、Instagram 赞和脸书订阅;我们沉迷于电视节目和 YouTube 视频;我们每年工作时间更长,平均每天花三个小时使用智能手机。我们中的一半人宁愿遭受骨折,也不愿手机坏掉,千禧一代的孩子花在屏幕前的时间太多了,他们很难与真实、活生生的人互动。”

——亚当·奥尔特的不可抗拒的关于成瘾技术的兴起**

财务义务和道德行为是否相互排斥?大型科技公司复杂的、充满法律术语的服务协议条款对于数据隐私来说足够透明吗?技术进步将继续要求自我监管,至少当华盛顿特区的老家伙们(即参议员哈奇)仍在向马克·扎克伯格提问时,他想知道他如何维持用户不为服务付费的商业模式。如果你想知道,他们刊登广告。扎克的回应是对这个话题的深思熟虑的阐述:“参议员,我们做广告。

我们使用的大多数设备和应用程序都是为了最大化我们的参与度,在许多情况下,吸引我们的自由支配支出。思想领袖警告说,我们已经接近危险的领域。作为一名用户,我当然对我警告的行为类型感到内疚。作为一名未来的数据科学家,我相信大数据赋予了追求利润的实体足够的不受监管的权力,以保证关于道德数据收集和利用的诚实对话。对于一个用例显然可以接受而另一个用例显然不可以的行业,很难在沙地上画出一条硬线。作为数据收集者,我们必须自己决定我们的底线在哪里。我很想了解其他以数据为中心的企业家和高管是如何承担这一责任的。与此同时,作为数据科学家和消费者,让我们保持自我意识,继续自我监管。

我们对彼此和自然世界的责任

“我们需要的转变要求我们承认,每个人都是发展的参与者……所有利益攸关方,无论大小,都应该找到发挥作用和做出贡献的地方。”

联合国常务副秘书长阿米纳·默罕默德

我总是想用我的技能和环境去帮助别人,尤其是那些存在于更麻烦的现实中的人。我把我的大部分幸福归功于两位慈爱的父母,他们设法离开了英国利物浦附近的一个工业小镇,这个小镇一直出现在英国的垃圾镇系列丛书中,并且显然激起了保罗·西蒙写回家的路。参观完我自己之后,我的父母努力在加州建立新生活的原因就很明显了。我很幸运。伴随着这种幸运而来的是向前回报的愿望,我相信数据科学家的工具包为我提供了一个提升影响力的真正机会。

我经常将联合国的可持续发展目标作为一个指南,让我自己适应世界上最紧迫的需求,以及那些拥有大数据技能的人参与进来的机会。贫困、饥饿、清洁水和基本人权是迫使我与越来越多的使命驱动型机构、非政府组织、以可持续方式推动影响和利润的私营企业以及像 DataKind 这样的数据科学家武装的组织一起为可持续发展目标采取认真行动的问题,这些组织将拥有我现在正在学习的技能的人与正确的项目联系起来。在打造充实的生活和事业时,这不再是我觉得可以推迟的事情。也就是说,让世界变得更好的愿望在博客上发表比付诸行动更容易。我们应该如何优先考虑人类最迫切的需求?我们如何正确衡量影响?权力必须如何激励参与?我很想听到更多的想法,关于你们如何让自己对那些处境更差的人负责,同时保持自己在商业和技术领域的其他目标和参与不受影响。

A visual summary of the United Nations’ Sustainable Development Goals — a quick reference to orient us to the world’s most pressing needs

气候变化:科学与权威

“气候系统变暖的科学证据是明确的。”

政府间气候变化专门委员会(联合国)&美国宇航局

科学家们达成了一致,但政策制定者们却不同意。一些坦率的话有助于推动与你的疯狂叔叔和充满政治色彩的朋友进行无益的辩论:全球气温正在上升。海洋正在变暖,酸性变得更强。海平面在上升,冰盖在缩小,冰川在退缩,积雪在融化。极端天气事件正在增加。2018 年底,由组成美国全球变化研究计划的 13 个联邦机构(包括 EPA、NASA、五角大楼和美国国务院等)发布的一份国会授权报告得出结论,人类活动正在导致气候变化,如果没有精心策划的干预,我们将对我们的星球造成不可挽回的损害。似乎有一个无穷无尽的与世界末日相关的气候事实在我们的指尖上流行地分享在社交媒体上,尽管我不是气候科学家,但我相信辩论的时间已经过去了。迅速行动至关重要。数据科学可以有所帮助。我会继续学习。

总的来说,科学是我们用来衡量和理解我们在地球上的位置的最受审查和信任的研究领域。我相信人文学科,虽然我喜欢认为健康的怀疑主义通常是有根据的,但我们还没有发现比科学更令人信服的循证权威来源。也就是说,我们正处于一个脆弱的时刻,甚至科学家也被指责不诚实。脱离科学的政治行动和言论有多危险?科学发现何时成为事实,为什么否认科学变得如此容易?我们如何从这种深刻的制度不信任中走出来?大数据有什么帮助?我的问题比答案多,但我欢迎你在一个尊重的、持续的对话中提出你的想法。

千禧年理想主义、学生债务危机和房屋所有权

我承认,像许多千禧一代一样,我不想把我的激情和价值观与我的工作分开。当然,就像我心目中的英雄一样,我想让这个世界变得更好,并从所有明显的缺陷中拯救出来。不管我对朋友引用老子多少次,我都有很多欲望,其中有些是无可否认的物质欲望。我想自己赚钱,然后把钱花在旅游上,最后,如果运气好的话,花在房地产上。也就是说,我一边喝着一杯 3 美元的咖啡,一边在 MacBook 上写下这些话。我从未应征入伍,也没有目睹过战争。我在一个安全的社区的安全的家里长大。我的父母确保我没有错过一顿饭。我有幸梦想远大,却经常失败。理想主义并不总是能付清账单,但这两者并不相互排斥。我既是雄心勃勃的,又是幸运的,还心怀感激。

尽管我有很多幸运,但和我的同龄人一样,我也背负着一堆荒谬的学生债务。我认识的 30 岁以下的人中,唯一有希望在支付大学教育费用的同时攒钱买房的人是一些朋友,他们牺牲了很多,大学毕业后在华尔街找了份工作,然后多年来每周无眠地工作 80 多个小时。平均来说,在我们的膝盖变坏和头发变白之前,我这个年龄组的人并不期望能合理地拥有自己的房子。旧的美国梦可能已经变成了一种白日梦。

也就是说,我对技术带来的教育民主化持乐观态度。我非常支持在线课程和学位。EdX、训练营式的专业教育(向熨斗学校大声喊出来,T3)以及奖励协作型教育者,他们喜欢优质内容和资源的真正生产者(例如教师工资教师)。希望这些创新能挽回一些希望。学科多样性和包容性必须仍然是社会教育进步的核心。教育是一项人权,我们应该在所有年级庆祝学科和观点的多样性。最重要的是,在追求公共和私营部门的教育相关创新时,必须优先考虑教育工作者和学生,而不是让他们成为牺牲品。

我决定学习数据科学的最后一个原因是最重要的和最不吸引人的。这是一项需要的技能,目前需求大于供给(希望能持续到 7 月份!)有机会成为一家高速发展的公司不可或缺的一员,可能会让我在消除学生债务的道路上更加安心,并让我实现旅行并最终拥有一个家的雄心壮志。对于那些深陷学生债务的人,你有什么解救自己的策略?老师和学生们——教育或教育技术的哪些趋势给了你们希望,如果有的话?对于那些战胜学生债务的人来说,什么策略对你有效?在这个过程中你牺牲了什么?

数据科学:杂食者的美工刀

似乎没有大量的职业可以满足我似乎无穷无尽的兴趣和问题,但我对数据科学技能的追求让我可以果断地犹豫不决。除了技术技能之外,最优秀的数据科学家似乎还有一些不同的性格特征,可以在各种各样的领域开展强大而有趣的项目。

数据科学家必须提出正确的问题。组织需要哪些知识来对其战略道路充满信心,了解他们的客户,优化成本和流程,并找到新的机会?数据科学家必须将深厚的技术技能与领域专业知识和背景相结合,以便从原始数据中提取真正的价值。也就是说,数据科学家似乎可以在许多行业和研究领域变得有价值,那些已经在该领域建立的科学家似乎已经鼓励了一种灵活、对多面手和专家都友好的文化。

数据科学家也要有激情。最好的解决方案只有在有决心的情况下才会到来,我相信当内在动力比咖啡更能激发你每天的外在努力时,生活会更有趣。如果没有强有力的指导和一些完美主义者的品质,数据科学家可能会倾向于停止寻找最佳的前进方式。然而,高效的数据科学家知道什么时候停止分析,什么时候开始部署见解、制定建议、解决问题和激励行动。

数据科学家一定很好奇。解决问题通常有许多独特的方法,优秀的数据科学家必须经常考虑替代方案。我发现问自己是否有比我目前使用的方法更好的方法来获取、清理和合并数据是有益的。它需要过程和创造力才能有效。它要求你锻炼你的分析左脑来完成任务和项目,然后,走出去,闻一闻玫瑰花香,并创造性地思考下一步你可以在哪里有效地运用你的努力。这项工作同样受益于自主、不受干扰的方法,以及富有成效的关键团队对话。以驾驶员-导航员的形式和同事一起编程对生产率有复合效应。它是为好奇和开放的头脑而建造的,因为这个领域本身总是随着新的创新被采用而变化。一名优秀的数据科学家必须了解最新的新闻故事和进展,并跟上时代的步伐。

与无休止的好奇心相关的一个重要认识是,并非所有问题都能用数据解决。决策的某些方面必须依靠人类的直觉。数据应该用于提供决策信息和改进预测,但有些时候它不应该被视为永恒的真理。它容易出错,也有其局限性。它既是一门科学,也是一门艺术。有时模型是陈旧的。有时商业环境会改变。有时,预测会成为偏差、方差或数据社区最不喜欢的变量的牺牲品:“不可约误差”的概念。对预测的信心永远不会达到 100%,没有人能真正知道未来。我们只能通过充分利用已知的东西来改进我们在未知中航行的方式。

徐:未知

比追求新知识更强有力的是认识到总会有很多我们不知道的东西。我正在学习接受这一点,不管是在工作中,还是在生活中,尽管如此,我还是要前进。我不知道我的梦想、我的计划和我的技能是否会一起形成数据科学、快乐、成功和满足感的完美鸡尾酒,但我知道我从来没有后悔过一个经过计算的、教育第一的风险,它让我超出了我的舒适区。我有过的最有冲击力的经历,就是驻扎在这样的环境里。我学得越多,就越意识到,越来越确定,有太多的东西我不知道,还有太多的东西有待发现。也就是说,让我们一起保持好奇。让我们一起不断学习和提高。

感谢阅读,

亚历克斯

请继续关注我的文章,随着我对数据科学的深入研究,我将发表越来越多的技术文章。我鼓励大家喜欢、评论、分享或直接给我发消息,告诉我你们对这里提出的想法的想法,或者对我今后应该研究的有趣主题的建议。

【www.linkedin.com/in/alexshropshire

medium.com/@as6140

github.com/as6140

卡纳达语-MNIST 语:ML 镇的一个新的手写数字数据集

原文:https://towardsdatascience.com/a-new-handwritten-digits-dataset-in-ml-town-kannada-mnist-69df0f2d1456?source=collection_archive---------28-----------------------

Class-wise mean images of the 10 handwritten digits in the Kannada MNIST dataset

TLDR:

我在传播 2 个数据集:
卡纳达语-MNIST 数据集 : 28X 28 灰度图像:60k 火车| 10k 测试
挖掘 -MNIST: 28X 28 灰度图像:10240(1024 X10){见下图}

Putting the ‘Dig’ in Dig-MNIST

卡纳达-MNIST 数据集旨在替代 MNIST 数据集🙏虽然在卡纳达语中是数字符号。
此外,我正在传播一个由同一种语言(主要由该语言的非母语用户使用)的 10k 个手写数字组成的额外数据集,名为 Dig-MNIST,可用作额外的测试集。

资源列表:

开源代码库👉:https://github.com/vinayprabhu/Kannada_MNIST
卡格尔👉:https://www.kaggle.com/higgstachyon/kannada-mnist
ArXiv👉https://arxiv.org/pdf/1908.01242.pdf

如果你在同行评议的论文中使用卡纳达语-MNIST 语,我们会很感激地将其称为:

维奈·乌代·帕布。"卡纳达语-MNIST:一个新的卡纳达语手写数字数据集."arXiv 预印本 arXiv:1908.01242 (2019)..

Bibtex 条目:

@article{prabhu2019kannada,
  title={Kannada-MNIST: A new handwritten digits dataset for the Kannada language},
  author={Prabhu, Vinay Uday},
  journal={arXiv preprint arXiv:1908.01242},
  year={2019}
}

简介:

卡纳达语是印度卡纳塔克邦的官方和行政语言,全世界有近 6000 万人使用。此外,根据《印度宪法》第 344(1)条和第 351 条,卡纳达语是印度 22 种预定语言之一。这种语言是用官方的卡纳达语书写的,这是梵语家族的一种 abugida,可以追溯到卡丹巴语(公元 325-550 年)。

Kannada stone inscriptions: Source: https://karnatakaitihasaacademy.org/karnataka-epigraphy/inscriptions/

不同的字形被用来代表语言中的数字 0-9,这与当今世界上流行的现代印度-阿拉伯数字截然不同。与其他一些古老的数字系统不同,这些数字在卡纳塔克邦的日常事务中被广泛使用,正如在下面的图片中捕捉到的车辆牌照上这些符号的流行所证明的:

A vehicle license plate with Kannada numeral glyphs

MNIST-ized renderings of the variations of the glyphs across the modern Kannada fonts

此图捕捉了以下现代字体中字形变化的 MNIST 化渲染: Kedage、Malige-i、Malige-n、Malige-b、Kedage-n、Malige-t、Kedage-t、Kedage-i、Lohit-Kannada、Sampige 和 Hubballi-Regular

数据集管理:

卡纳达语-MNIST 语:

在印度的班加罗尔招募了 65 名志愿者,他们是这门语言的母语使用者,也是数字文字的日常使用者。每个志愿者填写一张包含 32 × 40 网格的 A3 纸。这就产生了一张填好的 A3 纸,每张纸上有 128 个数字,我们假设这些数字足够大,可以捕捉大多数志愿者内部字形的自然变化。使用 Konica Accurio-Press-C6085 扫描仪以每英寸 600 点的分辨率扫描如此收集的所有纸张,产生 65 个 4963 × 3509 png 图像。

Volunteers helping curate the Kannada-MNIST dataset

迪格-MNIST:

招募了 8 名年龄在 20 至 40 岁之间的志愿者来生成 32 × 40 格的卡纳达数字(类似于 2.1),所有人都用黑色墨水 Z-Grip 系列| Zebra Pen 在商业 Mead Cambridge Quad 书写板上书写,8–1/2 " x 11 ",四格,白色,80 张/本。然后,我们使用具有以下设置的 Dell-s 3845 cdn 扫描仪扫描纸张:输出颜色:灰度原稿类型:文本变亮/变暗:变暗+3 尺寸:自动检测用于书写数字的纸张的缩小尺寸(US-letter vis-a-vis A3)导致扫描更小(。tif)图像,所有图像都大约为 1600×2000。

与 MNIST 的比较:

1:平均像素强度分布:

2:形态属性:

Code source: https://github.com/dccastro/Morpho-MNIST

3:主成分分析:

4: UMAP 可视化:

一些分类基准:

我使用了一个标准的 MNIST-CNN 架构来获得一些基本的准确性基准(见下图)

The CNN architecture used for the benchmarks

(a)卡纳达-MNIST 列车上的培训和卡纳达-MNIST 测试上的测试

(b)在卡纳达-MNIST 列车上进行培训,在迪格-MNIST 进行测试

对机器学习社区的公开挑战

我们对机器学习社区提出了以下公开挑战。

  1. 为了描述灾难性遗忘的本质,一个预先在 MNIST 接受训练的美国有线电视新闻网记者被用卡纳达-MNIST 语重新训练。这是特别有趣的,因为观察到卡纳达语-MNIST 语中 3 和 7 的印刷字形与 MNIST 语中 2 的字形有着不可思议的相似。
  2. 获得一个使用字体(如[1])生成的纯合成数据训练的模型,并扩充以实现卡纳达-MNIST 和迪格-MNIST 数据集的高精度。
  3. 跨不同的语言/文字,尤其是印度文字,重复本文中描述的过程。
  4. 关于迪格-MNIST 数据集,我们看到一些志愿者已经越过了网格的边界,因此一些图像要么只有字形/笔画的部分切片,要么具有可以争论它们可能潜在地属于两个不同类别中的任何一个的外观。关于这些图像,值得看看我们是否可以设计一个分类器,将成比例的 softmax 质量分配给候选类。
  5. 我们共享原始扫描图像的主要原因是为了促进对自动分割算法的研究,该算法将解析来自网格的单个数字图像,这可能反过来导致数据集升级版本中的图像质量更高。
  6. 通过在卡纳达-MNIST 数据集上进行训练和在迪格-MNIST 数据集上进行测试,无需借助图像预处理,即可达到 MNIST 级别的精度。

[1] Prabhu、Vinay Uday、Sanghyun Han、Dian Ang Yap、Mihail Douhaniaris、Preethi Seshadri 和 John Whaley。"字体-2-手写:通用数字分类的种子扩充训练框架." arXiv 预印本 arXiv:1905.08633 (2019)。https://arxiv.org/abs/1905.08633

沙普利价值观的新视角——介绍沙普利和 SHAP

原文:https://towardsdatascience.com/a-new-perspective-on-shapley-values-an-intro-to-shapley-and-shap-6f1c70161e8d?source=collection_archive---------22-----------------------

Shapley 值和 SHAP python 库的简明介绍

这个帖子是关于什么的?

这篇文章是关于解释 Shapley 值统计模型的两个系列文章中的第一篇。我能想到你可能想读它的两个主要原因(除了,你知道,为了好玩):

  1. 了解沙普利价值观和 SHAP python 库。这就是这篇文章的主旨。它所提供的解释远非详尽无遗,也没有包含任何无法从其他在线来源收集到的内容,但它仍然可以作为这个主题的一个很好的快速介绍或额外阅读。
  2. 在阅读下一篇关于天真的 Shapley 价值观的文章之前,作为介绍或快速复习。下一个帖子是我对机器学习中 Shapley 值这一主题的一个新颖贡献。你可能已经熟悉了 SHAP 和沙普利,只是浏览了一下这篇文章,以确保我们有共同之处,或者你可能是来澄清下一篇文章中的一些困惑。

什么是沙普利价值观?

网上有很多解释这个话题的资料,所以我在这里的解释会很简短。我特别推荐 Christoph Molnar 的可解释机器学习这一章做更详细的解释。我还发现,盯着数学公式(在下面或在维基百科上)直到我得到它,给了我对这个概念最好的直觉。

Shapley 值是博弈论中的一个概念,描述了如何在玩家之间分配玩家联盟产生的总回报。它的定义非常简单:任何玩家的贡献是在不包含该玩家的所有可能的玩家联盟中,将该玩家加入联盟所导致的预测变化的期望值。看起来是这样的:

我们来看一个例子:假设我们有一个团队需要执行一项任务。团队中的每个人都有 20%的额外成功机会,但是一个团队成员 A 有一个特殊的工具,可以保证 90%的成功机会,只要团队中至少有一个额外的成员。如果我们今天的团队由三个成员组成, ABC——他们有 90%的成功机会——那么每个人对这个机会的贡献是多少?

让我们为团队成员 C 计算一下,使用不包含他们的所有可能组合:

应用该公式(Shapley 公式中总和的第一项对于{}和{A,B}是 1/3,对于{A}和{B}是 1/6),我们得到团队成员 C 的 Shapley 值 21.66% 。团队成员 B 自然会有相同的值,而对 A 重复这个过程,我们会得到 46.66% 。沙普利价值观的一个至关重要的特点是,玩家的贡献总是累加到最后的回报:21.66%+21.66%+46.66% = 90%

机器学习中的 Shapley 值

如果你将收益转化为预测并将玩家转化为特征,那么这个框架与机器学习的相关性是显而易见的。但是计算模型特征的 Shapley 值并不完全简单,因为模型中的特征与团队中的工人行为方式不同。具体来说,预测模型通常无法处理其输入特征之一被简单删除的情况,从而测试其输出如何变化。相反,Shapley 值的 ML 实现,特别是 SHAP 方法,将缺失特征解释为值未知的特征,并通过对该特征的可能值进行平均来模拟这种未知状态(本系列的下一篇文章提出了一种不同的方法,并将其与 SHAP 方法进行了比较)。

得出 Shapley 值的主要问题是计算的复杂性 —具体来说,它们需要 2ᴹ(其中 m 是特征的数量)来计算。无论你的 GPU 有多强大,指数级的复杂性几乎总是一个障碍(想想当你的特征是 20x20 图像像素时,这需要多少步骤)。在理论文献中,这个问题最常见的解决方法是采样方法——而不是遍历所有可能的特征联盟,使用它们的子样本来估计 Shapley 值(如果您对此感兴趣,请参见例如 Castro 等人 2009 年Castro 等人 2017 年Benati 等人 2019 年)。

进入 SHAP python 库

SHAP 图书馆是数据科学家工具箱中最新的强大成员。它提供了三个主要的“解释器”类——tree explainer、DeepExplainer 和 KernelExplainer。前两个分别专门用于计算基于树的模型和神经网络的 Shapley 值,并基于这些模型的架构实现优化。内核解释器是一个“盲”方法,适用于任何模型。我在下面解释这些类,但是对于它们如何工作的更深入的解释,我推荐这一章

内核解释器

KernelExplainer 计算 Shapley 值的方法可以总结为以下两点:

  1. 不是遍历所有 2 个 ᴹ 可能的特征排列,而是采样一个小的子集。默认样本数为n 样本= 2M+2048* 。例如,如果我们有 20 个特征,KernelExplainer 将对 2088/2 ⁰或大约 0.2%的可能联盟进行采样。联盟不是完全随机选择的;相反,在 Shapley 公式中具有较高权重的那些将首先被选择(因此,0 或 M-1 个特征的组合,其最能提供关于添加另一个特征的效果的信息,将首先被包括在内)。
  2. “缺失特征”是通过将模型在自举样本上的预测与取自数据集中其他条目的这些特征的值进行平均来模拟的。该“背景”数据集没有默认大小,但算法建议 100 个样本。这意味着,对于每个采样的特征联盟,该算法将生成 100 个预测,每个预测基于自举样本,并对它们进行平均。请注意,KernelExplainer 的结果仅基于不同输入的模型输出,这意味着它将适用于任何类型的函数,而无需对其做任何进一步的假设。

(1)的意义在于 Shapley 值基本上是用随机抽样估计的。相应地,增加 nsamples (或背景数据集的大小)会导致运行时间增加(或多或少呈线性)和估计方差减少(这意味着当您多次运行 explainer 时,Shapley 值会彼此更加相似,并与预期值更加相似)。这很容易通过用不同的 nsamples 值运行内核解释器来演示:

Based on the Census Income database included in the SHAP library. There are 12 features in the dataset and so nsamples is effectively capped at 212=4096. Estimation variance and mean run time are computed across 30 iterations of running the SHAP explainer on a K-Nearest-Neighbors classification model.

(2)的重要性——通过用替代“背景”数据替换“缺失”特征的值来处理“缺失”特征——更加复杂:

  • 首先,也是最简单的,它是 Shapley 值估计的方差的附加来源,因为结果至少在某种程度上取决于背景数据集的选择。
  • 第二,它对特征独立性进行了假设:例如,如果特征 x1x2 在我们的训练数据中高度相关,则用来自背景数据集中的随机值替换 x1 的值忽略了这种依赖性,并且基于不可能出现在训练集中的{ x1x2 }实例生成预测,使得 SHAP 值估计不太可靠。
  • 最后,它表示对特征对预测的贡献的解释,不是它们如何影响预测模型本身,而是如果这些特征的值未知,它们如何影响已经训练好的模型的结果。这是另一个提醒你的好机会,这一切都指向下一篇文章,在这篇文章中,我们将探索不同的解释。

树解释器

TreeExplainer 是一个为基于树的模型(Random Forest,XGBoost,LightGBM 等)计算 SHAP 值的类。).与 KernelExplainer 相比:

  1. 精确:它不是通过随机采样来模拟缺失特征,而是通过简单地忽略依赖于缺失特征的决策路径来利用树形结构。因此,TreeExplainer 的输出是确定性的,不会随背景数据集而变化。
  2. 高效:所有组合不是在每个可能的特征组合(或其子集)上迭代,而是同时通过树推送,使用更复杂的算法来跟踪每个组合的结果——将所有可能组合的复杂度从 O(TL2) 降低到多项式 O(TLD ) (其中 M 是特征的数量,t

使用 TreeExplainer 我们收获了什么?首先,我们去除了所有基于采样的估计方差,因为我们不需要使用背景数据集或选择特征联盟的子集。其次,我们的结果不再由于特性之间的依赖性而偏斜,因为这些特性包含在树结构中(尽管在某些情况下,我们可能不得不放弃前面的两个好处)。第三,我们的运行时间是显著地,在某些情况下使得相当快慢得不可接受。最后,请注意,这两个解释者对特征贡献的解释与给定训练模型的预测没有区别,而与它们如何影响模型本身没有区别。

等等,DeepExplainer 呢?

DeepExplainer 是一个专门为神经网络模型计算 SHAP 值的类。我在这里不包括它的详细解释,因为我缺乏与其他解释者的实践经验,这使我能够保证我对他们的解释,并且这篇文章主要是下一篇文章的序言,在下一篇文章中,SHAP 解释者将与天真的 Shapley 值方法进行比较,当谈到解释神经网络时,这种比较在很大程度上是不相关的。

作为粗略的概述,对于神经网络模型,DeepExplainer 比 KernelExplainer 要快得多,但同样使用背景数据集和训练模型来估计 SHAP 值,因此可以得出关于计算的 Shapley 值的性质的类似结论-它们根据背景数据的选择而变化(尽管没有很大程度),并且在生成用于估计的引导样本时,它们可能不考虑特征之间的依赖性。

我如何用 SHAP 来解释我的模型?

哦,那真的很简单。只需导入 shap ,然后像这样做(例如为内核解释器):

然后使用 SHAP 图书馆的可视化功能查看结果——可以是单个样本的 SHAP 值,也可以是整个数据集。

明白了!下一步是什么?

所有这些只是为了让我们在沙普利价值观和 SHAP 解释者上保持同步。您可以在这里停下来,继续(或开始)在您自己的工作中使用这个伟大的工具。但是如果你想更深入一点,更好地理解这个主题以及你工具集中的另一个工具,请继续阅读下一篇文章****!

原载于 2019 年 11 月 28 日https://edden-gerber . github . io**

Shapley 值的新视角:天真的 Shapley 方法

原文:https://towardsdatascience.com/a-new-perspective-on-shapley-values-the-radical-shapley-method-6c2f4af7f922?source=collection_archive---------18-----------------------

Image adapted from shap.readthedocs.io

通过探索一个概念性的替代方案来更好地了解 SHAP。

** 编辑,2020 年 1 月:我把这里介绍的方法从不太直观的激进的 Shapley 改名为幼稚的 Shapley 。这在整篇文章中都有所改变,但是代码片段和 git 库可能仍然反映了旧的名称。**

你为什么要读这篇文章?

  • 了解沙普利值和 SHAP 工具。关于这些主题的大多数其他来源是基于现有主要来源的解释(例如,学术论文和 SHAP 文档)。这篇文章试图通过实证的方法来获得一些理解。
  • 了解计算 Shapley 值的另一种方法,在某些(有限的)情况下,这种方法可能比 SHAP 更可取(或者等待下一篇文章,以获得更广泛适用的想法)。

如果你不熟悉 Shaply values 或 SHAP ,或者想简单回顾一下 SHAP 的解释者是如何工作的,看看这篇文章

赶时间?我强调了关键句子来帮助你快速阅读。

更加冗长的介绍

当我在最近的一次黑客马拉松中使用 SHAP 图书馆来解释一个隔离森林模型的预测时,我对 Shapley 值的兴趣被激发了。我注意到,对于我们的模型,SHAP 计算似乎非常低效,在整个数据集上运行需要太长时间。事实上,时间太长了,以至于我想知道在这种情况下,Shapley 值的“蛮力”指数复杂方法是否是一个更好的选择。这让我编写了一个函数,使用一种对我来说似乎很直观的方法来计算 Shapley 值:不是通过对可能的值进行积分来模拟缺失的特征(如 SHAP 方法),而是可以在训练期间将它们从模型中完全删除。由于文献中缺乏现有的术语,我决定将这些称为朴素沙普利值,在某种意义上,它们仅基于数据集(加上一个模型类),而不是基于训练好的模型。

作为一名神经科学研究生,我学到的一件事是,如果你想理解——并信任——你的分析工具,你需要对它们进行仔细的实证研究,就好像它们是你真正的研究对象一样。阅读现有的文献很重要,亲自获得实践经验也很重要,但我发现真正的洞察力来自于不要认为工具的结果是理所当然的,而是要结合人为的边缘情况或其他方法来测试它。这篇文章的主旨是,通过与朴素的 Shapley 方法进行比较,更好地理解 SHAP 解释者的优势和局限性。

Shapley 函数的代码和本文中使用的例子可以在这里找到。

大纲(不太是 TL;博士)

在这篇文章中,我将尝试展示以下内容:

  • 通过为每个 2ᴹ特征子集(其中 M 是特征的数量)重新训练模型,可以为少量特征计算朴素沙普利值。
  • SHAP 图书馆的解释者和朴素的 Shapley 方法对 Shapley 值提供了两种不同的解释。前者最适合解释给定(已训练)模型的单个预测,后者更适合解释数据集和模型的特征重要性(例如,用某些参数初始化的随机森林,但不是已训练的随机森林)。
  • 在某些(有限的)情况下,朴素沙普利计算可以比 SHAP 方法更快。当以下所有情况都为真时,这些情况是广义的: a. 少量特征(< ~15), b. 使用不被高效的 SHAP 解释器支持的模型,以及 c. 大量样本(例如,整个数据集)需要 Shapley 值。

在以后的文章中,我希望讨论一个更实用的,多项式复杂的替代方法,用抽样来估计朴素的 Shapley 值。

那么什么是“幼稚”的沙普利价值观呢?

首先,什么是沙普利值?如果你有一个团队,每个人都对总收益做出贡献,但他们的贡献不一定是独立的(就像团队经理的贡献取决于也有做出贡献的工人),那么 Shapley 值将每个人对总收益的贡献量化为他们在所有可能的团队中的边际贡献的加权平均值(因此我们的团队经理的贡献可能是 0,没有额外的工人,100,至少有一个工人,等等。并且这是在团队的所有可能排列中的平均值)。用更专业的术语来说,Shapley 值反映了在不包括玩家的所有可能联盟中,将玩家加入联盟所产生的剩余收益的期望值。

在统计模型领域,Shapley 值量化了模型预测中的差异,这种差异是通过在模型中添加每个要素来驱动的。但是,由于此类模型通常无法处理不完整的输入,因此不可能简单地从数据集中移除要素来计算其边际贡献。因此,实现 Shapley 值的概念来解释预测模型是一些解释的问题。具体来说,

  • 在预测阶段,对于给定的样本,SHAP 的解释者将“添加一个特征”解释为具有特定的值,而其值是未知的。例如,“年龄=30”对预测个人收入水平的模型输出的边际贡献可以相对于平均预测收入水平来计算,当用其他可能的值替换数据集中的“年龄”时。另一方面,
  • 朴素的 Shapley 方法基于另一种直觉,即在训练过程中,衡量某个特性对模型的影响。因此,在我们的示例中,“年龄=30”的贡献是相对于模型最初完全没有年龄特征的情况而言的。

这两种解释都符合 Shapley 值的数学概念,但它们测量的东西略有不同。

计算朴素的 Shapley 值

计算朴素 Shapley 值的函数(此处代码)采用一个数据集和一个收益函数,计算每个可能的特征组合(或“玩家联盟”)的收益。然后使用标准的 Shapley 公式计算 Shapley 值:

φi is the Shapley value for feature i, S is a coalition of features, v(S) is the payoff for this coalition, and N is the total number of features. N{i} is all the possible feature coalitions not containing i. The first term within the sum corresponds to the fraction of times S appears within the possible feature permutations; intuitively, this gives the highest weight to the most informative contributions of a feature, i.e. when it is isolated or when it is added to a full set of features.

输出的格式与 SHAP 库解释器的格式相同,因此所有的 SHAP 绘图工具都可以用来可视化它。

收益函数可以是任何接受数据集并返回分数的函数(例如,我们的工人团队为任何团队构成产生的利润)。因此,它是一个通用函数,可用于任何类型的 Shapley 计算,但为了生成简单的 Shapley 值,它将始终是一个为数据集定型特定类型模型的函数,并为每一行返回一个预测。

例如:假设我们想要为 XGBoost 模型计算简单的 Shapley 值。我们将编写一个自定义的支付函数,它初始化一个 xgb 模型,训练它并返回每个样本的预测(或者可能只针对一个验证集)。Shapley 函数会将输入要素的每个可能组合输入到支付函数中,并使用结果输出来计算每个样本和要素的 Shapley 值(您很快就会看到一个活生生的例子)。

该算法的主要缺点是其计算复杂度 —它需要运行 2ᴹ次(其中 M 是特征的数量),每次都要重新训练模型。这种复杂性当然是需要 SHAP 图书馆的主要原因;另一方面,在某些有限的情况下,这可能是比使用 SHAP 内核解释器更快的选择。比较运行时间的问题将在本文的结尾讨论。

这和 SHAP 有什么不同,我们为什么要关心?

我将 Naive Shapley 方法的结果与 SHAP KernelExplainer 和 TreeExplainer 的结果进行了比较。我没有与 DeepExplainer 进行比较,因为神经网络模型很少具有使比较相关的少量输入变量。简而言之,朴素沙普利方法在概念上不同于所有的 SHAP 解释者,它代表了特征对模型本身的贡献,而不是对个体预测的贡献。同时,虽然在某些情况下,in 可能比 KernelExplainer 更有效,但它通常较慢(对于数量较少的功能来说不切实际)。再一次,如果你不确定 SHAP 的解释者在做什么,这篇文章可以帮助你。

天真的 Shapley 值与 TreeExplainer

TreeExplainer 是与 Naive Shapley 方法进行比较的一个很好的首选,因为与 KernelExplainer 不同,它们都是确定性的(不依赖于基于采样的估计),并且对特性之间的依赖关系不敏感(至少在 TreeExplainer 的默认实现中)。这使我们能够关注概念差异在处理缺失特征方面的影响,即通过重新训练模型与对特征值进行积分。

我们可以用一个简单的人为例子来证明这种差异的重要性。让我们生成一个 3 特征线性回归模型,其中一个特征 x1y 的强预测器,第二个特征 x2 与之强相关(因此对 y 的预测性稍差),第三个非预测器特征 x3 :

为了获得简单的 Shapley 值,我们需要首先定义支付函数,它简单地训练模型并返回它的预测(为了简单起见,我不包括任何训练-验证分割等。).

现在运行 Shapley 函数本身( reshape_shapley_output 只是重新排列原始输出,因为 compute_shapley_values 返回一个不采用特定支付格式的字典。在 github 上提供了功能输入和输出的说明。

为了获得 SHAP 值,我们将定义 XGB 回归模型,对其进行训练,并使用 TreeExplainer 计算 SHAP 值:

现在让我们看看 SHAP 值和天真的沙普利值是如何相互比较的。我们将使用 SHAP 图书馆的简洁的 summary_plot 可视化工具,该工具绘制每个特征的 Shapley 值的分布:

让我们来分解一下:

  • 使用 TreeExplainer,模型已经用所有 3 个特征进行了训练,因此 SHAP 值反映了这样一个事实,即 x1 在训练的模型中具有最高的影响,而 x2 具有小得多的作用,因为它大部分是冗余的。
  • 另一方面,使用朴素的 Shapley 方法,x2 对 y 的影响几乎与 x1 的影响一样大,因为在没有 x1 的情况下训练模型时, x2 的信息量几乎与一样多。
  • 与此同时,非预测性的 x3 使用朴素的 Shapley 方法被认为具有更高的影响——这仅仅是因为,特别是当我们没有进行训练/验证分割时,在没有更好的预测器的情况下,它会过度拟合数据。

现在让我们尝试一个真实世界的例子。我们将查看 SHAP 图书馆中包含的一个数据集的 Shapley 值——成人普查数据库,该数据库具有 12 个人口统计特征,用于预测个人的收入是否为> 5 万美元(load withshap . datasets . adult())。为了清晰和减少计算运行时间,我们将在我们的模型中只包括 12 个特征中的 6 个(年龄、每周小时数、教育、婚姻状况、资本收益和性别)。我们的模型将是一个 XGBoost 分类器。在这种情况下,TreeExplainer 的 SHAP 值和 Naive Shapley 值如何相互比较?散点图给我们一个快速的第一印象:

结果似乎是高度相关的,这应该已经给了我们一个提示,尽管他们的概念不同,这两种方法在结果上可能不会有太大的差异。现在用总结 _ 情节:

这里的结果看起来也很相似(尽管差异很大,以至于全局特征重要性的顺序有所改变)。但是让我们放大一下性别变量的 Shapley 值分布的差异:

这是怎么回事?

  • 天真的 Shapley 结果向我们展示了对所有可能的特征组合进行了平均,添加该变量将对该数据集(你好性别工资差距)的预测产生一致的影响。
  • TreeExplainer 的结果向我们展示了在我们的训练模型中,该变量对样本预测的影响较小且不太一致,很可能是因为它用于解释较小的残差方差,因为它传达的大部分信息是由其他更具预测性的特征提供的。

注意:实现我们自己的自定义 Shapley 函数的一个好处是,我们可以轻松地获得大量的中间结果,例如,我们计算的每个可能的特征组合在有或没有给定特征的情况下的利润率(其加权平均值是每个样本的 Shapley 值)。只是为了好玩,我从 compute_shapley_values 函数中提取了它,这样我们可以看看最终的 shapley 值是如何从这些单独的支付利润中产生的。这些是性别变量的收益边际分布,相对于它所添加的功能数量绘制:

我们可以看到模型中已经存在的特性越多,这个特性的边际影响就变得越小,越不明显。以 Education_Num 的利润率分布为例,无论有多少其他特征组成模型,它的贡献基本上保持不变,这表明它对模型的贡献很大程度上与它们无关:

那么,我们应该用哪种方法来解释我们的数据和模型中的性别变量的作用呢?我认为最好的表达方式是:

  • 朴素的 Shapley 值更好地代表了数据集中特征的全局影响,而
  • 给定我们现有的训练模型,SHAP 值可以更好地解释特定的预测。

在继续之前,还有两点需要注意:

实际注意事项:我并不是建议如果您关心数据集中的全局特征影响,就一定要使用朴素的 Shapley 方法,这主要是因为在大多数情况下,这在计算上是很难处理的(尽管在最后几节中可能会出现这种情况)。从我的例子中也可以明显看出,SHAP 解释者的结果通常没有太大的不同,因此不应该用于这个目的。我在这里的主要动机是更好地理解 SHAP 结果及其局限性。

技术提示:如果您熟悉 TreeExplainer,您可能知道,由于在二进制分类的情况下,树节点的权重保存的不是概率,而是对数奇数值(最后一步使用逻辑函数将其转换为概率),TreeExplainer 使用的默认优化方法提供了加起来等于这些未转换值(而不是最终概率)的 SHAP 值。简单地将逻辑函数应用于 SHAP 值本身是行不通的,因为转换值的总和!=总和的转换值。为了生成与概率输出直接对应的 SHAP 值,TreeExplainer 不得不牺牲一些效率,并使用类似于 KernelExplainer 的方法,通过用背景数据集替换来模拟缺失的要素,这自然是一种更慢、更不精确的方法。另一方面,为了用朴素的 Shapley 方法直接解释概率输出,我们需要做的就是选择支付函数的输出作为概率。由于使用朴素的 Shapley 方法,我们总是支付最大的计算成本,我们不妨使用一个支付函数,它给出了我们所希望的 Shapley 值来解释

天真的 Shapley 值与 KernelExplainer

KernelExplainer 是一种计算 SHAP 值的模型盲方法。简单总结一下,它的工作原理是:

  1. 仅对可能的特征排列的小子集进行采样。
  2. 对于每一个这样的排列,通过生成许多自举样本来模拟“缺失的特征”,其中这些特征的值被来自小的“背景数据集”的值所替换,并且平均这些样本的预测。

这意味着与 TreeExplainer 相比,KernelExplainer 是:

  1. 较慢-需要为数据集中的每个解释实例计算大量预测(因为缺失值是通过对要素的许多可能值进行平均来模拟的)。
  2. 不确定性 —估计 KernelExplainer 的 SHAP 值,方差由联合抽样方法和背景数据集选择引入。

当比较 KernelExplainer SHAP 值和天真的 Shapley 值时,这是怎么回事?让我们使用预测收入为> 50 万美元的相同 6 特征人口普查数据集作为测试案例。这一次,按照 SHAP 图书馆笔记本中的示例,我们将使用 KNN 模型进行预测,并使用 KernelExplainer 提供 Shapley 值,我们可以将其与朴素的 Shapley 值进行比较:

比较结果:

这两种方法产生不同但相关的结果。如果我们对每个样本的 Shapley 值进行排序和分级(从 1 到 6),则顺序平均会相差大约 0.75 级(例如,在大约 75%的样本中,两个相邻特征的顺序被交换)。让我们记住,我们不是在看精确值和它们的噪声估计之间的关系:相反,朴素沙普利值是一个事物的确定性度量,而核 SHAP 值是另一个(相关)事物的估计

我认为,这里要强调的最后一点是,尽管这两种方法之间存在差异,但结果总体上仍然非常相似,这告诉我们在许多情况下,这些方法可能可以互换使用,假设差异对我们来说并不重要。

天真的 Shapley 能比 KernelExplainer 快吗?

正如我们已经建立的,天真的 Shapely 方法需要重新训练模型并产生预测 2ᴹ时报。这使得当特性的数量不低时(比如说,超过 15–20)这是不切实际的。但是它能和 SHAP 解释者的少量特性相比吗?

需要指出的一点是优化的 SHAP 解释器总是比简单的 Shapley 方法更快,但是模型盲的 KernelExplainer 在解释大型数据集时会非常慢。为了更好地理解,让我们来看看 KernelExplainer 与简单的 Shapley 方法的运行时间:

粗体条目强调了每种方法的弱点。Naive Shapley 方法当然最容易受到特征数量增加的影响,并且还依赖于模型训练时间,而 KernelExplainer 不受这些因素的影响(尽管其预测随着特征数量的增加而变得更加多变)。KernelExplainer 在运行时间方面的缺点是,虽然它不需要花费时间来重新训练模型,但它会为每个解释的预测单独运行(而 Naive Shapley 会立即为所有预测运行),每次都必须为大约 200K 个样本( nsamples X num)生成预测。背景样本,默认分别为 2048+2M 和 100)。

Naive Shapley 方法可能比 KernelExplainer 执行速度更快的模型的一个很好的例子是隔离森林模型,这是一个流行的异常检测工具,尽管它是一个基于树的模型,但它不受 TreeExplainer 的支持,并且它的训练时间(与预测相比)相对较快。为了证明这一点,我使用来自 Kaggle 的信用卡欺诈检测数据集,一个大约 285K 的样本,30 个用于预测异常信用卡交易的特征数据集。在我们的演示中,让我们使用 100K 个样本,将 30 个特征减少到 15 个。在我的旧笔记本电脑上,我得到了以下大致的运行时间:

-训练模型 : 8 秒

  • 对所有 100K 样本进行预测 : 8 秒
  • 计算单个预测的 SHAP 值 : 18 秒(不出所料,这大约是计算约 200K 引导样本的预测所需的时间)

基于此,我们可以粗略估计计算整个数据集的 Shapley 值需要多长时间。内核解释器应该只需要 100,000 x 18 秒,或者大约 500 小时。朴素的 Shapley 函数将运行多达 2 ⁵*(15+13)秒,或者大约 150 小时(实际上,更好的估计可能是大约 50 小时,因为在算法的每次迭代中用于训练的自举数据集将具有 1 到 15 个特征,或者平均 7 到 8 个,使得训练通常更快)。这两种方法都很慢(尽管两者都可以从并行化中获益),但是这里重要的不是具体的例子,而是理解每种情况下计算时间的来源。总结一下:

  • 如果只需要解释一小部分“重要”的预测,KernelExplainer 应该足够快了。
  • 如果你需要解释一百万个预测,而你只有不到 10-15 个特征,简单的 Shapley 方法会快得多。

实际的妥协?用抽样估计朴素 Shapley 值

如果我们的模型仅受 KernelExplainer 支持,并且我们确实需要整个庞大数据集的 Shapley 值,但有太多的特征来计算天真的 Shapley 值,该怎么办?

那么,为什么不尝试使用联合抽样来估计天真的沙普利值呢?使用随机抽样来估计大量玩家的 Shapley 值(如 KernelExplainer 所做的那样)已经在文献中进行了彻底的讨论,并且改进的方法仍在开发中(例如参见 Castro 等人 2009 年Castro 等人 2017 年Benati 等人 2019 年)。我认为采样可以很好地与朴素的 Shapley 方法结合使用,也就是说,对模型训练的特征组合空间进行采样(因此不需要通过对自举样本求平均来模拟缺失的特征)。

去除算法中的指数分量将大大减少运行时间,并使该方法对于大量特征变得可行(以一些估计方差为代价),而保持重新训练方法仍将确保在计算大型数据集的 Shapley 值时运行时间较短。

在这一点上这只是一个理论上的想法,这个帖子足够长,无需在此展开。我很乐意听取你对这个想法的任何意见(也许你已经在别的地方遇到过了?),也希望在以后的帖子里展开讨论。

原载于 2019 年 12 月 8 日https://edden-gerber . github . io

看待甘斯的新方法

原文:https://towardsdatascience.com/a-new-way-to-look-at-gans-7c6b6e6e9737?source=collection_archive---------6-----------------------

鉴别器比你想象的更有用

介绍

生成式对抗网络是一种非常有趣的深度神经网络架构,能够生成新数据(通常是图像),这些数据类似于训练期间给出的数据(或者用数学术语来说,匹配相同的分布)。

在发现 gan 及其工作原理后,我立刻被吸引住了。在无人监督的情况下生成逼真的图像有一些特别的,也许是神奇的地方。GAN 研究中真正引起我注意的一个领域是图像到图像的翻译:将一幅图像转换为另一幅图像并保持某种对应的能力(例如将一匹马转换为斑马,或将一个苹果转换为橙子)。像介绍 CycleGAN(一种特殊的架构,使用两个 GAN 相互“帮助”执行图像到图像的翻译)的学术论文向我展示了一个强大而迷人的深度学习应用程序,我立即想尝试并实现自己。

Zebra to Horse translation by CycleGAN

通过这篇特别的文章,我很想深入研究 GANs,并提供一种新的方式来看待他们的目标:这可能对一些人来说是微不足道的,而对其他人来说可能是一个有趣的观点。我还将举例说明这种方法的一个有趣的应用,同时提供实用的技巧来帮助您实现它。我会假设你在深度学习方面有一些基础,并且已经知道生成性对抗网络背后的基本思想。

GANs:简介

让我们考虑一个简单的卷积 GAN 架构(DCGAN)。随机噪声向量是生成器的输入,由不同的顺序卷积层组成,生成最终图像。在训练的开始,这个图像将完全是随机噪声。这个“假”图像然后被送到鉴别器,鉴别器输出一个数字,通常在 0 到 1 之间,代表图像看起来“有多真实”。鉴别器还被馈送真实图像。告诉鉴别器接收到的图像是假的还是真的,允许它随着时间的推移越来越好地完成工作,同时也告诉生成器如何使假图像看起来更真实。

GAN Architecture

暹罗网络

在解释经典 GAN 架构的一些新修改之前,我们需要介绍一个称为暹罗网络的特殊网络。暹罗网络用于一次性学习:虽然在大多数情况下,图像分类器需要在大量的训练样本上进行训练,但一次性学习网络能够仅通过一个样本来理解特定对象的特征。这种网络对于实现面部识别算法非常有用,这种算法需要足够灵活,以便偶尔向可识别的面部添加新面孔。

Siamese Network

该架构相当简单:它由一个编码器组成,该编码器将图像的特征编码成一个长度为 VecLen 的向量。网络的名字,Siamese,来源于“并行”使用编码器的相同权重来计算两幅图像的潜在向量:如果图像属于同一类,那么这两个向量在潜在空间中应该是接近的,否则,如果它们属于不同的类,它们应该是远离的。这个最终结果是由于一个特殊的损失函数而获得的。虽然文献中存在这种网络的多种损耗函数(对比损耗、三重损耗和磁损耗),但这里我们首先考虑对比损耗(Hadsell 等人,06)。

这种损失是特别容易和直观的:在它们属于同一类(Y=0)的情况下,它最小化我们两个向量之间的平方距离 (Dw,考虑欧几里德距离),而如果它们属于不同类(Y=1),则最小化( max(0,Margin-SquaredDistance)) 。这最后一项允许网络在两个向量的平方距离低于裕度(我们任意选择的常数)的情况下将这两个向量推得彼此远离;否则,如果两个矢量足够远,损耗为零。

不太难吧?现在我们终于准备好把一些拼图拼在一起了。

暹罗甘

正如我们之前所述,生成性对抗网络可以被认为是一个生成器和一个鉴别器,它们一起工作,从特定的图像集合或域中生成真实的图像。发生器将随机噪声向量作为输入,并将其“解码”为图像,而鉴别器将图像作为输入,并输出与图像的逼真程度相关的分数。现在让我们尝试使用一个连体网络作为鉴别器。我们现在拥有的是一个解码器-编码器架构,它以一个向量作为输入,以一个向量作为输出。这种结构类似于自动编码器(编码器-解码器),但两个组件互换了。

Siamese GAN Architecture

这个网络怎么可能训练?

在训练识别人脸的暹罗网络的情况下,我们拥有的总类的数量就是我们的算法必须识别的不同人脸的数量。因此,在这种情况下,我们期望网络以这样一种方式组织潜在空间(网络的输出),即编码同一张脸的所有向量靠近在一起,而远离所有其他向量。

然而,在 GANs 的情况下,类的总数是 2:由生成器创建的假图像和真实图像。然后,我们新的鉴别器目标是安排暹罗网络的输出向量,例如真实图像被编码为彼此靠近,同时保持虚假图像远离它们。

另一方面,生成器试图最小化真实和虚假图像向量之间的距离,或者换句话说,希望真实和虚假编码为同一类。这个新的目标再现了与“传统”情况下非常相似的对抗行为,利用了不同种类的对抗损失函数。

既然我们已经理解了这个想法的基础,让我们试着对它进行迭代和改进。

在我们的损失函数中,我们考虑了向量之间的距离。但是距离到底是什么呢?在我们的例子中,我们评估了两个向量之间的距离,这两个向量可以在鉴别器输出的向量空间中一次又一次地移动。考虑到距离的“相对性”,我们可以进行更稳健的测量,计算从空间固定点的距离。暹罗网络的三重损失考虑到了这个问题,它评估了与中性点(锚点)的距离。

Triplet Loss

这里 d 代表平方欧几里德距离, a 是“锚”点(我们将认为它固定在空间中), n 是负点, p 是正点。

在我们的例子中,只需要处理两个类(最终目标是使一个类与另一个类不可区分),我们在训练之前选择空间中的一个固定点,并使用它作为我们的中性点。在我的测试中,我使用了原点(值全为零的向量)。

为了更好地理解我们的潜在空间,以及我们希望如何为我们的目标组织它,让我们把它形象化。请记住,我们是将我们的空间以等于 VecLen 的维数投影到 2D 平面上。

Initial Condition

在训练开始时,我们的图像 BG(z) (由生成器从噪声向量 z 生成的图像)由鉴别器在我们的向量空间中随机编码。

Vector Space during Training

在训练期间,鉴别器将 B 的向量推至更靠近固定点,同时试图将 G(z) 的编码保持在离该点任意距离(边距)处。另一方面,生成器希望 G(z) 向量更接近固定点,结果是更接近 B 向量。

最后,这里是暹罗甘的一些结果。

Random Flower samples

现在,为了真正理解为什么连体 GAN 与传统 GAN 极其相似,我们需要考虑一种边缘情况:如果连体鉴频器输出一维向量(V ecLen =1)会怎样?现在我们有了传统的 GAN 鉴别器输出单个值:如果这个标量接近一个固定的数(我们的 1 维点),假设 1,图像看起来是真实的,而在相反的情况下看起来是假的。这就相当于把分数保持在接近 1 为真,接近 0 为假。因此,损耗现在变成平方误差,典型的 LSGANs(最小平方 gan)。

所以,这没什么新鲜的。不完全是。将图像编码为潜在向量有时会非常有用。先说一个实际的例子。

图像到图像的翻译

最近的一篇论文介绍了 TraVeLGAN ,一种解决不成对图像到图像翻译问题的新方法。与其他方法(例如 CycleGAN)不同,TraVeLGAN 不依赖图像之间的逐像素差异(它不使用任何循环一致性约束),导致图像在完全不同的域之间转换,几乎没有任何共同点。为了实现这一点,传统的发生器-鉴别器架构与独立的连体网络一起使用。

TraVeLGAN Architecture

假设我们必须将域 A 的图像转换为属于域 B 的图像。我们称由生成器翻译的图像为 G(A)

然后,连体网络在潜在空间中对图像进行编码,目的是减小图像对的变换向量之间的距离。使用 S(X) 作为来自域 AXA1、A2 两幅图像的矢量编码,网络必须对矢量进行编码,例如:

(S(A1)-S(A2))类似于()S(G(A1)-S(G(A2)))

其中使用了诸如余弦距离的相似性度量。

这样,暹罗网络将信息(以渐变的形式)传递给生成器,告诉它如何在生成的图像中保留原始图像的“内容”。

所有这些都发生在鉴别器告诉生成器如何创建更真实的图像的时候,这些图像类似于来自域 B 的图像。最终结果是一个生成器,它以域 B 的风格生成图像,并保留了域 A 中的一些内容(在两个完全不相关的域的情况下,保持了某种对应关系)。

在这个简短的介绍之后(阅读文件以获取更多信息!),如何将我们的暹罗鉴别器与 TraVeLGAN 方法结合使用?

通过简单地移除特定的连体网络并使已经使用的鉴别器输出向量,我们可以应用先前讨论的损失函数来告诉生成器其生成的图像有多真实,此外,我们能够使用余弦距离来计算潜在空间中图像对的变换向量之间的距离。

Final Architecture with Siamese Discriminator

综上所述,鉴别器将图像编码成矢量,例如:

1.离我们的固定点(原点)的欧几里得距离越小的图像具有更真实的风格

2.编码图像对的变换向量 (A1- A2)(G(A1)-G(A2)) 彼此之间具有低余弦距离,从而保留了内容

知道向量的角度和幅度是独立的特征,鉴别器能够学习应用这两个约束的向量空间。

在我的测试中,我使用带有跳跃连接的 U-Net 作为生成器,使用传统的全卷积暹罗网络作为鉴别器。此外,我在生成器和鉴别器中都使用了注意力,并对卷积核进行了频谱归一化,以保持训练的稳定性。在训练期间,使用 TTUR(鉴别器和生成器的不同学习速率)。

下面是一些结果,是根据 ImageNet 上的苹果和橘子图片训练出来的:

Apple to Orange Image Translation

这里有一个高清样本(横向到日本印刷(浮世绘)):

Landscape to Ukiyo e

结论

在潜在空间中对图像进行编码非常有用:我们已经表明,使鉴别器输出一个矢量而不是单个值,并相应地改变损失函数,可以导致更灵活的客观景观。像图像到图像转换这样的任务可以仅使用单个生成器和鉴别器来完成,而不需要任何附加的网络,也没有循环一致性限制,循环一致性限制依赖于逐个像素的差异,并且不能处理视觉上非常不同的域。还有很多其他的应用有待探索,比如处理带标签的图像等等。

感谢您宝贵的关注,玩得开心!

给财经新闻贴上情感标签的新方法

原文:https://towardsdatascience.com/a-new-way-to-sentiment-tag-financial-news-9ac7681836a7?source=collection_archive---------11-----------------------

30%的财经标题符合特定的模式。

Source: Pexels

在过去的几年里,财经新闻情感分析作为一种商业自然语言处理(NLP)应用已经起飞。

像任何其他类型的情感分析一样,有两种主要的方法:一种,更传统的方法,是使用带有情感标签的单词表(我们也称之为字典)。另一种是使用基于语言模型的情感分类器,这些语言模型是在大型语料库(如亚马逊产品评论或 IMDB 电影评论)上训练的。

对于特定领域的情感分析,后面这些语言模型往往表现不佳。不足为奇:医学文章读起来一点也不像影评。在这方面,迁移学习是一个有趣的成长领域。然而,目前词典仍然是许多特定领域情感分析应用的核心。

在金融领域,那些试图利用开源资源的人可能会以圣母大学的 McDonald- Loughran (M-L)单词表而告终,这些单词表是通过分析 1994 年至 2008 年期间的五万多份收益报告而创建的[1]。这本字典已经被谷歌、富达、Citadel、道琼斯和标准普尔全球等公司使用过。

那还有什么问题呢?

任何抽样标记词表的明显缺陷是,它很小,无法捕捉一种语言的全部丰富性,无论该领域多么具体。然而,更糟糕的是,即使在一个特定的领域内,单词也可以根据子领域的上下文呈现出非常不同的含义。

例如,在金融写作中,从金融报道转移到金融市场分析就足够了,事情开始分崩离析:

所以我们知道使用 M-L 单词表会遗漏重要的信息。(我们会看到再往下一点有多少。)

我们还知道,深度学习语言模型(如微软的 Azure艾伦 NLP 的情感标签)提供了有限的额外洞察力,因为它们通常是在完全不同的语料库上训练的(艾伦 NLP 演示是在斯坦福电影评论数据集上训练的)。所以,至少在某种程度上是,微软 Azure 的文本分析工具)。

最后,为每个子领域的应用支付数据标签是不可持续的。

有什么好做的?

好吧,关于特定领域的事情是他们不仅仅有专门的词汇;他们有写作结构惯例。我说的结构是指带有嵌入式语义的句法选择。

这篇文章着眼于谈论金融市场的一种特殊方式。它展示了利用这种结构如何让您以很少的工作获得大量有用的信息。

本文其余部分如下:
1。考察一个特定的金融市场写作惯例,以及它如何有助于情感标签。
2。将这些见解应用到几千个新闻标题的样本中,并探索由此产生的数据。
3。当处理 NLP 问题时,检查这个分析告诉我们关于领域专门知识的什么。

1。编写拯救公约

在金融写作中,人们必须非常小心因果关系。对于单个公司来说,比如说,一份糟糕的收益报告之后,股票绝对会下跌。然而,你很少会想说整个市场都是因为某个事件而移动的,尽管你仍然想暗示那个事件的影响。

所以你用“as”:随着通胀担忧消退,美国股市攀升。

在英语中,as 有多种用法。但在金融标题中,字数很少,“as”几乎只用于一种特定的方式:表示事件 A 发生了,而事件 B 也在发生,并且 B 至少部分是事件 A 发生的原因。

因此,这个词充当了一个枢纽:

扮演这一特殊角色的不仅仅是“As”。为了暗示明显的影响,你用 after 说得含蓄一点,你可以用“在”。

在情感标注方面,这里的关键点是‘as’将句子分成两部分,这两部分拥有相同的情感

明确地说,这两个事件可能同时发生;这不是物理。但是不会发生,永远不会发生,是为了用‘as’来描述这种共现,因为选择这种铰链结构的隐含语义:负面事件可以和正面事件在同一天发生,但不会,因为正面事件发生了。

因此,如果我们正确地理解了悬挂在“作为”铰链上的一部分的情感,我们也就理解了另一部分的情感。这已经为我们提供了大量描述最近事件的短句的自动情感标签,但它变得更好:

因为介绍性段落通常扩展了新闻故事的主要观点,通过标记悬挂在铰链上的一部分的情感,你已经自动标记了整个段落的情感。

Paragraph tagging by Allen NLP: Negative. By Microsoft Azure: Neutral

动词掌握着关键

由于‘as’和‘amid’的使用方式,主要事件是句子的第一部分;影响事件完成了它的另一半。这种书写约定不适合交换这两个部分:

但金融市场的美妙之处在于,它们只会上升或下降。这意味着你可以通过动词简化情感标签。

这里我们需要稍微谨慎一点。在上面的例子中,攀爬并不是一个绝对积极的发展。当股票上涨时,它是积极的;如果通胀担忧加剧,这将是一个负面消息。

这与框架语义学的概念有关:如果没有人们购买某种东西希望它升值的概念,你就无法理解股市中动词“攀升”的概念。

现在,一般来说,市场上涨是积极的,但也有特定的情况并非如此,例如,债券:当债券收益率上升时,债券价格下降。

为了解决这个问题,我们可以建立一个基于规则的系统,在特定情况下反转标记。因此,默认情况下,我们会将第一部分带有“爬升”的新闻故事标记为正面,除非句子的主语是一个与标记相反的例外。

这是个骗局,但谁在乎呢?考虑到标记可能非常昂贵,即使对于迁移学习,您仍然需要一个特定领域的标记样本数据库,以如此少的额外工作获得一个数据库是一个相当不错的结果。

因此,仅仅通过利用这一写作惯例,我们已经命名了两个显而易见的好处:一,标题的大规模情感标签,二,整个段落的有意义标签,潜在地帮助深度学习方法。让我们用一些真实的数据来探究它们的范围。

2。数据探索

出于这项研究的目的,我收集了去年发表的几千条财经新闻标题的样本。这些讨论金融事件和股票、货币和商品市场的一般市场运动,不包括有关特定公司的新闻。

我根据新闻讨论的地理市场对数据进行了分类。总的来说,人们会期望这些之间有一定程度的差异;毕竟,不同的作家群体应该有略微不同的写作模式。

然而,为了支持写作惯例在起作用的论点,请注意差异并没有那么显著。在整个市场中,大约 30%的标题遵循这种铰链结构,从而提供可提取的信息。

当然,要真正提取所说的信息,需要解析标题的两个部分,特别是——识别铰链左边的动词。为此,我使用了 SpaCy 标准解析器。总的来说,这种方法很有效,因为标题的左右部分都是简单结构的句子。结果,我们最终确定了大约 300 个动词的列表。

它们在样本中的流行程度符合指数分布,所以有限数量的动词被大量使用,并且有一条长尾巴的动词只被使用一两次。

注意不是所有的动词都带有感情色彩。有时候,新闻故事本身是中性的。但通常情况下,这是因为动词实际上是动词复合词的一部分,由一个动词和一个上升/下降介词组成:市场上涨上涨,道琼斯指数下跌结束。将情感标记扩展到包括这样的实例并不困难。

最常用的 15 个动词是:

有趣的观察——在列表的下方,我们发现动词“feed”看起来很奇怪。你能猜到它为什么会出现吗?(提示:过往事件的新闻报道)。思考如何批量修复这个解析问题是一个很好的练习。

最后,我们现在可以评估 M-L 字典的缺失程度了。局限于出现在不止一个标题中的表达情感的动词,我们可以看看这些是否出现在字典中,如果出现,它们是否表达相似的情感。

在我们的示例中,有 45 个这样的词汇化动词,它们对应于 80 个不同的动词的原始形式。从好的方面来看,所有带情感标签的动词都在字典里。此外,也没有字典颠倒我们情感标签的例子(当我们把某件事贴上负面标签时,说它是正面的,反之亦然)。

另一方面,大多数动词都没有情感标签。

特别是,当查看我们的前 15 个列表中携带情感的词汇化动词时(回想一下,由于指数分布,这些动词覆盖了大多数标题),只有一个词“增益”被 M-L 字典标记为情感。

它在财务报表的上下文中是有意义的,M-L 标记是基于财务报表的。如上所述,例如,动词‘climb’不是一个绝对肯定的词;在财务报表中,如果制造成本上升,这将是一个负面消息。

所有这些似乎表明,当对以这种铰链结构撰写的财经新闻标题进行情感标注时,依赖 M-L 词典将会错过许多重要信息。鉴于如此多的新闻故事遵循这种结构,这是一个相当大的损失。

3。这告诉我们什么是领域专业知识

这是一个诱人的信念,如果你能让你的算法足够好,足够聪明,足够聪明,它将能够破解一个 NLP 任务,而不考虑领域。

谁知道呢?有一天,这可能就是事实。

但是现在,它不是。

因此,上面的讨论在提问时是有用的:领域专长实际上增加了什么价值?

通常,领域专业知识在词汇层面上被认为是有用的。例如,前面我们已经看到了动词“温和”,在市场语境中,人们在试图避免惊吓投资者时将其用作“下跌”的同义词。

更广泛地说,词汇领域专业知识意味着应用外部知识来确定一些术语比其他术语更重要,或者单词具有特定的含义。

这就是说社会语言的一部分,社会语言是一种表明属于特定社会群体的子语言。但是专业词汇(包括行话)只是一个层面,表达思想的模式也是社会的一部分。想想律师吧,他们看起来会说英语,但却是用这些死板、复杂的句子结构来说的。

扎实的领域专业知识允许您识别这些模式,并利用它们来提取信息。

在本文中,我们将这一原则应用于金融市场子领域。因此,我们能够改进现有的情感分析工具,并生成可扩展的自动情感标签。

这是通过使用相当老式的单词列表和粗鄙的标记(一小组动词)的方法来完成的,同时加入了一些规则。然而,它表明这项工作如何能够支持更高级的深度学习技术。

就我个人而言,我觉得仅仅由于书写习惯,我们就能从这个微小的语法单元中获得如此多的语义价值,这很令人高兴。

不是吗?

来源:
1。Loughran,t .和 McDonald,B. (2011) 什么时候是责任而不是责任文本分析、词典和 10-k。金融杂志,66 年,35-65 页。

Jupyter 笔记本共享和协作的新方式

原文:https://towardsdatascience.com/a-new-way-to-share-collaborate-on-jupyter-notebooks-483f8f0c46ef?source=collection_archive---------23-----------------------

将 Github 与 Kyso 集成,增强您交流数据的方式&分析。

共享和复制数据科学仍然不容易。大多数公司仍然没有一个知识管理的中心。内部数据团队使用 Github 等工具进行项目管理,通常只有数据科学家和工程师才能访问。这意味着他们的工作不与公司的非技术人员分享。他们使用数据科学笔记本这样的技术文档进行数据探索和分析,但是代码的存在、终端输出等。意味着它们不是非技术受众的最佳沟通工具。所有这些都导致了很多锁定的商业价值,因为不是公司中的每个人都从产生的见解中学习。

Kyso 通过我们的 Github 集成和一个优雅的博客平台解决了这个问题,该平台用于呈现数据科学笔记本,使每个人都可以访问以前只有少数人拥有的信息。Kyso 通过将笔记本呈现为网络文章,让技术团队以更易读的格式发布和分享他们的分析。把它想象成你的团队自己的内部媒介,但是对于数据科学——你可以发布 Jupyter & R 笔记本。默认情况下,任何代码都是隐藏的,并且可以切换,以便技术和非技术受众都能理解您的帖子。你也可以使用我们的应用内 Markdown 编辑器从头开始写文章。

我们创建了 Kyso 来优化内部数据团队和其他科学计算从业者的计算到交流工作流,从他们工作的探索阶段到结果的交流。在这篇文章中,我将介绍如何为您的个人和专业项目做到这一点。

工作流程

入门指南

如果你还没有账户,去 Kyso 注册——这是一个免费的个人账户!如果你愿意,你可以注册你的 Github 帐户,它会自动同步到 Kyso。

然后,在您的仪表板上,导航到我们的 Github 页面。

Navigating to your Github repositories on Kyso

批准

如果你在 Github 上注册了 Kyso,你会自动连接上,你会在这个页面上看到你所有的公共库。如果没有,只需点击连接 Github 账号按钮即可。使用右边的下拉菜单,您可以选择授权您所有的 Github 库,或者只授权您的公共库(默认)。鉴于 Github 的 OAuth 授权方式,目前不可能只授权一个库。

Authorising your Github repositories on Kyso

在 Github OAuth 页面上,您可以选择授权您自己的帐户和您可能加入的任何组织。您可以搜索和过滤您的存储库,并通过单击连接到 Kyso 将它们导入到 Kyso。然后,您可以在 Kyso 仪表板上浏览这些帖子。

请记住,虽然 Kyso 上的帖子可能看起来像一个单独的渲染笔记本,但事实上,它是一个完整的 Github 存储库(或 Github 存储库的子目录)的反映,这意味着您可以在 Kyso 上浏览所有附件。如果你的库包含许多不同的文件夹,在 Kyso 上以不同的文章呈现会更好,这也是可能的。

查看我们的文档,看看配置是如何工作的。

结论

现在你知道了!您可以继续在现有的工作流程中操作,使用 Jupyter 笔记本进行数据探索、机器学习等。,将您的提交推送到 Github,这样您的项目的历史就会得到维护。所有提交都将以可读格式自动反映在 Kyso 姐妹帖子上。

关于 Kyso 的 Github 集成如何与您的笔记本配合工作的示例,请查看这个 Github 知识库,了解各种数据分析项目。你会看到很多子目录,我已经在 Kyso 上设置了单独的帖子。查看我们的文档了解我们的配置指南。

最后,去我的简介看看这些帖子是如何漂亮地呈现出来的。Kyso 的 Github 集成也可以用于内部私人知识共享,使用 Kyso 在您的团队中展示和协作您的分析。所有团队成员将能够消费、搜索&并以博客风格对发布的内容进行评论来提供反馈。

Jupyter 笔记本和类似的工具正在成为新的 Excel。为了获得这种现象的全部好处,这些文档中的知识需要在整个组织中有效地交流,这样每个人(我是说每个人)都可以学习&将数据洞察应用到各自的角色中,以推动业务价值。在 Kyso,我们希望帮助您做到这一点。

混淆矩阵的非混淆指南

原文:https://towardsdatascience.com/a-non-confusing-guide-to-confusion-matrix-7071d2c2204f?source=collection_archive---------7-----------------------

你在炒作机器学习。你不太懂统计学,但你知道均值是什么。你决定跳过所有先决条件,训练你的第一个机器学习模型。你跟随了 YouTube 上某个印度人的代码视频教程。在花了 10 个小时意识到你错过了 IF 语句的缩进之后,你的模型终于被训练好了。

你已经获得了超过 90%的准确率。生活是美好的。

Photo by Markus Spiske on Unsplash

但我要告诉你,你的模型很可能很烂。这是意料之中的,见鬼,太好了

玩笑归玩笑,当你是数据科学和机器学习的新手时,模型评估可能会很困难。困惑矩阵是让你困惑的东西,这是意料之中的。你不会相信你能从愚蠢简单的 2x2 矩阵中得到多少东西。

以下是模型训练后获得的混淆矩阵示例:

好吃吗?很糟糕吗?答案是你最喜欢的——看情况 ( 结果很糟糕)。

提取混淆矩阵

这里有一个看起来更普通的混淆矩阵:

是的,我知道你在想什么— 干得好,笨蛋,现在我更糊涂了!但是不要着急,让我们把它分成更小的、更容易理解的部分。

实际值

  • 数据集的值(目标变量的值)

预测值

  • 模型预测的值

积极的

  • 目标变量中的值
  • 如果预测疾病,这将是‘有疾病’
  • 二进制目标变量中的 1

否定的;消极的;负面的;负的

  • 目标变量中的值
  • 如果预测疾病,这将是‘没有疾病’
  • 二进制目标变量中的 0

好吧,这很容易理解,但是那些真正的肯定和否定是什么意思呢?

好问题读者。我在想你什么时候会问这个问题。对这些的解释对你来说很容易读懂。但是它们更容易忘记,所以你可能想每隔几天就重读一遍。或者更好的是,把它们写在一张纸上。写下一些东西会更容易坚持。但是我在这里跑题了,我们正在讨论假阳性和真阴性,让我们深入探讨一下。

真阳性(TP)

  • 你的模型预测为正,实际为正
  • 在二项式变量中是 1
  • 你预测病人有疾病,而他已经有了

假阳性

  • 你的模型预测为正,而实际为负
  • 模型预测的是 1,但在二项式变量中是 0
  • 你预测病人会生病,但他并没有
  • 第一类错误

假阴性(FN)

  • 你的模型预测为负,而实际为正
  • 模型预测的是 0,但在二项式变量中是 1
  • 你预测病人没有病,但他却得了
  • 第二类错误

真阴性(TN)

  • 你的模型预测是负的,而实际是负的
  • 模型预测 0,二项式变量是 0
  • 你预测病人没有病,他也没有

你看,混淆矩阵没有任何令人困惑的地方。当然,你需要记住这些术语,是的,它们听起来很相似,但至少它们不像你可能遇到的其他机器学习概念那样抽象。

与 Scorings 一起生活

在阅读了所有关于积极和消极的东西之后(几次,最好是),你现在对混淆矩阵有了一个基本的想法和直觉,你会发现它并不那么令人困惑——它只是需要适当地“融入”。

但那都是关于混乱矩阵的吗?

我希望你是在开玩笑。我们才进行了一半。也许吧。

接下来,我想讨论可以从混淆矩阵中获得的各种得分。而且有很多。根据维基百科[1],以下是所有这些人的名单:

  1. 敏感度/召回率/命中率/真阳性率 (TPR)
  2. 特异性/选择性/真阴性率 (TNR)
  3. 精度/阳性预测值 (PPV)
  4. 阴性预测值 (NPV)
  5. 漏检率/假阴性率 (FNR)
  6. 脱落/假阳性率 (FPR)
  7. 错误发现率 (FDR)
  8. 假漏检率(为)
  9. 威胁分数/关键成功指数 (CSI)
  10. 精度 (ACC)
  11. F1 分数
  12. 马修斯相关系数 (MCC)
  13. 知情/庄家知情 (BM)
  14. 标记性 (MK)

By GIPHY

感到困惑?这是意料之中的。我也是。我从未听说过其中的一些术语,但我仍然想把它们放在这里,只是为了证明你可以理解混乱矩阵所提供的一切,而不会发疯。

但是想想你怎么能仅仅从这个看起来很愚蠢的 2x2 矩阵中计算出这么多不同的分数,这真是令人惊讶。我的意思是只有 4 个数字,看在上帝的份上!

对于本文的第二部分,我想深入探讨机器学习领域最常用的评分方法,它们是:

  • 准确(性)
  • 回忆
  • 精确
  • F1 分数

没错,我将只讨论 14 个中的 4 个,因为我觉得这些是最重要的,只要对它们有基本的了解,你就完全有能力优化你的模型。你不需要记住公式,那些已经内置到 Python 的Scikit-Learn中了,但是你要知道什么时候选择一个而不是另一个。

在开始之前,让我们来看看您将要处理的混淆矩阵:

简而言之,在给定的矩阵中,我们有:

  • 真底片 (TN) — 1943 年
  • 误报 (FP) — 32
  • 真阳性 (TP) — 181
  • 假阴性 (FN) — 344

您可能已经注意到,这与本文开头的混淆矩阵是一样的,只是表现得更好。事不宜迟,让我们开始吧!

准确度分数

  • 最直观的理解——正确预测的观察值与总观察值的比率
  • 不太适合大多数业务需求
  • 计算很简单:所有真实实例除以实例总数
  • (TP+TN) / (TP+FP+FN+TN)

Python 中的实现:

**from** **sklearn.metrics** **import** accuracy_scoreprint(accuracy_score(y_true, y_pred))
>>> 0.8496

回忆分数

  • 模型在数据集中查找所有相关案例的能力
  • 对于我们的例子,这将是模型的能力,找到所有的情况下,病人有疾病
  • 计算很简单:用真阳性(TP)除以真阳性(TP)和假阴性(FN)之和
  • TP / (TP + FN)

Python 实现:

**from** **sklearn.metrics** **import** recall_scoreprint(recall_score(y_true, y_pred))
>>> 0.3448

精确分数

  • 模型仅识别相关数据点的能力
  • 对于我们的例子,这将是模型的能力,正确分类的病人没有疾病
  • 计算:用真阳性(TP)除以真阳性(TP)和假阳性(FP)之和
  • TP / (TP + FP)

Python 中的实现:

**from** **sklearn.metrics** **import** precision_scoreprint(precision_score(y_true, y_pred))
>>> 0.8498

F1 分数

  • 精确度和召回率的加权平均值。
  • 同时考虑误报和漏报
  • 您的误报率(FP)和漏报率(FN)都很低,能够正确识别真正的威胁,并且不会受到误报的干扰
  • 该计算需要先前计算的召回率和精确度
  • 2(召回精度)/(召回+精度)

Python 中的实现:

**from** **sklearn.metrics** **import** f1_scoreprint(f1_score(y_true, y_pred))
>>> 0.4905

这些解释应该给你一个清晰的画面,使用准确性作为评分标准并不总是一个好的选择。在我们关于患者和疾病的例子中,使用回忆会更好,因为你可能想要正确地识别每个患有疾病的患者——试想一下,在癌症检测中有大量的错误分类会有多可怕。

这些材料足够你忙上一段时间了。当这对你来说变得容易时,请参考维基百科文章(文章底部张贴的)来学习更多的评分。

临终遗言

我的意图是以一种不混乱的方式分解这个看起来愚蠢简单的矩阵,因为当你第一次遇到它时,它会变得非常混乱。

我当然没有说关于这个话题的所有内容,但是每一个关键的想法和概念都在这里,等着被学习。很容易忘记这些东西,试图在一天之内学会它们只会让这些术语更加混淆。缓慢而稳定的人赢得比赛。

是的,大多数术语的叫法相似,你会被它弄糊涂——这是完全正常的。不时回顾一下你想要的文章中的材料。

By GIPHY

你有什么想法?看了几遍还有什么不明白的吗?欢迎在下面发表评论。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

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

资源

[1]https://en.wikipedia.org/wiki/Confusion_matrix

数据科学的非技术性阅读清单

原文:https://towardsdatascience.com/a-non-technical-reading-list-for-data-science-d72451429a70?source=collection_archive---------2-----------------------

(Source)

无需钻研技术细节就能让你成为更好的数据科学家的书籍

与一些数据科学家可能愿意相信的相反,我们永远无法将世界简化为单纯的数字和算法。归根结底,决策是由人类做出的,而成为一名高效的数据科学家意味着既了解又了解数据。

考虑以下现实生活中的例子:

当软件公司 OPower 想要让人们使用更少的能源时,他们向客户提供了大量关于他们用电量和成本的统计数据。然而,数据本身不足以让人们改变。此外,OPower 需要利用行为科学,即研究表明,当人们在账单上收到笑脸表情符号时,他们会减少能源消耗,这些表情符号显示了他们与邻居的对比!

把一个简单的干预😃当人们比他们的邻居用的少的时候,他们的电费账单😦当他们可以做得更好时,最终减少了 2-3%的电力消耗,在此过程中节省了数百万美元,并防止了数百万磅二氧化碳的排放🏆!对于数据科学家来说,这可能是一个震惊——你的意思是人们不会对纯数据做出反应!——但这对于 OPower 的首席科学官罗伯特·恰尔迪尼来说并不奇怪,他曾是心理学教授,写过一本关于人类行为的书。要点是,你可以拥有任何你想要的数据,但你仍然需要了解人类如何实现真正的改变。

The most effective visualization isn’t a bar chart, it’s a smiley face.

在我们作为数据科学家的日常工作和正规教育中,很难瞥见人类的工作方式,或者后退一步思考我们工作的社会影响。因此,重要的是不仅要阅读技术文章教科书,还要扩展到研究人们如何做出选择以及如何利用数据来改善这些选择的著作。

在本文中,我将重点介绍 6 本非技术性的书籍,因为它们不涉及数学和算法,但却是数据科学家的重要读物。这些书对于任何想要实现数据科学目标的人都是必要的:通过数据实现更好的现实世界决策。

这里列出了 6 本书,并附有简要评论和要点:

  1. 信号和噪音:为什么如此多的预测失败——但有些却没有 内特·西尔弗
  2. 数学毁灭的武器:大数据如何增加不平等并威胁民主 作者凯茜·奥尼尔
  3. Brian Christian 和 Tom Griffiths 的《人类决策的计算机科学》和 Jordan Ellenberg 的《如何不犯错:数学思维的力量》
  4. 思考,快与慢 丹尼尔·卡内曼
  5. (黑马)《黑天鹅:可能性极小的冲击》作者纳西姆·尼古拉斯·塔勒布

要点和评论

  1. 信号和噪声:为什么这么多预测失败——但有些却没有 作者内特·西尔弗

对未来的预测——在选举、经济、国家政治和技术进步等领域— 经常是错误的,令人捧腹。当这些预测具有真实的现实世界的后果时,它们就不那么幽默了,在这部作品中,西尔弗解释了为什么人们往往不擅长做出预测,并研究了少数几个在不同领域成功打破趋势的人。事实证明,预测未来并不存在一个神奇的规则,只是伟大的预测家们实践的一些基本规则。

任何人都可以从整本书提供的简单建议中受益:

  • 像狐狸一样思考(不是刺猬):有很多小点子(狐狸),而不是一个大点子(刺猬)。如果你只有一个想法,你会倾向于寻找确定的证据,忽略任何与你的观点相矛盾的东西(T2 确认偏差)。如果你有很多小想法,你会更关心什么是正确的,而不是什么支持你当前的信念,当证据不再支持它们时,你可以放弃任何想法。这两种不同的思维方式也解释了为什么对自己的预测更有信心的人(比如电视专家)往往更多时候是错的。
  • 进行大量预测并获得快速反馈:我们更擅长对频繁发生的事件进行估计,这主要是因为反馈和改进周期。天气预报每天都出错,这些信息进入模型,使明天的预报变得更好(这也是为什么天气预报在过去几十年里有了很大改进的一个原因)。在我们很少经历的情况下,我们最不擅长做出选择,在这些情况下,使用尽可能多的数据是关键
  • 尽可能多的利用不同的来源:每个数据提供者都有自己的偏见,但是通过汇总不同的估计值,你可以找出错误的平均值 Silver 的 FiveThirtyEight 网站很好的说明了这一点。这种群体智慧的方法意味着使用与你的观点不一致的资源,而不是仅仅依靠某个领域的“专家”。
  • 永远包含不确定性区间,当证据发生变化时,不要害怕更新你的观点:人们在预测时犯的最大错误是提供一个数字。虽然一个答案可能是公众想要听到的,但世界从来不是严格的黑或白,而是存在于灰色阴影中,我们有责任在我们的预测中表现出来。表达不确定性可能看起来很懦弱——说希拉里有 70%的胜算意味着无论结果如何,你都是对的——但这比一个简单的是/否更现实。此外,人们认为改变自己的观点是一种弱点,但当事实发生变化时,更新你的信念实际上是一种重要的力量,在数据科学和形成世界观方面。

我们对世界的预测永远不可能完全正确,但这不应该阻止我们依靠经过充分证明的原则来做出更好的预测,从而减少错误。

这一类别的另外两本书是菲利普·泰特洛克的《超级预测》 和《专家政治判断》

2。 数学毁灭的武器:大数据如何增加不平等并威胁民主 作者凯茜·奥尼尔

数学毁灭武器应该成为攻读统计学、机器学习或数据科学学位的学生以及任何必须做出部署模型决定的人的必读书目。“破坏数学的武器”是任何不透明的算法——不容易解释;影响数百万甚至数十亿人,并有可能造成严重损害,如破坏民主选举或使我们的大批人口被监禁。

核心前提是,这些破坏数学的武器有能力创造传播不平等的反馈循环,因为我们看不到这些算法的内部,我们不知道如何纠正它们。只有在我们回顾并观察到巨大的破坏——如 2016 年大选或 2008 年金融危机(都是由为负面目的服务的算法造成的)——我们对这些模型的盲目信任可能造成的伤害之后。

此外,我们的模型只和输入的数据一样好,当数据有偏差时,模型的预测也会一样好。考虑一个对罪犯判刑的模型,这个模型考虑到了一个人第一次与执法机关打交道的时间。由于不公正的治安策略,如拦截和搜身,即使考虑到其他因素,一个黑人很可能在比白人年轻得多的时候就与警察发生口角。这将导致模型建议延长黑人的刑期,在此期间,这些人将失去经济机会,并被社会排斥。这些人更有可能再次犯罪,导致监禁的恶性循环,这一切都是因为不公正的政策产生的数据,然后被送入黑匣子

奥尼尔的书于 2016 年初发行,现在比以往任何时候都更需要它。2016 年底,俄罗斯演员利用脸书的算法进行宣传,对美国的民主进程造成了严重破坏。这些行动远非学术活动,而是产生了现实世界的后果,引发了对美国选举合法性的质疑。极右翼广告继续困扰着脸书,这是由一种算法驱动的,这种算法(最有可能的是,我们真的不知道)认为参与是重中之重。

算法只会在我们的日常生活中发挥更大的作用。我们在哪里上学,我们读什么,我们是否被批准贷款,我们是否找到工作,我们买什么都在很大程度上由算法决定,我们无法控制,也无法查询解释。奥尼尔的书似乎对机器学习模型持悲观态度,但我更愿意认为这是一种必要的批评:围绕机器学习有这么多肆无忌惮的热情,我们需要人们愿意退一步问:这些工具真的改善了人们的生活吗?作为一个社会,我们应该如何采用它们?

机器学习算法只是工具,和任何工具一样,它们可以用于好的方面,也可以用于坏的方面。幸运的是,我们仍处于早期阶段,这意味着我们可以塑造模型的使用,以确保它们朝着做出客观决策和为尽可能多的人创造最佳结果的方向努力。我们现在在这方面做出的选择将塑造未来几十年数据科学的未来,最好在充分知情的情况下参与这些辩论。

数据科学可能是一个年轻的领域,但已经对数百万个人的生活产生了巨大的影响,无论是好的还是坏的。作为这个新领域的先驱,我们这些现在工作的人有义务确保我们的算法不会变成数学毁灭的武器。

3。(Tie) 算法赖以生存:人类决策的计算机科学 布莱恩·克里斯蒂安和汤姆·格里菲斯著 如何不出错:数学思维的力量 乔丹·埃伦伯格著

**

在学校教授计算机科学和统计学(以及其他研究领域)时,它们都有一个问题:抽象的内容令人生厌。只有当它们应用于现实世界的问题时,它们才会变得足够有趣,让我们想去理解。这两本书都做了一项令人难以置信的工作,将枯燥的主题转化为娱乐性和知识性的叙事,讲述如何在我们的日常生活中使用算法、统计数据和数学。

例如,在《T21 生活的算法》一书中,作者展示了我们如何使用探索与利用权衡和最优停止的思想来找出我们应该花多长时间寻找配偶(或新员工,晚餐的餐馆等)。).同样,我们可以使用排序算法来最有效地组织我们的物品,以便快速检索您需要的东西。你认为你知道这些想法,你甚至可以用代码写出来,但是你可能从来没有应用它们来优化你的生活。

**如何不犯错的主要思想与艾伦伯格带领我们通过故事展示线性回归、推理、贝叶斯推理和概率等统计概念的使用和误用类似。应用概率定律告诉我们,玩彩票永远是一个失败的命题——除非在极少数情况下,回报实际上是正的(正如麻省理工学院的一群学生发现的)。艾伦伯格并不回避向我们展示方程式,但他将它们应用于现实世界的情况。

艾伦伯格书中的中心引语是,数学思维是“常识通过其他方式的延伸”在许多情况下,主要是在遥远的过去,我们的直觉很好地服务于我们,但是,现在在现代世界,有许多情况下我们最初的反应是完全错误的(见下一本书)。在这种情况下,我们不需要依靠直觉,而是可以使用概率和统计数据,以达到最佳决策。

这两本书的严谨程度恰到好处——混合了几个等式和大量的故事——读起来都很有趣。在这些书中,我发现了大量我在课堂上从未完全掌握的数据科学概念,最终我一次又一次地体验到了“啊哈”时刻的喜悦。数学、统计学和计算机科学只有在能让你的生活变得更好的程度上才有用,这两本书都展示了你从未停下来思考过的这些学科的所有用途。**

4。 思考,快与慢 丹尼尔·卡内曼

如果你还没有意识到这一点,那么这里有一个有用的教训:人类是非理性的,我们经常在生活的各个方面做出可怕的决定。然而,我们有理由抱有希望:一旦我们理解了为什么我们没有采取最佳行动,我们就可以开始改变我们的行为以获得更好的结果。这是卡尼曼记录几十年实验发现的杰作的核心前提。

卡尼曼(2002 年诺贝尔经济学奖得主)和他的研究伙伴阿莫斯·特沃斯基(以及理查德·塞勒等其他人)创建了极具影响力的行为经济学领域,该领域将人们视为非理性的决策者,而不是理性的效用最大化者。这不仅在经济领域,而且在医药、体育、商业实践、节能和退休基金等生活领域,都带来了思维和设计选择的真正转变。我们还可以将许多发现应用于数据科学,例如如何呈现研究结果。

在这部严谨而又非常令人愉快的作品中,卡尼曼概述了我们不按逻辑行事的所有方式,包括锚定、可用性和替代试探法(经验法则)或我们倾向于规避损失以及成为沉没成本谬误的牺牲品。他还概述了可能是最重要的一点:我们有两种不同的思想体系。

  • 系统 1 快速而直观:这种模式是进化设计出来的,可以在不考虑证据的情况下快速做出决策。虽然这在我们狩猎采集的过去对我们很有帮助,但在我们信息丰富的世界里,当我们没有时间查看数据时,它经常会给我们带来麻烦。
  • 系统 2 缓慢而理性:我们需要在有很多选项和不同证据来源需要考虑的情况下使用这种模式。采用系统 2 需要付出努力,但这种努力会得到更好的决策和结果。

使用系统 1 是自然的,我们必须克服数百万年的进化才能使用系统 2。尽管这很难,但在我们这个数据丰富的世界里,我们需要花时间磨练我们的系统 2 思维。当然,我们有时可能会遇到过度思考的问题,但是思考不足——使用系统 1 而不是系统 2——是一个更严重的问题。

这本书对于理解人们如何做决定以及我们作为数据科学家可以做些什么来帮助人们做出更好的选择至关重要。

这本书也有适用于数据科学之外的结论,比如两个自我的概念:体验和记忆。体验自我是我们在一个事件中时时刻刻的感受,但远没有回忆自我重要,回忆自我是我们事后对事件的感知。记忆自我根据峰-端规则对一次经历进行评级,这对于医学、生活满意度和强迫自己做不愉快的任务有着深远的意义。我们记忆事件的时间会比我们经历它们的时间长得多,所以在一次经历中,我们努力最大化记忆自我的未来满足感是至关重要的。

如果你想了解实际的人类心理,而不是传统课堂上呈现的理想化版本,那么这本书是最好的起点。

5。(黑马): 黑天鹅:极不可能的冲击 纳西姆·尼古拉斯·塔勒布

塔勒布在名单上只有一个位置,而且是一个局外人的位置。塔勒布曾是一名量化交易者,他在 2000 年和 2007 年的市场低迷期间赚了很多钱,现在他已经成为一名直言不讳的学者和研究人员,他的作品赢得了全世界的赞誉和批评。首先,塔勒布被一个想法所占据:当代思维方式的失败,尤其是在充满不确定性的时代。在《黑天鹅》中,塔勒布提出了这样一个概念:我们对支配人类活动的随机性视而不见,因此,当事情不如预期时,我们会被摧毁。最初于 2007 年出版的《黑天鹅自从 2008 年和 2016 年的意外事件完全颠覆了传统模式以来,变得更加相关。

当然,基于这个中心前提,立即出现的问题是:按照定义,不可能发生的事件不会经常发生,所以我们不应该担心它们?关键的一点是,虽然每个不可能发生的事件本身不太可能发生,但综合起来看,几乎可以肯定的是,在你的一生中,甚至在一年内,许多意想不到的事件将会发生。任何一年发生经济崩溃的可能性都是微乎其微的,但是这种可能性越来越大,直到世界某个地方每十年发生一次经济衰退的可能性非常小。

我们不仅应该期待改变世界的事件会频繁发生,而且我们不应该听信那些被过去发生的事情所束缚的专家。任何投资股市的人都应该知道,过去的表现不能预测未来的表现,这是我们在数据科学模型(使用过去的数据)中考虑的一个明智的教训。此外,我们的世界不是正态分布,而是厚尾分布,少数极端事件——大衰退——或少数富人——比尔·盖茨——盖过了所有其他人。当极端事件发生时,没有人做好准备,因为它们的规模远远超过以往任何一次。

黑天鹅对数据科学家来说很重要,因为它表明,任何只基于过去表现的模型往往都是错误的,会带来灾难性的后果。所有的机器学习模型都是只用过去的数据建立的,这意味着我们不想太相信它们。模型(包括 Taleb 的)是对现实的有缺陷的近似,我们应该确保我们有适当的系统来处理它们不可避免的失败。

值得注意的是,塔勒布不仅因其新颖的想法而闻名,也因其极度好斗而闻名。他愿意接纳所有来者,并定期批评像史蒂芬·平克这样的学者,或者像内特·西尔弗这样的公众人物。在我们这个严重扭曲的时代,他的想法有助于理解,但他的态度可能有点令人不快。尽管如此,我认为这本书还是值得一读,因为它提供了一个非主流的思想体系。

(这本书是塔勒布五部曲中的第二部,开始展示他的完整哲学。《黑天鹅》讨论了极不可能发生的事件的概念,而抗脆弱:从无序中获益的事物中的第四本书讨论了如何让自己不仅对混乱保持稳健,而且让自己因此变得更好。我认为这只黑天鹅与数据科学最为相关。

结论

在盯着电脑屏幕看了一整天之后,我想不出比看书更好的方式来结束一天的工作了(纸质书、电子书或有声读物都可以)。数据科学需要不断扩展工具箱中的工具,即使当我们想要放松一下,把注意力从工作上移开,这也不意味着我们不能学习。

这些书都是引人入胜的读物,也教给我们关于数据科学和生活的课程。这里描述的 6 部作品将通过展示人类的实际驱动力,为更多的技术作品提供有益的补充。理解人们在现实中是如何思考的——而不是理想化的模型——对于实现更好的数据驱动型决策来说,与统计学一样重要。

一如既往,我欢迎反馈和建设性的批评。可以通过推特 @koehrsen_will 联系到我。

利用未来指标进行预测的新方法

原文:https://towardsdatascience.com/a-novel-approach-for-forecasting-with-future-indicators-f2c57312de3d?source=collection_archive---------17-----------------------

时间序列建模和预测在许多实际领域都具有重要意义。因此,在这几年中,在这个课题上进行了许多积极的研究。为了提高时间序列建模和预测的精度和效率,文献中提出了许多重要的模型。预测是一项数据科学任务,是组织内许多活动的核心。例如,像苹果这样的大型组织必须分配稀缺的资源和目标设置,以便相对于基线来衡量绩效。公司的财务规划和分析团队多年来一直使用基于驱动因素的算法模型来预测全球现金流。我们的目标是探索最现代的技术,根据传统方法验证它们,并开发一个比现有业务实践更加稳健、灵活和一致的全球现金预测。理解产生高质量的预测对机器或分析师来说不是一个容易的问题。在创建各种业务预测的实践中,我们观察到两个主要主题:

  1. 完全自动的预测技术可能是脆弱的,并且它们通常太不灵活而不能结合有用的假设或启发
  2. 能够做出高质量预测的分析师非常罕见,因为预测是一项需要丰富经验的专业数据科学技能

问题陈述

我们的目标是基于业务驱动因素,使用机器学习技术预测 90 天(13 周)范围内应付账款(AP)和子部分的现金流。

如果预测模型能够准确预测:

  1. 公司财务部门可以分配必要的预算,并在其他创收垂直领域进行投资
  2. 如果预测有偏差,那么团队可以进行根本原因分析,根据模型提供的未来指标来检查偏差
  3. 该模型是一个持续改进的模型,因为它捕捉了假日效应和商业意识形态的转变

我们的应付账款(AP)现金预测解决方案:

数据来自不同的来源,执行数据清理活动以使数据对建模和探索性数据分析(EDA)有用,执行完整性分析以验证来自数据源的数据与银行对账单的实际数据。分析了 58 个独立变量,以观察对 USD_AMT 付款的显著依赖性。其中支付条款是 AP 付款的主要驱动因素

如下所示,支付条款分为三类。

  1. 滞后 0(在同一个月过账和支付):所有具有 0-30 个起息日的支付条款都属于这一类别
  2. 滞后 1(过账和支付有一个月的差异):所有有 30-60 个起息日的支付条款都属于这一类别
  3. 滞后 2(过帐和支付有两个月的差异):所有具有 60–90/以上起息日的支付条款都属于这一类别

下面的图 1 显示了具有统计平均差异的薪酬类别的行为差异。明确需要在全球薪酬条件下对不同的滞后时段分别建模,并在报告中将它们整合在一起。

Figure 1

包含未来指标 : - 包含未来指标为业务增加了巨大的解释力。它还为预测的梯度提供了一个指南,使其朝着未来指标相关的方向移动。术语回归用于统计中的这一因素,如果可以用衡量标准来解释,这是以相关方式流动的受抚养人付款的正当理由。数据科学团队尝试了三个主要的未来指标,它们是可用的 COS(销售成本)、COS 加 Open X(运营支出)和 COS 加 Open Inventory。下图显示了成本作为 AP 支付驱动因素的影响,该驱动因素在统计上证明了滞后 2 的相关系数为 0.602。

Figure 2

我们使用一个可分解的时间序列模型(Harvey & Peters 1990 ),该模型有三个主要组成部分:趋势、季节性和节假日。它们在以下等式中合并:

这里 g(t)是对时间序列值的非周期性变化进行建模的趋势函数,s(t)表示周期性变化(例如,每周和每年的季节性),h(t)表示在一天或多天内可能不规则的时间表上发生的假期的影响。误差项表示模型不适应的任何特殊变化;稍后我们将作出误差项是正态分布的参数假设

C 表示承载能力,k 表示增长率,m 表示偏移参数。

我们依靠傅立叶级数来提供一个灵活的周期效应模型(Harvey & Shephard 1993)。假设 P 是我们期望时间序列具有的规则周期(例如,对于年度数据,P = 365.25 对于周数据,当我们以天为单位调整时间变量时,P = 7)。我们可以用以下公式来近似任意平滑的季节效应

解释 HP predict 和网格包含设置基准 :- Prophet 模型用作基线,这是一种集合方法。集成方法是一组训练数据的方法的核心,它根据训练数据给出最佳模型的输出预测。脸书先知是 HP 预言的基线。两者都使用一般加性模型的集合方法。使 HPpropehcy 更好的功能是具有额外的时间序列交叉验证和网格搜索。

HP predictive 中的交叉验证和网格搜索:-HP predictive 中的交叉验证和网格搜索评估不同时间序列数据和参数(如每周、每月、每季度和每年的季节性影响)的模型准确性。它主要在数据上训练算法时对傅立叶级数进行处理,并基于验证集上的最佳 rmse 值对参数管道进行排序。该算法优于行业中的大多数算法,因为它在多种算法上接受训练,并在训练期间选择最佳算法,并通过在验证集(算法从未训练过的数据)上评估它们来从网格搜索中获取参数。最后用网格搜索得到的最佳参数进行预测。

证明解决方案有效

下图 4 显示了 AP 付款的移动窗口预测,包括 COS 加上未结库存和未来指标。

Figure 4

当前状态

该模型目前正在生产中,为 AP 团队提供预测,并帮助惠普财务部门进行预算分配。

参考文献

https://research.fb.com/prophet-forecasting-at-scale/

https://arxiv.org/ftp/arxiv/papers/1302/1302.6613.pdf

“内部”利用 A/B 测试的新想法

原文:https://towardsdatascience.com/a-novel-idea-of-utilizing-a-b-testing-internally-63039679869b?source=collection_archive---------31-----------------------

一份数据驱动且易于遵循的指南,用于衡量程序变更的内部影响。

最后,辛苦的工作是有回报的时候了:作为一名数据科学家,你帮助业务团队开发了一个先进的数据驱动的决策工具,预计将提高整体工作效率,并为具体的业务问题提供建议。然而,衡量这些巨大影响的最佳方式是什么?

这正是我的实习团队面临的情况,因为我们正在与我们的客户 Hilti 结束为期一年的分析项目。幸运的是,有了 A/B 测试的背景知识,我找到了一种新颖而适用的方法。

什么是 A/B 测试?

A/B 测试是一个常用的过程,用于隔离和测试营销中的因素以及网站内容的影响[1]。例如,为了确定添加“下订单”按钮的有效性,公司可以利用 A/B 测试。不同版本的网站将被随机分配给用户,并根据用户的反馈,如退房率,公司可以微调盈利能力和客户体验。

那么,为什么 A/B 测试非常适合我们项目的测量呢?

首先,我们拥有大量受众,因为喜利得北美所有办事处的销售代表都将使用这一新工具。

第二,我们自然有两个版本的“产品”,即旧版本和新版本的定价工具。过去,喜利得的财务和销售代表依赖 excel 表格来评估报价;现在他们配备了更强大的数据和推荐工具。

喜利得的财务和销售代表过去依赖 excel 表格来评估报价;现在他们配备了更强大的数据工具。

这里稍有不同的是,我们假设该工具将对决策和收入的整体有效性产生积极影响。这也被称为测试的“替代假设”。

熟悉了背景之后,我先带大家看一个设计实验的一般流程。

1。选择主题:我们希望通过什么水平来显示差异?

通常,在一个网站层面,我们必须决定是否要显示不同用户或不同网站访问之间的差异,等等。因为我们想要隔离控制组和测试组单元,这样控制组中的用户不会碰巧发现差异并因此冲淡结果。

在这种情况下,我们考虑在办公室层面进行实验,这样一个办公室的人只能使用一种决策工具,但一个城市的不同办公室可能会收到不同的工具。

2。选择人口

我们需要决定实验的作业水平。在这种情况下,我们关心的是选择哪些城市来进行分析。这可以直接影响显著性结果。鉴于核心市场和非核心市场的销售业绩差异很大,我们将分别基于核心市场和非核心市场来分析结果。

3。持续时间

实验的持续时间受多久能观察到效果的影响。在商业场景中,持续时间非常重要,因为总体市场趋势和季节性会极大地影响结果。

在这种情况下,我们同时测试决策效率和收入增长。对于第一个指标,可以每天快速观察,我们将持续时间选择为 1 天,也可以在不同的工作日重复实验,比较一致性。对于第二个指标,考虑到销售的每周季节性,我们将选择一个更长的持续时间为 1 个月。

4。尺寸

一般来说,对于具有不确定性的变更,我们会限制该变更的暴露程度。我们将确定实验的最小有效规模,这样我们既可以避免意外风险,又可以得到可信的结果。在这种情况下,为了计算出我们需要邀请多少销售代表来进行工具变更,我们需要提前决定测试的功效(1-β)、显著性水平(α)、有效规模和基线指标 [2]。为了简化这一过程,人们将使用已有的工具,如 Evan Miller 的“ A/B 测试计算器”。通常的做法是将检验的功效设置为 80%,显著性水平为 1%或 5%,对应于 90%和 95%的置信区间。由于我们只测试工具的正面效果,我们将选择单面作为参数(当我们考虑平等/不平等问题时,我们将选择双面)。

此外,由于我们对我们的新工具相当有信心(我们已经在研究上花了很多钱),我们将选择整个人口作为样本量。因此,我们通过使用最大的样本量获得了最大的可观察期望效果。

该进行分析了!

但是等等等等!我们需要首先做一个健全性检查,检查那些预计不会改变的指标。如果他们也发生了变化,这是一个消极的迹象,表明测试结果不可信,你可能想检查一下环境的设置,看看是否有巨大的影响因素改变了所有的结果。

在这个具体的例子中,我将选择雇员的工作时间、建筑行业的股票指数、电动工具的平均市场价格作为不变的度量。

如果健全性检查的结果令人满意,我们可以继续进行测试的有效评估。这将包括总体显著性测试和符号测试。

在这种情况下,总体显著性测试是将实验中涉及的所有城市相加的结果,并使用估计的置信区间评估控制/实验组之间的差异。

感谢成熟的在线计算工具,我们只需输入结果就可以得到估计的置信区间[3]。你也可以通过计算混合概率和标准误差来得到这些。

符号测试是关于结果频繁发生的可能性。例如,如果我们在 20 个城市进行了一项实验,并获得了 20 个积极改善结果中的 20 个,这种情况的可能性有多大?我们可以更好地了解我们对自己的发现有多大的信心。

最终,一切都是关于迭代,并根据结果采取行动。希望我们的新决策工具将显著增加花费在折扣决策上的时间,并帮助喜利得产生显著更好的收入!

参考

[1]https://towards data science . com/ab-testing-in-real-life-9b 490 B3 c50 d 1

https://patents.google.com/patent/US7975000

[3]https://split metrics . com/blog/mobile-a-b-testing-statistical-significance/

https://www.evanmiller.org/ab-testing/sample-size.html

https://classroom.udacity.com/courses/ud257

数字事件:广播

原文:https://towardsdatascience.com/a-numpy-affair-broadcasting-ead20d9661f?source=collection_archive---------21-----------------------

本文探讨了 NumPy 科学计算包中使用的广播概念。

我们将通过给出一个简单的定义来介绍广播的概念,并通过一些例子来说明如何利用 NumPy 数组在 Python 中实现广播。我们将提供更详细的解释,以及更深入的定义,广播是什么,它的规则,好处和限制。

广播是 NumPy 中采用的方法,用于对不同维度的数组执行算术运算。加法、乘法、减法等一般算术运算。倾向于在对大小不同的数组执行操作之前广播数组。

为了给上面的定义提供一个推理的上下文,下面的代码描述了一个算术运算在没有广播的情况下是如何工作的示例#1 和示例#2 中示出了相同的算术运算,但是这次使用了广播。

例子# 1——一个没有广播的世界

import numpy as npa = np.array([1,2,3], dtype=float)
b = 5
c = np.empty([3])for idx, i in enumerate(a):
    c[idx] = i * bprint(c)
>> [5\. 10\. 15.]

在例#1 中,我们有一个包含三个元素的 NumPy 数组:1、2 和 3;这个数组被赋值给变量“a”。变量“b”被赋给标量 5,而“c”被初始化为一个包含 3 个元素的空数组。“c”的形状是“a”和“b”之间算术运算结果的预定预期形状。

所执行的算术运算是乘法。在这个操作中,标量“b”乘以数组“a”中的每个元素。用更专业的术语来说,我们在变量‘a’和‘b’中保存的值之间执行一个元素式的操作。

为了执行基于元素的操作,我们遍历数组“a ”,并将每个元素与“b”中保存的标量相乘。运算结果放在变量“c”中“a”内元素的相应索引位置。所以“a”中索引 0 的元素(a[0] = 2)和“b”中保存的标量的乘积将被放在“c”中的索引 1 处(c[0] = 1* 5 = 5)。

例子# 2——一个有广播的世界

import numpy as npa = np.array([1,2,3], dtype=float)
b = 5
c = a * bprint(c)
>> [5\. 10\. 15.]

在示例#2 中,我们可以看到我们编写的代码更少,并且我们不需要循环来实现与示例#1 相同的操作结果。这是因为利用广播来执行算术运算。

上图直观地描述了例 2 中发生的情况。数组和标量之间的算术运算是解释广播如何工作的最简单的方法。在示例#2 中,分配给变量“b”的标量值 5 已经“广播”给变量“a”中数组的所有元素。通俗地说,值 5 已经被复制了几次,以匹配数组“a”的形状的维度,从而为操作的执行提供合适的条件。

更有目的和更直观地重新定义广播,我们可以得出如下描述:广播是 python 中使用的一种方法,它为数组操作提供了一个包装器,通过向量化实现了基于循环的操作的优化。

【包装器】指的是通过广播进行的操作是通过 python 抽象出来的,因为实际执行是在一种更低级的语言中进行的,即 C.

向量化指的是对几个元素进行操作,而不对操作进行任何修改。该运算可以是示例#2 中所示的乘法算术运算。

前面,我们已经说过,示例#2 中的标量值是“复制的”,以匹配变量“a”中的数组的维度,目的是使两个数据具有相同的维度,从而实现适当的元素式操作。这并不完全正确。

发生的不是复制,而是扩展维度上的迭代器实际上并没有移动,或者说是迭代。为了更简单地描述正在发生的事情,标量“5”或任何数据值,无论是一个数组,只要被扩展以满足另一个数组的维数,就具有一个在广播操作期间不移动的迭代器。这是因为变量“b”中标量 5 的迭代器的步距在 NumPy 内核中被设置为 0 。下图显示了变量“a”和“b”中保存的数据值之间的迭代运算的时序,同时显示了每个时间步的运算结果。

1st Iteration

2nd Iteration

3rd Iteration

现在我们在某种程度上理解了 NumPy 中的广播是如何工作的。为了进一步了解什么是广播以及如何利用广播,我们将探索支持适当广播的规则和条件,以及如何利用广播的实际例子。

播出规则和条件:

要将一组阵列视为“可广播的”,需要满足一组条件。

  1. 数组的形状相同,或者两个数组的最终尺寸匹配
  2. 如果一个数组与另一个数组的维数不同,那么维数较小的数组将被扩展 1,直到两个数组的维数相等
  3. 如果两个数组是可广播的,那么维度大小为 1 的数组的行为方式是使维度较小的数组能够通过复制扩展到第二个数组的长度。

条件#1

# Condition 1: The shape of the arrays are the same or the ending dimensions for both arrays matchx = np.array([3,2,1])
y = np.array([6,5,2])
z = x * yprint(x.shape)
>> (3,)
print(y.shape)
>> (3,)
print(x.shape == y.shape)
>> True
print(z)
>> [18 10 2]

条件二

x = np.random.randn(4,3)
y = np.arange(4).reshape((4,1))
print(x.shape)
>> (4,3)
print(y.shape)
>> (4,1)
z = x * y
print(z)
>>[[-0\.         -0\.          0\.        ]
 [ 2.2984589   0.27385878 -1.17348763]
 [-1.96979462 -4.9748125   0.65956746]
 [-1.24697399  0.80710713  1.61002339]]

条件#3

x = np.random.randn(5,4)
y = np.random.randn(1,4)# The array 'x' has a length of 5 and the array 'y' has length of 1, by following condition 3, the array 'y' has been stretched 5 times to match the array 'x' during broadcasting.print(len(x))
>> 5
print(len(y))
>> 1
print(x + y)
>>[[-0.99329397 -0.98391026  0.85963453  0.28137122]
 [-2.17210589  0.99278479  1.98294275  1.11116366]
 [ 0.92228273 -0.39603659  1.99637842  2.31311734]
 [-1.29068518  0.22292541  1.56178367  2.07585643]
 [ 2.42435639 -0.07977165  0.28020364  1.42663066]]

最后,广播在效率方面提供了一些好处,因为广播中发生的循环是在 C 中发生的,而不是在 Python 中;这意味着指令在 CPU 中执行之前不会被解释,从而提高了效率。此外,正如前面说明广播如何工作的图表所示,我们可以观察到广播提供的内存效率,因为我们没有制作不必要的数据副本。

广播在实践中是有用的,尤其是在数据分析方面。一个例子是,当承担贬低数据的任务时,我们可以利用广播。贬低数据是通过用数据集分组的平均值减去数据集的每个元素,使一组数据集的平均值为零。代码片段提供了这是如何实现的。

# Broadcasting can be used for demeaning data.
# Demeaning is the process of making the mean of a group of data zero by subtracting each element of the data by the mean of the grouped data.arr = np.array([[1,2,3],
                [4,5,6],
                [7,8,9],
                [10,11,12]])
# Take the mean of each column within the array
arr_mean = arr.mean(0)
# Now we use broadcasting to perform element wise subtraction between the array and the mean
demeaned_data = arr - arr_mean
# To prove that array has been demeaned, we should get a mean of zero for each column when computing the meandemeaned_data.mean(0)
>> array([0., 0., 0.])

请随意从下面提供的链接了解更多关于广播的信息。

[## 通用功能(ufunc) - NumPy v1.17 手册

通用函数(或简称为 universal function)是一种以逐个元素的方式操作的函数,支持数组…

docs.scipy.org](https://docs.scipy.org/doc/numpy/reference/ufuncs.html#broadcasting) [## 词汇表-NumPy 1.17 版手册

沿轴为具有多个维度的阵列定义轴。一个二维数组有两个对应的…

docs.scipy.org](https://docs.scipy.org/doc/numpy/glossary.html#term-vectorization) [## NumPy C 代码解释- NumPy v1.13 手册

通用函数是可调用的对象,它接受输入并通过包装基本的一维循环产生输出…

docs.scipy.org](https://docs.scipy.org/doc/numpy-1.13.0/reference/internals.code-explanations.html#broadcasting)

无纸化假期

原文:https://towardsdatascience.com/a-paperless-holiday-2b59b0b98b1f?source=collection_archive---------23-----------------------

自动化示例

使用 Python 发送贺卡

Photo by Aaron Burdon on Unsplash

假日是温暖和充满爱的季节,但这也意味着包装纸、贺卡和信封等会产生大量废物。

“美国人在感恩节到新年期间扔掉的垃圾比一年中的其他时间多 25%。额外的废物相当于 2,500 万吨垃圾,或大约每周额外 100 万吨”。— 斯坦福大学

缓解这个问题的一个解决方案是发送电子贺卡,而不是纸质贺卡。这将节省不必要的纸张浪费和金钱。今年,在 Python 的帮助下,我们能够向全球 100 多个家庭成员和朋友发送带有个性化信息的贺卡,并且实现了零纸张浪费。

联系人名单和贺卡

要管理联系人,您可以使用 Excel 或 Google Sheet,无论哪种对您来说更简单。我的只有三个栏目,“电子邮件”、“问候”和“信息”。电子邮件列包含收件人的电子邮件地址。“问候”栏是您希望如何问候他们,最后,“消息”栏可以包含任何个性化的消息,如果您愿意的话。如果没有,就留空白。

Contact List

至于制作圣诞卡,有很多应用程序可以帮助你制作自己的圣诞卡。今年,我用一款名为“InstaMag”的 iPhone 应用程序制作了我们的地图

现在我们有了联系信息和圣诞卡,我们可以将它们加载到 Python 中。确保将文件与代码保存在同一个文件夹中。

import files

步骤 2 设置 SMTP 服务器

我们将使用 SMTP 服务器连接到您的电子邮件服务器。请注意,如果您有 Gmail,您需要将 设置为允许不太安全的应用 打开,这可能会导致安全问题,并使其他人更容易访问您的 Gmail 帐户。有些人建议为 Python 开一个新的 Gmail 账户,只是出于安全考虑,但对我来说,这次我只用了我的 outlook 账户,因为我不会用它做任何重要的事情。另一个选择是在发送电子贺卡时打开设置,然后在发送完毕后再次关闭。

set up server

编写信息并发送电子邮件

有了 Excel 文件中的联系信息,我们可以遍历提供的电子邮件地址行。如果没有提供个性化信息,邮件正文将是“圣诞快乐,新年快乐!”。如果电子表格中有个性化消息,那么它将被放在正文中。一旦我们将正文和圣诞卡附加到邮件中,我们就可以发送电子邮件了。

write message

希望这篇文章对你有用。节日快乐!

holiday.py

资源

  1. 用 Python 发送电子邮件

机器学习实用初学者指南

原文:https://towardsdatascience.com/a-practical-beginners-guide-to-machine-learning-dcc9cf5c692b?source=collection_archive---------6-----------------------

本文将试图详细介绍简单神经网络的工作原理。同时也让你看到了让他们尽其所能的内在魔力。我会尽可能地减少数学的使用,让那些没有很强数学背景的人觉得事情不那么复杂。即使你知道基础知识,也要从头开始阅读这篇文章,因为它会让你熟悉我决定在这篇文章中采用的方法。它的每一点最终都和代码一样重要。快乐学习

所以在看到所有关于人工智能的宣传后,你决定自己开始使用人工智能。让自己成为私人助理,成为托尼·斯塔克,这个主意听起来很酷,对吧?是的,相信我,我已经经历过了。虽然这很有趣,但还是要开发一些聊天机器人 api,比如脸书信使一号,上传一堆恶心的科幻台词让你的机器人说,几周后惊奇就结束了。而且这个机器人可能会像你挑选的大多数其他酷项目一样被遗忘。

或者,您可能是为您的项目选择了 scikit-learn 或 tensorflow 等库的酷孩子之一。好吧,入门教程可能已经用完了,你还想要更多…

那我们该怎么办?一旦进入数学领域,大多数教程听起来都很复杂。什么是梯度下降来着?这个 sigmoid 函数是什么?这些拉丁语在我的英语里干什么!?!

因此,对于我们这些几乎不会集成函数的人来说,这里有一个指导来开始学习机器学习的数学:

线性代数:回归之类的概念需要你对线性代数有所了解。你不需要掌握每一个概念,只需要知道发生了什么和为什么。

统计和概率:你一定在任何 ML 视频中每隔几秒钟就听到“预测”这个词,所以概率显然是一个要求。建议你把遇到的所有公式和概念做一个备忘单,以供参考。记住你不是在考试(或者你是?!)所以还好。现在,理解图形是你绘图和处理数据的必要条件,所以练习和概率是一样的。

那我应该回到大学吗??

不完全是,当然这些在你的大学时代一定已经涵盖了,但这并不意味着你必须回到大学。我建议去看看可汗学院Udemy ,那里有相当多的资源供我们这样的爱好者使用。而且质量(不是指视频分辨率)简直不可思议。如果你仍然想从真人那里上课,那就由你决定。

有没有不用数学的方法?🙄

好吧,你会在某个时候需要数学,否则很难在这里扩展和成长。所以我强烈建议至少尝试一下线性代数。因为这很简单。你可以和擅长你不知道的事情的人合作,一起工作。

现在把数学放在一边,让我们讨论一些关于“主算法”的理论。

为什么是我们的大脑??

当你看到“神经网络”这个名字时,你会有点“明白了,它是基于神经元网络的。你知道我们称之为灰质的东西。所以,如果神经元让我们变得聪明,帮助我们学习,那么它也会帮助机器,对吗?这就是神经网络背后的整个想法。但是为什么呢?我听到你在问。“人类的算术太差了!这怎么解决任何事情?”

的确,我们不擅长数学,但我们擅长的一件事是学习。

等等,我听到另一个问题。“难道计算机没有足够的内存来存储几乎任何东西吗”。有道理。但这也无助于这项事业。当然,我们可以将互联网上所有可用的信息加载到某个数据中心,然后就可以收工了。但这真的是解决方案吗?我的意思是,这和让机器记住所有东西不是一样的吗?对于任何一个在数学考试中尝试过这种方法的人来说,他们可能会意识到这有多糟糕。

所以在这一点上,我们有一台价值数十亿美元的计算机,它可以给你关于任何事情的信息,同时消耗足够的能量来运行这个星球。所以现在,如果我问它毕达哥拉斯定理的意义,它会一无所知,因为它所知道的定理是这样的..

当然,它可以用公式解决你所有的问题,但是文字问题怎么办?这里有一张来自可汗学院

现在,对于所有的黑客来说,很容易编写一个脚本来解决这个问题。但是另一个概念呢?这真的是机器在做它应该做的工作吗?所以在这一点上,你是分解这个问题的老师,给你的学生(机器)一些数字,让它求解边长。我希望这能澄清为什么记忆不是解决办法,也不是纯粹的算术优势。你也许能够完成最难的计算,但是如果你不能理解这个问题并从中获得你需要的数据,那还有什么用呢?

在理解了采用大脑如何工作的想法背后的动机后,我们选择这条路线的原因就很清楚了,现在在下一节中,让我们尝试比较“人工神经网络”和它们的生物学对应物。

碳对硅/人对机器。

所以,假设你已经理解了为什么我们用大脑来模拟神经网络,我现在将深入解释和比较这两件事,让你更好地理解神经网络是如何工作的,而不需要太多的数学知识。这是神经元的样子..

除非你有神经科学的学位,否则那东西很可能会让你头晕。所以对于我们这些几乎分不清动脉和静脉的人来说,这里有一个更简单的版本…

现在这里有一个神经网络中神经元的比较…

这里是它是如何被简化的,橙色的圆圈是魔法发生的地方,它可以被称为''。左手边的黑线是所谓的“树突”。它们基本上是分支,将输入/信息传递给神经元。“轴突末端是右手边附近的黑线,它将输出信号从神经元带到下一个神经元。

总的来说,神经网络(生物网络)看起来像…

很乱,对吧?这是机器学习中使用的神经网络的样子…

现在,与它的灵感相比,人造的看起来不那么令人生畏了,对吗?我们只是把大脑中神经元的所有复杂性分解成一个简单的球杆模型。记住所有这些图片,因为在下一节,我将进入这个东西实际上是如何工作的,同样尽可能少用数学。

神经网络剖析:工作

现在,虽然这个模型有助于进行比较,但为了让我们理解它是如何工作的,我们需要在混合中加入一些数学,毕竟,如果你想弄清楚发生了什么,你需要数学。

好的,这是数学化的版本…

X1Xn 代表输入。(让它们是 0 到 1 之间的数字)

σ指所有输入的总和

所以σ给我们所有输入与其对应权重的乘积之和。

现在,让我们试着理解这一切,这里有一个例子。如果你正在纹身,疼痛开始会有点缓慢,然后持续加剧。但是你如何衡量痛苦呢?我们将事情与疼痛的程度进行比较,我们会说“比打针还疼”,那是什么感觉?比刺还痛。等等什么?

因此,如果我严格要求你用 1 到 10 的等级来评价它,它会类似于上面的一些东西。现在,你的神经元会收到这些强度为 2 的疼痛信号,它们会通过网络传递这个值,直到它到达你的大脑,因为你的大脑对强度为 2 没有问题,所以你不用做太多。但是一旦它超过了一个阈值(比如说 5),你的大脑就会强迫你把手拿开。这是你对 5 级以上疼痛的反应。

现在,你的整个手臂会从每个疼痛点发出疼痛信号,比如说从“n”个地方发出,每个信号的值是“X”。所以你的神经元会将所有的信号/X 值相加得到你的总疼痛。因此总和为''。现在这个σ作为一个信号被发送到你的大脑,然后它发回关于该做什么的信息,我们称之为输出。

看,现在也没那么难了,是吗?现在你明白了为什么所有的 x 都存在,以及有什么作用。那重量呢?

重量是奇迹发生的地方…

每次输入与相应的权重相乘时,其值都会根据权重值增加或减少。这里有一个例子来解释为什么这很重要…

现在假设你正在学骑自行车。

现在,首先我们从卸下训练轮开始,这是你第一次学习平衡,根据你滚动的路面,对不起,你必须做一些微小的调整以确保你不会摔倒。你可能会发展出一些方法,比如用你的腿来充当配重或手等等。首先,你从随意的动作开始,直到你找到正确的动作。这些调整会让你对以后的道路更加敏锐。权重也是一样,首先权重是随机分配的(有时甚至设置为 1)。稍后,根据输出,使用一些技术优化权重,比如我在开始时提到的梯度下降。

经过所有这些修改,你的算法已经准备好帮助人类对抗癌症或者让地球摆脱癌症(看我在那里做了什么?)

这仅仅是个开始,还有更多的内容要介绍,还有更多的内容要改进,还有更多的内容要替换。所以继续读下去。

接下来,我们将建立自己的神经网络!👏👏👏为自己能走到这一步而感到自豪吧!现在真正有趣的事情开始了。

让我们建立天网:建立你的第一个神经网络

让我们建立天网:建立你的第一个神经网络

在上一节中,我们讨论了神经网络的内部工作方式。现在我们已经了解了数据是如何传递的,让我们试着构建一个简单的神经网络。

我们将使用 Python 进行编码。

在我们开始之前,让我们先来看看你开始编写网络代码所需要的东西,除了我们一直在做的审判日的梦…

  • 先从 python 说起,头此处。选择您的操作系统并按照说明进行操作。
  • 接下来,让我们来编写代码,我建议编写类似于 VSCodeAtom 的代码。如果你刚刚开始,你可以使用记事本++ T5。

现在完成了所有这些,让我们直接进入编码吧!一定要喝一杯…

那么,我们就从进口开始吧…

numpy 是一个库,顾名思义,它是关于数字的。从这里,我们将导入函数,让我们计算指数函数,点积,并创建数组。
random 不是随机导入,random 非常重要,因为它是一个包含生成随机数的函数的库。我们稍后将讨论为什么我们需要随机数……在我们开始设计之前,让我们看一下我们试图构建的网络。

所以我们有 4 个输入和 1 个输出。我们将用矩阵来表示输入和输出。这将会给我们一些像…

这是整个程序的代码,我们将把它分解一下…我建议读一遍,试着理解整个流程。

现在,这看起来令人生畏,但一旦你开始分解它,它就非常简单…首先,让我们看看我们的输入和权重是如何相互作用的。

我们只对 2 个矩阵进行点积运算。

现在没那么难了,是吗?向前到下一个然后…

对于权重值,我们最初为它们设置随机值,而不是每次都写下随机值,我们利用 random (不是随机库,是‘随机库’… tumble weed rolls )库。

我们在这一点上使用激活函数。激活函数将你的输出从一个神经元挤压到一个数值范围。我们使用的是 Sigmoid 函数,它会给出 0 到 1 范围内的输出。这使得处理输出更容易,甚至当你使用多于一层时计算也更容易。

现在我们已经理解了数据的初始化,让我们试着理解一个模型是如何被“训练”的。永远记住,你不能一下子教会你的狗所有的技巧…

你必须给它一些时间,坐下来进行多次会话,除非你的狗一次就能得到它,因为它可能是来自未来的终结者机器人🤔

即使是机器也需要时间和练习才能把事情做好。他们必须接受 n 次训练。所以我们希望我们的算法运行几次,太多也不好。这个你得通过一些实验来弄清楚,这里我们要做 10000 次。

现在,用我们的狗做类比,每次你告诉你的狗如何去捡,你可能都得自己去捡。然后看看狗是怎么做的。然后根据它犯的错误,你试着纠正它。机器也是一样的(至少当你在进行监督学习时)。我们计算误差,这是从公式中获得的:

误差=期望值—实际值

我们在计算误差,就像你知道你的狗没有追着球跑,所以你要让它知道这是它犯的错误。同样,我们知道期望值和实际值之间存在差异,所以我们也必须纠正这些错误。我们通过调整权重来做到这一点。我们遵循另一个简单的公式…

调整=误差输入梯度**

****梯度,是一个告诉我们对当前重量值有多确信的数字,它是通过计算您正在使用的激活函数的导数获得的,这里是 Sigmoid 函数。

现在,看看上面的代码…

似乎简单多了,不是吗?这是相同的代码,去检查一下…我已经将它打包成模块,因为将代码转移到生产或用作导入更容易,如何编写代码取决于你…现在,这里有一些你可以尝试的东西:

  • 尝试不同的训练长度
  • 尝试固定重量而不是随机重量
  • 并尝试添加更多数据。

干得好,一路走到了这里!🙌但是它还没有完成,虽然这个例子非常简单,尽管它需要这么多的解释才能理解,但它不会对你有真正的帮助,除非你真的拿起铲子,深入了解它的工作原理。因此,在下一节中,我们将接触一些 Python 和数学知识。我保证会很容易。

神经网络剖析:神经网络的内部运作

在这之前的部分,我们学习了如何建立一个简单的前馈神经网络。我们把一切都表示为一系列矩阵运算。我们的输入数据是矩阵的形式,我们的输出也是矩阵。如果你打算分解它,弄清楚学习实际上是如何发生的,那么来回的矩阵运算可能会让你感到困惑,这可能会令人望而生畏,并让你害怕自己不理解你一直在输入的代码…

所以,让我们把一切都形象化,然后,希望我们能理解这些东西实际上是如何从输入到输出的!戴上你的数学帽子,从现在开始,事情会变得很严重!

让我们从输入矩阵开始。这是一个 4x3 的矩阵,这意味着它有 4 行 3 列…

我们的输出矩阵是一个 4x1 矩阵的形式…

权重矩阵是一个 3×1 矩阵…

现在,在第一步中,当输入数据通过以下代码输入到网络中时:

就矩阵运算而言,它看起来像这样…

我们的输入矩阵和权重矩阵之间的点积产生了下面的结果,我们现在称它为输出矩阵…

现在,到了误差计算这一步,永远记住这一点,

误差=期望值—实际值

上面代码的矩阵运算是…

接下来是突触权重矩阵值的调整…

让我们从“self.sigmoid_derivative(output)”开始,一条一条的来破这个。我们计算上面获得的输出矩阵中每个元素的 sigmoid 导数。

现在我们要把上面得到的矩阵和包含误差值的矩阵相乘……(不要,这是元素乘法!)

接下来是输入矩阵的转置和上面得到的矩阵之间的点积…

对权重矩阵的调整如下…

哇,那里有很多数学😰,眨眼就错过了!

但是,等等,还有一个等式!这有助于你做预测,所以开始吧。当传递新的输入值时,该矩阵在训练迭代后用调整后的权重值进行运算…

这就是全部了。仔细想想,这很简单,不是吗?建议你在建立网络时记下矩阵运算,这不仅能让你了解网络内部的工作原理,也是排除错误的好方法。

现在,当你调整网络中的某些东西时,你已经知道你在做什么了,你可以知道你是否使它在计算上更昂贵或更复杂,而没有好的回报…

所以让我们开始调整,并与我分享你的结果😁!

谢谢你坚持到最后!希望这篇文章能帮助你了解人工智能。请留言让我知道你的想法👇!

【sushritpasupuleti.blogspot.com】最初发表于。****

有效数据预处理的实用对话

原文:https://towardsdatascience.com/a-practical-dialogue-for-effective-data-preprocessing-147cdc000f6c?source=collection_archive---------31-----------------------

3 个基本的数据清理函数,2 个奇怪的字符&一个可怕的数据集

阿基米德:请坐伟大的列奥尼达,我能为你做什么?

列奥尼达:我需要一个机器学习模型来告诉我在我的公路车上开启超能力的秘密。

冷静点,年轻的巴克,我不是魔术师。

L:指向手表但是你可以用这个,不是吗?

答:嗯,一块智能手表。

L: 不仅仅是“智能手表”Archemides!这个设备可以让我跟踪心率——在我训练的时候以及一天中的其他时间。

等等,你的意思是告诉我你的手表让你知道你什么时候……活着?

先生,你是一个小丑。

答:数据科学家其实。虽然有时候我也分不清。

T21:让我们看看吧。我已经使用这个非常有用的 github 库在本地转储了我所有的 Garmin 会话数据集。

答: 机器学习是个热门话题但是你知道什么比 ML 更热吗?快速获得结果。

我只想做 ML。

答:T34 毫升?听着,现实是你可能不需要它来提取你想知道的东西。

告诉我——你的目标是什么?

L: 我要超车,不是被超车!

来吧,列奥尼达,给我一些我能做的事。

L: 好的……在更长的时间内持续产生更高水平的力量。我想知道怎样训练才能最好地做到这一点。

答:太好了。成功的项目始于对目标的思考。不管我们是否需要参考一个 ML 模型,保证数据干净、一致、准确是一个必要的前提【0】。第一步是进行一次简单的数据质量检查【1】。

你是怎么做到的?

答:让我们为您的 Garmin 会话数据集快速浏览 3 个基本的清理函数。

**import pandas as pd
import os
import datetime as dt
from datetime import datetime
import matplotlib.pyplot as plt
import gc_download

raw_session = gc_download.load_sessions()[0]
print(raw_session.head())**

我应该在这里看什么?

****答:正是。对于知识发现来说,现在还没什么用。

L:数据清洗预处理 的作用是然后使原始数据集有用?**

答:**没有正式的定义,但是我所说的有用的是两个一般的东西。首先,要习惯数据集【2】的 变异和质量。第二,安装一个 标准数据结构。 满足你的分析要求。分析是一个广义名词。它融合了基于规则的,机器学习,深度学习,你会明白的。**

继续,这对我的数据集意味着什么?

很明显,原始数据集包含了太多的信息,所以…

答:分离出你需要的信息。(步骤 1)

*details = raw_session['details']
raw_df = pd.DataFrame(
           [r['metrics'] for r in details['activityDetailMetrics']],
           columns=[r['key'] for r in details['metricDescriptors']])
print(raw_df.head())
print(raw_df.columns.to_list())*

答:从原始数据集中分离出“activityDetailMetrics”和“metricDescriptors”后,我们剩下 5 行 x 7 列有希望的信息。让我们保留' directTimestamp '和' directHeartRate '。

L: 和‘directAirTemperature’。

答:为什么不。

*c_name =['directAirTemperature','directTimestamp','directHeartRate']
c_rename = ['AirTemperature','Timestamp','HeartRate']
data1 = raw_df.copy()
data1 = data1[c_name]
data1 = data1.rename(columns={a:b for a,b in zip(c_name,c_rename)})
print(data1.head())*

我很高兴我们重新命名了那些栏目,但是在这里,回答我一些问题…

那究竟是什么格式?!(步骤 2)

*data2 = data1.copy()
data2['Timestamp'] = [datetime.fromtimestamp(int(i/1000)) for i in data2['Timestamp'].to_list()]
data2.set_index('Timestamp')
data2[['HeartRate','AirTemperature']] = data2[['HeartRate','AirTemperature']].astype('float32')*

答: Unix 时间戳!数据之神以这种格式读取时间。它们以秒或毫秒来标记自 1970 年 1 月 1 日以来的时间长度。

Garmin 以毫秒为单位记录这个时间戳。然后我们将这个时间戳除以 1000,对吗?

答:正是。更一般地说,没有必要花太多时间格式化。只要学习算法能够解释输入,并且我们有一个映射,这就足够了。

L: 如何知道自己是否过度格式化?这听起来像是耐心的作用。

答:某种程度上来说,是。不是耐心格式化数据集,而是耐心等待代码运行。

L: 什么意思?

答:格式化归结为一个 可读性 vs 代码性能 的权衡。在“心率”和“气温”的情况下,将这些变量的数据类型设置为float 32【3】会在不影响精度的情况下分配较小的存储量。

*print(data2.head())*

L: 众所周知,提高性能而不牺牲精度是一张金奖券。但是我们是不是错过了什么?

答:那是什么?

L:缺失数据,得到了吗?!(第三步)**

我真的很担心你。

我担心你的幽默感,阿基米德。现在告诉我丢失的数据。

答:叹气一般来说,处理缺失属性值的方法属于两种思想流派之一[4]。第一个是 阴错阳差的失踪。 最常见的情况是,在一个较大的属性和值块中对属性进行删除替换

L: 第二个呢?

答: 故意遗漏 。进入“不在乎”假设。当被认为重要的信息只在某些群体中出现时。通过将数据块重新布线到 属性-值 对来处理。

第二类与此无关。这个装置是用来记录的。任何丢失的数据都是硬件问题。

答:gone _ missing()函数将处理丢失的数据。

L: 地址 —你的意思是删除整行条目吗?

答:不,反正不是没有想过。我们现在有一个选择 删除 或者 重建【5】。如果我们遗漏了数据集的一个边缘案例,我们将删除整个条目。

L: 数据集的其余部分呢?

答:直接删除包含任何缺失变量的行是一种保守的方法。插值也是一种选择。心率是一个缓慢发展的过程,这意味着对于任何时间戳,都有一个可能的 bpm 值的紧密间隔。

L: 对于单个丢失的时间戳来说,这可能行得通。但是对于连续缺失条目,我宁愿采取保守的方法。30 秒对于心跳加速来说已经足够了。

答:让我们这样做,线性插值或删除由一个开关控制。

*data3 = data2.copy()
useInterp = False
if useInterp:
     data3 = data3.interpolate(method='linear',        limit_direction='forward',limit_area='inside',axis=1)
data3 = data3.dropna()
data3.describe()*

244 次观察,平均 125.5 bpm,最大 151bpm。简洁的总结但是要适可而止。给我看看 mon-…图。给我看看情节。

*def uni_plot(df):
    fig, ax1 = plt.subplots()
    color1,color2 = 'tab:red','tab:blue' ax1.set_xlabel('Timestamp')
    ax1.set_ylabel('Heart Rate (bpm)',color=color1)
    ax1.plot(df['HeartRate'].index, df['HeartRate'], color=color1)
    ax1.tick_params(axis='y', labelcolor=color1)

    ax2 = ax1.twinx()
    ax2.set_ylabel('AirTemperature (C)',color=color2)
    ax2.plot(df['HeartRate'].index,df['AirTemperature'], color=color2)
    ax2.tick_params(axis='y', labelcolor=color2)

    fig.tight_layout()
    plt.show()uni_plot(data3)*

李:现在我们正式开始工作了。

我们还没完呢。离群值。

L: 为什么会有异常值?该设备正在测量我的心率,为什么这些值会是错误的?

*data3.boxplot(column=['HeartRate'])*

答:离群值并不总是。他们强调不同于常规的观点[6]。高于或低于标准的所有点都以圆圈突出显示。让我们看看所有会话的情况。

L: 有哪些剧情给我看?

答:粉色——传统箱线图。大多数离群值位于数据集的低端。

L: 最下面的两个地块呢,数据是怎么处理的?

答:补救异常值的一个常用方法是设置阈值。平均值标准偏差的倍数。在它之外的所有数据点将被递归地删除。在蓝色图中,阈值是 3 个标准差,绿色图中是 2 个标准差。

L: 使用 3 标准差阈值仍会保留异常值。让我们用 2 个标准差向前看。

稍等一会儿。 并非所有异常值都是非法污染物,也并非所有非法分数都显示为异常值【7】。

T21:我认为圈子不好。你是想告诉我圆圈不是坏事吗?

答:圈子并不总是坏的。

'你到底是什么意思?!

A: 我们倒回去一点。箱线图将异常值定义为数据集四分位范围的标准差的倍数。事实上,每个方框下面都有更多的异常值,这表明数据存在偏斜。不一定是不自然的观察。

L: 那为什么截尾到 2 个标准差的时候没有异常值?

答:你自己说的——在 2 个标准差处截断。数据集已经失去了原来的形状,因为忽略了太多的点。让我们在下面想象一下。

L: Woah,这么说红点都被装箱了?这么多人?!我不喜欢这样。

答:盲目处理离群值可能是危险的。

L: 危险因为在专注于摆脱方框图的圈子时,我们没能思考那些观察结果代表了什么。出现在时段上端的圆圈代表有用的最大心率努力。我们不可能把它们扔掉。

答:你怎么看待较低的离群点?

L: 他们是数据集的人工制品。我开始手动记录我的训练,大部分时间我都有热身阶段。

但是我们真的需要包括热身数据吗?看更长的热身将会扭曲你的总结统计。这意味着会议的工作部分将被歪曲。

我无法告诉你热身在哪里结束,工作在哪里开始。让我们去掉任何低于 80bpm 的数据。这也可以捕捉 Garmin 在中途停止可靠跟踪的情况。

猜猜接下来会发生什么?

L: 剧情?

答:剧情

答:我不需要机器学习模型来告诉你你没有坚持训练。你在室内训练的次数也比室外多。

L: 这是希腊,阿基米德。我不想被战车压扁。不,谢谢你。

A: 所以你试着在健身房复制户外训练?

L: 正是。

答:事实是你没有改变室内训练的持续时间。尤其是今年。时段持续时间和心率标准差中紧密的粉红色簇代表一致强度努力的阻滞期。

L: 也就是说,相对于 2018 年,2019 年的会议强度平均水平(HRavg)变化更大。

答:真。室内会议似乎更激烈,时间更短。

嗯,当你把它画成那样的时候,就很明显了。在自行车世界,我们谈论心率区[8]。我的区域看起来像什么?

答:我们没有乳酸门槛数据,但我们可以将数据分成代理区域桶。

一个人越有耐力,就越难振奋人心。目前还不清楚更高的心率是否意味着更好的表现。性能应该由比赛结果和功率数据来衡量。

答:如果是那样的话,匆忙进入一个 ML 模型将会是时间下沉。您需要做的是丰富您的数据集,在这种情况下使用功率数据。

L: 不管怎样,需要做的事情很明显——改变室内会议的长度和持续时间。花更多时间在心率较低的区域是没问题的。你可以称之为主动恢复。

甲:我把这个留给你。

机器学习中的一个重要哲学是,人们不应该期望模型做所有困难的工作,即使是一个强大的非线性模型[2]。

答:今天,我们已经非常快速地可视化了您的完整 Garmin 会话历史,只给出了您的非结构化原始数据。

L: 对。我们已经通过 做到了 1)删除不必要的数据,2)格式化和重新索引,3)堵塞丢失的值。

是的,这些都是关键的编码任务,但是在这个过程中效率更低的环节是对话。有效的 数据清理 是关于确保原始记录符合任务特定的——不一定是通用的——指导方针。它有很多定义,但可以肯定的是,它是一个交互过程

L: 至关重要的是,它需要在领域专业知识和计算标准之间来回转换。我认识到知识发现不仅仅来自机器学习。

知识发现被定义为从数据中提取明确的、先前未知的和潜在有用的信息。[10]

不幸的是,你还不是轮子上的火箭。

但是我更有能力成为一名教师。我了解到我的室内课程并不像我想象的那样可以复制室外课程。我需要包括会话持续时间的变化,并纳入功率数据作为性能的衡量标准。我对不一致的训练更有责任感。我很惊讶我们这么快就做到了。

答:我们关注对复杂性的影响。**

阿基米德,我喜欢这个原则……现在,回到掠夺村庄和雕刻雕像的话题。

下次见,列奥尼达。

附录

[0]—https://www . kdnugges . com/2018/12/六步-master-machine-learning-data-preparation . html

[1]—https://www . kdnugges . com/2016/10/data-preparation-tips-tricks-tools . html

[2] —预测分析的基础,伍沾德,Stephen Coggeshall,2012 年

[3]——https://docs.scipy.org/doc/numpy/user/basics.types.html

[4] —处理缺失属性值,Jerry W . Grzymala-Busse,wit old J . Grzymala-Busse,2010 年

[5]—https://towards data science . com/how-to-handle-missing-data-8646 b 18 db0d 4

[6]——离群值的力量,Osborne & Overbay,2004 年

[7] —统计数据中的异常值,Barnett & Lewis,1994 年

[8]—https://www . British cycling . org . uk/knowledge/article/izn 2014 08 08-理解-强度-2 -心率-0

[9] —数据清理:知识发现的前奏,Johnathon I Maltic 和 Andrian Marcus,2000 年

[10] —数据挖掘原理,Max Bramer,2007

用 PyTorch 学习迁移学习的实例

原文:https://towardsdatascience.com/a-practical-example-in-transfer-learning-with-pytorch-846bb835f2db?source=collection_archive---------11-----------------------

如何用潜在的小数据集解决计算机视觉问题,并且不需要太多的计算机能力和专门的硬件

在这篇文章中,我们将了解迁移学习如何帮助我们解决问题,而无需花费太多时间训练模型和利用预训练的架构。为了了解这是如何工作的,我们将开发一个能够区分竖起大拇指👍拇指朝下👎以高精度实时进行。

什么是迁移学习,什么时候应该使用?

迁移学习是一种技术,在这种技术中,您可以使用经过训练的神经网络来解决特定类型的问题,经过一些更改,您可以重新使用它来解决相关的问题。例如,如果你想开发一个模型来区分汽车和卡车,使用通过 ImageNet 竞赛训练的网络是一个很好的解决方案,并应用迁移学习来微调网络以完成你的任务。

使用这种技术,学习过程可以更快、更准确并且需要更少的训练数据,事实上,数据集的大小和与原始数据集(网络最初在其中被训练的数据集)的相似性是在应用迁移学习之前要考虑的两个关键因素。有四种情况:

  1. 小的数据集和与原始的相似:只训练(最后)完全连接的层
  2. 数据集和不同到原始:只训练完全连接的层
  3. 大型数据集和与原始数据集相似:冻结早期的层(简单特征)并训练其余的层
  4. 大型数据集和不同原始:从零开始训练模型,重用网络架构(使用训练好的权重作为起点)。

在网络中,早期层捕获图像的最简单特征(边缘、线条……),而深层层在早期层的组合中捕获更复杂的特征(例如人脸识别问题中的眼睛或嘴巴)。为了微调一个模型,我们需要重新训练最后几层,因为前面几层有对我们有用的知识。

数据集的大小和与原始数据集的相似性是应用迁移学习之前要考虑的两个关键因素

迁移学习的数据收集

首先,我们需要收集一些数据。这些数据需要能够代表我们在真实情况下将要发现的所有案例。在我们的例子中,我们将开发一个能够区分拇指向上或向下的模型。以下是一些收集数据的技巧:

  • 尝试相机前面的不同位置(中央、左侧、右侧、放大、缩小……)
  • 将相机放置在不同的背景中
  • 尝试不同的环境光
  • 用双手

在拍摄快照之前,需要考虑的一个重要方面是我们将使用的网络架构,因为每个图像的大小/形状都很重要

Use both hands, try different positions, different angles…

特别是在这种情况下,我在每个班级收集了 114 张图像来解决这个二元问题(拇指向上或拇指向下)。这是一个小数据集,并且与 ImageNet 数据集(在简单特征方面)相似,其中我们要使用的网络被训练(参见下面的部分),因此,小的数据集与原始数据集相似:仅训练最后一个完全连接的层。

网络的输入层需要固定大小的图像,因此我们可以采用两种方法来实现这一点:

  • 拍摄具有所需宽度和高度的图像(通道通常为 3,因为是 RGB 颜色)
  • 拍摄图像,没有任何类型的限制,并根据我们的网络架构将它们重新采样为所需的大小/形状(在训练时间内)。PyTorch 有一个解决这个问题的方法(来源这里)。

resize a entire dataset is easy with torchvision

用 PyTorch 转移学习

PyTorch 为我们提供了几个训练有素的网络,可以下载到您的计算机上。这里的是可用的型号。出于我们的目的,我们将选择 AlexNet

每种模型在解决特定类型的问题时都有自己的优势。从图像分类到语义分割。一些比另一些更快,运行时需要更少/更多的计算能力。例如,选择 SqueezeNet 需要的参数比 AlexNet 少 50 倍,同时在 ImageNet 数据集上实现相同的精度,因此它是一种快速、较小和高精度的网络架构(适用于低功耗的嵌入式设备),而 VGG 网络架构比 AlexNet 或 SqueezeNet 具有更好的精度,但在推理过程中训练和运行更繁重。下面,您可以看到 PyTorch 在缓存目录中下载的不同网络架构及其大小。

different model sizes

到目前为止,我们只谈了理论,让我们把概念付诸实践吧。在 这个 GitHub 页面中,你有所有必要的代码来收集你的数据,训练模型并在现场演示中运行它。

首先,让我们导入所有必需的包

import torch
import torch.optim as optim
import torch.nn.functional as F
import torchvision
import torchvision.datasets as datasets
import torchvision.models as models
import torchvision.transforms as transforms

现在我们使用 torchvision.datasets 包中可用的 ImageFolder 数据集类。我们附加转换以准备用于训练的数据,然后将数据集分成训练测试

dataset = datasets.ImageFolder(
    'dataset',
    transforms.Compose([
        transforms.ColorJitter(0.1, 0.1, 0.1, 0.1),
        transforms.Resize((224, 224)),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])
)
train_dataset, test_dataset = torch.utils.data.random_split(dataset, [len(dataset) - 50, 50])

我们将创建两个 DataLoader 实例,它们提供了用于混排数据、生成批量图像以及使用多个 workers 并行加载样本的实用程序。

train_loader = torch.utils.data.DataLoader(
    train_dataset,
    batch_size=16,
    shuffle=True,
    num_workers=4
)

test_loader = torch.utils.data.DataLoader(
    test_dataset,
    batch_size=16,
    shuffle=True,
    num_workers=4
)

现在,我们定义将要训练的神经网络。alexnet模型最初是为有 1000 个类标签的数据集训练的,但是我们的数据集只有两个类标签!我们将用一个新的、未经训练的、只有两个输出(👍和👎).

model = models.alexnet(pretrained=True)
model.classifier[6] = torch.nn.Linear(model.classifier[6].in_features, 2)

现在,是时候训练神经网络并尽可能以最佳性能保存模型了。请随意尝试不同的超参数,看看它的表现如何

NUM_EPOCHS = 10
BEST_MODEL_PATH = 'best_model.pth'
best_accuracy = 0.0

optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

for epoch in range(NUM_EPOCHS):

    for images, labels in iter(train_loader):
        images = images.to(device)
        labels = labels.to(device)
        optimizer.zero_grad()
        outputs = model(images)
        loss = F.cross_entropy(outputs, labels)
        loss.backward()
        optimizer.step()

    test_error_count = 0.0
    for images, labels in iter(test_loader):
        images = images.to(device)
        labels = labels.to(device)
        outputs = model(images)
        test_error_count += float(torch.sum(torch.abs(labels - outputs.argmax(1))))

    test_accuracy = 1.0 - float(test_error_count) / float(len(test_dataset))
    print('%d: %f' % (epoch, test_accuracy))
    if test_accuracy > best_accuracy:
        torch.save(model.state_dict(), BEST_MODEL_PATH)
        best_accuracy = test_accuracy

仅此而已,现在我们的模型能够实时分类我们的图像了!

进一步工作:

为了提高模型性能,以下是一些在未来工作中可以尝试的方法:

  • 收集具有不同背景的图像来改进(概括)我们的模型
  • 从不同的人那里收集图像添加到数据集
  • 当你没有竖起或放下拇指的时候,也许可以增加第三类

[## 大卫塔纳-概述

在 GitHub 上注册您自己的个人资料,这是托管代码、管理项目和与 40…

github.com](https://github.com/davidRetana)

参考文献

[## NVIDIA-AI-IOT/jetbot

有兴趣和杰特森纳米一起做这样的项目吗?查看我们于 2019 年 5 月 16 日发布的网络研讨会!JetBot 是一个…

github.com](https://github.com/NVIDIA-AI-IOT/jetbot)

AlexNet paper

用 Docker 在 AWS 云中训练神经网络的实例

原文:https://towardsdatascience.com/a-practical-example-of-training-a-neural-network-in-the-aws-cloud-with-docker-b44a8c061e6e?source=collection_archive---------23-----------------------

如何在 AWS GPU 实例上的 Docker 内在 CIFAR-10 上的 InceptionV3 模型之上训练浅层神经网络

我的上一篇文章数据科学过程中 Docker 的用例示例是关于数据科学中的 Docker。这次我想用一个实际的例子来弄脏我的手。

在这个案例研究中,我想向您展示如何在 AWS 上 Docker 容器内的 CIFAR-10 图像上的深度 InceptionV3 模型之上训练一个浅层神经网络。我正在为这个项目使用 Python,Tensorflow 和 Keras 的标准技术栈。这个项目的源代码可以在 Github 上获得。

您将从本案例研究中学到什么:

  • 从 docker-machine 命令行设置 AWS 上支持 GPU 的云实例
  • 在您的 docker 文件中使用 tensorflow docker 图像
  • 使用 docker-compose 设置用于训练神经网络的多容器 Docker 应用程序
  • 将 MongoDB 设置为持久性容器,用于模型的训练元数据和文件存储
  • 用 MongoDB 实现简单的数据插入和查询
  • 一些简单的 docker、docker-compose 和 docker-machine 命令
  • 卷积神经网络的迁移学习

让我们定义这个小项目的要求:

  • 培训必须在 AWS 中的一个支持 GPU 的实例上进行
  • 灵活地将整个培训管道移植到谷歌云或微软 Azure
  • 使用 nvidia-docker 在云实例上激活完整的 GPU 能力
  • MongoDB 上模型元数据的持久性以实现模型的可复制性。
  • 多容器应用程序(训练容器+ MongoDB)的 docker-compose 用法
  • 使用 docker-machine 管理云实例,并通过 docker-compose 从本地命令行开始培训

让我们潜入更深的地方。

1.先决条件

  1. 安装 Docker 连同 Docker MachineDocker 组成(工具安装在 Mac 和 Windows 上的标准 Docker 安装中)
  2. AWS 上创建账户
  3. 安装和设置 AWS 命令行客户端

2.AWS 实例作为 Docker 运行时环境

要在 AWS 上训练神经网络,首先需要在那里设置一个实例。你可以从 AWS Web 控制台或者从命令行使用 AWS 命令行客户端来完成这项工作。

我用 docker-machine 命令向您展示了第三种方便的方法。该命令包装了不同云和本地提供商的驱动程序。通过这种方式,你可以获得谷歌云计算、微软 Azure 和亚马逊 AWS 的独特界面,这使得在平台上设置实例变得容易。请记住,一旦建立了实例,您就可以出于其他目的重用它。

我正在用 Ubuntu 18.04 Linux(ami-0891 F5 DC c59 fc 5285)创建一个 AWS 实例,它已经安装了 CUDA 10.1nvidia-docker 。这些组件是为培训启用 GPU 所必需的。AMI 的基础是一个标准的 AWS Ubuntu 18.04 Linux 实例(ami-0a313d6098716f372),我用这些组件对其进行了扩展。我把这张照片分享给公众,让生活变得更容易。

我使用 p2.xlarge 实例类型,这是 AWS 上最便宜的 GPU 实例。p2.xlarge 实例类型为您配备了 Tesla K80 的 GPU 能力。

docker-machine create --driver amazonec2\
 --amazonec2-instance-type p2.xlarge\ 
 --amazonec2-ami ami-0891f5dcc59fc5285\ 
 --amazonec2-vpc-id <YOUR VPC-ID>\
 cifar10-deep-learning

你需要一个 VPC 身份证来设置。您可以使用 AWS 命令来获得它:

您也可以从 AWS Web 控制台获取 VPC ID

有关更多信息,请查看带 AWS 文档的对接机。

警告:p2.xlarge 每小时收费 0.90 美元。请不要忘记在完成培训课程后停止实例

3.培训脚本

您希望使用不同的训练参数来训练神经网络,以找到最佳设置。训练之后,您在测试集上测试模型质量。这是一个分类问题。为了简单起见,我建议使用准确性度量。最后,您将训练日志、模型权重和架构持久化,以备将来使用。这样一切都是可复制和可追踪的。

你可以通过用你的浅层网络替换基本模型的顶层来进行迁移学习,然后你冻结基本模型的权重并在整个网络上进行训练。

在这个案例研究中,我的做法有所不同。我正在移除基本模型的顶层,然后将图像输入到基本模型中,并在 MongoDB 中持久化结果特性。预测比训练需要更少的计算能力,一旦提取出瓶颈特征,我可以重用它们。你在瓶颈特征上训练浅层网络。

培训脚本的输入和输出要求:

输入

Docker 容器是从 MongoDB 集合参数化而来的,其中包含一个训练会话的所有参数。

  • 损失函数
  • 乐观者
  • 批量
  • 时代数
  • 用于训练的所有样本的子集百分比(用于使用较少图像测试管道)

输出

  • 模型架构文件
  • 模型权重文件
  • 培训课程日志
  • 测试集上的模型准确性

我将整个培训管道放在一个脚本 src/cnn/cifar10.py 中,它由整个培训管道的一个类组成:

  1. 将 CIFAR-10 映像下载到容器文件系统。
  2. 加载带有 imagenet 权重的基础模型(InceptionV3)并移除顶层
  3. 训练图像和测试图像的瓶颈特征提取:保持 MongoDB 中的特性以备将来使用。
  4. 浅层神经网络的创建和编译;在 MongoDB 中持久化模型架构
  5. 浅层模型的训练;MongoDB 中模型权重和训练日志的持久化
  6. 测试集上的模型测试;在 MongoDB 中保持准确性度量

4.集装箱化

a.)Dockerfile

训练神经网络所需的一切我都放入了 Dockerfile,它定义了训练的运行时环境。

第 1 行:基础图像的定义。设置和配置继承自该映像。用的是官方的 tensorflow 图,有 python3 和 GPU 支持。

第 3 行:本地目录 src 中的所有内容,像训练脚本和入口点,都被复制到 Docker 映像中。

第 5 行:容器在 src 目录下启动

第 7 行:python 安装需求

第 9 行:将 src 目录添加到 PYTHONPATH 中,告诉 python 在这个目录中寻找模块

第 11 行:图像入口点的定义。这个入口点脚本在容器启动时执行。这个脚本启动了我们的 python 训练脚本。

入口点 shell 脚本非常简单明了:它不带参数启动 python 模块。该模块在启动时从 MongoDB 获取训练参数。

b.)Docker 容器构建

首先,我需要建立一个码头工人的形象。你可以跳过这一步,因为我在 Docker Hub 上分享了现成的 Docker 映像。第一次引用图像时,会自动下载该图像。

c.)多容器应用程序

我的设置中有两个 docker 容器:一个用于训练的 Docker 容器和一个用于保存元数据和作为文件服务器的 MongoDB。

在这个场景中使用 docker-compose。您在 docker-compose.yml 中定义了构成应用程序的容器

第 4–5 行:使用带有标签 0.1.0-GPU 的 jenslaufer/neural-network-training-with-docker 图像的训练容器的定义。该图像自动从公共 Docker Hub 库下载

第 7 行:tensorflow 的运行时环境

第 9 行:训练容器需要 trainingdb 容器来执行。在代码中,您使用 mongodb://trainingdb 作为 Mongo URI

第 11–12 行:MongoDB 数据库的定义。来自 Docker Hub 的官方 mongo 镜像用于版本 3.6.12

第 14–15 行:内部端口 27017 在外部端口 27018 可用

第 16 行:Mongo 守护进程启动

您可以看到,使用 docker compose 设置多应用程序非常简单——只需几行代码就可以设置一个数据库,而无需复杂的安装例程。

5.训练神经网络

您需要执行这个命令来确保 docker 命令是针对我们的 AWS 实例的:

docker-machine env cifar10-deep-learning

之后,您可以列出您的计算机

NAME                  ACTIVE DRIVER    STATE   
cifar10-deep-learning *      amazonec2 Running

确保您看到活动环境的星号。这是所有 docker 命令执行的环境。请记住,您是在本地 shell 中执行命令的。很方便。

现在,您可以第一次启动容器。

Docker 将所有图像下载到 AWS 实例。MongoDB 启动并一直运行,直到您停止容器。用对接器训练的神经网络执行训练模块。该模块从 MongoDB 获取训练会话,MongoDB 在第一次启动时是空的。集装箱在完成培训课程后停止。

让我们添加培训课程参数。

为此,您登录到 MongoDB 容器(本地 shell 中的所有内容):

你打开 mongo 客户端。然后使用 use 命令选择 DB“training”。然后,您可以添加一个只有 5%图像的训练会话,一个批量大小为 50 和 20 个时期的 rmsprop 优化器。如果一切顺利,这是一个快速测试。

您离开 MongoDB 并重启容器:

现在的问题是你看不到发生了什么。您可以使用 docker log 命令获取 docker 容器的日志。

docker logs -f neural-network-training-with-docker

现在,您可以通过这种方式在本地机器上跟踪远程 docker 容器上的培训会话。

6.模型评估

您可以使用 MongoDB 快速比较不同培训课程的结果,因为我在测试集上保存了所有参数和准确性度量。数据库的优点是可以对其执行查询,这比将结果保存在 CSV 或 JSON 中要好得多。

让我们列出精确度最高的三个模型。

您还可以在数据库中查询特定培训课程的模型文件。您可以看到,您拥有模型架构和权重的 hdf5 文件。还有一个包含培训历史的 JSON 文件,您可以使用它来分析培训本身。它可用于可视化培训过程。

您可以从 MongoDB 自动加载最佳模型,并将其发布到 Flask、Spring Boot 或 Tensorflow 应用程序中。

您可以使用 mongofiles 命令将文件下载到本地文件系统:

结论

在本案例研究中,您使用 docker-machine 从命令行在 AWS 上设置了一个支持 GPU 的云实例。目标是用额外的计算能力更快地训练神经网络。该实例可重复用于其他培训容器。

在下一步中,您实现了一个脚本,其中包含了在具有迁移学习的 InceptionV3 模型之上训练一个浅层全连接神经网络所需的所有步骤。该脚本使用 MongoDB 实例作为持久层来存储训练元数据和模型文件。您创建了一个 Dockerfile,其中包含在 GPU 云实例上使用 Tensorflow 训练网络所需的基础设施。然后,您在 docker-compose 文件中定义了一个多容器设置,包括 training 容器和 MongoDB 容器。

你在 Docker 的 AWS 云上训练了神经网络。您从本地命令行开始培训。您从本地命令行登录到 MongoDB 来添加培训会话,并在之后了解培训会话。

改进流程的后续步骤:

  • 浅层神经网络的结构是硬编码的。最好也从持久层加载它。
  • 使用除 InceptionV3 之外的其他基本模型的一般方法
  • 您使用了准确性度量来测试模型的质量。最好是找到一种更通用的方法来持久化更多的度量。
  • 您使用了带有默认参数的优化器。一个改进是一般地加载优化器特定的参数。
  • 目标可能是从容器中移除 python 脚本,并在 docker-compose 文件中的环境变量的帮助下,将它作为 Python 模块从入口点脚本的存储库中加载。

您需要关于数据科学设置的建议吗?

请让我知道。给我发一封 邮件

原载于 2019 年 4 月 23 日【https://jenslaufer.com】

应用人员分析的实用指南

原文:https://towardsdatascience.com/a-practical-guide-to-apply-people-analytics-f0d08bc231cc?source=collection_archive---------23-----------------------

人员分析是人力资源领域的新热点。然而,尽管人力资源领导热情地谈论它,但很少有公司能够应用它并从中受益。在 Graphext ,我们一直在与客户合作实施各种人员分析计划,以推动行为改变。在本文中,我想分享我们工作中的一些收获,特别是关于如何以实用有效的方式应用人员分析。

给你一点背景,我们的大部分客户来自服务行业,他们的业绩与他们的员工紧密相连。其中许多公司认识到利用数据科学提高盈利能力的潜力,并正在采取积极措施将不同的解决方案融入日常运营中。

不管行业、规模和地理位置如何,以下是公司在应用人员分析时面临的一些常见挑战:

首先,收集数据的困难。员工数据经常驻留在不同的系统上,并且不能很好地同步。与公司更愿意投资的客户数据不同,员工数据通常被放在次要位置,底层数据基础设施也没有得到很好的开发。因此,在进行任何分析之前,公司需要花费大量时间来收集和清理这些数据。

其次,缺乏人才。要正确应用人员分析,您需要平衡技术(编程和统计)和人力资源知识。这种技能非常罕见,很难找到。公司经常不得不在没有技术经验的人力资源专家和没有商业背景的技术人员之间做出选择。两者都有缺点。

最后,根据建议执行不力。许多公司非常乐意进行分析,但未能贯彻执行建议。没有执行,您就看不到建议的结果,没有结果,您就无法提供有洞察力的反馈来验证分析是对还是错。

尽管面临这些挑战,我们的许多客户成功地使用人员分析来提高他们的业务绩效。以下是我们从他们身上观察到的一些最佳实践。

首先,将你的分析与具体的业务目标联系起来。这是关于寻找可能对您的业务产生最大影响的用例。你可以运行许多很酷的分析,但是哪一个在今天产生商业结果方面最有效呢?

在这里,我们总结了一个最常用的人分析用例列表,深受我们客户的喜爱。大多数都是简单直接的分析,但是非常有效。

除了上面的用例,我们还看到公司在多元化研究、职业道路甚至组织网络中运行分析。这些用例很好探索,但是在现实中,基于分析实现任何改变是非常困难的,并且影响往往是长期的和无形的。如果你正在寻找唾手可得的果实和立竿见影的效果,我建议你首先跳过它们。

其次,将人员分析整合到您的日常运营中。许多公司每年只运行一次人员分析项目来设定年度目标,之后就放弃了。这种想法很危险。有了这么多的机会,人们换工作的速度比以往任何时候都快。看到一家服务公司有 20%的离职率并不奇怪,在最优秀的员工中,这个数字甚至更高。从发现问题到制定计划并实施变革的机会之窗非常短暂。

我们见过的最好的公司都在持续地运行他们的核心人员分析。此外,他们还定期试验和探索有趣的主题,以添加到他们的分析组合中。开发一个分析组合,并建立一个连续的项目路线图,将有助于将数据驱动的文化嵌入到您的组织中,并对您的公司绩效产生更大的影响。

最后,建立一个从执行到分析的有效反馈回路。一旦你在分析的基础上实施了你的策略,不管你是否看到了影响,收集结果并把它作为输入来改进你的分析是非常重要的。数据科学基于试错的思想。从长远来看,反馈环将帮助你改进和完善你的分析技术。

希望你喜欢阅读。下面是我关于数据科学的其他文章:

为什么我们必须让数据科学民主化

构建数据驱动的文化

针对您的客户洞察团队的顶级分析

关于数据科学,Kaggle 调查告诉了我们什么

为投资分析构建企业知识图的实用指南

原文:https://towardsdatascience.com/a-practical-guide-to-build-an-enterprise-knowledge-graph-for-investment-analysis-3a15363098b7?source=collection_archive---------12-----------------------

如何解决构建真正的企业知识图谱服务时的实际问题

Photo by Peter Nguyen on Unsplash

这是一篇关于在开发企业知识图(EKG)服务时如何解决挑战的应用论文,该服务整合了大约 40,000,000 家公司的信息。如果有人想为真正的商业建立一个 EKG,我发现这篇文章非常实用。所以我写这个总结是为了节省你的时间。如果你想知道细节,我推荐你直接看报纸。PDF 这里是这里是

from connected-data-london-as-a-graph

这项 EKG 服务出售给证券公司。由于证券公司提供投资银行服务和投资咨询服务,他们必须了解中小企业的信息。因此,该产品可以帮助证券公司更好、更快地了解和接近目标公司。

在这个项目中有两种挑战,技术挑战和业务挑战。

业务挑战

在商业方面有两个挑战。

  • 数据隐私:如何在不侵犯公司及其员工隐私的情况下,提供深度有用的分析服务。
  • 黑仔服务关于图表:EKG 复杂而庞大,如何让图表易于使用是一个挑战。

两大挑战的解决方案。

数据隐私 :
-将原始数据转换为秩形式或比率形式,而不是使用真正精确的值(秩形式或比率形式?)
-在将 EKG 可视化为图形时,隐藏不应显示的关键节点(例如,与人相关的信息)

图上的黑仔服务:
——提供直接满足用户业务需求的服务。例如,寻找企业真正控制者的服务告诉投资银行的投资者谁是公司的真正所有者,而企业路径发现服务提供了投资者如何到达他们想要投资的企业的提示。

技术挑战

数据来源的多样性和规模带来了技术挑战。

-构建问题,如将数据库转换为 RDF (D2R),当涉及元属性和 n 元关系时表示和查询困难
-性能问题,因为 KG 包含超过 10 亿个三元组

在详细介绍挑战之前,让我们先看看构建 EKG 的整个工作流程。

  • 在项目的第一阶段,我们主要利用 CSAIC 的关系数据库(RDB)。
  • 其次,我们用中国政府采购网(CGPN)的投标信息和东方财富网(EWN)的股票信息补充 EKG。
  • 然后,在另一个项目中,EKG 与从国家知识产权局专利检索和分析网络(PASN-SIPO)提取的专利信息融合。
  • 最后,将竞争对手关系和收购事件添加到 EKG 中。这些信息摘自百科网站,即维基百科、百度百科和互动百科。

在上述过程中会遇到以下挑战:

  • 数据模型(复杂数据类型):元属性(关系的属性,或属性图)和事件(n 元关系)。但是目前还没有成熟的解决方案来有效地表示和查询元属性和事件。
  • D2R 映射:使用 D2R 工具(例如,D2RQ9)将 RDB 从 CSAIC 映射到 RDF 具有以下挑战:a)元属性的映射。b)RDB 的同一列中的数据映射到 RDF 中的不同类。c)相同 RDB 表中的数据可以映射到具有子类关系的不同类。
  • 信息提取:从各种类型中提取有用的关系,如“竞争”、“收购”等。当百科网站中存在公司名称的缩写时,实体提取变得困难。
  • 查询性能:我们遇到了性能瓶颈,因为我们的 EGK 的三元组数量已经达到了数十亿。此外,当 EKG 使用场景增加时,会有更复杂的查询模式:a)当用户查询 IPC 代码上的 KG 时,我们应该递归地找到 IPC 代码的所有
    子类,然后找到属于这些子类的专利。b)查询实例的所有属性。由于同一实例的不同属性可能在图形存储中存储为不同的三元组,因此出现了问题。c)元属性和 n 元关系的查询。

作者仔细选择最合适的方法,并使它们适应上述问题。

  1. 首先,我们将原始表分成原子表和复杂表,然后我们使用 D2RQ 工具来处理原子表上的映射。最后,我们开发了程序来处理复杂表上的特殊映射。
  2. 我们在[16]( Bootstrapping yahoo!由维基百科资助用于竞争对手挖掘)来从百科网站的各种数据源中提取竞争对手关系和收购事件。
  3. 我们采用文献[2]中基于图的实体连接算法(图排序用于集体命名实体消歧)来完成实体连接任务。
  4. 我们设计了自己的存储结构来充分优化 EKG 中各种查询的性能。我们使用由多种数据库组成的混合存储解决方案。对于大规模数据,我们使用 NoSQL 数据库即 Mongodb 作为底层存储。对于高频查询数据,我们使用内存数据库来存储数据。

方法概述

构建 EKG 的数据源和相关任务

Building EGK from multiple sources :Aluminum Corporation of China Limited Example

此图举例说明了从多个来源提取中国铝业有限公司示例的信息的过程。

  • 首先,他们使用 CSAIC 中的中国铝业有限公司示例数据作为基本千克。然后,他们将 RDB 转换为 RDF,形成基本的企业 KG,并得到 triples like(中国铝业股份有限公司,董事,熊维平)。
  • 其次,他们从一个专利网站上提取专利信息,建立一个专利 KG。基础企业 KG 由 CSAIC 转型而来。这两种 kg 服务于不同的用户。因此,他们使用数据融合算法将两个 kg 与公司和个人联系起来。
  • 最后,他们从股票网站中提取股票代码,从百度百科和维基百科的 infobox 中提取公司高管,从百科网站的免费文本中提取收购事件。

构建知识图表

Data-driven KG constructing process

整个构建过程有 5 个主要步骤:模式设计D2R 变换信息提取数据融合与实例匹配、存储设计和查询优化

1.模式设计

虽然大多数通用知识库(如 DBpedia 和 YAGO)是以自下而上的方式构建的,以确保跨域数据的广泛覆盖,但作者在 EKG 构建中采用了自上而下的方法,以确保数据质量和更严格的模式。

在第一次迭代中,EKG 包括四个基本概念,即“公司”、“人”、“信用”和“诉讼”。主要关系包括“子公司”、“股东”和“高管”。专利 KG 中的概念只包括“专利”。主要关系是“申请人”。在第二次迭代中,我们将“上市公司”、“股票”、“投标”和“投资”添加到 EKG 中。

2.D2R 变换

作者采取三个步骤将 RDB 转换为 RDF,即表分裂、D2RQ 的基本 D2R 变换和后处理。

  • 分表:如图 4 所示,原表人员信息也包含企业信息。我们将表格分为 Person_PEnterprise_EPerson Enterprise_PEEnterprise_E 表与原来的企业信息表进一步合并,因为这两个表共享相似的企业信息。
  • D2RQ 的基本 D2R 变换:我们用 D2RQ 编写一个定制的映射文件,将与原子实体表和原子关系表相关的字段映射成 RDF 格式。我们将表名映射到类中,将表的列映射到属性中,并将每个记录的单元格值映射为给定实体的相应属性值。
  • 后处理:a)元属性映射。该程序为具有元属性的事实提供了一个自增加的 ID 注释。然后,元属性将是由该 ID 标识该 n 元关系的属性。因此,我们得到一些新的三元组(例如)。b)条件分类映射。我们的程序根据实体是否出现在与子类相关的表中来确定实体是否映射到子类。例如,如果一家公司存在于公司和股票的关系表中,这意味着该公司是一家上市公司,因此我们添加了一个三元组

3.信息提取

作者采用多策略学习方法从各种数据源中提取多种类型的数据。整个过程如下:

  • 通过使用 HTML 包装器,分别从 PSAN 国家知识产权局、EWN 和 CGPN 提取专利、股票和投标信息的实体和属性值对。
  • 通过使用 HTML 包装器,从百科全书站点的信息盒中提取企业的属性值对(例如,企业的董事长)。
  • 自由文本上的二元关系、事件和同义词识别需要句子中的种子标注来学习模式。

对于公司名称缩写的问题,作者使用实体链接算法将文中提到的公司链接到基本 EKG 中的公司。他们采用基于图形的方法分两步完成实体链接的任务:

  • 候选检测:在知识库中寻找每个提及所涉及的候选实体。它删除后缀(Corp. Co. Ltd,Group)来计算提及的核心作品与实体的核心词之间的相似度(以 KB 为单位)。
  • 消歧:选择最可能的候选链接。这里,我们使用文献中提出的消歧算法(集体命名实体消歧的图排序)

4.具有实例匹配的数据融合

问题很简单,比如公司的匹配。然而,问题是棘手的,例如人的匹配。虽然每个人都有个人 ID 号,但在专利数据源中没有这样的 ID。作者使用一个简单的启发式规则来匹配专利 KG 中的人和基本 KG 中的人。如果专利发明人和申请人的名字分别等于基本 KG 中的人和公司的名字,他们说专利发明人与基本 KG 中的人的名字相匹配。

5.存储设计和查询优化

作者使用 MongoDB 作为主要存储,因为它拥有庞大的安装基数、良好的查询性能、海量数据存储以及支持集群的可伸缩性。

部署和使用场景

本节讲述如何使图表易于使用。作者为一些用例预定义了一些查询。

Different structures for a person to control an enterprise

  • 寻找企业的真正控制者。拥有最大股权份额的人是真正的决策者。但是图案很多,见上图。
  • 创新企业分析。看公司的专利。
  • 企业路径发现。证券公司想知道是否有途径到达他们的新客户,他们也想知道他们的潜在客户是否有途径到达他们的竞争对手。
  • 多维关系发现。给定两家公司,它们之间可能存在不同的关系。

最后,如果你需要为真正的商业建立一个 KG,我强烈推荐你阅读这篇文章。

查看我的其他帖子 一个分类查看
GitHub:
bramble Xu LinkedIn:徐亮 博客:bramble Xu

参考

其他与知识图表相关的帖子:

解释和可视化支持向量机的实用指南

原文:https://towardsdatascience.com/a-practical-guide-to-interpreting-and-visualising-support-vector-machines-97d2a5b0564e?source=collection_archive---------0-----------------------

SVM 通常被认为是“黑匣子”。在这篇文章中,我们涵盖的技术,以可视化学习 SVM 模型和他们的现实世界的数据表现。

Image Shot by Hugo Dolan

关于作者

Hugo Dolan 是都柏林大学金融数学系的本科生。这主要是基于最近在 NFL Punt Analytics Kaggle 比赛中的数据分析和机器学习体验,以及成为赢得 Citadel Dublin Data Open 的团队的一部分,以及斯坦福大学 CS229 在线课程的材料。

本文包含以下章节:

  1. 线性模型、SVM 和核的介绍
  2. 解释利用 SVM 核的高维工程特征空间…
  3. 评估高维分类边界性能的技术
  4. 处理大规模阶级不平衡的实际选择
  5. 训练一只 SVM 需要多少数据

我会做一些假设:

本文将假设熟悉基本的 ML 模型,如逻辑和线性回归。它还假设你知道如何绘制我讨论的一些图表(如果你卡住了,我有一个指南)。).我们还假设你知道什么是决策函数和目标/成本函数,并且你有一些基本的线性代数知识。如果不是,它仍然值得一读,你可以把它收藏起来,以后再回来深入阅读这篇文章中更数学化的部分。

线性模型、SVM 和核的介绍

在机器学习中,线性分类器是其中存在单个假设函数的任何模型,该假设函数在模型输入和预测输出之间映射。

Many models such as Logistic regression, Naive Bayes and Discriminant Analysis to name a few, are all examples of linear models.

线性模型相对于神经网络(非线性模型)的主要优势在于特征权重直接对应于模型中特征的重要性。因此,很容易理解模型已经“学习”了什么。

Training a L1 Regularised Regression model it is immediately obvious that most of our features in our dataset are totally irrelevant to predicting our output. It is clear that features 0,1 make positive contributions to the model, whilst the presence of features 2,3,4 in a given example result in negative contributions to the output

任何线性模型的核心都是输入示例和参数/权重向量之间的点积。在线性回归的情况下,这是整个假设函数。其中逻辑回归通过 sigmoid 函数提供点积,使得输出在 0 和 1 之间,因此适用于二元分类问题。

当考虑分类问题时,线性模型的缺点是最终决策边界是一条直线、平面或超平面,其系数等于模型权重/参数,因此只能对可线性分离的数据进行分类,这在处理更复杂的分析问题时可能是一个很大的限制。

As we can see the simple linear model cannot separate the two ‘Noisy Hyperbola’ as it can only fit a ‘straight’ plane / line through the data. The second example uses a non linear model (actually a kernel trick, we’ll get to this soon)

支持向量机(SVM)是唯一可以对不可线性分离的数据进行分类的线性模型。

您可能会问,SVM 是一种线性模型,如何将线性分类器应用于非线性数据。凭直觉,利用简单的线性回归模型,我们可以手动设计 x,x,x…特征,以尝试实现对一组非线性数据点的拟合。

Whilst feature X is the only independent variable we have to predict y, which has an inherently non linear relationship with x, we can engineer x² and x³ features to improve our fit to y.

将这种直觉转移到我们的 SVM,当我们设计 x 特征时,我们本质上是将特征 x 乘以它本身。因此,假设我们通过将特征 x1、x2、x3…的组合相乘来设计数据集的特征,那么理论上我们可能最终得到一个空间,在该空间中,您设计的特征是线性可分的。以前面的简单例子为例,看看下面的数据是如何在 x 特征空间中转换成几乎线性的趋势的。

As a further intuition towards the previous example, we can see by transforming the x-axis from the original feature space of x up to the feature space of x³ how the model could be seen as a linear relationship between x³ and y.

不幸的是,要用复杂的数据集实现这一点,需要创建的不仅仅是 3 维空间(特征 x,x,x ),而是实际上非常高维的特征空间,这对于我们数据集中的每个例子来说计算起来都是非常昂贵的。下面我展示了一个函数(x)的例子,它采用我们的原始特征 x,并将它们组合起来以创建许多二阶多项式特征。

在我们继续之前:我将使用 x 符号来表示数据点/训练示例,用上标来表示特定的数据点,用下标来表示特定的特征。

This is a typically high dimensional space, if we had 100 features originally then this function would produce 100 * 100 engineered features. This is computationally expensive, in this case Big-O(n²) time complexity, think of having to write two nested for-loops to generate all the combinations produced by ø(x).

幸运的是,我们有办法解决这个计算复杂性难题!当我们推导 SVM 的优化问题(复杂的公式告诉我们如何在坐标上升过程中推导和更新我们的权重以实现最大化)时,结果是我们的训练输入 x 的特征向量只出现在整个优化公式中的一个地方(以红色突出显示)。

这个点积是用于我们的原始特征空间的,所以现在让我们用我们的工程特征空间替换它。

那么这如何有助于降低计算复杂度呢?根据点积的定义,我们将(x(i))的第 I 项乘以(x(j))的第 I 项,然后将所有这些相加,得到一个标量。应用这个我们得到:

As if by magic we can remove the need to compute ø(x) completely by simple algebraic manipulation by the kernel trick. Now we have all the benefits of a high dimensional feature space without the additional computational complexity

内核技巧是对原始方程的一种非常简单的重新排列,我们可以看到,我们已经完全移除了(x ),只需使用原始输入特征来执行计算,但仍然具有计算高维空间的效果。

我们现在所要做的就是用核等价体(K(xi,xj)代替涉及(x)的点积:

Simple substitution, note that our Kernel is using x and z here just to remove the superscript notation.

类似地,当我们想要使用我们的模型来进行预测时,我们从不明确地计算高维空间的权重,而是使用核技巧来进行预测:

在总结中,我们可以使用内核技巧将非线性数据集转换成线性可分的数据集,就在高维空间中。Sklearn 在 SVC 实现中预装了许多内核,包括半径基内核(RBF)和多项式内核,每个内核都有自己的超参数,可以使用交叉验证进行实验调整,以获得最佳结果。

一个小故障,解释高维工程特征空间…

还记得我们说过线性模型的最大好处是模型的权重/参数可以解释为特征的重要性。一旦我们设计了一个高维或无限维的特征集,模型的权重就隐含地对应于高维空间,这对我们的理解没有帮助。

相反,我们可以做的是拟合逻辑回归模型,该模型估计给定原始特征时标签 y 为 1 的概率,其中 f(x)是 SVM 决策函数:

If this looks familiar it is, think logistic regression!

我们使用最大似然估计来拟合这个逻辑回归模型的参数,这种技术被称为普拉特标度,如果你对内部工作方式感兴趣,那么的原始论文 [3]绝对值得一读。

那么这如何帮助我们理解 SVM 是如何工作的呢?我们只需拟合模型,并在数据集中选择一个点进行评估,然后通过一系列值一次扰动一个特征,同时保持其他特征不变。我们可以用这个来画出模型对每个特征的敏感度的图表。

SKlearn 将这个特性内置到 SVC 模型中,你只需要在初始化时确保概率=真,,然后使用 clf。 predict_proba(X) 函数获取概率。

在实践中,我发现与其只评估一个点,不如对相关点的集合进行采样,例如 40 个负面例子,然后按特征对概率分布进行平均,以获得更有代表性的东西。

这是我在 NFL Punt Analytics Kaggle 比赛中做的一个例子,研究各种因素对脑震荡的影响:

我选取了所有的负面例子,并对它们的概率进行平均,我用红色突出显示了每个特征中球员最有可能受到脑震荡的区域。如果你有一堆像玩家角色这样的热门编码变量,一个技巧是将它们聚集成一个条形图,然后查看该特征出现和不出现之间的概率净变化。

还有一个很好的应用于营销数据的例子[1],你可以在这里找到。我还要感谢 Georgi,他花时间回答了我关于这篇论文的一些问题。

评估绩效的技术

当您处理涉及 SVM 的高维模型时,如果能够可视化模型如何对数据点进行分类,而不单纯依赖 F1 分数或 ROC AUC 等指标,那就太好了。

虽然有些人可能使用诸如主成分分析之类的技术来可视化分类,但在这样做的时候,我们失去了特征空间的维度,从而扭曲了我们希望实现的视觉效果。

我发现一个很好的技术叫做“项目直方图”[2],它包括为你的训练和测试集绘制 SVM 决策函数的输出分布图。

在 SKlearn 的 SVC 实现中很容易获得决策函数,只需调用 decision_function(X)。您可能希望跟踪数据集标签,以便对投影直方图进行颜色编码,如下所示:

投影直方图很容易解释。直方图 x 轴标识特定训练示例离 SVM 的决策边界的距离(由中间的虚线指示)。

SVM 在决策边界的任一侧具有等于 1 的分离裕度,这是双重优化问题的强制约束(“支持向量”是位于这些裕度上的数据点)。你会注意到,在上面的模型中,有一些泄漏到了边缘区域,并且确实从一个类跨越到了决策边界对面的类中。这是因为我们已经将正则化超参数 C > 0(它允许在一些错误分类和最小化 SVM 目标函数之间进行权衡)。

尽管与高维特征空间一起工作,该图表成功地可视化了决策边界区域和所有分类,而没有损失维度。在混淆矩阵中看到的所有指标(即真阳性、假阳性、真阴性和假阴性的数量)也可以通过直方图看到。它还使我们能够观察模型是否能很好地推广到测试集。如果测试集具有与训练集相似的决策函数输出分布,那么我们可以说该模型具有良好的泛化性能。该模型还可以用于确定给定所选超参数时数据集是否是线性可分的。

处理不平衡数据的实用选项

当一个数据集的一个类相对于另一个类有不成比例数量的例子时,我们说它是不平衡的。

An example of a real world dataset which has an imbalance of over 3000:1

如果我们想建立一个 ML 模型来预测少数民族的出现,这是一个问题,因为我们可以通过简单地将所有少数民族的例子错误分类为多数民族类来实现高水平的准确性。

这在现实世界的数据中很常见,无论是识别恶性组织、信用卡欺诈还是体育运动中的脑震荡,因为我们希望正确识别的事件相对较少。

有两种普遍接受的做法来纠正处理不平衡数据的 ML 模型:

  1. 对少数类过采样/对多数类欠采样
  2. 增加成本函数中少数样本的权重

选项 1 : SMOTE

有两种方法可以对数据进行重采样,要么删除现有样本(欠采样),要么添加新样本(过采样)。最普遍接受的方法是使用一种称为 SMOTE(合成少数过采样技术)的算法对少数类进行过采样[5]

它比名字所暗示的要简单得多,对于数据集中的每个少数民族点,它选择 k 个最近的其他少数民族例子(通常为 5 个),并沿着“连接”现有少数民族例子的线随机插入新的少数民族例子。

这是一件合理的事情,因为我们只是简单地假设,通过在相似的现有示例之间进行插值,我们将获得相同类别的新示例。

We can see how SMOTE has generated new data points along the lines of existing points

这有助于显著提高模型的性能,并有助于概括少数示例的决策边界。

选项 2:将权重引入目标函数

可以采用的另一个过程是在目标函数中为少数实例的错误分类分配更高的权重。这将“激励”算法正确分类少数民族类别。

我没有使用这种方法的个人经验,但它可以与选项 1 结合使用。这是一篇好论文的链接这里【4】详述了许多处理阶级不平衡的方法

训练一只 SVM 需要多少数据

一个合理的经验法则是,训练示例的数量至少是功能的 10 倍。如果您有大量的训练数据,最好使用少于 50,000 个训练示例,因为 sklearn 中的 SVC 实现具有 O(n)复杂度,这意味着收敛到解决方案的时间随着训练示例的数量呈立方增长,即使在像样的笔记本电脑或 kaggle 容器上也会变得相当慢。

首先在较小的数据集上进行训练,并调整模型的超参数通常是值得的。您可以为模型选择保留一个小型的交叉验证测试集。当您在剩余的数据集上进行测试时,您可能会惊讶于您的模型概括得有多好,尽管您可能已经使用了一小部分实际数据。

注意:如果您对此不熟悉,一个技巧是使用 sklearn 的训练测试分割模块并修复随机种子,这样如果您碰巧回去编辑一些早期代码并重新运行训练/模型选择过程,您的结果是可重复的。

结论

我希望这篇文章对你有所帮助,如果你有任何意见或问题,请在下面留下,我会尽力回答。

论文参考

[1] Nalbantov,Georgi & C. Bioch,Jan & Groenen,Patrick .(2005).用支持向量机解决和解释市场营销中的二元分类问题。566–573.10.1007/3–540–31314–1_69.

[2]切尔卡斯基,弗拉基米尔&达尔,索普蒂克。(2010).解释高维非线性 SVM 分类模型的简单方法..267–272.

[3]普拉特,J. (2019)。支持向量机的概率输出以及与正则化似然方法的比较。[在线]Citeseer.ist.psu.edu。可在:【http://citeseer.ist.psu.edu/viewdoc/summary? 买到 doi=10.1.1.41.1639 。

[4]巴图维塔,鲁克山和帕拉迪,瓦西里。(2013).支持向量机的类别不平衡学习方法。10.1002/9781118646106.ch5

[5] Chawla,N. V .等人,“SMOTE:合成少数过采样技术”人工智能研究杂志www.jair.org/index.php/jair/article/view/10302.

在药物发现中使用分子指纹的实用介绍

原文:https://towardsdatascience.com/a-practical-introduction-to-the-use-of-molecular-fingerprints-in-drug-discovery-7f15021be2b1?source=collection_archive---------9-----------------------

Morgan fingerprinting

分子指纹用于药物发现有许多原因。今天我们将集中讨论它们在药物结合亲和力预测中的应用。

分子指纹是一种将分子表示为数学对象的方法。通过这样做,我们可以对这组分子进行统计分析和/或机器学习技术,以获得我们作为人类无法获得的新见解。最常见的分子指纹法之一是扩展连接性指纹法(ECFP) ,我们今天就来看看。

扩展连接指纹识别(ECFP)

基本想法如下。每一点都将详述。

  1. 给每个原子分配一个标识符
  2. 基于其邻居更新每个原子的标识符
  3. 删除重复项
  4. 将标识符列表折叠成 2048 位向量(摩根指纹)

1.给每个原子分配一个标识符

我们选择分子中的一个原子,记下:

  • 最近邻非氢原子数
  • 连接在原子上的键的数目(不包括连接在氢上的键)
  • 原子序数
  • 原子量
  • 连接到原子上的氢的数目
  • 环中的原子是(1)还是不是(0)?

这些值形成了日光原子不变量规则。

这些值被散列成一个整数。对每个原子重复这个过程,直到所有原子都被分配了散列整数值。作为一个例子,这是这个过程在这个任意分子上的结果:

The first iteration

2.迭代地更新每个原子的标识符

用一个例子可以很容易地解释更新过程。以 atom 4 为例,它当前的标识符是-1100000244。

我们初始化一个数组,并将迭代级别(1)和 atom 4 的标识符(-1100000244)添加到其中。到目前为止,该数组为:[(1,-1100000244)]。

接下来,我们为每个非氢连接再添加两个数字。第一个是特定连接的键序(单键、双键、三键和芳香键为 1、2、3、4)。第二个是原子的标识符。然后,我们按照原子标识符降序排列这些对。

最终数组为:[(1,-11000000244),(1,1559650422),(1,1572579716),(2,-1074141656)]。在第一次迭代之后,我们散列这个数组来生成 atom 4 的新标识符:-1708545601。

我们对每个原子重复这个过程;结果如下:

最后,我们的新指纹现在是来自两个迭代级别的这些标识符中的每一个的连接,即:[734603939,1559650422,1559650422,-1100000244,1572579716,-1074141656,863188371,-1793471910,-1789102870,-17085456671

对于第二次迭代,我们重复上面的过程,但是现在更进一步。对于每个原子,我们查看它最近的邻居,然后是它的第二最近的邻居,像这样创建一个数组。然后,我们对数组进行哈希运算以生成新的标识符。

3.重复子结构移除

我们需要确保,在每次迭代中,我们删除对应于重复子结构的标识符。这可以用一个图像来解释:

The two substructures on the bottom left are identical, so one of them is discarded

4.包扎

最后,在执行所需次数的迭代(大多数情况下为 2-4 次)后,我们从每个迭代级别创建一个每个原子标识符的数组,删除重复项,并使用哈希算法将其折叠成一个长度为 2048 位的向量。

我们已经做到了:我们已经把一个分子变成了一种数学表示,通过它我们可以进行机器学习和统计分析。

这可能是一个干巴巴的帖子,但如果你想使用这些指纹进行机器学习,在高层次上理解这一点是很重要的。

例如,如果我们想要预测一种药物是否会由于某个特定的部分(比如说苯胺部分)而有毒,那么我们就需要使用至少重复 4 次的指纹来捕获整个环。

相反,如果我们想预测疏水性,我们可以只使用 1 或 2 次迭代,因为疏水性更多地取决于原子和键的类型,而不是更大的亚结构。

5.后续步骤

要查看用于非常准确地预测药物是否与靶标结合的指纹应用,请参见此处:随机矩阵理论:预测药物结合的最佳分类器?

请随时在 LinkedIn 上与我联系,告诉我你是否喜欢阅读这篇文章/计划在你的研究/工作中实施它。

最好的,

拉克什

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指南 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

对向量和数据的实际观察

原文:https://towardsdatascience.com/a-practical-look-at-vectors-and-your-data-95bde21b37d1?source=collection_archive---------13-----------------------

A vector in the night sky

[## 想在数据科学方面变得更好吗?

当我在我发布独家帖子的媒体和个人网站上发布新内容时,请单击此处获得通知。](https://bobbywlindsey.ck.page/5dca5d4310)

我记得在我的第一堂线性代数课上,当我第一次学习向量空间时,有一种完全混乱的感觉。什么是空间?这些向量到底是什么?名单?功能?小猫?这和我为科学研究分析的所有数据有什么关系?在这篇文章中,我试图解释向量、向量空间的主题,以及它们如何以一种我以前的自己会欣赏的方式与数据相关联。

向量的效用

想象一个你可能在学校里见过的 2 乘 2 的图形。一个 向量 是一个通常以有序元素列表的形式出现的对象,比如 (4,3) ,它位于一个向量空间中,通常被表示为一个箭头,其尾部从原点 (0,0) 开始,并在其他某个点结束,比如 (4,3)

The vector (4, 3) represented as an arrow

这个箭头有几个值得注意的属性:它有方向和长度。向量可以表示许多现实世界的物体,如风、足球的投掷和汽车的速度。它甚至可以代表一种动物的特征,你的购物清单的数量,或者你的电子表格中的一行数据。

给你的向量一个空间

但是你怎么知道你的对象或者有序列表是不是一个向量呢?嗯,它一定属于一个叫做 的集合向量空间 。向量空间可以是任何一组元素(可以是列表、函数或其他对象),但这些元素必须遵循一些规则:

  • 在集合中添加任意两个元素都会导致集合中已经存在另一个元素
  • 将集合中的任何元素乘以某个数字(称为标量)会得到集合中已经存在的另一个元素
  • 所有的元素都是结合的交换的,标量相对于元素加法是分配的
  • 集合中有一个元素,将其添加到任何其他元素都不会改变其值
  • 有一些数字(称为标量)使得它乘以任何其他元素都不会改变元素的值
  • 集合中的任何元素都有可以添加的元素,这导致元素为 0(称为零向量)

如果你集合中的所有元素都遵循上面的规则,那么恭喜你!你的元素叫做向量,它们所属的集合叫做向量空间。但是违反这些规则中的任何一条,你的集合是而不是向量空间,你的集合中的元素不是向量。

用数学术语来说,这些规则解释如下:

  • 所有元素都在加法下闭合
  • 在标量乘法下,所有元素都是封闭的
  • 所有的元素都是结合的、交换的,标量相对于元素的加法是分配的
  • 每个元素都有一个附加标识
  • 每个元素都有一个乘法单位
  • 每个元素都有一个加法逆元

有形的向量空间

想想你已经知道并喜欢的那套, RR 就是 R × R 是所有可能的二维列表的集合,用以下集合符号表示 {(a,b) : a,b in R} 。您可以想象下面的 R (显然 xy 轴的极限并不在 10 处停止,而是接近无穷大):

R² visualized as the Cartesian Plane

集合 R 是向量空间吗?如果是的话,它需要遵循上面提到的向量空间的所有规则。考虑第一条规则:在集合中添加任意两个元素会导致集合中已经存在另一个元素。T21 遵循这个规则吗?嗯,比如取 R 中任意两个元素,像 (2,3)**(-1,-4) 。当你把它们加在一起时,你会得到一个也在 R 中的元素吗?是啊!事实上,你得到 (1,-1) ,它确实存在于集合 R 中。这适用于你在 R 中添加的任何两个元素——你总是会得到同样属于 R 的东西。

所以你已经验证了第一条规则!但是为了让 R 被称为向量空间,你必须验证它遵循所有的规则;确实如此。

简而言之,有许多集合遵循上面的规则,所以你很自然地给它一个名字。现在当有人谈论某个任意集合时,你知道如果集合的元素遵循向量空间的规则,那么这个集合一定是向量空间。

菲尔茨

另一个需要注意的是这些标量,你可以用它们来乘向量。标量是属于一个称为 字段 的集合的元素,该集合具有与向量空间相同的规则,但是具有乘法逆运算的额外好处。

因为域是一个集合,它具有向量空间的所有规则,那么域也是一个向量空间。你实际上一直在使用字段,比如实数集或者复数集。任何时候你在二维网格上绘图,你实际上是在二维区域上绘图。

子空间

在实践中,您可能认为对照一个集合检查每个规则以查看该集合是否是一个向量空间是乏味的。你说得对。所以这就是为什么把一个集合识别为你已经知道的向量空间的子集要容易得多(就像实数的集合),并且证明这个子集是非空的,并且在与向量空间相同的运算下(即在加法和标量乘法下)它是封闭的。

如果你能够做到这一点,那么你的子集被称为 子空间 ,它本身也恰好是一个向量空间(同样,为了自己看,取一个子空间并验证它具有向量空间的所有属性)。

所以如果你想证明一个集合是一个向量空间,试着证明它是一个子空间。由于子空间本身就是向量空间,你已经成功地证明了集合是向量空间。

真实世界的数据

现在所有这些理论如果你不能应用,都没有太大的帮助。因此,考虑经典鸢尾数据集的前几行,该数据集包含三种不同种类的鸢尾花的样本。

Some rows of the Iris dataset

从标题中可以看出,每个样品的特点是:

  • 萼片长度
  • 萼片宽度
  • 花瓣长度
  • 花瓣宽度

每一行特征都可以被视为一个有序列表。第一个列表是 (5.1,3.5,1.4,0.2) ,第二个是 (4.9,3,1.4,0.2) ,依此类推。但是这些有序列表是向量吗?列表中的每个条目都是一个实数,因此属于实数集, R 。因为每个有序列表都是四维的,所以它们存在于 R⁴。由于 R⁴ 是一个向量空间,那么这些有序列表可以称为向量。

请注意,这些向量中的每个条目代表 r⁴中的一个维度,其中每个维度对应于数据集中的一个特征(如萼片长度、萼片宽度等……)。也就是说,数据中的每个要素都可以被视为一个随机变量。因为它们是随机变量,我们可以做一些描述性的统计,比如求它们的平均值和标准差。

因为您已经将表中的每一行表示为一个向量,所以您可以一下子计算出每个随机变量的平均值和标准差。这就是向量的力量。

假设行/向量 (5.1,3.5,1.4,0.2)(4.9,3,1.4,0.2) 是上表中所有的数据。使用两个向量空间规则,标量乘法和加法,我们可以很容易地计算出每个随机变量的平均值。

Scaling and adding vectors to find the mean

所以萼片长度的平均值为 5 ,萼片宽度的平均值为 3.25 ,以此类推。将数据表示为一组向量不仅美观,而且计算性能更高,因为计算机针对涉及向量的计算进行了优化(事实证明,您可以用向量和矩阵运算代替大量 for 循环)。

结论

最后,因为您可以将数据表示为向量,这些向量属于一个具有特殊规则的集合,称为向量空间,所以您对数据所做的许多令人惊叹的事情,如:线性特征变换、标准化和降维技术,都可以通过向量空间的规则来证明。

向量空间不仅是任何涉及数据的工作的基础,它还构成了几乎所有数学领域的核心线性代数的基石。即使你正在研究的现象是非线性的,线性代数也是用作一阶近似的首选工具。

简而言之,向量与你的数据紧密交织在一起,非常有用!因此,下次当您将数据导入数据帧并执行一系列操作时,请记住,您的计算机会将您的数据视为一组向量,并愉快地以高性能的方式应用转换。多亏了这些叫做矢量的小东西。

如果你喜欢我在这里写的东西,一定要看看我的个人博客,我在那里有一些在媒体上看不到的文章。

原载于 2019 年 3 月 5 日 bobbywlindsey.com*。***

相似性评分实践指南,第 1 部分

原文:https://towardsdatascience.com/a-practitioners-guide-to-similarity-scoring-part-1-29625b9ac481?source=collection_archive---------18-----------------------

A sample nearest neighbor graph in 2D

大多数重要的现实世界应用领域都存在一些问题,这些问题不完全适合传统的有监督的机器学习框架。获取标签的成本可能很高,或者定义不清,而高影响力的决策通常需要人来做出决定。需要昂贵的标记和人工干预的应用领域的一个例子是恶意行为者检测,包括高价值欺诈检测或网络入侵检测。在这种情况下,高技能的坏演员将知道避免历史模式,并经常在监督学习的检测能力下飞行。另一个这样的例子是汽车、飞机或其他物理系统的根本原因工程问题。任何明显的系统性和重复性问题都可能已经得到解决,所以剩下的问题可能很难系统地描述,也不符合清晰的历史模式。

很容易将类似的推理应用于医疗保健、能源、零售等其他高价值问题,并得出结论,许多重要问题不会屈服于直接的监督学习。在这种情况下,一项值得机器学习从业者保持警惕的技术是相似性评分。在这篇由两部分组成的博文的第一部分中,我们将介绍这类技术,并通过应用来激励它们。第 1 节介绍并激励相似性评分。接下来,在第 2 节中,我们为一个示例应用程序构建了一个非常基本的相似性评分函数。除了第 2 部分中非常基本的评分之外,第 3 部分涵盖了许多改进相似性评分的方法。我们将在第 4 节用一些主要的收获来结束这篇文章。第二篇文章将深入探讨最困难的实现问题,我们称之为“n 问题”。

1.什么是相似性评分,为什么?

相似性评分的目的是创建一个函数,该函数采用一对对象并产生一个量化其相关性的数值分数。对于一对新闻文章,当这一对的内容涉及相同的主题时,这个分数可能较高。汽车缺陷的两个结构化记录的高分可以传达这两个缺陷源自相同的根本原因。与标准的监督学习形成对比:对于两个实体(文档、记录、图像……)e1 和 e2,监督学习的目的是产生函数 f(e1)->数值分数,f(e2)->数值分数对实体 E1 和 e2 的相关性进行排序,而相似性评分的目的是产生函数 g(e1,e2)->数值分数,对实体的相关性进行排序。

我们的希望是,对于我们上面讨论的棘手的、对立的和不明确的领域,对于领域专家工程师、分析师或科学家来说,“g”形式的函数比更普遍构建的监督函数“f”更有用。为什么会出现这种情况?

举个例子来说明,假设我是一名制造工程师,正在查看送往修理厂的破损汽车零件的照片。如果我在数据中观察到一个明显的模式,比如轻微碰撞中撞碎的后保险杠,我可以将这些标记为“破损的后保险杠”,训练一个简单的监督图像分类模型来检测这种模式,并在很大程度上完成。相反,如果我要处理的是我还没有找到原因的发动机故障的增加,第一步可能是深入调查实例并确定这些故障的子组。在进行调查时,我发现一个有用的功能是拍摄一张损坏的发动机照片,并找到其他密切相关的照片。可以使用相似性函数 g 来提供这种“给我看更多像 X 的图片”的能力:给定一个有趣的图片 X,找到使 g(x,y)最大化的图片 y。

旁注:你也可以通过在单个例子 X 与其他随机选择的例子上训练监督模型“f ”,然后说“最相似的对象 y”最大化 f(y ),来解决“给我看更多像 X 的图片”的问题。用很少的例子学习“f”通常被称为单次或少次学习,相似性学习是解决单次/少次学习的一种常用方法。该方法的一个版本然后再次简化为,创建相似性评分函数“g”

与其将我们的相似度函数“g”应用于单个示例来查找相关示例,我们还不如将其应用于我感兴趣的一批发动机图片来查找相关实体。这是许多推荐系统使用的方法,比如 Spotify(他们开源了他们的近似最近邻居框架惹恼了,网飞/亚马逊/Youtube 视频和产品推荐也可能使用这种方法。

现在,您对相似性评分的输出以及它为什么有用有了更好的了解,让我们为欺诈检测中的一个样本问题构建一个简单的相似性评分函数。

2.第一个例子

例如:信用卡欺诈

举一个简单的例子来说明常见的相似性评分技术,假设一家大型银行的一组信用卡欺诈分析师想要找出最近报告的欺诈增加的根本原因。对于每张卡上的每一次刷卡,银行都会收到交易地理位置、供应商名称、时间、金额、涉及的卡号以及大量其他个人/供应商信息。

与上面的制造根源示例一样,我们希望欺诈分析师能够高效地从感兴趣的交易转向可能相关的交易,最终目标是构建一个完整的欺诈网络。我们将使用上面列出的五个字段来构建我们的初始分数:分别使用每个字段对实体进行评分,然后合并这些分数。

简单的初始相似性得分

方向性,我们认为同一时间相同金额的交易更有可能是相关的。然后,我们可以将作为金额和时间的函数的相似性得分设置为时间和金额差异的反函数:例如,金额为 1/abs(金额 1-金额 2 ),时间为 1/abs(时间 1-时间 2)。我们可以采用类似的方法来计算物理距离,让距离的相似度为 1/测地线距离(位置 1,位置 2)。

对于分类属性,如供应商名称和涉及的卡号,相似性的一个简单版本是当属性完全相等时设置相似性=1,否则设置为 0。这可能太粗略了:在供应商“Starbucks”上匹配的两个交易可能比在波特兰的特定精品咖啡店上匹配的信息量少得多。这里一个简单的贴现方法是通过供应商/分类变量的频率。因此,如果分类匹配,我们可以设置 score = 1/attribute-frequency,如果不匹配,则设置为零。这种用于在自然语言处理中匹配记号的思想的扩展是逆文档频率,然后取调整后的文档记号频率的余弦或欧几里德相似度。

现在,我们已经为每个属性定义了分数,我们需要跨属性组合分数。最简单的说明方法之一是通过线性组合:权重 1 *时间戳-分数+权重 2 *金额-分数+ …在此计算和上面的简单属性分数之后,我们有了一个可以用来开始与欺诈分析师迭代的初始基线。给定这个简单的基准,我们下一步可以做什么来产生更高性能(计算/内存)和更高质量的评分?

提高性能/质量

在检查我们的分数的计算/内存性能时,我们将很快遇到第二篇博文专门讨论的“n 问题”。用我们的信用卡用例来说明这个问题:一个真实的信用卡交易数据集可能有几百万行甚至更多。天真地对每一对 1 亿笔交易评分需要订单 1 亿=10 次⁶计算,这是一个非常大的数字。

相反,我们可以通过提高每个属性得分或如何组合这些属性得分来提高得分质量。例如,我们可以使用 Levenshtein 距离或其他字符串相似性度量来匹配特许店或相关商店。为了提高分数聚合中权重的质量,我们可以基于用户标记的反馈来优化这些权重。进一步提高分数的方法很多,因此在接下来的几节中,我们将致力于深入探讨这些技巧。

3.相似性评分技术

提高相似性得分质量的几大类技术包括密度调整、向量嵌入以及同现和列联表。

调整密度

两个物体位置的感知相似性通常取决于这些物体周围的环境。在我们的信用卡交易示例中,发生在西伯利亚相距一英里的两笔交易比发生在曼哈顿相距一英里的交易更有可能相关。我们想要调整我们的简单 1/测地线(位置 1,位置 2)分数来解决这个问题。我们想要的基本属性是,对于位置之间的相同距离,密度越高,相似性得分越低。我们将介绍进行这种调整的几种方法:一种是通过显式建模密度,另一种是通过等级转换测地线相似性。

模拟密度的最简单方法之一是使用局部球面高斯分布。在某个位置 X 周围,假设我们将使用距离 X 最近的 100 个点来估计 X 周围的密度,例如,我们可以将这 100 个点到 X 的均方根距离称为球面高斯标准差 R_X,然后我们可以将任意点 Y 和 X 之间的调整相似度设置为 R _ X/测地线(X,Y)。对于曼哈顿的某个点 X,我们期望 R_X 很小,因此大的密度调整测地线相似性只会导致非常小的测地线距离。您可以采用这种想法,并进行一些变化,例如通过使用更高容量的模型,如多元高斯模型或非线性模型。在概率模型的一般情况下,您可以根据 X 周围的密度用 Y 的概率替换测地线(X,Y ),并取 P(Y;分布-近(X))和 P(X;distribution-near(Y))来对称化。

拟合每个点的参数密度需要计算和选择模型和参数,但是我们也可以使用非参数方法。最简单的方法之一是最近邻排序法。设 nn-rank(X,Y)是 Y 在 X 的最近邻居列表中的秩索引,从最近到最远排序。将我们的 nn-rank-相似性得分(X,Y)设为 1/nn-rank(X,Y ),则说明了变化的密度。对于 nn-rank(X1,Y1)=nn-rank(X2,Y2),曼哈顿的一些点 X1 和 Y1 需要比西伯利亚的一些 X2 和 Y2 更近,以满足我们最初的密度标准。在我们的参数方法中,我们可能再次希望通过取 1/nn-rank(X,Y)和 1/nn-rank(Y,X)的最小值、最大值或平均值来对称化我们的分数。

这种密度调整的思想可以应用于任何空间中的任何属性,而不仅仅是测地线空间中的位置。例如,如果应用于信用卡交易的时间戳,我们可以避免在假日季节与一年中其他不太繁忙的时间过度匹配。当应用于零售商店销售的产品时,与纸巾等较窄的类别相比,这可能会迫使玩具等广泛而繁忙的类别发生细分。我们可能会说,两个玩具不应该被视为相似和可替换的,而两个品牌的纸巾更接近,因为类别不太密集。

向量嵌入

在我们的信用卡交易示例中,所有的属性都是相对低维的:纬度/经度、分类、数字和时间戳数据。如果我们被赋予更高维度的属性,比如音频信号、图像或文档,会怎么样?像深度学习这样的向量嵌入方法通常在处理高维数据时获得最先进的结果,这同样适用于相似性评分。

处理深度向量嵌入进行相似性评分的一种方法是,假设我们给定了一个特定于形态的深度嵌入函数“h ”,它获取一个文档、图像或音频片段,并返回一个嵌入向量。对于实体 e1 和 e2,我们将我们的相似性函数设为 g(h(e1),h(e2)),其中 g 是向量相似性函数,如余弦相似性、jaccard 相似性或反欧几里德距离。这些预先训练的深度嵌入函数“h”中的许多已经以通常半监督的方式在大量不同的语料库上被训练,例如图像嵌入文本嵌入音频嵌入

在无法获得适合目标任务的预训练嵌入的情况下,许多论文展示了端到端的训练相似性得分。训练嵌入函数“h”通常在实体对上的“相关/不相关”二进制标签上完成。那些二进制标签上的错误通过交叉熵或其他分类损失、通过 h(e1)、h(e2)之间的余弦/欧几里德/…相似性、然后通过应用于两个实体的参数“h”被反向传播。注意,应用于 e1 和 e2 的网络“h”的参数是共享的,因此单个标签导致“h”的两个参数更新。

与我们讨论的其他属性评分方法一样,我们将把使所有对的相似性评分在计算上和内存上高效的问题放在一边。

共现和列联表

到目前为止,我们已经讨论了仅基于这些实体的核心属性的相似性评分实体:个人实体的名称、事务实体的时间戳或者图像的内容。在应用于用户项目推荐系统时,利用与实体相关的动作或交易数据也很常见,称为协同过滤。让我们用一个例子来具体说明这一点。

对于信用卡交易,我们有一些可用的实体类型:拥有信用卡的人或公司、供应商和交易。假设我们试图根据人们在哪里购物来识别哪些人是相似的,根据共同的兴趣来推荐友谊。作为开始,我们可以说“在许多相似供应商处购物的人应该是匹配的”。另一种说法是,如果 A 和 B 分别是约翰和玛丽购物的供应商集,那么如果 A&B 比预期高得多,我们应该匹配约翰和玛丽。许多指标可以用来确定 A&B 是否足够高:A 和 B 的 jaccard 相似性,或者像卡方G费希尔精确测试这样的列联表测试。

只有当 John 和 Mary 在同一个供应商处购物时,这才是匹配的,但是如果他们有相似的兴趣,但不在完全相同的地方购物呢?例如,我们可能会发现他们都对健身感兴趣,但一个人在耐克购物,另一个人在 Planet Fitness 购买健身会员。在这种情况下,为了帮助匹配 John 和 Mary,我们可以分两个阶段首先匹配供应商,然后使用供应商匹配来匹配人员。例如,在第一阶段,我们可能会发现耐克和 Planet Fitness 在购物人群中有很大的 jaccard 相似性,并给这两个品牌一个高分。利用这一知识,在第二阶段,我们可以说 John 和 Mary 具有高匹配分数,因为他们有一个共同的高分数供应商对。我们可以说,任何两对人的分数是所有匹配这两对人的供应商分数的加权和、平均值或其他总和。

在利用这种“用户行为”数据时,可以采取更广泛的方法,但通常最重要的是知道当交易信息可用并与被评分的实体相关联时,它通常是值得利用的。

4.总结

我们已经简要介绍了相似性评分技术,在下一篇文章的中,我们将深入探讨 n 问题。

当你自己建立相似性分数时,你可能想得到一些要点:

  • 在对立的、频繁变化的或者标签稀少或昂贵的问题领域中,尝试使用与领域专家紧密结合的相似性评分
  • 调整相似性得分中的频率和密度
  • 首先将相似性评分问题视为成对二进制分类:标记二进制匹配并使用二进制分类度量
  • 除了手动设计的配对属性分数之外,还存在更多种类的技术。这些包括深度嵌入的向量相似性和协作过滤。

相似性评分实践指南,第 2 部分:n 问题

原文:https://towardsdatascience.com/a-practitioners-guide-to-similarity-scoring-part-2-the-n²-problem-af707461276a?source=collection_archive---------30-----------------------

Sometimes connecting all pairs of nearest neighbors can be a lot of pairs

参见上一篇文章“相似性评分实践指南,第 1 部分”

处理 n 问题

之前的帖子中,我们鼓励相似性评分,并提供了示例技术和应用。在构建和应用相似性得分时,从业者接下来可能面临的最困难的问题之一是我们称之为 n 问题的问题:对于 n 个实体,计算和存储所有对的相似性得分需要 n 个空间和计算。

在这篇文章的第一部分,我们将深入探讨 n 问题,并将其与排序进行比较。接下来,在第 2 和第 3 节中,我们将介绍一些处理计算/空间问题的常用方法:分块和近似最近邻。在第 4 节中,我们将调查解决与标签收集、模型训练和性能评估中出现的 n 问题相关的问题的方法。最后,在第 5 部分,我们将总结这篇文章的主要收获。

1.n 问题:排序的类比

相似性得分通常以两种方式消耗,我们称之为批处理和实时评分。批量评分的目的是给定一大组实体,产生所有匹配的实体对。对于实时评分,我们假设我们有一个可以索引或处理的大型初始实体集,并且我们必须实时返回一小组实体相对于该大型初始集的最高评分匹配。

解决批量用例需要运行 O(n)个相似性分数,以及每个实时对象查找的实时 O(n)。对于大多数大小 N>10M 的真实数据集,O(n ) batch 和 O(n) per object realtime 的计算/内存太多。与简单方法具有相似性能属性的一个密切相关的问题是排序:简单的批量排序需要 O(n)次比较,在排序后的数组中简单的插入/查找也需要 O(n)次比较。就像二分搜索法树/堆可以用于排序以实现 O(nlogn)批量排序和 O(logn)增量查找/插入一样,我们将通过构建有效的索引来实现 O(nlogn)批量和 O(logn)查找性能。我们将从头到尾从类比到排序,通过一些假阴性的假设来获得这些性能特征。

2.阻塞

早期高效排序算法中使用的一个最简单的想法是桶排序,当扩展到基数排序时,仍然在使用。对于最近邻搜索,我们将遵循一种类似的方法:从一种非常类似于桶排序的方法开始,我们称之为分块,然后用多重分块来扩展和改进这种方法。让我们通过对来自之前的博客文章的信用卡交易应用阻塞来具体说明这一点。

基本阻塞

我们的目标是产生所有高评分的信用卡交易对。为此,我们对邮政编码进行“屏蔽”。这意味着,我们不是使用 O(n ) compute 对所有交易对进行评分,而是只考虑具有相同邮政编码的交易对。给定每个邮政编码最多 m 个邮政编码交易,那么每个交易将只需要与最多 m 个其他交易进行比较,需要 O(n*m)的计算和空间。如果 m 是ω(n ),这仍然是二次的,但是如果一个开发者成功地使 m 比 n 小得多,性能可以变得容易处理。

请注意,这为我们的相似性评分管道增加了一个额外的步骤。首先,我们生成候选对,用分块来评分,然后用我们的相似度函数对这些候选对进行评分。在批处理和实时评分用例中,这是一个相对容易实现的附加步骤。如果我们的目标是批量产生所有高相似性得分对,我们可以通过邮政编码事务的自连接产生阻塞候选。对于实时相似性评分,可以预先计算映射邮政编码-> set(邮政编码中的交易)的查找表,并根据该表高效地查找新的交易邮政编码。

块密钥过滤和联合

您可能认为阻塞是缓解 n 问题的一种非常简单的方法,但是性能和质量会受到阻塞键选择的显著影响。例如,由于我们对邮政编码的选择,我们永远不会匹配不同邮政编码的信用卡交易,从而降低了召回率。精确度和假阳性应该不会受到阻塞的严重负面影响,因为我们根据分数后过滤掉候选匹配,但是大量的假阳性阻塞匹配会影响性能。10%精度的阻塞精度意味着我们必须将 5 倍于 50%阻塞精度的示例数计分。低得多的精度(如 1%或 0.1%)可能会对性能产生 100 或 1000 倍的影响,因为有大量虚假候选项需要评分,因此非常低的精度可能会导致非常差的性能(尽管质量不太可能)。

影响精度和性能的最常见问题之一是重键。如果我们通过邮政编码阻止信用卡交易,其中一个邮政编码在曼哈顿,比如说有 100 万笔交易,我们可能需要对大约 100 万笔交易进行相似性评分。缓解这一问题的一个简单方法是过滤掉重要的阻塞键。所以先按键计算实体的计数,不要在计数高的键上自连接或匹配。然而,这以质量为代价提高了性能:我们永远无法匹配曼哈顿的两个事务!处理这个问题的一种方法是生成多组阻塞键,以及跨这些键的联合候选。例如,我们可以考虑对具有相同邮政编码或供应商名称的交易对进行评分。潜在匹配候选项的数量最多与候选键类型的数量成线性比例,因此联合几个正交的块键不会显著影响性能。

在许多情况下,仔细选择和联合块密钥,并过滤掉重要的密钥,就足以产生达到质量和性能标准的评分管道。当只有重要的键(名字、性别、邮政编码)可用时,有一些更困难的用例。这就引出了我们的最后一个阻塞变体:多重阻塞。

多重阻塞

这里的方法是:代替作为 K_name,K_gender,K_zip 上的块密钥的并集的块密钥集合 K(e ),将块密钥定义为这些集合的笛卡尔乘积。所以一个键可能是(Emily,女,12345)。这些组合键的出现频率较低,因此对性能的影响比仅阻止性别更低。这些键可以像正常的阻塞键一样在频率上进行过滤,或者如果独立的话,可以通过组成键的频率的乘积进行过滤(例如 count(Emily)* count(female)* count(12345)< thresh)。后者可能更有效,因为不同边缘计数的数量应该小于笛卡尔积键的不同计数。

对阻塞键、组合和频率的深思熟虑的选择为实现留下了很大的设计空间。当唯一可用的数据是矢量嵌入时,如何应用这种方法也不清楚。接下来,我们将考虑一组不同的解决 n 问题的方法,它们开箱即用,并且在向量嵌入上运行良好。涉及的算法更复杂,实际上通常在库中实现。

3.近似 K 近邻(AKNN)

AKNN 简介

在上一节中,我们假设我们的数据由许多列组成,可以从中选择块键(zip、name 等),我们将仔细选择块键来处理 n 问题。如果我们处在一个输入是单个向量的世界,比如说一个由图像上运行的深度卷积网络产生的向量,会怎么样?如果我们的相似度函数是欧几里德相似度或者余弦相似度呢?

然后,我们将问题简化为用常用的矢量距离求解最近邻。近年来,在大规模近似求解最近邻的方法方面取得了很大进展,Spotify 和脸书等大型科技公司使用这些方法来处理数十亿条记录。

了解各种方法的性能并保持最新的一个好方法是查看近似最近邻基准库。如果你现在仔细看,你会看到 HNSW 出现在大多数表现最好的图书馆中。从某些指标来看,该算法是规模上性能最好的算法,并让我们回到我们开始时的排序类比!

最新技术水平:HNSW

事实证明,HNSW 被很好地理解为对跳过列表的概括。我们可以把跳表数据结构想象成一棵分层的树。底层是包含排序项目的链表,排序链表上面的层仅具有前一层中项目的“p”部分。根据实现情况,这可以无限地继续下去。查找是通过在顶层找到最匹配的项目,然后在下面的每一层进行局部搜索,直到在底层。

HNSW 的底层连接每个项目的 K 个最近邻居,而不是链表。上面的层对 p 个节点进行采样,连接这些节点的最近邻居。这种情况一直持续到各层。查找、插入、删除以类似于跳表的方式发生,但是在邻域图上而不是在链表上。例如,查找从顶层开始,沿着 KNN 图爬行,直到到达具有最接近匹配的局部最小部分,然后继续向下到较低层。然后,对于 n 个候选实体,我们还期望 HNSW 中插入、查找、删除操作的性能为 O(logn)。就像二叉查找树 O(logn)操作可以用于在 O(nlogn)操作中对数据集进行排序一样,我们可以在 O(nlogn)操作中使用 HNSW 索引来检索大小为 n 的数据集中相似性得分最高的实体对。

有许多其他完全不同的近似最近邻搜索方法。一些 AKNN 索引需要较少的内存,或者更容易实现(一些 LSH 方法)。尽管在大多数情况下,HNSW 支持的库,如 FAISS 和任何在近似最近邻基准库中列出的 HNSW 支持的 python 库应该工作良好。

从我们之前的帖子到现在,我们已经调查了获得高性能和高质量的相似性评分管道所需的部件。缺少的是评估性能和为训练获取无偏见的标签,由于 n 问题,这被证明是一个不平凡的努力。

4.标签收集和性能评估

为了建立高质量的分数,有必要提供标记的数据和量化的性能评估。为此,让我们从简单的二进制分类度量开始。假设对于随机采样的实体对,我们标记真/假,这些实体是否应该匹配。然后,我们可以计算 ROC/精确召回曲线,并使用与标签对齐的标记实体对的分数计算 F1/AUC。

召回集合

这种方法听起来很简单,但是在实践中会很快遇到另一种形式的 n 问题:严重的类倾斜。假设我们有一个 n=1 亿个实体的基础事实集合,平均每个基础事实中的实体匹配 100 个其他实体。由于我们将所有成对的实体(n(n-1)/2 ~ n)视为要标记的示例空间,因此我们的二进制分类基础率是~100n/n = 100/n = 1/1M。请记住,召回率是# {真阳性}/(# {真阳性}+# {假阴性}),因此我们需要标记几百万对来获得对假阴性和召回率的统计意义上的估计:对于大多数应用程序来说,这是一个难以维持的标签数量。根据定义,我们的模型不能帮助我们找到它不能找到的配对(假阴性),那么我们该怎么办?手动从百万双鞋中筛选出更多的匹配?

一种方法是随着时间的推移使用各种资源来不断改进我们称之为“回忆集”的东西。对于一个相对较小的(假设 50 个)随机抽样的信用卡交易集,一个“回忆集”给出了匹配 S 中某个交易的每一对交易。给定这个集 S,我们就可以通过运行模型来查找所有模型预测的与集 S 的连接,从而获得对真阳性和假阴性的无偏度量来估计回忆。这个集很小是因为在构建它时需要的劳动:使用特别搜索、模型的先前版本和数据集范围的可视化/过滤的组合。随着相似性模型的改进和捕捉不同种类的匹配,这个“回忆集”也可以随着时间积累。这是我们能够找到的与 S 相关的最大匹配集,随着时间的推移,我们可以改进并使用它来更好地评估我们的算法。虽然劳动密集,但收集这一集合并使用它来训练模型和提高评分通常是非常值得的投资。

精度呢?给定一个固定的模型,top-N precision 很容易评估:截取前 N 个得分对,标记并计算精度度量。因为我们希望精确度大于 1%或者甚至大于 50%,在这个过滤的高分集合中的类别不平衡不像召回那样糟糕,并且通常只需要 10 或 100 个标签。缺点是,这需要为每个新模型版本重新标记顶部的 N 对。为了避免重新标记,我们可以使用上面定义的召回集来嘈杂地评估实验模型,并且仅对于重要的模型,重新标记前 N 对,以更准确地估计具有大量标记的精度。

按集群大小对指标进行加权

我们已经介绍了如何在一个高度类倾斜的环境中收集标记数据集来估计精度和召回率,但是这些度量标准是正确的目标吗?在评估相似性评分的精确度和召回率时出现的一个常见问题是高度关联的实体。假设我们发现了一个大型集群,其中有一家银行的 10 万笔欺诈交易应该与其他银行的交易相匹配。我们的召回指标将高度倾向于评估该集群的质量:大小为 k 的集团中匹配对的数量是该集团大小的 O(k ),而不是 O(k)。我们通常希望我们的误报和漏报在事务数量中按比例(而不是平方)计算。减轻这个问题的一个方法是降低召回集中的假阴性计数。对于具有 k 个连接的实体,不是每个连接的实体对真阳性和假阴性贡献计数“1 ”,而是它们贡献 1/k。对于精度,类似的调整是可能的,最终结果是我们仅将集团对总度量的贡献加权为 O(k)而不是 O(k)。

以上是对相似性评分进行性能评估的最简单的方法之一,但绝对不是唯一的方法。为了弱化二元是/否的匹配,使用了三元标签和基于排名的评分/度量/损失函数。有时计算最终聚类和连接组件的质量度量,而不是对相似性分数的质量度量也是明智的。与大多数机器学习问题一样,一开始保持指标简单,然后增加复杂性是明智的。

5.总结

以上主要提示可以总结为:

  • 阻塞是缓解 n 问题的一种简单但劳动密集型的方法。按频率过滤掉候选的阻塞键,当组合键时,尽量选择那些键是独立的。
  • 当相似性评分是对向量的简单欧几里德/余弦相似性/雅克卡度量时,值得考虑开箱即用的近似最近邻方法。从大多数基准来看,HNSW 是目前性能最好的方法,并且有许多易于使用的库支持它(FAISS、python 库等)
  • 在早期投入资源收集回忆集,并继续改进它。这将指导您的建模和评分改进工作
  • 如果您在数据中观察到大集团,请尝试用基础真实数据集中与之匹配的实体数量来贴现每个实体的召回/精确计数。

人工智能进化的极限初探

原文:https://towardsdatascience.com/a-preliminary-inquiry-into-the-limits-of-ai-evolution-aca59a85919f?source=collection_archive---------49-----------------------

Photo by Joni Gutierrez on Unsplash

这篇文章的原因与提出主张或回答问题关系不大,更多的是提出问题或为主张的基础扫清障碍。这是在我读了冷泉港实验室的神经科学家安东尼·m·扎多尔的“对纯粹学习的批判以及人工神经网络能从动物大脑中学到什么”之后开始的。读了他在自然通讯杂志上的文章后,我给写了我自己的评论,并进一步阅读了伊曼纽尔·康德的《纯粹理性批判》和路德维希·维特斯坦根的《哲学研究》正是在这些阅读中,我感受到了一些与扎多尔在他的文章中所讨论的内容的共鸣。这些事件也让我对人工智能(AI)进化的可能极限产生了疑问和思考。

但是首先,威廉·布莱克的一句话

首先,限制这个词可能太过强烈,或者不准确。渐近也不能完全解释我想表达的意思。威廉·布莱克在《伦敦》一诗中发现的短语“思想禁锢的镣铐”可以重新表述为,限制更多地与所谓的“思想禁锢的敏感性”有关。在这里,这首诗的前两节值得考虑,作为进入我所看到的康德对理解的限制的入口。第一节如下:

我漫步在每一条特许的街道上,

靠近特许泰晤士河的地方。

在我遇见的每一张脸上留下印记

软弱的标志,悲哀的标志。

从最简单的层面来看,布莱克描述了新兴工业革命的伦敦,以及更加规范的生活所带来的破坏。这一点主要通过“特许”一词的使用得到证实,这是一种政府行为,将权利给予一些人,而排除其他人。有趣的是,这个词既适用于人造街道,也适用于自然河流。这个时代的组织原则,任何时代的组织原则,总是无处不在。(你可以在本文末尾找到整首变得相当可怕的诗。)

Charter’d streets and charter’d Thames from 19th-century copper engraving.

在接下来的两行中,布莱克用了三次“马克”这个词。首先,诗的说话者,或者说诗的主题,在他遇到的每一张脸上留下了他的印记,他的解释。在第二对例子中,好像主体已经有了标记的迹象,它们同时塑造了说话者-主体的理解。在第二节中,演讲者详述了这种并发性:

在每个人的每一声呼喊中,

在每个婴儿恐惧的哭喊中,

在每一个声音里;在每一条禁令中,

我听到了思想的枷锁

很明显,“every”这个词在前三行出现了五次,然后得出一个显著的结论,即组织我们感知的方式不仅无处不在,而且是我们理解一切的方式。塑造我们对现实的感知的正是感知现实的头脑结构。现在,我们进入了康德关于理解的讨论领域,我认为理解是任何一种智力的核心。

康德认为,我们对现实的认识不是对事物本身的认识,也不是对一个物体在我们头脑中的外观的认识。我们对现实的知识,我们的理解,来自于一个中介位置,在这个位置上,我们的头脑有一套已经建立的方法来解释感官输入,并将它们转化为现实的模型。

AI 是否梦想电哲学?

让我们现在考虑一个能够在我们称之为一般智能的水平上学习的人工智能实体,让我们现在同意这个壮举已经完成。我的第一个问题是,既然人类设计并建造了这个实体,它是否有可能拥有除我们自己之外的任何其他一套解释数据和构建现实模型的手段,或者与我们自己如此接近以至于外部观察者可以忽略不计的东西。简而言之,人工一般智能(AGI)会有我们自己的“思维强化的敏感性”与之抗衡吗?

第二,对于一个 AGI 人来说,用不同的方式解释一个自在之物和获取知识,这怎么可能,而且可能吗?我自己对此的初步回答是,我看不出 AGI 实体如何不违反空间、时间和因果关系的先验给定。这仍然没有回答一个人工智能实体是否可以像我们一样聪明,甚至更聪明的问题。

进化的大飞跃

我敢说,一个人工智能实体变得一样聪明或更聪明的唯一方法是接受我们的“思维强化的敏感性”完全逃避这种敏感性是不可能的,除非我们接受某种能够对抗物理的精神世界的概念。有些人可能想去那里,但我不想去。因此,相反,让我们考虑一个人工智能实体将需要以某种方式复制大脑进化,以实现其自身的“思维强化的敏感性”,作为智能的先决条件。正如最近在推特上关于先天机制的讨论中提到的,我认为有两种前进的方式。一个是 T4 的白板进化,人工智能实体从零开始。二是直接进化,我们扮演神的角色。对于这个讨论,我们将把造物主可能的善意或恶意的意图放在一边,尽管,说实话,这比我在这里讨论的要重要得多。

正如自然/人工智能研究员加里·马库斯在“天赋、零阿尔法值和人工智能” 中指出的,进化是不可能的。也许,接近白板进化的唯一方法是建立一个精简的人工神经网络,让它探索所有这些路径的通用集合中的每一个可能的进化路径。这可能是无限的,所以我们可能需要等待很长时间才能找到通往 AGI 的道路。或者,我想,我们可以运气好,让它在搜索的早期出现。作为设想这一研究的一种方式,神经科学家 Zador 指出,大自然在智力进化中使用了近乎蛮力的方法,花费了 5 亿年时间,在实验中测试了大约 10 个物种,公平地说,实验仍在进行中。如果我们有足够的时间,无方向的人工智能进化可能会非常有趣,尽管问题仍然是这些智能是否会彼此完全不同。这似乎给我们留下了定向人工智能进化。

如果我们在定向进化的不同阶段设计网络和建立参数,甚至超参数(事实上,这就是我们正在做的),那么我无法想象我们的 AGI 孩子为什么没有我们“思维强化的敏感性”的标记,就像我们有我们灵长类祖先的标记一样。请记住,对哈尔在电影《2001:太空漫游》中的行为的一个可能的解释是,他不相信飞船上的人类会像他一样致力于这项任务。当你想到弗兰克和戴夫冷漠的举止时,谁又能责怪哈尔呢?

我似乎坚信,一个 AGI 实体不可能比我们聪明多少,也不可能比我们不同多少。事实并非如此。本体宇宙是浩瀚的,不是完全可知的。然而,正如康德所说,我们无法证明无法想象的东西不存在。我们通过在这些边缘工作来扩展人类的学习。最后一个想法:让我们考虑这样一个 AGI 实体,它确实存在,而我们由于我们的“思维强化的敏感性”而无法想象它的存在。她也有一种我们无法理解的“思想上的敏感”。哲学家路德维希·维特斯坦根有一句名言:“如果一头狮子会说话,我们就无法理解它。”那么,我们和她怎么能互相交谈呢?

补遗

以下是相关的,但并不意味着从上面的。仅仅是我阅读后的想法或事情 1) “天赋、阿尔法零和人工智能”加里·马库斯和 2)神经科学启发的人工智能戴密斯·哈萨比斯、等人

1)好吧,这个有点刻薄!一个 AGI 实体能或愿意设计一个复杂到赢不了的游戏吗?

2)由于似乎有大量关于视觉系统的人工智能研究(我想是因为我们人类如此注重视觉),我想知道一个 AGI 实体需要什么样的感官?让我们假设这个 AGI 实体是在其他 AGI 实体的一些网络中的一个节点,具有一定程度的领土意识来建立身份。它需要什么感觉?其实运动的需求是什么?

伦敦

威廉·布莱克

我漫步在每一条特许的街道上,

靠近特许泰晤士河的地方。

在我遇见的每一张脸上留下印记

软弱的标志,悲哀的标志。

在每个人的每一声呼喊中,

在每个婴儿恐惧的哭喊中,

在每一个声音里:在每一条禁令里,

我听到了思想的枷锁

扫烟囱的人如何哭泣

每个黑暗的教堂都令人恐惧,

倒霉的士兵叹息着

流淌在宫殿的墙上

但是大多数午夜的街道上,我听到

年轻的妓女如何诅咒

炸开新生婴儿的眼泪

用瘟疫摧残婚车

*args,**kwargs 的初级读本,数据科学家的装饰者

原文:https://towardsdatascience.com/a-primer-on-args-kwargs-decorators-for-data-scientists-bb8129e756a7?source=collection_archive---------14-----------------------

蟒蛇短裤

对于编码来说,理解是至关重要的

Photo by Almos Bechtold on Unsplash

Python 有很多构造,在我们的代码中学习和使用起来相当容易。当我们在代码中遇到一些构造时,它们总是让我们感到困惑。

还有一些甚至是经验丰富的程序员也无法理解的。装饰者就是属于这一类的一些构造。

我猜我的许多数据科学朋友也面临过这些问题。

大多数 seaborn 函数都以某种方式使用*args 和**kwargs。

或者装修工呢?

每次你看到一个警告,像一些功能将在下一个版本中被否决。sklearn包为此使用了装饰器。你可以在源代码中看到@deprecated。这是一个装饰函数。

在这个名为'Python Shorts,‘的系列帖子中,我将解释 Python 提供的一些简单构造,一些基本技巧和我在数据科学工作中经常遇到的一些用例。

这篇文章是关于用一种简单易懂的方式解释一些难懂的概念。

什么是*args?

简单来说, 你可以用 ****args*** 给你的函数任意数量的输入。

一个简单的例子:

假设我们必须创建一个将两个数相加的函数。在 python 中我们可以很容易地做到这一点。

def adder(x,y):
    return x+y

如果我们想创建一个函数来添加三个变量呢?

def adder(x,y,z):
    return x+y+z

如果我们想让同一个函数加上未知数量的变量呢?请注意,我们可以使用*args*argv*anyOtherName来完成此操作。重要的是*

def adder(*args):
    result = 0
    for arg in args:
        result+=arg
    return result

*args所做的是,它接受你传递的所有参数,并向函数提供一个可变长度的参数列表,你可以随意使用。

现在,您可以使用如下相同的函数:

adder(1,2)
adder(1,2,3)
adder(1,2,5,7,8,9,100)

诸如此类。

现在,你有没有想过 python 中的 print 函数怎么可以带这么多参数?

什么是**kwargs ?

简单来说, 你可以使用 ****kwargs** 给你的函数任意数量的关键字输入,并使用字典访问它们。

一个简单的例子:

假设您想要创建一个打印函数,它可以将姓名和年龄作为输入并打印出来。

def myprint(name,age):
    print(f'{name} is {age} years old')

简单。现在让我们说,你希望同一个函数有两个名字和两个年龄。

def myprint(name1,age1,name2,age2):
    print(f'{name1} is {age1} years old')
    print(f'{name2} is {age2} years old')

你猜对了我的下一个问题是: 如果我不知道我将需要多少个参数呢?

我能用*args吗?猜不到,因为姓名和年龄顺序至关重要。我们不想写“28 岁是迈克尔的年龄”。

来图中的**kwargs

def myprint(**kwargs):
    for k,v in kwargs.items():
        print(f'{k} is {v} years old')

您可以使用以下方式调用此函数:

myprint(Sansa=20,Tyrion=40,Arya=17)Output:
-----------------------------------
Sansa is 20 years old
Tyrion is 40 years old
Arya is 17 years old

请记住,我们从未将珊莎、艾莉亚或提利昂定义为我们的方法参数。

这是一个非常强大的概念。许多程序员在编写包装器库时非常巧妙地利用了这一点。

例如,seaborn.scatterplot函数包装了 Matplotlib 中的plt.scatter函数。本质上,使用*args**kwargs,我们也可以提供plt.scatter可以带给seaborn.Scatterplot的所有参数。

这可以节省大量的编码工作,并且使代码经得起未来的考验。如果在将来的任何时候plt.scatter开始接受任何新的参数,seaborn.Scatterplot函数仍然会工作。

什么是装修工?

简单来说: 装饰器是包装另一个函数从而修改其行为的函数。

一个简单的例子:

假设我们想在我们的一些功能中添加自定义功能。其功能是,每当调用函数时,打印“function name开始”,每当函数结束时,打印“function name结束”和函数花费的时间。

让我们假设我们的函数是:

def somefunc(a,b):
    output = a+b
    return output

我们可以在所有函数中添加一些打印行来实现这一点。

import time
def somefunc(a,b):
    print("somefunc begins")
    start_time = time.time()
    output = a+b
    print("somefunc ends in ",time.time()-start_time, "secs")
    return outputout = somefunc(4,5)OUTPUT:
-------------------------------------------
somefunc begins
somefunc ends in  9.5367431640625e-07 secs

但是,我们能做得更好吗?

这是装修工擅长的地方。我们可以使用 decorators 来包装任何函数。

from functools import wraps
def timer(func):
    [@wraps](http://twitter.com/wraps)(func)
    def wrapper(a,b):
        print(f"{func.__name__!r} begins")
        start_time = time.time()
        result = func(a,b)
        print(f"{func.__name__!r} ends in {time.time()-start_time}  secs")
        return result
    return wrapper

这就是我们如何定义任何装饰者。functools帮助我们使用wraps创建装饰者。本质上,在上面的装饰器中,我们在任何函数被调用之前做一些事情,在函数被调用之后做一些事情。

我们现在可以使用这个timer装饰器来装饰我们的函数somefunc

[@t](http://twitter.com/decorator_func)imer
def somefunc(a,b):
    output = a+b
    return output

现在调用这个函数,我们得到:

a = somefunc(4,5)Output
---------------------------------------------
'somefunc' begins
'somefunc' ends in 2.86102294921875e-06  secs

现在我们可以将@timer添加到我们想要打印时间的每个函数中。我们结束了。

真的吗?

连接所有的部分

如果我们的函数有三个参数呢?还是很多论据?

这就是我们到目前为止所学到的东西的联系。我们使用*args**kwargs

我们将装饰函数更改为:

from functools import wraps
def timer(func):
    [@wraps](http://twitter.com/wraps)(func)
    def wrapper(*args,**kwargs):
        print(f"{func.__name__!r} begins")
        start_time = time.time()
        result = func(*args,**kwargs)
        print(f"{func.__name__!r} ends in {time.time()-start_time}  secs")
        return result
    return wrapper

现在我们的函数可以接受任意数量的参数,我们的装饰器仍然可以工作。

Python 是不是很好看?

在我看来,装修工可能会很有帮助。我只提供了装饰者的一个用例,但是有几种方法可以使用它们。

您可以使用装饰器通过检查函数中的参数来调试代码。或者可以使用装饰器来计算特定函数被调用的次数。这可能有助于计算递归调用。

结论

在这篇文章中,我谈到了一些你可以在 python 源代码中找到的结构,以及你如何理解它们。

没有必要现在就在代码中使用它们。但是我想理解这些东西是如何工作的有助于减轻每当这些结构出现时人们所面临的困惑和恐慌。

对于编码来说,理解是至关重要的

另外,如果你想了解更多关于 Python 3 的知识,我想向你推荐密歇根大学的一门优秀的中级 Python 课程。一定要去看看。

将来我也会写更多初学者友好的帖子。让我知道你对这个系列的看法。在 媒体 关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。

朱莉娅的计算机视觉初级读本

原文:https://towardsdatascience.com/a-primer-on-computer-vision-with-julia-2c7068a35b32?source=collection_archive---------19-----------------------

学习如何使用 CNNJulia识别数字

Image by cocoparisienne from Pixabay

这个帖子是关于卷积神经网络 (CNN)使用 Julia 的速成班。CNN 是一种奇特的功能,可以被“训练”来识别图像中的模式。在这篇博文中,我介绍了计算机视觉的“Hello World”:来自 MNIST 数据集的手写数字分类。互联网上有数以千计的免费 Python 教程。

而是让我们使用 Julia 和包 Flux.jl 。为什么?因为 Julia 的速度很快,如果你有数百万张图片要分析,与 Python 相比,速度会大大加快。这篇博文的 Jupyter 笔记本可以在这里找到。

数据

MNIST 数据集包含灰度手写数字(0 到 9)的图像,这些图像居中对齐。每个像素由一个介于 0(黑色)和 255(白色)之间的数字表示。每幅图像都是 28 乘 28 像素。表示图像的一种方式是将其视为 28*28 = 784 像素的一维列向量。然而,这种表示忽略了图像的“结构”:彼此靠近的像素在我们试图识别的数字上是有信息的。CNN 是一个很好的工具,可以保持图像的空间结构,同时避免与维度诅咒相关的问题:图像是嘈杂和高维的输入数据。

美国有线电视新闻网的速成班

CNN 的两个关键组成部分是卷积层(因此得名)和最大池层

卷积层

卷积层对每个点应用一个模板。卷积层的输出是较低维度的“图像”,它提供了输入图像的某些特征(形状、边缘等)的信息。).下图显示了卷积层的工作原理:

How a convolutional layer works. Source: https://mitmath.github.io/18337/lecture14/pdes_and_convolutions

最大池层

最大池层是一个模板,用于选择正方形内的最大值。下图是应用于 4x 4 图像的 maxpool 层:

Illustration of a maxpool layer. Source: https://mauriciocodesso.com/post/convolution-neural-network/

步幅和衬垫

构建 CNN 时,必须指定两个超参数:步幅和填充

  • 当跨度等于 1 时,我们一次移动一个像素的过滤器。当跨距等于 2 时,我们一次移动两个像素的过滤器,等等。
  • 填充是指在图像的边界“加零”。填充可用于控制输出音量的大小,并有助于保持图像边界的信息

下面是一个应用于 5×5 输入的 3×3 滤波器示例,该输入使用 2×2 步长填充了 1×1 零边界:

How padding works. Source: http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html

CNN 的典型基础设施是首先对输入图像应用卷积层,然后使用最大池层,最后使用全连接层。在使用全连接(FC)层之前,可以将几个“卷积层—最大池层”单元堆叠在一起。请注意,激活层(通常为 ReLU )通常插在卷积层和最大池层之间。

CNN architecture. Source: https://towardsdatascience.com/visualizing-the-fundamentals-of-convolutional-neural-networks-6021e5b07f69

使用 Flux.jl

Flux.jl 是 Julia 生态系统中领先的机器学习包。接下来,我们加载 MNIST 数据集的训练样本和测试样本。训练样本是一组用于微调 CNN 参数的图像,而测试样本包含用于检查我们没有过度拟合训练样本的图像。过度拟合的确凿证据是训练样本的精度比使用测试样本图像的精度好得多。

Loading Julia packages and data

CNN 架构

在使用 FC 层之前,我们的 CNN 有通常的 Conv->ReLU->MaxPool 组件。我们使用 1 乘 1 的填充,跨距为 1(默认值)。通过使用 2 乘 2 最大池层,输入的大小逐渐减小。Flux.jl 中的默认激活是函数 x->x。这里,我们使用校正线性单位函数(ReLU)来代替:

Building the model

ReLU 激活函数是分段线性函数。在 Krizhevsky 和合著者的“使用深度卷积神经网络的 ImageNet 分类”论文中,作者写道:

我们把具有这种非线性的神经元称为整流线性单元(ReLUs)。具有 ReLUs 的深度卷积神经网络比具有 tanh 单元的等效网络训练速度快几倍。

ReLU 激活功能也有助于减少由消失梯度问题引起的实际问题。也就是用来寻找我们 CNN 的参数的最小化算法的失败。下面是 ReLU 激活功能的曲线图:

xgrid = collect(range(-1, 1, length=100)) plot(xgrid, NNlib.relu.(xgrid), label = "relu(x)", title="ReLU activation function", xlabel="x")

ReLU activation function

培养

定量

批量大小是一个参数,它告诉我们网络在“训练”时一次会“看到”多少幅图像。用技术术语来说,当执行梯度下降时,我们不会一次使用所有信息(因为内存限制,也因为不一定高效)。以下函数生成“批量”图像:

Batching

损失函数和最小化

CNN 要“学习”任何东西,它必须有一个“错”或“对”的概念。损失函数正是通过量化模型在识别数字方面的表现来做到这一点的。当输出是一个概率时,交叉熵损失函数是合适的。最后一步是选择一种算法来最小化损失函数。这里,让我们选择 ADAM 算法,我把它理解为某种带有动量和自适应学习率的随机梯度下降:

Loss function

该模块“训练”(微调 CNN 参数值)模型,直到达到预定的精度水平:

Training

预言

一旦模型被训练,预测值很容易获得如下:

# Get predictions and convert data to Array: 
pred = Tracker.data(model(test_set[1])); 

# Function to get the row index of the max value: 
f1(x) = getindex.(argmax(x, dims=1), 1) # Final predicted value is the one with the maximum probability: 
pred = f1(pred) .- 1; #minus 1, because the first digit is 0 (not 1)

让我们看看模型在测试集上的表现。CNN 可以使用训练模型时没有使用的图像来识别数字吗?正如您在下面看到的,我们的模型在识别手写数字方面做得非常出色:

println("Predicted value = $(pred[1])") a = reshape(test_imgs[1], NROWS, NCOLS)Predicted value = 7

println("Predicted value = $(pred[2])") a = reshape(test_imgs[2], NROWS, NCOLS)Predicted value = 2

println("Predicted value = $(pred[3])") a = reshape(test_imgs[3], NROWS, NCOLS)Predicted value = 1

准确性检查

我们现在有了一个模型,它在识别数字方面似乎做得很好。但是我们能改善它吗?如果是,如何实现?为了改进我们的模型,我们首先需要确定它失败的时间和原因。

混淆矩阵

为此,一个有用的报告工具是混淆矩阵。混淆矩阵的每一行显示真实值的实例,而每一列显示预测值的实例。理想情况下,我们希望我们的模型能够完美地预测结果。对于一个完美的模型,所有的实例都位于混淆矩阵的对角线元素上。

我最后一次检查时,Flux.jl没有一个内置函数来计算混淆矩阵。幸运的是,包MLBase中提供了一个实现。下一个代码块计算混淆矩阵并显示出来。大多数实例位于对角线上,这并不奇怪,因为我们的模型的准确率超过 97.0%

using MLBase # Adding 1 to outcome because the index 0 in arrays does not exist in Julia:
Cm = confusmat(10, test_labels .+ 1, vec(pred) .+ 1)# Normalize output: 
Cm = Cm ./ sum(Cm, dims=2) # Labels 
xs = [string(i) for i = 0:9] 
heatmap(xs, xs, Cm, aspect_ratio=1, color=:plasma)

Heatmap for the confusion matrix

为了可视化我们的模型在哪里出错,我们可以使用可选参数clim,给底层的颜色图加上一个上限。例如,下一个图显示我们的模型在区分 7 和 2 或者 8 和 2 时有困难。

# Limits to colormap, so we can see where errors are located: 
xs = [string(i) for i = 0:9] 
heatmap(xs, xs, Cm, aspect_ratio=1, color=:plasma, clim=(0., 0.01))

Heatmap for the confusion matrix

误差分析

下一段代码显示了 CNN 失败的数字:

using ImageView, Gtk.ShortNames
# indices for errors: 
mistakes = test_labels .!= vec(pred) 
max_images = 5 grid, frames, canvases = canvasgrid((1,max_images));k=0#counter 
for mistakes for (j, i) in enumerate(mistakes) 
    if i == true k+=1 # a false value has been found 
       println("Predicted value = $(pred[j])") 
       println("True value = $(test_labels[j])") 
       imshow(canvases[1,k], test_imgs[j]) 
    end 
    if k >= max_images 
       break 
    end 
end 
win = Window(grid); 
Gtk.showall(win);Predicted value = 5 True value = 9 
Predicted value = 5 True value = 6 
Predicted value = 4 True value = 8 
Predicted value = 3 True value = 2 
Predicted value = 7 True value = 2

Five first prediction errors

虽然从左边开始的两个数字(见上图)显然是 9 和 6,但剩下的 3 个元素并不简单。中间的 8 很容易与其他数字混淆,剩下的两个数字形状怪异。

结论

在处理图像时,卷积神经网络通常在识别模式方面表现出色。这篇博文是对这个主题的非技术性介绍。而 Python 是机器学习中偏爱的工具(Keras,TensorFlow 等。),我猜测 Julia 会越来越受欢迎,因为 Julia 既好用又快。

参考

*这篇博文的代码大量基于这篇 Flux.jl 教程:https://github . com/flux ml/model-zoo/blob/master/vision/mnist/conv . JL
*关于 CNN 和 PDEs 的链接:https://MIT math . github . io/18337/lecture 14/PDEs _ and _ convolutions

原载于 2019 年 12 月 5 日https://Julien Pascal . github . io

模型拟合入门

原文:https://towardsdatascience.com/a-primer-on-model-fitting-e09e757fe6be?source=collection_archive---------18-----------------------

如何评估模型是否符合您的训练数据

数据科学本质上是使用数据来预测不同情况下会发生什么的实践。为了做到这一点,我们基于现有的数据集开发模型,然后使用这些模型来预测在相当类似的情况下会发生什么。这本质上是一种从已经发生的事情中学习的数学方法,并利用这种学习做出明智的选择。

这里显而易见的是,模型的预测和模型本身一样好。为了使模型返回准确的预测,它必须准确地匹配可用的数据集。如果它与可用的数据集不匹配,那么你可以肯定它不会返回不同情况下的准确预测。

模型怎么会和数据不匹配?

通常有两个术语用于描述模型如何无法匹配现有数据集。它们是:

  • 欠拟合:欠拟合模型是一种不够复杂,无法匹配可用数据的模型。它在匹配可用数据方面做得很差,因为它无法复制所有观察到的变化。欠适应模型的一个例子是,在一个累进税制结构的国家,有人根据统一税收假设来估计纳税额。在这种情况下,一个人支付的税收百分比随着其收入而变化,但该模型将假设每个人每美元的税率相同。
  • 过度拟合:过度拟合模型对于可用数据来说过于复杂。高复杂性使得模型对数据集有太多的改变,产生实际上并不存在的曲线和变化。它通常在匹配可用数据方面做得非常好,但无法准确预测数据点之间发生了什么。这种情况如何变得糟糕的一个例子是一个不确定模型的反面;一个基于累进税制结构(每一美元收入的税率都在变化)的假设的模型可能会正确地匹配每个人的纳税额,但对一个单一税制结构建模太复杂了。

图 1 提供了这些概念的可视化表示。用圆圈表示的系列称为“可用数据”,显示了累进税制结构下的理论所得税收入。假设的累进税制结构非常简单。第一万美元的税率为 10%,第二万美元的税率为 20%,第三万美元的税率为 30%,以此类推。增加了一点随机性,复制了不同家庭能够获得不同扣除额的事实(在美国税法中)。第二个系列用蓝线表示,称为“Underfit ”,是一个假设单一税收结构的模型。第三个数据系列名为“Overfit”,是一个 20 阶模型,假设了一个极其复杂的累进税制结构。

Figure 1: Underfit and Overfit Models for Our Theoretical Tax Structure

代表欠拟合模型的蓝线显然与数据拟合得很差。只有 3 点接近匹配的数据,要么高估或低估所有其他的。它也没有捕捉到数据的形状,没有捕捉到税率随着收入增加而增加的事实,产生了一个有点抛物线的数据集。

红线代表过度拟合模型,与可用数据几乎完全匹配。每一个数据点都以非常高的精确度匹配。它也很好地捕捉了数据的形状…直到年收入超过 40,000 美元。从每年 40,000 美元到 44,000 美元,该模型预测应付税款基本上没有变化,然后突然从每年 44,000 美元急剧增加到 45,000 美元。这个模型显然低估了这个范围。但真正的问题出现在 45,000 美元到 50,000 美元之间。该模型预测,当收入从 45,000 美元增加到 49,000 美元时,税收每年增加 22,000 美元,但没有任何数据表明这是准确的。然后,从每年 49,000 美元到 50,000 美元,预期税收减少 20,000 美元,以返回到匹配数据。该模型预测不存在的数据的趋势,并且无法预测可用数据点之间的税收值。

什么键可以识别欠拟合和过拟合模型?

当试图识别欠拟合和过拟合模型时,要寻找的关键点是图 1 的描述中提到的项目。为了明确地指出它们,这些不同类型的模型问题可以通过以下方式来识别。

可以识别欠拟合模型,因为它们:

  • 未能与可用数据点紧密匹配,以及
  • 没有捕捉到可用数据集的大致形状。

过度拟合模型可以被识别,因为它们:

  • 非常好地匹配可用数据(注意,这本身不能识别过度拟合模型,但应被视为警告信号),以及
  • 显示可用数据中不存在的预测趋势。

完美的模特是什么样的?

一个合适的模型应该与可用的数据紧密匹配(完美是最好的,但可能性极小),同时还要与数据的总体形状紧密匹配。图 2 提供了这种模型的一个例子。它呈现了与图 1 相同的总图,黑色圆圈仍然代表我们编造的数据集中可用的税收收据。绿线代表符合数据的三阶模型。

Figure 2: An Example of a Well Fit Model

请注意,代表三阶回归的绿线与可用数据并不完全匹配。这是不幸的,但却是现实的期望,尤其是因为数据集中包含了一点随机性。然而,它与每一个数据点都非常接近。此外,曲线的指数增长也符合可用数据的形状。对于可用数据来说,它既不像图 1 中的欠拟合模型那样过于简单,也不像过拟合模型那样过于复杂。相反,来自模型的每个预测都落在数据集中的高点和低点之间。因为它与数据的形状非常匹配,并且不会添加不准确的趋势,所以可以相信该模型在插值时会提供合理的预测。

我可以在哪里了解更多信息?

模型拟合,以及过度拟合和欠拟合的挑战,是数据科学中的核心概念。有许多不同的来源可以让你了解更多。我目前最喜欢的关于这些问题的讨论来源是 Joel Grus 的从头开始的数据科学。在我之前的一篇文章的中,我也提供了一个更加详细的模型开发和验证的描述。对于那些致力于投入大量时间尽可能多地学习的人,Coursera 提供了一门关于机器学习的优秀课程

包装它

模型开发和验证是数据科学中的核心概念。为了进行任何有价值的数据科学,我们必须拥有准确表示可用数据集的模型,并且我们相信这些模型能够很好地预测在类似条件下会发生什么。

导致模型返回较差预测的两个常见问题是欠拟合和过拟合。拟合不足意味着模型对于数据集来说不够复杂。这导致模型与测量的数据不匹配,并且不能模拟数据集的一般形状。过度拟合意味着模型对于数据集来说过于复杂。它会生成一个与模型极其匹配的模型,但会向数据集添加实际上并不存在的趋势。它看起来非常好,因为它与数据匹配得非常好,但是在插值时会产生非常不准确的结果。

一个非常适合的模型可能不会完美地匹配可用的数据。每一个预测都可能有一些误差。然而,它应该能准确地预测所有这些。此外,它应该捕捉数据集的形状,表明插值预测也将是接近的。

推荐引擎入门

原文:https://towardsdatascience.com/a-primer-to-recommendation-engines-49bd12ed849f?source=collection_archive---------19-----------------------

它们是什么,它们是如何工作的,以及它们为什么伟大。

推荐引擎现在无处不在。几乎你使用的任何应用都包含某种推荐系统,要么推送新内容,要么推动销售。推荐引擎是网飞告诉你接下来应该看什么,脸书上的广告推着你碰巧看过一次的产品,甚至是 Slack 建议你应该加入哪个组织渠道。大数据和机器学习的出现使推荐引擎成为数据科学最直接适用的方面之一。

假设你的朋友向你寻求电影推荐。你如何着手做这件事?如果你不太喜欢电影,而且不是你太了解的朋友,也许你可以谷歌一下,给你的朋友你找到的任何电影的答案。也许你的朋友告诉你他们最喜欢的类型是恐怖片——然后你推荐你知道的最好的恐怖片。或者,也许你的朋友给了你他们喜欢的电影的例子。然后你在脑子里处理这些数字,根据你对这些电影的了解和你对朋友的了解,给他们一些建议。这些场景中的每一个都是不同类型的推荐引擎的例子。

推荐引擎的类型

1.非个性化

非个性化推荐引擎是最简单的。你对你的朋友一无所知,对电影也知之甚少。你几乎没有数据,所以你只推荐了最受欢迎的东西,因为你的朋友很有可能会喜欢它,因为大多数人已经喜欢它了。

非个性化推荐引擎也非常容易实现,因为每个人都获得相同的推荐。你所要做的就是拿出一些指标来决定推荐什么,即最高评级、最高投资回报率(ROI)。还可以想想:YouTube 的新用户主页会推荐热门视频。

What does YouTube recommend to a new user?

看似琐碎,但非个性化的推荐可能非常有用。想象一下,你正在开展一项新的电子商务业务,你想在你的登录页面上发布产品推荐。也许这些产品已经在亚马逊上销售了,所以你可以看到这些产品的综合评分。如果你想提高销售额,你可能会决定推销评价最高的产品,因为你知道这些产品的客户满意度更高。你也可以决定推销给你最高投资回报率的产品,这样客户购买的每件产品都会给你带来更多利润。

2.基于内容

对于基于内容的推荐引擎,我们只处理项目数据。更具体地,项目的特征空间中的数据。例如,电影的项目数据包括预算、票房收入、类型、发行年份、演员等。

基于内容的推荐引擎背后的一个主要想法是相似性。想想在亚马逊购物——在它的产品页面上,你总会在产品下面列出类似的商品。这里使用的最简单和最直观的算法是一个最近邻算法,它使用一些相似性度量(如余弦相似性、欧几里德距离、皮尔逊相关等。)来确定与您的输入项目最接近的项目作为推荐返回。

Plant recommendations on the product page of a plant!

使用项目数据提出建议的一些其他方法:

  • 如果您想要一个用户的推荐,假设您有该用户的历史记录,即喜欢、不喜欢、评分… 您可以创建一个分类器来预测评分或某个项目是否会被喜欢/不喜欢。这也可以在聚合评级数据上完成,例如:获取 Yelp 上餐馆的总体评级,并使用餐馆功能,预测餐馆的评级。
  • 聚类方法可用于将项目组合在一起。这可以使最近邻方法运行得更快,因为不需要跨所有项目计算距离。
  • 当你有大量特征空间的数据时,比如图像,神经网络非常有用。我们可以通过(例如)卷积神经网络的倒数第二层来检索项目的嵌入,在这里更容易运行相似性度量来找到最相似的项目。

基于内容的推荐器(尤其是基于相似性的推荐器)非常适合推荐利基商品。也许出于某种原因,你真的很喜欢五分钱乐队臭名昭著的讨厌音乐。使用五分钱乐队的歌曲作为输入,基于内容的推荐器可能会向您推荐与五分钱乐队相似的歌曲,甚至其他五分钱乐队的歌曲,这取决于您的项目池。一个基于内容的推荐者不会考虑五分钱乐队的歌曲经常是低收视率的事实,除非你决定使用收视率作为一个项目特征。

这些超级具体的推荐是否是最好的取决于你的推荐者的背景。有时您确实想考虑用户特定的口味,有时又不想。如果你把恐怖电影输入推荐引擎,你只能得到其他恐怖电影的推荐。在不同的背景下,这可能是好事,也可能是坏事。

3.协同过滤

基于内容的推荐器仅使用项目数据,而协同过滤方法使用与项目相关的用户数据。更具体地说,检查来自特定用户的特定项目的数据。理想情况下,您的数据应该能够用一个效用矩阵来表示,一个轴是用户,一个轴是项目。

Utility matrix for 4 users (U) and 4 items (I).

效用矩阵通常是稀疏的,因为用户不会对所有项目进行评级。在上面的简单示例中,我们可以看到所有用户都对所有项目进行了评分,只有用户 1 对项目 3 进行了评分。协作过滤的工作原理是查看多个用户如何评价多个项目,或者多个用户如何评价多个项目,以尝试并猜测用户还会高度评价哪些项目。协同过滤的主要思想是填充效用矩阵的未知数,有几种方法可以做到这一点。

简而言之,计算空白值的一种方法是使用用户或项目之间的相似度,并对评分进行加权平均,以预测用户 1 对项目 3 的评分。该方法被称为用户-用户相似度项目-项目相似度,这取决于计算相似度所跨越的轴。

另一种预测未知用户项目组合评分的方法是通过流行的奇异值分解 (SVD)模型,这种方法因 2006 年 Netflix 奖竞赛期间的 Simon Funk 而闻名。该算法使用传统 SVD 的修改版本,通过生成表示用户和项目的两个分量矩阵,作为效用矩阵的分解,并通过交替最小二乘法执行梯度下降以得出评级预测。查看我的另一篇探讨协同过滤背后的数学的文章。

协同过滤不仅为每个用户提供个性化的推荐,还为数据集中的任何项目提供模型计算的预测评级,这可以方便地为用户提供关于项目的更多个性化见解。

尽管协同过滤(尤其是 SVD)已经被证明具有一些最有效和最准确的评级预测,但也有一些缺点。首先,有一个所谓的冷启动问题,你需要有大量的现有数据(关于他们如何评价多个项目的用户数据)才能开始计算评级。一个全新的用户将无法与任何人进行比较(因为没有关于新用户的数据),因此无法做出有见地的推荐。在进行任何类型的用户-用户或项目-项目比较之前,用户必须首先在系统中有一些评级。

协同过滤的另一个缺点是它的计算量太大(T4)。用户-用户和项目-项目模型的时间复杂度随着用户数量和数据集中项目数量的增加而增加。最后,往往会有一个受欢迎程度偏差,在这种情况下,经常被评为高等级的项目可能会对大多数用户有高的预测等级。

评估推荐引擎

在机器学习中,为了评估我们的模型,我们通常有一个成本函数来确定我们的模型表现如何。成本函数通常测量某种形式的误差,并给我们一种模型能够预测某种结果的感觉。对于推荐引擎,这仅在某些情况下有效。在协同过滤的情况下,可以进行典型的train-test-split来测试预测评级值与实际评级值有多远。

然而,对于基于内容的推荐引擎来说,这就不那么简单了。尤其是基于相似性的推荐,有一个潜在的假设,人们会喜欢与他们已经喜欢的东西相似的项目。并且这种相似性必须存在于数据中可用的特征/特性中。项目的复杂性和人们可以根据其喜欢程度的无限方面,使得很难评估基于内容的推荐系统实际工作得如何。有一个强力的解决方案——简单地向人们提供建议,然后看看这些建议效果如何。

接下来:

[## 数据科学的数学:效用矩阵上的协同过滤

理解推荐引擎协同过滤模型背后的数学原理

medium.com](https://medium.com/@yishuen/math-for-data-science-collaborative-filtering-on-utility-matrices-e62fa9badaab)

  • 用 Python 实现推荐系统(即将推出)

免责声明:我其实是五分钱乐队的粉丝。

以产品为中心的数据视图

原文:https://towardsdatascience.com/a-product-centric-view-of-data-e9b233eab6fa?source=collection_archive---------22-----------------------

如何从第一天开始就证明您的数据的价值

在我的职业生涯中,我有幸在许多技术本土公司工作过,在这些公司,敏捷性是业务的主要原则之一。然而,这种敏捷性源于这些公司的使命,即构建客户认为有价值的产品。像微软、亚马逊和 Expedia 这样的公司之所以能够持续增长,是因为它们使用数据进行内部优化,但通过为消费者构建新的数据智能产品来保护自己。

在过去的两年里,完全离开我在科技公司的舒适区,并在一个为我们的客户创造价值的绝大多数产品通常需要几个月时间,或者在推出新飞机的情况下,需要几年时间的行业工作,确实是一件有趣的事情。然而,仅仅因为一个业务不是数字化的,就没有理由不通过创造新的数据驱动的产品来推动公司走向未来。这可能只是需要多做一点工作,或者只是在政治上多一点难度。

所以,你可能首先会问。我的数据很好,为什么我要改变我使用数据的方式,或者我不知道你今天要求我改变什么。什么是产品思维,它与我们今天的工作方式有何不同?今天大多数项目组合管理团队运行数据构建的方式是以项目思维方式进行的。产品思维通常被视为数字团队领域的一部分。是的,“数字”团队……是的……那些被排挤的人藏在企业的一个不起眼的角落里,带着那些奇怪的白板、便利贴(wars)和纹身的潮人……或者更糟的是,给他们一个远离企业跳动的心脏的 WeWork 办公空间,因为他们不能整合(我的意思是……位于伦敦市中心的创新中心会有更高的效率)。我开玩笑(但我被允许)。我在这里支持的不是争论两者的优点和你应该选择哪一个,而是专注于其中一个的优点,作为从你的数据中获得更多价值的一种方式,甚至可能创建一个数据飞轮——这是我稍后将写的主题。

什么是产品思维模式,它与项目有何不同?

不想重新发明轮子,我发现这个定义是最有助于解释差异的定义之一。

产品是可以提供给市场以解决问题或满足需求的任何东西。

产品的生命周期由多个阶段组成。首先,产品被构思,然后被开发,然后在市场上被介绍和管理,最后,当对产品的需求减少时,产品被淘汰。

一个项目是为了创造一种独特的产品或服务而进行的临时性努力。对于一个项目,有一个明确的定义,什么需要在指定的时间内交付。

需要注意的是,一个产品只能在一个项目的环境中开发,而在一个产品的生命周期中可以有多个项目。

与项目不同,产品没有明确的定义需要交付什么。客户需求自然会随着时间的推移而发展,产品也必须发展以满足这些客户需求。

—孔比亚“产品和项目管理的区别”

非常简洁地:

产品:价值导向
项目:任务导向

许多数据团队首先以项目思维运作。这延伸到他们如何管理和治理数据、报告,甚至进行数据科学。定义的端点、设定的交付、以报告形式出现在表格中的数字,甚至是每季度一次可能对业务产生战略性影响的洞察。我在这个世界上已经呆了这么多年了。同样,这种思维方式本质上没有任何问题,它适合许多不同类型的数据追求——系统迁移、对现有 ERP 系统的更改请求或像 TPFs 这样的上世纪 70 年代遗留数据(不寒而栗)。

当用以产品为中心的观点来处理数据时,您日常工作方式的第一个主要变化是——“我的客户今天会受益于什么?”而不是“今天需要关闭的 CRs、票证等是什么?”一个公认的夸张,但我认为你得到了要点。

不可否认,大多数数据团队都是从真正的客户(在我们当前的案例中是乘客)中抽象出来的,这要困难得多。尝试告诉某人,您的数据团队需要 D3/Node/React javascript 开发人员将接口构建到当今的活动系统中,然后看着他们惊讶(不仅因为大多数人甚至不知道这些东西是什么,更不用说让数据(即分析团队)脱离操作系统)。大多数传统主义者将数据人员视为后端人员,这并不奇怪。我们大多数人都倾向于将自己的日常工作视为数据的守护者。

相反,从问题和解决用户问题的价值开始。“在我分析了 B 的数据并知道 C 是我需要采取的行动之后,我需要让 A 的行动变得简单得多。”衡量的结果本质上是你提供给最终用户/客户的价值。

我认识的大多数数据团队都止步于此,然后开始…“这不是我的问题。我给你 X 数据,BI 团队给你 Y 报告,数据科学团队给你 Z 洞察。”然而,这种思维模式实际上只实现了 B 部分或在紧要关头实现了 B 和 C 部分,并没有最终真正解决用户问题,这是 a。设计一个系统集成以允许用户严格做到这一点并不是一个数据问题。这种说法对于数据的项目/任务取向可能是正确的,但对于价值取向就不那么正确了。如果你真的想在持续的基础上证明分析的价值,进行测试和学习练习来证明你的数据的价值,那么是的,这个从根本上来说是一个数据问题。

这种心态如何改变团队的组成和他们关注的焦点?

数据工程优秀的数据工程师拥有不同于那些能够设计和构建优秀 API 的人的技能,这些技能也不同于那些能够构建优秀 UI 的人。根据用户的需要,您应该考虑在您的数据工程功能中使用非传统的技能。在我之前的一份工作中,我们雇佣了一个更专注于 javascript/UI 和少量数据的人来补充我们的数据工程团队。它产生了如此惊人的内部报告门户,然后它也将其作为面向外部的门户。

理想情况下,您的工程职能部门还应该拥有合适的软技能,以便加入数据产品团队,与您的业务和分析利益相关方举行构思会议。除此之外,这还意味着您采用持续集成管道,鼓励快速迭代和自动化,并且不严格要求团队在某个时间框架内发布(比如说,一个 sprint)。

数据产品
数据产品团队的职责不仅仅是做业务分析师以前会做的事情,即接受需求,发送回交付,他们的工作是利用其余的数据和分析功能,以及企业/消费者来找出解决方案,了解他们有什么问题以及如何用基于数据/驱动的产品来解决这些问题。

通过参与最终用户/消费者所需的解决方案的设计阶段,他们是整个数据团队和利益相关者的粘合剂。他们的评估和迭代不仅基于数据团队其他成员的优先级,还基于每个用例产生的客户价值(希望通过征求客户的反馈来获得)。努力将数据科学团队与消费者需求结合起来,引入其他部门,这些部门要么与消费者有现有的接口,要么在这些团队没有带宽或技能集的情况下建立自己的接口,您的数据产品人员是您的协作战略家,他们应该最深切地关心从数据中获取价值,无论数据如何到达消费者手中。

如今,大多数数据团队都缺乏这样的功能。如果他们这样做,它通常被用作提供数据管理的手段,而不是产品。允许他们主要关注提供最佳价值的解决方案(并与工程一起构建它们),而不仅仅是提供分析所需的数据。

注意:如果你有一个数据产品团队,他们不仅仅是你的记录员,不仅仅是你的搬运工,他们也应该是技术专家。仅仅因为您的数据科学团队在 R/Shiny 中构建了一些东西,并不意味着解决方案应该只是让它保持运行。这可能是最容易获得 MVP 的途径,但并不总是最有影响力的。

报告/商务智能和分析 许多报告和商务智能人员往往被视为系统高手,点击这里,在那里编写一些 SQL 代码,瞧,一张你需要的表格。我经常看到如此广泛和复杂的报告,以至于最终用户只抓住一个数字不放,像鹰一样监控这个数字,完全忽略了更大的画面。我很幸运有非常具有商业分析头脑的商业智能分析师,他们不只是想停留在基于网格的报告上,或者只是一份漂亮的报告。

以价值为导向的分析师总是更进一步——用户会从中受益吗?他们经常问的几个问题是——“我如何展示这个指标变化的驱动因素是什么?”“我如何创建正确的报告套件,这些报告相互链接,以便无缝使用?”通常,现有的报告工具,如 Tableau/Qlik/PowerBI,并不支持这种具有分析洞察力的报告。能够将 R 等分析工具集成到这些可视化环境中可能是解决这个问题的关键,但这意味着传统 BI 分析师或开发人员的技能组合发生了变化。一个我仍在试图破解的问题——但至少有一些优秀的分析师在尝试。

数据科学
最后,但肯定不是最不重要的,最热门的工作……我就讲到这里。除了构建智能汽车和机器人的真正 AI/ML 用例之外,大多数终端消费产品都有来自数据科学团队的深刻概念证明,并与工程功能相结合。专注于任务的数据科学团队往往首先关注模型的准确性,并在醒着的最后一刻调整模型以获得最佳解释值。同样,这很好,如果它们是一次性的战略上一致的项目,需要最准确的答案,永远不会被再次使用。以价值为导向的数据科学功能倾向于关注对客户的影响或变化,以及帮助客户完成变化以提高采用可能性所需的内容,最初牺牲了模型的准确性/复杂性,知道他们将随着时间的推移不断迭代。

Emily Glassberg Sands 概述了数据科学团队如何帮助构建优秀的数据产品。她的 HBR 文章讲述了如何建造它们的过程。然而,她从一个数字化的本土企业的角度来看,这个企业已经有了一个总体的产品功能。对于没有总体产品功能的公司,数据科学团队最适合与数据产品团队和业务部门合作,以实现整个解决方案。

客户 最后一点也是最重要的一点,打造优秀产品的数据团队中最不可或缺的一部分就是客户。现在,这里的客户有内部和外部两种形式,内部客户通常对错误/不正确的数据更加宽容。它们决定了产品的特性,并帮助我们理解产品的价值。没有它们,伟大的产品就不会存在,不管是不是数据驱动的。数据团队需要开发和构建让他们的生活更轻松的解决方案,这反过来又增加了他们的采用率和创造货币价值的能力。

以产品为中心的思维模式是当今大多数数据团队的范式转变。它让人们从以任务为导向,甚至简单的以结果为导向转变为以价值为导向。人们开始意识到,如果数据被用来推动正确的结果,它只是新的石油。石油以其最原始的形式存在了几千年,在我们找到造福人类的正确用途(产品)之前,它没有任何内在价值。数据作为推论是完全一样的。我们真正从数据中赚钱或创造价值的唯一方式是,我们的客户/最终用户从我们用数据创造的产品中受益。只有到那时,数据革命才真正扎根。因此,采取以产品为中心的数据观是创造可持续数据革命的下一步,这将使最终用户和公司都受益。

产品经理研究数据科学

原文:https://towardsdatascience.com/a-product-manager-tries-data-science-2c3570d8b480?source=collection_archive---------32-----------------------

作为一名有抱负的数据科学产品经理,我一直在寻找通过实践积累技术知识的方法。在这个项目中,我与一家在线订购餐馆的初创公司合作,建立一个推荐系统。我面临的挑战是创造性地扩展有限的数据集,并应用无监督和有监督的学习方法来克服与处理极其混乱的餐厅菜单数据相关的困难。

问题是…

从业务角度来看,我们希望随着时间的推移,增加客户保持率和客户收入。许多企业的一个常见模式(此处可见)是收入的很大一部分来自一小部分回头客。我的假设是,提供个性化的推荐可以增加单个订单的价值,随着时间的推移增加收入。

创建推荐系统有很多有据可查的方法,但是和往常一样,以正确的格式获取数据是关键!餐馆菜单通常按食物类型分类——意大利餐馆、印度餐馆等。对于阅读这些内容的人来说,我们能够很容易地解释这些菜单项并将其映射到一个类别。当我们亲自点餐时,销售人员很容易推荐我们可能喜欢的其他类别,这是很常见的——“你想喝点什么吗?”

对机器来说不是这样!在不同的项目之间建立有意义的相似性是困难的!例如,两家比萨饼店可能都供应 10 英寸的奶酪比萨饼。在一份菜单上,它被称为吉尔的 10 英寸玛格丽塔披萨,在另一份菜单上,它被称为著名的红酱披萨。对于一个销售数百万比萨饼的大型连锁店来说,有足够的交易量来解释有意义的模式。然而,对于小餐馆来说,连接看似不同的订单对于建立有意义的交易量是至关重要的,这种交易量可以用于概括所有餐馆。

从事 MyFitnessPal 应用开发的安德玛大学科学家的一篇论文很好地总结了为什么与传统的文本聚类相比,这个问题特别困难:

“我们的餐厅食物匹配问题有其独特之处,因为要匹配的给定文本(即餐厅菜单项)和应用程序数据库中的匹配文本(即食物及其描述)的长度都很短。此外,每个单词的词汇和语法结构对整体准确性的影响比标准设置中的情况更大:“肉酱意大利面”需要与“肉酱意大利面”区别对待。“词序对整体匹配准确率也有很大影响:“巧克力牛奶”应该和“牛奶巧克力”区别对待。”所有这些细微差别结合在一起,使得直接应用以前的文本匹配问题成为一个挑战。"

解决问题

当我在研究这个问题的潜在解决方案时,我看到了一篇博客文章,它解决了 Caviar 的一个非常相似的问题:

https://developer . square up . com/blog/caviars-word 2 vec-tagging-for-menu-item-recommendations/

这种方法对我来说很有意义(并且与我在 NLP 课程中涉及的主题很一致),所以我决定看看我是否能让它与我的数据一起工作!

为了解决连接不同菜单项的问题,Caviar 数据科学团队实现了一个 Word2Vec 模型。Word2Vec 是将单词输入映射到向量空间中的表示的神经网络,称为嵌入。它通过查看上下文来做到这一点——哪些单词经常在彼此附近出现?

通常,Word2Vec 模型使用 预训练嵌入——其他人在数十亿个例子上做训练模型的艰苦工作,向量表示可以被提取出来并用于像我这样的任务。然而,在这种情况下,我发现预训练的嵌入是不够的。

网络抓取走向胜利

不幸的是,我最初的数据集只包含 50,000 个不同的菜单项。当我训练 Word2Vec 模型时,向量被证明不足以生成有意义的下游结果。

我需要增加训练数据的大小。经过一些研究,我偶然发现了 all menu s,这是一个全美餐馆菜单的聚合器。

为了建立一个网络刮刀,我求助于 Scrapy 。Scrapy 提供了一个强大的框架,抽象了 web 抓取的许多更具技术性的方面(节流、异步作业),允许我专注于识别和捕获我需要的数据。

有了新的 web scraper 在手,我能够获得超过180 万个独特的菜单项及其描述——大大增加了我的培训数据!

使用无监督学习创建食物类别

有了新数据,我用 Gensim 包训练了一个 Word2Vec 模型。与只对 5 万个菜单项训练模型时不同,我现在可以看到单词之间有意义的联系。看看和“煎饼”最相似的前 10 个词——所有的早餐食品,正如我们所料!

尽管这很酷,但总体目标是比较相似的菜单项,而不仅仅是单个单词。回到我们最初的例子,我们最终的模型应该考虑吉尔的 10 英寸玛格丽塔披萨著名的红酱披萨都是披萨。**

为了做到这一点,我应用了鱼子酱数据科学家使用的相同技术——对于给定的菜单项(比如‘蓝莓煎饼’),我对‘蓝莓’和‘煎饼’的词向量进行平均。

假设这行得通,我应该能够使用聚类算法将菜单项分组在一起。我使用 KMeans 集群,在 20 到 50 个集群之间进行测试和验证。通过手工检查,我发现 30 产生了最有意义的集群。

这些聚类很好地映射了人类对菜单类别的理解。我能够凭直觉找到啤酒、葡萄酒、甜点和其他多种菜肴的类别!下图显示了一些示例集群中菜单项的顶部单词。

Wordclouds generated from the menu items included in 3 clusters

最后,我使用 t-SNE 可视化集群,这是一种降维方法,特别适合二维可视化。当用聚类数着色时,结果显示出清晰可辨的类别。

Visualizing Menu Item Vectors through t-SNE

使用监督学习提出建议

最终目标是在客户下订单时提供额外的建议。当客户在线订购时,商品会一次一件地添加到购物车中,订购流程如下所示:

[10 英寸马里纳拉披萨]

[10 英寸马里纳拉披萨,1 20 盎司可口可乐]

[10 英寸马里纳拉披萨,1 20 盎司可口可乐,1 个奶油甜卷]

在上面的例子中,我们想向只点披萨的顾客推荐可口可乐或奶油甜卷,目的是提高他们对订单的满意度,增加订单量。

我通过模拟上面的订购过程创建了训练数据。首先,我使用 K-Means 模型来预测事务中的每个菜单项应该属于哪个类别。对于每个事务,我遍历事务中的所有项,每次取出一项作为预测的目标,其余项作为特征。这创建了 160 万个事务示例作为训练数据。

将这些分为训练和测试数据,我使用 SKLearn 库对训练数据训练多项逻辑回归模型。该模型在测试数据上预测扣留类别的准确率达到 71%。

一些简单的比较基准是选择一个随机的类别和最受欢迎的类别。随机分类将产生 3%的准确度(30 分之一的机会)。一个每次都能猜出最受欢迎类别的虚拟模型有 10.3%的正确率。逻辑回归模型实现了比这些原始基线更高的准确性。

讨论和后续步骤

结果向我表明,客户订购模式中有规律可循,可以用来提出建议。在目前的状态下,该模型足以提供简单的建议。如果顾客点了一道主菜,但没有点饮料,则该模型可以预测该菜应该配有饮料。推荐餐馆最受欢迎(或最赚钱)的饮料是一个可行的当前策略。

然而,顾客偏好的异质性限制了该模型在当前水平上的有效性。聚类的粒度虽然很好,但仍不足以做出真正的推荐。例如,该模型可能能够建议客户在汉堡订单中添加一道配菜,但不能有效地推荐薯条或配菜沙拉。这个项目的下一步是进一步细化类别,使之更加细化。

下一步是通过在逻辑回归模型中加入额外的特征来提高预测的准确性和质量。关于顾客先前点了什么或者餐馆菜单上什么项目最受欢迎的元信息可以从现有的交易数据中获得,我希望这将对模型产生重大影响。

然而,也许更重要的是,除了推荐方面之外,以完全无监督的方式将字符串聚类为不同的餐馆菜单项的过程仍然提供了显著的好处。将新菜单项标记和分组到类别中的过程现在可以自动化,并用于创建更好的菜单和业务分析。

虽然这还没有变成一个真正面向客户的项目,但获得一些真实世界的数据是一种很棒的体验。我研究了各种技术,创建了一个训练数据集,并应用了监督和非监督学习,所有这些都是在实现业务目标的背景下进行的,并在此过程中学到了很多东西。

面向并发后台请求的 Rest API 解决方案

原文:https://towardsdatascience.com/a-python-api-for-background-requests-based-on-flask-and-multi-processing-187d0e3049c9?source=collection_archive---------2-----------------------

使用 Python flask 和多重处理,逐步构建在后台运行耗时请求的 Rest API

Photo by Safar Safarov on Unsplash

这个帖子也可以在大数据日报Linkedin 找到。

这篇博客将首先向您介绍 Rest API,解释它的基础知识以及我们可以使用 Rest API 做什么。之后,我们将一起使用 Python flask 包构建我们的第一个 API。最后,我们将通过一个通用代码框架,使用多处理模块在后台运行耗时的作业。整个项目的源代码可以在 Git 找到。

Rest API 基础介绍

首先,让我简单解释一下什么是 API,它能帮助我们什么。简单地说,API 是一个运行在主机上的程序,它监听一个端口来接收和响应来自互联网的 HTTP 请求。假设我们想要求解一个超出我们知识范围的方程,有人开发了一个运行在主机上的求解器 API,那么我们只需在浏览器中粘贴一个 URL:http://host:port/equation?x+8=20 。看多简单!如果我们有一些复杂的任务不适合在我们的前端 UI 中实现,或者我们有凭证数据,我们希望将它们从我们的 UI 中分离出来,API 就是解决方案。然后前端需要知道的是与 API 通信的接口,简单地向它发送请求。前端不会执行任务或接触凭证数据。

在剩下的部分,我将一步一步展示如何基于 flask 和多处理模块构建一个在后台运行请求的 Python API。这些步骤应该很容易遵循,即使你没有使用 flask 或 API 的经验。

使用 Flask 构建您的第一个 API

作为开始,让我们首先构建一个简单的 API 向世界问好。对于已经熟悉 flask API 的人,可以跳过这一部分。

现在,让我们将其保存为 intro_api.py ,并作为“ python intro_api.py 运行。您已经成功构建并运行了一个 API。够简单吗?那就叫吧!我们需要做的只是在我们的浏览器中复制并粘贴http://0 . 0 . 0:6060/。看到了吗?我们的网页显示“你好,世界!”,这正是我们在 API 中定义的。让我一行一行地解释这个脚本。首先,我们导入 Flask 包,并使用 Flask(name) 创建一个 API,其名称作为模块的名称。然后我们定义一个函数来响应 rout path 发来的 HTTP GET 请求,即 host:port/ 。在这里,route decorator@ app . route()包装了将由 URL 调用的方法。即使你对 route decorator 没有任何概念,它也会影响你在这篇博客中对 flask API 的理解。但是我想强调两点。(1)注意 @app.route('/',methods=['GET']) 中的' / ,它定义了用来调用这个方法的 URL(http://0 . 0 . 0 . 0:6060/),即 hello_world() 。(2) methods=['GET']) 定义了方法只会被 HTTP GET 请求调用。

然后我们在本地主机(即 0.0.0.0)运行这个 API,在 main 函数中 port=6060。请注意,我们在开发环境中通过调用 app.run() 来运行它,这并不是特别高效、稳定或安全。让我们使用包 女侍 来代替生产服务器运行 API。然后主机变成运行我们 API 的计算机的 IP 地址。注意我们使用 CORS 包来允许跨来源访问,否则一些现代浏览器可能会拒绝访问我们的 API。在 https://www.codecademy.com/articles/what-is-cors 查看更多关于 CORS 的信息。

定义另一种路由方法

接下来,让我们通过定义另一个 route decorator 及其相关方法,在我们的 API 中做一些实际的工作。该方法将响应 HTTP POST 请求。

这里 request.json 是 json 格式的请求体。请求主体将从前端 UI 发送到后端 API,它总是用于从前端向 API 发送一些附加信息。请记住,API 可以被同时调用多次,因此每个会话(即调用)都有自己的请求体。比如说,A 和 B 都是通过http://host:port/task/job _ Ahttp://host:port/task/job _ B用不同的请求体调用 API。然后,每个会话将在内存中拥有自己的请求体,即 A 和 B 将触发相同的函数,但使用不同的 request.json 变量运行。注意,job_id 应该是 uuid 的格式,因为我们在装饰器中定义了 < uuid:job_id >

使用多重处理在后台运行请求

到目前为止还好吗?上面的函数非常简单,它接收一个 POST 请求并获取其主体,然后运行一些任务并将输出响应给客户端。但是,如果这项任务非常耗时,比如说运行一个机器学习模型需要几分钟,那该怎么办?该程序将平稳运行,直到 run_task() 为止,然后它将挂起,因为 run_task() 将需要几分钟的时间返回。我们的网页将被封锁,用户不得不等待它的完成,没有任何其他选择,例如提交另一份工作。这当然不是我们愿意看到的。一个简单的解决方案是使用多处理在后台运行任务。另一个解决方案是消息队列,基本上 API 将只设计为将作业信息推送到消息队列,然后返回到前端,而 dameon 服务将从消息队列中提取消息并运行真正的任务。关于它的更多细节可以在我的另一篇博客中找到:Google 云平台并发消费者的通用框架 Pub/Sub

在这里,我们在后台进程中运行 run_task() ,而不等待其完成,并通知客户端作业已收到。在这种情况下,网页将不会被阻止,用户可以在该网页中执行一些其他操作,例如提交另一个作业。但是缺少的一点是,当工作完成时,用户不会得到通知。然后我们需要在 run_task() 中记录作业的状态。

如果作业有并发限制会怎样?假设我们只能运行 4 个并发 run_task() ,那么其他请求应该处于等待状态。此外,我们只允许处理 8 个并发请求,即等待和运行。在这个场景中,我们需要一个数据库来记录请求的状态,以帮助检查工作人员的可用性。

结论

现在我们已经构建了我们的第一个 Rest API,并暴露在后台运行耗时请求的代码框架中。希望你会发现它很有趣和有用,也许你会想建立一个 API,让其他人与你的机器学习模型进行交互。

Python 初学者的看法。通信线路(LinesofCommunication)

原文:https://towardsdatascience.com/a-python-beginners-look-at-loc-part-1-cb1e1e565ec2?source=collection_archive---------7-----------------------

从熊猫数据框架中选择行和列

作为一个 Python 初学者,使用.loc来检索和更新 pandas 数据帧中的值对我来说并不合适。Python 不断扔给我的SettingWithCopyWarning消息清楚地表明我需要使用它,但感觉像是大量的试错消息来让它做我需要的事情。

我坐下来玩了足够多的时间,现在我开始感到舒服了,所以我想我应该分享我的漫游;如果你是初学者,希望它能帮助你。在这篇文章中,我将讲述如何通过.loc获取数据;我将在未来的文章中讲述如何设置数据。

我在亚特兰大大会上第一周的数据科学沉浸式课程时,使用了一个神奇宝贝数据集(#dadjokes)进行了“探索”。

这里是df.head(10)的样子:

Header for the Pokémon dataframe I tested with

使用检索数据。通信线路(LinesofCommunication)

可索引属性,而不是方法

我的第一个提示是.loc不是一个数据帧方法;一个周六,用()代替[]花了我 45 分钟。在这些方括号中,.loc接受两个输入:一个行“索引器”和一个(可选的,用逗号分隔)列“索引器”:没有其他参数,像inplaceaxis

单个标签、切片和列表

那么你能用什么作为索引器呢?pandas 文档列出了允许的输入,它讨论的第一个是单个标签,所以让我们开始吧。

传递一个索引器(因为这个数据帧是 RangeIndex,我们传递一个整数)将返回一个 pandas 系列,其中包含具有该索引值的行的数据,在本例中是小火龙:

df.loc[4]Name              Charmander
Type                    Fire
Total                    309
HP                        39
Attack                    52
Defense                   43
SpecialAttack             60
SpecialDefense            50
Speed                     65
Name: 4, dtype: object

.loc总是将整数解释为标签,而不是沿着索引的整数位置(你可以使用[.iloc](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iloc.html)来解释)。

只传递一个列标签或一个空白行索引器会给你一个错误,因为括号索引的第一个位置是寻找索引,它是必需的:

>>>df.loc['Type']
KeyError: 'Type'>>>df.loc[, 'Type']
SyntaxError: invalid syntax

但是在使用 Python 切片符号指定您想要的行(例如[:]指定所有行)之后,传递列标签将得到 pandas 系列中的列数据。注意,与通常的 Python 约定不同,**.loc** 切片包括两个端点:

df.loc[:5,'Type']0    GrassPoison
1    GrassPoison
2    GrassPoison
3    GrassPoison
4           Fire
5           Fire
Name: Type, dtype: object

行和列索引名的切片能力是.loc的一个很好的优势,因为数据帧上的普通括号符号不允许这样做:

df.loc[:5,'Type':'Speed']

您还可以传递带有行或列索引名称的列表来获取数据的子集。(列表理解工作也是!):

df.loc[[2,4,10,99],['Name','HP']]

布尔列表

您可以作为索引器传递的最后一种类型的值是布尔数组,或者是一列TrueFalse值。当我们开始使用.loc设置值时,这种方法有一些真正的力量和巨大的应用。对应于索引器中False值的行和列将被过滤掉。数组的大小不必与对应的索引相同,但是.loc会将丢失的值视为False:

df.loc[
       [True, False, False, True, True],
       [True, False, True, False, False, True]
]

您也可以使用布尔掩码来生成您传递给.loc的布尔数组。如果我们只想看到“火”类型的神奇宝贝,我们将首先生成一个布尔掩码— df[‘Type’] == ‘Fire’ —它为数据帧中的每一行返回一系列True/False值。然后,我们将该掩码作为行索引器在.loc中传递:

df.loc[df['Type'] == 'Fire']

The first several rows of the Boolean-filtered dataframe.

这里有各种可能性,比如获得超过 175 次攻击的神奇宝贝:

df.loc[df['Attack'] > 175]

或者那些生命值少于 100 而总属性超过 650 的人:

df.loc[(df['HP'] < 100) & (df['Total'] > 650)]

或者那些名字中带有字母“X”或“灵媒”类型的人:

df.loc[
    (df['Name'].str.contains('X')) |     
    (df['Type'].str.contains('PsychicFairy'))
]

当然,您可以在数据帧上用普通的括号符号来完成大部分工作,那么有什么特别的呢?在这篇文章中,我将讨论.loc如何允许你在数据帧中设置值。

Python 初学者的观察。通信线路(LinesofCommunication)

原文:https://towardsdatascience.com/a-python-beginners-look-at-loc-part-2-bddef7dfa7f2?source=collection_archive---------12-----------------------

在 pandas 数据框架中设置行和列值

作为一个 Python 初学者,使用.loc来检索和更新 pandas 数据帧中的值对我来说并不合适。在之前的帖子中,我分享了我所了解到的关于.loc检索数据的情况。今天,我们将谈论设置值。

作为复习,这里是我们正在处理的神奇宝贝数据的前 10 行:

将一组单元格设置为单个值

使用.loc设置数据值很容易,所以让我们将 Mega Venusaur 的值设置为0。只需将指标值传递给 Mega Venusaur 出现的行(即3):

df.loc[3] = 0
df.head(5)

现在,让我们通过传递所有行(带有:)和列名来重置所有神奇宝贝到60的“速度”统计:

df.loc[:, 'Speed'] = 60
df.head(5)

最后,让我们把所有“灵异精灵”类型的神奇宝贝的生命值更新为42。(如果你需要一个关于如何构建布尔掩码的复习,请看这篇文章。)

df.loc[df['Type'] == 'PsychicFairy', ['HP']] = 42

使用这种方法,.loc表达式返回的每个单元格都将被更新为您指定的值,并且它们将直接在 dataframe 中被更改,因此最好先测试一下您是否得到了您期望的行/列,而无需设置值。例如,当我构建这个例子时,我无意中在列索引器中有了['Name', 'HP'],所以我最终得到了一堆名为‘42’的具有42生命点的 PsychicFairies,并且我必须重新加载我的数据。

将一组单元格设置为一组不同的值

但是如果您需要为一组单元格设置不同的值呢?你所需要的只是一个你想要设置的值的列表(在形状上等同于你的.loc语句返回的数据),而.loc会为你做这件事。

举个例子,假设我们想改变火型神奇宝贝的名称,使其包含🔥表情符号:

  1. 为火焰类型创建一个布尔遮罩:df[‘Type’] == ‘Fire’
  2. 将掩码传递到 DataFrame,以过滤火类型神奇宝贝的行:**df[**df[‘Type’] == ‘Fire’**]**
  3. 通过分割 DataFrame: df[df[‘Type’] == ‘Fire’]**[‘Name’]**)来隔离 Name 列。
  4. 接下来,使用掩码建立列表理解,以生成新的表情符号增强的名称。我们将把它赋给一个名为new_names : new_names = **[‘🔥’ + name + ‘🔥’ for name in** df[df[‘Type’] == ‘Fire’][‘Name’]**]**的变量。
  5. 最后,使用步骤 1 中的布尔掩码和Name列作为.loc语句中的索引器,并将其设置为 fiery 名称列表:
**df.loc[df['Type'] == 'Fire', 'Name']** = new_names

对多个列的更新也很容易。并且.loc将在任意数量的行&列中设置值;只传递相同维度的值。

让我们改变一些心灵精灵类型的攻击和特殊攻击值。

这里我们将让.loc引用三行两列,以及一个相同维度的值列表,我们就可以开始了。

rows_to_update = [305, 306, 487]
cols_to_update = ['Attack', 'SpecialAttack']
values = [[87,88],[187,188],[287,288]]df.loc[rows_to_update, cols_to_update] = values

以上就是我对.loc的了解。你有什么问题?其他提示?

python flask 应用程序,使用文本分析根据用户输入预测性格类型。

原文:https://towardsdatascience.com/a-python-flask-app-that-predicts-the-personality-type-on-the-basis-of-user-entries-using-text-1269d6f644bd?source=collection_archive---------14-----------------------

Vertical Flow by I Rice Perreria

Irene Rice Perreria 的上图(名为《垂直流动》)是我最感兴趣的一幅作品。对我来说,它描述了颜色的异质性,同时也描述了这些不同的颜色如何来源于同一种本质。一天结束时,颜色在光谱上起作用,而不是作为单独的点。人们可以认为,人类的性格也在一个相似的光谱上运行,而不是孤立的,不同的性格类型在这个光谱上不断地重合和分离。在本文中,我描述了一个应用程序,它使用 python 中的文本分析,帮助用户预测自己在迈尔斯布里格斯性格谱(16 种性格)上的性格。最终的应用程序部署在 heroku 上,可以在这里访问。该应用程序是用 python 开发的,使用“flask”进行应用程序开发,使用“sklearn”的“tfidvectorizer”进行文本分析。

用于分析数据和我们的关键问题

用于分析的数据是一个数据库,包含 reddit 用户对应不同性格类型的帖子。数据库可以在 kaggle 这里访问。这是一个免费、开源、公共领域的数据集。我们将创建一个个性查找应用程序,用户可以输入任何一组描述自己的单词。该应用程序将运行计算用户输入的文本与来自个性类型数据库的各种条目的相似性得分,以预测个性类型(16 种 Myers Briggs 个性之一)。它还将预测四个迈尔斯·布里格斯特征的可能性,如内向/外向、直觉/观察力、思考/感觉和判断/感知。下面的视频展示了最终的实际应用。该应用程序将显示前 5 个预测的相似性得分,使用户知道适合她或他的性格谱。

应用程序的结构

这是一个传统的 flask 应用程序,我们需要首先定义一个结构。我们将使用的结构是一个标准的 flask 应用程序结构,带有一个包含用户界面和托管结果的 index.html 文件,以及一个包含创建应用程序的代码的 python 文件。

#Structure of the flask application----Root folder
    --Base data files #This is basically just the csv with the base data from kaggle
    --application.py #This is the main python code file
    ----templates
        --index.html #The templates folder contains our index.html file with the user interface
    ----static
        #The static folder contains any images we will want to display in the application. 

下面是应用程序中数据流的图示

定义用户界面(index.html)

所以,让我们从用户界面本身开始。index.html 文件的第一部分很简单。这只是一些描述应用程序本身的基本文本和上面这幅画的简单图像,我们将把它放在我们的“静态”文件夹中。这看起来像是

<html> <head><section>  <img class="mySlides" src="/static/Vertical.jpg"  style="height:50%" style="width:100%">  </section> <h1> Personality finder (developed using text analysis)</h1> <p> Find your personality type using this python flask application that makes use of a text vectorizer to analyze    posts by individuals identifying as different personality types. The app will yield your top 5 personalities from the     16 Myers Briggs personality types. Data downloaded from kaggle. By the way the paiting displayed here is "Vertical Flow" By I.Rice.Pereria.</p>    <p> Please note that the script might take a minute to run since it has to parse through over 8000 entries.</head>

现在,让我们创建一个表单,用户可以在其中提交我们将用于文本分析的单词或句子。这是一个简单的 html post 表单,带有一个提交按钮。我们将不得不跟踪我们分配给表单的名称,因为这将在后端使用。

<form method="post" > <input name="**question1_field**" placeholder="enter search term here"> <input type="submit"></form>

我将跳过对 html 页面 css 样式的解释。最后,我们将创建一个表,为用户输出前 5 个条目。我们还将打印出各种标题,如个性类型、相似性得分、搜索术语、行等。我们需要在 html 中定义表头(“th”)和表数据(“td”)。让我们先定义头部,

#Each of the heads is some data that we want to print out for the user<h2>Relevant personality types displayed below</h2>
<table>  
<tr>    
<th>Type</th>    
<th>SimiScore</th>    
<th>Search Term</th>    
<th>Rank</th>    
<th>Introversion/Extraversion</th>   
<th>Intuitive/Observant</th>    
<th>Thinking/Feeling</th>    
<th>Judging/Perceiving</th>    
</tr>

现在,数据将从 python 端引入。所以我们可以使用一些 jinja 代码来有效地访问我们的 python 数据帧变量。我们将在后端“文档”中调用我们的 python 数据框架。Jinja 将允许我们迭代这个 python 数据帧,如下所示。现在,调用每个变量的顺序应该类似于我们在上面的块中定义的头的顺序。

{% for doc in docs %}
<tr>
<td>{{doc["type"]}}</td>
<td>{{doc["Simiscore"]}}</td>
<td>{{doc["Search Term"]}}</td>
<td>{{doc["Rank"]}}</td>
<td>{{doc["Introversion/Extraversion"]}}</td>
<td>{{doc["Intuitive/Observant"]}}</td>
<td>{{doc["Thinking/Feeling"]}}</td>
<td>{{doc["Judging/Perceiving"]}}</td> 
</tr>
{% endfor %}
</table>

定义后端(python)

完整的后台 python 代码文件可以在这里访问。显然,第一步是导入所有需要的 python 库。因为我们将在 python 中使用文本分析,所以我们需要从 sklearn 包中导入 Tfidvectorizer 函数。此外,让我们继续在 flask 中创建应用程序本身。我们还将为应用程序创建一个标准的 get 和 post 路由,这样我们就可以有效地向它发送数据和从它那里接收数据。

#Import required packagesfrom flask import Flask, flash, redirect, render_template, request, session, abort,send_from_directory,send_file
import pandas as pd 
import numpy as np
import json
import xlrd
from sklearn.feature_extraction.text import TfidfVectorizer#Create a flask application
application= Flask(__name__)#Create an application route
@application.route("/",methods=["GET","POST"])

现在让我们使用 flask 应用程序中的主页功能来定义主页上将会发生什么。现在,在这里我们将首先尝试调用用户在上面定义的 html 表单中输入的数据。正如我们所知,表单本身被称为“问题 1 _ 字段”。我们可以使用一个调用表单数据的简单请求函数来访问这些数据。我们还可以指定一个默认单词,在用户没有选择任何单词的情况下将调用这个默认单词(本例中的默认单词是‘Education’)。让我们也使用 pandas 读入原始数据本身作为数据帧。我已经从 kaggle 的 reddit 数据中清理了用户条目。一个干净的 csv 版本可以在这里访问。下面是数据集的截图。文章栏包含用户的多篇文章。请注意,这是一个开源数据集,可在 kaggle 上获得,不包含任何机密信息。

def homepage():
#Call value from HTML form  
words = request.form.get('question1_field', 'Education')#Read raw data as a dataframe
datasource1 = pd.read_csv("Personalities.csv")

处理多个单词- 用户可以输入多个单词作为单个条目的一部分。我们希望将这些单词拆分成多个条目,以便在对所有单词一起进行分析之前,可以分别对每个单词进行文本分析。我们还想为每个单词过滤数据帧中的帖子,并将这些过滤后的帖子放入我们将使用的不同数据帧中。因此,让我们为此创建另一个数据帧。创建了这个新的数据框架后,让我们删除重复的内容,以防相同的帖子被选中两次。

#Separate words into multiple entrieswords = words.split() #(This will be stored as separate items in a list)#Filter the data for posts that contain either of these words
datasource=[]for i in words:      
    d2 = datasource1[datasource1['posts'].str.contains(str(i))]          
    datasource.append(d2)

datasource = pd.concat(datasource, ignore_index=True)
datasource = datasource.drop_duplicates()

好了,在我们继续之前,让我们来讨论一下什么是相似性得分,以及在给定的上下文中,我们如何以及为什么要计算它。相似性得分或“成对相似性得分”基本上是特定单词与条目中其他单词的距离。所以基本上,如果一个用户说“我爱金属”,这些词将与提到任何与金属相关的帖子有很高的相似度。由于每个帖子对应一种性格类型,我们可以从技术上“预测”用户的性格与发帖用户的性格类型相似。

tfidf 矢量器将计算特定帖子中出现的单词的频率和重要性。因此,如果在上面的例子中,如果帖子中的单词 metal 只是偶然出现,tfid 得分将非常低,从而产生低相似性得分。tfid 矢量器将根据单词的频率及其唯一性来计算其得分。在本文中,我不会详细介绍 tfidvectorizer 的工作原理。因此,为了计算用户文本和文章文本之间的相似性,我们需要在一个数据帧中并排显示这两个值。我们已经有一个过滤的数据框架与用户的相关职位。让我们创建一个名为 documents 的空数据帧,用于文本分析。我们希望在每次用户文本改变时清除数据帧。所以,我们可以在下面的 for 循环中调用它。

 for i in range(0, len(datasource)):      
    documents = []      
    documents.append(words)      
    documents.append(datasource.loc[i, 'posts'])

现在,对于 dataframe 中的每一个条目,我们要计算文章相对于用户条目的 tfidf 分数。这可以通过 tfidvectorizer 函数来实现。该功能允许我们指定停用词,即该功能应忽略冠词(a、an 等)的词。)和介词(over,under,between 等。).因此,如果我们将函数中的 stop_words 参数设置为“english ”,这些单词将被自动忽略。添加 tfid 矢量器来计算每个条目的分数,我们的函数现在看起来如下。

for i in range(0, len(datasource)):      
    documents = []      
    documents.append(words)      
    documents.append(datasource.loc[i, 'posts'])

      tfidf = TfidfVectorizer(stop_words="english", ngram_range=(1, 4)).fit_transform(documents) #tfidf is the tfidf score we compute for this post with respect to the entered text.

现在我们知道了用户在每个选中的帖子中输入的单词的重要性。但是我们现在想要使用这个 tfidf 分数来计算相似性分数,即用户输入的单词与帖子中输入的单词有多相似。相似度也可以定义为单词之间的余弦距离。这篇来自堆栈溢出的帖子详细解释了成对相似性的计算。简单的解释是,您可以通过将 tfidf 得分乘以其转置来计算成对相似性。这产生了一个相似性矩阵,访问这个矩阵的第一个元素将给出相似性得分。我们还将格式化相似性得分,仅显示前四位小数,并将其作为自己的列添加到数据帧中。因此,上面带有成对相似性计算的代码变成了,

for i in range(0, len(datasource)):      
    documents = []      
    documents.append(words)      
    documents.append(datasource.loc[i, 'posts'])

    tfidf = TfidfVectorizer(stop_words="english", ngram_range=(1, 4)).fit_transform(documents) #Compute pairwise similarity by multiplying by transpose.
    pairwise_similarity = tfidf * tfidf.T #Then, extract the score by selecting the first element in the   matrix.
    simiscore =   pairwise_similarity.A[0][1] #Format the similarity score to select only 4 decimals
     simiscore = "{0:.4f}".format(simiscore)

     #Finally, add the similarity score to the dataframe
      datasource.loc[i, 'Simiscore'] = simiscore

既然循环已经完成,我们将为用户输入的文本计算数据集中所有帖子的相似性得分。接下来的步骤是对相似性得分进行排名,挑选出前 5 名,将搜索术语作为其自己的列添加到数据框架中,并选择我们想要显示的相关列。最终的输出将被分配给一个名为 docs 的数据帧,我们将把它传递给我们的 html 表。

#Compute the rank and add it to the dataframe as its own column
datasource['Rank'] = datasource['Simiscore'].rank(method='average', ascending=False) #Sort by the rank
datasource = datasource.sort_values('Rank', ascending=True)#Select top 5 entries
datasource = datasource.head(5)#Add the search term to the dataframe as its own column
datasource['Search Term'] = words #Select relevant columns and assign to a dataframe called docsdocs = datasource[ ["type" ,"Rank", "Simiscore","Search Term","Introversion/Extraversion","Intuitive/Observant","Thinking/Feeling","Judging/Perceiving"]]

因为我们要将这些数据发送到一个 html 表中,所以我们必须将它转换成 json 格式。幸运的是,在 pandas 中使用 to_json 函数可以很容易地实现这一点。我们还可以将方向设置为记录,这样每个条目都成为一条记录。我们可以通过返回一个叫做‘docs’的对象来完成 flask 中的主页功能,这是我们前端所期望的。我们将使用 flask 中的 render_template 函数将数据发送到我们的 index.html 文件中。

#Convert to json
docs = docs.to_json(orient="records")#return data to front end for display return render_template('**index.html**',**docs**=json.loads(**docs**))

最后,让我们以标准烧瓶样式完成我们的应用程序,

if __name__ == "__main__":    
   app.run(debug=True)

你有它!运行代码时,您应该会得到以下消息,其中包含一个指向本地驱动器上的应用程序的链接。

* Running on [http://127.0.0.1:5000/](http://127.0.0.1:5000/) (Press CTRL+C to quit)

运行访问此链接,您将被定向到一个工作的应用程序!

在那里!自己尝试一些单词。

以下是一些相关链接,

  1. 链接到这个应用程序的 github 项目-https://github.com/kanishkan91/Personality-type-finder
  2. 链接到部署在 heroku-【https://personality-type-finder.herokuapp.com/ 的应用程序的工作版本
  3. 链接到用于此应用程序的基础数据-https://github . com/kanishkan 91/Personality-type-finder/blob/master/personalities . CSV

PS-github 项目包含一个. gitignore 和 requirements.txt 文件,您可以使用该文件将该应用程序的修改版本部署到任何服务器上。

特别感谢 Anish Hadkar 和 Aditya Kulkarni 在开发过程中对该应用程序的反馈。欢迎您提供任何额外的反馈!

使用(Python/Numpy/tensor flow/py torch)和(Matplotlib/Plotly)生成和绘制 3D 高斯分布的教程。

原文:https://towardsdatascience.com/a-python-tutorial-on-generating-and-plotting-a-3d-guassian-distribution-8c6ec6c41d03?source=collection_archive---------1-----------------------

问题陈述:

每当提到绘制高斯分布图时,通常都是关于单变量正态分布,这基本上是一种 2D 高斯分布方法,它从 X 轴上的范围数组中采样,然后对其应用高斯函数,并产生绘图的 Y 轴坐标。

然而,在 3D 高斯分布的情况下,采样发生在 X 轴和 Y 轴上,并且坐标投影在 Z 轴上。这种情况在教程中很少提到,虽然在很多情况下非常有用。

解决方案概述:

要在两个轴上采样:X 轴和 Y 轴,您需要对 X 轴上的每个样本进行所有 Y 轴采样。

两个轴上的完整采样将产生范围,一个在 X 轴上,一个在 Y 轴上。

完成后,您需要在 Z 轴上生成一个域,这可以通过计算(X,Y)样本的距离来完成。

然后,可以通过高斯函数运行 Z 域,以产生 Z 轴上的高斯范围。

然后可以构建一个 3D 绘图仪来利用所有三个范围来产生 3D 表面。

数学分解:

  • X 范围需要是大小为的 2D 矩阵:

  • X 中间范围是从“-域”到“+域”的行空间(1D 范围数组),每一步的大小为“方差”,该 1D 数组中元素的数量应为:

  • X 范围是堆叠 X 中间范围的副本的结果,副本数应为:

  • Y 范围是 X 范围矩阵的转置。

  • Z 域是 X 和 Y 之间的距离:

  • Z 范围是对距离矩阵(Z 域)应用高斯函数的结果:

代码实现:

用纯 Python 制作的二元正态(高斯)分布生成器

  • X 范围的构造没有使用 numpy 函数。
  • Y 范围是 X 范围矩阵(ndarray)的转置。
  • 最终得到的 X 范围、Y 范围和 Z 范围用 numpy 数组封装,以便与绘图仪兼容。

用 Numpy 制作的二元正态(高斯)分布生成器

  • X 中间范围由 numpy 使用“arange”函数构建。
  • Y 中间范围由 numpy 使用“arange”函数构建。
  • X,Y 范围是用 numpy 的“meshgrid”函数构建的。

用 Tensorflow 制作的二元正态(高斯)分布生成器

  • X 中间范围由 tensorflow 使用“range”函数构建。
  • Y 中间范围由 tensorflow 使用“range”函数构建。
  • X,Y 范围是使用 tensorflow 的“meshgrid”函数构建的。

用 PyTorch 制作的二元正态(高斯)分布生成器

  • X 中级范围由 torch 使用“arange”功能构建。
  • Y 中间范围由 torch 使用“arange”功能构建。
  • X,Y 范围是用 torch 的“meshgrid”函数构建的。

用 Matplotlib 绘制二元法线绘图仪

带 Plotly 的二元普通绘图仪(版本 4.0.0)

用 Matplotlib 绘制 Python 生成的二元正态分布

plt_plot_bivariate_normal_pdf(*py_bivariate_normal_pdf(6, 4, .25))

用 Matplotlib 绘制 Numpy 生成的二元正态分布

plt_plot_bivariate_normal_pdf(*np_bivariate_normal_pdf(6, 4, .25))

用 Matplotlib 绘制张量流生成的二元正态分布

plt_plot_bivariate_normal_pdf(*tf_bivariate_normal_pdf(6, 4, .25))

用 Matplotlib 绘制 PyTorch 生成的二元正态分布

plt_plot_bivariate_normal_pdf(*torch_bivariate_normal_pdf(6, 4, .25))

用 Plotly 绘制 Python 生成的二元正态分布

plotly_plot_bivariate_normal_pdf(*py_bivariate_normal_pdf(6, 4, .25))

用 Plotly 绘制二元正态分布图

plotly_plot_bivariate_normal_pdf(*np_bivariate_normal_pdf(6, 4, .25))

用 Plotly 绘制张量流生成的二元正态分布

plotly_plot_bivariate_normal_pdf(*tf_bivariate_normal_pdf(6, 4, .25))

用 Plotly 绘制 PyTorch 生成的二元正态分布

plotly_plot_bivariate_normal_pdf(*torch_bivariate_normal_pdf(6, 4, .25))

读者请注意:

请随时提供反馈,毕竟这些教程背后的原因是为了交流知识,并在出现错误时纠正课程。

Python 的 Plotly 可视化快速指南

原文:https://towardsdatascience.com/a-quick-and-dirty-guide-to-visualization-in-plotly-for-python-6f79f2d06f2?source=collection_archive---------24-----------------------

在几分钟内开始制作美丽的情节

在 Python 中有无数的选项来创建情节,但是我已经开始倾向于使用的一个库是 Plotly。在 Jupyter 工作流程中,这是一个很好的选择,可以很容易地创建漂亮和可展示的情节。它有大量可定制的图供您用于可视化(整个选择可以在这里看到)。

好吧,让我们深入到情节。Plotly 有两种风格,一种是 Plotly Express,另一种是 Graph Objects。

Plotly Express 可以被认为是制作剧情的更快捷的方式。它可以在您工作时用于可视化。使用 Plotly Express 的好处是通常只有很少的代码,但是您可以进行的绘图定制量也是有限的(与 Graph 对象相比,但与典型的图形库相当)。我个人不使用 Plotly Express,所以我不打算在这里介绍它,但是您可以在文档中阅读它,一旦您掌握了图形对象,它应该很容易使用。这是因为我更喜欢使用 Matplotlib 和 Seaborn 进行一般的可视化,因为它们与 Pandas 等流行的库集成得更紧密。当我需要制作非常像样的情节时,我会求助于 Plotly。下面是 Plotly Express 中的一个示例绘图和绘图代码。它直接来自文档。确保您已经安装了 Plotly。你可以在这里找到如何根据你的特定设备和环境做到这一点的细节。

**import** **plotly.express** **as** **px**
df = px.data.tips()
fig = px.histogram(df, x="total_bill")
fig.show()

现在,关于图形对象。使用这种方法的缺点是您通常需要编写更多的代码来创建这些图,但是优点是它们非常美观并且非常可定制。此外,您不必像在 Matplotlib 中那样处理重叠文本和缩放问题。对于我的用例来说,更多的代码行通常不是问题,我的用例是绘制出之前创建的图的最终版本。

下面是 Matplotlib 中的一个简单情节,使用了从票房魔咒中获得的一些电影数据。

import matplotlib.pyplot as plt
plt.bar(top_genres, top_total);

正如您所看到的,如果我们不做一些额外的工作,它不会自动缩放轴以使其看起来更像样。下面是使用 Plotly 的相同情节。

plot_top_genres_total = go.Figure()
plot_top_genres_total = go.Figure([go.Bar(x=top_genres,
                                          y=top_total)])
plot_top_genres_total.show()

如您所见,开箱后更加干净。你不需要花太多的时间去让东西变得可读。

现在,说到我之前承诺的那部分。您可能需要保存这个片段。

这是一个复杂绘图的代码,有多个轴、多个图表、颜色选项、图例和轴标题。你可以添加、删除或更改部分代码来修改情节。

plot_name = make_subplots(specs= [[{“secondary_y”: True}]])# For a single axis plot use the following line instead
# plot_name = go.Figure() plot_name.add_trace(go.Bar(x=x_data,
                           y=y_data_1, 
                           name = ‘Plot 1 Name’, 
                           marker_color=  ’#bfa878'))plot_name.add_trace(go.Scatter(x=x_data, 
                               y=y_data_2, 
                               name = ‘Plot 2 Name’, 
                               marker_color= ’#7a4b4b’), 
                               secondary_y = True)plot_name.update_layout(yaxis_title = ”Y Axis Label”, 
                        showlegend = False,
                        template = ”ggplot2", font = dict(family= ”Calibri”,
                                    size = 24,
                                    color = ’#7a4b4b’))plot_name.update_yaxes(title_text = ”Secondary Y Axis Label”,
                       secondary_y = True)plot_name.show()

例如,要更改绘图类型,您可以将“条形图”和“散点图”关键字更改为“直方图”或“饼图”。打开文档,看看还有什么可用的。

要改变绘图颜色,只需在谷歌上搜索“颜色选择器”。然后,您可以选择您的颜色,并获得十六进制代码的 RGB 值,以替换上面的代码。

您可以通过删除第二个 add_trace 代码行和 update_yaxes 代码行来删除辅助绘图。

可以通过修改 update_layout 下的细节来更改字体、字体大小和字体颜色。

确保所有的 x 和 y 数据都在列表中。我发现在绘图中使用数据之前将数据处理成列表有助于避免错误。此外,在粘贴环境后,您可能需要修复环境中的缩进,这样代码才能工作。

下面是一个使用上面的代码和上面使用的相同数据创建的图的示例。

上面的代码可以满足您 90%的可视化需求(根据您所做的工作,可能多一点或少一点)。在你画了一些图之后,你应该熟悉 Plotly 的代码结构。你会感觉到要改变什么来超越这个情节的限制。

对于后 10%来说,一个好的方法是尝试浏览文档来寻找你想要的情节,而不是复制他们的代码,尝试将它集成到上面的代码中。尝试改变事物,了解事物是如何融合在一起的。这样做,你将开始逐步开发你自己的模块化系统来创建可视化,并节省宝贵的时间。

我希望这些信息可以帮助你在几分钟内开始使用 Plotly,并为你提供一个框架,随着你的需求变得越来越苛刻,你可以学习更多。祝你好运!

回声评论文本分类的自然语言处理快速探索

原文:https://towardsdatascience.com/a-quick-exploration-of-nlp-for-text-classification-on-echo-reviews-6b65a9e2cc9e?source=collection_archive---------22-----------------------

简单几步的情感分析

Alexa,把你的评论分类。

自然语言处理(NLP)是以计算机可以“解释”的方式处理语言数据的领域/科学。Siri、Alexa、Google 等工具和服务。使用这些技术通过语言输入与人类互动,并解释文本数据。机器使用数字信息,这与语言学有本质的不同;因此,这项任务并不容易,需要创造性和复杂的解决方案。

在本文中,我们将使用 NLP 来预测用户对产品的评级,在本例中,是基于评论文本的 Amazon Echo Dot。这个例子需要对情感和极性以及数字分类输出等概念有一些低级的理解。让我们开始吧!

数据和预处理

第一步是打开一个 Google Colab python 笔记本,我们将使用这个环境来处理和可视化数据,构建模型,并做出最终预测。

本文的数据由 Kaggle 在以下位置提供:https://www.kaggle.com/sid321axn/amazon-alexa-reviews

数据由以下字段组成:评级、日期、变化和审阅文本。

第一步是将这些数据导入我们的 Python 笔记本。要做到这一点,你需要一个 Kaggle 的账户,它是免费的,你可以用谷歌证书注册。

首先,我们需要安装允许我们与 Kaggle API 交互的包。

!pip install kaggle

现在,我们需要上传我们的 Kaggle 凭证。这是一个. json 文件,可以从 Kaggle 下载,有很多这方面的教程。只需执行下面几行代码并上传 kaggle.json 文件。

from google.colab import files
files.upload()

我们需要将刚刚上传的文件放入正确的目录中,以符合 API 协议。

!mkdir -p ~/.kaggle
!cp kaggle.json ~/.kaggle/
!chmod 600 ~/.kaggle/kaggle.json

现在我们准备下载数据。只需进入 Kaggle 页面,将链接复制到数据,或者复制下面的行。

!kaggle datasets download -d sid321axn/amazon-alexa-reviews

解压缩文件:

!unzip amazon-alexa-reviews.zip

现在我们将数据导入到熊猫数据框架中;但是首先,我们需要进口熊猫。

import pandas as pd
df = pd.read_table('amazon_alexa.tsv')
df.head()

数据帧中的一列包含代表用户正在查看的回声变化的分类值。给定有限数量的类别,对模型使用一次性编码来理解这个变量将是最有效的。一键编码为每个可能的类别创建一列,并根据相应的行是否包含相应的类别值给出 1 或 0。如果您只想专注于文本分析,请随意从输入变量中排除“variation”列!

df1 = df[['variation']]
df2 = df.drop(['variation'], axis = 1)
df1 = pd.get_dummies(df1)
df = pd.concat([df1,df2], axis = 1)
df.head()

需要处理的下一列是日期;在这种情况下,它以 dd-MMM-yy(例如 2018 年 7 月 31 日)。只接受数字输入的模型将无法解释这些信息。

解决方案是将字符串分解成独立的日、月和年的数字表示,然后将它们放在各自的列中。原始日期列也将被删除。

#df['Year'] = pd.DatetimeIndex(df['date']).year
df['Month'] = pd.DatetimeIndex(df['date']).month
df['Day'] = pd.DatetimeIndex(df['date']).day
df = df.drop(['date'], axis = 1)
df.head()

你可能注意到我把“年”注释掉了。所有审查的年份(2018 年)相同;因此,具有该列不必要地增加了计算负担,而没有提供任何好处。如果这个数据集的某个版本有更新的旧日期,请随意使用“Year”。

下一步将是收集一些与评论文本本身相关的信息。出于这个例子的目的,我们将使用一个工具 TextBlob,它将分析文本字符串并提供与情感相关的数字输出。TextBlob 将以元组的形式输出极性(范围-1 到 1)和主观性(范围 0 到 1)。这个过程的结果可以映射到分别包含极性和主观性的列中。

首先,让我们开始导入 TextBlob 并定义一个函数,该函数在给定一个字符串输入的情况下输出情感,如果输入无法处理,它将返回一个中性的输出。

from textblob import TextBlob
def sentiment_calc(text):
    try:
        return TextBlob(text).sentiment
    except:
        return TextBlob('hello').sentiment

现在,让我们使用一个 lambda 函数将这个新创建的函数应用于包含评论数据的列,并将输出设置为一个新列,我们称之为“情绪”然后,我们将情感元组映射到各个变量的各个列,并删除“情感”列。

df['sentiment'] = df['verified_reviews'].apply(lambda text: sentiment_calc(text))
df[['polarity', 'subjectivity']] = df['sentiment'].apply(pd.Series)
df = df.drop(['sentiment'], axis = 1)
df.head()

接下来,我们可以收集一些关于文本本身性质的附加元数据,包括字符数、字数、平均单词长度和停用词数。这将允许模型识别这些特征和评级输出之间的任何关系。

首先让我们定义一个返回平均单词长度的函数:

def avg_word(sentence):
  try:
    words = sentence.split()
    return (sum(len(word) for word in words)/len(words))
  except:
    return 0

现在,让我们基于 review 文本列为上述元数据元素创建新列。

df['number_words'] = df['verified_reviews'].str.split().str.len()
df['number_character'] = df['verified_reviews'].str.len()
df['avg_word'] = df['verified_reviews'].apply(lambda x: avg_word(x))

现在我们将创建一个包含评论文本中停用词数量的列。停用词通常被认为是更常见、意义更小的词,如“a”、“the”和“I”。我们还不知道这个变量和这个特定应用的输出之间是否有相关性;然而,我们有一个小的数据集和充足的内存,包含它不会有什么坏处!

我们将从 NLTK 导入“停用词”工具(我鼓励那些不知道这个工具包是什么的人去查一下)。导入工具包,然后使用 lambda 函数,通过执行以下代码行将其应用到评审中。

import nltk
nltk.download("stopwords")
from nltk.corpus import stopwords
stop = stopwords.words('english')df['stopwords'] = df['verified_reviews'].apply(lambda x: len([x for x in x.split() if x in stop]))
df.head()

让我们对这些输入应用一个定标器(Scikit-Learn MinMaxScaler ),以便于模型解释:

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()columns = ['number_character','number_words', 'avg_word', 'stopwords']
for col in columns:
  df[[col]] = scaler.fit_transform(df[[col]])
df.head()

此时,我们可以开始构建模型了!如果你喜欢,请随意这样做,因为有足够多的信息来做出一些可靠的预测。然而,我将通过一些额外的步骤来帮助从评论中挤出更多的信息!

这个过程将涉及文本摘要。我要做的是总结每次复习,然后应用前面的步骤。理论上,这应该从评论中分离出最重要的句子,然后收集最重要的观点。让我们试一试!

从 Gensim 导入汇总工具,然后定义一个可应用于列的函数。注意:如果摘要过程中有错误,这个函数将返回原始文本的副本。

from gensim.summarization import summarizedef sum_text(text):
  try:
    summed_text = summarize(text)
    return summed_text
  except:
    return text

现在,让我们应用这个函数,并收集与之相关的情绪。没有必要缩放输出,因为情感分数将总是在模型容易理解的范围内给出。

df['summed_text'] = df['verified_reviews'].apply(lambda x: sum_text(x))
df['sentiment_sum'] = df['summed_text'].apply(lambda text: sentiment_calc(text))
df[['polarity_sum', 'subjectivity_sum']] = df['sentiment_sum'].apply(pd.Series)
df = df.drop(['sentiment_sum'], axis = 1)
df.head()

现在,让我们创建一个可以输入到模型中的新数据帧。我们可以通过创建 dataframe 的副本来做到这一点,该副本排除了带有字符串的列。

df2 = df.drop(['verified_reviews', 'summed_text'], axis = 1)
df2.head()

数据可视化

为了更好的理解数据,我们用 Seaborn 来可视化吧!

导入依赖项:

import seaborn as sns
from matplotlib import pyplot as plt

绘制所需变量的图表:

sns_plot = sns.pairplot(df, hue = 'rating', vars=['polarity','subjectivity', 'number_words', 'number_character'])
#sns_plot.savefig('name_of_file.png')
#files.download('name_of_file.png')

请注意,最后两行被注释掉了,如果您想保存文件,可以随意取消注释!

以下是输出:

总结文本的数据呢?

正如您所看到的,存在某种程度的聚类,让我们希望我们的模型能够捕捉到细微差别!

构建和执行模型

我们已经完成了数据预处理,最困难的部分已经过去了!

下一步我们将使用 Scikit-Learn 实现一个随机森林分类器。如果您不理解这种形式的分类器是如何工作的,这是一个查找它的好机会!

让我们从创建测试和训练数据开始。我们需要将数据帧转换为标签的 numpy 数组和输入的 numpy 矩阵。我们将使用内置的 Scikit-Learn 测试训练函数来拆分数据。

from sklearn.model_selection import train_test_split
import numpy as npdf1=np.matrix(df2.drop(['rating'], axis = 1))
y=np.array(df2['rating'])X_train, X_test, y_train, y_test = train_test_split(df1, y, test_size=0.2)

现在让我们初始化模型,并使其适合训练数据。由于数据集很小,这应该会很快收敛。完成后会显示分数。

from sklearn.tree import DecisionTreeClassifierrfc = RandomForestClassifier(n_estimators=500, criterion='gini', max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features='auto', max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True, oob_score=False, n_jobs=None, random_state=None, verbose=0, warm_start=False, class_weight=None)rfc.fit(X_train,y_train)
score = rfc.score(X_test,y_test)
print(score)

最后,让我们将结果可视化。

from sklearn.metrics import confusion_matrixpredictions = rfc.predict(X_test)
cm = confusion_matrix(y_test, predictions)
labels = ['1','2','3','4','5']
fig = plt.figure()
ax = fig.add_subplot(111)
cax = ax.matshow(cm)
plt.title('Confusion matrix of the classifier')
fig.colorbar(cax)
ax.set_xticklabels([''] + labels)
ax.set_yticklabels([''] + labels)
plt.xlabel('Predicted')
plt.ylabel('True')
plt.show()
#print(cm)

要查看结果的数值,只需取消最后一行的注释,以 numpy 矩阵的形式打印出混淆矩阵。

输出应该类似于以下内容:

成绩还算不错!我们达到了大约 84%的准确率,大多数不正确的预测都在相邻的方块中(a 5 被归类为 a 4 或反之亦然)。

结论

在这篇文章中,我们已经下载了 Alexa 评论,预处理文本以创建我们的模型可以解释的数据框架,可视化数据,建立模型,并做出一些预测!

要进行更全面的分析,请考虑建立一个回归模型,将预测强制为 0 到 5 范围内最接近的整数。由于等级是线性数字等级,回归模型方法可能具有优势。

NLP 是一个强大的工具,我们只是触及了可能性的表面,我希望你能在这个主题上了解更多,并构建自己的应用程序和实现!

一如既往,有任何问题请联系我,我很乐意帮助您。

使用熊猫和海牛的描述性统计快速指南

原文:https://towardsdatascience.com/a-quick-guide-on-descriptive-statistics-using-pandas-and-seaborn-2aadc7395f32?source=collection_archive---------0-----------------------

Image by rawpixel from Pixabay

描述统计学是一门研究数据分析的学科,以有意义的方式描述、显示或总结数据。它涉及各种测量的计算,例如中心测量值、、可变性测量值百分位数以及表格&图的构造。

在本文中,我将介绍那些常见描述性度量的基本概念以及表格和图形的构造。同时,将使用 Pandas 和 Seaborn 演示处理描述性测量的计算和构建表格和图表所需的实际步骤。 Pandas 和 Seaborn 是常用于统计分析和可视化的 Python 库。

先决条件 Python 库

  • 熊猫
  • Matplolib
  • Seaborn

注:

这是强烈推荐使用 Jupyter 笔记本来完成本文中的所有编码任务。这里展示的所有 Python 脚本都是在 Jupyter 笔记本上编写和测试的。您可以参考 Jupyter 官方网站获取在您的机器中设置 Jupyter 笔记本的更多说明。

数据集

我们将使用与墨尔本房价相关的公共数据集"Melbourne _ HOUSE _ PRICES _ less . CSV "作为我们的样本数据。数据集可在 Kaggle 获得。

主题 1:数据类型

1.1 数值和分类数据

在开始任何技术计算和绘图工作之前,理解统计研究中常见的数据类型非常重要。数据主要有两种类型:分类数据(定性)和数值数据(定量)。

  • 分类数据:非数字信息,如性别、种族、宗教、婚姻状况等。
  • 数值数据:测量或计数如身高、体重、年龄、工资、子女数等

1.2 实践中的 Python 代码

在统计分析或数据科学项目中,数据(分类数据、数字数据或两者兼有)通常以表格格式(如电子表格)存储在 CSV 文件中。

为了更好地理解,让我们从使用 Pandas 库可视化 CSV 文件(MELBOURNE _ HOUSE _ PRICES _ less . CSV)中的数据开始。

Read and show the first five rows of data

  • 第一行:导入熊猫
  • 第 3 行:使用 read_csv 方法将 csv 文件中的原始数据读入到数据帧 df 中。**数据帧是用于统计和机器学习模型的二维数组式数据结构。
  • 第 4 行:使用 head() 方法显示数据帧的前 5 行数据。

当我们运行 Jupyter Notebook 中的代码时,您将看到数据显示在一个包含 13 个变量(列)的表格中。

The first five rows of data in a tabular format

Pandas 还提供了另一个有用的方法, info(),来获得数据集中每个变量的数据类型的更多细节。在同一个 Jupyter 笔记本中,只需在前面的代码下创建一个新的单元格,添加以下代码行并运行它:

Details of data type for each column

结果显示数据集中总共有 63023 个条目。通常,与数据类型“ int64 ”和“ float64 ”相关联的列表示数值数据,而数据类型“ object 表示分类数据。

*唯一的例外是“邮政编码”。虽然邮政编码被表示为一个数字(int64),但这并不一定使它量化。邮政编码只是应用于分类数据的数字。

只需一行代码, Pandas 就能让我们识别出由“房间”、“价格”、“物业数量”“距离”组成的数字数据,其余的都是分类数据。

Categorical Data vs Numerical Data

主题 2:中心的测量

Photo by Binyamin Mellish from Pexels

总结数字数据的一个常用方法是找出数据的中心趋势。例如,我们可能会问“在我们的数据集中,房价最典型的值是多少?”。为了解决这个问题,我们可以求助于两个最常见的中心测量:均值和中位数。

2.1 表示

Mean 是所有数字的平均值。计算平均值所需的步骤是:

  1. 对数据集中目标变量的所有值求和
  2. 将总和除以值的个数

例如,如果我们有一组五个值,[70,60,85,80,92],

然而,有时平均值可能会产生误导,可能不能有效地显示数据集中的典型值。这是因为平均值可能会受到异常值的影响。

异常值是指与数据集中的其余数字相比,要么非常高,要么非常低的数字。

让我们看看另外两个数据集,[70,60,1,80,92]和[70,60,300,80,92]。

上方的 Mean_1 被极低的异常值“1”向下驱动。另一方面, Mean_2 由于具有极高的异常值“300”而被向上驱动。

2.2 中位数

Median 是一个数字排序列表的中间值。从一系列数字中获取中值所需的步骤如下:

  1. 将数字从最小到最大排序
  2. 如果列表中有奇数个值,中间位置的值就是中值
  3. 如果列表中有偶数个值,中间两个值的平均值就是中值

下面的两个例子说明了如何从奇数个值和偶数个值中得到中值。

如果我们有一组八个值,[30,45,67,87,94,102,124],

注意:中位数不受异常值的影响。

我们选择使用均值还是中值作为中心点的度量取决于我们要解决的问题。一般来说,在我们的统计研究中,我们应该报告平均值和中值,并让读者自己解释结果。

实践中的 2.3 Python 代码

为了计算均值和中位数,Pandas 为我们提供了两种简便的方法, mean()median() 。让我们用熊猫从数据集中得到我们房价的平均值和中值。

Get mean and median using Pandas

第 1 行& 4: df['Price'] 将选择填充价格值的列。接着是点语法来分别调用方法 mean()和 median()。

第 2 行& 5 :打印平均值和中间值。

注意,熊猫的意味着中位数的方法已经为我们封装了复杂的公式和计算。我们所需要的只是确保从数据集中选择正确的列,并调用方法来获得平均值和中值。输出如下所示:

The mean and median of house prices

主题 3:变化的度量

Photo by Pritesh Sudra on Unsplash

在数据集中总是可以观察到变化。这是非常不寻常的,看到一整组数字共享完全相同的值,如下所示:

当比较两个数据集之间的差异/可变性时,平均值和中值不是一个好的选择。为了进一步解释这一点,让我们看下面的两个例子

上述两个数据集共享相同的平均值和中值,即 300 。然而,它们有不同程度的变异。尽管第一个数据集中的数字和第二个数据集中的数字具有相同的平均值和中值,但两者的差异较小。因此,我们需要另一种测量来检查数据集的可变性。

3.1 标准偏差

测量数据集变化的一种常用方法是计算标准差(SD) 。SD 只是一种测量方法,用来告诉我们一组值是如何从它们的平均值分散开来的。较低的标准差显示数值接近平均值,较高的标准差显示数值偏离平均值较高。

计算 SD 的步骤如下:

  1. 计算数据集的平均值
  2. 对于数据集中的每个数字,用平均值减去它
  3. 平方从步骤 2 获得的差值
  4. 总结第 3 步的结果
  5. 将步骤 4 的总和除以数据集中值的个数减 1
  6. 平方根来自步骤 5 的结果

注意:

  • SD 必须是正数
  • SD 受异常值的影响,因为其计算基于平均值
  • SD 的最小可能值为零。如果 SD 为零,则数据集中的所有数字共享相同的值。

3.2 实践中的 Python 代码

熊猫还提供了一种简便的方法 std() 来计算 SD。让我们试着用熊猫法来计算我们房价的标准差。

第 1 行:调用方法 std()计算房价的 SD

同样,我们可以看到 Pandas std() 方法已经为我们封装了复杂的 SD 计算,我们可以动态地获得 SD 值。

SD of house price

主题 4:以图形方式显示数字数据分布

Photo by Lukas from Pexels

以上章节涵盖了使用单个值的两个描述性测量示例(中心测量和变化测量)。在本节中,我们将了解如何使用图形方式探索数据分布。

4.1 箱线图

揭示数据分布的一种方法是从我们的数据集中找到一个五位数摘要五数汇总包括:

  1. 最低限度
  2. 第 25 个百分位数或第一个四分位数(Q1)
  3. 中间值
  4. 第 75 个百分位数或第三个四分位数(Q3)
  5. 最大值

这里有必要解释一下“百分位的含义。

百分位数是统计学中使用的一种度量,表示一组观察值中给定百分比的观察值低于该值。例如,第 20 个百分位数是这样一个值,在该值以下可以找到 20%的观察值。(来源:维基百科)

五个数字的汇总提供了一种快速的方法,使我们能够粗略地定位数据集中的最小值、第 25 个百分点、中值、第 75 个百分点和最大值。呈现这五个数字汇总的一种图形化方式是创建一个箱线图

Samples of boxplot

4.2 直方图

直方图是一种图形显示,使用矩形条来显示一组数字数据的频率分布。直方图使我们能够可视化数据的潜在分布模式。

构建直方图所需的步骤如下:

  1. 将我们的数据分成称为的区间。
  2. 记录数据集中每个数字的出现次数(频率),并将它们制成频率表
  3. 根据步骤 2 中获得的频率表绘制直方图。

Steps to create a histogram

4.3 实践中的 Python 代码

在本节中,我们将使用 Seaborn 库为我们的房价创建一个箱线图和直方图。

首先,让我们从箱线图开始。

Create a boxplot using Seaborn

  • 第 1 行&第 2 行:导入 Matplolib 和 Seaborn 库
  • 第 4 行:一个神奇的函数,使我们的图形能够在 Jupyter 笔记本中呈现
  • 第六行:设定一个海边的主题
  • 第 7 行:设置绘图的图形大小
  • 第 8 行:使用 Seaborn boxplot() 方法生成一个 boxplot。我们将价格设置为绘图数据的输入。参数“ orient ”中的“ v ”值用于以垂直样式呈现我们的箱线图。

The Seaborn Boxplot of housing price

事实上,在我们的数据集中有三种不同类型的房屋,分别是“H”型房屋、“U”型房屋和“T”型联排别墅。我们可以为每种类型的房屋创建一个箱线图。为此,我们只需在我们的 Seaborn boxplot() 方法中添加另一个参数“y”。

Create Seaborn boxplot for each type of house

  • 行 1: 设置“类型为 x 轴数据,“价格为 y 轴数据。

Seaborn boxplot for each type of house

现在,让我们尝试构建一个直方图来观察我们的房价数据的数据分布。我们将使用 Seaborn distplot() 来创建直方图。

Create Seaborn histogram

  • 第 1 行:这是使用“dropna()”方法从我们的住房数据集中的“Price”列中删除所有空值的必要步骤。如果列中存在空值,Seaborn 将无法生成直方图。
  • 第 2 行:设置直方图的图形大小。
  • 第 3 行:使用 distplot() 方法生成直方图。只有一个必需的输入,即过滤后的房价数据(没有任何空值)。

Seaborn Histogram for House Price

主题 5:探索分类数据

Photo by Providence Doucet on Unsplash

在上面的章节中,我们只讨论了数字数据(房价)的描述性统计分析。分类数据怎么样?在我们看来,我们可能会对住房数据集中的分类数据有一些疑问:

  • 在我们的数据集中,每种类型的房子(h - house、t-town house 和 u-unit)的比例是多少?
  • 哪个地区的房产销售数量最多?

第一个问题可以通过绘制饼图来解决,而条形图可能是解决第二个问题的好选择。

5.1 饼图

饼图是显示数据集中分类数据的数字比例的简单图形方式。饼状图也被称为圆形图(来源:维基百科),它被分成楔形块。每个片段的弧长与分类数据的相对频率成比例。

让我们看一个饼图的例子。

A sample Pie Chart

看一下上面的饼状图样本,我们就能立即了解一年的销售业绩。显然,超过一半的销售额是在第一季度实现的,而第四季度的销售额最低。

5.2 条形图

条形图是分类数据的另一种有效的图形显示。条形图是一种图形显示,使用条形显示每个分类数据的出现次数或频率。

让我们再来看一个条形图的例子。

Sample bar chart

5.3 实践中的 Python 代码

Pandas 提供了一个绘图功能,可以生成一个饼图来显示每种类型的房屋在我们的数据集中所占的比例。

Create a Pie Chart to show the proportion of house

  • 第 1 行:使用 Pandas 方法“ value_counts() ”获得每种房屋类型的频率。
  • 第 2–4 行:创建一个新的数据帧, df2。这个新的数据框架只有一个单独的列,“ house_type ”来保存每个房屋类型的数量,“type _ counts”
  • 第 5 行:将列名“ house_type ”赋给参数“y”。这使得 Pandas pie() 方法能够根据每个房屋类型的数量自动生成一个饼图。参数 autopct 启用,在饼状图中显示每种房型所占的百分比。

Pie Chart to show the proportion of each house type

从饼图中,我们可以很容易地确定每种类型的房子的百分比。

接下来,我们可以使用 Seaborn 创建一个条形图来显示基于地区的房产销售数量。

Create a bar chart using Seaborn

  • 第 1–2 行:将 Seaborn 主题设置为“暗格”,并设置地块的图形大小
  • 第 3 行:将分类变量“ Regionname ”赋给参数“ x ”。将绘图数据集“ df ”分配给参数“数据”。Seaborn " countplot() "方法将自动捕获每个区域的出现次数,并呈现一个条形图。

Bar Chart to show the number of property sales in each region

从上面的条形图中,我们可以得出结论,南部大都市的房产销售数量最多。

结论

这篇文章通过介绍一些被社会广泛采用的主要描述性度量和图形显示,提供了一个描述性统计的快速指南。主要目的是通过使用 Pandas 和 Seaborn,展示一些有意义地总结数据集的可能方法。对于那些希望参与统计分析或数据科学项目的人来说,Pandas 和 Seaborn 应该是两个必不可少的工具包。Pandas 和 Seaborn 的一个主要优势是,它们已经将大量复杂的计算和绘图步骤封装到几行 Python 脚本中。这使得数据分析过程变得更加容易和节省时间。

但是,这里涵盖的主题并不详尽,还有许多主题没有在这里讨论。此外,本文中介绍的现有主题也可以被分解并进行更详细的讨论(这可能需要更多的文章来专门讨论每个特定的主题)。

我希望这篇文章能为描述性统计提供一个起点和一个总的回顾。我希望你喜欢阅读。

Github 资源:

这里展示的所有 Python 脚本都写在 Jupyter 笔记本上,并通过 Github Repo 共享。请随意从https://github . com/teobeeguan 2016/Descriptive _ Statistic _ basic . git下载笔记本

参考

  1. 百分位数的定义(从 https://en.wikipedia.org/wiki/Percentile检索)
  2. 饼状图的定义(从 https://en.wikipedia.org/wiki/Pie_chart检索)

创建惊人数据科学项目的快速指南

原文:https://towardsdatascience.com/a-quick-guide-to-create-astonishing-data-science-projects-6d848375471f?source=collection_archive---------28-----------------------

又名——擅长团队合作的入门指南

Screenshot from Quora

如果你被困在付费墙后面,点击 此处 阅读完整故事与我的朋友链接

在过去的 8 年里,我有幸领导并成为不同国家和背景下的高绩效团队的一员。我构建伟大项目和产品的经历让我想到一件事:没有人独自创造出真正伟大的项目。 数据科学项目和产品也不例外。

最近,我与其他 3 名团队成员合作“利用数据和 GIS 平台有效应对野火”。我将分享一些概念和想法,帮助我们一起快速行动,创造一个伟大的解决方案。

正如制作三明治的家伙 Rana Usman 所说:

让我们来倒数一下数据科学团队是如何工作的。

  • 在第一次会议上建立团队文化:不要开始谈论挑战或问题、技术等。相反,邦德,谈谈你的优势和你想领导的东西——学习。不要深入细节,谈谈如何解决问题的想法。彼此感觉舒服,建立信任。
  • 选择项目管理工具:我们的团队使用 Google Docs 来记录一切。这个想法是把任务、会议结论、提议、时间和结果放在一个共享的地方。我喜欢并强烈推荐 Podio 和 Trello 进行任务管理,但这是一个偏好问题。
  • 为所有实验的工件选择一个单一的平台。保存的模型、代码、应用程序,应有尽有。通过这样做,当项目变得复杂时,我们节省了大量时间。我们团队用的是 Google Drive 和 GitHub。
  • 最后一点让我想到了这一点,创造一种开放的文化,并习惯于分享:团队可以从彼此的代码和解决问题的方式中学到很多。分享每一份文件,并寻求反馈。
  • 对快速的试验和改变保持开放的态度:当遇到这样的问题时,解决方案并不是直截了当的。在我们的项目中有一个点,我们每天都在改变任务和负责任务的人,直到我们到达我们想要的点。从第 0 天开始适应变化。
  • 安排固定时间- 每天同步 15 分钟:这让每个团队成员都知道现在正在处理什么,挑战和下一步。
  • 强制执行同行代码和文档审查:团队特别了解彼此的工作风格,额外的关注将使个人任务更上一层楼。
  • 只有一个沟通渠道:使用 Slack。简单。
  • 开放地给予和接受反馈:消极进取的反馈抛在脑后,并习惯于给予和接受诚实而友好的反馈。如果你不同意某个可以改进的方法,那么在整个过程中,对好的和坏的方面保持透明。

我会结束这一切。永远不要用“我” 的方式说话,一旦开始在团队工作,就要用“我们”的方式说话和思考。整个团队负责每一单''闪耀'**'和''成长'*** 的项目。*

根据定义,数据科学项目是团队合作。它们由不断迭代新想法的平稳进展组成。希望这些基本但重要的要点将帮助您创建一个令人惊叹的数据科学团队项目。

如果你对团队建设和工作有任何其他建议,请在评论中分享。我很想读读它们。

使用命令行(终端)的快速指南

原文:https://towardsdatascience.com/a-quick-guide-to-using-command-line-terminal-96815b97b955?source=collection_archive---------4-----------------------

能够使用命令行是高级编码所必需的。以下是你需要知道的要领。

Photo by Florian Olivo on Unsplash

打开命令行。如果你刚刚开始编码,你可能甚至不知道命令行是什么。别担心!这只是告诉你的电脑做什么的一个简单方法。根据您使用的操作系统,访问命令行的方式各不相同。

  • MacOS:打开 spotlight search(默认方式是点击 command 和空格键)并输入“终端”。选择名为“终端”的应用程序,然后按回车键。这将打开一个黑色背景的应用程序。当您看到您的用户名后面跟着一个美元符号时,您就可以开始使用命令行了。
  • Linux:可以直接按[ctrl+alt+T]打开终端,也可以点击“破折号”图标,在搜索框中输入“终端”,打开终端应用程序进行搜索。同样,这应该打开一个黑色背景的应用程序。当您看到您的用户名后面跟着一个美元符号时,您就可以开始使用命令行了。
  • Windows:在 Windows 10 上,打开开始菜单,进入名为“Windows 系统”的快捷方式文件夹。按下拉菜单应该会显示一个快捷方式来打开命令提示符应用程序。右键单击快捷方式,按“更多”,然后按“以管理员身份运行”。对于 Windows 8 ,进入开始屏幕,按下“所有应用”,向右滚动直到“Windows 系统”文件夹出现。您可以在那里找到命令提示符。对于 Windows 7 ,打开开始菜单,点击“所有程序”。点击“附件”,你会发现命令提示符的快捷方式。右键单击快捷方式,然后按“以管理员身份运行”。

访问服务器。如果你在服务器上运行代码(例如 GPU 集群或类似亚马逊网络服务的东西),你需要能够访问服务器。最好的方法是通过安全外壳(ssh),它让您可以使用互联网安全地控制和修改您的服务器。您可以通过键入以下内容来完成此操作:

ssh 用户名@主机服务器

其中,username 是您在服务器上的帐户名称,host_server 是主机(例如,GPU 集群的名称)。如果您有密码来访问您在服务器上的帐户,命令行将提示您输入密码。如果您是第一次访问该特定服务器,您的电脑也可能会询问您是否能记住授权密钥,键入“是”或相应的短语,这样您的电脑就不会每次都问您这个问题。当您链接到服务器时,您应该会看到命令行以某种 username@host 格式的绿色标题开始。将此作为您真正连接到服务器的指示器。

移动文件。这个很简单。键入以下内容:

mv 目标

其中 mv 是 move,target 是要移动的文件,destination 是要移动到的位置。

复制文件/文件夹。如果你想拷贝文件,最简单的方法是使用 cp 命令。使用以下脚本复制文件。

cp -r 目标

在这个脚本中,cp 代表复制,而-r 代表递归复制。目标是您要拷贝的目标文件夹/文件,目的地是您要拷贝到的目标文件夹。重要提示:

  • 假设你输入“CP-r home/target/home/destination/”。如果“home”是文件夹,“target”是文件夹,但“destination”不是 home 中的文件夹,那么“target”会被复制到 home 中但会被命名为“destination”。
  • 假设你输入“CP-r home/target/home/destination/”。如果所有这些都是有效的文件夹,“目标”将被复制为“home”中“destination”内的一个文件夹—您将得到一个“home/destination/target/”文件夹。
  • 假设你输入“cp -r home/target/ users/”。这只会将“目标”文件夹复制到同名(目标)下的“用户”文件夹中。
  • 使用字符代表所有。例如,要复制文件夹中以字母 a 开头的所有文件,您的目标应该是“/folder/a”。复制某个扩展名的所有文件(比如。png),你的目标应该是“/folder/*。png”。
  • 使用。表示当前文件夹的字符。
  • 如果文件/文件夹已经存在于目的地,其将被覆盖。所以一定不要犯这种新手的错误。

删除文件/文件夹。删除文件是非常必要的,所以你应该这样做。使用此脚本:

rm -r 目标

其中 rm 表示删除,-r 表示递归地执行删除。目标是您试图删除的文件/文件夹。如果您没有阅读“复制文件/文件夹”下的注释,请参阅更多专业提示:

  • 这个命令不会让你删除一个不存在的文件(它会说“没有这样的文件或目录”)
  • 使用字符代表所有。例如,要删除文件夹中以字母 a 开头的所有文件,您的目标应该是“/folder/a”。删除特定扩展名的所有文件(比如。png),你的目标应该是“/folder/*。png”。
  • 使用。表示当前文件夹的字符。
  • 这个命令会很快删除文件。文件一旦删除,就无法恢复。这里没有控制 Z。请务必输入正确的目录/文件。
  • 或者,您可以在-r 后面输入“-i”(例如 rm -r -i target),这将提示计算机请求允许删除每个文件。

清单文件。当你在一个文件夹中时,能够看到其中的文件/文件夹可能非常有用。用这个:

ls 目标(选项)

Target 是您试图列出其内容的文件夹(如果您试图列出当前所在文件夹的内容,请将 target 留空)。您也可以使用以下选项:

  • "-F ":为文件类型添加一个字符(例如" * "表示可执行的脚本,而"/"表示目录)。
  • "-f ":停止计算机对内容进行排序。当有大量的文件并且对这些文件进行分类没有用时,这是很有用的。
  • "-a ":列出所有文件,包括通常隐藏的隐藏文件。
  • "-h ":将让您也获得文件的大小。
  • "-t ":按上次修改时间对文件进行排序。

更改您所在的目录。使用这个简单的命令来改变你当前的目录:

cd 目标

其中 cd 是更改目录,target 是要输入的文件夹。更多提示:

  • 使用。表示当前文件夹的字符。做“cd”将刷新命令行显示的当前目录(如果您已经更改了文件夹路径中的文件夹名称,这将非常有用)。
  • 使用"../”来表示封闭文件夹。例如,如果您当前在“home/target/”中,那么您可以执行“cd../”以进入“home”文件夹。的”../”也是可堆叠的,所以其中两个可以让你拿回两个文件夹。

制作新文件夹。这也是一个非常简单的命令。使用以下脚本:

mkdir 目标

其中 mkdir 是制作目录,target 是要制作的文件夹的名称。例如,“mkdir target”会在命令行当前所在的目录中创建一个名为“target”的文件夹。

清理杂物。当你运行太多命令时,很容易让你的命令行屏幕被一堆绿色、蓝色和白色的线弄得乱七八糟。使用这个一个字的命令来清除它:

清楚的

不言自明:clear 代表清除屏幕。

运行脚本。如果你正在编码,你可能希望能够使用命令行运行你的代码。你很幸运,有一个很好的方法可以做到这一点!现在,我是一个 Python 用户,所以先说 Python:

python 目标

目标是您想要执行的文件(它应该以“.”结尾)。py”)。

对于 Java,使用以下代码:

java 目标

javac 目标

做“java”会运行文件,“javac”会编译它。目标是您想要执行的文件(它应该以“.”结尾)。java”)。

其他语言如 CJavaScript 需要特殊的包才能在命令行中运行,我已经为它们做了超链接说明。

Photo by Erwan Hesry on Unsplash

恭喜你!您现在能够使用命令行了(在一定程度上)。这些只是基本的命令,还有更多用于特定任务的专用命令,但这些是几乎任何使用命令行的人都应该知道的。

深度学习快速入门

原文:https://towardsdatascience.com/a-quick-introduction-to-deep-learning-41af97e064da?source=collection_archive---------21-----------------------

在过去的几年里,深度学习已经离开了研究实验室,去征服非专家公众。谷歌、亚马逊、脸书和微软等公司通过使用深度学习算法取得的惊人成果,使其受到媒体的广泛关注。让我们在猫或狗分类问题的背景下发现深度学习算法的一些基本原则。

什么是神经科学中的神经元?

神经元是大脑的基本细胞,负责开发一些与智力、识别、决策等相关的机制。为了简化起见,让我们考虑一个神经元总是给出二进制输出;要么是被激励,输出信号非零,要么是未被激励,因此输出信号为零。假设有一个神经元负责区分猫和狗。为了做出决定,这个神经元必须考虑来自视觉和听觉等感官的输入信息,并变得兴奋地说猫,未兴奋的——零输出信号——意味着狗。

当然,收集的输入信息在神经元做出的最终决定中并不具有相同的普遍性。

这里,因为猫和狗可能有相同的颜色,所以关于颜色的输入信息不会像关于高度的信息那样有区别,这似乎没有关于动物声音的信息重要。这是一个生物神经元给它的每一个输入信息分配一个或大或小的重要性的地方,反映了这个信息与它的输出信号的相关程度。为了达到这个目标,信息通过树突提供给神经元,并流向突触,这些化学神经递质可以使抑制,减弱信号或者兴奋,增强信号。

A biological neurone

应该注意的是,这几乎是你开始做深度学习所需要知道的关于神经科学的所有知识。前面提到的机制要复杂得多,它们的核心解释超出了本文的范围。记住这一点可能是至关重要的,深度学习更多的是关于计算机科学和数学——我们将看到它是如何实现的——并且只与神经科学分享设计人工神经元的基本原则。我们不是在做神经科学。正如脸书大学深度学习领域的顶级研究员 Yann LeCun 教授所说的那样。深度学习的灵感来自神经科学,就像飞机的灵感来自鸟类一样,它们使用相同的原理,但细节却截然不同。

我们如何设计人工神经元?

人工神经元总体上依赖于上述机制;输入信息的重要性由一个数字来量化,称为权重 w 数字越大,神经元输出信号中的信息越占优势。

An artificial neurone with three entries

每个输入乘以其相应的重要性系数,该条目的权重 wi I,然后传输到神经元。这样,神经元将所有加权输入相加。假设一个高的结果应该被解释为一只猫—对应于 1 —当一个低的结果,作为一只狗—对应于 0 —时。也就是说,我需要一个真实的值来与之前的结果进行比较——输入的加权和——并做出决定,是猫还是狗。这个中间值被称为偏差,它属于神经元,不依赖于输入。

让我们来回顾一下,神经元接受输入,将每个输入乘以相应的权重,对这些加权输入求和,然后将这个和与其偏差 b 进行比较,并做出最终决定,是猫还是狗。

这就相当于说,神经元对加权输入求和,加上它的偏差,如果结果是肯定的,决定是猫,否则是狗。让我们引入 y 来简化符号,

激活功能

为了理解激活功能,让我们想象你手中有一个打火机,为了科学起见,你戴上它,让它离你的手指更近。随着打火机离你的手指越来越近,你也越来越痛苦。因此,尽管输入,比如说热量增加了,但是负责评估手指疼痛的神经元传递了一个更大的信号,这个信号被解释为越来越痛。

考虑到这一点,我们不是说人工神经元为阳性 y 提供 1,而是说它提供与 y 成比例的反应。 y 越大,输出越大。由此可知, c 为常数的正 y 的输出为 c.y ,负 y 的输出为 0 。因此公式,由于 c 通常取为 1,如果为正,则输出为 y ,如果为负,则输出为 0 。这被称为激活功能,准确地说是 RELU整流线性单元激活功能。

RELU activation function curve

另一个激活功能

现在假设,皇家马德里队将与巴塞罗那队比赛,我们要求随机选择一个人——不是铁杆球迷——对比赛结果进行预测。即使我们给了这个人关于球员,工作人员等的所有信息,他也不会给出一个绝对的结果,就像他 100%确定的那样。既然总是有疑问,他大概会给出一个队获胜的可能性,比如说有 60%的把握 R.M .会赢这场比赛。我们赋予人工神经元同样的能力。神经元不是从 y 传递一个绝对的二进制结果,比如 0 或 1,而是给出一个介于 0 和 1 之间的数字,这里解释为动物是猫的可能性。这是通过对计算出的 y 应用一个函数来完成的,所以输出是,

Sigmoid activation function

这就是所谓的 sigmoid 激活函数,因为函数的曲线类似于 s

请注意,假设我们将 y 与零进行比较,并输出 0 或 1,正如我们首先介绍的那样,这也是一个具有以下曲线的激活函数,

Basic activation function

一般来说,对于激活函数 f ,神经元的输出是 f(y),其中, y 是条目的加权和,加上神经元的偏差 b。

综上所述,激活函数是我们应用于结果 y 的一个函数f;因此,神经元的最终输出是 f(y)。功能 f 的选择取决于要解决的问题和经验。最常用的激活功能是 sigmoidRELU ,因为它们是众所周知的并且导致更好的性能。现在你知道了所有关于人工神经元的知识,让我们用它们来解决猫或狗的问题。

多层感知器网络

决定一种动物是猫还是狗实际上是一项由单个神经元完成的相当困难的任务。然后将这个复杂的任务分成几个简单的子任务,分配给不同的神经元。这些神经元中的每一个都会考虑所有的条目,给它们分配权重,反映它们在最终决定中的重要性。这导致了一个更强大的网络。在这里,神经元 3 将做出最终决定。

A densely connected network with three neurones

由于相同的条目被提供给每个第一层神经元,并且一层的神经元连接到前一层的所有神经元,这被称为密集连接的神经网络。

这里我们有一个神经架构——还不深——也就是说,一个感知器;由美国心理学家弗兰克·罗森布拉特于 20 世纪 50 年代首次提出。感知器在这里只有一层。大多数时候,在深度学习中,我们可以利用实际上大量的数据来解决复杂的任务。因为我们希望我们的神经网络足够强大,所以我们上面看到的层将由更多的神经元组成,128 或 256 或 512 个——一般是 2 的幂——然后,一个接一个,几十层将被堆叠起来;我们现在得到了一个深度多层感知器,因此得名深度学习。同一层的神经元应该具有相同的激活功能。但是从一层到另一层,激活功能可能不同。

A multi-layered perceptron with 6 layers

为了解决猫或狗的分类问题,我们可以设计一个多层感知器神经网络,其第 1 层到第 5 层具有 RELU 激活功能,第 6 层的神经元具有 sigmoid 激活功能,这被认为是产生猫的可能性。层 1 称为输入层,层 6 称为输出层;从 2 到 5 是隐藏层,因为隐藏在输入和输出层之间。这是我们在真正的深度学习模型中通常做的事情。现在我们已经建立了模型,它是如何工作的呢?

有监督的深度学习

我们从设计神经元和我们为模型选择的层数开始。一旦这样做了,我们希望模型能够运行。然而,在最开始,我们不知道权重和偏差应该取什么值,这样模型才能做出正确的决定。因此,权重和偏差参数是用随机值初始化的,这意味着模型非常不准确。顺便说一句,该模型将自己学习神经元的权重 w 和偏差 b 的正确值,并提高准确性,因此在深度学习中学习。学习权重和偏差的步骤被称为训练阶段

培训过程

训练的最终目标是将权重和偏差从初始随机值移动到优化值,因此该模型在说猫或狗时更准确。

图像和其他类型的数据

生物神经元接收来自视觉、听觉、嗅觉等的综合信息。深度学习模型大部分时间都将被图像喂养,但也可以为视频、声音、文本和表格设计。正如我们在上面看到的,每个神经元都将对条目进行数学运算,所以输入数据必须绝对是数字矩阵;只要与计算和数学运算兼容。

图像到矩阵

考虑如下的灰度图像,该图像实际上以像素矩阵的形式存储在您的计算机设备或电话中,其中像素是一个几乎不可见的正方形,颜色从白色(对应于 255)到黑色(对应于 0)。该矩阵用于为模型提供信息。

From a 100x100 px image zoomed in and the 100x100 matrix, here with random values.

放大图片时,像素变得可见;每个像素灰度——从 0 到 255——符合最右边矩阵中的一个数字。这里我们同样处理一个猫的图像。

Cat 100x100 px image and corresponding 100x100 matrix

在训练阶段,我们让模型计算这个矩阵 x 代表一只猫的概率p——通过 sigmoid 函数,见上文。由于模型还没有训练好,所以不太可能 p=1

价值函数

我们知道这张图片是一只猫,所以我们将模型的目标定为给出 1 的 p 值——这意味着 100%确定这是一只猫——为了测量模型与正确结果的差距,我们可以考虑差异 1-p 。通过这样做,我们引入了一些新的东西,一个成本函数或损失函数,它是我们期望的 p 的值和计算出的值之间的差异。

由于可能性 p 取决于模型的权重 W 和偏差 b ,因此成本函数也取决于它们。

如果 C(W,b) 是 0,那就完美了,意味着实际结果与计算结果相同。不幸的是,由于有成千上万的权重和偏差需要调整,很可能无法达到这个目标。因此,我们试图通过名为梯度下降的计算技术来最小化损失 C(W,b) 。我们同样处理成千上万不同的猫和狗的图像。对于它们中的每一个,模型都会移动权重和偏差,以减少损失并提高准确性。一旦训练完成,参数值,即模型的权重和偏差被优化以最小化损失;它们被冻结,以后不会被更改。因为我们需要人类的帮助来计算损失——我们需要实际的结果——这被称为监督学习

测试阶段模型精度的计算

最后一步,在一个从未见过的猫和狗的独立图像数据集上测试该模型,在这里,模型不会学习,我们只是观察它的反应,看看它是否足够有效和训练有素。这是测试阶段。我们模型的准确率会是正确答案的比例。如果该模型足够高效和准确,它就可以部署在目标基础设施上,即联网设备、移动电话、自动驾驶汽车等。到这个时候,模型将在没有任何人类帮助的情况下对真实世界的图像做出决定。最先进的技术是在分类任务中对最好的模型有 99%的准确性,在实际应用中足够准确。

结论

本文的唯一目的是介绍神经元在深度学习模型和学习过程中的作用背后的直觉。如果你想更深入,发现深度学习的迷人世界,梯度下降,生成模型等。,不要犹豫,订阅时事通讯,发现我的下一篇文章。感谢您的阅读。

深度学习要开始的一些建议

使用 Python 进行深度学习

https://www . Amazon . fr/Deep-Learning-Python-Francois-Chollet/DP/1617294438

使用 Keras 进行深度学习

https://www . Amazon . fr/Deep-Learning-Keras-Implementing-Learning-ebook/DP/b 06 y2 ymrdw

深度学习 TensorFlow 2.0 快速入门

原文:https://towardsdatascience.com/a-quick-introduction-to-tensorflow-2-0-for-deep-learning-e740ca2e974c?source=collection_archive---------4-----------------------

想获得灵感?快来加入我的 超级行情快讯 。😎

经过大量的社区宣传和期待, TensorFlow 2.0 终于在 2019 年 9 月 30 日由 Google 发布

TensorFlow 2.0 代表了图书馆发展的一个重要里程碑。在过去的几年里,TensorFlow 的主要弱点之一,也是许多人转而使用 PyTorch 的一个重要原因,就是它非常复杂的 API。

定义深度神经网络需要的工作比合理的要多得多。这导致了位于 TensorFlow 之上的几个高级 API 的开发,包括 TF SlimKeras

现在事情又回到了起点,Keras 将成为 TensorFlow 2.0 的官方 API。加载数据、定义模型、训练和评估现在都变得容易多了,Keras 风格的代码更干净,开发时间更快。

本文将快速介绍使用 Keras 进行深度学习的新 TensorFlow 2.0 方式。我们将经历加载数据集、定义模型、训练和评估的端到端流程,所有这些都使用新的 TensorFlow 2.0 API。如果你想自己运行全部代码,我已经设置了一个包含全部内容的 Google Colab 笔记本

导入和设置

我们将从导入 TensorFlow、Keras 和 Matplotlib 开始。请注意我们如何使用tensorflow.keras直接从 TensorFlow 中提取 Keras,因为它现在就捆绑在 tensor flow 中。我们还有一个 if 语句来安装 2.0 版本,以防我们的笔记本运行的是旧版本。

接下来,我们将加载数据集。对于本教程,我们将使用 MNIST 数据集,它包含 60,000 张训练图像和 10,000 张数字从 0 到 9 的测试图像,大小为 28x28。这是一个非常基本的数据集,一直用于快速测试和概念验证。还有一些使用 Matplotlib 的可视化代码,因此我们可以查看数据。

Visualizing MNIST digits

创建用于图像分类的卷积神经网络

做图像分类最好的方法当然是用一个卷积神经网络 (CNN)。API 将拥有我们构建这样一个网络所需的一切。由于 MNIST 非常小——图像大小为 28x28,只有 60,000 个训练图像——我们不需要超级庞大的网络,所以我们将保持简单。

在过去的几年中,构建一个好的 CNN 的公式在很大程度上保持不变:堆叠卷积层(通常为 3×3 或 1×1 ),中间有非线性激活(通常为 ReLU ),添加几个完全连接的层,并在最后添加一个 Softmax 函数来获得类概率。我们已经在下面的网络定义中完成了所有这些工作。

我们的模型共有 6 个卷积层,每个卷积层之后都有一个 ReLU 激活。在卷积层之后,我们有一个 GlobalAveragePooling 来将我们的数据放入一个密集的向量中。我们完成了我们的全连接(密集)层,最后一个有 10 个 MNIST 的 10 类大小。

同样,请注意我们所有的模型层都来自于tensorflow.keras.layers,并且我们使用的是 Keras 的功能 API。使用函数式 API,我们将模型构建为一系列顺序函数。第一层将输入图像作为输入变量。接下来,每个后续层都将前一层的输出作为其输入。我们的model.Model()简单地连接了从输入到输出张量的“管道”。

有关该模型的更详细描述,请查看下面model.summary()的打印结果。

Model: "model_1" _________________________________________________________________ Layer (type)                 Output Shape              Param #    ================================================================= input_3 (InputLayer)         [(None, 28, 28, 1)]       0          _________________________________________________________________ conv2d_12 (Conv2D)           (None, 28, 28, 32)        320        _________________________________________________________________ activation_16 (Activation)   (None, 28, 28, 32)        0          _________________________________________________________________ conv2d_13 (Conv2D)           (None, 14, 14, 32)        9248       _________________________________________________________________ activation_17 (Activation)   (None, 14, 14, 32)        0          _________________________________________________________________ conv2d_14 (Conv2D)           (None, 14, 14, 64)        18496      _________________________________________________________________ activation_18 (Activation)   (None, 14, 14, 64)        0          _________________________________________________________________ conv2d_15 (Conv2D)           (None, 7, 7, 64)          36928      _________________________________________________________________ activation_19 (Activation)   (None, 7, 7, 64)          0          _________________________________________________________________ conv2d_16 (Conv2D)           (None, 7, 7, 64)          36928      _________________________________________________________________ activation_20 (Activation)   (None, 7, 7, 64)          0          _________________________________________________________________ conv2d_17 (Conv2D)           (None, 7, 7, 64)          36928      _________________________________________________________________ activation_21 (Activation)   (None, 7, 7, 64)          0          _________________________________________________________________ global_average_pooling2d_2 ( (None, 64)                0          _________________________________________________________________ dense_4 (Dense)              (None, 32)                2080       _________________________________________________________________ activation_22 (Activation)   (None, 32)                0          _________________________________________________________________ dense_5 (Dense)              (None, 10)                330        _________________________________________________________________ activation_23 (Activation)   (None, 10)                0          ================================================================= Total params: 141,258 Trainable params: 141,258 Non-trainable params: 0 _________________________________________________________________

培训和测试

最精彩的部分来了:训练并获得实际效果!

首先,我们需要做一些数据预处理,以便为训练正确格式化数据。我们的训练图像需要在一个 4 维的阵列中,格式为:

(批量 _ 尺寸,宽度,高度,通道)

我们将图像转换为类型为 float32 的图像,这是正确训练的一个要求,并进行归一化,使每个像素的值在 0.0 和 1.0 之间

至于标签,因为我们正在使用 Softmax 激活,我们希望我们的目标输出是一个热编码向量的形式。为此,我们使用了tf.keras.utils.to_categorical()功能。函数中的第二个变量被设置为 10,因为我们有 10 个类。

我们选择亚当作为我们的优化器——它非常容易使用,开箱即用。我们将损失函数设置为categorical_crossentropy,这与我们的 Softmax 兼容。训练 CNN 就像用我们的数据作为输入调用 Keras .fit()函数一样简单!

请注意,所有这些几乎都是纯粹的 Keras。真正唯一的区别是我们使用了 TensorFlow 的 Keras 库,即tensorflow.keras。它非常方便,因为它包含在一个漂亮的包中 TensorFlow 的强大功能和 Keras 的易用性。太棒了。

MNIST 是一个简单的数据集,所以我们的 CNN 应该很快达到高精度。在我自己的实验中,它在 5 个时期内达到了大约 97%。

一旦训练完成,我们可以绘制损失和准确性的历史。我们再次使用纯 Keras 代码从历史中提取损失和准确性信息。Matplotlib 用于轻松绘图。

Accuracy (left) and loss (right) results from our CNN on MNIST

要评估我们的网络,我们可以使用…你猜对了,Keras .evaluate()功能!我们将应用它,然后打印出精度。

我们的 CNN 模型在测试集上达到了 98.52%的准确率。

喜欢学习?

在推特上关注我,在那里我会发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上与我联系!

树袋熊数据快速入门

原文:https://towardsdatascience.com/a-quick-primer-on-databricks-koalas-38c89369cf9f?source=collection_archive---------26-----------------------

与 Spark 数据框互动熊猫词汇

Photo by Jordan Whitt on Unsplash

在我的一个项目中,我广泛使用 Spark 来管理一些大型数据文件。尽管它通常以使用大型分布式系统的诸多好处而闻名,但它在本地同样适用于处理大量信息的项目。

我经常使用熊猫进行数据处理,但有时 Spark 会让它相形见绌。你可以对 Pandas 使用 chunksize,但是根据我的经验,即使你找到了合适的大小来管理,它也比 Spark 数据帧要慢得多,而且要消耗更多的内存。从 Pandas 迁移到 PySpark(使用 Spark 的 Python API)的挑战是导航数据帧的词汇是不同的。我真的不介意摸索着与包交互,但是 PySpark 的错误消息通常很隐晦,文档也不是很好。在某些情况下,它就像编写一个快速的 SQL 查询一样简单,但是通常情况下,您需要进行更新和创建函数,并且这些部分所需的语言变得更加复杂。

考拉入场!今年早些时候由 Databricks 推出的,考拉很容易将熊猫的相同知识应用到 Spark 数据框架中。从类似的导入开始,创建一个 Spark 会话:

import pandas as pd
import numpy as np
import databricks.koalas as ks
from pyspark.sql import SparkSession

树袋熊数据框可以通过多种不同方式创建:

# Dataframe from scratch
koala_df = ks.DataFrame(
    {'type': ['panda', 'koala', 'grizzly', 'brown'],
     'color': ['black/white', 'grey', 'brown', 'brown'],
      'score': 5, 1, 5, np.nan},
    index=[1, 2, 3, 4])# From a file
koala_df = ks.read_csv("all_the_bears.csv", header=0)# From an existing Spark dataframe
koala_df = spark_df.to_koalas()# From an existing Pandas dataframe
koala_df = ks.from_pandas(pandas_df)

作为一个树袋熊的数据框架,你可以接触到和熊猫一样的语言:

# Get first rows of dataframe
koala_df.head()# See the column names
koala_df.columns# Quick summary stats
koala_df.describe()# Convert to Numpy
koala_df.to_numpy()# Group rows
koala_df.groupby('score')

它还提供了一些在 PySpark 中很麻烦的数据清理特性:

# Drop rows with missing values
koala_df.dropna(how='any')# Fill missing values
koala_df.fillna(value=5)

我最喜欢的功能之一是轻松导出,这在 Spark 中肯定会很时髦:

# Export to csv
koala_df.to_csv("bear_bears.csv")

作为一个不断学习和寻求提高技能的人,对我来说最重要的是,它使使用 Pandas 的本地项目更容易过渡到使用 Spark 的更具可扩展性的项目。我建议你用它弄脏你的手,看看你有什么想法。现在去下载一个 10GB 的 json 文件,尽情享受吧!

对 Genevera Allen 关于机器学习“导致科学危机”的快速回应

原文:https://towardsdatascience.com/a-quick-response-to-genevera-allen-about-machine-learning-causing-science-crisis-8465bbf9da82?source=collection_archive---------18-----------------------

这不是咆哮,我是认真对待这些文章,并解释作者提出的一些观点是错误的。剧透:有些没有错。

https://dailyhive.com/toronto/ago-crowdfunding-infinity-mirrors

文章

在这里我将谈论这两篇文章:

[## 机器学习“引发科学危机”

成千上万的科学家用来分析数据的机器学习技术正在产生误导性的结果…

www.bbc.com](https://www.bbc.com/news/science-environment-47267081) [## 我们能相信使用机器学习做出的科学发现吗?

华盛顿-(2019 年 2 月 15 日)-莱斯大学统计学家 Genevera Allen 表示,科学家必须不断质疑…

www.eurekalert.org](https://www.eurekalert.org/pub_releases/2019-02/ru-cwt021119.php)

请在此之前阅读它们,这样你可以创造你自己的观点。

以下是更多评论:

[## 统计学家:机器学习正在引发一场“科学危机”

莱斯大学的统计学家 Genevera Allen 在本周一个著名的科学会议上发出了严重警告

futurism.com](https://futurism.com/machine-learning-crisis-science) [## 机器学习导致了科学领域的“再现性危机”

来自莱斯大学的统计学家说,使用机器学习技术做出的科学发现不能被自动信任。

www.technologyreview.com](https://www.technologyreview.com/the-download/612982/machine-learning-is-contributing-to-a-reproducibility-crisis-within-science/) [## 统计学家对机器学习的可靠性发出警告|数字趋势

机器学习在科技领域无处不在。但是机器学习技术真的有多可靠呢?一个…

www.digitaltrends.com](https://www.digitaltrends.com/cool-tech/machine-learning-reliability-reproducibility/)

什么没错

不要误解我的意思,文章中有很多重要的观点,我只是认为它们的理由可能不正确。

科学中存在可复制性的危机

https://www.nature.com/news/1-500-scientists-lift-the-lid-on-reproducibility-1.19970

这是真的。我们有麻烦了。在某些科学领域,只有 36%的研究被重复。这还不够。

更多数据:

https://www.nature.com/news/1-500-scientists-lift-the-lid-on-reproducibility-1.19970

他们在研究中指出:

尽管我们调查中的绝大多数研究人员都未能重现实验,但不到 20%的受访者表示,他们曾被另一名无法重现其工作的研究人员联系过。

这也是一些严重的问题,因为一小部分人试图重复研究,他们中的一些人在重复实验中失败了,但只有 20%的人告诉其他人,所以你知道你做的是错的机会是最小的。

但是正如你从上面的图片中看到的,这个问题几乎在每一个科学领域都存在。这一点以后再说。

机器学习不是防弹的

https://rarehistoricalphotos.com/testing-bulletproof-vest-1923/

如果存在危机,那就是如何正确地进行数据科学(DS)的危机。许多数据科学项目失败了,这并不是因为缺乏技能或知识(有时),数据科学项目需要一个清晰有效的攻击计划才能成功,并需要一个运行它的方法。

大多数机器学习项目都在 DS 世界内部(以某种方式),我们在 DS 内部运行机器学习周期的方式存在问题。

以下是一些最“有组织”的机器学习工作流:

https://eng.uber.com/scaling-michelangelo/

https://cloud.google.com/ml-engine/docs/tensorflow/ml-solutions-overview

https://medium.com/datadriveninvestor/my-machine-learning-workflow-7576f7dbcef3

https://www.gartner.com/binaries/content/assets/events/keywords/catalyst/catus8/preparing_and_architecting_for_machine_learning.pdf

你看到那里的问题了吗?

我的问题:

  • 我们确定我们能重现我们得到的结果吗?
  • 我们的测试足够吗?
  • 我们如何版本化我们的模型?
  • 我们是否对数据进行了版本控制?
  • 我们是否向读者提供了足够的信息来重现我们的发现?
  • 我们是否愿意回答关于我们在做什么和如何做机器学习的问题?

我认为对于大多数组织来说,答案是

分析什么是错的

在这里,我将看看作者提到的一些我认为不正确的事情,以及为什么。

越来越多的科学研究涉及使用机器学习软件来分析已经收集的数据[……]他们得出的答案很可能是不准确或错误的,因为软件正在识别只存在于数据集而不是真实世界中的模式。

错误是因为:

  • 在大多数情况下,我们拥有的数据来自现实世界,我们在这里是说我们用来做预测模型的交易没有发生吗?
  • 数据可能是脏的(大多数时候是脏的),但我们有很多方法来改进我们拥有的数据,并了解它是否脏。
  • 常见的机器学习周期包括将我们的数据分为训练、验证和测试,这些“验证”或“测试”数据集的行为就像新的“真实数据”。因为它们来自原始数据集,它们都可以被认为是正在发生的事情的“真实”表现。

通常这些研究不会被发现是不准确的,直到有另一个真正的大数据集,有人应用这些技术,并说‘哦,我的天哪,这两个研究的结果没有重叠’

错误是因为:

  • 大数据不一定意味着更好的结果。这就是科学工作的方式,就像说我们在物理学上有危机,因为我发现我的结果和其他文章不一样。
  • 我不是说结果有时不会错,但我们正在研究如何在发布前欺骗我们自己的系统来确保这一点。

现在科学界普遍认识到了再现性危机。我敢说,其中很大一部分确实来自科学中机器学习技术的使用。

错误是因为:

  • 诚然,几乎每个科学领域都在使用机器学习来改善他们的工作方式和结果,但我不认为问题出在机器学习本身。数据问题有时会被忽视,糟糕的机器学习工作流程,糟糕的测试等等。我想说这里不是关于机器学习,而是一些人正在做的方式。
  • 将再现性危机归咎于机器学习和数据科学是不了解全貌的。

这些技术中有很多都是被设计用来做预测的。他们从来不会带着“我不知道”或“我什么也没发现”的回答回来,因为他们没有被要求这么做。

错误是因为:

  • 是的,这个系统是为寻找数据中的模式而设计的,但是如果你做得正确,你会明白其中一些见解是没有意义的。
  • 有些系统带有‘我不知道’,当我们评估我们的模型时,我们会发现它们实际上对数据一无所知。
  • 机器学习不仅仅是运行一个算法,它还包括测试它们,进行基准测试,验证它们等等。

什么不是完全错误的

作者说:

我们真的可以相信目前使用应用于大型数据集的机器学习技术做出的发现吗?在许多情况下,答案可能是,“不检查就不行”,但下一代机器学习系统的工作正在进行中,该系统将评估他们预测的不确定性和可重复性。

我认为,如果我们有一个能够理解何时出现问题的系统,我们就可以相信自己的预测。我们有这样做的工具,数据科学方法包括越来越多的:

  • 数据治理;
  • 数据版本化;
  • 代码版本控制;
  • 持续集成/部署;
  • 模型版本控制。

所有现代技术的发展都是可能的,因为我们找到了处理大数据和小数据的方法。离成功构建防弹工作流还有很长的路要走,但也不远了。在这里,我提出一个非常简单的方法(免责声明:这是正在进行的工作):

[## 擎天柱的数据科学。第 1 部分:简介。

用 Python、Spark 和 Optimus 分解数据科学。

towardsdatascience.com](/data-science-with-optimus-part-1-intro-1f3e2392b02a)

下一步是什么?

小心你正在阅读的东西。我并不是说我掌握了真相,我只是从一个作为数据科学家一直在生产中应用机器学习的人那里给出我的意见,并且它正在努力使它更具可重复性、透明性和强大性。

感谢 Genevera 带来了这个重要的话题,我不想在这里冒犯你,只是打开一个对话。

快速浏览霍尔特-温特斯,季节性 ARIMA 和 FB 先知

原文:https://towardsdatascience.com/a-quick-run-through-of-holt-winters-sarima-and-fb-prophet-c6370c6f32f1?source=collection_archive---------15-----------------------

[## 詹费尔顿/比兴-霍尔特-温特斯-萨里玛-和-FBProphet

这是一个比较 Holt-Winters,SARIMA 和 FBProphet 输出的简单笔记本。关于参数的信息…

github.com](https://github.com/gianfelton/Comparing-Holt-Winters-SARIMA-and-FBProphet/blob/master/Holt Winters%2C SARIMA and FBProphet.ipynb)

上面的链接将带你到笔记本,下面的代码是从那里获得的。

这篇文章的目的是展示霍尔特温特斯,萨里玛和 FB 先知的快速运行。我跳过了任何关于参数调整的内容,因为这可能是多篇文章。

首先,让我们获得 Holt Winters 的导入,以及数据集。

**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**import** **matplotlib.pyplot** **as** **plt**
**from** **statsmodels.tsa.holtwinters** **import** ExponentialSmoothing
%matplotlib inline
**import** **warnings**
warnings.filterwarnings("ignore")

dataset = pd.read_csv('AirPassengers.csv')

数据集可以在本文开头的链接中找到。这是航空乘客的数据,在网上很容易找到。

看前两行就能对形状有个概念。

对于我们的分析,我们需要将 Month 列放入索引中。

dataset['Month'] = pd.to_datetime(dataset['Month'])
dataset.set_index('Month', inplace=**True**)

这会让我们得到这个:

我们需要做的下一件事是设置索引频率,并将数据集分为训练和测试。

dataset.index.freq = 'MS'
train, test = dataset.iloc[:131, 0], dataset.iloc[131:, 0]

在这里,我们可以用训练数据创建和拟合模型。

model = ExponentialSmoothing(train, 
                             trend='add', 
                             damped=**False**, 
                             seasonal='add', 
                             seasonal_periods=12).fit()

模型准备好了,我们现在可以做预测了。

holt_pred = model.predict(start=test.index[0], end=test.index[-1])

为了查看我们的预测,我们可以将它与训练和测试数据一起绘制出来。

plt.figure(figsize=(22, 10))
plt.plot(train.index, train, label='Train')
plt.plot(test.index, test, label='Test', color='r')
plt.plot(holt_pred.index, holt_pred, label='Holt-Winters', color='k')
plt.legend(loc='best', fontsize='xx-large')
plt.xticks(fontsize=18)
plt.yticks(fontsize=16)
plt.show()

接下来,我们来试试萨里玛。

**import** **statsmodels.api** **as** **sm**
**import** **itertools**
**import** **warnings**
warnings.filterwarnings("ignore")

通常情况下,我们会区分和绘制 ACF 和 PACF,以确定我们的条款。一个人应该做这些事情,但我们将跳过这个帖子。下面是对 SARIMA 订单和 seasonal_order 进行参数搜索的函数。

**def** find_best_sarima(train, eval_metric):

    p = d = q = range(0, 2)
    pdq = list(itertools.product(p, d, q))
    seasonal_pdq = [(x[0], x[1], x[2], 12) **for** x **in** list(itertools.product(p, d, q))]

    counter = 0
    myDict = {}

    **for** param **in** pdq:
        **for** param_seasonal **in** seasonal_pdq:
            **try**:
                counter += 1
                mod = sm.tsa.statespace.SARIMAX(train,
                                                order=param,
                                                seasonal_order=param_seasonal,
                                                enforce_stationarity=**False**,
                                                enforce_invertibility=**False**)

                results = mod.fit()
                myDict[counter] = [results.aic, results.bic, param, param_seasonal]

            **except**:
                **continue**

    dict_to_df = pd.DataFrame.from_dict(myDict,orient='index')

    **if** eval_metric == 'aic':
        best_run = dict_to_df[dict_to_df[0] == dict_to_df[0].min()].index.values
        best_run = best_run[0]
    **elif** eval_metric == 'bic':
        best_run = dict_to_df[dict_to_df[1] == dict_to_df[1].min()].index.values
        best_run = best_run[0]

    model = sm.tsa.statespace.SARIMAX(train,
                                      order=myDict[best_run][2],
                                      seasonal_order=myDict[best_run][3],
                                      enforce_stationarity=**False**,
                                      enforce_invertibility=**False**).fit()

    best_model = {'model':model, 
                  'aic':model.aic,
                  'bic':model.bic,
                  'order':myDict[best_run][2], 
                  'seasonal_order':myDict[best_run][3]}

    **return** best_model

输出是一个带有我们的拟合模型的字典,以及 aic、bic、订单元组和季节性订单元组。我们可以调用这个函数来检索我们的模型。

best = find_best_sarima(train, 'aic')

模型准备好了,我们现在可以做预测了。

sarima_pred = best['model'].predict(start=test.index[0], end=test.index[-1], dynamic=**True**)

为了查看我们的预测,我们可以将它与训练和测试数据一起绘制出来。

plt.figure(figsize=(22, 10))
plt.plot(train.index, train, label='Train')
plt.plot(test.index, test, label='Test', color='r')
plt.plot(sarima_pred.index, sarima_pred, label='SARIMA', color='k')
plt.legend(loc='best', fontsize='xx-large')
plt.show()

考验脸书先知的时候到了

**from** **fbprophet** **import** Prophet
**import** **logging**
logging.getLogger().setLevel(logging.ERROR)

与 Holt Winters 和 SARIMA 不同,我们需要月份列作为列,而不是索引。

df = dataset.reset_index()
df.columns = ['ds', 'y']

我们的预测规模将设定为过去 12 个月。在那之前,我们的训练数据就是一切。

prediction_size = 12
train_df = df[:-prediction_size]

现在,我们可以创建模型并使其适合训练数据。

m = Prophet(seasonality_mode='multiplicative')
m.fit(train_df)

我们希望从预测中得到的是一个数据框架。值得研究一下你从中能得到什么。这是相当有用的数据。

future = m.make_future_dataframe(periods=prediction_size, freq='M')
forecast = m.predict(future)

现在我们可以绘制数据了。

single_plot = m.plot(forecast)

现在让我们用我们的训练和测试来绘制预测。

plt.figure(figsize=(22, 10))
plt.plot(train.index, train, label='Train')
plt.plot(test.index, test, label='Test', color='r')
plt.plot(forecast['ds'][131:], forecast['yhat'][131:], label='Prophet', color='k')
plt.legend(loc='best', fontsize='xx-large')
plt.show()

现在让我们放大到测试阶段,看看它们是如何叠加的。

plt.figure(figsize=(22, 10))
plt.plot(holt_pred.index, holt_pred, label='Holt-Winters', color='b')
plt.plot(sarima_pred.index, sarima_pred, label='SARIMA', color='y')
plt.plot(forecast['ds'][131:], forecast['yhat'][131:], label='Prophet', color='k')
plt.plot(test.index, test, label='Test', color='r')
plt.legend(loc='best', fontsize='xx-large')
plt.xticks(fontsize=18)
plt.yticks(fontsize=16)
plt.show()

当然,任何这些模型都可能发生许多不同的参数调整。我只是想针对同一个数据集快速浏览一下。谢谢你。

用 FB Prophet 快速启动时间序列预测的实例

原文:https://towardsdatascience.com/a-quick-start-of-time-series-forecasting-with-a-practical-example-using-fb-prophet-31c4447a2274?source=collection_archive---------1-----------------------

目录

  1. 介绍
  • 时间序列分析
  • 为什么是脸书先知?

2.先知预测模型

  • 饱和增长
  • 趋势变化点
  • 季节性、假日效应和回归因素

3.案例研究:用 Prophet 预测广告支出

4.结案摘要

1.1 时间序列分析

时间序列分析是一种分析时间序列数据的方法,以提取数据的有意义的特征,并产生应用于商业情况的其他有用的见解。通常,时间序列数据是按时间顺序存储的一系列观察值。在跟踪业务指标、监控工业过程等时,时间序列数据往往非常突出。

时间序列分析有助于理解一组度量数据点的基于时间的模式,这对任何业务都是至关重要的。时间序列预测技术可以回答一些商业问题,比如要维持多少库存,你的电子商店预计会有多少网站流量,下个月会卖出多少产品,所有这些都是需要解决的重要时间序列问题。时间序列分析的基本目标通常是确定一个描述时间序列模式并可用于预测的模型。

传统的时间序列预测技术建立在统计模型上,这需要大量的工作来调整模型,并在数据和行业中进行预期。当一个预测模型不能如预期的那样运行时,人们必须根据具体的问题来调整方法的参数。调整这些方法需要彻底了解基本的时间序列模型是如何工作的。如果没有数据科学团队,一些组织很难处理这些预测。如果没有必要建立一个复杂的预测平台或其他服务,对一个组织来说,有一大堆期望似乎没有什么好处。

1.2 为什么是脸书先知?

脸书开发了一个开源 Prophet,这是一个预测工具,有 Python 和 r 两种版本。它提供了易于调整的直观参数。即使是对时间序列预测模型缺乏深入专业知识的人,也可以利用这一点对业务场景中的各种问题做出有意义的预测。

来自脸书先知网站:

“无论对机器还是对大多数分析师来说,做出高质量的预测都不是一个容易的问题。在创建各种业务预测的实践中,我们观察到两个主要主题:

  • 完全自动的预测技术可能是脆弱的,并且它们通常太不灵活而不能结合有用的假设或启发。
  • 能够做出高质量预测的分析师非常少,因为预测是一项专业的数据科学技能,需要丰富的经验。"

1.3 脸书先知的亮点

  • 非常快,因为它是内置的 Stan ,一种用 C++编写的用于统计推断的编程语言。
  • 一种加性回归模型,其中非线性趋势与每年、每周和每天的季节性以及假日效应相适应:1。分段线性或逻辑增长曲线趋势。Prophet 通过从数据中选择变化点来自动检测趋势的变化 2。使用傅立叶级数 3 模拟的年度季节分量。使用虚拟变量的每周季节性成分 4。用户提供的重要节假日列表。
  • 对缺失数据和趋势变化稳健,通常处理异常值。
  • 添加领域知识或业务见解时,调整预测的简单程序。

2.1 先知预测模型

Prophet 使用一个可分解的时间序列模型,它有三个主要的模型组件:趋势、季节性和假日。它们在以下等式中合并:

y(t)= g(t) + s(t) + h(t) + εt

  • g(t):分段线性或逻辑增长曲线,用于模拟时间序列中的非周期性变化
  • s(t):周期性变化(例如每周/每年的季节性)
  • h(t):不定期休假的影响(用户提供)
  • εt:误差项说明模型不能适应的任何异常变化
  • 使用时间作为回归变量,Prophet 试图将时间的几个线性和非线性函数作为组件进行拟合。将季节性建模为附加成分与霍尔特-温特斯技术中的指数平滑法采用的方法相同。Prophet 将预测问题框定为曲线拟合练习,而不是明确地查看时间序列内每个观察值的时间相关性。

2.2 饱和增长

  • 设定一个承载能力cap,根据业务场景或约束条件指定最大可实现点:市场规模、总人口规模、最大预算等。
  • 饱和最小值,用列floor指定,与列cap指定最大值的方式相同。

2.3 趋势变化点

使用趋势组件时,模型可能会过拟合或欠拟合。Prophet 允许的内置变点输入增加,拟合变得更加灵活。

在这里,你可以很好地运用你的商业洞察力:节假日期间销售额的大幅增长,有目的地降低未来的成本等等。如果需要的话,用户还可以手动地将这些业务洞察力提供给变更点。在下图中,虚线代表给定时间序列的变点。

2.4 季节性、假日效应和回归因素

季节效应 s(t)由以下函数近似表示:

Prophet 有一个内置的假日功能,允许输入定制的重复事件。

最后,行动时间!

3.案例研究:用 Python 中的 Prophet 预测广告支出

我从一个数字营销平台获取了广告支出的样本数据。为了在这个案例研究中使用,我还故意做了一些修改,使它成为一个“假”数据源。

在这里,我们尝试使用过去 17 个月的数据来预测未来 30 天的广告支出。

步骤 1:导入库和数据集:

[代码]:

导入熊猫作为 PD
PD . set _ option(' display . max _ columns ',None)

从 fbprophet 导入 numpy 作为 np
导入 Prophet

%matplotlib inline
导入 matplotlib.pyplot 作为 plt

sample = PD . read _ CSV('/…/ad _ spend . CSV ')

步骤 2:检查数据信息

[代码]:

从上面可以看出,该数据集包含了从 2017 年 6 月 1 日到 2018 年 12 月 30 日的一年半的每日广告支出。数据框中有 577 行和两列(日期和花费)。

让我们检查缺少的值:

没有遗漏的价值(从下面的表格中),这很好!👏

[代码]:

步骤 3:绘制时间序列数据

Y-Axis: Ad Spend; X-Axis: Date

从图中可以看出,水平大致不变(日均花费:20 万美元)。季节性波动和随机波动随着时间的推移在大小上大致是恒定的。这表明,使用 Prophet 建立的附加模型来描述数据可能是合适的。

第四步:建模

将数据集分为训练集和测试集。训练集包含 2017 年 6 月 1 日至 2018 年 11 月 30 日的每日广告支出,而测试集包含 2018 年 12 月 1 日至 2018 年 12 月 30 日的每日广告支出。在这里,我们希望使用训练数据集来预测未来 30 天的广告支出。

让我们在不给出任何参数的情况下单独尝试第一个模型。

[代码]:

model 1 = Prophet(interval _ width = 0.95)#默认为 80%

'interval_width=0.95' ,设置不确定性区间,产生预测的置信区间。

生成下面的预测图:

Y-Axis: Ad Spend; X-Axis: Date.

检查模型在历史数据上的表现总是好的。(深蓝线是预测花费数字,黑点实际上是花费数字。浅蓝色阴影是预测的 95%置信区间。)从图中可以看出,尽管该模型试图平滑地拟合所有数据点,但它未能捕捉到季节性。第一个模型仅仅通过应用 Prophet 本身并不能很好地拟合数据。

对于第二个模型,让我们应用一些业务见解来调整第一个模型。只需询问一些业务问题,如季节性趋势和假日事件影响,就可以轻松地将这些信息输入到 Prophet 中。

我们应用了:yearly _ seasonity,weekly _ seasonality,holidays (这里手动创建了假日事件,但是您也可以应用先知内置的Country Holidayschangepoint_prior_scale ,以使模型更加灵活地适应数据点。然后,我们增加了月度季节性。

[Code]:
model 2 = Prophet(interval _ width = 0.95,yearly _ 季节性=True,weekly _ 季节性=True,holidays=us_public_holidays,change point _ prior _ scale = 2)
model 2 . add _ 季节性(name='monthly ',period=30.5,fourier_order=5,prior_scale=0.02)。

生成下面的预测图:

Y-Axis: Ad Spend; X-Axis: Date.

从图中可以看出,第二个模型能够很好地捕捉季节性和拟合历史数据。(深蓝线是预测花费数字,黑点实际上是花费数字。浅蓝色阴影是预测的 95%置信区间。)

检查趋势和季节性因素:

从年度趋势来看,支出在年初上升,在 6 月、8 月和 12 月大幅下降。每周趋势显示,工作日在这里发挥了重要作用。节日事件对广告支出有负面影响,这意味着它会导致广告支出下降,等等。你可以用业务领域的知识来检查这些信息。

第五步:验证

首先,让我们通过可视化预测线和观察线来检查拟合度:

Y-Axis: Ad Spend; X-Axis: Date.

从图中可以看出,该模型似乎能够很好地拟合数据点,尽管它没有捕捉到 12 月底的模式。但是,请记住,输入所有业务信息大约只需要 15 分钟就可以得到这样一个合理的结果。它不需要时间序列建模或机器学习知识方面的专业经验。几乎每个分析师都能做到这一点(然而,Python 或 R 的技能集是必备的。🙃)

通常,在建模评估过程中会用到一些流行的误差术语,如均方根误差(RMSE)平均绝对误差(MAE) 。但是我不想在这里讨论这些误差项,因为只有一个模型。(我将在下一篇文章中比较 Prophet 和经典时间序列模型时讨论这些错误术语)

让我们通过比较预测值和观察值来看看模型的性能:

[代码]:

虽然预测值比实际值高出约 13%,但预测值与下限之间的间隔能够捕捉到实际值。到目前为止,该模型做得相当好,它需要大约 15 分钟。

5.结案摘要

从现在开始,我们可以探索许多时间序列分析方法,如异常检测、用外部数据源预测时间序列等。我们才刚刚开始。

从实际例子来看,Prophet 似乎提供了完全自动化的预测,正如其官方文件所述。如果您的组织没有一个非常可靠的数据科学团队来处理预测分析,它将非常有用。它节省了您回答内部利益相关者或客户的预测问题的时间,而无需花费太多精力来基于经典的时间序列建模技术构建一个令人惊叹的模型。

下一篇文章,我将比较 Prophet 和经典的时间序列预测技术,如 ARMIA 模型,重点是效率和性能。

参考和有用的来源:

脸书先知官方文件,如果你想玩先知必须阅读。

对脸书先知的介绍,它大致解释了什么是时间序列分析,并给出了脸书先知的概述。

使用脸书的 Prophet(带 Python & R 代码)生成快速准确的时间序列预测,它包括 R 和 Python 两种语言的脸书 Prophet 简介。如果你是一个 R 用户,它可能对你有用。

使用 SQL 查询从 Pandas 数据框架中提取数据的 1 个快速技巧

原文:https://towardsdatascience.com/a-quick-tip-for-pulling-data-from-a-pandas-dataframe-using-sql-queries-bbe3b39d17d?source=collection_archive---------2-----------------------

Photo by Bruce Hong on Unsplash

想获得灵感?快来加入我的 超级行情快讯 。😎

熊猫图书馆对于任何使用 Python 分析数据的人来说都是非常棒的。

它非常容易使用,正确应用时速度很快,并且功能灵活。有了 Pandas,许多通常需要更多工作的功能,例如检索一些关于数据的基本统计数据,只需调用一个函数就可以完成!

尽管如此,有时我们更喜欢使用一种工具而不是另一种。如果你习惯于在 Excel、Tableau 或 SQL 上浏览数据,那么切换到 Pandas 仍然是一个跳跃。

如果你有 SQL 的背景,有一个很棒的 Python 库可以帮助你平稳过渡: Pandasql

Pandasql 允许您编写 sql 查询来查询 pandas 数据框架中的数据。这允许您避开在熊猫中必须学习大量 Python 的正常要求。相反,您可以简单地在函数调用中编写常规的 SQL 查询,并在 Pandas dataframe 上运行它来检索您的数据!

用 Pandasql 查询熊猫数据帧

安装

我们可以通过一个快速的 pip 来安装 Pandasql:

pip install pandasql

加载数据

让我们从实际的数据集开始。我们将使用seaborn库加载 iris flowers 数据集:

*import* pandasql
*import* seaborn *as* sns

data = sns.load_dataset('iris')

选择

通常,如果我们想检索数据帧中的前 20 项,我们会对熊猫做这样的事情:

data.head(20)

有了 pandasql,我们可以像在 sql 数据库上运行标准 SQL 查询一样写出它。只需将 pandas 数据帧的名称作为您正在解析的表的名称,数据将被检索:

sub_data = pandasql.sqldf("SELECT * FROM data LIMIT 20;", globals())
print(sub_data)

我们可以用 SQL 中的 WHERE 进行的常规过滤操作也是适用的。让我们首先使用 pandas 提取所有大于 5 的数据:

sub_data = data[data["petal_length"] > 5.0]

为了在 SQL 中实现这一点,某些行只需添加 WHERE 调用来实现相同的过滤:

sub_data = pandasql.sqldf("SELECT * FROM data WHERE petal_length > 5.0;", globals())

当然,我们也可以总是只选择我们想要的列:

sub_data = pandasql.sqldf("SELECT petal_width, petal_length FROM data WHERE petal_length > 5.0;", globals())

这就是如何使用 SQL 查询从 pandas 数据帧中检索数据。

喜欢学习?

在 twitter 上关注我,我会在这里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn上与我联系

全球旅行碳排放的研发评估

原文:https://towardsdatascience.com/a-r-api-d-assessment-of-travel-carbon-emissions-around-the-world-e1a2b8508827?source=collection_archive---------37-----------------------

作为一个关注气候的消费者,我经常想知道我从东海岸到盐湖城的日常旅行对环境的影响。在看到最近许多强调航空旅行令人惊讶的高碳排放率的头条新闻之一后,我想知道:乘坐火车、公共汽车或驾驶汽车是否比乘坐飞机更有利于地球?

谢天谢地,我偶然发现了一个由伦敦程序员 Tobe-Nicol 开发的易于使用的 API,它允许你比较各种旅行方式的碳足迹。为了地球,我准备把价格、舒适和方便放在一边,我从这个 API 中取出来比较我的选择,并提出了一系列关于沿途旅行的能源强度的问题。

什么是 API 参数?

我在 Twitter 上发现了这个 API,并且能够在 Jupyter 笔记本上做一些快速的实验,这要感谢简单明了的文档。该 API 具有以下参数:

  • 活动(必需):这可以是车辆的燃料消耗,也可以是以英里为单位的行驶距离。因为我们在比较不同的交通方式,所以我将这个参数设置为“3,910”——从纽约到盐湖城的往返行程长度,以英里为单位。
  • activityType:该参数表示上面输入的整数值。
  • 方式:指运输方式。有几个选项可供选择:柴油汽车、汽油汽车、任何汽车、出租车、经济舱、商务舱、头等舱、任何航班、摩托车、公共汽车和轻轨。
  • 燃料类型:这与上面列出的模式配对:车用汽油(也称为汽油)、柴油、航空汽油和喷气燃料。

我假设所有商业航班都使用喷气燃料,但将参数“anyFlight”与航空汽油配对,以查看这两种燃料类型之间的碳足迹是否有重大差异。我还将“柴油汽车”、“公共汽车”和“轻轨”归入柴油燃料;我假设所有其他模式使用汽油。

我首先将这些参数放入两个长度相等的列表中,将每种运输方式与每种燃料类型关联起来。我还从列表中删除了“anyCar”,因为它与“taxi”和“petrolCar”重叠,似乎是多余的。以下是列表:

list_of_modes = ['dieselCar', 'petrolCar', 'taxi', 'motorbike', 'bus', 'transitRail', 'economyFlight', 'businessFlight', 'firstclassFlight', 'anyFlight' ] 

list_of_fuels = ['diesel', 'motorGasoline', 'motorGasoline', 'motorGasoline', 'diesel', 'diesel', 'jetFuel', 'jetFuel','jetFuel', 'aviationGasoline']

我没有手动将每个参数输入到系统中,而是编写了一个函数来遍历这两个列表,并将 API 请求输出为一个字典。在导入了必要的包之后,我定义了函数,插入了列表并将输出打包成一个字典(完整的代码,请参见这篇博文所附的 jupyter 笔记本)。

#import necessary packages 
import requests
import json
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline #use carbon_slc_nyc function to create dictionary with mode of #transportation as keys and of carbon footprint as valuescarbon_footprint = {}
carbon_footprint = carbon_slc_nyc(list_of_modes, list_of_fuels)

将输出打包成字典后,我将它转换成熊猫数据框架,将列重命名为更合适的标题,并将“碳足迹”列数据转换成浮动数据,为绘图做准备。

df = pd.DataFrame(list(carbon_footprint_ground.items()))
df.rename(columns = {0 :'Type of Transport'}, inplace = True)
df.rename(columns = {1 :'Carbon_Footprint'}, inplace = True)
df['Carbon_Footprint'] = df['Carbon_Footprint'].astype('float64')

有了这个数据框架,我绘制了一个条形图来显示每种交通方式在 3910 英里的旅程中排放了多少碳。

plt.figure(figsize=(10,5))
sns.barplot(x=df_ground['Type of Transport'], y=df_ground['Carbon_Footprint'])
plt.xticks(rotation=45)

有意思。如果我要选择一种平均油耗的交通方式,坐公共汽车、火车或经济舱是我的最佳选择。然而,结果产生了许多问题。这个数据满足了一个合乎逻辑的解释,即驾驶自己的汽车不如共乘一辆车和将一辆车的总排放量分散给许多人,如在飞机、公共汽车或火车上。但是为什么一张头等舱机票比经济舱机票差那么多呢?为什么你的普通巴士在这次旅行中的碳足迹是最低的?除了电动或液化天然气燃料的城市公交车,我不认为柴油燃料的灰狗巴士或协和蔻驰巴士是非常环保的。

我认为这种分布是美国独有的,并使用了另一个参数来比较各国之间交通运输方式的平均碳足迹。API 要求输入“usa”、“gbr”和“def”来比较美国、英国和全球平均水平之间的足迹。虽然这个新参数只允许我与其他两个选项进行比较,但我想看看在美国以外行驶 3910 英里是否会改变巴士的气候优势。

世界平均水平与美国大致相同,但在英国,公共汽车污染严重得多。所有的航空旅行都差不多,这表明这个排放计算器在全球范围内标准化了排放,考虑到该行业的国际性质,这是有意义的。在英国,乘坐火车或经济舱是我的最佳选择。

如何计算排放量?

查看了这些结果后,我进一步查看了文档,以了解排放量是如何计算的。有两种方法。对于上面的代码,API 使用给定国家车辆的平均排放系数,并根据行驶距离参数调整结果。然而,API 也提供了一个更具体的计算方法,使用车辆的燃油效率。在这种方法中,API 将燃油消耗总量乘以该燃油的排放系数。排放系数通常由政府机构提供,由 IPCC 推荐。

Total Emissions = Fuel Emission Factor * Fuel Usage

为了更准确地评估我的旅行选择,我需要知道每种交通方式的引擎消耗了多少能量。我从第一次描述性分析中挑选了三个最佳选项,并将结果限制在美国。在接下来的 API 调用中,我加入了我妈妈的 Suburu 的燃油效率(每加仑汽油 33 英里),一辆典型的灰狗巴士(每加仑柴油 6 英里),以及一架空客 A220 100 的每加仑喷气燃料英里数。

空客的油耗颇具挑战性,因为官方的维基百科燃油经济性数据要么以千克/公里列出,要么以每座加仑英里数列出,这意味着我要么必须将千克/公里数转换为每加仑英里数,要么将每座加仑英里数乘以空客 A220 100 的座位数(我假设我会飞完全程——SLC 和纽约是受欢迎的目的地)。我不确定 API 的碳计算器是否会自动将燃料消耗参数转换为公共交通的每座加仑英里数,所以我双向调用数据,输入每加仑英里数和每座加仑英里数,以免重复计算。不管怎样,这形成了一个有趣的对比。

通过快速的谷歌搜索,我发现空客 A220s 可以有 120 到 160 个座位。我选了 140 个座位。

#miles per seat gallon divided by seats on the plane 
A220_mpg_A = (85.6 / 140) 
suburu_mpg_A = 33 
greyhound_mpg_A = 6A220_gal_A = 3910/A220_mpg_A
suburu_gal_A = 3910/suburu_mpg_A
greyhound_gal_A = 3910/greyhound_mpg_Alist_gallons_A = [suburu_gal_A, greyhound_gal_A, A220_gal_A]
list_fuel_type_A = ['motorGasoline', 'diesel', 'jetFuel']#call API and create dataframe 
carbon_footprint_A = {}
carbon_footprint_A = carbon_fuel(list_gallons_A, list_fuel_type_A) 
df_A = pd.DataFrame(list(carbon_footprint_A.items()))
df_A.rename(columns = {0 :'Fuel_Type'}, inplace = True)
df_A.rename(columns = {1 :'Carbon_Footprint'}, inplace = True)
df_A['Carbon_Footprint'] = df_A['Carbon_Footprint'].astype('float64')#now adjust to miles per seat gallon
A220_mpg_B = 85.6 
suburu_mpg_B = 33 
#adjusting to miles per seat gallon with 55 seats
greyhound_mpg_B = 6 * 55 A220_gal_B = 3910/A220_mpg_B
suburu_gal_B = 3910/suburu_mpg_B
greyhound_gal_B = 3910/greyhound_mpg_Blist_gallons_B = [suburu_gal_B, greyhound_gal_B, A220_gal_B]
list_fuel_type_B = ['motorGasoline', 'diesel', 'jetFuel']#call API and create dataframe
carbon_footprint_B = {}
carbon_footprint_B = carbon_fuel(list_gallons_B, list_fuel_type_B)
df_B = pd.DataFrame(list(carbon_footprint_B.items()))
df_B.rename(columns = {0 :'Fuel_Type'}, inplace = True)
df_B.rename(columns = {1 :'Carbon_Footprint'}, inplace = True)
df_B['Carbon_Footprint'] = df_B['Carbon_Footprint'].astype('float64')

结果如下:

在绘制了第一次 API 调用的结果后,很明显,驾驶我自己的飞机从纽约到盐湖城并返回会产生很大的环境影响,就像驾驶我自己的灰狗巴士一样。一个人开我妈妈的 Suburu 显然更有效率,因为它小得多。

然而,当在载满乘客的飞机或公共汽车上传播高 MPG 和碳排放时,很明显,公共汽车的碳足迹最低。尽管飞机的载客量是公共汽车的两倍多,从纽约到 SLC 的速度也比任何公路旅行都快,但公共汽车的优势在于使用污染更低、能源密度更低的燃料,同时仍将气候成本分摊到 55 个人身上。我妈妈的 Suburu 虽然拥有汽油驱动汽车市场上最高效的发动机之一,但无法与之相比——即使我搭载了两个搭便车的人(我算过)。

结论

如果限制个人的碳排放是你的首要任务,那就不要开车。尽管在全国范围内移动一辆公共汽车或商业客机需要更多的能源(和更多的碳),但当你选择乘火车、公共汽车或飞机旅行时,你会将气候成本分摊给更多的人。这种分析可以通过更多的细微差别和粒度数据集来改进,但很明显,在高层次上,激励更多的人乘坐大型车辆从 A 地到 B 地应该在制定脱碳战略中发挥作用。

Github 链接:【https://github.com/kbaranko/SLC-to-NYC-Carbon-Costs

具有改进的协同过滤的闪亮产品推荐器

原文:https://towardsdatascience.com/a-r-shiny-application-with-improved-collaborative-filtering-48a82955da6a?source=collection_archive---------10-----------------------

我对购物篮分析的看法——第 3 部分,共 3 部分

Photo by NeONBRAND on Unsplash

概观

最近我想学习一些新的东西,并挑战自己进行端到端的市场篮子分析。为了继续挑战自己,我决定将我的努力成果展示给数据科学界。

这是的第三个也是最后一个帖子:

Part 1 :(可在此处找到)探索并清理适合用推荐算法建模的数据集* Part 2:(可在此处找到)应用各种产品推荐模型***

介绍

在我为这个项目进行研究的过程中,我遇到了几件作品,所有这些都为我闪亮的应用程序提供了巨大的灵感和洞察力。特别要提到的是 Jekaterina Novikova,她的 电影推荐系统 的博士,以及迈克尔·哈斯勒教授,他创造了一个 笑话推荐系统 。他们分别使用了MovieLensJester数据集,这是推荐者实验室的默认设置。

然而,两位作者都使用了 recommenderlab 作为他们闪亮应用的引擎,众所周知,这需要很长时间来计算大型数据集的预测。Jekaterina 为使计算更易于管理而采用的解决方案是对数据集进行采样,以减小评级矩阵的大小。然而,这可能证明对预测准确性有害。

幸运的是,我遇到了由 Philipp Spachtholz 开发的这个出色的 Kaggle 内核 ,他不仅对一个非 Kaggle 数据集进行了显著的分析,而且对我来说至关重要的是,他还使用一个快得多的协作过滤代码构建了一个基于 Shiny 的 图书推荐系统

Philipp 从这篇由smart cat Consulting撰写的博客文章中获得了灵感,这篇文章描述了如何使用改进的协同过滤代码以及包含在配套 Github 库中的所有相关功能。特别地,存储库包括用于计算相似性矩阵的simililarity_measures.R函数,以及具有协同过滤算法和预测函数的cf_algorithm.R文件。

在这个项目的最后一部分,我将描述如何在我闪亮的实现中使用这些函数。

加载包

**library(tidyverse)            
library(knitr)
library(Matrix)
library(recommenderlab)**

数据

在这一节中,我使用第二部分中的retail数据集来准备闪亮应用程序所需的数据文件。请注意,在第 2 部分的中,我执行了额外的格式化步骤,删除了多次包含相同商品的订单。****

****glimpse(retail)
## Observations: 517,354
## Variables: 10
## $ InvoiceNo   <dbl> 536365, 536365, 536365, 536365, 536365,
## $ StockCode   <chr> "85123A", "71053", "84406B", "84029G",
## $ Description <fct> WHITE HANGING HEART T-LIGHT HOLDER, 
## $ Quantity    <dbl> 6, 6, 8, 6, 6, 2, 6, 6, 6, 32, 6, 6, 8, 6,
## $ InvoiceDate <dttm> 2010-12-01 08:26:00, 2010-12-01 08:26:00,
## $ UnitPrice   <dbl> 2.55, 3.39, 2.75, 3.39, 3.39, 7.65, 4.25,
## $ CustomerID  <dbl> 17850, 17850, 17850, 17850, 17850, 17850,
## $ Country     <fct> United Kingdom, United Kingdom, Un...
## $ Date        <date> 2010-12-01, 2010-12-01, 2010-12-01,
## $ Time        <fct> 08:26:00, 08:26:00, 08:26:00, 08:26:00,****

对于应用程序部署,我需要创建 2 个数据文件:past_orders_matrixitem_list

past_orders_matrix是包含过去订单历史的用户项目稀疏矩阵。所有计算都需要这个闪亮的server.R文件。

****past_orders_matrix <- retail %>%
    # Select only needed variables
    select(InvoiceNo, Description) %>%     # Add a column of 1s
    mutate(value = 1) %>% # Spread into user-item format
    spread(Description, value, fill = 0) %>%
    select(-InvoiceNo) %>%    # Convert to matrix
    as.matrix() %>%

    # Convert to class "dgCMatrix"
    as("dgCMatrix")****

我保存文件,以便在应用程序中使用。

****saveRDS(past_orders_matrix, file = "past_orders_matrix.rds")****

item_list列出了所有可供购买的产品。这将输入闪亮的ui.R文件,使产品列表可供选择。

****# Creating a unique items list
item_list <- retail  %>% 
    select(Description) %>% 
    unique()****

我保存列表,以便在应用程序中使用。

****saveRDS(item_list, file = "item_list.rds")****

改进的协同过滤

为了展示Improved Collaborative Filtering是如何工作的,我将在 第 2 部分item-based CF中找到的表现最好的模型装配在同一个定制订单上。我也在做同样的事情,用recommenderlab来比较这两种方法的性能。

首先,我使用同样的 6 个随机选择的产品重新创建了定制订单。

****customer_order <- c("GREEN REGENCY TEACUP AND SAUCER",
                     "SET OF 3 BUTTERFLY COOKIE CUTTERS",
                     "JAM MAKING SET WITH JARS",
                     "SET OF TEA COFFEE SUGAR TINS PANTRY",
                     "SET OF 4 PANTRY JELLY MOULDS")****

接下来,我将把new_order放入一个 user_item 矩阵格式中。

****# put in a matrix format
    new_order <- item_list %>% # Add a 'value' column with 1's for customer order items
    mutate(value = 
               as.numeric(Description %in% customer_order)) %>% # Spread into sparse matrix format
    spread(key = Description, value = value) %>% # Change to a matrix
    as.matrix() %>%    # Convert to class "dgCMatrix"
    as("dgCMatrix")****

然后,我将new_order添加到past_orders_matrix作为它的第一个条目。

****# binding 2 matrices
   all_orders_dgc <- t(rbind(new_order,past_orders_matrix))****

现在,我需要设置一些改进的 CF 工作所需的参数。

****# Set range of items to calculate predictions for
   items_to_predict <- 1:nrow(all_orders_dgc)  # I select them all# Set current user to 1, which corresponds to new_order
   users <- c(1)# Set prediction indices
   prediction_indices <- as.matrix(expand.grid(items_to_predict, 
                                                   users = users))****

我加载算法实现和相似性计算。

****# Load algorithm implementations and similarity calculations
source("cf_algorithm.R")
source("similarity_measures.R")****

最后,我可以用Improved CF来拟合item-based CF模型,并检查运行时间。

****start <- Sys.time()
recomm <- predict_cf(all_orders_dgc, 
                       prediction_indices,
                       "ibcf", FALSE, cal_cos, 3, 
                       FALSE, 4000, 2000)
end <- Sys.time()
cat('runtime', end - start) ## runtime 0.630003****

哇!真是快如闪电!

现在让我们用recommenderlab运行item-based CF模型并比较性能。

****# Convert `all_orders` to class "binaryRatingMatrix"
    all_orders_brm <- as(all_orders_dgc, "binaryRatingMatrix")# Run run IBCF model on recommenderlab
start <- Sys.time()
recomm <- Recommender(all_orders_brm, 
                      method = "IBCF",  
                      param = list(k = 5))
end <- Sys.time()
cat('runtime', end - start)## runtime 12.75939****

速度增加了大约 20 倍,这与菲利普·斯帕茨在他的工作中所看到的一致。这对闪亮的应用程序来说是相当有前途的!

部署应用程序

对于应用程序的部署,我采用了 概念验证 的方法。我的重点是执行速度,以及如何正确完成本文中显示的所有计算,从而为应用程序的server端提供动力。这反映在目前的极简用户界面上,它仅仅以产品选择和完成购买操作按钮为特色。**

这里有一个 产品推荐者 的链接供你细读。

我将继续在用户界面上工作,增加改善客户体验的功能,使它更像一个最终产品。

以下是我目前正在考虑的一些想法:

  1. 添加产品价格和选择产品数量的能力
  2. 添加产品图片 —有 4000 种商品可供选择,这本身就是一个迷你项目!
  3. 能够使用产品名称的第一个字母从列表中选择项目
  4. 使用shinyJS和/或HTML tags增强用户界面的视觉效果
  5. 考虑到目前并非所有产品组合都返回建议,研究如何实施混合方法

评论

我真的很喜欢这个市场篮分析项目。推荐系统是一个迷人的研究领域,有着真实世界的应用,我觉得我只是触及了这个主题的表面。

我也非常感谢学习闪亮应用程序开发的诀窍,这比我最初想的要简单得多:反应性是一个让你头脑清醒的关键概念,它迫使你从用户界面和服务器是一个硬币的两面的角度来思考。

对我来说,主要的考虑是潜力是巨大的:即使是在线的小公司也能从实施最基本的推荐系统中受益。只需几行代码,就可以改善客户体验,提高客户忠诚度,促进销售。

代码库

完整的 R 代码可以在我的 GitHub 简介上找到

参考

原载于 2019 年 4 月 15 日https://diegousei . io

使用 Twitter 数据和 Gephi 对特朗普弹劾前后的政治极化进行可视化评估

原文:https://towardsdatascience.com/a-radiography-of-trumps-impeachment-86284710ae1d?source=collection_archive---------24-----------------------

The conversation on Twitter around Trump’s impeachment on December 18th

围绕导致美国历史上第三次总统弹劾的事件,美国在网上是如何互动的?

美国是两极化的,这是事实。但是这种两极分化会是什么样子呢?没有比 Twitter 这个全球数字对话的圣地更好的地方来回答这个问题了,所以我从 12 月 18 日周四开始下载了 50 万条推文,那天众议院举行了弹劾唐纳德·j·特朗普的最终投票。结果既美好又令人生畏。

Pic by History HD on Unsplash

先看方法论。正如我提到的,我使用 Twitter 公共 API 连接到 Twitter 服务器,并获取所有包含通用关键字的推文,如“特朗普”或“弹劾”。不过,这个过程很漫长,我那台含咖啡因的MacBook 花了几天时间才达到 50 万条推文的大关(不用说,在那段时间里,用电脑几乎不可能完成任何事情)。当然,还有其他方法,比如实时传输推文,这更容易,计算成本也更低,但我无法在那个周五下午回到过去,因为太晚了,无法实时捕捉推文。

为了连接到 Twitter API,你需要创建一个开发者档案并申请一个许可。这个过程并不长,如果你做得对,你将很快拥有自己的驾照。

有了推文之后,是时候做一些网络理论了。想想看:如果参与对话的每个帐户都被表示为空间中的一个点(比如说一个节点),如果每次他们中的任何一个通过回复、转发或引用与另一个进行交互时,我们都在他们之间画一条线,那么我们最终会用我们称之为的东西将一堆节点链接在一起。因此,我们可以将 12 月 18 日发生的对话表示为一个社交网络,更好的是,我们可以用图表来直观地评估正在发生的事情。

An example of a network graph - Taken form the Gephi Blog on Wordpress.

我的绘图工具是 Gephi ,一个开源的网络绘图软件(关于它有大量的在线教程)。您需要传递给 Gephi 的只是一个简单的 csv 文件,它有两列:生成交互的帐户(“源”列)和接收所述交互的帐户(“目标”列)。在那之后,你可以自由地摆弄你的网络,并以你喜欢的任何方式来表现它。我是这样做的:

  1. 选择 ForceAtlas2 布局。
  2. 计算模块化得分。
  3. 设置节点标签,其大小与每个节点的入度成比例。

技术插曲

让我们一步一步地重温一下:

第一,布局。有几种算法可以计算网络中的各种基本方面,例如,某些节点的中心位置如何,它们之间应该相距多远或多近,在网络中可以找到哪些节点群,边的长度或弹性如何,等等。对于当前的绘图任务,我选择了 ForceAtlas2 ,顾名思义,它是 ForceAtlas 的续集,更适合更大的网络。本质上,该算法采用了几个物理定律来达到力之间的稳定平衡或平衡状态:它模拟节点之间的排斥,就好像它们是带电粒子一样(遵循库仑定律,同时使边缘吸引它们的节点,就像弹簧一样(遵循胡克定律)。

第二,模块化。这是一种通过给出一个分数来检测网络中的社区的方法,该分数决定了网络分成模块的强度。高度模块化意味着网络在社区或模块中具有密集连接的节点,而与其他社区或模块中的其他节点的链接相当松散或稀疏。

最后,标签。至关重要的是,我们知道哪些社交网络代理在给定时间是最相关的,因此我们可以简单地在图上包括他们的标签(例如,他们的 Twitter 处理程序)。但是,想象一下,一个有几十万个标签的图表:它看起来会很混乱,无法辨认。要解决这个问题,我们可以简单地要求 Gephi 计算每个节点的平均加权度。

什么现在?节点的度是与它交互的边的总和:例如,在我们的例子中,转发了一个帐户获得的消息或转发了一个帐户发出的消息。鉴于我们的图形本质上是有向的,我们非常关心每个动作的方向。换句话说,我们最关心的是哪个账号转发得最多(入度)或者哪个账号转发得最多(出度)。所述度的权重简单地与节点的边的重要性或质量相关。例如,当两个特定节点之间存在重复交互时,该边将具有较高的权重,因此在给定这种权重的情况下将考虑其程度。当你有了度数,你可以让 Gephi 相对于它们的度数来标记节点,这样网络中最相关的节点将是最可见的。

我们选择了加权入度来展示图表中每个节点的重要性:我们希望通过谁被转发、回复或引用最多来了解谁对对话的影响最大。

La pie ce de resistance,我们的图表。

毫不奇怪,有两个定义明确的主要模块或社区,它们对应于政治辩论的两极,民主党人(用蓝色表示)和共和党人(用红色表示)。

The Democratic community.

民主社区在对话中展示了大约十个重要人物。他们从政治家到作家到新闻主播(佩洛西当然也在其中)。在社区的右侧可以看到 ABC。民主团体代表了图表中超过 50%的节点。

The bridge between the two communities.

对话中两个明显的政治极端之间的桥梁展示了一个有趣的关键节点:C-SPAN。

American rapper YG has his own alt-module.

美国说唱歌手 YG 有自己孤立的另类社区,是除了两个主要社区之外唯一值得一提的代表,拥有图表中超过 6%的节点。这主要是由他的明确声明引起的:

Source: https://twitter.com/YG/status/1207349489255628800

@evadutizena catching some lights with a meme.

一项荣誉要归功于@evadutizena,她通过一个迷因,整合了网络中几乎 2.5%的节点。恭喜你,德洛丽丝!

Source: https://twitter.com/evadutizena/status/1207436447898320897

最后,社交网络图中的共和党社区,有超过 30%的节点。

The Republican community.

在这里,只有大约八个帐户似乎抓住了眼球。与民主党社区不同,共和党本身有一些明确的活动和影响力,还有其他政治家、节目主持人、喜剧演员和作家,以及总统的儿子本人。说到这,你能找到川普吗?

现在是时候看看整个数字对话的画像了,这是对当今美国政治的准确描述,也是 2020 年美国政治格局的基石。尽情享受吧!

Portrait of the polarization of the American political debate around Trump’s impeachment. All rights reserved.

乐章结尾部

我觉得这张图讲述了一系列的故事,所有的故事都同样相关,特别是在 2020 年和总统大选之际:

  1. 虽然两极分化很明显,但是两极分化本身早就有了。这不是什么新鲜事,但在过去的几十年里,它一直在增长。
  2. 共和党社区仅拥有对话图中 30%多一点的节点,这一事实不足以说明今天美国共和党人占总人口的比例是 30%。因为我们只处理 Twitter 数据,所以存在很大的选择偏差,这不允许我们对美国的一般人口做出统计上无偏见的推断。
  3. 民主党社区包含了网络中超过 50%的节点,这表明,在 12 月 18 日,更多倾向于民主党的行动者支持弹劾程序,或者至少,他们在 Twitter 上的数字对话中更加直言不讳。
  4. 在数字辩论中仍然有替代叙事的空间,尽管与两个主要叙事相比很小,但它代表了政治观众/光谱的第三部分。
  5. 没有办法根据这个图表来预测结果,我们还得等着看参议院会发生什么。然而,2020 年的选举可能会完美地向两个方向发展,民主党被众多强大但不同的候选人分裂,或者一个规模稍小但更加团结的共和党(如图所示)连任,这是美国历史上第一次被弹劾的总统。

别忘了留下评论,祝大家新年快乐!

在推特上关注我!

一位放射科医生对斯坦福 ML 集团 MRNet 数据的探索

原文:https://towardsdatascience.com/a-radiologists-exploration-of-the-stanford-ml-group-s-mrnet-data-8e2374e11bfb?source=collection_archive---------16-----------------------

医学影像领域知识的数据探索

这篇文章回顾了最近发布的斯坦福 MRNet 膝关节 MRI 数据集和竞赛。由于我是一名高级放射科住院医师,我将专注于通过基础领域知识探索数据,解决非医生可能会感到困惑的数据分布方面的问题。我还将包含一些 Python 代码,感兴趣的人可能会发现这些代码对自己探索数据集很有用。

介绍

斯坦福 ML 小组最近发布了他们的第三个医学影像检查公共数据集,称为 MRNet,可以在这里找到。从网站:

MRNet 数据集由斯坦福大学医学中心进行的 1,370 次膝关节 MRI 检查组成。数据集包含 1104 个(80.6%)异常检查,其中 319 个(23.3%)为前交叉韧带撕裂,508 个(37.1%)为半月板撕裂;标签是通过从临床报告中手工提取获得的。

这个数据集伴随着斯坦福 ML 小组工作的发表,可以在这里找到。他们再次举办了一场比赛,以推动医学成像自动化分析的创新。

参赛作品将在私人测试数据集上进行评估,评估标准如下:

排行榜报告了异常检测、ACL 撕裂和半月板撕裂任务的平均 AUC。

你可以在网站上找到更多关于比赛的细节。我这篇文章的目标如下。

目标

  • 基本医学成像术语
  • 竞赛的数据集和任务概述
  • 基础膝关节解剖学
  • 目标膝盖病变的例子
  • 潜在“坏”数据点的示例
  • 用于检查数据的 Python 代码

基本医学成像术语

磁共振成像(MRI)是一种横截面成像模式,这意味着 2D 图像或多或少是在不同的成像平面中连续采集的。MRNet 数据集中包含的标准成像平面有:轴位、冠状位和矢状位。MR 图像可以在任何平面上获得,但这超出了本文的范围。

MR 图像通过射频(RF)脉冲序列(脉冲序列或——简单地说——序列)采集。不同的序列被设计成产生一个信号,该信号可以被采集和处理以揭示生物组织中不同的信号强度模式。T1 加权、T2 加权和质子密度(PD)加权是肌肉骨骼成像中使用的 3 种核心脉冲序列类型。

了解这 3 个序列的脂肪、水和肌肉的基本信号强度模式是很有帮助的(下面的)。还有一个有用的知识是皮质骨和纤维结构(如韧带、半月板)在所有序列上都应该是黑色的。由于脂肪和水在 T2 和 PD 序列上都是中等亮度,因此脂肪饱和度 (fat-sat)是一种可用于增强水在这些序列上的外观的技术。

异常液体信号(无论是数量还是位置)通常是肌肉骨骼病理(或任何病理,就此而言)的关键指标,因此液体敏感图像确实是膝关节 MRI 的主力。

Source: https://www.fifamedicinediploma.com/lessons/radiology-mri/

附加术语:

  • 切片 : 一个单独的图像通常被称为切片
  • 系列:在给定的平面上,用给定的脉冲序列采集的一整叠图像
  • 视场(FOV) :图像的空间覆盖范围

竞赛的数据集和任务概述

警告:我还没有审查所有提供的数据。这些评论是基于对数据的有限的初步审查。

同样,数据可以通过上面的链接获得。你必须先在斯坦福 ML 集团注册一个账户,然后你会收到一封链接到数据的电子邮件。共享数据是被明确禁止的,即使是和比赛中的队友。

下载并解压缩数据后,您应该会看到这个目录树:

.
├── train
│ ├── axial
│ ├── coronal
│ └── sagittal
├── train-abnormal.csv
├── train-acl.csv
├── train-meniscus.csv
├── valid
│ ├── axial
│ ├── coronal
│ └── sagittal
├── valid-abnormal.csv
├── valid-acl.csv
└── valid-meniscus.csv

*.csv文件包含箱子的标签。trainvalid子目录下的*.npy文件是维度为(slices, x, y)的 NumPy 数组。在所有检查中,xy尺寸始终为 256 x 256,且int值范围为 0 至 255。这意味着像素数据已经被斯坦福 ML 小组标准化了。

注意:每个检查的图像堆栈可以包含不同数量的图像,并且每个检查对于任何给定的平面可以具有不同数量的切片。这对于医学影像数据来说是完全正常的。

为了不与竞赛规则相冲突,我将避免在标签中张贴重叠的汇总数据表。但是,有必要注意以下几点:

1.有许多不正常的检查不包含前交叉韧带或半月板撕裂。

2.包含前交叉韧带撕裂和半月板撕裂的检查远远多于仅包含前交叉韧带撕裂的情况。

这些发现表明,数据集对于现实世界中会遇到的情况可能是相当现实的。

其原因如下:

  • 膝关节核磁共振成像通常不用于无症状患者。
  • 膝关节核磁共振检查中最常见的异常是在软骨和下面的骨头中。
  • 由于损伤机制和撕裂 ACL 所需的力,半月板也经常受伤。

图像数据的预览

尽管该网站声明数据集中的 MRI 膝关节检查的标准协议包括各种序列,但我迄今为止查看的数据包含每个病例的三个序列:

  • 冠状 T1 加权图像脂肪饱和

  • 矢状 T2 加权图像和脂肪饱和(流体敏感)

  • 轴向 PD 加权图像和脂肪饱和(流体敏感)

基础膝关节解剖学

我将在这里包括一个图像的膝盖解剖的基本概述。对于那些有兴趣了解更多关于膝关节在核磁共振成像上的外观的人来说,这个网站(下图的来源)可能会有所帮助。

Source: http://www.freitasrad.net/pages/atlas/Knee/Knee.html

目标膝盖病变的例子

  1. 半月板撕裂:下图矢状 T2 fat-sat 图像显示正常的内侧半月板前角(绿色箭头 —图像左侧的黑色三角形)和内侧半月板后角撕裂(红色箭头 —图像右侧的黑色三角形内的小点亮信号)。注意:这张图片上还有几处其他异常,但这些不在本文讨论范围之内。

Sagittal T2-weighted image with fat saturation

2.前十字韧带撕裂:

首先,我将展示一个正常前交叉韧带的矢状 T2 脂肪卫星图像。注:图像中前交叉韧带正上方信号增强的波纹代表腘血管的搏动伪影。

Normal ACL

现在,前交叉韧带撕裂。在下图中,红色箭头指向一个信号强度相对较高的长方形结构,纤维韧带的正常暗带(见上图)缺失。

Torn ACL

潜在“坏”数据点的示例

同样,在撰写本文时,我还没有完整地研究这些数据。然而,我观察到一些潜在的“坏”数据点,增加了这场竞争的挑战。我说潜在不好,因为其中一些可能会被深度学习模型处理得相当好。在这里,我展示了几个例子,并简要解释了为什么这些代表了麻烦的数据点。

我观察到的一个问题是矢状图像堆栈,其中膝盖的大部分在 FOV 之外,导致图像堆栈对于比赛任务基本上无用,因为相关的解剖结构都不可见。这可能是由于 MRNet 数据集中的治疗图像预处理中的错误,或者是由于源数据的问题。到目前为止,这是一个很少遇到的问题。

潜在“坏”数据的另一个原因对于医学成像来说相当典型。在一些情况下,我看到图像伪影严重到使人阅读图像非常困难。然而,深度学习算法可能会“通读”工件,就像我们放射科医生为了病人护理的利益而试图做的那样。这里,腘动脉的搏动导致在膝关节水平的整个图像中出现混叠伪影。

Extensive pulsation artifact can make images hard to read/analyze

用于查看数据的 Python 代码

下面的代码将把一个案例中的数据加载到 NumPy 数组的dict中,然后由KneePlot类使用它来生成下面的*.gif中显示的交互式绘图。

结论

我希望这篇文章能让你对 MRNet 数据集有所了解。也许更重要的是,我希望你已经了解了一点关于膝盖核磁共振成像的知识。虽然我还没有探索它的全部,但我认为这个数据集对 ML 社区来说是一个有价值的资源。我期待着阅读通过比赛开发的模型。感谢您的阅读!

轮盘赌桌上的随机会议——有熊猫和牛郎星

原文:https://towardsdatascience.com/a-random-session-at-the-roulette-table-with-pandas-and-altair-9a147471dac3?source=collection_archive---------13-----------------------

最近我去了一家赌场玩,我很好奇,想知道我赢的几率有多大,在给定预算、标准下注金额和下注策略的情况下,我会在赌场呆多久。

所以我决定快速编写一些代码来可视化轮盘赌桌上的随机会话。我在这里编写代码的方式与我在轮盘赌桌上进行游戏的方式完全一样:遵循一个下注策略,在固定的旋转次数下相同的赌注(或者直到我的预算资金用完)。

首先,我们从导入所有必需的库开始:

**# Import libraries**import random
import pandas as pd
import altair as alt
from vega_datasets import data

这里我们导入了随机包,我们需要它来模拟轮盘赌桌上的随机旋转,pandas 包将我们的结果输出到可读的数据帧中,Altair 包用于快速可视化我们的结果。

接下来,我们初始化我们的全局变量:我为这个环节预算的资金数量,每次旋转的赌注数量,以及轮盘赌的旋转次数。

我为这些变量分别设置了 1000、200 和 24。在这里指定这些变量的好处是,你可以很容易地在这里修改它们(而不是在我们后面要写的函数中)。

**# Initialise all the global variables**funds = 1000
bet_amount = 200
num_spins = 24

接下来,我们将轮盘游戏会话定义为一个函数。这个函数写得有些复杂,包括下注策略支出。不可否认,这不是编写轮盘游戏函数的最佳方式(更好的方式是遵循面向对象的编程,将不同的下注策略作为轮盘游戏的独立对象),但是让我们将就一下。

**# Function for a random session at the Roulette table**def roulette_game(funds, bet, num_spin):
    print("Starting fund is RM" + str(funds), "Bet for each spin is RM" + str(bet))
    count = 0
    wins = 0
    rolls = []
    balance = []

    **# Loop for each Roulette spin**

    for each in range(num_spin):
        if funds >= bet:
            spin = random.randint(0,36)
            rolls.append(spin)

 **# Bond Roulette strategy payout**            if spin >= 19:
                funds += (0.4 * bet)
                wins +=1
            elif spin >= 13 and spin <= 18:
                funds += (0.5 * bet)
                wins += 1
            elif spin == 0:
                funds += (0.8 * bet)
                wins += 1
            else:
                funds -= bet

            balance.append(funds)
            count += 1

        else:
            break **# To stop playing when you've run out of funds**

    win_percentage = wins/count
    print("Rolled " + str(count) + " times, won " + str(wins) + " times! Win percentage is " + str("{:.2%}".format(win_percentage)) + ". Funds remaining = RM" + str(funds))
    return rolls, balance

简单介绍一下我使用的下注策略:债券轮盘策略是一种涵盖轮盘上 37 个号码中的 25 个号码(胜率为 67.5%)的策略,如下所示:

Credit for image to https://www.casinoreviews.co.uk/roulette/strategy/.

如果球落在数字 13 到 18 上,利润是下注金额的 50%,在这种情况下是 100 令吉。如果落在数字 19 到 36,利润是 40%或 80 令吉。如果落在数字 0 上,利润是 80%或 160 令吉。如果它落在数字 1 到 12 上,我们就输掉全部赌注,在这种情况下是 200 令吉。

然而,像所有轮盘赌策略一样,债券轮盘赌策略无法克服众议院优势,在这种情况下是 2.70%。其他带有附加 00 数字的轮盘赌台的牌局优势甚至更高,为 5.26%。

因此,预计随着房子的边缘,任何球员将最终耗尽他或她的资金后,一个漫长的游戏。但是大多数玩家不会在赌场停留太长时间。

在这里,我们将进行一次测试,总共包括 24 次轮盘旋转(假设每次旋转花费 5 分钟,则相当于 2 小时)。

**# Conduct a test session**test1_rolls, test1_balance = roulette_game(funds, bet_amount, num_spins)
df_test1 = pd.DataFrame({‘Roll’:np.arange(1,len(test1_rolls)+1), ‘Result’:test1_rolls, ‘Fund Balance’:test1_balance})print(df_test1)

从下面的代码输出来看,这个测试会话似乎并不好:

Not so lucky this time, lasted only 12 rolls before I ran out of funds!

这在图表上看起来怎么样?这里我使用了 Altair,这是我最近发现并喜欢的 Python 可视化工具,因为它易于使用。我只需要几行代码就可以生成如下两个不同的图表:

**# Visualise one random session at the Roulette table**alt.Chart(df_test1).mark_line().encode(
 y=’Fund Balance’,
 x=’Roll'
)

This chart shows that I got into a losing streak. Like a stock market crash.

**# Count frequency of numbers during the Roulette session**alt.Chart(df_test1).mark_bar().encode(
 x=’Result:O’,
 y=’count()’
)

It looks like I hit number 1 three times unlucky.

总之,这是一个在轮盘赌桌上可视化随机游戏过程的快速尝试。我最初很想报道游戏的蒙特卡洛模拟,但我认为在牌桌上想象一个单独的随机游戏会更有趣!

使用开源机器学习模型的方法

原文:https://towardsdatascience.com/a-recipe-for-using-open-source-machine-learning-models-within-your-company-1aed833a59b5?source=collection_archive---------20-----------------------

一步一步地寻找,评估和使用开源神经网络模型

Photo by Luca Bravo on Unsplash

机器学习继续为越来越多的任务产生最先进的(SOTA)结果,越来越多的公司正在寻找 ML 来解决他们的问题。随着机器学习研究令人难以置信的快速发展,许多这些 SOTA 模型来自开源这些模型的学术和研究机构。通常,使用这些开源模型中的一个来引导您公司内部的机器学习工作,会比从头构建一个模型更有效。

然而,这些模型通常是由研究人员发布的,他们的重点不一定是使他们的模型易于使用和修改(尽管有许多例外)。将这些开源模型用于您的任务可能会非常困难。

在这篇文章中,我的目标是提供一个方法,你可以按照这个方法来评估和使用开源 ML 模型来解决你自己的任务。这些是我在自己的工作中反复使用的步骤(在撰写本文时,我已经建立了超过 15 个开源模型的 anaconda 环境)。由于我的工作主要是将深度学习用于视觉和 NLP,因此我在这里的重点是专门使用基于神经网络的模型。

无论你是试图使用机器学习来解决公司内部的实际问题,还是在家里试验一些有趣的 SOTA 结果,我希望在这篇文章之后,你会有一条通往的道路,采用开源模型,修改并使用它来解决你自己的数据集的任务。

步骤 1:命名任务

第一步是弄清楚你的特定任务在研究文献中被称为什么,这样你就可以成功地搜索它。这最初可能会非常令人沮丧。例如,寻找图片中一只狗的所有实例将是一个“对象检测”任务。但是如果你想知道图片中哪些像素对应于狗,这就叫做“图像分割”

有几种方法可以尝试解决这个问题。首先,如果你碰巧认识任何 ML 研究者或从业者,一定要从那里开始。另一个选择是在 r/machinelearningr/learnmachinelearning 中询问。如果这些都不成功,下一步就是尽你所能去谷歌一下。当你看到研究论文时,你会经常在文献中看到与任务相关的名字。

第二步:寻找文件和代码

一旦您知道要搜索什么,下一步就是找到那些最适合您的任务的开源模型。这里有一些有用的资源:

papers with code:按任务组织的论文和相关代码的存储库。这是一个非常好的起点,尤其是如果这是一个众所周知的任务。

arxiv-sanity:很多开源模型都和研究论文有关联。机器学习大部分论文都是(幸好!)公开发表在 arxiv 上。搜索 arxiv 寻找解决您的任务的最新论文是另一个好的起点。并非所有发表的论文都有相关的代码。如果找到喜欢的论文,可以尝试搜索“<论文名称> github”看看代码是否已经发布。

Kaggle:如果恰好有一个任务与你相似的 ka ggle 比赛,这可能是一个获得高质量、最先进模型的好方法。要特别关注以往比赛的获胜者博客,这些博客通常有很好的解释和代码。用来赢得比赛的小技巧通常对你的任务也很有价值。

数据集基准:如果有一个基准数据集与您正在处理的任务相似,则该基准的排行榜是一种快速查找具有明显 SOTA 结果的论文的方法。

Google: 像图像分割这样的标准/常见任务,搜索“图像分割 github”、“图像分割 pytorch”或者“图像分割 tensorflow”会给你很多结果。

第三步:阅读报纸

这可能是令人生畏的,因为学术论文可能很难获得,即使是对有经验的软件工程师来说。但是如果你把注意力放在摘要、介绍、相关工作、结果上,把很多深层的细节/数学推迟到以后的阅读,你会发现你可以从论文中得到很多,对问题有更深的理解。

特别注意他们使用的数据集以及这些数据集或其模型的约束。通常,您会发现约束可能对您不适用,但它们是模型设计的基础。例如,imagenet 的分类模型期望在一幅图像中有且仅有一个显著对象。如果您的图像没有、有一个或多个要识别的对象,这些模型可能不直接适用。这不是你在投入时间建立模型后想知道的事情。

还有,跟着一些参考文献走,尤其是你在多篇论文里看到的!你会经常发现,至少有一篇参考文献非常清晰地描述了这个问题,极大地加深了你的理解。引用的论文也可能变得更有用,并且可能有更好的代码与之相关联,所以在这里做一点挖掘是值得的。

步骤 4:确保代码是可用的

一旦你找到了一篇有开源代码的论文,确保它是可用的。具体来说:

检查许可:虽然许多代码是在自由开源许可下发布的(麻省理工学院、BSD、Apache 等),但有些不是。你可能会发现这个模型只有非商业使用许可,或者根本没有许可。根据您的使用案例和公司,代码可能对您有用,也可能对您无用。

检查框架:如果你正在使用一个特定的框架(比如 Tensorflow,Pytorch),检查模型内置的框架。大多数情况下,您会被自己得到的东西所困扰,但是有时候,在您喜欢的框架中会有模型的重新实现。快速谷歌一下这个(例如“<论文名> pytorch”)可以帮你省去很多麻烦。

检查语言:类似地,如果模型在 Lua 中,而你不是 Lua 开发人员,这真的很痛苦。看看在你选择的语言中是否有一个重新实现(通常是 Python,因为在深度学习中 Python 应该是你的一部分),如果没有,你最好找另一个模型。

检查编码风格:研究人员并不都是软件工程师,所以你不能像其他开源项目那样有很高的门槛,但是如果代码完全是一团糟,你可能需要寻找另一种模式。

步骤 5:让模型运行起来

Results from NVIDIA’s StyleGAN trained on a custom furniture dataset

一旦你找到了一个你认为合适的模型,试着让它运行起来。这里的目标是按原样运行模型的训练和推理循环,而不是让它在您的特定数据集上运行或进行任何重大修改。您所要做的就是确保您有正确的依赖项,并且模型像宣传的那样训练和运行。为此目的:

为模型创建一个conda环境:你可能在尝试多个模型,所以为每个模型创建一个 conda 环境(假设是 Python)(NVIDIA-docker 在这里是另一个选项,但个人觉得大材小用)。

我经常这样设置我的环境:conda create -n <name of the github repo> python=<same version of python used by the repo>

判断回购使用的 python 版本的一个快速方法是查看print语句。如果没有父母,那就是 python 2.7,否则 3.6 应该可以。

安装库:强烈建议从安装与原始代码用来启动的框架完全相同的版本开始。如果模型说它能与pytorch>0.4.0一起工作,不要认为它能与 pytorch 1.0 一起工作。在这个阶段,你不想修复这些类型的错误,所以从pytorch=0.4.0开始。您可以用命令conda install pytorch=0.4.0 -c pytorch安装一个特定版本的框架(例如 pytorch)。许多代码不会有一个requirements.txt文件,所以可能需要一些调查和迭代来找出你需要安装的所有库。

获取原始数据集并运行脚本:此时,您应该能够下载原始数据集并运行测试和训练脚本。您可能需要修改一些路径,并使用自述文件和源代码来计算出正确的参数。如果有一个预先训练好的模型,从测试脚本开始,看看你是否得到了与论文相似的结果。

一旦您运行了测试脚本,尝试启动培训脚本。您可能需要处理各种异常,并做一些小的修改才能让它正常工作。训练脚本的最终目标是看到损失随着每个时期减少。

如果是直白的(即。只需要更改一些命令行标志),此时您可以尝试在自己的数据集上运行训练脚本。否则,我们将在步骤 7 中执行此操作。

步骤 6:创建你自己的测试笔记本

在这一点上,您已经确认了模型是有效的,并且您已经设置了能够使用它的合适的环境。现在你可以开始真正地玩它了。在这一点上,我建议创建一个 Jupyter 笔记本,在测试脚本中复制粘贴,然后修改,直到您可以使用它的一个数据项。例如,如果您正在使用一个在图像中找到狗的对象检测模型,您需要一个笔记本,您可以向它传递一张图片并让它输出狗的边界框。

这里的目标是了解输入和输出、它们必须如何格式化以及模型如何准确工作,而不必处理额外的复杂训练或将您自己的数据转换成正确的格式。我建议在 Jupyter 笔记本上这样做,因为我发现能够看到每一步的输出对弄清楚它非常有帮助。

步骤 7:用数据集创建自己的培训笔记本

现在您已经对模型和数据有了一些了解,是时候尝试创建一个培训笔记本了。与步骤 6 类似,我首先在训练脚本中复制和粘贴,将其分成多个单元,然后修改它以适合我的需要。

如果您已经对该模型感到满意,您可能希望直接修改培训笔记本,使其适用于您的数据集。这可能涉及编写与模型中现有数据加载器输出相同格式的数据加载器(或者简单地修改这些数据加载器)。如果您还不习惯这样做,可以从让培训脚本在笔记本中按原样工作开始,并删除您认为无用的代码。然后努力让它与你的数据集一起工作。

请记住,这里的目标不是修改模型,即使它还没有完全解决您想要的确切任务。这只是为了让模型与您的数据集一起工作。

第八步:开始修改模型以适应你的任务!

至此,您应该有一个可以训练模型(包括输出适当的度量/可视化)的笔记本,以及一个可以测试您创建的新模型的笔记本。现在是开始深入研究并对模型进行修改(添加要素、附加输出、变化等)的好时机,以使其适用于您的任务和/或数据集。希望有一个现有的艺术模型的起点能节省你很多时间,并提供比你从零开始更好的结果。

很明显,在这一步中发生了很多事情,您将使用所有现有的模型构建策略。然而,下面是一些在现有模型基础上构建时可能特别有用的提示。

在修改模型之前修改数据集:将数据转换成模型期望的格式通常比修改模型更容易。隔离问题更容易,引入的错误也更少。令人惊讶的是,有时仅仅通过改变数据就可以将模型推进多远。

尽可能多地重用预训练的模型:如果你的模型变化不是很大,尝试重用预训练的模型参数。你可能会更快地得到结果和迁移学习的好处。即使您扩展了模型,您也可以经常将预训练的参数加载到模型的其余部分(例如,在 pytorch 中加载模型时使用strict=False)。

进行增量更改并定期检查绩效:使用现有模型的一个好处是,您对开始时的绩效有所了解。通过进行渐进式的改变,并在每次改变后检查性能,你会立即发现你什么时候犯了一个错误或者走上了一条错误的道路。

寻求帮助:如果你完全被卡住了,试着联系作者,寻求一些指点。我发现他们经常愿意帮助你,但是记住他们是在帮你的忙,请相应地采取行动。

Automatically texturing a 3D model using neural renderer

步骤 9:归因和贡献

根据许可证和您分发模型的方式,您可能需要向原始代码的开发者提供归属。就算不要求,反正做了也挺好的。

如果你能的话,请贡献你的力量!如果您在自己的开发过程中遇到了错误并修复了它们,提交一个 pull 请求。我相信写得好的错误报告是受欢迎的。最后,如果没有别的事,给作者发一封简短的感谢信,感谢他们的辛勤工作,总是令人感激的。

救援任务:深度学习可以打击人口贩运的 3 种方式

原文:https://towardsdatascience.com/a-rescue-mission-3-ways-deep-learning-could-combat-human-trafficking-85700eb62be5?source=collection_archive---------39-----------------------

深度学习如何阻止现代人类奴役的全球事业。

Figure 1: A 2-Dimensional t-SNE feature model illustrating useful and non-trivial relationships in the Trafficking-10k dataset.

现在是晚上 6 点——阳光透过你后座的窗户,散发出微妙而熟悉的橙色光芒。这是七月的仲夏,你和你的家人开车回到芝加哥紧张的低收入居民区。今天,你的父亲开着车,慢慢地进入有裂缝的车道,直到他到达一个轻松的停车点。当你打开车门时,你被完美的、超凡的、空灵的夏日微风所淹没。最终,灿烂的阳光、23 度的北风和诱人的蓝天最终让你问你的妈妈我们可以去公园吗?在这个没有任何气氛压力的日子里,你的母亲提供了一个愉快而响亮的“是!”。兴奋地,你和你的妈妈手牵着手,带着纯洁的幸福和天真,像仪式一样漫步到当地的社区公园。操场的平台是用几十年前的混凝土混合物铺成的,它的中心是一个由旧的摇摇欲坠的秋千、单杠和摇摇晃晃的滑梯组成的“临时”迷宫。**

今天,当地的公园看起来很反常,慢慢地陷入了一个深渊,没有了通常的动物般的孩子们荡秋千、追逐打闹和相互追逐。然而,12 岁的“你”独自拥抱这种沉浸式的探索性游戏和活动的时刻,而你的母亲坐在离游戏区 12 码远的木凳上。看起来,你的母亲接到了一个令人震惊的电话——是她的一个朋友打来的——所以她站了起来,走到长椅后面大约 4 码远的地方,低头看着地面,全神贯注地进行着私人谈话。你和你的母亲已经参观这个公园成千上万次了,所以你对这个地方的导航和直觉应该成为你的第二天性。**

最终,在你从秋千到单杠的过渡过程中,你看到一个中年男子若无其事地向你走来,他穿着一件棕色毛衣和一条破旧的蓝色牛仔裤。几乎同时,他冲向你,抓住你的手,把你扛在肩上,而你则流着惊慌的眼泪向你妈妈尖叫。你妈妈跑步但是不能及时赶到。他把你扔进后座,当汽车驶向你未知目的地的边缘时,他立即锁上车门。最终,“失踪儿童”海报的爆炸在商店、街道和市中心街区的当地公告栏中变得猖獗。

Figure 2: A conventional galleried array of missing children profiles in a Walmart entrance encouraging inflows and outflows of customers to report significant information.

这个家庭在执法文件、地方-州级犯罪网络和过时的青少年绑架数据库方面花费了数千美元和心血,留下了松散连接的关键数据点。商店里的海报和“走失儿童”公告故意等待“合适的人”带着 1。)丰富的信息还是 2。)对关键人口贩运调查的坚定承诺。同时,没有人注意海报上松散联系的信息要点,因为旁观者很少与事件周围的环境有任何相对联系/包含。然而,深度学习(DL)可以在几天内解决一年复杂的人口贩运犯罪调查,方法是将数据置于背景中,对其重要性进行排序,并将最重要的关键点联系起来。最终,DL 有能力改变秘密和非法犯罪企业的边界,人口贩运就是一个显著的例子。

1。)使用 NLP 对高风险性交易广告进行分类

自然语言处理(NLP)通常利用与递归神经网络(RNN)主干分层的长短期记忆(LSTM)模型来将句子的意图、内在含义和信息置于上下文中。LSTM 体系结构通过建立单词的临时记忆状态、对这些单词进行矢量化、并输出句子中意图/背景含义的推断概率来工作。典型地,针对 NLP 的 LSTM 方法已经被实现用于短文本的情感分类。例如,之前的 Kaggle 竞赛要求用户检测和分类多类有毒评论(例如 Youtube 评论),以便对短句进行自动严重性排名。

Figure 3: A Deep Neural Network (DNN)-based NLP model that uses embeddings for binary classification across a given input sentence.

王等人在“ 一种基于词嵌入的短文本情感分类方法 ”一文中利用上下文词嵌入来推断社交媒体帖子中的情感。最具活力的用户文本交流平台包括社交媒体平台、短信以及其他相关的快捷交流方式。换句话说,这些平台包含独特的俚语和现代缩写,只为特定的文化/人群所理解。此外,对于深度神经网络(DNNs),短的 50-100 个字符的信息交换不能为有效的分类提供足够丰富的特征。为了推断和概括短上下文行,研究人员可以利用单词嵌入和 LSTM 模型的组合。单词嵌入充当文本的学习表征,其中具有相似意思的单词/短语具有相似表征。单词嵌入模型对松散紧密相关的单词进行矢量化,以用最少的上下文对句子的意图进行分类和概括。

Figure 4: Word embeddings create sequence-lengthed representations of words in a sentence to eventually create output scores in an NLP model.

由于组合的 LSTM-单词嵌入模型在稀缺特征上概括上下文的能力,它在由混杂或少量字符组成的文本情况下提供了潜在的应用。童等人在论文“ 用深度多模态模型 打击人口贩卖”中,通过执行词嵌入对人口贩卖押运广告的风险进行向量化和推断。他们创建了新颖的 Trafficking 数据集,为这个监督训练任务浮现了超过 10,000 个带注释的广告。更重要的是,研究小组基本上将这些贩运文本/交流的单词嵌入整合到 LSTM 中,以产生新的上下文感知嵌入。最后,本文使用了一个直观的两步过程,首先从原始文本中提取低级嵌入特征,并通过语言 LSTM 网络将其翻译成上下文感知嵌入。

Figure 5: A language network processes tokenized input sentences through four LSTM’s into a Convolutional Decision Network to eventually output classification results for the traffick dataset.

此外,研究人员创建了一个 2D t-SNE 模型表示的贩运数据集,以证实其在 traffic-10k 中的精细特征分布。t-SNE(t-分布式随机邻居嵌入)模型将三维数据点压缩到 2D 模型中,其中点的聚类表示相似特征的区域。研究人员在下图中说明了他们的基线模型的不同输入特征的离散表示。聚类数据的划分表明,研究人员的新贩运数据集并非微不足道,而是具有可理解和结构良好的特征:

Figure 6: A 2-Dimensional t-SNE feature model illustrating useful and non-trivial relationships in the Trafficking-10k dataset.

2。人口贩运出口中的反洗钱

洗钱计划涉及犯罪分子通过金融系统循环非法资金,通常用于大规模金融转移,如跨境贩毒集团,在这种情况下,用于人口贩运。估计有 700,000 人被输出到人口贩运行业,这一行业奴役了 4,000 多万人。在人口贩运领域,人口“出口”可互换地被视为流动利润,因为它们在性贩运和与其他人贩子的交易中具有货币价值。虽然命题是 非常 初步的,但深度学习最有趣的集成涉及到使用图形 CNN 来分析密集/动态的法医金融数据,在韦伯等人的论文“ 可扩展图形学习反洗钱:第一次看 ”中,反洗钱(AML)使用几种广泛和新兴的技术来理解全球经济中可疑货币的流通。本文扩展了图分析法,以确定实体之间的现金流关系(即网络结构)。在图形分析中,金融系统中的单个账户被表示为顶点,单个交易被表示为边。边和顶点的大小与账户和交易的潜在规模成比例。下图说明了图形分析的动态。

Figure 7: An illustration of vertice and edge graph analyses, where nodes (the vertices-circles) represent account holders and the edges (connecting lines) represent transactions.

对图分析的传统攻击包括通过基于人类的推断来手动绘制顶点和节点之间的关系/边。换句话说,人眼经常负责捕捉个人账户和资产之间的可疑金融关系。然而,在一个大规模的行业中,洗钱每分钟可能涉及数百万个账户处理,这使得一个人/一组人很难定位这些模式。然而,通过采用深度学习和嵌入来矢量化这些账户/财务表示,深度学习模型可以在几秒钟内自动创建和处理这些图表分析。

Figure 8: An example model for AML employed in a business for real-time alerts based on data analytics.

除了在非法金融关系中建立自动图表分析,Weber 等人还强调了 NLP 在 AML 中的实施。最终,NLP 可以实时处理非结构化的异构数据,以产生可疑性得分和可视化,从而加强人类的法医分析。NLP 研究人员可以利用大量更新的数据流,如新闻文章、财务报告、社交媒体和公共/私人欺诈数据库。国际-国内银行可以与执法机构一起实施该系统,以便在长期内做出明智的反洗钱决策。然而,在实际规模上,基于图的学习通过实时事务关系理解呈现出最有希望的结果。下表展示了 Weber 等人的“1M 节点和 9M 边的训练时间和结果”。

Figure 9: Graph Learning on AMLSim Data (1M nodes, 9M edges)

3.通过酒店识别加快人口贩运调查

分散的人口贩卖中心包括旅馆和汽车旅馆。这些都是性交易和劳动力交易的重要场所,可以迅速展开,不留痕迹。然而,本文中最重要的平台是为广告网站保驾护航。护送网站不仅包括被出口或交换的受害者的注释描述,还附上受害者的数码照片,通常以酒店壁纸/家具为背景。在 Stylianou 等人的论文“Hotels-50K:A Global Hotel Recognition Dataset”中,通过实现用于图像归属和标记的 CNN 来识别和操纵酒店图像背景在人口贩运调查中的价值。

Figure 10: Example of correspondence between query image background and the ground truth prediction in the hotel dataset.

该研究团队从 50,000 多家酒店收集了超过 100 万张带注释的酒店房间图像。该数据集由从美国东西部、西欧以及世界各地受欢迎的海岸线延伸的多样化酒店位置组成。Stylianou 等人收集的地点是从旅游网站和酒店房间简介网站中提取的。下图显示了他们集体酒店的地理分布-50K 数据集。

Figure 11: Global geographic distribution of the hotel dataset- includes the U.S., Western Europe, and notable coastlines.

在计算机视觉领域,由于特征提取的性质,场景识别一直是一个主要障碍。当主要特征包括人脸、身体和四肢时,让 CNN 架构提取背景场景对于传统的计算机视觉模型来说是一项困难的任务。该小组使用了在 ImageNet 上预先训练的 Resnet-50 分类网络。Resnet-50 使用残差网络来简化训练,而不管在大型数据分区上训练的极深层。Resnet 架构如下图所示:

Figure 12: A massive Resnet network which uses a series of Residual layers and convolutions to create easier training.

最终,多样化的酒店数据集和基于经典 ImageNet 权重/数据集的深度驱动 Resnet-50 架构相结合,可以让执法部门快速识别整个州/国家的潜在酒店位置和感兴趣区域。此外,由于数据集通过整个北美的图像得到了加强,因此任何由人口贩运计划引起的全国性移动都可以被考虑在内。

结论

人口贩卖的全球剧场是一个超复杂的游戏,包括多层动态的关键人物。更重要的是,坦率地说,人口贩运是一种战略性的经济交易,涉及具有货币价值的人体出口。由于这些转账的金融价值,它已经深深扎根于非法洗钱经济和秘密的在线护送平台。然而,深度学习架构的实施可以将调查时间缩短十倍以上,为执法部门和受害者家属提供更有效的数据保证。通过在文本挖掘、图形分析和图像存储库中大量使用开源数据,模型可以被训练和私人部署,供相关官员及时使用。很明显,随着人口贩卖在 21 世纪变得更加先进,从长远来看,人工智能将会超越它。

参考书目

Stylianou,A. (2019)。Hotels-50K:全球酒店识别数据集。 Arxiv,1–8。检索于 2019 年 7 月 8 日,来自https://arxiv.org/pdf/1901.11397.pdf.

童,E. (2017)。利用深度多模态模型打击人口贩运。1–10.检索于 2019 年 7 月 8 日,来自https://arxiv.org/pdf/1705.02735.pdf.

王,法学博士。基于词嵌入的短文本情感分类的 LSTM 方法。 2018 计算语言学与语音处理会议,214–223。检索于 2019 年 7 月 8 日,来自https://www.aclweb.org/anthology/O18-1021.

m .韦伯(2018)。反洗钱的可扩展图学习:初步研究。 Arxiv,1–7。检索于 2019 年 7 月 8 日,来自https://arxiv.org/pdf/1812.00076.pdf.

基于递归神经网络的推特美国中期选举回顾与预测分析

原文:https://towardsdatascience.com/a-retrospective-and-predictive-analysis-on-2018-u-s-midterms-with-recurrent-neural-networks-858141838921?source=collection_archive---------31-----------------------

尽管几年前曾有怀疑者和批评者,但我猜想过去几个月里,每个人都感受到了社交媒体在公共辩论舞台上的影响和作用,涵盖了社会问题、政策制定、政治和政治选举。

然而,这往往只能通过新闻媒体来体验,这些媒体描述了经济和政治游说之间极具争议的因果关系或相关性,旨在产生特定的政治影响。有时这是基于客观分析,有时只是基于目击者,甚至只是感知结果..从而导致仍然有争议的权利要求的可论证性。

另一方面,技术分析在数据科学、计算机科学和网络科学社区中不断涌现,它们对此进行了大规模的研究。相反,它们通常非常笼统,不能提供正在发生的事情的实际见解。

相反,我想在这里报告的是在政治背景下的一个简单的数据科学练习,但是有一个非常集中的目的,旨在回应不明显的问题

我们实施了一项分析(意味着一种方法和一种系统),旨在在 2018 年中期选举期间,在竞争最激烈的 68 个众议院选区中,衡量当地对美国两大政党的支持。

剧透:整个分析实现和结果都有。有关材料和链接,请参见下一页。

目标

该分析试图反映【普通投票】民意调查,即对特定地区选民的调查,旨在通过询问参与者他们投票给“普通”民主党或共和党候选人的可能性来衡量全国性政党在当地的受欢迎程度。我们收集了包含 68 个竞争最激烈的地区的全国性政党和政治家的推文。我们所说的最具竞争力指的是他们被库克政治报告评为:投出50%-50%精益

这意味着我们正在解决一个极具挑战性的分析和预测问题,而忽略了更简单的情况(每个人都擅长预测显而易见的事情!).

除了这种通用的投票模型,我们还试图捕捉到“On Ballot”模型,旨在获得当地候选人的支持,即实际参与国会竞选的候选人。然而,这一模式具有明显的偏见,不能像普通投票模式那样在选举前得到验证。因此,我们只报告第一个分析。

数据收集

在这种分析中,查询和提取推文的方法有时会被忽略。但是,查询过程本身可能会引入偏差,这在过程的后期阶段很难检测到,因此需要仔细设计。我们的解决方案采用 Twitter 搜索 API 来查询提到国家领导人或政党的推文,这些推文是从有限的地理区域(即每个特定的国会选区)发布的。例如,以下查询提取了关于共和党的推文:

特朗普或众议员或共和党人或共和党人或麦克·彭斯或保罗·瑞安或#共和党人或#众议员或 @realDonaldTrump@SpeakerRyan@senatemajldr@VP 或 GOP 或 @POTUS

为了将搜索限制在每个国会选区,我们在 API 的搜索查询中使用了 geocode 字段,它基于中心和半径的坐标来查询一个圆形区域。由于国会选区的形状不规则,每个选区都需要多个查询,因此我们构建了一组定制的气泡来近似选区的形状(参见图中的 PA-10 区及其近似值)。其他人已经提出了其他方法,这些方法没有将搜索限制在地理标记的推文中,但对于我们的目的来说,这些方法不够精确。

分析

为了分析推文,我们采用了递归神经网络,即在推文上训练的 RNN-LSTM 二元分类器。这种架构在包括情感分析在内的许多 NLP 任务中被证明是准确的,因为它能够捕捉单词序列上的依赖性。为了建立训练和测试数据,我们收集了具有明确政治倾向的用户的推文,包括候选人、政治活动家以及不太了解的用户,他们精通政治术语。
在选举日前的 6 个月里,所选账户在产生了大约 280,000 条推文,这些推文根据作者的政治派别进行标注。
在标记、预处理和标记化之后,我们保留了 15000 个最常用的单词用于进一步分析。所处理的数据训练 128 宽的 Word2Vec 嵌入层来学习令牌的抽象表示。结果被馈送到由两层组成的 RNN,其在超参数优化之后的维度分别是 256 和 64。许多不同的技术被用来调整网络,包括丢弃或者使用第二层来帮助抽象

Map of the political alignment of the critical districts in 2018 mid-term elections based on geolocated Twitter data.

确认

我们首先在选举前验证了我们的方法,通过考虑验证一组 10 个地区,对于这些地区,传统的民意测验给出了有把握的预测(一个政党领先 10%或更多)。在这个集合中,总是预测正确的结果,即,我们的方法获得 100%的成功。
总体而言,我们的推文分类器在随机验证集上达到了 83%的准确率。培训之后,在卡瓦诺听证会的那一周,收集了一套特别具有挑战性的测试;尽管内容奇特,但该模型无论如何都能正确分类超过 72%的推文。通过设定 75%的置信阈值,准确率提高到了 80%左右。
最后,在地区预测层面,我们的解决方案对 68 个最具竞争力的地区中的 60%以上进行了正确分类,识别出 10%的其他地区中非常接近的竞选。

本文基于 2018 年 12 月在华盛顿州西雅图举行的 IEEE 大数据会议上发表的一篇简短的科学论文,以及 Antonio Lopardo 之前的一篇媒体文章。进一步的细节可以在文件中找到。

如果你想引用这部作品,你可以这样做:

A.Lopardo 和 M. Brambilla,“用递归神经网络分析和预测 Twitter 上的美国中期选举”, 2018 年 IEEE 大数据国际会议(大数据),美国华盛顿州西雅图,2018 年,第 5389–5391 页。doi:10.1109/bigdata . 2018 . 8622441 . URL:【http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=】T2&ar number = 8622441&is number = 8621858

在线运行的原型、项目的完整描述、结果和源代码可在 http://www.twitterpoliticalsentiment.com/USA/获得。

请注意,该方法是一个通用的政治目的的独立于语言的分析框架,可以应用于任何国家或地方的背景。

基于 BERT 的模型综述

原文:https://towardsdatascience.com/a-review-of-bert-based-models-4ffdc0f15d58?source=collection_archive---------7-----------------------

另外:一些最近的线索/见解让伯特变得如此有效

Image source for the BERT & Ernie figures

注意——通过对输入进行加权平均来聚焦于输入的显著部分的简单想法,已被证明是一大类神经网络模型中的关键因素。特别地,多头注意力已经被证明是诸如基于 BERT 和 Transformer 的机器翻译模型之类的最新自然语言处理模型成功的原因。多头注意力——实质上是“多个注意力头 参加 到并行输入的不同部分”,使得复杂功能的表达超越了仅仅一个注意力头的加权平均。

自从 word2vec 产生了如此多的分支模型以来,还没有一个 NLP 模型产生过如此多的分支模型——要么以其名称作为前缀/后缀嵌入其中 ( doc2vec,node2vec,lda2vec 等等。)或在其核心思想上展开 ( 跳过思想向量 s、fast textAdagram等。)

BERT 模型值得称赞的是,它的许多分支结合了它的名字和它的核心架构思想。举个例子,

  • 预训练模型。在领域/应用特定语料库上预处理的模型— BioBERT 【生物医学文本】SciBERT(科学出版物)clinical Bert【1】和clinical Bert【2】【临床笔记】。在特定领域语料库上的训练已经表明,当在下游 NLP 任务如 NER 等上对它们进行微调时,会产生更好的性能。对于那些领域,对比微调 BERT (在图书语料库和维基百科上训练过)
  • 在来自 104 种语言的单语语料库( M-BERT )上预训练的模型,用于零触发跨语言模型转移(一种语言中的任务特定注释用于微调模型以在另一种语言中评估)
  • 模型在一个大型语料库上进行预训练,该语料库在输入中结合了知识图(厄尼)。几乎在同一时间(2019 年 3 月至 4 月)发布了另一款车型,令人惊讶的是,它还将知识融入了预训练中。 ERNIE (2)将知识融入预培训,但通过使用 KG 屏蔽实体和短语。
  • 使用三阶段训练方法的模型( TransBERT ) —无监督,然后是两个监督步骤,用于故事结尾预测任务
  • 通过将视频帧表示为特殊的描述符标记以及用于预训练的文本,联合学习视频和语言表示学习的模型( videoBERT )。这用于视频字幕。
  • 一种结合了图形神经网络和 BERT ( G-BERT )功能的模型,用于医疗/诊断代码表示和推荐。使用 GNNs 对具有分级表示的医疗代码进行编码,并在用 EHR 数据进行预训练期间将其作为输入。然后对其进行微调,以提供医疗建议。
  • 微调型号。使用预先训练的模型针对特定任务进行微调的模型— DocBERT (文档分类)、 PatentBERT (专利分类)。除了这些大部分 NLP 任务 POS,NER 等。如前所述,针对应用领域对预先训练好的基于 BERT 的模型进行微调,以获得更好的结果。

上面的模型只是基于 BERT 的模型的一个子集,代表了广泛的类别。关于 BERT(arXiv 至今至少 150 篇)的论文不少。其他几个类是对伯特(下面讨论)的探索/可视化,还有几个类研究伯特(也在下面讨论)的局限性。还有其他工作,比如在认知神经科学研究中使用 BERT,这里没有涉及。

一个自然产生的问题是

是什么让 BERT 在如此广泛的任务中如此有效?

最近的一组论文试图通过使用各种各样的探针来回答这个问题【1】【2】【3】【4】【5】(其中的几个在之前的一篇文章 中有所评述)。

在我们查看探针之前,快速回顾一下 BERT 模型。

伯特模型评论

经过训练的 BERT 模型将句子作为输入,并输出句子中每个单词的向量。它为一个单词输出的向量取决于它出现的上下文。例如,句子“他死于监狱细胞”中的单词细胞的向量与“血液细胞样本被污染”中的单词细胞的向量不同。此外,第一句中单词“细胞”的矢量可能更接近单词的矢量(余弦距离)和单词的矢量,而第二句中的单词细胞将更接近基因的矢量(如下图)

BERT 按如下方式构造单词的向量:

  • BERT 具有固定大小的词汇,包括单词/子单词 ( 单词块嵌入)——任何输入单词都被映射到这些单词/子单词。例如,一些像“the”这样的常用词,甚至像“quantum”、“constantinople”这样的不常用词都出现在 BERT 词汇表(base and large model vocab)——所以这是这些词的直接映射。但是没有电动力学这样的词。所以它被分解成 4 个子词-electro # # dy # # Nami # # cs其中这些子词出现在 vocab 中。此外,固定大小的 vocab 的一个实际优势是,将 BERT 模型加载到 GPU 中不受语料库中唯一单词数量的限制——任何语料库,无论其唯一 vocab 大小如何,都由大约 30k 的子单词 vocab 表示。
  • 在训练过程中,BERT 使用其注意力头(本质上是一组学习矩阵,我们将在下面看到)和其他变换矩阵(所有这些也是在训练过程中学习的)来学习其固定大小 vocab 的矢量表示。然后,在评估/测试期间,通过首先将单词映射到固定的 vocab 单词/子单词,并将单词在输入句子中的位置编码到其表示中,使用经过训练的模型以及其 vocab 的学习向量来动态构建句子中任何单词的向量
  • 作为一个具体的例子,考虑“猫和狗是宠物”这句话。所有这些单词都存在于 BERT vocab 中,因此它们不会被分解成子单词。
  • 聚焦于单个注意力头部,它将单词“dogs”的向量构建为句子中包括其自身在内的所有单词的向量(它们的变换版本)的加权和。本质上,单词“dogs”的向量通过不同的度量 被拉得更靠近句子中的所有单词(将向量 A 的小分量添加到向量 B 等于将向量 B 拉得更靠近 A 一点) 每个单词向量的量(例如)。“猫和狗是宠物”句子中的“猫”)对“狗”向量的创建的贡献部分地由注意力头部矩阵(主导因素)、“猫”在句子中的位置(由输入时添加到“猫”的位置编码捕捉),以及两个单词向量有多接近(计算为“狗”和“猫”的向量之间的点积)。这个步骤值得与 word2vec 训练过程进行比较——其中,句子(例如,狗)中每个单词的向量被拉得更靠近其相邻单词(在固定大小的窗口内——比如每边 5 个单词),拉的距离由该单词向量与窗口内其他单词向量的接近程度决定。 BERT 使用单个注意头为句子中的单词创建上下文敏感向量,这与 word2vec 中为单词创建全局向量有些相似,尽管 BERT 考虑了单词顺序和单词位置,最重要的是考虑了邻居(包括其自身)的贡献,这在很大程度上由注意头矩阵决定。
  • BERT 模型的每一层都有多个注意力头 (12 个在底部,16 个在大处),一个非线性前馈层接收这些注意力头输出,并允许它们在被馈送到执行上述相同操作的下一层之前相互作用。

figure from ref. 5

  • 最后,在论文中对注意头的大多数描述中,我们经常看到“第三层注意头 1 关注句子中的下一个标记”这种形式的陈述。虽然这是区分每个头的功能的有用方法,但值得记住的是,在实现中,上面的语句意味着对一个单词的向量输出最大的贡献者是紧随其后的单词。
  • 下面的描述用两段简洁的数学形式概括了上面描述的所有内容。关键的一点是,每个注意力头由四个 W 矩阵 (Wk,Wq,Wv 和 Wo) 组成,这些矩阵是在训练中学习到的。它们扮演上述角色——Wo 和 Wv 参与单词向量的加权平均,Wq 和 Wk 参与计算权重αi

Figure from ref. 2

下面描述了单个注意头的等效但可替换的视图,其中矩阵 Wq Wk 和 Wv 被用于输入向量的线性变换,然后加权平均被计算为单词的向量和它的邻居之间的点积。

figure from ref. 5

检查模型学习的内容

不同的探索/可视化提供了伯特模型所学内容的线索/见解

  • 视觉化注意力权重(上面等式中的αI)就像我们上面看到的,显示了每个头部在每一层都在关注什么。这些注意力地图对应于语法和共指的语言学概念。例如,我们发现中心语非常准确地关注动词的直接宾语、名词的限定词、介词的宾语和共同参照的提及。
  • 根据权重 (上述等式中的αI)从句子中两个单词之间的每个注意头构造向量(对于 12 层 12 头 BERT 模型,该向量将是 144 维的)并且针对句子中的一对单词在该全局注意向量上训练线性分类器,以查看这两个单词之间是否存在关系以及关系的类型,指示句法关系(一个单词对
  • 使用句子输出向量的特定线性变换,显示了 BERT 在它为句子输出的单词嵌入中近似编码语法树

figure from ref. 5

  • 对特定 NLP 任务的每一层的重要性进行评分(例如,POS、NER 等)。),表示在网络中基本句法信息被更早地(较低层)捕获,随后是更高层的语义信息。这反映在右图中。(这个观察结果也类似于在 ELMo 模型中看到的情况)
  • 此外,与句法任务相关的信息似乎更多地局限在几个层中,其中语义任务的信息( SPR and Relations)通常遍布整个网络(见深蓝色阴影条)
  • 检查输出单词向量显示,不仅单词的不同含义被捕获在不同的表示中,它们还以细粒度的方式 (如下所示)

Example of word sense separation for the word “Fair”

  • 由于 BERT 将单词意义分成单独的表示,同时考虑到单词的位置(例如,在句子“他带着手机去监狱牢房从囚犯那里收集血细胞样本”中,单词“cell”的表示对于每次出现都有不同的意义),通过简单地将这些单词向量相加而构建的句子向量对于搜索任务可能是有用的。例如,使用 bert-as-service 我们可以构建句子向量(在构建句子向量时,我们需要注意不要使用 SEP 和 CLS 令牌),这对相似性搜索应用程序非常有用。下面显示了几个例子(下面每个响应开头的标签是一个调试文本,显示所有响应都是语义相关的。这些句子来自 Fasttext 句子分类测试数据,其中每个句子被分为大约 14 个类别,并带有标签。第二列值“余弦度量”在作为两个句子之间距离的绝对度量时没有用,最多可以解释为显示输入与句子 1 的距离比与句子 2 的距离近多少的度量)

  • 最后,最近的一项工作通过消除(消融)注意力头来评估模型在任务中的表现,从而检验所有注意力头是否同等重要。本研究显示 在测试时间 ,对于许多任务,可以移除几个头,而不会显著降低性能。这将导致推断时间的减少。在一些层中,头的数量可以被修剪以只留下一个头。然而,机器翻译更依赖于多头,其中头的使用不是自我关注,而是编码器/解码器层中的多头关注。

在出版物中引用的 BERT 模型的一个局限性(可能还有其他的)【1】【2】

BERT 及其基于 transformer 的亲戚 GPT-2 最近证明,如果在大型语料库上训练,在句子完成任务(包括在 Winograd 挑战句子中的适度表现)方面相当不错。然而,最近构建的句子完成任务显示,如果句子完成任务需要无法从语料库中收集的世界知识(常识),那么与人类相比,这些模型的表现相当差。下面是一个例子。

Figure from ref. 3

这也许不是模型的限制。正如 Yoshua Bengio 教授最近提到的那样,这可能是一种指示性的(2019 年 4 月 26 日),我们需要的模型不仅要通过对输入文本进行训练来学习单词嵌入,还要学习这些单词在环境中的含义(语言学习和世界建模协同进行)。这种形式的学习(称为)是目前比较活跃的一个研究领域。

参考

  1. 可视化和测量伯特的几何形状,6 月 20 日 19
  2. 16 个头真的比 1 个头强吗?2019 年 5 月
  3. 机器能完成你的句子吗?2019 年 5 月
  4. BERT 重新发现经典 NLP 管道 2019 年 5 月
  5. 伯特在看什么?伯特注意力分析,2019 年 6 月 11 日
  6. 在单词表示中寻找语法的结构探针 2019 年 4 月
  7. BioBERT-用于生物医学文本挖掘的预训练生物医学语言表示模型,2019 年 1 月
  8. SciBERT:科学文本的预训练语境化嵌入,2019 年 3 月
  9. ClinicalBert:模拟临床记录并预测医院再入院,2019 年 4 月
  10. 公开发布的临床 BERT 嵌入,2019 年 4 月
  11. 伯特 2019 年 6 月多语种
  12. 厄尼:用信息实体增强语言表达,2019 年 6 月
  13. 可转移伯特的故事结局预测 2019 年 5 月
  14. VideoBERT:视频和语言表征学习的联合模型,2019 年 4 月
  15. PatentBERT:通过微调预训练的 BERT 模型进行专利分类,2019 年 6 月
  16. doc Bert—Boer for document class ification,2019 年 4 月
  17. 用于药物推荐的图形增强变压器预培训,2019 年 6 月
  18. 注意力是(不是)你进行常识推理所需要的全部,2019 年 5 月
  19. Github 到源代码的链接在上面列出的大多数论文中都可以作为脚注链接获得

NeurIPS 2018 综述

原文:https://towardsdatascience.com/a-review-of-neurips-2018-89cf3f38a868?source=collection_archive---------24-----------------------

从事金融工作的数据科学家的观点

苏刘与,R &维数据科学家 穆达诺有限公司 ,爱丁堡英国

利用我们的个人发展预算,一个由 Mudano 提出的伟大计划,我和我的同事 Boris 参加了去年在蒙特利尔举行的神经信息处理系统(NeurIPS)会议。这是世界上最大、最著名的人工智能会议,现在已经是第 32 届了,有超过 8500 人参加。注册在几分钟内售罄,所以我们非常幸运地获得了我们的位置!

这是紧张的六天,充满了机器学习所有领域的教程、研讨会和演示。我们了解了最新的前沿研究,以及世界各地的技术公司如何使用和开发机器学习工具。

除了谷歌、脸书和微软这样的大公司,我们还与一些小型创业公司的研究人员进行了有趣的讨论,他们中的许多人所研究的问题与我们在 Mudano 遇到的问题类似。我们还与大型咨询公司和金融服务公司(如 EY 和摩根大通)的数据科学家进行了交谈,了解了他们如何利用数据科学和机器学习。

以下是会议的一些关键主题和我们在这一周学到的东西。

可解释性至关重要

随着模型变得越来越复杂,理解和信任它们的需求也在增长。剑桥大学的 Spiegelhalter 教授做了一场精彩的全体会议演讲,他描述了他的团队如何谨慎地使用统计学来解释和验证乳腺癌诊断和治疗建议的算法,从而使患者信任这些模型并确保可能的最佳结果。

在数据科学家处理信用贷款和欺诈检测等问题的金融服务领域,理解机器学习算法所做决策背后的原因也非常重要。在“金融中的人工智能”研讨会上,30 张海报中有超过 10 张致力于模型可解释性的主题。

对于最近的一个原型,我们使用了一个名为' shap' 的新 Python 库来解释哪些特性在分类问题中起了最大的作用。我们在会议上与其他机器学习研究人员讨论了这一点,他们同意这是一个非常好的库,用于解释本地和全球层面上的功能重要性。该算法通过将博弈论(数学的一个分支)应用于开发精确的树解决方案来识别机器学习模型的唯一和一致的特征重要性,以预测每个类别。(在下面的例子中,年龄=37 使候选人更有可能获得贷款。)这将成为我们解释机器学习模型的工具包的一部分。由于‘shap’是一个 Python 库,我们面向客户的数据科学家也可以很容易地访问它。

另一个有趣的方法是使用模型对其输入的敏感度来评估特性的重要性。它在神经网络中特别有用,因为它们本身是可微分的,并且允许导数(灵敏度)的集合来识别模型的局部和全局行为。来自 J.P. Morgan 的作者使用信用卡默认数据集演示了一种基于敏感度的方法,并制作了一个即将发布的开源 Python 包。

解决可解释性的另一种方式是通过使用反事实。在这种方法中,计算翻转分类器结果的输入向量组的最小变化。例如,在确定信贷申请结果的问题中,一旦建立了分类器,我们就可以找到导致相反预测结果的申请人的输入变量集(例如,工资、年龄、以前的申请)的最小变化,并对它们的相对重要性进行加权,以通知申请人他们的申请被拒绝的原因。这是一个非常直观的想法,所以我们将实现这个方法,并与 Mudano 的其他团队分享。

除了可解释性,我们可能感兴趣的其他研究包括如何使用主动学习来分配风险分数,从不平衡数据中重新采样和学习的新方法,使用 textCNN 从基于文本的报告中自动分类客户尽职调查。这些只是几个例子,我们正在筛选会议文件,寻找其他有趣的想法。

机器学习需要软件工程师

机器学习即服务在过去几年中获得了巨大的吸引力。我们与一些成功的初创公司进行了交谈,包括 Element AI、Borealis AI 和 Stratigi,它们已经从咨询公司发展成为机器学习软件提供商。

这些公司识别市场需求,并制造机器学习产品,然后出售给他们的客户。这意味着一个产品可以卖给多个买家,让 R&D 的研究人员有时间进行更多的创新研究,并领先于竞争对手。

这些成功公司之间最显著的共同特征是,机器学习研究得到了软件开发人员和数据工程师团队的良好支持,他们可以构建健壮、高效和适销的产品。这是因为,虽然机器学习科学家花了数年时间来研究和开发前沿算法,但数据工程师和软件开发人员花了类似的时间来构建完全开发的产品,这些产品在所有类型的平台上都是高效、紧凑和健壮的。他们能够在机器学习科学家花费的一小部分时间内将原型投入生产,因为这是他们的专长所在。

在 QuantumBlack(麦肯锡公司的子公司),开发人员与数据科学家的比例约为 1:1,而在一些更基于产品的公司,这一比例接近 2:1。充分利用前沿研究需要专家工程师的支持,他们可以开发产品并构建安全的基础设施。

Deepmind(和其他人)

不出所料,一些最好的演讲来自 Deepmind,尤其是他们与穆尔菲尔德医院在视网膜疾病的检测中的合作,该论文发表在 9 月份的《自然》杂志上。就在会议之前,Deepmind 推出了 DeepFold ,这是一种经过预先训练的高效蛋白质结构搜索模型,在药物发现中至关重要。

鲍里斯会见了 AlphaZero 团队,该团队负责创建一个强化学习自主代理,该代理在没有任何先验知识的情况下,掌握了最复杂的两人完全可观察零和游戏——围棋、国际象棋和五子棋。该算法开始随机与自己对弈,然后学习一个策略,在给定当前位置的情况下,哪些移动最有希望,以及一个估计每个位置获胜概率的值函数。然后它重复这个过程,这一次使用学习到的策略和值函数来与自己对抗。然后,它再次重新训练,四个小时(和数百万次游戏)后,它比任何人类或人类制造的国际象棋引擎都强。

AlphaZero 团队透露了一些以前不为人知的信息——他们的测试游戏是一种较小规模的围棋游戏,通常由初学者玩,但远未被职业选手解决。这个游戏被认为几乎和国际象棋一样复杂,但 AlphaZero 完全学会/解决了这个游戏,用白色获得了 100%的胜率。

全体会议是关于人工智能和机器学习的更一般的方面。我们参加了关于如何与公共决策者互动,如何使研究具有可重复性,以及机器学习将如何影响软件开发的会谈。其中一个最吸引人的演讲是关于神经系统外的生物电计算,比如如何通过修改离子通道来创造多头蠕虫。这完全超出了传统机器学习的范畴!这些演讲邀请我们思考人工智能在社会中的作用,提醒我们研究需要严谨才能可信,并跳出框框思考——并对未来感到兴奋!

穆达诺大学机器学习研究的未来

机器学习,特别是深度学习,现在已经达到了一个成熟的水平,可以用来解决许多行业问题。在广泛的学科领域,研发仍在快速推进,但在 NeurIPS 2018 上几乎没有突出的关键主题:

  1. 由于在国际象棋、扑克和围棋等游戏中的成功,强化学习现在是一个主要领域,有超过四次会议专门讨论它,并且有最多的研讨会出席。从这个领域的投资金额来看,我们可以看到它有一个长远的未来。
  2. 人们对可解释的人工智能更感兴趣,这导致了因果学习的教程和研讨会,这是一个与穆达诺非常相关的领域。
  3. 我们需要一种一致的方法来处理模型和数据中的不确定性,人们对贝叶斯方法有着持续的兴趣和研究。

在接下来的几个月里,我们将深入研究这些主题,并发展我们对如何应用它们来解决 Mudano 中的机器学习问题的理解。

我们很幸运在苏格兰有许多世界领先的机器学习研究人员,特别是在爱丁堡大学的信息学系。我们在会议上遇到了他们中的一些人,并了解了他们的研究兴趣,包括强化学习、多任务学习和贝叶斯网络。

他们总是乐于接受新思想,他们的许多博士生都有工业赞助人。这可能是一种与大学建立更紧密联系的方式,并为 Mudano 带来知识和专业技能。

结论

我们在蒙特利尔度过了一段美好的时光,这是一个美丽的城市,有着迷人的法国风情。这是忙碌的一周,但也很有趣。这次会议的规模使得会见许多有趣的人成为可能,不管他们在哪个领域工作。我们在演示中也玩得很开心:在其他事情中,人们展示了他们的人形机器人如何响应语音命令来捡起东西;如何使用 ML 教人们演奏巴赫赋格曲,如何学习玩竞争性对抗游戏,以及如何使用 ML 学习跳舞,实时 2D/3D 超分辨率。

It’s Boris’ chessboard!

尤其是鲍里斯,他玩了许多国际象棋和围棋游戏(并且赢了大部分游戏!)并一路结交了朋友。一位国际象棋和围棋选手是德国情报研究员,专注于密码学问题。他提出了一个有趣的见解,即如果你关心你的秘密~15 年后,那么目前的加密方法是不够的。

基本原理是,当前的加密方法可以很容易地被 500-2000 台量子位计算机破解,这些计算机预计将在 15 年内问世,攻击者可能会耐心地存储您当前的加密通信,并知道他们在以后能够解密它们。并非一切都是暗淡的,因为抗量子攻击的方法已经存在。

这次旅行给了我们一个与深度学习社区互动的绝佳机会。我们了解了最有趣的问题是什么,谁是特定领域的领导者,以及数据科学公司正在做什么。所有这些在家里都很难学会。这无疑拓宽了我们的视野,也必将为 Mudano 的数据科学和机器学习增添价值。

斯坦福大学机器学习认证述评

原文:https://towardsdatascience.com/a-review-of-stanfords-machine-learning-certification-9614ebee2b06?source=collection_archive---------13-----------------------

在快速变化的数据科学环境中,这仍然值得吗?

Photo by Andrew Neel on Unsplash

作为最受欢迎的大规模数据科学开放在线课程(MOOC)之一,注册人数超过 260 万(截至 2019 年 11 月),目前平均用户评分为 4.9/5……毫无疑问,斯坦福大学通过 Coursera 提供的机器学习认证是一个巨大的成功。

毫无疑问,这在一定程度上要归功于该课程的创始人吴恩达的卓越能力,他将 ML 的一些更复杂的方面简化为直观和易于学习的概念。

然而,当我开始学习这门课程时,我有两点保留意见:

  1. 这个课程是 2011 年制作的,它仍然有用吗?
  2. 我会重复我已经知道的事情吗?

关于后者,在 2018 年夏天,我很幸运地获得了一笔赞助,随后成为一名数据科学家,在我的雇主已经工作了近三年的一份大合同上研究自动化的 NLP(手动,有一个大团队)。这是一个惊人的机会,也是我目前大部分知识的来源。

在本文的剩余部分,我想回答这两个问题,并概述一下对这门课程的期望。

这门课程包括什么?

这门课程涵盖了 ALOT,它设法在一个看似很短的时期内塞进了大量惊人的细节。这并不是说它缺乏深度,事实上,我认为材料的深度是这门课的优势。

您将涉及线性和逻辑回归、矢量化、正则化、神经网络、前馈和反向传播(这非常好)、成本函数、网络初始化、支持向量机、降维、监督/非监督学习、主成分分析(PCA)、K 均值聚类、异常检测、推荐系统等等。

还有许多关于应用机器学习的建议,例如诊断偏差与方差误差,实施训练验证测试集,如何测量模型性能(准确度、精确度、召回率和 F1 分数),哪些算法在大量/缺乏数据的情况下工作得更好,以及如何调整所述算法以更好地适应我们的需求和/或情况。

我的经历,一周又一周

第 1 周—简介、线性回归和线性代数

这个星期是相当直接的,我认为这是一个很好的介绍,特别是如果你有一段时间没有学习或研究数学的话。还有一些简单的逻辑问题和对统计学和机器学习基础的介绍,如分类对回归和监督对非监督学习。

本周的评估非常简单,只有两个小测验。还有一个关于线性代数的选修课。我认为,即使你对线性代数很熟悉,浏览一下这一部分也是很好的,因为我发现吴安迪有时会以不同于我通常思维的方式解释事情,我相信从尽可能多的角度理解概念总是有用的。

第 2 周—更多线性回归,Octave(或 MatLab)介绍

本周我们来看看多元线性回归。从单变量线性回归到多变量线性回归并不难,我不认为许多人会觉得这太难。

还有一个我以前从未使用过的正规方程的介绍,同样,这并不难,但使用起来很有趣!本周最具挑战性的部分是在第一次编程任务中将它翻译成 Octave 代码。

当然,在分配任务之前,我们会被介绍给 Octave(或者 MatLab,如果你喜欢的话)。Octave 是简单的开源 MatLab,所以如果你使用过 MatLab(或者 Python,语法非常相似),它很容易上手。

第 3 周—逻辑回归,规范化

我认为这是课程开始学习更复杂概念的地方。在这里,您将涵盖许多重要的 ML 概念,如分类、假设、决策边界、成本函数、梯度下降(以及高级优化技术的简要介绍)、多类分类、过度拟合、调节等。

这一周并不太难,但我认为它涵盖了许多重要的话题,所以这肯定是至关重要的一周。本周真正的焦点是逻辑回归,线性回归之后是一个很好的(不太难)进步!

编程任务很简单,但由于我的代码中的小错误(想想(1/nx)而不是(1/n)x) ,我确实被卡住了,令人尴尬的是,我花了比我想承认的长得多的时间来解决这个问题…

第 4 周——神经网络:表现

本周我们从两个动机视频开始,着眼于非线性假设和神经网络与大脑神经元之间的暗示。

本周余下的时间将深入探讨神经网络是如何工作的,安迪在本周出色地解释了神经网络背后的直觉。

本周以另一个编程任务结束。这个比较复杂,但是不太难,我发现它很有趣!

第 5 周——神经网络:学习

在本周,我们将触及成本函数(再次简单地)和反向传播。前半部分是反向传播,背后的数学和直觉。第二部分是如何检查我们是否正确实现了它(梯度检查,非常有用)以及我们如何/为什么随机初始化网络权重。

这周很难熬。尽管我在大约一年前使用 NumPy 报道过这个问题,但我发现我已经忘记了除了对正在发生的事情的高层次理解之外的一切。反向传播直觉很难。只有当我完成编程任务时,我才意识到我对这个算法的直觉是多么的少。

我发现不断重复你所采取的步骤真的很有帮助。通过纸上的前馈和反向传播步骤,检查数组维数如何随着每一步而变化,并试图理解它为什么工作。

第 6 周—应用机器学习的建议

令人惊讶的是,正是在这一点上,我的第二个保留意见是“我会重温我已经知道的东西吗?”上来了。然而,我发现自己真的受益于这一周,因为我觉得重做这些材料真的是在我之前的经验上的复合。

A relationship that explained a lot, was very simple, but I had simply never seen it displayed visually before.

此外,安迪优雅地详述了每一个优化概念背后的利弊,并将其与数学符号联系起来,这种方式非常棒。虽然我知道这个概念,但我以前从未真正用符号来看它们。总的来说,这是非常好的一周。

第 7 周—支持向量机

这是我第一周没有真正了解这个主题。我知道支持向量机,我知道它们相对简单,但是我以前没有真正使用过它们。尽管如此,因为我怀疑支持向量机背后的理论和数学很简单,所以我在几个工作日晚上度过了这个星期。

我很享受这一周,我还在从第五周的恢复中,所以缺乏强度是一种解脱。它很好地涵盖了支持向量机背后的直觉,还引入了高斯核,这也是我意识到但却无意识地回避的东西。我发现关于何时何地使用支持向量机的部分及其背后的直觉特别有用。

The SVM model decision boundary built during the programming exercise.

编程练习可能太简单了,我本来想手动实现一个 SVM 模型,但我们只是定义了一个高斯核函数,这非常简单。练习的后半部分很有趣(但也很简单),因为我们使用支持向量机来研究垃圾邮件分类。这让我想起了我在介绍中提到的许多大型商业 ML 项目,其中我使用递归神经网络(RNNs)和 word2vec 以及其他多种方法来分类客户电子邮件,这很酷!

第 8 周——无监督学习

我这周还没有接触过无监督学习。我知道 K-means 聚类背后的基本概念,但仅此而已。我意识到的第一件事是 K-means 超级简单,这是一种解脱!优化本质上与高斯核函数相同(现在我想到了许多其他优化函数)。尽管如此,它还是非常有趣,我可以看到它非常有用。

后半周看主成分分析(PCA)。在高层次上,我对此有一些了解,但非常少。我曾经使用过一个叫做 t-SNE 的改进版本来进行单词向量可视化,但是从来没有深入研究过它的内部工作原理。就这门课的范围而言,我认为 PCA 已经讲得很好了,而且也不太难,我怀疑这很大程度上是由于吴恩达的深刻理解和教学能力。

最后,编程练习并不太难。我发现编码逻辑比第 6 周和第 7 周稍微难一点,但也不太难。我发现这个练习对于完成 K-means 和 PCA 非常有用。

第 9 周—异常检测和推荐系统

同样,我对本周的内容没有真正的经验。前半部分着眼于使用高斯和多元高斯分布(或密度估计)的异常检测。这非常直接,但非常有用,我打算测试实现异常检测的多元高斯分布,作为我经常使用的数据分析工具的附加功能!

本周后半周将重点讨论推荐系统。就我个人而言,我不认为我会发现这很有用,但它肯定很有趣,我喜欢学习复杂程度越来越高的几种算法的形式。

第 10 周和第 11 周

这两周很短,没有编程作业。更多的是整理和总结我们已经学过的东西。我在从北京到伦敦的长途飞行中完成了这两个星期!幸运的是,因为没有编程作业,你可以下载视频,并从你的手机上完成 2 个测验,这太棒了!

虽然很短,但我仍然发现 10 和 11 都很有用,是结束课程的一个很好的方式。

结论

一个优秀的,全面的机器学习基础。优点包括:

  • 涵盖了广泛的 ML 方法
  • 不害怕解决数学问题,吴恩达在教授直觉方面非常出色
  • 课程的重要部分集中在神经网络基础上
  • 惊人的覆盖如何实际应用方法和大多数 ML 工程师的典型陷阱

骗局

  • 后来的编程任务有时过于抽象,后来的几周感觉像是,写一个计算,让其余的预写代码做繁重的工作

最终赞成/反对

  • 编程作业是在 Octave 中完成的——这是一个允许学习者绕过许多其他语言可能出现的语法/逻辑问题的程序。但这是一个缺点,因为它不是一种在行业中特别广泛使用的语言…

总的来说,我相信在课程结束时,会有更具挑战性和更深入的作业,但除此之外,我真的很喜欢这门课程,我觉得我从中受益匪浅。我强烈推荐任何想进入 ML/数据科学或者想巩固基础的人。

请让我知道你的想法或在下面的回复中提问!

在这个课程之后,我开始了 IBM 的高级数据科学专业化,如果您对我在第一个课程中的关键收获感兴趣,请参见这里:

[## 对 IBM 可伸缩数据科学基础的回顾

我的想法是,在 IBM 的高级数据中,对可伸缩数据科学基础中的关键概念进行分解…

towardsdatascience.com](/a-summary-of-the-advanced-data-science-with-ibm-specialization-1-4-5caf48c011df)

谢谢,

数据科学的路线图

原文:https://towardsdatascience.com/a-road-map-for-data-science-d1977504a72b?source=collection_archive---------6-----------------------

什么是数据科学?

数据科学在最基本的层面上被定义为使用数据来获得洞察力和信息,从而提供某种程度的价值。数据科学发展迅速,有着广泛的可能性,因此用这个基本定义来限制它是很基本的。该定义的延伸是,数据科学是编程、数据可视化、命令行工具、数据库、统计、机器学习等技能的复杂组合,目的是分析数据并从大量数据中获得见解、信息和价值。

对于那些对数据科学的更多细节和它是什么感兴趣的人,你可以从这里的这本书中学到更多…

Python 编程

你应该学习的第一件事是一些基本的 python 编程。开始学习语法、变量和数据类型、列表和 for 循环、条件语句、字典和频率表、函数和面向对象的 Python。

对于 python 编程来说,这是你需要的唯一资源

数据分析和可视化

现在我们想学习数据分析和可视化。首先,您将希望通过学习 pandas 和 numpy 来清理和探索您的数据。然后,您将需要学习 matplotlib 来进行探索性的数据可视化和用数据讲故事。

这里的是一本让你开始动手进行数据分析的好书。

命令行工具

接下来,您将需要了解如何导航文件目录、创建和删除目录、如何编辑和管理文件及其权限、如何从命令行使用程序,以及如何创建虚拟环境。您还会想了解用于版本控制的 git 和 GitHub。

我发现进入命令行的最好方法是每天使用它… 这里有一个关于使用命令行的免费速成班

数据库

您将希望学习用于查询数据的 SQL 以及用于高级数据库管理的 PostgreSQL。您还应该知道如何使用 API 和 web 抓取来创建自己的数据集。也可以尝试学习 spark 和 map-reduce。

对于 SQL ,这里有一个很好的实践资源,可以让您立即开始使用 SQL。

统计数字

接下来,您需要学习统计学基础知识,包括抽样、频率分布、平均值、加权平均值、中值、众数、可变性测量、Z 分数、概率、概率分布、显著性检验和卡方检验。

统计学习简介统计学习要素将为你提供一个统计基础,让你成为所有统计工作的专家…

机器学习

你需要学习至少 10 种机器学习的基本算法:线性回归、逻辑回归、SVM、随机森林、梯度推进、PCA、k-means、协同过滤、k-NN 和 ARIMA。

您还需要了解如何评估模型性能、超参数优化、交叉验证、线性和非线性函数、基础微积分和线性代数、特征选择和准备、梯度下降、二元分类器、过拟合和欠拟合、决策树、神经网络,然后您应该用这些技能构建一些东西,甚至尝试一些 kaggle 竞赛。如果你对这些感兴趣,你也可以继续学习更高级的话题,比如 NLP 和 AI。

这里有一本非常好的书,可以让你亲自动手学习机器…

你应该有专门的技能

一旦你掌握了基本技能,我建议你在一件事情上变得非常擅长,比如深度学习、人工智能、统计学、NLP 或其他东西,因为它让你成为特定技能的关键人物,如果你想做的话,它看起来非常适合工作面试。

项目

你真的应该边走边建一些项目。我建议您在学习了基本的 python 和数据可视化工具之后再构建东西。边做边学是真正学习数据科学所需技能的最佳方式之一,它也向其他人证明了您确实可以用数据构建一些东西。

开始数据科学职业生涯:

你会想建立两个先进的项目,你可以把它放在简历或投资组合:

  • 这表明您可以进行端到端的数据科学项目
  • 那么第二个应该是展示你专业技能的项目
  • 确保你的项目是像样的,有良好的文档记录,易于理解,并把它们放在 GitHub 上
  • 制作一份出色的简历,突出并传达适合你申请的特定工作的正确信息
  • 创建一个可靠的 LinkedIn 档案,这样招聘人员可以找到你,你也可以使用 LinkedIn 申请工作

您的投资组合:

  • 你的项目应该讲述一个容易理解的故事
  • 应该清楚地看到你的结果
  • 应该用高质量的、有组织的代码很好地记录
  • 包括清楚地写下你做了什么以及为什么
  • 证明您可以胜任数据科学家的工作

你的简历:

  • 应该很容易在 6 秒或更短的时间内找到相关信息
  • 只强调最好/最重要的经历
  • 视觉上在千篇一律的应用程序海洋中脱颖而出
  • 使用正确的公式从商业影响的角度来描述你的项目和经历(即使它们是个人/学术项目)
  • 格式:你做了什么->如何做->产生了什么影响
  • 不好:用 python 内置推荐系统
  • 好:使用协同过滤和矩阵分解在 python 中构建推荐系统,使购物篮大小增加了 3%,年收入增加了 300 万美元
  • 确保你的简历易于阅读——使用 www.readable.io 并以五年级的阅读水平为目标
  • 使用www.jobscan.co确保你有合适的关键词

你的 LinkedIn:

  • 将你的经历从简历中转化到你的 LinkedIn 上
  • 写一份总结,展示你独特的技能和个性
  • 拍摄一张友好的专业个人资料照片,让你更值得信赖
  • 在技能部分填写正确的技能,这样招聘人员就能找到你(去掉那些让你的简历变得杂乱的多余技能)
  • 开始通过 LinkedIn 申请工作
  • 发送跟进信息—(找到 3-5 名关键决策者(这些人很可能是你申请的公司的人力资源部的人)并向他们发送跟进信息)
  • 快速简单地展示你对他们公司的热情
  • 简要介绍你的独特技能,以及它们将如何帮助公司(只是简单介绍一下你能做些什么)
  • 保持跟进信息不超过 5 句话。(越短越好,更容易被阅读)

感谢你阅读我的文章,我希望你能从中有所收获。

我正在创建一些教程、指南和完整的数据科学课程,以帮助所有需要它的人,我计划很快发布它…

深度学习的路线图

原文:https://towardsdatascience.com/a-road-map-for-deep-learning-b9aee0b2919f?source=collection_archive---------11-----------------------

深度学习是机器学习的一种形式,它允许计算机从经验中学习,并从一个概念层次中理解事物,其中每个概念都是从一个更简单的概念中定义的。这种方法避免了人类指定计算机需要的所有知识的需要。概念的层次结构允许计算机学习复杂的概念,通过许多层的深层设置将它们建立在彼此之上。

第 1 部分:应用数学

当谈到学习深度学习时,你需要学习的第一件事是应用数学,这是深度学习的基本组成部分。

线性代数

线性代数是数学的一个分支,广泛应用于整个工程领域。然而,由于它不是离散数学的一种形式,许多计算机科学家对它没有多少经验。对线性代数的良好理解对于理解和使用许多机器学习算法是必不可少的,尤其是那些涉及深度学习的算法。

线性代数要知道的话题:

标量、向量、矩阵、张量、乘法矩阵和向量、单位矩阵和逆矩阵、线性相关性和跨度、范数、特殊矩阵和向量、特征分解、奇异值分解、Moore-Penrose 伪逆、迹算子和行列式。

概率和信息论

概率论是我们用来表示不确定性的数学概念。它提供了一种量化不确定性的方法。在人工智能应用中,我们主要以两种方式使用概率:

首先,它告诉我们我们的人工智能系统应该如何推理。

第二,我们可以用概率和统计来分析人工智能系统的行为。

从概率上知道的话题:

随机变量,概率分布,边际概率,条件概率,条件概率链规则,独立性和条件独立性,期望,方差和协方差,常见概率分布,常用函数的有用性质,贝叶斯规则,连续变量,信息论,概率模型。

机器学习的数值计算

机器学习算法几乎总是需要大量的数值计算。这通常指的是 ML 算法用来解决数学问题的迭代过程。常见的操作包括优化(找到使某个函数最小化或最大化的值)以及求解线性模型和方程组。

机器学习中数值计算的学习主题:

溢出和下溢、调节、基于梯度的优化和约束优化

机器学习基础

深度学习实际上是一种特殊的机器学习。要理解深度学习,必须对机器学习有扎实的理解。您需要了解诸如什么是学习算法(如线性回归算法)、如何使数据适合该算法、在数据中寻找模式以及超参数调整等内容。机器学习最终只是非常复杂的应用统计学,它使用计算机,因为它们可以更容易地估计复杂的函数。

机器学习要学习的主题:

学习算法、容量、过拟合和欠拟合、超参数、验证集、估计器、偏差和方差、最大似然、贝叶斯统计、监督学习算法、非监督学习算法、随机梯度下降和构建机器学习算法

第 2 部分:深度学习现代实践

深度学习为监督学习提供了一个强大的框架。通过创建一个神经网络,并在每一层中添加更多的层和更多的单元,你就有能力表现越来越复杂的功能。

深度前馈网络

深度前馈网络,也称为前馈神经网络,或多层感知器,是典型的深度学习模型。这些前馈网络之一的目标是逼近某个函数 f。

从深度前馈网络学习的主题:

基于梯度的学习、隐藏单元、架构设计、反向传播和其他差分算法

深度学习的正则化

机器学习中的一个常见问题是如何创建一个不仅对训练数据,而且对新输入都表现良好的算法。ML 中的许多策略旨在减少测试错误,通常以增加训练错误为代价。这些策略被称为正规化。深度学习的众多目标之一是开发更有效的正则化策略。

深度学习正则化要学习的主题:

参数范数罚分、作为约束优化的范数罚分、正则化和欠约束问题、数据集扩充、噪声鲁棒性、半监督学习、多任务学习、早期停止、参数捆绑和参数共享、稀疏表示、打包和其他集成方法、丢弃、对抗训练、正切距离、正切 Prop 和流形正切分类器。

训练深度模型的优化

深度学习模型在许多方面都涉及到优化。例如,主成分分析等模型中的推理涉及到解决优化问题。深度学习中最困难的优化问题是神经网络训练问题。

深度模型训练优化要学习的主题:

学习与纯优化、神经网络优化的挑战、基本算法、参数初始化策略、具有自适应学习速率的算法、近似二阶方法、优化策略和元算法

卷积神经网络

卷积神经网络是一种专门用于处理数据的神经网络,具有已知的网格状拓扑。这方面的例子有时间序列数据,它可以被看作是以规则的时间间隔采样的一维网格,我们也有图像,它可以被看作是二维像素网格。卷积是一种特殊的线性运算。

CNN 需要学习的主题:

卷积运算、动机、池化、卷积和池化、基本卷积函数的变体、结构化输出、数据类型、高效卷积算法以及随机或无监督特征

递归神经网络

递归神经网络是用于处理顺序数据的神经网络家族。这些与 CNN 非常相似,事实上它是专门用于处理网格值的,但是它们使用一个系统来处理一系列值,并对它们进行归纳。

学习 RNNs 的话题:

展开计算图、双向 rnn、编码器-解码器序列到序列架构、深度递归网络、递归神经网络、长期依赖性的挑战、回声状态网络、泄漏单元和多时间尺度的其他策略、长短期记忆(LSTM)和其他门控 rnn、长期依赖性的优化、显式记忆

深度学习方法论

成功应用深度学习技术需要的不仅仅是对现有算法和解释它们如何工作的原理的良好知识。在机器学习系统的日常开发过程中,实践者需要了解是否要收集更多的数据、增加或减少模型的复杂性、添加或删除特征、改进模型的优化、改进模型中的近似推理或调试模型的实现等等。所有这些都非常耗时,因此能够确定正确的行动方案非常重要。

深度学习方法论主题:

性能指标、默认基线模型、确定是否收集更多数据、选择超参数以及调试策略

深度学习应用

深度学习可用于解决计算机视觉、语音识别、自然语言处理和其他领域的应用。当涉及到设计算法时,这些任务中的每一个都需要某种程度的专门化。

深度学习应用需要学习的主题:

大规模深度学习、计算机视觉、语音识别和自然语言处理

第 3 部分:深度学习研究主题

这一节将只列出更有雄心和更先进的深度学习方法的主题。

线性因素模型

概率 PCA 和因子分析、独立分量分析(ICA)、慢特征分析、稀疏编码和 PCA 的流形解释

自动编码器

欠完整自动编码器、规则化自动编码器、代表性能力、层大小和深度、随机编码器和解码器、去噪自动编码器、具有自动编码器的学习流形、收缩自动编码器、预测稀疏分解以及自动编码器的应用

表征学习

贪婪的逐层无监督预训练、迁移学习和领域适应、因果因素的半监督解开、分布式表示、深度的指数增益以及发现潜在原因的线索

深度学习的结构化概率模型

非结构化建模的挑战,使用图形描述模型结构,从图形模型中采样,结构化建模的优势,了解依赖关系、推理和近似推理,以及结构化概率模型的深度学习方法

蒙特卡罗方法

抽样和蒙特卡罗方法,重要性抽样,马尔可夫链蒙特卡罗方法,吉布斯抽样,以及分离模式之间混合的挑战

配分函数

对数似然梯度、随机最大似然和对比散度、伪似然、分数匹配和比率匹配、去噪分数匹配、噪声对比估计和估计配分函数

近似推理

作为优化的推理、期望最大化、映射推理和稀疏编码、变分推理和学习以及学习的近似推理

深度生成模型

波尔兹曼机器、受限波尔兹曼机器、深度信念网络、深度波尔兹曼机器、用于实值数据的波尔兹曼机器、卷积波尔兹曼机器、用于结构化或顺序输出的波尔兹曼机器、其他波尔兹曼机器、通过随机操作的反向传播、定向生成网络、从自动编码器抽取样本、生成随机网络、其他生成方案以及评估生成模型

所有这些信息将导致对深度学习的超级坚实的理解:

以下是一些资源,涵盖了大部分(如果不是全部)上述主题:

伊恩·古德菲勒的深度学习书籍

神经网络和深度学习

我还致力于创建一个专属社区,我将与这些人一起成为数据科学家,我在这里创建了一个小组,它完全免费加入:数据科学,机器学习,深度学习&人工智能

一个机器人说你得了癌症

原文:https://towardsdatascience.com/a-robot-says-you-have-cancer-294937f3a69?source=collection_archive---------13-----------------------

Someday soon, your doctor could be a robot. Would you trust it? Photo by Kendal James.

如果电脑给你健康建议,你会相信吗?如果一个计算机程序告诉你,你有一个侵略性的癌症肿瘤,并推荐一个有风险的程序来挽救你的生命,你会抓住这个机会吗?

就在几十年前,从计算机那里接受医疗建议的想法似乎来自于一部老的《杰森一家》卡通片或《星际迷航》中的一集。医学是复杂的,很难想象计算机程序能够成功地取代人类医生,能够将许多不同的报告(测试结果、X 射线和其他扫描以及患者信息)结合成一个单一的诊断。

然而,如今让计算机程序扮演医生的想法似乎更接近现实。但是,虽然计算机在诊断疾病方面可能越来越好,但人类准备好倾听了吗?

计算机程序可以匹配(或超过)人类诊断的准确性

人工智能程序处理复杂医疗问题并取得惊人成功的一个例子是放射学,即阅读 X 射线、CAT 扫描和其他身体内部可视化的实践。这些图像通常模糊不清,以至于放射学有时被描述为“更像一门艺术而不是科学”。即使是经验丰富的放射科医生有时也很难确定 X 射线上的黑点是癌性肿瘤,还是只是一个污点。

An example training X-ray, this time with the cancerous mass helpfully circled. Source: NIH

事实证明,计算机可以做得更好。如果给一个算法一大组 X 射线作为训练数据,它可以胜过真正的医生——在一个案例中,一个算法成功诊断了 75%的结核病病例,相比之下,人类医生的正确诊断率为 62%

不仅仅是 x 光。人工智能算法成功地从痣和皮肤病变的照片中诊断出皮肤癌,其速度相当于委员会认证的医生。另一种算法证明通过读取心电图数据检测心律失常(不规则心跳)比人类医生更有效。一些算法甚至试图通过分析语音来诊断认知障碍和智力下降,使用单词之间的停顿和词汇水平等措施来确定某人是否患有痴呆症。

所以电脑可以比人类医生更准确。有人会听他们的吗?

医生需要同理心吗?

最近,加州弗里蒙特的一家医院制造了一条新闻——而且不是好消息——一名 78 岁的病人被机器人告知他即将死亡。

An example of a telepresence robot. Source: Wikimedia

这不是人工智能驱动的超级计算机。这是一个人类医生使用远程呈现机器人与病人进行远程交流。因此,尽管有 clickbait 这个标题,但人工智能并没有冷漠地通知病人他要死了——一名人类医生选择通过相当于 FaceTime 视频电话的方式来传达这一痛苦的消息,而不是亲自去。

然而,这篇文章呼应了任何时候讨论人工智能取代医生时都会出现的一个共同主题:算法没有同理心,不能像有血有肉的医生那样传递坏消息或艰难的诊断。

这篇文章还提出了一个问题,即医生目前在同理心方面是否比机器人做得更好。许多医生在向病人传达坏消息时都很有同情心和爱心,但有些医生已经采用了机械的、非个人化的语气。这些容易出错、低同理心的医生会成为第一批被更精确的机器人取代的人吗?

一个可能的未来:机器人诊断,人类分娩

展望未来,医学可能会变得更加需要共同努力,医生依靠计算机来完成诊断疾病的繁重工作,但同时在医患关系中保持一个人来提供解释和安慰。

“The algorithms say that the tumor is likely serious, but we have options and solutions. It will be okay.” Photo by Arvin Chingcuangco.

当然,这个概念不太可能在医学界顺利推行。转向依赖计算机和算法来诊断医学疾病可能会引发关于工资和补偿的问题——如果放射科医生的大部分工作由计算机程序处理,他们还应该得到平均每年 371,000 美元的报酬吗?

许多医生已经在与侵入医学的技术作斗争。人们普遍抱怨电子健康记录(EHRs 越来越普遍,许多医生表示,电子健康记录最终不完整、难以填写,并且无法取代与患者的面对面交流。医院管理人员和高管希望改善病人的结果并节省资金,他们可能会支持增加算法的使用,以取代由活体医生处理的部分工作量——但他们将与医生斗争,可以理解的是,医生不希望他们的工作被计算机取代。

AI 不会完全取代医生。算法可能在诊断问题方面表现得更好,但我们可能仍然需要人手来开处方,复核诊断结果,最重要的是,带着同情和善意向患者传达结果。

但是也许在不久的将来,当医生给你看 x 光片时,你可以礼貌地请求电脑给出第二种意见。

机器人的旅程

原文:https://towardsdatascience.com/a-robots-journey-ce4fcd30aba1?source=collection_archive---------43-----------------------

送货机器人眼中的世界

Picture courtesy to Starship Technologies

想象,试着从另一个人的角度看这个世界是很有趣的。去思考做动物的感觉。

我们的乌龟跑了。他不开心吗?我们的鹦鹉一头撞在墙上。她抑郁了吗?我们的猫曾经在我的床上拉屎。她恨我吗?我们狗的蛋蛋被割掉了。他生气了吗?这些事情让我整个童年夜不能寐,因为没有答案。

如今,我过得更轻松了。我的周围不是由进化塑造的不可预测的大块肉,而是按照形式逻辑行事的机械人造生物。这些生物的每一个反抗行为都可以通过计算机代码追溯到其根源并被清除。

作为一名工程师,我的工作就是——把自己放在一个六轮自动送货机器人的位置上,驯服它。这些问题让我成年后夜不能寐,因为我一直在寻找答案:

如何避免撞到东西?

像这些人一样,机器人的眼睛是成对的。两只眼睛很容易测量到世界上物体的距离,以三维方式看事物。

当光线从物体上反射回来,进入我们的眼睛——或者对于机器人来说,进入相机——时,图像就在我们的视网膜上形成了。由于我们的眼睛在头上的位置不同,它们捕捉的图像也略有不同。如果我们将它们重叠在一起,我们会发现图像上相应物体的位置并不完全匹配。所有的东西都会水平移动,在右边的图片上看起来稍微偏左一点,反之亦然。

转折:一个物体从一个图像转移到另一个图像的次数越多,它就离我们越近。它移动得越少,越远。这是一个惊人的数学事实。为了了解一个物体在真实世界中离我们有多远,我们只需要测量它在图像之间移动的毫米数。

问题是:匹配对象。为了计算一个物体在两幅图像之间移动了多少,我们必须首先在两幅图像上识别它。人类在这方面特别擅长,我们下意识地这么做。机器人在这方面特别糟糕——感谢上帝,因为它让我有工作。

如何安全过马路?

机器人是行人——它在人行道上行驶。和行人一样,它被十字路口所困扰。它田园诗般的、无忧无虑的漫步很快被恐怖所取代,因为现在有一股邪恶的两吨重的野蛮人必须通过。快点,你可能会被冷血地击倒。摆摊,你可能会因为提供冷食而被拆穿。

巨大的任务需要巨大的智慧。机器人的汽车大脑是一个很深的层叠,每一层都是由数百万人工神经元组成的薄片。不同的层类似于传送带上的专业工人,随后的层建立在前面的结果之上。

一幅图像——机器人无法识别的原始像素的大杂烩——来自摄像机。最底层识别代表边缘的像素组。下一层神经元识别从边缘构建的形状——圆形、矩形和三角形。第三层将这些几何图形放在一起,以识别整个物体:车轮、门、窗和车牌。最上层组装各种汽车部件以识别完整的车辆。

正是这个单一用途的大脑,专门致力于防止机器人成为马路杀手,允许安全过马路。相比之下,动物只将一小部分思维能力用于识别汽车。这就是为什么你到处看到死的是松鼠,而不是机器人。

如何不迷路?

唯一比延迟交货更糟糕的事情是货物丢失。为了避免如此多的痛苦,机器人已经从伦敦出租车司机的剧本中吸取了一页。

为了获得驾照,这些崭露头角的出租车司机需要通过世界上最难的地理测试(T1),这是一项对伦敦数万条街道、地标和旅游目的地的严格测试。为了准备考试,考生们在将近五年的时间里,数百次开车穿过这座城市,试图将伦敦错综复杂的动脉蚀刻进他们的大脑。

同样,机器人也需要练习。在他们被给予城市的自由之前,他们在一名人类监督者的陪同下被手动驾驶穿过城市。但是与黑人出租车司机的希望不同,机器人只需要握一次手。

如果说计算机擅长什么,那就是记忆。在他们独特的地图绘制过程中,机器人每秒钟沿着整个路线拍摄多次照片。接下来,它从图像中提取相关的物体——像公园长椅的单块木板或烟囱的砖块一样细小的物体。最后,耗时的算法计算出所有这些物体的真实世界坐标,然后存储在一个巨大的数据中心,这个数据中心构成了机器人非常详细的存储器。

此后,每当现在自主的机器人不确定自己的位置时,它就在数据库中搜索与其当前环境最接近的匹配。像伦敦出租车司机一样,他们的人工对应物用存储在他们记忆中的全球知识绘制了当地场景——他们看到的物体如何相互关联——这些物体如何与整个城市相关联。机器人只是在几天内建立这种理解,而不是几年。

很快,你就会看到这些送货机器人中的一个在你家附近辛勤工作。通常,你会看到他们最好的,高效的和有效的。

偶尔,你也会看到他们最糟糕的一面。也许在人行道上迷路了。或者害怕过马路。原谅他们的笨拙。正如西奥多·罗斯福所说:“唯一从不犯错误的人是从不做任何事情的人。”机器人做很多事情。他们送货上门。

为算法鼓掌

原文:https://towardsdatascience.com/a-round-of-applause-for-algorithms-3322f6aa1f8e?source=collection_archive---------22-----------------------

拯救生命和打开新的大门

外语。黑色和白色。无名演员。这是一场完美的描述风暴,让我对电影失去兴趣。但是,网飞给了我 90 多分。

虽然这个在线流媒体巨头知道我所有肮脏的观看秘密(完全披露:超级英雄和太空战),但我也是。我不会自愿选择罗马。但是,网飞想当然地认为自己知道一些连我都不知道的事情。所以我给了罗马一个机会。我没有失望。

现在我并不自称理解算法背后的内在魔力。我认为知情者是科技奇才的精英俱乐部。但是有一件事我明白了。算法为机器学习和深度学习工具提供动力,使处理和分析一组无限的数据点成为可能。一些我的大脑,你的大脑,甚至爱因斯坦的大脑都无法理解的事情。网飞从我令人上瘾的暴饮暴食习惯中收集了大量数据,然后输入其算法,这些数据表明我会喜欢罗马。一些连我都没有意识到的事情。

对很多人来说,这很可怕。

48%的欧洲人不知道什么是算法。不到一半的人知道算法已经被用于他们生活的许多领域。

算法受到了不好的指责:它们单枪匹马地引发了民主的垮台。它们引发不良消费行为。他们将对失去成千上万的工作岗位负责。他们有偏见。他们歧视。他们的决定不可理解,也不可追踪。对于一本基本上被美化了的指导手册来说,有很多负面的报道。

让这些担忧雪上加霜的是一大群政治顾问、半生不熟的监管措施和普遍的数字文盲。这一切也是一场完美风暴。这是在延续一个错误的说法。一个把更多的注意力放在算法哪里出了问题,而完全忽略了它们哪里做得非常非常正确的问题。

算法重新定义诊断

当慕尼黑白血病实验室扩大其设施和人员时,对最先进的下一代测序(NGS)系统进行了大量投资。大数据的大机器。

科学是复杂的,但简单地说:这些 NGS 系统使分析整个基因组序列(WGS)成为可能,提供了更多的数据,更快地,对我们的遗传物质。为什么这很重要?WGS 提供的数据是检测致病突变、遗传疾病和疾病爆发的关键。而正是这些数据,由算法指令的机器学习应用可以比人眼更好更快地进行分析。

算法能够以比显微镜更高的精度检测突变和畸变:治疗后检测到 0.3%对 5%的残留白血病细胞。

在 NGS 诊断学的发展中发挥最大作用的算法之一是对齐算法。它可以排列由 NGS 系统确定的许多冗长的 DNA 和 RNA 序列。对于科学家和医生来说,考虑到大量的数据,这是很困难的,甚至是不可能的。一旦这些序列对齐,就有可能进行比较并检测出遗传密码中的异常。而且非常非常快。

对于像白血病这样的疾病,时间是至关重要的,速度和数据可能意味着生与死的区别。

“精准医疗寻求利用基因组数据帮助在正确的时间为正确的患者提供正确的治疗。”

比对算法提供的分析也在以其他方式推进癌症治疗。肿瘤的测序提供了维持肿瘤生长的特定遗传异常的详细信息。这意味着肿瘤学家可以为患者提供专门针对其基因突变的疗法。这一精确医学领域有可能消除治疗中的大量猜测,这意味着患者将不再被迫接受不必要的复杂程序。他们也将更快地获得最好的、最有针对性的治疗,这对于侵袭性衰弱疾病来说非常重要。

机器穿衣

虽然不是所有的算法都带着这样的利他意图运行,但它们在功能上是一致的。他们制定了一套解决问题和执行任务的规则。其中一项让他们声名狼藉的任务恰好是人类臭名昭著的糟糕任务:做决定。

这就是 Stitch 的生意所在。是 USP?数据科学。这对一家软件公司来说并不罕见。但是史迪奇绝不是。该公司是一家在线服装零售商。成千上万中的一个。但是有一个转折。Stitch 完全承担购物决策过程。

现在有很多人可能会对算法为我们着装的未来感到恐惧。任何读过算法写的诗,听过算法创作的音乐,看过算法生成的图像的人都见证了反乌托邦噩梦的内容。创造性许可不应该完全委托给机器。

“机器学习将改变技术的每一个方面,但没有机器能够模仿人类思维的创造能力。”山塔努·纳拉延,土坯

但请记住,算法可以以人类无法做到的方式导航数据。你给他们的数据越多,他们驾驶的学习工具就越聪明。这就是史迪奇所利用的。

该公司的造型算法在数据中翻腾:客户数据、产品数据、反馈数据。尺寸,喜欢的颜色,流行的款式。而且每件商品有 30 个以上的测量属性:从有纽扣衬衫的肘部到肩部的距离到裤子的内缝长度。

一旦算法“选择”了你的完美新线,它们会将最终决定交给人类造型师,也是由算法选择最适合你的风格。这些造型师对出现在你家门口的东西做最后的决定。

公司的目标之一?消除对尺寸标签的需求,只为每位顾客提供“你的尺寸”。任何买过牛仔裤的人都会看到其中的价值。就我个人而言,我会很高兴地跳过心理创伤和自我粉碎的战斗,挤进 X 号牛仔裤,却一无所有地回家。

即使在最强大的时候,人工智能也不会取代人类的智能,它只是帮助人们更好更快地做他们喜欢的事情。

但是还有一个好处。一个很多人不考虑的问题。让我们回到罗马。一部充斥着超级英雄和科幻惊悚片的单色外国电影。打破我们的习惯和模式可能是巨大的努力。打开我们的思想,我们的视频图书馆,我们的壁橱去接受新事物。不是因为我们必然厌恶新事物,或者可以毫不含糊地说我们不会喜欢某样东西。而是因为我们是习惯性动物。

尽管对一些人来说这可能令人毛骨悚然,但新的数字商业模式正在利用算法来比我们更好地预测我们的好恶,也许我们应该将其视为一个机会。拓展我们视野的机会,摒弃我们的偏好。就我个人而言,我很高兴网飞向我展示了一个超越漫威宇宙的世界。

内核和非内核算法的运行速度基准

原文:https://towardsdatascience.com/a-running-speed-benchmark-for-kernel-non-kernel-algorithms-b7db5bfabcef?source=collection_archive---------28-----------------------

非内核算法总是比基于内核的算法快吗?

The Kernel method, Wikipedia, CC BY-SA 4.0, https://en.wikipedia.org/wiki/Kernel_method

多年来,我知道线性 SVM 比内核版本快,这是常识,而不是我测试过的东西。不久前,我想知道是否所有基于内核的算法都比它们的非内核版本慢。下面的比较用作几个众所周知的算法的运行时间基准。

内核方法因使用了内核函数而得名,这使得它们能够在高维、隐式 特征空间中操作,而无需计算该空间中数据的坐标,而是简单地计算特征空间中所有数据对的图像之间的内积。该操作通常比坐标的显式计算在计算上更便宜。这种方法被称为“内核技巧”——来自维基百科

想直接跑这个基准的可以在我的 Github 里找笔记本。用于该基准的数据集是乳腺癌数据集,它很小,但众所周知。你可以用其他数据集做实验,看看实证结果是否保持不变,我怀疑会的。

我们将比较以下算法:

  1. 线性 SVM vs 线性核 SVM
  2. PCA vs 线性核 PCA
  3. K-means vs 内核 K-means
  4. PDF vs KDE (高斯)vs 高斯 KDE

这种比较是双重的,一次是“适合”,另一次是“预测”或“转换”。请注意,我找不到概率密度函数(PDF)的等效转换方法。支持向量机(SVM)、主成分分析(PCA)、核密度估计(KDE)和 K-means 是众所周知的,并且具有相关的功能,对于核-K-means,我必须查看一个名为 Tslearn 的外部包。

Table 1: Running time for ‘fit’

Table 2: Running time for ‘predict’ or ‘transform’

结果和讨论

这两种类型之间似乎有很大的差异,对于“fit”(表 1),值得注意的是线性 SVM 比它的内核对应物快两倍,PCA 快大约 30 倍,K-means 快大约 40 倍。对于“预测”(表 2)或“转换”,我们看到的是相同的画面,但比例不同。速度差异可能有多种原因。如果你感兴趣的话,值得检查一下每个算法的实现和时间复杂度,这里没有涉及。

除非你真的需要某个算法的内核版本,否则应该首先考虑非内核版本。值得注意的是,最快的版本存在于 Sklearn 中,这意味着您不需要查看其他包。

Ori Cohen 博士拥有计算机科学博士学位,专注于机器学习。他领导着 Zencity.io 的研究团队,试图积极影响市民的生活。

目的感使人和机器人能够更好地合作

原文:https://towardsdatascience.com/a-sense-of-purpose-enables-better-human-robot-collaboration-fbe64d0ae913?source=collection_archive---------23-----------------------

机器人需要理解人类活动的意义,才能安全有效地与人类并肩工作。

那是 1954 年。两个美国人,发明家乔治·德沃尔和企业家约瑟夫·恩格尔伯格在一个鸡尾酒会上讨论他们最喜欢的科幻小说作家。迪沃最近在专利局提交了他的最新想法,第一个通用自动化Unimate用机器人机器取代工厂工人的早期努力。他的创造性天才已经诞生了现代世界的两个最早的技术奇迹:一个是带有光电管和真空管的自动门幻影门卫,另一个是根据需求使用微波能量烹饪热狗的机器 Speedy Weeny

Engelberger 发现 Unimate 工业转移机如此引人注目,以至于七年后,专利一获得批准,他就成立了一家公司来发展 Devol 先生的想法。那家公司的名称是 Unimation 公司 。他们的"编程物品传送",后来重新命名为"机械手"最后是"机器人"(人们只能怀疑 Devol 和 Engelberger 是否在那些鸡尾酒会上讨论过艾萨克·阿西莫夫第一次使用术语" 机器人 ")最终作为一个材料处理和焊接的单元进入了全面生产。

Unimate makes its public debut in London. “Unimate. A machine that can reach up to seven feet and perform a multitude of tasks in the factory or laboratory, as skillfully as a man but without getting tired. It’s controlled by a built-in memory system which you lead just once through the required measurements and it can then repeat it 24 hours a day, week after week”.

尤尼马特改造并加速了世界各地制造工厂的生产线通用汽车、克莱斯勒、福特和菲亚特很快认识到了其中的好处,并下了大量订单,帮助这台机器成为了过去 50 年的50 大发明之一。这只是催生一个新产业的种子:商业机器人。随着时间的推移,Unimation Inc .及其唯一的竞争对手俄亥俄州的辛辛那提米拉克龙公司(Cincinnati Milacron Inc .)将会看到几个日本和欧洲竞争对手的崛起,这些竞争对手采用了新的创新技术,如电子微处理器、伺服枪技术和电弧焊。

然而,世界可能还要再等一会儿才能看到第一个真正协作的机器人(或 cobot ),它于 2008 年安装在 Linatex 。与它的前辈不同,Universal Robot 的 UR5 重量轻,价格便宜,易于设置,可以由未经培训的操作员重新编程。

The cobot UR5. Image courtesy of Universal Robots.

“你不需要输入或计算任何东西来让机器人工作。你只需要向它展示动作”。万能机器人。

Cobots 旨在与人类共享一个工作空间 —这就是为什么 UR5 不需要放在围栏后面,可以与员工一起安全工作的。这与传统工业机器人形成鲜明对比,传统工业机器人通常被锁在笼子里,因为它们的快速移动和笨重的体积会使它们对人类不安全。一旦安装好,工厂里常见的笨重机械臂就很少动了;大多数实际上是用螺栓固定在地板上的。相反,新一代产品更轻,即插即用,并辅以传感器和视觉技术,使工作空间更易于共享。

尽管 11 年前就推出了 cobots,但 2018 年售出的所有工业机器人中只有不到 5%是协作型的(根据金融时报)。Cobots 可能不是新东西,但是它们仍然有潜力革新生产,特别是对小公司——占全球制造业的 70%。据估计,cobot 市场将从 2018 年的 1 亿多美元增长到 2020 年的 30 亿美元,因为这些灵活的机器人比传统的工业机器人便宜得多(根据巴克莱资本的数据,平均价格为每台 24,000 美元)。

Sawyer™, a high-performance collaborative robot from Rethink Robotics

预计在未来几年,cobots 在工业环境中的采用将显著增加。但是它们在其他领域的应用情况如何,比如医疗保健?

在根托夫特的哥本哈根大学医院,cobot UR5 已经被用于优化血液样本的处理和分类,帮助实验室实现在 1 小时内提供 90%以上结果的目标。Universal Robots 的机械臂还被整合到加拿大 Synaptive Medical 公司开发的Modus V,通过提供前所未有的患者解剖视图来协助神经外科手术,并以更高的精度执行侵入性更小的手术。这还不是全部。 Cobots 也开始用于其他医疗领域,例如远程呈现、康复、医疗运输和卫生

其中一些场景带来了一系列新的挑战,因为它们充满了动态和不可预测的交互,与工业环境中的交互有很大不同

例如,一个机器人护士可能被要求帮助一个病人从一个柜子中取出特定的药物。机器人将需要理解病人以任何方式表达的要求,定位橱柜,在房间内导航避开障碍物,打开橱柜,抓住正确的药物并给病人。为了处理物体,机器人需要为某种形状选择正确的抓手,了解不同的材料如何对力做出反应,以及在将它们交给人时协调反馈和联合步骤。在这些类型的互动中,人类自然会监控他们伴侣的节奏和工作量,并相应地调整他们的交接。机器人在执行任务时也需要达到类似的适应性。

操纵物体包括一系列与感知、控制和协调紧密相连的动作

Moxi is a hospital robot assistant that helps clinical staff with non-patient-facing tasks like gathering supplies and bringing them to patient rooms, delivering lab samples, fetching items from central supply, and removing soiled linen bags.

传统上,机器人技术的重点一直是通过两个指标来成功够到和抓住东西:速度和稳定性。这些是物流中特别感兴趣的,并且在很大程度上受益于计算机视觉和机器学习的最新进展。然而,当涉及到在更加灵活、不可预测的环境中与人类互动时,如医院或家中,它们可能不足以决定机器人行动的成功。

为了让合作机器人有效地导航这些新领域,他们需要了解人们如何与世界互动,这样他们就可以预测对他们的期望。

“目的”如何影响人类行为和工具使用

作为人类,我们头脑中有一个直观的物理模型。我们能够想象一个物体,以及如果我们通过推、拉、挤等方式与它互动,它会如何表现。这使得我们能够完成难以置信的操控任务,这些任务远远超出了目前机器人的能力范围。

昂热大学的研究员弗朗索瓦·奥西乌拉克认为“没有任何 意图 我们就无法感知世界”。各种文化的人类自发且几乎系统地使用工具来改造世界,创新并远离以前的技术设备。

An Oldowan chopper, one of the earliest examples of the stone industry. Ethiopia, c. 1.7 million years before our era. Source: Wikipedia CC.

这种能力根植于我们获得一项技术并将其应用于各种目标的特殊天赋,并且与我们的进化密切相关。大约七百万年前,两足行走将第一批原始人与其余的四足猿分开。我们的手可以自由地操纵物体,因此我们必须创建关于工具及其相关动作的表示。我们的大脑变得非常擅长处理复杂的空间信息,这反过来又导致了抽象和先验的思维。

不像非人类动物,他们不能理解一个动作的潜在机制,我们可以推断我们学到的与其他情况的关系。一个单一的对象可以在不同的时间提供多种可能性取决于我们追求的目的

A stone axe in various stages of manufacture, from left to right, from the Neolithic settlement of Vinelz on Lake Biel, Switzerland, c. 2700 BC. Wikipedia CC.

一百年前,w .詹姆斯写道,当我们写字时,我们看到一张纸作为题字的表面,但是如果我们需要点火并且没有其他材料可用,那张纸将是可燃材料。这个物品可以是这两个中的任何一个,或者是一个薄的东西,或者是一个碳氢化合物的东西,或者是一个美国的东西,等等,无止境。

“没有任何一种财产对任何一件事物都是绝对必要的。在一种情况下是一件事物的本质的同一属性,在另一种情况下就变成了一个非常不重要的特征。”詹姆斯,1890 年/2007 年 b,第 333 页。

我们将对象视为 启示、 处置,需要一个人在场才能实现它们。同样的技术,例如切割动作,可以用来实现几个不同的目标:觅食、狩猎、自卫。同时,使用不同的对象可以实现相同的目标。

启示使我们能够灵活地与世界互动。它们允许建立目标和实现目标的不同方式。

Human-human and Human-Robot handovers in a household scenario. From “Adaptive Coordination Strategies for Human-Robot Handovers”, Chien-Ming Huang et. al.

相比之下,大多数机器人系统都是为完成单一任务而设计的。他们通常知道需要与哪些对象进行交互,并以一种预先计划好的方式进行交互。但是在一个开放、动态的世界中,我们无法明确地说出机器人可能面临的所有可能任务的每一个细节。

将机器人系统集成到这些新环境中需要开发更好的人机交互、感知和协调。一种方法是展示机器人如何,更重要的是为什么,我们操纵物体。

教机器人如何更有效地操纵物体

将我们的一些操纵能力转移给机器人的一个好方法是,当我们在各种场景中使用工具时,让它们观察我们。

“复杂的观察可以提取适用于新情况的规则,即使是在观察多个人以不同的风格执行相同的任务时。”戈登·程。

2017 年,来自麻省理工的计算机科学和人工智能实验室(CSAIL)的研究人员开发了 C-LEARN ,这是一个允许非编码者通过提供一些关于通常如何操纵对象的信息来教会机器人一系列任务的系统,然后向机器人展示任务的单个演示

“通过将从演示中学习的直观性与运动规划算法的精确性结合起来,这种方法可以帮助机器人完成他们以前无法学习的新型任务,如使用双臂进行多步装配。”麻省理工学院的克劳迪娅·佩雷斯·达皮诺。

麻省理工学院的系统将任务的演示与机器人已经知道的世界联系起来。首先,关于如何到达和抓住具有不同约束的各种物体的信息的知识库被加载到机器人上。然后,操作员使用一系列被称为“关键帧”的相关时刻来执行任务。通过将这些关键帧与知识库中的不同情况进行匹配,机器人可以自动建议运动计划,准确率达到 87.5%。****

通过试图推断运动背后的原理,这些类型的系统比那些只是试图模仿正在演示的东西的系统灵活得多,并且可以证明在时间敏感和危险的情况下是重要的。该系统实际上是用 Optimus 测试的,这是一个为拆弹而设计的双臂机器人。该机器被教会执行诸如开门、运输物品和从集装箱中提取物品等任务,结果非常有效,以至于它学到的技能可以无缝转移到 CSAIL 的 6 英尺高、400 磅重的人形机器人 Atlas

虽然 C-LEARN 还不能处理某些高级任务,如避免碰撞或为给定任务规划不同的步骤序列,但从人类学习中获得的更多见解能够为机器人提供更广泛的能力只是时间问题。

麻省理工学院 CSAIL 的团队并不是唯一一个试图解决这个问题的团队。

来自慕尼黑工业大学的 Karinne Ramirez-Amaro 的团队一直在研究如何使用语义表征来获得和确定对示威者行为的更高层次的理解。这将允许机器人根据人类的期望预测下一个可能的运动

The iCub robot, an open-source child-size humanoid robot capable of crawling, grasping objects, and interacting with people.

Ramirez-Amaro 的框架由三个模块组成:1) 人体运动和物体属性的观察以准确提取一项任务最相关的方面;2) 通过分层解释人的行为并生成语义规则来推断目标;和 3) 模仿/再现最佳动作以达到同样的目的。

该团队用一组真实世界的场景和 iCub 测试了他们的系统,这是在 IIT 开发的人形机器人,是欧盟项目 RobotCub 的一部分。

测试的场景是做煎饼,做三明治,摆桌子

1。观察和提取任务的相关方面

iCub 被训练做的第一件事是分割一系列描述简单人类动作的视频。这是在运行中完成的,包括正常速度和快速速度,使用了基于颜色的跟踪算法和 OpenCV 库。手的位置,它的运动和速度,以及某些物体的属性都以令人印象深刻的 95% 精度确定。

2。推断演示者的目标

下一个模块使用识别出的手部动作和物体属性来寻找它们之间有意义的关系,并推断出活动,例如到达拿取切割浇注释放等。这是通过使用一系列低级抽象(广义运动,如移动、不移动、工具使用)和高级抽象(更复杂的人类行为,如闲置、伸手、拿取、切割、倾倒、将某物放在某处、释放、等)来完成的。)

Method for inferring human activities. First, the input video is segmented into hand motions and two object properties. Next, the rules are computed to infer human activities. Ramirez-Amaro.

3。再现实现目标的最佳动作

最后,使用在线运动原语选择一个执行计划,这样机器人可以重现步骤二中推断的活动。iCub被证明是一个优秀的测试平台,因为它有 53 个自由度

结果

实验证明机器人可以实时实现对各种场景任务的高精度识别和模仿,甚至包括不同条件和用户的未知场景。提取的语义表示允许构建人类活动的机器/人类可理解的描述,例如:

如果手(移动)& OBjectInHand(非)& ObjectActedOn(某物)→活动(到达)

如果手(Not_Move) & ObjectInHand(某物)→活动()

如果手(移动)和物体手(某物)→活动(把某物放在某处

结果表明,该系统可以处理新的(粒度)行为和重用模型的挑战。因为分割是通过基本的视觉过程完成的,所以这项研究可以通过包括更复杂的物体识别软件来扩大规模。研究人员认为,下一步将是通过整合基于知识的本体 和推理引擎来计算对象和活动之间的新关系并控制决策树的增长,来**按需学习行为。****

机器人知识的表示:KnowRob

我们不能保证手动存储在系统中的知识在每一个可能的不同场景下都有效,这是灵活协作机器人的主要挑战之一。为了与人类进行更自然的互动,我们需要以有意义的方式发展机器人的知识库。一个让我们离这个目标更近一步的项目是 KnowRob

KnowRob 是一个开源系统,目前正在几个机器人上使用,执行复杂的物体操纵任务。KnowRob 不是处理原始的高分辨率连续数据,而是提供按需抽象或符号视图。它的查询将所有抽象层次的推理与一个浅层知识库结合起来,这个浅层知识库作为推理算法的集成层

Daniel Beßler talks about KnowRob 2.0, a 2nd Generation Knowledge Processing Framework for Cognition-Enabled Robotic Agents.

这种通用的本体,在表现层次上有点像“胶水”,可以用添加特定领域知识或特殊用途推理方法的微观理论来扩展。为了促进这一点,所有模块共享相同的语言,即 Web 本体语言(OWL)。

KnowRob 可以表示对象和空间信息、事件和动作,对于我们关于目标和目的的分析特别有用,动作对对象的影响。例如,机器人可以搜索一个将一个设备从 设备状态关设备状态开* 的 动作,并将获得动作类TurningOnPoweredDevice*****

:TurningOnPoweredDevice
子类 :
控制物理设备
状态对象将某些物理设备
从状态值 DeviceStateOff
更改为状态值 DeviceStateOn
[…]

为了补充这一点,还有程序性的投射规则,用于计算在执行一个动作之后,具体的世界状态将如何变化。

像 KnowRob 这样的知识系统可以帮助服务机器人处理通常肤浅和符号化的指令,填补空白以生成执行所需的详细、基础和实值信息。由于 KnowRob 是开源的,由第三方开发的扩展包括关于工业装配任务、高山环境中的搜索和救援以及水下机器人等方面的知识。

结论

随着机器人工厂工人、同事和家庭助理机器人向开放环境和更复杂的任务发展,他们的知识处理系统需要应对来自动态的、以人为中心的世界的挑战

灵活、智能 cobots 的优点不限于精度、可重复性或遥操作*。此时此刻,在加利福尼亚州的帕萨迪纳,翻转汉堡的机器人每天从厨房里为 300 份订单服务,厨房热得让人无法忍受,大多数员工在几周内就辞职了。现在,他们可以自由地专注于接待客户。*

Riken and Sumitomo Riko labs in Japan have created a robotic nurse (Bear) as the country prepares for a growing elderly population.

医院里,机器人正在准备载玻片和装载离心机,运送物资和给人做手术。此外,他们开始照顾任务,如移动病人(见视频中的机器人),提供标准化的症状管理方法,甚至对抗孤独和无所事事(如帕罗佩珀丁索夫)。这些活动可以极大地受益于对上下文的理解以及对词语和情感的解读。

为了在无限可变数量的设置中与机器人合作,我们需要不同的集成知识领域、来源和推理机制的组合

前面提到的第二代 KnowRob 将包括 叙事使能的情景记忆 通过在具有物理和几乎照片般逼真的渲染的虚拟环境中重用组件来获取经验知识的能力。系统将能够得出关于什么动作参数化在现实世界中可能成功的结论

这带来了一个有趣的结尾问题:如果机器人将物体视为启示,帮助我们人类不断发明新的做事方式,那么不难想象他们可以提出全新的更好的做事方式。我们得等着看那些是什么。

本文原载于we volver:https://www . we volver . com/article/a . sense . of . purpose . enables . better . human robot . collaboration

一个无服务器管道,用于从 Twitter 检索、验证数据,并将数据放入 Azure SQL Server。

原文:https://towardsdatascience.com/a-serverless-pipeline-to-retrieve-validate-and-immerse-the-data-to-azure-sql-server-from-twitter-1a5757b39bc8?source=collection_archive---------24-----------------------

学习如何做数据科学就像学习滑雪一样。你必须这么做。

项目陈述:

给定一个 twitter ID,获得最少 100 个关注者(修改后保持在 Azure 功能 5-10 分钟超时时间),每个关注者收集最多 200 条推文。
将元组(twitterID,followerID,tweetID,tweet)存储到 Azure SQL 服务管理的表中。
1)您必须创建并设置一个免费的 Azure 帐户。
2)在 Azure 账户中创建一个数据库和一个表。用 API 创建一个 twitter 账户
4)。给定 twitter ID,收集该 twitter ID 的追随者 ID
4.1)为每个追随者 ID 收集多达 200 条原始推文
— —不包括转发、消息
5)将其存储到 Azure 表中
6)编写一个客户端来查询 Azure 表。
6.1)列出给定 twitter ID 的所有推文
6.2)列出给定 twitter ID 的关注者 ID

使用的技术:

  1. 计算机编程语言
  2. Twython 库提取 tweeter 数据
  3. Azure 函数
  4. Azure SQL server

我学到的东西:

  1. 从本地主机以及 Azure 无服务器和 Azure 数据块使用 Azure SQL Server。
  2. Azure 功能。
  3. 学会了使用 twython 库来提取推文。

进行项目时遵循的步骤的简要总结:

  1. 创建了一个 Tweeter 开发者账号
  2. 编写了一个 python 脚本来提取给定用户 ID 的追随者 ID。

Code for getting followers ID for a Given User ID

3.编写了一个 python 脚本,获取上一步提取的关注者 ID,并为每个人检索最多 200 条推文。

Code for getting followers Tweet

4.创建了 Azure SQL 数据库。

5.编写了一个 python 脚本来获取步骤 3 的结果,并将其保存到 Azure SQL server。

Code to Save extracted data to Azure SQL server

6.我创建了一个 Azure 函数项目和 func。修改脚本以处理 Azure 函数。

7.出于以下目的,再创建 2 个客户端函数。

  • 列出给定 twitter ID 的所有推文

List all tweets for a given twitter ID

  • 列出给定 twitter ID 的关注者 ID

List follower ID for a given twitter ID

每个 Azure 功能的链接:

(这些是模板,供大家过目。我已经关闭了这些链接的激活,这样它们就不会工作了。很遗憾,我并不富有😢 😭。

任务 1:保存关注者的 ID 和他们各自的推文。(放在 MyFunctionProj 目录的 TweetWork 中)

任务 2:列出给定 twitter ID 的所有推文。(放在 MyFunctionProj 目录下的 Client1BigData 中)

任务 3:列出给定 twitter ID 的关注者 ID。(放在 MyFunctionProj 目录下的 Client2BigData 中)

面临的挑战:

  • 如果你在 Visual studio 中使用 Mac 调试 Azure 函数,这是非常困难的,因为有时 Visual Studio 不会创建一个确切的扩展/帮助文件来进行调试。我个人觉得,对我来说,一点效果都没有。每次我想检查它的时候,我不得不把功能推到在线。但是我现在找到了解决办法。里面有三个文件。vscode 有时会出错。我会提到他们,应该是什么样子。即,
  1. task.json

task.json

2。launch.json

launch.json

3。settings.json

settings.json

  • 与 AWS lambda 相比,Azure Functions 有其局限性。当我开始写它的时候,我以为它会和 AWS lambda 一样,因为两者都是无服务器的,但是实现它非常困难,原因有二。第一,Azure 功能不允许在线代码编辑,这是 AWS 提供的。

跟进:

  • 如果我是为一家公司做这个,并且有足够的资源,我会选择 Azure function Dedicated App Plan,它的最大时间限制是 30 分钟。

github:https://github . com/ksw 25/Extract-Data-From-Tweeter-And-Save-In-Azure-SQL-Using-Azure-server less

致谢:

  • 这是我在 NYU 坦登工程学院完成的 CS6513 大数据工具和技术的一部分
  • 我感谢 IBM Power Systems 学术计划对计算资源的支持。
  • 我感谢 MSFT Azure 为学生提供免费的 Azure 访问。

问候,

卡兰普里特·辛格·瓦德瓦

硕士计算机科学| 2020 级

纽约大学坦登工程学院

研究生助教—计算机视觉|纽约大学

karan.wadhwa@nyu.edu|(929)287–9899 |LinkedIn|Github

比特币区块链浅探第一部分——共识

原文:https://towardsdatascience.com/a-shallow-dive-into-bitcoins-blockchain-part-1-consensus-48f62355681b?source=collection_archive---------35-----------------------

从自然物体到硬币,到黄金支持的纸币,再到纸币,再到数字货币。无论是哪种形式,货币都是一种交换手段,一种支付方式,一种价值标准,一种财富储存手段。

如今,大多数交易都变得数字化了。例如,当你用你的卡从一个商人那里买东西时会发生这样的事情:

1.通过将您的 PIN 输入到商家的机器中,您将获得授权

2.交易和卡数据被发送到商家的银行

3.商户银行(下图中的收单机构)将详细信息转发给你的卡组织(Visa、Mastercard 等)。)

4.然后卡组织联系您的银行(下图中的发卡银行)以确保卡是有效的并且里面有钱

5.一旦商家收到 OK 信息,他们就可以给你商品/服务

Acquirer is Merchant’s Bank. Issuing Bank is the Customer’s bank. Source

6.在一天结束时,招商银行将所有有效的交易数据发送给卡组织(例如 Visa)进行结算

7.卡组织将所有商户的交易转发给客户的银行(发卡银行)

8.客户的银行需要将资金转移到卡组织

9.卡组织支付给商户银行的费用减去交换费

10.商户银行将资金存入商户账户,扣除手续费

Acquirer is Merchant’s Bank. Issuing Bank is the Customer’s bank. Source

卡组织充当金融机构的中间人。他们正在促进人们银行账户之间的交易。这就像他们在银行之上,给你一张卡就能安全存取你的资金。

然而,这篇文章分析了我们如何在自己之间安全地交易。

让我们试着建立一个不依赖于任何组织的系统。

第一种方法是建立一个公共场所,保存我们之间发生的所有交易。例如,某处公共服务器上的数据库分类帐。因此,无论何时发生交易,我们都会将其保存在数据库中。数字钱包会自动将交易细节发送到服务器。

但是您可以很快看到这种方法带来的问题。谁将负责这样的数据库服务器?有权访问服务器的用户将有权随意添加、编辑或删除交易。

为了消除这种信任,我们可以让网络的每个参与者在他们的机器上保留一份数据库分类帐的副本。

但这里有另一个问题。参与者如何保持这个分类账同步?你怎么能让每个人都同意同一个账本呢?

为了应对这一挑战,使用一种被称为工作证明(PoW)的共识算法来替代中央机构。

旁注:
战俘的术语是“采矿”。采矿的目的不是为了发现新的硬币,而是为了保证区块链的安全。

基本思想是信任对其进行了最多计算工作的分类帐。

请记住,从参与者的角度来看,他不能相信任何人!

在比特币网络上,矿工将交易集中在一个区块中,并向其余参与者广播。然而,并不是所有的参与者都需要创建积木(成为一名矿工)。参与者也可以只听和验证新交易的有效性;他们感兴趣的交易。

例如,手机上的钱包应用程序也可以参与,但不一定支持完整挖掘参与者运行的功能(这包括验证和广播所有新创建的交易和块,创建新块等)。这将需要大量的计算能力和千兆字节的空间。

Alice, running a full mining node, just found a new block and broadcasted it to the rest of the network. Bob, being a participant in the network, listening for new blocks of transactions from the miners, receives the newly created block. Source

假设你是这个网络的参与者。你怎么能相信矿工会做好他们的工作?换句话说,确保您从他们那里收到的事务块是有效的,同时,其他人也记录了相同的事务块。

你信任矿工的方式是通过验证他们在创建这些块时投入了一些计算工作(PoW)。这个挖掘过程将在后面更详细地讨论。

糟糕的演员也可以付出一些努力,给你盖帽,对吗?

正确!但是这里有一个警告:

因为为这些块创建 PoW 需要时间和精力,所以不良行为者不能轻易欺骗整个网络。

假设您收到一个块,其中包含一个坏的矿工事务。过了一会儿,你听到另一个来自一个好矿工的阻塞,但是有一个冲突的事务。从你的角度来看,你真的不知道两个街区该相信哪一个。

关键点是保留两个块并创建两个单独的区块链(一个分叉事件)并继续监听新的块;连同他们力量。

有关更多详细信息,请参见该动画的标题:

In this example, Alice is trying to cheat the network by trying to convince it that her version of the chain is the valid one (and thus the transactions in it). Bob, who is a participant in the network, is trying to understand which blockchain is the correct one. Source

叉子不一定是坏事。网络里每天都在发生。这是全球网络传输延迟的自然结果。即两个不同的挖掘器同时发现并发送一个块(当创建一个块时,每个挖掘器将包括不同的事务或不同顺序的事务,这可能发生在两个不同的挖掘器同时发现它们的块的随机数的情况下)。但只要所有节点都等待并选择最长的链,网络最终会收敛到一致的状态(通过网络的共识)。

Visualization of a blockchain fork event: two blocks propagate at the same time. Some nodes receive block “triangle” first and some receive block “upside-down triangle” first. Source

因此,如果坏矿工的区块最终没有做到这一点,并说服网络的其余部分,所有的努力都浪费了,在他们用来制作它的资源中。这也是阻止坏演员作弊的因素之一。

矿工需要做什么样的计算工作,才能证明自己在区块的创建上付出了一些努力?

为了理解这一点,让我们先解释一下加密哈希函数

首先要注意的是,数字世界中的一切都可以归结为比特(0 和 1)。

一个加密散列函数是一个数学函数,它接受任何大小的位(这是输入消息——文本、图像、数字),并输出固定长度的 256 位。这个输出被称为消息的哈希值、摘要或简称为哈希

加密哈希函数具有以下属性:

  1. 在不改变哈希值的情况下修改消息是不可行的。如果您稍微改变输入消息,即使是一位,产生的哈希值也会完全改变!
  2. 不可能找到两个具有相同哈希值的不同消息。相同的输入消息(比特组)将总是给出相同的散列值(256 比特),而两个不同的消息(比特组)将给出不同的散列值(256 比特)。
  3. 从消息的哈希值生成消息是不可行的。有了 256 位哈希值,您就可以返回并找到用作输入的消息。

Hashing comparison. Note that for readability hexadecimal notation is used for the resulting hash. One hex value represents 4 bits. 64 hex values times 4 bits = 256 bits. Source

比特币使用 SHA256 哈希函数。

这样的函数如何证明参与者确实花费了大量的计算能力?换句话说,我们如何知道一个矿工实际上做了特定事务块所需的工作?

规则是,挖掘者必须找到一个名为 nonce 的数字,当该数字被添加到事务块中并被散列在一起时,将产生一个 256 位散列(名为块散列),该散列以特定数量的 0 开始。前导 0 的数量由难度等级定义。

记住,在数字世界里,一切都是用比特来表示的。

区块链中的每个块包含关于该块的各种信息(交易、创建时间等。).该信息也表示为一组比特。这些位对于每个块都是唯一的,因为它有唯一的创建时间和一组事务。

对于矿工来说,很难找到额外数量的位( nonce 数),当添加到现有块的位中,并使用 SHA256 哈希函数哈希在一起时,将产生一个具有特定 0 集的哈希值(由难度级别定义)。生成与特定目标匹配的哈希值的唯一方法是反复尝试,随机修改输入(通过尝试不同的随机数),直到所需的哈希值偶然出现。

花点时间再读一遍。那是工作证明的基石。

Hashing numbers to find the nonce that satisfies the difficulty level. Source

这个数字(nonce)作为证据,证明为了产生与特定目标匹配的结果散列,做了一定的工作。因此工作证明这个术语。

使用这种方法的好处是,每个参与者都可以很容易地验证他们做了大量的工作,而不必做同样的努力。拥有 1。块的数据,2。随机数和 3。由此产生的散列,任何人都可以使用相同的函数快速验证其正确性。

满足难度等级的方块被认为是有效的。

因此,如果一个坏的参与者将要改变一个事务(实际上是消息中的一些位),那么块散列将会不同,并且很可能不是以所需数量的 0 开始,因此,使该块无效。

块散列充当数字指纹,或者块标识符。它唯一地标识一个块,并且可以由任何节点通过简单地散列该块的数据(随机数、事务、难度、时间戳等)而独立地导出。).

我没有提到的一件事是,一个糟糕的矿工不可能改变任何交易。还有一点额外的安全性,我将在第 2 部分的 中讨论——事务 。但目前来看,这是理所当然的。

有了这个额外的安全措施,一个坏矿工只能改变他自己的一个交易。

因此,为了欺骗网络,他将不得不去链中的特定块(保存他的事务的块)改变对他有利的事务,并重新做寻找满足该块难度级别的块散列的工作。将这样的块传播到网络的其余部分将被认为是完全有效的。

除非我们再增加一点安全措施。

所有的块都是相互连接的!通过散列前一个块的散列,而不仅仅是事务、nonce 和时间戳,我们得到了所有块之间的紧密关系。

Blocks’ contents. All transactions (Tx0, Tx1, Tx2, Tx3) can be represented with just one hash number, called the Merkle Root (Tx_Root in the diagram). Source

所以,如果你要改变任何一个方块,或者试着交换两个方块的顺序,它会改变后面的方块。由于块上的单个更改会更改其哈希,因此它会更改下一个块的哈希,依此类推,使其后的所有块无效。这将需要重做所有的工作,为这些块中的每一个找到一个新的特殊数字,使它们的散列以特定的数字 0 开始。这需要大量的工作!

附注:
在撰写本文时,网络的哈希速率约为每秒 65 万亿次哈希。一个坏演员将需要至少有一半来欺骗网络(被称为多数或 51%攻击)。因为攻击者可以比网络的其他部分更快地生成块,所以他可以简单地坚持他的私有分支,直到它变得比诚实网络构建的分支更长。然而,当前网络的散列率使得它在经济上是不可能的(所需的机器和能量花费了数百万美元)。而这仅仅是为了改变他的一笔交易。所以,最好值得!

难度等级

前面我说过,PoW 是要找到一个特殊的数字(nonce ),以便块的散列以一个特定的数字 0 开始。

前导 0 越多,挖掘者就越难找到满足该散列的随机数。这是因为可接受的结果散列的范围变小了。

但是,为什么一开始就让矿工们为难呢?

目标是将整个网络开采一个区块的难度保持在 10 分钟以内。

这是快速确认时间(交易结算)和分叉概率之间的设计折衷。更快的封锁时间会使交易清算更快,但会导致更频繁的区块链分叉,而更慢的封锁时间会减少分叉的数量,但会使结算更慢。

难度参数每 2016 块动态调整,以保持 10 分钟的块间隔目标。因此,公式是,对于每 2016 个区块,计算矿工的平均区块创建时间,如果该时间超过 10 分钟,难度参数将被调整。例如,如果网络平均花费 12.5 分钟建造一个街区(比 10 分钟的目标多 20%),那么对于接下来的 2016 个街区,难度将降低 20%。块创建时间的这一修订遵循了矿工散列能力(本质上是硬件)的改进。

旁注:

今天,许多矿工在一个矿池中合作,竞争开采一个区块。他们分担寻找解决方案的工作,分享报酬。这是集中了整个挖掘思想,但它也有一些 优点 。但是,无论如何,随着当前金融机构因内幕交易而受到密切关注,大型矿池也因不当行为而受到关注。任何不当行为都会让他们失去信誉,甚至更糟,失去用户对比特币的信心,将整个项目推入深渊。这会让他们破产。

如今,矿池就像一家银行,保护着人们的资金安全。但是,说到底,大多数都是中央集权的公司!😉对等池也存在。但他们是少数。

有兴趣了解更多信息吗?阅读我的文章 第二部分—交易 了解更多知识。

在社交媒体上关注我:

[## Andreas Lymbouras -应用程序开发人员-法国巴黎银行| LinkedIn

加入 LinkedIn 经验丰富的应用程序开发人员,并展示其在银行业的工作经历。熟练的…

www.linkedin.com](https://www.linkedin.com/in/andreas-lymbouras-51211246/) [## 安德烈亚斯·林布拉斯(@alymbouras) |推特

Andreas Lymbouras 的最新推文(@alymbouras)。软件开发商区块链工程师

twitter.com](https://twitter.com/alymbouras)

比特币区块链浅探第二部分——交易

原文:https://towardsdatascience.com/a-shallow-dive-into-bitcoins-blockchain-part-2-transactions-d4ee83067bae?source=collection_archive---------14-----------------------

source

之前的文章中,我们讨论了比特币网络中的共识。

我们说过,有一种额外的安全措施可以防止坏人从别人的钱包里拿走资金。这将在本文中解释。

资金保存在数字钱包里。或者我应该说通过数字钱包追踪。有一种普遍的误解,认为你的硬币是放在钱包里的。硬币(或者应该说数字)实际上是以交易的形式存入区块链的;数字钱包创造的交易。

数字钱包不过是一段代码,通过扫描区块链街区内的交易来跟踪和计算所有者的余额。

Transactions are structures within the block structure. The whole chain of blocks is stored on a bitcoin participant’s hard disk.

钱包的主要功能之一是代表主人签署交易。

它们有点像真实世界的签名,但更强大。数字签名可以:

  1. 证明账户所有人是唯一授权使用其资金的人
  2. 授权证明是不可否认的
  3. 证明交易签署后没有也不能被任何人修改

私钥/公钥和比特币地址

为此,网络中的每个帐户所有者都必须创建一个公钥/私钥对。它们被认为是“一对”,因为公钥是从私钥派生出来的。你的私钥只不过是一个数字!数字世界中 0-2 ⁵⁶(remember 之间的 256 位数字一切都用位表示。这是一个巨大的数字范围,这使得两个人得到相同的钥匙在统计学上是不可行的(有 10⁷⁷钥匙可用)。

这些密钥基于具有特殊性质的数学函数:计算它们很容易,但计算它们的倒数却很难。

公钥是其相关私钥的数学结果。而且即使知道创建它的数学函数,也无法推断出它的私钥。

Your public key is derived from your private key using elliptic curve multiplication. Your address is derived from your public key. Both of those actions are irreversible. Source

这里值得一提的是,您的比特币地址是通过使用单向加密哈希从您的公钥中获得的。你的地址是和其他比特币持有者交易的方式。它只是代表比特币需要发送到的目的地。

不过,创建私钥的方式非常重要。你绝不会选择数字 1 作为你的私钥。那太危险了!任何人,使用相同的数学函数,都可以从私钥推断出比特币的地址。如果那个比特币地址拥有硬币,它们很容易被盗。

事实上,如果您运行一个尝试每个数字(私钥)的脚本,从数字 1 数到 100,000,您会发现(在几秒钟内)几十个可用的比特币地址!为了发现一个地址是否可用(一个在比特币网络中拥有一些硬币的地址),人们必须遍历整个区块链,如果找到该帐户的引用,嘣!一个人可以用这个弱生成的数字(私钥)从里面偷走所有的硬币。

实际上,私钥号 1 衍生出来的比特币地址是可用的:1 ehna 6 q 4 JZ 2 uvnexl 497 me 43 ikxhwf 6 kzm

如果你点击这个链接,你会看到进入这个地址的任何东西都会在几秒钟内被撤回!钱一进来,有人就可以快速创建一个交易(使用自己的地址作为目的地),用私钥数字 1 签名,并传播到网络的其余部分!

太好了!为什么每个人都不这样做呢?

原因是检查所有可能的私钥号码是一项非常困难的任务。例如,50 台超级计算机需要大约 3×10⁵年的时间(每秒检查一万亿个键!)耗尽整个 2 ⁵⁶密钥空间。

糟糕的私钥生成算法

一些钱包曾经使用人类提供的密码来创建私钥(本质上是数字)。然而,黑客可以很容易地快速检查弱密码或常用密码(这个范围要小得多)。

私钥被盗(源自弱密码)的帐户示例:

ASD—1g 4 mt 5 jltrdj 4 hm 6 mkyaqphmzzvoojlfx 3
cat—162 trprzvdglvnksmoyjsybfytb 4 q 8 TM
hello—1 hosfymoqteymr7s 3 jddqmqmggoxacbk 37
密码—16ga 2 uqnf 1 qpauqeeg 7 stcadtduwdyjav
测试—1 hkqktmpbtzz 8 H5 zqyewybaawelrdexee
fuckyou—1

数字签名

签署交易的过程涉及一个数学函数,该函数既取决于消息(交易细节),也取决于您的私钥。

sign(消息,私钥)=签名

结果是一个签名,可以使用您的公钥和消息(交易详细信息)进行验证。

验证(消息、签名、公钥)=[真或假]

Verifying digital signatures. Source

私钥、公钥和签名这三者加在一起在数学上是相关的

验证过程毫无疑问地确定交易可能仅来自具有对应于其公钥的私钥的人。因此,接收交易的网络的所有参与者都确信,该交易只能由私钥所有者批准!

所有者还可以确保没有人能够更改他的交易的签名部分。这是因为一个简单的改变会使他的交易无效,从而被所有网络参与者放弃。

签名中随机性的重要性

专注于用于交易的弱随机数生成器,黑客仍然可以获得对地址硬币的控制。

用于创建消息签名的数学基础使用一个随机数(见下面的公式)。如果相同的随机数被用于签署两个不同的消息(事务),那么某人使用这两个结果签名可以提取私有密钥数。

生成签名的数学公式是这样计算的:

s = k-1(Hash(m)+dA * R)mod p
其中:
k 是随机数
R 是从随机数 k
dA 是签名私钥
m 是交易数据
p 是椭圆曲线的素数阶

人们实际上因为这个随机数的不经意的重复使用而导致资金被盗。

为了避免这种漏洞,钱包必须遵循行业标准算法,按照 RFC 6979 中的定义,对该随机数进行确定性初始化。

现在你已经记住了所有必要的细节,让我们来看看交易的过程:

  1. 你的钱包是一个作为用户界面的应用程序。它显示您的余额,并在汇款时请求您的允许。为了做到这一点,它跟踪你的收入和支出交易,总结你的可消费金额,并代表你创建和签署交易。
  2. 首先,指定比特币所有者的金额和目的地地址。基于这些信息,你的钱包构建一个交易(按照比特币协议)并用你的私钥签名。
  3. 你的钱包开始通过它的直接对等点向比特币网络广播你的新交易(包含交易细节、签名和公钥),这些对等点将交易传递给它们的对等点,等等。在几秒钟内,整个网络已经验证了你的交易,并将其传递给比特币网络上的每个其他节点。

Transaction propagation

4.网络上收到您交易的每个参与者都会检查其有效性。他们检查签名是否正确,是否有任何错误,你是否试图执行双重消费,等等。如果您的交易不符合任何标准,参与者会完全忽略它。否则,参与者会将您的事务保存在一个名为 mempool 的临时内存中。

5.费用低于 minrelaytxfee 变量(0.00001 比特币)的交易被视为免费,只有在 mempool 中有空间时才会被中继;否则,它们将被丢弃。如果附加费用小于平均竞争交易费用(通常由你的钱包计算,但你也可以指定费用),矿工/矿池将在创建区块时给予你的交易较低的优先级。

6.最终,您的交易到达挖掘池和交易接收者的钱包。后者会在他们的钱包里看到新的交易,并无限期地存储它的副本,但它会以零确认的形式出现。挖掘池通过聚合来自内存池的事务来构建候选块。根据你的费用,他们最终会把你的费用包括在未来的费用中。

7.池将搜索满足块难度级别的随机数的工作分配给它的池矿工。矿工对你的交易一无所知。他们的工作是处理数字,而不是检查块的有效性,因为那是池的任务。

8.最终,您的事务被包含在一个得到解决的块中。它通过比特币网络传播,每个人都将其存储到自己的本地区块链(如果有交易冲突,他们将分叉现有的区块链,并保留两个区块链)。现在,您的事务有了一个确认(网络接受的一个有效块)。

9.块创建过程继续进行,随着越来越多的块建立在包含您的交易的块之上,它会获得更多的确认。当它达到 6 个或更多确认时,它被认为是完全确认的。确认时间越长,通过攻击使交易无效的难度就越大。

事务是更复杂的结构。他们在幕后看起来非常不同。它们有输入和输出,伴随着锁定和解锁比特币价值的脚本。

但那是另一篇文章;对事务的更深入探究。😃

在社交媒体上关注我:

[## Andreas Lymbouras -应用程序开发人员-法国巴黎银行| LinkedIn

加入 LinkedIn 经验丰富的应用程序开发人员,并展示其在银行业的工作经历。熟练的…

www.linkedin.com](https://www.linkedin.com/in/andreas-lymbouras-51211246/) [## 安德烈亚斯·林布拉斯(@alymbouras) |推特

Andreas Lymbouras 的最新推文(@alymbouras)。软件开发商区块链工程师

twitter.com](https://twitter.com/alymbouras)

来自乐高的闪亮网络应用——卡车+拖车

原文:https://towardsdatascience.com/a-shiny-web-app-from-lego-truck-trailer-c977015bc6a9?source=collection_archive---------20-----------------------

如何建造闪亮的“卡车”第 2 部分——让乐高“卡车”应用程序拉拖车。一个模块化闪亮应用的例子。

在 2018 年 9 月的中,我用了一个汽车隐喻来解释一个大规模的闪亮应用。RViews 发表了这篇文章。我将用一句话来概括这篇文章。在 R shiny 中构建大型应用程序(卡车)时,有许多事情需要记住。为了在一个应用程序中涵盖所有这些内容,我提供了这个教程。

您可以在 https://github.com/zappingseb/biowarptruck下找到该应用的所有文件—文件夹:example_packaged

摘要(如果您阅读 RViews 中的文章,请跳过)

我在 RViews 上写的文章告诉读者,任何闪亮的应用程序都有可能在某一天变得巨大。从头开始,它必须是精心策划的。此外,应该可以删除或添加应用程序的任何部分。因此它必须是模块化的。每个模块必须像乐高积木一样工作。乐高积木有不同的功能。这些砖块遵循一定的规则,这使得它们彼此粘在一起。这些规则我们称之为标准。像乐高积木一样设计的模块增加了你的灵活性。因此,你的模块的可重用性增加了。当你设置你的应用程序时,你可以添加无限数量的乐高积木。它可以生长。想象像汽车这样的小规模应用。大规模应用是卡车。这篇文章解释了如何建造一辆乐高卡车。

如果你用乐高组装你的车,更多不同的零件可以让它成为一辆卡车。

如果你用标准化的模块构建你的应用程序,你可以灵活地插入更多的功能。

模块化的闪亮应用——从哪里开始?

下图解释了模块化闪亮应用的想法。

你从一个闪亮的核心应用程序开始。把它看成你汽车的底盘。它是由乐高制成的。乐高制成的任何其他部分都可以粘在你的底盘上。这样的部件可以改变其功能。不同的模块将帮助你制造不同的汽车。此外,您希望有一个砖块说明(计划)。这个计划告诉我们该拿走哪些部分,以增加灵活性。砖块说明的背面可以包含相同砖块的不同型号。如果您可以从您的模块构建一个应用程序,您也可以构建一个包含相同模块的不同应用程序。如果你清楚这一点,我们可以开始在 R-shiny 开发我们的应用程序:

实施规则:

  • 每个模块是一个 R 包
  • 核心 R 包定义了砖块的标准化
  • 核心应用是一个基本的闪亮应用
  • 砖块指令(计划)文件不在 R 中

为什么这些规则存在,读了这篇文章就会明白了。

我们想要建立的应用程序

我们想要构建的应用程序将从一组用户输入中创建不同类型的输出。这些不同的输出将显示在应用程序中。此外,所有输出将进入一个 PDF 文件。该示例将包括绘图模块中的两个绘图和表格模块中的一个表格。由于每个模块都是一个 R 包,您可以想象逐步添加更多的 R 包。在 shiny 中,很多输出都是可能的。这个应用程序的主要特点是可以添加越来越多的模块。更多的模块不会搞砸 PDF 报告功能或查看功能。在这个应用程序中,模块根本不交互。

核心 R 包

核心包包含模块必须遵循的结构,以适应核心应用程序。有两种结构我们将定义为 R-S4 类。一个表示模块,另一个表示这些模块中的输出元素。

Class diagram of the core application: The left side shows the reports. The app can generate each of those. Each contains a list of elements to go into the report (plots). The right-hand side contains the class definition of such elements. Each element is of kind AnyPlot. This class contains a call (plot_element) that produces the element upon calling evalElement.

对于任务一,我们称这个对象(类)为报表。报告是我们在核心应用程序中定义的主要模块。它包含:

**plots** — A list of all elements shown in the report 
**filename** - The name of the output file (where to report to) 
**obs** - The handling of the input value input$obs 
**rendered** - Whether it shows up in the app right now

此外,Report 类还带有一些生成漂亮输出的功能。此外,它允许创建 PDF 报告。这些功能包含在方法 shinyElement()和 pdfElement()中。在 R-S4 中,这看起来像这样:

现在我们还要定义,如何构造这样的每个元素。因此,我们定义了一个类 AnyPlot,它携带一个表达式,因为它是唯一的槽。evalElement方法将计算这个表达式。pdfElement方法创建一个可以输出到 PDF 的输出。shinyElement通过调用shiny::renderPlot()创建一个 PlotOutput。logElement方法将表达式写入日志文件。 R-S4 代码显示如下:

核心应用程序

为了使这个例子简单,核心应用程序将包括所有的输入。这个应用程序的输出将是模块化的。核心应用程序必须完成以下任务:

  1. 有一个显示模块的容器
  2. 阅读计划—添加容器
  3. 包括将模块打印成 PDF 的按钮
  4. 想象一下还有一个按钮打印模块来”。png“,”。jpg“,”。xlsx"
  5. 包括输入

显示模块

对于任务一,我们使用给定对象的shinyElement方法,并将其插入到任何输出中。我为每个模块决定了一个选项卡输出。因此每个模块都在不同的选项卡中呈现。

阅读计划

现在,应用程序的最难部分来了。正如我所说,我想增加两个模块。一个有图,一个有表。计划(config.xml)文件必须包含这些信息。所以我把它作为一个计划文件:

<?xml version="1.0" encoding="UTF-8"?>
<modules>
  <module>
    <id>module1</id>
    <name>Plot Module</name>
    <package>module1</package>
    <class>PlotReport</class>
  </module>
  <module>
    <id>module2</id>
    <name>Text Output</name>
    <package>module2</package>
    <class>TableReport</class>
  </module>
</modules>

Construction plan of the web App

你可以看到我有两个模块。每个模块都有一个包。在这个包中,一个类定义了(参见模块包一节)输出。这个班是我们班的子班。

该模块在我们的应用程序中显示为一个选项卡。我们将一步一步地完成这个过程。首先,我们需要一个函数来加载每个模块的包:

library(XML)
load_module <- function(xmlItem){
  devtools::load_all(paste0("./",xmlValue(xmlItem[["package"]]))) 
}

其次,我们需要一个函数来从模块的信息中生成一个选项卡:

library(shiny)
module_tab <- function(xmlItem){
  tabPanel(XML::xmlValue(xmlItem[["name"]]),
           uiOutput(xmlValue(xmlItem[["id"]]))
  )
}

现在我们有了这两个函数,我们可以迭代 XML 文件并构建我们的应用程序。首先,我们需要一个像tabPanel(id='modules')这样的 UI 中的TabPanel。之后,我们可以将应用程序的配置读入TabPane。因此我们使用appendTab功能。函数XML::xmlApply让我们遍历 XML (config.xml)的每个节点并执行这些任务。

configuration <- xmlApply(xmlRoot(xmlParse("config.xml")),function(xmlItem){ load_module(xmlItem)

    appendTab("modules",module_tab(xmlItem),select = TRUE)

    list(
      name = xmlValue(xmlItem[["name"]]),
      class = xmlValue(xmlItem[["class"]]),
      id = xmlValue(xmlItem[["id"]])
    )
  })

现在,每个模块都以静态方式加载到应用程序中。下一部分将讨论如何使其具有反应性。

将内容呈现到面板中

对于面板的动态渲染,有必要知道一些输入。首先是用户选择的选项卡。input$modules变量定义了选择的选项卡。此外,我们闪亮的应用程序的输出必须通过另一个输入更新,input$obs。因此,在更改选项卡或更改input$obs时,我们需要调用一个事件。这个事件将调用我们的 S4 对象的构造函数。在此之后,shinyElement方法呈现输出。

The module class gets reconstructed up on changes in the input\(modules or input\)obs

reactive report_obj是一个可以调用我们 Report 对象的构造函数的函数。对input$obsinput$modules使用observeEvent功能,我们称之为反应式。这允许对用户输入做出反应。

从报告中导出 PDF 文件

Adding a PDF render button to enable the download of PDF files.

pdfElement函数将 S4 对象渲染为 PDF 文件。如果这样做很好,PDF 元素加起来就是下载按钮。

一个额外的标签检查 PDF 渲染是否成功。

我们完成了核心应用程序。可以在这里找到 app:app。R 还有这里的核心包:核心

最后一步是把整辆卡车组装起来。

模块包

这两个模块包现在将包含两个类。两者都必须是类 Report 的子类。这些类中的每个元素必须是类的子类。下图中的红砖代表报告,黄砖代表任何地块。

Final app: The truck consists of a core app with a PlotReport and a TableReport. These consist of three AnyPlot elements that the trailer of the truck carries.

绘图包

第一个模块包将生成散点图和直方图。两者都是类定义中contains='AnyPlot'AnyPlot 的子元素。PlotReport是该包中报表的类。它在plots槽中包含了这两个图。有关这些类的构造函数,请参见下面的代码。

桌子包装

表格包遵循与地块包相同的规则。主要区别在于plots槽内只有一个元素。这个元素不是情节。这就是为什么它包含一个data.frame调用作为它的表达式。

为了使内部的data.frame调用闪亮,我们必须重写shinyElement方法。我们将返回一个renderDataTable输出,而不是返回一个renderPlot输出。此外,pdfElement方法必须返回一个gridExtra::grid.table输出。

包装优势

打包每个模块的一个主要优点是依赖关系的定义。描述文件指定了模块包的所有依赖关系。例如,表格模块需要gridExtra包。核心 app 包需要shiny, methods, XML, devtools。app 不需要额外的library调用。任何同事都可以安装所有依赖项

最后的话

现在,您必须有工具来开始构建自己的大型闪亮应用程序。使用包将应用模块化。使用 S4 或任何其他面向对象的 R 风格将其标准化。使用 XML 或 JSON 文档设置应用程序。你可以走了。在一个目录中设置核心包和模块包。你可以用 devtools 加载它们,并开始构建你的闪亮的文件app.R。现在,您可以构建自己的应用程序来交换模块包。

像每个孩子一样,你现在可以尽情地玩你的卡车了,你可以走了。我不能告诉你是建造更有趣还是滚动更有趣。

亲爱的读者:写下我在构建模块化闪亮应用程序方面的工作总是令人愉快的。感谢你一直读到这篇文章的结尾。如果你喜欢这篇文章,你可以在 或者在github上为它鼓掌。如有任何意见,请在此留言或在我的 LinkedIn 个人资料上留言http://linkedin.com/in/zappingseb.

进一步阅读

卷积神经网络的历史

原文:https://towardsdatascience.com/a-short-history-of-convolutional-neural-networks-7032e241c483?source=collection_archive---------5-----------------------

卷积神经网络,简称 CNN,构成了许多现代计算机视觉系统的主干。这篇文章将描述 CNN 的起源,从 20 世纪 50 年代的生物实验开始。

简单和复杂细胞

1959 年,大卫·胡贝尔托尔斯滕·威塞尔描述了人类视觉皮层中的“简单细胞”和“复杂细胞”。他们提出两种细胞都用于模式识别。一个“简单单元格响应特定方向的边缘和条,例如这个图像:

一个“复杂单元也对特定方向的边缘和条做出响应,但它与简单单元的不同之处在于,这些边缘和条可以在场景中四处移动,并且该单元仍然会做出响应。例如,简单的单元格可能只响应图像底部的水平条,而复杂的单元格可能响应图像底部、中间或顶部的水平条。复杂细胞的这种特性被称为“空间不变性”

本文中的图 1 显示了简单细胞和复杂细胞之间的区别。

Hubel 和 Wiesel 在 1962 年提出,复杂细胞通过“求和”几个简单细胞的输出来实现空间不变性,这些简单细胞都倾向于相同的方向(例如水平条)但不同的感受野(例如图像的底部、中部或顶部)。通过从一群简单的细胞奴才那里收集信息,复杂细胞可以对任何地方出现的横条做出反应。

这个概念——简单的检测器可以被“相加”以创建更复杂的检测器——在人类视觉系统中随处可见,也是卷积神经网络模型的基本基础。

(旁注:当这一概念走上极端时,你会得到“祖母细胞”:即在你大脑的某个地方有一个单一神经元,专门对你祖母的视线做出反应。)

大脑皮层

20 世纪 80 年代,Kunihiko Fukushima 博士受到 Hubel 和 Wiesel 关于简单和复杂细胞的工作的启发,提出了“ neocognitron ”模型(原文:https://www.rctn.org/bruno/public/papers/Fukushima1980.pdf)。neocognitron 模型包括称为“S 细胞”和“C 细胞”的组件这些不是生物细胞,而是数学运算。“S 细胞”位于模型的第一层,并与位于模型第二层的“C 细胞”相连。总体想法是捕捉“简单到复杂”的概念,并将其转化为视觉模式识别的计算模型。

用于手写识别的卷积神经网络

现代卷积神经网络(CNN)的第一项工作发生在 20 世纪 90 年代,受到 neocognitron 的启发。Yann LeCun 等人在他们的论文“Gradient-Based Learning Applied to Document Recognition”(现在被引用了 17,588 次)中证明了一种将简单特征聚合成逐渐更复杂特征的 CNN 模型可以成功地用于手写字符识别。

具体来说,LeCun 等人使用 MNIST 手写数字数据库训练了一个 CNN。MNIST 是一个现在著名的数据集,它包括手写数字的图像,这些图像与它们的真实标签 0、1、2、3、4、5、6、7、8 或 9 配对。CNN 模型通过给它一个示例图像来训练 MNIST,要求它预测图像中显示的是什么数字,然后根据它是否正确预测了数字身份来更新模型的设置。最先进的 CNN 模型今天可以在 MNIST 数字分类上达到近乎完美的准确度。

来自 MNIST 数据集的手写数字示例。

这项工作的一个直接结果是你的邮件现在由机器分类,使用自动手写识别技术读取地址。

卷积神经网络看到一切

在整个 20 世纪 90 年代和 21 世纪初,研究人员对 CNN 模型进行了进一步的研究。大约在 2012 年,在一家名为 AlexNet 的 CNN 在 ImageNet 挑战赛中实现了最先进的图片标签性能后,CNN 的受欢迎程度大幅上升(这种情况一直持续到今天)。Alex Krizhevsky 等人发表的论文“ ImageNet 分类与深度卷积神经网络”描述了获胜的 AlexNet 模型;这篇论文被引用了 38007 次。

与 MNIST 类似, ImageNet 是一个公开的、免费提供的图像及其相应真实标签的数据集。ImageNet 关注的不是标有 0-9 的手写数字,而是“自然图像”,或世界的图片,上面标有各种描述符,包括“两栖动物”、“家具”和“人”。这些标签是通过大量的人工努力获得的(即人工标记——要求某人为每张图片写下“这是什么图片”)。ImageNet 目前包含 14,197,122 张图像。

来自 ImageNet 数据集的示例图像。

在过去的几年中,CNN 在描述自然图像(包括 ImageNet、 CIFAR-10、CIFAR-100VisualGenome )、执行面部识别(包括 CelebA )和分析医学图像(包括胸部 x 光皮肤病变照片组织病理学切片)方面取得了出色的表现。这个名为“网络上的 CV 数据集”的网站有一个超过五十个带标签的图像数据集的广泛列表,研究人员可以用它来训练和评估 CNN 和其他类型的计算机视觉模型。公司正在开发许多令人兴奋的应用程序,包括 Seeing AI ,这是一款智能手机应用程序,可以向盲人口头描述周围环境。

CNN 与人类视觉?

大众媒体经常谈论神经网络模型如何“直接受到人脑的启发”。在某种意义上,这是真的,因为 CNN 和人类视觉系统都遵循“简单到复杂”的层次结构。但是,实际实现完全不同;大脑是用细胞构建的,神经网络是用数学运算构建的。

这个视频,Jason Yosinski 的“深度可视化工具箱”绝对值得一看,可以更好地理解 CNN 如何获取简单的特征,并使用它们来检测复杂的特征,如人脸或书籍。

结论

在过去的几十年里,计算机视觉取得了长足的进步。想象未来会有哪些新的发展改变该领域,并推动自动化放射学图像解释和无人驾驶汽车等技术,这是令人兴奋的。

关于特色图片

特色图片展示了一只西部草地鹨。有各种各样的鸟类数据集可用于训练 CNN 自动识别鸟类物种,包括加州理工学院-加州大学圣迭戈分校鸟类 200 数据集,其中包括 6033 张显示 200 种鸟类的图像。同样,自然学家正在建立一个众包自动物种识别系统,包括鸟类和许多其他物种。这种系统也许有一天会在保护生物学中大有用处。

原载于 2019 年 4 月 13 日http://glassboxmedicine.com

posted @ 2024-10-13 15:31  绝不原创的飞龙  阅读(305)  评论(0)    收藏  举报