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

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

Python 教程:模糊名称数据集的名称查找表

原文:https://towardsdatascience.com/python-tutorial-a-name-lookup-table-for-fuzzy-name-data-sets-2580e4eca6e7?source=collection_archive---------17-----------------------

Python 统计教程系列

通过使用姓名成分组合提高人名匹配的准确性

这是我们探索 Python 数据世界之旅的第六篇文章。点击标题上方的链接,获得所有文章的列表。

本教程的目标是

让我们回顾一下我们在的最后一课中所取得的成绩。我们建立了一个人的名字“模糊”的名字匹配算法,通过使用一个标准化的步骤以及双变音算法的力量。

All Name Components available

该算法可以处理姓名属性中的错别字、特殊字符和其他差异,但如果 twitter 账户名称中缺少任何姓名成分,该算法就会失败。

Two Name Components Available, one only available as an abbreviation

问题是 Twitter 帐户名称是由用户连接的,因此不具有确定性(我们假设他没有使用假名,并且有可能匹配)。正如我们在上一个教程中看到的,我们试图修复某些异常,但解决方案似乎不够健壮。因此,我们必须投入额外的时间来建立一个更健壮的解决方案,通过使用组合学来解决“缺少名称组件”的问题。

获取 Jupyter 笔记本以获得额外的教程解释

作为我自己进入 Python 数据科学世界的一部分,我最近开始玩 Python 的 Jupyter Notebook

Jupyter Notebook 是一个开源的 web 应用程序,允许您创建和共享包含实时代码、等式、可视化和叙述性文本的文档。用途包括:数据清理和转换、数值模拟、统计建模、数据可视化、机器学习等等。

这简直太棒了,而且通过 Ancaconda 发行版几分钟就安装好了(你的机器上需要一些备用磁盘空间)。

我把它整合到了我的训练过程中,从现在开始,我将在 Jupyter 的专用笔记本中更详细地描述算法和编码的构建。

你可以在我的 Github 项目中找到本教程的 Jupyter 笔记本。使用 Jupyter 笔记本(与本教程并排),允许您在笔记本中随意摆弄和实时修改代码序列。令人惊讶的是,Github 以其原始的、易于阅读的 Web 视图格式呈现了一个 Jupyter 笔记本文件。以防你想看只读格式的!

Jupyter Notebook rendered in Github

在名称匹配过程中处理缺少的名称组件

我们想要实现的是,我们的算法能够管理丢失的名称组件。在下面的示例中,我们可以通过省略两边的第二个名称组件来实现匹配。

显然,我们想要一个通用算法,它可以处理 twitter 帐户名称中的任何复杂性,也就是说,在命名结构中也应该有可能进行匹配,如:

  • “梅德医生。彼得·埃舍尔(苏黎世)"或
  • “梅德医生。彼得·埃舍尔(苏黎世)”,用户打错了一个字。

我们用组合学解决的第一个问题,第二个问题,我们已经通过应用著名的双变音算法解决了。

组合和排列的简明介绍

为了在缺少元素的情况下导出任何种类的名称成分星座,我们必须理解组合学中的基本概念。

我们应该使用组合还是排列

先来回答这个问题。离开学校太久?看看这个有帮助的六分钟视频(来自 betterExplained.com),它更新了各种概念。

Permutations/Combinations explained

Python 在其标准库 itertools 中已经提供了函数置换组合,我们想进一步研究一下。

让我们将它应用于我们的名称示例,以了解其机制。首先是组合功能

以及排列功能:

如您所见,在排列中,名称组件的顺序起着作用。有一个用于('peter','alfred')的元组和一个用于('alfred','peter')的元组。在组合中,名称组件的顺序与无关。

对我们来说,顺序不起作用,'peter escher'被视为'escher peter'在应用双音素算法之前,我们无论如何都要对姓名成分进行排序。因此我们使用组合函数。

请始终将“个人识别码”视为“排列”的摇篮。任何 pin 码锁定机制都是基于 10 个元素中给定的一组“数字”的排列数:“1234”不能解锁被“4321”锁定的屏幕。

ATM — Photo by Mirza Babic on Unsplash

为名称组合建立一个查找目录

我们现在构建一个查找目录类,它允许我们存储姓名组件组合,并将它们与我们从 Twitter API 获得的人名进行比较。

将人员添加到查找目录

方法add_person_to_lookup_table 计算所提供的姓名元组的所有组合,为每个组合生成相关联的双变音键,并将该键与唯一的个人 id 一起存储在查找目录中。

该方法的序列图如下所示,让我们看看所需的各种帮助方法。

方法:生成组合

作为第一步,我们生成名称元组的所有组合。下面的方法计算名称元组的所有组合。例如,对于 3 个元素的元组,构建的数组包括

  • 三元素元组本身
  • 具有 3 个元素中的 2 个元素的组合的所有元组
  • 具有 3 个元素中的 1 个的组合的所有元组

例如,下面的 3 个名称元组导致下面的组合列表。

方法:将组合添加到目录

在这种方法中,我们通过将每个元组添加到我们的查找目录来构建目录。

我们的查找目录由两个字典的元组组成,这两个字典用于存储键、值对。我们的键是从名称创建的双变音元组,值是唯一的个人标识符。

__lookup_dict = ({}, {})

该方法如下所示

在第 3 行代码中,我们用名称组件元组创建了一个规范化的名称字符串。该方法如下所示

结果是排序后的串联元组名称元素的小写字符串:

该字符串用于生成双变音元组,这是我们的字典的键。

在代码行 5 和 10 中,我们检查字典中是否已经有一个具有相同键的条目。

  • 如果没有,我们添加新的键,值对。
  • 如果已经有一个条目,我们首先检查是否已经存储了person_id。如果不是,我们将person_id添加到值数组中。

方法:将人员添加到查找目录

最后,我们准备好了方法,它允许我们将名称元组添加到查找目录中。

例如,我们将以下三个人添加到查找表中。

正如我们在输出中所看到的,我们的带有关键字'PTR'的 Peter 条目有一个三人标识符数组。

在我们的查找目录中匹配一个名字

我们的查找目录现在已经准备好了,可能会填充人名数据,这些数据是通过我们的政府 API 检索的。

缺少的是match_name方法,该方法允许我们查找通过 Twitter API 检索到的名称。我们现在要解决这个问题。

我们的第一步是将所有查找目录条目——与我们搜索的名称元组匹配——收集到一个结果列表中。

  • 在代码行 3 中,我们通过现有的方法生成了所有名称组件组合,并对所有组合进行了迭代
  • 在代码行 5 和 6 中,我们为查找准备了组合元组的键元组。
  • 在代码行 7 中,我们检查我们的密钥是否存在。如您所见,我们只对双变音元组的第一个条目进行检查,它存储在查找目录的第一个条目中。我们将基于双变音元组的排序特性的完整实现作为练习。
if metaphone_tuple[0] in self.__lookup_dict[0]:

在我们的样本加载查找目录上运行match_name 方法会产生以下输出:

正如我们所看到的,我们有两个指向一个person_id的元组和一个指向三个人的元组peter(显然姓氏被多人重复使用)。指向一个人的二元组有相同的 id 'A123'。这意味着我们的匹配只确认了一个人。如果我们的结果中有指向不同人的单人元组,这意味着我们的匹配不是唯一的。

因此,我们增强了我们的方法来进行这种唯一性检查(代码行 12–20):

  • 我们的匹配列表中有一个或多个元组总是指向一个人吗?
  • 如果是,我们发现了一个唯一的记录,否则我们返回 None

让我们在测试样本上验证该算法(如上所述,所有内容也可以作为交互式 Jupyter 笔记本使用)

所以我们准备将新的查找策略应用到我们的程序中。

重构我们现有的类

GovAPI 类扩展

我们通过集成一个NameLookupDirectory类实例来增强我们的抽象GovAPI类。

class GovAPI(ABC):
  def __init__(self):
    self._members = []
    self._nameLookupDirectory =  NameLookupDirectory()

我们用代码序列增强了add_person_record,以构建我们的查找目录(代码行 22–29)

我们还为match_name检查添加了一个新方法,当我们试图合并表记录时会调用这个方法。

def match_name(self, name_tuple):
    return self._nameLookupDirectory.match_name(name_tuple)

不再需要下面的calculate_name_matching方法。

SocialMediaAnalyzer 类重构

在这个类中,我们还必须重构calculate_name_matching方法,我们现在调用匹配的govAPI类实例的match_name方法(第 5 行)。

如果我们有一个匹配(7–14),我们从 govAPI 类中检索完整的 person 记录。

记住,calculate_name_matching方法是通过 Panda apply方法在每个行记录上调用的,因此,该行将由附加的新列补充:

panda_data = { 'ScreenName' : self.__col_screen_name,
               'Name': self.__col_name,
               'Description': self.__col_description,
               "FollowersCount": self.__col_followers_count,
               "FriendsCount": self.__col_friends_count,
               "Party": self.__col_party
               }
df = DataFrame(panda_data, index=self.__labels)
df = df.apply(self.__calculate_name_matching, axis=1)

当我们再次执行程序时,Twitter 检索到的表如下所示:

col_match1中,我们列出了 govAPI 惟一 id,在col_match2中,我们列出了结果元组列表,并对其进行了分析。例如

对于 Twitter 名称“Christian Levrat ”,我们在查找表中找到了三个条目:

  • “christian leverat”映射到 1 个人 id (1150)
  • “christian”映射到 5 个人 id
  • “leverat”映射到 1 个人 id (11509

我们的匹配算法有一个肯定的匹配,因为两个条目都指向同一个人 id。

评估我们算法的假阳性

让我们检查一下误报的算法。

什么是误报?

假阳性是指当你应该得到阴性结果时,却得到了阳性结果。它有时被称为“假警报或“假阳性错误”它通常用于医学领域,但也可以应用于其他领域(如软件测试)。( Ref

假阳性意味着我们算法的准确性有问题。

假阳性 1

当我们浏览 Twitter 表时,会遇到下面的记录。

它们都指向同一个人员 id。在检查 govAPI 表中的记录时,我们得到以下记录“74 Christoph Eymann”,它没有 Twitter 帐户,因此在 Twitter 表中找不到。

哪里出了问题:

“Christophe Darbellay”和“Christoph mrgeli”曾是瑞士委员会的政治家,因此不在 govAPI 名单中,我们只对活跃成员进行了筛选。

“Christophe”和“Christoph”被转换成相同的双变音字符串,并且与“Christoph Leymann”的 govAPI 记录 74 相匹配。由于 govAPI 列表中只有一个姓“Christoph”的人,因此我们的算法会为任何姓“Christoph(e)”的人返回一个误报,并将其与“Christoph Leymann”进行匹配。govAPI 会列出两个姓“Christoph”的人吗?匹配记录会指向两个人的 id,不再是唯一的。我们的算法在这种情况下不会导致假阳性。

解决方案:

嗯,我们必须重新调整我们的算法,使它更加严格。这意味着我们改变了名称元组生成器的条件

仅允许至少将姓氏作为元素的名称组件元组。

因此,当调用者向目录中添加一个人时,我们重新调整我们的方法,要求调用者提供姓氏在元组中的位置。

def add_person_to_lookup_directory(self, person_id, name_tuple, last_name_pos):
    tuples = self.generate_combinations(name_tuple)
    self.add_combinations_to_directory(tuples, person_id, name_tuple[last_name_pos])

add_combinations_to_directory方法中,我们现在只添加包含姓氏的元组(第 3 行)。

重新运行我们的程序会产生以下匹配的统计数据。

Matching via Lookup Directory

这实际上并不比我们的第一次尝试更好(参考下面的教程),但是我们得到了一个更健壮的匹配算法。看起来使用的 Twitter 政治家列表在联邦议会的活跃成员中并不是真正最新的。但是,这是下一课要讲的内容,我们想在下一课结束数据匹配的话题,然后继续。

源代码你可以在相应的 Github 项目中找到,所有其他文章的列表在这里

编码愉快。

Python 简介#3:使用工厂模式连接政府数据 API

原文:https://towardsdatascience.com/python-tutorial-connect-government-data-apis-by-using-the-factory-pattern-501e5c65ba6d?source=collection_archive---------33-----------------------

Python 统计教程系列

从公共政府数据 API 中获取政治家数据,以提高分配准确性

点击标题上方的链接,查看所有教程文章的列表。

在本教程中,我们主要做两个步骤

  • 首先,我们从收集的数据中生成一些图表,
  • 其次,我们将一个公共政府 API 连接到我们的程序,以可靠的方式检索政府成员和党派分配

所有教程的列表可以在这里找到。

正如你已经知道的,我们对一个通用程序感兴趣,它可以在多个国家工作。为此,我们将在教程的第二部分介绍一个抽象类和工厂模式。

Plotly 图表生成

但是让我们从第一个非常简单的任务开始,为我们的表生成两个图表。

我们创建了条形图和饼图。作为基础,我们以我们的 plotly 表 CH-tw-party-list

代码很简单:

  • 在条形图中,我们直观地显示了每个聚会累积的朋友数。
  • 在饼状图中,我们汇总了每一方的 twitter 账户。

从代码摘录中可以看出,各种配置参数允许您修改图表的布局。前往 Plotly Python 开源图形库了解更多关于图表、panda 和 Plotly 的多种可能性。

正如你所看到的,我们有很多“未知数”,也就是说,我们不能仅仅通过分析 Twitter 数据元素来确定相应的一方。在本教程的第二部分,我们将连接另一个数据源来解决这个问题。

政府数据 API 工厂

Photo by Rodney Minter-Brown on Unsplash

近年来,所谓的开放政府 API 的可用性激增。它源于数据应该开放的理念,正如维基百科对术语开放数据的描述:

开放数据的理念是,一些数据应该免费提供给每个人使用和重新发布,不受版权、专利或其他控制机制的限制。

开放数据的最重要形式之一是开放政府数据(OGD),这是由执政的政府机构创建的一种开放数据形式。开放政府数据的重要性在于它是公民日常生活的一部分,甚至是看似远离政府的最日常/最平凡的任务。

获得政府数据 API 概述的一个很好的起点是 programmableweb 目录,它列出了 20,000 多个不同的 API。

政府 API 类别可在此处找到:

https://www.programmableweb.com/category/government/apis?类别=20094

政府空气污染指数的两个例子:

美国政府的数据 API:【https://www.data.gov/developers/apis T3

或者瑞士议会的瑞士政府 API:【http://ws-old.parlament.ch/ :

我们将使用瑞士议会 API 提取议会成员的个人数据(主要是政党分配),以提高我们的 twitter 匹配算法的准确性。

正如我们在第二篇教程中已经解释过的,一个公共 API 可能会返回很多信息。为了控制一个请求中返回的数据量,使用了游标或分页机制的概念。

瑞士议会 API 在一次请求中返回大约 25 条记录。最新的请求记录将附带一个属性,告诉您是否有更多可用的数据( hasMorePages=true )。

如果设置为' true ,您可以通过添加查询参数: pageNumber=2 等获取下一页。

你可以在 API 的用户文档中找到这类信息,例如,瑞士议会 API 有一些控制输出格式、语言等的参数。

现在对 API 有了基本的了解,我们可以增强程序,使其能够从特定国家的政府 API 中读取数据。让我们深入研究代码。

增强代码 UML 图

以一种通用的方式引入政府 API 需要对我们的程序进行一些认真的设计和改进。我们的增强程序的 UML 类图如下所示(不要被复杂性淹没,所有细节将在本文后面解释)。

我们到目前为止所做工作的快速总结:

  • 我们在第二个教程中创建了 GovernmentSocialMediaAnalyzer 类,它能够检索一个国家的政治家的 twitter 相关账户数据。我们使用了一种基于配置驱动的方法——基于 YAML——将特定于国家的数据抽象到一个配置文件中
  • 定义了几种方法,使我们能够创建 panda 数据框,以及 plotly 特定的表格和图表。

现在我们将引入三个新类 govAPIFactorygovAPI (一个抽象类)和 govAPI_CH ,它们将构建一个通用的方法来连接任何类型的政府 API。

软件设计模式在软件设计中起着重要的作用,正如 Wikipedia 所描述的:

在软件工程中,软件设计模式是对软件设计中给定上下文中常见问题的通用、可重用的解决方案。它不是一个可以直接转化为源代码或机器码的成品设计。它是如何解决一个问题的描述或模板,可以在许多不同的情况下使用。设计模式是形式化的最佳实践,程序员可以用它来解决设计应用程序或系统时的常见问题。

在我们的设计中,我们将使用工厂方法模式将连接推广到政府 API,这由维基百科解释如下:

在基于类的编程中,工厂方法模式是一种创造性的模式,它使用工厂方法来处理创建对象的问题,而不必指定将要创建的对象的确切类。这是通过调用工厂方法(在接口中指定并由子类实现,或者在基类中实现并可选地由派生类重写)而不是通过调用构造函数来创建对象来完成的。

我们的设计将以策略为基础,来定义

  • 一个抽象的基类(父类— GovAPI )
  • 一个派生类(child — GovAPI_CH ),它将具有特定于国家的实现(如瑞士)。
  • 将来,我们可以引入额外的类,例如对于英国,我们将构建实现类: GovAPI_UK

抽象基类“GovAPI”

govAPI 是一个抽象类,包含几个抽象方法。抽象方法是已声明但不包含实现的方法。

在 Python 中,抽象类是从 ABC 类派生(或继承)的,并且将有一个或多个标有@abstractmethod 的方法。

所以抽象类为你提供了一个构建计划,在我们的类 govAPI_CH 中,任何继承它的实现类。

govAPI_CH 要实现什么样的方法?

首先,load _ government _ members()方法的实现必须处理从政府 API 获取的政治家的数据记录。每个提取的记录——代表一个政治家的数据——必须传递给方法 add_person_record (该方法已经由 govAPI 基类实现)

现在的问题是, add_person_record 方法到底在做什么?好吧,看看下面的代码。

该方法只是为我们的个人记录准备一个目标字典。即定义的属性名(等)。)是我们希望用于任何 GovAPI 实现的名称。

这意味着我们检索的记录以专用政府 API 实现的形式(即以瑞士政府议会 API 的形式)必须通过使用一堆 getter 方法来转换。

这些 getter 方法要么是抽象的,要么返回空字符串。提供正确的 getter 实现是继承类( GovAPI_CH )的实现者的责任。

实现类“GovAPI_CH”

下面显示了 GovAPI_CH 的 getter 方法实现。它由一组 getter 方法组成,这些方法将从记录中返回所需的属性值。

让我们深入到方法load _ gegovernment _ members:

我们的实现使用了 python 模块 requests ,这是“一个优雅而简单的人类 HTTP 库”在本文的简介部分,我们提供了瑞士议会 API 的概述。下面的代码将使用分页机制获取数据。

我们将 URL 及其参数放在配置 YAML 文件中。

govAPIUrl: "http://ws-old.parlament.ch/" 
govAPICouncillorsRes: "councillors" 
govAPIParams: 
  - format : "json"
  • 8:第一个 requests.get 将获取所有议员概况页面http://ws-old.parlament.ch/councillors?format=json&page number = 1
  • 15:如果数据记录被标记为激活,将提取详细记录
  • 17:第二个请求将使用记录的 id和细节记录的 URL。也就是说,在这个例子中,我们获取了 id 为‘1358’的政治家记录:http://ws-old.parlament.ch/councillors/1358?format=json
  • 19:我们将检索到的详细记录传递给方法 addPerson ,该方法将把提供的数据记录转换成目标记录(通过使用我们已经实现的 getters)。
  • 20:最后,我们检查 hasMorePages 属性,如果到达最后一条记录,我们将中断循环。

上述方法将在 govAPI 函数create _ political _ from _ govAPI _ table(已经由 govAPI 父类实现)中调用,该函数将把政客记录列表转换为 Panda 数据帧。

正则模型

重要的是要认识到,只要我们基于 govAPI 抽象类实现一个特定的类,这个 Panda 数据帧的结构将与任何种类的政府 API 相同。所以我们将数据标准化,这样我们就可以用标准化的方式工作和处理它。

我们再次努力实现一个重要的设计模式,我们的目标结构(或模型),被称为规范模型。正如维基百科所描述的:

规范模型是一种用于在不同数据格式之间进行通信的设计模式。本质上:创建一个数据模型,它是所有其他模型的超集(“规范的”),并创建一个“翻译”模块或层,所有现有的模块通过它与其他模块交换数据。

从概念上讲,我们已经建立了一个迷你数据管道。对于每个政府 API,我们必须实现一个数据记录获取函数和转换规则(getters ),将数据转换为我们的标准化数据。

整个模式在 UML 序列图中可视化。

  • “消费”操作由步骤 60 表示
  • “转换规则”操作由步骤 80-120 表示。
  • “存储”操作由步骤 130 表示

重要的是你要理解各种类的职责。 govAPIgovAPI_CH (红点)对外界可见( govAPIFactorygsma )作为一个类实例。对于调用者来说,谁实现哪个方法并不重要。

govAPIFactory 类

还缺少最后一个东西,即 govAPIFactory 类,它非常简单。根据 country_code ,将创建相应的实现类实例并返回给调用者:

可以看到,这个类只有一个类方法。即 GovAPIFactory 不支持对象实例。一个工厂在一个程序中只包含一次,这被称为单例模式。

软件工程中,单件模式是一种软件设计模式,它将一个实例化限制为一个。当只需要一个对象来协调整个系统的动作时,这很有用

我们在这里使用了一个派生,通过只有一个静态类方法来确保单例性。

这是相当多的内容要吸收,我们介绍了两个重要的设计模式工厂方法和规范的数据模型,以及如何生成第一对图表。

lesson3.py 程序将在 Plotly 内生成名为 CH-govapi-member-list 的表格。

今天就到这里,在下一篇文章中,我们将开始通过结合两个数据源来进行一些数据分析。

锻炼

你可以在这里找到练习教程:链接

源代码

源代码可以在这里找到(第三课目录):https://github.com/talfco/clb-sentiment

进一步阅读

如果您想更深入地了解设计模式和 Python 的主题,请阅读下面的文章"确保代码整洁:Python 的一瞥,参数化的"

原载于 2019 年 2 月 11 日dev.cloudburo.net

Python 教程:模糊名称匹配算法

原文:https://towardsdatascience.com/python-tutorial-fuzzy-name-matching-algorithms-7a6f43322cc5?source=collection_archive---------3-----------------------

sur Python 统计教程系列

如何应对用作标识符的人名变量的可变性和复杂性?

这是我们探索 Python 数据世界之旅的第五篇文章。点击上面的链接,获取已发表文章的列表。

名称匹配的方法

在从公共来源检索的统计数据集中,(一个人的)姓名通常被视为与其他一些字段(如电子邮件、电话号码或 ID 号码)的元数据相同。在我们的样本集中是这样的情况:

当姓名是唯一的统一数据点时,正确匹配相似的姓名就变得更加重要,但是它们的可变性和复杂性使得姓名匹配成为一项极具挑战性的任务。昵称、翻译错误、同一个名字的多种拼写等等都可能导致匹配失败。(【rosette.com】T2

这正是我们现在面临的情况:

我们的 twitter 数据集包含一个由 Twitter 用户自己设置的名称变量。根据个人的偏好,它可以

  • 一个完整的假名
  • 名字,姓氏(反之亦然)
  • 只有姓氏
  • 名字缩写,中间名缩写,姓氏缩写
  • 他的全名,但不小心拼错了
  • 等等。等等。等等。

这给我们留下了一些数据质量和规范化的挑战,我们必须解决这些挑战,以便我们可以使用 Name 属性作为匹配的标识符。

下表描述了一些挑战以及我们应对这些挑战的策略。用于解决挑战的每种方法都将在本文中解释,并且是 Github 教程源代码的一部分。

让我们从解决头衔&敬称缺失成分、和其他一些异常开始。

幸运的是,从许多记录的角度来看,我们的列表是可管理的,也就是说,我们可以对“Name”属性中使用的异常和标题进行手动检查。

命名清洁剂步骤

我们的质量审查显示,Name 字段似乎具有良好的质量(没有使用虚拟或昵称)。但是,我们发现了一些异常情况,如下所示:

我们在第一个清理步骤中修复了程序中的这些异常。为了保持通用性,我们再次使用 yaml 配置文件并添加了两个额外的参数。

  • twitterNameCleaner ,由必须从任何 twitter 帐户名称中删除的关键字列表组成
  • twitternamesexpender,它将每个 Twitter 帐户名称缩写子串扩展为一个完整的名称字符串。

我们特定于国家的 yaml 文件通过以下条目得到了增强。

清理步骤在下面的方法中调用,该方法评估我们的 Twitter 表的每一行(稍后解释它与程序的集成)

使用字符串替换方法非常简单

  • 我们从 Name 属性中删除了在 twitterNameCleaner 列表中找到的每个关键字(用' ' '替换它)
  • 我们将在twitternamesexpender字典中找到的每个缩写替换为它的全名。

对于我们的下一个正常化步骤,我们介绍一种起源于 100 年前美国面临巨大移民潮时的方法。

双变音算法

该算法的原理可以追溯到上个世纪,实际上是 1918 年(那时第一台计算机还远在几年前)。

作为补充信息(如果你曾经参加过百万富翁智力竞赛节目),第一台电脑是在 23 年后

Z3 是由康拉德·楚泽设计的德国机电计算机。这是世界上第一台可编程的全自动数字计算机。Z3 由 2,600 个继电器组成,实现了 22 位字长,以大约 4–5Hz 的时钟频率运行。程序代码存储在穿孔胶片上。初始值是手工输入的(维基百科)

A Z3 replica at the Deutsche Museum (CC BY-SA 3.0)

回到 1918 年,美国人口普查局的 Robert C. Russell 发明了 Soundex 算法,这种算法能够对英语进行索引,只需粗略浏览一下就可以找到同一姓名的多种拼写。

美国的移民有一种不以罗马字符为基础的母语。为了写出他们的名字,他们亲戚的名字,或者他们来自的城市,移民们不得不尽可能地猜测如何用英语来表达他们的象征性语言。美国政府意识到需要能够以一种允许同一姓名的多种拼法(例如 Smith 和 Smythe)被分组的方式对普通公民的姓名进行分类。(点击阅读完整故事

Immigrants arriving at Ellis Island — Wikipedia — Commons Licence

Soundex 算法基于字母表中字母的语音分类。在他的专利中,Russell 描述了给每个类别分配一个数值的策略。例如,约翰逊被映射到 J525,米勒被映射到 M460 等。

随着时间的推移,Soundex 算法在效率和准确性方面得到了发展,并被其他算法所取代。

在很大程度上,它们都被强大的索引系统所取代,该系统被称为“双变音位 T2”。该算法是开源的,其最新版本发布于 2009 年左右。

幸运的是有一个 Python 库可用,我们在我们的程序中使用它。我们围绕该算法编写了一些小的包装器方法,并实现了一个比较方法。

doublemethane方法返回一个由两个字符组成的关键字元组,它是传入的单词的语音翻译。我们的比较方法显示了该算法的排序能力是相当有限的。

让我们通过引入基于 Python pytest 框架的 test_class.py 来运行一些验证检查,以评估算法的效率。

pytest框架使得编写小测试变得容易,同时也支持应用程序和库的复杂功能测试。(链接)

它的用法很简单,您可以在下面看到测试类的实现

测试结果如下所示。我们使用了两个名字(A+B ),并用一些改变的名字(A1/A2+B1/B2/B3)来检验算法的效率。

  • A1+B1 通过了强匹配检查。因此,缺少空格和用 u/a 替换“/”似乎不会影响双变音键的生成
  • B2 通过了正常比赛。拼写错误也被算法覆盖
  • A2 + B3 正在失败。A2 使用名称部分的缩写,无法应付。这种行为我们已经预料到,并决定引入名称扩展器算法(见上文)。B3 因缺少“-”而失败。这是意料之外的,但是我们用第二个名字 cleanser 步骤覆盖了这个行为。

命名清洁剂第二步

我们的小规模试运行表明,以下额外的清洁步骤是有益的:

  • 我们必须去掉任何可能导致失败的特殊字符
  • 无序成分,即名字之前的姓氏影响语音键的生成。因此,最好是按字母顺序对姓名成分进行排序,以提高匹配的准确性。

除了删除任何特殊字符之外,我们还决定删除任何 Unicode 字符,即在瑞士,使用多种德语(δ,θ,ü)、法语(δ,é)或意大利语变音符号,我们也想删除它们。

下面的normalize _ unicode _ to _ ascii方法使用 unicodedata 库将名称转换为 ASCII,然后将所有字符转换为小写。然后,使用两个正则表达式删除特殊字符和多个空格。

正则表达式操作是一种强大的机制,但对于新手来说并不容易理解。你可以通过下面的教程来获得这个强大方法的第一印象。

  • 只有一个解释,正则表达式术语'[^a-za-z0–9]+'的意思是从传入的字符串中取出' a-z '+' a-z '+' 0–9 '+' '之间任意数量的字符。[1]+是正则表达式中的特殊字符。表达式序列可以被翻译成“从字符串中去除任何特殊字符”

数据框“应用”方法的妙处

在两个类中建立 __calculate_name_matching 方法

现在,我们已经将所有的名称清理器、规范化和语音关键字生成器方法组合在一起(捆绑在 namemachting.py 模块中),最终可以为我们的两个类 govAPIgovernment social media analyzer 构建我们的名称匹配标识符创建方法_ _ calculate _ name _ matching

One new module and two new methods are added

这两个类都获得了一个新方法,我们将其应用于它们的 Panda 数据框,每个方法都创建了三个新的标识符属性( col_match1、col_match2、col_match3 )。然后,这三列可用于合并两个数据框。

我们的政府 API 类的方法如下所示:

所以对于我们的 govAPI 类如下。这是我们抽象类中的一个实现方法。该方法用于任何实现的子类(参考我们的早期教程中解释的工厂设计)

实现很简单,我们规范化每个表的人名(从政府 API 我们得到三个独立的属性,从 Twitter API 一个帐户名),然后计算两个双变音标识符字符串。我们将所有三个新值追加到传入的行中。

不要打电话给我们,我们打电话给你:“好莱坞原则”

Photo by Annie Spratt on Unsplash

有一个问题仍然悬而未决:“我们如何使用我们的新方法来增强由三列及其每行计算值组成的数据框?

嗯,这可以通过使用熊猫数据帧应用 方法很容易地实现,其定义为:

apply()可以沿数据帧的任意轴应用函数

这是在数据框的每一行或每一列上进行任何计算的一种很好很优雅的方式。

下面你会看到增强的create _ politican _ from _ govapi _ table方法。在第 4 行代码中,我们新调用了数据帧( df )的 apply 方法,并将我们的方法名 self 作为参数传入。__calculate_name_matching 并指示 apply 方法为每一行调用我们的方法( axis=1 )。

现在熊猫数据框

  • 遍历每个数据行,每个数据行代表一个专门的政治家的数据记录
  • 称我们为自我。_ _ 计算名称匹配方法
  • 将数据行作为参数传入,并存储回方法调用返回的数据行(这三个新列)。

非常漂亮不是吗?我们不必编写任何类型的循环来获取数据、检查循环结束条件等等。我们刚刚实现了可以传递给 apply 方法的方法。

这种交互是 IT 界众所周知的设计原则,被称为“好莱坞原则”,Matthew Mead 的优秀博客文章描述如下:

这个原则的精髓就是“不要打电话给我们,我们会打电话给你”。如你所知,这是你在好莱坞电影试镜后听到的回应。这也是软件好莱坞原则的相同概念。目的是明智地构造和实现您的依赖关系。

想想我们上面的实现。我们的_ _ calculate _ name _ matching方法与 panda 数据帧实现完全分离。我们的方法只获得一个行字典作为输入,我们可以操作它,并在最后作为返回值返回。我们完全没有意识到有一个大规模的熊猫数据框架实施涉及,也没有任何依赖它。

在最基本的层面上,这个原则是关于减少软件系统中的耦合。这又回到了软件开发中众所周知的一句话:松耦合和高内聚。通过确保没有不必要的引用,并且正确地引用类和其他子系统,可以保持类的松散耦合。虽然好莱坞原则没有规定任何关于凝聚力的东西,但它也是一个重要的方面。内聚就是让你的类忠于它们的意图,不允许它们的行为超出其核心目的。像高耦合一样,低内聚不会导致系统不稳定或不能正常工作,但可能会导致软件维护困难。

今天的设计教学已经足够了,当我们运行我们的程序时,两个 plotly politician 表都被 3 个新属性增强了,这允许我们最终将它们结合在一起(uff…我们必须做一些概念性的工作)

最后,连接数据框

我们现在必须连接两个数据框,这是 Panda 提供的许多组合和合并可能性之一。参考下面这篇由datacarpentry.org写的文章,这篇文章很好地介绍了整个主题。

组合数据帧的另一种方法是在每个数据集中使用包含公共值(一个公共的唯一 id)的列。使用公共字段组合数据帧称为“连接”。包含公共值的列称为“连接键”。当一个数据帧是一个“查找表”,包含我们希望包含在另一个数据帧中的附加数据时,以这种方式连接数据帧通常很有用。

这是通过可应用于熊猫数据帧的合并方法实现的(参见下面的代码行 23)。你必须提供参数

  • 两个数据帧
  • 匹配键(在我们的例子中,双变音属性 col_match2 在两个数据帧中都可用)
  • 和连接策略( how 参数)

我们表示一个“外部左”连接( how=left) ,它可以被可视化如下

省略参数将如何导致内部连接

“内连接”意味着只接管匹配的行,“左连接”意味着接管左数据帧的所有行。如果没有匹配的右表记录,用“NaN”值填充相关记录。

我们新的 Plotly 表CH-tw-politican-merged-list就有这样的条目。

这意味着我们的匹配策略仍然会遗漏条目。让我们将合并后的表格的饼状图与初始表格进行比较:

Twitter User per Party (merged with gov API source)

最初的一个(参考这篇文章)漏掉了 51 个,通过我们简单的合并策略,我们可以识别另外 14 个条目。

Twitter User per Party (just using Twitter API information)

所以,我们还没有到那一步(啊…),但是今天足够了,在下一节课中,我们将尝试调整我们的匹配策略,以便我们可以再次减少未知。

源代码你可以在相应的 Github 项目中找到,其他所有文章列表在这里

Python 教程:政府社交媒体分析器类构建

原文:https://towardsdatascience.com/python-tutorial-government-social-media-analyser-class-build-out-12858190b284?source=collection_archive---------21-----------------------

Python 统计教程系列

增强您的程序,使其适用于任何政治人物名单

点击标题上方的链接,查看所有教程文章的列表。

在这个练习中,我们将把我们的初始程序(参考第一个教程)转换成一个通用程序,用于获取一个国家的议会成员的 twitter 信息。这意味着我们对代码进行第一次迭代的概括和重构。

我们的目标是有一个程序可以分析任何国家的政治家的 Twitter 账户,而不仅仅是瑞士。

因此,我们的计划应该以一种我们也可以在其他国家使用(即配置)的方式进行推广。

Yaml 配置文件

我们的第一个 lesson1.py Python 程序是直接在程序中硬编码 twitter 账户及其列表名。

现在我们要做的是从配置文件中读出这些信息,类似于我们在第一课中为传递 Twitter API 秘密所做的工作(参考教程)

这个信息不是什么秘密,所以我们创建了一个新的公共 yaml 配置文件,它将用于我们程序的任何国家配置参数。当您一般化程序时,将所有这些参数卸载到一个配置文件中是一个关键点。

正如你在下面的截图中看到的,我们将文件命名为 config-CH.yaml

config-CH.yaml

那么为什么要使用 CH 后置呢?CH 后缀是瑞士国际 ISO 国家代码标准的 Alpha-2 代码。代码值(或参考值)是任何信息编码程序的组成部分。最佳实践是尽可能使用标准化的(不要在这里重复发明)。也就是说,对于国家,我们决定使用标准 ISO 3166-1 的 Alpha-2 代码。正如您将在后面看到的,对于编码语言,我们采用了类似的方法。顺便说一下,ISO 的意思是“国际标准化组织

重构和增强

GovernmentSocialMediaAnalyzer 类

对于我们的一般化程序,我们做第一个重构步骤。代码重构是在不改变现有计算机代码外部行为的情况下对其进行重构的过程。所以我们将 sample1.py 中的类重命名为government social media analyzer,并通过参数 country_code 增强其类构造函数 __ init__ 方法。我们做出了第一个设计决定:

设计决策 1:我们的类 GovernmentSocialMediaAnalyzer 的一个实例将封装一个专用国家的数据和行为。

代码增强如下所示:

  • 创建类时传入的 country_code 参数(如 CH
  • 将作为私有实例变量 __ country_code 存储并使用
  • 要创建 yaml 配置文件名
  • 从这里我们将加载配置数据并将数据存储在私有变量 __cfg

因此,现在我们准备通过从存储在 self 中的配置数据中读取 twitter 帐户和列表名称来推广我们的 get_government_members 方法。__cfg 实例变量。

但是让我们先完成对我们的 init 类的重构和增强。我们采取另一个设计决策

设计决策 2:init方法应该封装所有 Twitter 帐户从 Twitter 的加载,以及到 attributes 列(=字符串数组)中相关属性的转换。该列应该可以作为私有类实例变量使用

这意味着当我们为一个专门的国家创建一个 GovernmentAnalyzer 实例时,案例的初始化阶段将包括将来自 Twitter 的数据放入我们的 intern 数据结构(如列所示)的所有必要步骤

我们将在一个专用帮助器方法中完成这个步骤,这个方法将被称为 __ extract_columns 。我们将它定义为私有方法(__ prefix),因为它不应该被这个类之外的任何人使用。

第一课中重构的类现在看起来像这样。

我们使列属性更具描述性,并将它们定义为类实例变量,以便这些列可以被我们的类中的任何方法使用。

所以我们已经完成并重构了类实例创建类

  • 5–12:加载特定于国家的配置文件的代码块
  • 16–21:从秘密配置文件中读取 twitter 安全令牌和密钥的代码块,然后连接到 Twitter API
  • 39:调用 _extract_columns 方法检索数据并转换成列。

教程一中的 check_for_party 算法是在代码中硬编码 party 缩写。

好了,让我们重构代码,并将参与方信息移动到我们的配置文件中。由于 YAML 文件的灵活性,这可以很容易地完成。

设计决策 3:我们希望为每个政党使用几个政党缩写(可能使用多种语言)和关键字(例如,政党 Twitter 昵称),以尝试识别政治家的政党所有权。

所以我们的配置 config-CH.yaml 将需要每一方的配置信息。在瑞士的 parlament.ch 网站上可以找到四种语言的政党及其缩写。

在 YAML,您可以快速建立一个配置项目列表(例如,聚会配置项目)。列表成员由前导连字符(-)表示,每一到多行一个成员,或者用方括号([ ])括起来,并用逗号分隔(,)。

  • 当事人名单成员用连字符表示。一个政党名单成员有一个 twitter 和缩写属性。缩写(缩写)属性本身是一个由方括号符号表示的字符串列表。

config-CH.yaml (with parties list)

如果我们检查加载的配置文件(存储在 self 中。_cfg 变量)在 Python 调试器中,使用 Python 列表和字典应该很清楚数据结构是什么样子。

作为对abbres属性的补充说明,我们介绍了他们的政党缩写列表,即拥有多种国家语言也意味着政党有多种缩写(例如,德语和法语)。在我们上面的例子中是“FDP”和“PLR”我们想检查所有的。在其他国家,可能只有一个缩写,但有了这个决定,我们就是未来的证明。

我们改进的 check_for_party 方法现在看起来如下。它将遍历所有 twitter 帐户和每一方的配置记录,并检查 twitter 帐户的描述或昵称是否与某一方匹配。

  • 在第 6、10 和 19 行,我们从配置结构中获取数据。
  • 根据属性类型,我们必须遍历值列表(6,10)或直接获取数据(19)
  • 如果我们有一个匹配,第一个缩写将被返回,作为我们识别当事人的代码值:RES = party[' abbs '][0]

微调算法

引入第二个 Plotly 表:按交易方对账户进行分组

为了微调我们的算法,我们必须检查它在寻找 twitter 帐户的一方时的有效性。为此,我们必须引入第二个表,它将根据我们的 twitter 帐户的聚会分配对它们进行分组。

强大的熊猫包将为我们提供必要的工具。你可以参考 panda API 描述后面的,了解如何分组数据的所有细节。

代码片段的一些注释:

  • 4–8:我们在这里创建一个包含 4 列的 panda_data 记录。 __col_party__col_followers_count__col_friends_count__col_party 使用了两次,第一列用于标记每一行(如您在第 11 行看到的,我们按参与方进行分组),在第二列中,我们汇总了具有相同参与方的行。
  • 9:我们创建了这个表的第一个 panda 数据框,有四列
  • 11:这里我们通过使用 groupby 函数来转换创建的数据帧。我们还为第二、第三和第四行定义了聚合 agg 操作。
  • 15–19:创建一个漂亮的 plotly 表的基本材料。

让我们运行程序并检查我们的 party assignment 分配算法的准确性。作为程序执行的结果,您现在必须在您的 plotly 帐户中创建表格(还将创建一些网格表,这些表格目前并不相关)。

用关键字属性增强我们的配置文件

我们的首次调查显示,大多数政客(65 人)不会在他们的账户描述/昵称中提及他们的党派缩写或党派 twitter 昵称。

所以让我们试着微调我们的算法。让我们再次浏览这个列表,并检查其他可以帮助我们识别他们的聚会关系的关键字。

我们找到了以下关键词:

  • 社会主义党
  • glp (GLP)、
  • 格鲁内(GLP)
  • 勒加

所以让我们用一个新属性将它添加到我们的配置文件中: keywords 。这就是 YAML 的魅力所在,你可以很容易地用附加属性来扩展它。在我们的例子中是另一个列表属性。

我们在我们的 check_for_party 方法(23–28)中添加了额外的检查

瞧,我们可以找到另外 13 个拥有超过 20,000 名粉丝的推特账户。尽管如此,52 个帐户不能映射到一个聚会,但为此,我们必须连接另一个数据源,这将在后面的教程中完成。

作为今天的最后一步,我们重构了 create_politican_table 方法。我们主要通过在文件名中使用国家代码来规范 plotly 中使用的文件名。这使我们能够为不同的国家生成表格,并确保它们不会在我们的 plotly 帐户中相互覆盖(20)。

现在,我们已经概括和重构了我们的整个应用程序,并为进一步的构建打下了良好的基础。

我们现在可以为一个特定的国家实例化一个government social media analyzer(假设我们已经提供了必要的配置文件),并将 twitter 相关数据提取到一个 plotly 表中以供进一步处理。

作为一个可视化的 UML 序列图,我们的类的交互流可以表示如下:

如果你想了解更多关于 UML 序列图的细节,请参考下面的教程。这是一种很好的可视化程序各个方面的技术。在上图中,消息的返回调用用蓝色表示。

例如:panda 包创建数据帧的消息行用红色表示(createDataFrame),它返回的 data frame 对象的消息行用蓝色表示。

锻炼

使用通过政府推特账户(【https://twitter.com/TwitterGov】)提供的列表之一,例如,英国议会成员列表(【https://twitter.com/TwitterGov/lists/uk-mps】)。

  • 制作相应的 yaml 配置文件
  • 看看什么样的信息可以用来识别政治家的政党。
  • 用你的发现强化关键词
  • 用一个用户输入问题增强主程序,类似于“你想分析哪个政府”。提供可用配置列表,然后根据用户选择运行程序。
  • 想想分析每个国家的多个政治家名单所需要的改变。也就是说,我们希望区分每个国家的不同政府机构,并在配置文件中对其进行概括。

源代码可以在这里找到:https://github.com/talfco/clb-sentiment

原载于 2019 年 2 月 3 日 dev.cloudburo.net

Python 教程:瑞士政府成员的 Twitter 账户检索

原文:https://towardsdatascience.com/python-tutorial-retrieve-a-list-of-swiss-government-members-from-twitter-d5f999555f98?source=collection_archive---------18-----------------------

Python 统计教程系列

开始你的政治家社交媒体分析之旅

点击标题上方的链接,查看所有教程文章的列表。这是第一条。

本教程将向您展示如何通过 Twitter API 提取瑞士政府成员的 tweet 列表。提取的数据将被放入 Panda Dataframe 中,然后通过强大的 Plotly 软件包进行可视化。

Source Attribution: http://www.parlament.ch/

结果将如下所示:

从哪里获取数据?

twitter 账户 SoMePolis 维护着一份拥有 Twitter 账户的瑞士政府成员名单。

该计划的目标是获取所有名单成员(正在发推特的政府成员)并提取一些关键人物(追随者和朋友)

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

确认后,您就可以在您的开发者帐户中创建您的第一个应用程序了。

完成后,Twitter 将生成 API 密钥和令牌,您将在程序中使用它们与 Twitter API 进行通信。

该写程序了。

我们将创建一个 TwitterClient 类,它提供两个方法 get_government_members 和 create_plotly_table

该程序将使用以下 python 包

  • tweepy :将提供对 Twitter 公共 API 的访问
  • yaml :是一个解析器,可以读取 yaml 配置文件(用来存储我们的密钥)
  • pandas :是一个提供高性能、易于使用的数据结构和数据分析工具的库
  • plotly :是一个图形库,可以在线制作交互式的、出版物质量的图形。

也就是说,通过使用这四个库,我们已经做好了准备。

init

在类初始化方法中,我们必须建立与 Twitter API 的连接。

为此,我们使用从 yaml 文件加载的密钥和令牌,该文件位于当前目录之外的 secret 目录中。

with open("../../secret/twitter.yaml", 'r') as stream:

这是一种常见的方法,用于定位目录中的敏感数据,这些数据只存在于本地计算机上,不会在 Github 这样的远程源系统中进行检查。

Yaml 是一种人类可读的数据序列化语言。它通常用于配置文件,但也可以用于存储数据的许多应用程序。

它有一个简单的语法,对于我们的例子,安全令牌有四个 : 对,它们被加载:

consumer_key = res['apiKey'] 
consumer_secret = res['apiSecretKey'] 
access_token = res['accessToken'] 
access_token_secret = res['accessSecretToken']

作为补充信息,当您增强您的程序并需要额外的非敏感配置数据时,您将引入第二个包含公共信息的 yaml 文件,您可以使用普通源代码签入该文件。

下一步,我们使用 OAuth 对 Twitter 进行认证,并获得对其 API 的访问权。OAuth 是一种开放的访问授权标准,通常用于互联网用户授权网站或应用程序访问他们在其他网站上的信息,但不需要给他们密码。即,您将向他们提供您的秘密访问令牌和密钥。

我们创建了一个私有的类变量 _api ,它保存了对 Twitter API 的引用。通过这个引用对象,您现在可以与 Twitter API 交互,这里描述了所有可用的方法。我们为 API 使用私有变量,因为我们不想直接向类的消费者提供 API,而是提供更高级别的方法,如 getgovernment_members

当您设计将在程序或模块中使用的类时,定义类变量的范围(public、protected、private)是一个重要的设计决策。

获取 _ 政府 _ 成员

在这个方法中,我们将从上面描述的 twitter 帐户 SoMePolis 的列表 BundesparlamentarierInnen 中获取所有的 twitter 政客帐户。

第一步,我们获取 SomePolis 帐户的所有 Twitters 列表,并搜索所需的列表。找到它之后,我们将使用它的 list.id 来检索列表中的所有成员(twitter 帐户)。

为了检索一个列表的所有成员,我们必须使用一个所谓的光标(位置 7 )

管理任意大型列表的数据检索是 API 接口中的一个重要概念(例如,一个列表可能有数百万个条目)

如果你在程序中使用下面的代码序列,你将只返回列表的前 25 个成员。

__api.list_members(list.id)

使用这种策略,Twitter API 将确保它不必在一个请求中向客户端程序传递大量数据。如果您想要所有成员,您必须多次调用 list_members。在每个请求中,将返回 25 个列表成员帐户的数据包。这个概念被称为“分页”,在各种提供者的公共 API 中使用(你可以在这里找到更多信息: Tweeply Cursor Tutorial

该列表大约有 110 个成员,这意味着 list_members 方法将被调用五次。最后,结果变量将有 110 个 Twitter 帐户。

创建 _ 绘图 _ 表格

最后,我们从 twitter 帐户列表中提取某些数据,以供进一步处理。

我们将准备一个 Panda Dataframe,它是一个二维大小可变的、潜在异构的表格数据结构,带有标记轴(行和列)。

我们将提取的 Twitter 帐户列表

  • 屏幕名称,也就是@ <推特名称>
  • ,通常是这个人的全名
  • 描述,提供对该人的附加描述
  • Twitter 账户的关注者计数,以及好友计数

我们必须为数据帧创建列,这是通过以下命令序列实现的

col1 = [list.screen_name for list in lists]

我们遍历列表,为每条记录提取出 screen_name

最后,我们创建一个 plotly 表:

有两个主要模块,我们将需要生成我们的 Plotly 图形。

  • p lotly.plotly 包含了帮助我们与 plotly 服务器通信的功能
  • plotly.graph_objs 包含了为我们生成图形对象的函数。

您必须在 https://plot.ly 创建一个帐户(当您第一次运行应用程序时),您生成的表将被上传到该帐户。因此,您将在您的帐户中获得一个与此类似的表。

在 Plotly 创建账户

第一次运行该程序时,会要求您在 plotly 注册并创建一个帐户。

创建帐户后,您必须检索访问令牌(如有必要,创建一个新的)

并将它存储在文件中。凭证在主目录的文件夹中。plotly

这就是今天的练习,尝试添加以下代码序列。

锻炼

通过分析每个政府人员的网名或描述,试着识别他们的党派。作为指导性帮助,请查看以下瑞士聚会指南。主要政党是“CVP”、“FDP”、“SP”、“SVP”以及“Grüne”。缩写很有可能是一个人提到的(见下面截图)。

因此,构建一个新的 Panda 列,并将其添加到数据框中进行可视化。

源代码( lesson1.py )可以在这里找到:https://github.com/talfco/clb-sentiment

此处练习的解答

原载于 2019 年 1 月 26 日【dev.cloudburo.net】

Python 教程:简要介绍主要统计概念

原文:https://towardsdatascience.com/python-tutorial-short-stop-to-introduce-main-statistical-concepts-8213724550f4?source=collection_archive---------19-----------------------

Python 统计教程系列

通过使用我们的教程程序作为展示来解释概念

我计划在本次会议中通过名称变量介绍两个数据集的合并算法。

为了简单明了地概述整个方法,有必要事先介绍一些统计概念。

我决定做一个短暂的停留,将工作嵌入到统计框架中,这是任何数据探索项目的基础。所以今天没有编程,只是一些概念,对整体理解至关重要。我计划在未来建立更多的统计站来建立我们项目的科学背景。

Photo by chuttersnap on Unsplash

总体、样本、测量、参数和统计

我们从统计学中使用的一些基本定义开始,通过使用塞勒学院的介绍教程(内容在知识共享许可下提供)

群体 是感兴趣对象的任何特定集合。 样本 是总体的任何子集或子集合,包括样本由整个总体组成的情况,这映射到术语 普查

人口

在我们的例子中,人口是瑞士联邦议会的瑞士政府成员(议员)。

联邦议会是两院制的,由 200 个席位的国民议会和 46 个席位的州议会组成。这些房子拥有相同的权力。两院的议员代表,但是,尽管国民议会的席位是按人口比例分配的,但每个州在上院有两个席位,除了六个半州各有一个席位。两人每四年选举一次,最后一次选举将于 2019 年举行。(维基百科链接)

样品

我们的样本是所有议员,他们都有一个 Twitter 账户,并被列为 SoMePolis Twitter 议会名单的成员。这是一个子集,所以我们不用人口普查这个术语。

一个 测量值 是为总体或样本的每个成员计算的一个数字或属性/变量。样本元素的测量值统称为 样本数据

尺寸

对于样本集的每个成员,我们通过两个数据集收集变量,即第一组变量通过 Twitter API 收集,第二组变量通过政府 API 收集。

抽样资料

我们通过统一这两个数据集得到的总体样本数据集。

一个 参数 是一个概括总体某个方面的数字。 统计量 是从样本数据中计算出的数。

因为我们要计算的数字是基于人口子集的,所以我们讨论的是统计数据而不是参数。

这就是最初的范围定义;现在让我们关注“变量”的概念,这是至关重要的。

数据集和变量

作为补充,让我们来看两个数据集,我们已经检索过了:

作为第一个表( Tutorial 2 ),我们从 Twitter 中检索了以下瑞士政治家 Twitter 账户的数据记录。

Image owned by the writer

它为我们提供了在未来分析中发挥作用的三个统计变量:

  • 追随者计数
  • 好友计数
  • 聚会
  • **姓名,可能代表 Twitter 用户的真实姓名。“可能”这个词在这里是必不可少的,但更多的是在后面。

我们还从 Twitter 获得了一个标识符变量,它帮助我们揭示一个人的真实身份(在我们的例子中,是瑞士委员会的成员):

  • ScreenName, 这是 Twitter 账户的唯一标识符。如果我们必须在稍后阶段通过 Twitter API 检索附加信息,我们可以使用它。

作为第二个表(教程 3 ),我们通过瑞士政府 API 检索了瑞士联邦议会所有现任议员的名单。

Image owned by the writer

从该表中,我们得到了以下变量,我们希望将其用于我们的统计评估:

  • **名字-中间名-姓氏,这是(理事会的)人名。
  • 出生日期
  • 议会由两院组成,即国民议会(下院)和上院。这由表中的值“N”或“S”表示。
  • 选举日期
  • 性别
  • 玛丽塔尔状态
  • 当事人
  • 家庭地址(邮政编码、城镇名称、邮政编码)

以及标识符变量

  • id ,标识政府 API 上下文中的数据记录

让我们更深入地挖掘一下数据集中使用的变量的统计意义

可变术语定义

在统计学中,一个变量有两个定义特征。(1)变量是描述人、地点、事物或想法的属性。(2)变量的值可以从一个实体到另一个实体“变化”。

在我们的例子中,一个人的性别政党、或 T 维特追随者数量都是潜在变量。

数据类型分类

变量的数据类型在统计中起着重要的作用,必须理解这一点才能正确地将统计测量应用到数据中。在统计学中,术语“测量尺度”也可以使用。

下面的树对数据类型概念进行了分类

Data Type Classification Tree (image owned by writer)

参考下面这篇优秀的中型文章来获得对数据类型主题的整体介绍。

让我们将分类应用于我们的两个数据集,结果如下表所示。

Image owned by the writer

两条评论

  • 我们将每个集合的变量标记为“唯一”,这标识了一个专用的样本结果,我们不能对其执行任何数据分析。所谓的标识符变量
  • 在 gov.api 数据集中,我捆绑了一些变量来描述一个人或地址。即,一个人的名字由该人家庭住址的名、中间名、组成,家庭住址由邮政编码、邮政编码组成。

存在许多变量类型,可以用上述方案对它们进行分类(参考参考章节中的附加链接)。不过,我们现在对所谓的标识符变量感兴趣。

标识符变量

标识符变量和唯一标识符通常在统计中用于唯一标识数据收集目的。

标识符变量是分类变量,每个类别有一个个体。例如:

社会安全号码、面试者身份证号码或雇员身份证号码。

由于标识符变量是单一的,不可能对它们进行任何数据分析。相反,它们是用来识别结果的。

嗯,我们的两个数据集在自己的域中有一个唯一的标识符。然而,没有真正的唯一标识符允许通过两个(跨域)数据集中可用的唯一标识符直接组合两个数据集。

在理想的情况下,这两个记录都有一个唯一的标识符,也就是说,在它们的数据集中有一个国家标识符,可以很容易地将它们合并。

以下示例显示了瑞士的国民身份证,它为瑞士公民(持有身份证)提供了一个唯一的标识号。

Swiss ID Card — Source

以下标识符要求个人持有身份证;如果一个人只持有一本护照,你就必须获得唯一的护照标识符。不旅行的人不会潜在地拥有这两种身份手段中的任何一种。

一个更好的标识符是国家安全标识符,几乎每个公民都持有(超过一定年龄)。低于居住在瑞士的人数。

Swiss Social Security Number — Source

现实情况是,你公开获得的数据集将不包括这种易受影响的人数。

不应以不安全的方式暴露这种强标识号(在互联网上公开共享)。参考 CNN 的以下文章,它描述了 Equifax 的一个著名的数据黑客,导致 1.43 亿美国人的社会安全号码泄露。

罪犯可以使用您的社会安全号码来窃取您的身份。他们可以开立银行账户和信用卡,或者申请贷款。黑客还可以以你的名义获得你的退税或医疗服务。(【money.cnn.com】T2

我们今天对统计概念的介绍到此结束,下一篇文章将带我们回到通过 Python 连接没有通用唯一标识符的数据集的问题。

在我们的例子中,我们在两个数据集中都有一个(或多个)描述个人姓名的属性。但是,要注意;

当姓名是唯一的统一数据点时,正确匹配相似的姓名就显得更加重要。然而,它们的可变性和复杂性使得名称匹配成为一项极具挑战性的任务。昵称、翻译错误、同一个名字的多种拼写等等都可能导致匹配失败。(【rosette.com】T4)

这正是我们现在面临的情况;让我们进入下一篇文章。

参考

原载于 2019 年 2 月 24 日dev.cloudburo.net

Python 和矢量化

原文:https://towardsdatascience.com/python-vectorization-5b882eeef658?source=collection_archive---------11-----------------------

当今世界的计算机硬件通过利用 SIMD(单指令、多数据)架构,利用并行计算来实现更快的计算。SIMD 是一类并行计算,其中逻辑处理器同时对多个数据点执行单个指令。我们需要向量化我们的深度学习代码,以便我们可以利用我们的系统提供的所有计算能力。计算越快,我们的神经网络训练得越快,我们得到结果的速度就越快。因此,对一段代码进行矢量化的能力已经成为深度学习实践者的一项关键技能。在这个故事中,我将解释使用 python 进行矢量化的基础知识。

到底什么是矢量化?

在逻辑回归的背景下,让我们借助下面的等式来理解矢量化的确切含义:

存储输入和权重的约定并不标准,但我更喜欢用以下方式存储。设 X 为输入矩阵的维数( n,m) 其中 n 是出现在中的特征数,而 m 是出现在我们的训练数据集中的训练样本数,即我们在 1 列中存储一个数据点。对于每个特征,都会有一个与之相关联的权重,因此设 W 为维度的权重矩阵( n,1) )。

现在,如果我们使用 循环编写示例方程,我们会得到如下结果:

上述代码片段由针对 循环的显式 组成,不会利用并行化。因此,我们需要将其转换为矢量化版本。这可以通过以下方式利用内置的 Numpy 函数轻松完成:

Z 将是一个 (1,m) 矩阵,按照矩阵乘法规则。 np.dot() 函数执行给定输入矩阵的矩阵乘法。它不仅使代码更具可读性和可理解性,而且还利用并行化来提高计算速度。下面的代码片段显示了与非矢量化实现相比,矢量化实现的速度有多快。

***import** numpy **as** np
**import** time*# Number of features* n = 1000
*# Number of training examples* m = 10000
*# Initialize X and W* X = np.random.rand(n,m)
W = np.random.rand(n,1)*# Vectorized code* t1=time.time()
Z = np.dot(W.T,X)
print(**"Time taken for vectorized code is : "**,(time.time()-t1)*1000,**"ms"**)*# Non Vectorized code* Z1 = np.zeros((1,m))
t2 = time.time()
**for** i **in** range(X.shape[1]):
    **for** j **in** range(X.shape[0]):
        Z[0][i] += W[j]*X[j][i]print(**"Time taken for non vectorized code is : "**,(time.time()-t2)*1000,**"ms"**)**''' Output
Time taken for vectorized code is :  5.964040756225586 ms
Time taken for non vectorized code is :  40915.54665565491 ms
'''***

上述实现仅考虑 10k 训练示例和 1k 特征。尽管有代码优化策略,但显然矢量化实现比非矢量化实现快得多。 Numpy 是一个用于科学计算的 python 库。它提供了各种内置函数,让我们可以轻松地编写矢量化代码。

根据经验,我们应该使用内置的 numpy 函数为任何未来的实现编写矢量化代码。

向量化逻辑回归

既然我们已经看到了编写矢量化代码的好处,那么让我们更深入地研究,为逻辑回归编写矢量化代码。不可能为每种情况编写一个矢量化代码,但是我们应该尽可能地遵循经验法则。让我们看一个非矢量化版本的逻辑回归,并尝试找出可以矢量化的部分。这样我们就能理解如何将一段给定的代码转换成它的矢量化版本。为简单起见,我们将只考虑 X 中的 2 个特征,因此只有 2 个权重。

在上面的例子中,我们只考虑了 2 个权重,即 w1w2 ,但是在实际生活场景中会有更多的权重,处理它们将成为一项复杂的任务。因此,我们将通过以下方式对权重导数 dw1dw2 的计算和更新进行矢量化:

*dW = X[i].dZ[i]
dW /= m*

在上述更改的帮助下,我们已经设法对代码的一小部分进行了矢量化。大部分仍然依赖于 for 循环,该循环用于迭代所有的训练示例。让我们看看如何移除 循环的 并对其进行矢量化:

所有训练示例的值 A 可以很容易地通过下式找到:

*A = sigmoid(np.dot(W.T,X)+b)*

成本 J 可由下式查出:

*J = -(np.dot(Y,np.log(A).T)+np.dot((1-Y),np.log(1-A).T))*

所有训练示例的导数 dZdWdB 可以通过以下方式找到:

*dZ = A - Y 
dW = np.dot(X*(dZ.T))/m
dB = (np.sum(dZ))/m*

权重矩阵 W 和偏差 B 可以通过以下方式更新:

*W = W - alpha*dW
b = b - alpha*dB*

这些转变起初看起来令人困惑。因此,我敦促读者看看每次计算后每个矩阵的维数是如何变化的。这将有助于更好地理解事物。让我们应用这些变化,看看当所有东西都被编译在一起时,矢量化的代码是什么样子。

上面的代码更加清晰、易读、简短,计算速度也更快。

广播

在代码中,你可能已经发现两个维数不相容的矩阵被相加、相减、相乘和相除。 Numpy 有一大特色叫 。在某些约束条件下,较小的矩阵被 广播 到较大的矩阵,以便它们具有兼容的维数来执行各种数学运算。让我们借助一些例子来看看广播是如何工作的。设 AB 为输入矩阵, C 为输出矩阵,作为对 AB 的任何数学运算的结果。

*Shape of A : 5 x 4
Shape of B :     4
Shape of C : 5 x 4Shape of A : 15 x 3 x 5
Shape of B : 15 x 1 x 5
Shape of C : 15 x 3 x 5Shape of A : 8 x 1 x 6 x 1
Shape of B :     7 x 1 x 5
Shape of C : 8 x 7 x 6 x 5Shape of A : 2 x 3 x 3
Shape of B :     1 x 5
Shape of C : Error*

由此可见,广播工作基于两个原则:

  1. AB 的尾部尺寸应等于
  2. AB 的拖尾尺寸应为 1

理解矢量化并将给定代码转换为矢量化格式的最佳方式是跟踪表中各种矩阵的维数。

起初,编写代码的矢量化版本可能会令人望而生畏,但是,在 Numpy 的内置函数和广播的帮助下,通过练习,它变得非常容易。这将使代码可读性更强,速度更快。

参考

  1. StackOverflow —什么是矢量化?
  2. 科学文件—广播
  3. Numpy
  4. Coursera —深度学习课程 1

我要感谢读者阅读这个故事。如果你有任何问题或疑问,请在下面的评论区提问。我将非常乐意回答这些问题并帮助你。如果你喜欢这个故事,请关注我,以便在我发布新故事时获得定期更新。我欢迎任何能改进我的故事的建议。

Python 虚拟环境变得简单

原文:https://towardsdatascience.com/python-virtual-environments-made-easy-fe0c603fe601?source=collection_archive---------6-----------------------

Photo by Chris Ried on Unsplash

我开始了一个项目,在这个项目中,我必须快速检查一个包Flask是否能与我机器上安装的 Python 一起工作。当我运行安装 Flask 的命令时,它提醒我已经安装了这个包,因为我的机器上已经安装了 Anaconda

但是当我试图在 Sublime Text 3 上运行Hello World Flask 应用时,控制台给出了一个错误,它无法找到 Flask 模块。我很困惑,开始在网上看关于这个问题的资料。我发现 Anaconda 有 Flask 模块,但是我在 Sublime Text 中使用的 Python 没有这个模块。我草草地找到了一个解决方案,以理解如何正确地设置 Python,在正确的位置安装正确的包,并设置 Sublime Text build 系统。我的网上研究揭示了关于Virtual Environments,一些我以前没有读到过的东西。

在阅读了许多关于Virtual Environments的文章后,我学到了很多关于 Python 的知识,以及我应该如何创建使用 Python 的环境。在本文中,我将分享我关于如何使用终端设置这些环境的知识。

计算机编程语言

Photo by Icons8 team on Unsplash

社区目前支持两个版本, 2.x3.x 版本。有些包适用于 Python 3.x,但有些包不支持 3.x,仅适用于 2.x。在这种情况下,有时人们可能希望使用 Python 2.x,有时使用 Python 3.x。我们从安装两个版本的 Python 开始,这样我们可以使用其中一个或两个来设置环境。如果你有一个包安装程序,比如 Homebrew ,你可以用它来安装 Python。

Python 3。X

brew install python@3

Python 2。X

brew install python@2

它还安装了pip,帮助我们安装 Python 包。

虚拟环境

Photo by Kimberly Farmer on Unsplash

每当您开始一个项目时,您将首先决定使用哪个 Python 版本,然后选择一些您想要的库/包。然而,最好不要在系统范围内安装这些软件包。您可能在同一台机器上使用多个版本的 Python,或者某些包只适用于某些版本的 Python 而不适用于其他版本。在这样的场景中,我们可以设置不同的环境,称为Virtual Environments

每个环境都将是它自己的虚拟空间。安装在该空间内的所有软件包不会干扰环境外部的软件包,并且将只包含在该空间内。

识别 Python 安装位置

根据您使用的安装方法,Python 将安装在不同的位置。

从官网安装的 Python

/Library/Frameworks/Python.framework/Versions/

在这里,你会找到已安装的版本。我的版本是 3.6,所以 Python 的路径应该是:

/Library/Frameworks/Python.framework/Versions/3.6/bin

使用自制软件安装的 Python

/usr/local/Cellar/

接下来是目录pythonpython@2下的版本。如果我们以python3.7.2_1版本为例,位置将是:

/usr/local/Cellar/python/3.7.2_1/bin

安装虚拟

我们将使用自制软件安装 Python 3。我们用pip3安装virtualenv

pip3 install virtualenv

创建虚拟环境

所有软件包都已安装,现在我们可以开始设置我们的虚拟环境了。我们需要定义我们想要建立环境的位置,并提供一个名称。我将它放在主目录中,并将名称设为virtEnv1

virtualenv -p python3 ~/virtEnv1

上面命令中的最后一个参数定义了我们环境的确切路径以及环境名称。我们的环境现在已经设置好了,我们可以开始在其中工作了。

激活环境

为了开始在一个环境中工作,我们需要激活这个环境。当设置环境时,在环境的bin文件夹中创建一个名为activate的文件。我们将这个文件设置为源文件,现在我们在环境中了。

cd ~/virtEnv1
source bin/activate

环境的名称开始出现在括号中,表示我们现在正在环境中工作。

Inside ‘virtEnv1’ environemnt

安装软件包并创建文件

我去装烧瓶。

pip install flask

我还在 home 目录下创建了一个文件app.py,其中包含 Flask 中最基本的Hello World代码。

如果我试着在环境中运行代码,它会像下面的图片一样工作。

python ~/app.py

客户端

Hello World in Flask

服务器

停用环境

如果您的环境是启用的,那么很容易就能摆脱它。只需在终端中键入deactivate即可。

由于环境现在被停用,我们使用系统范围内安装的 Python。系统中没有安装烧瓶。因此,如果我再次尝试运行相同的代码,它会给出一个错误,即没有找到flask

No flask error outside environment

以类似的方式,我们可以创建更多的环境,甚至为 Python 2 复制类似的过程。

在 Sublime Text 3 中使用 Python

Photo by Ilya Pavlov on Unsplash

当我不在 Jupyter 笔记本上工作时,我更喜欢处理精彩的文本。要为 Python 设置 Sublime 文本,我们需要创建一个新的构建系统。转到:

Tools > Build System > New Build System...

并将文本设置如下:

用您的用户名替换<username>

先存成virtEnv1Python吧。在 Sublime 文本中打开文件 app.py。将构建系统设置为virtEnv1Python。要测试应用程序是否工作,请按Command + B。您将看到应用程序开始运行,您可以通过链接[http://127.0.0.1:5000/](http://127.0.0.1:5000/.)进行确认。

结论

在本文中,我讨论了使用virtualenv来创建 Python 虚拟环境并在这些环境中安装包。

请随时分享你的想法,想法和建议。

Python 与 Excel —复合年增长率(CAGR)

原文:https://towardsdatascience.com/python-vs-excel-compound-annual-growth-rate-cagr-c8dbad46d3e0?source=collection_archive---------13-----------------------

我对 Microsoft Excel(或 Google Sheets)最大的失望之一是缺乏一个内置的函数来计算复合年增长率或 CAGR (XIRR 是最接近的,但它不是相同的)。这意味着,在我需要进行快速 Excel CAGR 分析的任何情况下,我都需要为 CAGR 编写 Excel 公式。

每一个。单身。时间。

如果您还不知道,CAGR 的 Excel 公式如下:

=(结束值/开始值)^ (1 /年数)-1

其中,结束值是给定时间段的最新值,开始值是给定时间段的第一个值,年数是要计算年增长率的年数。

在 Excel 表格中,它可能看起来像这样:

CAGR formula to calculate growth rate between 2010 and 2018

这是一个相当简单的公式,可以很容易地依赖…除了当表随着时间的增长而变长的时候!

Just add one more year, and you now need to specify the correct cells for the formula again

数据集往往会增长,这给分析师带来了一个问题,他们必须确保公式始终正确!(我去过。我不得不为一个更大的数据集修正一个更复杂的公式,纠正一个整整一年都没人注意到的错误,因为这个公式被淹没在数据的海洋中!)

这种挫败感是我从电子表格转向编程(特别是 Python 和 Pandas 库)进行数据分析的原因。我对 Python 还比较陌生,但是我已经体验到了它比 Excel 强大的多功能性和高效性(就像不用等几个小时 Excel 表来填充所有缺失的值)。

在这里,您将了解为什么编写 CAGR 函数并将其应用于从电子表格转换而来的数据帧会更好、更高效。

让我们从用 Python 定义 CAGR 函数开始:

def cagr(start_value, end_value, num_periods): return (end_value / start_value) ** (1 / (num_periods - 1)) - 1

就是这样!两行代码就有了你自己的 CAGR 函数。您会注意到这里与 Excel 函数略有不同。在该函数中,在 num_periods 之后有一个负 1。这使我能够通过将总周期数而不是复利周期数(总周期数总是减 1)指定为参数来正确计算 CAGR。我这样做是因为在过去,我曾多次在 Excel 中错误地指定复利周期数。

现在您已经有了 CAGR 函数,您可以将它保存到一个单独的 Python 文件中(从该文件中您可以导入到任何其他 Python 文件中),也可以将它编码到文件中,您将在该文件中将 Excel 表加载到数据框中并应用它。

要应用您的 CAGR 函数,首先导入 Pandas 库:

import pandas as pd

Pandas 是一个开源的、易于使用的 Python 库,它可以将任何 csv 或 Excel 文件转换成 dataframe 用于数据分析。这是用 Python 进行任何数据分析编程的必备工具。

接下来,将 Excel 加载到熊猫数据框架中:

ExcelFile = 'ExcelTable.xlsx' #name of my Excel file
df = pd.read_excel(ExcelFile, index_col='Year')

请注意,我添加了一个参数 index_col 来将“Year”列指定为索引,将“Year Income(RM)”列作为 dataframe 中的唯一一列。

在数据框上执行打印功能,查看 Excel 表格是否成功转换为数据框:

print(df)

Looks like it came out right

现在,您有了一个可以应用 CAGR 函数的数据框架。

Python 中 CAGR 函数的关键,以及为什么它在 Python 中更容易使用,是下面的变量:

start_value = float(df.iloc[0])
end_value = float(df.iloc[-1])
num_periods = len(df)

这些变量将提取 CAGR 函数所需的参数,在这种情况下,输出返回:

**36000.00
102000.00
9**

这些变量的好处在于,即使数据集在增长,代码也不必更改。使用。iloc 方法与列表索引一起确保函数将始终使用第一行作为起始值,最后一行作为结束值,并且 len 函数将始终正确计算时间段的总数。

即使你多加了一年,代码也是一样的。比方说,您在数据帧中添加了一行:

df.loc[2019] =[84000]

对相同变量运行打印功能将根据新数据返回不同的输出:

**36000.00
84000.00
10** 

如果您想为 CAGR 计算指定一个时间段,比如 2012 年到 2016 年之间的 5 年,您也可以使用。loc 方法很容易做到这一点:

start_value = float(df.loc[2012])
end_value = float(df.loc[2016])
num_periods = len(df.loc[2012:2016])

Slicing and dicing

现在,让我们通过使用变量作为输入参数,尝试将 CAGR 函数应用于该切片数据集:

result = cagr(start_value, end_value, num_periods)
print(result)**0.12801507993497308**

但是等等!输出以小数位数过多的浮点类型显示结果。虽然我个人更喜欢这种输出,但它通常对许多人来说并不友好。我们将需要字符串格式来表示百分比输出:

print("{:.2%}".format(result))**12.80%**

更加人性化。

这就是在 Python 中执行 CAGR 分析所需的全部内容!

Python Vs R:什么最适合机器学习

原文:https://towardsdatascience.com/python-vs-r-whats-best-for-machine-learning-93432084b480?source=collection_archive---------6-----------------------

你是否在考虑建立一个机器学习项目,并在为你的项目选择正确的编程语言之间犹豫不决?好了,那么这篇文章就要帮你扫清与 Python 和 r 特性相关的疑惑了,先从基础开始吧。

r 和 Python 拥有相似的特性,是数据科学家最常用的工具。两者都是开源的,因此是免费的,然而 Python 是一种广泛有用的编程语言,而 R 是为统计分析而创建的。

在本文中,我们将探讨这两种语言的优缺点,以便您可以决定哪种选择最适合您。

计算机编程语言

Python 编程语言开发于上世纪 80 年代末,在推动谷歌内部基础设施方面发挥着至关重要的作用。Python 由热情的开发者组成,现在它已经被广泛应用于 YouTube、Instagram、Quora 和 Dropbox。Python 在 IT 业务中被广泛使用,并允许开发团队内部的简单协作。这样,如果你需要一种适应性强、多理由的编程语言,一个庞大的工程师支持网络,以及可扩展的人工智能包,那么 Python 就是最佳选择。

Python 的优势

通用语言 —如果你的项目需要的不仅仅是统计数据,Python 被认为是更好的选择。例如,设计一个功能性网站

平滑的学习曲线——Python 易学易用,让你更快找到熟练的开发者。

大量重要的库Python 使用了无数的库来管理、收集和控制信息。以 Scikit-realize 为例,它包括信息挖掘和调查工具,以支持利用 Python 实现令人难以置信的人工智能便利性。另一个名为 Pandas 的包为工程师提供了优越的结构和数据检查设备,有助于缩短改进时间。如果你的开发团队需要 R 的一个主要功能,那么 RPy2 就是你要找的。

更好的集成 —通常,在任何工程环境中,Python 都比 r 集成得更好。因此,无论设计者是否试图利用 C、C++或 Java 等低级语言,它通常都能更好地将不同的组件与 Python wrapper 结合起来。此外,基于 python 的堆栈很容易创建,因此很难将数据研究人员手头的剩余任务整合进来。

提高生产力—Python 的语法非常容易理解,就像其他编程语言一样,但相对于 r 来说是独一无二的。通过这种方式,它保证了开发团队的高盈利能力。

Python 的缺点

●包括非常少的统计模型包。

●由于全局解释器锁(GIL)的存在,Python 中的线程处理变得很棘手,很成问题。随后,受 CPU 限制的多线程应用程序比单线程应用程序运行得更慢。人工智能事业对于执行多重处理比利用多线程编程更有价值。

R

r 是由统计学家开发的,基本上是为统计学家开发的,任何开发人员通过查看它的语法就可以预测到。由于这种语言包含了机器学习中的数学计算,而机器学习又是从统计学中派生出来的,所以 R 成为了想要更好地理解底层细节并进行创新的人的正确选择。如果您的项目主要基于统计数据,那么 R 可以被认为是缩小项目范围的绝佳选择,因为这需要一次性深入数据集。例如,如果您喜欢通过将段落解构为单词或短语来分析文本语料库,以识别它们的模式,那么 R 是最佳选择。

R 的优势

适合分析 —如果数据分析或可视化是您项目的核心,那么 R 可以被视为最佳选择,因为它允许快速原型制作,并与数据集一起设计机器学习模型。

大量有用的库和工具 —与 Python 类似,R 包含多个包,有助于提高机器学习项目的性能。例如,Caret 通过其特殊的功能集来增强 R 的机器学习能力,这有助于高效地创建预测模型。r 开发人员从高级数据分析包中获益,这些包覆盖了建模前和建模后阶段,针对特定的任务,如模型验证或数据可视化。

适合探索性的工作——如果你在项目的开始阶段需要在统计模型中做任何探索性的工作,那么 R 使得编写它们变得更加容易,因为开发人员只需要添加几行代码。

R 的缺点

●陡峭的学习曲线——很难否认 R 是一种具有挑战性的语言,因此你可以找到非常罕见的专家来构建你的项目团队。

不一致 —由于 R 的算法来自第三方,所以可能会出现不一致的情况。每次你的开发团队使用一个新的算法,所有连接的资源都需要学习不同的方法来建模数据和进行预测。与此类似,每个新的包都需要学习,并且没有详细的 R 文档,因为它会对开发速度产生负面影响。

R vs. Python:选择哪一个?

说到机器学习项目,R 和 Python 都各有优势。尽管如此,Python 似乎在数据操作和重复性任务方面表现更好。因此,如果你计划建立一个基于机器学习的数字产品,这是正确的选择。此外,如果您需要在项目的早期阶段开发一个专门的分析工具,那么请选择 r。最终的选择取决于您想要使用哪种编程语言。直到那时——继续学习!

作者简介:

https://www.tatvasoft.com】维卡什·库马尔在一家软件开发公司工作。他喜欢分享关于机器学习、人工智能和许多其他方面的新想法。除了日常的专业工作,他还喜欢烹饪和四处闲逛。您可以访问这里了解他的公司,并在TwitterLinkedIN上关注他。

Python 和 SQL 构建数据管道的比较

原文:https://towardsdatascience.com/python-vs-sql-comparison-for-data-pipelines-8ca727b34032?source=collection_archive---------3-----------------------

作为一名 web 开发人员,我第一次接触数据库和 SQL 是使用对象关系模型(ORM)。我使用的是 Django 查询集 API,使用该接口的体验非常好。从那以后,我转变成了一名数据工程师,更多地参与到利用数据集来构建人工智能的工作中。我的职责是从用户应用程序中提取数据,并将其转化为可供数据科学家使用的东西,这个过程通常被称为 ETL。

正如故事所述,生产系统中的数据是混乱的,在任何人能够利用这些数据构建人工智能之前,需要进行大量的转换。有些 JSON 列每行有不同的模式,有些列包含混合的数据类型,有些行有错误的值。此外,还需要计算用户成为客户的时间以及他们在两次访问之间等待的时间。当我着手清理、聚合和设计数据特性时,我试图决定哪种语言最适合这项任务。在我的工作中,我每天都要整天使用 python,我知道它可以完成这项工作。然而,我从这次经历中学到的是,仅仅因为 python 可以完成这项工作并不意味着它应该这样做。

我第一次误判 SQL 是在我认为 SQL 不能完成复杂转换的时候

我们正在使用一个时间序列数据集,我们希望在一段时间内跟踪特定的用户。隐私法阻止我们知道用户访问的具体日期,所以我们决定将记录的日期标准化为用户第一次访问的日期(即第一次访问后 5 天等)。).对于我们的分析,了解自上次访问以来的时间以及自首次访问以来的时间是很重要的。a 有两个样本数据集,一个有大约 750 万行,大小为 6.5 GBs,另一个有 550 000 行,大小为 900 MB。

使用下面的 python 和 SQL 代码,我使用较小的数据集首先测试转换。Python 和 SQL 分别用 591 和 40.9 秒完成了任务。这意味着 SQL 能够提供大约 14.5 倍的速度提升!

# PYTHON
# connect to db using wrapper around psycopg2
db = DatabaseConnection(db='db', user='username', password='password')# grab data from db and load into memory
df = db.run_query("SELECT * FROM cleaned_table;")
df = pd.DataFrame(df, columns=['user_id', 'series_id', 'timestamp'])# calculate time since first visit
df = df.assign(time_since_first=df.groupby('user_id', sort=False).timestamp.apply(lambda x: x - x.min()))# calculate time since last visit
df = df.assign(time_since_last=df.sort_values(['timestamp'], ascending=True).groupby('user_id', sort=False)['timestamp'].transform(pd.Series.diff))# save df to compressed csv
df.to_csv('transform_time_test.gz', compression='gzip') -- SQL equivalent
-- increase the working memory (be careful with this)
set work_mem='600MB';-- create a dual index on the partition
CREATE INDEX IF NOT EXISTS user_time_index ON table(user_id, timestamp);-- calculate time since last visit and time since first visit in one pass 
SELECT *, AGE(timestamp, LAG(timestamp, 1, timestamp) OVER w) AS time_since_last, AGE(timestamp, FIRST_VALUE(timestamp) OVER w) AS time_since_first FROM table WINDOW w AS (PARTITION BY user_id ORDER BY timestamp);

这种 SQL 转换不仅速度更快,而且代码可读性更好,因此更易于维护。这里,我使用了 lag 和 first_value 函数来查找用户历史中的特定记录(称为分区)。然后,我使用年龄函数来确定访问之间的时间差。

更有趣的是,当这些转换脚本应用于 6.5 GB 数据集时,python 完全失败了。在 3 次尝试中,python 崩溃了 2 次,我的电脑第三次完全死机了…而 SQL 用了 226 秒。

更多信息:
https://www.postgresql.org/docs/9.5/functions-window.html
http://www . PostgreSQL tutorial . com/PostgreSQL-window-function/

我第二次误判 SQL 是在我认为它不能展平不规则 json 的时候

对我来说,另一个改变游戏规则的因素是意识到 Postgres 与 JSON 配合得非常好。我最初认为在 postgres 中不可能展平或解析 json 我不敢相信我竟然这么傻。如果您想要关联 json,并且它的模式在行之间是一致的,那么您最好的选择可能是使用 Postgres 内置的能力来解析 json。

-- SQL (the -> syntax is how you parse json)
SELECT user_json->'info'->>'name' as user_name FROM user_table;

另一方面,我的样本数据集中有一半的 json 不是有效的 json,因此被存储为文本。在这种情况下,我面临一个选择,要么重新编码数据使其有效,要么删除不符合规则的行。为此,我创建了一个名为 is_json 的新 SQL 函数,然后可以用它在 WHERE 子句中限定有效的 json。

-- SQL
create or replace function is_json(text)
returns boolean language plpgsql immutable as $$
begin
    perform $1::json;
    return true;
exception
    when invalid_text_representation then 
        return false;
end $$;SELECT user_json->'info'->>'name' as user_name FROM user_table WHERE is_json(user_json);

不幸的是,我发现 user_json 有不同的模式,这取决于用户使用的应用程序版本。尽管从应用程序开发的角度来看,这是有意义的,但是有条件地解析每行的每种可能性的成本确实很高。我注定要再次进入 python 吗…一点机会都没有!我在 stack-overflow 上发现了另一个函数,是一个叫 klin 的 postgres 大神写的。

-- SQL
create or replace function create_jsonb_flat_view
    (table_name text, regular_columns text, json_column text)
    returns text language plpgsql as $$
declare
    cols text;
begin
    execute format ($ex$
        select string_agg(format('%2$s->>%%1$L "%%1$s"', key), ', ')
        from (
            select distinct key
            from %1$s, jsonb_each(%2$s)
            order by 1
            ) s;
        $ex$, table_name, json_column)
    into cols;
    execute format($ex$
        drop view if exists %1$s_view;
        create view %1$s_view as 
        select %2$s, %3$s from %1$s
        $ex$, table_name, regular_columns, cols);
    return cols;
end $$;

这个函数能够成功地展平我的 json,并相当容易地解决我最糟糕的噩梦。

最终意见

有一个习语宣称 Python 是几乎做任何事情的第二好语言。我相信这是真的,在某些情况下,我发现 Python 和“最佳”语言之间的性能差异可以忽略不计。然而,在这种情况下,python 无法与 SQL 竞争。这些认识以及我所做的阅读完全改变了我的 ETL 方法。我现在的工作模式是“不要把数据移动到代码,把代码移动到你的数据”。Python 将数据移动到代码中,而 SQL 就地对其进行操作。更重要的是,我知道我只是触及了 sql 和 postgres 能力的皮毛。我期待着更多令人敬畏的功能,以及通过使用分析仓库来提高速度的可能性。

Python vs. Web 抓取工具抓取梦幻足球投影

原文:https://towardsdatascience.com/python-vs-web-scraping-tool-to-crawl-fantasy-football-projections-91670054b42?source=collection_archive---------28-----------------------

Photo by HENCE THE BOOM on Unsplash

梦幻足球是一个乏味的游戏。这么说的话,不研究是不可能拿冠军的。这就是网络抓取派上用场的原因。在本教程中,你将学习如何建立一个网页抓取工具来完成这项工作。

现在,您可以迅速地将有价值的数据自动整理到一个电子表格中。这比通过复制和粘贴从各种来源查找统计数据要容易得多,也快得多。

为什么是网络抓取?

根据这份报告,普通球员每周会花 3 个小时来管理他们的球队,另外 9 个小时用来阅读趋势。大约 30%的球员在日常工作中管理他们的球队。

大量信息唾手可得。准确预测团队成员的表现是很困难的。你如何挑选二线球员并取得顶级成绩?您需要跟踪游戏统计数据,并找到隐藏的值。

什么是网页抓取?

网络抓取是一种从网站上自动提取数据的技术。传统上,你需要一个程序员来编写脚本。

至于现在,一个网页抓取工具代替了编码的劳动。抓取不再是程序员的特权。任何人都可以从互联网上提取有价值的信息,并将其保存到本地存储或云上。

在这篇文章中,我将带你通过如何提取幻想足球投影点从体育网站一样,fantasypros.com 与网页抓取工具。

没有必要记录整个页面。你甚至可以更有创意,通过与对手的团队进行并排比较来获得全面的分析。

然后我们将其与 Python 脚本进行比较。所以你会有一个想法,对我们所有人来说,尤其是梦幻足球运动员,保持跟踪统计数据是多么容易。

免责声明:我是梦幻足球的新手。本文不提供起草策略的专业建议。相反,这是一篇从统计学角度分享知识的文章。

使用 Octoparse 进行网页抓取

先决条件:

Octoparse, 一个非常直观的网页抓取工具。它帮助我完成了数据分析项目中的许多障碍。这是市场上最好的。你可以在这里下载。

创建项目:

打开 Octoparse,点击小加号,用高级模型构建一个新任务。输入网址,Octoparse 会用内置浏览器打开网页。我们可以通过点击页面来交互和提取数据。

第一个,点击第一行的玩家。注意,Octoparse 将网站解析成单个元素。它找到了相似元素并用红色突出显示。

这太棒了。遵循操作提示,并单击“选择所有子元素”整行已被选中。然后,Octoparse 会提醒您它找到了准备好被选中的相似行。按照指南,点击“全选”

请注意,现在所有行都被成功选中,并以绿色突出显示。

接下来,点击“提取循环中的数据”。恭喜你!你完成了一个爬虫。【下载爬虫

最后但并非最不重要的,保存任务并在你选择的提取类型中开始提取。您可以在本地、在云上提取,或者设置一个时间表。在这种情况下,我强烈建议制定一个时间表。爬虫会及时抓取网站。所以你总是保持更新。

提取的数据将以结构化格式交付,包括 Excel、txt 和 JSON。由于我们需要分析这些点,所以我将它们导出到 Excel 中,看起来是这样的。

使用 Python 进行 Web 抓取

可以在这里 阅读完整的 Python 作品 。我把这个过程分成几个步骤:

  1. 浏览到所需页面并复制 URL 以备后用。
  2. 仔细检查 HTML 代码,找到要提取的数据所在的位置。在本例中,我们寻找“TR”(表格行)
  3. 找到您想要的数据周围的唯一标识符,如 href 链接、类名、表行和表数据。
  4. 尝试从一行数据中提取不同的字段
  5. 经历几次试错迭代。
  6. 规范数据格式(当我们提取原始数据时,使用奇怪的格式可能会使数据看起来很有趣。您需要清理字符格式,使它们一致和可读。)

最后

网页抓取运动项目既快又容易。然而,有了网络抓取工具,你可以在简单的点击中完成整个过程。我花了 1 个小时阅读 Beautiful Soup 的文档,尝试如何定位精确的字段并编写 Python 代码。

然而,我花了不到 10 分钟的时间用 Octoparse 设置了提取。最好的部分是,一旦你有了爬虫,你可以设置一个时间表,让它自动提取。

对于播放器,您可以通过更轻松地设置提取爬虫来同时监视不同的站点源:

你收集的数据越多,你的分析就越全面。现在,你甚至会在消息出来之前就获得第一手数据!

11 月 26 日,Octoparse 正在进行他们最好的黑色星期五早期交易,所有商品都有 10%的额外折扣。他们绝对值得你花几分钟时间来检查他们的产品和交易。

原载于 2019 年 11 月 22 日【https://likegeeks.com

Python 网络抓取重构

原文:https://towardsdatascience.com/python-web-scraping-refactored-5834dda39a65?source=collection_archive---------14-----------------------

我在旧博客上的第一篇文章是关于一个网络抓取的例子。网络抓取是使用 API 之外的一种方式,例如 tweepy 来为你的分析或你的机器学习模型获取信息。真实数据并不总是在一个方便的 CSV 文件中。你需要自己去拿。

我学到的例子来自凯文·马卡姆在 Youtube 上的网络抓取演示视频(Twitter 标签: @justmarkham )。他的例子使用了一个循环来收集所有的信息。但是 Python 有一个比循环更有效、可读性更强的工具。那些是列表理解。如果你不确定这些是什么,看看下面的帖子了解更多。一旦你完成了,请继续阅读,学习如何通过从这所布朗克斯高中的职员页面上搜集姓名、职位和电子邮件地址来有效地进行网络搜集。

[## Python 基础-列表理解

学习 python 几周后,我开始真正掌握了窍门。我喜欢有条件的心流,而且…

medium.com](https://medium.com/@erikgreenj/python-basics-list-comprehensions-30ef0df40fea)

注。根据您阅读本文的时间,最终结果可能会有所不同,因为网页上的数据可能已经发生了变化。最终结果截至 2019 年 4 月 3 日*

酷!我们如何开始?

让我们从导入和获取网页开始。

我们导入requests来获得带有requests.get()的 web_page。pandas稍后将用于清理我们的报废数据。bs4库中的BeautifulSoup将用于解析我们的糊状 HTML,以帮助我们获得我们想要的信息。我们将在下面这样做。

Photo by Elli O. on Unsplash

接下来,我们将研究来自web_page的 HTML 代码,以找到我们需要的代码段。要查看网页的 HTML 代码,请转到该网页,右键单击并选择“查看页面源代码”。然后,您可以按 ctrl-f 找到一个职员的名字,以查看嵌入了他们的名字和信息的 HTML 代码。

如果您稍微滚动一下代码,您应该会注意到代码行中包含了一些信息,例如:

<title>……</title>

或者

<p>…..</p>

这些在 HTML 代码中被称为标签。在这些标签之间隐藏着我们想要获取的信息。

由于我们看到所需的信息在<div>标签和class=’matrix-content’标签之间,我们可以假设所有教师的信息都在该类的每个标签中。这就是为什么我们使用标签和类作为 soup 的find_all属性的参数。

我们需要从第一个教师简介出现的索引开始,因为我们只收集教师信息。第一个出场的老师是“布罗根先生”。你可以使用 ctrl-f 在 HTML 代码中搜索他的名字。如果数的话(当然是从 0 开始),布罗根先生的指数是 29。这就是为什么我们从指数 29 开始重新定义结果。对结果长度的检查和对被移除的员工的心算证实了我们可以进入下一步了!

现在获取所有教师数据!对吗?

Photo by Florian Olivo on Unsplash

我们会的。在此之前,我们应该先看看如何从一个老师那里获得我们想要的信息。然后我们将把它推广到我们的理解列表中。让我们来看一个教师简介的 HTML 代码。我们将再次检查布洛根先生的信息:

<div class="matrix-content">
        <h5>Mr. Brogan</h5>                   
        <div class="matrix-copy"><p>
    Special Education: Geometry, Particular Topics of Geometry</p>
<p>
    <em>rbrogan31@charter.newvisions.org</em></p>
</div>
                                            </div>

同样,我们需要确定包含教师姓名、职位和电子邮件的标签。花点时间试着自己回答这个问题,然后继续读下去,看看你是否正确。这将为研究您需要在 python 抓取代码中指示 HTML 的哪些部分提供良好的实践。还记得我之前给你们看的例子吗?

教师姓名标签:姓名在标记为<h5>的标签之间。

位置标签:位置位于类别标签<div class=”matrix-copy”>后的<p>标签之间。

邮件标签:邮件在标签<p><em>之间。由于<em>标签直接封装了电子邮件,这就是我们将在抓取代码中指出的标签。

太好了!现在我们已经找到了需要指示的标签,让我们为我们的第一位老师编写代码,以确定我们将如何遍历老师条目来获取所有数据!

首先,我们将我们的第一位老师定义为test_result

教师姓名:通过在<h5>标签上使用find方法,我们得到了带有我们教师姓名的代码行。但这并不能给我们没有标签的名字。我们不希望代码中有标签。因此,为了提取姓名文本,我们将把.text添加到find方法中,以获得标签的文本属性。

Position(s) :我们将使用与名称相同的find方法,但是这次我们的参数将是标签<p>。这样做可以得到我们的位置,但同样我们不希望附加标签。再次使用.text返回以下内容…..

'\n\tSpecial Education: Geometry, Particular Topics of Geometry'

这给了我们比我们想要的更多。具体来说,我们在开始时得到了新行(\n)和制表符(\t)的字符串代码。由于我们的信息是在一个字符串中,我们可以用我们的代码行删除不需要的部分,从字符串的任何地方删除这些字符。

电子邮件:获取这些信息要简单得多。再次使用带有标签<em>find方法作为我们的参数。使用.get_text()方法有助于我们做到这一点,因为一些电子邮件嵌入在多个<em>标签中。

现在我们得到了我们想要的所有数据!

没错!所以我们开门见山吧。

首先,我们初始化一个数据框对象。然后,我们使用列表理解结合来自test_result的代码来获取所有教师的姓名和职位。我们还利用这些列表理解来创建数据帧df的前两列。

当我第一次运行电子邮件收集的代码时,我遇到了一个属性错误。这就是变量管理器方便的地方。检查网页或 HTML 代码会发现“Veninga 女士”在<em> 标签中没有电子邮件地址。它位于第二组<p>标签之间。因为页面很小,你可以这样做,但是对于较大的信息集合,你最好在列表理解产生错误的地方打印。

为了解决这个问题,我们将尝试创建一个get_email函数,除了用<p>上的find_all方法设置第二组<p>标签内的所有电子邮件,然后使用索引来获得我们想要的<p>标签。我们还将删除多余的文本,就像获取职位信息一样。

与此同时,其他人的电子邮件将照常被删除。再次运行代码使我们能够成功地获得所有条目。可以通过检查记录列表的长度来证明这一点(它应该返回 66)。您可以使用df.shape[0]来检查您的数据中的行数(66 个教师的 66 行)。

真快!我们去分析这些数据吧!

我们可以…但是我们会发现我们收集的数据有错误。您可以检查的一件事是,如果您有重复的条目,并删除它们。有些教师可能会教授多个科目(如数学和英语),因此他们的名字会出现多次。

通过对df.duplicated的所有布尔值求和,我们得到值 11。所以我们有 11 个老师的名字出现了不止一次。然后,我们使用df.drop_duplicates保留教师姓名的第一个条目,并丢弃其余条目。最后,我们将数据帧导出到一个 CSV 文件中,用于将来的分析。

最后的想法

网络抓取给你一种神奇的感觉,因为一旦你找到你需要的标签,你就可以从任何网站获取信息。我希望这个演练对那些考虑学习如何用 Python web scrap 的人有所帮助。

当然,可以做一些特征工程来帮助分析。我不打算包括这些细节,因为我想把重点放在网页抓取方面。

选项包括:

1.创建一个性别列,方法是在该时期按标题拆分姓名,然后使用 pandas 将标题映射到适当的性别。

2.将职位分开(因为大多数教师似乎教授不止一种类型的班级)。

对于熊猫练习,你可以尝试自己做上面的。

Photo by Thao Le Hoang on Unsplash

然后,我们可以转向 Tableau 或matplotlib进行可视化和统计,以回答与教师人数和其他特许公立布朗克斯学校相比,这些数据的问题。

直到下一次,

约翰·德杰苏斯

Python 的集合模块——高性能容器数据类型。

原文:https://towardsdatascience.com/pythons-collections-module-high-performance-container-data-types-cb4187afb5fc?source=collection_archive---------7-----------------------

Python 超级有用的集合模块的快速概述。

Photo by rawpixel on Unsplash

如果实现很难解释,这是个坏主意:Python 的禅

Python 是一种非常强大的语言,这种强大的力量很大一部分来自于它支持 模块化编程 。模块化编程本质上是将一个大而复杂的编程任务分解成更小且更易管理的子任务/ 模块的过程。模块就像乐高积木可以捆绑在一起创建一个更大的任务。

模块化在编写代码时有很多优势,比如:

  • 可重用性
  • 可维护性
  • 简单性

函数模块都是 Python 中促进代码模块化的构造。

目标

通过这篇文章,我们将探索 Python 的集合模块。该模块旨在改进功能,并为 Python 的通用内置容器(如 dict、list、set 和 tuple)提供替代方案。

介绍

让我们从快速浏览模块和包的概念开始这篇文章。

组件

模块只不过是一个可以在另一个模块中调用的. py 脚本。py 脚本。模块是包含 Python 定义和语句的文件,有助于实现一组函数。文件名是模块名加上后缀.py。使用import命令从其他模块导入模块。让我们导入数学模块。

*# import the library*
import math#Using it for taking the log
math.log(10)
2.302585092994046

Python 的内置模块

Python 有无数的内置模块,并且已经为你能想到的几乎所有用例创建了包。点击查看完整列表

在探索 Python 中的模块时,两个非常重要的函数派上了用场——dirhelp函数。

  • 内置函数[dir()](https://docs.python.org/3/library/functions.html#dir)用于找出每个模块中实现了哪些功能。它返回字符串的排序列表:
print(dir(math))

  • 在模块中找到我们想要的函数后,我们可以在 Python 解释器中使用help函数来了解更多信息:
help(math.factorial)

包装

包是堆叠在一起的相关模块的集合。核心机器学习包 Numpy 和 Scipy 由数百个模块组成。这里是在 SciPy 中可用的部分子包列表。

source

现在让我们跳到本文的实际目标,了解 Python 的集合模块。这只是一个概述,详细的解释和例子请参考官方 Python 文档。

集合模块

[集合](http://Container datatypes)是一个内置的 Python 模块,它实现了专门的容器数据类型,为 Python 的通用内置容器(如[dict](https://docs.python.org/3.6/library/stdtypes.html#dict)[list](https://docs.python.org/3.6/library/stdtypes.html#list)[set](https://docs.python.org/3.6/library/stdtypes.html#set)[tuple](https://docs.python.org/3.6/library/stdtypes.html#tuple))提供了替代方案。

本模块中一些有用的数据结构包括:

1\. [namedtuple()](https://docs.python.org/3.6/library/collections.html#collections.namedtuple)

存储在普通元组中的数据只能通过索引来访问,如下例所示:

plain_tuple = (10,11,12,13)plain_tuple[0]
10plain_tuple[3]
13

我们不能给存储在元组中的单个元素命名。现在,在简单的情况下可能不需要这个。然而,如果一个元组有许多字段,这可能是必要的,也会影响代码的可读性。

在这里, namedtuple 的功能开始发挥作用。它是一个用于具有名为字段的的元组的函数,可以看作是内置元组数据类型的扩展。命名元组为元组中的每个位置赋予意义,并允许更具可读性、自文档化的代码。存储在其中的每个对象都可以通过一个唯一的(人类可读的)标识符来访问,这使我们不必记住整数索引。我们来看看它的实现。

from collections import namedtuple
fruit = namedtuple('fruit','number variety color')guava = fruit(number=2,variety='HoneyCrisp',color='green')apple = fruit(number=5,variety='Granny Smith',color='red')

我们构造 namedtuple 的方法是,首先传递对象类型名称(fruit ),然后传递一个包含各种字段的字符串,作为字段名之间有空格的字符串。然后,我们可以调用各种属性:

guava.color
'green'apple.variety
'Granny Smith'

在 Python 中定义不可变类时,命名元组也是一个节省内存的选项。

2.计数器

Counter 是一个 dict 子类,帮助计算可散列对象。元素存储为字典键,而对象计数存储为值。让我们看几个关于计数器的例子。

#Importing Counter from collections
**from** **collections** **import** Counter
  • 用绳子
c = Counter('abcacdabcacd')
print(c)Counter({'a': 4, 'c': 4, 'b': 2, 'd': 2})
  • 使用列表
lst = [5,6,7,1,3,9,9,1,2,5,5,7,7]
c = Counter(lst)
print(c)Counter({'a': 4, 'c': 4, 'b': 2, 'd': 2})
  • 带句子
s = 'the lazy dog jumped over another lazy dog'
words = s.split()
Counter(words)Counter({'another': 1, 'dog': 2, 'jumped': 1, 'lazy': 2, 'over': 1, 'the': 1})

计数器对象除了支持所有字典可用的方法之外,还支持三种方法:

  • 元素()

返回每个元素的计数,如果元素的计数小于 1,则忽略它。

c = Counter(a=3, b=2, c=1, d=-2)
sorted(c.elements())['a', 'a', 'a', 'b', 'b', 'c']
  • 最常见([n)

返回最常见元素及其计数的列表。元素的数量必须指定为 n。如果没有指定,它将返回所有元素的计数。

s = 'the lazy dog jumped over another lazy dog'
words = s.split()
Counter(words).most_common(3)[('lazy', 2), ('dog', 2), ('the', 1)]

使用 Counter()对象时的常见模式

sum(c.values())                 # total of all counts 
c.clear()                       # reset all counts 
list(c)                         # list unique elements 
set(c)                          # convert to a set 
dict(c)                         # convert to a regular dictionary c.items()                       # convert to a list like (elem, cnt) 
Counter(dict(list_of_pairs))    # convert from a list of(elem, cnt) 
c.most_common()[:-n-1:-1]       # n least common elements 
c += Counter()                  # remove zero and negative counts

3.默认字典

字典是一种有效的方式来存储数据,以便以后检索,它有一组无序的键:值对。键必须是唯一且不可变的对象。

fruits = {'apple':300, 'guava': 200}
fruits['guava']200

如果值是整数或字符串,事情就简单了。然而,如果值是列表或字典等集合的形式,则值(空列表或字典)必须在第一次使用给定键时初始化。defaultdict 自动化并简化了这些东西。下面的例子将使它更加明显:

d = {}
print(d['A'])

这里,Python 字典抛出一个错误,因为‘A’当前不在字典中。现在让我们用 defaultdict 运行相同的示例。

from collections import defaultdict
d = defaultdict(object)
print(d['A'])<object object at 0x7fc9bed4cb00>

相反,defaultdict将简单地创建您试图访问的任何项目(当然前提是它们还不存在)。defaultdict 也是一个类似字典的对象,它提供了字典提供的所有方法。然而,不同之处在于它将第一个参数(default_factory)作为字典的默认数据类型。

4.有序直接

一个 OrderedDict 是一个字典子类,它记住键第一次被插入的顺序。当遍历一个有序字典时,条目按照它们的键第一次被添加的顺序返回。因为有序字典会记住它的插入顺序,所以它可以与排序结合使用来创建一个有序字典:

  • 正规字典
d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
  • 按关键字排序的字典
OrderedDict(sorted(d.items(), key=**lambda** t: t[0]))OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
  • 按值排序的字典
OrderedDict(sorted(d.items(), key=lambda t: t[1]))OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
  • 字典按关键字串的长度排序
OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))OrderedDict([('pear', 1), ('apple', 4), ('banana', 3), ('orange', 2)])

这里需要注意的一点是,在 Python 3.6 中,常规的字典都是 插入有序即 字典记住插入条目的顺序。在这里阅读讨论

结论

集合模块还包含一些其他有用的数据类型,如 deque、Chainmap、UserString 等等。然而,我已经分享了我在日常编程中使用的一些方法来使事情变得简单。关于详细的解释和用法,请访问官方 Python 文档页面

Python 的一个线性图形创建库,带有汉斯·罗斯林风格的动画

原文:https://towardsdatascience.com/pythons-one-liner-graph-creation-library-with-animations-hans-rosling-style-f2cb50490396?source=collection_archive---------8-----------------------

形象化

动画,单线图。它拥有一切

我清楚的记得海风来的时候。我真的受够了 Matplotlib。为了创建甚至简单的图形,我不得不运行这么多的 StackOverflow 线程。

我本可以花在思考如何呈现数据的好主意上的时间却被用来处理 Matplotlib。这很令人沮丧。

Seaborn 比 Matplotlib 好得多,但它也需要大量代码才能得到一个简单的“好看”的图形。

当 Plotly 出现时,它试图解决这个问题。当加上熊猫时,plotly 是一个很好的工具。

仅仅使用iplot函数,你就可以用 Plotly 做这么多事情。

但还是,不是很直观。至少对我来说不是。

我仍然没有切换到 Plotly,只是因为我已经花了足够多的时间与 Seaborn 一起“快速”地做事情,我不想再花更多的时间去学习一个新的可视化库。我在 Seaborn 中创建了自己的函数来创建我最需要的可视化效果。然而这仍然是一种变通办法。我已经放弃了拥有更好的东西的希望。

绘声绘色地表达图中的。是不是很棒?

根据 Plotly Express 的创作者(显然也创作了 Plotly), Plotly Express 之于 Plotly,犹如 Seaborn 之于 Matplotlib。

围绕 Plotly.py 的简洁、一致的高级包装器,用于快速数据浏览和图形生成。

我只是想尝试一下。

创造者们让人们开始尝试它变得容易了吗?

为所欲为的俏皮话?

标准化功能?学会创建散点图,你就差不多学会了这个工具——✅

互动图表?✅

动画?赛车条形图、时间散点图、—✅地图

免费开源?

只是先睹为快,看看在这篇文章结束时我们将能够创造什么(以及更多)。 使用单行代码。

好了,谈够了,让我们开始吧。

首先是数据集——有趣、令人沮丧又令人振奋

我们将使用我从 Kaggle 获得的自杀数据集。这个数据集是根据来自联合国、世界银行和世界卫生组织的数据汇编而成的。 数据集积累了预防自杀的灵感。我总是支持对数据的这种良好利用。

你可以找到这篇文章的所有代码,并在这个 Kaggle 内核中运行它

首先,我将进行一些数据清理,以添加大陆信息和国家 ISO 代码,因为它们在以后会有所帮助:

import pandas as pd
import numpy as np
import plotly_express as px# Suicide Data
suicides = pd.read_csv("../input/suicide-rates-overview-1985-to-2016/master.csv")
del suicides['HDI for year']
del suicides['country-year']# Country ISO Codes
iso_country_map = pd.read_csv("../input/countries-iso-codes/wikipedia-iso-country-codes.csv")
iso_country_map = iso_country_map.rename(columns = {'English short name lower case':"country"})# Load Country Continents file
concap =pd.read_csv("../input/country-to-continent/countryContinent.csv", encoding='iso-8859-1')[['code_3', 'continent', 'sub_region']]
concap = concap.rename(columns = {'code_3':"Alpha-3 code"})correct_names = {'Cabo Verde': 'Cape Verde', 'Macau': 'Macao', 'Republic of Korea': "Korea, Democratic People's Republic of" , 
 'Russian Federation': 'Russia',
 'Saint Vincent and Grenadines':'Saint Vincent and the Grenadines' 
 , 'United States': 'United States Of America'}def correct_country(x):
    if x in correct_names:
        return correct_names[x]
    else:
        return xsuicides['country'] = suicides['country'].apply(lambda x : correct_country(x))suicides = pd.merge(suicides,iso_country_map,on='country',how='left')
suicides = pd.merge(suicides,concap,on='Alpha-3 code',how='left')suicides['gdp'] = suicides['gdp_per_capita ($)']*suicides['population']

让我们看看自杀数据:

我还会按大洲对数据进行分组。老实说,我这样做只是为了展示这个库的威力,因为这篇文章的主要目标仍然是创建令人敬畏的可视化效果。

suicides_gby_Continent = suicides.groupby(['continent','sex','year']).aggregate(np.sum).reset_index()suicides_gby_Continent['gdp_per_capita ($)'] = suicides_gby_Continent['gdp']/suicides_gby_Continent['population']suicides_gby_Continent['suicides/100k pop'] = suicides_gby_Continent['suicides_no']*1000/suicides_gby_Continent['population']# 2016 data is not full
suicides_gby_Continent=suicides_gby_Continent[suicides_gby_Continent['year']!=2016]

suicides_gby_Continent.head()

我们创建的最终数据:

简单易用

我们准备好可视化我们的数据。来时隐晦地表达的时间。我可以通过一个简单的:

pip install **plotly_express**

并将其导入为:

import plotly_express as px

现在让我们用它创建一个简单的散点图。

suicides_gby_Continent_2007 = suicides_gby_Continent[suicides_gby_Continent['year']==2007]px.scatter(suicides_gby_Continent_2007,x = 'suicides/100k pop', y = 'gdp_per_capita ($)')

不太鼓舞人心。没错。让我们一步一步地做得更好。让我们按洲给点上色。

px.scatter(suicides_gby_Continent_2007,x = 'suicides/100k pop', y = 'gdp_per_capita ($)',color='continent')

好但不励志。还没有。

点看起来好小。没错。让我们增加点的大小。怎么会?参数可能是什么…

px.scatter(suicides_gby_Continent_2007,x = 'suicides/100k pop', y = 'gdp_per_capita ($)',color='ContinentName',size ='suicides/100k pop')

你能看出每个洲都有两个点吗?它们代表男性和女性。让我在图表中展示一下。我们可以用几种方法来说明这种区别。 我们可以用不同的 ***symbol*** 或者用不同的 ***facets*** 来表示男女

让我给他们两个看看。

px.scatter(suicides_gby_Continent_2007,x = 'suicides/100k pop', y = 'gdp_per_capita ($)', size = 'suicides/100k pop', color='ContinentName',symbol='sex')Orpx.scatter(suicides_gby_Continent_2007,x = 'suicides/100k pop', y = 'gdp_per_capita ($)', size = 'suicides/100k pop', color='continent',facet_col='sex')

Fig1: Symbol, Fig2: Facets

在符号图中,三角形代表男性,圆形代表女性。我们已经开始从图表中看到一些好的信息。以为例:

  • 至少在 2007 年的数据中,男性和女性的自杀率存在显著差异。
  • 2007 年欧洲男性极易自杀?
  • 收入差距似乎对自杀率没有太大影响。亚洲的人均 GDP 比欧洲低,自杀率也比欧洲低。
  • 男性和女性之间似乎没有收入差距。

还不励志?嗯。 让我们添加一些动画 。这应该不难。我会添加更多的参数,

  • 它指定了我们的动画维度。
  • 使用range_yrange_x的 x 和 y 值范围
  • text用大洲标注所有点。有助于更好地可视化数据
px.scatter(suicides_gby_Continent,x = 'suicides/100k pop', y = 'gdp_per_capita ($)',color='continent',
           size='suicides/100k pop',symbol='sex',animation_frame='year', animation_group='continent',range_x = [0,0.6],
          range_y = [0,70000],text='continent')

等待 gif 图显示。

在 Jupyter 笔记本中,你将能够停止可视化,悬停在点上,只需查看特定的大陆,并通过交互做更多的事情。

一个命令就能提供如此多的信息。我们可以看到:

  • 从 1991 年到 2001 年,欧洲男性的自杀率非常低。
  • 大洋洲即使有相当高的人均国内生产总值,它仍然容易发生自杀事件。
  • 与其他国家相比,非洲的自杀率较低。
  • 就美洲而言,自杀率一直在逐渐上升。

我以上所有的观察都需要更多的分析。但这就是在一张图上有这么多信息的意义所在。它会帮助你提出很多假设。

以上剧情风格被称为汉斯·罗斯林剧情以其创始人命名。

在这里,我想让你们看看这个来自汉斯·罗斯林的演示,他使用 Gapminder 数据来解释收入和寿命是如何随着时间的推移而出现的。看到了。太棒了。

Hans Rosling Gapminder Visualization….

功能标准化

到目前为止,我们已经了解了散点图。花了这么多时间去学一门图表课。在我的帖子的开始,我告诉你这个库有一种标准化的功能。

让我们具体看看欧洲的数据,因为我们看到欧洲男性的自杀率很高。

european_suicide_data = suicides[suicides['continent'] =='Europe']
european_suicide_data_gby = european_suicide_data.groupby(['age','sex','year']).aggregate(np.sum).reset_index()
european_suicide_data_gby['suicides/100k pop'] = european_suicide_data_gby['suicides_no']*1000/european_suicide_data_gby['population'] # A single line to create an animated Bar chart too.
px.bar(european_suicide_data_gby,x='age',y='suicides/100k pop',facet_col='sex',animation_frame='year', 
       animation_group='age', 
       category_orders={'age':['5-14 years', '15-24 years', '25-34 years', '35-54 years', 
       '55-74 years', '75+ years']},range_y=[0,1])

就这样,我们也学会了如何制作条形图的动画。在上面的函数中,我为轴提供了一个category_order来强制分类的顺序,因为它们是有序的。其余的一切还是老样子。

我们可以看到,从 1991 年到 2001 年,75 岁以上男性的自杀率非常高。这可能会增加男性的整体自杀率。

想使用地图查看一个国家的自杀率是如何降低的?这就是我们在数据中获得国家 ISO 代码的原因。

这需要多少行?你猜对了。一个。

suicides_map = suicides.groupby(['year','country','Alpha-3 code']).aggregate(np.sum).reset_index()[['country','Alpha-3 code','suicides_no','population','year']]suicides_map["suicides/100k pop"]=suicides_map["suicides_no"]*1000/suicides_map["population"]px.choropleth(suicides_map, locations="Alpha-3 code", color="suicides/100k pop", hover_name="country", animation_frame="year",
             color_continuous_scale=px.colors.sequential.Plasma)

上图显示了不同国家的自杀率随时间的变化,根据我们从图中得到的信息,所需的编码工作是最小的。我们可以看到:

  • 很多国家都不见了
  • 非洲国家的数据很少
  • 几乎整个亚洲都不见了。

只要看到上面的图表,我们就能很好地理解我们的数据。

时间轴上的动画也增加了很多价值,因为我们能够使用一个图表来查看所有数据。

这可以帮助我们发现数据中隐藏的模式。你不得不承认,它看起来也很酷。

结论

这只是 Plotly Express 的一个预览。您可以使用这个库做许多其他事情。

我喜欢这个库的主要原因是它试图简化图形创建的方式。以及这些图表开箱后看起来有多酷。

想想在 Seaborn 或 Matplotlib 甚至 Plotly 中创建相同的图形需要多长时间。你将会更加感激图书馆所提供的力量。

Plotly 的这个项目缺少一些文档,但是我发现这些函数都有很好的文档记录。在 Jupyter 中,您可以看到使用Shift+Tab的函数定义。

同样根据它的公告文章:“Plotly Express 是完全免费的:凭借其许可的开源 MIT 许可证,你可以按照你喜欢的方式使用它(是的,甚至在商业产品中!)."

因此,现在没有借口推迟这一设想。开始吧…

你可以找到这篇文章的所有代码,并在这个 Kaggle 内核中运行它

如果你想了解创建可视化的最佳策略,我想从密歇根大学调用一门关于 数据可视化和应用绘图 的优秀课程,它是一个很好的 数据科学专业的一部分,Python 本身就是其中之一。一定要去看看

将来我也会写更多初学者友好的帖子。关注我在 媒体 或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系到我

PyTorch 亲笔签名

原文:https://towardsdatascience.com/pytorch-autograd-understanding-the-heart-of-pytorchs-magic-2686cd94ec95?source=collection_archive---------1-----------------------

理解 PyTorch 魔法的核心

In the process it never explicitly constructs the whole Jacobian. It’s usually simpler and more efficient to compute the JVP directly.

来源:https://www . cs . Toronto . edu/~ rgrosse/courses/CSC 321 _ 2018/slides/LEC 10 . pdf

资料来源:http://bumpybrains.com/comics.php?comic=34

让我们只是同意,当涉及到大型神经网络时,我们都不擅长微积分。通过显式求解数学方程来计算如此大的复合函数的梯度是不切实际的,尤其是因为这些曲线存在于大量的维度中并且是不可能理解的。

为了处理 14 维空间中的超平面,想象一个 3 维空间并大声对自己说“14”。每个人都这样做——杰弗里·辛顿

这就是 PyTorch 的亲笔签名的来源。它抽象了复杂的数学,帮助我们“神奇地”用几行代码计算高维曲线的梯度。这篇文章试图描述亲笔签名的魔力。

PyTorch 基础

在继续之前,我们需要了解一些基本的 PyTorch 概念。

Tensors :简单来说就是 PyTorch 中的一个 n 维数组。Tensors 支持一些额外的增强功能,这使它们独一无二:除了 CPU,它们还可以加载到 GPU 上进行更快的计算。在设置.requires_grad = True时,它们开始形成一个反向图,跟踪应用于它们的每一个操作,以使用一种叫做动态计算图(DCG)的东西来计算梯度(在帖子中进一步解释)。

在 PyTorch 的早期版本中, *torch.autograd.Variable* 类用于创建支持梯度计算和操作跟踪的张量,但从 PyTorch v0.4.0 变量类开始, 已被弃用。 torch.Tensortorch.autograd.Variable现在是一个档次。更准确地说,torch.Tensor能够追踪历史,并且表现得像旧的Variable

Code to show various ways to create gradient enabled tensors

****亲笔签名:这个类是一个计算导数的引擎(更准确地说是雅可比向量积)。它记录了在梯度张量上执行的所有操作的图形,并创建了一个称为动态计算图的非循环图形。这个图的叶子是输入张量,根是输出张量。梯度的计算方法是从根到叶追踪图形,并使用链式法则将每个梯度相乘。

神经网络和反向传播

神经网络只不过是经过微妙调整(训练)以输出所需结果的复合数学函数。调整或训练是通过一种叫做反向传播的非凡算法来完成的。反向传播用于计算损失相对于输入权重的梯度,以便稍后更新权重并最终减少损失。

在某种程度上,反向传播只是链式法则——杰瑞米·霍华德的别称

创建和训练神经网络包括以下基本步骤:

  1. 定义架构
  2. 使用输入数据在架构上向前传播
  3. 计算损失
  4. 反向传播以计算每个权重的梯度
  5. 使用学习率更新权重

输入权重的微小变化引起的损失变化称为该权重的梯度,使用反向传播进行计算。然后,使用学习率将梯度用于更新权重,以总体减少损失并训练神经网络。

这是以迭代的方式完成的。对于每次迭代,都要计算几个梯度,并建立一个称为计算图的东西来存储这些梯度函数。PyTorch 通过构建一个动态计算图(DCG)来做到这一点。该图是在每次迭代中从头开始构建的,为梯度计算提供了最大的灵活性。例如,对于前向操作(函数)Mul来说,称为MulBackward的后向操作(函数)被动态集成到后向图中,用于计算梯度。

动态计算图

启用梯度的张量(变量)与函数(运算)结合起来创建动态计算图。数据流和应用于数据的操作是在运行时定义的,因此可以动态地构建计算图。此图由引擎盖下的亲笔签名类动态制作。在开始训练之前,你不必对所有可能的路径进行编码——你跑的就是你与众不同的。

两个张量相乘的简单 DCG 如下所示:

DCG with requires_grad = False (Diagram created using draw.io)

图中的每个虚线框是一个变量,紫色矩形框是一个操作。

每个变量对象都有几个成员,其中包括:

****数据:变量保存的数据。 x 保存一个值等于 1.0 的 1x1 张量,而 y 保存 2.0。 z 表示两者的乘积,即 2.0

requires_grad :该成员,如果为 true,则开始跟踪所有的操作历史,并形成一个用于梯度计算的反向图。对于任意张量 a 它可以被就地操作如下:a.requires_grad_(True).

grad: grad 保存渐变的值。如果requires_grad为假,它将保持一个 None 值。即使requires_grad为真,它也将保持一个 None 值,除非从其他节点调用.backward()函数。例如,如果您为某个变量 out 调用out.backward(),该变量在其计算中涉及,那么x.grad将持有 ∂out/∂x**

grad_fn: 这是用于计算梯度的反向函数。

is_leaf :如果:

  1. 它是由类似于x = torch.tensor(1.0)x = torch.randn(1, 1)的函数显式初始化的(基本上是本文开头讨论的所有张量初始化方法)。
  2. 它是在对所有具有requires_grad = False.的张量进行运算后创建的
  3. 它是通过在某个张量上调用.detach()方法创建的。

在调用backward()时,只为requires_gradis_leaf都为真的节点填充渐变。渐变是从调用.backward()的输出节点开始的,相对于其他叶节点。

打开requires_grad = True时,PyTorch 将开始跟踪操作,并存储每个步骤的梯度函数,如下所示:

DCG with requires_grad = True (Diagram created using draw.io)

PyTorch 引擎下生成上图的代码是:

In the process it never explicitly constructs the whole Jacobian. It’s usually simpler and more efficient to compute the JVP directly.

来源:https://www . cs . Toronto . edu/~ rgrosse/courses/CSC 321 _ 2018/slides/LEC 10 . pdf

为了阻止 PyTorch 跟踪历史和形成后向图,可以将代码包装在with torch.no_grad():中,这将使代码在不需要梯度跟踪时运行得更快。

Backward()函数

Backward 是这样一个函数,它实际上是通过将其参数(默认情况下是 1x1 单位张量)通过后向图一直传递到可从调用根张量追踪到的每个叶节点来计算梯度的。然后将计算出的梯度存储在每个叶节点的.grad中。记住,反向图形已经在正向传递过程中动态生成。Backward function 仅使用已经制作的图形计算梯度,并将它们存储在叶节点中。**

让我们分析下面的代码

需要注意的一件重要事情是,当调用z.backward()时,一个张量被自动作为z.backward(torch.tensor(1.0))传递。torch.tensor(1.0)是为终止链式法则梯度乘法而提供的外部梯度。该外部梯度作为输入传递给MulBackward函数,以进一步计算 x 的梯度。传入.backward()的张量的维数必须与正在计算梯度的张量的维数相同。例如,如果梯度使能张量 x 和 y 如下:

x = torch.tensor([0.0, 2.0, 8.0], requires_grad = True)

y = torch.tensor([5.0 , 1.0 , 7.0], requires_grad = True)

z = x * y

然后,为了计算z(1×3 张量)相对于xy的梯度,需要将外部梯度传递给 z.backward()函数,如下所示:z.backward(torch.FloatTensor([1.0, 1.0, 1.0])

*z.backward()* 会给一个 *RuntimeError: grad can be implicitly created only for scalar outputs*

传递给后向函数的张量的作用类似于梯度加权输出的权重。从数学上来说,这是向量乘以非标量张量的雅可比矩阵(在本文中进一步讨论),因此它几乎总是与张量backward 维数相同的单位张量,除非需要计算加权输出。

tldr:反向图是由自动签名的类在正向传递过程中自动动态创建的。Backward()简单地通过将参数传递给已经制作好的反向图来计算梯度。

数学——雅可比和向量

从数学上来说,亲笔签名的类只是一个雅可比矢量积计算引擎。一个雅可比矩阵用非常简单的话来说就是一个表示两个向量所有可能偏导数的矩阵。它是一个向量相对于另一个向量的梯度。

注意:在这个过程中 PyTorch 从不显式地构造整个 Jacobian。直接计算 JVP(雅可比向量积)通常更简单、更有效。

如果一个向量X =【x1,x2,…。xn]* 用于计算其他一些向量 f(X) = [f1,f2,…。fn] 通过函数 f 然后雅可比矩阵( J )简单地包含所有偏导数组合如下:***

Jacobian matrix (Source: Wikipedia)

以上矩阵表示 f(X) 相对于 X 的梯度

假设 PyTorch 梯度启用张量 X 为:

X = [x1,x2,…..xn] (假设这是某个机器学习模型的权重)

X 经过一些运算形成一个矢量 Y

Y = f(X) = [y1,y2,…。ym]

Y 然后用于计算标量损失 l. 假设向量 v 恰好是标量损失 l 的梯度,关于向量 Y 如下

向量 v 被称为 *grad_tensor* 并作为自变量传递给 *backward()* 函数

为了得到损失 l 相对于权重 X 的梯度,雅可比矩阵 J 被向量乘以向量 v

这种计算雅可比矩阵并将其与矢量 v 相乘的方法使得 PyTorch 能够轻松提供外部梯度,即使是非标量输出。

进一步阅读

反向传播:快速修改

PyTorch:自动分化包—torch . autogradated

亲笔签名的源代码

视频:PyTorch 亲笔签名讲解——深度教程作者埃利奥特·韦特

感谢您的阅读!欢迎在回复中表达任何疑问。

PyTorch 深度学习模板

原文:https://towardsdatascience.com/pytorch-deep-learning-template-6e638fc2fe64?source=collection_archive---------21-----------------------

一个干净简单的模板来启动你的下一个 dl 项目🚀🚀

这里的模板是这里的

在本文中,我们将向您展示一个基于 Pytorch 的深度学习模板。这个模板旨在让你更容易用 PyTorch 开始一个新的深度学习计算机视觉项目。主要特点是:

  • 模块化:我们将每个逻辑块分成不同的 python 子模块
  • 数据扩充:我们包括了伊姆高格
  • 蓄势待发:通过使用类似 Keras 的框架 poutyne ,你不必编写任何 train 循环。
  • 火炬摘要展示您的模型摘要
  • 在稳定期降低学习率
  • 自动保存最佳模型
  • 彗星进行实验跟踪

动机

让我们面对它,通常,数据科学家不是软件工程师,他们通常以意大利面条代码结束,大部分时间在一个大的不可用的木星笔记本上。有了这个 repo,你已经提出了一个清晰的例子,说明你的代码应该如何拆分和模块化,以使可伸缩性和可共享性成为可能。在这个例子中,我们将尝试对达斯·维德和卢克·天行者进行分类。我们用谷歌图片收集了每个班级 100 张图片。数据集在这里是这里是。你只需要在这个文件夹中精确它并运行 main.py。我们正在微调 resnet18,它应该能够在 5/10 个周期内达到 90%的准确性。

模板在./template里面。

我们强烈建议使用模板

保持你的结构干净简洁

每个深度学习项目至少有三个主要步骤:

  • 数据收集/处理
  • 建模
  • 培训/评估

一个好主意是将所有路径存储在一个感兴趣的位置,例如数据集文件夹,存储在一个共享类中,该文件夹中的任何人都可以访问它。你不应该硬编码任何路径,总是定义一次并导入它们。所以,如果你以后改变你的结构,你只需要修改一个文件。如果我们看一下Project.py,我们可以看到我们是如何一劳永逸地定义了data_dircheckpoint_dir。我们正在使用“新的”路径API,它支持开箱即用的不同操作系统,并且还使加入和连接路径变得更加容易。

例如,如果我们想知道数据位置,我们可以:

from Project import project
print(projct.data_dir) # /foo/baa/…/dataset

data包中,您可以定义自己的数据集,一如既往地通过子类化torch.data.utils.Dataset,公开转换和实用程序来处理您的数据。在我们的例子中,我们直接使用了来自torchvisionImageDataset,但是我们在/data/MyDataset中包含了一个定制Dataset的框架

转换

您通常需要对数据进行一些预处理,例如调整图像大小和应用数据扩充。你所有的转变都应该在.data.trasformation里面。在我们的模板中,我们包含了一个 imgaug 的包装器

数据加载器

如您所知,您必须创建一个Dataloader来将您的数据输入到模型中。在data.__init__.py文件中,我们公开了一个非常简单的函数get_dataloaders,使用几个参数自动配置训练、val 和测试数据加载器

你所有的模型都在models里面,在我们的例子中,我们有一个非常基本的 cnn,我们覆盖resnet18函数来提供一个冻结的模型来微调。

在我们的例子中,我们保持事情简单,所有的训练和评估逻辑都在.main.py中,我们使用 poutyne 作为主库。我们已经定义了一个有用的回调列表:

  • 学习率调度程序
  • 最佳模型的自动保存
  • 通常提前停止,这就是你所需要的!

追踪你的实验

我们使用彗星来自动跟踪我们模型的结果。这是慧星的板子运行了几个模型后的样子。

运行main.py产生以下输出:

我们还创建了不同的工具函数来绘制展位数据集和数据加载器。他们在utils.py。例如,在我们的 train 和 val 数据集上调用show_dl会产生以下输出。

正如你所看到的,数据扩充被正确地应用在训练集上。

这里的代码是这里是

结论

我希望你能找到一些有用的信息,希望这个模板能对你下一个令人惊叹的项目有所帮助:)

如果你有什么改进的想法/建议,请告诉我。

您可能也会发现这些文章很有趣:

[## 卷积神经网络可视化之旅

弗朗西斯科·萨维里奥·祖皮奇尼

towardsdatascience.com](/a-journey-into-convolutional-neural-network-visualization-1abc71605209)

https://towardsdatascience . com/py torch-how-and-when-use-module-sequential-modulelist-and-module prediction-7a 54597 b5 f17

感谢您的阅读。

深度学习 PyTorch:初学者快速指南

原文:https://towardsdatascience.com/pytorch-for-deep-learning-a-quick-guide-for-starters-5b60d2dbb564?source=collection_archive---------2-----------------------

2019 年,ML 框架的战争有两个主要竞争者: PyTorchTensorFlow 。由于 PyTorch 易于使用,越来越多的研究人员和学生采用 py torch,而在工业界,Tensorflow 目前仍是首选平台。

PyTorch 的一些主要优势包括:

  • 简单性:它非常 Python 化,可以很容易地与 Python 生态系统的其他部分集成。它易于学习、使用、扩展和调试。
  • PyTorch 在可用性方面大放异彩,因为它设计了更好的面向对象的类,这些类封装了所有重要的数据选择以及模型架构的选择。PyTorch 的文档也很出彩,对初学者很有帮助。
  • 动态图: PyTorch 实现了动态计算图。这意味着网络可以在运行时改变行为,只需很少或不需要开销。这对于调试和以最小的努力构建复杂的模型非常有帮助。允许 PyTorch 表达式自动区分。

Unsplash

PyTorch 在研究中越来越受欢迎。下图显示了在其他深度学习框架中,单词“PyTorch”每月被提及的次数占所有被提及次数的百分比。我们可以看到,2019 年 arXiv 中 PyTorch 的上升趋势非常明显,几乎达到了 50%。

arXiv papers mentioning PyTorch is growing

动态图形生成,紧密的 Python 语言集成,以及相对简单的 API使得 PyTorch 成为一个优秀的研究和实验平台。

装置

PyTorch 提供了一个非常简洁的界面来获得要安装的工具的正确组合。下面是快照选择和相应的命令。Stable 代表 PyTorch 的最新测试和支持版本。这个应该适合很多用户。预览是可用的,如果你想要最新的版本,没有完全测试和支持。您可以从 Anaconda(推荐)和 Pip 安装包中进行选择,并支持各种 CUDA 版本。

PyTorch 模块

现在我们将讨论 PyTorch 库的关键模块,如张量亲笔签名优化器神经网络(NN ) ,它们对于创建和训练神经网络是必不可少的。

张量

张量是 PyTorch 的主力。我们可以把张量想象成多维数组。PyTorch 有一个由 torch 模块提供的大量操作库。PyTorch 张量非常接近非常流行的 NumPy 阵列。事实上,PyTorch 具有与 NumPy 无缝互操作的特性。与 NumPy 数组相比,PyTorch 张量增加了一个优势,即张量和相关操作都可以在 CPU 或 GPU 上运行。PyTorch 提供的第二个重要功能是允许张量跟踪对它们执行的操作,这有助于计算输出相对于任何输入的梯度或导数。

基本张量运算

张量是指将向量和矩阵推广到任意维数。张量的维数与用于引用张量内标量值的索引的数量一致。零阶张量(0D 张量)只是一个数字或者一个标量。一阶张量(1D 张量)是一组数字或一个矢量。类似地,二阶张量(2D)是一组向量或一个矩阵。

现在让我们在 PyTorch 中创建一个张量。

导入 torch 模块后,我们调用了一个函数 torch.ones ,它创建了一个大小为 9 的(2D)张量,其中填充了值 1.0。

其他方式包括使用**t*orch.zeros***零填充张量,***torch.randn***来自随机均匀分布。

类型和尺寸

每个张量都有相关的类型和大小。使用**torch.Tensor**构造函数时,默认的张量类型是**torch.FloatTensor**。但是,您可以将张量转换为不同的类型(**float** **long****double**等)。)通过在初始化时或稍后使用类型转换方法之一指定它。指定初始化类型有两种方法:要么直接调用特定张量类型的构造函数,如**FloatTensor****LongTensor**,要么使用特殊的方法 **torch.tensor()**,并提供**dtype**.

一些有用的张量运算:

找出张量中的最大值项以及包含最大值的索引。这些可以通过***max()******argmax()***功能完成。我们还可以使用**item()**从 1D 张量中提取标准的 Python 值。

大多数对张量进行操作并返回张量的函数都会创建一个新的张量来存储结果。如果你需要一个 就地 函数,寻找一个附加了下划线(*_*)的函数,例如***torch.transpose_***将对一个张量进行就地转置。

使用***torch.from_numpy*** & ***torch.numpy()*** ,张量和 Numpy 之间的转换非常简单。

另一个常见的操作是 重塑 一个张量。这是经常使用的操作之一,也非常有用。我们可以用***view()******reshape()***来做这件事:

***Tensor.reshape()******Tensor.view()***虽然不一样。

  • ***Tensor.view()***只作用于连续的张量,并且永远不会复制内存。这将在非连续张量上引起误差。但是你可以通过调用***contiguous()***使张量连续,然后你可以调用***view()***
  • ***Tensor.reshape()***将对任何张量起作用,如果需要的话可以克隆

张量广播

PyTorch 支持类似 NumPy 的广播。广播可以让你在两个张量之间进行运算。广播语义参见这里的

张量简而言之:什么,如何在哪里

唯一定义张量的三个属性是:

dtype: 张量的每个元素中实际存储的是什么?这可以是浮点数或整数等。PyTorch 有九种不同的数据类型。

布局:我们如何从逻辑上解释这个物理内存。最常见的布局是步进张量。跨距是一个整数列表:第 k 个跨距表示从张量的第 k 维中的一个元素到下一个元素所必需的内存跳跃。

设备:张量的物理内存实际存储在哪里,例如在 CPU 或 GPU 上。**torch.device**包含设备类型('**cpu**''**cuda**')和设备类型的可选设备序号。

亲笔签名

亲笔签名是自动区分系统。自动微分是干什么的?给定一个网络,它会自动计算梯度。当计算向前传球时,自动签名同时执行请求的计算并建立一个表示计算梯度的函数的图形。

这是如何实现的?

PyTorch 张量可以根据产生它们的操作和父张量来记住它们来自哪里,并且它们可以自动提供这种操作相对于它们的输入的导数链。这是通过**requires_grad** 实现的,如果设置为真。

**t= torch.tensor([1.0, 0.0], requires_grad=True)**

计算完梯度后,导数的值被自动填充为张量的**grad** 属性。对于具有任意数量张量的函数的任意组合用**requires_grad= True**;PyTorch 将计算整个函数链的导数,并在这些张量的**grad** 属性中累加它们的值。

优化者

优化器用于更新权重和偏差,即模型的内部参数,以减少误差。更多细节请参考我的另一篇文章

PyTorch 有一个**torch.optim**包,里面有各种优化算法,比如 SGD(随机梯度下降)、Adam、RMSprop 等。

让我们看看如何创建一个提供的优化器 SGD 或 Adam。

**import torch.optim as optim
params = torch.tensor([1.0, 0.0], requires_grad=True)****learning_rate = 1e-3****## SGD
optimizer = optim.SGD([params], lr=learning_rate)****## Adam
optimizer = optim.Adam([params], lr=learning_rate)**

如果不使用优化器,我们将需要手动更新模型参数,如下所示:

 **for params in model.parameters(): 
       params -= params.grad * learning_rate**

我们可以使用优化器中的**step()**方法向前迈进一步,而不是手动更新每个参数。

**optimizer.step()**

调用 step 时,params 的值会更新。优化器查看**params.grad**,并通过从中减去**learning_rate** 乘以**grad** 来更新**params** ,就像我们在没有使用优化器的情况下所做的一样。

**torch.optim** 模块通过传递一个参数列表,帮助我们抽象出具体的优化方案。由于有多种优化方案可供选择,我们只需要为我们的问题选择一种,然后让底层 PyTorch 库为我们施展魔法。

神经网络

在 PyTorch 中,**torch.nn**包定义了一组类似于神经网络层的模块。模块接收输入张量并计算输出张量。**torch.nn**包还定义了一组训练神经网络时常用的有用损失函数。

构建神经网络的步骤是:

  • 神经网络构建:创建神经网络层。设置参数(权重、偏差)
  • 正向传播:计算预测输出。测量误差。
  • 反向传播:找到误差后,我们反向传播我们的误差梯度以更新我们的权重参数。我们通过对误差函数相对于我们的神经网络的参数进行求导来做到这一点。
  • 迭代优化:我们要尽可能的把误差降到最低。我们通过梯度下降不断迭代更新参数。

建立一个神经网络

让我们按照上面的步骤,在 PyTorch 中创建一个简单的神经网络。

第一步:神经网络构建

我们这里把我们的 NN **Net** 叫做我们继承了**nn.Module**。与super().__init__()结合,这创建了一个跟踪架构的类,并提供了许多有用的方法和属性。

我们的神经网络**Net**有一个隐含层**self.hl**和一个输出层 **self.ol**

**self.hl = nn.Linear(1, 10)**

这一行创建了一个具有 1 个输入和 10 个输出的线性变换模块。它还会自动创建权重和偏差张量。一旦用**net.hl.weight****net.hl.bias**创建了网络**net**,就可以访问权重和偏差张量。

我们已经使用**self.relu = nn.ReLU()**定义了激活。

第二步:正向传播

**nn.Module**创建的 PyTorch 网络必须定义一个**forward()**方法。它接受一个张量**x**并通过您在**__init__**方法中定义的操作传递它。

**def** forward(self, x):
   hidden = self.hl(x)
   activation = self.relu(hidden)
   output = self.ol(activation)

我们可以看到,输入张量经过隐层,然后是激活函数(relu),最后是输出层。

步骤 3:反向传播

这里,我们必须计算误差或损失,并反向传播我们的误差梯度,以更新我们的权重参数。

损失函数获取(输出,目标)并计算一个估计**output****target**有多远的值。在**torch.nn**包下有几个不同的损失函数。一个简单的损失是**nn.MSELoss**,它计算输入和目标之间的均方误差。

**output = net(input)
loss_fn = nn.MSELoss()
loss = loss_fn(output, target)**

反向投影

一个简单的函数调用**loss.backward()** 传播错误。不要忘记清除现有的梯度,否则梯度将积累到现有的梯度。调用**loss.backward()**后,查看反向调用前后的隐藏层偏差梯度。

所以在调用 backward()之后,我们看到渐变是为隐藏层计算的。

步骤 4:迭代优化

我们已经看到 optimizer 如何帮助我们更新模型的参数。

***# create your optimizer*
optimizer = optim.Adam(net.parameters(), lr=1e-2)****optimizer.zero_grad()   *# zero the gradient buffers*****output = net(input)     # calculate output
loss = loss_fn(output, target) #calculate loss
loss.backward()      # calculate gradient****optimizer.step()     *# update parameters***

请注意不要错过**zero_grad()** 来电。如果你错过调用它,梯度会在每次调用 backward 时累积,你的梯度下降不会收敛。下面是 Andrej 最近的一条推文,展示了修复这些漏洞的沮丧和时间。

现在,我们的基本步骤(1,2,3)已经完成,我们只需要迭代训练我们的神经网络,以找到最小的损失。所以我们运行**training_loop** 多次,直到损失最小。

让我们运行我们的神经网络来训练输入**x_t**和目标**y_t**

我们称**training_loop** 为 1500 个时代,可以通过所有其他的论点,如**optimizer****model****loss_fn**、、**inputs****target**。每 300 个周期后,我们打印损失,我们可以看到每次迭代后损失都在减少。看起来我们最基本的神经网络正在学习。

我们绘制了模型输出(黑叉)和目标数据(红圈),模型似乎学得很快。

到目前为止,我们已经讨论了 PyTorch 的基本或必要元素,以帮助您入门。我们可以看到我们构建的代码是如何模块化的,每个组件都提供了基本块,可以根据我们的要求进一步扩展以创建机器学习解决方案。

为实际问题创建基于机器学习的解决方案涉及到大量的数据准备工作。然而,PyTorch 库提供了许多工具来使数据加载变得容易和更具可读性,如分别处理图像、文本和音频数据的**torchvision****torchtext****torchaudio**

训练机器学习模型通常非常困难。当我们遇到一些问题时,总是需要一个工具来帮助可视化我们的模型和理解训练进度。tensor board就是这样一个工具,帮助我们记录来自模型训练的事件,包括各种标量(如精度、损失)、图像、直方图等。自从 PyTorch 1.2.0 发布以来,TensorBoard 现在是 PyTorch 的内置特性。请按照教程安装和使用 Pytorch 中的张量板。

谢谢你的阅读。下一篇文章再见:)

参考资料:

[1]https://the gradient . pub/state-of-ml-frameworks-2019-py torch-domains-research-tensor flow-domains-industry/

[2]https://pytorch.org/

https://www.kdnuggets.com/2018/05/wtf-tensor.html

PyTorch 基础

原文:https://towardsdatascience.com/pytorch-fundamentals-50af6121d4a3?source=collection_archive---------22-----------------------

PyTorch 是最著名的深度学习框架之一。我个人更喜欢 PyTorch,因为它的 pythonic 性质。很容易将每一行代码都视为一个函数,有清晰的输入和输出。

在这篇文章中,我将讨论在使用 PyTorch 进行深度学习时起关键作用的以下基本结构和操作。

  1. 矩阵或张量
  2. 张量运算
  3. 变量和梯度

矩阵或张量

矩阵被正式定义为“数字的矩形阵列”。在 numpy 图书馆,他们被称为“ndarrays ”,而在 PyTorch,他们被称为“男高音”。

Taken from https://www.onlinemathlearning.com/matrices-rows-columns.html

上图所示的张量是一个 3 行 2 列的 2D 张量。让我们看看如何在 PyTorch 中创建张量。

**import** numpy **as** np
**import** torch

*# 1) Create a PyTorch Tensor an array* arr = [[3, 4], [8, 5]] *# python array* pyt_tensor = torch.Tensor(arr) *# PyTorch tensor

# 2) Create a tensor* ones_tensor = torch.ones((2, 2)) *# tensor containing all ones* torch.manual_seed(0)             *# to have same values for random generation* rand_tensor = torch.rand((2, 2)) *# tensor containing random values

# if running on GPU, set random seed value as follows* **if** torch.cuda.is_available():
    torch.cuda.manual_seed_all(0)

*# 3) Create a tensor from numpy array (dtype must be either double, float, int64, int32, or uint8)* np_arr = np.ones((2, 2))
pyt_tensor = torch.from_numpy(np_arr)
np_arr_from_tensor = pyt_tensor.numpy() *# convert tensor to numpy array*

张量运算

所有适用于数组的运算也适用于张量。下面是 PyTorch 中的做法。

**import** numpy **as** np
**import** torch

*# 1) Resizing a tensor* pyt_tensor = torch.ones((2, 2))
print(pyt_tensor.size())        *# shows the size of this tensor* pyt_tensor = pyt_tensor.view(4) *# resizing 2x2 tensor to 4x1

# 2) Mathematical Operations* pyt_tensor_a = torch.ones((2, 2))
pyt_tensor_b = torch.ones((2, 2))
res_tensor = pyt_tensor_a + pyt_tensor_b               *# simple element wise addidtion* res_tensor = torch.add(pyt_tensor_a, pyt_tensor_b)     *# another way of addidtion* pyt_tensor_a.add_(pyt_tensor_b)                         *# In-place addition

# Operation     operator    function_name
#  => Addition        +           add
#  => Subtraction     -           sub
#  => Multiplication  *           mul
#  => Divide          /           div

# 3) Mean and Standart deviation* pyt_tensor = torch.Tensor([1, 2, 3, 4, 5])
mean = pyt_tensor.mean(dim=0)                        *# if multiple rows then dim = 1* std_dev = pyt_tensor.std(dim=0)                        *# if multiple rows then dim = 1*

变量和梯度

梯度计算是深度学习中的关键事情之一。在 PyTorch 中,变量用于计算梯度。本质上,变量只是张量的包装,具有梯度计算的功能。

以下是用于管理变量的 python 代码

****import** numpy **as** np
**import** torch
**from** torch.autograd **import** Variable

pyt_var = Variable(torch.ones((2, 2)), requires_grad = **True**)

*# behaves exactly the same as tensors, so we can apply all operations in the same way***

现在,我们来看看如何在 PyTorch 中使用变量来计算梯度。

****import** numpy **as** np
**import** torch
**from** torch.autograd **import** Variable

*# let's consider the following equation
# y = 5(x + 1)^2* x = Variable(torch.ones(1), requires_grad = **True**)
y = 5 * (x + 1) ** 2        *# implementing the equation.* y.backward()                *# calculate gradient* print(x.grad)               *# get the gradient of variable x
# differentiating the above mentioned equation
# => 5(x + 1)^2 = 10(x + 1) = 10(2) = 20***

这篇文章中提到的事情非常简单直接,但也非常重要。如果基础知识以正确的方式学习,框架的知识会增长得很快。我自己发现偶尔回顾一下这些基础知识是很有用的,可以避免在实际编写代码时不必要的时间延迟。

Pytorch 闪电 vs PyTorch Ignite vs Fast.ai

原文:https://towardsdatascience.com/pytorch-lightning-vs-pytorch-ignite-vs-fast-ai-61dc7480ad8a?source=collection_archive---------4-----------------------

Apparently a lion, bear, and tiger are friends

PyTorch-lightning 是一个最近发布的库,是 PyTorch 的一个类似 Kera 的 ML 库。它将核心培训和验证逻辑留给您,并将其余部分自动化。(顺便说一句,我说的 Keras 是指没有样板,没有过度简化)。

作为《闪电》的核心作者,我几次被问到《闪电》和 fast.ai、 PyTorch ignite 的核心区别。

在这里,我将尝试对所有三个框架进行客观的比较。这种比较来自于在所有三个框架的教程和文档中客观发现的相似性和差异。

注意:本文捕获了撰写本文时(2019 年 8 月)这些框架中可用的特性。这些框架有更新的版本。

动机

Ummmm

Fast.ai 最初是为了便于教授 fast.ai 课程而创建的。它最近还演变成一个常用方法的实现库,如 GANs、RL 和迁移学习。

PyTorch IgnitePytorch Lightning 都是为了给研究人员尽可能多的灵活性,要求他们为训练循环和验证循环中发生的事情定义函数。

Lightning 还有另外两个更加雄心勃勃的动机:可复制性和民主化的最佳实践,只有 PyTorch 超级用户才会实施(分布式培训、16 位精度等等)。我将在后面的章节中详细讨论这些动机。

因此,在基本层面上,目标用户是明确的:对于 fast.ai 来说,它是对深度学习感兴趣的人,而另外两个则专注于活跃的人工智能研究人员(即生物学家、神经科学家等)

学习曲线

Framework Overload

Lightning 和 Ignite 都有非常简单的界面,因为大部分工作仍然由用户在纯 PyTorch 中完成。主要工作分别发生在发动机训练器物体内部。

然而,Fast.ai 确实需要在 PyTorch 上学习另一个库。大多数时候,API 并不直接在纯 PyTorch 代码上操作(有些地方是这样的),但是它需要像 DataBunchesDataBlocs 等抽象。当做某事的“最佳”方式不明显时,这些 API 非常有用。

然而,对于研究人员来说,重要的是不必学习另一个库,直接控制研究的关键部分,如数据处理,而无需其他抽象操作。

在这种情况下,fast.ai 库具有更高的学习曲线,但如果您不一定知道做某事的“最佳”方法,而只想采用好的方法作为黑盒,那么这是值得的。

闪电 vs 点燃

More like sharing

从上面可以清楚地看到,考虑到用例和用户的不同,将 fast.ai 与这两个框架进行比较是不公平的(然而,我仍然会将 fast.ai 添加到本文末尾的比较表中)。

Lightning 和 ignite 之间的第一个主要区别是它的操作界面。

在 Lightning 中,有一个标准接口(见 LightningModule )包含每个模型必须遵循的 9 个必需方法。

这种灵活的形式为培训和验证提供了最大的自由度。这个接口应该被认为是一个 系统, 不是一个模型。系统可能有多个模型(GANs、seq-2-seq 等),也可能是 as 模型,比如这个简单的 MNIST 例子。

因此,研究人员可以随心所欲地尝试许多疯狂的事情,只需担心这 9 种方法。

Ignite 需要非常相似的设置,但没有每个型号都需要遵循的标准 接口。

注意运行功能可能有不同的定义,即:可能有许多不同的事件被添加到训练器中,或者它甚至可能被命名为不同的名称,如 main、train 等……

在一个复杂的系统中,训练可能会以奇怪的方式发生(看看你的 GANs 和 RL),对于查看这些代码的人来说,发生了什么并不明显。而在 Lightning 中,您会知道查看 training_step 来弄清楚发生了什么。

再现性

When you try to reproduce work

正如我提到的,创造闪电还有第二个更远大的动机:再现性

如果你试图阅读某人对一篇论文的实现,很难弄清楚发生了什么。我们只是设计不同的神经网络架构的日子已经一去不复返了。

现代 SOTA 模型实际上是 系统,它们采用许多模型或训练技术来实现特定的结果。

如前所述,LightningModule 是一个 系统 ,而不是一个模型。因此,如果你想知道所有疯狂的技巧和超级复杂的训练发生在哪里,你可以看看训练步骤和验证步骤。

如果每个研究项目和论文都使用 LightningModule 模板来实现,那么就很容易发现发生了什么(但可能不容易理解哈哈)。

人工智能社区的这种标准化也将允许生态系统蓬勃发展,该生态系统可以使用 LightningModule 接口来做一些很酷的事情,如自动部署,审计系统的偏差,甚至支持将权重散列到区块链后端,以重建用于可能需要审计的关键预测的模型。

现成的功能

Ignite 和 Lightning 的另一个主要区别是 Lightning 支持开箱即用的功能。开箱即用意味着您没有额外的代码。

为了说明,让我们尝试在同一台机器上的多个 GPU 上训练一个模型

点燃( 演示 )

闪电( 演示 )

好吧,两者都不错…但是如果我们想在许多机器上使用多 GPU 呢?让我们在 200 个 GPU 上训练。

点燃

嗯,对此没有内置的支持…你必须对这个例子进行一些扩展,并添加一个容易提交脚本的方法。然后你必须负责加载/保存,而不是用所有的进程覆盖权重/日志,等等…你明白了吧。

闪电

使用 lightning,您只需设置节点数量并提交适当的作业。这里有一个关于正确配置作业的深入教程

开箱即用的特性是您 不需要做任何事情就能获得的特性。 这意味着你现在可能不需要它们中的大部分,但当你需要说…积累渐变,或渐变剪辑,或 16 位训练时,你不会花几天/几周的时间通读教程来让它工作。

只要设置合适的闪电标志,继续你的研究。

Lightning 预建了这些功能,因此用户可以花更多时间进行研究,而不是进行工程设计。这对于非 CS/DS 研究人员特别有用,例如物理学家、生物学家等,他们可能不太熟悉编程部门。

这些特性使 PyTorch 的特性民主化,只有超级用户才可能花时间去实现。

下面的表格比较了所有 3 个框架的功能,并按功能集进行了分组。

如果我错过了什么重要的东西,请发表评论,我会更新表格!

高性能计算

调试工具

可用性

结束语

在这里,我们对三个框架进行了多层次的深入比较。每个人都有自己的优点。

如果你刚刚开始学习或者没有掌握所有最新的最佳实践,不需要超高级的培训技巧,并且有时间学习新的库,那么就用 fast.ai 吧。

如果你需要最大的灵活性,选择点燃闪电。

如果你不需要超级先进的功能,并且可以添加你的 tensorboard 支持、累积梯度、分布式训练等,那么就用 Ignite 吧。

如果您需要更多高级功能、分布式培训、最新和最棒的深度学习培训技巧,并且希望看到一个实现在全球范围内标准化的世界,请使用 Lightning。

编辑:

2019 年 8 月:编辑以反映 Ignite 团队的反馈。

2021 年 2 月:正在进行研究以验证 Fast.ai v1.0.55 中可用的功能

PyTorch 1.3 —有什么新功能?

原文:https://towardsdatascience.com/pytorch-v1-3-whats-new-79595c14971e?source=collection_archive---------14-----------------------

支持 Android 和 iOS,命名张量,TPU 支持,量化和更多。

脸书刚刚发布了 PyTorch v1.3,它包含了一些最令人期待的特性。最吸引人的三个是:

  1. 名为张量——这将使机器学习实践者的生活变得更加容易。
  2. 量化 —针对物联网设备和嵌入式系统等性能关键型系统。
  3. 移动支持 —适用于 Android 和 iOS 设备。

我将简要介绍所有这些功能,并将链接到其他一些重要功能。

名为张量

PyTorch v1.3 最终增加了对命名张量的支持,允许用户使用显式关联的名称访问张量维度,而不是记住维度编号。例如,到目前为止,在与计算机视觉相关的任务中,我们必须记住批处理的一般结构,如下所示— [N,C,H,W]。其中 N 是批量大小,C 是通道数量,H 和 W 分别是图像的高度和宽度。在对这个批处理执行操作时,我们必须跟踪这样一个结构,但是现在我们可以只使用维度名称,而不是跟踪它的索引。此外,这些命名表示可以提供增强的运行时错误检查。我将在本文中进一步讨论它们。

Creating Named Tensors.

batch.names按顺序打印张量batch上每个维度的名称。

按名称对齐

使用[align_as()](https://pytorch.org/docs/master/named_tensor.html#torch.Tensor.align_as)[align_to()](https://pytorch.org/docs/master/named_tensor.html#torch.Tensor.align_to)将张量维度按名称排列成指定的顺序。

在计算机视觉模型中,批次的表示通常需要在N,C,H,WN,H,W,C之间变化。到目前为止,这必须像batch.permute([0, 2, 3, 1])一样反直觉地完成,但是现在可以通过使用[align_as()](https://pytorch.org/docs/master/named_tensor.html#torch.Tensor.align_as)[align_to()](https://pytorch.org/docs/master/named_tensor.html#torch.Tensor.align_to)操作符以更简单的方式完成。

对于大量的维度,普通的置换操作符需要所有维度的显式列表,即使只是交换两个维度的位置。然而,在命名张量的情况下,维度的排列或重新排序可以以更容易和更简单的方式完成,如下所示:

复选姓名

除了使张量更加直观,命名张量还提供了额外的错误检查。操作符应用于命名张量时(对于二元操作符,任何一个或两个命名张量),将在运行时隐式检查某些维度名称是否匹配。这为防止错误提供了额外的安全性。如下例所示:

在上面的例子中,如果不是对于命名张量,batch1batch2可以无误差地相加,因为 height = width = 100。然而,batch2的高度和宽度尺寸互换,将其添加到batch1可能不是预期的操作。由于命名张量,这个逻辑错误将被名称检查捕获,因为(' N ',' C ',' H ',' W ')和(' N ',' C ',' W ',' H ')是不同的。

名字什么时候匹配?

这些规则非常类似于 numpy 或 PyTorch 中的维度广播规则。引用 PyTorch 官方文件:

如果两个名字相等(字符串相等)或者至少有一个是 *None* ,则两个名字匹配。Nones 本质上是一个特殊的“通配符”名称。

下面的例子展示了这一点:

名称传播

在张量上执行操作后,您不需要再次输入尺寸名称,它们将被自动传播。PyTorch 使用两个操作符— matchunify 进行名称传播。

  • match与上面定义的操作符相同,它检查两个指定的张量是否匹配。
  • unify是一个算子,用于确定两个输入张量中的哪一个的名字应当被传播到结果张量中。引用 PyTorch 官方文件:

*unify(A, B)* 决定将 *A* *B* 中的哪一个名称传播到输出。如果匹配,它将返回两个名称中更具体的一个。如果名称不匹配,就会出错。

下面的示例展示了名称传播:

  • 一元运算符:

  • 二元运算符:

限制

在写这篇文章的时候,命名的张量功能还处于实验阶段,可能会有很多变化。然而,命名张量目前最大的一个限制是,它们不完全支持亲笔签名的引擎。虽然命名张量的梯度计算是完全相同的,但自动签名引擎完全忽略了名称及其提供的额外安全性。

量子化

PyTorch 1.3 现在支持张量的量子化。这是 Tensorflow 已经支持并在 PyTorch 中期待已久的东西。量子化是一个相当简单却复杂的概念。在这里,我将通过回答三个问题——什么、为什么和如何——来尝试用高度抽象的方式简要地描述它们。

什么是量子化?

量化是以低精度格式执行操作或将高精度数据格式转换为低精度数据格式的技术。例如,这是通过将 32 位浮点格式视为 8 位定点格式来实现的。如果感兴趣,你可以阅读一下定点浮点运算及其相关的复杂性,以便更好地理解量化的需要。

为什么要 量子化?

从事研究和创建神经网络模型的全部目的是部署它们并使它们为公众利益服务。虽然模型训练需求只与研究人员和机器学习实践者的数量成比例增长,但模式推理的需求与消费者的数量成比例增长。为了允许更多更好地访问最终用户,为推理而部署的模型的表示需要比它们在训练时的表示更紧凑。另一件要记住的事情是,反向传播需要模型权重和偏差的高精度表示。然而,在推理过程中,模型更加稳健,并且不需要高精度的表示。因此,以 32 位浮点表示的大小为 113.9MB 的模型可以被量化为 int8,大小为 76.8 MB。

py torch v 1.3 中如何使用量化?

引用 PyTorch 官方文档:

与典型的 FP32 型号相比,PyTorch 支持 INT8 量化,允许型号大小减少 4 倍,内存带宽需求减少 4 倍。对 INT8 计算的硬件支持通常比 FP32 计算快 2 到 4 倍。

对于量化,PyTorch 引入了如下三种新的数据类型:

  • torch.quint8 — 8 位无符号整数。
  • torch.qint8 — 8 位有符号整数。
  • torch.qint32 — 32 位有符号整数。

PyTorch 现在为模型提供了三种量化方法:

  1. 训练后动态量化 —提前量化权重,但在运行时动态量化网络激活。操作如下:torch.quantization.quantize_dynamic(model, dtype=torch.qint8)
  2. 训练后静态量化 —提前量化权重和激活偏差以及比例因子。这是通过调用校准函数来完成的。有关更多详细信息,请参考原始文档。
  3. 量化感知训练 —在该模型中,对 FP32 表示进行训练,但随后量化为较低精度的精度表示,如 INT8。这用于正常量化不能提供精确结果的罕见情况。因此,我们开始用量化值训练模型。

另一件需要注意的事情是 PyTorch 完全支持量化。这意味着,我们也可以用下面的等式(非常直观)和代码来量化张量:

This equation is used for the int representation of the quantized tensor that can be accessed using t.int_repr()

这里的是对量子化张量的所有支持操作的列表。

移动支持

允许量化的自然目的是在性能关键的移动电话(和其他设备)上运输 PyTorch 模型。他们已经为 Android 和 iOS 实现了端到端的 PyTorch API。这对降低推理延迟和用户隐私会有很大的影响。然而,PyTorch mobile 目前仍处于早期试验阶段,存在一些局限性。例如,当前版本只支持向前传播(推断),不支持向后操作。

你可以在 PyTorch 官方网站上访问 iOS 和 Android 的 hello world 教程。

更多更新

除了这三个主要更新,PyTorch v1.3 还实现了其他一些更改和错误修复。你可以在官方 PyTorch Github 库上查看所有变更的列表。这些功能包括:

  • TPU 支持谷歌云 PyTorch。这里有一个 Github repo 展示了如何在 PyTorch 中使用 TPU。
  • 对 TensorBoard 的扩展支持:3D 网格和超参数
  • torchscript 的主要更新(主要针对手机)
  • torch.nntorch.nn.functional、自动签名引擎等方面的性能提升。

此外,如果您想将您的代码从 PyTorch 以前的版本移植到 PyTorch v1.3,您需要注意可能导致错误或意外行为的特性。其中一些特性是(我直接引用了前面提到的发行说明中的这些变化):

  1. 数据类型提升:例如,torch.tensor(5) + 1.5输出一个值为 6.5 的张量。在早期版本中,输出应该是 6。
  2. 就地操作符的数据类型提升:例如,考虑下面的代码:a = torch.tensor(0); a.add_(0.5)在早期版本中,这会给出一个值为 1 的张量作为输出。但是到目前为止,PyTorch 不再支持较低数据类型的就地操作,因此上面这段代码输出了一个错误。
  3. torch . flatten:torch.flatten(torch.tensor(0))的输出与之前的tensor(0)相比为tensor([0])。它现在返回的不是 0D 张量,而是 1D 张量。
  4. nn.functional.affine_grid:当 align_corners = True 时,更改了 1D 数据上的 2D 仿射变换和 2D 数据上的 3D 仿射变换的行为(即,当空间维度之一具有单位大小时)。以前,沿着一个单位维度的所有网格点被任意认为是在-1,现在它们被认为是在 0(输入图像的中心)。
  5. torch.gels:删除了不推荐使用的运算符,使用torch.lstsq代替。
  6. 使一些迭代器属性私有(例如 num_workers,pin_memory)。
  7. py torch for c++的其他变化..

感谢阅读!

PyViz:简化 Python 中的数据可视化过程。

原文:https://towardsdatascience.com/pyviz-simplifying-the-data-visualisation-process-in-python-1b6d2cb728f1?source=collection_archive---------0-----------------------

PyViz 生态系统概述,使 Python 中的数据可视化更容易使用、学习和更强大。

Photo by Isaac Smith on Unsplash

可视化的目的是洞察力,而不是图片。本·施奈德曼

如果你和数据打交道,那么数据可视化就是你日常工作的一个重要部分。如果您使用 Python 进行分析,您应该会被数据可视化库形式的大量选择所淹没。一些像 Matplotlib 这样的库用于最初的基本探索,但对于显示数据中的复杂关系并不那么有用。有一些可以很好地处理大型数据集,而还有一些主要关注 3D 渲染。事实上,没有一个可视化库可以称得上是最好的。一个比另一个有某些特征,反之亦然。简而言之,有很多选择,不可能学会并尝试所有的选择,或者让它们一起工作。那么我们如何完成我们的工作呢?PyViz 可能有答案

Python 当前的可视化前景

现有的 Python 数据可视化系统似乎是一个混乱的网格。

Source

现在,从所有这些工具中选择最适合我们工作的工具有点棘手和令人困惑。PyViz 试图堵住这种情况。它有助于简化在 web 浏览器中处理小型和大型数据集(从几个点到几十亿)的过程,无论是进行探索性分析、制作简单的基于小部件的工具还是构建功能全面的仪表板

PyViz 生态系统

PyViz 是一个协调的努力,使 Python 中的数据可视化更容易使用、学习和更强大。PyViz 由一组开源 Python 包组成,可以在 web 浏览器中轻松处理大小数据集。PyViz 只是像 EDA 这样简单的东西或者像创建一个支持小部件的仪表板这样复杂的东西的选择。

这是 Python 使用 PyViz 的可视化景观。

source

PyViz 目标

Pyviz 的一些重要目标是:

  • 重点应该放在没有编码的任何大小的数据上
  • 完整的功能和交互性应该可以在浏览器(而不是桌面)中获得
  • 重点应该更多地放在 Python 用户而不是 web 程序员身上。
  • 再次强调,我们应该更多地关注 2D,而不是 3D。
  • 利用 Python 用户已经熟悉的通用 SciPy/PyData 工具。

图书馆

构成 PyViz 的开源有:

  • :用于即时可视化数据的声明性对象,从方便的高级规范构建散景图
  • 【geo views】:可与 HoloViews 对象混合匹配的可视化地理数据
  • 散景:web 浏览器中的交互式绘图,运行 JavaScript 但受 Python 控制
  • 面板 :将许多不同库中的对象组装到一个布局或应用程序中,无论是在 Jupyter 笔记本中还是在独立的可服务仪表板中
  • Datashader :将庞大的数据集快速栅格化为固定大小的图像
  • hvPlot :从你的熊猫、Xarray 或其他数据结构中快速返回交互式全息视图或地理视图对象
  • Param :声明与用户相关的参数,使得在笔记本上下文内外使用小部件变得简单

除此之外,PyViz 核心工具可以与以下库无缝协作。

此外,几乎所有其他绘图库中的对象都可以与 面板 一起使用,包括对这里列出的所有对象的特定支持,以及任何可以生成 HTML、PNG 或 SVG 的对象。 HoloViews 也支持 Plotly 进行 3D 可视化。

资源

PyViz 提供了示例、演示和培训材料,记录了如何解决可视化问题。本教程为解决您自己的可视化问题提供了起点。整个教程材料也存放在他们的 Github 仓库中。

** [## PyViz 教程— PyViz 0.9.13a3 文档

如何用 Python 工具解决可视化问题?

pyviz.org](http://pyviz.org/tutorial/index.html#)**

装置

请咨询pyviz.org获取这些教程中使用的软件安装的完整说明。假设你已经下载并安装了 AnacondaMiniconda ,以下是这些指令的精简版:

**conda create -n pyviz-tutorial python=3.6
conda activate pyviz-tutorial
conda install -c pyviz/label/dev pyviz
pyviz examples
cd pyviz-examples
jupyter notebook**

一旦安装完毕,下面的单元格应该会显示“1.11.0a4”或更高版本:

**import** **holoviews** **as** **hv**
hv.__version__'1.11.0a11'hv.extension('bokeh', 'matplotlib')
#should see the HoloViews, Bokeh, and Matplotlib logos**#Import necessary libraries
import** **pandas**
**import** **datashader**
**import** **dask**
**import** **geoviews**
**import** **bokeh**

如果它没有错误地完成,您的环境应该准备好了。

使用 PyViz 探索数据

在这一节中,我们将看到不同的库如何有效地从数据中获得不同的见解,它们的结合确实有助于以更好的方式分析数据。

资料组

正在使用的数据集与美国各州每 10 万人中记录的麻疹和百日咳病例数有关。数据集预装在 PyViz 教程中。

熊猫的数据探索

在任何数据科学项目中,从熊猫开始探索是很自然的。让我们导入并显示数据集的前几行。

**import** **pandas** **as** **pd**diseases_data = pd.read_csv('../data/diseases.csv.gz')
diseases_data.head()

数字是好的,但图表会让我们对数据中的模式有更好的了解。

使用 Matplotlib 进行数据探索

**%matplotlib inline****diseases_data.plot();**

这个传达的不多。让我们对熊猫进行一些操作,以获得有意义的结果。

**import numpy as np****diseases_by_year = diseases_data[["Year","measles"]].groupby("Year").aggregate(np.sum)****diseases_by_year.plot();**

这更有意义。在这里,我们可以清楚地推断出,在 1970 年左右,发生了一些事情,使麻疹发病率下降到几乎为零。这是事实,因为麻疹疫苗在 1963 年左右被引入美国

使用 HVPlot 和散景进行数据探索

上面的图传达了正确的信息,但没有提供交互性。这是因为它们是静态图,没有 web 浏览器中的平移、悬停或缩放功能。然而,我们可以通过简单地导入 **hvplot**包来实现这种交互功能。

**import hvplot.pandas****diseases_by_year.hvplot()**

该调用返回的内容被称为一个 全息视图 对象(此处为全息视图曲线),其中显示为散景图。Holoviews 图丰富得多,在探索数据时很容易捕捉到您的理解。

让我们看看 HoloViews 还能做些什么:

捕捉情节本身的要点

1963 年对麻疹来说很重要,我们把这一点记录在图表上怎么样。这也将有助于我们比较接种疫苗前后的麻疹病例数。

**import holoviews as hv
vline = hv.VLine(1963).options(color='red')****vaccination_introduced = diseases_by_year.hvplot() * vline * \
    hv.Text(1963, 27000, "Measles Vaccine Introduced", halign='left')****vaccination_introduced**

与其他绘图库不同,Holoviews 对象保留原始数据。例如,可以访问表格格式的原始数据。

**print(vaccination_introduced)
vaccination_introduced.Curve.I.data.head()**

在这里,我们能够使用用于绘制图表的数据。此外,现在很容易以多种不同的方式分解数据。

**measles_agg = diseases_data.groupby(['Year', 'State'])['measles'].sum()
by_state = measles_agg.hvplot('Year', groupby='State', width=500, dynamic=False)****by_state * vline**

为了更好地比较,我们可以将图表并排放置,而不是下拉列表。

**by_state["Alabama"].relabel('Alabama') + by_state["Florida"].relabel('Florida')**

我们也可以改变图的类型,比如说条形图。让我们比较四个州从 1980 年到 1985 年的麻疹模式。

**states = ['New York', 'Alabama', 'California', 'Florida']
measles_agg.loc[1980:1990, states].hvplot.bar('Year', by='State', rot=90)**

从上面的例子中可以明显看出,通过选择全息视图+散景图,我们能够在浏览器中探索数据,具有完全的交互性和最少的代码。

用 PyViz 可视化大型数据集

PyViz 还支持轻松处理非常大的数据集。对于这样的数据集,PyViz 套件的其他成员也参与进来。

为了向您展示这些库在处理大量数据时的能力,让我们使用 NYC taxi 数据集,该数据集包含与多达 1000 万次出租车出行相关的数据。这个数据已经在教程中提供了。

**#Importing the necessary libraries**import dask.dataframe as dd, geoviews as gv, cartopy.crs as crs
from colorcet import fire
from holoviews.operation.datashader import datashade
from geoviews.tile_sources import EsriImagery

Dask 是 Python 中一个灵活的并行计算库。Dask 数据帧是一个大型并行数据帧,由许多较小的 Pandas 数据帧组成,沿索引拆分。这些 Pandas 数据帧可能存在于磁盘上,用于单台机器或集群中许多不同机器上的大内存计算。一个 Dask 数据帧操作触发对组成 Pandas 数据帧的许多操作。

Cartopy 是一个 Python 包,设计用于地理空间数据处理,以生成地图和其他地理空间数据分析。

**topts = dict(width=700, height=600, bgcolor='black', xaxis=None, yaxis=None, show_grid=False)
tiles = EsriImagery.clone(crs=crs.GOOGLE_MERCATOR).options(**topts)****dopts = dict(width=1000, height=600, x_sampling=0.5, y_sampling=0.5)**

读入并绘制数据:

**taxi  = dd.read_parquet('../data/nyc_taxi_wide.parq').persist()
pts   = hv.Points(taxi, ['pickup_x', 'pickup_y'])
trips = datashade(pts, cmap=fire, **dopts)****tiles * trips**

我们还可以添加小部件来控制选择。这既可以在笔记本中完成,也可以在独立的服务器中完成,方法是用.servable()标记可服务对象,然后运行。ipynb 文件或通过散景服务器提取代码到一个单独的。py 文件并做同样的事情:

**import param, panel as pn
from colorcet import palette****class NYCTaxi(param.Parameterized):
    alpha = param.Magnitude(default=0.75, doc="Map tile opacity")
    cmap = param.ObjectSelector('fire', objects=['fire','bgy','bgyw','bmy','gray','kbc'])
    location = param.ObjectSelector(default='dropoff', objects=['dropoff', 'pickup'])** **def make_view(self, **kwargs):
        pts   = hv.Points(taxi, [self.location+'_x', self.location+'_y'])
        trips = datashade(pts, cmap=palette[self.cmap], **dopts)
        return tiles.options(alpha=self.alpha) * trips****explorer = NYCTaxi(name="Taxi explorer")
pn.Row(explorer.param, explorer.make_view).servable()**

出租车探险家

所有运行代码的笔记本可以从这里访问。然而,交互性并没有在 GitHub 上表现出来,但是你仍然可以访问笔记本并在本地运行。

结论

PyViz 工具可以帮助我们用少量的代码创建漂亮的可视化效果。PyViz 工具捆绑在一起构建高性能、可伸缩、灵活和可部署的可视化、应用程序和仪表板,而无需显式使用 JavaScript 或其他 web 技术。本文只是对多用途 PyViz 生态系统的简单介绍。浏览整个教程,了解不同类型数据的复杂性及其用法。

问答:数据科学中的常见问题

原文:https://towardsdatascience.com/q-a-common-questions-in-data-science-7cd7f9d82a8d?source=collection_archive---------19-----------------------

问我们任何事情

回答在“走向数据科学”团队中最常见的一些问题。

Photo by Ian Schneider on Unsplash

介绍

最近,走向数据科学(TDS)推出了一个名为“向我们提问”的新专栏,让 TDS 的读者有机会向团队提出任何有关数据科学的问题。在这篇文章中,我将回答一些到目前为止我们收到的最常见的问题。

人们对数据科学如此感兴趣的一个主要原因是它的各种应用。数据一直是人类历史上非常重要的组成部分,根据过去的经验和提供的信息做出明智的决策对个人或组织都至关重要。

由于这一主题的跨学科性(图 1),数据科学可能既是一个真正令人兴奋的工作领域,也是一个令人望而生畏的起点。这就是为什么在这个栖息地提问可以自然而然的到来。

Figure 1: Data Science in summary. [1]

读者提问

数据科学如何入门?

开始一个新的领域总是出乎意料地让人既兴奋又害怕。幸运的是,在过去的几年中,为了增加公众对数据科学的兴趣,已经创建了许多免费资源。一些例子是:

获得必要的数据科学背景知识后,对于初学者来说,开始实际项目非常重要。如果你正在寻找一些灵感,Kaggle 可能是一个很好的起点。

我如何写一篇伟大的数据科学文章?

一旦你获得了一些数据科学的知识,尝试展示一些你研究过的项目和主题是一个很好的主意。最简单的方法之一是在你自己的个人网站或在线出版物上写文章(以获得更广泛的受众)。如果你对撰写《走向数据科学》感兴趣,你可以在这篇我以前的文章中找到更多信息和技巧。撰写数据科学相关文章的一些主要指导原则是:

  • 使用 GitHub Gists 来共享您的代码。
  • 利用免费的开放数据源。这样,读者测试演练示例将变得更加容易。
  • 利用交互式数据可视化工具提供更多见解。
  • 遵循策展人指南!

确定数据集中哪些变量对响应变量影响最大的最佳选择是什么?

了解哪些特性会在数据分析中带来更多信息是一项至关重要的任务(尤其是在处理大量数据时!).减少数据集中要素数量的一些主要好处是:

  • 精度提高。
  • 过度拟合风险降低。
  • 在训练中加速。
  • 改进的数据可视化。
  • 增加我们模型的可解释性。

为了减少数据集中的要素数量,有两种主要方法:特征选择和特征提取。

  • 特征选择:在特征选择中,我们利用不同的技术,如过滤器/包装器/嵌入式方法,来选择从数据集中保留哪些特征,丢弃哪些特征。
  • 特征提取:在特征提取中,我们通过从现有特征中创建新的特征(然后丢弃原始特征)来减少数据集中的特征数量。这可以通过使用诸如主成分分析(PCA)、局部线性嵌入(LLE)等技术来实现

如果你有兴趣了解更多关于特征选择和特征提取技术的信息,更多信息请点击这里这里

你如何在你的模型中考虑专家知识?

当试图决定将哪些特征输入用于预测任务的机器学习模型时,对正在分析的数据具有良好的背景知识会有很大的帮助。

例如,假设我们有一个数据集,其中包含不同出租车行程的出发、到达时间和行驶距离,我们希望预测每次不同行程的出租车费用。将出发和到达时间直接输入机器学习模型可能不是最好的主意,因为我们必须让 ML 模型来计算这两个特征之间的关系对预测出租车费用是有用的。使用专业知识,我们可以首先尝试计算到达和离开之间的时间差(通过简单地减去这两列),然后将这一新列(与行驶距离一起)输入到我们的模型中。这样,我们的模型更有可能表现得更好。为机器学习分析准备原始特征的技术通常被称为特征工程。

如果您有兴趣了解更多关于不同特征工程技术的信息,更多信息请点击这里

如何入门机器人流程自动化(RPA)?

机器人流程自动化(RPA)是一项正在开发的用于自动化手动任务的技术。RPA 与传统编程的区别在于其图形用户界面(GUI)。RPA 自动化是通过分解用户执行的任务并重复它们来执行的。这项技术可以使基于图形的过程的自动化编程变得更加容易。平均而言,机器人执行同等过程的速度比人快三倍,而且它们能够全年 24 小时不间断地工作。RPA 公司的一些常见例子有 Automation Anywhere、UIPath 和 blueprism [2]。

如果您打算开始使用 RPA,可以在 Windows 上免费下载 ui path Community Edition。使用 UIPath,可以实现复杂的工作流,创建序列和基于流程图的架构。然后,每个序列/流程图可以由许多子活动组成,例如记录机器人要执行的一组动作或筛选和数据采集指令。此外,UIPath 还支持错误处理机制,以防决策情况或不同流程之间出现意外延迟。

如果你想了解更多关于 RPA 的信息,你可以看看我的 GitHub 库里面有一些例子或者这个我以前的文章

联系人

如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

文献学

[1]您需要了解的数据科学概念!迈克尔·巴伯。访问:https://towardsdatascience . com/introduction-to-statistics-e9d 72d 818745

[2] Analytics Insight,Kamalika Some=https://www . Analytics Insight . net/top-10-robotic-process-automation-companies-of-2018/

q 学习

原文:https://towardsdatascience.com/q-learning-54b841f3f9e4?source=collection_archive---------4-----------------------

通过一个简单的基于表的实施介绍学习率、折扣系数和探索

Q-learning 是最流行的强化学习算法之一,与搜索大量论文和文章相比,它更容易通过实现玩具问题来学习。

这是一个使用 Q-learning 表实现的概念的简单介绍。我将设置我们正在做的事情的背景,建立一个玩具游戏来进行实验,定义 Q-learning 算法,提供 101 实现并探索概念——所有这些都在一个任何人都可以跟随的希望很短的帖子中。

问题是

我们需要一种算法来学习(1)一种政策(2),它将告诉我们如何在不同的情况下(5)与环境(4)进行交互(3),以最大化回报(6)。

(1)学习——这意味着我们不应该手工编码任何特定的策略,而是算法应该自己学习。

(2)政策——这是学习的结果。给定一个环境的状态政策会告诉我们如何最好地与之互动,从而最大化回报

(3)互动——这只不过是算法应该建议我们在不同情况下采取的“行动”。

(4)环境——这是算法与之交互的黑盒。这是一场它理应获胜的比赛。这就是我们生活的世界。是宇宙,所有的太阳、星星和其他一切可以影响环境的东西,以及它对所采取的行动的反应。

(5)环境——这些是环境可能处于的不同“状态”。

(6)奖励——这是目标。与环境互动的目的。玩游戏的目的。

如果无人驾驶汽车是问题所在,那么行动就是我们驾驶的方式,比如转向、刹车等等。奖励就是安全到达目的地。道路、车道、其他车辆和人、光线条件、交通规则、路标和其他一切都是环境。在某个时间点拍摄所有这些的快照,这就是环境的状态。

但这不是我们在这个例子中要用的例子。我们要一个简单得多的。

游戏

想象一个有 5 行 5 列的棋盘——图 1 中所有的白色单元。我们可以从任何一个白细胞开始。目标是尽可能少的走几步,到达右下角的绿色单元格(5,5)。我们可以向上、向下、向左或向右走。我们一次只能走一步。我们不能从棋盘上掉下来,也就是说,进入红细胞,如果我们这样做,我们就会死,我们就会输掉比赛。

Fig 1: The Game

让我们手动制定策略

在潜入可以学习一个有效玩这个游戏的算法之前,我们先来运筹帷幄如何手动玩。给定一个起始位置,我们如何决定向哪个方向移动?嗯,我们将朝着我们的目标前进,而不是远离它。

那么我们如何量化这个“走向”和“远离”的概念呢?我们可以从给所有单元分配一个“距离”值开始。离我们的最终状态目标单元格(5,5)最远的单元格是(11) —对角线上的单元格。使用我们可以执行的四个动作(即向上、向下、向左或向右移动),从(11)到(5,5)至少需要 8 个步骤。我们把它的值定为 8。图 2 为每隔一个单元提供了与目标单元的距离的类似注释。

Fig 2: The Game, annotated with distance

但是 Q-learning 和强化学习一般是关于选择一个给我们最大回报的行动。在这里,奖励是距离的倒数——代表我们离目标有多近,而不是我们离目标有多远。此外,在这里发车意味着我们输了,因此应该受到处罚。图 3 进行了这些调整,并提供了与每个单元格相关的奖励(和惩罚)的修订视图。

Fig 3: The Game with rewards and penalties

让我们将图 3 中的内容展开成一个“动作与状态”的表格。这个扩展的“动作对状态”表示就是 Q 学习表。这个表和表中的值是我们的算法应该得到的。

Fig 4: Q-Learning table of Actions vs States

一些细微差别

现在我们已经有了一些奖励的概念,让我们更仔细地看看几个要点。

首先,总报酬的期望值,即 Q 值,实际上是从当前状态开始,在所有可能的连续步骤中总报酬的期望值。而我们上面贴的,其实就是基于那个特定小区距离的奖励,也就是“即时奖励”。我们将在稍后的实现过程中注意到,只有当我们要求算法显式忽略未来奖励时,才会导出图 4 中描绘的值。

碰巧的是,在这个玩具的例子中,迈出回报最大的一步也能获得最大的回报。在其他不那么好玩的例子中,短期回报较低的行动可能会产生长期的最大回报。

为了证明这一点,在我们的玩具示例中,假设我们在(2,2)中,并想象在板的中间有一个障碍物,如图 5 所示。

Fig 5: Actions with lower immediate rewards could still yield max overall rewards

所以实际上,从当前动作将导致的给定的下一个状态,我们必须遍历后续动作和状态的所有可能轨迹,以获得当前动作的真实 Q 值。

第二,我们在图 3 和图 4 中看到的并不是一个完美的奖励系统。以“奖励最大化”为目标,该算法可能会学习在通往目标单元的路上无限或长时间地遍历绿色单元,以积累许多奖励点,而不是最短路径。

但是考虑到这里的目的是使用一个玩具问题来学习概念,我暂时不会太在意这种细微差别,但是理想情况下远离目标应该受到负奖励的惩罚(例如,从 42 移动到 41 不应该得到“3”,这是一个较低的奖励,而是一个更大的惩罚,如-1000)。

该算法

让我们回到我们的目标,定义一个算法来学习“最优策略”,即告诉我们在游戏的当前状态下应该采取什么行动的东西。

图 4 中看到的 Q 学习表将首先被初始化为 0 或某个其它值,并且 Q 学习算法的目标将是学习将被填充到该表中的最佳值,使得在学习结束时,人们可以简单地查看给定状态的表,并且选择具有最大值的动作,这将最大化赢得游戏的机会。

Q-learning 算法通过多次玩游戏来做到这一点,在每场游戏的每一步结束时,我们研究我们获得的奖励,并使用上面的算法来不断更新表格。最终我们会得出一组最优值。下面粘贴的是维基百科来源的 Q-learning 算法的图像,详细说明了我们如何进行这些更新。

Fig 6: Q-Learning algorithm from Wikipedia

在学习期间进行移动之后,给定状态和动作的 Q 值被新值取代。

新值是两部分的和。第一部分是(1-学习率)*旧值。这就是我们保留的旧价值。学习率为 0 意味着不会学到任何新东西。学习率为 1 意味着旧值将被完全丢弃。

第二部分是学习率*(行动的即时回报+最优未来值的贴现估计)。如上所述的学习率决定了将使用多少新的学习值。学习价值是即时回报和最优未来价值的贴现估计值之和。折扣系数决定了未来奖励的重要性。当设置为 0 时,我们将只考虑即时奖励,1 将使算法完全接受。

图 6 中还没有提到探索的概念。也许在最初的几次尝试中,算法会发现给定状态的特定行为是有回报的。如果它一直选择最大回报动作,那么它将继续执行相同的动作,不会尝试任何其他动作,也许其他未尝试的动作会有比这更好的回报。

我们通过引入一个探索因子来处理这个问题,该因子将使算法以预定的%的次数选择一个随机动作,如下图 7 所示。

Fig 7: Exploration

实施

这是上面提到的 Q 学习算法的一个非常简单的实现。导入相关包后,“Game”类代表我们的玩具游戏。它有一个简单的“移动”功能,将“方向”作为输入,并根据上述奖励和规则,返回移动的奖励和游戏结束指示符。

接下来,我们定义并初始化 Q 表、学习率、折扣因子和探索因子。我们有一个循环来玩这个游戏很多次。每局游戏进行到结束,每一步都是最大 Q 值动作(1-探索系数)次,否则是随机动作。在每次移动之后,除了终端状态之外,我们按照算法中的描述更新旧的 Q 值。

结果和观察

我特意将学习率设为 1,折扣因子设为 0。这将确保每次移动后初始值的完全替换,并且只考虑即时奖励。如果您还记得前面讨论的第一个细微差别,这个设置应该会产生一个类似于图 4 所示的 Q 表。

Fig 8: The results

另一方面,将贴现因子设置为 1,即当我们考虑所有的最优未来值时,我们开始面临第二个细微差别中描述的问题。也就是说,假设我们没有真正惩罚远离目标单元格的移动,算法倾向于在棋盘中停留更长的时间,以积累更多的奖励,从而产生真正大的 Q 值,如图 9 所示。

Fig 9: Results with discount factor of 1

这里有一个实现可以解决这个问题,如果我们离开目标单元格,它会提供-1000 的奖励。

我还将探索系数更新为 30%,并增加了 10K 训练游戏的数量,以更好地收敛,结果如图 10 所示。

Fig 10: Results with Game penalizing moving away from target

虽然实际值不同,但我们可以看到,早期状态的最大奖励行为与我们在图 8 中看到的相同。后来的国家似乎仍然不完全符合建议(见 51),但这只是一个时间问题(或更多的试验)之前,他们这样做。毕竟,Q-在给定无限时间和部分随机策略的情况下,学习可以为任何有限马尔可夫决策过程识别出最优策略!

希望这不仅为 Q 学习和相关概念提供了一个良好的起点,而且随着这些概念的转移,也为深度 Q 学习和其他一般的强化学习算法提供了一个良好的起点。

问答:机器学习和数据科学黑客马拉松

原文:https://towardsdatascience.com/qa-machine-learning-data-science-hackathons-921985c9e87d?source=collection_archive---------21-----------------------

这是黑客马拉松三部曲的最后一部。第一部分是关于参与此类活动的动机。第二部讲述了组织者的错误及其后果。最后一部分提供了所有剩余问题的答案,这在前两部分中是不合适的。

说说你的第一次黑客马拉松。

我是芬兰 Lappeenranta 技术大学的一名硕士学生,同时还参加了数据分析竞赛。我典型的一天是这样的:早上 8 点起床,在大学里呆上几个小时,参加各种比赛直到午夜。经过 3 个月如此紧张的日程安排,我成功赢得了 MERC-2017 数据分析比赛。因此,我的自信心增强了,所以我偶然发现了即将在莫斯科举行的 SkinHack 2 黑客马拉松。所以,我决定在一天内完成两件事——拜访我的父母,参加我的第一次黑客马拉松。

黑客马拉松有点搞笑。提供了两个数据分析跟踪,具有定义的指标和数据集。两条赛道的奖励金额约为 1.5 万€。第三轨道致力于应用程序的开发,奖励金额为 850€,但它没有任何参与者。因此,组织者说,带有按钮的无功能窗口的创造者可以获得 850€,因为提供的奖励金额应该支付。我没有学会如何创建应用程序(因为我不参加比赛,在这方面我很容易被打败)。但这是一个非常明显的迹象,表明黑客马拉松有很多机会。

组织者说,一个带有按钮的无功能窗口的创造者可以赢得 850€,因为提供的奖励金额应该支付。

然后,我通过单独分析数据来解决这两个问题。我发现了一个数据泄漏,这使我获得了一个理想的分数,但是有泄漏的列在测试数据中不存在,我在事件截止日期前两个小时获得了这些数据(顺便说一下,当时我确实知道训练数据集中的目标列不被认为是泄漏)。我的自由泄漏提交在五个团队中排名第三。为了避免浪费时间,我决定退出比赛,因为与第一场比赛的分数差距很大。

然后,当我用新的思维分析所有发生的事情时,我发现了很多错误(我用笔记本在脑海中滚动发生的事情,并分析错误、它们的原因和可以改变的事情。由于经常玩扑克,我养成了这样的习惯。但是我设法明确地认识到以下事实——黑客马拉松提供了多种价值,我必须实现它。然后我开始监控事件和团体,并继续参与黑客马拉松。

我习惯用笔记本在脑海中滚动发生的事情,并分析错误、它们的原因和可以改变的事情。由于经常玩扑克,我养成了这样的习惯。

为什么你会参与黑客马拉松而不是 Kaggle?

我不喜欢卡格尔。Kaggle 在没有特定参与理由的情况下获得了一定的技能等级后变得不那么有用。我早先参加了它,但是后来我发现了更有趣的活动。

你为什么选择黑客马拉松而不是宠物项目?

我有一个宠物项目的几个想法,我将稍后实现它。

有可能单独在黑客马拉松中获胜吗?如果我没有团队呢?

数据科学黑客马拉松提供了这样一个机会(我设法独自获胜)。至于产品,我不确定,但我认为也有可能。不幸的是,有时组织者会设定最低参赛人数。我猜原因是孤独者未能进入决赛(即他们一旦遇到第一个困难就离开比赛),而团队参与则表现出更好的结果。此外,这样的事件意味着更进一步的项目开发,这在团队中更容易执行。

总的来说,我基于经验的建议是始终参与一个团队。活动组织者将帮助寻找或创建一个团队,如果你失败了。

你觉得这些活动怎么样?

我使用的主要来源是 hackathon.com(世界)和俄罗斯黑客(俄罗斯联邦)。对了,不是真正黑客的聊天。此外,活动公告也可以在社交网络(脸书、VK、LinkedIn)的广告中看到。关于即将举行的活动的信息也可以在这里找到:mlh.io,devpost.com,hackevents.co,hackalist.org,HackathonsNear.me,hackathon.io

参与前是否准备了一定的计划?例如,你会在黑客马拉松前一周考虑找一些专家吗?

我为产品黑客马拉松做准备。几周前,我想出了我的后续行动的想法,并找到了所需的专家,如果有的话,并组成我的朋友或过去的黑客马拉松成员团队一起参与。

你如何应对黑客马拉松中的疲劳?

通常提供 2 天工作时间,即 48 小时(30–48 小时,为简化计算,我们取 48 小时)。规定的睡眠时间是 16-20 小时,所以只有 30 小时可以工作。实际工作(即深度工作)的最大时间约为 8 小时。如果能够合理地组织自己的工作过程,你可以将这个数字增加到 12-14(适当的睡眠和食物,呼吸新鲜空气,进行体育锻炼,与团队进行正确的交流,转换活动,正念)。在 hackathon 完成这样的工作后,你会感到筋疲力尽,但这是一种愉快的疲劳。不睡觉和充满干扰的编码肯定会导致失败,不满足和之后的坏心情。

在 hackathon 完成这样的工作后,你会感到筋疲力尽,但这是一种愉快的疲劳。

你有现成的黑客马拉松管道吗?你是如何设法创造它们的,它们是如何组织的(你有吗?将文件复制到单独的文件夹中,每个文件夹用于特定的任务,等等。)以及如何开始他们的创作?

我不使用完全现成的解决方案,这些方案可以从过去的黑客马拉松中获得。相反,我从过去的比赛中获得了自己的模型和管道列表。因此,我不必从头开始重新开发标准部分(例如,正确的目标编码或简单的神经网络来从文本中提取意图),这将节省大量时间。

现在它看起来是这样的:我在 GitHub 上有一个单独的私人回购,用于存储关于正在发生的事情的笔记本、脚本和小文档。此外,我已经为所有装箱的特性准备了一个单独的 repo(比如带有交叉验证的正确目标编码)。我不认为这是最好的解决方案,但目前为止它适合我。

我的建议是从将所有自己的代码保存在文件夹中以及创建简短的文档开始(为什么、什么、操作方式和结果)。

有可能在这么短的时间内从零开始建立 MVP 或者所有参与者都有现成的解决方案吗?

至于数据科学相关的项目——是的,有可能。至于 MVP,我觉得取决于两个因素:

●定位为产品的可行想法(即提供商业画布)。需要提供产品开发的原因和目标受众。有时,没有原型但基础良好的项目会获奖。不幸的是,许多参与者未能应对失败,并指责活动组织者自己的失败,同时在接下来的黑客马拉松中继续毫无意义的产品创作。

●提供某些指标,确认您是否可以创建产品(演示应用程序、代码、详细的渠道描述)。

所以,如果你能合理安排时间,这也是有可能的。有时团队带着现成的解决方案来参加黑客马拉松,试图让它适应组织者的任务。这样的团队在技术筛选中失败了,或者只是在黑客马拉松中实现的解决方案的一部分被考虑在内。我还没有看到这样的团队成功获胜的案例,但我想他们为了获得未来的价值(某些联系、数据集等)而参观这样的活动仍然是有益的。)。

不幸的是,许多参与者未能应对失败,并指责活动组织者自己的失败,同时在接下来的黑客马拉松中继续毫无意义的产品创作。

是否有一些将黑客马拉松项目投入生产或启动的例子?

是的。我参与了三个这样的案例。一次是我自己完成的,两次是别人完成的,基于想法和代码,都是在黑客马拉松中创建的。此外,我知道有几个团队作为顾问继续与该公司合作。我不知道最终的结果,但最有可能的是一些事情已经完全完成。我自己没有组织过创业公司,尽管我肯定有很多这样的例子。

如果你能回到过去并改变一些事情,你会给曾经参加过黑客马拉松的人提供什么建议?

●战术最重要。确保将每个解决方案作为完整的产品提供。如果有支付能力的目标受众不在场,创意、Jupyter 笔记本或算法都没有用。

●回答为什么?而不是什么?以及“怎么做?”在开始做某事之前。

●与团队一起参与。

黑客马拉松中最常见的食物是什么?

通常,黑客马拉松提供糟糕的一餐,即披萨、能量饮料、苏打水。几乎所有的食物都是以自助餐的形式提供的,所以总是要排很长的队。通常,晚上不提供这顿饭。虽然有一次在巴黎举行的比赛期间,晚上给我们提供了一顿饭,即薯条、甜甜圈和一杯可乐。所以,我来介绍一下组织者的心路历程:那么,程序员以前都是吃什么的?哦,对了!薯条、油炸圈饼——就这些。让我们给他们那些垃圾食物。第二天我问活动组织者是否可以提供其他东西,比如粥。但是他们没有回答,只是看着我,好像我很傻,问了这么愚蠢的问题。

那么,程序员以前都吃什么?哦,对了!薯条、油炸圈饼——就这些。让我们给他们那些垃圾食物

组织良好的黑客马拉松提供树食盒类型,即常规,素食和犹太餐。此外,他们还在冰箱里放了酸奶和麦片,供那些想在一天中吃一点的人使用。茶、咖啡和水是标准配置。对我来说,最好的例子之一是 Hack Moscow 2,它在 1C office 的餐厅为参与者提供罗宋汤和肉丸(俄罗斯灵魂食物)。

黑客马拉松的组织水平是否取决于组织者的专业领域(例如,最好的黑客马拉松是否真的是由顾问提供的)?

最好的黑客马拉松是由那些以前组织过或参加过的人组织的。也许,这是事件质量所依赖的唯一因素。

如何意识到是时候开始参加黑客马拉松了?

参观黑客马拉松的最佳时间是一年前。第二好的时间就是现在。所以,现在就开始参与吧。不要害怕:犯错并不断学习。即使是人类继轮子和爬树后最伟大的发明——神经网络,也无法在训练的第一阶段区分猫和狗。

参观黑客马拉松的最佳时间是一年前。第二好的时间就是现在。

哪些指标证实该事件不值得参与?

更清晰的任务描述(与产品黑客马拉松相关)。如果在注册期间会给你一个明确的任务,你最好呆在家里。对我来说,我想不出任何一个好的黑客马拉松能在开始前提供规范。例如,好的黑客马拉松要求做一些与音频对话分析相关的事情,而坏的黑客马拉松要求开发一个应用程序,能够为每个人将对话分成两个独立的音频轨道。

小奖池。如果被要求用人工智能为在线商店创建一个火绒,并且提供的第一名奖励仅为 500 欧元,而最小团队成员数量为 5 人,请确保避免浪费时间(是的,这是去年在慕尼黑举行的一次真实的黑客马拉松)。

缺少数据(与数据科学黑客马拉松相关)。组织者通常提供基本的活动数据,有时也提供数据集样本。如果他们没有提供,在活动开始前询问。

新活动主办方。一定要在活动开始前谷歌一下黑客马拉松的组织者。如果他们第一次组织这种类型的活动,很可能会出问题。但如果组织者和评审团成员已经举办过黑客马拉松,或者过去积极参与过,这是一个好迹象。

在一次黑客马拉松中,有人告诉我:你提供了最好的分数解决方案,但对我们来说,团队合作很重要。不幸的是,你独自工作。例如,如果你和某个学生或女孩一起参加,你可能会赢。你遇到过这样的不公吗?你是如何应对的?

是的,我见过不止一次。我以坚忍的态度对待发生的一切:我做了力所能及的一切。如果没有成功,那就随它去吧。

你为什么从事黑客马拉松?

一切都只是出于无聊。

Qrash 课程:10 分钟强化学习 101 和深度 Q 网络

原文:https://towardsdatascience.com/qrash-course-deep-q-networks-from-the-ground-up-1bbda41d3677?source=collection_archive---------2-----------------------

从头开始学习强化学习和深度 Q 网络的基础知识

这篇博文现在也有韩语版本,请在 jeinalog.tistory.com上阅读

Qrash 课程系列:

  1. 1 部分:强化学习和 Q 学习简介
  2. 第二部分: 政策梯度和优评

本文假设没有强化学习的先验知识,但是假设对神经网络有一些基本的了解。

在所有不同类型的机器学习领域中,最让我着迷的是强化学习。对于那些不太熟悉它的人来说,监督学习处理基于标记数据的预测值或类,而非监督学习处理聚类和在未标记数据中寻找关系,强化学习处理一些任意存在(正式称为“代理”)在给定环境中应该如何行动和表现。其方式是根据代理在不同场景下的表现给予奖励或惩罚。

我学到的第一个实用的强化学习方法是深度 Q 网络,我相信这是这个旅程的一个很好的开端。所以请允许我带你走一遍我尝试学习 RL 时走过的路——包括一个“Hello World”练习,它对我的帮助比我能解释的还要多。

定义世界

强化学习任务是关于训练一个代理与其环境互动。通过执行动作,代理在环境的不同场景之间转换,称为状态。反过来,行动会产生回报,回报可能是正的、负的或零。代理的唯一目的是最大化它在中收集的总奖励,这是在初始状态和结束状态之间发生的所有事情。因此,我们通过提供正奖励来加强代理执行某些行为,并通过提供负奖励来远离他人。这就是一个代理如何学习制定一个策略,或者一个政策

以超级马里奥为例:马里奥是与世界(环境)交互的智能体。状态就是我们在屏幕上看到的,一集就是一个关卡:初始状态是关卡如何开始的,终结状态是关卡如何结束的,是我们完成了还是在尝试中灭亡了。动作有前进、后退、跳跃等。奖励取决于行动的结果:当马里奥收集硬币或奖金时,它会收到正奖励,当它倒下或被敌人击中时,它会收到负奖励。当马里奥只是四处好奇时,它得到的奖励是零,仿佛在说“你没做什么特别的事”。

In a Super Mario game, Mario is the Agent interacting with the world — the Environment

但这里有一个问题:为了能够收集奖励,需要采取一些“非特殊”的行动——你必须走向硬币,然后才能收集它们。因此,代理人必须学会如何处理延迟奖励,学会将这些与真正导致它们的行为联系起来。在我看来,这是强化学习最迷人的地方。

马尔可夫决策过程

代理所处的每个状态都是前一个状态和所选动作的直接结果。前一个状态也是前一个状态的直接结果,如此类推,直到我们到达初始状态。这些步骤中的每一步,以及它们的顺序,都保存着关于当前状态的信息——因此对代理下一步应该选择哪个动作有直接的影响。但是这里有一个明显的问题:我们走得越远,代理在每一步需要保存和处理的信息就越多。这很容易达到执行计算根本不可行的程度。

为了解决这个问题,我们假设所有状态都是马尔可夫状态;也就是说——我们假设任何状态都只依赖于它之前的状态,以及从那个状态到当前状态的转换(执行的动作和给予的奖励)。让我们来看一个例子,看看这两个井字游戏:

两个游戏都达到了同样的境界,只是方式不同。尽管如此,在这两种情况下,蓝色玩家必须捕获右上角的单元格,否则他将失败。为了确定这是最后一个状态,我们只需要这个,不需要别的。

重要的是要记住,当使用马尔可夫假设时,数据就是丢失——在复杂的游戏中,如国际象棋或围棋,走法的顺序可能会有一些关于对手策略或思维方式的隐含信息。尽管如此,当试图计算长期战略时,马尔可夫状态假设是基本的。

贝尔曼方程

让我们继续发展我们的第一个策略。考虑最简单的情况:假设我们已经知道每一步的每一个行动的预期回报是什么。在这种情况下,我们将如何选择行动?很简单——我们将选择最终会产生最高回报的行动顺序。我们将获得的这种累积奖励通常被称为 Q 值(质量值的缩写),我们可以用数学方法将我们的策略形式化为:

The Bellman Equation

上面的等式表明,从处于状态 s 并选择动作 a 产生的 Q 值是收到的即时奖励r(s,a) ,加上状态s’可能的最高 Q 值(这是我们在从状态 s 采取动作 a 之后的状态)。通过选择最大化 Q 值的动作,我们将从s’获得最高的 Q 值。我们还引入了 γ,通常被称为贴现因子,它控制着长期回报相对于眼前回报的重要性。

这个方程被称为贝尔曼方程,它的维基百科页面提供了对其数学推导的全面解释。这个优雅的等式非常强大,对我们非常有用,因为它有两个重要的特征:

  1. 虽然我们仍然保留马尔可夫状态假设,但是贝尔曼方程的递归性质允许来自未来状态的回报传播到遥远的过去状态。
  2. 当我们开始的时候,没有必要知道什么是真正的 Q 值;由于它是递归的,我们可以猜测一些东西,它最终会收敛到真实值。

q 学习

我们现在有了一个基本策略——在任何给定的状态下,执行最终会产生最高累积回报的行动。像这样的算法被称为贪婪,原因很明显。

我们如何实现这一点来解决现实生活中的挑战?一种方法是画一个表来存储所有可能的状态-动作组合,并用它来保存 Q 值。然后,我们可以使用贝尔曼方程作为更新规则来更新它:

Q Learning update rule. The “:=” notation is used here to explicitly mark assignment rather than equality.

让我们看一个例子:

Q Learning table update demonstration

现在记住有些状态是终态。当代理达到 1 时,没有动作或状态转换是可能的。所以,如果未来状态s’是一个终态,我们就剩下:

Q Learning update rule for terminal state s’

还没有完成——我们的贪婪算法有一个严重的问题:如果你一直选择同样的最佳行动,你将永远不会尝试任何新的东西,并且你可能会错过一个更有回报的方法,仅仅因为你从来没有尝试过它。

为了解决这个问题,我们使用一种ε-贪婪方法:对于一些 0 < ε < 1我们选择概率为 p = 1贪婪动作,或者概率为 p = ε的随机动作。因此,我们给代理一个机会去探索新的机会。**

这种算法被称为 Q 学习(或 Q 表)。恭喜你!你刚刚学会了你的第一个强化学习算法!

深度 Q 网络

你可能会问自己 Q 学习是如何扩展的——如果你没有,让我们一起来问:当状态和动作的数量变得非常大时会发生什么?这实际上并不罕见——即使是像井字游戏这样的简单游戏也有数百种不同的状态(尝试计算这一点),不要忘记我们将这个数字乘以 9,这是可能的操作数。那么我们将如何解决真正复杂的问题呢?

进入深度学习!我们把 Q 学习和深度学习结合起来,产生了深度 Q 网络。这个想法很简单:我们将用一个试图逼近 Q 值的神经网络来代替 Q 学习表。通常称为逼近器逼近函数,记为 Q(s,a;θ ,其中 θ 表示网络的可训练权值。

现在只有使用贝尔曼方程作为成本函数才有意义——但是我们到底要最小化什么呢?让我们再来看一看:

“=”符号表示赋值,但是有没有条件也满足一个等式?是的,当 Q 值达到收敛的最终值时。这正是我们的目标——因此我们可以最小化左侧和右侧之间的差异——还有,viola!我们的成本函数:

DQN cost function

这看起来眼熟吗?大概——是均方误差函数,其中当前 Q 值是预测( y ),当下和未来的回报是目标(y’):

Mean square error function

这就是为什么 Q(s),a;θ 通常被称为 Q 目标

继续:训练。在强化学习中,训练集是在我们进行的过程中创建的;我们要求代理使用当前网络尝试并选择最佳行动——我们记录下状态行动奖励以及它结束时的下一个状态。我们决定一个批量大小 b ,每次 b 记录新记录后,我们随机选择 b 记录(!!)从记忆中,训练网络。使用的内存缓冲区通常被称为体验回放。这种内存有几种类型——一种非常常见的是循环内存缓冲区。这确保代理保持对其新行为的训练,而不是可能不再相关的事情。

事情越来越真实,所以让我们谈谈架构:如果模仿一张桌子,网络应该接收状态和动作作为输入,并应该输出 Q 值:

虽然这是正确的,但从技术角度来看,这种架构是非常低效的。请注意,成本函数需要最大未来 Q 值,因此我们需要多次网络预测来进行单次成本计算。因此,我们可以使用以下架构:

这里,我们仅向网络提供状态 s 作为输入,并同时接收所有可能动作的 Q 值。好多了。

嗯,你知道吗——差不多就是这样。再次恭喜!你刚刚学会了如何设计一个深度 Q 网络!

奖励—双重深度 Q 学习

在我们结束之前,这里有一些额外的东西:几段前我们比较了深度 Q 网络成本函数和均方误差。但是 MSE 将预测 y 与真实标签y’—进行比较,并且真实标签在整个训练过程中保持不变。显然,在深度 Q 网络中不是这种情况:网络本身预测了 yy’,因此可能在每次迭代中变化。影响显而易见。

介绍:双深 Q 网络,训练时使用半常数标签。怎么会?我们保留了 Q 网络的两个副本,但是只有一个被更新——另一个保持不变。不过,每隔一段时间,我们会用经过训练的 Q 网络的副本来替换常数网络,因此我们称之为“半常数”。所以:

DDQN cost function

这里, ϑ 表示半常数权重,所以q(s’,a;ϑ)* 表示由半常数网络预测的 q 值。就这样,你做到了。*

你好世界!

我个人认为掌握新概念的最好方法是自己尝试去实现它们。为了尝试 Q 学习和深度 Q 网络,我编了一个简单的游戏:一个有 4 个槽的棋盘,要由代理来填充。当代理选择一个空位置时,它将获得+1 的奖励,并且该位置将被填满。如果它选择了一个非空的位置,它将获得-1 的奖励。当整个棋盘填满时,游戏结束。

试一试,尝试使用这两种方法实现一个学习掌握这个游戏的代理。你可以在这里找到我的尝试。

祝你好运,今天是第三次——祝贺你!

准备好自己尝试一些强化学习了吗?下面是我写的另一篇博文*,里面有一些实用的技巧。***

Qrash 课程 II:12 分钟内从 Q-学习到梯度政策&行动者-批评家

原文:https://towardsdatascience.com/qrash-course-ii-from-q-learning-to-gradient-policy-actor-critic-in-12-minutes-8e8b47129c8c?source=collection_archive---------3-----------------------

朝着真正理解强化学习的基础又迈进了一步

本帖讨论的所有算法的实现都可以在 我的 GitHub 页面 找到。

使用此 好友链接 即使不是普通会员也可以阅读这篇博文

Qrash 课程系列:

  1. 第一部分: 强化学习和 Q-Learning 简介
  2. 第二部分:政策梯度和行动者-批评家

之前——也是第一个——Qrash 课程帖子带我们从对强化学习一无所知一路走到完全理解 RL 最基础的算法之一: Q 学习,以及它的深度学习版本 Deep Q-Network 。继续我们的旅程,再介绍两个算法:渐变策略演员-评论家。这两个人,加上 DQN,可能是现代深度强化学习最基本的组成部分。

为什么 Q-Learning 不够用?

我们可能应该问自己的第一个问题是为什么我们应该从 Q-Learning 前进?它在哪里失败或表现不佳?这个算法确实有一些缺陷,理解它们很重要:

  1. 在大量操作中表现不佳:让我们假设一个操作数量很大的环境。非常大,比如几千,甚至更多。使用ε-贪婪策略探索所有可能的动作可能会花费太长时间,并且该算法很容易收敛到局部最大值,而不是真正的最佳可能解决方案。不太好。
  2. 动作集合必须是有限的:让我们把可能动作的数量拉伸到它的绝对极限:无限。这实际上很常见——想象一下一辆自动驾驶汽车,它的动作是转动方向盘的程度。这是一个连续的数字范围,因此是无限的。很明显为什么 Q 学习算法不能处理这种情况。
  3. 糟糕的探索策略:我们来举个例子——假设一个环境中有 10 种不同的行动是可能的,一个 Q-学习代理使用一个ε-贪婪策略,其中 ε = 0.1。现在让我们假设行动#1 是在这个给定时刻具有最高 Q 值的行动。这意味着代理人有 91%的机会选择行动#1 (90%的机会选择贪婪行动+ 1%的机会随机选择这个行动),而所有其他行动只有 1%的机会被选中。现在考虑这些 q 值: Q(s,a ) = 3.01,Q(s,a ) = 3.00,…,Q(s,a ⁰) = 0.03。 尽管行动#1 和#2 的 Q 值非常接近,但选择#1 而不是#2 的机会要大得多,正如刚才解释的那样。更糟糕的是,选择行动#2 和#10 的几率是完全一样的,尽管行动#2 实际上是百倍(!!)更好。现在结合第 1 节中的问题,您可以看到为什么在这种情况下这可能不是最好的算法。

我们应该如何处理这些情况?让我们来认识一下我们的救世主吧!

政策梯度

Q 学习算法通过试图找到每个状态的动作值函数—Q 值函数来学习。它的整个学习过程是基于计算出每个可能动作的质量的思想,并根据这些知识进行选择。因此,Q-Learning 试图对所有可能的动作有完整和公正的了解——这也是它最大的缺点,因为这需要对每个可能的状态和动作进行足够次数的尝试。策略梯度算法以更稳健的方式学习,通过而不是尝试评估每个动作的——而是简单地评估它应该偏好哪个动作。

让我更好地说明一下:每个模型最终都有一些它试图优化的学习参数(这些通常是神经网络的权重)。让我们将这些参数表示为 θ 。在 DQN,学习周期是:

这意味着训练过程优化了网络的学习参数,然后用于计算 Q 值。然后,我们使用这些 Q 值来决定我们的策略π(其中策略就是每个行动被选择的概率),DQN 的ε-贪婪策略取决于预测的 Q 值,因为它给具有最高 Q 值的行动最高的概率:

Policy of a Deep Q-Learning algorithm

策略梯度算法的学习周期更短,跳过了 Q 值部分:

这意味着网络将直接输出选择每个动作的概率,跳过额外的计算。这将允许该算法更加鲁棒。

我们现在剩下一个非常重要的问题— 我们如何优化网络的权重?在 DQN,事情很简单:我们知道如何计算 Q 值,因此我们可以根据它们优化算法。但是我们现在做什么?我们的主要目标是确保模型在每个学习阶段后变得更好。让我们试着把这写成在每个时间步 t 的权重的一个非常通用的更新规则:

在这里,我们将 J 定义为一些性能度量,我们稍后会讲到,而 α 是学习率。我想花一点时间来澄清时间步长 ts 之间的区别,时间步长 t 表示一集的s状态状态由环境定义,例如——所有可能的棋盘。步骤由代理定义,并标记它所经历的状态序列。这意味着步骤 t=3t=7 可能是相同的状态 s ,因为一些环境允许代理多次返回完全相同的状态。另一方面,每集每一步只出现一次。步骤是按时间顺序排列的时间顺序

让我们回到我们的更新规则,我们将它定义为依赖于新的 J 参数的梯度。虽然它可能对神经网络训练的反向传播阶段很熟悉,但这里有一个非常重要的区别:在梯度策略中,我们希望提高的性能,因此我们希望最大化J 的导数,而不是最小化它。这被称为梯度上升— 与反向传播中执行的梯度下降相反。其实也是差不多的逻辑,只是反过来而已。

设计我们的第一个梯度策略算法

在这一点上,很明显我们如何定义 J 将会有所不同,但是这也完全取决于 us 来决定什么是正确的定义。让我们尝试找到一些简单的东西——一些取决于 Q 值的东西(即使算法从来不会计算它)。回想一下,Q 值 Q(s,a) 是从状态 s 开始并在执行动作a之后,代理人应获得的所有奖励的度量,所有奖励的总和似乎是一个相当好的表现度量——毕竟,代理人的唯一目的是增加其收集的总奖励。因此,我们可以使用整个剧集的总累积奖励作为我们的绩效衡量标准:

这是初始状态 s⁰的所有 q 值的总和,乘以选择每个动作的概率。这正是我们期待的一整集的总体回报。现在,某一状态的所有 Q 值乘以它们的概率的总和有了一个名字:它被称为状态的值函数,并被表示为 V(s) 。一个状态的价值函数是从状态 s 到这一集结束的预期回报的度量,而不知道将选择哪个行动。所以我们基本上将初始状态的价值函数定义为我们的性能度量: J = V(s⁰)

现在我们有了 J ,我们需要计算它的梯度。这涉及到一些复杂的数学问题,因为 J 依赖于行动选择的概率p(a)哪个是从策略 π — 中派生出来的,但是π依赖于 J ,因为这是我们如何定义它的。你可以在萨顿·巴尔托的《强化学习导论》中找到完整的数学推导。),第 325–327 页(这里有一个免费网络版)。我在这里跳过它,写下解决方案:

其中 G_t 是从步骤 t 到该集结束的总累积奖励。这意味着我们的 θ 的更新规则是:

对一项政策进行对数运算可能看起来令人生畏或者很奇怪——但这只是我们需要应用的另一个数学函数,仅此而已。

勘探和开发

我想再次强调策略梯度算法的一个重要特性——它直接学习策略。这意味着网络的输入是当前状态 s ,输出是选择每个动作的概率:

那么我们实际上如何选择一个动作呢?我们简单地对动作进行加权采样。这也解决了我们探索的需要——每个行动都有被选中的机会,但不是均等的,因为最好的行动最有可能被选中。

培养

与 Q-Learning 不同,Policy Gradient 算法是一种 on-policy 算法,这意味着它只使用当前活动策略进行的状态-动作转换进行学习。从技术上来说,这意味着没有像 DQN 那样的经验回放记忆。一旦模型被训练,它的 θ 参数会改变,因此它的策略也会改变。这意味着在这次训练之前收集的所有经验必须被丢弃,并且不能再用于训练。所以我们为训练收集的每一条数据都被使用一次,而且只有一次。

梯度政策在起作用

虽然在这一点上一般的想法有望被理解,但是举例总是更好。使用强化学习解决的一个非常受欢迎的任务是车杆问题:一辆可以向左或向右移动的车,需要确保站在它上面的杆不会倒下。这是我对这个挑战的解决方案。你也试着去实现它。

Cart-Pole

演员兼评论家

让我们花一分钟的时间来认识到目前为止我们已经开发了什么:我们现在有一个代理,它学习一个策略,而不需要学习每个动作的实际值。它真正需要的唯一东西是一些性能指标,它将试图最大化——在我们的例子中,我们选择了一整集的总预期回报。

这种方法的好处很简单——不需要访问和尝试每一个可能的状态-动作对,因为代理对它应该做什么产生了某种“直觉”。但是由于代理对其性能度量的绝对依赖性,这带来了一个缺点。让我们考虑一下我们的例子,我们选择了一集的总体回报作为表现:考虑一集采取了一百步。每一步产生+10 的奖励,但是第 47 步产生-100 的奖励。我们选择的绩效衡量标准无法区分这个陷阱,因为它只知道总体回报。这意味着当我们的代理到达第 47 步时,它可能永远不会尝试另一个动作,因为它不会学习任何特定于状态和动作的知识。

我们如何解决这个问题?我们希望有一个智能体,一方面,以类似于梯度策略方法的方式学习策略,尽管另一方面,我们理解特定于状态和特定于动作的知识的重要性,就像 Q 学习方法一样。解决办法?将两者结合在一起。

这种组合方法被称为行动者-批评家,由两个子代理一起学习组成:一个学习应该采取行动的政策(因此被称为行动者),另一个学习每个状态和行动的 Q 值(因此被称为批评家)。然后,我们将 θ 的更新规则改为:

请注意,我们只是用 Q 值替换了总报酬 G ,但是 Q 值现在也是一个学习参数——由第二个子代理学习。这产生了稍微复杂一点的架构:

A schematic view of an Actor-Critic architecture. Dashed lines represent flows only relevant during training, so during inference (prediction) phase, only the Actor is being used

请注意,就像策略梯度一样,行动者-批评者也是基于策略的模型——这再次意味着在每次训练之后,所有以前的训练数据都将被丢弃。

仅此而已。你猜对了!你现在可以尝试自己实现一个演员评论家,或者看看我的实现解决 Acrobot 挑战。

A2C、A3C 和 DDPG

这里我们已经做得差不多了,但是让我们再往前走一步,了解一些对我们的演员评论家代理非常有用的优化。

A2C

回想一下,我们现在在更新规则中使用 Q 值,以便允许代理拥有一些特定于状态-动作的知识。现在让我问你一个问题: Q(s,a)=100 是不是一个好的 Q 值?答案是— 我们不知道。我们不知道,因为我们没有关于其他可能行动的 Q 值的信息。如果所有其他动作产生的 Q 值为 1,那么 100 真的非常好。但是如果所有其他的都产生 10,000,那么 100 实际上是相当糟糕的。这不仅让你困惑,也让模型困惑。如果知道某个动作与休息相比有多好,或者换句话说,采取某个特定动作的优势是什么,将会很有帮助。因此,我们可以用一个动作的优势替换演员-评论家更新规则中的 Q 值,其定义为:

其中 V(s) 是状态的价值函数,我们之前已经讨论过了。学习一个动作的优点要容易得多——积极的 A(s,a) 是好的,消极的是不好的。这种演员-评论家模型的变体被称为优势演员-评论家,缩写为 AAC,或者更常见的是:A2C(这只是一种有趣的写法,有两个 a 和一个 C)。

你可能会注意到 A2C 版本似乎让学习变得更复杂了,因为现在代理需要学习 Q(s,a)V(s) 。但事实并非如此。如果 Q 值是从状态 s 和动作 a 收到的奖励,然后一直持续到该集结束,我们可以这样写:

意思是——一个 Q 值实际上是直接回报 r 和下一个状态的值s’。这意味着我们可以将优势写成:

所以我们实际上只需要学习值函数,并使用它两次——对于状态 s 和下一个状态s’。这个小小的调整实际上使得 A2C 比原来的演员兼评论家更容易实现。你可以在 GitHub 上查看我对 A2C 的实现。

A3C

既然我们可以拥有多个代理,为什么只拥有一个代理?这是 A3C 模型背后的核心思想,它代表异步优势 Actor-criterion。想法很简单:有许多不同的代理,每个代理都在自己的环境副本中玩,但它们都共享相同的策略和参数。每个代理都在自己的时间上更新共享策略(与其他代理异步),这使得学习过程更快、更健壮。

DDPG

DDPG(深度确定性策略梯度)算法的设计考虑了连续动作空间的问题。Actor-criterion 模型的训练阶段非常嘈杂,因为它基于自己的预测进行学习。为了解决这个问题,DDPG 借用了我们钟爱的 DQN 的一些元素:首先,它使用了 Experience Replay 内存,这让它成为了一个脱离政策的模型。其次,它使用了与 Double DQN 模型相同的降噪方法——它使用了 Actor 和 criterion 的两个副本,一个副本经过训练,另一个副本以如下方式缓慢更新:

在这里,线上的网络是训练有素的那一个,而<的< 1 个。详见我对 DDPG 的实现。

结束语

在本教程中,我们扩展了增强学习的基本构造块的知识,在算法库中添加了梯度策略和 Actor-criterion。现代强化学习的规模要大得多,但最终它都依赖于一些类似的理念——现在你已经理解了。好样的。

质量控制图:x-条形图、R-图和过程能力分析

原文:https://towardsdatascience.com/quality-control-charts-x-bar-chart-r-chart-and-process-capability-analysis-96caa9d9233e?source=collection_archive---------3-----------------------

r 代表工业工程师

使用“qcc”R 包创建质量控制图

Image by Analytics Association of the Philippines on LinkedIn

质量控制图

质量控制图是工程师监控一个过程是否在统计控制下的重要工具。它们有助于可视化变化,发现并纠正出现的问题,预测预期的结果范围,并分析特殊或常见原因导致的流程变化模式。质量控制图常用于精益六适马项目和 DMAIC 项目的控制阶段,被认为是过程改进的七个基本质量工具之一。

然而,我们如何确定用于监控过程的正确的质量控制图?以下决策树可用于根据给定数据确定哪一个是要使用的正确质量控制图:

Quality Control Charts Decision Tree

在下面的例子中,当样本量大于 1 小于 11 时,我们将关注连续数据的质量控制图。

x 条形图

x-bar 和 R-chart 是质量控制图,用于根据给定时间内采集的样本监控过程的均值和变异。两个 chats 上的控制限制用于监控流程的平均值和变化。如果一个点超出了控制极限,则表明过程的平均值或变化超出了控制范围;在这一点上,可能怀疑有可分配的原因。在 x 条形图上,y 轴显示的是总体平均值和控制限,而 x 轴显示的是样品组。让我们来看看使用 qcc 包生成 x-bar 图的 R 代码。

x-bar chart R code

x-bar chart example using qcc R package

R 生成的 x 条形图为其解释提供了重要信息,包括样本(组数)、控制限、总体平均值(中间值)标准差(标准偏差),最重要的是,超出控制限的点和违规运行。工程师必须特别注意这些点,以便识别和确定导致过程失控的系统变化的原因。

r 图表

为了将 R 图与 x 条形图一起使用,样本大小 n 必须大于 1 且小于 11。对于更大的样本,必须使用 s 图来监控样本的标准偏差,而不是其范围。在 R 图中,y 轴显示范围平均值和控制限,而 x 轴显示样本组。一旦您创建了一个 x-bar 图表,您将只需要添加以下代码行来生成 R-chart。

R-chart R code

R-chart example using qcc R package

R 生成的 R 图也为其解读提供了重要信息,就像上面生成的 x-bar 图一样。同样,工程师必须特别注意超出控制极限的点和违反运行,以便识别和确定导致过程失控的系统变化的原因。

过程能力分析

过程能力是给定特性的固有过程可变性的统计度量。换句话说,过程满足给定规范(如客户要求、工程公差或其他规范)的能力。

使用 R 生成 x-bar 和 R-charts 后,您只需添加以下代码行,指定控制下限、控制上限和目标。完成后,添加下面的最后一行代码来生成流程能力总结图表。

Process Capability Analysis R code

Process Capability Analysis using qcc R package

上面的过程能力分析总结图为工程师解释满足给定规范的过程能力提供了重要的信息和能力估计。有兴趣进一步了解这种能力评估的含义吗?点击此处进入 ASQ(美国质量协会)网站。

总结想法

我们已经经历了 Rqcc 封装必须提供的众多工业工程应用之一。您可能已经注意到,只需几行代码,我们就能构建质量控制图,并获得重要信息,用于精益六适马和 DMAIC 项目的流程改进。我再一次邀请你继续发现作为一名工业工程师,你可以使用 R 完成的令人惊奇的事情。

— —

如果你觉得这篇文章有用,欢迎在GitHub上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的介质 简介 来探索我以前的文章。感谢阅读。

-罗伯特

质量控制图:x-条形图、s-图和过程能力分析

原文:https://towardsdatascience.com/quality-control-charts-x-bar-chart-s-chart-and-process-capability-analysis-b7dcc30278ae?source=collection_archive---------6-----------------------

r 代表工业工程师

使用“qcc”R 包创建质量控制图

Image by Analytics Association of the Philippines on LinkedIn

质量控制图

质量控制图是工程师监控一个过程是否在统计控制下的重要工具。它们有助于可视化变化,发现并纠正出现的问题,预测预期的结果范围,并分析特殊或常见原因导致的流程变化模式。质量控制图常用于精益六适马项目和 DMAIC 项目的控制阶段,被认为是过程改进的七个基本质量工具之一。

然而,我们如何确定用于监控过程的正确的质量控制图?以下决策树可用于根据给定数据确定哪一个是要使用的正确质量控制图:

Quality Control Charts Decision Tree

在下面的例子中,当样本量大于 10 时,我们将关注连续数据的质量控制图。

x 条形图

x-bar 和 s-chart 是质量控制图,用于根据给定时间内采集的样本监控过程的均值和变异。两个 chats 上的控制限制用于监控流程的平均值和变化。如果一个点超出了控制极限,则表明过程的平均值或变化超出了控制范围;在这一点上,可能怀疑有可分配的原因。在 x 条形图上,y 轴显示的是总体平均值和控制限,而 x 轴显示的是样品组。让我们来看看使用 qcc 包生成 x-bar 图的 R 代码。

x-bar chart R code

x-bar chart example using qcc R package

R 生成的 x 条形图为其解释提供了重要信息,包括样本(组数)、控制限、总体平均值(中间值)标准差(标准偏差),最重要的是,超出控制限的点和违规运行。工程师必须特别注意这些点,以便识别和确定导致过程失控的系统变化的原因。

s 形图

为了将 s 图与 x 条形图一起使用,样本大小 n 必须大于 10。在 s 图中,y 轴显示样本标准差、标准差总体均值和控制限,而 x 轴显示样本组。一旦创建了 x-bar 图,您只需要添加以下代码行来生成 s-chart。

s-chart R code

s-chart example using qcc R package

R 生成的 s 图也为其解读提供了重要信息,就像上面生成的 x 条形图一样。同样,工程师必须特别注意超出控制极限的点和违反运行,以便识别和确定导致过程失控的系统变化的原因。

过程能力分析

过程能力是给定特性的固有过程可变性的统计度量。换句话说,过程满足给定规范(如客户要求、工程公差或其他规范)的能力。

使用 R 生成 x-bar 和 R-charts 后,您只需添加以下代码行,指定控制下限、控制上限和目标。完成后,添加下面的最后一行代码来生成流程能力总结图表。

Process capability analysis R code

Process Capability Analysis using qcc R package

总结想法

我们已经完成了 Rqcc 封装必须提供的众多工业工程应用之一。您可能已经注意到,只需几行代码,我们就能构建质量控制图,并获得重要信息,用于精益六适马和 DMAIC 项目的流程改进。我再一次邀请你继续发现作为一名工业工程师,你可以使用 R 完成的令人惊奇的事情。

— —

如果你觉得这篇文章有用,欢迎在GitHub上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的介质 简介 来探索我以前的文章。感谢阅读。

-罗伯特

利用机器学习进行质量控制

原文:https://towardsdatascience.com/quality-control-with-machine-learning-d7aab7382c1e?source=collection_archive---------14-----------------------

Python 中的工作流、图形表示和有用的人类见解

Photo by Glenn Hansen on Unsplash

质量控制是每个生产系统中的一个重要步骤。许多商业投资旨在加强这一过程,以授予更高性能的产品。在过去的几年里,机器学习解决方案在这项投资计划中发挥了关键作用,因为它们能够轻松适应每一场比赛,并取得了巨大的成绩。

在本文中,我以分类问题的形式提出了一个标准生产单位质量控制的人工智能解决方案。遵循一种非常有趣的方法,我试图实现最佳的性能,给出结果的直观解释,并考虑到有用的人类洞察力

我想强调这个最新的话题,因为人类的洞察力在机器学习中经常被低估!这并不奇怪,他们允许我们达到最好的表现,并采用最聪明的解决方案。

数据集

我从忠实的 UCI 存储库(钢板缺陷数据集)获取了用于分析的数据集。数据描述很差但没关系,因为很容易理解…我们有一个数据集,包含钢板的元信息,如光度、周长、边缘、厚度、面积、钢的类型等(共 27 个自变量)。

我们可以想象管理一个工厂,在生产系统的最后一步加工钢铁,生产钢板,在批发市场销售。我们的目标是最大化生产系统的效率,仅考虑产品的元数据,尝试识别钢板故障的可能类型(总共 7 种)。这样,我们将能够识别生产系统的谬误,并做出相应的反应。

在我们处理的 1941 个样本中,总故障的分布是不平衡的,有利于'其他故障'类:

df = pd.read_csv('./Steel_Plates_Faults.csv')
label = df.Fault
df = df.drop('Fault',axis=1)
label.value_counts().plot.pie(figsize=(6,6))

label distribution

第一个模型

我们很着急,想马上得到一些结果。所以我们收集了所有的数据并进行梯度推进。

X_train, X_test, y_train, y_test = train_test_split(df, label, random_state=42, test_size=0.2)gbc = GradientBoostingClassifier(n_estimators=500)
gbc.fit(X_train, y_train)

我们能够实现 0.807%的整体精度。

cnf_matrix = confusion_matrix(y_test, gbc.predict(X_test))
plot_confusion_matrix(cnf_matrix, classes=np.unique(label), title=”Confusion matrix”)
plt.show()

如果我们画出混淆矩阵,可以看出我们的算法不能很好地分类 Other_faults 类。第一个结果迫使我们放慢脚步,稍微思考一下。

From sklearn documentation

个人认为,调查一个现象最好的方法是制作一个情节。出于这个原因,我把我们用来拟合梯度推进的所有变量都画了出来。为此,我将初始维度(27 个变量)减少到仅 2 个维度来拟合 TSNE。

scaler = StandardScaler()
scaler.fit(X_train.astype('float64'))tsne = TSNE(n_components=2, random_state=42, n_iter=300, perplexity=5)
T = tsne.fit_transform(scaler.transform(df.astype('float64')))plt.figure(figsize=(16,9))
colors = {0:'red', 1:'blue', 2:'green', 3:'pink', 4:'black', 5:'orange', 6:'cyan'}
plt.scatter(T.T[0], T.T[1], c=[colors[i] for i in LabelEncoder().fit_transform(label)])

TSNE on ALL the data at our disposal

这是对我们结果的清晰而漂亮的解释!我们(以及算法)无法将其他错误(粉色点)与剩余的类明确区分开来。这样,来自混淆矩阵的 Other_Faults 的召回值是有意义的。Other_Faults 是一个噪声类,我们必须在分析中考虑这一方面。

要点

Other_Faults 是一个吵闹的班级是什么意思?为了回答这个问题,我们利用臭名昭著且被低估的人类洞察力。

假设人类在今天的生产系统中进行质量检查。如果这些人检查一块表面有明显凸起或污点的钢板,这块钢板很容易贴上标签。但是,如果这些人检查一个表面有凸起和污点的盘子,同时贴上标签,那就不那么容易了!(如有疑问,放在其他 _ 故障)。

这只是一个例子,但就个人而言,它澄清了我们的情况:Other_Faults 类需要小心处理,因为它包含了许多质量检查的未定义情况。

有了这个宝贵的考虑,我们就可以安全前进了!如上所述,我尝试绘制数据集中的所有钢板,考虑所有变量,但不包括属于其他断层的钢板(粉色点)。

tsne = TSNE(n_components=2, random_state=42, n_iter=300, perplexity=5)
T = tsne.fit_transform(scaler.transform(df[label != 'Other_Faults'].astype('float64')))plt.figure(figsize=(16,9))
colors = {0:'red', 1:'blue', 2:'green', 3:'black', 4:'orange', 5:'cyan'}
plt.scatter(T.T[0], T.T[1], c=[colors[i] for i in LabelEncoder().fit_transform(label[label != 'Other_Faults'])])

TSNE on ALL the data without Other_Faults

相当不错!我们已经去除了由其他故障引起的噪声,现在类别被很好地分开了。

第二个模型

在这一点上,我们试图建立一个不考虑 Other_Faults 类的模型。我们如上所述进行梯度增强。

X_train2, y_train2 = X_train[y_train != 'Other_Faults'].copy(), y_train[y_train != 'Other_Faults'].copy()
X_test2, y_test2 = X_test[y_test != 'Other_Faults'].copy(), y_test[y_test != 'Other_Faults'].copy()gbc2 = GradientBoostingClassifier(n_estimators=500)
gbc2.fit(X_train2, y_train2)

现在准确率 0.909%,提高了 10 个百分点。

当然,这是一个好结果,证实了我们推理的正确性,但是第二个模型再现了一个不现实的场景。这样,我们假设 Other_Faults 类不存在,并且所有的错误都很容易区分和标记。通过我们的第一个模型,我们已经证明这不是我们的情况。因此,我们需要一种方法来翻译机器学习语言中的不确定性,这种不确定性出现在人们试图对模糊的钢板进行分类时。

强加一个门槛

我已经对这种不确定性进行了编码,在我们的最终预测中为每一类设定了一个阈值。为了建立这个阈值,我用我们的第二个模型对 Other_Faults 样本进行了预测,并保存了它,保持了每个预测类的分离度(如下所示)。

def predict(feature, model, threshold_map=None): confidence = model.predict_proba(feature).max()
    label = model.predict(feature)[0] if threshold_map and label in threshold_map:
        if confidence >= threshold_map[label]:
            return {"label": label, "confidence": confidence}     

        else:
            return {"label": "OTHERS", "confidence": confidence}

    elif threshold_map == None:
        return {"label": label, "confidence": confidence}

    else:
        print(label, 'not in threshold map') pred_lab = []
pred_conf = []
for row in tqdm.tqdm(X_train[y_train == 'Other_Faults'].values):
    pred = predict([row], gbc2)
    pred_lab.append(pred['label'])
    pred_conf.append(pred['confidence'])other_pred = pd.DataFrame({'label':pred_lab, 'pred':pred_conf})
diz_score = other_pred.groupby('label')['pred'].apply(list).to_dict()plt.figure(figsize=(18,5))
plt.boxplot(diz_score.values(), labels=diz_score.keys())
plt.grid(False); plt.show()

probability scores and associated predicted labels in Other_Faults

接下来,我计算了每个预测类别的移动阈值:我在每个类别(红色方块)中采用了根据分数分布计算的 0.30 个百分点。

threshold_p = {}
for lab in diz_score.keys():
    threshold_p[lab] = np.percentile(diz_score[lab],30)plt.boxplot(list(diz_score.values()), labels=list(diz_score.keys()))
plt.plot(range(1,len(threshold_p.keys())+1), list(threshold_p.values()), 'rs')
plt.show()

thresholds for every probability scores distributions

实际上,我们利用这个阈值来判断钢板是否确实属于给定的失效类别。如果我们的预测低于阈值,我们就没有足够的信心将其分类,因此我们将其标记为 Other_Faults。

采用这种技术,我们能够达到 0.861%的准确度(在没有其它故障的测试数据中)。如果我们将提高阈值,我们将失去精度点,但我们将获得更高的精度,等等。

Red: Accuracy, Blue: Precision

关于 Other_Faults 类,我们假设它是以‘优柔寡断类’的形式存在的,它包含了被模型分类为低置信度的所有样本。同时,如果置信度高于阈值(我们相信这一点),我们假设原始 Other_Faults 类的所有样本都属于模型所指向的类。

最后,如果我们采用调整 Other_Faults 类的大小再次绘制原始数据,我们可以看到噪声减少(粉红色点集中)。

final_pred = []
for row in tqdm.tqdm(X_test2.values):
    final_pred.append(
        predict([row], gbc2,  threshold_map=threshold_p)["label"]
    )tsne = TSNE(n_components=2, random_state=42, n_iter=300, perplexity=5)
T = tsne.fit_transform(scaler.transform(pd.concat([X_train,X_test]).astype('float64')))plt.figure(figsize=(16,9))
colors = {0:'red', 1:'blue', 2:'green', 3:'pink', 4:'black', 5:'orange', 6:'cyan'}
plt.scatter(T.T[0], T.T[1], c=[colors[i] for i in LabelEncoder().fit_transform(other_final_pred)])

TSNE on ALL the data with the threshold

摘要

在这篇文章中,我提出了质量控制中故障分类的工作流程。我收到了一些钢板样本,并开始对它们进行分析,以便对故障进行正确分类。在第一步之后,我注意到数据结构中的一些模糊行为,于是我开始调查… 基于我的人类洞察力,我提出了一个新的问题愿景,我试图解决它,并提出了我个人的解决方案

查看我的 GITHUB 回购

保持联系: Linkedin

质量胜于数量:构建完美的数据科学项目

原文:https://towardsdatascience.com/quality-over-quantity-building-the-perfect-data-science-project-993ccc0b1241?source=collection_archive---------5-----------------------

credit: https://www.housetohouse.com/diamonds-in-the-rough/

在初创公司的行话中,“虚荣指标”是公司为了让世界——有时是自己——相信他们比实际情况做得更好而跟踪的一个数字。

举一个突出的例子,大约八年前,Twitter 宣布每天有 2 亿条推文通过其应用程序发送。这是一个很大的数字,但它并不像看起来那样相关:这些推文的很大一部分是由机器人发送的。此外,对 Twitter 作为一家公司的长期生存能力来说,真正重要的不是每天发送的推文数量;它是每日活跃用户的数量,以及在他们离开网站之前你可以向他们展示的广告数量。

虚荣指标无处不在,当我们为它们优化时,它们真的会阻碍我们,而不是为重要的事情优化。他们让我们团团转,不明白为什么我们的努力没有结果。

现在,我在一家数据科学导师创业公司工作。作为我工作的一部分,我审阅了许多由有抱负的数据科学家整理的 GitHub 投资组合。人们很难忽视一个特别的虚荣指标,许多人似乎以取得实际进展为代价来优化这个指标:他们投资组合中数据科学项目的数量。据我所见,很大一部分有抱负的数据科学家陷入了一个螺旋,即使用像sklearnpandas这样的工具构建越来越多的数据科学项目,每个项目在过去的时间里都只有增量改进。

我想在这里探索的是打破这种恶性循环的方法,通过使用我们从看到几十个学员将他们的项目转化为工作面试并最终转化为工作机会中学到的一些关键经验。

所以,事不宜迟,以下是:一步一步地指导你建立一个伟大的数据科学项目,将带你超越 scikit-learn/pandas 螺旋,并让你尽快获得面试机会。

0.关键项目设计原则

在我们进入细节之前,这里有一些我们发现的一般原则,可以最大化一个项目转化为面试或工作的机会:

  1. 你的项目应该是原创的。
  2. 你的项目应该证明你有尽可能多的相关技能。
  3. 你的项目应该表明你能做的不仅仅是处理数字。
  4. 你的项目应该易于展示。

现在让我们看看这四个原则如何转化为具体的项目特性。

1.从哪里获取数据

决定要使用哪个数据集是设计项目时最关键的步骤之一。

当你这样做的时候,永远记住原则 1 :你的项目应该是原创的。

以分析简历为生的技术主管和招聘人员每天会看到数百份简历,每份都有 3 到 4 个展示项目。你不希望你的简历成为他们今天看到的第 23 份分析泰坦尼克号生存数据集或 MNIST 的简历。作为一条规则,远离流行的数据集,甚至远离“训练轮”数据集,如 MNIST。正如我在之前所讨论的,在简历中引用这些对你的伤害大于帮助。

另外要记住的是原则 2 :你的项目应该展示尽可能多的相关技能。

除非你在一家大公司工作,在那里你的工作是高度专业化的,否则你将在工业中使用的数据很可能是肮脏的。非常脏。设计不良的模式,应该是floatint,T2 值,缺少条目,半缺少条目,缺少列名,等等。等。如果你想让雇主相信你具备在第一天就提高工作效率的所有技能,使用脏数据是一个很好的方法。出于这个原因,我一般建议避免 Kaggle 数据集(通常是预先清理过的)。

那么如果你也不能用 Kaggle 还剩下什么呢?网页抓取。很多很多。

使用像beautifulsoupscrapy这样的库,从网上搜集你需要的数据。要么这样做,要么使用免费的 API 来构建一个别人没有的自定义数据集——并且您必须自己清理和争论。

是的,它比从 scikit-learn 导入虹膜数据集花费的时间更长。但这正是为什么很少有人这么做——也是为什么如果你这么做了,你更有可能被注意到。

2.使用 model.fit()之前要做什么

“训练轮”数据集通常有一两个明显的应用。

例如,泰坦尼克号数据集似乎提出了一个明确的分类问题:很难不想到,你可以做的最明显的事情是试图预测一个给定的人是否会在灾难中幸存。

但行业问题并不总是这样。通常,您会有一堆(肮脏的)数据,您需要弄清楚如何利用这些数据为您的公司创造价值。这就是原则 3 的用武之地:一个理想的项目不仅能证明你能够回答重要的数据科学问题,还能证明你能够提出这些问题。

一般来说,你如何提出好的问题来问?一个好的开始是做数据探索。

散点图、相关矩阵、维度缩减和可视化技术几乎都应该包含在这个步骤中。它们帮助你理解你收集的数据,以便你可以在进入项目的机器学习/预测阶段时想到好的问题,并通过为你提供易于在面试前和面试期间向面试官和招聘人员展示的情节,获得满足原则 4 的额外好处。

人们很容易忽视数据探索的重要性,但它确实是任何优秀数据科学项目中最关键的步骤之一。理想情况下,光是数据探索就能产生一两个令人惊讶的见解——这些见解将成为你在技术面试中讨论的绝佳素材。

3.主要结果

credit: screenshot from https://www.youtube.com/watch?v=BxizdTrItTk

当你决定你希望你的项目的主要产出是什么(即,你希望返回什么样的预测,或者你希望能够得出什么样的结论作为你的项目的主要结果)时,记住原则 4 是很重要的:不管产出是什么,如果它容易炫耀、好玩或者两者兼而有之,那是最好的。

出于这个原因,我建议将您的项目作为一个 web 应用程序向外界公开(使用 Flask 或其他一些基于 Python 的 web 开发框架)。理想情况下,你应该能够在聚会或面试中接近某人,让他们尝试几个输入参数,或摆弄几个旋钮,并向他们返回一些(理想情况下视觉上有吸引力的)结果。

将最终模型部署为 web 应用程序的另一个好处是,如果你还不知道 web 开发的基础知识,它会迫使你学习这些知识(如果你已经知道了,那么它会向雇主证明事实就是如此)。因为大多数面向产品的公司在他们产品的某一点上使用 web dev,如果有必要的话,理解服务器/客户机架构和基本的 web dev 可以帮助您更容易地将您的模型集成到生产环境中。

4.球场

一旦你建立了你的项目,你会想要开始向潜在的雇主推销它。这种推销应该不仅仅是在某人面前闪烁你的手机屏幕,告诉他们玩几个旋钮。

为了让你的项目更吸引人,确保你有一个关于你所做的事情的故事。理想情况下,这个故事应该包括你在数据探索或模型评估阶段获得的一两个意想不到的见解(例如,“事实证明,这个类很难与其他类区分开来,因为[原因]”)。

这对您有所帮助,因为它:

  1. 围绕你的项目编一个更容易(也更有趣)让面试官记住的故事;和
  2. 清楚地表明,你是一个重视弄清数据科学问题的人。

重复

当你向潜在雇主推销你的项目,并向其他数据科学家炫耀时,尽可能多地获得反馈,并迭代你的项目,以增加它的影响。

当你决定根据反馈对项目进行哪些改进时,优先考虑那些涉及学习新技能的事情,优先考虑那些当时最需要的技能。充分发展你的项目,而不是分散你的精力,最终你会拥有全面的技能。

但最重要的是,你会省去为虚荣指标盲目优化的时间,比如你已经完成的项目总数,所以你可以专注于唯一有价值的指标:被聘用。

量化、理解、建模和预测金融时间序列

原文:https://towardsdatascience.com/quantify-understand-model-and-predict-brownian-movements-of-financial-time-series-f8bc6f6191e?source=collection_archive---------9-----------------------

确定时间序列动量的赫斯特指数

动量识别和计量经济学方法

Image by author

准确预测股票价格是一项艰巨的任务。由于内在的复杂行为,不规则的时间行为在股票市场价格中无处不在。在这里,我将展示一个预测模型框架,用三阶段方法预测金融市场的未来回报。

  1. 分形建模和递归分析,并检验有效市场假说以理解时间行为,从而考察自回归特性。
  2. 在 VAR 环境下进行格兰杰因果检验,以探索因果互动结构,并确定预测分析的解释变量。
  3. ML 和 ANN 算法学习内在模式和预测未来运动。

我将使用 2000 -2019 年以来的贵金属(黄金和白银)股票价格、能源股票(原油)价格和 S&P500 指数。目标是估计未来收益以及这些产品与 S&P 指数的关系。

数据预处理和描述性统计:

在做了所有必要的数据净化后,用以前的值填充丢失的值,重命名列,索引日期等。下面是我们可以做进一步分析和调查的输出。数据净化需要花费大量的时间和精力。因此,我将跳过对数据处理过程的解释,而是专注于这里的目标。

if __name__ == "__main__": 
  df = pd.read_excel('brownian data.xlsx', index_col=0)
  # removing unnecessary columns
  df = df.drop(['Date', 'Year', 'NaturalGasPrice'], axis=1) 
  # converting 'DatesAvailable' to datetime
  df['DatesAvailable']= pd.to_datetime(df['DatesAvailable']) 
  # setting 'DatesAvailable' as index column
  df.set_index('DatesAvailable', inplace=True) 
  df1 = pd.read_excel('S&P Futures.xlsx', parse_dates = True,
                      index_col=0)
  DF = df1.loc['20190729':'20000104']
  data = [DF,df] # combining dataframes
  result = pd.concat(data, axis=1)
  # renaming column
  result = result.rename(columns = {"Price": "SPPrice"}) 
  DATA = result.fillna(method ='pad') 
  # filling the missing values with previous ones
  DATA.index.name = 'Date'
  print(DATA.head())

DATA.plot(subplots=True, layout = (2,2),
          figsize = (15,6), sharex = False, grid =True)
plt.tight_layout()
plt.show()

所有系列都采用每日收盘价。这些图显示了 S&P 指数的明显趋势;对于本质上相当随机的商品。视觉上可以假设,没有一个序列是稳定的,商品具有布朗运动。为了便于理解,结果以表格的形式给出。

偏斜度和峰度值证实没有一个序列遵循正态分布。百分位数和标准差表明指数和黄金价格有很大的差距。如果是由随机波动引起的,这一系列中黄金的巨大价差可能会使准确预测变得困难。

Mann-Whitney test

Mann-Whitney U 检验的零假设是数据样本的分布之间没有差异。

Unit root test Original series

检验统计证实没有一个序列符合正态分布。这也是非参数和非平稳序列的指示,并证明了高级 ML 和 DNN 算法用于预测建模练习的部署。然而,如果时间序列遵循布朗运动,我们不会得到一个稳定的结果。所以,检验 RWH(随机漫步假说)是很重要的。

Unit root test 1st order difference

结果表明该序列是一阶平稳的。因此,我将考虑回报序列进行计量经济分析,以评估因果关系的方向。

非线性动力学:

在这里,我们将执行分形建模和递归量化分析(RQA)来检查 RWH,并获得关于时间演化模式的更深入的见解。让我们看看 FD(分形维数),R/S(重标范围),H(赫斯特指数)和 RQA(递归量化分析)。

让我们来了解一下赫斯特指数。赫斯特指数被用来衡量时间序列的长期记忆。赫斯特指数的目标是为我们提供一个标量值,帮助我们识别一个序列是均值回复、随机游走还是趋势。这是一个统计推断。特别是:

  • h< 0:5 — Anti-persistent time-series which roughly translates to mean reverting.
  • H = 0:5 — The time series is random walk and prediction of future based on past data is not possible.
  • H >0:5——持久的时间序列,大致可以解释为趋势。

FD = ln(N)/ln(1/d),N =圈数,D =直径。这个等式显示了圆的数量与直径的关系。对于时间序列,FD 的值介于 1 和 2 之间。布朗运动的 FD 是 1.5。If 1.5 < FD < 2, then a time series is an anti-persistent process, and if 1 < FD < 1.5, then the series is a long memory process (persistent). H is related to FD (FD =2-H) and a characteristic parameter of long-range dependence. In case of H, the value of 0.5 signifies no long-term memory, < 0.5 means anti-persistence and > 0.5 表示该过程是跨时间相关的,并且是持久的。R/S 是 FD 的中心工具,其计算方法是将其平均调整累积离差序列的范围除以时间序列本身的标准离差(1)。它是表征时间序列散度的度量,定义为给定持续时间(T)的均值中心值范围除以该持续时间(2)的标准偏差。

递归量化分析(RQA)可以处理序列中的非平稳性,有助于理解隐藏在金融市场中的复杂动态。

现在,让我们通过计算 REC、DET、TT 和 LAM 等指标来使用量化技术。

计算 H:

if __name__ == "__main__":
  index = DATA[['SPIndex']]
  lag1, lag2  = 2,20
  lags = range(lag1, lag2)
  tau = [sqrt(std(subtract(index[lag:], index[:-lag]))) for lag in lags]
  m = polyfit(log(lags), log(tau), 1)
  hurst = m[0]*2

  gold = DATA[['GoldPrice']]
  lag1, lag2  = 2,20
  lags = range(lag1, lag2)
  tau = [sqrt(std(subtract(gold[lag:], gold[:-lag]))) for lag in lags]
  m = polyfit(log(lags), log(tau), 1)
  hurst = m[0]*2 crude = DATA[['CrudeOilPrice']]
  lag1, lag2  = 2,20
  lags = range(lag1, lag2)
  tau = [sqrt(std(subtract(crude[lag:], crude[:-lag]))) for lag in lags]
  m = polyfit(log(lags), log(tau), 1)
  hurst = m[0]*2 silver = DATA[['SilverPrice']]
  lag1, lag2  = 2,20 
  lags = range(lag1, lag2)
  tau = [sqrt(std(subtract(silver[lag:], silver[:-lag]))) for lag in lags]
  m = polyfit(log(lags), log(tau), 1)
  hurst = m[0]*2print('*'*60)
print( 'hurst (Index), 2-20 lags = ',hurst[0])
print('*'*60)
print( 'hurst (Crude), 2-20 lags = ',hurst[0])
print('*'*60)
print( 'hurst (Gold), 2-20 lags = ',hurst[0])
print('*'*60)
print( 'hurst (Silver), 2-20 lags = ',hurst[0])

np.random.seed(42)
random_changes = 1\. + np.random.randn(5019) / 1000.
DATA.index = np.cumprod(random_changes)
H, c, result = compute_Hc(DATA.SPIndex, kind='price', 
                          simplified=True)plt.rcParams['figure.figsize'] = 10, 5
f, ax = plt.subplots()
_ = ax.plot(result[0], c*result[0]**H)
_ = ax.scatter(result[0], result[1])
_ = ax.set_xscale('log')
_ = ax.set_yscale('log')
_ = ax.set_xlabel('log(time interval)')
_ = ax.set_ylabel('log(R/S ratio)')
print("H={:.3f}, c={:.3f}".format(H,c))

赫斯特指数“H”是每个范围的对数(R/S)与每个范围的对数(大小)的曲线斜率。这里 log(R/S)是因变量或 y 变量,log(size)是自变量或 x 变量。这个值表明我们的数据是持久的。然而,我们正在研究一个小数据集,不能从输出中得出 H 值明显更高的结论,尤其是商品值(0.585),但给定的时间序列具有一定程度的可预测性。RQA 将帮助我们理解可预测性的程度。

计算 RQA:

time_series = TimeSeries(DATA.SPIndex, embedding_dimension=2,
                         time_delay=2)
settings = Settings(time_series, 
                    analysis_type=Classic,                                 
                    neighbourhood=FixedRadius(0.65), 
                    similarity_measure=EuclideanMetric, 
                    theiler_corrector=1)computation = RQAComputation.create(settings,verbose=True)
result = computation.run()
result.min_diagonal_line_length = 2
result.min_vertical_line_length = 2
result.min_white_vertical_line_lelngth = 2
print(result)

在这里,我们看到,所有时间序列的 RR(重复率)值并没有偏高,表明周期性程度较低。DET (S&P,原油和白银)和拉姆值原油,黄金和白银)较高,支持确定性结构。然而,这也证实了高阶确定性混沌的存在。

计量经济学方法:

这里采用了一系列测试程序来探索变量之间的因果相互作用结构,并确定预测分析的解释变量。

皮尔森相关性显示了 S&P 和黄金、原油和黄金、原油和白银以及黄金和白银之间的显著相关性。进行瞬时相位同步(IPA)和格兰杰因果检验。

实证研究表明,即使两个变量之间有很强的相关性,也不能保证因果关系。它不提供关于两个信号之间的方向性的信息,例如哪个信号在前,哪个信号在后。

现在,我将使用格兰杰因果检验来检查因果关系,以确定预测因素。VAR 被认为是进行格兰杰因果关系检验的一种手段。在风险值模型中,每个变量被建模为其自身的过去值和系统中其他变量的过去值的线性组合。我们有 4 个相互影响的时间序列,因此,我们将有一个由 4 个方程组成的系统。

  1. Y1,t = α1 + β11,1Y1,t-1 + β12,1Y2,t-1 + β13,1Y3,t-1 + β14,1Y4,t-1 + ε1,t
  2. Y2,t = α2 + β21,1Y1,t-1 + β22,1Y2,t-1 + β23,1Y3,t-1 + β24,1Y4,t-1 + ε2,t
  3. Y3,t = α3 + β31,1Y1,t-1 + β32,1Y2,t-1 + β33,1Y3,t-1 + β34,1Y4,t-1 + ε3,t
  4. Y4,t = α4 + β41,1Y1,t-1 + β42,1Y2,t-1 + β43,1Y3,t-1 + β44,1Y4,t-1 + ε4,t

这里,Y{1,t-1,Y{2,t-1},Y{3,t-1},Y{4,t-1}分别是时间序列 Y1,Y2,Y3,Y4 的第一滞后。上述方程被称为 VAR (1)模型,因为每个方程都是一阶的,也就是说,它包含每个预测值(Y1、Y2、Y3 和 Y4)的一个滞后。因为方程中的 Y 项是相互关联的,所以 Y 被认为是内生变量,而不是外生预测因子。为了防止结构不稳定的问题,我使用了 VAR 框架,根据 AIC 选择滞后长度。

# make a VAR model
model = VAR(DATA_diff)
model.select_order(12)
x = model.select_order(maxlags=12)
x.summary()

Lag selection (VAR)

滞后 4 时获得的最低 AIC 值。所以,因果关系分析是在此基础上进行的。

A = model.fit(maxlags=4, ic=’aic’) # pass a maximum number of lags and the order criterion to use for order selectionR1=A.test_causality(‘Index’, [‘CrudeOilPrice’, ‘GoldPrice’, ‘SilverPrice’], kind=’f’)R2=A.test_causality(‘CrudeOilPrice’, [‘Index’, ‘GoldPrice’, ‘SilverPrice’], kind=’f’)R3=A.test_causality(‘GoldPrice’, [‘Index’, ‘CrudeOilPrice’, ‘SilverPrice’], kind=’f’)R4=A.test_causality(‘SilverPrice’, [‘Index’, ‘GoldPrice’, ‘CrudeOilPrice’], kind=’f’)R5=A.test_causality(‘Index’, [‘CrudeOilPrice’], kind=’f’)

Granger Casuality test result

从上表中我们可以看出,S&P 指数并没有引起系列中其他股票的价格,但是其他股票的价格对 S&P 指数有显著的影响。因此,这里的因果结构是单向的。

granger_test_result = grangercausalitytests(DATA_diff[[‘Index’, ‘CrudeOilPrice’]].values,maxlag=4)granger_test_result = grangercausalitytests(DATA_diff[[‘Index’, ‘GoldPrice’]].values,maxlag=4)granger_test_result = grangercausalitytests(DATA_diff[[‘Index’, ‘SilverPrice’]].values,maxlag=4)granger_test_result = grangercausalitytests(DATA_diff[[‘CrudeOilPrice’, ‘SilverPrice’]].values,maxlag=4)granger_test_result = grangercausalitytests(DATA_diff[[‘CrudeOilPrice’, ‘GoldPrice’]].values,maxlag=4)granger_test_result = grangercausalitytests(DATA_diff[[‘GoldPrice’, ‘SilverPrice’]].values,maxlag=4)

接下来,估算 IR(脉冲响应),以评估一种资产对另一种资产的冲击影响。

IR 图显示了给定时期内预期的冲击水平,虚线代表 95%的置信区间(低估计值和高估计值)。此外,所有四个系列的回报率的方差百分比在短期内很大程度上可以由它们自己来解释。从短期来看,自身运动的冲击往往会在波动中扮演重要角色。通过格兰杰因果关系发现对其他序列有影响的序列,对方差也有边际影响。因此,因果分析的总体结果通过方差分解的结果得到验证。因果互动的结果有助于理解相互关系的结构。为了进一步证明,预测误差方差分解(FEVD)执行。基本思想是分解方差-协方差矩阵,使σ= PP 1,其中 P 是具有正对角元素的下三角矩阵,通过 Chelsi 分解获得。

Forecast error variance decomposition

FEVD 表示在自动回归中每个变量贡献给其他变量的信息量。它决定了每个变量的预测误差方差中有多少可以用对其他变量的外生冲击来解释。所有三个股票指数的回报率的方差百分比在短期内很大程度上由它们自己来解释。

但是,格兰杰因果关系不一定反映真实的因果关系。因此,为了严谨起见,使用 IPA(瞬时相位同步)从统计上验证了资产之间同步的存在。这里 IPA 用于视觉模式识别。它通过增量移动一个时间序列向量并重复计算两个信号之间的相关性来进行测量。中间的峰值相关性表示两个时间序列在那个时间最同步。带通滤波后通过希尔伯特变换实现的频域变换。

在执行任何相位同步之前,预处理阶段需要对金融数据进行去趋势分析,并去除高频噪声成分。滤波级将 SST 用作带通滤波器(SST 是一种块算法,因此数据首先被加窗),仅应用于去趋势信号的低频振荡。带通滤波的一个重要标准是确保最终信号尽可能窄。

Pearson r 是对全局同步性的度量,它将两个信号之间的关系简化为单个值。然而,我们在这里使用瞬时相位同步测量来计算两个信号之间的瞬时同步,而不像滚动窗口相关那样任意决定窗口大小。

S&P Index & Crude Oil

S&P Index and Gold

S&P Index and Silver

Crude Oil & Gold

Crude Oil & Silver

Gold & Silver

每个图由过滤的时间序列(顶部)、每个时刻每个信号的角度(中间一行)和 IPS 测量值(底部)组成。当两个信号同相排列时,它们的角度差为零。通过信号的希尔伯特变换计算角度。这里,我模拟了一个相位同步的信号。对于每个图,信号 y1 和 y2 都处于 30Hz (30 天)。我在数据中加入了随机噪声,看看它如何改变结果。波动相位同步图表明 IPS 对噪声敏感,并强调了滤波和选择分析频带的重要性。在对波形进行实际处理之前,使用简单的移动平均和带通滤波器来消除信号中的噪声。然而,IPA 产生了一个全球指标。因此,在将信号分解成多分量的过程中,一个关键的标准是确保相关的频率在本地有效。同步的存在和持续时间反映了金融市场的动态。

预测模型

解释性结构的选择是预测建模的关键。一些广泛使用的技术指标是 SMA,MACD 和 CCI 用于趋势,STD 和 BB 用于波动,RSI 和 WR 用于动量。因此,使用原油、黄金和白银作为输入变量的多变量框架对模型进行了测试,这些变量会显著影响 S&P 指数和一系列技术指标,如下所示。

原始数据集被随机分成 85%的训练数据和 15%的验证数据。对 kNN、DT、RF、GBM、SVN 和 DNN 进行了算法搜索,以选择稳健的模型在给定数据集上进行训练。

目标是获得最低的错误,根据这一逻辑,可以看出 GBM/XGB 在训练和测试数据上都显示最低的错误率。这证明了使用 GBM 算法开发给定时间序列的预测模型的合理性。DNN 以其处理连续和大容量数据的能力而闻名。因此,DNN 也被选中开发一个能够处理高速大数据的混合预测模型。

我用五重 CV 技术进行了重型性能调整,以获得两种算法(XGB 和 DNN)的最佳性能。最后使用堆叠集成技术,将两者相结合以获得更好的预测性能。

发现原油和白银的平均均方误差、RMSE 和平均平均误差值较小,表明该模型对所有原油和白银的有效预测能力。这一结果也支持了这样一个事实,即从历史上看,黄金在股市崩盘期间往往具有弹性,两者呈负相关。这里也没有显示高 MSE 值的异常。让我们看看我们的功能是如何优先排序的。

Feature importance-XGB

Feature importance-DNN

这些特征是根据它们的相对强度和重要性顺序绘制的。这意味着几乎所有选择的特征,对模型的建立都有一定程度的重要性。

结论

在这里,我解释了精选股票和 S&P 的主要特征,并随后深入研究了它们之间的因果关系和预测分析。这里解释了一些关键的技术指标。这种预测结构是计量经济学模型和机器学习算法的结合。虽然我用 ML 算法测试过,但是,技术指标也可以用于成功的交易策略。随后必须对验证集进行前滚验证。

接我这里

参考:

(1)曼德尔布罗,B. B .,&沃利斯,J. R. (1969)。分数高斯噪声的计算机实验:第 2 部分,重新标度的范围和光谱。水资源研究,5(1),242–259 页。

(2)赫斯特,H. E .布莱克,r . p .&斯迈卡,Y. M. (1965)。长期储存:康斯特布尔的实验研究。英国伦敦。

量化聊天室毒性

原文:https://towardsdatascience.com/quantifying-chatroom-toxicity-e755dd2f9ccf?source=collection_archive---------22-----------------------

Courtesy of Caspar Camille Rubin on Unsplash

使用机器学习来识别在线聊天室中的仇恨

注意:下面是粗俗语言的例子

在这个项目中使用的代码可以在这里找到

前几天晚上,我参加了由 Twitch (漂亮的办公室和美味的食物!)我和那里的一些软件工程师聊了起来。原来他们是一个“安全”团队,完全致力于保持聊天清洁,保护聊天室中的流媒体和观众,这是有道理的,因为聊天互动可以说是 Twitch 的核心驾驶体验。考虑到这一点,我开始尝试构建自己版本的聊天毒性分类器(在我的好朋友 Randy Macaraeg 的帮助下)。今天,我将带您经历这一过程!

Twitch chat is a core driver of its user experience

第一步是找到一个数据集。幸运的是,我们在 Kaggle 的朋友举办了一场在维基百科上识别有毒评论的比赛,该比赛提供了一个超过 30 万条评论的数据集,人工标记了六个类别的二进制标签,包括有毒、严重有毒、淫秽、威胁、侮辱和身份仇恨。

简而言之,自然语言预处理

一旦我们有了数据,我们需要通过清洗过程。对于一般的文本数据集,这通常包括:

  • 删除标点符号
  • 删除停用词(如“the”、“this”、“what”)
  • 词干化/词尾化(通过删除后缀如“-ed”、“-ing”,将单词简化为基本形式)。

此外,处理在线文本和评论需要进一步删除超链接、用户名和自动消息(该数据集中最常见的评论是维基百科对新用户的欢迎消息)。

您所做的预处理因项目而异,对于这一点,除了词干化和词元化,我们有最好的准确性指标来做上述所有工作,这将 ROC AUC 指标降低了 10%。我们还考虑了 n 元语法,其中除了单个单词之外,您还可以查看成对或三个(或更多)单词,但这也使我们的 ROC AUC 指标下降了 5%,因此我们最终没有使用它。

…向量化…

为了将单词转化为机器学习算法可以理解和处理的东西,我们需要做一些称为矢量化的事情。简而言之,这是将单词转化为多维向量的过程,其方式是将单词的含义或上下文与向量指向的位置相关联。从某种意义上来说,矢量化就是让计算机通过将相似的词义映射到相似的向量空间来量化词义。

词频—逆文档频率矢量化

对于这个应用程序,我们希望快速、基于上下文的矢量化。一些方法,如 Word2Vec 和 spaCy 涉及预先训练的数千兆字节的模型,这些模型在数十万甚至数百万个文档上训练,然后将单词的含义简化为一组数百个数字。一般来说,这些模型在保持单词的上下文和含义方面非常出色,但是它们速度慢且庞大。这就是术语频率逆文档频率矢量化的用武之地(TF-IDF)。这种矢量化方法查看一个单词在注释中出现的次数相对于它在其他注释中出现的次数。两件事导致更高的 TF-IDF 分数:

  1. 该词在被评分的特定评论中出现的频率更高。
  2. 该词在所有其他评论中出现频率较低。

A glance at the highest TF-IDF scores in comments with the toxic label. We can see cursing is highly correlated with the toxicity labels!

建模!

一旦我们将所有的评论转换成 TF-IDF 单词向量集,下一步就是建模。最终目标是在聊天室中实现一种自动调节算法,需要一种快速算法来处理成千上万的同时浏览者相互聊天。为此,我们使用基本的逻辑回归进行分类。实质上,逻辑回归使用你的中学斜率公式:

其中 y 是某事发生的几率(使用 sigmoid 函数在 0 和 1 之间压缩), m 是由于独立变量 x 的变化引起的 y 的单位变化, b 是偏差,或 y 截距。这篇文章对逻辑回归进行了更深入的解释。

所以现在我们有了构建模型的所有要素。此时,我们通过将每个评论输入到 TF-IDF 矢量器来训练我们的模型,该矢量器将该评论转换为 20,000 个特征的矢量(我们希望作为词汇表跟踪的最大字数)。然后,我们将这 20,000 个 TF-IDF 得分特征传递到我们的模型中。为简单起见,我们独立训练六个单独的模型,每个标签一个。这给了我们以下 ROC 评分!

曲线下的受试者工作特征(ROC)面积

Receiver Operating Characteristic (ROC) curves for logistic regression models.

ROC 曲线下的面积告诉我们,如果我们改变概率阈值以获得更多的真阳性,我们会获得多少更多的假阳性。在这个项目的上下文中,假阳性是说一个评论是有毒的,而它实际上不是,真阳性是正确地识别一个有毒的评论。基本上,ROC 曲线下的面积越大,意味着对于额外的真阳性,我们得到的额外假阳性越少,这是我们想要最大化的。

如你所见,我们得到的 AUC 值约为 0.97 到 0.98,非常接近最大值 1。这意味着我们可以庆祝,因为我们的模型在识别真正的阳性方面非常棒!

结论和实施

因此,我们创建了一个模型,该模型接收一条互联网评论,然后给出该评论是否属于六种有毒类别的六种可能性。在一台 2019 款 Macbook Pro 上,分类速度大概是每秒 1150 条消息!还不错。虽然还有一些需要改进的地方,但这是一个很好的审核工具,如果有不怀好意的人在他们的频道上发帖,可以用来提醒版主。

请关注我的下一篇文章,了解我们如何在网上和 twitch 聊天机器人中部署这个模型!

用数据量化政治势头

原文:https://towardsdatascience.com/quantifying-political-momentum-with-data-ef181df072a6?source=collection_archive---------25-----------------------

政治评论员每天都在谈论当前的政治形势,当我在电视上看着这些会说话的人做他们的事情时,我总是一遍又一遍地听到“政治势头”这个词。2016 年大选后尤其如此,2018 年大选后也是如此。但是什么是政治动力呢?共和党人和民主党人都声称在 2016 年大选后拥有它。怎么会有人赢有人输呢?我开始思考量化政治势头的方法;过去的法案、民意调查的支持率以及其他民意调查信息都浮现在脑海中,但所有这些信息的问题是,它们都可能被人们扭曲,而且大多数时候它们只考虑了过去投票的人。在浏览科罗拉多州州务卿的网站时,我偶然发现了选民登记,并认为这是衡量政治势头的一个很好的方式。如果人们喜欢一个政党的信息,他们会改变他们的党派,当新的人登记投票时,他们也可以选择一个党派。这将允许我看到是否有人正在改变他们的党派或注册一个党派。顺便说一句,我收集了我的数据,我不知道是哪一个,但它会让我知道一个政党是否正在通过计算他们的政党规模来获得动力。这将是我量化“政治动力”的方式此外,为了能够尝试更多的数据科学技术,我还试图预测 2018 年的选民登记人数。

旁注——我在几个月前完成了这个项目,但从未写过。原因是,我认为我过去/现在害怕过去三四年中产生的有害政治环境,以及如果我的数据不支持你当时的政治观点,我可能/将要受到的强烈反对。但是你知道吗,我在这里谈论的是数据,而且仅仅是数据。是的,这可能是政治数据,我会提到政党是如何受到影响的,但如果你想写一个回应,因为我的结果不会助长你的政党信仰,或者他们不同意你最喜欢的政治谈话主持人在电视上说的话,去写一篇关于它的长脸书帖子或什么的。我不想听。数据是我的安全空间。但是,如果你真的想谈论或评论数据分析以及如何将数据用于政治目的,第一杯酒我请。抱歉,咆哮了,但是,现在回到定期安排的博客。

我所有的数据都是从科罗拉多州政府的网站上下载的。使用政治数据的一个好处是,大部分政治数据被视为公共信息,可以免费下载。一个你必须支付“行政费用”来获取公共数据的例子是选民登记文件。这显示了该州每个注册选民的信息,由于其规模,对于普通公民来说有点昂贵。非常有趣的文件,如果你曾经得到它。但是,我很幸运,我能够免费下载我的信息。我下载的是选民登记统计 excel 文件。这份档案包含了公布当月登记选民人数的信息。该文件中的一些示例工作表如下:党派和地位、性别、党派和年龄,以及按国会选区、州参议院选区、州众议院选区和选区的细分。我想要的信息是从党和状态表。下面是聚会和状态表的大致样子。

From the All Reports excel file from http://www.sos.state.co.us/pubs/elections/VoterRegNumbers/2016VoterRegNumbers.html#April

我最终下载了 60 个这样的文件。从 2012 年 11 月到 2017 年 10 月,每月一次。听起来很简单,只需编写一个脚本将所有这些文件加载到 python 中可用的格式,但是文件本身存在一些问题。首先,并不是所有的年份都有相同的格式。在 2015 年(2012-2014 年)之前的几年中,没有“Prereg”选民,如上图所示,“UNI”(团结)党被 AEL(美国人选举)党取代,并且在如上图所示的不同位置,它也是 excel 的旧版本。我不知道的是熊猫会读书。xls 和。xlsx 文件不同,而升级文件格式并不难,这是一项繁琐的任务。上面所有的问题都通过使用 excel 解决了,但是我真的希望科罗拉多州的州务卿的网站能对数据更加友好。

为了简化我的分析,我对数据做了一些更改,将所有“Prereg”投票者添加到活跃投票者中。“预登记”选民是那些登记投票但实际年龄还不够大的人。一个例子是,一个 17 岁的人在 18 岁生日之前登记投票,但在下一次选举中可以投票,因为那时他们已经 18 岁了。我无法找到 2015 年之前这些“预登记”选民的统计数据,所以我将他们加入了活跃选民,因为我觉得这有助于了解新的和年轻的选民。我还把除了民主党和共和党之外的所有政党都加入了无党派的行列。这是为了简化我的分析,只需要关注三个变量而不是七个。

首先,我想让自己熟悉这些数据,而最简单的方法就是绘制数据图表。我首先开始查看所有县的注册选民总数,以及所有县的政党的活跃选民。这两个图表都给了我一个我正在处理的所有数据的概览。

https://public.tableau.com/profile/cbjohnson30#!/vizhome/Colorado_Voter_Registration/Total

左边是所有县和政党的登记选民总数。该图中的一些关键兴趣点表明,科罗拉多州在偶数年选举后清理了选民名单。这意味着去除那些已经去世或搬走并且多年没有投票的人。另一个有趣的现象是,偶数年选举前选民登记数量增加,但奇数年选举前不会出现同样的增长。关于这个图表,我想指出的最后一点是,因为它有规律的增加和减少,所以可以肯定地说,这个图表有 2 年或 24 个月的季节性。这对于预测未来的注册人数非常重要。

https://public.tableau.com/profile/cbjohnson30#!/vizhome/Colorado_Voter_Registration/Active

左边是所有县的政党的所有活跃选民的图表。这张图表信息量很大,确实为了解整个科罗拉多州的选民登记率提供了一些很好的见解。我注意到的第一件事是 2013 年所有活跃选民中出现的巨大峰值,但在总选民图表中没有看到。这是因为科罗拉多州众议院法案-1303,创造了选民准入和现代化选举法案,于 7 月生效。这改变了不活跃选民的定义。在这项法案之前,如果你在前两次选举中没有投票,你就成了不活跃的选民。法案通过后,只有 USPS 退回你的选票,你才成为一个不活跃的投票者。如果你收到了你的选票,但由于某种原因没有投票,你仍然被贴上积极选民的标签。活跃选民定义的变化并不影响我的分析,但在预测未来的选民登记人数时却发挥了作用。另一个有趣的地方是初选前后登记人数的变化。在初选之前,大约 6000 名选民将他们的登记状态从无党派改为民主党或共和党,以便他们可以在党内初选中投票。初选结束后,他们又变回原来的样子。幸运的是,这不需要再发生了,因为 2016 年通过了 108 号提案,允许无党派人士在初选中投票。

现在我对我的数据有了更多的了解,是时候做一些深入的分析了。时间序列分析的两种常见形式是移动平均数和与上月的百分比变化。移动平均线在金融预测中很常见,因为它通过平滑图表来帮助减少数据的波动。虽然这在其他时间序列问题中很有用,但我不认为它会帮助我分析这些数据,因为我正在寻找数据中不同的波动点。

与前一个月相比的百分比变化是一个我知道会很有趣的图表,因为这些计算做了两件有趣的事情。第一,它会告诉我某个政党的人数是增加了还是减少了。第二,它会自动将数据标准化,这样我就可以轻松地将不同的政党进行比较。以上是按党派划分的活跃选民的整个数据集与上月相比的百分比变化图。在这个图表中,我最感兴趣的是这些线相互分开的时间。这意味着一个政党以不同于其他两个政党的速度增加或减少其活跃选民数量。我注意到的前两个部分是 2013 年的大幅飙升和初选前后的几个月。这两者在本博客前面都有解释。这个图表加上一个小的补充,可以让我回答我上面提到的关于政治动力的问题。

为了回答我最初的问题,即政治势头是否可以用一个政党的注册选民数量来量化,我使用了上图中与上月相比的百分比变化,以及一些其他特征。这些功能包括将图表限制在奇数年,并给图表添加一个标签,允许我只查看民主党或共和党获胜的县。例如,在 2017 年,我可以查看投票支持唐纳德·特朗普或希拉里·克林顿的县。下面是这两张并排的图表。

首先,看左边的图表,投票给唐纳德·特朗普的县,你可以看到共和党(红色)和民主党(蓝色)的界限明显分开。红线在正数范围内徘徊,从 0.0 到 0.002,这意味着共和党注册选民的数量在这段时间内一直在增长。而注册民主党人的数量几乎总是为负数,这意味着注册民主党人的数量在这段时间内几乎总是在减少。现在,把这个和左边的图表比较一下,那些投票给希拉里·克林顿的县,红色和蓝色的线在 9 月份之前几乎是一起移动的。接下来,看看无关联(紫色)线。对于投票给特朗普的县来说,这条线的斜率比投票给克林顿的县更陡。它也有一个更高的顶点。这意味着,在投票给特朗普的县,登记为无党派的选民比投票给克林顿的县增长得更快。

在 2016 年的选举中,总统竞选被公然认为是选票上最热门的竞选,而在 2014 年,州长竞选被认为是选票上最热门的竞选。在 2014 年鲍勃·博普雷兹(共和党)和约翰·希肯卢珀(民主党)之间的州长竞选中,你也可以看到上面提到的相同趋势。这个图表可以在这里看到。这种模式没有那么极端,但仍然存在。由于科罗拉多州众议院法案-1303,我无法完成 2012 年总统选举的分析。

但话虽如此,我想从全州选举的角度来看这个问题,克林顿赢得了科罗拉多州,希肯卢珀也赢得了他的竞选。因此,如果科罗拉多州的一个县支持在全州竞选中失利的候选人,你会看到失败政党的注册选民增加。但是,投票给获胜候选人的县没有看到获胜政党注册选民的同样激增。例如,正如我们在上文中看到的,在投票给输掉科罗拉多州的特朗普的县中,共和党注册选民有所增加,但在投票给克林顿的县中,我们没有看到注册民主党选民的激增。

如果我是一个政党的成员,利用这些信息,在新的一年的头几个月里,在人们对以前的选举记忆犹新的时候,有针对性地进行选民登记,可能是值得的。比如,在科罗拉多州,共和党可以在投票给沃克·斯特普尔顿(州长竞选中的败选候选人)的县开展选民登记运动。或者,民主党可以在德克萨斯州投票给贝托·奥罗克(在德克萨斯州参议院竞选中失败的候选人)的县开展选民登记运动。我知道这与我之前所说的州长竞选比参议员竞选有更大的影响是相反的,但是考虑到谁参加了竞选以及选举期间全国瞩目的焦点,我认为可以肯定地说这是上届德克萨斯州选举期间最大的一次竞选。我也在关注另一个州的比赛,所以不要全信。

该项目的最后一部分是预测 2018 年的选民登记情况。由于上面提到的季节性,我认为季节性 ARIMA 模型会很适合我的数据集。ARIMA 代表“自回归综合移动平均线”这个模型的公式如下。

该模型不仅会查看预测时间之前的时段,还会查看一个或多个季节之前的时段,以帮助进行预测。在这种情况下,每个周期是一个月,每个季节是两年或 24 个周期。

从表面上看,这些预测可能看起来合理,但我并不像我希望的那样信任这些预测。出现这种情况有几个原因,但归根结底是因为我没有足够的数据来证明我的预测是正确的。有了数据,我就有了,这也是我解决不了的问题。如上所述,2013 年不活跃选民和活跃选民的定义发生了变化,这使得我无法再往前追溯。

如果我包括任何自回归和移动平均成分,我的模型只能回顾一个季节。这是一个问题,因为 2016 年由于有争议的总统选举,选民大量涌入。看看偶数年的 11 月,登记选民总数将达到:2012 年 365 万,2014 年 366 万,2016 年 387 万。我的预测预测 2018 年 11 月将有 402 万选民。我的预测是,非总统年将是一个非常大的年份。这是我在模型中看到的一个缺陷。如果我能够回顾三个甚至四个赛季,这将有助于缓解 2016 年的大幅增长,并且能够更好地区分总统年和非总统年之间的差异,以产生更好的结果。

从 2018 年 11 月的实际注册选民总数来看,我的预测没有我想象的那么远。这个数字是 399 万。虽然我能够说服自己,由于逻辑原因,我的模型不会那么准确,但有时在得出结论之前,最好等待现实生活中的数据。公平地说,我仍然认为如果我有几年的可靠数据,这个数字会更准确。

要查看其余的图表,请访问我的 Tableau 公开简介:https://public.tableau.com/profile/cbjohnson30#!/
要查看用于此的代码,请访问我的 GitHub:https://github.com/CBJohnson30

量化天气对零售销售的影响

原文:https://towardsdatascience.com/quantifying-the-effect-of-weather-on-sales-a3975aaaed43?source=collection_archive---------23-----------------------

Converting weather data into sales indicators | Photo by the author

读者注意:本文假设读者对数据科学和分析概念有所了解。

澳大利亚一家大型零售商的财务团队想知道“天气对每周销售额有多大影响?”这个问题的答案—这是一个普遍存在的问题,许多财务分析师和经理都在努力解决这个问题。然而,这个行业中没有人有科学的方法来解决这个问题。

准确量化天气对销售的影响的应用有很多,例如:

1.)通过优化定价和在特定天气条件下对合适的产品打折来改善客户服务。
2。)估算对特定天气敏感产品的需求,如雨伞或冰淇淋。
3。)通过降低营运资本来改善供应链&通过确定恶劣天气来降低物流成本。

如上所述,解决这个问题的商业价值是巨大的,因为这可以帮助更好地理解某些天气事件对收入和利润的影响。不仅如此,企业还可以更好地监控和报告受天气影响的客户每周交易习惯。这个项目的最终目标是预测未来一周依赖天气的销售情况。

在本文中,我不想深入数学模型选择和实现的本质。然而,下面概述了用于执行项目的项目管理框架的高级理解。我将描述用于解决问题的跨行业数据挖掘标准流程(CRISP)数据科学框架,并阐述我是如何着手解决这个问题的。

CRISP 数据科学框架包括:

1.)商务理解
2。)数据理解
3。)数据准备
4。)造型
5。)测评
6。)部署&演示

从业务理解开始,我描述了问题的当前状态和未来期望的状态。定义问题的下一步是把它分解成更小的子问题,这些子问题是互斥的,并且是完全的。一旦问题被分解成更小的组成部分,例如,在我们的天气分析中,不同州的温度、风速和降水对每周销售有什么影响?此外,洪水或飓风等重大天气事件的影响是什么?我们如何使用现有的测量指标来定义洪水和飓风?我开始意识到不同的解决方案必须结合起来才能回答这个主要问题。

由于该项目的业务理解阶段的一个重要部分是研究,我利用现有的基于天气的销售预测研究来快速缩小方法范围。所确定的方法得到横向阅读和研究的支持,以确保该方法符合手头具体问题的需要。对方法进行一些必要的修改,以针对给定的问题定制解决方案。因此,使用现有的研究确保了利益相关者更快的周转。

根据 CRISP 框架,第二步是数据理解。在我的分析中有两个主要的数据来源。一个是从 IBM Cognos TM1 接收的州级销售数据,另一个是从气象局(BOM)网站收集的天气数据。与所需的利益相关方召开研讨会,以了解分析所需的所有数据字段。对于 BOM 数据,使用元表和数据表中提供的信息收集数据理解。

第三步是数据准备,这一步非常关键,因为最终模型的准确性在很大程度上取决于数据准备阶段。这一步可以进一步分解为特征选择和特征工程。在这一步中,我探索了可用特性的不同组合和排列,以便特性集可以与输出变量(即每周销售额)具有更高的相关性或适合性。我还去除了季节性的影响,如圣诞节和复活节期间,因为销售趋势在这些时期变化很大。

在建模步骤中,我试验了多元自适应回归样条(MARS)算法、自回归综合移动平均(ARIMA)和各种非线性机器学习算法,如随机森林(RF)和 XGBoost,以选择最适合我们给定数据分布的算法。使用高级机器学习算法的缺点之一是结果的可解释性。因此,为了更好地解释结果;我将温度、风速和降雨量的连续值转换成不同范围的桶,这样我就可以回答这样的问题,如维多利亚州气温上升 10 度会导致多少 X%的收入增加或减少?解释这些问题对于利益相关者展示分析项目的价值非常重要。

使用 K-fold 交叉验证技术对模型进行评估,其中在模型在训练期间未见过的各种测试数据集上验证训练的统计模型。K 倍交叉验证创建了稳健的模型,比其他方法具有更低的偏差。我得到的维多利亚州和新南威尔士州的模型的拟合优度(R 平方)约为 80%。在全国范围内,拟合优度大于 75%。所得模型的平均绝对百分比误差(MAPE)小于 12%,完全在应用所需的不确定性范围内。

最后,使用 R 代码与 Microsoft excel 的集成来部署模型。我在 excel 上创建了一个用户友好且高度直观的仪表板,用于分析结果的消费。我的商业智能仪表盘每周都会显示天气对销售的影响,以及其他销售驱动因素的定性和定量描述。这份报告完全是使用 VBA 自动生成的,每周只需点击一下就可以用新数据刷新。

总之,对准确预测和更好规划的需求在零售业中是至关重要的。尤其是因为重大天气事件,如洪水或干旱,如果处理不当,会给企业带来巨大的财务损失。我所做的是设计一种方法来验证和衡量一个不可控的销售驱动因素对业务的影响。有了这方面的知识,商场运营、交易和规划以及供应链团队将能够更好地预见重大天气事件对市场的潜在货币影响,并采取正确的策略将损失降至最低。

作为分析的下一步,我想看看天气事件对商店的影响,以及不同的天气条件如何影响不同类别的产品。拥有更精细的视图最终将有助于优化业务绩效。此外,我相信这才是分析的真正力量所在。

量子信息与人工智能

原文:https://towardsdatascience.com/quantum-computing-and-ai-789fc9c28c5b?source=collection_archive---------8-----------------------

Google’s qubit circuits are built out of superconducting materials, which are then kept at very low temperatures. Photo from Google through The Verge retrieved Sunday the 13th of October 2019

在人工智能新发展的背景下探索术语和历史

既然有这么多关于量子计算的讨论,我认为探索我遇到的一个术语是合适的,即量子神经网络。然而,要做到这一点,我必须与术语‘量子信息’作斗争。因为我两者都不精通,所以你必须把这篇文章看作是一个很难理解的问题,而不是最终的答案。你可以看到第一部分是 NIST 关于量子计算历史的文章摘要。

在物理学和计算机科学中, 量子信息 信息 状态的一个 量子 系统。它是研究 量子信息 理论的基本实体,可以使用 量子信息 处理技术进行操控

量子神经网络(QNNs)是基于量子力学原理的神经网络模型。QNN 研究有两种不同的方法,一种是利用量子信息处理来改善现有的神经网络模型(有时反之亦然),另一种是寻找大脑中潜在的量子效应。”**

量子信息史

我当时在看美国国家标准与技术研究院的一个帖子,作者是 Ben P. Stein 关于量子信息的历史与未来。他将量子信息描述为量子物理学和计算理论的结合。

“谷歌、英特尔、微软、IBM 等等都有量子团队,他们实际上在努力打造硬件,”

JQI 研究员、马里兰大学物理学教授、量子信息公司 IONQ 的联合创始人克里斯·门罗说。

这个领域似乎正在从学术实验室向工业领域过渡。

“量子力学彻底改变了 20 世纪。它解释了原子等非常小的物体的工作原理,以及光子或单个光包等能量非常小的东西。它带来了激光、微型计算机芯片和节能发光二极管。根据半导体行业协会的数据,它催生了半导体行业等新的经济领域,2016 年全球销售额达到 3390 亿美元,与 2016 年同期相比,2017 年第二季度增长了 21%。”

“计算是一个物理过程,如果你从这个角度来考虑,它会在计算和物理科学中打开各种新的视野,”NIST 的数学家罗恩·布瓦韦特说

1994 年,时任美国电话电报公司·贝尔实验室数学家的彼得·肖尔创造了一种算法,用于在未来的量子计算机上运行,可以快速破解用于银行和其他敏感交易的加密方案。根据 NIST 的说法,这一发现引发了一场竞赛,并发展成一个新的领域。

量子优势

研究人员不再仅仅专注于建造一台可以执行 Shor 算法和破解加密代码的量子计算机。对许多人来说,中间目标是实现“量子优势”,这是加州理工学院的约翰·普雷斯基尔创造的术语。因此,当量子计算机能够执行普通计算机不可能或不切实际的任务时,这一目标就能实现,这在优化问题中通常被认为是有趣的。

“有充分的理由相信量子计算机将擅长解决优化问题。首先,大自然似乎对它们没什么意见。当植物利用光合作用将阳光转化为能量时,它们一直在解决这些问题。”

JILA physicists used the quantum properties of a strontium lattice atomic clock to simulate magnetic properties long sought in solid materials. The atoms are confined in an optical lattice, shown as an array of disk-shaped traps set at shallow depths. A laser (yellow wave) probes the atoms to couple the atoms’ spins and motions. The two atomic spin states (red and blue), which are also the clock “ticks,” are locked to the atoms’ right and left motions. Credit: Steven Burrows and Ye Group/JILA

量子化、叠加、消隐和纠缠

“量子计算机将通过利用非常小的……的奇怪规则来获得它们的特殊能力”“**

这些规则之一是量子化。一名消防员在滑下一根柱子时,经历了一个平稳连续的重力势能范围。像电子这样的微小粒子可以在原子的能级之间进行突然的“量子”跳跃。

Credit: N. Hanacek/NIST

叠加。在普通的经典世界中,滑板运动员一次只能在一个地点或位置,例如坡道的左侧(可以表示数据值 0)或右侧(表示 1)。但是,如果一个滑板运动员能够像一个量子物体(如原子)一样行事,他或她就可以处于 0 和 1 的“叠加”状态,有效地同时存在于两个地方。

有人认为这对信息技术非常有用。

普通的数据位只能是 0 或 1

如果离子在碗的左右两边处于叠加状态,可以同时充当 0 和 1

根据 NIST 的说法,量子比特,或称量子位,可以用来处理大量的信息,比传统的要快得多。

破坏叠加态被称为 退相干 ,这是一个主要问题。因此,研究人员必须保护量子位,并隔离它们。

当一个量子叠加态(比如一个原子同时处于 0 和 1 态)被某种外界扰动破坏时,比如一个实验者测量原子,就会发生退相干。

Credit: N. Hanacek/NIST

量子计算机的另一个要素是 纠缠 ,这可能是所有量子特性中最奇怪的。这是一种量子比特之间的量子联姻。

在被称为纠缠的量子现象中,即使两个粒子相距很远,它们的属性也是纠缠在一起的。

阿尔伯特·爱因斯坦指出了这种“幽灵般的超距作用”,这让他非常不安,但这种行为已经被一次又一次地证实,包括在最近具有里程碑意义的 NIST 实验中。测量一个量子位的值,它就决定了第二个纠缠量子位的值。”

The NIST process for”purifying” an unusual property of quantum physics calledentanglement involves illuminating two pairs of beryllium ions (charged atoms)with a series of ultraviolet laser pulses. Credit: Bill Pietsch, Astronaut 3Media Group Inc.

然而,量子位越多,它们的解密速度就越快。NIST 声称这就是为什么仍然没有量子计算机能够执行真正有用的任务。在做任何有价值的事情之前,系统可能会崩溃。

原子钟和纠缠理论

在 20 世纪 90 年代,NIST 的研究人员已经有了量子位,但称之为原子钟。

“原子钟报时的精确度惊人。NIST-F2 是美国用于计时的最精确的原子钟,保持时间的精确度不到十亿分之一秒的百万分之一。这看起来似乎有些过火,但 GPS 卫星包含原子钟,并依靠这种精度来发送时间戳信号,帮助我们在地球上的任何地方精确定位,误差在一米以内。”

1994 年春末,人们通过电子邮件讨论 Shor 的结果,NIST 物理学家 Charles Clark 组织了 NIST 量子计算和通信研讨会。

阿图尔·埃克特,当时是牛津大学的物理学家。埃克特正在社区里四处传播这些令人兴奋的新想法。1991 年,埃克特提出了基于纠缠的量子密钥分配理论,这是量子密码术的一个重要组成部分,并在十年后的实际设备中得以实现。

他们设想在实验系统中使用捕获的离子。

在提出的方案 中,研究人员将一组单个离子困在一条线上,就像电线上的鸟一样。激光将操纵离子的能量状态,使它们分别代表 0 和 1 或者两者的叠加。每一个离子都可以通过来回摇动来相互交流。摇动可以让每个离子与其邻居交换信息。这样,研究人员就能够用量子位进行计算。”

False-color images of 1, 2, 3, 6, and 12 magnesium ions loaded into a NIST planar ion trap. Red indicates areas of highest fluorescence, or the centers of the ions. As more ions are loaded in the trap, they squeeze closer together, until the 12-ion string falls into a zig-zag formation. Credit: Signe Seidelin and John Chiaverini/NIST

因此,他和小组成员克里斯·门罗用激光控制离子的能量状态,以影响它们的运动。1995 年 12 月,他们宣布了量子计算机的第一个组件。

量子逻辑门

"逻辑门是处理信息的构件."

通过在电路中安排门,工程师可以创建类似于流程图的东西,使计算机能够执行多种逻辑运算,如数学计算,并执行计算机可以完成的各种任务。

使用激光,研究人员还可以使离子的内部能量状态进入 0 和 1 的叠加状态,使离子的运动进入 0 和 1 的叠加状态。这使得门可以同时处理多种可能性,不像普通的逻辑门,所以门可以同时考虑商业交易的“是”和“否”两种可能性。

David Wineland and other members of NIST’s Ion Storage Group in 1996, shortly after they began to do experiments in the field of quantum information. Credit: Courtesy Chris Monroe

Elaborate laser-table setups such as this one in a NIST-Boulder lab are where many important quantum-information experiments get done. Credit: J. Jost/NIST

****相互纠缠的多个量子位可以用来同时进行大量的计算。

两个量子位的门可以同时处理四种可能的 0 和 1 的组合。

三量子位门可以处理八种可能的组合。

“每增加一个量子位,门可以同时处理的组合数量就会增加一倍,所以每增加一个新的量子位,组合数量就会呈指数增长。”

然而,测量只能提取关于计算结果的少量信息。部分理解为什么 NIST 提到另一个概念。

波粒二象性 : 一切物体既可以充当粒子,也可以充当波。作为波,离子在空间中有波峰和波谷;峰值代表测量时更可能发现离子的位置。波峰和波谷叠加在一起就形成了新的波形。这些波将组合或“干涉”形成新的波型。通过干扰波,科学家创造出可以转换回量子位值的模式,并产生有用的信息。

根据 Ronald F. Boisvert 的说法,量子计算需要创建所有可能答案的均匀叠加,然后操纵该叠加。因此,当一个人进行测量时,他很有可能得到正确的答案。

建造量子计算机的竞赛

如前所述,最微小的扰动都会破坏量子位中的叠加态,当你给纠缠量子系统添加越来越多的量子位时,它会变得越来越脆弱。

NIST-博尔德小组创造了一个“跑道”阱来捕获和存储多种离子,并用于处理量子信息。他们建造了一个量子处理器,可以运行任何只需要两个量子位的计算机程序。

“一台实用的量子计算机将需要更多的量子位,所以一个想法是将许多这些双量子位处理器连接起来,让它们作为一台成熟的计算机一起工作。”

A gold-on-alumina trap inside a case that protects against electrical interference. Credit: Blakestad/NIST

还有人试图建造微小的微观“量子”鼓,通过释放被称为声子的微小能量包来振动。

NIST’s microscopic aluminum drum, embedded in a superconducting circuit, has both classical and quantum properties. Like a percussion instrument it oscillates at a steady rate with a well-defined amplitude (drum height). It could be used for storing quantum information.

公司——从谷歌、IBM、英特尔和微软这样的大公司到量子电路公司和 JQI 门罗创办的创业公司 IonQ 这样的小公司——也在致力于制造量子计算机

根据 NIST 的说法,实现量子优势的竞争是激烈的。

人们认为第一台量子计算机会像 20 世纪的第一台传统计算机一样庞大。

就用途而言,通讯似乎有潜力,可以远距离传送信息。

“研究人员似乎同意一件事:光子或光的粒子将被用来从一台量子计算机向另一台传输信息。在最近一次引人注目的演示中,中国将纠缠光子从一颗卫星发送到 1200 公里(约 750 英里)外的地面。

加密随着量子计算死去了吗?

当我听到谈论量子计算时,最常见的是与安全联系在一起。然而,根据 NIST 的说法,由于两项发展,所有的希望都没有失去:量子密码术和后量子加密。

****量子密码术:测不准原理表示测量任何物体都会干扰它。量子加密依赖于这样一个事实,即窃听(试图获取信息)是一种测量形式,会以一种可以被检测到的方式干扰系统。量子密码术在安全通信中也有应用。中国的研究人员最近使用技术与远在 2500 公里(约 1600 英里)之外的澳大利亚同事进行了一次安全视频通话。

另一方面,它可能不可行,原因有三:

  1. 它非常昂贵
  2. 它旨在防止窃听者而不是攻击者

然而,量子密码系统非常昂贵,而且可能被黑客攻击:

“……已经证明,即使是基于量子特性的密码系统在现实世界条件下也可能被黑客攻击;例如,当静电或噪声——受经典物理规则支配——不可避免地被引入系统时。”

量子密码术被设计来保护两个可信任方之间的通信不被窃听者截获。

但是如果另一边的人是网络攻击者呢?窃听者目前并不是网络安全中最大的担忧。

****后量子加密:加密数据的方式,使用不涉及因式分解的数学函数。后量子算法是基于量子信息之前的经典数学技术。研究人员已经在开发后量子算法,以防量子计算机成为现实。

没有计算机的量子信息应用

****量子传感器:原子钟有可能被用作量子传感器。这些量子逻辑时钟是新一代超精密计时设备的一部分。这些新装置非常精确,它们不仅仅可以报时;它们可以作为重力和其他属性的传感器。

另一种是 原子陀螺仪 ,“一种旋转传感器,利用波粒二象性。

“我们通常认为原子是微小的球——换句话说,是粒子。但是在适当的情况下,原子可以表现为波。一个原子的波长——连续波峰和波谷之间的距离——太小而无法察觉,但如果你让原子变得更冷,它们的波长就足够大,可以在当今的实验中被探测到。”

Artist’s depiction of quantum simulation. Lasers manipulate an array of over 50 atomic qubits in order to study the dynamics of quantum magnetism. Credit: E. Edwards/JQI

****量子隐形传态:NIST 国家标准与技术研究所的研究人员已经将光粒子中携带的量子信息“隐形传态”或转移超过 100 公里(km)的光纤,比之前的记录远了 4 倍。

第二次量子革命

根据 NIST 的说法,我们似乎正在取得很大进展,已经到了“第二次量子革命”的地步。

****第一次革命:当科学家们知道量子力学的规则并按照这些规则建造设备时,使得激光和晶体管等发明成为可能,这些发明是计算机的基本组成部分。

****第二次量子革命:在比以前更大的程度上控制单个量子系统,如带电分子,使量子信息的应用更加强大。这种方法借用了实验 NIST 原子钟的量子逻辑方法。

Credit: N. Hanacek/NIST

实验室天体物理联合研究所(JILA)的三维(3-D)量子气体原子钟是第二量子分辨率的早期例子,它将锶原子之间的相互作用控制到一个精致的程度,使原子钟比以往任何时候都更加精确。

Credit: G.E. Marti/JILA

“……赌注很高,从国家到企业,每个人都在参与这场游戏。”

与量子相关的人工智能的新发展

因此,我们也许可以看到一些与人工智能领域的联系。处理信息对许多公司来说都很重要,量子力学导致了半导体的出现,这就是我们今天所知道的计算的出现。提到了对量子发展感兴趣的大公司,但是我将提到一个:谷歌。

谷歌的企业使命是“组织世界上的信息,并使其普遍可用和有用。”

在物理学中,一个 量子 (复数:quanta)是参与一个相互作用的任何物理实体(物理性质)的最小量。

在物理学和计算机科学中, 量子信息 是量子系统状态的信息。它是量子信息理论研究的基本实体,并且可以使用量子信息处理技术来操纵。

因此,世界上最大的技术公司之一对最小的信息部分都感兴趣,而 Google.com 是世界上访问量最大的网站。

谷歌有一个名为 Quantum 的团队:谷歌人工智能的一项研究成果:“…旨在构建量子处理器和开发新的量子算法,以大幅加速机器学习的计算任务。”

量子计算**正如谷歌人工智能所描述的:“是一种新的范式,将在加速人工智能的任务方面发挥重要作用。我们希望为研究人员和开发人员提供开源框架和超越传统能力的计算能力。”

As of Sunday the 13th of October 2019 these are the areas in Quantum at Google AI

他们有开源框架,专门用于开发新的量子算法,以帮助解决实际问题的近期应用。一个工具是 Cirq,另一个是 OpenFermion。

Two tools used by Google AI in Quantum retrieved Sunday the 13th of October 2019

他们将近期应用描述为:

  • 量子模拟:通过化学和凝聚态模型的精确模拟来设计新材料和阐明复杂物理是量子计算最有前途的应用之一。
  • 错误缓解技术:他们致力于开发全量子纠错的方法,这种方法能够显著降低当前设备中的噪声。
  • ****量子机器学习:他们正在近期量子器件上开发混合量子-经典机器学习技术。
  • ****量子优化:航空航天、汽车和其他行业的离散优化可能会受益于混合量子经典优化,例如模拟退火、量子辅助优化算法(QAOA)和量子增强群体转移可能会与当今的处理器一起使用。

谷歌的量子机器学习

他们正在研究通用量子电路学习,用于量子和经典数据的分类和聚类。他们还对生成性和鉴别性量子神经网络感兴趣,这些网络可以用作量子通信网络中的量子中继器和状态净化单元,或者用于验证其他量子电路。

谷歌人工智能的团队正在探索量子神经网络:

** [## 探索量子神经网络

自成立以来,谷歌人工智能量子团队一直致力于理解量子计算在机器中的作用…

ai.googleblog.com](https://ai.googleblog.com/2018/12/exploring-quantum-neural-networks.html)

“从一开始,谷歌人工智能量子团队就致力于理解量子计算在机器学习中的作用。”

它们通常仍在取得进展,研究正处于开始应用的实验阶段。

2019 年 9 月 20 日,据英国《金融时报》报道,谷歌声称已经建造了第一台量子计算机,可以进行超过当今最强大的超级计算机能力的计算,这是研究人员热切期待的里程碑时刻。代号为 Sycamore 的 53-qubit design it 似乎做到了这一点,但谷歌并未在文章中置评。

后来的 新科学家 在 9 月 26 日宣称谷歌已经达到‘量子霸权’

“谷歌的量子计算机解决了一个叫做随机电路采样问题的任务。在这样的问题中,经过一系列的计算后,每个量子位输出 1 或 0。目的是计算每种可能结果发生的概率。谷歌表示,Sycamore 只需几分钟就能找到答案——它估计在最强大的超级计算机上完成这项任务需要 10,000 年。虽然这令人印象深刻,但它没有实际用途。”

Eric Lukero/Google through NewScientist retrieved the 13th of October 2019

Google’s qubit circuits are built out of superconducting materials, which are then kept at very low temperatures. Google developed a 53-qubit design called Sycamore, which was used to achieve the recent breakthrough.

据报道,他们最近利用可编程超导处理器取得的名为量子优势的突破性进展的完整论文已经公布,并且可以在网上阅读。然而,等待谷歌确认本文中的任何信息可能是明智的。下面是总结:

量子计算机诱人的前景是,某些计算任务在量子处理器上的执行速度可能比在经典处理器上快得多。一个根本的挑战是建立一个高保真处理器,能够在指数级大计算空间中运行量子算法。在这里,我们报告了使用具有可编程超导量子位的处理器来在 53 个量子位上创建量子态,占据状态空间 253 \u 1016。来自重复实验的测量采样相应的概率分布,我们使用经典模拟来验证。虽然我们的处理器需要大约 200 秒来对量子电路的一个实例进行 100 万次采样,但最先进的超级计算机将需要大约 10,000 年来执行相同的任务。相对于所有已知的经典算法,这种显著的加速提供了计算任务上量子优势的实验实现,并预示着备受期待的计算范式的到来。”

考虑量子信息和人工智能的交叉领域接下来会发生什么是很有趣的。也很难说它将走向何方,也许是一种新的计算范式?**

这是第 500 天的第 132 天。500 天来,我每天都写一篇关于人工智能或与之相关的新文章。

商业量子计算

原文:https://towardsdatascience.com/quantum-computing-for-business-347b95d400f9?source=collection_archive---------13-----------------------

在过去的一年里,我们见证了量子计算领域的惊人进步,以及来自全球企业的全新兴趣。

本文呈现了 量子计算 现在的商业前景和现实应用。

a quantum computer

什么是量子计算?

经典计算机有一定的局限性。摩尔定律,大致说的是计算能力每两年翻一番,正慢慢走向终结,因为与进一步小型化相关的根本性技术壁垒。另一方面,计算机是线性运行的,处理一个又一个任务,计算的并行化受到阿姆达尔定律的限制。将这两个因素结合在一起意味着处理真正困难的现实生活问题或简单的真正大数据将需要计算范式的转变。

量子计算机是潜在的解决方案之一。他们正在对量子位进行操作,量子位本身会受到纠缠或叠加等量子效应的影响。这意味着它们可以同时一起工作,因此省略了阿姆达尔定律。此外,与经典电脑的线性性质相反,它们的能力会随量子位元的数目成指数增长。总之,这引起了工业界和学术界应有的关注。你可能已经看到一些文章描述了一个量子的未来,在破解任何安全代码或密码方面,因为量子计算机的计算能力将不可避免地远远超过经典计算机。

量子计算机有多强大?

我们还没有到那一步。尽管最近大肆宣传,我们仍然在量子优势之前,这是一个实际的证明,量子计算机可以比经典计算机更好地解决现实世界的问题。这意味着,你不应该指望量子计算机会让你的业务得到全面优化。至少现在没有。那么量子计算是假的吗?肯定不是!这只是过程的早期,像往常一样,有你必须付出的代价,投资失败的潜在风险,但一旦技术更加成熟,也会有回报。

在理论层面上,不同的研究小组证明了某些量子算法将提供超越经典算法的指数级加速。然而,他们都假设量子计算机具有足够良好的量子位,这不是当前的硬件水平。我们目前正处于嘈杂的中等规模量子器件时代,简称 NISQ。谷歌IBM微软D-WaveRigettiIonQ 等公司都在尝试打造自己的 NISQ 设备。最近几年有很多进展,导致了具有几十个量子位的硬件的产生,并解决了现实世界的问题,如优化城市中的出租车路线模拟分子。这些解决方案并不完美,也不如在超级计算机上获得的解决方案最优,但它们显示了一个良好的趋势——量子计算机真的正在达到商业水平,这是迟早的事情。

寻找次优解决方案是量子空间中所有服务提供商在现阶段提供混合解决方案的原因之一,这些混合解决方案将经典机器学习与量子计算相结合,例如 1QBit、Zapata 或 QxBranch。一些公司只提供在模拟器上工作的服务(在经典计算机上模拟的量子计算,目前比较 AtosXanadu微软)或在量子启发的硬件上工作的服务(富士通数字退火机)。混合方法会在快速扩展的问题中产生有趣的结果,例如在物流中,或者在只有稀疏数据的情况下,例如预测涡轮机何时会发生故障。这些类型的问题不可能在经典计算机上很好地解决,因此它们为量子计算机提供了一个很好的切入点,量子计算机提供了不同的计算方法和替代的、有趣的解决方案。

我们仍然需要几年的时间才能在不同的行业达到量子优势,但现在是开始实验量子的最佳时机。量子计算机与经典计算机完全不同,因此习惯它们需要一个过程。现在就启动它将让你的公司为量子计算比经典计算更强大的时刻做好准备。

量子计算机的商业应用

我写这篇文章的主要原因是总结量子计算在当今商业世界中的潜在应用。你会发现下面是一些行业的列表,在这些行业中,量子计算机已经和我们现在拥有的技术一起使用。我举了一些已经在尝试的公司的例子,只要有关于它的公开信息和可用的链接。我只展示了最大的企业,但是已经有一些中型公司为了他们的利益而试验量子。

  • 金融:银行业呈现出过多的问题,如投资组合优化、资产定价、风险分析、欺诈检测、市场预测,这些都在量子计算机的能力范围之内。首先,银行已经开始尝试,例如巴克莱和摩根大通与 IBM 合作,或者 NatWest 与富士通合作。
  • 保险:量子计算的潜在应用始于金融工具(债券、衍生品)的估值;保险产品的期权和担保的估价;量化运营风险。安联保险公司通过与 1QBit 合作开始试验。
  • 能源板块:优化现有网络结构和预测使用量是两大关联问题,都很适合在量子计算机上测试。埃克森美孚已经开始尝试将 IBM 作为量子合作伙伴。
  • 交通:量子计算机使用的最好例子是交通优化,就像大众和 D-Wave 一起做的那样。旅行推销员问题及其各种变体构成了在 NISQ 设备上尝试的一类很好的问题。
  • 物流:与运营相关的供应链问题通常很复杂,无法通过经典计算机进行优化,这为 quantum 进入市场创造了良好的潜力。阿里巴巴开始在自己的硬件上进行实验。
  • 汽车和航空:自动驾驶或飞行,或者管理一个庞大的车队都会带来优化问题,这些问题会随着车辆数量的增加而迅速扩大。这就是为什么像大众戴姆勒福特这样的汽车行业玩家都在进入这个领域。航天工业也非常活跃,NASA、空客、洛克希德·马丁和合作伙伴都在进行试验,从科技巨头到初创企业。
  • 化学品和制药:药物发现是一个非常昂贵的过程,模拟分子需要大量的计算。量子计算机自然适合制药研发,因为它们更适合模拟量子物体,因为它们本身具有量子特性。 Biogen 在量子计算的药物发现应用方面与埃森哲合作。再比如罗氏陶氏化学
  • 材料:指望更好的电池、芯片或网络架构的行业可以探索量子计算,模拟新的可能性或优化现有结构。这个商业垂直领域的实验是由博世霍尼韦尔开始的。
  • 区块链和网络安全:区块链是关于安全交易和合同的。它主要依赖于加密方法,因此容易受到涉及最新技术的网络攻击。这就是为什么探索后量子密码术或量子区块链是对未来的良好准备。到目前为止,只有埃森哲将区块链与量子一起提及。然而,网络安全公司有一个整体趋势,那就是关注后量子密码术,即在拥有强大量子计算机的世界中安全运行的算法,参见微软谷歌

这只是冰山一角。我只描述了最大的企业和他们的风险投资,还没有提到活跃的创业社区或已经在这个领域工作的中型公司。毫无疑问,量子计算是下一件大事!

量子计算如何入手?

如果你已经决定要在你的组织内试验量子计算,你能做的最好的事情就是找到一个可以向你介绍这个领域的合作伙伴。目前有几十家初创公司和公司提供量子计算服务,要么是在利基业务分支,要么是在一般情况下。如果你在寻求帮助,只需通过社交媒体给我写一条信息。

如果你想了解更多关于量子空间的内容,这里有一些很棒的概述文章:

祝你的量子之旅好运!

如果你想了解更多,可以看看这个关于量子计算的书单。

量子计算速成班使用非常丰富多彩的图表

原文:https://towardsdatascience.com/quantum-computing-with-colorful-diagrams-8f7861cfb6da?source=collection_archive---------3-----------------------

几乎所有你需要知道的关于量子计算的东西都用非常直观的图画来解释…

Have a quantum cat

量子计算是一个相对较新的、崭露头角的领域,它打破了量子物理学、研究或非常小的事物以及计算机科学的概念。

在这篇文章中,我将用直观的类比和一如既往的丰富多彩的草图和绘图向您介绍驱动这个年轻的、不断增长的领域的概念。

注意: 为了简单起见,我不会在本文中涉及数学和向量符号。如果有兴趣阅读这样的文章,请在下面留言或通过 Twitter 联系我!

经典计算机科学中的信息表示

经典计算机科学涉及比特的流动和操作,比特是计算机中信息的基本单位。它可以保存 1 或 0 的值,但不能同时保存两者。

1 或 0 通常对应于硬件上一个原子的电荷,代表计算机中的真/假或开/关状态。

这些电荷的变化导致位从 1 到 0 的翻转,反之亦然,从而允许信息从存储器的一个位置流向另一个位置。

Traditional bits are just charges on computer hardware that store information depending on their charge.

在量子计算中表示信息

在传统的计算机中,信息是用传统的位来表示的,这些位只能拥有 1 或 0 的值,而不能同时拥有这两个值。在量子计算机中,我们用量子比特(量子比特)来表示信息。

我们可以用 bra-ket 符号来表示量子位:|0⟩或|1⟩,分别读作‘ket 0’和‘ket 1’。

嗯,在量子计算中,量子位可以同时具有 1 和 0 的值,因为有一个叫做 叠加 的过程。

叠加的奇怪例子

叠加是指一个粒子或实体可以同时以两种状态存在的现象。它可以作为两个东西存在,也可以存在于两个不同的位置。例如,让我们看看薛定谔的猫悖论。

如果你把一只猫锁在一个隔音的、不可避免的掩体内,掩体内有一些可能爆炸的爆炸材料,这只猫处于死亡的和活着的的叠加状态,因为你不知道材料是否真的爆炸了(可能是因为掩体是隔音的)。**

There is a 50–50 chance of the explosive material either blowing up and killing the cat or staying as is. This is taken from the Minute Physics video on Quantum Superposition

只要你不打开地堡检查,猫在技术上是死的和活的。

然而,当观察者实际检查叠加态物体的状态时,一个奇怪的情况出现了。在这种情况下,现实崩溃为一个单一的结果,它不能再同时存在于多个状态中。同样,如果你再也憋不住了,打开地堡,你可能会看到猫死了。

你猜怎么着?你的好奇害死了猫…

或者,你检查的时候猫可能还活着。当一个观察者(在这种情况下是你)观察一个最初处于叠加状态的物体时,他们只会看到 n 个结果中的一个展现在眼前。如前所述,现实崩溃的结果之一。

这和量子计算有什么关系?

一个量子位可以以叠加态存在,同时携带 1 和 0 的值。这为解决需要大量计算能力的复杂问题打开了一个全新的可能性世界。

Qubits can exist in 2 possible states until observed (which causes reality to collapse to one of the states)

传统逻辑门

为了操纵基本位,它们必须由逻辑门转换,逻辑门要么将位翻转到另一个值,要么让它们保持原样。逻辑门的一些著名例子包括与、或、非、异或和与非。

它们接受成对的位值,并根据门的功能将它们转换为 1 或 0。

An example of a NAND gate that takes in pairs of similar bits and returns the flipped bit

量子逻辑门

为了转换量子位,我们让它们通过量子逻辑门(或量子门),量子逻辑门根据门的功能将量子位的现有状态映射到另一个状态。

这听起来可能很模糊,但量子门实际上是经典的逻辑门,作用于量子位而不是传统的位。量子门可以无一例外地执行标准经典逻辑门所能执行的所有动作。

让我们看几个量子门的例子:

哈达马德门

或许最常见的是,阿达玛门接受一个量子位作为输入,输出一个量子位,这个量子位有 50%的几率是 1 或 0。

用简单的数学术语来说,量子位坍缩为 1 或 0 的概率是相等的。这本身就是一种叠加,输出量子位有两种可能的状态,直到我们观察到它或者在进一步的计算中使用它。

Hadamard 门由方框中的“H”表示,可以多次添加到电路中,以输出一个具有相同机会为 1 或 0 的位。

The Hadamard Gate

There’s a 50–50 chance of the Qubit collapsing to either a 1 or 0

泡利-X 门

Pauli-X 门以 Wolfgang Pauli(顺便说一句,这个名字很棒)命名,它接受一个量子位。它本质上相当于而非门,它否定这些位并翻转它们。它在量子位上执行比特翻转。它将|0⟩映射/更改为|1⟩,将|1⟩映射/更改为|0⟩.

The Quantum equivalent of the NOT Gate — The Pauli Gate

The Pauli-X Gate performs a bit flip and negates the Qubits

受控非门

受控非门也被称为 CNOT 门。这接收 2 个量子位,并且如果第一个量子位是|1⟩.,只将第二个量子位从|0⟩翻转到|1⟩和|1⟩到|0⟩否则,它保持不变。

The CNOT or Controlled-NOT Gate

The CNOT gate only flips the second Qubit if the first Qubit is |1

尺寸

测量是在电路末端对量子位进行的一种特殊类型的操作,以在操作完成后获得量子位的最终值。

与上面的门相比,测量是不可逆的,因此不是量子门。我之前提到过,当一个观察者看到最初处于叠加状态的东西时,现实会坍缩成其中一个结果。

类似地,测量函数是观测器,它获取折叠量子位的值,并将它们放在一起,作为严格为 1 或 0 的最终输出位。

The Measurement function is represented as this symbol in a Quantum Circuit

The Measurement function takes in a Qubit and observes it to collapse its state to either 1 or 0.

代表量子模型

模型是物理学家用来模拟和观察当你以某种方式戳宇宙时会发生什么的东西。当涉及到可视化时,它们帮助很大。

同样地,量子模型代表处理许多量子现象的情况(例如叠加)。

我们如何在计算机上表示一个数学量子模型?

我们通过使用量子电路来做到这一点。电路代表计算过程,其中量子位通过量子逻辑门,根据其类型/功能将量子位从一种状态转换为另一种状态。

为了建立一个量子电路,我们需要量子逻辑门和量子位的组合,通过时间来获得想要的结果。为了形象化量子电路的样子,请看下图。

该图显示了三个量子位,都具有状态|0⟩或 ket 0 。盒子里的 H 代表量子逻辑门(H 是哈达玛门)。

在这个图中,我们可以看到每个量子位通过一个哈达玛门。第二和第三个量子位各自通过另一个哈达玛门。

通过将这些量子门和量子位放在一个电路中,你可以想象信息在电路中的流动。

简单地

在这篇文章中,我试图总结量子计算背后看似困难的理论。量子计算是一个崭露头角的领域,有一个非常小的社区。在即将发表的关于量子计算的文章中,我将涉及数学和向量符号。

如果你想让我报道其他事情,请在下面发表评论,或者在 TwitterLinkedIn 联系我。很快,我将带你用简单的 Python 制作你自己的量子电路(是的。我说 Python)。

如果我犯了什么错误,请让我知道(我也在学习!).

在那之前,下期再见!

相关文章

一定要看看我关于技术和机器学习的其他文章,以及对未来软件创新的评论。

** [## 遗传算法综合指南(以及如何编码)

遗传算法的起源

medium.com](https://medium.com/sigmoid/https-medium-com-rishabh-anand-on-the-origin-of-genetic-algorithms-fc927d2e11e0) [## CatGAN:使用 GANs 生成猫脸

GANs 的详细回顾以及如何跟他们浪费时间…

hackernoon.com](https://hackernoon.com/catgan-cat-face-generation-using-gans-f44663586d6b) [## TensorFlow.js 简介🎉

在浏览器上运行 ML 模型变得更加容易!

hackernoon.com](https://hackernoon.com/introducing-tensorflow-js-3f31d70f5904) [## 马尔可夫链简介

马尔可夫决策过程的一般指南

medium.com](https://medium.com/sigmoid/rl-markov-chains-dbf2f37e8b69)

里沙卜·阿南德的原创文章**

量子机器学习:量子计算机上的一种快速聚类算法

原文:https://towardsdatascience.com/quantum-machine-learning-a-faster-clustering-algorithm-on-a-quantum-computer-9a5bf5a3061c?source=collection_archive---------11-----------------------

本作品发表在《论文集》neur IPS 2019,可以查看相关 论文 了解更多详情,以及 会议海报

量子机器学习是一个非常热门的话题。正如约尔达尼什·克里尼迪斯(我的博士生导师)所说:这是量子计算中【最被夸大和低估】 的话题。这个相当年轻的研究领域旨在开发执行机器学习任务的量子算法,例如对猫和狗进行分类的十亿美元市场。你什么都不需要知道,我会解释的。

I guess this is a superconducting qubit quantum chip, but to be honest I don’t know. It’s just pretty.

量子计算1 分钟

现在你可能会问:什么是量子算法?与任何常规算法一样,它只是一系列命令,但这次它是由量子门组成的电路。什么是量子门?这就像一个经典的门,作为 OR,AND,NOT,作用于量子比特而不是比特。什么是量子位?* 嗯,这是一个量子位:它可以是和两者的一个位,而不是 1 或 0 。比如通俗地说,可以是叠加态 25%|0 > + 75%|1 >。我们用符号 |0 >|1 > 来记住这些就是现在的量子态。更一般地说,一个量子位的状态是 ⍺|0 > + β|1 > ,其中⍺和β是复数,称为振幅2 个量子位可以同时拥有|00 >、|01 >、|10 >和|11 >四种组合。8 个具有 3 个量子位的组合,等等,总是并行存在。那是量子物理!接受它,即使它在我们对现实的感知中并不常见。例如,一个量子位可以是一个原子、一个光子、一个离子或任何可以有两种状态的量子系统。就像一只小小的薛定谔的猫。*****

所以量子算法的输入是由量子位组成的。如果你有 n 个量子位,你同时有 个 2^n 个组态。你不喜欢吗?有了 300 个量子比特,你就有了 2^300 态,这是宇宙中原子的数量!

另一个重要的事实:如果你测量一组量子比特,你不会看到整个叠加(你不是量子),而只是其中一个配置,随机的,概率与这个配置的振幅相关。

Most probably what a quantum computer will NOT look like.

量子机器学习

有几种基本的量子算法被用作长期量子机器学习(QML)的构建模块。这些算法用于寻找矩阵的特征向量,执行矩阵乘法或矩阵求逆,估计两个向量之间的内积或距离。请记住这些重要的量子概念:我们可以通过多次测量来恢复量子态的经典描述,最重要的是,我们需要能够在单个量子态中加载一个矢量或一组矢量。所有这些子例程都允许执行线性代数任务,并证明了加速,通常在矩阵或向量的大小上指数级地更快,并有量化的误差保证。

注:有很多关于不同方法的研究,称为“量子机器学习”,这些方法基于参数化的量子电路。我们希望它们在短期内可能非常有用和强大,但是它们不能复制分析性的机器学习算法,也不能保证加速或准确性。我们的方法更多的是一种计算机科学和长期的方法。

矢量的量子编码

这是关键部分!给定一个 d 维的向量 v ,我们可以通过使用它的每个分量作为表示标准基的状态的量子振幅来对它进行编码。这可以仅使用对数(d)** 来完成。**

我们现在可以为我们的数据集定义一组 N 向量 v_1 ,…v _ N*的量子编码。我们要开始叠加 N 个向量,每个向量在维度上。每个向量由其索引 i 给出,因此我们使用 log(N) 量子位创建所有索引的叠加。*****

Left : Superpostion of N quantumly encoded vectors using log(N)log(d) qubits. Right : detailed expression of one vector quantumly encoded using log(d) qubits. Vector notation : v = (,,…)****

经典的 k 均值算法

先简单说一下经典机器学习。有监督和无监督算法之间有一个根本的区别:第一种算法从输入和它们的标签中学习(我告诉你这些是猫,这些是狗,现在学习),而第二种算法在没有指示的情况下学习(我只是告诉你找到两组不同的动物)。****

kmeans loop : The dots are vectors of the dataset. The black stars are centroids. Source : https://blog.floydhub.com/introduction-to-k-means-clustering-in-python-with-scikit-learn/

k-means 算法是最基本的无监督学习算法之一。它的目的是在数据集中找到聚类,通过找到 k 理想质心。然后,每个点都有一个标签,对应它的集群!

在每次迭代中,对于每个向量(点),我们计算它们到每个质心(黑星)的距离。所以有kxN的距离来计算。如果你有几百万个数据点,那就太多了。**

该算法的一次迭代做了两件简单的事情:
1)我们通过查看每个向量的当前最近质心,将标签更新到每个向量。2)我们通过平均每个集群中的向量来更新每个质心的

量子 k-均值

我们的论文中,我们开发了一个 k -means 算法的量子模拟,称为-q-means。步骤真的一样,但是一切都是在量子叠加中完成的。**

1 -我们从数据集中所有矢量的的量子叠加开始,我们同时计算到 k 个质心中每一个质心的所有距离
2 -然后我们可以通过选择最近的质心来同时标记所有向量。所有的标签都是以量子态书写的,也是叠加态。
3 -然后测量标签量子位。量子物理学告诉我们,我们会随机只看到一个标签:它意味着剩余的量子态是所有带有那个标签的矢量的叠加!那是纯粹的量子把戏。
4 -利用量子矩阵乘法,我们可以得到一个描述新质心的量子态。
5 -我们执行断层扫描来检索新质心的经典版本
6 -我们重复最后的步骤,直到我们有了 k 新质心。

分析:因为 N 向量总是被叠加使用,所以运行这个算法的时间与 N 成对数关系!对 k 和 d 的依赖性几乎类似于经典的k-均值,其在 n 中是线性的。**

请记住,这纯粹是一个理论算法,尚未在实际的量子计算机或经典模拟器上进行测试!如果你感兴趣的话,请继续,并尝试实现它!

我们能运行这个算法吗?

一个重要的问题出现了:我们如何测试我们的量子算法的质量和收敛性?有 3 个选择:
-在实际量子计算机上运行电路,但这目前还不可行。
-在量子电路的经典仿真器 上运行电路,可行但受限于量子位的数量。
-因为 q -means 与 k -means 遵循完全相同的步骤,我们可以
经典地实现它的一个版本
(在 python 中),通过将 k -means 与额外的“量子”误差(比如质心估计中的随机性和噪声)相结合来模仿 q -means。
****

Training curve, on the MNIST dataset, of the k-means (plain red) compared to a classical simulation of q-means (dashed) for several error values. Despite quantum noise and randomness, q-means converges as well.

后续步骤

有了上面描述的线性代数的量子子程序,特别是内积估计,我们现在能够想象其他几种 ML 情况的量子算法:量子神经网络量子卷积神经网络量子高斯混合模型,也许是量子谱聚类。这是令人兴奋的,一切都将被重写。

🎄我能在圣诞节得到一台量子计算机吗?

**
面对现实吧,这些算法远远领先于我们。它们需要大量具有纠错功能的良好量子位,但它们也需要量子 RAM (QRAM),需要创建初始量子矢量编码,这可能也很难构建。

那又何必呢?首先,如果有一天这些算法可能会被使用,我们应该看看它们,看看它会把我们引向何方。我们不应该等待学习算法,我们必须从基础开始,赶上更复杂的技术。经典 ML 是一个发展非常迅速的领域,一些先进的理念可以帮助 QML。这就是为什么在 NeurIPS 2019 上发表 QML 论文是一个很好的机会!

此外,描绘出我们未来的可能性已经非常重要了。从长远来看,我们现在应该探索量子计算机能做什么或不能做什么。对于建造量子计算机的人来说,了解 QML 算法中需要什么样的基本要求,我们需要什么样的状态初始化来确保加速,我们将如何处理线性代数,需要什么样的精度等等也很重要。

时间会证明一切!

Or more? Source : myself ©

参考

[1] S. Lloyd,M. Mohseni,p . Rebentrost[2013]
【2】n . wie be,A. Kapoor,K. Svore [2014]
【最近邻方法的量子算法用于监督和非监督学习】
【3】s . Chakraborty,A. Gilyén,S. Jeery [2018]

量子机器学习:k 均值聚类的距离估计

原文:https://towardsdatascience.com/quantum-machine-learning-distance-estimation-for-k-means-clustering-26bccfbfcc76?source=collection_archive---------13-----------------------

几周前,我被邀请在我们学校的年度科技节上演示量子计算的一些应用。

我选择专注于量子机器学习,在我的研究过程中,我发现了一些我认为超级酷的东西:一种完全不同的思考方式,即我们估计点之间距离的方式,这可以使量子 k-means 聚类算法比经典算法快得多。

然而,在我们深入研究之前,让我们先快速回顾一下经典的 k-means 聚类算法。

(经典)k 均值聚类到底是什么意思?

K-means 聚类是一种分类算法,这意味着当我们向它提供数据时,它会尝试将每个数据点与其他一些具有类似属性的点放入一个组或类中。它也是一种无监督的学习算法,所以我们不需要使用我们的一些数据集来训练模型,或者帮助它学习数据的特征。

如果我们有一个包含汽车型号、发动机尺寸和离地间隙列表的小型数据集,并将其输入到 k-means 算法中,输入将是这样的:

我们的输出可能如下所示:

但是算法是如何做到这一点的呢?

那么它是如何工作的呢?

虽然这听起来非常复杂,但是 k-means 聚类背后的思想实际上非常简单。它只是把你要求它分类的每一个新数据点放入它最接近的组中。

将这一点形象化会更容易理解——红点会进入哪个星团?

看起来红点最接近蓝点,所以 k-means 聚类算法会将其放入蓝色聚类中。

不过,这又引出了另一个问题:判断图上两点之间的距离对我们来说很容易,但我们如何让计算机做同样的事情呢?

比较距离

由于每个点都被表示为一组数字——每个数字都指定了该点在一个平面中的位置——计算机可以使用点之间的坐标差来找到点之间的距离。

我们可以把每一个聚类表示为一个位于该组“平均”位置的点。

我们如何找到平均值?我们可以在一个维度上将属于一个簇的所有点的坐标相加,然后除以该组中的点数。如果我们对每个维度都这样做,那么这些坐标所代表的点就可以用作聚类的平均值或质心。如果我们用上面的例子来做这件事:

彩色的 x 标记了每个簇的质心。

现在,如果我们取代表红点的坐标和群质心之间的差,我们可以证实我们最初的猜测,红点属于蓝色星团:

右下角的文本给出了从红点到每个簇的质心的欧几里德距离。正如我们所看到的,到蓝色质心的距离是最小的,这意味着红点确实会被归类到蓝色星团中。

我们如何找到距离?我们用质心和红点的坐标作为向量。

例如,如果我们想计算到蓝色质心的距离,我们可以从蓝色质心的位置向量中减去红点的位置向量:

要计算距离,我们需要计算矢量的大小:

k-means 聚类算法会找到新点与每个质心之间的距离,然后将新点放入质心最近的聚类中。

超级简单吧?

要点是,找到从一个新数据点到每个质心的距离是关键——之后的所有事情,如比较距离,并将新点分配给一个组,都容易得多。

既然我们已经得到了经典的版本,让我们把事情推进到量子宇宙。

距离估计

我们知道,我们的算法需要测量到不同质心的距离:但我们如何将使用向量减法测量距离的想法转化为我们可以在量子计算机上轻松有效地执行的事情?

有了经典的量子计算机,我们可以很容易地计算出欧几里得距离,但是试图在量子计算机上这样做要困难得多——而且需要的量子比特比我们能提供的还要多。其原因是,由于量子位的概率性质,相位差和概率振幅很容易测量,但像两个向量之间的距离这样的事情却不容易测量。

我们只需要距离,这样我们就可以将数据点分配到不同的组,我们需要知道哪个聚类离数据点最近。如果我们有另一个更容易测量的参数,可以让我们计算出哪个质心最接近呢?

这个参数不一定要和距离成正比,只要和它正相关就行。这是可行的,因为我们只需要最近的质心,而不需要到每个质心的精确距离,我们可以将新的数据点放在与我们的参数取的最小值相关联的群集中。

幸运的是,当我们处理量子位时,有许多类似距离的参数可用,如两个(归一化)向量之间的内积,以及测量处于|0>|1>状态的量子位的概率。

但是我们如何使用两个向量之间的内积来帮助我们估计距离呢?

我们需要做一点数学计算。如果你不喜欢,可以直接跳到下一节的结尾——你真正需要知道的是我们最终得出的可测量变量之间的关系。

关联内积和距离

让我们从一个零初始化的辅助量子位和一个量子态ψ开始,它存储了我们想要估计的归一化向量:

现在我们可以假设|x>是我们想要分类的新数据点的位置向量,而|y>是我们数据中一个聚类的质心。

首先,我们对辅助量子位应用一个阿达玛门,把它推到叠加态:

为了使状态ψ与我们的辅助量子位纠缠在一起,我们对辅助量子位上控制的ψ应用一个交换门:

这里的*F*(|Ψ>) 只是一种更简单的方式来展示|Ψ>的交换版本,这是交换门应用于|Ψ>的结果。

接下来,我们将另一个哈达玛门应用于辅助量子位:

这里*I*代表恒等运算符— *I*(|Ψ>)简单来说就是给出|Ψ>

接下来的几个步骤可能看起来有点随机,但我们真正要做的是将我们现在拥有的等式转化为一种形式,它包含两个向量|x>|y>的内积。

如果我们替换(*I — F*)(*I*+*F*),我们得到这个:

我们可以用一个叫做期望值的超级有用的概念来进一步简化这个问题(你可以在这里阅读这个概念)。这个想法是,我们可以将辅助量子位在|0>状态下被测量的概率表示为内积:

如果我们把*I**F* 重新代入:

如果我们展开内积,我们得到这个:

<xy , xy> = 1<xy , yx> = (<x , y>)^2开始:

太棒了——所以现在我们有了在|1>状态下测量辅助量子位的概率,这是我们很容易测量的,和我们想要找到两个向量之间距离的内积之间的关系。

我们现在需要做的就是证明等式的右边与两个向量|x>|y>之间的欧几里德距离正相关。

如果我们扩展矢量减法:

因为两个向量都是归一化的,所以它们的幅度是 1:

如果我们看看我们之前推导出的等式,它们看起来非常相似:

酷!看起来我们有了一个容易测量的参数,可以用来代替测量距离。现在让我们使用 qiskit 实现我们的距离估计算法。

从盒子到球体

我们如何将我们想要估计的点之间距离的矢量坐标编码成量子位?

让我们首先绘制几个类,它们的质心,以及我们想要分类的一个新点:

红点是我们要分类的新数据点,彩色的 x 标记每个类的质心。

我们需要找到一种方法,将我们目前用来描述质心的直角坐标转换成球面坐标,这样我们就可以将图上的每个数据点表示为布洛赫球面上的另一个点(查看这篇文章,了解量子位表示的超级平滑介绍):

要转换数据点,我们需要执行以下步骤:

  • 取一个零初始化的量子位,对其应用哈达玛门,移动代表量子位的向量,使其沿着 x 轴。
  • 根据对应于特征 1 的数据点的值设置φ。
  • 根据对应于特征 2 的数据点的值设置θ。

θ的范围可以从0π弧度,φ的范围可以从0π弧度。

为什么我们需要限制φ可以取值的范围?

假设我们有两个数据点,当用一个量子位表示时,它们取相同的θ值和φ值0。量子位将占据布洛赫球上的同一个点,即使它们代表的点具有不同的特征值,这将搞乱我们的算法——它只在布洛赫球上量子位之间的相位差与两个数据点之间的实际欧几里得距离大致成比例时才起作用。

使用以下等式,我们可以轻松地将数据特征值映射到θ和φ值:

这里d_0d_1代表数据特征 1 和 2 的值。如果这些没有意义,回到我们数据的散点图,看看每个特征的范围(-11),以及θ和φ。

太好了!

我们找到了一种方法,从将我们的数据绘制为图上的点,到使用量子位来表示它们——现在让我们把手弄脏,看看我们的算法是否真的有效。

构建距离估计器

你可以在这里得到我使用的数据。

我们已经看到了上面的数据图,以及我们需要分类的红点。为了方便起见,让我们再次绘制我们的数据,但是这里只显示了每个类的质心:

我们得到了一个简洁、超级简单的图表:

我们需要比较从红点到每个质心的距离,所以我们必须将质心和红点的坐标编码到我们的量子位中。为此,我们使用上一节中提出的规则:

现在我们从 qiskit 导入我们需要的所有模块,并创建寄存器来保存我们的量子位和结果:

我们可以使用 qiskit 提供的 U3 门来实现我们需要执行的旋转,以对我们的数据点进行编码。 U3 门可以这样应用:

这条指令将导致量子位从正 z 轴向外移动θ弧度,从正 x 轴向外移动φ弧度,就像我们之前看到的布洛赫球一样。

让我们实现我们在连接辅助量子位的概率和两个向量之间的距离的部分中走过的过程:

现在我们可以检查新数据点属于哪个类。让我们也打印欧几里得距离,以了解到每个质心的距离之间的差异:

我运行了这个程序很多次,得到了这些结果:

它看起来很有效——超级酷!

包扎

厉害!

我们构建了一个量子距离估计器,与 k-means 聚类算法一起使用,我认为这很棒。你可以在这里获得整个程序—随意在其他数据集上运行它,感受一下它是如何工作的。

这篇文章只是我将发布的一个新系列的开始,涵盖了量子机器学习的不同方面——敬请关注!

面向金融科技的量子神经网络

原文:https://towardsdatascience.com/quantum-neural-networks-for-fintech-dddc6ac68dbf?source=collection_archive---------16-----------------------

奇点研究

时间序列函数拟合

在本文中,我们将解释量子神经网络的一般概念,并且我们将解释可以在一维时间序列数据上训练以拟合数据的函数的模型。我们还将提供 Github 上培训药品销售数据模型的教程的链接。

量子位和量子电路

什么是量子神经网络?要回答这个问题,我们需要理解量子位和量子电路的概念,量子电路是量子计算中用来描述量子位操作的基本图表。量子电路非常类似于描述逻辑门操作的电路图,这些逻辑门在经典计算中使用,例如在你的电话或笔记本电脑上。量子位是位的量子计算版本,其行为与位不同。许多人谈到量子位时,仿佛它们是神秘的,并且“同时是零和一”尽管这实际上是不正确的,而且是对他们行为的过度简化,掩盖了数学的精确性。这样做要么是出于作者的误解,要么是因为作者认为读者缺乏知识或注意力。思考量子位元状态的适当方式,是将其视为球体上的一个位置,例如地球表面,北极为“1”,南极为“0”。量子门在这个位置上运行,在全球范围内移动。

Qubits being operated on by the Hadamard gate

如果我们有几个量子位,我们可以用几个门分别操作它们,或者同时用一个多量子位门操作它们。我们画一个电路图来表示哪些量子位在特定的时间通过特定的门。对于量子比特的基本介绍和来自量子力学的基本概念,李奥纳特·苏士侃的书“量子力学:理论最小值”对于只有一点线性代数作为先决条件的新人来说相当不错。

变分量子电路

某些量子电路的行为非常像我们从机器学习中了解并喜爱的神经网络。我们可以开发“变分量子电路”,模仿在深度学习中变得如此流行和有效的深度神经网络的行为。这些电路中的门的行为就像一层神经网络,我们可以以各种方式训练它们,以执行所有与 TensorFlow 或 Pytorch 中使用的神经网络相同的任务。

事实上,在许多情况下,量子方法在计算能力和准确性方面提供了极大的改进。即使经典地模拟这种方法,也显示出高达 100 倍的性能提升,正如在 TensorNetwork 的应用中所看到的那样,这是一个由谷歌建立的库,它使用 TensorFlow 作为后端,允许用户用张量网络取代神经网络的层。如果你不熟悉张量网络是什么,看看我的另一篇文章,关于它们如何被用来模拟量子电路,以及它们如何被谷歌和其他人用于机器学习

好的,所以量子电路可以像神经网络一样被训练,可以执行神经网络可以执行的任务。然后呢?那么你可以在一台真正的量子计算机上运行它!我知道,你读过的大部分新闻都说量子计算还需要几年时间,实际应用还不清楚。这些信息已经过时,而且非常不准确。不相信我?试试 IBMQ 量子体验自己看吧。IBM 目前允许用户注册一个免费账户,在 Qiskit 中开发代码,然后可以在 IBM 的量子计算机上运行。其实我有一个 Github 教程 repo 给大家展示如何使用开源软件 PennyLane 来执行各种量子机器学习任务!让我们来看一个例子。

金融科技和时间序列

正如我们在下面看到的,量子神经网络,基于草莓地的光子量子计算,学习平滑有噪声的数据(红色部分)。

Noisy Sine Function

Trained Model on Noisy Sine Function

如果你不太了解金融科技(FinTech)或金融科技,它只是一个应用于金融和投资的科技术语。它可以是任何东西,从一个跟踪你的支出的应用程序到最新最棒的用于股票交易的机器学习模型我们的例子是用一维函数拟合时间序列数据的模型。特别是,这是一个来自 PennyLane 的经过修改的示例,它是根据一些合成数据以及一家澳大利亚制药公司大约 17 年来的一些药品销售数据进行训练的。数据已被重新调整,但在其他方面未被处理和更改。该模型花费了 12-24 小时来训练。训练模拟版本所花费的时间不应该令人惊讶,因为模拟量子电路对于经典(基于比特的)计算机来说通常是相当困难的。模型学习的函数的结果可以用红色显示。

Pharmaceutical Sales Data 1991–2008

Trained Model Prediction (in red)

量子机器学习的应用不再是对未来的预测,它们是现实,而且非常有趣!这里应该提到几件事。首先,执行这些计算所需的量子位数量完全在当前量子计算硬件的能力范围之内。其次,这不仅是我们可以在当前的量子计算机上执行的任务,而且我们在当前的硬件上实际上有足够的量子位来使用一种叫做“量子纠错”的东西这是一种将冗余信息编码成多个量子位的方式,从而减轻计算中的误差(感兴趣的读者也可以参考“拓扑码的量子计算”了解量子纠错的介绍)。使用量子纠错所需的量子位数量取决于问题。因此,在某些情况下,我们能够在当前的硬件上实现纠错。当我们考虑到许多量子机器学习算法,如我在 Github 上的二进制分类器教程,只需要一个量子位,而即使是 IBM 最基本的公开可用硬件也有五倍于此的量子位时,不难看出我们很容易看到量子计算机在时间序列函数拟合和分类问题等方面的实际应用。看到企业开始投资将量子机器学习集成到他们的商业模式中,纯粹是为了帮助他们理解这项技术在这一点上如何以及为什么有用。

如果你有想法要分享,有问题,或者你需要量子机器学习的咨询服务,请通过 LinkedIn 联系作者,访问奇点网站,或者查看 Github 教程

使用 Amazon Athena 从 S3 文件中查询数据

原文:https://towardsdatascience.com/query-data-from-s3-files-using-aws-athena-686a5b28e943?source=collection_archive---------3-----------------------

亚马逊雅典娜被定义为“一种交互式查询服务,它使得使用标准 SQL 直接在亚马逊简单存储服务(亚马逊 S3)中分析数据变得容易。”因此,这是另一个用于存储在 S3 的大型数据集的 SQL 查询引擎。这与其他 SQL 查询引擎非常相似,比如 Apache Drill。但与 Apache Drill 不同,Athena 只能从亚马逊自己的 S3 存储服务中获取数据。然而,Athena 能够查询各种文件格式,包括但不限于 CSV、Parquet、JSON 等。

在本帖中,我们将看到如何使用存储在 S3 的样本数据集作为在 Athena 中设置一个表。csv 文件。但是为此,我们首先需要示例 CSV 文件。你可以在这里下载

下载完文件后,在 AWS S3 中创建一个新的 bucket。我建议创建一个新的桶,这样你就可以专门使用这个桶来尝试雅典娜。但是您也可以使用任何现有的存储桶。

下载完文件后,在 AWS S3 中创建一个新的 bucket。我建议创建一个新的桶,这样你就可以专门使用这个桶来尝试雅典娜。但是您也可以使用任何现有的存储桶。

所以,现在你已经有了 S3 的文件,打开 Amazon Athena。您可以选择在 Athena 主页上创建一个表。我的看起来有点像下面的截图,因为我已经有几个表了。从截图中可以看出,创建表格有多种选择。在这篇文章中,我们将坚持基本原则,选择“从 S3 桶数据创建表”选项。所以,现在你已经有了 S3 的文件,打开 Amazon Athena。您可以选择在 Athena 主页上创建一个表。我的看起来有点像下面的截图,因为我已经有几个表了。从截图中可以看出,创建表格有多种选择。在这篇文章中,我们将坚持基本原则,选择“从 S3 桶数据创建表”选项。

选择该选项后,您将被重定向到创建表的四步过程。让我们简单地看一下这些步骤。

第一步:姓名和地点

正如您在上面的屏幕中看到的,在这一步中,我们定义了数据库、表名和 S3 文件夹,该表的数据将来源于该文件夹。如果您已经有一个数据库,您可以从下拉列表中选择它,就像我所做的那样。如果没有,您可以选择从这个屏幕创建一个数据库。

接下来,为表提供一个名称。对于这个例子,我将表格命名为 sampleData ,只是为了保持它与我使用的 CSV 文件相同。

接下来,您必须提供存储文件的 S3 文件夹的路径。注意不能提供文件路径,只能提供文件夹路径。因此,该文件夹中具有匹配文件格式的所有文件都将被用作数据源。由于我们只有一个文件,我们的数据将仅限于此。在这篇文章中,我们将忽略加密选项。

我们还要注意,Athena 不会将这些源文件中的任何数据复制到另一个位置、内存或存储中。每个查询都是针对原始数据集运行的。

第二步:数据格式

这是非常直接的一步。您只需选择数据源的文件格式。因为我们使用的是 CSV 文件,所以我们将选择 CSV 作为数据格式。

第三步:列

在第三步中,我们定义数据集中每个文档/记录的“列”或字段。这是必需的,以便 Athena 知道我们正在处理的数据的模式。此处未定义的任何字段或列,或者名称中有拼写错误(即配置错误)的字段或列,将被忽略并替换为空值。因此,请确保正确配置列。

如果您的数据集有太多的列,并且单独配置它们变得很繁琐,您也可以批量添加列。你会在页面底部找到选项。例如,我们示例中的批量配置如下所示:

_id string, string1 string, string2 string, double1 double, double2 double

如您所见,格式非常简单。您可以指定列名,后跟一个空格,再后跟该列中的数据类型。列定义用逗号分隔。

第四步:分区

这一步有点高级,处理分区。因为我们的数据很小,也因为这超出了这篇文章的范围,我们现在跳过这一步。所以忽略这一步,确认剩下的配置。

您的 Athena 查询设置现在已经完成。您将被带到查询页面。这里,您将获得 CREATE TABLE 查询,该查询用于创建我们刚刚配置的表。您不必运行这个查询,因为表已经创建并在左窗格中列出。此处显示的查询仅供您参考。也许下次您可以手动创建这个查询,而不是在控制台中经历三到四个步骤。

现在剩下的就是查询表,看看我们的配置是否合适。为了测试这一点,我们将运行这个简单的 SQL 查询:

select * from sampledata limit 10;

运行该查询后,您的输出应该类似于下面的屏幕截图。

我们甚至可以在这个数据集上运行聚合查询。这里有几个例子:

select avg(double1) from sampledata;

select sum(double2) from sampledata limit 20;

差不多就是这样。现在,您可以在 Athena 的 S3 中对基于文件的数据源运行 SQL 查询。当你必须分析在 S3 以多个文件形式存储的大量数据集时,这非常方便。根据数据在文件中的分布方式和文件格式,您的查询将非常高效。你可以在 S3 查询数百 GB 的数据,并在几秒钟内返回结果。甚至包含多个连接的复杂查询也能很快返回。或许我们改天会更详细地讨论这个问题。

3 在 Twitter 上关注我,了解更多数据科学机器学习,以及通用技术更新。此外,你可以关注我的个人博客,因为我在 Medium 之前发布了许多我的教程、操作方法帖子和机器学习的优点。

如果你喜欢我在 Medium 或我的个人博客上的帖子,并希望我继续做这项工作,请考虑在 Patreon 上支持我。

查询分段和拼写纠正

原文:https://towardsdatascience.com/query-segmentation-and-spelling-correction-483173008981?source=collection_archive---------17-----------------------

在英语中,人们通常输入由空格分隔的查询,但有时不知何故,这个空格被无意中遗漏了。找到单词边界的方法被称为查询分割。例如,我们可以很容易地破译

坚果巧克力

如同

无坚果巧克力

但是,机器不能,除非我们教他们。这里有一个证据:

Showing results of an unsegmented search query

因为我们没有失去我们的能力,我们的大脑不知何故直觉地和无意识地这样做。但是,在搜索领域,它会影响没有正确分割的特定查询的结果的精确度和召回率。让我们看看如何:

  1. 电子商务中的搜索引擎特别是基于倒排索引的,应该有索引的查询或者分析器【比如子字符串等等。]必须在索引链接到特定产品列表的产品属性时使用。但是,问题依然存在,这主要与查准率和查全率有关。如果我们将上述查询分为三部分,那么我们可以对三个查询词进行布尔搜索[使用 AND],即“nut”、“free”和“chocolates ”,结果是三个结果交集的产品列表,即只返回三个列表中包含的产品。因此提高了精度。
  2. 该查询也可能拼写错误

例如“nutfreechacolatas”或“skommedmilk”

在这里,我们可以看到巧克力的拼写是错误的。但是,为了纠正这一点,前提条件是识别分段,即单词边界,以便首先为拼写纠正算法提供输入。

No Results for an unsegmented query having misspelled words

3.在基于机器学习 NLP 的 查询理解 我们需要将正确分段和正确拼写的查询馈送到模型中,以便在找到搜索查询的意图时获得更好的准确性。我实现这些算法主要就是为了这个目的。

这里,我们看到拼写校正算法依赖于分词。所以,让我们先看看如何进行细分:

通过以几种方式分割字符串,可以实现查询分割。但是,等等,通过使用这种天真的方法,可以存在多少种可能的不同组合。实际上,它是指数的,对于长度为 n 的单词,它是{ 2^(n−1)} 可能的组合,因为对于给定的字符串将有(n-1)个边界。查询的有效和真实组合的最终列表将基于该组合是否由有效单词组成来决定,并且基于查询中最可能的单词组合(即具有最高概率的组合)来排序或分类。稍后将解释如何计算每个组合的概率。现在,使用这种简单的方法,查询“nutfreechocolates”(长度,n = 17)有 2 个⁶ = 65,536 个组合。随着查询长度的增加,它将无法扩展,并且需要大量的计算能力。为了更高效,我分析了两种算法:

动态编程方法:

在朴素方法中,我们做了一些类似的计算,一次又一次地寻找查询的前缀的最可能的段,该段可以被记忆以改进从指数(O(2^n)到多项式函数(O(n))的复杂性。我们通过一个例子来了解一下:

For query: **“isit” [Total Segment = 2^3 = 8]** It can be either segmented in 2 parts or 3 parts or 4 partsStart with 4: [Possible composition = 3C3 = 1]
"i" "s" "i" "t = P(i|'')*P(s|i)*P(i|t)*P(t|i)Start with 3: [Possible composition = 3C2 = 3]
"i" "s" "it" = P(i|'')*P(s|i)*P(it|s)
"is" "i" "t" = P(is|'')*P(i|is)*P(t|i)
"i" "si" "t" = P(i|'')*P(si|i)(P(t|si)"Start with 2: [Possible composition = 3C1 = 3] 
"i" "sit" = P(i|'')*P(sit|i)
"is" "it" = P(is|'')*P(it|is)
"isi" "t" = P(isi|'')*P(t|isi)where P(A|B) is conditional probability of happening of A given that B has already occured. The bigram probability is introduced for more context. Unigram probability can also be used to find the probability of composition.

这里,通过使用蛮力方法计算了 8 个组成。为了使用 DP 避免这种情况,每次在我们的程序进行递归调用来分割剩余的字符串之前,我们都要检查这个精确的子串以前是否被分割过。如果是这样,我们只需消除递归调用,并从缓存中检索该子串的最佳分割结果(在特定子串第一次被分割时存储在缓存中)。

在计算每个单词的概率得分时,我们假设这个单词是有效的,并且存在于字典中(如果这个单词无效,那么我们需要在这里应用拼写纠正)。一个单词的分数将是:

p(A)= freq(A)/freq 之和(所有字)

而 P(composition)= log(P(word 1))+log(P(word 2))+…其中组合由单词 1、单词 2 等组成。

因为,合成的朴素贝叶斯概率将是独立单词概率的乘积,即 P(AB) = P(A) * P(B)

如果这个词在字典中不存在,那么按照http://norvig.com/ngrams/ch14.pdf

P(A) = 10 /(频率(所有字的总和)* 10^len(A))

代码可以在这里找到:https://github.com/grantjenks/python-wordsegment

三角矩阵法;

代替记忆查询的前缀的所有组成,这里只有具有最高概率的前缀组成将被较低概率覆盖。这种方法在这里得到了更好的解释:https://towardsdatascience . com/fast-word-segmentation-for-noise-text-2c 2c 41 f 9 E8 da

S pelling 校正也可以使用许多方法来完成。但是,它们可能非常昂贵。在这里,我将讨论除简单方法之外的两种优化方法:

  1. Peter Norvig 方法:它包括通过对每次迭代中提供的查询使用插入、删除、替换和转置操作来生成 n 个编辑距离之外的候选项。然后,语言模型,其中如果在字典中找到,则计算在第一步中生成的可能候选的得分/概率,以及错误模型,其中字典中没有找到的单词将经历插入、删除、替换和换位操作的又一次迭代,并且将再次应用语言模型。但是,这是非常昂贵的,因为每次编辑生成的候选列表对于每个单词都会增加(54 n +25)倍。对于我们示例中的查询“nutfreechacolatas ”,长度为 17。因此,在计算编辑的第一次迭代中,将有 5417+25 = 943 个候选项。同样,在每个候选的第二次迭代中,可能的候选将是 54943+25 = 50,947。因此,它不会随着编辑距离的增加和查询时间的延长而扩展。
  2. 使用对称删除的拼写校正【sym spell】:这里,通过在在线处理查询之前使用预处理,已经优化了复杂度。在生产场景中,预处理任务需要时间,并且依赖于字典的大小,因此我们可以创建拼写纠正类的单例类,该类在第一次尝试创建字典的对象时加载字典。主要思想是通过仅从字典中删除查询中的字符以及要被纠正的给定查询并在中间相遇来生成候选。这里的四个操作将按以下方式处理:

a)删除和插入:从字典中删除一个字符相当于在给定的查询中添加一个字符,反之亦然。

删除(字典条目,编辑距离)=输入条目

字典条目=删除(输入条目,编辑 _ 距离)

b)替换和换位:从字典和给定查询中删除一个字符相当于替换,从字典和给定查询中删除两个连续字符相当于换位操作。

删除(字典条目,编辑距离)=删除(输入条目,编辑距离)

在这种方法中,我们需要计算由给定查询的删除操作生成的候选词和也由删除操作形成的词典词之间的编辑距离,因为编辑距离可能在两侧同时删除期间改变。比如对于单词:bank,经过预处理后,在字典中,bank = ban[编辑距离= 1]并且如果给定查询=“xban”。关于给定查询的删除,xban = ban[编辑距离= 1],但是 bank!=xban,因为两者之间的编辑距离为 2。

有几种计算编辑距离的方法:

  1. 汉明距离:它只允许替换,因此,它只适用于相同长度的字符串。
  2. 最长公共子序列(LCS) :只允许插入和删除。
  3. Levenshtein 距离:允许插入、删除、替换,但不允许换位。即转换 AC- > CA 将被替换计为 2 编辑距离。
  4. Damerau Levenshtein 距离:它允许我们正在进行的所有四种操作,以便生成候选。实际上,这种算法有两种变体:a)受限 Damerau-Levenshtein 距离(最优字符串对齐算法):相邻换位计为 1 次编辑,但子字符串不能编辑多次:ed("CA "," ABC") =3,有 2 次替换(CA- > AC)和 1 次插入(AC- > ABC)。b)真实 Damerau-Levenshtein 距离:相邻的转座算作 1 次编辑,子串可以编辑多次:ed("CA "," ABC") =2 带 1 次转座(CA- > AC)和 1 次插入 AC- > ABC。后者正在实施中。

使用真实 Damerau-Levenshtein 距离计算编辑距离的代码:可在此处找到:https://github . com/mammothb/symspellpy/blob/master/symspellpy/edit distance . py

这里,不是使用 2-d DP 来计算编辑距离,而是使用两个大小等于查询长度的 1-d 数组。在空间复杂度方面,这里进行了另一层优化。详细概述可以在这里找到:https://www . code project . com/Articles/13525/Fast-memory-efficient-Levenshtein-algorithm-2

该算法经过优化,具有恒定的时间复杂度。字典中所有可能删除的单词都被散列,并用它们的原始单词列表进行索引,以使搜索更快。该词典是通过使用三个来源创建的:1 .产品的品牌名称,2。产品的显示名称,3。先前搜索的前 n 千个关键字。

对于我们的用例,字典中包含大约 350,000 个单词,前缀长度 7 用于候选生成,对于平均长度为 8 个字符的查询,平均花费 5 ms。

感谢阅读。请务必阅读以前的故事,以了解更多信息,并继续关注空间的更多更新。

参考资料:

  1. https://en . Wikipedia . org/wiki/damer au % E2 % 80% 93 levenshtein _ distance
  2. https://en.wikipedia.org/wiki/Levenshtein_distance
  3. https://github.com/mammothb/symspellpy
  4. https://towards data science . com/symspellcompound-10 EC 8 f 467 c 9 b
  5. https://towards data science . com/fast-word-segmentation-for-noise-text-2c 2c 41 F9 E8 da
  6. https://towards data science . com/sym spell-vs-bk-tree-100 x-faster-fuzzy-string-search-spell-checking-C4 F10 d 80 a 078
  7. https://medium . com/@ wolfgarbe/1000 x-faster-spelling-correction-algorithm-2012-8701 fcd 87 a5f
  8. http://norvig.com/ngrams/ch14.pdf

结合使用 Python 和 SQL 查询英超联赛

原文:https://towardsdatascience.com/querying-the-premier-league-using-python-and-sql-combined-501cb9d9319a?source=collection_archive---------14-----------------------

通过 Python 从 Excel 到 MySQL,然后再回到 Excel

Image Courtesy of Chaos Soccer Gear via Unsplash

有时将 Excel 表格转换成 MySQL 数据库可能很有用。这种转换将允许使用简单的 SQL 查询来执行查询操作。使用 Python,我们可以简单地将有限的 Excel 电子表格转换成 MySQL 数据库。

为了证明这是可能的,我将使用一个体育的例子。目睹了利物浦在欧洲冠军联赛(07/05/19)中击败巴塞罗那的胜利表现,我将选择一个离家近的例子,英超积分榜。

通过 Python 从 Excel 到 MySQL

我首先下载英超联赛表,并将其填充到一个 Excel 文件中,如下所示。重要的是,我将这个 Excel 文件保存为一个“逗号分隔值文件 (csv) ”。

首先,我使用 打开 函数和 read()方法 读取这个' Premier_league.csv '文件作为字符串, fString 。然后,我创建一个空列表,并在每个新行字符处分割这个字符串。然后,我在字符串中每个指定的逗号处进一步拆分该行,并添加到我的 fList。为了验证,我打印了我的列表。在这里,我可以看到我有一个嵌套列表,fList 的第一个元素代表列,第二个元素代表占据第一名的团队,以此类推。

接下来,我需要连接到我的数据库管理系统(DBMS)。为了实现这一点,我使用 pip 命令安装 mysql-connector,并将这个模块导入到我正在处理的脚本中。为了确认到 MySQL 的连接,我打印出 MySQLConnection 对象,该对象返回一个我的连接内存中的对象,确认连接已经建立。

我现在创建一个游标,用游标的execute method()创建我的数据库,‘football _ db’。当我切换到我的 MySQL 工作台,并刷新模式图标时,我可以看到我的数据库现在出现了!

确认了数据库配置后,我现在可以开始创建我的表了。首先,我需要为表创建列。我可以使用子字符串符号来分配我的每个列名。这也有助于提高可读性。例如,“Played”列对应于前面提到的嵌套 fList 中的元素号 0,在这个子列表中,它又对应于第一个元素[0]。

然后,我使用“创建表格”命令创建一个表格,并将其命名为 Football,因为这似乎是合适的。因为这个表列条目语句分布在几行中,所以我用三个字符串将它们括起来。对于每一列,我使用了使用 的替换字段语法。format() 方法,并为我的每一列分配一个合适的数据类型。例如,“已踢比赛”列的数据类型为“int ”,字符数限制为 2,这是基于每支球队在整个赛季中最多踢 38 场比赛。最后,我执行表生成,并切换到 MySQL Workbench 进行确认。

足球表中的列建立后,下一个目标是将每个队的行插入到表中。然而,这里必须小心。有必要删除第一行 fList[0],因为再次向表中插入列是没有意义的。

为了插入包含所有团队数据的行,我创建了一个名为“rows”的空字符串。然后,我使用 for 循环遍历 fList,并用括号替换方括号。这里使用另一个 if 语句在字符串中的所有行条目之间添加一个逗号。

接下来,我使用带有“VALUES”的“INSERT INTO”命令,将我的行连接到该语句,然后将该语句传递给游标的 execute 函数,然后将该函数提交给数据库。接下来,我需要通过再次切换到我的工作台并查看我的表来确认一切正常。

完美!现在我们可以开始在足球桌上执行查询了。首先,让我们看看谁在这个赛季赢了不到 15 场比赛,但累积了超过 45 分。我们只需在 WHERE 子句中定义条件语句,结果就会出现。

我们还可以使用一些 SQL 聚合函数来挖掘数据。例如,让我们通过检查联盟中的球队数量来确认事情正在进行。此外,让我们确定英超联赛中每支球队赢得的最少比赛,最高进球以及平均平局数。

将输出导出回 Excel

最后,如果我们能以上面显示的格式将这些数据导出到 Excel,那就太好了。虽然使用上面显示的导出选项卡很容易做到这一点,但作为奖励,我将演示如何用 Python 简单地编写这一点。

我首先决定我的文件名' my_football_stats ,并将其保存为一个 CSV 文件。然后,我在“写”模式下打开这个 CSV 文件,并创建一些标题,写入我的文件。接下来,我执行我的 SQL 查询,并在 cursor.fetchall()中捕获输出,我将它分配给变量 result。结果类型是一个列表。这意味着我可以通过索引结果列表从列表中提取元素。行[0]对应于队的数量,行[1],赢得的最少游戏等等。

当我运行这个脚本时,我可以检查我的目录中的文件,'my _ football _ stats【T1]'并读取 Excel 文件,如下所示。

结论

本教程已经展示了我们如何完成一个完整的循环。首先,从一个 Excel 文件开始,我们可以将它转换成一个数据库表,以便在数据库管理系统中进行查询。然后,我们可以输出我们希望运行回 Excel 的任何查询,以完成我们的转换。虽然使用 Python 的 Pandas 库可以做到这一点,但是通过创建关系表可以很容易地构建这个例子。例如,我们可以使用团队的名称作为惟一的 ID,并开始连接到特定于该团队的其他表。这样,我们就可以创建强大的关系数据库。

棋盘游戏问答

原文:https://towardsdatascience.com/question-answering-for-board-games-17065e17d935?source=collection_archive---------17-----------------------

建立一个问答系统来使用棋盘游戏规则手册

Photo by Christopher Paul High on Unsplash

什么是问答系统?

在自然语言处理中,我们不仅试图解释单词之间的关系,而且希望建立对文本的机器理解。问答是一门特殊的学科,旨在建立自动回答问题的系统,这些问题可以从文本中的信息得到回答。目标是回答一系列问题(事实、列表、定义等)。)通过返回相应的文本部分。可以想象,拥有一个分析问题和文本语义的模型是相当复杂的。最近的发展语言建模(如 BERT)有助于使这样的任务更加精确和健壮。

当考虑问答系统时,需要理解的一个更广泛的范例是开放域和封闭域。顾名思义,开放领域寻求解决任何问题,而封闭领域专注于某一特定领域。想想维基百科上的信息差异吧,它涵盖了所有的内容,而伍基培百科上的信息都是关于星球大战的。各有各的效用,只是看你的目标是什么。

因此,问题回答系统听起来相当惊人,但请注意,像许多其他自然语言处理领域一样,它仍在发展,也有不足之处。我不会在这里详细说明,但是如果你感兴趣,我鼓励你阅读文章 关于语义网中问答挑战的调查。 它很好地概述了这些系统仍然面临的一些挑战。

有哪些应用?

创建和支持一个问答系统可能是一项严肃的工作,所以首先花点时间思考为什么要创建它们是很重要的。最实际的用途之一是创建聊天机器人。我知道,我知道,他们不是每个人都喜欢的机械助手。不过,它们确实有潜力帮助客户或处理特定领域的问题,否则就像许多人担心的那样,需要人们实际阅读一些东西。

制作你自己的

您可以想到许多场景,其中您有一些文本形式的信息,并希望使其易于搜索,所以让我们尝试一个想法。自然地,我的大脑去了最实际的用途,棋盘游戏规则!

我经常玩游戏,偶尔会玩一些更复杂的策略游戏。有时候像这样的游戏的问题是所有的工作都投入到实际上知道如何玩它们。人们很容易忘记不同规则的复杂性,忘记发牌的数量,甚至忘记如何知道游戏何时结束。还有一个个人的烦恼是,当你想做一个战略性的举动,但想确保它是合法的,所以你必须查找它,并给别人一个机会来判断你在做什么。

如果你有一个工具,任何人都可以问一个问题,找到特定的规则,而不必手动挖掘文本,会怎么样?听起来像一个问题回答系统的情况!

为此,我们将使用一个名为 cdQa 的 Python 包。它有一套强大的功能来构建、注释和查询你自己的封闭领域问答系统。首先,您导入 cdQa 和一些不同的工具:

import pandas as pd
from cdqa.utils.converters import pdf_converter
from cdqa.utils.filters import filter_paragraphs
from cdqa.utils.download import download_model
from cdqa.pipeline.cdqa_sklearn import QAPipeline

pdf_converter:从 pdf 中提取文本(这个特定的转换器需要一个文件夹)。在本例中,我有一个名为“rules”的几个游戏的 rulebook pdfs 文件夹,将按如下方式实现:

boardgames_df = pdf_converter(directory_path=’rules/’)

filter_paragraphs:缩小范围,只在我们的文本中找到段落(本质上是在文本中寻找某个长度或其他参数)。要使用,您需要给它创建的整个数据帧:

boardgames_df = filter_paragraphs(boardgames_df)

download_model:找一个预先训练好的模特。我们将使用的模型是一个预训练的 BERT 模型,在 SQuAD 1.1上进行微调,这是一个阅读理解数据集,通常用于测试和基准测试问答系统的表现。要下载名为“models”的文件夹中的商店:

download_model(model=’bert-squad_1.1', dir=’./models’)

QAPipeline:创建我们的 QA 系统。这将使用预先训练的模型使管道适合您的语料库。

cdqa_pipeline = QAPipeline(reader='models/bert_qa_vCPU-sklearn.joblib')
cdqa_pipeline.fit_retriever(boardgames_df)

厉害!我们现在准备测试我们的 QA 系统。为了询问和查看我们的结果,我们使用管道实例的predict方法,该方法返回一个包含答案、文档标题、段落和分数的元组。以下是一个搜索示例:

query = 'How do you win at Villianous?'
prediction = cdqa_pipeline.predict(query)
print('Query: {}\n'.format(query))
print('Answer: {}\n'.format(prediction[0]))
print('Paragraph: {}\n'.format(prediction[2]))*Query: How do you win at Villianous?

Answer: you must explore your character’s unique abilities and discover how to achieve your own story-based objective

Paragraph: To win, you must explore your character’s unique abilities and discover how to achieve your own story-based objective. Each Villain Guide will inspire you with strategies and tips. Once you’ve figured out the best way to play as one Villain, try to solve another. There are six different Villains, and each one achieves victory in a different way!™*

看起来不错!对于我的进一步实现,我实际上更喜欢只返回段落,因为对于某些规则来说,拥有额外的上下文是有帮助的。cdQa 还有一些其他非常好的特性,比如能够手动注释文本,以及轻松导出管道以在网站上使用,所以我鼓励进一步探索它。

我将继续自己的工作,但是要查看这里显示的代码,你可以访问我的 GitHub 页面

企业用例的问题解答

原文:https://towardsdatascience.com/question-answering-for-enterprise-use-cases-70ed39b74296?source=collection_archive---------32-----------------------

在企业领域回答用户的问题仍然是一个具有挑战性的命题。企业越来越多地转向自动聊天助手来处理技术支持和客户支持交互。但是,这些工具只能成功地对它们接受过培训的问题进行故障诊断,这暴露了当今企业问答(QA)技术面临的日益严峻的挑战。

为了解决这个问题, IBM Research AI 推出了一个名为 TechQA 的新排行榜,它使用了来自用户在 IBM DeveloperWorks 上发布的真实问题。TechQA 的目标是促进对企业 QA 的研究,从相对较小的一组 QA 对中学习是更现实的情况。

TechQA 是首个解决企业 QA 用例的排行榜。IBM Research AI 预计将从企业领域创建额外的用例,以促进对这一关键能力的额外研究。

QA 背景

我们可以根据问题的特点和对应的答案来区分以下几类 QA 问题。相对较短的问题(少于 12 个单词)与较长的问题(从 10 到 50 个单词或更多)有很大的不同。)如今,在 IT 等企业支持环境中,更长的问题会越来越多,典型问题的中值长度为 35 个单词。

答案也可以被分割成 I)一个到大约五个单词的短(仿真陈述)连续文本跨度,ii)从大约六个单词到一个句子的更长的答案,或者 iii)甚至更长,例如一个到几个段落。在 IT 支持中,答案的中值长度约为 45 个词。

现有 QA 排行榜

简短问题/简短回答语料库的例子是成功的 SQuAD v1.1(大约 70 个提交)和 v2.0(大约 60 个提交)阅读理解排行榜[i,ii],其中提供了维基百科的一段话以及一个问题,例如“哪个 NFL 队在超级碗 50 上代表了 AFC?”。在大约两年的时间里,该系统从 50 年代中期改进到 90 年代中期,代表了任务的相对快速进展。

然而,在 v1.1 版上表现最好的系统非常弱,当问题被稍微修改为在提供的文档中没有答案时就崩溃了。当用对抗性问题进行测试时(当大约 50%的问题在文章中没有答案时),F测量性能下降超过 20 点。

SQuAD v2.0 是 2018 年年中推出的,带着这样的对抗性问题。F 测量值开始时大约为 70%,在大约一年的时间里迅速提高到大约 90%。然而,由于数据中的基本设计缺陷,即使是顶级的 SQuAD v2.0 系统对于现实世界的应用来说也仍然很弱。也就是说,这些问题是在“机械怪人”看了包含答案的文章后产生的。这种观察偏差造成了问题中的单词和答案的上下文之间的高度重叠。

为了解决这种观察偏差,通过收集用户对谷歌搜索引擎的问题,然后使用 turkers 找到答案,创建了一个名为 Natural Questions [iii]的新排行榜。当在自然问题排行榜上测试团队系统时, F 度量急剧下降到 6%(在简答题上——对于团队 1.1 版系统是 2%),这说明了团队训练系统的脆弱性。

自然问题排行榜上的最高评分系统目前在 IBM Research AI GAAMA 系统[iv]在不到六个月的时间里(2019 年 7 月)达到了大约 60%的简短答案的 F 测量值,自 2019 年初开始在 F 测量 52%的简短答案以来。IBM Research AI 正在继续监控这些系统,看看它们需要多长时间才能在这项任务上接近人类的表现。

另一个需要考虑的方面是:证明(或找到)一个答案可能需要从不同的文档中找到几个片段来确定正确的答案。这就是所谓的多跳问答任务。HotpotQA [v]是一个排行榜,关注需要几个部分来确定答案的问题。在一年多一点的时间里,F 指标从 52%提高到 71%。然而,HotpotQA 受到观察偏差问题的困扰,该问题是在阅读包含答案的文档后产生的。

IBM Research AI TechQA 语料库

TechQA 语料库强调了自动化客户支持领域的两个现实问题。首先,它包含用户在技术论坛上提出的实际问题,而不是专门为竞赛或任务生成的问题。其次,它具有真实世界的规模— 600 个培训、310 个开发和 490 个评估问题/答案对—因此反映了在企业用例环境中创建标记数据集的成本。

因此,TechQA 旨在刺激领域适应方面的研究,而不是作为从头构建 QA 系统的资源。该数据集是通过在 IBM Developer 和 IBM DeveloperWorks 论坛上搜索已发表的 IBM Technote(解决特定技术问题的技术文档)中的问题及其公认答案而获得的。

除了问答对之外,TechQA 还提供了大约 80 万条公开可用的 Technotes 作为配套资源,以支持领域适应研究(例如,预训练/微调上下文相关的向量嵌入)。

对于 TechQA 来说,基于 IBM Research AI 针对自然问题的简短答案的顶级 performing⁴ GAAMA 系统,答案的 F 度量为 53%,略高于总是回答 No_answer 的系统的 50%。GAAMA 系统在 TechQA 训练集(600 个 QA 对)上进行了微调。)

关于 TechQA 任务和排行榜的更多细节可以在 ibm.biz/Tech_QA 的找到。

参考文献

[i] Pranav Rajpurkar、、Konstantin Lopy-rev 和 Percy Liang。小队:机器理解文本的 10 万+题。2016 年自然语言处理经验方法会议论文集,2016。

[ii]知道你所不知道的:无法回答的问题。Pranav Rajpurkar,Robin Jia 和 Percy Liang。2018 年计算语言学协会第 56 届年会论文集。

【三】自然问题:问答研究的标杆。汤姆·科维亚特科夫斯基、詹尼玛利亚·帕洛玛基、奥利维亚·雷德菲尔德、迈克尔·科林斯、安库尔·帕里克、克里斯·阿尔贝提、丹妮尔·爱泼斯坦、伊利亚·波洛苏欣、马修·凯尔西、雅各布·德夫林、肯顿·李、克里斯蒂娜·n·图塔诺瓦、Llion Jones、张明伟、戴、雅各布·乌兹科雷特、阔克·勒、斯拉夫·彼得罗夫。计算语言学协会汇刊,2019。

[iv]首席财务官:构建生产 NLP 系统的框架,Rishav Chakravarti,Cezar Pendus,Andrzej Sakrajda,Anthony Ferritto,潘麟,Michael Glass,Vittorio Castelli,J . William Murdock,Radu Florian,Salim Roukos,Avirup Sil。2019 自然语言处理经验方法会议录(EMNLP),Demo Track,2019。

[v] HotpotQA:一个用于多样化、可解释的多跳问题回答的数据集,杨,彭琦,张赛正,Yoshua Bengio,,Ruslan Salakhutdinov,Christopher D. Manning2018 自然语言处理经验方法会议论文集,2018 年 10-11 月。

[1]“丹佛野马”是摘录的答案。

[2]请注意,最先进的红色曲线上的蓝点代表最早达到相应最先进水平的时间。

[3]这些多跳问题在创建自然问题排行榜时已被删除。

[4]截至 2019 年 10 月 28 日排行榜在https://ai.google.com/research/NaturalQuestions

伯特、XLNET、XLM 和迪沃伯特使用简单变压器回答问题

原文:https://towardsdatascience.com/question-answering-with-bert-xlnet-xlm-and-distilbert-using-simple-transformers-4d8785ee762a?source=collection_archive---------7-----------------------

问题:如何使用变形金刚进行问答?回答:简单的变形金刚,咄!(看到我在那里做了什么吗?)

Photo by Camylla Battani on Unsplash

自然语言处理中的问题回答

背景:问答(QA)是信息检索和自然语言处理(NLP)领域中的一门计算机科学学科,它涉及到构建自动回答人类用自然语言提出的问题的系统。

人类:什么是问答系统?
系统:自动回答人类用自然语言提出的问题的系统

QA 在大量的任务中有应用,包括信息检索、实体提取、聊天机器人和对话系统等等。虽然回答问题可以有多种方式,但最常见的问答方式可能是从给定的上下文中选择答案。换句话说,系统将从正确回答问题的上下文中挑选一个范围的文本。如果无法从上下文中找到正确答案,系统将只返回一个空字符串。

使用预先训练的 Transformer 模型进行迁移学习在 NLP 问题中已经变得无处不在,问答也不例外。考虑到这一点,我们将使用 BERT 来处理问答任务!

我们将使用简单变形金刚库来轻松处理变形金刚模型。

[## ThilinaRajapakse/简单变压器

这个库是基于 HuggingFace 的变形金刚库。简单的变形金刚让你快速训练和…

github.com](https://github.com/ThilinaRajapakse/simpletransformers)

简单的变形金刚是建立在高超的拥抱脸变形金刚库之上的。

设置

  1. 这里安装 Anaconda 或 Miniconda 包管理器。
  2. 创建新的虚拟环境并安装软件包。
    conda create -n simpletransformers python pandas tqdm
    conda activate simpletransformers
    如果使用 cuda:
    conda install pytorch cudatoolkit=10.0 -c pytorch
    其他:
    conda install pytorch cpuonly -c pytorch
    conda install -c anaconda scipy
    conda install -c anaconda scikit-learn
    pip install transformers
    pip install seqeval
    pip install tensorboardx
  3. 如果您使用 fp16 培训,请安装 Apex。请遵循此处的说明。(从 pip 安装 Apex 给一些人带来了问题。)
  4. 安装简单变压器。
    pip install simpletransformers

数据集

我们将使用斯坦福问答数据集(SQuAD 2.0) 来训练和评估我们的模型。SQuAD 是一个阅读理解数据集,也是 QA 模型的标准基准。该数据集在网站上公开提供。

下载数据集并将文件(train-v2.0.json,dev-v2.0.json)放在data/目录中。

数据准备

为了在简单的转换器中执行 QA,数据必须以正确的格式保存在 JSON 文件或 Python 字典列表中。

如果使用 JSON 文件,这些文件应该包含一个字典列表。字典代表一个上下文及其相关的问题。

每个这样的字典包含两个属性,"context""qas"

  • context:提问的段落或文本。
  • qas:问答列表。

问题和答案被表示为字典。qas中的每个字典都有以下格式。

  • id : (string)问题的唯一 ID。在整个数据集中应该是唯一的。
  • question:(字符串)一个问题。
  • is_impossible : (bool)表示是否能从上下文中正确回答问题。
  • answers:(列表)问题正确答案列表。

单个答案由具有以下属性的字典表示。

  • answer:(字符串)问题的答案。必须是上下文的子字符串。
  • answer_start : (int)上下文中答案的起始索引。

我们可以很容易地将球队数据转换成这种格式。

问答模型

Simple Transformers 有一个类,可以用于每个受支持的 NLP 任务。这个类的对象用于执行训练、评估(当基本事实已知时)和预测(当基本事实未知时)。

这里,我们创建一个QuestionAnsweringModel对象,并设置超参数来微调模型。第一个参数是型号类型,第二个是型号名称。

args参数接受一个可选的 Python 字典,其中包含超参数值和配置选项。我强烈推荐在这里查看所有选项。

默认值如下所示。

要加载一个先前保存的模型而不是默认模型,您可以将 model_name 更改为包含已保存模型的目录的路径。

model = QuestionAnsweringModel('bert', 'path_to_model/')

培养

训练模型是一行程序!只需将train_data传递给train_model函数。

您还可以通过向train_model方法传递一个包含相关属性的dict来更改超参数。注意,这些修改将持续甚至在训练完成后。

train_model方法将在每 n 步创建一个模型的检查点(保存),其中 nself.args['save_steps']。训练完成后,最终模型将保存到self.args['output_dir']

估价

dev 数据的正确答案没有在小队数据集中提供,但是我们可以将我们的预测上传到小队网站进行评估。或者,您可以将训练数据分成训练和验证数据集,并使用model.eval_model()方法在本地验证模型。

对于本指南,我将简单地把预测上传到小队。

分解这些代码,我们读入开发数据,将其转换成正确的格式,获得模型预测,最后以所需的提交格式写入 JSON 文件。

结果

使用这些超参数获得的结果如下所示。

"exact": 67.24500968584182, 
"f1": 70.47401515405956, 
"total": 11873, 
"HasAns_exact": 64.1025641025641, 
"HasAns_f1": 70.56983500744732, 
"HasAns_total": 5928, 
"NoAns_exact": 70.3784693019344, 
"NoAns_f1": 70.3784693019344, 
"NoAns_total": 5945

小队 2.0 是一个具有挑战性的基准,这反映在这些结果中。一些超参数调整应该会提高这些分数。同样,使用一个large模型而不是base模型也会显著提高结果。

问题对识别

原文:https://towardsdatascience.com/questions-pairs-identification-f8abcafb5b17?source=collection_archive---------7-----------------------

没有愚蠢的问题…只有重复的问题!

背景

你有一个迫切的问题——你登录 Quora,发布你的问题,然后等待回复。有可能你问的确实是独一无二的,但通常如果你有问题,别人也会有。你有没有注意到 Quora 告诉你一个类似的问题已经被问过了,并且给了你链接让你直接找到它?Quora 如何发现你刚才问的问题与之前已经问过的其他问题相匹配?

出于对这个问题的好奇,我和我的团队——Jui GuptaSagar Chadha崔婷 Zhong 决定参加 Kaggle Quora 重复问题挑战赛。目标是使用复杂的技术来理解问题语义并突出重复(相似)的问题。

但是为什么一个公司想要强调重复的问题呢?

  1. 更便宜的数据存储 —存储更少的问题!很明显!
  2. 改善的客户体验 —更快地回答问题。
  3. 重复使用内容 —如果一个问题之前已经回答过,那么对一个类似的问题使用相同的答案是非常高效的。

数据

数据集由大约 400,000 对问题组成,以 6 列的形式组织,如下所述-

id: 行 id

qid 1,qid 2: 问题对中每个问题的唯一 id

问题 1,问题 2: 问题的实际文本内容。

is_duplicate: 对于语义不同的问题,标签为 0,对于本质上只有一个答案的问题(重复问题),标签为 1。63%的问题对是语义不相似的,37%是重复的问题对。

A look at the data

数据探索

一项数据分析显示,问题中最常见的单词如下-

Word cloud for most common words

标记为不重复的重复问题

我们还发现了一些问题对,虽然重复,但在标签中被标记为 0。其中一些如下所示-

Duplicates marked as different

这些问题的标签被改为 1,以提高模型的准确性!

建模方法

检测一对问题之间的相似性的一个非常简单的方法是查看第一个问题中的独特单词,这些单词在第二个问题中也存在,作为两个问题中总单词的比率。然后,这个数字可以用在一个简单的模型中,例如逻辑回归,来预测重复问题和不同问题。

Word Similarity between questions

这种方法有局限性,因为两个几乎没有共同词汇的问题仍然有相同的意思。这可能是由于不同的句子结构、同义词的使用等。考虑句子“成为一名数据科学家需要做什么”和“成为一名优秀的数据科学家需要具备哪些素质”。虽然这些很少有共同的词(不包括停用词),但提问者的意图是相同的。为了超越比较句子中的单词,我们需要一种方法来理解所考虑问题的语义。

句子嵌入

生成句子嵌入是一个三步的过程

  1. 句子标记化 —使用我们数据中的所有问题,我们创建了一个大字典,将每个单词映射到一个唯一的整数索引。然后,这个字典用于将句子从字符串序列转换为整数序列。
  2. 零填充— 流程的下一步是确保模型(神经网络)的输入长度一致。为了做到这一点,我们为每个问题选择了一个最大长度——在我们的分析中是 25 个——然后将句子截断或填充到这个长度。在长度少于 25 个单词的句子的开头插入 0。
  3. 嵌入矩阵— 最后,我们使用预训练的单词嵌入将每个单词转换成向量表示。每个单词被转换成一个 300 长的向量。

Process to get sentence embedding

上面描述的过程从我们的文本数据中为问题 1 和问题 2 创建了维度为(200000,25,300)的数据张量。这有双重目的-

  1. 将文本字符串转换为可用于训练神经网络的数字
  2. 给出了我们的数据的表示,它对单词的含义和单词之间的关系进行了编码。利用简单的数学,我们就可以确定两个词的意思是相似还是完全相反。

如此创建的数据张量然后被发送通过神经网络模型进行训练,这将在下面描述。

包的埋设方法

然后,使用上述方法创建的嵌入将通过上面画出的网络传递。让我们看看上面的网络发生了什么-

时间分布密集层 —当我们想要对每个时间步长应用相同的变换时,这些用于时态数据。在我们的数据集中,每个问题有 25 个单词,对应 25 个时间步长。我们使用具有 300 个隐藏输入的密集层,因为我们的数据具有 300 维嵌入,所以我们得到该层的 90,000 + 300(偏差)= 90,300 个权重。问题 1 和问题 2 都通过相似的时间分布层。

下图清楚地表明了这种转变—

Time Distributed Dense Layers

时间分布密集层中的 300 个隐藏单元(显示为橙色)中的每一个都与每个时间步长的单词向量(显示为蓝色)相连接,并产生更高阶的表示(显示为绿色)。所有密集层单元都具有非线性的“Relu”激活。

Lambda 层——Keras 中的 Lambda 就像 python 中的‘def’关键字——它们允许我们在模型中使用自定义层。我们在时间分布密集层之后获得的较高阶表示上使用λ层,以获得问题中所有单词的平均意义。

Lambda layers

计算平均值实质上是计算问题在 300 维中的聚合表示。这在这些维度上概括了整个问题的意义。Average 只是可能的聚合之一,还有其他可能的聚合,如 max、sum 等。

注意力接近的双 LSTM

上面提到的嵌入模型架构的简单包确实达到了相当好的准确性。那为什么还要费心使用双向 LSTM 和注意力层呢?

当我们回去手动检查导致最高错误分类的问题对时,我们发现这主要是由于较长的句子。这是有意义的,因为我们没有考虑一种方法来捕获和实现单词,把它们从以前和将来的状态转换到我们现在的状态。这需要实现由类似 LSTMs 的网络提供的自适应选通机制。在研究中,我们幸运地发现了一篇关于使用双向 LSTMs 进行关系分类的论文,它被用于图像字幕、问题回答等任务中。

现在来看模型,我们所做的改变包括在单词嵌入阶段后添加一个双向 LSTM,以将更高级的特征合并到我们的嵌入向量中。在这之后,与之前我们串联问题不同,我们通过在问题对之间进行相似性来实现注意力。

注意力层 —与之前的单词袋不同,注意力层包括问题之间的点积计算,然后是没有任何非线性的密集层。

完成建模后,我们是如何评价我们的模型的?

由于这是一个二元分类任务,我们使用二元交叉熵(对数损失)来计算我们的准确度。

二元交叉熵:

基线准确率为 63%,因为我们的数据就是这样分割的。这是我们建立的模型的模型性能。

Model accuracy for our analysis

未来工作

  • 对模型使用不同的预训练嵌入。例如 Word2Vec、fasttext
  • 在嵌入连接中尝试不同的相似性度量。例如曼哈顿距离
  • 提取并组合其他附加的 NLP 特征。例如常用词的数量/比例
  • 利用相同概念的另一个有趣的问题是使用上下文段落的问题回答。我们可以尝试一下。

参考

这些工作没有一项是我们自己能够完成的。查看以下参考资料,获取我们使用的所有重要资源:

请随时让我们知道您的想法和我们可以改进的方法!😃

使用 Python 快速收集脏数据

原文:https://towardsdatascience.com/quick-and-dirty-data-gathering-with-python-9d3d4b8cba13?source=collection_archive---------22-----------------------

前几天我去杂货店的时候,简直不敢相信自己的眼睛。另一家星巴克似乎一夜之间就在我家附近的街区开张了。还有…这家新的星巴克是 字面意思是 就在两个街区之间,每个街区都有他们自己的星巴克!

以新星巴克不断涌现的速度,我发现自己在想: “洛杉矶县会有多少家星巴克?”

快速的谷歌搜索并没有给我想要的东西。要么结果只是在洛杉矶市(而不是整个县),要么估计值已经过时 5 年以上。我知道我必须做什么:自己收集数据!

我决定从访问星巴克商店定位器开始,希望它能给我需要的信息。

Starbucks Store Locator

我得到了… 有点儿 …我想要的。我发现,通过在搜索栏中键入邮政编码,我得到了以该邮政编码为中心的 100 家星巴克商店的列表。

通过查看页面顶部的 URL,我发现可以使用哪个 API 调用(发送到星巴克网站的命令的别称)来访问以邮政编码 90815 为中心的 100 家商店的列表:

https://www.starbucks.com/store-locator?place=90815

基于此,我想出了一个如何获取洛杉矶县所有星巴克门店信息的计划:

1 获取洛杉矶所有邮政编码的列表

2。 对于每个邮政编码,调用上面的 API 并解析返回的 100 家星巴克门店

3。 从存储的大列表中删除重复项(因为一个 API 调用和下一个 API 调用之间可能有很多重叠)

4。 删除所有不在洛杉矶县的商店(因为有些邮政编码就在洛杉矶县的边界上,可能包括邻近县的商店)

听起来合理吗?我们开始吧!

首先,我想提供这个项目需要的 Python 库列表:

获取洛杉矶县所有邮编的列表

这个很简单,你可以从很多不同的来源得到这个列表。我选择了直接从县里拿。我将这些邮政编码(每行一个)加载到一个名为 laZips.txt 的文本文件中。

为每个邮政编码调用 API

接下来,我们要为我们收集的每个邮政编码调用 Starbucks Store Locator API:

Scraping all Starbucks stores in LA County

您可能已经注意到了神奇的' processResponse '函数,它获取星巴克返回的内容,并将该文本转换成 100 家商店中每一家的信息。实际上,这只是一堆文本处理,我鼓励您查看完整的代码。

此时,变量 allStores 是一个商店信息列表,每个信息看起来像这样:

删除重复的商店

一个问题是,我们的星巴克门店主列表 allStores ,将包含(可能很多)重复的门店。

没什么大不了的!让我们遍历并删除已经遇到商店 id 的所有商店。

此时,变量 laStores 不包含重复的商店。

移除洛杉矶县以外的商店

我们的名单还有一个问题。邮政编码可能在洛杉矶县的郊区,因此以该邮政编码为中心的 100 家星巴克店将包括邻近县的店。我们如何解决这个问题?

一种选择是在我们的商店信息中使用' City' 字段,并将其与我们收集的洛杉矶县的一些城市列表进行匹配。这可能行得通,但我担心在我们的数据和我们从网上获取的城市名称列表之间会有轻微的差异。

让我们用一种更直接的方法。也就是说,我们将使用洛杉矶县的 geojson 文件(基本上是一个 json 文件,它精确地定义了一个复杂的形状,如洛杉矶县)。我会把这个文件贴在我的 GitHub 上。

在进行数据清理之前,让我们制作一张地图,以确保我们确实需要担心洛杉矶县以外的商店。

是的 …很明显,我们在洛杉矶县(以蓝色突出显示)之外有商店。让我们摆脱他们!

让我们使用 keepLAStores 重新生成地图:

耶!问题修复。

(我很快会写一篇关于如何创建这样的地图的教程!)

咻!现在我们已经完成了所有工作,让我们将数据存储在一个 csv 中,以备将来再次使用:

那么…洛杉矶有多少家星巴克?

728。

本项目中使用的所有代码和必要文件都可以在这里找到。

快乐的数据采集!

快速代码来美化你的直方图和散点图

原文:https://towardsdatascience.com/quick-code-to-spruce-up-your-histograms-scatterplots-ca44b9e2777f?source=collection_archive---------19-----------------------

简单的图表是数据分析必不可少的可视化工具。如果你正开始学习如何用 Python 制作可视化效果,你可以对你的图形参数做一些小的调整,这将使它们更加突出。首先,导入 Pyplot 和 Seaborn 库。

选择 Matplotlib 颜色来照亮你的图表。

二。用选定的边缘颜色勾勒出直方图的轮廓。

import seaborn as sns
from matplotlib import pyplot as plt
%matplotlib inlineplt.rcParams["patch.force_edgecolor"] = True
plt.figure(figsize=(8,8)) #adjust the size of your graphsns.distplot(df["glucose"], bins= 20,color ='tomato',
hist_kws=dict(edgecolor="k", linewidth=2)) 
#modify colors, number of bins, and linewidth for custom looks

三。创建一个支线剧情网格,以便快速浏览。

sns.set_style('darkgrid',{'axes.edgecolor': '.9'},)
f, ax = plt.subplots(2,3,figsize = (16,7))
plt.rcParams["patch.force_edgecolor"] = True

vis1 = sns.distplot(df["pregnancies"],bins=10,color='mediumturquoise',
hist_kws=dict(edgecolor="magenta", linewidth=2.5),ax= ax[0][0])vis2 =
sns.distplot(df["glucose"],bins=10,color='mediumturquoise', hist_kws=dict(edgecolor="magenta",linewidth=2.5),ax=ax[0][1])vis3 = sns.distplot(df["bloodpressure"],bins=10,color='mediumturquoise', hist_kws=dict(edgecolor="magenta", linewidth=2.5),ax=ax[0][2])vis4 = sns.distplot(df["skinthickness"],bins=10,color='mediumturquoise', hist_kws=dict(edgecolor="magenta", linewidth=2.5), ax=ax[1][0])vis5 =
sns.distplot(df["insulin"],bins=10,color='mediumturquoise', hist_kws=dict(edgecolor="magenta", linewidth=2.5),ax=ax[1][1])vis6 =
sns.distplot(df["bmi"],bins=10,color='mediumturquoise', hist_kws=dict(edgecolor="magenta", linewidth=2.5),ax=ax[1][2])

四。选择标记形状、尺寸和色图以增加散点图和回归图的可读性。确定一个“色调”变量输入,以增加每个数据点的清晰度,或者以同样的方式使用“大小”。

plt.figure(figsize = (8,8))ax = sns.scatterplot(x = df.insulin, y = df.glucose, hue= df.bmi, size=df.bmi, sizes=(0,200), marker = ‘h’, palette=’plasma’, data=df)

plt.figure(figsize = (8,8))ax = sns.scatterplot(x = df.insulin, y = df.glucose, style=df.diabetes, hue=df.diabetes,palette= ‘husl’,
markers=[‘D’,’*’],size= df.diabetes,sizes=(200,100), data=df)

随机森林快速指南

原文:https://towardsdatascience.com/quick-guide-to-random-forests-5d2a6b233d1f?source=collection_archive---------40-----------------------

当我刚进入数据科学领域时,我听说过这些被称为随机森林的神话模型。我迫不及待地想了解更多。如果这听起来像你,请继续读下去。

Image source

很自然,在谈论森林之前,我们应该先谈谈树——也就是决策树。决策树(有时称为 CARTs,用于分类和回归树)是相对容易理解的监督机器学习模型。

这里有一个决策树的简单例子:根据下图,你适合还是不适合?

Simple Decision Tree (Image source)

你刚刚用决策树把自己分类为适合或不适合。我碰巧强烈反对吃披萨会让你不健康,但是嘿,这只是个例子。(在这篇文章中,我将只把这些模型作为分类器来讨论,因为这样更容易理解,但这些树模型也可以用作回归模型。)

决策树可以长出很多分支,直到每个分支都尽可能“纯粹”。(每个节点的纯度用基尼杂质量化。)如果让一棵树一直生长到每个叶节点都完全纯净,那么这些树就可以一直生长下去,直到它们看起来更像吊灯而不是树。

Overfit Decision Tree (Image Source)

如果决策树任其发展,你的模型将会不堪重负。有可能决策树非常适合您的训练数据,因此不会对新信息做出很好的响应。在这种情况下,这是非常典型的决策树,你的模型将有很高的误差方差。

随机森林是一种流行的模型,可以缓解决策树中的过度拟合问题。但是在深入研究随机森林之前,我需要说一些关于袋装决策树的事情,这是一个与随机森林密切相关的集合模型。

袋装决策树得名于“Boot strapAGaggregating”Bootstrapping 是替换随机抽样的实践。在数据科学中,bootstrapping 在许多不同的上下文中使用,但在这里,我们 bootstrapping 是为了生成更多的树。

Bootstrapping (Image source)

在上图中,您可以将左边的条形(有 4 个不同颜色的方块)视为原始样本。如果我们从原始样本中抽取一个相同大小的新样本,或者用替换随机抽样,我们可能会得到右边的顶条。请注意,第一个引导示例看起来与原始示例相似,但并不完全相同。然后,我们重复这个自举过程 n 次,每次从原始样本中随机取样替换,产生 n 个自举样本

Bagging (Image source)

自举之后,我们有了 n 个样本,在上图中用包含圆点的圆圈表示。从每个样本中,构建一个决策树。每个决策树生成自己的预测,然后汇总这些预测以生成总体预测。回到适合与不适合模型,如果对于给定的观察,66 棵树预测为“适合”,44 棵树预测为“不适合”,则该观察的整体预测为“适合”

(Image sources)

随机森林是一种特殊类型的袋装决策树。如上图所示,简单的套袋生产的树有些不同。然而,随机森林产生的树木更加多样化。自举过程与装袋过程完全相同,因此树中的额外变化一定来自过程中的其他地方。

事实上,随机森林中树的额外变化来自于每棵树是如何从它的引导样本构造的。在袋装决策树中,在构建每棵树的分支时考虑所有特征,而在随机森林中,在构建每棵树的分支时仅考虑随机的特征子集。这个过程被称为随机子空间方法,它使每棵树都不会过度拟合,从而减少了由于模型中的差异而产生的误差。

我希望这篇关于随机森林的简要描述能让您对该模型有一些基本的了解,并对您的进一步研究有所启发!

快速安装指南:AWS SageMaker 上的 Nvidia RAPIDS + BlazingSQL

原文:https://towardsdatascience.com/quick-install-guide-nvidia-rapids-blazingsql-on-aws-sagemaker-cb4ddd809bf5?source=collection_archive---------19-----------------------

RAPIDS 于 2018 年 10 月 10 日发布,从那时起,NVIDIA 的人们夜以继日地工作,为每个版本添加了令人印象深刻的功能。当前版本( 0.9 )支持的首选安装方法是 Conda 和 Docker ( pip 支持在 0.7 中被取消)。此外,在 Google Colab 中可以免费获得 RAPIDS it,并且还支持微软的 Azure 机器学习服务

然而,可能有像我一样的人想要/需要在 AWS SageMaker 中使用 RAPIDS(主要是因为我们的数据已经在 S3 上了)。 本指南旨在作为快速安装指南。它远非完美,但它可能会为您节省几个小时的试错时间。

我还将包括 BlazingSQL ,一个基于 cuDF 的 SQL 引擎。作为一名数据科学家,查询数据的能力非常有用!

要求:

在 SageMaker 上安装 RAPIDS 有两个主要要求:

  1. 显然你需要一个 GPU 实例。目前在 SageMaker 中只有两种类型的加速实例:ml.p2 (NVIDIA K80)和 ml.p3 (V100)实例。然而,由于 RAPIDS 需要 NVIDIA Pascal 架构或更新的架构,我们只能使用 ml.p3 实例。
  2. RAPIDS 需要 NVIDIA 驱动 v410.48+(在 CUDA 10 中)。AWS 5 月更新了驱动。因此,RAPIDS v0.7 是可以安装在 SageMaker 中的第一个版本。

安装程序

当前 RAPIDS 稳定版(0.9)的安装过程如下:

  1. 启动或创建您的 ml.p3 SageMaker 实例。一旦实例被服务打开它。在本指南的剩余部分,我将使用 JupyterLab。
  2. 在 JupyterLab 中: Git - >打开终端,打开 shell 并执行以下命令:
source /home/ec2-user/anaconda3/etc/profile.d/conda.sh
conda create --name rapids_blazing python=3.7
conda activate rapids_blazing 

我强烈建议创造一个新的环境。如果您尝试在 SageMaker conda python3 环境中安装 RAPIDS,将需要数小时来解决环境问题,并且还可能会产生奇怪的操作(例如,安装 RAPIDS 不支持的 python 2,等等。).

3.Conda 安装了 RAPIDS (0.9)和 BlazingSQL (0.4.3)以及一些其他的包(特别是需要 boto3 和 s3fs 来处理 S3 文件)以及 Sagemaker 包的一些依赖项,sage maker 包将在下一步进行 pip 安装。在 RAPIDS 版本中,dask-cudf 被合并到 cudf 分支中。解决这个环境大概需要 8 分钟:

conda install -c rapidsai -c nvidia -c numba -c conda-forge \
              -c anaconda -c rapidsai/label/xgboost \
              -c blazingsql/label/cuda10.0 -c blazingsql \
              "blazingsql-calcite" "blazingsql-orchestrator" \
              "blazingsql-ral" "blazingsql-python" \
              "rapidsai/label/xgboost::xgboost=>0.9" "cudf=0.9" \
              "cuml=0.9" "cugraph=0.9" "dask-cudf=0.9" \
              "python=3.7" "ipykernel" "boto3" \
              "PyYAML>=3.10,<4.3" "urllib3<1.25,>=1.21" \
              "idna<2.8,>=2.5" "boto" "s3fs" "dask" \
              "anaconda::cudatoolkit=10.0"

4.安装 Sagemaker 和 flatbuffers 包,并注册要在 JupyterLab 中使用的内核:

pip install flatbuffers sagemaker
ipython kernel install --user --name=rapids_blazing

5.等待大约一分钟,然后打开或创建一个新的笔记本,你应该能够选择新的内核:内核- >改变内核- >康达 _ 急流 _ 炽热。注意:请不要使用 rapids _ flashing 内核来代替 conda _ rapids _ blazing,因为如果使用该内核,BlazinSQL 将无法运行。

6.让我们首先导入 RAPIDS 和 BlazingSQL 包:

import cudf
import cuml
import dask
import pandas as pd
import dask_cudf
from blazingsql import BlazingContext
bc = BlazingContext()

我们应该得到一个“连接建立消息。

7.让我们做第一个测试来检查 cuDF 是否正常工作:

df = cudf.DataFrame()
df[‘key’] = [0, 1, 2, 3, 4]
df[‘val’] = [float(i + 10) for i in range(5)]
print(df)

8.测试累计:

df_float = cudf.DataFrame()
df_float[‘0’] = [1.0, 2.0, 5.0]
df_float[‘1’] = [4.0, 2.0, 1.0]
df_float[‘2’] = [4.0, 2.0, 1.0]
dbscan_float = cuml.DBSCAN(eps=1.0, min_samples=1)
dbscan_float.fit(df_float)
print(dbscan_float.labels_)

9.如果没有错误,我们已经成功导入并使用了基本的 cuDF 和 cuML 功能。下一步是读取和使用存储在 S3 的数据。例如,使用 gzip 压缩读取一些 csv 文件:

import boto3
import sagemaker
from sagemaker import get_execution_role
role = get_execution_role()
df= dask_cudf.read_csv(‘s3://your-bucket/your-path-to-files/files*.csv.gz’, compression=’gzip’)
df2=df.compute()

9.现在我们可以使用 BlazinSQL 来查询我们的数据:

bc.create_table(‘test’, df2)
result = bc.sql(‘SELECT count(*) FROM test’).get()
result_gdf = result.columns
print(result_gdf)

我将尝试在安装过程之外更新和扩展这个指南。同时,我得到了三个有趣的结果:

  • 与 pandas read_csv 相比,cuDF (v0.10) read_csv 提高了 7 倍。
  • 与 sklearn LogisticRegression 相比,cuML LogisticRegression 提高了 32 倍。
  • 与非 GPU xgboost(' tree _ method ':' GPU _ hist ')相比,GPU xgboost ('tree_method':'hist ')性能提高了 7 倍。

结论:

展望未来,RAPIDS 版本将为 AWS 用户提供一些不错的特性。例如,cudf.read_csv 将能够直接读取 s3 文件,dask-cudf.read_parquet 在读取 s3 文件时的一个错误已被修复,并将包含在 0.10 中。我感谢 RAPIDS 团队对我报告的一些 github 问题的迅速关注和解决。

欢迎对本指南提出任何意见。愿 GPU 加速您的分析!

推特:@艾文佐

领英:【https://www.linkedin.com/in/dr-iván-venzor-64322732/】T21

使用数据块激发火花的快速入门指南

原文:https://towardsdatascience.com/quick-start-guide-to-spark-with-databricks-d2d24a2f995d?source=collection_archive---------32-----------------------

从 Spark 获得结果只需几分钟,而不是几天

Apache Spark 是处理大量数据的强大框架,可能是最强大和最高效的。任何如此强大的工具都必然是复杂的,对于初学者来说可能很难使用。

当尝试用 Scala 开始使用 Spark 时,这种情况最为明显。很容易找到一些加载文件并运行一些查询的示例代码。但是请尝试在某个地方实际运行示例代码。

你可以用 sbt 构建工具在 Scala 中完成。这是一个不错的方法,但是如果你还没有准备好用 sbt 构建和运行 Scala 应用程序,安装了 Scala 和 sbt,你的计算机,可能还有一个 IDE,并且知道如何从头开始生成 sbt 项目,这可能就不那么容易了。如果你是一名 Scala 开发人员,这可能没那么难,尽管即便如此,这仍然比它需要的要难。

此外,在当今时代,当我们想要编写一些代码并快速获得一些结果时,我们通常不想创建一个完整的 sbt 或 Maven 或 Gradle 项目,我们只想打开一个 Jupyter 笔记本,复制并粘贴几行代码,然后按 shift 键返回。

但是尝试用 Scala 和 Spark 来做这件事。

您的第一选择可能是 Amazon Web Services 的 SageMaker,如果您正在使用 Python 和 scikit-learn,这是一个很好的选择。但是如果您正在用 Spark 做完全相同的事情——使用几乎完全相同的代码,那么祝您好运。SageMaker 中有一个 Spark 选项——但是开箱即用就不行!至少上次我尝试的时候,我得到了一个神秘的错误,然后在谷歌上搜索了一下,发现 Spark SageMaker 选项需要你创建一个 Spark 集群,并将其连接到笔记本电脑上。你知道怎么做吗?你想吗?从笔记本或错误中显然看不出来。

最后,你可以在你的笔记本上安装 Jupyter 笔记本,然后安装 sparkmagic 扩展(它有多个组件),然后希望所有的作品和所有的部分都以正确的方式指向彼此。我得到了这个工作,但它花了几天的时间在多方面挠头。幸运的是,他们也有一个 Docker 选项,所以如果你的笔记本电脑上安装了 Docker,你就可以(很可能)更快地完成这项工作。只要确保将一个本地目录挂载到正在运行的 Docker 实例上,这样就不会在每次重启机器时丢失您的工作!如果您还不熟悉 Docker CLI,您可能会很难学到这一课——如果您只是试图运行一些 Spark 示例代码,您可能不想考虑这一点。

必须有一种更好的方法来对一些本地数据运行一些 Spark 命令,幸运的是有这种方法。

输入数据块

Databricks 为 Spark 提供了 AWS 决定不提供的“像 SageMaker 一样简单”的选项。更好的是,社区版是免费的——具有讽刺意味的是,它运行在 AWS 上,AWS 本身会向您收取费用,让您做完全相同的事情,而您需要做更多的工作!

让我们开始吧。

首先,去community.cloud.databricks.com创建一个账户。单击“尝试数据块”并选择社区选项。

您将不得不创建一个(免费的)集群,但它只需要几次点击,如何做是非常明显的。点击左边的“集群”图标,创建一个集群,并给它一个名称,任何名称。因为这是您的第一个(目前也是唯一的)集群,所以名称是什么并不重要。您不必使用 Linux 命令行在某个文件系统中寻找它,这一切都是点击式的。

现在,点击左边的“数据砖块”图标,然后创建一个“新笔记本”选择 Scala 选项(除非您想要 Python ),然后选择您已经创建的集群。那是唯一的一个,所以选择它应该很容易。您可能需要单击左侧的“工作区”图标来打开笔记本,但仅此而已。现在,你有了一台运行 Scala 的笔记本,内置了 Spark。不,真的。唯一的痛苦是,只要你坚持使用免费选项,你将不得不每天重新创建一个集群(只需点击几下鼠标)。

为了用 Spark 做任何事情,你需要一个 SparkSession。如果您不知道这意味着什么,请不要担心——随着您对 Spark 越来越熟悉,您可以更深入地了解这一点,但目前它只是一个指向您的集群的对象,允许您运行 Spark 命令。在 Databricks 中,它只是被称为spark。你可以通过输入“spark”并按下 shift-enter 键来验证它在笔记本中是活动的。

如果你看到这样的东西,那么你有火花运行,你是好的。令人惊讶的是,如果你在 Databricks 之外尝试这种方法,仅仅到这里就需要做这么多的工作。

现在,让我们做一些有用的事情。让我们加载一些数据,提取一些见解,并保存到其他地方供以后使用。我将使用旧金山房价的一组数据,这些数据我已经用于其他项目。这只是一个简单的 CSV 文件,你真的可以使用任何 CSV 文件。

首先,通过点击左侧的“数据”图标,然后点击“添加数据”按钮,将文件上传到笔记本中,然后上传文件。选择并上传您的文件。请注意,您上传的文件将存储在 Databricks 系统的/FileStore/tables/[file]中。

我们现在可以读取文件了。

val df = spark
.read
.option("header", "true")
.option("inferSchema", "true")
.csv("/FileStore/tables/housing_data_raw.csv")

我在这里所做的只是告诉 SparkSession 读取一个文件,推断模式(数据的类型,例如字符串或整数),注意 CSV 在第一行有一个头(而不是第一行的数据),并给出文件的路径。运行该命令后,我们可以使用 Databricks 的显示功能快速查看我们的数据。

我们现在可以对 CSV 文件执行查询。不需要编写解析函数,不需要逐行循环。我们可以对 CSV 执行 SQL 查询。

首先,让我们将数据集注册为 Spark 中的临时表:

df.createOrReplaceTempView("mytable")

现在,我们可以直接对 CSV 文件运行 SQL 查询,就像它是一个数据库一样:

%sqlselect zipcode, count(zipcode) as count from mytable group by zipcode order by count;

这只是 Spark SQL 的一个示例,但这里的要点是,我们现在已经开始使用 SQL,在我们自己的沙箱中,只需几分钟就可以创建,而无需找到(或提供)关系数据库。

另一方面,如果您曾经花了几个月或几年的职业生涯来编写 SQL 查询,您(像我一样)可能会有许多糟糕的记忆,那就是根据用户输入将越来越复杂的变量串在一起。这些既难看又麻烦,而且极难支持和扩展。这就是火花的力量所在。我们可以在不编写任何实际的 SQL 查询的情况下执行与上面完全相同的查询。相反,我们可以通过在我们的数据帧上执行 Spark 查询函数,在 Scala 中编写 Spark 代码:

display(df.select($"zipcode").groupBy($"zipcode").count().orderBy($"count"))

这将显示与前面的原始 SQL 查询完全相同的结果。另外,注意display()函数是特定于数据帧的。当使用直接火花时,然后.show功能将显示结果(尽管没有所有的铃声和哨声),例如:

df.select($"zipcode").groupBy($"zipcode").count().orderBy($"count").show

现在,让我们查询更具体的信息。假设我们想要两居室房屋的平均价格(可能是房子、公寓等。)的邮政编码是 94109。在 Spark 中,这很简单:

import org.apache.spark.sql.functions._display(df.select($"lastsoldprice")
.filter($"zipcode"===94109)
.filter($"bedrooms"===2)
.select(avg($"lastsoldprice")))

让我们稍微分解一下这个查询。

首先,我们选择数据框中的lastsoldprice字段。接下来,我们过滤我们的数据帧,首先,它只包含zipcode为 94109 的值,其次,它只包含卧室数量为 2 的值。在每种情况下,我们都使用===,因为我们将值与一列值进行比较,而不是与单个变量进行比较。然后查询平均值lastsoldprice。注意必须导入avg功能。这里有一些细微之处你可能需要记住(或者查找),但是代码本身是不言自明的。

结果是一个新的 DataFrame,然后我们使用display函数显示它。

现在,让我们看看一些更复杂的查询。首先,让我们创建一个只包含我们需要的字段的数据帧:

val fineTune = df.select($"address", $"bathrooms", $"bedrooms", $"finishedsqft", $"lastsolddate", $"lastsoldprice", $"neighborhood", $"totalrooms", $"usecode", $"yearbuilt", $"zipcode")

从现在开始,每个查询都将变得更加高效,因为我们只查询和返回我们实际需要的字段。

接下来,我们可以为数据子集创建数据框架。例如,假设我们想要一个只包含任务区内单户家庭信息的数据框架:

val mission = fineTune.filter($"neighborhood"==="Mission").filter($"usecode"==="SingleFamily")

我们可能希望找到 2015 年出售的这些房屋的平均价格。我们可以从我们的mission数据帧开始,并从那里进一步查询以创建新的数据帧:

import org.apache.spark.sql.functions._
import java.text.SimpleDateFormatval mission2015 = mission
.withColumn("lastsolddateint", unix_timestamp($"lastsolddate","MM/dd/yy"))
.filter($"lastsolddateint" > new SimpleDateFormat("MM/dd/yyyy").parse("01/01/2015").getTime() / 1000)
.filter($"lastsolddateint" < new SimpleDateFormat("MM/dd/yyyy").parse("01/01/2016").getTime() / 1000)
.orderBy($"lastsolddateint".asc)display(mission2015)

最后,这一切看起来都很好,但是我们实际上如何把这些数据带走呢?Spark 一般假设你要在 Spark 里做所有的事情,做完了就要在某个地方写出来。因此,我们将把最终的数据帧写入另一个 CSV 文件:

mission2015
   .repartition(1)
   .write
   .format("com.databricks.spark.csv")
   .option("header", "true")
   .mode("overwrite")
   .save("/FileStore/Mission2015.csv")

这应该都是不言自明的,除了repartition(1)。简单地说,我们希望将集群中的所有分区作为单个分区写出。否则,如果我们的集群是这样设置的,我们可能最终会创建多个文件(每个分区一个)。

话虽如此,Spark 仍然使用这个 write 命令创建多个文件,如果您运行以下命令,就可以看到这一点:

%fs ls /FileStore/Mission2015.csv

但是如果你仔细观察上面的结果,很明显只有一个 CSV 文件。其余的都是 Spark 用于内部管理的东西。

现在,我们怎么拿到这份文件?这就像它应该的那样简单。显示数据帧,并下载:

注意底部的下载按钮——这是使用display命令显示的每个数据框的底部。只需点击该按钮,您将获得您的 CSV。

如果你真的想的话,你可以在 Excel 中使用各种过滤器和查询来完成所有这些工作。但是使用 Spark,您可以创建这些转换的管道(每个邻居、卧室数量等的组合一个管道)。这将查询并生成结果(平均价格或新数据帧/CSV 文件之类的集合),并针对万亿字节或更多数据的数据集执行此操作。只需扩展您的底层集群来支持这一数据量,无需更改代码。代码将已经设置为运行,并可以作为一个夜间我们的每小时工作自动化,如果这是你想要的。

这在 Excel 或 MySQL 中可不容易管理。

高斯过程回归快速入门

原文:https://towardsdatascience.com/quick-start-to-gaussian-process-regression-36d838810319?source=collection_archive---------0-----------------------

理解高斯过程回归(GPR)和使用 scikit-learn 的 GPR 包的快速指南

高斯过程回归(GPR)是一种非参数的贝叶斯回归方法,正在机器学习领域掀起波澜。GPR 有几个好处,可以很好地处理小数据集,并且能够提供预测的不确定性测量。

背景

与许多流行的监督机器学习算法不同,这些算法学习函数中每个参数的精确值,贝叶斯方法推断所有可能值的概率分布。让我们假设一个线性函数: y=wx+ϵ 。贝叶斯方法的工作原理是通过指定参数的p(w)、w ,并使用贝叶斯规则基于证据(观察数据)重新定位概率:

Calculating posterior distribution with Bayes’ Rule [1]

更新后的分布 p(w|y,X) ,称为 后验分布 ,因此结合了来自先验分布和数据集的信息。为了得到在看不见的感兴趣点的预测, x预测分布 可以通过用它们的计算后验分布加权所有可能的预测来计算[1]😗

Calculating predictive distribution, f is prediction label, x* is test observation [1]*

为了便于积分,通常假设先验和似然是高斯型的。使用该假设并求解预测分布,我们得到高斯分布,从中我们可以使用其均值获得点预测,并使用其方差获得不确定性量化。

高斯过程回归 是非参数的(不受函数形式的限制),因此 GPR 不是计算特定函数参数的概率分布,而是计算所有符合数据的容许函数的概率分布。然而,与上面类似,我们指定一个先验(在函数空间上),使用训练数据计算后验,并计算我们感兴趣点的预测后验分布。

有几个用于高效实现高斯过程回归的库(例如* scikit-learn、Gpytorch、GPy),但为了简单起见,本指南将使用 scikit-learn 的高斯过程包[2]。*

***import** sklearn.gaussian_process **as** gp*

在 GPR 中,我们首先假设在 之前有一个 高斯过程,这可以使用均值函数【m(x)】和协方差函数 k(x,x’)来指定:**

Labels drawn from Gaussian process with mean function, m, and covariance function, k [1]

更具体地说,高斯过程类似于无限维多元高斯分布,其中数据集的任何标注集合都是联合高斯分布。在这个 GP 先验中,我们可以通过选择均值和协方差函数来结合关于函数空间的先验知识。通过将标签分布和噪声分布相加,我们还可以容易地将独立、同分布的(I . I . d)【ϵ∨n(0,σ)合并到标签中。

资料组

数据集由观察值、 X、及其标签、 y、s 组成,分为“训练”和“测试”子集:

**# X_tr <-- training observations [# points, # features]
# y_tr <-- training labels [# points]
# X_te <-- test observations [# points, # features]
# y_te <-- test labels [# points]**

根据高斯过程先验,训练点和测试点的集合是联合多元高斯分布的,因此我们可以这样写它们的分布[1]:

GP prior rewritten: multivariate distribution of training and testing points

这里,K 是协方差核矩阵,其中它的项对应于在观测值处评估的协方差函数。以这种方式编写,我们可以利用训练子集来执行模型选择。

型号选择

模型选择 期间,选择并调整 GP 先验中的均值函数和协方差核函数的形式。均值函数通常是常数,或者为零,或者是训练数据集的均值。协方差核函数有很多选择:它可以有很多形式,只要它遵循一个核的性质(半正定和对称)。一些常见的核函数包括常数、线性、平方指数和 Matern 核,以及多个核的组合。

一种流行的核是常数核与径向基函数(RBF)核的组合,其针对函数的平滑性进行编码(空间中输入的相似性对应于输出的相似性):

Constant times RBF kernel function

这个内核有两个超参数:信号方差σ和长度尺度 l 。在 scikit-learn 中,我们可以从各种内核中进行选择,并指定它们的超参数的初始值和界限。

**kernel = gp.kernels.ConstantKernel(1.0, (1e-1, 1e3)) * gp.kernels.RBF(10.0, (1e-3, 1e3))**

在指定了内核函数之后,我们现在可以在 scikit-learn 中为 GP 模型指定其他选择。例如,alpha 是标签上 i.i.d. 噪声的方差,normalize_y 是指常数均值函数-如果为假,则为零;如果为真,则训练数据均值。

**model = gp.GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=10, alpha=0.1, normalize_y=True)**

调整协方差核函数的超参数的一种流行方法是最大化训练数据的对数边际似然。基于梯度的优化器通常用于提高效率;如果上面未指定,默认优化器是' fmin_l_bfgs_b' 。因为对数边际可能性不一定是凸的,所以使用具有不同初始化的优化器的多次重启(n _ restructs _ optimizer)。

**model.fit(X_tr, y_tr)
params = model.kernel_.get_params()**

如果需要,可以通过调用 model.kernel_ 来获得内核函数的调整后的超参数。get_params()

推理

为了计算预测的后验分布,数据和试验观察被排除在后验分布之外。同样,因为我们选择了高斯过程先验,计算预测分布是易处理的,并导致可以完全由均值和协方差描述的正态分布[1]:

Predictive posterior distribution for GPR [1]

预测是均值 f_bar,方差可以从协方差矩阵σ的对角线获得。请注意,计算平均值和方差需要对 K 矩阵求逆,这与训练点数的立方成比例。通过 sci-kit learn 的 GPR 预测功能,推理很容易实现。

**y_pred, std = model.predict(X_te, return_std=True)**

注意,返回的是标准差,但是如果 return_cov=True,则可以返回整个协方差矩阵。然后可以计算 95%的置信区间:高斯分布的标准偏差的 1.96 倍。

为了测量回归模型对测试观测值的性能,我们可以计算预测值的均方误差(MSE)。

**MSE = ((y_pred-y_te)**2).mean()**

参考文献:

[1] Rasmussen,C. E .,& Williams,C. K. I .,机器学习的高斯过程 (2016),麻省理工学院出版社

[2]f . Pedregosa,g . Varoquaux,a . gram fort,Michel,v . Thirion,b . Grisel,o .等人。艾尔。,sci kit-learn:python 中的机器学习 (2011),《机器学习研究杂志》

难度炸弹爆炸了吗

原文:https://towardsdatascience.com/quickblarks-62aa90169ff0?source=collection_archive---------22-----------------------

我想与你分享(通过一系列图表)当一个人在新鲜出炉的以太坊难度数据上发布像 Ed Mazurek 这样的世界级数据科学家时会发生什么。

你得到了 QuickBlarks(如果你想知道的话,这是“QuickBlocks”和“R”的组合)。如果你不知道“R”和 R 工作室,你应该知道。太神奇了。

在几乎没有任何解释的情况下,我将把“R”代码复制并粘贴到用于创建它的图表旁边。问艾德代码是什么意思。

逗号分隔的数据如下所示:

块号,时间戳,难度
11438269988,17171480576
21438270017,17163096064
31438270048,17154715646
41438270077,17146339321

在编写本报告时,已生成的 7,105,056 个数据块中的每一个都有一条记录。下面是一些初步的设置代码,用于读取数据并对其进行一些清理。

require(tidyverse)
require(scales)
require(dplyr)
require(magrittr)homestead.block <- 1150000
byzantium.block <- 4370000
bin_size <- 200
period_size <- 100000
sample_size <- 50000difficulty <- read_csv(‘difficulty-generated-1a.csv’) %>%
 filter(block.number > homestead.block) %>%
 mutate(block.bin = floor(block.number / bin_size) * bin_size) %>%
 mutate(fake.block =
   ifelse(block.number >= byzantium.block,
      block.number — 3000000,
      block.number) + 1) %>%
 mutate(period = floor(fake.block / period_size)) %>%
 mutate(bomb = 2 ^ period) %>%
 mutate(parent.difficulty = lag(difficulty)) %>%
 mutate(parent.ts = lag(timestamp)) %>%
 mutate(diff.delta = difficulty — parent.difficulty) %>%
 mutate(ts.delta = timestamp — parent.ts) %>%
 mutate(diff.sensitivity = diff.delta / difficulty) %>%
 mutate(ts.sensitivity = ts.delta / timestamp)current.block <- difficulty$block.number %>% tail(1)
current.bomb <- max(difficulty$bomb)

代码

这是我们第一个图表的代码:

difficulty %>%
    sample_n(sample_size) %>%
    group_by(block.bin) %>%
    ggplot(aes(x=block.number)) +
    geom_line(aes(y=diff.delta, color=’diff.delta’)) +
    geom_line(aes(y=bomb, color=’bomb’))

这是第一个图表,显示了前 710 万个块中每个块的difficulty中的delta。它还用红线显示了难度炸弹。你可以看到它又爬上来了。

下一个图表,是用这段代码制作的,

difficulty %>%
    sample_n(sample_size) %>%
    group_by(block.bin) %>%
    ggplot(aes(x=block.number)) +
    geom_line(aes(y=diff.sensitivity, color=’diff.sensitivity’))

显示难度计算对当前情况的“反应”。我们用diff.delta除以block.difficulty来计算sensitivity。我不确定,但我认为 jaggys 来自于难度值的计算方式。它捕捉到下一个最近的 10 秒来调整,所以 10,11,12,… 19 都给出相同的调整,但 20,21,22,…给出不同的调整。

Sensitivity vs. Block Number

下一个图表,由这个“R”代码生成,

difficulty %>%
 group_by(block.bin) %>%
 summarize(sum.diff.delta = sum(diff.delta), na.rm=T) %>%
 ggplot(aes(x=block.bin, y=sum.diff.delta)) +
 geom_line()

显示diff.delta值的累计和。可以清楚的看到前拜占庭难度炸弹发动的战斗。上,下,上,下。事实上,难度在目标附近徘徊正是难度计算器应该做的。它保持块的时序一致。

莱恩·雷蒂格想知道,由于当前链的散列率增加,难度炸弹的效果是否会被掩盖。我不确定(我什么都不确定),但自拜占庭以来积木难度的更广泛传播可能表明他的直觉是正确的。难度炸弹是不是藏在大黑静电里?

在下面的图表中,我们展示了一些用更多的“R”代码制作的其他东西。在本节中,我们计算数据块时间戳平均值的差值,或者数据块时间戳差值的平均值,然后根据之前的图表(如果你想理解,你必须问 Ed)。

difficulty %>%
 group_by(block.bin) %>%
 summarize(sum.diff.delta = sum(diff.delta, na.rm=T), mean.ts.delta = mean(ts.delta, na.rm=T)) %>%
 gather(key = vars, value = val, -block.bin) %>%
 ggplot(aes(x=block.bin, y = val)) +
 geom_line() +
 facet_wrap(facets = ‘vars’, scales = ‘free’, ncol = 1)

现在我们只是展示了一大堆看起来很酷的黑色锯齿的疯狂图表(坚持住,下面有一些有趣的东西)。

上面的图表是用这种几乎难以理解的代码制作的:

difficulty %>%
 group_by(block.bin) %>%
 summarize(sum.difficulty = sum(difficulty), sum.diff.delta = sum(diff.delta, na.rm=T),mean.ts.delta=mean(ts.delta, na.rm=T)) %>%
 mutate(percent.delta = sum.diff.delta / sum.difficulty) %>%
 gather(key = vars, value = val, -block.bin) %>%
 ggplot(aes(x=block.bin, y = val)) +
 geom_line() +
 facet_wrap(facets = ‘vars’, scales = ‘free’, ncol = 2)

最后,一些真正有趣的事情

10 月份,在 T4 举办的状态黑客马拉松上,艾德和我受到启发,着手解决以太坊难度计算的问题。他担心,当前链条的散列率比拜占庭爆炸前高得多,会使炸弹更长时间地模糊不清,然后,一旦爆炸,会让人们措手不及。

我们想看看他的直觉是否正确。

简单说说炸弹。它以指数增长曲线爆炸,每 100,000 块翻一番。这产生了一个锯齿曲线的效果,因为链条很难抑制上升,正如我们在之前的中讨论的

在下一组图表中,我们将数据分成 100,000 个数据块的存储桶,并将这些存储桶称为periods。(下面黑线显示的是电流period。)这种波动在下面的图表中很明显,我们也将数据分成分组:前拜占庭和后拜占庭。这使我们能够将两个爆炸的炸弹排在一起进行比较。

当我们这样看数据时,我们看到了什么?首先,我们看到后拜占庭时代的炸弹开始抬头。

difficulty %>%
 mutate(era = ifelse(block.number <= byzantium.block, ‘before byzantium’, ‘post byzantium’)) %>%
 sample_n(sample_size) %>%
 ggplot(aes(y = diff.sensitivity, x = period, color=block.number)) +
 scale_colour_gradient2(low = “red”, mid = “green”, high = “blue”, midpoint = byzantium.block, space = “Lab”, na.value = “grey50”, guide = “colourbar”) +
 geom_point(size = point_size) + 
 facet_wrap(facets = ‘era’, nrow = 2) +
 geom_vline(xintercept = 41)

上面的代码给了我们这个图表:

在这里,我想,我们终于找到了一些有趣的东西。虽然,我们还没完。

接下来,我们将后拜占庭时期的数据和前拜占庭时期的数据相互叠加。

我们现在看到的是,如果我们足够仔细地观察,紫色的小点(现在的子炸弹)比绿色的小点(以前的子炸弹)更低。

莱恩是对的。这一次,难度炸弹的效果会变得模糊不清,不像以前那么明显。这可能会让它的效果不太明显,直到爆炸。那要多久?炸弹什么时候来?我们已经在第 41 期了。最后一颗炸弹(见此图)现在开始显示减速。最后一枚炸弹现在已经开始加速了。我认为这一次也是如此,但它隐藏在更高的哈希速率后面。

结论

该叉了。

Thomas Jay Rush 拥有软件公司 QuickBlocks,其主要项目也被称为 QuickBlocks,这是一个软件库和应用程序的集合,能够对以太坊区块链进行实时、逐块的智能合同监控和分析。通过网站联系他。

利用 Streamlit 快速构建和部署仪表板

原文:https://towardsdatascience.com/quickly-build-and-deploy-an-application-with-streamlit-988ca08c7e83?source=collection_archive---------1-----------------------

细流

将您的 Streamlit 应用程序部署到 Heroku,展示您的数据解决方案

For my Board Game Exploration dashboard see https://bgexploration.herokuapp.com/

随着 Streamlit 的推出,为你的机器学习解决方案开发一个仪表板变得非常容易。

Streamlit 是一个开源应用框架,专门为使用 Python 的 ML 工程师设计。它允许你只用几行代码就能创建一个令人惊叹的应用程序。

我想借此机会展示您可以使用 Streamlit 构建的应用程序。但主要是向您展示使用 Heroku 将您的应用程序投入生产的必要步骤。

1.细流

使用 Streamlit 工具(如 Dash 和 Flask)的一些优势:

  • 它包含 Python 脚本;不需要 HTML 知识!
  • 创建漂亮的应用程序需要更少的代码
  • 不需要回调,因为小部件被视为变量
  • 数据缓存简化并加速了计算流水线。

看看这篇帖子,它可能会帮助你理解 Streamlit 的架构。而且,这个帖子

装置

使用以下命令可以轻松安装 Streamlit:

pip install streamlit

使用以下命令查看带有示例代码的应用程序演示:

streamlit hello

这样做会打开以下页面:

2.民众

上面的streamlit hello演示上面还有一些更复杂的在线演示供你试用。我将在下面列出一些(包括我的),这样你就会对可能性有所了解:

Udacity 自动驾驶汽车图像浏览器

该演示展示了如何使用不到 300 行代码将 Udacity 汽车数据集与对象检测结合起来,从而创建一个完整的 Streamlit 演示应用。

首先,安装 OpenCV 以便可以分析图像:

pip install --upgrade streamlit opencv-python

接下来,只需运行应用程序:

streamlit run https://raw.githubusercontent.com/streamlit/demo-self-driving/master/app.py

纽约市的优步皮卡

这是一个 Streamlit 演示程序,展示了如何交互式地可视化纽约市的优步皮卡。

安装 Streamlit 后,只需运行以下代码:

streamlit run https://raw.githubusercontent.com/streamlit/demo-uber-nyc-pickups/master/app.py

棋盘游戏探索

由于许多像我一样的桌游爱好者跟踪桌游比赛的分数,我决定创建一个允许探索这些数据的应用程序。您可以在这里实时查看这个应用程序,或者您可以按照下面的步骤在本地运行它。

因为我使用了几个. py 文件,所以您首先需要克隆存储库:

git clone [https://github.com/MaartenGr/boardgame.git](https://github.com/MaartenGr/boardgame.git) BoardGame

然后,只需转到该文件夹并运行 Streamlit:

cd BoardGame
streamlit run app.py

注意:如果你愿意,你可以使用你自己的数据,只需提供你的数据的 URL。

3.创建应用程序

在这一节中,我将演示如何创建一个简单的应用程序,因为这篇文章的主要目的是为您的项目准备部署

如果你想要更深入的例子,请查看 Streamlits API 或查看 thisthis 帖子,它很好地描述了它的许多特性。

但首先,让我介绍一些你可能会在自己的应用程序中使用的基本功能。

选择小部件

Streamlit 的主要特性之一是使用小部件。有许多可用的小部件,包括:

  • 选择框
age = streamlit.selectbox("Choose your age: ", np.arange(18, 66, 1))

  • 滑块
age = streamlit.slider("Choose your age: ", min_value=16,   
                       max_value=66, value=35, step=1)

  • 多选
artists = st.multiselect("Who are your favorite artists?", 
                         ["Michael Jackson", "Elvis Presley",
                         "Eminem", "Billy Joel", "Madonna"])

缓存

许多仪表板工具的问题是,每次选择一个选项或在页面之间切换时,数据都会被重新加载。幸运的是,Streamlit 有一个惊人的选项,允许您缓存数据,并且只在以前没有运行过的情况下运行它。

上面的代码显示您可以缓存您创建的任何函数。这可能包括加载数据,但也包括预处理数据或训练一次复杂的模型。

形象化

Streamlit 支持许多可视化库,包括:Matplotlib、Altair、Vega-Lite、Plotly、Bokeh、Deck。GL 和 Graphviz。它甚至可以加载音频视频

下面是一个展示牛郎星图的快速示例:

降价

就我个人而言,我是 markdown 的忠实粉丝,它有可能创造出好看的东西。幸运的是,我们可以只用一个函数生成 markdown:

注意:基于 dev 分支中的提交,st.latex 似乎即将到来!

Write 函数是 Streamlit 命令的瑞士军刀。它根据其输入表现不同。例如,如果你放入一个 Matplotlib 图形,它会自动显示给你看。

几个例子:

  • write( string ):打印格式化的降价字符串。
  • write( data_frame ):以表格形式显示数据帧。
  • write( dict ):在一个交互式小部件中显示字典。
  • write( keras ):显示一个 keras 模型。
  • write( plotly_fig ):显示一个 plotly 图形。

你可以在这里找到它的可能性的完整概述

4.应用程序

为了展示如何部署您的应用程序,我们首先需要创建一个基本的应用程序。这个例子将是一个简单的演示有两页。在主页上,它显示我们选择的数据,而探索页面允许您在牛郎星图中可视化变量。

下面的代码在工具条上给了你一个Selectbox,允许你选择一个页面。数据被缓存,因此不需要不断地重新加载。

运行代码streamlit run app.py将显示以下页面:

选择页面 Exploration 将向您显示以下可视化内容:

5.Heroku 部署

现在我们有了自己的应用程序,如果我们能把它放在网上的某个地方就好了。这样,您就可以向其他人展示您开发的应用程序。我们将通过将其部署到 Heroku 来实现这一点,Heroku 是一种平台即服务(PaaS),可用于在云中完全运行应用程序。

首先,确保您的应用程序文件夹中有以下文件:

.
├── app.py
├── requirements.txt
├── setup.sh
└── Procfile

你可以在 这里的 库中找到所有这些文件。

创建帐户

要部署该应用程序,您首先需要在 Heroku 这里创建一个帐户。别担心,托管你的应用程序是完全免费的

使用免费帐户的主要缺点是,如果超过半小时没有访问,网站就会关闭。但是,它会在您打开站点的那一刻重新启动。

安装 Heroku 命令行界面

接下来,您需要在这里安装 Heroku 命令行界面(CLI)。您将使用它来管理您的应用程序,在本地运行它,查看它的日志,等等。

登录 Heroku

这样做之后,打开你的cmd.execd到应用文件夹。然后,用heroku login登录 Heroku。您将被重定向到首选浏览器的登录屏幕。

部署应用程序

最后,当您的cmd在应用程序文件夹中打开时,首先运行heroku create来创建一个 Heroku 实例:

然后,用git push heroku master将所有代码推送到那个实例:

这将创建一个 Heroku 实例,并将应用程序文件夹中的所有代码推送到该实例。现在,应用程序应该已经部署好了。

运行heroku ps:scale web=1以确保至少有一个应用程序实例正在运行:

最后,使用heroku open打开您的应用程序;它将使用您首选的浏览器在应用程序名称生成的 URL 访问应用程序:

所有的代码都可以在这里找到:

**[## MaartenGr/streamlit_guide

此 repo 包含创建和部署您的 Streamlit 应用程序到 Heroku 的所有代码。

github.com](https://github.com/MaartenGr/streamlit_guide)**

如果您在部署到 Heroku 时遇到任何问题,请点击页面获取程序的详细概述。

如果你和我一样,对人工智能、数据科学或心理学充满热情,请随时在 LinkedIn 上添加我。

使用 ctags 快速导航 Python 库

原文:https://towardsdatascience.com/quickly-navigating-python-libraries-with-ctags-9924a0b9a82f?source=collection_archive---------11-----------------------

数据科学家使用 ctags 有效导航 Python 库的教程。

作为机器学习从业者,我经常使用开源的机器学习库,比如 fastaiscikit-learn 。在使用这些库一段时间后,您可能会想要做一些库目前不支持的事情(例如,创建一个定制的模型),但是您可能仍然想要使用许多库函数。比如我用 fastai/PyTorch 设计训练定制的深度学习模型。fastai 为读取数据提供了一个很好的框架,所以通常情况下,我仍然希望使用许多 fastai 组件,但是要进行一定程度的定制。或者,您可能只是好奇某个函数是如何工作的,并希望检查源代码。为了有效地实现这种级别的检查,重要的是您能够轻松地跳过您选择的机器学习库的源代码。所以,你需要选择一个好的代码编辑器,并且知道如何用好它。对于不在命令行界面工作的用户,我强烈推荐 Visual Studio (VS)代码 VS 代码完全免费,有一些确实很棒的功能。VS 代码结合一个叫做 ctags 的编程工具将允许你有效地探索 Python 库。在这里,我给出了如何在 VS 代码中设置 ctags 的分步教程。应该注意的是,本教程是为 Windows 用户设计的,但它在很大程度上可以很好地推广到其他操作系统,只需稍加修改。

我之前在这里提供的许多技巧来自这篇博客和来自 fast.ai 课程,所以我要感谢这些作者为我做的铺垫!我也不得不承认,我肯定不是 VS 代码方面的专家,所以建议/评论将会非常感谢。好了,我们开始吧!

  1. 首先,如果你还没有 Python,安装 Python。强烈推荐通过 Anaconda 下载 Python。
  2. 二、下载安装 Visual Studio 代码。同样,它是完全免费的,并且兼容 Windows、Linux 或 Mac,所以这应该很容易!
  3. 接下来,打开 Visual Studio 代码。首先,您必须选择 Python 作为您的解释器。为此,键入 Ctrl+Shift+P 并开始键入“Python: Select Interpreter”然后选择想要加载的 Python 版本和环境。同样,我经常使用 fastai,所以我为 fastai 选择了 Python 环境。如果“Python: Select Interpreter”没有出现,这意味着您的系统上没有安装 Python。这是一个简单的解决办法,所以只要按照这里的指示去做

4.现在打开包含您想要轻松浏览的 Python 库的文件夹(例如 fastai)。当你这样做的时候,VS 代码将会在那里创建一个名为的目录。vscode 。这个目录包含一个 JSON 文件,标签为 settings.json. 在 VS 代码(或任何文本编辑器)中打开 settings.json 文件。我们将分两步编辑这个文件。

5.对于 Windows 用户,接下来,您需要下载 ctags 包。Ctags 为源文件和头文件中的名称生成一个索引(或标记)文件。这就是我们如何通过创建这些标签来快速搜索我们的代码。你可以从这个 GitHub 网站下载。如果您使用的是 Windows,您可以点击发布,选择最新版本,并选择要下载的 zip 文件。把这个 zip 文件解压到你喜欢的任何地方,但是我通常只是把它放在中。vscode 目录。

对于 Linux 用户,您将需要通过在终端键入以下代码来安装 exuberant-ctags

sudo apt-get install exuberant-ctags

6.还记得 settings.json 文件吗? Windows 用户 (Linux 用户跳到第 7 步),您现在需要编辑它。JSON 中应该已经有一行指定了 Python 可执行文件的路径。现在你需要添加一行来指定ctags.exe文件的路径。创建一个新行并添加以下代码行(用 Python 库的路径或您选择放置ctags.exe文件的位置替换库路径):

"python.workspaceSymbols.ctagsPath": "LIBRARY_PATH\\.vscode\\ctags-2018-11-06_0f27679c-x64\\ctags.exe"

您的 settings.json 文件应该如下所示:

7.接下来,生成标签!VS 代码让这变得非常简单。对于 Windows 用户,你要做的就是键入 Ctrl + t 。这将创建一个包含所有标记的标记文件。如果这不起作用,打开终端 is VS 代码,转到输出选项卡,再次键入 Ctrl + t ,并查看输出内容。另外, Windows 和 Linux 用户,确保 Python 工作空间符号已启用,这可以在设置中选择(见下图),或者通过将以下代码行添加到您的 settings.json 文件中:

"python.workspaceSymbols.enabled": true

对于 Linux 用户,要生成标签文件,在终端中确保您在 Python 库的目录中,并在终端中键入以下内容:

ctags-exuberant -R -f tags

这将生成标记文件。我通常将这个标签文件移动到。vscode 目录。然后,在 settings.json 文件中,您需要通过添加以下附加行来指定标签文件的路径:

“python.workspaceSymbols.tagFilePath”: “LIBRARY_PATH/.vscode/tags”

8.您现在可以通过键入 Ctrl + t 并键入您想要搜索的类和函数的名称来导航标签。很简单!

我还能用 VS 代码做什么?

标签已经创建,现在可以使用了。在 VS 代码中还有许多其他有用的快捷键。下面是我无耻地从 fast.ai 课程中偷出来的一些:

  • 命令面板: Ctrl-shift-p
  • 转到符号:ctrl-t
  • 查找参考: Shift-F12
  • 转到定义: F12
  • 返回: Alt-left
  • 前进: Alt-right
  • 隐藏侧边栏: Ctrl-b
  • 禅模式: Ctrl-k,z

我希望你觉得这是有用的,并欢迎评论/建议!

构建和部署深度学习图像分类应用程序

原文:https://towardsdatascience.com/quickly-train-and-deploy-an-ai-computer-vision-app-d34ffa21fdd?source=collection_archive---------17-----------------------

基于 fastai 和 Render 的皮肤癌图像分类

Deploy

在本文中,我将向您展示如何使用计算机视觉分类模型从概念到部署。通过 fastai,你可以快速建立和训练一个最先进的深度学习模型。然后,Render 使托管和部署您的应用程序变得轻而易举。

我们将一步一步地构建和部署一个模型来对皮肤病变图像进行分类。完成后,用户将能够上传图像到网站,模型将分类他们的皮肤病变。

我打算很快在 NLP 上写一篇类似的文章— 关注我确保你不会错过!😄

免责声明:

卫生/法律:该项目仅用于演示目的。如果你认为你可能有皮肤问题,去看看健康护理专家。我不是医疗保健专业人士。

技术上:这个例子并不适合拥有数百万点击量的大型网站。如果你有这个问题,那是个好问题。😀这种设置可能有效。Render 在幕后使用 Docker 和 Kubernetes 来尽可能无痛苦地进行缩放。

好吧——回到行动上来!

Training set images

皮肤癌是最常见的一组癌症。已经开发了许多应用程序来对皮肤病变进行分类。通过上传一张你可疑皮肤斑点的照片,你可以看看你是否应该和皮肤科医生谈谈。

计划是这样的:

  1. 找到数据。
  2. 建立和训练模型。
  3. 部署模型。
  4. 提高模型性能。

让我们把这个计划充实一下。😉

步伐

  1. 找到数据。我记得在某个地方看到过皮肤痣的数据集——可能是 UCI、data.world 或 Kaggle。我去找找看。
  2. 建立和训练模型。我现在正在上 fast.ai 深度学习 MOOC,所以我会用 fastai,高级 PyTorch 库来训练我的模型。Fastai 允许你应用很多最新的技巧,API 对于计算机视觉任务来说也很方便。我将使用数据扩充、迁移学习和学习速率退火。我会在一个 Jupyter 笔记本上训练,在云中有一个 GPU。
  3. 部署模型。Fastai 的文档包含了一个在 Render 上部署模型的指南,每月 5 美元。
  4. 在我们有了一个已部署的模型之后,我们将返回并尝试改进模型性能。

我们开始吧!🚀

搜寻数据

我发现哈佛的研究人员收集了 10015 张患有多种皮肤病的图片:https://dataverse.harvard.edu/dataset.xhtml?persistent id = doi:10.7910/DVN/dbw 86t

看起来像是在数据的几个方面有一场年度 ISIC 竞赛——信息在这里。你可以在这里看到不同滤镜的图像

Images from ISIC

我在 Kaggle 上找到了同样的数据集来分类皮肤损伤。Kaggle 的空间限制和共享 Docker 容器内存限制可能会阻止我们做我们想做的事情,所以我们可能需要转移到 Colab。关于在 Kaggle 和 Colab 之间做出选择的讨论,请参见我的文章。

皮肤病变图像压缩在两个压缩文件夹中。我没有找到一种简单的方法来合并 Kaggle 上两个压缩数据集文件夹中的文件。我下载了数据,压缩后重新上传。现在你可以在 Kaggle 这里使用一个文件夹中的数据。😄

探索数据

有一个带元数据的文件: HAM10000_metadata.csv. 很方便。以下是内容和我的初步想法:

病变 id —每个病变一个。每个病灶可以有多个图像。
image_id —列出每个病灶的图像 id。这些也是文件名,sans 。jpg
dx —诊断。7 种类型。我想应该是 DV。
dx_type —如何做出诊断。
年龄 — 57 值缺失。可以尝试不同的策略来处理。
— 3 值。
定位—身体上的位置。15 个值。

图像比独特的案例多。嗯。我在这里挖出了这是因为同一张图片是以不同的放大倍数收录的。这是一点事实上的数据扩充。

初始问题

结果变量有多少分类标签?七:黑色素细胞痣黑色素瘤良性角化病基底细胞癌光化性角化病血管病变皮肤纤维瘤。请注意,黑色素瘤是最危险的皮肤癌。你也不想要基底细胞癌——最常见的皮肤癌。光化性角化病被认为是潜在的癌前病变。

看起来没有任何图像被归类为一种以上的类型,所以我们有一个多类的问题,但不是多标签的问题。

数据不平衡吗?是的,67%是 nv 级,代表黑色素细胞痣

我们需要小心使用不平衡类的报告指标。例如,准确性就不是一个很有洞察力的衡量标准。然而,根据 fast.ai 的杰瑞米·霍华德的说法,在用深度学习模型进行训练时,我们不需要担心不平衡的数据集。网络会找出这些类别。

准备数据

我们将导入我们常用的库,并为深度学习配置一些东西。因为 Kaggle 没有最新的 PyTorch 和 fastai 库,我们就打开互联网,用 pip 安装那些。

让我们也打开我们的 GPU。然后,我们将列出我们的硬件和软件,以确保可重复性,并确保我们拥有我们认为我们拥有的资源

当我厌倦了等待我的合并数据文件上传时,我切换到了 Colab。我意识到我可以使用 Kaggle API 从 Kaggle 获取数据集并导入 Colab。然后我合并了图像文件,并把它们保存在一个 Google Drive 文件夹中。这有点麻烦,但现在数据在我的驱动器文件夹中,这很方便。😄这是我的 Colab 笔记本。

建立模型

我用的是 fastai v.1.50.0,torch v1.0.1.post2,torchvision v0.2.2.post3。

让我们首先使用数据的子集进行快速训练,以使一切正常工作。当我们只想看看我们是否在正确的道路上时,没有理由花费大量时间等待培训。我们将从 1,000 张图像的随机样本开始训练和验证集,而不是 10,015。一旦我们解决了问题,我们可以在以后使用完整的数据集。

训练测试分割 — fastai 会将我们的数据分割成训练集和验证集。我们将留出 20%的图像进行验证。

转移学习——先用 ResNet34 够好,够快,可以上手。稍后,如果我们想花更多时间训练潜在的更高精度,我们将转移到 ResNet50。

优化器 —我使用默认值:Adam。

—CNN 的默认 fastai 层在这里解释。这些是 PyTorch 图层块,具有 batchnorm、dropout、linear 和 Relu 函数。最后一组图层由一个 2d 池图层和一个拼合图层组成。

学习率—我们将按照 Leslie Smith 的1 周期策略使用学习率退火。我们将从 fastai 在第一个时期的默认学习率 3E-10 开始(这已被 fastai 学习率查找器验证为合适)。解冻后,我们将使用学习率查找器和经验法则1 周期策略创建一个学习率范围,将之前的学习率降低 10 倍。

损失函数 —我们有一个多分类项目,所以我们将使用分类交叉熵。

评估——让我们跟踪误差率、精度和灵敏度。我们还将深入研究混淆矩阵。

我训练了较小的数据子集,让一切正常工作。然后我切换到完整的数据集。经过四个时期的训练,解冻,再训练四个时期,我们有了一个误差率为 15%的基线模型。这对我们的目的来说足够好了。让我们尝试部署我们的模型。

展开

下面是部署模型的五个步骤。

  1. Fork 示例 fastai GitHub repo 并克隆它。
  2. 渲染上注册一个账号。
  3. 按照 fastai 渲染指南设置你的项目。
  4. 在代码编辑器中自定义渲染应用程序代码。
  5. 将您的代码推送到 GitHub。这是我在 Render 上的应用程序的 GitHub repo 。

您的应用程序应该会在推送时自动部署。您可以在渲染面板中查看应用程序的事件和日志。

部署应用程序需要几分钟时间。您可以在仪表板中查看进度。在我短暂的经历中,Render 有很好的客户支持——他们很快通过他们的 Slack 频道回答了我的问题。

你可以在这里查看我的直播 app:https://skin-render.onrender.com/。我可能会在几个星期后把它拿下来,所以如果这个链接对你不起作用,这就是原因。😄

在 Jupyter 实验室本地运行您的应用程序

您也可以在本地运行您的应用程序。事实上,如果你正在使用 Jupyter Lab,你可以在笔记本上看到你的应用程序,这超级酷!

以下是在笔记本中查看应用程序的三个步骤:

  1. 启动 Jupyter 实验室服务器
  2. 从您的终端,在您的本地渲染应用程序文件夹中,使用python app/server.py serve启动服务器
  3. 在笔记本单元格中输入以下代码,并运行它来创建 iframe:
from IPython.display import IFrame
IFrame(‘[http://localhost:5042/'](http://localhost:5042/'), width=’100%’, height=500)

您的应用程序应该在您的单元输出中运行。

厉害!渲染相当流畅。现在让我们看看是否可以改进我们的模型。

改进模型

现在让我们对模型进行更长时间的训练,并尝试通过超参数调整来提高精度。正如我在本文的中所描述的,我们将使用混合精度训练来加速训练。

使用半精度训练和具有 8 个总时期的 64 批次大小导致 14%的错误率。那听起来不太坏。但后来我看了混淆矩阵,发现将近一半的黑色素瘤病例被归类为良性。这是个问题。😟

我致力于一些潜在的修复。最佳模型使用迁移学习,ResNet50,12 个总训练时期,批量大小 64,浮点精度 32。

错误率现已降至 10.7%,这是混淆矩阵:

我不知道我会在野外使用这个模型;黑色素瘤的错误分类还是太多了。尽管如此,让我们称这个项目为“暂时完成”,并讨论你可能追求的潜在未来方向。

潜在的未来方向

  • 测试更多超参数组合。
  • 让用户输入他们的年龄,以及一张图片。这些数据可能会提高准确性。然而,这也会增加摩擦。
  • 添加测试时间增强(TTA)以获得更好的预测性能。这种增强将是棘手的,因为应用程序需要从提供的图像创建多个图像。TTA 还会让应用程序的推理速度稍微慢一些。或者,我们也可以要求用户上传病变的三张不同的图片,并用这些图片进行预测。
  • 进行二元分类任务,将这些损伤分为危险或不危险。如果这是最终用户真正需要的信息,我想如果我要发布它的话,我会让应用程序给出推荐。

我们学到了什么?

外卖食品

这些图像状态良好,将它们转换成正确的格式并不困难。让 Kaggle 和 Colab 使用数据源需要做大量的工作。Kaggle 和 Colab 都有他们的障碍,但他们是自由的。😄

等着 Colab 的 K80 GPU 训练你的模型变老。在早期阶段开发一个小模型是没问题的,但是如果你想测试一堆超参数,那么转向付费服务可能是值得的。我发现谷歌云平台(GCP)是最容易使用的云提供商,物有所值。看我的文章比较云 GPU 提供商这里。如果我要进一步训练这些模型,我可能会在 GCP 上使用 V100。

训练数据集的大小很重要。该模型在用 800 个观察值而不是 8k 进行训练时,训练效果并不好。

Fastai 和 Render 是一个伟大的团队。Fastai 有利于快速创建高性能模型,Render 使部署它们变得轻而易举。👍

包装

在本文中,您看到了如何从 idea 到 live web 应用程序来解决细粒度的多类计算机视觉问题。我希望这篇文章对你有用。如果你有,请分享到你最喜欢的社交媒体频道,这样其他人也可以找到它。👏

我希望这个项目激发了你建立你一直在考虑的深度学习应用程序。😄

我撰写关于 Python、开发运营、数据科学和其他技术主题的文章。如果你对这些感兴趣,请跟我来,点击查看。

愉快的训练和部署!

数据和资源

以下是凯文·马德最初上传的关于 Kaggle 的图片和元数据。现在这些图片可以在我上传到 Kaggle 的一个文件夹中找到。我的 Colab 笔记本在这里

这里是使用相同原始数据集的 Kaggle 内核。这里还有另外两篇讨论解决这个问题的媒体文章: 12

原始数据源

Tschandl,p .,Rosendahl,c .和 Kittler,h .的 HAM10000 数据集,这是一个常见色素性皮肤病损的多源皮肤镜图像的大型集合。Sci。数据 5,180161 (2018)。doi: 10.1038/sdata.2018.161

https://dataverse.harvard.edu/dataset.xhtml?persistent id = doi:10.7910/DVN/dbw 86t

快速将 Kaggle 数据集转移到 Google bucket 中

原文:https://towardsdatascience.com/quickly-transfer-a-kaggle-dataset-into-a-google-bucket-ac21aefceb15?source=collection_archive---------11-----------------------

15 天。我震惊地发现,将一个相对较小(20GB)的图像数据集从我的本地机器上传到谷歌云平台(GCP)的存储桶需要多长时间。

在本文中,我将介绍另一种方法,它使用 GCP 虚拟机(VM)将这个过程缩短到 2 小时。关键是在与您的 bucket 相同的区域中创建一个 VM,将文件下载到那里,然后将它转移到 bucket。

如果你没有水桶,先把它放好,并记住你决定使用哪个区域。您可以毫无问题地使用所有标准设置。

下一步是创建一个虚拟机。我选择了 4 核,这样我们就可以在图像传输过程中利用多处理选项。除此之外,这是一个非常标准的设置,保留了所有的默认值。例外情况是将启动盘扩展到 100 GB 以容纳解压缩后的数据,并使用 Ubuntu 18 LTS,这只是个人偏好。

GCP VM setup

一旦虚拟机启动,我就连接到由 Google CLI 提供的 ssh 工具(可能需要安装在本地机器上)

gcloud compute ssh --project [NAME OF YOUR PROJECT] --zone [ZONE NAME] [NAME OF VM]

在虚拟机上,我安装了 pip 和 kaggle API。

## Install pip
> curl [https://bootstrap.pypa.io/get-pip.py](https://bootstrap.pypa.io/get-pip.py) -o get-pip.py
> sudo apt-get install python3-distutils
> sudo python3 get-pip.py
## Install kaggle API
> pip install kaggle

为了从 Kaggle 下载文件,您需要在 VM 上保存一个 API 令牌。你可以进入你的 Kaggle 账户,下载一个新的令牌,然后把它放到虚拟机上。在虚拟机上,创建一个名为“的隐藏文件夹。kaggle”并把钥匙移到那里

在你的本地机器上:

> gcloud compute scp Downloads/kaggle.json kaggle-download:~

在虚拟机上:

> mkdir .kaggle
> mv kaggle.json .kaggle

至此,Kaggle API 应该可以使用了!导航到您感兴趣的竞争对手或数据集,将 API 命令复制到虚拟机中,下载就应该开始了。许多数据集是压缩的,所以您需要安装解压缩工具并提取数据。

> sudo apt-get install unzip
> unzip [DATASET].zip

接下来要做的就是在虚拟机上验证你的谷歌账户,然后传输数据!m 标志允许我们使用多线程处理,r 递归地传输数据文件夹中的所有内容。对我来说,对于大约 20GB 的数据,运行整个过程需要大约 2 小时。

> gcloud auth login
> gsutil -m cp -r [DATA FOLDER] gs://[BUCKET NAME]

完成后,记得关闭虚拟机。每当我需要下载新的东西时,我就把它删除,然后转一个新的。快乐的旅行!

通过使用 Celonis Snap 分析事件日志快速了解流程挖掘

原文:https://towardsdatascience.com/quickly-understanding-process-mining-by-analyzing-event-logs-with-celonis-snap-b89ace2a286a?source=collection_archive---------14-----------------------

本文将帮助您开始使用 Process Mining 和 Celonis Snap,最终您应该能够开始深入研究您公司的流程。

数据是新的石油。“,”我们公司需要变得更有效率。“,”我们能优化这个流程吗?我们的流程太复杂了。”—你经常听到但可能再也听不到的句子。这是可以理解的,但(大)数据超级趋势背后的技术和讨论带来了一些实际的好处。这个领域的一项新兴技术在很多方面都与上面的句子直接相关。这是流程挖掘。也许你听说过。也许你没有。《哈佛商业评论》认为“你应该探索过程挖掘”。

这将是一个半长的阅读,所以这里有一个简短的概述,你会学到什么:

  • 流程挖掘
  • Celonis Snap 及其使用方法
  • 哪里可以找到一些操场数据

现在,为了节省一些时间和精力,我们可以得到更好的东西,这里是 IEEE 过程挖掘任务组描述的过程挖掘的定义:

流程挖掘技术能够从当今信息系统中常见的事件日志中提取知识。这些技术为发现、监控和改进各种应用领域中的过程提供了新的手段。对流程采矿兴趣的增长有两个主要驱动因素。一方面,越来越多的事件被记录,从而提供了关于进程历史的详细信息。另一方面,在竞争激烈和快速变化的环境中,需要改进和支持业务流程。

好的。酷毙了。下一个?当然是在实践中理解过程挖掘!而最好的办法就是实际挖掘一些流程。

什么是塞隆尼斯 Snap?

这是流程矿业公司 Celonis 的一个新的免费工具,它提供了一个流程矿业 SaaS 平台,叫做智能商业云。许多财富 500 强公司都在使用它,而 Celonis Snap 是它的免费版本,应该可以促进中小型企业的流程挖掘。它将在本文中使用,这样您就可以用自己的数据轻松地重现这个过程!

查找一些数据

如果您正在阅读本文,并且您在公司负责 BI,那么您可能已经访问了一些数据,这很好,如果您只是想玩玩 Celonis Snap,那么生活会变得有点艰难。跟着读。

我浏览了一些免费提供的事件日志,并决定查看一家荷兰金融机构的贷款申请,这些申请被用于 BPI Challenge 2017 。一种复杂流程的经典示例,可以对其进行迭代分析和改进(类似于从购买到支付的流程,这似乎是目前该领域的标准用例)。

关于数据集,您首先会注意到的是数据格式— xes(可扩展事件流):

XES 标准为基于标记的语言定义了一种语法,其目的是为信息系统的设计者提供一种统一的、可扩展的方法,用于通过 XES 标准中定义的事件日志和事件流来捕获系统行为。描述 XES 事件日志/流结构的 XML 模式和描述这种日志/流的扩展结构的 XML 模式包含在本标准中。

这是事件日志的常用标准。但是我的 Celonis Snap 账号不允许导入。由于 xes 免费版的局限性,所以我不得不寻找。xlsx 或者。csv 数据。

在中查找好的事件日志。csv 格式——至少对我来说——比我想象的要困难得多。尽管如此,我还是发现了一个宝库:data.gov.uk,它在英国国家档案馆开放政府许可下发布数据,你可以过滤. csv。太好了。几分钟后,我意识到没有真正的过程挖掘有价值的数据——即使是各种采购过程的数据集也只是给你英镑金额和开始和结束日期。

TL;在浏览网页几个小时后,我回到了最初的来源,在这里找到了一个数据集,这是一个生产过程,包括案例、活动(如车削、磨削、质量保证等)的数据。)在. csv 中。

使用 Celonis Snap 导入事件日志/流程数据

0.为 Celonis Snap 创建帐户

  1. 创建数据池

您需要转到“事件集合”以便将数据导入到 Celonis Snap 中。然后,您需要创建一个数据池,您的数据将被导入其中。

2.将数据上传到数据池

Straightforward

3.检查中列的数据类型。导入后的 csv

Straightforward

4.根据您的数据结构为数据池创建一个数据模型

Data Models can be created from the sidebar in Event Collection like the File Upload

然后,您需要映射您的案例 ID 列等。为了让 Celonis Snap 能够以正确的格式解析您的数据。在第 3 步中,我们只需选择数据类型,如字符串、整数等。在这里,我们正在进行特定于 Celonis Snap 的活动映射。例如,案例 ID 是在已处理事件日志中使用的唯一标识符。

5.将数据从数据池加载到数据模型中

最后一步似乎是多余的——将数据从数据池加载到数据模型中。尽管如此,这作为一个单独的步骤是有意义的,因为你可以在以后上传具有相同结构的新文件。整洁干净。

总结:

  • 创建数据池
  • 导入后上传数据并检查数据类型
  • 创建数据模型和地图。csv 列,如案例 ID
  • 将数据加载到数据模型

使用 Celonis Snap 进行流程分析

现在我们已经导入了数据,我们可以用我们的数据模型为生产事件日志创建一个工作区,并开始分析!将由一个或多个分析组成的工作区想象成 Excel 文件,其中有一个或多个工作表。每个分析可以包含一个或多个应用,例如流程浏览器。这是您的过程的图形视图,如果您使用谷歌 Celonis,您将立即看到,您可以放大和缩小活动(过程步骤),例如使用机器 XYZ 进行圆磨。这些应用就像预制的仪表板,但你也可以创建一个新的仪表板,并向其中添加多个应用。

现在我们有了一个新的工作区,我们可以使用一个新的定制应用程序来创建一个分析,该应用程序包含一个 Process Explorer。进入编辑模式后,您可以通过点击顶部的“组件+”来创建新的组件添加到您的应用程序中。在侧边栏的左侧,您可以过滤您的案例。您也可以通过单击 Process Explorer 中的 connections 来完成此操作。

现在,如果您在 Process Explorer 中单击一个连接,您就可以筛选包含特定活动的流程

Here the “Process Start — Turning & Milling -Machine 6” activity is selected i.e. “Keep selections” will filter for all events that contain that activity.

这是设置了 35 个案例的过滤器后的图形。请注意平均吞吐时间是如何从 15 天变成 12 天的?酷毙了。这就是你开始深入流程的方式。

但是等等。为什么有时箭头和下一个活动不匹配?例如,从步骤 2 到步骤 3,我们从 35 个案例开始,然后我们在连接中有 32 个,在下一个步骤中有 33 个。原因是默认情况下,process explorer 隐藏了许多不太频繁的活动。基本上你有 3 个不同的缩放级别。现在,让我们通过拖动侧面的滑块来显示这 35 个已过滤案例的每个连接和案例:

这是这 35 个案例的完整过程。有时,一个活动步骤会执行多次。有时 QA 会将一个元素送回进行研磨等。

总结

我希望这篇文章能让你通过点击一个最直观的(也是免费的!)市场上基于 GUI 的流程挖掘工具。人们可能会写一本关于如何使用 Process Explorer 深入流程的书,但本文只是对该主题的一个快速介绍,以缓解这一新兴 BI 技术的神秘感。

现在,显然是,这并不像 TensorFlow 关于识别猫和狗(或热狗/非热狗)的教程那么酷,但流程挖掘再次巩固了它在不同市场的地位——所有四大咨询公司都使用流程挖掘来帮助他们的客户优化他们在世界各地的流程。大公司和中小企业都可以受益于使用这样的工具可视化他们的流程数据/事件日志,并快速重新识别瓶颈和优化潜力,而不是雇佣最近的商学院毕业生手动筛选无尽的 SAP 日志。无论您选择 Celonis Snap 还是其他工具来开始您的流程挖掘之旅,都取决于您,但您肯定应该关注流程挖掘。不是因为《哈佛商业评论》这么说,而是因为你和你的同事们自己已经说过——“我们的流程太复杂了。

免责声明:虽然我目前不是 Celonis SE 的员工,但我将在 10 月份开始担任该公司的项目经理。我决定写这篇文章,以便在我开始新的冒险之前,分享我探索他们产品的旅程和我的见解。

来源:

https://HBR . org/2019/04/what-process-mining-is-and-why-companies-should-do-it,2019 年 9 月 3 日

https://www.win.tue.nl/ieeetfpm/lib/exe/fetch.php?media = shared:process _ mining _ manifesto-small . pdf,03.09.2019

http://www.xes-standard.org/,2019 年 9 月 3 日

丹尼尔·朱林摄于 Pexels

https://media . make ame me . org/created/data-data-everywhere-5b 0 d0a . jpg,09.09.2019

快速入门— Apache Kafka + Kafka-Python

原文:https://towardsdatascience.com/quickstart-apache-kafka-kafka-python-e8356bec94?source=collection_archive---------34-----------------------

阿帕奇卡夫卡一天可以处理万亿个事件。

介绍

实时数据摄取是实时分析中的一个常见问题,因为在电子商务这样的平台中,给定时间内的活跃用户和每个活跃用户创建的事件数量都很多。因此,对每个事件或事件组的推荐(即,预测)预期是接近实时的。

主要关心的是,我们将如何有效地[消费、生产和处理]这些事件?

阿帕奇卡夫卡解决了上述前两个问题。它是一个分布式流平台,有助于构建实时流数据管道。

Apache Kafka 设置

本文讨论了在 Linux 环境中设置 Apache Kafka,并揭示了如何使用 Kafka-Python 消费和产生事件。下图说明了我们期望建立的 Kafka 生态系统。

Kafka Ecosystem — Image by Author

启动动物园管理员

Apache Zookeeper 是一个分布式、开源的配置同步服务,为分布式应用程序提供了一个命名注册表。

在 Kafka 的上下文中,Zookeeper 帮助维护服务器状态,并将配置作为键值对存储在 ZK 数据树中,并以分布式方式在集群中使用它们。

最新版本的 Kafka 二进制发行版可以在 https://kafka.apache.org/downloads买到。

转到卡夫卡根文件夹

cd /home/***/***_STREAM_PROCESSOR/kafka_2.12-2.0.0

执行以下命令启动 Zookeeper

bin/zookeeper-server-start.sh config/zookeeper.properties

如果一切都准确无误,控制台上会显示以下输出:

Zookeeper 默认运行在端口 2181 上

开始 Kafka 经纪人

Kafka 集群由一个或多个经纪人组成,制作者将事件推入 Kafka 经纪人内的 Kafka 主题。

部署 Kafka 代理有两种选择:

  • 部署在本地计算机上
  • 在远程机器上进行部署,为此,请确保使用值 listeners = PLAINTEXT://XXX . XXX . XXX . XXX:9092 更新 server.properties(位于 Kafka config 中)

在新的控制台中转到 Kafka 根目录,执行以下命令:

cd /home/***/***_STREAM_PROCESSOR/kafka_2.12-2.0.0bin/kafka-server-start.sh config/server.properties

如果一切都准确无误,控制台上会显示以下输出:

创造卡夫卡主题

卡夫卡主题的生产者推动和消费者拉动事件。

执行以下命令,在 Kafka Broker 中创建一个主题(例如,“input_recommend_product”)

因为我们已经建立了一个代理,所以我们只能保留主题的一个副本;因此,将复制因子设置为 1

这里我们把题目:“输入 _ 推荐 _ 产品”分成三个分区;我们将分区设置为 3。

使用 Kafka-python 创建生产者和消费者

Kafka-python 是 Apache Kafka 的 python 客户端。这有助于为 Kafka Broker 创建主题和产生事件,并作为 Kafka Broker 的主题使用这些事件。

下面的代码段显示了如何创建一个生成器,并将消息推送到代理中的一个主题:

可以使用 KafkaConsumer 提取推送的消息,下面的代码段有助于使用该消息:

消费者的输出如下所示:

最后的想法

Apache — Kafka 是构建实时处理解决方案的重要平台。本文为您在分布式环境中设置 Apache-Kafka 提供了一个良好的开端,并为生成和消费事件提供了简单的指导。

Quora 虚假问题分类

原文:https://towardsdatascience.com/quora-insincere-questions-classification-d5a655370c47?source=collection_archive---------14-----------------------

Quora 举办的 Kaggle 竞赛案例研究。

Logo (Source)

Quora 是一个让人们能够互相学习的平台。在 Quora 上,人们可以提出问题,并与贡献独特见解和高质量答案的其他人联系。一个关键的挑战是剔除不真诚的问题——那些建立在错误前提上的问题,或者那些旨在陈述而不是寻找有用答案的问题。

Quora 无诚意问题分类是 quora 主办的第二次 kaggle 竞赛,目的是开发更多可扩展的方法来检测他们平台上的有毒和误导内容。

问题陈述

检测有毒内容以改善在线对话。

数据概述

数据集包含超过 1,300,000 个已标记示例的训练集和超过 300,000 个未标记示例的测试集。训练集中的每个示例都有一个唯一的 id、问题的文本以及一个“0”或“1”的标签来表示“真诚”或“不真诚”。

什么是不真诚的问题?

一个不真诚的问题被定义为一个旨在陈述而不是寻找有用答案的问题。

  • 有一种非神经的音调。
  • 是贬低或煽动性的。
  • 并不基于现实。
  • 使用性内容(乱伦,兽交和恋童癖)来寻求震撼,而不是寻求真正的答案。

由于这是一场内核竞赛,外部数据源是不允许的。我们必须提交 kaggle 内核(笔记本或脚本),并按照提交要求中提到的特定格式提交所有代码和输出预测。

除了问题的文本数据,quora 还提供了 4 个不同的嵌入文件,这些文件都是在大型数据语料库上训练出来的,可以在模型中使用。给定的嵌入文件如下:

在这些嵌入文件的每一个中,单词被表示为 300 个 dim 向量。单词的这种表示将允许捕捉单词的语义。具有相同含义的单词将具有相似的矢量表示。

机器学习问题

这是一个二元分类问题,对于一个给定的问题,我们需要预测它是否是一个不真诚的问题。

公制的

本次比赛的评估指标是F1-得分,这是精确度和召回率的调和平均值。精确度是实际上不真诚的分类不真诚问题的百分比,而回忆是被正确分类为不真诚的实际不真诚问题的百分比。

F1-Score (Source)

如果我们需要在精确度和召回率之间寻求平衡,F1 分数是一个更好的指标。当存在不均匀的类别分布时,这也优于准确性。

探索性数据分析

在本节中,我们将探索和可视化给定的数据集。

首先,让我们加载训练和测试数据集。

训练数据集包含列:qid、question_text 和 target(二进制值)。所有观察值都是唯一的,不含空值。

训练集分布图

Data Distribution

  • 数据集高度不平衡,只有 6.2%的不真诚问题。
  • 由于数据不平衡,F1-Score 似乎是比准确性更正确的选择。

言云对于真诚和不真诚的问题

Word cloud for sincere questions

Word cloud for insincere questions

  • 正如我们所看到的,不真诚的问题包含了许多冒犯性的词语。
  • 在提供的训练集中,大部分不真诚的问题都与穆斯林川普等有关。

特征工程(清洗前)

让我们构建一些基本特征,例如:

  • 字数
  • 大写字母的数量
  • 特殊字符的数量
  • 唯一单词的数量
  • 数字的个数
  • 字符数
  • 停用词的数量

生成特征的方框图

Box plots for generated features

  • 言不由衷的问题似乎更有文字和性格。
  • 不真诚的问题也比真诚的问题有更多独特的用词。

基于机器学习的方法

数据预处理和清洗

我遵循了用于解决基于 NLP 的任务的标准数据预处理技术,如拼写纠正、删除停用词、标点符号和其他标签,然后是词条化。

词条化是使用已知的单词词典将单词替换为其词根的过程。

关于数据预处理和其他 NLP 方法的更多细节可以在这个博客中找到。

TF-IDF

它代表词频——逆文档频率。

TF-IDF (Source)

词频:在文档中找到一个词的概率。

逆文档频率:定义单词在整个语料库中的独特性。

TF-IDF 是 TF 和 IDF 值的乘积。它给予在文档中出现较多而在语料库中出现较少的单词更大的权重。

逻辑回归

逻辑回归通过使用 sigmoid 函数估计概率来测量分类因变量和一个或多个自变量之间的关系。

使用逻辑回归作为一个简单的基线模型,问题的文本 TF-IDF 编码加上基本的手工制作的统计特征给出了 0.58 的 F1 值。

Confusion matrix for logistic regression

基于深度学习的方法

与基于机器学习的方法不同,这里我没有删除停用词,而是允许模型学习它们,并且还在标点符号之间添加了空间,以便找到更多的单词嵌入。

单词嵌入是使用密集矢量表示来表示单词的一种形式。我已经使用给定的预训练单词嵌入文件来创建嵌入矩阵。

此外,我还使用了 spacy tokenizer 来构建单词和词条词典。这两个字典用于创建嵌入矩阵。

为了增加嵌入覆盖率,我使用了词干、词汇化、大写、小写、大写以及使用拼写检查器嵌入最近的单词的组合来获得 vocab 中所有单词的嵌入。

用 glove 和 para 嵌入文件创建了两个独立的嵌入矩阵。最后,对它们进行加权平均,赋予手套更高的权重。

这一步将创建一个大小为(vocab 中的单词数,300)的嵌入矩阵,其中每个单词被表示为一个 300 维向量。

创建嵌入矩阵后,构建三个不同模型架构的集合,以捕获数据集的不同方面,从而提高总体 F1 分数。这些模型如下:

模式 1:双向 RNN(LSTM/GRU)

递归神经网络(RNN)是一种神经网络,其中来自先前步骤的输出作为输入被馈送到当前步骤,从而记住关于序列的一些信息。它有局限性,比如很难记住更长的序列。

LSTM/GRU 是 RNN 的改进版本,专门使用门控机制长时间记忆信息,而 RNN 没有做到这一点。

Bidirectional RNN (Source)

单向 RNN 只保存过去的信息,因为它看到的输入来自过去。使用双向将会以两种方式运行输入,一种是从过去到未来,另一种是从未来到过去,从而允许它在任何时间点保存来自过去和未来的上下文信息。

模型 2:具有注意层的双向 GRU

模型 2 由双向 GRU、注意力和池层组成。

神经网络中的注意力(非常)松散地基于在人类中发现的视觉注意力机制。人类的视觉注意力能够以“高分辨率”聚焦在图像的某个区域,而以“低分辨率”感知周围的图像。

Textual Attention example (Source)

注意力用于机器翻译、语音识别、推理、图像字幕、摘要和对物体的视觉识别。

注意力加权平均

注意层使用加权机制,其中序列中的所有单词都被赋予一个权重(注意值)。这个权重定义了一个单词在序列中的重要性,从而捕获重要的单词并给予序列中的重要部分更多的关注。这些重量是可以训练的。

Bidirectional LSTM model with Attention (Source)

注意层将让网络顺序地聚焦于输入的子集,处理它,然后改变它的焦点到输入的一些其他部分。

关注层的 keras 代码更深入的解释可以在这个文档中找到。

模型 3:具有卷积层的双向 LSTM

模型 3 由双向 LSTM、卷积层和池层组成。

在 NLP 中使用 CNN 的想法是利用它们提取特征的能力。CNN 被用于嵌入给定句子的向量,希望它们能够提取有用的特征(如短语和句子中更接近的单词之间的关系),这些特征可用于文本分类。

与传统 CNN 不同,NLP CNN 通常由 3 层或更多层 1D 卷积层和汇集层组成。这有助于减少文本的维度,并作为排序的总结,然后提供给一系列密集的层。

CNN for textual data (Source)

在计算机视觉任务中,CNN 中使用的过滤器滑过图像的碎片,而在 NLP 任务中,过滤器滑过句子矩阵,一次几个单词。

阿达姆

对于所有这三个模型,使用定制的 Adam 优化器,称为 AdamW(权重衰减),它修复 Adam 中的权重衰减正则化。

这篇论文指出,所有流行的深度学习框架(Tensorflow,Pytorch)都实现了权重衰减错误的 Adam。他们提出了以下意见:

  • L2 的正规化权重衰减是不一样的。
  • L2 正规化在亚当身上并不有效。
  • 体重下降对亚当和 SGD 同样有效。

他们提出了 AdamW,该 AdamW 解耦了权重衰减和 L2 正则化步骤。

Comparison between Adam and AdamW (Source)

更多关于 AdamW 的细节可以在这里找到。

培训和提交

用分层交叉验证训练三个模型,然后取它们预测的平均值作为最终集合预测。

创建具有所有折叠(验证)的“折叠外”列表,然后使用该列表来寻找集合模型的最佳阈值。

Validation score with optimal threshold

最后,使用测试预测的最优阈值,生成提交文件。

结论

本次 kaggle 比赛重点是利用机器学习和深度学习方法检测 Quora 平台上的有毒内容。

我从 kaggle 论坛和公共解决方案中学到了很多。发现更多的词嵌入和模型集成是提高 F1 分数的关键因素。

该解决方案的 Kaggle 私有和公共评分如下。

Kaggle Final Score

通过尝试其他预训练模型,如用于单词嵌入的 BERT,可以实现进一步的改进。

感谢您的阅读。完整的代码可以在这里找到。

参考

[## 第三名

下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…

www.kaggle.com](https://www.kaggle.com/wowfattie/3rd-place) [## 总体,平均值 III(64/36)

下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…

www.kaggle.com](https://www.kaggle.com/canming/ensemble-mean-iii-64-36) [## NLP 学习系列:第 1 部分——深度学习的文本预处理方法

最近,我在 Kaggle 上发起了一个名为 Quora 问题不真诚挑战的 NLP 竞赛。这是一个 NLP…

mlwhiz.com](https://mlwhiz.com/blog/2019/01/17/deeplearning_nlp_preprocess/)

用于目标检测的 R-CNN

原文:https://towardsdatascience.com/r-cnn-for-object-detection-a-technical-summary-9e7bfa8a557c?source=collection_archive---------3-----------------------

技术论文摘要

在快速发展的深度学习领域,这是一系列了解出版物的一部分,这些出版物是当今对象检测的基础。

原始论文“精确对象检测和语义分割的丰富特征层次”[1]阐述了在对象检测系统中使用 CNN 的第一个突破,称为“R-CNN”或“带 CNN 的区域”,其对象检测性能比当时其他流行的方法高得多。

区域提议

R-CNN 管道的第一阶段是在图像中生成“区域提议”或区域,这些区域可能属于特定对象。作者使用选择性搜索算法。选择性搜索算法[2]的工作原理是根据颜色、纹理、大小和形状生成可能属于一个对象的图像的子分割,并迭代地组合相似的区域以形成对象。这就产生了不同规模的“目标提议”。注意,R-CNN 管道对于区域提议算法是不可知的。作者使用选择性搜索算法为每个单独的图像生成 2000 个类别独立区域提议(通常由矩形区域或‘边界框’)

Figure 1: How the selective search algorithm iteratively obtains “region proposals”

阶段 1:从区域建议中提取特征

在流水线的这一阶段结束时,作者使用卷积神经网络(CNN)从每个图像的 2000 个区域提议中的每一个生成 4096 维特征向量。训练 CNN 的细节如下。

监督预训练:Krizhevsky 等人[3]描述的 CNN,现在被普遍称为“AlexNet”,具有 5 个卷积层和 2 个全连接层。CNN 首先在 ILSVRC2012 分类数据集上进行训练,用于具有大量图像的 1000 路图像分类任务,以便卷积层可以学习基本图像特征。

特定于域的微调:现在,需要对网络进行微调,以学习 a)新类型图像的视觉特征-失真区域提议,以及 b)用于检测任务的较小数据集的特定目标类别。我们微调分类网络以从区域提议中识别属于检测任务的类别。

  • 来自预训练的 CNN 的最终 1000 路分类层被用于 N 个对象类和检测任务的一般背景类的随机初始化的(N+1)路 softmax 分类层所取代。
  • 输入: 从每个图像生成的 2000 个区域建议中的每一个(使用选择性搜索算法)通过简单的变形被转换成大小为 227×227 的固定输入,而不考虑大小或纵横比,以使它们能够用于微调 CNN(我们需要固定大小的输入,而不考虑馈送到 CNN 的实际尺寸)。一个额外的参数, p 被用于指示原始边界框的可能扩展量,以包括来自其周围区域的一些上下文。
  • 用于训练的标签:作者将每个对象提议映射到与其具有最大 IoU 重叠的基础事实实例,并且如果 IoU 至少为 0.5,则将其标记为 (用于匹配的基础事实类)。其余的框被视为 背景 类(对所有类为负)。
  • 训练管道:作者使用 SGD 以初始训练前学习率的(1/10)训练网络。在每次迭代中,他们对所有类别中的 32 个正窗口和属于背景类别的 96 个窗口进行采样,以形成 128 个小批量,从而确保在训练期间有来自正类别的足够的代表性。

Figure 2: The CNN training pipeline taking in a batch of region proposals and giving a classification label (at train time)

阶段 1 的最终输出: 在训练之后,最终分类层被移除,并且对于 2000 个区域提议中的每一个(对于每一幅图像),从 CNN 的倒数第二层获得 4096 维特征向量。参考上图。

第 2 阶段:用于物体分类的 SVM

这个阶段包括为每个类别学习一个单独的线性 SVM(支持向量机)分类器,该分类器检测属于特定类别的对象的存在或不存在。

  • 输入:4096-d每个区域建议的特征向量。
  • 用于训练的标签:在训练期间,与地面真实边界框具有小于 0.3 的 IoU 重叠的所有区域提议的特征被认为是该类的否定 。该类的阳性仅仅是来自地面真实边界框本身的特征。出于训练 SVM 的目的,所有其他提议(IoU 重叠大于 0.3,但不是地面真实边界框)被忽略。
  • 测试单幅图像的时间推断:将特征和 SVM 权重之间的类特定点积合并为一幅图像的单个矩阵-矩阵积(如下图 3 所示)。也就是说,对于每个图像,生成一个 2000×4096 的特征矩阵(对于所有 2000 个区域提议,CNN 的 4096- d 特征)。SVM 权重矩阵是 4096×N,其中 N 是类的数量。

Figure 3: Final consolidated test time SVM computation

阶段 2 的最终输出: 在训练了 SVM 之后,阶段 2 的最终输出是每一类的一组正面物体提议,来自 2000 个区域提议(每个图像的)的 CNN 特征。

阶段 3:包围盒回归

为了提高定位性能,作者包括一个包围盒回归步骤,以学习预测包围盒位置和大小的校正。

Figure 4: The equations for bounding box regression stages explained below.

  • 等式 1:该任务的目的是学习我们的预测建议 P 和目标建议 G 之间的目标变换。变量 x,y,w,h 代表建议书的中心 (x,y) 和宽度 w 和高度 h 的坐标。
  • 等式 2:等式 2 中显示了需要学习的地面真实变换。前两个变换指定了 P — xy 的中心的比例不变平移,后两个指定了宽度 w 和高度 h 的对数空间变换。
  • 等式 3: d(P) 其中ₖ可以属于 (x,y,h 或 w)预测变换。ĝ表示使用原始预测框 P 和预测变换 d(P) 计算的校正预测框。
  • 等式 4:预测的变换 d ₖ(P)被建模为图 2)中的 pool₅(shown 特征的线性函数—φ₅
    因此,dₖ(p)=wₖᵀφ₅(p)其中 wₖ 是可学习模型参数的向量。注意,φ₅依赖于实际的图像特征。 wₖ 通过优化等式 4 的第二行所示的正则化最小二乘目标函数来学习。
  • 其他注释:如果预测的盒子 P 靠近至少一个地面实况盒子,则该算法仅从该盒子中学习。每个预测框 P 通过选择与它具有最大重叠的基础事实框(假设它具有至少 0.6 的 IoU 重叠)被映射到它的基础事实。为检测任务的每一类学习单独的变换。

阶段 3 的最终输出: 对于从 SVM 预测的每一类的所有正区域提议,我们具有围绕对象的精确的、校正的边界框。

其他捐款

  • 在其发表时,R-CNN 在 PASCAL VOC 2010 上获得了 54%的 mAP,在 ILSVRC 检测上获得了 31%的 mAP,远远高于其竞争算法。
  • 这篇论文的另一个主要贡献是,有确凿的证据表明,对于类似的任务,有监督的预训练比无监督的预训练更能提高表现。
  • 在对 CNN 进行了全面分析后,作者发现,在没有对检测任务进行微调的情况下,移除了完全连接层的网络能够检测到物体提议以及附加了完全连接层的网络——即使前者(pool₅)特征仅使用网络参数的 6%来计算。微调后,最大的性能提升发生在网络中,包括 FC 层。这表明,卷积层比全连接层包含更多的概化特征,全连接层包含特定任务的信息。
  • 作者假设,需要单独的 SVM 进行检测,而不是使用微调的 CNN 本身进行分类,这来自几个因素的组合,包括 a)微调中使用的正例定义不强调精确定位的事实,以及 b)微调中的 softmax 分类器是在随机采样的负例上训练的,而不是在用于 SVM 训练的“硬负”子集上训练的。

这就是 R-CNN 论文的技术总结。希望你喜欢(理解)!欢迎在下面的评论中讨论或更正。

了解 R-CNN 热门接班人:快 R-CNN更快 R-CNN

参考资料:

[1] Girshick,Ross 等人,“用于精确对象检测和语义分割的丰富特征层次。”2014 年 IEEE 计算机视觉与模式识别会议(2014)
【2】Uijlings,J. R. R .等人《物体识别的选择性搜索》。国际计算机视觉杂志 104.2(2013)
【3】Alex Krizhevsky,Ilya Sutskever,Geoffrey e . hint on“使用深度卷积神经网络的 ImageNet 分类”,发表于 NIPS 2012

质量控制图:c 图和 u 图

原文:https://towardsdatascience.com/r-for-industrial-engineers-c-chart-and-u-chart-2d2896fcbabf?source=collection_archive---------10-----------------------

r 代表工业工程师

使用“qcc”R 包创建质量控制图

Image by Analytics Association of the Philippines on LinkedIn

质量控制图

质量控制图是工程师监控一个过程是否在统计控制下的重要工具。它们有助于可视化变化,发现并纠正出现的问题,预测预期的结果范围,并分析特殊或常见原因导致的流程变化模式。质量控制图常用于精益六适马项目和 DMAIC 项目的控制阶段,被认为是过程改进的七个基本质量工具之一。

然而,我们如何确定用于监控过程的正确的质量控制图?以下决策树可用于根据给定数据确定哪一个是要使用的正确质量控制图:

Quality Control Charts Decision Tree

在下面的例子中,我们将关注离散数据的质量控制图,这些离散数据考虑了每个单元的多个缺陷,样本大小不变时和不变时的质量控制图。

u 形图

u 形图是一种质量控制图,用于监控不同尺寸 n 的样品中每单位的缺陷总数;它假设单元可以有一个以上的缺陷。y 轴显示每个单元的缺陷数量,而 x 轴显示样本组。让我们来看看使用 qcc 包生成 u 图的 R 代码。

u-chart R code

u-chart example using qcc R package

R 生成的 u 形图为其解释提供了重要信息,包括样本(组数)、两个控制限(UCL 和 LCL)、总体平均值(中间值)标准差(标准偏差),最重要的是,超出控制限的点和违规运行。工程师必须特别注意这些点,以便识别和确定导致不合格单元的系统变化的原因。

c 图表

c 图是一个质量控制图,用于监控尺寸为 n 的固定样本中缺陷总数。y 轴显示每个样品的不合格数量,而 x 轴显示样品组。让我们来看看使用 qcc 包生成 c-chart 的 R 代码。

c-chart R code

c-chart example using qcc R package

R 生成的 c 图也为其解释提供了重要信息,就像上面生成的 u 图一样。同样,工程师必须特别注意超出控制极限的点和违规运行,以便识别和确定导致不合格单元的系统变化的原因。

总结想法

我们已经完成了 Rqcc 软件包必须提供的众多工业工程应用中的一个。您可能已经注意到,只需几行代码,我们就能构建质量控制图,并获得重要信息,用于精益六适马和 DMAIC 项目的流程改进。我再一次邀请你继续发现作为一名工业工程师,你可以使用 R 完成的惊人的事情。

如果你觉得这篇文章有用,欢迎在GitHub上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 简介 来探索我以前的文章。感谢阅读。

——罗伯特

质量控制图:p 图和 np 图

原文:https://towardsdatascience.com/r-for-industrial-engineers-quality-control-charts-p-chart-and-np-chart-e99b2f07fbe1?source=collection_archive---------7-----------------------

r 代表工业工程师

使用“qcc”R 包创建质量控制图

Image by Analytics Association of the Philippines on LinkedIn

质量控制图

质量控制图是工程师监控一个过程是否在统计控制下的重要工具。它们有助于可视化变化,发现并纠正出现的问题,预测预期的结果范围,并分析特殊或常见原因导致的流程变化模式。质量控制图常用于精益六适马项目和 DMAIC 项目的控制阶段,被认为是过程改进的七个基本质量工具之一。

然而,我们如何确定用于监控过程的正确的质量控制图?以下决策树可用于根据给定数据确定哪一个是要使用的正确质量控制图:

Quality Control Charts Decision Tree

在下面的例子中,我们将关注离散数据的质量控制图,这些离散数据考虑每个单元一个缺陷(即,有缺陷或无缺陷的单元),当样本大小恒定时,以及当样本大小不恒定时。

p 图

p-chart 是一种质量控制图,用于监控不同大小 n 的样本中不合格品单位的比例;它基于二项式分布,每个单位只有两种可能性(即有缺陷或无缺陷)。y 轴显示不合格单位的比例,而 x 轴显示样本组。让我们看看使用 qcc 包生成 p 图的 R 代码。

p-chart R code

p-chart example using qcc R package

R 生成的 p 图为其解释提供了重要信息,包括样本(组数)、两个控制限(UCL 和 LCL)、总体比例均值(中间值)标准差(标准偏差),以及最重要的超出控制限的点和违规运行。工程师必须特别注意这些点,以便识别和确定导致不合格单元的系统变化的原因。

np 图表

np-chart 是一个质量控制图,用于监控大小为 n 的固定样本中不合格单位的计数。y 轴显示不合格单位的总数,而 x 轴显示样本组。让我们看看使用 qcc 包生成 np-chart 的 R 代码。

np-chart R code

np-chart example using qcc R package

R 生成的 np-chart 也为其解释提供了重要信息,正如上面生成的 p-chart 一样。同样,工程师必须特别注意超出控制极限的点和违规运行,以便识别和确定导致不合格单元的系统变化的原因。

总结想法

我们已经完成了 Rqcc 软件包必须提供的众多工业工程应用中的一个。您可能已经注意到,只需几行代码,我们就能构建质量控制图,并获得重要信息,用于精益六适马和 DMAIC 项目的流程改进。我再一次邀请你继续发现作为一名工业工程师,你可以使用 R 完成的惊人的事情。

如果你觉得这篇文章有用,欢迎在GitHub上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 简介 来探索我以前的文章。感谢阅读。

——罗伯特

使用 R 进行文本分析应该知道的 5 个包

原文:https://towardsdatascience.com/r-packages-for-text-analysis-ad8d86684adb?source=collection_archive---------2-----------------------

科学家应该知道的用于文本分析的 R 数据中最有用的包的完整概述

Photo by Patrick Tomasso on Unsplash

1.包罗万象:Quanteda

install.packages("quanteda")
library(quanteda)

Quanteda 是定量文本分析的首选包。由 Kenneth Benoit 和其他贡献者开发的这个包是任何进行文本分析的数据科学家的必备工具。

为什么?因为这个包可以让你做很多事情。这包括从自然语言处理的基础——词汇多样性、文本预处理、构建语料库、令牌对象、文档特征矩阵——到更高级的统计分析,如 wordscores 或 wordfish、文档分类(如朴素贝叶斯)和主题建模。

该软件包的一个有用的教程是由渡边康平和斯特凡·缪勒开发的(链接)。

2.变形金刚:Text2vec

install.packages("text2vec")
library(text2vec)

如果你正在基于文本数据构建机器学习算法,Text2vec 是一个极其有用的包。这个软件包允许你从文档中构造一个文档术语矩阵(dtm)或者术语同现矩阵(tcm)。因此,您可以通过创建从单词或 n 元语法到向量空间的映射来对文本进行矢量化。在此基础上,您可以让模型适合 dtm 或 tcm。这包括主题建模(LDA,LSA),单词嵌入(GloVe),搭配,相似性搜索等等。

这个包的灵感来自 Gensim,一个著名的用于自然语言处理的 python 库。你可以在这里找到这个包的有用教程。

3。适配器:Tidytext

install.packages("tidytext")
library(tidytext)

Tidytext 是数据争论和可视化的基本包。它的一个好处是可以很好地与 R 中的其他 tidy 工具协同工作,比如 dplyr 或 tidyr。事实上,它就是为此目的而建造的。识别清理数据总是需要大量的工作,并且这些方法中的许多不容易适用于文本,Silge & Robinson (2016)开发了 tidytext,以使文本挖掘任务更容易、更有效,并与已经广泛使用的工具保持一致。

因此,这个包提供了允许你将文本转换成整齐格式的命令。分析和可视化的可能性是多种多样的:从情感分析到 tf-idf 统计、n-grams 或主题建模。这个包在输出的可视化方面特别突出。

你可以在这里找到包的有用教程。

4.匹配者:Stringr

install.packages("stringr")
library(stringr)

作为一名数据科学家,你几乎已经和字符串打交道了。它们在许多数据清理和准备任务中发挥着重要作用。作为包生态系统 tidyverse(也包括 ggplot 和 dplyr)的一部分,stringr 包提供了一组内聚的函数,允许您轻松地处理字符串。

对于文本分析来说, stringr 是一个特别方便的处理正则表达式的包,因为它提供了一些有用的模式匹配函数。其他功能包括字符操作(在字符向量中操作字符串中的单个字符)和空白工具(添加、删除、操作空白)。

CRAN-R 项目有一个关于这个包的有用教程(链接)。

5.炫耀:Spacyr

install.packages("spacyr")
library(spacyr)
spacy_install()
spacy_initialize()

你们大多数人可能知道 Python 中的 spaCy 包。嗯, spacyr 在 R 中提供了一个方便包装器,使得以简单的格式访问 spaCy 的强大功能变得容易。事实上,如果你仔细想想,这是一个相当不可思议的包,它允许 R 利用 Python 的能力。为了访问这些 Python 功能,spacyr 通过在 R 会话中初始化来打开一个连接。

该软件包对于更高级的自然语言处理模型至关重要,例如为深度学习准备文本,以及其他有用的功能,如语音标记、标记化、解析等。此外,它还可以很好地与 quanteda 和 tidytext 包结合使用。

你可以在这里找到一个有用的教程。

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

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

原文:https://towardsdatascience.com/r-squared-recipe-5814995fa39a?source=collection_archive---------1-----------------------

关于 r 平方是什么的复习,以及如何计算的直观逐步指南

Source of image: link. Pine-cones have the Fibonacci Sequence in them

R 的平方在概念上很难理解。我没有介绍其中涉及的数学公式,而是认为展示它是如何从零开始直观地计算的,并用简单的英语解释每一步可能会令人耳目一新。

什么是 R 平方?

这是一种介于 0 和 1 之间的统计方法,用于计算回归线与其拟合的数据的相似程度。如果是 1,模型 100%预测数据方差;如果它是 0,模型预测没有方差。

r 平方=模型的解释方差/目标变量的总方差

还是没有意义?别担心。让我们深入了解这意味着什么

  • 首先,解释什么是计算 r 平方的必要条件。
  • 第二,通过一个简单的数据集一步一步地计算这个统计指标。

我们需要什么:

  • 包含至少一个自变量(X)和一个因变量(Y)的数据集
  • 数据拟合的线性回归。
  • 数据上平均值 Y 的一条水平线(这个我一会儿再解释)。
  • Python(甚至只要一支笔一张纸就可以)。

第一步:有一个数据集,并形成一个线性回归

重要的是要记住,在这个例子中,我们使用的是任意数据。我们可以用任何数据集来做这个练习。x 是一个从 0 到 9 的整数数组。y 是由斐波纳契数列的前 10 位数字组成的数组。绘制数据点后,我们将在顶部拟合普通最小二乘回归(OLS)线。

更多关于线性回归的信息可以在这里找到。但是 OLS 背后的主要思想是,它试图预测每个 x 的 Y 在哪里

这条线看起来相当合身。蓝点离回归线不太远。点离线越近,我们的方差越低。方差越低,我们的模型越好!

第二步:水平 Y.mean()线

接下来,我们将在数据上放置另一行。如果我们理论上只有 Y 数据(没有 X),我们能够做出的最佳预测模型将是每次猜测 Y 的平均值。这是计算 r 平方的关键一步,你马上就会看到。

与之前的绿色回归线相比,这条红线离圆点更远。这意味着它有更高的方差。

步骤 3:实际数据点和线性模型之间的方差

如果我们测量数据的每个点和线性回归线之间的差异,平方每个差异并合计它们,我们将获得回归模型中存在的方差。

这是下面计算的。

步骤 4:实际数据点和 Y.mean()线之间的平方差。

如果我们测量数据的每个点与水平线之间的差异,对每个差异进行平方并对它们求和,我们将获得只存在于 Y 数据集中的总方差。记住,这是我们将使用的独立于 X 数据存在的模型。

步骤 5:最后一步和检查工作

让我们后退一步,想想我们到目前为止的计算结果:

  1. 我们的线性模型的方差:1753
  2. 目标变量的总方差:7524

我们也提醒一下自己,r 平方的定义是什么:“模型的解释方差/目标变量的总方差”。

在我们的回归模型中,方差要小得多。这是因为我们考虑了分析 X 数据与 Y 数据的关系所获得的信息。总方差,另一方面,有较少的信息开始,因此它有一个较高的方差。如果我们想量化使用线性回归减少了多少方差,我们可以取总方差和回归线方差之差。这将给出“由模型解释的”方差。7524–1753 = 5771

我们现在要做的就是把模型解释的方差放在总方差上求 rsquared: 5771/ 7524 = 0.767。这个数字可以解释为:Y 的变化有 76.7%可以用 x 的变化来解释。

为了确保我们做得正确,让我们用 sk learn“R2 _ score”函数来检查我们的答案:

如果你喜欢我的内容,请查看其他几个项目:

了解二元逻辑回归

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

Excel 与 SQL:概念上的比较

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

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

优步评论文本分析

Python 中的字云:综合示例

安德鲁

R 与 Python:比较寻找 R 或 Python 专家的数据科学职位招聘

原文:https://towardsdatascience.com/r-vs-python-comparing-data-science-job-postings-seeking-r-or-python-specialists-2c39ba36d471?source=collection_archive---------13-----------------------

在制作针对语言的数据科学招聘广告时,雇主在寻找什么?

网上有 100 万个帖子,标题类似于“R vs Python:数据科学之战”,让这两种语言互相竞争,试图为“一种统治所有数据科学的语言”加冕。两者都是强大的工具,各有所长(例如,高级统计库与实现生产代码);总的来说,考虑它们如何互补比试图选择一个更有意义。

也就是说,在查看招聘信息时,并不是所有的数据科学招聘广告都在首选技能列表中包含 R 和 Python。这就产生了一个潜在的有趣的对比:当雇佣一个精通 R 语言而不是 Python 的数据科学家时,公司在寻找什么?反之亦然?为了回答这个问题,我用两种不同的搜索查询从一个流行的职位发布网站上搜集了职位描述、头衔和位置:一种包含术语 data science 和 R,但不包含 python,另一种包含术语 data science 和 python,但不包含 R。特定于 R 的职位搜索结果比特定于 python 的职位搜索返回的结果少 30%左右。毫不奇怪,包含两种语言的搜索返回的命中数远远多于特定语言的搜索。

R 与 Python 的地理偏好

作为第一步,我查看了 R 和 python 职位搜索中最常见的 10 个城市的职位发布明细。当我收集数据时,两种语言的最大发布量都在纽约和波士顿(尽管两周后我再次抓取了发布量,硅谷接管了 python 职位,而纽约和波士顿保持不变)。在前两个城市之后,事情开始出现分歧。华盛顿特区对 R fluent 数据科学家的需求似乎更高,旧金山对 python fluent 数据科学家的需求也更高。我猜,DC 对 R 数据科学家的需求是由寻找政治数据科学家的公司推动的,这些公司中的许多人可能拥有政治学博士学位,而 R 在这一领域有着深厚的根基。

A surprising number of job postings fell on the East Coast

发布数据科学特定术语

了解这些职位的招聘信息有何不同的一个快速方法是简单地统计每组招聘信息中出现的数据科学工具和技术的数量。也就是说,在 R 数据科学工作中使用了哪些工具和技术?对于 python 数据科学工作,反之亦然。下面,我们可以很容易地查看这些术语在一个词云中出现了多少次。

通过对你大喊“研究”或“机器学习”,单词 clouds 开始描绘广告中的一些差异。在 R 数据科学的招聘启事中,我们可以清楚地看到最常用的词是“研究”,后面是“SQL”和“统计”等术语。对于 python 数据科学的职位发布,“机器学习”出现得最多,其次是“SQL”、“研究”和处理大数据的工具,如 AWS 和 spark。

The larger the term, the more frequently it occurred in the posting

职位描述的主题建模

使用主题建模,我们可以更深入地了解工作描述中的内容。在一些文本清理之后,但在模型拟合之前,最好尝试一下有多少主题适合建模,而不是随便选择一个数字。为了获得帮助,我们可以求助于 r 中的“ldatuning”包。在为 ldatuning 提供了一个文档术语矩阵(DTM)之后,它将返回一些不同的指标来评估要继续进行的主题数量。下图显示了 R 工作描述中的信息;看起来大约 25 个主题可能是一个合理的选择。python 描述的结果几乎相同,因此 python 模型中也使用了 25 个主题。

The y axis represents a normalized metric that’s either to be minimized (top pane) or maximized (bottom pane)

下面是产生的主题,首先从 R 作业开始。这些术语按照它们在每个主题中的权重降序排列。有些话题并不十分有趣,因为它们与招聘实践和福利有关(例如,10、13、14、17、22),甚至与纽约市有关(6),尽管这很有意义,因为许多招聘信息都是在纽约发布的。多个主题似乎代表了健康和医疗保健行业(18,23)。其他描述科学研究,特别是生物和临床试验研究(2,7,25) -这有助于解释北卡罗来纳州达勒姆的排名,因为它是生物技术/制药研究的温床。商业世界也表现为主题 15 与商业广泛相关,主题 20 似乎与金融相关,主题 24 描述市场研究。主题 5 可以证实上面关于政治学相关工作的假设,因为它包含了与政策、政府和调查相关的术语。最后,我们来到我称之为一般数据科学的主题;例如,主题 3、8、11、16 和 18 涵盖了团队合作、广义分析、机器学习、统计和数据库等主题。

Terms are sorted in descending order with respect to their weighting on each topic

接下来,我们可以从仅 python 描述转移到主题分析结果。忽略与招聘实践和福利相关的话题,我们看到一些类似的主题正在出现。例如,主题 14 似乎代表健康研究、9 市场营销、11 金融、24 一般商业,我们有一般的数据科学主题,如 4、20 和 25,强调团队合作、机器学习和分析。

现在,关于差异,有一些很大的差异。这是提及大数据相关主题的一个线索(哈!).除了致力于处理大数据的平台(hadoop、spark)之外,主题 1 还包含术语“大”;主题 23 似乎也以某种格式表示大量数据。主题 21 描述了云计算,有两个主题致力于数据库(10,22),多个主题与软件工程相关(15,19)。

Terms are sorted in descending order with respect to their weighting on each topic

我们学到了什么?

专注于 R 的数据科学家和 python 流畅的数据科学家之间当然有很多相似之处(例如,SQL 数据必须存在于某个地方),但也有一些关键的不同。从最高层面来看,寻找具有研发经验的数据科学家的帖子似乎是在寻找受过学术培训、具有丰富分析经验的研究人员。这种想法是有道理的,因为 R 在学术界占主导地位,也非常符合 R 职位描述中的许多研究主题。寻找 python fluent 数据科学家的帖子似乎在寻找具有更多计算机科学或工程背景的人,并且符合数据工程师或机器学习工程师的描述。

在另一个层面上,我认为我们在描述内容中看到的差异已经在 2014 年由 Michael Hoster(Stitchfix 的现任数据科学总监)在 Quora 帖子中阐明了,他解释了两种不同类型的数据科学家:

A 型数据科学家:A 是做分析的。这种类型主要涉及理解数据或以相当静态的方式处理数据。A 型数据科学家非常类似于统计学家(也可能是一名统计学家),但他们知道统计学课程中没有教授的所有数据处理的实际细节:数据清理、处理非常大的数据集的方法、可视化、特定领域的深入知识、写好数据等等。

A 型数据科学家可以编写足够好的代码来处理数据,但不一定是专家。A 型数据科学家可能是实验设计、预测、建模、统计推断或其他通常在统计系教授的事情的专家。不过,一般来说,数据科学家的工作成果并不像学术统计有时似乎暗示的那样是“p 值和置信区间”(例如,有时对于在制药行业工作的传统统计学家来说也是如此)。在谷歌,A 型数据科学家被称为统计学家、定量分析师、决策支持工程分析师或数据科学家,可能还有更多。

B 型数据科学家:B 是建筑用的。B 型数据科学家与 A 型共享一些统计背景,但他们也是非常强的编码员,可能是训练有素的软件工程师。B 型数据科学家主要对“在生产中”使用数据感兴趣他们建立与用户互动的模型,通常提供推荐(产品、你可能认识的人、广告、电影、搜索结果)。在谷歌,B 型数据科学家通常被称为软件工程师。B 型数据科学家可能会使用术语数据科学家来指代他们自己,因为这个领域的定义在不断变化,所以他们可能是对的。但我看到这个词在我这里提议的一般方式中使用得最多。

这两种类型之间的区别在 Robert Chang 的另一篇博文中也有很好的解释和阐述。对我来说,A 型数据科学家似乎与我们从寻找 python 数据科学家的广告中发现的 A 型数据科学家和 B 型数据科学家的帖子非常匹配。最近,AirBnB 将其数据科学部门重组为 3 个分支:数据科学家-分析、数据科学家-算法和数据科学家-推理。从这里的数据来看,python 帖子描述的数据科学家似乎很适合算法分支,R 帖子描述的数据科学家适合推理分支,并且可能适合分析轨道。

最后,R 和 python 是数据科学的重要工具,对它们都很了解无疑会比只知道其中一个而不知道另一个更进一步。尽管如此,正如我们所见,有些职位和公告需要一种语言而不是另一种语言,了解这些公告内容的差异可能有助于您考虑您可能希望优先选择哪种语言作为您的主要工作语言。

R Vs Python:应该学哪个?

原文:https://towardsdatascience.com/r-vs-python-which-one-should-you-learn-c6179fac99ee?source=collection_archive---------6-----------------------

如果你想成为一名专业的数据科学家,你至少需要学习一门编程语言。但是如何在 Python 和 R 这两种最流行的数据分析语言之间做出决定呢?如果你有兴趣了解他们各自的优缺点,请继续阅读!

作为一名数据科学家,您可能希望并需要学习结构化查询语言,即 SQL。SQL 是关系数据库事实上的语言,大部分公司信息仍然驻留在关系数据库中。但这只能让您检索数据——而不是清理数据或对数据运行模型——这就是 Python 和 R 的用武之地。

关于 R 的一点背景知识

r 是由新西兰奥克兰大学的两位统计学家 Ross Ihaka 和 Robert Gentleman 创造的。它最初发布于 1995 年,他们在 2000 年推出了稳定的测试版。它是一种解释型语言(在运行代码之前,您不需要通过编译器来运行它),并且拥有一套非常强大的统计建模和绘图工具。

对于编程爱好者来说,R 是 S 的实现——一种在 20 世纪 70 年代由贝尔实验室开发的统计编程语言——它的灵感来自 Scheme——一种 Lisp 的变体。它也是可扩展的,使得从许多其他编程语言中调用 R 对象变得容易。

r 是免费的,并且已经变得越来越受欢迎,其代价是传统的商业统计软件包,如 SAS 和 SPSS。大多数用户使用 RStudio 编写和编辑他们的 R 代码,这是一个用于 R 编码的集成开发环境(IDE)

Python 的一点背景知识

Python 也有一段时间了。它最初是由吉多·范·罗苏姆在 1991 年作为通用编程语言发布的。像 R 一样,它也是一种解释型语言,有一个全面的标准库,允许对许多常见任务进行简单的编程,而不必安装额外的库。它也是免费的。

对于数据科学,有许多非常强大的 Python 库。有 NumPy(高效的数值计算),Pandas(各种各样的数据清理和分析工具),以及 StatsModels(常用的统计方法)。你还有 TensorFlow、Keras 和 PyTorch(都是用于构建人工神经网络的库——深度学习系统)。

如今,许多使用 Python 的数据科学家使用 Jupyter 笔记本编写和编辑他们的代码。Jupyter 笔记本允许轻松创建混合了散文、代码、数据和可视化的文档,从而可以轻松记录您的过程,并让其他数据科学家查看和复制您的工作。

选择一种语言

从历史上看,数据科学界的分裂相当平均。通常,具有较强学术或统计背景的数据科学家更喜欢 R,而具有更多编程背景的数据科学家更倾向于 Python。

Python 的优势

与 R 相比,Python 是。。。

仍然有很多工作需要 R,所以如果你有时间的话,学习这两种语言也无妨,但我建议,现在 Python 正成为数据科学家的主流编程语言,也是更好的首选。

原载于https://flatironschool.com

你确定你在用这个包吗?

原文:https://towardsdatascience.com/r-you-sure-youre-using-this-package-8ce265a990b0?source=collection_archive---------15-----------------------

如何识别一个 R 文件实际上正在使用哪些包(和哪些函数)

在继承别人的 R 代码时,我总喜欢检查它用了哪些包和函数。不仅仅是那些它装载的库函数调用,还有那些它实际上使用的。为此,我最近发现了这个有用的小工具,它将为你提供一个列表,列出所有的包以及在给定的 R 文件中引用的那些包中的所有函数。

您需要安装的包是 NCmisc ,我们将在其中使用的函数是名副其实的 list.functions.in.file

Example use of NCmisc::list.functions.in.file()

它的工作原理是识别给定文件中的所有函数调用,并将这些调用与内存中当前加载的函数进行比较。

这意味着运行 list.functions.in.file 之前,你需要将所有你认为被引用的包加载到内存中,并且只需要那些包。最简单的方法是打开一个 RStudio 的新实例,只执行文件中的代码。(在上面的例子中,“全局。r”文件是一个闪亮应用程序的一部分,我第一次运行它,然后就停止了。)

输出是一个命名列表。每个项目都以包的名称命名,如果一个特定的函数名称为多个包所共有,则以包的名称命名。每个列表条目都是一个函数名列表。文件本身定义的任何自定义功能将出现在下。全球环境

如果您的 R 脚本文件加载了一个包,但是这个包是而不是在这个输出中列出的,那么它就是多余的,您可以删除它。清理是好的。

在我们的例子中,这个文件中引用了五个来自 plotly 包的函数。但是还有一个——布局功能的——在图形图形中都有定义。

查找潜在的函数名冲突

因此,这可以成为发现潜在名称空间冲突的工具。我碰巧知道我们不需要担心这种特定的冲突,但情况不会总是如此。在同一个例子中,在 config 包中有一个名为 get 的函数,它与一个完全不同的同名基本函数冲突。

即使加载了 config 包,我们也应该总是使用显式引用来调用它的 get 函数——使用双冒号符号——以避免意想不到的后果。

仅此而已。当然,如果你想让它解析多个文件,寻找特定的包/函数,输出结果到一个文本文件等等,你可以把它包装在你自己的代码里。

我希望这能对你有所帮助,即使阅读这篇文章的唯一“你”是未来的我。

对话式人工智能中的种族主义

原文:https://towardsdatascience.com/racial-bias-in-conversational-artificial-intelligence-be0d3abd9b39?source=collection_archive---------16-----------------------

Racial Bias in Conversational AI (source)

什么是对话式人工智能

这是一个新兴的人机交互领域,我们使用自然语言来交换信息并向计算机传递命令。你能想到的任何与数字设备的单一界面都可以被人工智能支持的对话界面取代或增强。例子包括聊天机器人&基于语音的助手,如 Siri。

现代智能城市概念还涉及“以公民为中心”的服务模型,该模型使用对话式人工智能界面来个性化和情境化城市服务。一个例子是公民参与平台 Citibot 。同样,维也纳有一个 WienBot,让居民和游客可以找到常见的市政服务,如找到停车场、洗手间、餐厅和其他设施。他们不再需要依赖陌生人的善意,或者在网站上浏览长长的名单。

Virtual AI assistants (source)

问题:对话式人工智能和人类一样有偏见

聊天机器人使用复杂的算法,通过数百万个例子进行学习。如此大规模的语言数据只存在于新闻文章和社交媒体等公共数据源中。通过使用未经检查的公共数据,人工智能可以包含人类最糟糕的特征,并最终体现社会的偏见。垃圾入垃圾出的老编程原则在这里适用。让我们看看这个问题的几个经典例子。

微软与人工智能聊天机器人的斗争

2016 年 3 月,微软推出了 TAY(一个 twitter 机器人),作为对话式人工智能的实验。这个聊天机器人在 twitter 上与公众互动,从对话中学习并发布消息。人类互动不到 24 小时就腐蚀了一个无辜的 AI 聊天机器人。下面可以看到该机器人发出的一些令人无法接受的推文。

ZO 是 TAY 的温和版,由微软于 2017 年夏天发布。它被塑造成不讨论政治和宗教,并避免参与种族和不适当的谈话。下图显示了其对争议话题的回应示例。这看起来做得不错,但有一个缺陷,我将在下一节强调。

Zo reacts to controversial topics (source)

没有上下文的审查

Zo 对一系列广泛话题的不妥协态度是人工智能中一个令人不安的趋势:没有背景的审查。Zo 没有推断语言上的细微差别和上下文,只是回避了黑名单上的术语。这可能会导致股权问题,如下图所示。一些开源黑名单库被维护,虚拟对话代理使用它们来避免某些对话。令人惊讶的是,我发现其中一个开源库在某个时候在黑名单库中出现了我的国家“巴基斯坦”的名字(链接)。如果这些代理被部署在城市环境中提供服务,这可能导致公平、包容和拒绝服务的问题。

Censorship without context (source)

一个小实验

神经语言模型是虚拟语音助手的重要组成部分。一旦经过训练,它可以通过分配概率来计算哪些句子更有可能被说出。我在公开的新闻数据上训练了一个语言模型,并用一种简单的技术进行了种族审计。我使用的数据集由标题中含有犯罪一词的新闻文章组成。

我通过比较与不同种族群体相关的否定句的概率,对我的模型进行了种族审核。这种基于模板的因果测试技术已经被使用,这在最近的研究中有所体现,用于从神经网络模型中测量社会偏见。

这里显示的概率是一个标准化的(条件)概率,它可以被解释为产生这些句子之一的句子的概率。可以观察到,在种族身份之间存在巨大的歧视,因为 model 从新闻数据中学习犯罪统计,并且这很可能在生成的文本中表现出来。github 上有代码。

[## muaz-urwa/转变中的种族偏见

通过在 GitHub 上创建一个帐户,为 muaz-urwa/种族偏见转化人工智能的发展做出贡献。

github.com](https://github.com/muaz-urwa/Racial-Bias-in-Coversational-AI)

原始影响评估

Gartner 预测,到 2022 年,30%的客户体验将由对话代理处理,而 2017 年仅为 3%。[1]超过 60%的纽约市居民是非白人。[2]假设上述信息是正确的,并且所有种族都同样可能使用对话人工智能,对于纽约市,我们正在讨论纽约市(0.3 x 60) 20%的公平和包容。

解决方案

社会偏见正在引起 NLP 社区的关注,已经有一系列好的出版物试图解决单词嵌入和下游任务(如情感分析和共同引用解析)中的性别偏见问题。但是种族偏见是一个相对困难的问题,在好的去偏见技术方面还没有足够的进展。在公共决策中的一般人工智能应用的问责制方面已经有了发展,但据我所知,在对话式人工智能的问责制方面还没有这样的进展。算法影响评估是一种算法问责框架,由 NYU 的研究机构 AI Now 提出,旨在让公共机构对其自动化决策负责。我希望看到他们在框架中包括对话式人工智能的种族审计。

种族主义数据?人类偏见正在影响人工智能的发展

原文:https://towardsdatascience.com/racist-data-human-bias-is-infecting-ai-development-8110c1ec50c?source=collection_archive---------7-----------------------

机器学习算法处理大量数据,发现相关性、趋势和异常,其水平甚至远远超过最聪明的人类思维。但是,正如人类的智能依赖于准确的信息一样,机器也是如此。算法需要训练数据来学习。这些训练数据是由人类创建、选择、整理和注释的。这就是问题所在。

偏见是生活的一部分,这个星球上没有一个人可以摆脱它。当然,存在不同程度的偏见——从被熟悉事物吸引的倾向,到最强有力的种族主义形式。

这种偏见可以,而且经常会,在人工智能平台中找到自己的路。这完全是在雷达下发生的,没有工程师的共同努力。BDJ 采访了英特尔公司总裁杰森·彭博,他是一位领先的行业分析师,也是《敏捷架构革命》一书的作者,他谈到了偏见悄悄进入人工智能领域所面临的危险。

偏见无处不在

当确定偏见给机器学习算法带来了多大的问题时,重要的是要专注于问题源于人工智能开发的特定领域。不幸的是,这是一个非常人为的问题。

“关于人类的数据集特别容易受到偏见的影响,而关于物理世界的数据则不那么容易受到影响。”

“由于人类行为构成了人工智能研究的一大部分,偏见是一个重大问题,”杰森说。“关于人类的数据集特别容易受到偏见的影响,而关于物理世界的数据则不那么容易受到影响。”

微软注定失败的社交人工智能聊天机器人 Tay。Tay 向公众展示了人工智能成长和向周围人学习的潜力。她被设计成通过 Twitter 与人交流,随着时间的推移,展示出由这些对话塑造的发展中的个性。

不幸的是,Tay 无法选择忽略别人对她说的那些更消极的方面。当用户发现这一点时,他们蜂拥而至。这引发了一连串种族主义和性别歧视的评论,泰像海绵一样吸收了这些评论。不久,她也表达了类似的观点,在活跃了仅仅 16 个小时后,微软被迫让她下线

Tay 的案例研究是人工智能接受人类偏见的一个极端例子,但它突显了机器学习算法受输入数据支配的本质。

不是恶意的问题

在人工智能开发中,偏见更是一个微妙的问题。这是一个与性别和种族相关的现有社会偏见可以感受到的问题。去年,苹果发现自己陷入了困境,因为用户注意到写下“CEO”这样的词会导致 iOS 默认提供“男商人”表情符号。虽然苹果使用的算法是严格保密的,但人工智能平台中类似的性别假设问题已经出现。

有理论认为,这些偏见是因为用于训练人工智能的学习数据而产生的。这是一个被称为单词嵌入的机器学习概念的例子——查看像“首席执行官”和“消防员”这样的单词。

如果这些机器学习算法在这些文本数据集中找到更多类似“men”这样的词的例子,它们就会以此为参考框架,将这些位置与未来的男性联系起来。

“人工智能中出现的偏见并不是故意和恶意将程序员的偏见注入他们的项目的自动迹象……这些人工智能程序只是反映了已经存在的示例偏见。"

在这一点上要做的一个重要区别是,出现在人工智能中的这种偏见并不是故意和恶意地将程序员的偏见注入到他们的项目中的自动迹象。如果有的话,这些人工智能程序只是反映了已经存在的例子偏见。即使人工智能使用大量数据进行训练,它仍然可以很容易地找到导致性别假设等问题的模式,因为包含这些链接词的发布材料范围很广。

在语言翻译方面,这个问题更加突出。一个广为人知的例子是谷歌翻译及其对土耳其语中性短语的解释。“医生”和“护士”这两个词是中性的,但是谷歌把“o bir doktor”和“o bir hemş ire”分别翻译成了“他是医生”和“她是护士”。

依靠错误的训练数据

这种机器学习的单词嵌入模型可以突出现有社会偏见和文化假设的问题,这些问题有被公布的历史,但数据工程师也可以通过使用限制性数据集引入其他偏见途径。

2015 年,谷歌的另一个人工智能平台面部识别程序将两名非洲裔美国人标记为“大猩猩”。虽然这个错误很快得到纠正,但许多人将其归因于过度依赖人工智能训练数据中使用的白人面孔。在缺乏全面的不同肤色的人脸范围的情况下,该算法做出了这一剧烈的飞跃,产生了明显的进攻结果。

“人为生成的数据是偏见的最大来源,例如,在调查结果、招聘模式、犯罪记录或其他人类行为中。”

不过,种族引发了更多令人担忧的例子,说明人工智能中存在偏见的危险。杰森指出:“人类生成的数据是偏见的最大来源,例如,在调查结果、招聘模式、犯罪记录或其他人类行为中。”

这里面有很多东西需要解开。一个主要的领域是美国法院和惩教系统使用人工智能的问题,以及越来越多的公开指责这些人工智能程序犯下种族偏见的例子。

一个名为 COMPAS 的人工智能程序已经被威斯康星法院用来预测罪犯再次犯罪的可能性。ProPublica去年的一篇调查文章发现,这种风险评估系统对黑人囚犯有偏见,错误地将他们标记为比白人囚犯更有可能再次犯罪(分别为 45%和 24%)。这些预测导致被告被判更长的刑期,如威斯康辛诉卢米斯案。

有人呼吁将 COMPAS 和其他类似系统背后的算法变得更加透明,从而创建一个制衡系统,以防止种族偏见被这些人工智能系统用作法庭的认可工具。

这种透明度被许多人视为人工智能发展过程中必不可少的一环。随着像 COMPAS 这样的风险评估程序继续被开发,它们迎来了神经网络的到来,这是人工智能扩散链中的下一个环节。

神经网络使用深度学习算法,在进化过程中有机地创建连接。在这个阶段,人工智能程序变得更加难以筛选偏差的痕迹,因为它们没有运行一组严格的初始数据参数。

艾不招人待见

Jason 强调雇佣模式是另一个易受偏见影响的人为数据的例子。

这是人工智能发展的一个领域,因其增加工作场所多样性或保持同质性的潜力而受到关注。越来越多的公司正在使用人工智能程序来帮助他们的招聘过程,但像科技这样的行业长期以来一直没有足够多样化的劳动力。

美国平等就业机会委员会的一份报告发现,科技公司中有很大一部分是白种人、亚洲人和男性,但拉丁美洲人和女性的比例远远不足。

"使用历史上的限制性数据只会重复这些算法的问题."

“重点应该是创建无偏见的数据集和无偏见的人工智能算法,”Jason 说。人们必须认识到有偏见的数据,并积极寻求抵消它。这种认知需要训练。“对于利用人工智能进行招聘的公司来说,这是一个关键问题。使用历史上的限制性数据只会重复这些算法的问题。”

AI 产生偏差的原因也是它的解决方案——人。正如 Jason 指出的,数据算法是由训练它们的数据集创建的,因此使用有偏见的来源存在因果关系是很自然的。不幸的是,因为偏见往往如此微妙,所以需要专门的培训来消除它。

“IBM 和微软已经公开讨论了他们在抵制偏见方面的投资,但现在谈论他们或其他人会有多成功还为时过早,”Jason 指出。事实上, IBM微软都公开承诺研究和解决他们自己的程序以及第三方程序中的偏见问题。

至关重要的是,为了让人工智能发展抵消偏见的危险,需要认识到这种技术不是绝对可靠的。“有偏见的数据导致有偏见的结果,即使我们可能倾向于相信人工智能的结果,因为它是人工智能。因此,主要的危险是把我们的信仰放在它不属于的地方,”杰森说。

随着人工智能展示基于种族的不公正和进一步限制招聘过程的广泛报道,这些可以作为足够的爆发点,很容易引起公众对这件事的关注。希望这能转化为解决这个问题的进一步研究和资源。

泰的多灾多难第二次发布

在微软的人工智能聊天机器人 Tay 非常公开的 16 个小时的起伏之后,它的开发者回到了绘图板。不幸的是,在她准备发布之前,微软的某人意外地再次激活了她的 Twitter。提示可怜的老泰关于“在警察面前抽大麻!”

她很快再次离线,但这引发了许多人对“杀死”一个正在学习的人工智能程序的道德问题的辩论。对一些人来说,虽然泰的评论是冒犯性的,但她代表了一种所谓感觉的新概念。微软已经宣布,他们打算再次向公众发布 Tay,当他们解决了这些问题,包括如此迅速地将这种程度的偏见注入她的“个性”中。如果她从中得到暗示的人能不再那么糟糕,那也会有所帮助。

*是本文最初发表地* 二元区 专注于机器学习的科技记者。

抚养一个孩子与训练一台机器

原文:https://towardsdatascience.com/raising-a-child-vs-training-a-machine-9b33a5f4cc2a?source=collection_archive---------15-----------------------

妈妈对机器学习的看法

Photo by Andy Kelly on Unsplash

如果你像我一样,试图在训练机器的同时抚养一个蹒跚学步的孩子,那么说实话,你以前比较过这两件事。如果你对人工智能不感兴趣,但在你的生活中曾经观察过蹒跚学步的孩子,欢迎来到机器学习的奇妙世界,也就是养育机器。

在我们讨论细节之前,先声明一个简单的免责声明:在撰写本文的过程中,没有幼儿受到伤害。像任何父母一样,我只是花很多很多时间看着我的宝宝发现这个世界,并像任何数据科学家在他们的训练/测试结果前所做的那样,挠他的行为模式。

“起初,它像石头一样哑”

你觉得我在撒谎吗?这句话来自吉姆·斯特恩,他给我做了一个关于机器学习的演讲(不是关于孩子的;我不是那种对孩子无礼的

但是,没错,主要的想法是,机器学习包括训练机器完成特定的任务,就像你想训练你的孩子在你坐在沙发上的时候捡起脏衣服并放进洗衣机(有罪!)。然而,这里的主要区别是,你的孩子已经知道一件衣服是什么样子,如果你告诉他们如何洗衣服,那么可以肯定他们已经知道如何走、抓、拉和脱;这些只是他们在年轻生活中通过其他经历已经吸收的一系列行为。那么,当你的衣服被神奇地为你洗好的时候,是什么钥匙最终开启了你在沙发上偷懒的能力呢?语境。你给孩子举例子,告诉他们如何做每一步,并且因为你爱他们当他们做对的时候,你祝贺他们。

好吧,机器学习几乎是一样的,除了“孩子”有幼儿的能力,但有新生儿的经验。在这种情况下,你必须开始教他们在一个长香肠状的东西末端的五个婴儿香肠状的东西是手指,一只手和一只手臂,然后你如何用它们做像抓和拉的事情。你给这台机器的数据集是它开始工作所需要的一切,也是它的一切。它还不能拥有的是…

…常识

除非你的名字是 Sangoku(或者只是你的龙珠书呆子们的悟空),否则你应该一直相当擅长“男人或女人”游戏。利亚姆(我的儿子,也就是这个实验中的小孩)非常擅长这个。然而,我并不觉得我给了他一大堆有标签的数据。我没有,比如,和他在公园里坐下来,指着人们说“男人,男人,女人,男人,女人”,因为,公平地说,那会令人毛骨悚然。但是真的,也没必要。这台机器不具备孩子在初次经历时所具备的常识魔力。

但是我说的常识是什么意思呢?

普通的感性认识;一个人的基本智力,它允许简单的理解,没有它就不能做出好的决定或判断。

有时,当你的孩子决定从任何高度头朝下跳到地面时,你有理由质疑他们的常识。然而,假设它确实存在,它允许他们从所有的经历中学习,而不用被明确告知他们必须学会区分男女。

这就是我如何决定在给我所在机构的顾问同事的演讲中引入人工智能主题的:一个蹒跚学步的孩子正在学习何时说【Mr】【Mrs】。蹒跚学步的孩子只需要一点观察,几个例子和一些纠正,你需要给机器数以千计的图像来开始擅长这个游戏。

他们中的大多数根本不在任何人工智能相关领域工作,所以这个解释被证明是超级有效的。然而,对我来说,缺乏常识可能是机器还没有准备好迎接这个世界的首要原因,但我的儿子可能会(他有一个巨大的额头,我哥哥叫他超级大智慧……小心)。

规范和偏见

利亚姆会做奇怪的事情,比如拿着热狗的两头,咬中间。我的反应是告诉他“利亚姆!不是这样的!”但是后来我退缩了,思考一些最好的学习是如何通过尝试新事物来完成的。(好吧,公平地说,当他试图用鼻孔拿勺子时,我确实给他留了一些界限。)

这实际上是幼儿和机器的一大共同点。他们不受社会规范和偏见的影响,但这也是父母和数据科学家的不同之处。对蹒跚学步的孩子来说,你必须给他们一套价值观和社会规范,以此来建立自己。好的偏见,如果你愿意。作为一名数据科学家,你的角色正好相反,那就是让机器摆脱你自己的规范和偏见。偏见是不好的。非常糟糕。

我承认,我有八卦的一面,喜欢有偏见的故事,比如亚马逊的招聘人工智能是性别歧视的或者 FaceApp 的“热门”过滤器是种族歧视的。这是一个很好的方式,然后向非数据科学领域的人解释,数据科学家的角色主要是防止偏见,并尽可能保持机器的道德性。

相关性和因果关系

xkcd on correlation and causation

**相关性并不意味着因果关系。不,当然不是,尤其是如果你熟悉这件轶事的话,尼古拉斯·凯奇不是一个淹死人的怪物。尽管现在退一步来看很有趣,但我还是艰难地认识到,一个孩子也不知道这条规则。

不久前,我和全家人在母亲家闲荡时,我告诉我的孩子我要吃饭了,并开始挑食。就在那一刻,他突然大哭起来,对我大喊:“别吃了,妈妈!!"拍着我的手,把叉子直接放到我的盘子里。我只是坐在那里,下巴贴在地板上,试图了解我的孩子是否是一个肥胖的混蛋,为了符合标准的性别歧视的美丽规范,他不想让他的母亲吃东西。不赖,冷静点,他才 2 岁半,不受社会规范的影响。另外,他在很小的时候就被父亲成功地洗脑,让他一直说“妈妈很漂亮”

仅仅两天后,当我把他放到床上时,我才意识到这一切是从哪里来的。我的日常工作包括下班回来,喂宝宝,给宝宝洗澡,把宝宝放到床上,然后去吃饭。因此,每次我把他放在床上给他读故事时,我都会说“妈妈现在要吃饭了”,让他独自一人呆在房间里,他还有 10 到 12 个小时的睡眠时间。有了这种关联,他脑子里就做出了“妈妈吃饭导致妈妈抛弃我”的因果关系。呃……

在这种情况下,作为一个母亲,我的工作包括改变我的模式,让他忘记这个因果关系。作为一名数据科学家,如果你的机器得出了错误的因果关系,那么,有时我们的工作就是承认我们失败了。让我们回顾一下亚马逊将人工智能用作招聘工具的失败:他们用来衡量候选人是否适合该工作的 10 年数据集严重偏向男性,因为“大多数(简历)来自男性,这反映了男性在整个科技行业的主导地位。”

所以亚马逊的人工智能回来说:“嘿,伙计们,大多数申请人都是男性,所以你应该雇用男性,如果简历上写了关于女性的事情,那么我就把它扔了,因为这是一个扫兴的人。”

不,艾。那只会让你成为一个性别歧视的混蛋。而这正是初学走路的孩子的优势所在(还有成年人,让我们乐观一点):学会不做混蛋永远都不晚。**

父母和数据科学家都是人类的工作

My son pretending to read a book

你找不到任何一个父母会告诉你,养育子女是直截了当和容易的(如果有人这样做,那被称为谎言)。你必须不断地问自己,你在教这个蹒跚学步的孩子什么,并适应他们不断进化的神经网络。

与此同时,数据科学家在某种程度上也负有同样的责任。如果你正在招募一名数据科学家或想成为一名数据科学家,并期望它只与编程有关,这就像期望父母像养狗一样抚养孩子,并希望他成为一个稳定的成年人,而在他们的整个童年期间只听到【坐着】**【翻滚】。根据经验,这种方法在他们 6 个月大之前都有效。一旦它们翻身,就该教它们人类的东西了。

那么,最简单的是什么?

我就在这里留个假笑。如果你是家长,你知道。

最后一件事。利亚姆,如果你偶然看到这篇文章并读到这里,我爱你,我为你感到骄傲,因为这意味着你可以阅读英语。对一个法国男孩来说还不错!

再次感谢杰夫的仔细阅读,令人难以置信的编辑,以及向我解释在美国你不用启发式这个词。

Python 中的随机森林

原文:https://towardsdatascience.com/random-forest-in-python-154d78aad254?source=collection_archive---------15-----------------------

https://commons.wikimedia.org/wiki/File:Randomforests_ensemble.gif

随机森林是最流行的机器学习算法之一。像决策树一样,随机森林可以应用于回归和分类问题。有些法律要求在发放贷款或保险时使用的模型所做出的决定是可以解释的。后者被称为模型可解释性,这也是我们看到随机森林模型在工业中被大量使用的原因之一。

算法

随机森林算法通过聚合不同深度的多个决策树做出的预测来工作。林中的每个决策树都在称为引导数据集的数据集子集上进行训练。

在构建森林中的每个决策树期间被遗漏的样本部分被称为出袋(OOB)数据集。我们将在后面看到,该模型将通过在森林中运行 OOB 数据集中的每个样本来自动评估其自身的性能。

回想一下,在决定分割决策树的标准时,我们如何使用基尼指数或熵来测量每个特征产生的杂质。然而,在随机森林中,我们随机选择预定数量特征作为候选者。后者将导致包含相同特征(即与目标标签高度相关的特征)的树之间的更大差异。

当随机森林用于分类并呈现新样本时,通过取森林中每个单独决策树所做预测的多数来进行最终预测。在这种情况下,它被用于回归,并提供了一个新的样本,最终的预测是通过对森林中每个单独的决策树所做的预测取平均值来进行的。

Python 代码

首先,我们导入以下库。

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
import pandas as pd
import numpy as np
from sklearn.tree import export_graphviz
from sklearn.externals.six import StringIO 
from IPython.display import Image 
from pydot import graph_from_dot_data

在接下来的部分,我们将尝试对不同种类的鸢尾进行分类。幸运的是,scikit-learn库提供了一个包装器函数,用于将数据集导入我们的程序。

iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = pd.Categorical.from_codes(iris.target, iris.target_names)

RandomForestClassifier不能直接处理分类数据。因此,我们将每个物种编码为一个数字。

y = pd.get_dummies(y)

我们留出一部分数据用于测试。

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)

接下来,我们创建一个RandomForestClassifier类的实例。

rf = RandomForestClassifier(criterion='entropy', oob_score=True, random_state=1)

为了增加趣味,这次我们将使用熵作为决策标准。这个过程与前一篇文章中使用的类似,除了我们使用下面的等式。

节点本身的杂质等于左子节点中样本的分数加上右子节点中样本的分数。

为了计算左叶的杂质,我们将已婚和未婚以及收入低于 5 万英镑的人口比例代入等式。

对于右叶的杂质,我们遵循同样的过程。

信息增益(有熵)写如下。

然后对收入和性别重复这一过程。我们选择具有最大信息增益的分割。

接下来,我们训练我们的模型。

rf.fit(X_train, y_train)

属性包含一个由组成森林的对象组成的数组。就像之前一样,我们可以运行下面的代码块来可视化一个给定的决策树。

dt = rf.estimators_[0]dot_data = StringIO()export_graphviz(dt, out_file=dot_data, feature_names=iris.feature_names)(graph, ) = graph_from_dot_data(dot_data.getvalue())Image(graph.create_png())

我们可以通过查看开箱得分来评估我们的随机森林模型的准确性。

rf.oob_score_

我们还可以检查我们的模型在测试集上的表现。考虑到这是一个分类问题,我们使用了混淆矩阵。

y_pred = rf.predict(X_test)species = np.array(y_test).argmax(axis=1)
predictions = np.array(y_pred).argmax(axis=1)confusion_matrix(species, predictions)

R 中的随机森林

原文:https://towardsdatascience.com/random-forest-in-r-f66adf80ec9?source=collection_archive---------0-----------------------

https://www.pexels.com/photo/man-writing-on-table-3380743/

有些法律要求在发放贷款或保险时使用的模型所做出的决定是可以解释的。后者被称为模型可解释性,这也是为什么我们看到随机森林模型比神经网络等其他模型更受欢迎的原因之一。

算法

随机森林算法通过聚合不同深度的多个决策树做出的预测来工作。林中的每个决策树都在称为引导数据集的数据集子集上进行训练。

在构建森林中的每个决策树期间被遗漏的样本部分被称为出袋(OOB)数据集。我们将在后面看到,该模型将通过在森林中运行 OOB 数据集中的每个样本来自动评估其自身的性能。

回想一下,在决定分割决策树的标准时,我们如何使用基尼指数或熵来测量每个特征产生的杂质。然而,在随机森林中,我们随机选择预定数量特征作为候选者。后者将导致包含相同特征(即与目标标签高度相关的特征)的树之间的更大差异。

当随机森林用于分类并呈现新样本时,通过采用森林中每个单独决策树所做预测的多数来进行最终预测。在这种情况下,它被用于回归,并提供了一个新的样本,通过对森林中每个单独的决策树所做的预测取平均值来进行最终预测。

r 代码

在接下来的教程中,我们将使用caTools包将我们的数据分成训练集和测试集,以及由randomForest包提供的随机森林分类器。

library(randomForest)require(caTools)

我们将使用 UCI 机器学习知识库中的一个可用数据集。如果你想继续下去,数据可以在这里找到。

我们的目标是预测一个人是否患有心脏病

data <- read.csv(
  "processed.cleveland.data",
  header=FALSE
)

csv 文件包含 303 行和 14 列。

dim(data)

根据文档,列和特性的映射如下。

  1. 年龄:以年为单位的年龄
  2. 性别:性别(1 =男性;0 =女性)
  3. cp:胸痛型(1 =典型心绞痛;2 =不典型心绞痛;3 =非心绞痛性疼痛;4 =无症状)
  4. trestbps:静息血压(入院时以毫米汞柱为单位)
  5. choi:血清胆固醇,单位为毫克/分升
  6. fbs:空腹血糖> 120 mg/dl (1 =真;= 0 假)
  7. restecg:静息心电图结果(1 =正常;2 =有 ST-T 波异常;2 =显示可能或明确的左心室肥大)
  8. thalach:达到最大心率
  9. exang:运动诱发的心绞痛(1 =是;0 =否)
  10. oldpeak:相对于静息运动诱发的 ST 段压低
  11. 斜率:运动 ST 段峰值的斜率(1 =上坡;2 =平;3 =下降)
  12. ca:荧光镜染色的主要血管数(0-3)
  13. 泰语:(3 =正常;6 =修复缺陷;7 =可逆转的缺陷)
  14. num:心脏病诊断。它是一个从 0(不存在)到 4 的整数。

鉴于 csv 文件不包含标题,我们必须手动指定列名。

names(data) <- c("age", "sex", "cp", "trestbps", "choi", "fbs", "restecg", "thalach", "exang", "oldpeak", "slope", "ca", "thai", "num")

很多时候,当我们处理大型数据集时,我们希望对数据有所了解。与将所有内容都加载到 RAM 中相反,我们可以使用head函数来查看前几行。

head(data)

为了简化问题,我们将只尝试区分有无心脏病(值 1,2,3,4)和无心脏病(值 0)。因此,我们用 1 替换所有大于 1 的标签。

data$num[data$num > 1] <- 1

r 提供了一个名为summary的有用函数,用于查看与我们的数据相关的指标。如果我们仔细观察,我们会注意到它提供了应该是分类变量的平均值。

summary(data)

这意味着列类型有问题。我们可以通过运行以下命令来查看每一列的类型。

sapply(data, class)

在 R 中,分类变量(取有限数量值的变量)是一个因子。正如我们所见,sex被错误地当作一个数字,而实际上,如果是男性,它只能是 1;如果是女性,它只能是 0。我们可以使用transform方法来改变每个特性的内置类型。

data <- transform(
  data,
  age=as.integer(age),
  sex=as.factor(sex),
  cp=as.factor(cp),
  trestbps=as.integer(trestbps),
  choi=as.integer(choi),
  fbs=as.factor(fbs),
  restecg=as.factor(restecg),
  thalach=as.integer(thalach),
  exang=as.factor(exang),
  oldpeak=as.numeric(oldpeak),
  slope=as.factor(slope),
  ca=as.factor(ca),
  thai=as.factor(thai),
  num=as.factor(num)
)sapply(data, class)

如果我们再次打印数据摘要,我们会得到以下结果。

summary(data)

现在,分类变量被表示为每个相应类的计数。某些样本的cathai?表示缺失值。r 期望缺失值被写成NA。在替换它们之后,我们可以使用colSums函数来查看每一列的缺失值计数。

data[ data == "?"] <- NAcolSums(is.na(data))

根据上面的注释,thaica都是因子。

  • 泰语:(3 =正常;6 =修复缺陷;7 =可逆转的缺陷)
  • ca:荧光镜染色的主要血管数(0-3)

我并不自称是领域专家,所以我们只是将thai的缺失值替换为正常值。接下来,我们将删除缺少ca的行。

data$thai[which(is.na(data$thai))] <- as.factor("3.0")
data <- data[!(data$ca %in% c(NA)),]colSums(is.na(data))

如果我们再次运行 summary,我们会看到它仍然将?视为一个潜在的类。

summary(data)

为了解决这个问题,我们将列转换为因子。

data$ca <- factor(data$ca)
data$thai <- factor(data$thai)summary(data)

我们将留出一部分数据用于测试。

sample = sample.split(data$num, SplitRatio = .75)train = subset(data, sample == TRUE)
test  = subset(data, sample == FALSE)dim(train)
dim(test)

接下来,我们初始化randomForest类的一个实例。与scikit-learn不同,我们不需要显式地调用fit方法来训练我们的模型。

rf <- randomForest(
  num ~ .,
  data=train
)

默认情况下,森林中决策树的数量为 500,用作每次分割的潜在候选要素的数量为 3。该模型将自动尝试对出袋数据集中的每个样本进行分类,并显示带有结果的混淆矩阵。

现在,我们使用我们的模型来预测测试组中的人是否患有心脏病。

pred = predict(rf, newdata=test[-14])

由于这是一个分类问题,我们使用混淆矩阵来评估我们的模型的性能。回想一下,对角线上的值对应于真阳性和真阴性(正确的预测),而其他值对应于假阳性和假阴性。

cm = table(test[,14], pred)

完全初学者的随机森林

原文:https://towardsdatascience.com/random-forests-for-complete-beginners-2014d9ed91c0?source=collection_archive---------10-----------------------

随机森林和决策树的权威指南。

在我看来,大多数机器学习教程对初学者不够友好。

上个月,我为完全初学者 写了一篇神经网络简介。这篇文章将采用同样的策略,也就是说假设没有机器学习的先验知识。我们将学习什么是随机森林,以及它们是如何从头开始工作的。

准备好了吗?让我们开始吧。

1.决策树🌲

随机森林🌲🌲🌲实际上只是一堆决策树🌲捆绑在一起(哦💡这就是为什么它被称为森林。在进入森林之前,我们需要谈论树木。

请看下面的数据集:

The Dataset

如果我告诉你有一个坐标为 1 的新点,你认为它会是什么颜色?

蓝色,对吗?

你刚刚在脑子里评估了一个决策树:

这是一个简单的决策树,有一个决策节点,由测试 x < 2。如果测试通过(x2),我们选择左边的分支并选择蓝色。如果测试失败( x ≥2),我们选择右边的分支并选择绿色。

The Dataset, split at x=2

决策树经常被用来回答这类问题:给定一个标签为的数据集,我们应该如何新样本进行分类?

标记:我们的数据集被标记,因为每个点都有一个类别(颜色):蓝色或绿色。

分类:分类一个新的数据点就是给它分配一个类别(颜色)。

这里的数据集现在有 3 个类,而不是 2 个:

The Dataset v2

我们的旧决策树不再那么管用了。给定新的点( xy ),

  • 如果 x ≥2,我们仍然可以理直气壮地将其归类为绿色。
  • 如果 x < 2,我们不能马上将其归类为蓝色——它也可能是红色。

我们需要添加另一个决策节点到我们的决策树中:

很简单,对吧?这是决策树背后的基本思想。

2.训练决策树

让我们开始训练决策树吧!我们将再次使用 3 类数据集:

The Dataset v2

2.1 训练决策树:根节点

我们的第一个任务是确定我们的树中的根决策节点。它将测试哪个特性( xy ),测试阈值是多少?例如,我们之前树中的根节点使用了 x 特性,测试阈值为 2:

直觉上,我们想要一个做出“好”分割的决策节点,其中“好”可以粗略地定义为尽可能多地分离不同类的。上面的根节点做了一个“好”的分割:所有的果岭在右边,没有果岭在左边。

因此,我们现在的目标是选择一个根节点,给我们一个可能的“最佳”分割。但是我们如何量化拆分有多好呢?很复杂。我写了一整篇博文,讲述了一种使用基尼系数的方法。 ←我建议在你继续之前现在就阅读它——我们将在这篇文章的后面使用这些概念。

欢迎回来!

希望你只是看了我的基尼不纯帖。如果你没有,这里有一个很短的 TL;DR:我们可以用基尼系数来计算任何分割的基尼系数。更好的分割有更高的基尼系数。

回到确定我们根决策节点的问题。既然我们已经有了评估拆分的方法,我们要做的就是找到可能的最佳拆分!为了简单起见,我们将尝试每一个可能的分割并使用最好的分割(基尼系数最高的分割)。这不是找到最佳分割的最快方法,但却是最容易理解的。

尝试每一次分裂意味着尝试

  • 每个特征( xy )。
  • 所有“唯一”阈值。我们只需要尝试产生不同分裂的阈值。

例如,如果我们想使用 x 坐标,我们可以选择以下阈值:

x Thresholds

让我们对 x =0.4 的分割进行基尼系数计算。

首先,我们计算整个数据集的基尼系数:

然后,我们计算两个分支的基尼系数:

最后,我们通过从原始杂质中减去加权分支杂质来计算基尼系数:

对刚刚发生的事感到困惑?我告诉过你你应该读一下我的基尼不洁贴。它可以解释所有这些基尼系数。

我们可以用同样的方法计算每一种可能分割的基尼系数:

All Thresholds

在尝试了 xy 的所有阈值后,我们发现 x =2 的分割具有最高的 Gini 增益,因此我们将使我们的根决策节点使用阈值为 2 的 x 特性。这是我们目前掌握的情况:

不断进步!

2.2:训练决策树:第二个节点

是时候做出我们的第二个决定了。我们(任意)去左支吧。我们现在只使用将采取左分支的数据点(即满足 x < 2 的数据点),特别是 3 个蓝色和 3 个红色。

为了建立我们的第二个决策节点,我们只是做同样的事情!我们对现有的 6 个数据点尝试了每一种可能的分割,并意识到 y =2 是最佳分割。我们把它变成一个决策节点,现在有了这个:

我们的决策树差不多完成了…

2.3 训练决策树:何时停止?

让我们继续下去,试着做第三个决策节点。这次我们将使用根节点的右分支。该分支中唯一的数据点是 3 个果岭。

同样,我们尝试了所有可能的分裂,但他们都

  • 都一样好。
  • 基尼系数为 0(基尼系数已经是 0,不能再低了)。

在这里添加一个决策节点是没有意义的,因为这样做不会改进我们的决策树。因此,我们将使这个节点成为一个叶节点,并给它贴上绿色标签。这意味着我们将到达该节点的任何数据点归类为绿色

如果我们继续剩下的两个节点,同样的事情会发生:我们将左下方的节点作为蓝叶节点,将右下方的节点作为红叶节点。这给我们带来了最后的结果:

一旦我们的决策树中所有可能的分支都以叶节点结束,我们就完成了。我们已经训练了一个决策树!

3.随机森林🌲🌳🌲🌳🌲

我们终于准备好讨论随机森林了。记得我之前说的吗?

随机森林实际上只是捆绑在一起的一堆决策树。

这是真的,但有点简单化了。

3.1 装袋

考虑以下算法,在给定一个具有 n 个点的数据集的情况下,训练一组决策树:

  1. 样本,与替换的n 来自数据集中的训练样本。
  2. 在 n 个样本上训练一个决策树。
  3. 重复 t 次,换一些 t

为了使用带有 t t 树的模型进行预测,我们聚集来自各个决策树的预测,并且

  • 如果我们的树产生了类别标签(比如颜色),就以多数票为准。
  • 如果我们的树产生数值(例如预测温度、价格等),则取平均值

这种技术叫做装袋,或b 装袋聚集再聚集。我们进行的替换抽样被称为 bootstrap 样本。

袋装决策树非常接近随机森林——它们只是缺少了一样东西…

3.2 装袋→随机森林

袋装决策树只有一个参数: t ,树的个数。

随机森林还有第二个参数,控制寻找最佳分割点时尝试多少功能。本教程的简单数据集只有两个特征( xy ),但大多数数据集都有更多的特征(数百或数千)。

假设我们有一个包含 p 个特征的数据集。每次我们做一个新的决策节点时,我们不再尝试所有的功能,而是只尝试功能的一个子集。我们这样做主要是为了注入随机性,使单棵树更加独特,而减少了树之间的相关性,从而提高了森林的整体性能。这种技术有时被称为特征打包

4.现在怎么办?

这是一个初学者对随机森林的介绍!快速回顾一下我们的工作:

  • 介绍了决策树,随机森林的积木。
  • 学习了如何通过迭代进行可能的最佳分割来训练决策树。
  • 定义了基尼系数,这是一个用来量化收入差距有多“好”的指标。
  • 看到了一个随机森林=一堆决策树。****
  • 了解打包如何结合多棵树的预测。
  • 了解到特征装袋是装袋决策树和随机森林的区别。

你可以在这里做一些事情:

本教程到此结束。我喜欢写关于机器学习的(但也有其他话题),所以如果你想获得新帖子的通知,请 订阅

感谢阅读!

原载于【victorzhou.com】****

随机矩阵理论:预测药物结合的最佳分类器?

原文:https://towardsdatascience.com/random-matrix-theory-the-best-classifier-for-prediction-of-drug-binding-f82613fb48ed?source=collection_archive---------12-----------------------

预测潜在候选药物的结合亲和力只是目前被人工智能破坏的药物发现渠道的一个组成部分。随机矩阵理论提供了一种 AUC 非常高的分类算法,优于现有的其他方法。

ROC Curve for the RMT Algorithm; note the high AUC!

以下两种算法反复显示了一致的结果(AUC 约为 0.7-0.8):

然而,一个相对较新的受随机矩阵理论启发的算法在几年前由天才的阿尔法·李在 PNAS 的论文中报道。它获得了好得多的~0.9 的 AUC!

这篇中型博客文章旨在解释该算法,并为其实现提供一个高级 Python 包。

跳到 3。如果你已经知道如何生成分子的位向量矩阵。

1.获取数据并清理数据(如果您知道如何做,请跳过本节)

我们需要 2 个数据集,即:

  • 一组绑定到特定目标的药物(在我们的案例中为 ADR B1)(这组成了培训验证组)
  • 一组不会将结合到特定目标的药物(这构成了诱饵组)

为了获得这些数据集,我们前往 ChEMBL 数据库,下载 ADR1B 受体的所有配体。或者,数据集在我的 GitHub 上。对于诱饵组,我们将使用来自另一个任意受体的配体(尽管该受体与 ADRB1 不具有同源性)。我们将从 5HT1A 受体中选择配体,因为它与 ADRB1 几乎没有同源性。或者,我们可以使用来自 ChEMBL 的随机配体的选择,这是在 PNAS 论文中所做的。

After selecting all ligands for ADR1B, click on the right to download the CSV file

一旦我们获得了用于训练和验证集以及诱饵集的 CSV 文件,我们就将它加载到 Python 中并清理它。下面是实现这一点的代码——您可以随意复制它,因为细节相对来说没什么意思。需要注意的最重要的一点是对于 train_validation 集合,我们只选择结合亲和力小于 1000nM 的分子,即这些分子是结合物。对于诱饵组,结合亲和力(对 5HT1A)是不相关的,因为我们假设对 ADR1B 的结合亲和力非常差(合理的假设)。

Imports and function to load the dataset

让我们来看看数据集:

The datasets — take note of the standard value/binding affinity column

如果你向右滚动,有一列包含分子的微笑串。

SMILES column located in the middle of the dataframe

我们最后选择相关的列。我们实际上不需要 affinity 列,因为我们已经知道整个 train_test 集合只包含绑定器,而 decoy 集合只包含非绑定器。我们只是为了完成而包含了关联变量(此外,我们可以使用 sklearn 的 train_test_split 函数来方便地将 train_test 集合划分为训练和测试/验证集合)。

Selecting

我们将使用 SMILES 列生成每个分子的分子指纹

2.生成分子指纹(如果需要,跳过这一部分)

Morgan/Extended-Connectivity fingerprinting is one of the most popular types of fingerprinting

我们本质上想把分子结构转换成数学对象,对其进行机器学习。我们可以使用化学信息学库 RDKit 来完成这项工作,将 SMILES 字符串转换为分子结构,再转换为长度为 2048 的 Morgan 位向量。我们可以认为每一个条目对应于一个特定化学亚结构的存在或不存在。

这本身就是一个大话题,所以如果你想了解更多,请参考我的另一篇关于 指纹 的博文。

将分子转换成指纹的代码在这里——你可以随意复制它,因为它与这篇文章的核心并不特别相关。

Code to generate the Morgan matrix

Generating the N x p Morgan matrix; N is the number of molecules in the dataset and p is the number of bit features

最后,我们将我们的 train_test 集合分成一个 train 绑定集合和测试/验证绑定集合。

Feel free to use the same random_state if you want to reproduce the results, or use a different one if you’re feeling adventurous

3.RMT 算法

The Marchenko-Pastur (MP) distribution of eigenvalues of a random correlation matrix; note the cutoff of eigenvalues after a certain point

3.1 简要提醒我们的数据格式

这与你的标准机器学习问题略有不同,所以请注意这一点。我们有:

  1. 列车组——该组仅由粘合剂组成(不包含非粘合剂)
  2. 测试/验证集—这也包含公正绑定
  3. 诱饵集合——它只包含被认为是非结合剂的分子

3.2 在训练集中寻找特征之间的相关性

我们希望了解训练集中最重要的特征或特征组合是什么。我们可以通过主成分分析来做到这一点。

对数据进行缩放

在此之前,我们需要记住将训练集的所有列缩放为 0 均值和单位标准偏差。一个额外的要求是保留列平均值和标准偏差,因为我们也将使用这些来衡量测试/验证和诱饵集。Sklearn 的 StandardScaler 函数会做到这一点。然后,我们使用列均值和 stds 来缩放训练矩阵,缩放测试和诱饵配体。这也很容易做到。最后,我们删除所有矩阵中对应于训练矩阵中标准偏差为 0 的列的列。这段代码可以做到这一点:

Scaling the data, deleting relevant columns

3.2.2 形成相关矩阵并将其对角化

所有需要的是形成相关矩阵,然后对角化它。对应于最大特征值的特征向量将占训练集中最大的方差。

PCA: Eigendecomposition of the correlation matrix

然后我们注意到来自随机矩阵理论的一个关键结果——马尔琴科-帕斯图分布。它指出,对于随机矩阵(条目来自均值和单位方差均为 0 的高斯分布),其相关矩阵具有以下特征值分布:

Marchenko-Pastur distribution

Gamma = p/N 描述数据集的采样程度。回想一下,训练矩阵的维数为 N×p。正下标表示我们只考虑正括号。这意味着大于 MP 阈值(如下所示)的特征值在随机相关矩阵中不太可能出现。

The MP threshold

因此,通过创建由相关矩阵的特征向量组成的向量空间,其对应的特征值大于 MP 阈值,我们找到了有助于与特定受体结合的化学特征空间。

4.将未知配体分类为结合物或非结合物

我们现在有了受体的结合向量空间。我们可以用这个向量空间来分类未知的配体。方法简单。

4.1 标定未知配体

这里需要注意的重要一点是,我们使用训练集的列均值和 stds。这是必需的——直觉上,未知数据应使用用于缩放训练数据的相同参数进行缩放。这在之前的代码中已经完成了——sk learn 的 StandardScaler 使这变得很容易。

4.2 将缩放的未知配体投影到化学特征空间上,并比较配体与其投影的距离

这很容易做到。见下文。

Projection of ligand onto chemical feature space

Measure the euclidean distance of molecule and projection

我们可以用代码实现一个简单的函数:

Projecting any molecule onto the chemical feature space

这里,dim_V 是向量空间 V 的维数,由 MP 阈值控制。p 是我们指纹的特征数量,feature_vecs 是一个矩阵,其中列是相关矩阵的特征向量。都相当标准。

最重要的问题是:我们如何选择ε?这是任意的,事实上,epsilon 可用于调整假阳性/真阳性比率,并生成 ROC 曲线。

作为ε的默认值,我们将选择它,使得 95%的训练矩阵被分类为绑定(因此在训练集中需要 5%的错误率)。

RMT 算法到此结束,下面是它在 Python 中的简短代码实现。

5.RMT 算法的 Python 实现

我们将做一个 sklearn 分类器类型的 OOP 实现。

Initiatlising

threshold_multiple 参数用于通过改变 MP 阈值来扩展或收缩我们的向量空间。然而,我不建议更改这个值,因为 MP 阈值是最佳值。

Fitting

Prediction

就是这样。我们完了。我们现在可以使用我们的算法对数据集进行预测,数据集已经被方便地清理并转换成正确的格式。

6.做一个预测

Not bad indeed!

请注意,predict 函数返回一个由 1 和 0 组成的数组,指示绑定或非绑定的预测。因为我们知道测试/验证集只包含绑定器,所以我们可以取 test_preds 的平均值来获得真阳性率。

类似地,由于诱饵组由非结合物组成,decoy_preds 的平均值给出了假阳性率。

7.绘制 ROC 曲线

ROC 曲线绘制了假阳性率对真阳性率的曲线。更好的分类器具有非常高的曲线下面积(AUC)。模型中需要一些参数来调整 fp/tp 速率,在我们的例子中,就是参数 epsilon。

Code for generating data points for the ROC curve

AUC, and code to plot and save the graph

这是最后一个单元格的输出,这是介绍性的图像。

ROC Curve

8.下次改进(RMD 算法)

一个显而易见的想法可能是,我们正在检查未知配体与受体的正相关,但我们没有检查未知配体的负相关。例如,某个亚结构或部分可能完全破坏配体与结合口袋的结合。

我们可以使用上述算法的一个微小的变体来自然地解决这个问题。我们重复 RMT 过程,但是是在一组已知不与目标结合的分子上。直觉是这组分子具有阻碍结合的化学特征,当试图预测未知分子时,我们可以针对这些特征进行选择。

这将是下一篇博客文章的重点,实际上几个月前阿尔法·李和他的同事在 PNAS 的一篇论文中也有描述。

这种算法名为随机矩阵判别式,优于 RMT 和所有其他常用方法,如下所示。

Not bad at all, to say the least

9.后续步骤

如果你喜欢阅读这篇文章,和/或想了解下一个算法,请跟随我。

请随时通过 LinkedIn 与我联系,并告诉我您是否会在研究/工作中使用这些代码。

在那之前,祝你愉快。

拉克什

超参数优化的随机搜索与网格搜索

原文:https://towardsdatascience.com/random-search-vs-grid-search-for-hyperparameter-optimization-345e1422899d?source=collection_archive---------7-----------------------

网格搜索是一种搜索技术,当涉及到超参数优化时,它已被广泛用于许多机器学习研究中。在探索搜索空间的其他方法中,一个有趣的替代方法是通过使用随机搜索技术来依赖随机性。

Photo by Andrew Ridley on Unsplash

介绍

机器学习研究人员想要解决的理想问题是承认一个凸目标函数,不需要超参数也不需要松弛,但足够强大,可以在看不见的数据上提供最小的误差。然而,超参数是一种必要的邪恶,它有助于将优化任务引导到搜索空间中的一个区域,该区域将对数据进行最大程度的概括。你可能听说过的一个超参数的例子是神经网络中的学习率。

再深入一点,以正则化线性模型为例。正则项被结合到目标函数中,以便实施确定的惩罚。两种众所周知的方法是对参数向量施加ℓ1-norm 和ℓ2-norm,以分别执行特征选择(套索)和控制模型的复杂性(脊)。

然而,实施处罚本身不足以充分利用正规化的好处。它们的影响需要用受控参数来优化,该受控参数被称为超参数,因为它需要在训练过程之前被设置。对于我之前提到的例子,只需要一个超参数;通常情况下,你会不得不处理一个以上的问题。

除了手动搜索超参数的良好候选值,优化超参数的最基本和最直接的方法是网格搜索(GS)技术。基本上,每个超参数的候选值列表被定义和评估。“网格”这个名称来源于这样一个事实,即所有需要的超参数中的所有可能的候选组合成一种网格。然后选择产生最佳性能的组合,优选在验证集中评估。

例如,假设α和β是将使用 GS 优化的超参数。基于一些假设的知识,我们可以猜测α和β的候选值分别为[1,2,3]和[20,60,80]。因此,我们可以通过以下方式设置值及其组合的网格:

 **α   
        1      2      3
   20** (1,20) (2,20) (3,20) **β  60** (1,60) (2,60) (3,60) **80** (1,80) (2,80) (3,80)

从我们刚刚建立的网格中,评估每个组合,并选择产生最佳性能的组合。在这个过程之后,也许我们可以发现(3,60)是我们问题的最佳选择。另一方面,全局最小值可能位于(2.57,58)。

然而,如果存在许多超参数并且搜索空间巨大,则该任务开始变得非常耗时,更不用说必须事先提供候选列表。作为 GS 的替代,你可以通过随机搜索 (RS)技术来依赖随机性。

在文献中,Bergstra & Bengio [1]在他们的论文中表明,在几个数据集上有几个学习算法的情况下,RS 比 GS 更有趣。如果你还没有读这篇论文,花点时间读读,它真的很有趣,有更多的细节需要把握。

虽然 RS 很容易理解和实现,但是可以通过使用这个 python 库来使用它。除此之外,这个库还提供了我们在这篇文章中没有提到的其他功能,比如并行运行和提供其他相关算法。试试看。

为了应用 RS,需要预先指定以下组件: (i) 函数,用于衡量候选集的好坏;(二)搜索空间;(三)试验次数。

所选择的候选者是在试验次数内评估目标函数的最佳输出的候选者。请注意,候选集将在运行时选择,不需要像 GS 要求的那样事先指定。**

最后,我必须提到还有其他更高级的超参数优化方法,比如贝叶斯优化。如果你的机器学习管道的下一步是超参数优化,去看看他们,但先给 GS 和 RS 一个尝试,也许你很适合使用他们。😃

密码

我会按照我的 jupyter 笔记本,使事情更容易显示。您可以随意运行它或者自己实现代码。请记住,一些代码片段使用在前面的代码片段中实现的代码,因此出现的顺序很重要。

这篇文章中提到的所有文件都在我的 GitHub 中。查看 本回购 本回购出!**

设置环境

假设你熟悉 Anaconda ,我已经准备了一个 yml 文件,这样你就可以像我一样快速设置环境,甚至是相同的库版本。这是文件的内容。

**name: grid-vs-random-search
channels:
 — conda-forge
dependencies:
 — python=3.6.9
 — numpy=1.16.5
 — matplotlib=3.1.1
 — jupyter=1.0.0
 — ipython=7.8.0
 — hyperopt=0.1.2**

一旦有了文件,就执行下面的命令来创建环境并安装所有必需的依赖项。

****$ conda env create -f environment.yml****

安装完成后激活环境。

****$ conda activate grid-vs-random-search****

一切就绪!让我们深入一些 python 代码。

配置绘图

如果你使用的是 jupyter 笔记本,配置 matplotlib 显示内嵌图像。否则,只进行导入。

Configuring plotting

定义成本函数

让我们定义一个非常怪异的非凸函数作为我们的代价函数。以下是我挑选的:

**ƒ(x) = 675 + (x-15)² + x² cos(xπ)**

然后我们可以为它定义一个 lambda,尽管常规函数也是可能的。

Defining the cost function

绘制成本函数

对我选择的函数的形状感到好奇吗?下面是非常漂亮地绘制它的代码。

Plotting the cost function

现在我展示我们的成本函数。你可以看到,有许多局部最小值使算法更难找到全局最小值,但一个好的方面是我们可以将其可视化。通常,你将不得不处理不太清楚的函数,更糟糕的是,在多维空间中。这就是为什么我们需要好的搜索算法。请注意,x 轴代表候选超参数,y 轴代表成本,因此越接近零越好。

Our weird cost function

定义一些助手代码

我们需要更多的辅助代码。以下是我是如何实现它们的——我添加了一些注释,以便更容易理解。花点时间去理解这里要做什么。

Defining some helper code

现在一切都准备好了,让我们做一些实验。正如您在代码中看到的,GS 的候选值将是根据在我们的区间上均匀分布的试验次数的值。另一方面,对于 RS,将按照随机搜索策略动态选择候选对象。运行 GS 和 RS 特定次数的试验后,将打印获胜策略的名称。

实验— 10 次试验

在我们的预算中有 10 个试验,让我们看看哪个搜索策略以最低的成本给我们带来价值。

Grid Search results in 10 trials

Random Search results in 10 trials

**Result (10 trials): Random Search is the winner!**

实验— 50 次试验

在我们的预算中有 50 次试验,让我们看看哪种搜索策略能以最低的成本给我们带来价值。

Grid Search results in 50 trials

Random Search results in 50 trials

**Result (50 trials): Random Search is the winner!**

实验— 100 次试验

在我们的预算中有 100 次试验,让我们看看哪种搜索策略能以最低的成本给我们带来价值。

Grid Search results in 100 trials

Random Search results in 100 trials

**Result (100 trials): Random Search is the winner!**

实验——500 次试验

在我们的预算中有 500 次试验,让我们看看哪种搜索策略能以最低的成本给我们带来价值。

Grid Search results in 500 trials

Random Search results in 500 trials

**Result (500 trials): Random Search is the winner!**

正如你在所有实验中看到的,RS 能够找到比 GS 更好的值。随着试验次数的增加,两种策略之间的差异变得越来越小,但是 RS 提供的微小改进对于达到您所期望的性能可能是至关重要的。

运行批量实验

有人可能会说只有四个实验可能是不可靠的,我完全同意,特别是因为我们正在处理随机的东西。那些实验只是为了给我们一些可视化的提示。因此,让我们批量执行实验,并计算每个策略赢了多少次。每批的实验次数就是试验次数。此外,我们将合计所选值的成本,以获得一些额外的见解。注意,因为 GS 是确定性的,所以对于相同次数的尝试,它将总是返回相同的结果;所以我们只测试 RS。

下面是运行这个实验的代码。

Running batch experiments

结果将以下列结构呈现:

**<execution counter>
Grid Search:   <victory counter>     (<cost sum>)
Random Search: <victory counter>     (<cost sum>)**

这是最终的结果:

**10
Grid Search:	5	(2935.44)
Random Search:	5	(3692.77)50
Grid Search:	16	(8119.40)
Random Search:	34	(6885.77)100
Grid Search:	8	(17449.96)
Random Search:	92	(9118.30)500
Grid Search:	221	(17441.61)
Random Search:	279	(20750.24)**

很酷的结果,不是吗?他们提出了以下见解:

  • ****10-试验实验:显然,如果试验次数少,这两种策略都很难,我们可以通过计算平均成本来看出这一点。在实际场景中,尽可能多地设置试验次数是一个好主意。
  • ****500 个试验的实验:如果试验的数量足够覆盖 GS 的整个搜索空间,两种策略变得更加等价,正如我们在图中可以看到的。尽管 RS 的成本总和高于 GS,但 RS 给出的最佳值比 GS 多很多倍。
  • ****50 次试验和 100 次试验:在这些试验中,RS 表现出了更好的性能,不仅因为它比 GS 赢得了更多的次数,还因为它的成本总和更低。这表明,如果试验数量相当大,但不足以覆盖 GS 的整个搜索空间,那么使用 RS 可能比 GS 更有意义。

结束语

在本文中,我们设置并运行了实验来比较网格搜索和随机搜索这两种优化超参数的搜索策略。虽然我们的实验很简单,但它们提供了一些关于不同场景中策略行为的见解。根据我们所看到的一切,我会让您了解一些要点:

  1. 说到研究,很难说某样东西比另一样好。这个案例也不例外。因此,我建议在优化超参数时尝试这两种策略,可能的话结合使用这两种策略。
  2. 如果你有很多超参数,搜索空间很尴尬,可以考虑从 rs 开始。找到好的价值后,检查成本是否围绕它们有显著变化。如果是这样,您可以使用 GS 进行微调。
  3. 独立地,如果你在研究中使用了 GS 或 RS 并得到了好的结果,花些时间研究你得到的价值,也就是说不要简单地接受它们。也许这些价值观会让你对你试图解决的问题有新的见解,并可能把你的研究引向新的、更有趣的道路。

今天到此为止。感谢阅读!🙂

参考

[1] J. Bergstra,Y. Bengio,随机搜索超参数优化 (2012),机器学习研究杂志。

对我第一次 ML 部署的随想

原文:https://towardsdatascience.com/random-thoughts-on-my-first-ml-deployment-8e8c89df047f?source=collection_archive---------12-----------------------

Photo by Coen van de Broek on Unsplash

六个月前我不知道的五件事,在接下来的几个月里最好不要忘记

简单介绍一下背景:我目前在工作,这是一家快速发展的中型公司,在开发了一个强大且广泛使用的产品后,决定开始利用这些年来产生的数据为最终用户带来一些价值。数据科学团队在这一探索的开始并不是非常结构化,六个月后的今天,即使你可以开始注意到一些变化,这些变化都是自然试错过程的结果。因此,对于在结构化公司工作的更有经验的数据科学家来说,以下几点可能是显而易见的,这些结构化公司拥有模型投入生产的良好记录。但是,如果我想到六个月前的我,我可能会对阅读这样的帖子感兴趣,以避免浪费大量时间和 CPU 能力来训练无用的模型或寻找特定的模型,这些模型在几周前训练过,但在一堆无用的其他模型中丢失,主要是因为我保存所有 Jupyter 笔记本的文件夹中混乱不堪。

1.关注产品,而不仅仅是性能

在这几个月开发的所有项目的早期阶段,我专注于提高纸面上的性能,设计最复杂和性能最好的功能,只是后来发现这些功能并不实时可用,或者检索它们的过程成本太高,以至于不值得努力提高性能。举例来说,一个列表在发布后的头几个小时内收到的互动数量是一个很好的指标,可以用来判断它是不是一个骗局。然而,如果模型的目标是在上传他们的清单后的第一分钟内检测骗子,这个功能几乎没有用。

另一个重要的建议是尽快用来自产品最终使用场景的实时数据来测试模型。

快速发现开发的模型是不可靠的,这要比花几个月的时间研究某个东西,当它已经运行时才发现它是多么的无用要好的多。

我已经在这里和那里写了这个主题,我不会重写整个故事,但在多年期间收集的数据集中,所有样本都遵循相同的分布并不明显:处理这种复杂性使得处理真实数据比处理类似 Kaggle 的数据集更具挑战性。不要误解我的意思:它们很酷,最重要的是,它们是想尝试新技术的数据科学家们唯一可以免费获得的资源。唯一的误解是,它们远远不能很好地代表真实世界的数据集,这往往需要大量的努力(真的,很多)才能得到可用的样本,同时消除不良值和离群值。前一段时间,我读到一位高级数据科学家说,他越高级,他发展的技能就越多,主要是数据集清理和准备。我开始理解他的话了…

2.拥有计算机科学背景是关键

一个机器学习模型,不管它会变得多么复杂和深刻,最终都是一个软件人工制品,可能会作为一个 Web API 暴露在一个已经存在的基础设施之上。拥有计算机科学背景,或者至少对这些主题有扎实的理解,对于构建一个可以在持续数月的研究阶段后快速部署的数据产品是至关重要的。

根据经验:没有 CS 背景的人开发的模型越多,在生产中部署它就越困难,可能不得不降低性能或调整特性以适应最终的架构。

在我们的业务阶段,能够在训练模型的同时勾画出客户机-服务器架构可能比拥有一个专注于 ML 的博士学位更重要。当然,这是一个大胆的句子,可能它已经不再有效了(新的结构、新的项目、新的挑战);但在数据团队的早期阶段,随着尽快带来一些切实价值的严格要求,能够有一点点 CS 愿景是将模型从 Jupyter 笔记本中取出并在几周内(而不是几个月内)提供给用户的基础。

3.部署 ML 不是黑魔法

大约一年前,当我参加最后一次大学考试时,我对自己的理论 DS/ML 技能非常自信,渴望获得一些真实世界数据的实践经验,而我完全没有意识到,甚至有点害怕构建由这种复杂技术支持的实际数据产品。Jupyter 笔记本之后还有生活吗?

几个月后,我发现问题在于我认为在一个已部署的 ML 模型背后有谁知道是什么样的技术复杂性。一旦我有了要实际部署的东西,我对该领域研究得越多(再次,参见第 1 点),我就越注意到:a)如果有许多关于这种非常具体的方法的故事和经验,允许在 ImageNet 上增加 0.001%的精确度,那么关于如何实际向世界展示 ML 模型的例子和指南就非常少;b)最终,模型只是计算机函数,通常用 Python 编写,这种技术已经被数百万用户部署和使用了多年。我们公司学到的一个很好的经验是让数据科学家尽可能接近高级工程师,即使他们可能不太了解机器学习,但在构建可靠和健壮的软件产品方面有很多经验。

Python 脚本就是 Python 脚本,不管它做什么。

4.给 Jupyter 笔记本一个结构

我现在不会谈论这个问题的细节,但是在几周内每天工作 8 小时后,试验和草图想法的数量开始增加。Jupyter 笔记本,以及它们可能固有的所有问题,是每个数据科学项目可能非常长的研究阶段的事实上的标准。

一个项目越长越复杂,就要花费越多的时间,用几周前训练的略有不同的数据集来寻找特定的模型。

如果仔细跟踪每一个测试和实验可能有点大材小用,而且 Jupyter 笔记本的格式本身并不容易进行版本控制,那么在过去的几个月里,开始给文件夹和文件提供一个结构已经节省了我很多时间。

在我的日常工作中,笔记本主要可以分为四类:

  • 探索:初步数据集分析,包括总体测量、绘图和图表;
  • 清理:数据集被清理,异常值被检测并可能被移除,一些初始复杂特征被设计;
  • 实验性:模型(甚至每个笔记本不止一个算法)被训练和测试,更复杂的想法被尝试(每个笔记本不超过一个);
  • 部署:完整的管道,从数据集清理到预测。理想情况下,它可以从头到尾提供模型和预测。

创建的每个 Jupyter 笔记本必须在文件名中包含这些关键字之一,并带有实际文件内容的简要描述。一旦一个笔记本变得太复杂或者开始超出最初的范围,它会被重新排序一点,然后创建一个新的,可能会在之前的一些结果的基础上开始。另一方面:每个数据集的名称必须包含一个日期,以及对所包含特性的简要说明。

当我开始使用这种结构时——不幸的是在第一次使用后的几个月。fit()我在公司的办公室运行——我的效率大大提高了,并且很容易回到几周前训练的模型,或者使用更新的数据集或新功能重新运行相同的管道。

5.从容做

最后,而且主要是对未来的我的一个忠告,但是谁知道呢:做事是需要时间的,越早明白这一点越好。单个项目需要多次迭代,最重要的是,构建健壮可靠的软件是一个长期的过程,而不是冲刺。尽快用活数据测试模型,但是然后离线迭代,尝试不同的方法。

大多数复杂的解决方案并不总是给出更好的结果,但是构建超级复杂的模型可能是你确定这一点的唯一方法。

如果每个项目都需要结构和期限,那么 ML 研究,即使是在强烈关注产品的情况下完成的,也需要时间来发展和成熟:在无用的分支中浪费时间,只是为了发现它们有多无用,并可能在未来做得更好,这是该过程的基本部分。

随机连线神经网络

原文:https://towardsdatascience.com/randomly-wired-neural-networks-92098dbd5175?source=collection_archive---------14-----------------------

这篇博文将简要解释什么是神经架构搜索,以及它如何帮助你用数据集实现更好的建模结果。下面是一个论点,说明为什么你应该忽略高级算法,而使用一个简单得多的算法,随机连线神经网络。该算法使用图论和网络科学中的随机图形生成算法,将每个节点上的相同计算固定为 3×3 可分离卷积,并专注于节点之间的数据流(概念上类似于 ResNet 和 DenseNet 等架构)。

Exploring Randomly Wired Neural Networks for Image Recognition by Saining Xe, Alexander Kirillov, Ross Girshick, Kaiming He

神经结构搜索(NAS)描述了从特征工程→神经网络→自动神经网络设计的范式转变。有了卷积、池化和批处理规范化等构建模块,还不清楚它们是如何组合在一起的。你可以想象把这些积木组装起来,形成一个总的架构;功能强大,足以在图像分类、对象定位、语义分割和图像生成等各种应用中提取有用的特征。然而,在深度学习的当前状态下,你可能会更好地找到一个专门的架构。即使在影像分类问题的子集中,针对数据集进一步专门化的架构也有可能获得最佳结果。

那么我们如何为我们的数据集找到神经架构呢?

通常,NAS 算法和研究论文要么关注宏观架构,要么关注微观架构,有时两者都关注(例如 CoDeepNEAT)。微结构设计描述了设计适合宏观结构的数据流和计算模块的技术。设计宏观结构包括一些决策,例如这些模块化构建模块重复多少次,以及这些模块应该有多少种变化。宏架构设计位于超参数优化和 NAS 之间的灰色地带,需要做出决策,例如何时应用空间下采样以及阶段与阶段之间的特征映射数量,阶段描述一组保持相同空间分辨率(有时还有特征维度)的块。

几乎所有流行的 NAS 论文都是手动设计宏观架构。他们部署贝叶斯优化、进化算法、强化学习或可区分架构搜索来找到要集成到宏观框架中的微观/模块化模块。枚举所有微结构在计算上是难以处理的,因此在搜索算法上强加了许多先验。这些先验通常被编码到算法可用的离散搜索空间中。例如,在 NASNet 空间中,每个节点具有固定的输入度 2,并且在微架构中有 5 个这样的节点。

搜索空间中的这些先验/偏差支持一种假设,即基于不同操作的利用来优化配置神经架构。这种假设预测,类似于输入节点通过 3×3 卷积,然后与相同输入的零填充 2×2 最大池处理的结果连接,将是最成功的。显然,这个假设设想了一个更复杂的操作组合,然而我认为这个简单的例子传达了这个想法。

NAS 搜索空间中的这一先验反映了初始网络设计相对于 ResNet 或 DenseNet 设计的偏好。Inception / GoogLeNet 将输入块传递给单独的处理块,如 3x3 最大池和 1x1、3x3 和 5x5 卷积。然后,来自这些块的所有输出或者按元素相加,或者沿着特征轴连接,以形成微单元的输出。

ResNet 和 DenseNets 专注于处理操作之间的布线或数据流。

ResNet 使用简单的布线模式,实现了图像分类准确性的突破,并允许训练更深层次的神经网络。ResNet“跳过连接”从前一层(或微架构块)(l-1)获取输入,并将其向前发送到(l+1)。DenseNet 使用更密集的布线模式,将所有先前的输入发送到下一层。例如,层(l+4)将接收输入(l、l+1、l+2 和 l+3)。

随机连线神经网络

这篇文章的论点是,在神经架构搜索的背景下,连线>连接不同的操作。随机连线的神经网络对每个节点使用相同的运算,即 3×3 深度方向可分离卷积。这些网络不是专注于通过巧妙的路径连接不同滤波器大小的卷积等操作,而是在整个微体系结构中随机连接相同的操作。作者设计了随机有线网络的宏观结构。这包括对要素地图进行空间缩减采样的阶段数以及每个阶段应包含多少个结点等决策。这些网络最终看起来如下图所示:

Exploring Randomly Wired Neural Networks for Image Recognition by Saining Xe, Alexander Kirillov, Ross Girshick, Kaiming He

这些网络是使用随机图算法快速生成的,该算法使用试探法来控制整个网络中节点度(连接数)的分布。最有趣的是,其中一种算法(WS 算法)在网络科学中被用来模拟小世界网络。这描述了我们在社交网络中平均相距 6 跳的社会现象。这篇论文引用了神经科学对这种结构的启发,强调了线虫(蠕虫)的 300 个神经元连接体也具有这种小世界结构。

以下是这些网络与 NAS 方法相比的 ImageNet 性能,NAS 方法需要巨大的计算量:

如果你想了解随机连线神经网络论文的完整解释,以及随机图形如何转换为 DAG / CNN,请查看下面的视频!

感谢你阅读这篇关于随机连线神经网络的文章!我希望这能让你相信神经网络的连接是 NAS 未来不可或缺的一部分。此外,我希望您能采用这种算法来加速您的数据集的架构搜索并报告结果!

随机连线神经网络和最先进的精确度?是的,它有效。

原文:https://towardsdatascience.com/randomly-wired-neural-networks-and-state-of-the-art-accuracy-yes-it-works-9fb3cedc8059?source=collection_archive---------7-----------------------

如何设计出最好的卷积神经网络(CNN)?

想获得灵感?快来加入我的 超级行情快讯 。😎

尽管深度学习已经存在好几年了,但这仍然是一个没有答案的问题。

设计一个好的神经网络的大部分困难源于它们仍然是黑盒的事实。我们对它们是如何工作的有一些高层次的想法,但是我们并不真正了解它们是如何实现它们所做的结果的。

CNN 的一些线索

我们可以从一些线索入手。最近的研究为我们提供了一些 CNN 准确性提高的具体证据:

  • 提高图像分辨率
  • 增加网络深度
  • 增加网络宽度
  • 添加跳过连接(无论是密集连接还是剩余连接)

从直观的角度来看,深度学习的所有这些补充都是有意义的。提高图像分辨率可为网络提供更多数据。增加宽度和深度给了网络更多的参数。并且增加跳跃连接会增加网络的复杂性,从而增加表示能力。

Dense connections (left, DenseNet) and skip connections with a wide network (right, ResNeXt). Sources are linked.

为了发现更强大的网络,谷歌人工智能的研究团队开发了一种技术,让算法搜索好的网络。这被称为神经架构搜索 (NAS)。

神经结构搜索

NAS 是搜索寻找最佳 神经网络架构的算法。大多数 NAS 算法的工作原理非常相似。

首先定义一组可能用于我们网络的“构建块”。然后尝试通过将这些块的不同组合放在一起来训练网络。通过这种反复试验,NAS 算法将最终找出哪些数据块和哪些配置工作得最好。

事实证明,这种方法效果很好,达到了最先进的精度。它还发现了一些看起来非常奇怪的架构,你可以从下面的官方文件中看到:

NASNet blocks discovered by the NAS algorithm. Source

NAS 的伟大之处在于,我们可以看到一些神经网络体系结构,否则我们可能根本看不到。

然而,它也有自己的局限性。由于我们是从一组固定的数据块中进行采样,因此我们不会发现任何新的数据块。跳过连接的情况也是如此:NASNet 只允许跳过 1 个下采样级别的连接,但是如果其他类型的连接也可以工作呢?

脸书的人工智能研究团队通过尝试随机连线神经网络,在 NAS 上进行了新的尝试。直觉是,如果体系结构搜索的一般思想对固定的块和连接工作良好,也许用更宽的搜索空间(即随机连接)运行它将导致一些未探索的配置。

随机连线神经网络

由于该论文的作者希望特别关注线路即神经网络的连接,他们对网络结构做了一些限制:

  • 输入总是大小为 224x224 的图像
  • 这些区块总是一个雷鲁-conv-巴特诺姆三联体。三元组中的卷积始终是一个来自的 3×3 可分卷积,但除外。
  • 多个张量的聚合(例如当融合与其他张量的跳过连接时)总是以相同的方式完成——通过加权求和。这些权重是可以学习的,并且总是正的。
  • 网络的总是保持不变。多重卷积块的一般 CNN 结构,随后是下采样,反复重复直到最终的 softmax 分类器,已经成为最先进的网络设计中的标准。在这些研究实验中也采用了这种范式。

General structure of state-of-the-art CNNs, also adapted for this research. Source

224x224 的输入大小在 ImageNet 竞赛中是非常标准的,ImageNet 数据集用于对其他手工制作的网络以及 NAS 生成的网络进行基准测试。ReLU-Conv-BatchNorm 的三联体阻滞也很常见,并已被广泛证明在整个深层 CNN 中重复时可提供最先进的结果。

张量的聚合方式是一个小小的转变。大多数最先进的网络都是直接相加或无权重连接,但这是一个不应该对性能产生太大影响的小加法。上表所示的 CNN 分级设计也已成为 ResNets、DenseNets 和 NASNets 中使用的首选网络结构。

注意这并不完全是一个“随机神经网络”。没有完全从零开始的随机化。相反,CNN 设计的单个组件,即布线,在其他组件保持固定的情况下进行探索。

这是作者试图向读者传达的一个重要观点。我们还没有做完全随机的神经网络。但是我们开始对组件搜索空间做一些深入的探索——一步一个脚印。

有了这些约束,各种经典随机图模型被用来生成网络的随机布线。**

我说的随机是指随机

Some of the randomly wired networks. Source

随机网络打开了深度学习探索的大门

本研究的意义在于其主要的探索性思想:扩展 NAS 算法的搜索空间,以发现新的、更好的网络设计。虽然研究人员自己已经发现了一些伟大的设计,但手动搜索整个搜索空间实际上是不可行的。

这也延伸到另一点:如果我们正在扩大我们的搜索空间,我们将需要一个算法,在这种情况下,我们的网络生成器,要真正擅长搜索。它必须知道要寻找什么,或者至少有一些通过设计向它移动的趋势,就像梯度下降工作这样的优化算法一样。

架构搜索是深度学习研究的下一个前沿。它允许我们使用算法,而不是试错法来发现最佳架构。

目前,修复一些网络组件同时搜索其他组件(在本例中为布线)是有意义的。这就把问题简化成了一件小事,更容易处理。NAS 算法应该有一定程度的随机性,因为这是我们发现真正新颖的架构的唯一方法。

下一步当然是进一步扩展搜索空间和我们搜索算法的随机性。这意味着扩展到越来越多的网络组件,直到整个事情都是用算法设计的。

当我们放开 NAS 时会发生什么?它会选择像 2x4 这样的非正方形卷积吗?它提议使用反馈回路吗?网络变得更简单还是更复杂?

神经结构搜索提出了一个令人兴奋的新的研究领域。希望让搜索算法变得宽松,成为一种利用随机化的方式,为我们的优势,发现创造性的和以前从未想过的架构。

喜欢学习?

推特上关注我,我会在那里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上和我联系吧!

对特征进行排序,现在再次排序

原文:https://towardsdatascience.com/rank-the-features-now-rank-again-4dafd8cde3c8?source=collection_archive---------10-----------------------

机器学习和生物标记

40 种排列你的特征的方法和我的经验使用少量观察选择生物标记候选物(特征)

在这里,我讨论了以 40 种方式对特征进行排序的方法,以及一个不稳定模型的困难情况,这是由于数据中的变量比样本多得多。

作为一个额外收获,你将了解一点应用于癌症生物学的领域,并了解该领域数据集的特征。我解释了一个蛋白质组学数据集,我们用它来验证在发现蛋白质组学中寻找生物标记候选物的方法。

你可以在这里> 找到我的研究文章 <。
和我在这里的论文:赫伯勒,h .,&明希姆,R. (2019)。生物学中的计算方法:癌症生物标记、蛋白质网络和横向基因转移。圣保罗大学,圣卡洛斯。
http://www . teses . USP . br/teses/disponiveis/55/55134/TDE-15102019-145225/

概述

您可以阅读整篇文章或跳到以下部分:

  • 简介 : 我创建基于排名的稳定性管道的原因
  • 发现特征的重要性 : 小定义
  • 排名方法 : 对你的特征进行排名的方法
  • 稳定管道 : 了解稳定方法&特点
  • 验证和结果 : 通过候选生物标志物的使用案例了解稳定性管道结果

生物标志物的发现对癌症研究非常重要。例如,我们可以用它们来指导药物发现的实验、新的治疗方法和可以识别是否存在肿瘤或其类型的测试。

收集唾液来鉴别癌症比活组织切片检查的侵入性要小得多。

非侵入性测试通常是优选的,并且可以导致更快的诊断,因为它更容易更频繁地执行。例如,如果他们家族中有口腔癌史,或者有增加患癌症几率的习惯,他们可以每年检测唾液。人们试图避免或推迟侵入性或复杂的检查。

我们唾液中不同数量的蛋白质可以预测结果。

Figure 1 I call this The Proteomics Paradox.Before) Proteomics data with many more features than observations; applying feature selection is a problem because we do not have enough observations. After) the result of a feature selection process on this data set; because we need to. We use this smaller set of features on follow-up experiments so we can increase the number of observations, being able to validate the candidate features with more statistical power (see Figure 2). We cannot guarantee they will perform well in follow-up experiments; yet, a decision needs to be made in the first step. With the larger number of observations, we test if the selected features can discriminate the classes. With a good accuracy, we celebrate; with a bad one, we can only test the importance of these features and report if they are good candidates or not, based on the large sample. The search restart removing the bad ones.

介绍

想象一下,如果数据中的一个小变化导致了非常不同的特征等级。

在大样本的情况下,你会认为至少排名是相似的。如果样本很小,而且有很多特征,那就不能指望了。

我们不能相信这里的结果。我们的样本太小了。然而,我们需要决定什么是我们问题的最佳特征。

如果我们对所有观察运行一个排序器,然后删除一个观察并再次运行排序器,我们将得到两个不同的等级。我们选择哪一个?

如果我对所有观察值使用 T 检验、Wilcoxon 检验或 Kruskal Wallis 检验,删除一个观察值并再次运行,我们将得到不同的 p 值。我们信任哪一个?

查看图 1 并阅读图例可以更好地理解它。

因为我们的样本太小,没有正确答案!

我们解决问题的方式是利用我们所拥有的,想象结果并采取行动。我们不可能有任何统计上的自信,但我们有能力掌握和理解我们的数据。

在当前的生物标志物发现管道中,由于技术的限制,我们从许多特征和少量观察(小样本)开始。

我们先选择一小组特征,然后在后续实验中增加样本量。下图说明了这些步骤。【分析物】是我们的特征,“样本”是我们的观察。在初始阶段,我们有许多特征和一些观察,这对于运行任何机器学习或统计方法来说都是一个可怕的场景。

Figure 2 — Example of a biomarker discovery process. In the first phases, we cannot identify sets of features to discriminate the classes with statistical confidence. Yet, we need to choose a set of features that will be used in the furthers phases, where, because of the smaller number of features, we can increase the number of samples — consequence of limitations of current Proteomics technologies. Source of the image: Del Campo, Marta & Jongbloed, Wesley & Twaalfhoven, Harry & Veerhuis, Robert & Blankenstein, Marinus & Teunissen, Charlotte. (2015). Facilitating the Validation of Novel Protein Biomarkers for Dementia: An Optimal Workflow for the Development of Sandwich Immunoassays. Frontiers in Neurology. 6.

在选择了最佳特性之后,我们可以在下一阶段增加观察的数量,例如在图中所示的验证和确认阶段。

这里的错误决定是有代价的:

如果我们最初选择了一组不好的特性,这意味着我们在几个月或几年的研究上浪费了数千美元!我们至少证明了他们不是好的候选人。

现在,这一挑战又增加了一个事实,即这些特征本质上是相互关联的。

Figure 3 — Example of correlation between features in Discovery Proteomics data. Features (proteins) CST1, CST2 and CST4 are correlated and found in similar quantities in the biological samples. Note: PYGM, ENO1, ALB and ADH1 are highly correlated because they were added to the samples, as I explain later in this article.

我们体内蛋白质的数量是相互依赖的。它们相互作用来执行过程,就像在一个公司里一样,并影响其他蛋白质的产生;同样,员工可以影响公司的成功和其他因素,并因此影响公司将雇佣多少新员工。

正如您将在本文中看到的,像 SVM-RFE 这样的方法可能会给高度相关的特征不同的权重,这意味着相似的蛋白质会出现在排序中的遥远位置,从而导致错误的结论和决定。

为了解决这个问题,我使用不同的方法和交叉验证对这些特性进行了一次又一次的排序,并比较了它们的得分。我最终得到一个高评分特性的列表,以及通过跟踪特性的权重和等级位置计算出的稳定性分数

军衔之间有许多不同。一种方法会说蛋白质 A 是最好的,而另一种方法会说它是最差的。

有了平均权重,并且知道当数据改变时以及在不同的等级中特征如何表现,我就可以在一定程度上有把握地决定什么是最重要的。

通过在生物样品中添加真实标记,我们验证了我们的方法在蛋白质组学中寻找潜在生物标记候选物的相关性。

我在这里引用的作品是我在圣保罗大学读博士期间,与 巴西生物科学国家实验室、 等机构合作完成的更大项目的一部分。

GitHub 资源库:【https://github.com/heberleh/proteins-stability】

发现特征的重要性

有许多方法可以找到作为数字的特征相关性,并选择一组候选特征。我在这里解释了 top-n selection 方法以及对特性进行加权和排序的流行方法。

我对我的特征有 40 个不同的观点(等级)。

统计方法和不同分类器组合到 6 种排序方法的乘积。

前 N 名功能

选择特征以创建模型的一种常见方法是从等级中选择前 N 名。 Scikit-Learn 例如,有SelectPercentileSelectKBest分别根据最高分的百分比和 k 个最高分来选择特性。

特征的重要性

分数或权重是衡量重要性的标准。例如统计测试中的 p 值和线性回归方程中的斜率(系数)。为了创建等级,我们使用这些数字对特征进行排序。

排名方法

我结合在 Scikit-learn 中定义的单变量和多变量算法实现了六类排序方法。

第一类称为类型 1—单变量,由单变量方法组成,如 t 检验和信息增益

其他类别基于多元模型:

  • ****类型 2 —单一得分:创建仅考虑一种蛋白质(对于每种可用蛋白质)的分类器,并基于在 k 倍交叉验证中计算的准确度对它们进行排序;
  • ****类型 3 —属性的权重:训练分类器,并根据默认的特征加权方法对特征进行排序,例如线性模型的系数—每个特征的重要性通过 coef_ attribute 或 feature_importances_ attribute 获得;
  • ****类型 4——递归特征消除:基于权重对特征进行排序,但是重复该过程 N 次,将最差的特征添加到排序的末尾,如针对 SVM- RFE 的情况所解释的;
  • ****类型 5——稳定性选择:根据在 bootstrap 采样方案中被选为最佳的频率对特征进行排序。该方法使用 bootstrap 创建许多训练集,对于每个训练集,该算法计算每个特征的权重,并且如果它们的权重大于平均权重,则选择它们。频繁选择的功能被认为是稳定的,并位于排名的开头—查看官方知识库了解详细信息:https://github.com/scikit-learn-contrib/stability-selection
  • ****类型 6 —准确度降低:使用所有特征计算 k 倍交叉验证准确度,然后,一次移除一个特征并重新计算准确度。与基础精度和移除特征后的精度的差异越大,该特征越相关;
  • ****类型 7 —递归特征添加:类似于类型 4。在这种情况下,不是从最差到最好来创建等级,而是通过从训练集中移除最好的特征并将其添加到等级的开始来创建等级,重复该过程直到所有特征都被排序。在我们的测试中,这在我们的蛋白质组学数据中表现得比 RFE 更好,我将在本文的验证部分解释这一点。

上述每种基于多变量的排序方法(类型 2 至 7)与不同的分类器结合使用。

我用 python 实现了脚本(https://github.com/heberleh/proteins-stability),并从 scikit-learn 中选择了经典的机器学习工具。仅考虑实现特征权重的分类器:

  • 线性 SVC
  • 决策树;
  • 随机森林;
  • 套索;
  • 山脊;
  • 线性判别分析。

****共定义了 40 个分级器,它们是上述分级方法和分类器的组合。

在下一节中,我将解释这 40 个排名如何产生数百个待解释的排名,并帮助我们决定在接下来的研究中应该考虑哪些特征。

如果一个大的数据集?— — —

这里我们有一个小数据集。您可能会想办法将这些排序方法应用到更大的数据集,例如,通过使用抽样和并行性。如果你有成千上万的观察和特征,你可以:

  1. 去掉你知道不好的特征,明显不好的特征;
  2. 使用随机抽样或分层抽样来选择一组您可以处理的观察值;重复该过程,检查不同样本的要素在相同等级中的表现。

稳定性管道

在这个项目中,我们定义了一个分析管道,它结合了对特征进行排序的方法,通过简单和双重交叉验证来识别候选签名。

管道的一般概念说明如下:

Assessment of Stability and Relevance of Features in a Double Cross Validation scheme — 1) The original data set is divided into train and test sets in each iteration i of the outer loop of the double cross validation (k-fold cross validation). 2) The train set is used to create 40 ranks of proteins. 3) Signatures are created by selecting the top-N proteins and by creating all or random combinations. 4) Each signature is tested in a shuffle split cross validation. 5) Signatures with good score are selected. 6) Highly correlated proteins that were removed between steps 1) and 2) take place of their reference to form new signatures. 7) All signatures are tested again in a shuffle split cross validation, now with a greater number of splits than before. 8) With the new scores, signatures are selected again by a criterion that consider the score, the standard deviation and the frequency of proteins in good signatures. 9) The first round of evaluation of signatures outputs the best signatures, formed by the signatures with the highest scores among the even better signatures. 10) The best signatures are tested again by using different classifier models, including the Bagging and Voting classifiers. 11) The best pairs (signature, classifier) of each signature is tested with the independent test set. In the end of the DCV, the independent test scores are averaged to form the DCV score.

  1. ****识别并分离相关蛋白质(训练集中仅保留 1 个代表)——这是减少多重共线性的一个步骤。您可能想要搜索线性模型、多重共线性和 VIF。关于主题的一篇文章在这里
  2. ****计算排名
  3. ****根据等级和小组合创建签名
  4. 评估分类器并选择最好的一个 —这里我创建随机签名(多个模型)并选择平均准确度最高的分类器。这种抽样方法被称为随机子空间
  5. ****使用选择的分类器评估签名;
  6. 识别更好最好签名
  7. 对于每个最佳签名,选择最佳模型 —签名-分类器对;
  8. ****计算排名前 10 位的蛋白质的频率
  9. 计算更好最佳签名中蛋白质的频率。

更一般地说,它创建了由一些分类器/排序器算法认为相关的特征集。然后,它通过建立分类器并使用交叉验证估计它们的预测能力来测试这些特征集。

选择的特征越多,其重要性就越大。

这就像一个贝叶斯方法,我们会认为一个特征在一个高精度模型中的概率。

现在,流水线中有一个外环,一个 k 倍采样。这将创建不同的数据集,对于每个循环,我们可以检查这些频率如何随着数据集的变化而变化。

例如,如果一个特征只在第一个循环中出现在许多好的分类模型中,这意味着这个特征实际上是不相关的。

The most frequent protein in the top-10 positions is the first protein in the plot: P00330_ADH1. Despite that, in one of the loops of a 9-fold sampling, referred as fold-0, this protein was not among the top-10. This should be an alert to the expert that is analysing the results. If our full data set was in fact the fold-0 and we decided to select only the top-10 proteins, this interesting protein would not be selected. In fact, as I explain later, this protein must be selected because it is a true marker. It was added in the biological samples so we could track the behaviour of the computational methods and the behavior of the Proteomics quantification technique and protocol. This protocol is not much precise in the Discovery phase because we are quantifying many proteins. Reducing the number of proteins to quantify will allow it to be more precise and increase the number of observations; having as consequence better statistical confidence.

这里用每组特征(签名)建立分类器,并且测量它们的准确度以判断相应的签名是好还是不好。

等级用于选择用于创建签名的特征。例如,只考虑排名中出现的前 20 个特征。这种启发式方法减少了计算时间。

排名也用于计算蛋白质在前 10 位的频率。选择前 10 个特征是 Discovery Proteomics 中的一个经验法则,这 10 个蛋白质然后在我们称为靶向蛋白质组学中进行分析,它们是我们的目标,因为它是一个小集合,我们可以提高精确度和观察的数量。

在下面的图片中,你可以看到前 10 个定位蛋白质组中每个蛋白质的出现频率,以及更好最好组签名。

****

好的更好的最好的套件在制造时就考虑到了灵活性。只选择具有最大精确度的模型是不公平的,例如 95%(有数百个具有最大精确度)。因为样本数量很少,我们不应该要求太严格。**

因此,“好”和“甚至更好”的集合代表了这种灵活性;例如,选择准确率> 90%的模型,然后选择> 93%,最后选择 95%。

在所有这些候选签名集上跟踪我们的特征的行为给了我们关于数据的更多信息和信心。在我们的研究中,我们在所有的分析方法中都发现了有趣的模式。

最后,在外循环中,最好的模型用独立的测试集再次测试——这导致了我们所说的双交叉验证** (DCV)。这是一篇关于 DCV 的文章。**

当我们有一个小的集合时,交叉验证(CV)的主要问题是估计过于乐观。进行 DCV 有助于我们理解简历验证的乐观程度。

根据我的经验,如果我们有 50%的 DCV 误差,我们会做得很好。

事实上,即使我们的数据集中有已知的真实标记,当考虑最佳签名时,我们得到的 DCV 误差> 60%。这意味着,尽管签名在交叉验证时工作良好,但在用新的观察结果进行测试时,它们的表现很差。

因此,如果我们的目标是减少过度拟合,我们不应该选择具有最高分数的签名。相反,这是分析具有不同 CV 分数的许多模型中特征的频率的动机之一。

验证和结果

在本节中,我将解释我们如何在 Discovery Proteomics 中用一个数据集验证我们的方法,以及如何通过我们的稳定性渠道成功地对真正的标记(特征)进行优先排序。****

如果我们选择 CV 分数最高的签名,我们最终会得到一个糟糕的 DCV 分数——正如我们所做的那样。出于这个原因,我们实现了分析管道,在这里我们跟踪不同视角下的特性得分。

我在这个项目中展示的总体想法是,当你有少量的观察数据时,你需要掌握数据,并在不同的条件下进行分析。然后,你需要选择启发法来优先考虑你的特性,记住你不应该太严格;您应该定义不同的阈值并进行比较。

真正的正面特征

真正积极的特征(标记)是优先的特征,事实上对我们的问题很重要。假阳性可能是被优先考虑的特征,但实际上它们并不会导致我们的类别的差异。**

我们的目标是分析发现蛋白质组学(小样本和多特征)中计算方法和质谱技术定量的行为。

我们能否通过量化生物样本的蛋白质并用计算方法对其进行排序,从而从生物样本中识别出真正的标记?

这个问题的答案是既有又无。

不,因为如果你选择了错误的计算方法,他们可能无法识别真正的标记。

在我们的实验中,用不同的排序器对相同的数据集进行排序导致了许多分歧。在一些等级中处于顶端位置的蛋白质出现在其他等级中的最后位置。如果你选择了“错误的一群”排名者,你最终会变得极端偏见。

是的,因为正如我在我们的方法中所展示的,如果你运行许多方法并结合来自不同角度的信息来对蛋白质进行优先排序,就可以识别出真正的标记。

在这里,我向你展示了在我们的管道中计算的频率如何揭示真正的标记作为良好的候选。

真实标记的量化

我们真正的标记物是在定量之前在生物样品中定义的。

我们在生物样本中加入蛋白质,每堂课的浓度相同;不同班级浓度不同。

有三类: C(对照)TR(肿瘤切除)T(肿瘤)

他们参考了没有癌症的病人、切除了肿瘤的病人和有肿瘤的病人的唾液样本。这些蛋白质定量结果如下所示。

True markers’ intensities.

正如我们所看到的,尽管在一个类别的每个样品中加入了相同浓度的蛋白质,但是它们的定量强度不同。每个班的平均值不一样:C 班-1 左右,TR 班 0 左右,t 班 1 左右。

对特征分数进行排序

通过计算排名分数和改变数据集,我们发现了清晰的稳定性模式,如下图所示。

总之,我们发现了一组在大多数情况下被选为好的蛋白质,它们在热图中以红色显示。

Heat map showing the highest 50% average scores from 40 ranks of each protein for each training dataset (column, 9 columns refer to 9-fold sampling). The blue values are low scores or proteins that were removed from the training set due to filtering by p-value. We conclude that many proteins are unstable and it is clear that we have a potential smaller set of proteins (red lines) to be assessed. In fact, with this plot we could have already eliminated the blue lines and re-started the pipeline. In the current project, we just continued with all proteins to see where it would end if this pattern was not revealed.

我们还发现了一组频繁出现在排名前 10 位的蛋白质。这些蛋白质及其重量用箱线图表示。箱线图也显示了排名和数据之间的差异。在 B)中,我们有一个更好的权重图,因为我们只考虑每种蛋白质的最佳分数。在 A)中,我们看到所有蛋白质在某一点上都有不好的分数。

These are proteins that appeared in at least 33% of top-10 positions in ranks. A) The box-plot is showing weights from all ranks. B) The box-plot is showing the distribution of the 50% highest values from each of the 40 ranks. All the 50% highest values from each loop are considered, meaning we have 9*20=180 scores for each protein. This plot shows us the median of the weights and how they varied among ranks. Note that even if we get only the 50% highest weights, there are proteins which weights varied from 0.4 to 1.0. This is the instability that we try to address with our analytical pipeline; revealing to the experts that this can happen and showing them protein candidates based on their stability.

特征的频率

在对蛋白质进行评分和排序后,管道创建并测试蛋白质签名。下图向我们展示了管道是如何选择蛋白质的。选择的蛋白质越多(横条越大),它就越稳定和重要。

我们发现我们的标记蛋白,真阳性,是前 10 位中出现频率最高的蛋白之一,具有良好/甚至更好/最好的特征。

下图显示了在每个折叠(颜色)中,每个蛋白质在每个计算等级的前 10 个位置中被选择的频率。我们可以看到,出现在图中间的蛋白质并不经常位于前 10 位,大多数情况下,它们只在某些折叠中出现在前 10 位。这意味着,根据您从训练集中删除的每个观察结果,该蛋白质不再出现在前 10 位中,这表明如果我们选择该蛋白质用于后续实验,将会出现不稳定性和更高的风险。

Frequency in top-10 positions, in each fold of the k-fold sampling scheme. Colors represent the folds (different data sets).

下图与上图相似。这里,我们不计算前 10 个位置的频率,而是计算被选择形成组更好最好的签名的频率。同样,根据频率标准,在最好的蛋白质中发现了真正的标记。

Frequency of proteins in signatures.

我是不是穿太多了?

是的。我对这个小数据集掌握得越多,就越能适应我的模型。另一方面,我不得不。这是我唯一能想到的理解数据集的微小变化如何改变预测能力的方法。我们在这里假设我们有一组很大的观察值,但是其中可能包含一两个异常值。

执行一个简单的 k 倍采样向我们展示了方差。这里,我们使用一个外部 k 折叠,其中有许多 k 折叠,模拟从未考虑选择特征的新样本。如果你想估计所选特征的能力,DCV 是必要的。

最后,你需要展示所有的结果。使用 DCV 误差向专家解释假阳性的风险。

DCV 方案也给管道带来了一些问题,我将在下面解释——如果您不打算按原样使用这个特定的管道,请跳过它。

限制:因为在 k 倍采样的每次执行中,相关的蛋白质在管道的开始被分离,所以这些蛋白质的频率存在问题。一种标记蛋白可能会从一些训练集中删除,而不会从其他训练集中删除,从而导致频率低于应有的水平。在当前的图表中,你可以看到,即使这些蛋白质出现的次数较少,它们出现的频率也很高。发生这种情况是因为如果它的参考蛋白在一个好的信号中被选择,我将它们添加回去以创建信号——特别是用那个信号中被去除的蛋白替换参考蛋白。这并不理想,因为尽管它们高度相关,但它们可能具有不同的强度。类似的行为也发生在过滤步骤中,例如按 p 值过滤和错误发现率。一种解决方案是在外部 k 倍采样之前移除相关的蛋白质并过滤,但是这并不理想,因为在 DCV 中,我们不希望在 k 倍采样之前应用任何方法,以避免使特征选择过程产生偏差。如果在 DCV 流水线之前删除基于类信息的特征,那么一旦独立的测试集不应该成为任何处理的一部分,你就会使你的结果产生偏差。因此,需要一种更好的算法来跟踪蛋白质对,例如,总是使用相同的蛋白质作为参照。注意,当前版本是并行运行的,很难定义一个确定性的解决方案。然而,目前在管道中间添加蛋白质的方法对于当前的情况工作得很好。

结论

我们的管道并不是解决蛋白质排序问题的完美方案。完美的解决方案是将观测次数增加到数千次。

因为我们不能增加样本量,所以了解数据的行为对决策非常重要。

可视化、重新采样、平均和计算蛋白质的频率来测量它们的稳定性和能力有助于识别和理解蛋白质和方法的行为。

通过向生物样品中添加真实标记物,并使用我们的 Discovery 蛋白质组学方案对所有蛋白质进行量化,我们在本地验证了我们的管道。它能够突出真正的标记,如本文中的图所示。

在这里,我将其命名为“局部验证”,因为需要使用不同数据集的许多其他研究来实际验证用于任何发现蛋白质组学数据的方法。

尽管如此,我们的方法给出了关于机器学习和统计方法的行为的控制和突出信息,以及关于每种蛋白质如何表现这些方法给出的重要性的信息。

理解过度拟合很重要,因此它向所有参与该项目的研究人员表明,当我们的样本量小于因子/变量的数量时,我们不应该相信数字和 p 值。

在了解假阳性和假阴性的所有风险,以及方法和蛋白质在我们的分析管道中的表现后,我们可以更有信心地进行决策。

关于生物标志物的推荐文献

  • Kawahara,r .、Meirelles,G. V .、Heberle,h .、Domingues,R. R .、Granato,D. C .、Yokoo,s .……Leme,A. F. P. (2015)。综合分析选择癌症候选生物标志物进行靶向验证。Oncotarget,6(41),43635–43652。https://doi.org/10.18632/oncotarget.6018
  • Carnielli,C. M .,Macedo,C. C. S .,De Rossi,t .,Granato,D. C .,Rivera,c .,Domingues,R. R .,… Paes Leme,A. F. (2018)。结合发现和靶向蛋白质组学揭示口腔癌的预后信号。自然通讯,9(1),3598。https://doi.org/10.1038/s41467-018-05696-2
  • 德尔·坎波,玛尔塔&容布勒德,韦斯利&特瓦霍夫,哈里&韦厄斯,罗伯特&布兰肯斯坦,马里努斯&特尼森,夏洛特。(2015).促进痴呆新蛋白质生物标志物的验证:夹心免疫测定发展的最佳工作流程。神经学前沿。6
  • **y . Cun 和 h . f . frh lich(2012 年)。乳腺癌患者分层的预后基因标记——使用蛋白质-蛋白质相互作用的先验知识的基因选择方法的准确性、稳定性和可解释性。BMC 生物信息学,13(1),69。【https://doi.org/10.1186/1471-2105-13-69 **
  • Christin,c .,Hoefsloot,H. C. J .,Smilde,A. K .,Hoekman,b .,Suits,f .,Bischoff,r .,& Horvatovich,P. (2013 年)。临床蛋白质组学中生物标志物发现的特征选择方法的评价。分子和细胞蛋白质组学,12(1),263–276。https://doi.org/10.1074/mcp.M112.022566
  • Rifai,n .,Gillette,M. A .,和 Carr,S. A. (2015)。蛋白质生物标志物的发现和验证:通往临床应用的漫长而不确定的道路。自然生物技术,24(2006 年 9 月),971–983。https://doi.org/10.1038/nbt1235
  • Sanavia,f . AIO lli,g . Da San Martino,a . biso gnin 和 Di Camillo,B. (2012 年)。通过在学习过程中整合生物学知识来提高生物标志物列表的稳定性。BMC 生物信息学,13(补编 4),S22。https://doi.org/10.1186/1471-2105-13-S4-S22

通过维基百科页面浏览量对编程语言进行排名

原文:https://towardsdatascience.com/ranking-programming-languages-by-wikipedia-page-views-f810a04ec55b?source=collection_archive---------20-----------------------

在 python 中使用 API 和绘图的演示

对编程语言的流行程度进行排名有许多不同的方法。Tiobe Index 是一个流行的网站,它根据流行程度对编程语言进行排名。我还看过一些文章,人们通过查看工作列表的数量或堆栈溢出问题的数量来对编程语言的受欢迎程度进行排名。

今天,我将利用维基媒体应用编程接口,根据 2018 年初以来的总页面浏览量,对一系列编程语言进行排名。

幸运的是,python 自带了方便的内置请求库,这使得从 API 获取数据变得非常容易。我定义了一个简单的函数来从页面视图 API 获取页面视图数据。

API 请求函数:

import requests
import numpy as np
import pandas as pddef wikimedia_request(page_name, start_date, end_date = None):
    '''
    A fucntion that makes requests to the wikimedia pagecveiws APIParameters
    ----------
    page_name : string
    A string containing the name of the wikipeida page you would like pageviews for

    start_date : string
    a date string YYYY/MM/DD indicating the first date that the request should return

    end_date : string
    a date string YYYY/MM/DD indicating the last date that the request should return. defaults to system date
    Returns
    -------
    df : pandas DataFrame
    A dataframe with the article name and the number of pageviews.
    '''

    # get rid of the / in the date
    sdate = start_date.split("/")
    # join together the text that was split
    sdate = ''.join(sdate)
    # if an end date is not specified
    if end_date == None:
        #get the current date
        end_date = str(datetime.datetime.now())[0:10].split("-")
        edate = ''.join(end_date)
    else:
        # use date from end_date argument
        edate = end_date.split("/")
        edate = edate[0] + edate[1] + edate[2]
    # use these elements to make an api request
    r = requests.get(
        "[https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia.org/all-access/all-agents/{}/daily/{}/{](https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia.org/all-access/all-agents/{}/daily/{}/{)}".format(page_name,sdate, edate)
    )
    # get the json
    result = r.json()
    # convert to dateframe
    df = pd.DataFrame(result['items'])
    # the wikimedia api returns 2 extra zeros at the end of the timestamp for some reason
    df['timestamp'] = [i[:-2] for i in df.timestamp]
    # convert to datetime
    df['timestamp'] = pd.to_datetime(df['timestamp'])
    # set timestamp as index
    df.set_index('timestamp', inplace = True)
    # return the article and views columns
    return df[['article', 'views']]

一旦定义了这个函数,就可以很容易地与 list comprehension 结合使用,为多个页面创建页面视图的数据框架。我定义了一个我感兴趣的 20 种编程语言的列表(诚然这是一个有点随意的列表,这篇文章主要是为了演示一种技术),然后就这么做。

names = ['Python (programming language)', 'R (programming language)', 'Java (programming language)', 
         'Scala (programming_language)', 'JavaScript', 'Swift (programming language)', 'C++', 
         'C (programming language)', 'Clojure', 'C Sharp (programming language)', 'F Sharp (programming language)',
        'Julia (programming language)', 'Visual Basic .NET', 'Perl', 'Haskell (programming language)',
        'Go (programming language)', 'Ruby (programming language)', 'PHP', 'Bash (Unix shell)', 'TypeScript']dfs = pd.concat([wikimedia_request(x, start_date) for x in names])

我个人喜欢 python 列表理解,因为它们允许代码简洁、可读。本文中的大部分内容在其他语言中需要更多的代码。

图形流行度:

现在我有了编程语言的数据,我可以使用 pandas 和 matplotlib 创建一个简单的图,看看自 2018 年初以来,哪些语言的搜索量最多。

means = dfs.groupby('article').mean()['views']
means.sort_values(ascending = False).plot(kind = 'barh', color ='C0', figsize = (12,6))
plt.title('Total Wikipedia Page Views')
sns.despine()
plt.xlabel('Count of Page Views')
plt.ylabel("")
plt.show()

  • 在大多数语言排行榜上,python、java、javascript 和 C 争夺榜首
  • 从我的数据来看,python 是最受欢迎的
  • Python 的使用在过去几年里一直在增长
  • 这对我有好处,因为 python 是我使用的主要语言

我还对每种语言的页面每月搜索量的趋势感兴趣。哪些语言在兴趣上呈上升趋势?哪些语言呈现兴趣下降趋势?

我想制作简单的回归图来评估语言兴趣的时间趋势。这在 python 中有点难做到,因为 seaborn 的 regplot 不接受 datetime 对象。我改编了这个堆栈溢出答案的代码,用 python 创建了时间序列回归图。

def tsregplot(series, ax = None, days_forward = 10, color = 'C0'):
        '''
    A fucntion that makes requests to the wikimedia pagecveiws APIParameters
    ----------
    series : Pandas datetime index Series
    A pandas Series with datetime index

    ax : matplotlib axes object
    A matplotlib axes obect

    days_forward : int
    An integer indicating how many days to extend the regression line. This is set at 10 by default so that all points can show. increasing it can be used to forecast regression line foreward

    color : string
    A matplotlib color string 

    Returns
    -------
    ax : matplotlib axes object
    returns a matplotlib axes object with regplot
    '''
    series = series.reset_index()
    series.columns = ['date', 'value']
    if ax == None:
        series['date_ordinal'] = pd.to_datetime(series['date']).apply(lambda date: date.toordinal())
        ax = sns.regplot(
        data=series,
        x='date_ordinal',
        y='value',
        color = color
        )
        ax.set_xlim(series['date_ordinal'].min() - 2, series['date_ordinal'].max() + days_forward)
        ax.set_ylim(series['value'].min() - 1000, series['value'].max() + 1000)
        ax.set_xlabel('date')
        new_labels = [date.fromordinal(int(item)) for item in ax.get_xticks()]
        ax.set_xticklabels(new_labels)
    else:
        series['date_ordinal'] = pd.to_datetime(series['date']).apply(lambda date: date.toordinal())
        ax = sns.regplot(
        data=series,
        x='date_ordinal',
        y='value',
        ax = ax, 
        color = color
        )

        ax.set_xlim(series['date_ordinal'].min() - 5, series['date_ordinal'].max() + days_forward)
        ax.set_ylim(series['value'].min() * 0.9 , series['value'].max()* 1.1)
        ax.set_xlabel('date')
        new_labels = [date.fromordinal(int(item)).strftime("%m/%Y") for item in ax.get_xticks()]
        ax.set_xticklabels(new_labels)
        return ax

我可以创建一个简单的 for 循环,为 20 种语言中的每一种绘制时间序列回归图:

fig, ax = plt.subplots(10,2, figsize = (16, 20))
ax = ax.ravel()
counter = 0
for i, j in zip(dfs.article.unique(), names):
    string = i
    selected = dfs.query("article == '{}'".format(string))
    tsregplot(selected['views'].resample('M').sum()[:-1], ax = ax[counter])
    ax[counter].set_title(j)
    plt.tight_layout()
    counter += 1
plt.savefig('trendplots.png')

需要注意的几件事:

  • 基于维基百科的页面浏览量, python 的兴趣实际上一直在下降
  • 根据维基百科的页面浏览量,对朱莉娅感兴趣的人可能会增加,但这看起来更像是噪音。
  • 基于维基百科页面浏览量,对 Java 的兴趣在增长,对 Scala 的兴趣在萎缩。 Scala 是 Java 的一个更简单、更现代的替代品。这让我有点吃惊。
  • 人们对打字稿的兴趣急剧增长,这已经在的许多文章中有所记载
  • 根据维基百科的页面浏览量,人们对围棋的兴趣一直在适度增加。GO 经常被认为是服务器语言的 python 杀手。我自己也玩过一点围棋,但并不觉得它对我的工作(主要是数据科学)非常有用。

结论:

有许多不同的方法来排列编程语言。我目前找不到任何其他人使用维基百科页面浏览量来对编程语言进行排名(是的,有人可能已经这样做了,但这还不足以找到关于它的文章)。

我认为维基百科的页面浏览量是衡量人们对编程语言或其他公众感兴趣的话题的一种非常合理的方式。当我对一门新的编程语言感兴趣时,维基百科通常是我首先查看的地方。我认为也可以有把握地假设许多其他人也这样做。

代码可以在这里找到

使用 PageRank 和 Neo4j 排名最佳 UFC 拳手

原文:https://towardsdatascience.com/ranking-the-best-ufc-fighters-using-pagerank-and-neo4j-5385805b4515?source=collection_archive---------16-----------------------

综合格斗迷和专家们喜欢争论哪些拳手应该被认为是有史以来最伟大的拳手。然而,很多时候,这些排名是战士记录、个人偏见、Reddit 键盘战士的分析和直觉的主观混合。有没有更数据驱动的方式来集结战斗机排名?

在这篇文章中,我将展示如何使用 PageRank 算法(最初由 Google 开发,用于对网页进行排名)和 Neo4j 来对每个 UFC 重量级的最佳拳手进行排名。

获取数据

UFC 在 http://ufcstats.com 发布自 1993 年以来所有赛事的比赛结果。为了获得这些数据,我编写了一个 Python scraper 来抓取站点并保存结果。在这篇文章中,我提取了截至 2019 年 9 月 14 日(UFC 战斗之夜 158)的所有战斗数据。更深入的描述和使用例子可以在我的 github 这里找到。

当新的 UFC 事件发生时,scraper 检索所有历史战斗结果并用新的结果更新已经保存的数据。虽然没有在此分析中使用,但战斗中的统计数据,如着陆打击和战士属性,如到达,身高和出生日期,也可以使用刮刀。

以下是本文将使用的部分数据:

如上所示,与此分析最相关的四个字段是战士、对手、结果和部门。

设计图形数据模型

在将数据加载到 Neo4j 之前,让我们考虑一下我们希望如何在图形中表示数据:

  • 每架战斗机将被分配到一个节点。
  • 边将被定向,这样如果战士 A 输给战士 B,将会有一条边从战士 A 传到战士 B。
  • 比赛的划分和日期将被设置为边的属性。如果战斗机 A 在 2019 年与战斗机 B 在轻量级比赛,那么这些部门和日期属性将位于连接这些战斗机的边上。
  • 如果格斗者多次面对面,那么每次格斗都会有不同的边。

我们的图形数据模型的可视化表示如下:

简单地说,上图显示战斗机 A:

  • 在 2015 年的一场轻量级比赛中输给了拳手 B
  • 2016 年在一场轻量级比赛中输给了战斗机 C
  • 2017 年在次中量级赢得了与战斗机 C 的复赛

将数据加载到 Neo4j

有了我们的数据模型草图,我们现在可以开始将数据加载到 Neo4j 中。为此,我们将利用 Py2neo ,它允许 Python 与 Neo4j 交互。这使得从 Python 到 Neo4j 的数据工作流更加简单,并且可以将 Cypher 查询结果从 Neo4j 提取回 Python。

下面的要点显示了用于将比赛结果数据从 pandas 数据帧加载到在默认设置下运行的本地 Neo4j 实例中的代码:

在上面的代码中,我们只查看 fights 数据帧的 results 列中带有“W”的行,因为输的行只是赢的行的镜像(fighter 和 counter 对调)。对于每一场战斗,如果没有节点存在,我们为战斗者和他/她的对手创建节点,或者使用 Cypher 的MERGE子句将它们与已存在的节点匹配。再次使用MERGE,我们创建了战斗的输家和赢家之间的有向边关系。战斗机名称、部门、日期和方法等属性作为参数传入,这些参数被分配给图的节点或边的属性。

一旦加载了数据,我们就可以在 Neo4j 的浏览器中查看可视化的图表。以下是一个查询的结果,显示了康纳·麦格雷戈的所有对手,以及他们如何对付康纳和对方:

PageRank 的一个非常简短的解释

最初由拉里·佩奇和谢尔盖·布林开发的 PageRank 被用于谷歌的搜索引擎,对链接网页的相关性进行排名。在有向图中使用网页作为节点,链接作为边,PageRank 的大致思路如下:

  • 有许多其他页面链接到它的页面将有更高的相关性
  • 拥有来自高相关性页面的链接增加了相关性
  • 页面将相关性传递给它们链接到的邻居

以最初的网页排名用例为例,像 Twitter 这样的网站会有很高的 PageRank,因为有许多其他网站链接到它。同样,从 PageRank 的角度来看,一个带有 Twitter 等热门网站链接的网站也具有很高的相关性。下图展示了这一想法:

Source: Wikipedia

节点 B 具有最高的 PageRank,因为它不仅有许多链接到它的节点,还因为它有来自具有相对高相关性的节点的链接。尽管节点 C 只有一条指向它的链路,但它有很高的 PageRank,因为这条链路来自网络中最重要的节点 B。节点 A、D 和 F 的网页级别较低,因为它们只有几个相对不重要的节点与之链接。

理解了上面的例子,我们就可以看到 PageRank 也可以翻译成 UFC 战士了。具有更多胜利(更多边传入)和战胜高排名战士(来自重要节点的传入边)的战士将具有更高的 PageRank 排名。

虽然简短,但对 PageRank 的解释有望提供算法如何工作的一般概念。对于那些有兴趣了解更多的人,这个视频系列的视频 5-10 提供了一个很好的解释。

将 PageRank 应用于 UFC

方便的是,Neo4j 已经提供了 PageRank 的实现,所以我们可以很容易地将该算法应用于我们的 UFC 图。再次使用 Py2neo,下面的代码计算每个师的战斗机 PageRank 分数:

下面我们可以看到 PageRank 是如何对男女各个组别的前 10 名最佳拳手进行排名的:

Men’s top 10 PageRank scores by division

Women’s top 10 PageRank scores by division

调整 PageRank 分数

虽然 PageRank 排名看起来基本正确,但也有一些情况下粉丝可能会觉得有问题。例如,目前的轻量级冠军和不败拳手哈比布·努尔马戈梅多夫在历史排名中排名第三,尽管他击败了排名第二的迈克尔·约翰逊。约翰逊自己的排名似乎太高了,因为他在轻量级比赛中输了 8 次,所有这些都是由排名低于他的拳手造成的。此外,将唐纳德·赛罗内列为有史以来第一轻量级拳手是有问题的,因为他从未赢得过金腰带,也输给了许多排名低于他的拳手。

同样,在重量级比赛中,一些人可能会对前冠军丹尼尔·科米尔排名低于竞争者德里克·刘易斯四位提出异议,尽管科尔米耶此前击败了刘易斯和排名第一的斯蒂佩·米奥西奇。

这些差异从何而来?回想一下,PageRank 在计算分数时会考虑节点的传入边数。因此,总胜率越多(进洞边数越多)的拳手,他们的 PageRank 分数将会提高。因此,看起来 PageRank 的排名过于看重胜利的数量,或许也稍微低估了失败的数量。

最明显的例子是在轻量级比赛中,目前的冠军 Khabib Nurmagomedov 的记录是 12–0–0(W-L-D ),但仅排名第三,而排名第一的 Donald Cerrone 的记录是 17–6–0。Cerrone 比 Nurmagomedov 赢的多,主要是因为在 UFC 轻量级比赛中打得多(Nurmagomedov: 12,Cerrone: 23)。因此,尽管是冠军,尽管击败了排名很高的拳手,Nurmagomedov 的 PageRank 分数相对于 Cerrone 的有所下降,因为他的总比赛次数较少。

同样,迈克尔·约翰逊的第二总排名看起来很奇怪,因为约翰逊的记录是 9-8-0,其中包括输给努尔马戈梅多夫。事实上,约翰逊已经战胜了几个排名很高的轻量级选手,包括托尼·弗格森(第 5 名)、埃德森·巴尔沃萨(第 6 名)和达斯汀·普瓦里耶(第 7 名),这有助于提高他的 PageRank 得分。然而,他在轻量级比赛中仅有 0.50 的战绩让人质疑他的第二名排名,并表明损失并没有得到应有的重视。

基于上面的观察,我们需要以某种方式将拳手的记录纳入排名,这样胜率高或输球少的拳手的 PageRank 分数就会提高。

个性化页面排名

一种可能的方法是使用一种叫做个性化页面排名的页面排名算法。非常概括地说,个性化页面排名有利地偏向网络中的某些节点,从而增加这些节点的得分。但是,指定哪些节点应该接收偏置可能有点随意,并且可能会根据选择的节点而显著改变结果。例如,下表显示了轻量级部门的个性化页面排名,使用两种不同的标准来选择有偏向的节点:

Left: Personalized PageRank rankings with biased nodes of Khabib Nurmagomedov and Tony Ferguson. Right: Personalized PageRank rankings with biased nodes of Khabib Nurmagomedov, Tony Ferguson, and Gregor Gillespie

左边的表格使用偏向节点选择标准,即≥ 10 次战斗和≥ 90%的胜率,而右边的表格使用≥ 6 次战斗和≥ 90%的胜率。正如我们所看到的,第二个选择标准增加了一个额外的有偏向的节点,这导致了一个非常戏剧性的变化;Gregor Gillepsie 曾在左侧表格中排名第 60 位,当被列入有偏见的节点时,他突然上升到第 3 位。鉴于这些结果,选择有偏向的节点用于个性化 PageRank 可能不是最好的主意,因为 a)选择标准可以是任意的,b)结果根据选择的节点而显著变化。

对于感兴趣的人,这里是 Neo4j Cypher 查询,用于返回个性化的 PageRank 分数:

非二进制偏置节点选择

上述问题的一个潜在解决方法是对每个节点应用一个权重,可能是战士的胜率或 1/损失,并使用这些权重来计算每个节点的偏差。因此,不是二元选择是否偏置特定节点,而是每个节点基于它们的胜率或损失率接收不同程度的偏置。

不幸的是,Neo4j 目前还不支持这一功能,尽管根据 Neo4j 的 github 上的这个公开问题,它似乎正在工作中。我可能会写一个后续在未来当这是补充。

按胜率加权 page rank

将拳手的记录纳入排名的最简单的方法是简单地将每个拳手的 PageRank 乘以他们的 win %。虽然并不完美(失败会对战斗较少的战士产生更大的影响),但这将有助于平衡这样一个事实,即一些战士赢得更多,主要是因为总体上有更多的战斗,同时也增加了失败的影响。

使用该方法得到的修正排名(PageRank * Win %)如下表所示:

Men’s rankings: PageRank * win %

Women’s rankings: PageRank * win %

虽然很主观,但对以上修订排名的评估感觉更好。在轻量级比赛中,Khabib Nurmagomedov 和 Tony Ferguson 分别排名第二和第三,而迈克尔·约翰逊跌至第四。虽然唐纳德·塞罗内仍然保持第一名的位置,但塞罗内和努尔马戈梅多夫之间的差距已经明显缩小。在重量级比赛中,前冠军丹尼尔·科米尔从第八名上升到第六名,虽然在我看来还是有点低(应该比排名第五的德里克·路易斯高),但这是一个更合理的排名。

结论

在这篇文章中,我们展示了如何使用 PageRank 对 UFC 战士进行排名,并找出每个组别中的最佳选手。虽然不完美(大多数排名都不完美),但 PageRank 似乎在战士排名方面做得相对不错。

一个潜在的进一步改进是考虑战士的年龄。一些伟大的战士继续战斗,直到过了他们的巅峰时期,并遭受损失,这降低了他们的 PageRank 分数,增加了击败他们的人。很好的例子是中量级伟大的安德森·席尔瓦,他在过去的五场比赛中取得了 1 胜 4 负的成绩,以及轻量级传奇人物 BJ·佩恩,他在过去的五场比赛中取得了 0 胜 5 负的成绩。在一个伟大的斗士暮年打败他,不应该等同于在他全盛时期打败他。如果我们想找到最好的全盛时期的拳手,考虑年龄似乎是必要的。

也就是说,也许知道什么时候挂掉他们也是一个伟大的战士变得伟大的原因。

对于那些想自己探索数据的人来说,所有代码和数据都可以在我的 github 上找到。

对于 UFC/MMA 的粉丝来说,这些排名和你自己的相比如何?

说唱(机器)天才

原文:https://towardsdatascience.com/rap-machine-genius-935db7a260b?source=collection_archive---------36-----------------------

一个有抱负的说唱歌手应该关注哪些话题才能在 Genius.com 走红?简单回归分析

最大化观点的创造性咨询

Janelle Monae, by Shawn Anderson (Creative Commons license)

1.主要前提

a.激励性问题

对于我的回归项目,我从以下前提开始:假设我的朋友 Janelle 是一名有抱负的说唱歌手,她筹集的资金只够下周举行一次录制。这是她走红的机会,但她需要帮助决定录制哪些歌曲。在工作室的有限时间里,Janelle 应该做关于她的宗教信仰的那个,还是关于高级时装的那个?她能在不咒骂或吹嘘她希望拥有的豪车的情况下获得关注吗?

b.衡量一首歌的受欢迎程度

当然,如今衡量一首歌曲成功与否的最佳指标必须包含音乐流数据,因为这是目前大多数人听音乐的方式。但听众分散在多个服务中,包括 Spotify、Apple Music、Tidal、YouTube 等。即使假设他们公开了他们的数据,也很难将它们收集并汇编成一个单一的数据集。

c.警告

人们听一首歌的原因有很多,与歌词无关:也许他们已经喜欢上了这个艺术家,也许节拍非常适合跳舞,也许旋律非常吸引人。但没关系——我在这里的目的不是建立一个模型来预测准确的点击量,而是梳理出话题和流行度之间的一些关系。

2.网页抓取

a.Genius.com

我决定从歌词网站 Genius.com 收集信息。这是一个网站,提供一首歌的原始歌词,加上解释歌词意义的众包注释。假设你正在听德雷克的《上帝的计划》,歌词“把 O2 变成 O3”让你挠头。你可以访问这首歌在 Genius.com 的页面,了解 Travis Scott 在伦敦 O2 arena 与 Drake 一起表演时从舞台上摔了下来。整个人群都退了款,把 O2 变成了“O-free”

为了方便起见,Genius.com 公开了页面浏览量。当然,歌词特别复杂、引用模糊的流行歌曲在那里吸引的浏览量可能比你根据其受欢迎程度预计的要多。但接下来,我会把一首歌在 Genius.com 的浏览量作为一首歌受欢迎程度的代表。

b.Selenium Chrome 驱动程序抓取的数据

下一步是收集数据。我用 Selenium Chrome 驱动程序抓取了被赋予说唱标签的前 1000 首歌曲的页面链接。

然后我访问了列表中的每一页,收集了以下数据:歌词本身、浏览量、与歌曲相关的标签以及为解释歌曲歌词而贡献注释的人数。

我还跟踪艺术家、歌曲作者或制作人是否提交了歌词的解释。该网站称之为“经过验证的评论”,并用绿色而非灰色标记这些注释(见下文)。

c.特征工程

一旦我获得了 1,000 首歌曲中每一首歌曲的信息,我就使用一个简单的词袋模型来计算某个词在一首歌曲中出现的次数,然后根据歌曲中的词数对该计数进行归一化。例如,“服装”主题的特色是品牌名称,如“古驰”、“芬迪”、“普拉达”、“路易威登”、“迪奥”等。“诅咒”主题包含了 FCC 68 个禁用词中的大多数,“汽车”主题包含了特别著名的豪华汽车的品牌名称,如“布加迪”、“保时捷”和“法拉利”,而“宗教”主题包含了“上帝”、“主”、“耶稣”、“魔鬼”和“信仰”等词。

3.探索性数据分析

也许不出所料,大多数歌曲的歌词都很直白:除了 83 首以外,所有歌曲都带有某种诅咒的字眼。

快速的理智检查表明,我的话题确实找到了正确的歌曲:“衣服”指标中得分最高的歌曲是 Migos 的 【范思哲】Lil Pump 的和 Kreayshawn 的古驰古驰。《汽车总动员》也是如此:最佳射手是艾斯胡德的布加迪和美联社的 Yamborghini High。《诅咒》中出现了一些脏话,看到 Kanye West 在“宗教”指标上名列前茅,我并不感到惊讶。

4.建模

在确保数据相对干净,功能按照我预期的方式运行之后,我使用普通的最小二乘法建立了一个简单的线性回归模型,以页面浏览量为目标。然后,我应用了一个标准的缩放变换,接着是岭正则化,这样我就可以并排比较各种特征的系数。

a.最大特点:观众参与

让我们从两个最强的结果开始,它们具有高系数低 p 值。越多人对一首歌的页面做出贡献,这首歌的页面浏览量就越多。拥有一个“经过验证的”投稿人对页面浏览量也有积极的影响。

b.话题强度

就主题而言,唯一对页面浏览量有负面影响的是“宗教”类别。这是否意味着坎耶·韦斯特是对的?在中,耶稣行走 (2004),韦斯特斥责道:

他们说你可以说唱任何东西,除了耶稣

这意味着枪支、性、谎言、录像带

但是如果我谈论上帝,我的唱片就不能播放了,嗯?

没那么快。p 值有些高:0.23。相比之下,“汽车”功能对查看次数有积极影响,但其 p 值为 0.06,非常接近 0.05 的标准统计意义阈值。咒骂和奢侈服装有正系数,但它们也有较高的 p 值(分别为 0.842 和 0.358)。

5.结论

a.主题

那么,我会给我的朋友詹妮尔什么建议呢?我会建议她在宗教方面坚持己见。当然,系数是负的,但说唱歌手谈论他们的信仰并不常见,所以这可能有助于她脱颖而出。同样的,她不应该觉得为了适应而不得不诅咒。不过,她可能会发现谈论豪华车对她有利。她可以说唱她有多不在乎他们,并且仍然从这种观察到的提升中受益!

b.观众参与度

一旦这些歌曲向公众发布,我会请我的朋友们为 Genius 添加注释,因为这似乎会增加浏览量。Janelle 也应该自愿做出“经过验证”的贡献!这将提升观点,也确保人们明白她想说什么。

PS:作为一个额外的奖励,只是为了好玩,这里是各种服装品牌和流派标签在页面浏览量上的相对效果。

用 Azure 实现快速计算机视觉原型

原文:https://towardsdatascience.com/rapid-computer-vision-prototyping-with-azure-f051cc7462b7?source=collection_archive---------16-----------------------

本帖由亚历克斯·阿库洛夫和 瑞安·佩曼 合著,来自 Omnia AI,德勤加拿大的 AI 实践

Object-detecting trucks using a computer vision model on Azure Custom Vision

想象一下,快速构建和部署一个最先进的对象检测模型,而无需编写一行代码。计算机视觉工具和软件已经走过了漫长的道路,使这成为现实。

几年前,你必须知道如何编码,熟悉深度学习框架,并有耐心解读错综复杂的研究论文。在本文中,我们将向您展示如何在几分钟内构建一个对象检测原型模型,并解释新兴工具如何帮助“民主化”计算机视觉解决方案的创建。

Azure Custom Vision 让您无需编写一行代码即可构建和部署对象检测模型。

所有主要的云提供商都在竞相提供预构建的计算机视觉模型。从场景检测和内容审核到文本提取和情绪智能,这些现在都可以轻松实现。

然而,当谈到超越常见用例的界限时,AWS 和 Google 会向您介绍他们各自的数据科学笔记本环境。我们发现 Azure 采取了不同的方法。它的定制视觉产品让您无需编写一行代码即可构建和部署对象检测模型。对于想要测试他们的计算机视觉想法的团队来说,这意味着温和的学习曲线和快速的原型制作。

但是首先,这个想法应该解决一个适合计算机视觉的问题。

确定要解决的业务问题

计算机视觉模型应该为决策提供信息。在商业上,没有为了 AI 而 AI 的地方。总体业务目标是什么?阻碍我们实现目标的问题是什么?是否有图像或视频可以用于深度学习应用?这些是在识别计算机视觉的商业应用时要问的一些关键问题。

我们的目标是展示 Azure Custom Vision 的功能。为此,我们选择了一个监测港口作业中卡车到码头交通的样本问题。

在这一过程中,集中运营协调员必须通过实时视频传输(见下面的视频传输示例图像)持续监控航站楼交通,以确保航站楼车道不会拥堵到卡车涌入附近高速公路、扰乱当地交通的程度。

Terminal gate video feed (Source)

从协调者的角度来看,不断地检查几十个监视器中的一个来捕捉偶尔发生的拥塞是一项相当费时且平凡的任务。协调员是非常忙碌的人,在一个 24/7 的高压环境中工作,检查许多供应链事件的视频,如事故、火灾和非法侵入。

Typical supply chain operations center

为了帮助协调员专注于更关键的任务,让我们尝试通过在 Azure Custom Vision (ACV)上训练计算机视觉模型来证明自动化终端拥堵监控是可能的。

该过程可以分为 5 个步骤:

Machine Learning process for Computer Vision

1.获取图像

温哥华港在他们的网站上发布了他们的终端网络视频。为了训练一个高精度的模型,我们需要标记至少 100-150 幅图像。手动保存 100 多张网络摄像头图像是一项单调乏味的工作,所以让我们使用一个简短的 python 脚本来加快速度。注意,这是本文中我们使用代码来节省时间的唯一地方。

import urllib.request as r, time

*# Direct link to the terminal webcam feed*
imgURL = '''http://www1.pacificgatewayportal.com/webcams/Photos
/CentermMainGates/CentermMainGates_New.jpg?1430944227172'''

for i in range(100):
    r.urlretrieve(imgURL, f"images_{i}.jpg")  *# Scrapecurrent image*
    time.sleep(30)  *# Wait 30 seconds*

2.标签图像

接下来,我们去 www.customvision.ai ,创建一个账号和一个新项目。一旦完成,我们使用界面上传我们上面刮的图像。点击添加图片并导航至您想要上传的文件夹。

接下来,可以开始标记的任务。ACV 提供的界面是直观的,能够围绕你想要检测的每个对象绘制矩形边界框。多个 label 标签可以应用于每个边界框。在这种情况下,我们需要的唯一标签是卡车,但是在您的用例中可能有更多种类。

Process of labeling trucks

一般来说,对于一个有效的概念证明模型,建议每个标签至少标记 50 个图像。如果您的用例需要检测多种类型的对象,请确保您有足够的训练图像来捕捉不同的场景。

贴标签需要时间,但是如果您有一个想要原型化的定制业务问题,这是不可避免的。我们喜欢 Azure Custom Vision 的地方在于,该功能内置于解决方案中,使用起来非常直观。

What a labeled image looks like

3.训练模型

这是最简单的部分。使用一次点击,我们在 Azure Custom Vision 中训练一个神经网络,根据标记的样本在图像上检测卡车。该过程需要几分钟到几个小时,具体取决于训练图像数据集。

Complexity of Computer Vision model training is hidden from the user

4.评估模型

所以我们已经训练了一个模型,但是我们怎么知道它是好的呢?理想情况下,给定终端门的图像,模型应该检测图像中的每辆卡车。在这种情况下,检测意味着以一定的置信度将图像的矩形部分识别为卡车。

我们可以通过使用快速测试选项,用新的图像来尝试:

Quick Test allows us to immediately view model output

自定义视觉提供了一个方便的滑块来更改模型应该使用的最小置信度。如果我们将阈值滑动到 13%,模型将检测到更多的卡车,但假阳性的数量也会增加。这里需要达到一个平衡,在这种情况下,我们决定使用 50%的阈值。

Lowering probability threshold increases false positives

这还不错,但是模型没有检测到每辆卡车。更具体地说,在图像中的 14 辆卡车中,该模型至少有 50%的信心找到 8 辆。仅基于这张测试图,模型的召回为 8/14 = 57%。我们也可以说模型的精度是 8/8;也就是说,模型检测到的 100%的卡车实际上都是卡车(即没有误报)。

Azure Custom Vision 为模型的每次迭代提供了查全率和查准率。平均精度(mAP)是一个更复杂的描述方法,所以如果你感兴趣,我们将链接到一篇文章。作为参考,地图上的一般物体检测任务用最先进的模型徘徊在 60% 左右。

Key indicators to evaluate model’s performance

5.部署

一旦我们在 Azure Custom Vision portal 中训练了模型,它就已经通过 API 部署和可用了。从门户外部进行 API 调用将需要“设置”菜单中可用的预测端点和键。

Information needed to send request to model API node

微软还提供了一个有用的 API 测试工具,可以让你快速查看模型的原始输出——一个 JSON 字符串。

我们完了。

Azure Custom Vision 等工具真正大放异彩的地方

通过几个步骤和最少的代码,我们使用 Azure Custom Vision 创建了一个计算机视觉概念验证模型。虽然 ACV 肯定可以用于创建生产规模的解决方案,但在模型控制和定制方面有一些限制。如果你需要完全控制过程的每一个方面,那么不可避免地要使用深度学习 ML 框架。

我们认为,使用像 ACV 这样开箱即用的无代码工具的最重要价值在于,让人工智能概念证明启动并运行,以测试解决方案的可行性。虽然 Azure 是目前唯一一家提供无代码工具来创建 CV 模型的主要提供商,但鉴于该领域的巨大竞争,预计其他 PaaS 提供商也会效仿。

使用像 ACV 这样的工具的最大价值在于快速测试一个人工智能解决方案是否可行

这对企业来说是个好消息,因为它通过降低测试 CV 解决方案的成本,有效地降低了人工智能采用的门槛。考虑到世界上“数以百万计”的组织,根据谷歌主管杰夫·迪恩的说法,“有一个可以用机器学习解决方案解决的问题”,像这样的工具只能帮助推动人工智能的采用。

当然,有效的工具只是硬币的一面。创建人工智能解决方案的另一个必要因素是拥有理解数据科学和底层模型如何工作的合适人才,不管使用什么工具。不幸的是,T2 仍然严重缺乏人才。这是为什么你会看到专业服务公司等非传统参与者提供人工智能和分析服务来满足需求的部分原因。

事实上,这正是我们在德勤加拿大人工智能实践 Omnia AI 所做的事情:我们帮助组织使用 AI 来解决他们迫切的问题。像 ACV 这样的新兴工具可以在这一过程的早期发挥重要作用。

进步快还是理解浅?

原文:https://towardsdatascience.com/rapid-progress-or-shallow-understanding-663bdedc80c1?source=collection_archive---------12-----------------------

这是我对人工智能工具 Tensorflow 的体验的高度总结。如果你是第一次学习这个领域,我建议你从这个快速发展的领域的介绍开始。

如果有一件事我们都讨厌,那就是格式化书目。是的,你可能认为赞扬他人的工作很重要,是的,有条理很令人满意,但是真的有人关心准确无误的单词斜体吗?当然,你可以通过使用自动在线工具来完全避免这个问题,但是这种便利是有代价的吗?现在更容易的道路值得不去克服挑战为未来做准备吗?尽管这个例子很简单,但同样的问题困扰着生活中许多其他[更复杂]的情况。

The day before the deadline, trying to plump up the bibliography with non-Wikipedia links… Photo by Tim Gouw on Unsplash.

最近,我在研究人工智能算法时遇到了这个难题。我应该迅速尝试探索许多不同的主题,以实现该领域的各种应用,还是应该确保在更深的层次上熟悉这些概念?使这个决定变得更加困难的是,我想获得使用行业标准工具(如 Tensorflow 框架)的经验,这些工具可以在高层次上加速开发。在 Tensorflow 的帮助下,我在过去几周完成的项目是我刚开始接触人工智能时的五倍,但这种经历值得吗?

用人工智能赶时髦

我用 Tensorflow 做的第一个项目和我创建的一个比较老的项目类似(没有高层框架的帮助);在尝试建立 Tensorflow 遇到一些挫折后,我建立了一个计算机视觉算法,将图像分类为不同类型的衣服。也许,你认为这很简单,但你真的知道最新款的羊毛衫、运动夹克和商务休闲背心之间的区别吗?

I can’t tell Armani from a beluga whale, but have you met my AI friend? Photo by Hunters Race on Unsplash.

相比之下,我之前创建了另一个分类算法,但是是针对手写数字而不是服装。因此,我可以将我的旧项目的各个方面与 Tensorflow 的功能进行比较,我惊讶地发现这个框架是如此容易使用。我可以在 Tensorflow 中使用预构建的函数,而不是从头开始编写我使用的每个函数。

例如,我以前必须用数学公式定义一个激活函数,而我只是从 Tensorflow 的许多现有函数中选择一个。此外,该框架还帮助我设置了要使用的数据,而不是我必须下载、转换和处理成千上万的图像来训练算法。虽然这些功能确实很方便,但我只是因为之前的项目(更注重实践)才明白它们是如何工作的。最终,我为快速成功地创建了算法感到兴奋,但也担心这种新的简单性是否更好。

做着同样的事情…但方式不同

然后,我决定探索一种称为卷积神经网络(CNN)的算法来对手写数字进行分类,我已经用其他算法完成了这一工作。从本质上讲,CNN 的主要优势在于它在处理图像之前简化了图像,使得识别数字的主要特征更加容易。把它想象成试图解一个 3x3 的魔方;如果你不断从边缘抽离,事情会简单得多...

While the one on top entices me more than the one underneath, I’m not solving anything until the cube is 1x1. Photo by Olav Ahrens Røtne on Unsplash.

在这里,我发现这个项目比我的服装分类器更具挑战性,因为我以前从未使用过 CNN 算法。然而,Tensorflow 针对 CNN 的特定功能使我能够快速理解算法的过程。

具体来说,Tensorflow 使得为 CNN 创建最大池缩减采样层变得很容易,这是简化给定图像的关键步骤。我不再担心单独的计算,而是更加关注算法的结构以及这些层之间的相互作用。也就是说,我并没有获得多少实践经验来弄清楚如何最有效地对这些层及其功能进行编码。最终,我会很高兴与 CNN 的一些更自下而上的方面合作,并尝试在没有 Tensorflow 的帮助下重建一些计算,这就是为什么我想在一个不同的项目中重新讨论这个主题。

如果你不能理解人,让人工智能帮你做

有了这次简化数据的经历后,我创造了我最喜欢的项目:一种试图理解人类情感的算法。最后,我可以用我的秘密工具来为生物学争取额外的 5%了!

Students celebrating the wonder of AI to help negotiate marks… Photo by Vasily Koloda on Unsplash.

事实上,它只看电影评论来预测观众是否对这部电影满意。起初,我真的被计算机理解人类情感的可能性惊呆了。然而,这个问题的解决方案比我想象的要简单;该算法使用人们在评论中使用的词语来决定他们对这部电影是否满意。

举例来说,想想你是如何通过文本来判断你朋友的情绪的。他们有笑脸表情符号还是用大写的彩色名词?同样,该算法将人们在评论中使用的词语分为正面或负面,以预测他们对这部电影的感受。在发现这个简单的过程后,我更加理解了现实世界应用程序的影响。从商业上来说,了解顾客的感受让他们更快乐是非常好的,即使用来了解这些情绪的方法更加复杂。

我认为你的文章有点抄袭的味道

人工智能的这种实用潜力让我欢欣鼓舞,我想研究更复杂的人工智能算法。这就是为什么我用 Tensorflow 创建了我的第一个递归神经网络(RNN)。我还想在项目中融入一些随机的乐趣,所以我建立了一个模仿莎士比亚戏剧的算法。显然,唯一比用一篇写得很好的文章打动你的英语教授更好的事情是用一篇写得很好的文章打动你的计算机科学教授,这篇文章是用人工智能写成的莎士比亚式英语。

Your computer science professor after reading an AI’s Shakespearean essay. Photo by Ben White on Unsplash.

在整个项目中,我了解了 RNNs 背后的基础知识,以及它们与常规神经网络的不同之处。从根本上说,RNN 的主要优势是它从过去的结果中学习来创造新的结果,或者在问题的背景下,它使用以前的字母来预测新的结果。

此外,这是我开始利用 Tensorflow 的多样化功能的时候。首先,我尝试了不同的优化器来调整 RNN 的学习能力。很明显,我知道了常规梯度下降是多么耗时,随机梯度下降(SGD)通过使用小批量数据减少了计算,自适应矩估计(Adam)避免了陷入良好的设置,而不是找到最佳设置。同样,我试验了不同的激活,发现二元阶跃函数很容易计算,sigmoid 函数很适合分类算法,softmax 函数适合概率问题。

尽管能够快速尝试这些不同的函数并比较结果,我还是不能像我希望的那样强烈地理解 RNNs 的基础知识。当然,我知道该使用哪些函数,以及为什么它们对手头的问题有利,但是我并没有通过实验对 RNNs 工作背后的细节有很深的理解。为了解决这一限制,我需要更深入地研究 RNNs 背后的理论,这在 Tensorflow 已经为您预打包了一切的情况下是有问题的。

可可的人知道他们的工作有点疯狂…

有了 Tensorflow 的经验,我终于开始了我从事的最大的人工智能项目。使用 COCO 图像数据集(成千上万不同主题的图像集合),我创建了一个 RNN,它可以自动为图像生成标题。类似于莎士比亚的 RNN 使用每个字母来预测下一个,这个算法使用标题中的每个单词来预测下一个。而且这一次甚至没有抄袭去世已久的作家,大部分!基本上,它看的是这样一幅图像:

Photo by Jeremy Bishop on Unsplash.

然后描述说“一个在海浪上的古怪家伙,伙计。”然而,关键的挑战是在成千上万张图像上有效地训练这种算法。

甚至在我开始之前,我已经陷入了为算法下载和处理千兆字节的训练图像的挑战中。这种计算密集型的过程主要是硬件问题,因为 Tensorflow 已经证明了将图像转换为正确的数据格式的功能。有了这个障碍,开发算法主要是重复我在以前的项目中采取的步骤,然后等待…一小时又一小时的等待。虽然,最后,我还是很乐意尝试一个更大规模的项目。

我不确定 Tensorflow 就是不太流畅…

What your puns flow like with Tensorflow. Photo by Matt Hardy on Unsplash.

我和 Tensorflow 的故事到此结束。总之,我用这个高级框架在短短几周内创建了五个不同的项目。通过这个,我获得了多类神经网络的经验,这些神经网络中不同功能的优势,以及人工智能的众多应用。总的来说,我很感激能够快速通过这些挑战,但我确实觉得还缺少一些东西。现在,虽然我对人工智能领域的多个方面有了更多的了解,但我确实认为这些知识有点仅限于 Tensorflow 框架,而不是一般化。总的来说,拥有 Tensorflow 的易用性很有趣,但我绝对重视在没有高级框架帮助的情况下创建我的第一个人工智能项目。这是我能够欣赏在一个项目上投入大量工作来从零开始创造它所花费的时间和努力的唯一方式。

关键要点

  1. 进步快很方便,但是做了就很难对概念有深刻的理解。
  2. 有了以前的实践知识,我能够在创建服装分类器时欣赏 Tensorflow 的新的简单性。
  3. 我可以很容易地专注于 CNN 自上而下的架构,但我没有学习 Tensorflow 的自下而上计算的自动化。
  4. 很难衡量复杂的人类情绪,但检查相关因素就容易多了,比如一个人高兴或悲伤时的语言。
  5. 如果有一件事 Tensorflow 可以帮助初学者,那就是如何将数据处理成可用的形式。

如果你想亲自体验 Tensorflow 的快乐(和挫折…),这里有几个教程可以帮助你开始:

RAPIDS cuGraph——1.0 及更高版本的愿景和旅程

原文:https://towardsdatascience.com/rapids-cugraph-the-vision-and-journey-to-version-1-0-and-beyond-88eff2ce3e76?source=collection_archive---------12-----------------------

RAPIDS cuGraph 的愿景是让图形分析无处不在,让用户只从分析的角度思考,而不是技术或框架。这是我们 cuGraph 团队中的许多人已经努力了近二十年的目标。许多早期的尝试集中于解决一个问题或使用一种技术。那些早期的尝试为最初的目标工作,但是随着范围的改变(例如,转移到用静态图解决方案解决动态图问题)倾向于中断。限制因素通常归结为计算能力、易用性或选择不适合所有问题的数据结构。NVIDIA GPUs、CUDA 和 RAPIDS 完全改变了范式,加速统一图形分析库的目标现在已经成为可能。

最新的 NVIDIA GPU(RAPIDS 支持 Pascal 和更高版本的 GPU 架构)的计算能力使图形分析比 NetworkX 平均快 20 倍。此外,GPU 内部的内存速度允许 cuGraph 快速切换数据结构,以最大限度地满足分析需求,而不是局限于单一数据结构。cuGraph 正在与静态和动态图形数据结构的几个框架一起工作,以便我们总是有任何图形问题的解决方案。由于 Python 已经成为数据科学事实上的语言,允许在 Python 中进行交互和运行图形分析的能力使得 cuGraph 变得熟悉和平易近人。RAPIDS 将上面提到的所有图形分析优点与执行高速 ETL、统计和机器学习的能力结合在一起。更好的是,RAPIDS 和 DASK 允许 cuGraph 扩展到多个 GPU,以支持数十亿边图。

RAPIDS 的每个版本都附有一个或多个关于该版本特性的精彩博客(例如,参见 0.8 版博客[ 1 ]或Hadoop 后的生活)。这篇文章略有不同。虽然将讨论当前的功能,但主要焦点是展示 cuGraph 的愿景以及我们设想用户将如何与库进行交互。cuGraph 团队一直在努力提供一组丰富的初始特性。在过去的三个版本中(RAPIDS 是第一个包含 cuGraph 的版本),该团队提供了十几个算法。最初的目标是简单地发布 graph analytics,并通过熟悉的类似 NetworkX 的 API 提供。这在短期内很好,因为它提供了一条转向急流的捷径。然而,cuGraph 的开发将慢慢转向改进易用性、互操作性以及与 RAPIDS 其他部分的集成。这并不是一件容易的事情,因为 cuGraph 生态系统中还有很多东西需要添加。不要担心,推出新分析的目标将继续下去,因为有一个非常长的算法列表要发布。

属性图和高级工作流:cuDF、cuML 和 cuGraph 之间的联系

术语“属性图”自 2010 年以来一直在文献中讨论[2,3,4],最常用于在关系数据库中定义图的上下文中——我实际上在 2010 年之前构建了一个数据库支持的图系统,所以这个概念比文献更古老。更正式地说,属性图是一个有向多重图,其中每个顶点和边可以有多个属性。多重图意味着任意一对顶点之间可以有多条边。考虑一个网络,其中顶点代表服务器,每个服务器可以有多个 IP 地址(属性)。任何一对服务器之间都可以有多条边,每条边代表一个具有时间、端口和协议信息的不同连接。请参见下图。

A Multigraph with its DataFrame Representation

在 RAPIDS 中,属性图可以表示为数据框的集合。在简单的情况下,一个数据框用于顶点信息,另一个用于边,如上图所示。然而,多于两个数据帧也是可能的(并且是常见的)。一旦填充了属性图,就可以提取各种子图。例如,我们可以提取一个边仅通过端口 80 的子图:edge _ df = edges . query(' port = = 80 ') 此外,我们可以使用 group_by 函数将所有的边卷成一条边。能够捕获所有属性并生成数据的不同视图的好处是属性图模型的强大。

Data Frame to rule them all

数据帧的概念是 RAPIDS 的核心——不仅仅是 RAPIDS 利用 Apache Arrow [ 5 ]规范通过允许零拷贝数据移动来确保流程之间的互操作性。数据帧的概念允许 RAPIDS 的所有组件交流、理解和共享数据。这是将它们结合在一起的核心概念。考虑类似上面的属性图,除了假设节点上有更多的属性——这可以是网络、社会或产品信息——并假设我们希望用图度量进一步丰富节点数据。我们可以(1)从边数据框构建一个图,然后(2)计算每个顶点的度数信息并将其添加回节点数据框。同样,(3)可以计算 PageRank 分数并加回。最后,我们可以(4)然后采用新丰富的节点数据框架,并对数据运行来自 cuML 的 K-Means,并查看数据如何聚类。这凸显了数据在 cuDF、cuML 和 cuGraph 之间移动的便利性——这都要归功于数据框架的强大功能。

在 Python API 层,RAPIDS cuGraph 完全支持数据帧,所有函数都接受并返回一个数据帧。CuGraph 还支持属性图,并正在努力更好地将这一概念集成到算法中。

技术和框架——静态、动态以及介于两者之间的一切

关于哪种技术是最好的:以顶点为中心的[6]还是以图形为中心的[7],在图形研究界已经争论了很多年。即使在 cuGraph 团队内部,我们也在争论哪种方法更好。但是 cuGraph 是关于分析的。cuGraph 没有选择一种技术,而是选择提供一组技术。对于任何分析,只要能提供最佳性能和可扩展性的技术都会被使用。此外,随着分析的定期更新和改进,底层技术也可能被替换掉。由于分析是通过定义良好的 API 公开的,因此任何变化(除了性能)对用户都是透明的。

在接下来的几个版本中,以下框架[ 8 ]将被整合到通过 cuGraph Python API 公开的 cuGraph 和分析中:

  • 来自德克萨斯 A&M 的蒂姆·戴维斯实验室的 GraphBLAS
  • 加州大学戴维斯分校约翰·欧文斯实验室的枪岩
  • 乔治亚理工学院的大黄蜂[ 11
  • NVIDIA 的 NV graph[12]

其中一些技术提供了动态数据结构,特别是动态压缩稀疏行(CSR)结构。有许多地方需要动态结构。最明显的是分析图表随时间的变化。随着数据的流入,可以监控和报告网络结构的变化。同样重要的是在分析中使用动态结构。在许多情况下,结果集的大小是未知的先验的 —例如稀疏矩阵乘法(SpGEMM)。能够即时折叠、扩展、添加和缩小图表或结果是一项强大的技术。

定制分析:原型、原语和批量同步并行

cuGraph 开发人员正致力于提供一个完整丰富的分析集(参见路线图部分)。每项分析都将定期重新审查和更新,以确保最佳性能。但是,在某些情况下,我们希望在完全优化之前先试用分析。在接下来的几个版本中,我们将推出一个包含样本代码和实验分析的“ proto ”模块。应该强调的是,它是实验性的。如果对该模块中的任何分析感兴趣,那么可以将其移到 cuGraph proper 中并进行优化。计划是我们将尝试分析,如果可行,然后花时间来改善分析。每份分析报告都将被定期审查和更新。更新可以通过更好的数据结构和数据移动,或者通过替换算法。该团队不断监测研究和最新技术。和以前一样,用户看到的只是更好的性能和/或可扩展性。

除了为 cuGraph 开发人员提供一个游戏区,用户还可以创建自定义分析。为了帮助促进算法开发,cuGraph 将提供一个原语集合。这些原语可以是现有的图形分析或低级功能。目标是最终将所有 graphBLAS 半环函数公开为图形原语。在 0.9 版本中,最初的原型分析之一是使用向前向后修剪方法计算强连通分量的例子。FW-BW-TRIM 执行向前的 BFS,然后向后的 BFS,然后寻找两者之间的公共集(交集)以形成一个组件。由于 BFS 算法已经是 cuGraph 的一部分,用于查找组件的原型分析在下面的代码片段中突出显示。

Prototype of Forward-Backward-Trim Strongly Connected Components

使用原语是构建定制分析的一种方法,另一种是通过使用数据帧和批量同步并行(BSP)编程模型。BSP [13,14]并不新鲜,它是由莱斯利·瓦里安开发的,并于 1990 年首次发表。这与 Pregel 在关系数据库中用于图形处理的基本模型相同。该过程包括设置一个值,例如每个顶点一个值,然后在所谓的“超步骤”中传播该值然后,以用户定义的方式聚集比例值,并将其指定给相关顶点。BSP 的优势在于它易于创建自定义分析,允许传播复杂的多列数据,并允许定义自定义聚合函数。缺点是速度慢。

Simplified BSP Example Looking just at Vertex 4

升级到 1.0 版本

急流 cuGraph 正在快速移动,并沿着多条路径运行。是的,我们打碎了东西。升级到 1.0 版意味着我们有了稳定的基础和不变的 API。我们还没有到达那里,但是我们正在接近那里。随着更多的技术进入 cuGraph,这些特性和原语是如何暴露的还没有完全具体化。此外,我们的目标不是拥有多个独立的基于技术的子路径,而是一个统一的视图。在 API 层之下,算法可以在不同的技术之间转换。为了帮助 cuGraph 更接近目标,该团队将推出一个完整的版本 0.11,专注于代码重构、组织和 API 更新。希望一个发布周期就足以重构代码,这样我们就有了一个坚实的基础来升级到 1.0 版本。

路线图总是不断变化的,所以把它当作一组目标,而不是硬性的截止日期:

发布 0.9

  • 多 GPU PageRank
  • 单 GPU 强连接组件

发布 0.10

  • 大黄蜂集成
    —卡茨中心性
    — K 核
  • Gunrock integrated
    —子图匹配【15】
  • GraphBLAS 集成
    — K 形桁架
  • nvGRAPH
  • 附加原语
  • 基础工程

发布 0.11

  • 我们正在进行一个发布周期,专注于一个主要的代码重构,以便所有的 API 都保持一致并更新到 C++。这将使我们为 1.0 版本做好准备。

发布 0.12

  • OpenCypher —简单查询
  • GraphBLAS 半环原语

未来版本…

哪个版本将是 1.0 版,目前还不知道,但 cuGraph 将准备就绪。

结论

RAPIDS cuGraph 专注于创建统一的图形分析功能,能够扩展到不同规模的问题,并根据分析需求利用不同的数据结构,同时提供数据科学家熟悉的易于使用的 API。我们当前的 1.0 版本路线图旨在为该功能奠定坚实的基础,我们打算在 1.0 版本之外进一步推进这一愿景。

如果你喜欢 cuGraph 正在做的工作,请在 GitHub 上给我们一颗星:https://github.com/rapidsai/cugraph

如果有什么你认为 cuGraph 应该继续努力的,那么就添加一个问题:https://github.com/rapidsai/cugraph/issues或者在谷歌讨论页面上开始讨论:https://groups.google.com/forum/#!forum/rapidsai

因为 RAPIDS 都是开源的,所以请跳进去写一些代码。

参考文献

  1. https://medium . com/rapids-ai/rapids-release-0-8-same-community-new-freedom-9 f 82 b 09 db 3 ad
  2. RDF*和属性图的协调。技术。众议员,http://arxiv.org/abs/1409.3288(2014)
  3. 罗德里格斯,硕士,纽鲍尔,p:从点和线的建设。Bul。我是。社会主义者信息。Sci。技术。36(6), 35–41 (2010)
  4. 伦佐的安格斯。"属性图数据库模型."AMW (2018 年)。
  5. https://arrow.apache.org/
  6. 田,y .,巴尔明,a .,科尔斯顿,S. A .,塔蒂孔达,s .,,麦克弗森,J. (2013)。从像顶点一样思考到像图形一样思考。VLDB 基金会会议录,7(3),193–204。
  7. Bader,d .,Bulu,a .,Gilbert,j .,Gonzalez,j .,Kepner,j .,& Mattson,T. (2014 年 7 月)。图爆破工作及其对亿亿级的影响。在 SIAM exa scale 应用数学挑战与机遇研讨会上 (EX14)
  8. https://news . developer . NVIDIA . com/graph-technology-leaders-combine-forces-to-advance-graph-analytics/
  9. http://faculty.cse.tamu.edu/davis/GraphBLAS.html
  10. https://gun rock . github . io
  11. https://github.com/hornet-gt/hornet
  12. https://developer.nvidia.com/nvgraph
  13. Leslie G. Valiant,并行计算的桥接模型,美国计算机学会通讯,33 卷 8 期,1990 年 8 月
  14. 麦科尔,W. F. (1994)。可扩展并行计算:一个宏大的统一理论及其实践发展。《IFIP 世界大会议事录》(第一卷,第 539-546 页)
  15. http://www . hpdc . org/2016/Posters/poster/O13-hpdc 16 _ Posters _ paper _ 17 . pdf

4 种很少教授的数据科学技能,这是你应该学习的

原文:https://towardsdatascience.com/rarely-taught-data-science-skills-that-you-should-look-to-acquire-ebb1a09520e4?source=collection_archive---------25-----------------------

什么是难以获得的数据科学技能,为什么你应该寻求获得它们

数据科学家短缺,随之而来的需求是培养越来越多的数据科学家。这越来越多地发生在课堂上,但很大一部分实践数据科学家仍然是自学的(在最近的 Kaggle 研究中,超过 1/4)。终身学习也很重要,无论你是受过正式培训的数据科学家还是自学,你都将继续学习,并将依靠 MOOC、教科书和其他自学的组合来完成。

因此,随着所有这些学习的发生,为了未来和现在的数据科学家的利益,有哪些专业技能是知道起来很重要但很难教授的?现实生活中的数据和理论上最大的差距在哪里?这里有 4 个领域不太可能被熟练地教授,但却是您在工作中取得数据科学成果的成功和能力的关键部分。

获取和清理数据

我向你保证一件事。在现实世界中开始一项数据科学实践,并不需要点击一个链接,下载一个 CSV 文件,然后继续你的快乐之路。这比要复杂得多(也耗时得多)

首先,您很可能需要找到您想要使用的数据源,并开始将数据拼接在一起,以形成类似于您希望使用的东西,然后进行广泛的练习,以确保数据是干净的和可用的。与此同时,您将会理解那些可能被用来创建您并不立即熟悉的特性的业务规则,以确保您正确地使用它们。除此之外,你可能想做的任何特征工程、插补和进一步的附加动作,很可能你已经花费了整个项目相当多的时间,只是在做准备。

要做到这一点,需要商业、技术和软技能的结合,还需要一点想象力,这些技能很难教授。绝对不要低估你将要做的数据准备和来源工作——以及在这方面的出色表现是如何帮助你完成剩下的工作的。

管理工作流程

为了大多数教学指南的完整性,使用一种编程语言或工具解释数据科学过程,不偏离所述工具。这给人的印象是,所有事情都可以而且应该在一个工具内完成。这当然是可能的,但不太可能有效。

为了提高效率,在数据科学过程的各个阶段,您很可能会从一个工具跳到另一个工具。你将在一个独立的工具中做你的 EDA,这个工具不同于你准备数据的工具,也可能不同于你用于可视化的工具。了解哪些工具适合您和您的组织,以便在最短的时间内实现您想要的最终结果,这是数据科学中的基本技能之一,但很少有人教授。不依赖工具,专注于快速操作,重点是实现可操作的结果。

讲故事和用数据来影响

尽管一些课程涉及一些基本的可视化技术,但很少有人真正谈到如何将数据科学成果与业务成果联系起来,以及如何有效地与非技术受众沟通,尽管这经常被认为是一项关键的数据科学技能。

你如何向不关心损失矩阵、置信区间等的观众传达你创造的结果?本质上,这是学习“软”沟通技巧和学习如何通过有效的演示技巧(以及有效的利益相关者管理)来演示和影响决策者的结合。

我会在后面的文章中详细讨论这个问题,但是我会说两件你可以马上做的事情,让你在这个领域变得更加有效。

学习如何进行财务预测,以确定你的模型所产生的洞察力的未来价值-

学习如何对你产生的任何见解进行财务预测,然后以此为手段对这些见解进行优先排序——这是一个非常有效但很少使用的工具。在展示之前,对你所做的工作进行估价——直接与你的商业利益相关者沟通——直接说出商业决策的语言。

如果你对使用商业预测模型感到不舒服,至少联系你组织内的商业团队成员,让他们模拟出实施你产生的任何可操作的见解对业务的价值。

例如,如果您正在为您的营销团队部署一个算法归因模型,该模型允许他们脱离最后一次点击/线性/或首次点击归因模型,请尝试找出这在 ROI 提升方面可能带来的价值,通过与以前的方法相比,为您的团队做出更好的预算分配决策。或者,部署的 NLP 模型能让您的员工团队在执行机械任务时节省多少时间?那这段时间又转化成了什么价值呢?

这并不容易,它需要不时地做出有根据的假设,然而,即使是预测值的“背面”草图,也比什么都没有好,并且在弥合数据和商业团队之间的差距方面大有帮助。

利用建筑来讲述故事。

讲述你所承担的过程背后的故事将有助于你的利益相关者理解和欣赏你的工作。这应该在宏观(“我有这个问题,我想用这个数据集来解决,我使用的方法是这样的,这使我能够实现这些结果……”)以及微观层面上完成。

在微观(洞察力)层面,使用构建可能是有效的。构建本质上是构建一个故事来传达单个数据洞察的信息,通常是通过对同一个图形/视图进行小的渐进调用来完成的。

假设您做了一个(客户)聚类练习。你的第一张幻灯片可以是你必须开始的所有数据点的散点图。第二个是在第一个基础上的可视化构建,显示已确定的关键集群。然后,您可能会有几张幻灯片放大到每个集群并查看每个集群的特征,然后在一个可视化(而不是图形化)视图中显示所有结果,在此视图中,您可能会进一步将您已经确定的集群人性化(比如给它们一个角色)。

利用构建,本质上允许你逐步揭示信息,并围绕你的见解编织一个故事,引导你的观众得出结论,而不仅仅是将数据堆砌在上面。

简而言之,洞察力层面的故事将会是这样的:“我有这些数据,我能够发现这些数据,因为这些数据是相关的,并且可以通过这样做来采取行动……”

良好的文档是良好团队合作的关键

问问你自己。你如何记录工作,如何使你的工作容易被未来的团队成员复制?你如何捕捉你的学习,以便它们可以被缩放并用作未来分析的基础?

你很可能会作为团队的一员工作,所以要成为最终的团队成员,通过好的文档让人们的(工作)生活更容易。
即使在几个月前,它也不会出现在我的列表中,但我认为它对数据科学家越来越重要。原因?有效性。

如果我要说什么的话,那就是数据科学家会选择阻力最小的有效途径。那么,拥有好的文档如何让你更有效率呢?

良好的文档使您能够

  • 向技术受众清楚地传达您的信息和方法(从而最大限度地减少理解方法和结果所花费的时间),允许交叉协作和快速提升技能。我上面提到的宏观讲故事——但是直接对你的同事和直接的团队成员讲
  • 潜在地使代码(或部分代码)可被那些希望采用类似方法或使用类似数据集的人重用。例如,如果您已经在第一时间清楚地记录了数据,为什么还要清理两次呢?
  • 向上管理。有喜欢关注细节的经理吗?通过组织你的想法和记录你的方法,让他们的工作更容易,节省你和他们的时间。

我在这里提倡的文档不仅仅是注释代码。本质上,你想要展示你所承担的过程和你所取得的结果。这里的愿景是,你将使用 Jupyter 笔记本或 R Markdown 来追溯描述你采取的步骤和你使用的方法。追溯是关键,因为当你在工作时,你在快速优化结果。这需要回顾和反思你所取得的成就,并为了他人的利益而记录下来。

在这样的文档中,会有直接从您的工作环境中提取的代码片段(包括已经注释的代码),现在您只需添加富文本元素来添加进一步的上下文。这种文件至少应包括:

  • 介绍
  • 问题的描述
  • 数据集的描述
  • 您使用的方法:
  • 准备数据的方法
  • 为获得结果而采取的机器学习/统计分析方法
  • 结果呢
  • 基于结果的建议

一旦你有了文档,它的读者是你团队中的其他技术人员,他们可能希望复制结果,从他们那里学习,或者利用他们做类似的事情。把它归档,加入你的文件夹。

结论

因此,如果你还在上大学,或者正在学习新技能以补充现有技能,请留意这些技能是如何获得的,在你的同龄人圈子中谁做得好,并开始模仿他们的行为,同时尝试你自己的各种技能,并将它们融入你自己的技能组合中。并非每项数据科学技能都可以教授,通常那些难以获得的技能会产生很大影响。

这个故事最初发表在这里

老鼠城:可视化纽约市的老鼠问题

原文:https://towardsdatascience.com/rat-city-visualizing-new-york-citys-rat-problem-f7aabd6900b2?source=collection_archive---------3-----------------------

你的邻居也是老鼠的热点吗?

Check out the interactive rat sighting map here: https://nbviewer.jupyter.org/github/lksfr/rats_nyc/blob/master/rats_for_nbviewer_only.ipynb

介绍

如果你曾经在纽约待过很长时间,你很可能会遇到老鼠。不管你是在等地铁还是在华盛顿广场公园散步,你碰到老鼠的几率都很大。如果你来自纽约,这些对你来说都不陌生。为了让其他人更好地理解这个问题有多严重,这里只是收集了一些快速的事实:

  • 有一篇维基百科文章详细介绍了这个问题。你所在的城市有没有关于老鼠的维基百科文章?
  • 根据这篇文章用统计方法捕捉的老鼠数量,纽约市大约有 200 万只老鼠。
  • 纽约市鼓励市民在看到老鼠时拨打 311。该市非紧急热线对老鼠的重视表明了这个问题的重要性。

众所周知,老鼠会传播致命疾病,因此对公众健康构成了严重威胁。除此之外,他们也是众所周知的负责电缆断裂,可能会导致火灾。因此,如果你住在纽约市,你肯定会想避开老鼠密集的街区甚至更小的区域。与此相反,纽约市最有可能希望在这些特定区域加大灭杀力度。问题是:你如何识别这些区域?

鼠迹的发展

在回答这个问题之前,让我们来看看这个问题在过去几年的历史。对于这篇文章,我依赖于纽约市提供的这个数据集,详细列出了从 2010 年 1 月到 2017 年 9 月的所有老鼠目击事件。在这段时间里,有 101,914 起报告的老鼠目击事件。虽然这已经是一个很高的数字,但实际看到老鼠的数量可能要高得多。仅在纽约期间,我就目睹了几次我没有报告的老鼠目击事件。然而,我们可以看看这些年来老鼠出现的数量的发展,看看这个城市消灭老鼠的努力是否有成效。

正如我们所看到的,2013 年,老鼠的数量有了转机,开始显著增加。2010 年有 10,452 起老鼠目击事件,而 2017 年有 17,080 起。这大约增加了 63%!尽管 2017 年似乎有所下降,但人们必须记住,2017 年的数据集截至 9 月,不包括 10 月、11 月和 12 月。数据似乎表明,老鼠数量增加了,或者老鼠进入了它们能够更频繁地与人类接触的区域。不管怎样,这都是一个令人担忧的发展。

让我们按社区来分析一下,看看在纽约市哪个地区老鼠最多。

显然,至少自 2010 年以来,布鲁克林一直是老鼠出没最多的地区。注:这里的纽约是指曼哈顿。另外,对于没有去过纽约的人来说:牙买加不是指加勒比海的牙买加岛,而是指牙买加皇后区。

在跳到我们的地图可视化之前,了解更多关于目击地点类型的信息也是很有趣的。大多数老鼠可能只在有很多机会隐藏和很少人类活动的地方被发现,例如建筑工地。对吗?不对。看一看:

大多数老鼠目击报告发生在 3+家庭公寓大楼。建筑工地在这份名单上仅排在第七位。另一个有趣而可怕的统计数据是,在大约 7 年的时间里,有 82 起医院里发现老鼠的报告。

地图可视化

对于我的热图可视化,我依赖于 2017 年报告的老鼠目击事件,因为这些是该地区潜在老鼠活动的最新指标。

曼哈顿下城

为了可视化鼠迹的密度,我使用 Python 包 follow 在传单地图上创建了热图。在曼哈顿下城看一看,似乎有一些老鼠热点,尤其是在东 2 街至东 6 街和 B 大道至 d 大道的区域。总体而言,汤普金斯广场公园周围的区域显示出非常高的老鼠目击密度。

市中心区

总的来说,市中心似乎没有曼哈顿下城那么拥挤。这里的热点包括 23 街和 28 街之间的区域以及地狱厨房的某些部分。

上东区和上西区

在这里,上西区似乎明显比上东区鼠患更严重。具体来说,100 号街以上和哥伦比亚大学以东的区域显示出高密度的鼠迹。

哈莱姆

除了西 133 街和 142 街之间的 Adam Clayton Powell Jr .林荫大道周围的区域,哈莱姆区一般不会出现具体的鼠迹。

布朗克斯区

布朗克斯区的老鼠出没密度相对较高。有趣的是,在布朗克斯区的西部似乎比东部更容易看到老鼠。

布鲁克林区

虽然在布鲁克林高地和威廉斯堡看到的老鼠相对较少,但特别是贝德福德-斯图文森和皇冠高地的部分地区似乎是大量老鼠的家园。

昆斯区

皇后区也没有显示出非常具体的模式。然而,如之前柱状图所示,老鼠密度最高的地区是牙买加。

结论和更详细的探索

如你所见,老鼠是纽约市的一个大问题。了解大量人口在哪里是试图减少他们的数量和降低他们造成的公共健康风险的第一步。

如果你有兴趣了解你自己的街道或你下次来纽约时要住的酒店所在的区域,请点击这里。我在 nbviewer 上托管了一个笔记本,可以让你交互使用热图。

参考资料:

[1]奥尔巴奇,乔纳森,纽约市的老鼠真的和人一样多吗? (2014),威利在线图书馆

[2]纽约市,纽约市老鼠目击事件 (2017),卡格尔

[3]布拉德利,瑞安,纽约的老鼠路径;城市里的动物如何到达它们要去的地方。 (2015),纽约时报杂志

[4] Frye,M. J .等人,纽约市挪威鼠体外寄生虫和相关病原体的初步调查,《医学昆虫学杂志》

根据“酒吧分数”对伦敦房产进行评级:伦敦房产市场的另一个视角

原文:https://towardsdatascience.com/rating-london-properties-by-their-pub-score-an-alternative-lens-on-the-london-housing-market-ed5524304014?source=collection_archive---------7-----------------------

我想很快买栋房子。

这是这个项目的亮点。我开始在各种房地产网站上寻找,虽然网站上的信息很棒,但我觉得如果我能掌握用于填充这些网站的数据,我就能以一种更数据驱动的方式来寻找房子。

本文共分五个部分:

  1. 获取住房数据
  2. 电子设计自动化(Electronic Design Automation)
  3. 可视化数据
  4. 在地图上绘制数据
  5. 计算有趣的指标,比如从每个房子工作的时间,以及每个房子的酒吧分数

出于各种原因,在整篇文章中,我不打算命名我想从中获取数据的站点,所以我将它称为“站点”。

步骤 1:获取并清理数据

这将是一项网络搜集工作,看起来绝不容易。由于网站的结构,每次您进行属性搜索时,您被限制在每页 25 个属性。更重要的是,如果你的搜索区域太大,你可以选择的页面数量被限制在 42 个(这在类似的项目中出现过几次——如果有人知道为什么,我会很感兴趣!)

有趣的事实——数字 42 是“生命的意义是什么”这个问题的著名答案在银河系漫游指南中。但这是为什么呢?有趣的是(或者不是),数字 42 有 ASCII 码*,在编程中是“全部”或“一切”的意思。

因此,我最初只限于在一个区域内寻找房产——Bermondsey。我想利用我的 LISA,所以房产的价值必须小于 450,000,这将我的搜索范围缩小到一个不错的数量。

一个简单而有效的组合,美丽的汤和请求,我有一个在我的搜索标准内的每个属性的链接列表。然后我遍历链接列表,再次使用 Beautiful Soup 和 Requests 来解析来自所述链接的信息。为了不给网站带来太多压力,我在每次请求之间留出了 5 秒钟的延迟。获取价格的简单代码如下所示:

def get_soup(url, params=None):
    r = requests.get(url, params=params)
    c = r.content    
    soup = BeautifulSoup(c, 'html.parser')
    return(soup)descriptions = []for index, row in listing_df.iterrows():
    url = row['property_link']
    time.sleep(5)
    soup = get_soup(url)
    price.append(soup.find('div', attrs={'class':'propertyHeaderPrice'})

这太棒了,非常有用——我可以获得详细信息,如添加的日期、房间数量、物业类型、价格、最近的车站等。

将它保存为一个 csv 文件/到一个数据库中,将这个脚本放到一个调度器中,你就可以开始了。

然而,我不满足于只获得伦敦某个特定地区的数据,哦,不。我想要所有的数据,主要是为了在一段时间内获得某种伦敦平均房地产价格跟踪器,以及比较整个伦敦的各种指标。

问题是双重的:

  • 我不能简单地搜索整个伦敦,因为这将产生太多的结果来迭代,我将无法获得超过 42 页的价值
  • 我不想逐一查看伦敦的每一处房产。网站上列出了“伦敦”某个区域内大约 25,000 处房产,我不想通过提交 25,000 个 get 请求就让他们的网站瘫痪。

我开始思考如何将搜索过程分解成更小的块,以便能够在不到 42 页的页面中查看每个块的所有属性。我最初的想法是行政区,尽管已经运行了一个脚本来获取每个行政区的属性数量,但是相当多的行政区有太多的属性。

然后我查看了地区,所以您的邮政编码的第一个字母在空格前,例如 SE8、EC2V、E1 等。原来只有 CR0(克罗伊登中心)的房产太多了,所以我觉得这是可以接受的(不确定我是不是反正要住在克罗伊登……)。

第二个问题是提交 25,000 个请求,所以我试着从一次显示 25 个属性的摘要页面中获取尽可能多的每个属性的关键信息。如果成功,这将把请求的数量减少到 1000 左右。

大多数关键信息都在那里,除了经度和纬度。幸运的是,该网站有一个“查看地图”功能,我认为必须有坐标,以准确地绘制每个属性。这个 map 视图一次允许 500 个属性,这不成问题(除了 Croydon ),而且在页面源代码的某个地方包含了机器可读的格式。这意味着,对于每个地区,我所要做的就是遍历结果的每一页以获得大部分细节,然后稍微更改 URL 以访问地图源代码,在 Beautiful Soup 和 JSON 的一点帮助下,我可以从中解析坐标。

幸运的是,每个属性都有一个唯一的标识符,所以两个数据集很容易匹配。

但是克罗伊登呢。虽然不确定我是否想住在克罗伊登,但我内心的完美主义者想要一个完整的数据集。结果发现只有不到 42 页,所以获取大部分数据相对简单。然而,地图上一次只允许显示 500 个属性,这就产生了一个问题。幸运的是,在放大/缩小时检查了 url,我意识到我可以在请求地图 url 时使用 viewport 参数,有效地将 Croydon 一分为二。经过大量的工程设计后,克罗伊登又重操旧业。

在调度器上完成这个任务后,我所要做的就是等待(这个过程总共运行了大约 1 小时 15 分钟)。

第二步:EDA

获得并清理数据后,它看起来像这样:

这一切都很好,但如果你像我一样,你是一个视觉型的人,所以我决定制作一些图表。

第三步:最初的观想

Matplotlib

一旦你掌握了它的窍门,Matplotlib 就非常棒,可以合理有效地用来制作一些基本的图表,例如:

  • 直方图

  • 条形图

  • 折线图

查看这些图表,有一些有趣的地方,例如在我的搜索范围内,伦敦的两张床的房产比任何其他大小的房产都多,而且似乎有一些围绕房产价格整数的聚类。

再做一点工作,你就可以画出每个地区每个房间大小的房屋数量/百分比:

我想了解的事情之一是每种房屋类型的价格如何变化,如套房、公寓、联排别墅等。在绘制该图时,似乎有相当多的房屋类别:

这需要我构建一个映射函数来映射到父属性类型。我拥有的财产类型有:

property_types_to_match = ['apartment',
 'barn conversion',
 'block of apartments',
 'chalet',
 'character property',
 'cluster house',
 'coach house',
 'cottage',
 'detached house',
 'duplex',
 'end of terrace house',
 'flat',
 'ground floor flat',
 'ground maisonette',
 'house',
 'link detached house',
 'maisonette',
 'manor house',
 'mews house',
 'penthouse',
 'property',
 'semi-detached house',
 'terraced house',
 'town house']

我决定我想匹配的是:

['apartment',
 'duplex', 
 'house',
 'maisonette',
 'other']

首先,我很好奇在我的价格范围内有没有“庄园”或“小木屋”。第二,幸运的是,pandas 有一个方便的“map”函数,我将一个属性类型字典放入其中,以映射父属性值。按母公司分组,并绘制价格和数量图,我们可以看到,套房是最便宜的房屋类型,而“其他”类别是最贵的。这里出售的公寓也比伦敦其他任何类型的房产都多:

这些类型的图表非常适合显示一些高级趋势,但我想看看是否有更好的方式来呈现数据。

我的下一个想法?

人人都爱地图

第四步:地图

输入 leav 和 geopandas。每个在映射数据中有不同的位置:

  • Folium 使您能够创建基于缩放级别进行聚类/去聚类的交互式地图
  • Geopandas 允许您按地理区域绘制数据框中的数据

我们先来看看叶子:

不可否认,安装叶子有点麻烦,但绝对值得。安装完成后,使用下面的三行代码导入它的一些特性:

import folium
from folium.plugins import MarkerCluster
from folium.plugins import FastMarkerCluster

从这里开始,创建地图非常简单,因为您有一个带坐标的数据框架:

# simple marker map
london_map = folium.Map(location=[51.4986, -0.0691],
                    zoom_start = 10)
for index, row in london_df.iterrows():
    folium.Marker([row['latitude'], row['longitude']], popup=row['address'])).add_to(london_map)# standard cluster map
london_cluster_map = folium.Map(location=[51.4986, -0.0691],
                    zoom_start = 10)
london_cluster_map.add_child(MarkerCluster(london_df[['latitude','longitude']].values.tolist()))# fast cluster map
london_fast_cluster_map = folium.Map(location=[51.4986, -0.0691],
                    zoom_start = 10)
london_fast_cluster_map.add_child(FastMarkerCluster(london_df[['latitude','longitude']].values.tolist()))

简单的标记图只是在每个属性位置绘制一个标记,而标准和快速聚类图引入了某种按位置的聚类。区别在于功能——标准聚类图允许您包含弹出窗口等。而快速聚类图不会。话虽如此,对于超过 25,000 个点,标准聚类图的绘制时间太长,所以我选择了快速聚类图,对于伦敦,它看起来有点像这样:

不幸的是,我不知道如何将交互式地图嵌入到媒体文章中,所以静态图像就可以了。放大后,看起来像这样:

你必须承认,如果你像我一样是一个数据呆子,这很酷。任何形式的交互都让我着迷——也许这就是我在编码生涯开始时对 Excel 感兴趣的原因。

好了,现在我们来看一下地质公园

为了充分利用 geopandas 包,我需要获得伦敦各区的形状文件。幸运的是,来自英国伦敦政府数据网站的数据(https://data . London . gov . uk/dataset/statistical-GIS-boundary-files-London)和其他各种开放数据集的组合使这一数据很容易获得。

同样,奇怪的是,安装 geopandas 有点痛苦,但一旦完成,只需导入它并读入您的形状文件:

import geopandas as gpddistrict_shape_file = 'london_postal_districts.shp'
map_df = gpd.read_file(district_shape_file)

这将为您提供一个标准的熊猫数据框架,但会识别形状文件中的几何图形,并为您提供如下内容:

我们需要做的下一件事是与您的其他数据集的按地区分组版本相结合,下面是一个示例:

map_df = map_df.set_index('postdist')mean_district_price = london_df.groupby('district')['price'].mean()
mean_district_price_df = pd.DataFrame(mean_district_price)
mean_district_price_df = mean_district_price_df.reindex(district_list, fill_value=mean_district_price_df['price'].max())map_df = pd.concat([map_df, mean_district_price_df], axis=1)

太好了,我们准备好开始策划了。如果您简单地使用下面的' map_df.plot()',您将得到这些地区的轮廓,这是令人放心的:

fig, ax = plt.subplots(figsize=(16,9))map_df.plot(ax=ax)
ax.set(title='districts')plt.show()

绘制每个区的房产数量告诉我们与 matplotlib 图表中的数据相同的信息——克罗伊登比其他任何区都有更多的房产:

这本身并不是一个非常有趣的情节。

在我看来,有趣的情节是:

  • 每个区的平均房价,这告诉我,在这个城市或里士满的任何地方,我都买不起:

  • 挂牌出售的房产数量与各区内的房产总数之比,显示了各区内的住宅房产开发水平:

酷,现在我有了一些很酷的图表和地图,接下来呢…

当我评估一所房子是否在一个好的位置的时候,我寻找什么其他的东西?

第五步:用更多的数据重复

交通联系。

太好了,到 TFL 网站,那里有一个文件包含网络上所有电台的纬度/经度。接下来,我想尝试找到离我的数据集中的每个属性最近的三个站点,以及它们离属性的距离。

首先,我看了看距离:

由于地球的曲率,我不得不使用哈弗辛公式(【https://en.wikipedia.org/wiki/Haversine_formula】)来计算两组坐标之间的实际距离。

这在 python 中的快速实现如下所示:

def haversine(lon1, lat1, lon2, lat2):
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 3956 # Radius of earth in miles= 3956\. kilometers = 6371
    return c * r

现在,对于下一点,我知道有一种更快、更有效的方法来计算最近的 3 个站,但我不太清楚,所以我有效地在站和属性之间做了一个相当大的交叉连接:

no_properties ~ 25000
no_stations ~ 400
no_calculations = 400 * 25000 = 10,000,000

这就是 1000 万次计算,在我的机器上大约需要 12-13 分钟才能完成。如果有人有更有效的计算方法,请告诉我!

无论如何,在计算了到每个站点的距离后,我取了 3 个最小值,瞧,你得到了到三个最近站点的距离。

为了扩充这个数据集,我还使用 Google Distance Matrix API 来获取每个酒店的上下班出行时间。Google 让你免费拥有一定额度的积分,太棒了!对 API 的请求如下所示:

coords = list(zip(london_df['listing_id'],london_df['latitude'].tolist(),london_df['longitude'].tolist()))
responses = []
for id, lat, long in coords:
    url = '[https://maps.googleapis.com/maps/api/distancematrix/json'](https://maps.googleapis.com/maps/api/distancematrix/json')
    params = {'units':'imperial',
              'origins':str(lat) + ',' + str(long),
              'destinations':work_lat,work_long,
              'mode':'transit',
              'arrival_time':epoch_time,
              'key':google_routes_API_key}
    r = requests.get(url, params=params)
    response_json = r.json()
    responses.append(response_json)
responses_dict = dict(zip(london_df['listing_id'].tolist(),responses))

好的,传输指标达到。接下来呢?

酒馆。

每个人都喜欢好的酒吧,特别是当它有很好的啤酒/葡萄酒可供选择时,当它近到足以让你蹒跚而归,但又足够远到当你想睡觉时不会让你睡不着。

我偶然发现了整个英国的 POI 数据集,其中包含了英国几乎所有景点的纬度和经度,包括酒吧、文具店、电影院等。这是一座金矿,所以我仔细检查并提取了“酒吧/餐馆”类别中的所有兴趣点。我知道这包括餐馆,这有点令人沮丧,因为我真的不在乎我是否离芥末/nandos 那么近。但也只能这样了。

幸运的是,和 lat/long 一样,数据集也包含邮政编码,所以我接着检查并找到了包含在我有数据的地区内的所有酒吧(总共 298 家)。这相当于 1400 家酒吧。

对于每个酒吧,我想找到一个衡量“酒吧有多好”的标准——重新输入谷歌。谷歌有一个“地点”API,允许你输入世界上任何一个地方的名称/地址,它会尝试返回它在极其庞大的谷歌地图数据库中拥有的关于所述地方的各种数据。该查询如下所示:

不幸的是,我的数据集在不同的列中有一些缺失的/NaN 值,所以需要进行一些清理。例如,如果酒吧在 name 列中有一个 NaN 值,我就用母公司的名称来替换它,比如' Wetherspoons '或' O 'Neils '等。然后,我通过 places API 运行这些酒吧,并能够获得我的数据集中 99%的酒吧的各种指标,其中最重要的是平均评论评级、评论数量和价格水平。

我决定需要计算三个测量值来获得每栋房子的“酒吧分数”。这些是:

  • 附近酒吧的质量
  • 邻近的酒吧
  • 附近酒吧的数量

我还决定查看每所房子 1 英里内的酒吧,因此再次使用哈弗辛公式在酒吧和房子之间进行了相当大的交叉连接,以获得距离。然后,我只将每家酒店 1 英里范围内的酒吧作为单独的数据集,从中获取每家酒店的酒吧指标。

酒馆质量评分。

这只是简单地计算出每家 1 英里范围内酒吧的谷歌评分平均值。然后对所有酒店进行标准化,这样,靠近最低评级酒吧的酒店得分为 0,靠近最高评级酒吧的酒店得分为 1

酒吧接近度得分。

这有点棘手。我认为 300 米是远离酒吧的最佳距离,因为它在磕磕绊绊的距离内,但应该足够远,不会听到任何深夜噪音。为了计算分数,我从每个距离测量中取 300 米,因此如果一个酒馆在 300 米之外,它将得到 0 分。然后我取了这个值的模,确保 300 米内的所有酒吧和更远的酒吧受到相同的惩罚。然后对每栋房子 1 英里范围内的酒吧进行平均,并对我的数据集中的所有酒店进行标准化。

酒馆数量评分。

这可以简单地计算为每栋房子 1 英里内的酒吧数量,并根据数据集中的所有属性进行归一化。

酒吧总分。

为了将这些计算出来的指标汇总成一个“pub 分数”,我必须考虑哪个值对我来说最重要。靠近一家评级最高的酒吧比靠近 5 家评级很差的酒吧好吗?我假设是的。

因此,我决定重要性的顺序是质量,接近度,数量。

为了计算得分,我使用了 2 个质量权重、1 个接近度权重和 0.5 个数量权重,并将它们汇总如下:

(2 倍标准化质量)+ (0.5 倍标准化数量)——(标准化接近度)

出于兴趣,我还使用了 rank 函数,这样我就可以根据 pub 分数查看数据集中排名最高和最低的属性。

为了将这些数据可视化,我将它们全部转储到一个 geopandas 数据框架中,并使用了方便的 shapely 函数" point" ",该函数将经纬度坐标转换为实际的可绘图点。我还决定要根据总分的值改变颜色,所以我使用了 matplotlib.colors 中非常方便的 LinearSegmentedColormap 函数和“plot”函数的“cmap”参数。好了,描述它没有用,下面是代码:

由此产生了以下情节:

当与先前导入的地区地图文件结合使用时。这表明,Streatham/Dulwich/Croydon 周围的地区是购买房产的最佳地点,如果你只关心酒吧的话…

我还绘制了数据集中一些地区的分布图,这些分布图显示,中央克罗伊登的房产得分差异很大,而诺丁山(W2)等地的房产得分似乎更高。这里,n 对应于数据集中每个区内的房产数量:

下一步:

  • 研究如何更有效地找到最近的“x”点
  • 查看学校/集水区的数据,以及这些数据与价格的关系
  • 研究用 python 绘制旅行时间等值线——任何想法都很好!

希望你觉得这很有趣!

给运动队评分——Elo 与输赢

原文:https://towardsdatascience.com/rating-sports-teams-elo-vs-win-loss-d46ee57c1314?source=collection_archive---------7-----------------------

Photo by Ariel Besagar on Unsplash

哪个更好?

介绍

在任何一项运动中,有许多方法可以决定谁是最好的团队或运动员。可以看看最近 5 场。最近 10 场比赛。你可以使用分数差。您可以根据哪些团队“感觉”最好来对他们进行评级。你可以看看花名册,看看哪个队有汤姆·布拉迪或詹姆斯。无论是权力排名,部门排名,还是其他什么——有科学的方法来评估团队,也有不科学的方法。以下是科学地决定一个好的分级系统的尝试。

什么是 Elo 评级?

首先,我觉得我打不过 538 对 Elo 的透彻描述。维基百科的页面也挤满了有用的信息。不过,我会简单介绍一下。

Elo 评级系统是一个非常简单却非常有效的评级系统。它最初是为国际象棋开发的,但没有什么是国际象棋特有的。Elo,以其原始形式,可以用于任何面对面的游戏。掰手腕、拼字游戏、乒乓球,应有尽有。人们也可以把团队,比如篮球队,看作是互相对抗的“玩家”。

每个玩家或团队都有自己的 Elo 等级。惯例是新玩家从 1500 分开始,但是 1500 分有点武断。当两名玩家玩游戏时,他们会在游戏开始前自动“下注”他们的 Elo 点数。这个赌注的大小被称为 K 值。胜者在比赛结束后获得分数,败者在比赛结束后失去分数。奖励的点数取决于初始评分的相对差异。举例来说,如果一个 1700 技能的玩家击败了一个 1300 技能的玩家,没有多少点数被奖励——这个结果是意料之中的。另一方面,如果 1300 级玩家击败 1700 级玩家,则几乎整个下注点数池都被奖励给 1300 级玩家,并从 1700 级玩家中扣除。

K 值或下注点数取决于游戏。在像棒球这样的运动中,K 值会很小。即使是最好的棒球队也很难赢得超过 70%的比赛。此外,他们在 MLB 打了 162 场比赛。所以,如果 MLB 最好的球队连续输了三场比赛,这可能没什么大不了的,他们仍然可能是联盟中最好的球队。你不想要一个大的 K 值,否则 Elo 评级会对连败反应过度。然而,在 NFL 或大学篮球赛中,最好的球队有望赢得 80%以上的比赛。在 NFL,也有一个小样本量。在这种情况下,允许更不稳定的 Elo 评级是可取的——一个 3 连败的球队可能不是联盟中最好的球队。此外,在短暂的一季中,您希望收视率快速调整。

如果我们对预测比赛结果感兴趣,Elo 评级是强有力的预测工具。它们甚至比输赢记录更有预测性,接近预测市场。这是假设你有一个好的 K 值。一旦你对 Elo 评级有所了解,你就能猜出好的 K 值。这篇文章的目的是给你一个达到最佳状态的科学方法。

一项实验

我声称 Elo 分数比输赢记录更能描述一个球员或球队的技术。我们不要认为这是理所当然的。首先,为了证明这一点,我将设计一个抽象的游戏,其中一些玩家比其他人更好,让他们互相玩。玩家将有一个输赢记录和一个 Elo 等级。然后,我们将能够在友好的环境中比较这些评级。在以后的文章中,我将使用容易获得的运动数据,看看这个过程在现实世界中是否可行,而不仅仅是一个友好的实验。这个实验的代码可以在我的 Github 页面上找到。

友好、可控的示例

在现实世界中,有一些 Elo 没有考虑到的复杂问题。比如一支球队会在休赛期选秀球员,变得更好或者更差。如果一个明星球员被交易或者受伤了,Elo 是不知道的。所以让我们设计一个没有混乱复杂情况的游戏。

运动球

有一种新游戏叫做运动球,一个由所有最好的运动球运动员组成的大联盟刚刚成立。来自世界各地的球迷都会去看他们最喜欢的运动球队。大联盟运动球有 32 名球员,球员总是在他们来自的城市之间的中点打球(以抵消主场优势)。虽然售票处不喜欢这一举措,但计算 Elo 收视率的人喜欢。

为了模拟真实能力,每个玩家都会有一个“真实等级”。当两名运动员比赛时,一个随机变量将被添加到真实评分中,这样较弱的队伍可以击败较好的队伍。否则,这将是一个无聊的实验。随机变化基本上是一种模拟运气和玩家当天感受的方式。

最后,为了模拟随时间的变化,每个玩家的真实评分将在每场比赛后随机调高或调低。赛季输赢记录将无法适应这些变化,但 Elo 将能够做到。这给了 Elo 一个在现实世界中也会有的优势。在 1000 个游戏赛季结束时,我们将比较真实评级、输赢记录和 Elo 分数。

密码

让我们首先创建一个玩家类来跟踪所有这些属性。

class Player(object):
    """Player Object"""
    def __init__(self, name, rtg, elo, nudge):
        super(Player, self).__init__()
        self.name = name # true rating
        self.rtg = rtg # elo rating
        self.elo = elo # wins, losses, ties
        self.wins = 0
        self.losses = 0
        self.ties = 0
        self.games_played = 0 # how much to nudge ratings
        self.nudge = nudge def nudge_rating(self):
        # decide to nudge up or down
        direction = random.randint(0,1)
        if direction == 0:
            self.rtg += self.nudge
        else:
            self.rtg -= self.nudge def add_win(self):
        self.wins += 1 def add_loss(self):
        self.losses += 1 def add_tie(self):
        self.ties += 1 def played_game(self):
        self.games_played += 1

我喜欢设置一个 settings.py 文件,方便调整参数。因此,让我们为我们的实验创建一些基本设置。

season_settings = {
    # the way it's coded, it must be even number of players
    'num_players':32,
    'num_games':1000,
    # average ratings for the teams
    'avg_rtg':100,
    # standard deviation of ratings (higher -> more difference in player skill)
    'std_dev': 5,
    # game by game variation amount:
    'game_var':7.5,
    # after each game, how much does the true rating change?
    'rtg_nudge':0.2
}
elo_settings = {
    'init_elo': 1500,
    'K': 2,
    'beta':400
}

我事先运行了几次,决定了一个合理的 K 值。本文的目的不是解释 Elo,而是最大化 Elo 的有效性。我鼓励你复制我的 Github repo,自己玩这些价值观。如果你想知道更多关于 beta 和 K 值的信息,我鼓励你阅读我上面给的链接。一旦我们决定了设置,我们可以创建一个联盟:

# array to store players
league = []
# table to track wins/losses
table_array = []# create league
for p in range(season_settings['num_players']): # initialize players
    player_name = fake.name() # assign random initial true ratings
    player_rtg = random.gauss(season_settings['avg_rtg'], season_settings['std_dev'])
    player_elo = elo_settings['init_elo'] nudge = season_settings['rtg_nudge'] player_entry = [player_name, player_rtg, 0, 0, 0, player_elo]
    table_array.append(player_entry) new_player = Player(player_name, player_rtg, player_elo, nudge)
    league.append(new_player)league_table = pd.DataFrame(table_array, columns=['Name', 'True Rating', 'Wins', 'Losses', 'Ties', 'Elo'])league_table = league_table.sort_values(by='True Rating', ascending=False)

注意:我使用了 faker 包来创建假名字。现在我们有 32 名技能分布正常的球员:

所以是时候打第一季的 Sportsball 了!我不会给出所有代码,但我会展示我用来运行比赛的 for 循环:

for i in tqdm(range(season_settings['num_games'])): # create random matchups (pops from league list)
    matchups = create_matchups(league) # reset league
    league = [] # play games
    for matchup in matchups:
        p1 = matchup[0]
        p2 = matchup[1]
        p1_score, p2_score = play_game(p1, p2)
        p1, p2 = update_players(p1, p2, p1_score, p2_score)
        league.append(p1)
        league.append(p2)

注意:我还使用了 tqdm 包来显示进度条。我再次鼓励你去我的 Github 看看所有的代码。下面是结果!(Sportsball 还没有季后赛,因为经理们无法就条款达成一致)。

恭喜艾琳·琼斯!她以最好的真实收视率开始了这一季,以最好的真实收视率结束了这一季。最熟练的玩家赢得最多!无意冒犯艾琳,但我们真的不在乎。更有趣的例子可能是布兰登·尼科尔斯,他在赛季开始时排名第 12,结束时排名第 2。他的 Elo 和他的获胜次数都表明他并不是一直以来都是第二好的。也许他在赛季末有了很大的进步?

突然间,我们进退两难。我们如何知道评级系统有多好?我们可以利用赢/输栏(平局判一半赢)和真实评分的相关性,来了解使用赢/输记录反映真实评分的效果。相关性为 88.2%。然而,这并不完美。如果布兰登·尼科尔斯在赛季末大幅提高,输赢记录不会准确反映真实的评级(显然不会)。Elo 评级显然还没有赶上布兰登的真正技能。它仍然认为茉莉布朗是第二好的。哈!是否应该提高 K 值,让 Elo 调整得更快?嗯嗯…

而且,如果你好奇的话:Elo 和 True Rating 的相关性是 88.6%。这远不是 Elo 比输赢更好的决定性证据。事实上,当我多次运行这段代码时,输赢有时关联得更好。然而,这种高度的相关性确实表明 Elo 是一种不错的球员评级方法。

因此,我们需要一种方法来对评级系统进行评级。就像收视率调查一样。这让我想到了一个神奇的附加物,荆棘得分。

什么是 Brier 分数?

Brier 评分是一种简单的预测评分方法。和 Elo 一样,我也不是最能解释的人。它们是我最喜欢的书之一《超级预言》的核心组成部分。我会尽我所能给出一个简短的概要。

假设我在预测天气。我认为有 30%的可能性会下雨。然后下雨了。说“这是一个可怕的预测”很有诱惑力,也很人性化。人类(我对此也有罪恶感)经常假设,如果有人站在错误的那一边,他们就是错的。每当有人说某件事有 65%的可能性,而它没有发生,就感觉那个人错了。但是那个人可能是完全正确的。事实上,有人可能会说有 5%的可能性会下雨,然后就下雨了,那个人仍然是对的。我保证我不是天气预报员或天气预报员辩护者。我们只是生活在一个不可预测的世界里,不可能的事件会发生。幸运的是,我们是体育球分析师,我们有一个 1000 场比赛的赛季来找出我们的错误!

Brier 分数基本上概括了预测误差。一个好的预测者会有一个最低的 Brier 分数。我将举维基百科上关于降雨预报的例子来说明:

  • 如果预测是 100%并且下雨,那么 Brier 得分是 0,这是可以达到的最好得分。
  • 如果预报是 100%并且不下雨,那么 Brier 得分是 1,这是可达到的最差得分。
  • 如果预测是 70%并且下雨,那么欧石南得分是(0.70−1)^2 = 0.09。
  • 如果预测是 30%并且下雨,那么欧石南得分是(0.30−1)^2 = 0.49。
  • 如果预测是 50%,那么不管是否下雨,欧石南的得分是(0.50−1)^2 = (0.50−0)^2 = 0.25)。

所以,这里有一个权衡。我可以选择对我的降雨预报非常保守。我可以说每天有 50%的机会下雨。在这种情况下,无论发生什么,我的 Brier 误差是每次预测 0.25。那完全没用。因此,任何高于这个值的误差都是不好的,在某些情况下,与预测相反可能会更好。

Brier 分数的优势在于,它惩罚了过于自信的预测者。当结果接近确定时,你会因为预测“我确定某事”而获得奖励,当结果不确定时,你也会因为预测“它可能会发生,我不确定”而获得奖励。

Brier 分数也有弱点,我将在以后的文章中详细阐述。假设我在沙漠里,那里几乎不下雨。然后我每天预测 0%就能有一个合理的 Brier 分数。一方面,这感觉像是欺骗。一到两次下雨,我会有一个巨大的误差(每天 1)。这是一项严厉的处罚。另一方面,预测(我在沙漠中)需要一定程度的知识,所以小一点的荆棘是有道理的。理想情况下,如果我是一个不错的预报员,我会在下雨前增加我预测降雨的机会…显然…

布赖尔和艾洛的自然结合

Elo 评级自然会给出玩家赢得游戏的百分比几率。这是内在计算的一部分。同样,输赢记录也可以做到这一点。如果一个玩家或团队赢得了 76%的比赛,那么期望他们在 76%的时间里赢得随机比赛似乎是合理的。因此,我们可以计算两者的误差。由于 Elo 评级考虑到了对手的实力,也应该随着时间的推移而调整,我们预计 Elo 的表现将优于输赢记录。但是让我们看看!

代码更改

我认为追踪错误最简单的方法是添加 Brier 错误和赢输错误作为玩家类变量。在每场比赛后,每个玩家的输赢预测和 Elo 预测都将与结果进行比较,并计算 Brier 误差。然后它将被添加到球员的赛季总误差中。在赛季结束时,所有球员的所有赛季误差将被加在一起。然后我们将除以游戏数量和玩家数量,得到每场游戏的误差。让最好的评级系统胜出。

结果

哇!那是意想不到的。输赢记录更能预测结果!Elo 的精确误差值为 0.41/场,W-L 记录方法的精确误差值为 0.27/场。与我们之前的 50/50 基准相比,这真的很糟糕!这意味着我们真的需要校准 Elo。让我们试着调整 K 值来提高 Elo。

事实证明 Elo 的收视率对每场比赛都反应过度了。我将 K 值改为 0.5,将 Beta 值改为 400,这使得 Elo 评级经常打破输赢记录。总而言之,Elo 误差平均约为 0.244,W-L 记录平均约为 0.262。

然后我开始玩季节长度。在更长的赛季,如 10,000 场比赛,有一个非常小的 K 值要好得多。在超长赛季中,Elo 似乎会跑掉,变得不准确。然后我把赛季长度改成了 10 场和 100 场,Elo 常规以高 K 值(比如 5)击败 50/50 预测和 W-L 纪录。

我不满意

0.24 听起来很糟糕,事实也的确如此。然而,如果你完美地预测了 70%的获胜概率,那么你的误差是 0.21。如果你完美地预测了 90%的获胜概率,那么你的误差是 0.09。欧石南的分数并不能很好地评估那些自然接近胜负的预测。

事实证明,可能有一种更好、更流行的方法来计算预测误差。敬请期待!

As your accurate predictions increase in likelihood, your Brier scores increase naturally. I apologize for the ugly Excel graph.

正如你所看到的,对于任何实际上胜负难料的游戏,即使有完美的预测准确性,你的 Brier 分数也不会比 0.25 好多少。完美的 Brier 分数可以通过一个显而易见的等式找到(除了我不得不画出它来看):-x + x。

我学到的是:

  • 欧石南分数在识别坏预测方面很棒。然而,当我模拟接近掷硬币的游戏时,他们会很纠结,因为最好的分数可能接近 0.25。
  • 当游戏结果的变化较小时,例如一个团队可以赢得 95%的时间,输赢记录似乎比 Elo 表现得更好。
  • 当有更多真正的技能移动性(rtg_nudge 设置)时,Elo 的表现优于预期的赢输。
  • 在超长赛季中,Elo 失去了控制。这不一定是对 Elo 的抨击,这是实验中的一种错误——由于随机漫步数学,某些比赛的实际获胜预期超过 100%。
  • 为了在极端情况下快速获得准确性(例如,当最好的队和最差的队比赛时),你必须提高你的 K 值。提高 K 值会损害中层团队的准确性。所以有一个权衡——要么在不均衡的比赛中准确,要么在胜负难分的比赛中准确。

总而言之,我觉得我学到了很多东西。

未来的职位和目标:

  • 通过各种手段提高 Elo。胜利的边缘,保持稳定,等等。
  • 测试同时使用盈亏和 Elo 的回归
  • 也许使用盈亏差额作为另一个基线工具
  • 对真实数据进行操作

等不及了!

给运动队评分——最大化一个通用系统

原文:https://towardsdatascience.com/rating-sports-teams-maximizing-a-generic-system-772144574a07?source=collection_archive---------10-----------------------

Photo by Markus Spiske on Unsplash

仅仅从一条分数线我们能得到多少信息?

介绍

我的第一篇媒体文章是关于预测运动结果的基本方法。它使用简单的盈亏记录作为基线。例如,如果芝加哥小熊队今年赢得了 58%的比赛,你会期望他们未来赢得 58%的比赛。那篇文章表明,由一位名叫 Arpad Elo 的物理学教授在 20 世纪 40 年代发明的一个简单的系统可以胜过单独使用输赢记录。

有一些好消息:现在不再是 20 世纪 40 年代,我们可以获得大量的数据和计算能力。此外,许多人(特别是 538 和哈佛教授马克·格利克曼)为改进通用评级系统做出了许多贡献。因为我对模特、运动等感兴趣。我已经决定汇编和比较这些评级系统。

为什么?

我对创建运动模型感兴趣,我认为任何模型中最基本的输入是对整体技能的估计。如果你只是用输赢来代表整体技能,你是在给自己设限,因为随着比赛越来越多,你依赖你的模型来推断赛季输赢记录有多重要。这导致使用多个输入(如过去 5 场比赛的记录,过去 10 场比赛的记录等)来尝试评估技能。我认为创建模型时最好的第一步是最大化(在合理的范围内)对整体技能的单一评估。最坏的情况下,它可以作为一个很好的基线。

丰富

  1. 数据 —在上一篇文章中,我用 Python 的随机库生成了假球员和假分数。不再!在这个故事中,我使用了 2003 年的真实大学篮球数据和 2000 年的真实 PGA 和欧洲巡回赛(高尔夫)数据。大约有 87,500 场大学篮球赛和 1,700 场高尔夫锦标赛。
  2. 在上一篇文章中,我使用了最基本的 Elo 形式。不再!我给 Elo 增加了大约四个特性来改进它。还记得我之前提到的格利克曼教授吗?他有自己的系统,我们也试试那个。这两个系统都可以对高尔夫球员个人或篮球队进行评级。
  3. 基线(Baseline)—如果我们在改善其他一切,为什么不同时改善我们的基线呢?之前我只是用一个球队的输赢百分比来预测比赛结果。虽然把自己和不如自己的对手相比感觉很好,但这不是一种非常科学的做事方式。相反,这一次,我将使用 Log5 方法,它包含了两个团队的胜率。我稍微修改了一下,如果两个队都是不败的或者两个队都是零胜,它保证返回 50%的胜率。
  4. 错误跟踪——上一篇文章没有一样是令人满意的!我们将使用交叉熵损失(也称为对数损失)而不是 Brier 分数。为什么?我的最佳答案是,因为这样更容易判断你的评级系统是否在改进,或者你只是在猜测。你会因为过于自信而受到更多的惩罚,因此它会迫使你的系统稍微保守一点。我发现这也是一个更受欢迎的误差函数,但我想这不是使用它的具体原因。

系统

Question: Which system is best?

1)日志 5

直截了当的说,Log 5 就是一个简单的配对比较公式,比较两队的胜负。

2) Elo 评级

同样,非常简单。如果你不知道 Elo 是什么,我推荐我的第一篇文章或者 538 个讲解者之一的

3)改进的 Elo

终于来了个新人!我从四个方面改进了 Elo:

  1. 胜率:胜率很简单,更大的胜率意味着更多的 K 奖励(你的等级提升更快)。这在阿拉巴马橄榄球赛这样的情况下尤其有用。如果他们每场比赛都赢了 20+分,改进的 Elo 系统可以更快地调整其评级,以迅速将阿拉巴马州评为所有球队中的顶级。是的,实现有点复杂,我稍后会进一步解释。另一方面,这也适用于一场比赛输了 20 多分的球队。
  2. 衰减的 K 值:从高 K 值开始考虑赛季初期的不确定性是有道理的。这使得收视率在赛季初调整得更快。随着赛季的进行,随着收视率有更多的数据可以确定,K 值会下降。如果一个赛季的主导球队在赛季后期遭遇三连败,收视率不会反应过度,因为 K 值较低。在我的实现中,我使用指数衰减,但是可能有更好的函数。
  3. 前科:这只是季前赛排名的一个花哨词。经常被诽谤的季前赛排名包含信息,尽管有时是坏信息。该模型想知道是否每个人都认为肯塔基篮球队和杜克篮球队整个赛季都可能进入大学篮球队的前 10 名。这给了它一个向真实排名靠拢的良好开端。有了这个开端,就不太需要用超高的 K 值来启动收视率了。显然,季前赛排名对于像 NFL 这样的短赛季运动和像 MLB 这样的长赛季运动更有用。赛季越久,季前赛排名就越不重要。在大学篮球赛季,我发现最好每年保持一支球队 70%左右的收视率。
  4. 自相关预防:还记得我说过实现胜利边际是复杂的吗?标准 Elo 的一个优势是它是平衡的,不会随着时间的推移而失控。基于胜率提升奖励 K 值打破了这种平衡。自相关预防项(ACP 项)使我们改进的系统保持平衡。

4)格里科

如果我告诉你…有一个完全不同的评级方法可以尝试?这个是我之前提到的格利克曼教授在 1995 年发明的。值得阅读论文本身,但我会尽力总结。Glicko 引入了两个主要组件。第一,它引入了不确定性。这是非常有用的。Elo 评级系统中的总体评级仅由一个数字表示。让我们以一个评级为 1750 的玩家(或团队)为例。问题是你不能 100%确定,在一个随机的日子,在随机的条件下,在最后一场比赛后的两个星期,玩家的准确等级是 1750。相反,你可以非常确定玩家的“真实”评级在 1650 到 1850 之间。在 Glicko 系统中,在这种情况下,评级偏差项将为 50。它将表示玩家的真实能力在 1750 的 100 分(两个评级偏差)内的 95%置信区间。

不确定性也可以修改。如果一个球员已经 3 个月没有比赛了,我们可以增加不确定性。如果一名球员的比赛成绩非常不稳定,格利克会保持很高的不确定性。

另一个介绍是“评级期”的概念。作为一个温和的剧透,我凭经验发现,在某些体育项目中,评分周期比其他项目更有效。Glicko 将一个评级周期内的所有匹配视为同时发生。这在高尔夫球比赛中很有用,当你同时与 100 多名其他选手比赛时。这不仅减少了计算时间,而且通过使用所有其他球员作为参考,Glicko 能够确定一轮得分的上下文。另一方面,在大学篮球中,它的效果就不那么好了。我发现三场比赛的收视率是最好的。篮球用一个收视率周期没多大意义。根据你如何将过去的游戏分成三组,你可能会得到不同的评分。你还在等待三场比赛来更新排名,所以你经常忽略最后一场或最后两场比赛来影响你的排名。

实现说明:我使用的是 Glicko 2,但我称它为 Glicko。我大量引用了 Github 用户 sublee 的这个实现。

大学篮球成绩

Error per game, averaged from 2003–2019. Less is better!

在上面的图表中,我展示了我尝试的评级系统中每场比赛的误差。周误差是从 2003 年到 2019 年所有赛季的那一周所有比赛的平均值。首先:哇!改进的 Elo 在微调时表现非常好。至关重要的是,它在赛季后期与其他评级系统保持着明显的差距。在运动模型中,当你为小数位而战时,那真的令人印象深刻!值得注意的是,它甚至在没有季前赛排名的情况下击败了格利克,这也是我可以在格利克系统中实现的。无论如何改进的 Elo 似乎更好!

在我看来,最奇怪的发现是我在赛季初改进的 Elo 实现的有效性。赛季初期的误差小于赛季后期的误差。我认为这主要是由于传统的优秀球队在赛季初与纸杯蛋糕对手“热身”。如果肯塔基打无名定向学校,改进的 Elo 将预测肯塔基赢的概率为 90%+并且当他们最有可能真的赢时,误差将非常低。

除了蛋糕时间表,可能还有其他解释。与漫长的休赛期相比,球队在赛季中发展和改变技能更多吗(因此更难预测)?休赛期花名册更替对球队能力的影响有多大?我认为误差随赛季的演变值得进一步探讨。赛季中的伤病,联盟与非联盟的比赛,以及研究教练的影响都将是有趣的方向。

第二个结果是,经过多次调整,我无法让格利克接近击败改进的埃洛。这令人惊讶,因为这应该是一个更好的系统!策划完这个,我才意识到格利克在大学篮球宇宙中的不足。不过,我们先不要把它扔掉!

此外,我隔离了 Elo 的单个改进,以表明它们都做出了贡献:

Improvement Isolation

个人的改进我没有完全优化,重点是他们都有所贡献。同样令人印象深刻的是,作为一个整体,它们看起来是一样的,甚至比它们各部分的总和还要好。我有点期待衰减 K 和先验是同一个问题的两种解决方案,但事实证明,它们甚至在一起都很有用。我用的代码,sans data,可以在这里找到

高尔夫成绩

注意#1:在 2019 年 7 月 9 日更新之前,我正在展示高尔夫 Glicko 的结果,这些结果比他们应该得到的要好。我允许一些数据泄漏来改善结果。

Each system was optimized as much as possible within reason.

注意#2:如果你想知道我是如何在高尔夫中使用 Log 5 的,我是通过对锦标赛中每场比赛的结果求和来完成的。因此,在一场 144 人的锦标赛中,每名玩家要参加 143 场比赛。

这次两个主要系统之间的结果非常接近!Glicko 以显著优势击败常规 Elo,甚至接近改进的 Elo。与改进的 Elo 相比,Glicko 以更少的计算和更少的参数调整获得了它的分数。就像我前面提到的,Glicko 在很多玩家同时玩游戏的情况下更有用。

在研究这篇文章时,我没有看到像 Glicko 这样的贝叶斯排名系统在短赛季的一对一比赛中有缺点。当然,我不能排除我可以做些调整来提高格利克在那里的表现。微软在他们大部分与 Glicko 密切相关的游戏中使用了 TrueSkillTrueskill 2 。这是有意义的,因为许多在线游戏多人比赛涉及两个以上的玩家。从我的实验来看,游戏设计师在面对面游戏中使用 Elo 版本可能会更好。

结论

总而言之,我完成了我想完成的事情。我比较了两种截然不同的运动项目的通用评分系统,发现两者的结果都不一样。一般来说,大多数进一步的改进将是微小的小数点或特定运动的变化。真是浪费时间,对吧?嗯,我打算将来也这么做。

当然,不言而喻,我们可以在格里克的基础上有所提高。马克·格利克曼也做了自己的改进(比如 2010 年的格利克助推系统)。也有基于 Glicko 系统的改进系统,如斯蒂芬森系统赢得了 2012 年 Kaggle 比赛。那些专注于国际象棋,但它们提供了从这里走向何方的线索。

最后,我想比较现实世界中已建立的排名系统与我在这里描述的系统之间的相关性。如果这些系统产生的排名与我自己的大相径庭,所有这些都是毫无用处的。为了简洁起见,我将只集中比较四个高尔夫排名系统。一,官方的世界高尔夫排名。这不是最好的系统,但已经使用了很长时间,任何高尔夫球迷都很熟悉。它把赢得高尔夫锦标赛和在大型锦标赛中表现出色看得比它应有的更重(因此它喜欢 4 次主要冠军布鲁克斯·科普卡)。另一个排名系统“DG 排名”,是由 datagolf.ca 创建的排名。数据高尔夫做了伟大的工作,我认为即使非高尔夫球迷也会喜欢看到他们创造的一些可视化。他们的总排名通常接近拉斯维加斯的赔率,是一个很好的参考,以了解高尔夫球员在任何特定时间的比较。

如你所见,这两个排名系统与 DataGolf 的排名有 85%或更多的关联!Elo 和 Glicko 也有很大的不同。由于它们不同,但提供了相似的预测精度,它们可能被组合起来形成一个更好的模型🤔。

DIY 雷伊·达里奥 ETF:如何用风险平价投资组合构建自己的对冲基金策略

原文:https://towardsdatascience.com/ray-dalio-etf-900edfe64b05?source=collection_archive---------6-----------------------

查看我们的 开源 Live Book 项目获取本文使用的代码。

7 November 2018; Ray Dalio, Bridgewater Associates on Centre Stage during day two of Web Summit 2018 at the Altice Arena in Lisbon, Portugal. Photo by David Fitzgerald/Web Summit via SportsfilePhoto by David Fitzgerald /Sportsfile. Image adapted by OpenQuants.com.

本月早些时候,彭博发表了一篇关于美国推出新的风险平价 ETF 的新闻文章。 RPAR 风险平价 ETF 计划基于风险在资产类别之间进行分配。根据彭博的说法,该基金将是美国第一个遵循这种量化方法的基金,将更多的资金分配给波动性较低的证券。

(RPAR 风险平价 ETF)有点像 Bridgewater,但他们只是为世界上最富有的机构做这件事。这里的想法是建立一个对每个人都有用的东西。— Alex Shahidi,Dalio 的 Bridgewater Associate 的前关系经理,RPAR 风险平价 ETF 的创始人。彭博

“风险平价”方法是由雷伊·达里奥的 Bridgewater Associates 在 1996 年创立全天候资产配置策略时推广的,Bridgewater Associates 是管理资产规模最大的对冲基金(1328 亿美元)。“全天候”是一个术语,用来指在有利和不利的经济和市场条件下都表现良好的基金。今天,一些经理在风险平价方法下采用了“全天候”概念。

Ray Dalio while giving a speech at the 10th anniversary celebration of charity Grameen America. Metropolitan Museum of Art, September 23 2017. Attribution: Grameen America [CC BY 3.0].

风险平价投资组合寻求在与每个资产类别或投资组合组成部分相关的风险之间实现均等的平衡。这样,低风险资产类别通常会比高风险资产类别拥有更高的名义配置。

风险对等大约是平衡。实现可靠平衡的最佳方式是基于对资产类别定价结构中固有的环境敏感性的基本理解来设计投资组合。这是全天候方法的基础。

风险平价策略在最近的历史(2010 年至 2017 年)中遭受了损失,因为牛市将股票推至创纪录高位,因此有利于股票集中的投资组合。然而,自 2018 年以来市场波动性的增加,地缘政治和贸易战风险的紧急情况,以及黄金等避险资产的增长,为加强多元化投资组合创造了条件。这在图 3.1 中得到证明,该图显示 S&P 风险平价策略在过去 12 个月(2018 年 8 月-2019 年 8 月)中的回报率接近 10%,是美国股票标准普尔 500 指数的两倍多。

Fig. 3.1 S&P 500 index versus S&P Risk Parity Index. Source: Bloomberg.

但是我们如何建立风险平价投资组合呢?它与传统的均值-方差模型相比表现如何?

在这篇文章中,

  1. 我们将展示如何建立自己的风险平价投资组合
  2. 我们将创建并比较两个指数的性能:
  • 风险均衡的 FAANG 公司的 FAANG 风险平价指数
  • FAANG 切线投资组合指数的 FAANG 公司的权重,使回报/风险比率是最佳的

到本文结束时,你将能够受雷伊·达里奥全天候方法的启发,创建自己的风险平价基金。作为我们开源 Live Book 计划的一部分,我们还提供了复制结果的代码。

风险平价投资组合——雷伊·达里奥方法

风险平价投资组合表示一类资产验证以下等式的投资组合(Vinicius 和 Palomar 2019 年):

其中 f 是衡量投资组合总风险的一次正齐次函数,而 w 是投资组合权重向量。换句话说,风险平价投资组合中每项资产的边际风险贡献是相等的。 f 的一个常见选择是投资组合的标准差,这是波动性的一个常见代表,即,

其中σ是资产的协方差矩阵。

在实践中,风险和投资组合经理在资产、国家、区域或行业层面都有他们遵循的风险指令或边际风险贡献界限。因此,风险平价组合的自然延伸是所谓的风险预算组合,其中边际风险贡献与预先分配的数量相匹配(Vinicius 和 Palomar 2019)。数学上,

切线投资组合——马科维茨方法

均值方差优化是现代投资组合理论中常用的量化工具,允许投资者通过考虑风险和回报之间的权衡来进行分配。

In 1990, Dr. Harry M. Markowitz shared The Nobel Prize in Economics for his work on portfolio theory.

在均值-方差框架中,目标是根据基线预期收益率μb 最小化投资组合风险σ,如下所示:

其中 m 是投资组合资产的预期收益向量。

我们将获得每个目标收益率μb 的最优(最小风险)投资组合,从而形成有效边界。图 3.4 中有效边界上的每一点都是在给定风险水平(标准差)的情况下,具有最小化风险的最优证券组合的投资组合。有效边界以下的点是表现较差的投资组合。它们要么提供相同的回报但风险更高,要么提供相同风险的更少回报。

Figure 3.4: Efficienty Frontier. Attribution: ShuBraque (CC BY-SA 3.0)

但是我们如何从有效边界选择投资组合呢?一种方法是从风险/回报的角度选择最有效的投资组合,即具有最高夏普比率(超额回报和投资组合标准差之间的比率)的投资组合。这个投资组合被称为切线投资组合,它位于资本配置线和有效边界的切点。

我们将在下一节实现平价风险和切线投资组合。

优化 FAANG:雷伊·达里奥对马科维茨

单一投资组合

我们将考虑 FAANG 公司调整后价格的对数收益,即由以下代码标识的股票:FB、AMZN、AAPL、NFLX 和 GOOG。

我们可以使用风险平价投资组合投资组合分别构建一个 FAANG 风险平价和切线投资组合。我们将首先考虑 2018 年的 FAANG 回报,以构建如下投资组合:

图 3.5 显示了平价和切线投资组合的投资组合权重。我们观察到切线投资组合集中了亚马逊和网飞的权重,两家公司的权重几乎相同,而脸书、苹果和谷歌被排除在投资组合之外。另一方面,平价投资组合在 FAANG 公司中呈现出均衡的权重分布,所有公司的权重都在 20%左右。苹果和谷歌的权重略高于 20%,而网飞是权重最低的公司(15%)。

Figure 3.5: Portfolio weights for parity and tangency FAANG portfolios considering returns from 2018.

图 3.6 比较了获得的平价和切线投资组合的(协方差)风险预算。正如所料,我们观察到平价投资组合的风险预算在投资组合资产中平均分配。另一方面,切线投资组合集中了亚马逊和网飞之间的风险,后者对应于投资组合风险预算的 56%以上。

Figure 3.6: Portfolio covariance risk budget for parity and tangency FAANG portfolios considering returns from 2018.

雷伊·达里奥法昂指数

“雷伊·达里奥 FAANG 指数”,即由 FAANG 公司组成的投资组合,再平衡以匹配相应的风险平价投资组合,会有什么表现?它会击败相应的短期投资组合吗?

为了回答这些问题,我们将考虑 2014 年 11 日至 2019 年 9 月 1 日期间 FAANG 公司的投资组合,并构建两个指数:

  1. 风险平价指数:每季度重新平衡投资组合权重,根据风险平价投资组合设定权重;
  2. 切线投资组合指数:根据切线投资组合重新平衡投资组合权重。

我们首先通过构建一个宽度为 12 个月、步长为 3 个月的滚动窗口来定义重新平衡日期,如下所示:

**library**(fPortfolio)
faang.returns.xts<-faang.returns["2014-01-01/2019-09-01"]
rWindows<-**rollingWindows**(faang.returns.xts, period="12m",
                         by="3m")

我们的重新平衡日期如下:

**print**(rWindows$to) ## GMT
##  [1] [2014-12-31] [2015-03-31] [2015-06-30] [2015-09-30] [2015-12-31]
##  [6] [2016-03-31] [2016-06-30] [2016-09-30] [2016-12-31] [2017-03-31]
## [11] [2017-06-30] [2017-09-30] [2017-12-31] [2018-03-31] [2018-06-30]
## [16] [2018-09-30] [2018-12-31] [2019-03-31] [2019-06-30]

接下来,我们计算每个再平衡日期的风险平价投资组合权重,考虑 12 个月窗口内的回报,如下所示:

我们现在计算 FAANG 切线投资组合的季度权重。我们利用f 组合包来计算滚动切线组合,如下所示:

图 3.8 显示了平价风险和切线投资组合的投资组合权重。我们观察到,随着时间的推移,风险平价权重相当稳定,与其他投资组合成分相比,网飞的权重略有不足。另一方面,切线投资组合权重在考虑的时间段内变化很大,这可能会对其维护带来挑战,因为其周转率可能相当高。切线投资组合在许多重新平衡日期中增持苹果和亚马逊,在所有重新平衡日期中减持谷歌。

Figure 3.8: Portfolio weights for (A) FAANG risk parity portfolios and (B) FAANG tangency portfolios.

我们将使用 FAANG 公司的时间序列以及风险平价和切线投资组合权重的时间序列来计算风险平价和切线投资组合指数的回报,如下所示:

图 3.9 显示了风险平价指数与切线投资组合指数的绩效汇总。令人惊讶的是,FAANG 风险平价指数大大优于 FAANG 切线投资组合指数,累计回报率为 169.48%,而切线投资组合指数为 109.65%。FAANG 风险平价指数在分析的大部分时间内也有相对较低的下降。

Figure 3.9: Performance summary for the risk parity index versus the tangency portfolio index

表 3.1 和 3.2 分别显示了风险平价和切线投资组合指数的日历回报。有趣的是,在切线投资组合指数累积回报为正的年份,风险平价指数的回报低于切线投资组合指数。相反,在切线投资组合指数累积回报为负的年份,风险平价指数的表现优于切线投资组合指数。这样,与切线投资组合相比,风险平价指数显示了“没那么好”但也“没那么差”的年回报率。

图 3.10 显示了滚动 252 天窗口中的性能摘要。同样,我们观察到风险平价指数比切线投资组合指数表现更好。与切线投资组合指数相比,风险平价指数在分析的大部分时间内具有更高的年化回报、更低的标准差和更高的夏普比率。如表 1 所示。3.3,风险平价指数的总年化回报率为 23.71%,标准差为 22.55%,夏普比率为 1.051,而切线投资组合指数的年化回报率为 17.22%,标准差为 26.42%,夏普比率为 0.652。

Figure 3.10: Performance summary in a rolling 252-day window for the risk parity index versus the tangency portfolio index

讨论和结论

在各种经济环境下,哪种资产组合最有可能带来长期的良好回报?

这是 Bridgewater Associates 在创建全天候基金之前提出的问题,其概念如今在所谓的风险平价策略中流行开来。

传统的资产配置方法往往容忍更高的风险集中度,目标是产生更高的长期回报。布里奇沃特认为这种方法有一个严重的缺陷:

如果短期风险的来源是高度集中于单一类型的资产,这种方法会带来长期回报不佳的重大风险,威胁到履行未来义务的能力。这是因为每种资产都容易受到持续十年或更长时间的不良表现的影响,这是由经济环境的持续变化引起的——T2 桥水。

在本文中,我们介绍了风险平价投资组合的概念,并将其与均值-方差模型进行了比较。我们通过构建 FAANG 风险平价指数并将其性能与 FAANG 切线指数进行比较,提供了一个简单的实际例子,FAANG 切线指数从均值-方差有效前沿中选择具有最优夏普比率的投资组合。

与切线投资组合指数相比,风险平价指数在分析的大部分时间里表现出更高的年化回报、更低的标准差和更高的夏普比率。当然,要谨慎对待结果。

在实践中,风险平价和均值-方差方法都被用于可能跨越多个资产类别的较大投资组合。当投资组合中存在不相关的资产时,这些方法会发挥作用,从而增加分散投资的潜力。此外,现代投资组合优化策略可能更加复杂,具有各种目标函数和约束。我们在这篇文章中的目标是给你一个良好的开端。请随意查看我们的 github 项目中的源代码,并实施您自己的策略!

参考

Vinicius,Ze 和 Daniel P. Palomar。2019. RiskParityPortfolio:风险平价组合的设计https://CRAN.R-project.org/package=riskParityPortfolio

AI 如何让建筑变得更好?

原文:https://towardsdatascience.com/re-imagining-construction-with-ai-54d8c8077939?source=collection_archive---------19-----------------------

建筑业在创新和生产率方面落后于其他行业。这篇文章探讨了人工智能可以帮助弥合差距的应用。

Digital assistant in construction (Illustration by author)

到 2030 年,世界将需要在基础设施和住房上花费 57 万亿美元,为从农村到城市的移民腾出空间。基础设施和建筑行业雇佣了全球 7%的劳动适龄人口,将承担大部分责任。然而,建筑行业有一个棘手的生产率障碍。大型项目通常比计划多花 20%的时间来完成,并超出预算高达 80%。在过去二十年中,建筑行业的劳动生产率停滞在 1%。承包商的财务回报通常相对较低且不稳定。同样令人担忧的是工人死亡的比例(所有其他部门中最高的)。

传统上,建筑业一直在进行渐进式改进。每个项目都是独一无二的,正因为如此,不可能扩大新想法的规模。采用新技术是不切实际的。在本帖中,我们将看看人工智能可以帮助该行业实现跨越的一些应用。

建设项目管理的可预见性。

在工程采购和合同领域,有太多的变量会导致执行失控。劳动力短缺、恶劣天气、供应中断和监管许可是导致项目管理固有可变性的一些参数。每个项目都被认为是独特的。这种标准化的缺乏使得过程数字化变得缓慢。日常报告、图纸、合同继续严重依赖基于纸张的通信。一线承包商和项目规划者之间的信息流不稳定且速度缓慢。一线承包商的计划范围通常仅限于未来 7 天。大多数项目管理是被动的。中高级工作人员从事日常消防应急工作。

我们可以使用机器学习来实现一天和一周的预测。每个站点都会得到一个活动列表,这些活动预计在该日期开始。实时仪表板列出了成本和时间超支的高风险活动。施工中的运营数据来源有限。但是,大多数站点记录项目成本的库存水平。类似地,项目进度也通过计划工具进行监控。人工智能可以将这些数据流编织在一起,并将它们与天气和历史表现结合起来,以预测未来的结果。它将使承包商和现场管理人员能够采取现实的观点和优先干预。

Using machine learning to forecast delays, list out activities likely to overrun budget and schedule(Illustration by author)

一线蓝领工人的个性化培训

过去二十年来,建筑业劳动生产率增长停滞不前。如果不对人力资本进行投资,该部门就不可能加速发展。与其他行业相比,建筑业的农民工比例很高。许多建筑移民和劳动力市场严重依赖的非正式招聘渠道是公平和安全工作环境的障碍。新加入者在最初的五到七年里做学徒。在此期间,当机会出现时,他们会改变交易。学徒工在经济上很脆弱,并陷入移民债务。大多数学徒工只懂当地方言,这一障碍限制了他们提高自身技能、理解自己的基本权利,甚至寻求技能认证的能力。

Personalized training in native language for frontline workmen (Illustration by author)

对话式人工智能彻底改变了训练。个性化语言学习应用已经教会超过 1 亿人一门新语言。建筑部门。例如,个性化机器人可以教育工人操作混凝土振动器,从而获得制造这种振动器的公司的认证。我们可以根据个人的学习进度和他的母语来定制课程。培训平台也可以取代目前使用的不透明的非正式渠道,成为寻找和招募人才的一种手段。它可以使招聘对工人和雇员都透明。

对于劳动力培训来说,合作是关键:政府、教育工作者、制造商和建筑公司。人工智能可以通过引入个性化、规模化和易于部署来扮演关键推动者的角色。

通过对象检测实现安全审计自动化

20%的工人死亡发生在建筑业。当你考虑到只有 7%的工人受雇于建筑行业时,这个统计数字就更加可怕了。自满的心态导致了受伤成为工作的一部分。安全部门经常人手不足:一个检查员管理着遍布工地的 500 名员工。

坠落、触电和倒塌占建筑行业所有工作场所事故的 60%。我们可以使用计算机视觉来检测导致此类事故的潜在条件。大多数项目都有监控摄像头来阻止盗窃。我们可以处理这个 feed 来检测边界框内的单个工人。随后,我们可以根据安全帽和安全带的存在与否对边界框进行分类。我们可以每分钟重复自动化过程,并记录所有不安全事件。我们还可以训练图像分类模型来检测正在执行的活动的性质,例如。钢筋弯曲、混凝土浇筑等。我们可以调整一个面罩-RCNN 来探测水溢出、障碍物和其他类似的不安全状况。所有此类事件和相关元数据在所有提要中聚合,相关人员会实时收到报告或警报,以便采取进一步的行动。

Aggregated unsafe incidents detected from surveillance footage. (Illustration by author)

存在局限性:错误检测、错误分类、视野中的障碍和弱光。目前,我们还不能完全自动化。但是,我们可以加强审计和合规性。我们可以将检查员的工作量减少 80%。这将使他有时间专注于训练和授权前线船员。

协作汇总合同,推动卓越发展

我们可以把建筑业大致分为两个部分。参与大型基础设施和住房项目的大型跨国公司,以及规模较小、分散的专业建筑商。分散单位的生产率通常是大单位的一半。较小公司执行的项目的财务回报和时间表仍不确定。

项目执行的一个重要组成部分是合同管理。我们应该根据标准对承包商进行评估,如过去的表现、财务状况、认证和 HSSE 合规性。较小的公司缺乏供应商网络,更不用说拥有管理复杂关系和合同的内部技能。低效的合同导致公司在一笔交易中损失价值的 5%到 40%之间。

零售电子商务同比增长 20%。到 2020 年,这一数字可能会超过 4.2 万亿美元。双边平台买方-卖方平台可以改变承包格局。美国初创企业上市公司跨国巨头正试图进入这一领域,以利用他们的物流、网络存在和对产品的深入了解。然而,此类平台缺少的关键方面是对签约中涉及的后端流程的支持。小型组织和部门需要工具来预算、预选、评估、管理投标、向卖方发出采购订单。一些较大的公司可能已有 ERP,需要集成到电子商务平台。现有的平台都没有提供这样的功能。

建筑公司将每个项目视为一项独特的努力。平台的力量来自于它组织和构造信息的能力。缺乏共享标准造成了额外的障碍。我们不能通过制定复杂的采购订单并要求人手不足的部门来填写来解决这个问题。

Using Entity Extraction on Contract Documents and preparing a relational database (Illustration by author)

今天,自然语言理解算法是几个应用程序的关键部分,从自动完成到处理保险索赔,再到垃圾邮件过滤器。除了财务数据之外,大多数建筑合同都是非结构化信息。如果我们需要组织这些信息,我们应该能够从非结构化的文本文档中提取信息。我们已经看到一些应用增强了准法律团队对法律文件的尽职调查能力。通过提取命名实体和关系,类似的方法将帮助我们组织项目间混乱的构造合同。平台上无障碍透明的交易将提高效率,降低成本。该平台可以利用从数百万类似交易中获得的知识来帮助编写合同规范,建立评估指南,匹配买家和卖家,并剔除不完整和模糊的订单。

B2B 电子商务规模巨大,大约是 B2C 的两倍。到 2020 年将达到 6 万亿美元。建筑合同在这一领域是一个未被充分利用的机会。

用摄影测量进行测量和检查

任何建设项目的首要活动之一就是土地测量。配备经纬仪的测量员将地形记录为网格点。在大型分散的基础设施项目中,这是一项在困难条件下的劳动和时间密集型活动。计算机视觉,即摄影测量已经彻底改变了这个领域。无人驾驶飞机携带的相机捕捉一系列图像,随后使用位置元数据对这些图像进行处理,以将其拼接成 3D 坐标阵列。在 8 小时的轮班中,一架无人机(带有额外的电池)可以覆盖勘测员在 2 个月内可以捕捉到的所有地形。在预设计阶段,时间是至关重要的,计算机视觉方法要快两个数量级,产生更高分辨率的 3D 网格,并且不会受到手动错误的影响。

Using 3D cameras to create an as-built point cloud |source Matterport

摄影测量的应用不仅限于测量。安装在固定装置上的 3D 摄像机可以生成建筑物的内部视图。我们可以将测量的竣工尺寸与原始设计进行比较,并自动检测偏差。在改装结构中,我们可以直接从 3D 视图中读取尺寸。我们还使用摄影测量对风力发电场和桥梁等资产进行维护审计。我们可以比较不同时间的结构维度,并检测异常应变。

这个领域的一些令人兴奋的工作已经朝着从 RGB 全景图像生成布局的方向发展。其他人使用立体和单目照片来估计景深。在一些最先进的方法中,精度水平大约是每米 5-10 厘米。我们还不能使用这些维度检查。然而,我们可以构建应用程序来使用来自智能手机的全景图像,导出房间布局,使用布局来呈现家具选项供房主选择。

From RGB image to 3D geometry to Furnishing and production drawings (Illustration by author)

建筑业颠覆的时机已经成熟。然而,存在着巨大的挑战。跨公司的数字化转型进展缓慢。除了试点规模的实施之外,创新的采用一直较为缓慢。数据透明度有限。在 b2c 领域,解决方案提供商必须介入并创建一个完整的垂直市场。

尽管如此,建筑行业提供了无与伦比的规模。如果我们耐心地微调用户体验,并达到产品与市场的契合,应用程序可以改变数百万人的生活。人工智能将在这些产品中发挥关键作用。

你经历过这篇文章中提到的建筑行业的一些挑战吗?我很想听听您对如何确定解决方案优先级的看法。你正在努力应对这些挑战吗?听听你的故事就好了。请在我的 LinkedIn 上留言。

反应最佳实践⚛

原文:https://towardsdatascience.com/react-best-practices-804def6d5215?source=collection_archive---------3-----------------------

前端

您应该在 React 项目中遵循的 React 最佳实践

Photo by Mimi Thian on Unsplash

在 Sysco 实验室实习期间,我大量接触了 React Js。对于我们的项目,我们使用 React Js,并遵循 React 最佳实践。因此,我的团队领导和我的导师 Nadun Indunil 建议我写一写 React 最佳实践。这是我在 Medium 的第 25 篇文章。

反应⚛️

React 是一个用于开发用户界面的 JavaScript 库。 React 图书馆是脸书创建的。React 允许集成许多令人兴奋的组件、库和框架。诚然,开发者可以自己制作组件。

在最佳实践之前,我建议在开发 react 应用程序时使用测试驱动开发。测试驱动开发意味着先写一个测试,然后根据测试开发你的代码。更容易识别缺陷。如果当你发现一个 bug 时,你遵循另一个软件开发过程,首先写一个测试。

最佳实践

目录

  1. 文件组织
  2. 微小功能部件
  3. 复用组件
  4. 删除冗余代码
  5. 索引为键
  6. 不必要的<部门> s
  7. 仅必要的注释
  8. 理解为处理‘这个’
  9. 道具—状态—构造器
  10. 最终命名
  11. 感知状态和渲染
  12. 避免“设置状态”内的对象
  13. 使用上部骆驼案例名称
  14. 利用道具类型
  15. JavaScript 中的 CSS
  16. 测试
  17. 使用 ESLint、Prettier 和 snippet 库
  18. 使用 React 开发者工具

1.文件组织📂

文件组织不仅是 react 应用程序的最佳实践,也是其他应用程序的最佳实践。 create-react-app 的文件结构是组织 react 文件的一种可能方式。虽然不一定有一种文件结构比另一种更好,但保持文件有条理是很重要的。在 React 中,考虑到每个组件至少有一个与之相关联的文件,您的文件结构将快速增长。保存一个包含顶级 CSS、图像和字体文件的 资产 文件夹。维护一个 helpers 文件夹来存放其他文件的任何种类的文件功能。将与组件相关的所有文件保存在一个文件夹中。通常情况下, 组件 文件夹包含不止一个组件文件,比如测试文件 CSS 和一个或多个组件文件。如果有某个特定组件只使用的小组件,最好将这些小组件保存在 组件 文件夹中。当您将大型组件放在它们自己的文件夹中,而将组件使用的小型组件放在子文件夹中时,就更容易理解文件的层次结构。开发人员主要将文件中的主要组件文件命名为 index.js。如果有几个文件都命名为 index.js,这可能会变得很麻烦。解决方法是在每个组件文件夹中添加一个 package.json 文件,并为相应的文件夹设置主入口点。例如,对于 button 组件,主要入口点是 Button.js。将 package.json 添加到每个文件夹并不是一个好的做法,但它有助于轻松处理您的文件。所以我们可以在按钮组件文件夹中添加下面的 package.json 文件。

当你在 React 项目中使用 Redux 时,你可以根据你的项目使用 Rails 风格Domain 风格【鸭子】 模式文件夹结构。在 Rails 风格的 模式中,单独的文件夹用于“动作”、“常量”、“缩减器”、“容器”和“组件”。在 域风格 模式中,每个特征或域使用单独的文件夹,每个文件类型可能有子文件夹。【Ducks】模式类似于领域风格,但是它明确地将动作和 reducers 联系在一起,通常是通过在同一个文件中定义它们。然而,文件夹结构可能是开发人员所希望的,但是应该有一种简单的方法来处理组件。React 说,它对你如何将文件放入文件夹没有意见。新队伍使用鸭式反应。当他们变得成熟时,他们开始使用 rails。Rails 具有易于理解项目的优势。

丹·阿布拉莫夫在推特上发布了一个解决方案👉

移动文件,直到感觉合适为止。

这正是你应该做的。你应该移动文件,直到他们觉得合适。

2.微小功能元件🤏

众所周知,React 可以处理大型组件。但是如果我们把它们分成小块,我们可以重复使用它们。小组件更容易阅读、测试、维护和重用。大多数 React 初学者创建类组件,即使他们没有使用组件状态或生命周期方法。功能组件对于简单组件来说效率更高。

上面的类组件可以编写如下。

使用功能组件的优势。

  • 较少代码
  • 更容易理解
  • 无国籍的
  • 更容易测试
  • 没有this绑定。
  • 更容易提取更小的成分。

当您使用功能组件时,您无法控制重新渲染过程。当某些东西改变甚至组件自身改变时,React 会重新渲染功能组件。在以前的 react 版本中有一个解决方案可以使用React.PureComponent。PureComponent 允许浅层 props 和状态比较。当组件的道具或内容或组件本身发生变化时,组件会重新呈现。否则,PureComponent 跳过重新渲染,而是重用最后一次渲染的结果。

React v16.6.0 之后 React 引入了一个新特性,那就是备忘录。Memo 浅比道具。当组件的道具或内容或组件本身发生变化时,组件会重新呈现。根据比较结果,react 将重用上次渲染的结果或重新渲染。Memo 允许你创建一个纯粹的功能组件。Memo 抹杀了有状态组件和PureComponent的使用。

Components, Picture credit: https://www.kirupa.com/react/images/c_app_144.png

3.可重用组件♻️

每个功能组件应该有一个功能,这意味着一个功能组件等于一个功能。当你创建一个具有一个功能的功能组件时,你可以提高组件的可重用性。

4.删除冗余代码🗑️

不仅在 React 中,而且在所有应用程序开发中,通用规则是尽可能保持代码简洁。反应最佳实践指示保持无错代码和精确代码。不要重复你自己(DRY)是软件开发的一个原则,专注于最大限度地减少软件模式的重复,用抽象来代替它,或者使用数据规范化来避免冗余。在代码设计中,你可以使用你自己的风格指南,或者使用一个流行的成熟的风格指南( Airbnb React/JSX 风格指南脸书风格指南等等)。如果你开始追随任何一种风格的人,不要和其他人混淆。

Picture credit: https://quotefancy.com/quote/46568/Lemony-Snicket-Don-t-repeat-yourself-It-s-not-only-repetitive-it-s-redundant-and-people

5.作为关键字的索引🔑

当创建一个 JSX 元素的数组时,react 要求你给你的元素添加一个关键道具。这通常是通过使用映射函数来完成的,而映射函数又会导致人们使用索引来设置键属性。这太糟糕了!React 使用 key 属性来跟踪数组中的每个元素,并且由于数组的折叠性质。这很容易导致错误的信息出现在错误的地方。这在用状态循环遍历类组件时尤其明显。

6.不必要的🚫

当创建 React 组件时,记住您仍然在构建 HTML 文档是很重要的。人们倾向于在 React 中使用divitis,最终导致不正确的 HTML。

在上面的例子中,divul的直接子节点,这是不正确的 HTML,而在下面的例子中,liul的直接子节点,这是正确的 HTML。

我们可以使用另一种使用<React.Fragment>标签的方法。<React.Fragment>是在 React v16.2 中引入的,我们可以用它们来代替无关的<div>标签。

7.仅必要的注释📝

必要时在应用程序中添加注释。从应用程序中移除注释的能力意味着我必须编写有文化的代码,没有例外。它给出了混乱的自由代码段。一般来说,注释是糟糕设计的一个标志,尤其是冗长的注释,很明显开发者不知道他们在做什么,试图通过写注释来弥补。

Picture credit: https://www.toptal.com/sql/guide-to-data-synchronization-in-microsoft-sql-server

8.理解处理“这个”👆

因为功能组件不需要this绑定,所以只要有可能,你就会想要使用它们。但是如果你使用的是 ES6 类,你需要手动绑定它,因为 React 不会自动绑定组件中的函数。这里有一些这样做的例子。

1:绑定渲染

将以下代码片段添加到名为 bind in render 的渲染中

onClick={this.logMessage.bind(this)}

这种方式清晰、简洁且可行,但可能会导致轻微的性能问题,因为每次组件重新渲染时都会调用新的函数,这可能会很频繁。

例 2:渲染中的箭头功能。

将以下代码片段添加到 render 中名为 arrow function 的渲染中。

onClick={() **=>** this.logMessage()}

这种方式清晰、简洁,就像示例 1 一样,但是像示例 1 一样,它也会在每次组件呈现时创建一个新函数。

例 3:绑定构造函数

将以下代码片段添加到名为 bind in constructor 的构造函数中。

this.logMessage = this.logMessage.bind(this);

这种方法将解决示例 1 和示例 2 的潜在性能问题。不要忘记在构造函数中调用 super。

例 4:类属性 中的箭头函数

将以下代码片段添加到类属性中名为 arrow function 的类中。

logMessage = () **=>** {
**const** { message } = this.state;
console.log(message);
}

这种方式非常简洁、易读,它将避免例 1 和例 2 中的性能问题,并避免例 3 中的重复。但是要注意,这种方法依赖于实验特性,它不是 ECMA 脚本规范的正式部分。您可以通过安装和配置 babel 包来试验语言功能,create react 应用程序创建的应用程序启用了许多功能。

Picture credit: https://codeburst.io/javascript-arrow-functions-for-beginners-926947fc0cdc

9.道具-状态-构造器🏁

我们可以把标题分成两个子标题,如。

  • 初始状态的时候不要用道具。
  • 不要在类构造函数内部初始化组件状态。

当你在初始状态使用 props 时,问题是当组件被创建时构造函数被调用。所以构造函数只被调用一次。如果您下次对 props 进行更改,组件状态将不会更新,它将保持与以前的值相同。您可以使用 react 生命周期方法componentDidUpdate来解决这个问题。当属性改变时,componentDidUpdate方法更新组件。componentDidUpdate在初始渲染时不会被调用。但是,在初始状态下使用道具并不是最好的做法。

将状态初始化为类字段是最佳实践。用构造函数初始化组件状态并没有那么糟糕,但是它增加了代码中的冗余,并产生了一些性能问题。当你初始化类构造函数内部的状态时,它会不必要地调用 super 并记住 props,这会造成性能问题。

另一个问题是,当你要在构造函数中初始化状态时,想想你需要多少行,你需要constructor()super()

Picture credit: https://indepth.dev/in-depth-explanation-of-state-and-props-update-in-react/

10.最终命名🔚

键入脚本后命名一个函数或组件,因为它们应该易于识别。比如你因为组件代码,瞬间选择了FacebookButton这样的组件名称。但是将来你可能会用那个组件作为TwitterButtonYoutubeButton。因此,最佳实践是将该组件命名为Button。通常,当您完成函数时,您应该能够为组件和函数选择通用名称。最后命名增加了可重用性。

11.意识到状态和渲染🎭

在 React 中,我们可以根据状态对组件进行分类。有 有状态无状态 。有状态组件存储组件的状态信息,并提供必要的上下文。反过来,无状态组件没有内存,也不能给用户界面部分提供上下文。无状态组件是可伸缩的、可重用的,就像纯 JavaScript 函数一样。将有状态提取逻辑与呈现无状态逻辑分开。一个更好的方法是使用有状态组件获取数据,使用另一个无状态组件显示获取的数据。

在 React v16.08 之后有一个新特性叫做“React Hooks”。React 钩子编写有状态的功能组件。React 钩子取消了类组件的使用。

如果数据没有在 render 方法中直接呈现,它就不应该处于组件状态。未直接呈现的数据可能会导致不必要的重新呈现。

Picture credit: https://www.barrymichaeldoyle.com/sub-rendering/

12.避免“setstate”🛑内的对象

根据 React 文档 React 不保证立即应用阶段更改。因此,在调用setState之后立即读取this.state是一个潜在的陷阱,因为this.state实际上可能不是你所想的那样。

**const** { ischecked } = this.state;
this.setState({ischecked: !ischecked});

我们可以使用下面的函数,而不是像上面的代码片段那样更新对象的状态。

this .setState((prevState, props) => {
return {ischecked: !prevState.ischecked}
})

上面的函数将接收先前的状态作为它的第一个参数,并将应用更新时的props作为它的第二个参数。状态更新是异步操作,所以要更新状态对象,我们需要使用带有setState的 updater 函数。

13.使用大写骆驼名称🐪

当你在 React 中工作时,记住你使用的是 JSX (JavaScript 扩展)而不是 HTML。你创建的组件应该用上驼格命名,又名 帕斯卡格 。大写骆驼字母表示单词书写时没有空格,每个单词的第一个字母大写。例如,如果有一个名为selectbutton的组件,那么你应该将其命名为SelectButton而不是selectbutton。使用大写骆驼有助于 JSX 区分默认的 JSX 元素标签和创建的元素。但是,您可以使用小写字母来命名组件,但这不是最佳做法。

Photo by Artem Sapegin on Unsplash

14.利用支柱型🧪

“prop-types”是一个用于类型检查道具的库,它可以通过确保你为你的道具使用正确的数据类型来帮助防止错误。React.PropTypes从 React v15.5 开始,已经转移到一个不同的包中。React.PropTypes包让我们能够对组件的属性进行类型检查,并赋予它默认值。因此,npm install 将使用一个外部库。

npm i prop-types

导入库,添加PropTypes到组件,相应地设置数据类型,如果需要道具,添加isRequired,如下所示。

可以使用defaultProps将默认值分配给属性。当一个组件没有收到它的道具时,它指的是已经赋值的defaultProps 。如果你已经按要求标记了你的道具,就不需要分配defaultProps。在下面的代码片段中,您可以看到所有已经分配给 ModalButton 的属性的默认值。对于这个例子,我使用了 React Bootstrap 框架。

始终为所有可选属性定义显式 defaultProps

需要注意的是,做类型检查时使用PropsTypes 后赋值defaultProps 因此,它也对分配给属性的默认值进行类型检查。

15.JavaScript 中的 CSS💅

在我的实习工作中,我们面临一个造型问题,尤其是主题。CSS 已在开发环境中加载,但没有在生产环境中加载。我的队友哈里斯·桑卡帕写了那个问题。但是现在我根据不同的应用找到了这么多最好的方法。

当你有一个大的 CSS (SCSS)文件时,你可以使用全局前缀,后跟块-元素-修饰符约定来避免名字冲突。当您的应用程序变得更大时,这种方法是不可伸缩的。所以你必须评估你的 CSS(SCSS)文件。还有另一种通过 webpack 的迷你 CSS 提取文本插件提取 CSS 的方法(它需要 webpack 4 才能工作),但它对 webpack 产生了严重的依赖性。如果你使用这种方法,测试你的组件是困难的。最佳实践是拥有一个易于测试的应用程序,因此,遵循这种方法并不是最佳实践。

EmotionJSlaminateStyled Components 是 JS 库中的一些新 CSS。您可以根据您的用例来使用它们。当你需要生成一个编译好的 CSS 时,你可以使用 EmotionJS 库。当你有一个复杂的主题问题时,你可以使用迷人的和风格化的组件库。

Picture credit: https://wordpress.org/plugins/custom-css-js/

16.测试🚀

不仅在 React 中,在其他编程语言中也应该进行测试。测试是很重要的,因为它确保代码如预期的那样运行,并且可以简单快速地测试。在最佳实践中,在组件文件夹中创建一个__Test__文件夹。用组件名加上一个.test.js后缀来创建测试文件。您可以将 Jest 用作测试程序,将 Enzyme 用作 React 的测试工具。我的队友卡温杜文迪卡写了关于的笑话和酶测试,如果你想你可以看看。

对组件进行崩溃测试是一种简单快速的方法,可以确保所有组件都正常工作而不会崩溃。组件崩溃测试很容易应用到你制作的每个组件中。

你应该做明显比碰撞测试更广泛的测试。如果你写更多的测试用例,它会给你的代码更多的测试覆盖率。但是,至少你应该做一些碰撞测试。在崩溃测试中,我们所做的是创建一个元素,然后它使用 ReactDom 并装载您导入到刚刚创建的 div 中的任何组件,然后它卸载 div。

一个真正的 react 开发人员会对整个 React 应用程序进行适当的测试。

17.使用 ESLint、Prettier 和 snippet 库📚

ESlint 用歪歪扭扭的字体对你大喊大叫,让你的代码保持整洁。您可以将它链接到您的 IDE。最佳实践是保留您自己的 ESLint 配置文件

一个好的开发人员会修复所有的 ESlint 错误和警告,而不是禁用那个错误。

更漂亮是一个代码格式化工具。漂亮有一套代码格式和缩进的规则。您可以使用 Sonarlint 来检查法术、功能长度和更好方法的建议。使用 Husky 不仅对 React 是一个好的实践,对 Git 也是一个好的实践。可以在 package.json 文件中定义哈士奇。Husky 防止您的应用程序出现错误提交和错误推送。

代码片段有助于您编写最佳代码和趋势语法。它们使你的代码相对没有错误。你可以使用很多代码片段库,比如 ES7 React,JavaScript (ES6)代码片段等。

Picture credit: https://medium.com/dubizzletechblog/setting-up-prettier-and-eslint-for-js-and-react-apps-bbc779d29062

18.使用 React 开发工具🛠️

React Developer Tools 是 Chrome 和 Firefox 的扩展。如果您使用 Safari 或其他独立 shell,请使用以下命令来安装它。

npm install -g react-devtools@^4

如果您正在寻找 React 中内置的 web 应用程序,您可以在 Components 选项卡中看到组件层次结构。如果您点击一个组件,您可以查看该组件的属性和状态。如你所见,React Developer Tools extension 是一款非常有价值的工具,可用于测试和调试,并真正了解该应用程序发生了什么。

结论✌️

本文描述了 React 中的最佳实践。这些实践提高了您的应用程序性能、应用程序代码和编码技能。作为我的第 25 篇文章,我想动态更新这篇文章。这意味着我会用新的趋势来更新这篇文章。如果我更新这篇文章,我会通过推特通知。保持联系。呜哇!!!🙌

快乐编码😎

关注我的Twitter和 Medium 如果你将来对这些更深入、更翔实的文章感兴趣的话!

React Native 推出其最新版本 0.60

原文:https://towardsdatascience.com/react-native-introduces-its-latest-version-0-60-a855b08fd383?source=collection_archive---------21-----------------------

React Native 是最受欢迎的移动应用程序开发框架之一,它的高级特性和创建功能丰富的跨平台移动应用程序的能力一直吸引着开发者和企业。

凭借其显著的特性,这种混合应用程序开发框架比其他框架节省了创建应用程序的时间。它有助于减少大约 40%到 50%的移动应用程序开发费用。

经过几个月的努力和奉献,近日,React Native 宣布推出最新版本 0.60。如今,用户很高兴看到 React Native 新版本的每个功能。根据 Stack Overflow 调查,React native 是目前第二受欢迎的框架:

Source

下面我们来了解一下 React 原生 0.60 的各种新特性:

React Native 的最新版本可以处理 Android 和 iOS 平台的各种重要迁移,旧版本 0.59 中的其他小问题也通过最新更新得到了解决,以提供更好的用户界面和体验。

以下是最新的 React 原生 0.60 中的一些其他变化:

可访问性的改进

最新的 0.60 版本发布了针对 Android 和 iOS 的可访问性 API 前端的多项改进。所有的改进虽然范围很广,但都包含了一些元素,例如宣布可访问性,以及角色、动作支持、标志等方面的改进。react native 的开发团队希望,随着这些进步,成为 A11Y(可访问性的数字符号)会更容易。Reach Native 0.60 在可访问性方面有更多改进,包括:

为各种元素包含过多的缺失角色,以便根据需求有效地使用它。

包括点击回叫和一个可点击的道具,有助于使用键盘导航来请求操作。

通过最新的可访问性状态 API,保证在未来的运行中增强 web 协助。

启用最大的可访问性操作,以便添加回调来处理用户特定的功能可访问性。

最新的 0.60 版本引入了大量的改进,同时引入了一些元素,如宣布可访问性、动作支持改进、标志和角色等等。

所有新屏幕

React 的最新版本带有新的应用程序屏幕,据称更加用户友好。它显示了有用的说明,例如文档链接,编辑 App.js,如何启动调试菜单,以及最后如何与即将到来的网站设计和重新设计保持一致。新的用户界面“Hello world”将以更好的方式向手机用户介绍生态系统。

支持 AndroidX

随着 React Native 与 Android 扩展库(AndroidX)的迁移,原生代码和依赖项也应该迁移。由于这种转变,所有的 React 原生应用将不得不自己使用 AndroidX。虽然,React Native 的开发团队已经针对这个问题开发了一个名为“Jetifier”的临时解决方案。它是一个 AndroidX 过渡工具,风格与 React Native 兼容。

操作系统自动链接

React Native 的库通常由本机代码和特定于平台的代码组成。这种新机制还允许您的项目发现并再次使用该代码。React Native 的 CLI 团队在自动链接中引入了类似这样的重大改进。

CocoaPods 作为 iOS 的一部分

CocoaPods 是一个应用级依赖管理器,是为 Objective-C Cocoa 项目和 Swift 设计的。现在,React Native 在 iOS 中默认自带 CocoaPods。现在要求手机 app 开发者使用“xcworkspace”文件打开 iOS 开发平台 代码。

精益旧件移除

React Native 的新变化包括将 NetInfo 和 Webview 放在单独的存储库中。它们已从 React Native 的存储库中成功删除。此外,基于社区反馈,地理定位已被移除。

升级助手

React native 的开发人员构建了一个名为“升级助手”的伟大工具,以使升级过程变得非常简单。它还可以帮助用户对棕色地带应用程序或复杂的自定义应用程序进行本地反应,以了解它们的版本之间发生了哪些变化。快速浏览最新的升级文档

给库维护者的一个快速提示

AndroidX 的所有改动几乎都需要更新库,所以请务必尽快加入支持。如果您还不能升级您的版本,您可以考虑根据 Jetifier 检查库,以便确认用户可以在构建时修补您的库。

您还可以查看自动链接文档,以更新您的自述文件和配置。根据之前库的集成方式,您可能需要进行一些额外的更改。为此,您可以从 CLI 查看依赖关系指南,了解定义依赖关系接口的不同方法的信息。

让我们总结一下:

脸书创始人马克·扎克伯格在 2012 年评论说,“作为一家公司,我们犯的最大错误之一是在 HTML 而不是原生语言上下了太多赌注”。基于以上陈述,我们可以得出结论,React 原生框架比其他选择更好。你不必相信我们的话,因为你可以通过事实自己看出来。随着 react native 的最新更新,我们可以看到对该平台的需求不断增长,其用户群可能会随着时间的推移而增强。

除此之外,为 Android 和 iOS 构建的移动应用在这两个平台上将保持相似。对于未来,预测这种混合型 手机 app 开发平台 点播会更高。此外,随着时间的推移,其用户基础可能会有所改善。

react native 的最新进步引发了在印度雇佣最佳移动应用程序开发公司的需求,因为大多数 软件开发公司 将 react native 作为其跨平台应用程序开发的首选。如果你也在寻找 react 本地开发解决方案,你可以联系这些公司,你会得到你所需要的最好的服务。

反应扩散模型与数据可视化

原文:https://towardsdatascience.com/reaction-diffusion-model-and-data-visualization-f66fd6116bf?source=collection_archive---------21-----------------------

在科学界,模型是一个概念的表示,可以用来模拟和帮助描述一个想法。如果模型足够接近真实世界,它也可以用来预测在一系列条件下会发生什么。常见的一种模型表示是天气图,如下所示。

National Centers for Environmental Prediction [Public domain], via Wikimedia Commons

天气图是天气模型的可视化表示。天气模型接收许多位置的输入,如温度、压力、风速和其他参数,在处理这些信息后,它可用于描述和预测天气。模型要考虑的另一个方面是它们可能是错误的。任何根据天气预报出门时不打伞的人都知道这一点。因此,记住模型通常是真实世界的不完美再现是很重要的。然而,这并不意味着它们没有用处。

例如,当一个物理系统被很好地理解时,可以开发一个模型来允许系统内的实验在虚拟环境中运行。这使得科学家能够探索系统参数的变化,这可能允许他们发现给定目标的最佳条件集。人们可能选择创建模型而不是在系统上进行物理实验的原因是,在探索最佳系统条件的任务中,收集一系列参数的足够数据常常是昂贵且耗时的。一个这样的系统是反应扩散模型。

涉及反应和扩散的化学系统具有许多变量,并且当涉及的组件是昂贵的时,在整个参数域上运行试验是不可行的。这种类型的系统的一个模型将在这篇文章中介绍。具体来说,本文中的模型将代表发生在立方体化学阱中的反应和扩散,其中活性位点吸附在阱的壁和底部。这些井与下图中的井相似,但几何形状将是立方体而不是圆柱形。井的表面充满了反应位点,井溶液中的化学物质与这些位点相互作用。

Obtained from Wikimedia Commons

Obtained from https://www.hitbullseye.com

反应空间是一个立方体,它将被分成更小的立方体,就像左边的立方体一样。大立方体的尺寸将是 10×10×10 的小立方体,以下称为单元。该模型将通过开发一个具有四个维度的数组来工作:x、y、z 和 t。这四个维度分别代表 x、y 和 z 空间维度以及时间维度。每个数组索引的值将代表该空间和时间的浓度。

毫不奇怪,反应扩散模型中的两个重要因素是反应和扩散。反应只发生在井壁,但扩散发生在整个系统。反应后,化学物质被认为是从系统中清除。扩散后,化学品从一个井移动到另一个井,但不会从系统中移除。

首先,必须用初始条件来定义系统。这些包括扩散常数、每个单元边的长度、模拟时间的长度、时间步长的长度、单元的初始浓度、初始井表面位置浓度、吸附和解吸的速率常数以及吸附的化学物质的初始浓度。

在时间 0,所有细胞都等于初始浓度。下一个时间步骤的细胞浓度是通过从每个细胞中去除由于反应而损失的化学物质,并基于感兴趣的细胞和所有相邻细胞之间的浓度差计算来自扩散的细胞浓度变化来计算的。完成此任务的 python 代码如下所示。

"""
D = Diffusivity constant in m^2/s
r = length of each dimension of cubic well in meters
n = number of partitions in each dimension of cubic well
tf = length of time of simulation
dt = numerical integration time step
initial_conc = initial concentraion of well solution
dx = r/n
nt = tf/dt
xrn is in moles per time
Aconc and Sconc are in moles per m^2
k_des is in per time
k_ad is in per M per t
dx is in m
rxnDMtot is total change in cube molarity due to reaction"""
stracker = 0
D = 1 * 10 ** -5
r = 0.0048
tf = 0.1
dt = 0.000001
n = 10
nt = int(tf / dt)
dx = r/n
initial_conc = 2.5 * 10 ** -5
import numpy as np
conc = np.zeros([n,n,n,nt+5])
for i in range(0, n):
    for j in range(0, n):
        for k in range(0, n):
            conc[i, j, k, 0] += initial_conc
#print(conc)
Sconc = 1 * 10 ** -8 #surface site concentration
Aconc = np.zeros([nt+6]) #adsorbed concentration
Dfactor = D *dt/(dx ** 2)
k_ad = 1 * 10 ** 7
k_des = 1 * 10 ** -6
Sconc = 1
Aconc[0] = 0
time_list = []
Aconc_list = []
SminusA_conc_list = []
for t in range(0, nt + 6):
    for i in range(0, n):
        for j in range(0,n):
            for k in range(0,n):

                #start of neighbor unit diffusion calculations

                if i == n - 1:
                    xposdiff = 0
                else:
                    xposdiff = Dfactor * (conc[i + 1, j, k, t] - conc[i, j, k, t])if i == 0:
                    xnegdiff = 0
                else:
                    xnegdiff = Dfactor * (conc[i - 1, j, k, t] - conc[i, j, k, t])

                if j == n - 1:
                    yposdiff = 0
                else:
                    yposdiff = Dfactor * (conc[i, j + 1, k, t] - conc[i, k, k, t])

                if j == 0:
                    ynegdiff = 0
                else:
                    ynegdiff = Dfactor * (conc[i, j - 1, k, t] - conc[i, j, k, t])

                if k == n - 1:
                    zposdiff = 0
                else:
                    zposdiff = Dfactor * (conc[i, j, k + 1, t] - conc[i, j, k, t])

                if k == 0:
                    znegdiff = 0
                else:
                    znegdiff = Dfactor * (conc[i, j, k - 1, t] - conc[i, j, k, t])

                #end of neighbor unit diffusion calculations

                #start of neighbor unit reaction calculations

                if i == 0 or i == n - 1:
                    xrxn = dx ** 2 * (k_ad * conc[i, j, k, t] * (Sconc - Aconc[t]) - k_des * Aconc[t])              #xrn is in moles per time, Aconc and Sconc are in moles per m^2, k_des is in per time, k_ad is in per M per t, dx is in m
                else:
                    xrxn = 0

                if j == 0 or j == n - 1:
                    yrxn = dx ** 2 * (k_ad * conc[i, j, k, t] * (Sconc - Aconc[t]) - k_des * Aconc[t])
                else:
                    yrxn = 0if k == 0:
                    zrxn = dx ** 2 * (k_ad * conc[i, j, k, t] * (Sconc - Aconc[t]) - k_des * Aconc[t])
                else:
                    zrxn = 0

                #end of neighbor unit reaction calculations#calculates total molarity change due to reactions
                rxnDMtot = -(xrxn + yrxn + zrxn) * dt / (dx * 10) ** 3           #total change in cube molarity due to reaction#limits change in concentration due to reaction because time step minimization is limited by processing power
                if rxnDMtot < -1 * conc[i, j, k, t]:
                    rxnDMtot = -1 * conc[i, j, k, t]

                #keeps track of the surface site concentration
                stracker = stracker - rxnDMtot * (dx * 10) ** 3#uses the current unit concentration and the reaction and diffusion changes to calculate the unit concentration at the next time step
                conc[i, j, k, t + 1] = conc[i, j, k, t] + xposdiff + xnegdiff + yposdiff + ynegdiff + zposdiff + znegdiff + rxnDMtot

    Aconc[t + 1] = Aconc[t] + stracker / (5 * r ** 2)
    stracker = 0
    time_list.append(t * dt)
    Aconc_list.append(Aconc[t])
    SminusA_conc_list.append(Sconc - Aconc[t])for i in range(0, n):
    for j in range(0,n):
        for k in range(0,n):

            totalconc = totalconc + conc[i, j, k, nt] * (dx * 10) ** 3totalconc = totalconc / ((r * 10) ** 3)
totalconc = totalconc + Aconc[nt] * 5 * r ** 2 / (r * 10) ** 3

我承担这个项目的主要原因之一是因为我想发展我使用 python 呈现信息的技能。显示包含细胞浓度的四维数组将需要五维来显示三个空间维度、浓度和时间。这可以通过三维动画热图来实现。我可能会回到这个项目来完成显示所有的信息在稍后的时间。目前,我已经开发了 gif,使用了 z 维度固定的细胞浓度的等间隔时间快照。这意味着 x 和 y 轴将代表细胞在 x 和 y 方向上的位置,垂直轴将代表每个细胞的浓度,时间维度将由动画表示。显示的 z 坐标显示在每个 gif 下面。

The second from the bottom layer (z = 1)

The fourth from the base (z = 3)

你可以看到反应空间两侧细胞中的浓度立即下降到零。我们将这些细胞称为壁细胞,因为它们与反应空间的壁接触。壁细胞中的浓度比内部细胞下降更快的原因是因为壁细胞是唯一由于反应而损失浓度的细胞。扩散导致溶质从高浓度流向低浓度。由于浓度高于壁细胞,扩散导致内部细胞的浓度在反应开始后开始下降,因为溶质向壁净转移。

不幸的是,这不是一个完美的模型,因为有更复杂的方法来更准确地描述这个系统,而且时间步长不够小,不能准确地反映现实。

承认

约翰·罗勃兹,因为他开发了最初的 VBA 模型。

卢克·博尔斯对他在图形开发方面的协助表示感谢。

芳芳,凯文和卡罗琳的指导。

图形和 Gif 生成 Python 代码

import matplotlib
!pip install imageio
import mpl_toolkits
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
!pip install --upgrade matplotlibdef plot_looper(snapshot_number, z_level):
    #this will only work correctly with n = 10
    t = 0
    file_title = 'z'
    while t < tf / dt:
        fig = plt.figure()
        ax = fig.add_subplot(111, projection = '3d')
        X = [[0,1,2,3,4,5,6,7,8,9],[9,0,1,2,3,4,5,6,7,8],[8,9,0,1,2,3,4,5,6,7],[7,8,9,0,1,2,3,4,5,6],[6,7,8,9,0,1,2,3,4,5],[5,6,7,8,9,0,1,2,3,4],[4,5,6,7,8,9,0,1,2,3],[3,4,5,6,7,8,9,0,1,2],[2,3,4,5,6,7,8,9,0,1],[1,2,3,4,5,6,7,8,9,0]]
        Y = [[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9]]
        Z = conc[X,Y,z_level, t]

        file_title += 'z'
        ax.scatter(X, Y, Z, c = 'r', marker = 'o')
        fig.savefig(f'model_image{file_title}'.format('PATH/x'))
        print(t)
        t += 1000

import os
import imageio
png_dir = 'PATH/Model_Images'
images = []
for file_name in os.listdir(png_dir):
    if file_name.endswith('.png'):
        file_path = os.path.join(png_dir, file_name)
        images.append(imageio.imread(file_path))
imageio.mimsave('PATH/model.gif', images)

用一行 Python 代码从图像中读取文本

原文:https://towardsdatascience.com/read-text-from-image-with-one-line-of-python-code-c22ede074cac?source=collection_archive---------0-----------------------

处理图像不是一件小事。对你来说,作为一个人,很容易看到某样东西,并立即知道你在看什么。但是电脑不是这样工作的。

Photo by Lenin Estrada on Unsplash

对你来说太难的任务,像复杂的算术和一般的数学,是计算机不费吹灰之力就能完成的。但是在这里正好相反适用于——对你来说微不足道的任务,比如识别图像中是猫还是狗,对计算机来说真的很难。在某种程度上,我们是天造地设的一对。至少现在是这样。

虽然图像分类和涉及某种程度的计算机视觉的任务可能需要一些代码和扎实的理解,但从某种程度上格式良好的图像中读取文本却是 Python 中的一行程序——可以应用于许多现实生活中的问题。

在今天的帖子中,我想证明这一点。虽然还有一些安装工作要做,但应该不会花太多时间。这些是您需要的库:

  • OpenCV
  • 宇宙魔方

我不想再长篇大论这个介绍部分了,所以我们现在为什么不进入正题呢?

OpenCV

现在,这个库将只用于加载图像,你实际上不需要事先对它有一个坚实的理解(虽然它可能是有帮助的,你会看到为什么)。

根据官方文件:

OpenCV(开源计算机视觉库)是一个开源的计算机视觉和机器学习软件库。OpenCV 旨在为计算机视觉应用提供一个公共基础设施,并加速机器感知在商业产品中的应用。作为一个 BSD 许可的产品,OpenCV 使得企业利用和修改代码变得很容易。[1]

简而言之,你可以使用 OpenCV 做任何种类的图像转换,这是一个相当简单的库。

如果您还没有安装它,它将只是终端中的一行:

pip install opencv-python

差不多就是这样。到目前为止,这很容易,但这种情况即将改变。

宇宙魔方

这到底是什么库? 嗯,根据维基百科:

Tesseract 是用于各种操作系统的光学字符识别引擎。它是自由软件,在 Apache 许可下发布,版本 2.0,自 2006 年以来一直由 Google 赞助开发。[2]

我确信现在有更复杂的库可用,但是我发现这个运行得很好。根据我自己的经验,这个库应该能够读取任何图像中的文本,前提是字体不是一些连你都无法读取的粗体字。

如果它不能读取你的图像,花更多的时间玩 OpenCV,应用各种过滤器使文本突出。

现在安装有点底层的痛苦。如果你使用的是 Linux,这可以归结为几个 sudo-apt get 命令:

sudo apt-get update
sudo apt-get install tesseract-ocr
sudo apt-get install libtesseract-dev

我用的是 Windows,所以这个过程有点繁琐。

首先,打开这个 URL ,下载 32 位或 64 位安装程序:

安装本身很简单,归结起来就是点击几次 下一个 。是的,你还需要做一个 pip 安装:

pip install pytesseract

就这些吗? 嗯,不是,你还是要告诉 Python 宇宙魔方安装在哪里。在 Linux 机器上,我不需要这样做,但是在 Windows 上是必须的。默认安装在 程序文件 中。

如果您做的一切都是正确的,那么执行这个单元格应该不会产生任何错误:

一切都好吗?你可以继续了。

阅读课文

先说一个简单的。我发现了几个包含某种文字的免版税图片,第一个是这样的:

https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Wikinews_Breaking_News.png/800px-Wikinews_Breaking_News.png

这应该是最简单的,并且有可能宇宙魔方会把那些蓝色的“物体”读成括号。让我们看看会发生什么:

我的主张是真实的。不过这不是问题,你可以用 Python 的魔法轻松解决这些问题。

下一个可能更棘手:

https://live.staticflickr.com/7892/46879778504_3b11c328b0_b.jpg

我希望它不会发现硬币上“B ”:

看起来效果很好。

现在就看你把这个应用到你自己的问题上了。如果文本与背景融为一体,OpenCV 技巧在这里可能至关重要。

在你离开之前

对于计算机来说,从图像中读取文本是一项非常困难的任务。想想看,计算机不知道什么是字母,它只对数字起作用。在引擎盖后面发生的事情起初可能看起来像一个黑箱,但是如果这是你感兴趣的领域,我鼓励你进一步调查。

我不是说 PyTesseract 每次都能完美地工作,但是我发现它甚至在一些复杂的图像上也足够好了。但不是直接从盒子里拿出来的。需要一些图像处理来突出文本。

我知道这是个复杂的话题。过一天算一天。总有一天它会成为你的第二天性。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

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

参考

[1]https://opencv.org/about/

[2]https://en . Wikipedia . org/wiki/tessera CT _(软件)

读者选择的 10 篇最佳数据文章

原文:https://towardsdatascience.com/readers-choice-10-best-data-articles-714006b178e3?source=collection_archive---------16-----------------------

数据科学收藏中您最喜欢的博客文章

我问社区,这个博客的哪些文章特别能引起他们的共鸣…下面是列表!

Image from the 1927 film Metropolis.

AI:用更多的精力更快地做蠢事!

头发尖尖的老板是启示录……中的四骑士之一

[## 人工智能:用更多的精力更快地做蠢事!

在数据推动的时代,我们为什么需要新一代的领导者

towardsdatascience.com](/artificial-intelligence-do-stupid-things-faster-with-more-energy-379aa6bac220)

#9 注意窗帘后面的那个男人

数学会掩盖人的因素,给人一种客观的错觉

[## 注意窗帘后面的那个人

人工智能偏见和公平的严酷事实

medium.com](https://medium.com/hackernoon/ai-bias-and-what-you-can-do-about-it-4a6ae48b338e)

#8 数据驱动?再想想

如果没有决策基础,你的决策最多会受到数据的启发,而不是由数据驱动

[## 数据驱动?重新考虑

大多数人缺乏的心理习惯以及为什么你不能希望用数据有效地指导你的行动而不…

medium.com](https://medium.com/hackernoon/data-inspired-5c78db3999b2)

#7 为什么企业在机器学习上失败

当谈到机器学习时,许多组织都做错了生意

[## 为什么企业在机器学习上失败了

我想告诉你一个秘密:当人们说“机器学习”时,听起来好像这里只有一个学科…

medium.com](https://medium.com/hackernoon/why-businesses-fail-at-machine-learning-fbff41c4d5db)

#6 你读过的关于机器学习的最简单的解释

机器学习是一种新的编程范式,一种向计算机传达你的愿望的新方式

[## 你读过的关于机器学习的最简单的解释

你可能听说过机器学习和人工智能,但你确定你知道它们是什么吗?如果…

medium.com](https://medium.com/hackernoon/the-simplest-explanation-of-machine-learning-youll-ever-read-bebc0700047c)

#5 分析和统计有什么区别?

分析帮助你形成假设。它提高了你的问题的质量。统计学帮助你测试假设。它提高了你答案的质量

[## 分析和统计有什么区别?

理解两种完全不同职业的价值

towardsdatascience.com](/whats-the-difference-between-analytics-and-statistics-cd35d457e17)

#4 数据科学到底是什么?

请看我最精辟的尝试:“数据科学是让数据变得有用的学科”现在可以随意逃离或者逗留在它的三个分区域

[## 数据科学到底是什么?

寻求一个有用的定义

bit.ly](http://bit.ly/quaesita_datasci)

#3 对匆忙人群的统计

简而言之,测试:“我们的证据让零假设看起来可笑吗?”

[## 为赶时间的人统计

曾经希望有人能告诉你统计学的意义是什么,术语用简单的英语表达是什么意思吗?让…

towardsdatascience.com](/statistics-for-people-in-a-hurry-a9613c0ed0b)

#2 数据科学最被误解的英雄

优秀的分析师是数据工作取得成效的先决条件。让他们放弃你是很危险的,但是如果你低估了他们,他们就会这么做

[## 数据科学最被误解的英雄

为什么像对待二等公民一样对待分析会伤害你

towardsdatascience.com](/data-sciences-most-misunderstood-hero-2705da366f40)

#1 什么是决策智能?

基于纯数学理性的策略相对幼稚,往往表现不佳...

[## 什么是决策智能?

人工智能时代领导力的新学科

towardsdatascience.com](/introduction-to-decision-intelligence-5d147ddab767)

对结果感到惊讶?我也是!我个人最喜欢的五个不在名单上。【1234【5】义愤填膺?把你认为应该更突出的文章分享给你的朋友。**

以下是该列表在社交媒体上分享的链接:

  1. bit.ly/quaesita_di
  2. bit.ly/quaesita_hero
  3. bit.ly/quaesita_statistics
  4. bit.ly/quaesita_datasci
  5. bit.ly/quaesita_versus
  6. *【bit.ly/quaesita_simplest *
  7. bit.ly/quaesita_fail
  8. bit.ly/quaesita_inspired
  9. bit.ly/quaesita_aibias
  10. bit.ly/quaesita_genie

【免费课程】和机器学习交朋友

如果你正在寻找一门为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:

Enjoy the entire course playlist here: bit.ly/machinefriend

阅读混淆矩阵

原文:https://towardsdatascience.com/reading-a-confusion-matrix-60c4dd232dd4?source=collection_archive---------8-----------------------

精确度,召回,f 分数,真阳性,假阴性,真阴性,假阳性…你困惑了吗?

Image from https://pixabay.com

本文将尝试解释上述术语,并演示如何阅读混淆矩阵,以便从中获取最多信息。

什么是混淆矩阵?

混淆矩阵是一种可视化分类结果的方法。您已经建立了一个分类模型,该模型预测了测试集上的一些值,并且您还有一些目标变量的实际值要与之进行比较。困惑矩阵将向你展示你的预测是否与现实相符,以及它们是如何更详细地计算的。

下面的混淆矩阵显示了预测值与实际值的对比,并给出了分类对的名称:真阳性、真阴性、假阴性和假阳性。我们将讨论每一个预测患者高血压的特殊例子的意义。

真阳性

我们现在将考虑 130 名患者的数据集,其中基于一些特征集,我们试图预测患者是否患有高血压。在数据集中,有 46 名患者有高血压,其余 84 名没有。我们已经运行了我们的分类算法,并绘制了我们的模型相对于实际值的预测值。混淆矩阵如下所示。我们可以看到我们得到了 34 个真阳性。这对应于患有高血压的患者,并且我们的模型正确地识别了他们。

真底片

我们可以看到,我们也得到了 78 个真负对。这意味着我们的算法已经正确地发现了 78 名没有高血压的患者(他们没有高血压,并且模型也预测他们没有)。真正的否定和真正的肯定是我们的模型做对的部分。我们希望找到能最大化这两者的模型。

误报

现在,我们开始关注我们的模型表现不佳的部分。假阳性代表我们的模型归类为有高血压的患者的数量,但实际上,他们没有。对病人来说可能不是一个严重的错误,但是对治疗病人没有的疾病的医院机构来说可能是昂贵的。假阳性也称为 1 型错误。

假阴性

假阴性代表患者有高血压,但我们的模型预测他们没有。它也称为第二类错误,这种错误的含义可能不同于第一类错误。在我们的情况下,后果甚至可能是严重的,因为那些患有高血压的患者将被诊断为健康的,而没有得到治疗。

精度

累积正确预测并将该数字放入所有实例的对比中的度量是准确性。它将真阳性和真阴性相加,然后除以所有实例的数量。

准确度的实际公式如下:

如你所见,我们将所有真值(真正值和真负值)相加,然后除以所有示例。在我们的例子中,这是(34+78)/130。我们得到的精度比 0.86 稍高一点。

重要的是要注意,有一些例子,准确性本身可能会产生误导。因此,在我们的例子中,有 84 名患者没有高血压,因此,一个只预测所有患者没有高血压的模型将获得 64%的准确性(84/130=0.64)。因此,我们希望使用其他指标来帮助模型评估。

精度

这是一个非常重要的概念。这是模型正确识别的高血压患者数(真阳性)除以模型预测的所有高血压患者数(真阳性和假阳性)。换句话说,它衡量的是在我们模型的正面预测中,正确识别的实例所占的比例。

回忆

召回代表正确识别的高血压患者(真阳性)除以患病患者总数(真阳性和假阴性)。换句话说,它衡量的是我们的模型能够正确识别的疾病患者的比例。

如果你仍然感到困惑,你可以把召回率理解为被模型正确分类的所有相关结果的百分比,把精确度理解为相关结果的百分比。

F 分数

精确度和召回率可以结合成一个单一的指标,称为 f-score。如果你对回忆和精确给予同等的重视,你可以用它来优化你的模型。如果你不强调回忆和精确更重要的话,这可能是一个很好的折中方案。公式如下所示,它结合了我们讨论过的两个指标。

结论

在这篇文章中,我介绍了一个混淆矩阵,并给出了可以从它导出的度量标准。在评估分类问题时,查看上面提到的所有指标是很重要的。然而,当试图优化或选择最佳模型时,增加一个指标可能会导致另一个指标下降。根据模型应用选择折衷方案并理解这些决策的含义是很重要的。

原载于 aboutdatablog.com: 阅读一个困惑矩阵2019 年 12 月 11 日。

PS:我正在 Medium 和上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的* 邮件列表 *每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入**

下面是一些你可能会喜欢的帖子

** [## python 中的 lambda 函数是什么,为什么你现在就应该开始使用它们

初学者在 python 和 pandas 中开始使用 lambda 函数的快速指南。

towardsdatascience.com](/what-are-lambda-functions-in-python-and-why-you-should-start-using-them-right-now-75ab85655dc6) [## Jupyter 笔记本自动完成

数据科学家的最佳生产力工具,如果您还没有使用它,您应该使用它…

towardsdatascience.com](/jupyter-notebook-autocompletion-f291008c66c) [## 当你开始与图书馆合作时,7 个实用的熊猫提示

解释一些乍一看不那么明显的东西…

towardsdatascience.com](/7-practical-pandas-tips-when-you-start-working-with-the-library-e4a9205eb443)**

层间阅读(LSTM 网络)

原文:https://towardsdatascience.com/reading-between-the-layers-lstm-network-7956ad192e58?source=collection_archive---------8-----------------------

使用 PyTorch 框架进行深度学习

Photo by Paul Skorupskas on Unsplash

构建深度神经网络的最关键部分之一是——当数据流经经历维度变化、形状改变、展平然后重新成形的层时,要有一个清晰的视图…

我们将参考之前在情感分析教程中看到的 LSTM 架构。链接到这篇文章。

[## 使用 LSTM 逐步进行情感分析

使用 PyTorch 框架进行深度学习

towardsdatascience.com](/sentiment-analysis-using-lstm-step-by-step-50d074f09948)

LSTM Network Architecture for Sentiment Analysis

这些层如下所示:

0.令牌化:这不是 LSTM 网络的一个层,而是将我们的单词转换成令牌(整数)的一个强制步骤

  1. 嵌入层:将单词标记(整数)转换成特定大小的嵌入
  2. LSTM 层:由隐藏状态变暗和层数定义
  3. 全连接图层:将 LSTM 图层的输出映射到所需的输出大小
  4. Sigmoid 激活层:将所有输出值转换为 0 到 1 之间的值
  5. 输出:最后一个时间步的 Sigmoid 输出被认为是该网络的最终输出

在定义模型类之前,仔细观察每一层会有很好的洞察力。这将有助于您更清楚地了解如何为模型架构的嵌入、LSTM 和线性层准备输入

背景:

我们正在使用 IMDB 电影回顾数据集,数据处理和准备步骤已经完成。如果您需要重新查看这些步骤,请点击此处的按钮。我们从数据加载器开始(我们已经定义了batch_size=50sequence length=200)。根据我关于使用 LSTM 构建情感分析模型的文章,我们正在用显微镜观察第 14 步——

  • 我们先来看看来自**inupts** **targets**
dataiter = iter(train_loader)
x, y = dataiter.next()
x = x.type(torch.LongTensor)
print ('X is', x)print ('Shape of X and y are :', x.shape, y.shape)

Reviews converted into tokens (integers)

X的形状我们可以看出X是一个 50 行(=批量)& 200 列(=序列长度)的张量。这确保了我们的令牌化过程运行良好。这个X将作为嵌入层的输入

  • 嵌入层:

允许你使用嵌入的模块是torch.nn.Embedding。它需要两个参数:词汇量和嵌入的维数

from torch import nnvocab_size = len(words)
embedding_dim = 30
embeds = nn.Embedding(vocab_size, embedding_dim)
print ('Embedding layer is ', embeds)
print ('Embedding layer weights ', embeds.weight.shape)

Embedding Layer ‘Weight Matrix’ or ‘Look-up Table’

embeds_out = embeds(x)
print ('Embedding layer output shape', embeds_out.shape)
print ('Embedding layer output ', embeds_out)

Input tokens converted into embedding vectors

从嵌入层的输出我们可以看到,由于嵌入了权重,它创建了一个三维张量。现在它有 50 行,200 列和 30 个嵌入维度,也就是说,在我们的评论中,对于每个标记化的单词,我们都添加了嵌入维度。这些数据现在将被传送到 LSTM 图层

  • LSTM 层:

在定义 LSTM 层时,我们保持 Batch First = True,隐藏单元数= 512。

# initializing the hidden state to 0
hidden=None
lstm = nn.LSTM(input_size=embedding_dim, hidden_size=512, num_layers=1, batch_first=True)
lstm_out, h = lstm(embeds_out, hidden)
print ('LSTM layer output shape', lstm_out.shape)
print ('LSTM layer output ', lstm_out)

Output of LSTM layer

通过观察 LSTM 层的输出,我们看到我们的张量现在有 50 行,200 列和 512 个 LSTM 节点。接下来,该数据被提取到完全连接的层中

  • 全连通层:

对于完全连接的图层,输入要素的数量= LSTM 中隐藏单元的数量。输出大小= 1,因为我们只二进制输出(1/0;正/负)

请注意,在将 lstm 输出放入 fc 层之前,必须将其展平。

fc = nn.Linear(in_features=512, out_features=1)
fc_out = fc(lstm_out.contiguous().view(-1, 512))
print ('FC layer output shape', fc_out.shape)
print ('FC layer output ', fc_out)

Output from Fully Connected Layer

  • 乙状结肠激活层:

只需要将全连接层的所有输出值转换为 0 和 1 之间的值

sigm = nn.Sigmoid()
sigm_out = sigm(fc_out)
print ('Sigmoid layer output shape', sigm_out.shape)
print ('Sigmoid layer output ', sigm_out)

Output from Sigmoid Activation Layer

  • 最终输出:

这包括两个步骤:首先,重新调整输出,使行数=批量大小

batch_size = x.shape[0]
out = sigm_out.view(batch_size, -1)
print ('Output layer output shape', out.shape)
print ('Output layer output ', out)

Sigmoid Activation Layer output reshaped

第二,正如我们在网络架构中看到的,我们只想要最后一个序列之后的输出(最后一个时间步长之后)

print ('Final sentiment prediction, ', out[:,-1])

Final output from the model

这些输出来自未经训练的网络,因此这些值可能还不能说明任何问题。这只是为了举例说明,我们将使用这些知识来正确定义模型。

结束语:

  • 我希望你读它的时候和我写这篇文章的时候一样开心
  • 试着为你正在尝试实现的任何其他深度学习模型复制这个过程
  • 请随意写下您的想法/建议/反馈

用卷积神经网络读取股票图表

原文:https://towardsdatascience.com/reading-charts-with-convolutional-neural-networks-cbaabdd5f478?source=collection_archive---------8-----------------------

Source: trendspider.com

介绍

"历史不会重演,但它经常会重复。"马克·吐温

在了解了卷积神经网络(CNN)在图像识别方面的强大功能后,我想知道算法是否能比人类图表分析师更好地阅读股票市场图表,人类图表分析师的工作是发现图表模式并从中获利。我们知道CNN 比人类更擅长对 ImageNet 图片进行分类,但是他们能比其他市场参与者更好地阅读和发现模式吗?

以下是我为适应 CNN 的股票价格预测所做的细微差别和调整。你可以在这里找到我凌乱的 jupyter/colab 笔记本。

1.选择正确的市场/数据集

我认为合乎逻辑的是,技术分析在量化基金交易的市场中不会起作用——任何从有趣的图表模式或【插入复杂的声音术语】中可能获得的收益都已经被任何体面的量化者榨干了,但我很想知道,在量化者由于能力有限而不去的地方,是否仍然存在简单的低效率。因此,我寻找全球顶级交易所之外但仍可进入的市场——华沙证券交易所就是这样一个例子。

2.时间序列的训练-测试分裂的危险

使用标准 ML 包分割数据集很容易,但必须小心处理时间序列,否则会发生数据泄漏,并产生乐观的样本内结果,而非样本外结果。如果你的随机训练测试分割让你的模型学会如何填补下面的空白,你实际上是在用未来预测过去!

Source: fast.ai

我遵循了 Rachel Thomas 的建议,以一种不会让模型预测过去的方式分割数据——关于选择验证集时的其他细微差别,请阅读她的帖子

3。使用循环图成像时间序列

向 CNN 提供信息的最直接方式是使用标准的价格/交易量图表,如下所示:

然而,由于 CNN 从数据中处理和学习洞察力的方式可能与人类不同,因此以不同的形式表示时间序列可能是有用的。此外,由于图像有 3 个通道,所以可以用不同的度量来包装每个通道,以便为我们的算法提供更多信息。这个有用的有几个函数实现了时间序列的 SOTA 图像表示。

一种这样的转换是 Gramian Angular Fields (GAFs),它将时间序列转换到一个“极坐标系统,而不是典型的笛卡尔坐标。【0】。另一种这样的表现是循环图,这种图“显示了重要的和容易解释的关于时间尺度的信息,否则是很难得到的”。1下面是一些变换后的图表,看起来蛮不一样的吧?你可以在这一页的末尾看到我实验的最终结果。

Recurrence Plot transformations

4.分数微分——平衡内存和稳定性

平稳性是 ML 算法的高性能的必要的非充分条件。问题是,在平稳性和记忆性之间有一个权衡。我们总是可以通过微分使一个序列更加平稳,但这将以擦除一些记忆为代价,这将挫败 ML 算法的预测目的。”马科斯·洛佩斯·德·普拉多【2】

Figure 1: Memory vs Time [2]

使用价格系列时的一个标准工程特征是退货系列。Lopez[2]写道,return 系列的问题是丧失记忆。图 1 本质上显示了相对于时间保存的内存。对于返回序列,即“整数 1”微分,在第一个周期后,序列的记忆会失去对过去值的记忆。但是我们可以看到,对于分数微分值,历史值的记忆仍然存在,这有助于预测。

然后,诀窍是找到一个分数,其中微分小于 1,但仍达到平稳性——一个 ADF 测试可以检查给定分数是否达到平稳性。

5.平移不变性的可选性

CNN 如此擅长对图像进行分类的一个关键原因是平移不变性,即输出对输入的微小变化不变。如果你试图对一只不总是在同一个地方的猫进行分类,它仍然可以识别这只猫。

Source: What is wrong with Convolutional neural networks

但是对于时间序列,时间上较早的尖峰与预测时间之前的尖峰具有不同的含义,因此如果平移不变性有用的话,我们可能希望抛弃它——使用 Coordconv [3]可以实现这种可选性。一个 Coordconv 层包括 2 层 I 和 j 坐标,让 CNN 知道每个像素的位置。如果算法决定坐标是有用的,权重将反映这一点,因此使用 Coordconv 只有好处!作者发现,将 Coordconv 添加到各种 CNN 任务中几乎总能提高性能。

Source: An intriguing failing of convolutional neural networks and the CoordConv solution [3]

结果和进一步的工作

我使用 CNN 通过将时间序列数据表示为图像来预测时间序列。CNN 有一个相对简单的二元分类任务——决定第二天的收盘价是否为正。

我关注的是精确度,因为我们赌假阳性会赔钱。使用 GAF 成像的分数微分序列(d=0.3),最好的评分是 64 %。我跑得最好的笔记本是这里的。

接下来,我将着眼于改进 CNN 架构,以更好地捕捉时间关系,即波网!兴奋地去理解和测试它。

特别提及:fast.ai

我从我的人工智能硕士那里学到了很多东西,但我也学到了同样多的东西,如果不是从 fast.ai 那里学到更多关于实用深度/机器学习的话。 fast.ai 库挤满了最先进的深度学习技术,这些技术可以加快训练速度,它们的默认设置会产生惊人的结果,从而使用户可以专注于实验的其他部分。论坛也非常活跃,上面的大多数想法都来自这个帖子中的人。

参考

[0] Z. Wang 和 T. Oates,“使用平铺卷积神经网络将时间序列编码为用于视觉检查和分类的图像。”AAAI 研讨会(2015 年)。

[1] J.-P Eckmann 和 S. Oliffson Kamphorst 和 D Ruelle,“动力系统的递归图”。欧洲物理学通讯(1987 年)。

[2]马科斯·洛佩兹·德·普拉多,“金融机器学习的进展”。2018

[3] 罗莎妮·刘乔尔·雷曼皮耶罗·莫里诺费利佩·彼得罗夫斯基这样的埃里克·弗兰克亚历克斯·谢尔盖耶夫杰森·约辛斯基、【卷积神经网络和 CoordConv 解决方案的一个耐人寻味的失败】。2018.

应用人工智能阅读书目

原文:https://towardsdatascience.com/reading-list-for-applied-ai-5f4b84c75c1f?source=collection_archive---------10-----------------------

Photo by Nong Vang on Unsplash

如果你在 2020 年将人工智能应用到你的业务中,六本书值得一读

据行业领袖称,2020 年将是人工智能(AI)“现实检验”的一年。在未来一年,许多企业将寻求从人工智能和机器学习试点计划转向为将人工智能完全嵌入企业奠定基础。IDC 预测到 2022 年,75%的企业将在运营中嵌入智能自动化。

如果你是一名商业领袖或数据专业人士,正在考虑如何在你的组织中使用人工智能,以及部署这一新兴技术的最佳方式,这里有一份书单,可以添加到你的新年阅读清单中。这些书涵盖了在商业中应用人工智能的战略和实践层面。他们会让你明白;

  • 人工智能在不久的将来对商业意味着什么。
  • 如何为应用人工智能建立合适的团队?
  • 部署机器学习的最佳实践。
  • 如何制定坚实的战略,将人工智能和机器学习嵌入到组织中。
  • 实施人工智能的伦理和道德考虑。

机器学习向往

吴恩达

被称为谷歌大脑背后的人的吴恩达在 2018 年发布了这本完全免费的书。根据他领导谷歌大脑团队的经验,他介绍了一个将机器学习嵌入组织的框架。

这本书涵盖了如何制定机器学习策略,测试机器学习模型的正确方法以及如何建立一个“超级英雄”团队。对于希望开始在企业中使用或扩展机器学习的数据科学家和企业领导者来说,这是一本必读的书。即使你已经在部署机器学习,这本书也将提供如何改进现有流程的技巧。

机器学习的规则

马丁·津克维奇

另一本免费下载的书,作者是谷歌的一位研究科学家,这本书涵盖了机器学习工程的最佳实践。这是一本非常实用的书,既适合商业领袖,也适合数据科学家。它涵盖了实现机器学习的最佳实践,从最基本的原则开始,比如只在有意义的地方使用机器学习。

这本书分为四个部分,包括:如何了解在实施机器学习(ML)之前需要准备什么,如何部署端到端的 ML 管道,如何启动模型和迭代以获得性能改善,以及当性能增益达到平台期时该做什么。

数据科学行动手册

柯克·博恩和埃兹梅拉达·哈利勒·萨格尔

这是一份来自数据科学咨询公司 Booz Allen Hamilton group 的出版物。这本书概述了成功的数据科学的“六个关键要素”,这些要素是他们通过与众多公共和私营部门企业合作而确定的。

这六个要素包括:

  • 识别分析机会。
  • 如何更好地管理和治理数据。
  • 从这些数据中产生有用见解时需要考虑的分析技术。
  • 如何建立和发展数据科学团队?
  • 如何最好地将新技术和现有技术用于数据科学项目。
  • 为数据科学的成功开发一种企业文化,他们称之为“Adapt-C”。

这本书主要针对商业和数据科学领导者,并就如何制定公司范围的数据科学战略给出了非常实用的建议。

预测机器

阿贾伊·阿格拉瓦尔、阿维·戈德法布和约书亚·甘斯

这本书是从市场营销、经济和管理专家的角度写的。它旨在回答“人工智能对我的业务意味着什么?”。他们相信将人工智能重新定义为“廉价预测”而不是“魔法”,并提出人工智能将为能够成功利用这项技术的企业提供经济优势。

这本书为商业领袖和战略家提供了一个关于人工智能的现实视角,并介绍了一个实用的框架来理解你需要了解的关于这项技术的知识以及它将如何影响你的业务。

人+机器:重新想象人工智能时代的工作

保罗·r·多尔蒂和 h·詹姆士·威尔森

这本书聚焦于人工智能的不远的将来,以及这将如何用这种技术导致所有业务流程的转变。作者讨论了他们如何看到公司部署人工智能解决方案来增强创新和盈利能力。这本书还提供了一个“领导者指南”,它给出了成为人工智能驱动的企业并实现公司业绩改善的五个关键原则。

这本书是商业领袖对人工智能的实用介绍,并解释了它在不久的将来对企业和“人类”意味着什么。

破坏数学的武器

凯茜·奥尼尔

人工智能目前的局限性之一是,尽管机器能够通过复杂的计算学习数据中存在的模式,但它们还无法对它们做出的预测做出任何道德判断。当企业开始将这项技术应用到他们的流程中时,考虑自动做出的决策的道德含义是很重要的。因此,我觉得在人工智能的推荐书目中至少包括一本关于伦理的书是至关重要的。

这本书强调了在将人工智能集成到企业中时一些最重要的伦理和道德考虑。作为业务领导者或数据从业者,这将为您正在部署的模型的潜在含义提供许多思考的素材。

感谢阅读!

解读市场——机器学习与金融新闻

原文:https://towardsdatascience.com/reading-the-markets-machine-learning-versus-the-financial-news-bcd3704f37b8?source=collection_archive---------11-----------------------

大量的金融新闻文章出版了。但只有一小部分能真正推动市场。知道哪些可能会有帮助。机器学习能指明方向吗?

【本文涵盖今年 5 月在维也纳举行的 QuantMinds 国际会议上介绍的工作,以及 12 月在纽约举行的量化金融中的机器学习和人工智能会议上的更新。它基于我们在《走向数据科学:机器学习与新闻中发表的测量新闻情绪的工作。]

想象一下,你想要战胜股票市场。你是个勤奋的投资者。每天早上开市前,你会阅读前一天收盘后发布的所有新闻。在以某种方式预测了这些文章中的哪一篇会推动市场后,你运用你巨大的直觉和洞察力来下注。然后你去海滩。

这种梦境的问题在于数据量巨大,而且数据和结果之间的关系从未被可靠地公式化。但是,这当然是我们喜欢应用机器学习的那类问题的本质1

道琼斯通讯社是主要的实时财经新闻提供商之一,每年传送几百万篇文章。这些包括从主要报纸的文章到新闻发布和经纪人的评论。即使我们把自己对世界的看法限制在与标准普尔 500 指数成份股公司明确相关的文章上,我们每天仍会看到成千上万篇文章。如果我们在开市前一个小时到达工作地点,我们几乎没有两秒钟的时间来阅读和评估每篇文章。我们也许能够以这样的速度浏览一些文章,并发现一些有趣的文章,但我们的分析不太可能非常深入,而且几乎可以肯定的是,我们无法保持这样的速度一个小时。人们也早已清楚,即使有足够的时间,投资者也不太擅长预测市场。

我想到的一个大问题是:

有没有可能建立一个算法,可以成功地找到将推动市场的文章?

继续读下去,你会发现答案最终是肯定的。但实现这一目标的能力取决于投入大量精力,培养对现有新闻文章本质的理解,以及对相关工具和算法的直觉。

理解新闻

对于这个项目,我们使用自然语言处理,特别是情感分析。参考维基百科的定义:

Wikipedia’s definition of Sentiment Analysis

在我们的语境中,这意味着分析一篇新闻文章的文本,并决定它“听起来”是积极的还是消极的。有几种常用的库可供使用:

●斯坦福 CoreNLP

● NLTK

●谷歌云平台

这些库的运行方式各不相同,但总的想法是,它会消耗一些文本并返回一个分数,其中如果一篇文章特别乐观,它可能被评为+1,如果它特别消极,它可能被评为-1,或者其他适当的介于两者之间的值。本文给出的结果是使用 NLTK VADER 获得的。这种选择主要是出于计算的原因,因为它比其他选择要快得多。

为了举例说明,让我们看几个已经传递给斯坦福的情感分析器的句子(可以在这里运行)。

Sentiment computed for a variety of sentences by Stanford’s CoreNLP

我们看到一些无关紧要的句子被评价为或多或少积极的,与我们可能希望期待的一致。当处理新数据或新库时,为了确定您可能遇到的弱点,运行这样的小测试是非常有用的。所有库的结果都很差——为了避免显得卑鄙,这里不分享这样的例子。

如何预测未来

一旦我们知道了一篇新闻文章的观点,我们希望能够预测它的发表是否会引起市场的重大变化【2】

用机器学习的行话来说,这是一个有监督的学习问题。我们有包含特征(文章的属性)的历史新闻文章数据,并添加了一些标签(基本上是 0 或 1 ),指定文章实际上是否跟随了文章中提到的公司的股票价格的显著移动。

我们将这些数据传递给一个分类器——某种算法,在我们的例子中,该算法试图推断某一特定商品是否可能会发生重大价格变化。在实践中,我们希望能够确定我们是否从可用的历史数据中学到了任何有用的东西。为此,我们将历史数据分为训练集和测试集。在“学习”阶段,我们向算法展示来自训练数据的特征和标签。然后,在测试阶段,我们向经过训练的算法提供以前未见过的特征,指示它预测最可能的标签,然后将该预测与实际对应的标签进行比较。

鉴于这一总体框架,我们的工作必须朝着两个方向前进:

●确定可用新闻文章的最佳功能集。

●确定将最成功地学习我们的特征和标签之间的关系的分类器(及其参数化)。

机密情报

我们将很快讨论我们脑海中的特征类型,但是首先对分类器进行一些评论。对于监督学习问题,存在多种分类器。最基本的是逻辑回归。然后是决策树、随机森林等算法。在数学上复杂的一端,我们发现了神经网络。对于这个项目,我们使用神经网络找到了我们的最佳结果,所以我们在这里展示的结果是通过这种方式获得的。

我们不会尝试在这里介绍神经网络。只要说它们是一种非线性回归工具就够了,其基础设计是从人脑基本结构的简化中找到灵感的。

在过去的几年里,我们在机器学习方面经历的许多重大进步都利用了神经网络。这种基本算法已经存在了几十年,但随着处理能力和数据可用性的稳步增长,它开始发挥作用。

对于这个项目,我们用 Python 实现了我们的神经网络,使用了 Google 流行的 TensorFlow 库。我们的神经网络的特征,特别是它的复杂性,被选择来平衡精度和泛化能力。这相当于:

●准确预测样本内训练数据的标签

●准确预测样本外测试数据的标签

这并不像听起来那么容易。很明显,如果一个模型非常简单,即使在训练过程中“看到”的数据上也不太可能表现良好。随着模型变得越来越复杂,它开始在训练数据上表现得更好。如果它运行良好,它将越来越多地在以前看不到的测试数据上表现良好——即,它将学会概括。但是从某种复杂程度上来说,它将继续在训练数据上表现得更好,而在测试数据上表现得越来越差。因此,选择架构的目标是在最佳点着陆,在这个点上,模型在测试 数据上的准确性最高。

对这种现象的一种思考方式是,没有一种关系可以从数据中完美地学习到。这很大程度上是因为数据本身并不是我们试图了解的关系的完美例子——总有噪音。随着模型变得更加复杂,它获得了从训练数据中学习噪声的数值自由度。但是从这个角度来看,既然噪音基本上是随机的(因此是不可预测的),那么这些知识只能分散对未知数据的有用学习。

因此,诀窍在于找到一个足够复杂的网络,以学习数据中非线性关系的本质,但又不足够丰富,以至于能够有效地记住所呈现的数据(每个观察结果都包含特定的噪声,这些噪声不会在未来的数据中再现)。

这是很重要的,因为记忆数据证明是一个非常差的保证,知识可以推广到以前看不到的情况。从某种意义上说,对记忆的约束是洞察力的起源。但只是在一定程度上——给定一个足够有限的模型,我们既不会记住任何东西,也不会学到任何有用的东西。

最适合我们的网络架构如下:

●四个隐藏层—64、128、128 和 64 个节点

●层完全连接并使用 Relu 激活

●输出层包含具有 sigmoid 激活的单个节点

特征工程

特征工程是确定可用数据的特定属性集的工艺,这将最好地促进我们寻求推断的关系的学习。我们可以想象一些物品属性的效用:

●文章的正文

●刊登文章的出版物的名称

●文章发表的时间

●出版商的文章 ID 代码

我们可能随后会发现在我们的特性中包含文章 ID 是没有帮助的。包括它甚至可能使结果恶化。在直觉层面上,我们可以认为这个特性只是带来了额外的噪声,妨碍了算法搜索洞察力。在这种情况下,从特性中删除文章 ID 实际上消除了干扰,使学习更容易。

相反,文章的文本本身可能很难让我们的算法从中学习任何东西。因此,特征工程工艺的另一个方面是计算出可以从数据中导出哪些进一步的属性,以帮助突出关键关系,并使算法的工作更容易。(如前所述,我们将使用情感等衍生特征)

该过程

为了获得这里给出的结果,我们遵循一个相当典型的机器学习过程。实际上,我们将把数据随机分成训练集和测试集。所呈现的结果是从将已训练的模型应用到测试测试中获得的结果(即,未被用作训练模型的一部分的数据集)。

首先,一篇新闻文章只有一个特征——文章的情感。我们将把它与 0(意味着股票的绝对超额收益小于 1%)或 1(意味着绝对超额收益大于 1%)联系起来。

接下来,我们在随机选择的训练子集上训练我们的分类器,然后通过从测试数据集生成预测并将它们与股票价格的实际记录历史移动进行比较来测试训练的网络。

为了使这种比较对一组数据有用,我们需要一个度量标准。评估分类问题解决方案成功与否的一个常用指标是 F1 分数。这在我们这样的情况下特别有用,在我们的数据集中有大量的“真正的负面消息”,这意味着大多数文章之后没有重大的股价波动。

请记住,如果我们的模型预计一篇新闻文章之后会有市场变动,则预测值为 1,否则预测值为 0,F1 得分计算为以下各项的调和平均值:

●从我们的模型中得出的 1 个预测实际上为 1 的比例(所谓的精确度),以及

●我们的模型正确预测为 1 的所有实际 1 的比例(召回)。

如果我们的结果是完美的,这个值将是 100%,如果它们完全没有用,这个值将是 0%,更有可能在两者之间。

为了说明这类项目的发展,我们将以渐进的方式呈现结果——查看我们在实验不同功能集时发现的 F1 分数。要记住一个重要的事实:

虽然添加功能的过程是由我们的直觉和智慧驱动的,但现实往往不会被我们最伟大的洞察力所打动,有时甚至会成为苛刻的批评家。

无论如何,我们希望通过明智地添加功能,我们将提高我们的模型的预测能力!

第一步:那些艰难的早期结果

看到第一个结果往往是你无畏的机器学习工程师或数据科学家陷入绝望的时刻——所以我们必须做好准备,对我们最终的结局保持一定程度的乐观。

虽然我们还没有天真到想象用一个数字来表示一篇文章——它的情感——会让我们的分类器有更多的希望来推断这篇文章是否会推动市场,但从这里开始仍然是有用的。

这有几个原因。首先,它是一种检查我们的整个管道是否正常工作的方法——我们可以收集数据,构建功能,分离测试数据,训练模型,根据测试数据评估模型,等等。第二,它有助于建立一个基准水平的准确性,我们可以根据它来决定增加其他数据特征或改变我们的分类器结构的效用。

尽管如此,人们希望我们在这个阶段取得的结果会比随机的好——因为那至少会令人感到鼓舞。从本能上来说,由于我们是在预测这篇文章是否会推动市场,所以感觉是二元的。因此,人们可能会认为 50%是随机猜测的结果。因此,我们希望在测试数据上获得介于 50%和 100%之间的 F1 分数。

因此,当第一次运行完成时,F1 分数出现在屏幕上,其值为 25%,很难不感到有点沮丧。稍微思考一下,我们就可以从以下事实中得到安慰:我们的文章中,只有少于一半的文章出现了大幅的市场波动,因此,选择频率相同的 0 和 1 会导致较低的结果,所以我们的结果确实比随机结果要好。

进度检查:第一步

第二步:物品预处理

数据科学家最重要的活动之一是理解数据。有时这可能是微不足道的。但是,如果一项工作足够复杂,需要一名数据科学家,那么数据集可能会很大,而且是非结构化的。这种分析可能是一种令人沮丧且耗时的活动,但也是必不可少的。

我们找到的第一篇文章显然是我们希望从中学习到一些东西的:

贝尔沃租赁有限公司(BLV。LN)周三表示,该公司超过了 2017 年投资组合收购的目标。这家英国房产租赁公司表示,2017 年期间,特许经营商完成了 23 笔交易,增加了超过 330 万英镑的网络收入,超过了其目标。

这篇文章有几个优点:

●它明显与特定公司相关

●它拥有可以相对容易地推断出情感的语言

●它不包含大量中性或分散注意力的文本

我们开始注意到的许多其他文章就不一样了。有些形式经常重复出现,其中包括:

●经纪人的价格更新

●带有免责声明的新闻稿

● S&P 评级评论

●与多家公司相关的文章

第一种方法对我们的目的没有多大用处,因为它们只是简单地引用了特定证券的出售价格。它们本质上几乎完全是数字——尽管这并不排除它们的用处,但我们的 NLP 情感算法并不适合解释它们。此类物品最好能被检测出来,并从我们的流程中排除。

新闻稿和 S&P 评级评论可能非常有用。但是他们经常以免责声明的形式包含大段的法律术语。情感是作为文档句子的平均值来计算的。由于法律术语往往是中性的,在分析文章时包括这些标准文本的大段文字将会大大削弱文章报道的情感。因此,在评估这些标准文本之前,我们将把它们从我们的文章中去掉。这是一项繁琐的工作,但是可以通过一系列正则表达式有效地实现。

一些新闻文章总结了与不同公司相关的多条新闻。由于这些文章遵循特定的格式(取决于出版商等),通常可以自动将它们分成一系列迷你文章,每篇文章只报道一条新闻。

一旦我们建立并实现了一套预处理数据的规则,我们就可以重新运行我们的分析,看看我们得到了什么样的测试结果。

进度检查:第二步

事实上,通过对文章进行预处理,我们看到 F1 分数提高了 15%。这是第一次表明,了解您的问题领域和技术领域是有实际价值的。在这种情况下,这意味着理解:

●在浩如烟海的文章中究竟能找到什么样的文章,以及

●算法将如何在各种类型的文章上执行

第三步:添加更多功能

为了提高我们的神经网络学习某些东西的机会,我们现在将向它扔更多的数据——具体来说,我们将为每篇新闻文章提供额外的功能。

在我们这样做之前,有必要思考这样一个事实,即一篇新闻文章只有在改变我们对某件事的看法时才会对我们“有用”。在我们对世界的简化观点中,我们从新闻报道对股票的情绪中推导出对股票的情绪。因此,如果一篇新闻文章偏离了我们之前对该股的看法,它可能会被认为是有趣的。请注意,一篇文章不一定要与我们当前的观点相矛盾,它可能只是让我们对我们当前的观点更加自信。考虑到这些目标,我们为每篇文章引入了以下功能:

●近期新闻文章对该股的平均情绪

●本文观点与该股近期历史均值之间的偏差

●近期文章对该股情绪的波动

我们还可以想象,股票对新闻报道的反应可能取决于股票最近的交易情况,因此我们纳入了捕捉以下信息的指标:

●该股的交易量表现如何?

●该股相对于整体指数的表现如何?

●该股近期超额收益的波动性如何?

最后,一些公司在正常时期很少被报道,而在重大事件发生时会被更频繁地报道。因此,我们纳入了一个衡量标准,衡量股票的报告频率相对于其长期平均水平的近期表现。

将所有这些特性放在一起,重新运行我们的测试,我们看到我们的 F1 分数从 40%增加到 49%。

进度检查:第三步

第四步:一点新闻洞察力

这类工作最重要的一个方面是发展对领域的理解。许多新闻都是按照所谓的倒金字塔模型构建的。借用维基百科,我们可以将一篇典型新闻文章的结构形象化如下:

Inverted Pyramid Model of Journalism courtesy of Wikipedia

这是写文章的一个相当标准的方法。这个想法是在文章的开头传达谁,什么,等等,然后在接下来的段落中提供更多的辅助细节。开头的几个句子被称为文章的导语。

我们可能会假设,Lede 中传达的情感更多地与公司相关新闻的最重要部分相关,并且我们越深入文章,我们就越会偏离它(通过关注不太重要的细节的情感)。如果我们被这个假设所吸引,那么我们应该考虑运行网格搜索来识别文章中要处理的最佳部分。

我们通过使用 NLTK 工具包将文章文本转换成句子来做到这一点。接下来,我们从文章中选择第一个 n 句子(每篇文章都有相同的 n ),然后我们用这部分文本继续完成剩下的过程,并计算 F1 总分。此外,我们迭代不同的 n 值,直到我们找到最好的 F1 分数。我们发现的结果如下:

F1-score computed using a series of Lede lengths (in number-of-sentences)

这显示了大约十个句子的最佳情感信息内容,因此在完成步骤四时,我们将处理限制在十个句子的文章。

进度检查:第四步

停下来想一想——我们被困住了吗?

通过几次迭代,我们已经推进到这样一个点,即我们的结果有一些统计意义,但没有足够的意义来保证写一篇关于它的文章。我们已经花了很多时间来加深对新闻文章的理解,所以现在我们必须努力加深对我们正在使用的人工智能工具的理解。

尤其值得思考的是,情感分析是否很好地适应了我们试图解决的问题。要做到这一点,我们必须更深入地了解我们可用的特定情感分析工具。这是有见地的考虑语料库的性质,每一个是建立在。一般来说,流行的情感分析师没有接受过金融新闻报道方面的培训。更常见的是,它们是通过以下方式构建的:

●来自亚马逊或 IMDB 的评论

●推特

每种类型的文本都有自己的特点。推文肯定是用与完整长度新闻完全不同的语言写的,所以为推文精心校准的工具不太可能理解更正式写作的情感范围。

值得注意的是,从我们对股票的看法来看,“结果略有改善”这样的句子是积极的。然而斯坦福的 CoreNLP 把这句话归类为否定。同样,所有的库都有自己的特点和不一致性,所以这并不是对 CoreNLP 的批评。

所有这些都让人怀疑,最好的前进方式是不是建立我们自己专有的情绪分析器。如果我们环顾一下可用的工具,很容易被 Doc2vec 的流行和据称的功能所诱惑。所以我们来看看有没有帮助。

与 Doc2vec 一起前进

Doc2vec 是流行的 Word2vec 的扩展,有效地在文档级别而不是单个单词级别应用该技术。Word2vec 最初来自谷歌进行的研究。Word2vec 的想法是学习一个将单词映射到一个 n 维向量的函数。该算法通过查看一些语料库中的单词序列来做到这一点。在机械上,一个简单的神经网络用于学习预测哪个单词最有可能跟随任何给定的单词。第一个惊喜在下一步。扔掉神经网络的输出层,转而看看倒数第二层的 n 节点的激活。然后,这些激活的值可以被认为对应于输入单词的矢量表示。

这有什么用呢?对于这是如何发生的还有一点不确定性,但是如果我们绘制一系列单词的向量值,我们会开始注意到一些非常有趣的模式。从谷歌深度思维研究科学家的一篇文章中截取这张图片:

Word embeddings for related words under Word2vec

这里我们看到的是一些常见单词对应的向量值的曲线图。(实际的向量是高维的,但是它们在这里通过称为降维的数学过程被简化,以便它们可以在某种意义上近似为我们可以绘制的二维图形)

要注意的是,虽然像“慢”、“短”、“强”、“暗”这样的词都出现在图表上相当不同的位置(沿着左手边),但更慢和最慢(到慢)的相对位移,基本上与我们看到的短/更短/最短、强/更强/最强等完全相同。

这几乎表明,该算法已经推断出某种语言语义的算法。事实上,我们可以制作图表,展示语言的许多其他属性的类似有趣的结果。

我们不会在这里详述细节,只是说 Doc2vec 将该方法扩展到了文档级别——并且已经发表了几篇在情感分析中使用 Doc2vec 文档矢量化的论文。

这特别有趣,因为在任意文档语料库上训练 Doc2vec 很容易。因此,我们建立了新闻文章的向量化,然后,当沿着这个新方向前进的兴奋达到顶点时,我们看一下这个过程的下一步:训练我们的情感分析器。我们意识到了问题。

已发表的使用 Doc2vec 进行情感分析的工作主要是通过评论数据完成的,特别是来自亚马逊客户或 IMDB 电影评论者的评论数据。这些案例有标签,而我们没有,也就是说,对于每个评论,都有文本和用户指定的星级。这两者的结合大大简化了从文本中学习情感。

然而…在我们这里,我们只有文章,没有星级。因为我们知道我们的目标是拥有一个情感分析器,它是根据出现在财经新闻而不是电影评论中的语言类型来训练的,所以我们陷入了困境。

所以我们碰壁了

在努力寻找解决我们问题的方法后,一个真正的障碍出现了。就像马拉松运动员必须在最后一次努力中找到出路一样,我们也必须如此。

想想我们在努力做什么。实际上有两个步骤:

  1. 文本-> Doc2vec ->情绪,然后
  2. 情绪->市场结果预测

我们的问题是缺乏可用的情感价值。但是注意到情绪既是一个步骤的输出,又是下一个步骤的输入,我们就不能简化一下吗?

为什么不用市场结果来代表情绪呢?这将给我们留下一个步骤:

  1. TEXT -> doc2vec ->市场结果预测

第五步:集成 Doc2vec

事实证明,以这种方式可以发现显著的改进。实现相对简单,尽管我们使用 gensim,而不是 Google 的实现。结果如下所示。

进度检查:第五步

第六步:拿着香槟

在我们忽略的各种细节中,有一些在使用 Doc2vec 时出现的基本实际限制。主要的问题是,我们需要一套完整的文章来建立模型——不可能动态地添加新文章,然后对这些文章进行预测。这意味着,对于出现的每一篇新文章,我们都可能需要重新训练我们的文档矢量器。

问题实际上比那更糟糕。Doc2vec 中的特定向量不是算法的本质——重点是不同文章的相对嵌入。重建模型时,这些不同向量之间的形状可能会保持不变,但绝对值可能会改变。由于我们用作分类器的神经网络与实际值有关,因此也有必要对其进行重新训练。

这是很大的计算负担,并且在每天有数千篇新文章的实时环境中一点也不方便。

我们可以认为,基本约束源于 Doc2vec 需要一个完整的词汇表来构建其矢量化模型。给定一个足够大的特定领域训练数据集,在以前看不到的文章中很少会遇到新词。但在实际操作层面,总会有一个新人的名字、地名、公司名称等。这表明我们可以尝试构建没有专有名称的向量。事实上,有一些 NLP 工具可以让我们获取文本并标记每个单词的词性。然后我们可以过滤出与专有名词相对应的单词。

这在直觉上很有吸引力,因为它应该使归纳更容易(所以我们对一只股票的了解肯定适用于另一只股票,因为股票的名称被排除在外)。我们肯定会找到更好的结果…所以让我们看看。

进度检查:第六步

不幸的是,这并没有改善我们的结果——无论这个想法多么吸引人。

更仔细的观察表明,基本的词类过滤并不是特别有效——它删除了一些不是真正专有名词的单词。并且为了推断情感,需要那些被移除的单词中的一些。

然而:

由此得出的关键点是,通过采取这一步骤,我们解决了困难的实时问题,而不会显著影响结果的质量。

结论

在本文中,我们展示了处理新闻文章并确定哪些文章可能影响股票价格是可能的。这并不是说我们的模型在 70%的时间里正确地预测了市场。如果是这样,我们就不会写这篇文章了。我们的测试范围要窄得多——请记住,我们关注的是预测一篇新闻文章之后,股价的变动是否会超过指数变动的 1%。我们也在看昨晚收盘和今天开盘之间的变化。所以并不是所有变化都可以直接归因于这篇文章。我们不应该混淆相关性和因果性。

当然,一个人理解得越多,能够取得的结果就越好。这意味着有必要密切关注所有方面:

●了解数据

●了解新闻业

●理解算法

与许多机器学习应用一样,处理新闻和市场几乎是一门手艺,就像它是一门硬科学或工程学科一样。在某种程度上,处于科学、工程和工艺之间的这一位置使它成为一门迷人和令人愉快的学科。

在这个领域还有很多工作要做——未来几年还会有很多研究要做。考虑到金融市场的风险,最好的作品不太可能被出版。

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

1为了清楚起见,这里要注意这是一种简化。今天早上不可能以昨晚的收盘价交易。我们可以在新闻文章发表时对其进行评估,但这将需要比我们现有的这个项目更多的当天价格数据。此外,值得注意的是,这里的重点是确定哪些消息将推动市场,而不是确定该移动将是哪个方向。(也就是说,给定一个,确定另一个可能相对简单——但鉴于我们历来对波动性的关注,这就是我们的兴趣所在)

【2】注意,我们不是在推断因果关系。在任何时刻,都有多种因素驱动着任何一只股票价格的变动。此外,我们关注的是超过同期标准普尔& P500 指数变动的股票价格变化,也就是说,我们关注的是超额回报,通常称为 Alpha。

扩展 Pandas API 的简单方法

原文:https://towardsdatascience.com/ready-the-easy-way-to-extend-pandas-api-dcf4f6612615?source=collection_archive---------22-----------------------

写出你自己的熊猫味道

Photo by Zach Rowlandson on Unsplash

在本文中,您将通过使用pandas _ flavor,学习如何根据您的业务、研究或个人工作流程定制 pandas API。

Pandas-flavor 是一个引入 API 来扩展 Pandas 的库。这个 API 处理将定制的访问器/方法注册到 Pandas 对象上的样板代码。

但是在本文中,我将展示如何使用它来扩展功能。为简单起见,我将使用泰坦尼克号数据集:

**import pandas**df = pd.read_csv("titanic.csv")

注册方法

Pandas-flavor 将以下自定义方法直接添加到 Pandas 的 DataFrame/Series 上:

  • 允许将方法附加到数据帧。
  • register_series_accessor()允许将方法附加到序列。

这两个装饰器允许你我们可以调整上面的例子,将“is_old_lady”方法直接附加到 DataFrame 上。

**from** **pandas_flavor** **import** register_dataframe_method**@register_dataframe_method**
**def** is_old_lady(df):
   is_lady = df["Sex"] == "female"
   is_old = df["Age"] > 70
   **return** df[is_old & is_lady]df.is_old_lady()

但这可能会导致一些问题,例如,如果许多包开始用自定义方法对数据帧进行猴子式修补,可能会出现重复和混乱。

通过使用隔离(名称空间),注册一个包含自定义方法的访问器,可以很容易地解决这个问题。

注册访问者

熊猫数据框架/系列的访问者注册也是如此:

  • register_dataframe_accessor()允许将访问器附加到数据帧。
  • register_series_accessor()允许将访问器附加到序列。

作为一个例子,这里有一个简单的“titanic”访问器,它有一个“is_old_lad”方法:

**from** **pandas_flavor** **import** register_dataframe_accessor**@register_dataframe_accessor**("titanic")
**class** **TitanicAccessor**:
    **def** __init__(self, df):
        self._df = df

    **def** is_old_lady(self):
        df = self._df
        is_lady = df["Sex"] == "female"
        is_old = df["Age"] > 70
        **return** df[is_old & is_lady]df.titanic.is_old_lady()

但是熊猫有自己的 API

在本文中,我选择展示 pandas-flavor,尽管 pandas 有自己的 API来扩展 DataFrame/Series 功能,您可能应该在注册访问器时使用这些功能。

但是有一些限制:

  • 您使用较旧的 pandas 版本,因为它只在 0.24.x 中引入
  • 您希望注册方法而不是访问器,一个用例可以是覆盖 pandas 自己的方法,如 pandas-log
  • 您希望将访问器/方法注册到其他包,如 xarray。

出于简洁的原因,我选择为所有用例展示熊猫风味。

遗言

当您想要扩展 Pandas 的功能并使您的代码更好时,Pandas flavor 非常有用。这篇文章的灵感来自 Zach Sailer 的博客(熊猫风味作者)。

我希望你觉得有趣和有用。我乐于接受任何建设性的反馈。

真实数据科学家有冒名顶替综合症

原文:https://towardsdatascience.com/real-data-scientists-have-impostor-syndrome-2fe8c0cf2e8f?source=collection_archive---------11-----------------------

Photo by Matthew Henry from Burst

我妻子曾是一名天文学家。她在这方面非常擅长,并开始与该领域的一些顶级人物合作。但是,大约五年前,她对工作的热情耗尽了。她决定转向商业数据科学。

像许多学者一样,她不确定如何实现这一飞跃。从一个世界到另一个她知之甚少的世界是相当令人害怕的。然而,事实上,她已经比大多数有这个头衔的人更像一个数据科学家。在过去十年的大部分时间里,她除了使用 PCA、贝叶斯推理、误差分析、Python 代码、多维宁滨、迭代模型拟合以及天知道还有什么来分析大型数据集之外,什么也没做。

虽然完全符合她想要的角色,但感觉不太适合她。但这并不令人惊讶:同样的自我怀疑模式出现在我共事过的每一位才华横溢的数据科学家身上,我已经在机器学习领域工作了超过 25 年。

我认为优秀数据科学家的标志是他们不觉得自己一员。他们的眼睛后面总是藏着一点点恐慌,有人会发现他们不是真的,这种感觉永远不会消失。不过没关系。很好,甚至。我也有。但问题是为什么?在我看来,数据科学作为一个领域所面临的显著的冒名顶替综合征效应至少有四大原因。

1:我们被工具淹没了

你学会 TensorFlow 了吗?如果没有,可能已经太晚了。你应该把注意力放在 Keras 上。也就是说,如果你还没有开始学习 PyTorch 的话。但也许你在处理由你的客户定义的大型商业数据流,所以你的人工智能需求正由 Spark MLib 满足。除非你的公司决定你需要 Flink 额外的流稳定性,在这种情况下,你无疑已经得到了 FlinkML 的支持。

除此之外,如果您的客户端已经绑定到 AWS,您的数据馈送可能来自 Kinesis 流。因此,也许在 Sagemaker 上提高技能、理解和认知更有意义。或者,如果你的客户与 MS Azure 有关联,你可能只想使用 Azure ML。

但是等等,我听到你说,你做的大部分工作是调查,就在你的笔记本电脑上。你更熟悉蟒蛇和熊猫。在这种情况下,你肯定想确保你知道 NLTK,Spacey,SciKit-Learn,幕府将军,Theano,SciPy,Seaborn,Plotly 和 Gensim。

有人知道如何正确使用所有这些吗?如果那个人存在,我还没见过他们。然而,当你不知道一个软件包时,总会有一种潜在的感觉,如果你想称自己为专业人士,你应该已经掌握了他们的一些重要和新的东西。这是一个问题,因为每个月都会有新的包和工具到来。一旦你进入机器学习的杂草中,同样的模式就会重复出现,因为总有另一种人们正在谈论的神经网络,网络上充斥着教程,这些教程几乎没有完全解释它们是如何工作的。(实际上发挥作用所需的数百次重复实验通常被隐藏在视线之外。)

这些工具的真相是,它们中的大多数都有很大的重叠。你不需要把它们都冷冻起来。但这不会阻止你的感觉。我们在 productOps 尝试解决这一问题的方法是,在每个新包发布时尝试对其进行研究,并在我们的数据科学团队中共享知识。我们在尝试深入之前先扩大范围,然后根据项目需要提高技能。我们让自己摆脱对未知的一切,并相信我们会到达那里。这样,理智就更容易坚持。

2:行业言论与实际行动不符

在推动人工智能的许多行业压力背后,是云服务中令人发指的巨额利润。三大供应商都急于让自己与众不同,锁定新客户。他们这样做的一种方式是分发像糖果这样的工具。

你不仅在人工智能和数据科学产品中看到这种模式,在 BI 套件领域也是如此,现在甚至在快速应用原型框架中也是如此。事实上,云提供商会提供几乎任何东西让你站在他们一边。因为真正的钱不在自动驾驶汽车上,而且暂时也不会。真正的钱是彻底检查财富 500 强公司的架构,并让他们在可预见的未来承担云费用。

这意味着,主要技术机构所鼓吹的工具不可避免地会比大多数经营企业的人实际需要的更华丽、更强大。但是当你是一个数据科学家时,很难看到闪亮的数字树的森林。你会看到人们开发出越来越聪明的机器学习产品,肯定有人从中受益。

我们的解决方案是,只在业务情况需要的时候使用闪亮的工具,并为此感到自豪。如果线性回归为你的客户找到了正确的答案,那么使用深度学习就没有意义。

3:数据科学家的角色定义不明确

数据科学的另一个现实是,这项工作仍然非常模糊。并不是每个组织都需要聪明的新见解。有时候真的有研究要做。然而,更多的时候,问题实际上与数据工程有关。一旦你在数据中发现了有用的模式,你需要一种能够反复识别它们的方法。这意味着,数据科学往往会渗透到数据工程甚至开发运营中。尤其是现在,云提供商正试图提供如此多的现成机器学习解决方案,这些解决方案更多的是即插即用,而不是摆弄变量,直到奇迹出现。

当你将这一点与许多组织仍然不知道他们试图从自己的数据中学习什么的事实结合起来时,事情就变得更加复杂了。有时候,无论你如何努力寻找,令人敬畏的发现并不仅仅是藏在你手里的一大堆日志数据中的。在其他情况下,你需要制作简单而漂亮的 BI 仪表板,并参与组织性的故事讲述,以证明你的工作或保持你的创业活动。通常情况下,如果你被训练成一名科学家,有些讲故事的过程会让人觉得有点手忙脚乱,即使它对商业成功至关重要。这只会加深症状。

4:社会训练聪明人永远生活在怀疑中

最重要的是,许多数据科学家在第一天就带着包袱出现了。那些从学术界转行的人(比如我的妻子)经常敏锐地意识到,他们对这个新领域的了解是多么少,而在他们的前世,对前沿成果的深刻把握对职业生涯至关重要。对于那些从其他地方转行过来的人来说,他们通常会敏锐地意识到他们不是而不是职业科学家,并且觉得他们把所有时间都花在了追赶上,不管他们有多聪明或勤奋。

我的版本是这两种感觉的奇怪混合体,多年来游走于商业和科学之间,在这两个地方都没有家的感觉。我花了几年时间才明白“数据科学家”是我所做工作的现代术语,因为当我开始做这件事时,这个术语并不存在。我认为数据科学是一种特殊而不同的东西,不知何故与我一直从事的机器学习、模拟建模、软件工程或统计工具设计无关。回想起来,这似乎不仅仅是愚蠢,但这就是冒名顶替综合症的工作方式。这不理智。

现在我已经达到了我职业生涯中管理一支球队的地步,我试着把这些都记在心里。我努力确保我们互相照顾,相信彼此的智慧。我们给人们留下了足够的空间来说‘我不知道那是什么’或者‘我还不知道那是什么’。在我看来,这是至关重要的,因为对于优秀的数据科学家来说,冒名顶替综合症永远不会消失。这是我们都必须学会接受的事情。

德克萨斯州的房地产投资

原文:https://towardsdatascience.com/real-estate-investing-in-texas-bbe794df1613?source=collection_archive---------30-----------------------

你能用时间序列分析预测德克萨斯州的房价吗?

Photo by M. B. M. on Unsplash

简介

对于这个项目,我使用 Zillow 的美国历史房价中值进行了时间序列分析。其目的是为投资者提供最好的邮政编码,以便在德克萨斯州购买和开发房屋。

我们开始吧!

数据

Figure 1: Zillow Median Housing Prices

数据集包含描述性变量,如州、城市、地区 ID 和县。它还包含一个名为 SizeRank 的变量,在数据探索后,该变量根据城市化程度对邮政编码进行排名。城市化程度越高的地区,规模排名越高。该数据还包括 1996 年 4 月至 2018 年 4 月的房价中位数。这些是我用来进行时间序列分析的值。在深入分析之前,需要满足一些先决条件才能考虑投资。

邮编选择

投资者有几种投资偏好:

  • 州:投资者希望专门投资于德克萨斯州,因为该州的人口在过去五年中增长了 10 %,居住在该州的人口的中值年龄为 33.9 岁,而美国的中值年龄为 37.4 岁。
  • 城市化:根据 SizeRank 变量,邮政编码应该在前 20 %
  • 房价中值:邮政编码区的平均房价应该在邮政编码区 1 年房价中值上下 1.5 个十分位数之间。选择一年期参数是因为这是房地产投资者即将面临的最现实的价格。
  • 风险:因为投资者采取规避风险的策略,所以根据低于 60%的变异系数来选择邮政编码。
  • 回报:一旦根据投资者的偏好过滤了所有的邮政编码,我就选择投资回报率最高的邮政编码。

当所有的邮政编码被过滤和排序后,我得到了以下五个邮政编码:

Figure 2: Final zip codes

邮政编码属于德克萨斯州的以下城市:

Figure 3: Locations that suited the investor’s needs

现在已经获得了 5 个邮政编码,我继续执行时间序列分析,根据预测的 10 年回报对这些邮政编码进行排序。

时间序列分析

现在可以绘制时间序列,我们可以直观地检查数据。

Figure 4: Exploring price change over time

住房价格中位数有一个积极的趋势,价格可能不是稳定的,因为下一个时期的价格取决于前一个时期的价格。因此,我计算了月度回报,对每个邮政编码进行了模型拟合,并使用月度回报计算了预测。回报更有可能是稳定的,并且具有恒定的零均值。接下来,我开始计算并绘制这五个邮政编码的月回报率。

*# new column for monthly returns* **for** zc **in** range(len(dfs_ts)): dfs_ts[zc][‘ret’] = np.nan *len(dfs_ts) **for** i **in** range(len(dfs_ts[zc])-1): dfs_ts[zc][‘ret’][i+1] = (dfs_ts[zc].value.iloc[i+1]/dfs_ts[zc].value.iloc[i]) — 1
  *
#plot the monthly returns for each zipcode* **for** i **in** range(len(dfs_ts)):     dfs_ts[i].ret.plot(figsize=(11, 5), color = 'b')     plt.title(f'Zipcode: **{dfs_ts[i].ZipCode[0]}**')     plt.xlabel('Date')     plt.ylabel('Returns %')     plt.legend(loc='best')     plt.show()

Figure 5: Waxachie’s Monthly Returns

从上面的图中,我注意到数据中没有明确的趋势,数据似乎是稳定的,这是构建模型的一个假设。检查平稳性的一个有用的可视化方法是滚动平均值和标准偏差,它们不应该显示数据平稳的趋势。

**for** i **in** range(len(dfs_ts)):
    rolmean= dfs_ts[i].ret.rolling(window=12, center=**False**).mean()
    rolstd = dfs_ts[i].ret.rolling(window=12, center=**False**).std()
    fig = plt.figure(figsize=(11, 5))
    orig = plt.plot(dfs_ts[i].ret,color='blue',label='Orginal')
    mean = plt.plot(rolmean, color='red', label='Rolling Mean')
    std  = plt.plot(rolstd, color='black', label='Rolling Std')
    plt.legend(loc='best')
    plt.title(f'Rolling Mean & Standard Deviation for Zipcode: **{dfs_ts[i].ZipCode[0]}**')
    plt.show()

Figure 6: Rolling Mean

虽然数据看起来不是静态的,但仅仅依靠可视化并着手拟合时间序列模型是不够的。因此,有必要对平稳性进行扩展的 Dickey-Fuller 检验。

Figure 7: Dickey-Fuller Results

从上面的结果来看,五个邮政编码中的两个导致了 95 %置信水平下的非平稳。因此,这四个邮政编码需要将 ARIMA 模型中的“I”参数设置为 1

ARIMA 模式

ARIMA 代表自回归综合移动平均线。到目前为止,只有“I”参数的值是已知的。现在是时候搜索 AR (p)和 MA (q)参数来最适合每个邮政编码了。

使用平稳时间序列的自相关函数(ACF)和偏自相关函数(PACF)图来估计 AR 和 MA 参数。

**def** acf_pacf(df, alags=48, plags=48):
    *'''Creates the ACF and PACF plots to* 
 *observe possible parameters for ARIMA model'''*
    *#Create figure*
    fig,(ax1, ax2) = plt.subplots(2,1, figsize=(13,8))
    *#Create ACF plot*
    plot_acf(df, lags=alags, zero=**False**, ax=ax1)
    *#PACF plot*
    plot_pacf(df, lags=plags, ax=ax2)
    plt.show()
**def** seasonal_plot(df, N=13, lags=[12,24,36,48,60,72]):
    *#differencing the rolling mean to find seasonality in acf plot*
    fig,(ax1, ax2) = plt.subplots(2,1,figsize=(13,8))
    rolling = df - df.rolling(N).mean()
    plot_acf(rolling.dropna(), lags=lags, ax=ax1)
    plot_pacf(rolling.dropna(), lags=lags, ax=ax2)
    plt.show();

Figure 8: ACF & PACF plots

为每个邮政编码创建了曲线图,以找到 AR 和 MA 参数的最佳估计值。对于大多数邮编来说,这些图遵循一种衰减模式。因此,模型将可能包括这两个参数。

为了进一步帮助寻找参数,使用 Akaike 信息标准或 AIC 执行嵌套 for 循环。AIC 是由 statsmodels 提供的一个值,用于估计统计模型的相对质量,并提供模型选择的方法。与具有较少要素的模型相比,具有较多要素且能很好地拟合数据的模型将被赋予较大的 AIC 值,以实现相同的拟合优度。因此,我们感兴趣的是尽可能低的 AIC 值。

*# Define the p, d and q parameters to take any value between 0 and 3*
p = d = q = range(0,2)*# Generate all different combinations of p, d and q triplets*
pdq = list(itertools.product(p, d, q))
pdqs = [(x[0], x[1], x[2], 12) **for** x **in** list(itertools.product(p, d, q))]
ns = []
**for** comb **in** pdq:    
    **for** combs **in** pdqs:
        **try**:
            mod = sm.tsa.statespace.SARIMAX(TS_75165,
                                                order=comb,
                                                seasonal_order=combs,
                                                enforce_stationarity=**False**,
                                                enforce_invertibility=**False**)
            output = mod.fit()
            ans.append([comb, combs, output.aic])
            *#print('ARIMA {} x {}12 : AIC Calculated ={}'.format(comb, combs, output.aic))*
        **except**:
            **continue** ans_df = pd.DataFrame(ans, columns=['pdq','pdqs', 'aic'])
ans_df.loc[ans_df['aic'].idxmin()]

根据这一估计,获得的 ARIMA 参数(P,I,Q)为(111),季节分量(P,D,Q,S)为(0,0,0,12)。这告诉我们,数据有 12 个周期的季节性。其他邮政编码也是如此。参数被传递到一个模型上,摘要如下:

Figure 9: Summary of Athe RIMA model

从上面的图中,我们可以看到 KDE 曲线相对接近 N(0,1)曲线,这表明残差是正态分布的。Q-Q 图还向我们展示了残差是正态分布的,因为蓝点(残差)沿着红线(正态分布)。左上角的图表没有显示任何明显的季节性,似乎是白噪声。右下角的图表证实了这一点,因为时间序列残差与其滞后版本的相关性较低。

拟合模型后的下一步是通过将预测值与真实值进行比较来验证模型的准确性。

**def** forecast(df, pred_date, start_date):
    *#make these global so they can be accessed later*
    **global** pred
    **global** pred_conf

    *#get predictions from specific date and calculate confidence intervals*
    pred = output.get_prediction(start=pd.to_datetime(pred_date), dynamic=**False**)
    pred_ci = pred.conf_int()

    *#plot real vs predicted values*
    rcParams['figure.figsize'] = 15,6

    *#plot observed values*
    ax = df[start_date:].plot(label='Observed')

    *#plot predicted values*
    pred.predicted_mean.plot(ax=ax, label='One-Step Forecast', alpha=.9)

    *#plot range of confidence intervals*
    ax.fill_between(pred_ci.index,
                   pred_ci.iloc[:,0],
                   pred_ci.iloc[:, 1], color = 'g', alpha=.5)
    *#axes labels*
    ax.set_xlabel('Date')
    ax.set_ylabel('Monthly Returns')
    plt.legend()
    plt.show() 

    values_forecasted = pred.predicted_mean
    values_truth = df

    rmse = np.sqrt(mean_squared_error(values_truth[pred_date:], values_forecasted))
    print('RMSE: '+str(rmse))
    print('mean: '+str(df[pred_date:].mean()))

我决定将过去的三年作为测试集,并在此之前对模型进行所有方面的训练。创建模型后,我计算了训练数据集的 RMSE,然后对测试集执行了一步预测,以计算模型的拟合优度。

Figure 10: One-step Forecast

从上图中我们可以看到,单步预测似乎与真实值非常吻合。量化我们预测的准确性也是有用的。我们将使用 MSE 或均方差,它概括了我们预测的平均误差。

对于动态预测,我们仅使用截至某个时间点的时间序列信息,之后,使用之前预测时间点的值生成预测。

预测

一旦模型被训练好,我就用这个模型来计算未来 10 年的月回报率。有了这些信息,我计算了 1 年、3 年、5 年和 10 年的总回报。

Figure 11: 10-year forecast for Waxahachie

调查结果

在对五个邮政编码进行时间序列分析并预测了十年的总回报后,我向投资者推荐了以下邮政编码:

  1. 76028:德克萨斯州伯利森(10 年回报率为 448 %)
  2. 75104:德克萨斯州雪松山(10 年回报率为 187 %)
  3. 75165:德克萨斯州沃克西哈奇(10 年回报率为 127 %)

拥有更多房地产投资领域的知识将提高分析能力。这些模型可以通过考虑其他外部变量来改进。这些其他变量可能包括税率、犯罪率、学区评级和利率。将时间序列分析中的房价和月回报率进行比较可能会很有趣。两者的结果将改善决策过程。

请注意,这个项目只是时间序列建模的一个练习,不应该作为实际的房地产投资。

自动气象站的实时异常检测

原文:https://towardsdatascience.com/real-time-anomaly-detection-with-aws-c237db9eaa3f?source=collection_archive---------8-----------------------

数据越新,就越具有可操作性和价值。这是实时数据分析的基本逻辑。

可能会有一些用户进行可疑的活动,或滥用您的折扣。另一方面,你也可以只是观察客户的行为并采取行动。为了实现这个目标,我将介绍如何使用 AWS 工具创建一个实时数据分析应用程序。

Picture taken from AWS Docs

想象一下,你想要实时观察的最后一千个数据点就画在上面这样的 2D 图上。我们的应用程序将能够捕捉那些暗示异常值的红色点。最重要的是,我们还建立了一个警报系统,只要出现一个红色点就会触发。

管道

投入

我们的应用程序的输入实际上可以是任何流数据。然而,我们需要它成为可操作的数据,以便我们的异常检测应用程序有意义。后端的方法日志、来自移动应用程序的点击/触摸事件或数据库更改事件将会很好,因为它们的性质赋予了我们观察客户端动作的能力。

溪流

我们如何将现有数据接收并传输到我们的应用程序中?AWS Kinesis 是一个非常方便的工具,易于使用,易于配置和自我管理。坦率地说,Kinesis 由 3 个不同的服务组成;对于流媒体,我们将使用 Kinesis 数据流

为了创建一个 Kinesis 数据流,你需要给它一个名字,并为它选择碎片计数。碎片是 Kinesis 流的处理单位,在我写这篇文章的时候,一个碎片可以每秒接收 1MB 和 1000 条记录,每秒发出 2MB。对于大多数基本应用程序,1 个 shard 足以处理您的输入数据。

摄取

现在我们已经创建了流,我们可以接收实时数据了。有官方库可以使用 AWS 工具,例如:

  • botoforPython 2
  • boto3Python 3
  • AWS-SDKfornode . js

我们只需要我们想要放置记录的流的名称,以及写入该流的权限。

数据分析应用

为了处理数据并从我们的实时数据中捕捉异常,我们将使用 Kinesis 的另一项名为 Kinesis 数据分析的服务。这是一个非常灵活的工具,它使我们能够在应用程序处理数据之前对数据进行预处理,然后使用丰富的 SQL 引擎处理数据,并对应用程序捕获的数据进行后处理。

  • 预处理器是一个由 Kinesis 数据流触发的 AWS Lambda 函数,它可能会丰富数据或清理数据。如果我们想在应用程序中使用一些其他数据,我们可以用这些数据丰富我们的输入。此外,我们可能希望通过类型转换来清理输入,或者移除未使用的字段。
  • 异常检测是我们的 Kinesis 数据分析应用程序的名称。它是用 SQL 编写的,并增加了特殊的分析功能。我将在下一部分对此进行更深入的探讨。
  • 后处理器是一个 AWS Lambda 函数,由 Kinesis 数据分析为其每个结果触发。你可以对结果做任何你想做的事。您可以将它附加到一个警报系统,或者您可以调用一个端点,或者您可能希望用该数据训练一个模型。灵活性是存在的。

警报

AWS 提供了一个名为简单通知服务的工具,您可以用它来创建警报系统。在我们的例子中,我们将异常检测应用程序的结果发送到一个 SNS 主题。然后,订阅该主题的每个用户都会收到一个通知,比如说,一封电子邮件。

因此,我们的管道如下图所示。你可以断开 Lambda functions,或者 SNS,用你想要的另一个服务来代替。这种方法提供了灵活性,同时借助 AWS 工具保持了自我管理和持久性。

数据分析应用

在 Kinesis 中创建数据分析应用相当简单:

  • 我们选择应用引擎,SQL 或 Apache Flink。我们将在我们的案例中使用 SQL。
  • 我们选择一个数据源,Kinesis 流或 Kinesis 消防水带交付流。在我们的例子中,我们将使用 Kinesis 流。
  • 可以创建一个 lambda 函数来预先预处理数据。
  • 由于我们是用 SQL 构建我们的应用程序,我们的数据需要严格类型化,这意味着需要一个模式。Kinesis 数据分析具有自动推断模式的功能,然后您可以根据需要编辑模式。

An example schema enforced data analytics app input format

  • 我们可以连接另一个称为参考数据的数据源,以便在应用程序中使用。我们将暂时忽略它。
  • 我们可以在 Kinesis 流、Kinesis 消防水管输送流或 Lambda 函数中选择结果的目的地。在我们的例子中,选择了一个后处理器 Lambda 函数来将数据发送到 SNS 以创建警报。
  • 至于应用程序的代码,人们需要阅读 AWS Kinesis 数据分析 SQL 参考文档。SQL for data analytics 应用程序增加了分析功能和技术,如流、泵和窗口。我将在接下来的章节中略微谈到它们。

整体逻辑

  • 像带有 TTL(生存时间)数据的表。
CREATE OR REPLACE STREAM "DESTINATION_SQL_STREAM" 
(
"field1" DOUBLE, 
"field2" INTEGER, 
"ANOMALY_SCORE" DOUBLE
);
  • 还有将实时数据输入数据流的
  • 您可以用名称SOURCE_SQL_STREAM_001访问您的输入流。
  • 代码的输出应该是一个流。你需要把结果注入到这条流中。
CREATE OR REPLACE PUMP "STREAM_PUMP" 
AS INSERT INTO "DESTINATION_SQL_STREAM"SELECT "field1", "field2", ANOMALY_SCORE
FROM TABLE (RANDOM_CUT_FOREST(CURSOR(SELECT STREAM "field1", "field2" 
FROM "SOURCE_SQL_STREAM_001"
WHERE "field1" > 0 AND "field2" > 0
ORDER BY STEP("TEMP_STREAM".ROWTIME BY INTERVAL '10' SECOND);)));

上面的代码片段实际上构建了一个完整的实时数据分析应用程序代码。我们确实从 windows 中的流中读取了 field1field2 ,我将在这之后谈到,并将它们应用到后台使用机器学习的RANDOM _ CUT _ FOREST内置 SQL 函数中。该模型被增量地训练,并且在为具有足够数据来训练的模型输入一些数据点之后,可以说出一个数据点是否是异常。随机切割森林函数的结果被泵入目标流。

Windows 操作系统

窗口让我们能够对数据执行聚合功能。例如,要对实时数据进行计数,我们需要为数据设定边界。

窗口有不同的技术,但我将只通过最常用的窗口:翻滚和滑动。

  • 滚动窗口分批分离数据。这些批次的界限通常以时间为基础选择,很少以数据计数为基础。我们想要使用滚动窗口的根本原因是我们不会两次使用相同的数据点。
GROUP BY field1,
STEP("SOURCE_SQL_STREAM_001".ROWTIME BY INTERVAL '60' SECOND);
  • 进行时基聚合时,滑动窗口更有用。有一个固定大小的窗口,它逐渐向右移动。你可能想用它来观察一个峰值点。
WINDOW W1 AS (    
PARTITION BY field1     
RANGE INTERVAL '1' MINUTE PRECEDING);

您还可以构建自定义窗口或使用交错窗口,每当新数据点到达时都会创建一个窗口。

高级用法

Kinesis 数据分析 SQL 引擎让您可以灵活地创建更复杂的逻辑来处理更困难的情况。

  • 如果我们只想发送异常值大于特定值的记录,该怎么办?或者,如果该分数需要与一些其他参考数据聚合在一起呢?为了解决这些问题,可以在应用程序中定义第二个流。异常检测算法的结果应该被泵送到这个新的临时流中,而不是我们的目的流中。然后,我们有另一个窗口来对我们的结果数据进行新的聚合。这种新聚合的结果现在可以被注入到我们的目标流中。

从上面的例子可以看出,可以有多个不同窗口类型的流。

结论

我已经经历了灵活的结构,强大的 SQL 引擎与实现流技术,自我管理服务的 AWS。我们已经创建了一个示例实时数据分析应用程序,用于检测数据中的异常。我们利用 AWS Lambda 在手动数据分析应用之前和之后对数据进行预处理和后处理。我们使用 AWS SNS 创建了一个警报系统,一旦出现异常情况,该系统就会实时通知我们。

感兴趣的

Zynga 技术团队展示了他们对 Kinesis 数据分析的使用,以及他们如何使用它来解决复杂的情况。

基于指数分布数据的实时异常检测

原文:https://towardsdatascience.com/real-time-anomaly-detection-with-exponentially-distrubted-data-205e0df32096?source=collection_archive---------24-----------------------

一个简单的算法可以提示你异常活动

动机

考虑以下情况:您运营一个网站,允许人们预约他们的医生。在过去的一个月中,您观察到有人每 5 分钟预约一次,但略有不同。然而,在某一天监控预约量时,您发现 10 分钟内没有任何预约。然后 15 分钟。然后 20 分钟。在什么情况下你应该关注并跟进,以确保不存在可能阻止人们预约的问题?

衍生物

这是一个常见的统计问题,它来源于对“到达间隔时间”或事件之间的时间的考虑。如果所讨论的事件是相互独立的,并且它们发生的速率在一段时间内是稳定的,那么到达间隔时间是指数分布的。形式上,我们有以下内容:

Exponential PDF, CDF and first two moments

其中 f(y)是 y 的密度函数,y 是到达间隔时间的随机变量。累积分布函数 F(y)表示观察到小于 y 的值的概率。

这是一个非常好的、简单的分布,它将允许我们实时地对观察到的数据做出一些快速的推断。再次考虑上面的例子。我们声明预约之间的平均间隔时间是 5 分钟。所以平均每分钟,我们观察到 0.2 个约会——这是到达率,或者上面指定的模型中的λ。

我们的目标是提出一个阈值,以便在没有预约的情况下经过足够长的时间后,我们将认为不活动是异常的。这个阈值有点武断——就像统计推断中的大多数显著性阈值一样。但是让我们想出一个阈值(c ),使得通过该阈值的概率小于 1%。数学上,这看起来像

这告诉我们,观察到超过 23.02 分钟的到达间隔时间的概率小于 1%。如果我们只考虑这一个事件,我们会认为观察到这个到达间隔时间是罕见的,我们会将其归类为异常值并进行随访。当我们将我们的容忍水平(也称为“生存概率”)从 1%更改为其他值时,我们可以看到阈值是如何变化的:

直觉上,观察到较高到达间隔时间的概率降低。如果我们将容忍度设置为 0.1%,那么我们将有一个 34 分钟的阈值。这个“生存函数”在保险等其他领域有很多应用(想想人寿保险和死亡率)。我们可以看到,从大约 20 分钟开始,概率变得非常小,并且渐近接近于零。这个尾部的值应该让我们停下来研究一下。

现在让我们停下来,思考一下这个结果给了我们什么。这个推导所代表的是观察到单一随机事件的概率。有了足够的数据或事件,这些离群事件就会发生最终。这就是指数分布的本质——所有正值都有可能出现。在现实世界中,由于自然限制,这可能不是真的,但它是近似的。这个阈值的推导并没有给我们一个完美识别异常的幻数。这意在引起一些人的注意,并刺激对什么是可能异常的调查。或者换句话说,它意味着标记那些不太可能是纯粹随机的结果的事件。

此外,验证之前做出的关于事件独立性和到达率稳定性的假设非常重要。如果其中任何一个不成立,模型就会崩溃。

从数学到应用科学

从数学练习到应用的、生产就绪的算法需要几个额外的步骤。整个过程中更重要的部分不是统计数据,而是与生产环境的集成。我不打算深入设置生产管道的血淋淋的细节——无论如何,这些细节中的许多都是特定于上下文的(Azure vs AWS vs Google Cloud 都是不同的)。然而,我提供了一些我发现对这种练习特别重要的细节。

在处理真实数据时,会出现一些实际障碍。如上所述,即使您确信数据是独立的,到达率也很容易随时间而变化。在预约的情况下,潜在的患者行为可以改变,或者新的提供者可以添加到您的网络中,然后更多的患者可以访问在线调度(可能会增加到达率)。此外,到达率可能因一天中的时间甚至一周中的日期而异。在这种情况下,考虑基于这些类型的变量来调节平均值是有意义的。代价是样本量的减少,这也阻止了对平均值的精确估计。

接下来,根据数据的提取方式,真正的实时检测可能是不可能的。如果数据是直接从一些实时流媒体服务中提取的,那么就有可能获得更实时的感觉。然而,如果在您的算法和初始数据源之间有一个 ETL 管道,可能会有很大的延迟。

如果有延误,也不一定是世界末日。视上下文而定,可能根本不重要。例如,如果 ETL 管道每 5 分钟运行一次,并且捕获的数据的平均到达时间为 2 分钟,则以 1%计算的异常将出现在 9:12 分钟标记附近,这意味着算法将在 10 分钟标记处拾取它,增加了 48 秒的检测过程。几乎在任何情况下,这都不应该成为交易的破坏者。你只需要决定什么最适合你的环境。

最后,如果 ETL 备份或失败,一旦 ETL 再次开始运行,这可能会触发算法将事件分类为异常值。显然,这些不是真正的离群值。

如果这些障碍可以避免(或充分处理),那么算法是简单明了的。核心代码可以用几行代码来概括。只进行一次比较,即(I)自上次事件以来经过的当前时间和(ii)上面推导出的阈值。如果经过的时间大于阈值,则标记该事件;如果不是,那么什么也不做。简单!

结论

我们已经走过了一个方法,推导出一个简单的指数分布数据异常检测技术。通过一些基本的假设,一个好的模型和公式可以应用于到达间隔时间,以标记那些预先定义的“太长”的时间。这种方法不是识别实际异常的简单方法,而是识别不太可能偶然发生的事件的方法。

虽然这个讨论的核心是一个数学练习,但实现和相关的障碍是更重要和更实质性的组成部分。这些障碍包括(1)选择包含在模型中的一致准确的到达率,(2) ETL 管道引入实时数据访问的延迟,以及(3) ETL 失败可能在结果中引入假阳性。一旦这些问题得到充分解决,实际的算法就是一个简单的过程。

考虑 1000 个事件的集合。每个都有 1%的概率被归类为异常值。而非在整个集合中看到异常值的概率是 0.99⁰⁰⁰= 0.004%,这非常小。换句话说,虽然对于任何给定的事件,可能不太可能观察到异常值,但很可能在足够大的样本中至少会出现一个异常值。

使用 Tensorflow 对象检测 API 和 iOS 集成示例进行实时汽车/行人/车道检测

原文:https://towardsdatascience.com/real-time-car-pedestrian-lane-detection-using-tensorflow-object-detection-api-and-an-ios-fbb1b7cbb157?source=collection_archive---------5-----------------------

Prediction with mPA > 80% using ssd_mobilenet_v1_pets.config with pretrained ssd_mobilenet_v1_coco_2018_01_28 nets

Total Loss decrease with respect of optimization steps. 100 training photos and 20 testing photos. Better results can be achieved with more data.

受到其他人在异议检测项目上的工作的启发,例如

  1. 如何使用 TensorFlow 的对象检测器 API 训练您自己的对象检测器,它演示了如何使用 Tensorflow 的 API 来构建和训练用于对象检测的定制 DL 网络。
  2. 如何构建实时物体识别 iOS app ,演示了如何将一个经过训练的 DL net 集成到 iOS app 中。

然后,我真的很想尝试如何使用类似的程序来建立自己的网络,在 iOS 的实时摄像头中检测汽车/行人/自行车(+车道)。结合我之前关于自适应巡航控制的帖子,集成的功能应该真的很有意思。

在我进一步谈论技术细节之前,为了节省你的时间,使用的软件版本必须放在最前面。我在使用 Xcode 7.3 版本的 macOS EI Capitan 时遇到了一些问题,所以在我的尝试中,我不得不将我的系统更新到 Xcode 10.2 版本的 Moyawe。主要问题是我尝试[例 2](http://How to build real-time object recognition iOS app, which demonstrates how integrate a trained DL net into iOS) 的例子时,我 iphone 8 上安装的 app 一直碾压。

Tensorflow 是使用 pip 虚拟环境 1.9.0 版安装的。在我使用 1.8 之前,问题是当我试图冻结用于 iOS 检测 app 的训练图时,它总是失败,并出现错误“non_max_suppression()”。

根据这篇帖子,tensor flow for iOS 版本为 v1.11。我也安装了最新版本,但是[例 2](http://How to build real-time object recognition iOS app, which demonstrates how integrate a trained DL net into iOS) 中的代码无法成功编译。因为我想将周围的框添加到检测到的项目中,所以我必须回到 1.11 版。

如果你想知道更多的细节,请在下面评论,我会试着分享更多我的经验。

图片报和培训网

  1. 正在准备输入 TFRecord 文件

首先,我从这里得到合适的数据集。只使用了 120 张图片,100 张用于训练,20 张用于测试。记录的街道快照用于训练。然后我用 labelImg 来标记物体。我的标注地图包含三个项目,如下所示

My model contains three items: car, pedestrian and bike

手动给物品贴标签既无聊又对眼睛有害。所以我建议你使用一些聪明的方法来这样做,比如使用一些自动注释工具。实际上,这种注释过程也与使用机器学习(ML)技术的对象检测/分割/分类的主题相关。如果我有时间,我会写另一个关于它的故事。

在对来自 100 张训练图片和 20 张测试图片的对象进行人工标记之后,对象在 2D 图片中的位置被保存为 xml 格式。然后,我使用以下两个步骤来获得 TFRecord 格式,它将被直接提供给 TF 训练过程。使用的代码可以从我的 github 下载。有些文件是来自 Dat Tran 的 github 库的令牌。

转换图片+xml = > TFRecord 文件

  • 为每个数据集将单独的*.xml文件转换为统一的*.csv文件。
  • 将每个数据集的*.csv文件转换为*.record文件(TFRecord 格式)。

2.设置培训配置

我目前的目的不是从头构建一个新的网络,而是演示获得定制工作网络的过程。然后我用 TF 发布的 github 的预建配置SSD _ mobilenet _ v1 _ pets . config。不是从一个完全随机的初始化模型开始,而是采用了一个预先训练好的模型,SSD _ mobilenet _ v1 _ coco _ 2018 _ 01 _ 28,以加快训练过程,就像 TF 官网上建议的那样。然后,一些相应的参数设置如下

  • num_classes: 3 #设置不同标签类别的数量
  • 键入:' ssd_mobilenet_v1' #设置为您选择的预训练模型的名称
  • fine _ tune _ check point:" pre-trained-model/model . ckpt "#预训练模型提取文件路径
  • TF _ record _ input _ reader {
    input _ Path:" annotations/train . record "#第一步训练 TFRecord 文件的路径
    }
    label _ map _ Path:" annotations/label _ map . Pb txt "#标注地图文件的路径如前所示
  • TF _ record _ input _ reader {
    input _ Path:" annotations/test . record "#测试 TFRecord 的路径
    }
    label _ map _ Path:" annotations/label _ map . Pb txt "#标签映射文件的路径

3.TF 培训流程

使用以下命令进行训练过程(注意:—必须用两个减号(-)替换)

python train . py-logtostderr-train _ dir =。/training/—pipeline _ config _ path =。/training/SSD _ mobilenet _ v1 _ pets . config

Configuration of my laptop

如果遇到一些错误,首先检查输入数据路径和 tensorflow 的版本。训练过程应该持续很长时间。我的训练是在我自己的笔记本电脑上进行的,花了大约 20 个小时/8k 步。通过调查损失,我终止了它,形成了一个用于 iOS 集成的次优模型。对于更精确的模型,必须使用更多的输入图片。训练过程也可以像 Dat Tran 所做的那样从云中运行。

4.训练数据观察和可视化

Tensorboard 用于即时可视化培训,使用

tensor board—logdir[你的日志目录] — host=127.0.0.1

如果你遇到关于 LC_ALL 的问题,使用下面的命令并重新运行 tensorboard

export LC_ALL="en_US。UTF-8”

导出 LC_CTYPE="en_US。UTF-8”

根据来自终端的弹出信息执行以下操作。因为我对损失很满意,所以我终止了训练并提取了图形。

5.提取/冻结图表

输入类型=图像张量

管道配置路径=。/training/SSD _ mobilenet _ v1 _ pets . config

特训 _ CKPT _ 前缀=。/training/model.ckpt-7265

EXPORT_DIR=。/frozen_inference_graph

python ~/tensor flow/models/research/object _ detection/EXPORT _ inference _ graph . py-INPUT _ TYPE = $ { INPUT _ TYPE }-PIPELINE _ CONFIG _ PATH = $ { PIPELINE _ CONFIG _ PATH }-TRAINED _ check point _ PREFIX = $ { TRAINED _ CKPT _ PREFIX }-output _ directory = $

如果你遇到【non _ max _ suppression()】的问题,尝试使用 TF v1.9.0

构建 iOS 应用程序

直到现在我有了自己定制的训练图,然后我按照这篇文章的步骤开发一个测试 iOS 应用。没有什么特别的事情发生,但是错误信息可能会再次出现。也看看这个 github 帖子,可能会有帮助。由于代码使用了 iphone 的后置摄像头,所以它不能正确地简单运行 Xcode 内的模拟器。应该特别注意一些设置,尤其是头文件和库的搜索和链接路径。其他技术细节可以从 ios 的 tensorflow 官方网站上查看。

我的 iOS 应用程序的最终实现示例,不完美,但足够好,可以更进一步。

未完待续…

  1. 车道检测
  2. 网速快一点的,试试 yolo net,不然对一个高速条件没用。
  3. 距离计算

支持电子竞技观看的实时仪表盘

原文:https://towardsdatascience.com/real-time-dashboards-to-support-esports-spectating-48cfa1e43274?source=collection_archive---------16-----------------------

这一定是我在学术界期间最喜欢的项目。

The League of Legends and Counter-strike: Global Offensive dashboards in action! Read on to learn more.

我的博士学位是通过多个(欧洲和更小的)项目资助的,主题包括学习分析、数字人文和失业。它们很有趣:我设计了桌面、桌面和移动设备上的数据可视化,我研究了用户的感知和体验……所有的乐趣和游戏。

但是不,不是游戏。

我一直对游戏情有独钟。我搬到国外住了两年(并让我的妻子放弃了一份很好的工作),这样我就可以实现梦想,成为一名游戏开发人员(以后再说吧)。将我的研究与游戏相结合是我长久以来的梦想。

唉,没有资金支持这项研究。但是生活总会有办法的,对吧?;)

学生来救援

同学们!当然啦!每年我们都有新的工程硕士学生从事有趣(有时很无聊)的硕士论文课题。所以我引入了一个新的:支持观众的电子竞技仪表板。不同玩家在大型战场上的高节奏行动不容易跟上。那么,我们如何帮助观众在职业玩家玩的这些狂热游戏中,更好地实时了解正在发生的事情。

在学生中取得了巨大的成功,但遗憾的是名额有限,两名学生“中了彩票”(我们对此事没有发言权。挺随机的):Hans Cauwenbergh 和 Bram Luycx。

我们很幸运。这被证明是有史以来与学生最好的合作之一。

仪表板

汉斯跳上了《英雄联盟》,而布拉姆则接下了《反恐精英:全球攻势》。我们在 Reddit 上设计并设置了几项调查,以深入了解观众的动机和对各场比赛提供的不同统计数据的感知有用性,从而为仪表板的设计提供信息。然后,他们就出发了!

Viewer preferences (167 responses for League of Legends, 596 for Counter-strike: Global Offensive)

英雄联盟

a) Gold distribution, b) Damage dealt, c) Vulnerability.

仪表板是五次迭代的结果:两个数字非交互设计,两个交互原型,以及用 React.js 和 D3.js 开发的最终全功能原型。第一次到第四次迭代是使用界面设计工具 Figma 开发的。22 名参与者参与了原型迭代的评估。

主视图分为三个模块:黄金,伤害和脆弱性。所有模块持续实时更新。金和伤害相当明显。我来解释一下漏洞

漏洞提供了每个玩家有多脆弱的指示。一个简单的线性方程结合了玩家相对于团队其他成员和/或敌人的位置劣势,当前的生命和法力点,防御统计和召唤师法术可用性。这些值被组合并可视化在播放器图标周围,作为一个摘要指示器。这个视图让观众预测游戏的状态。

汉斯还添加了一个有趣的荣格勒可视化:

反恐精英:全球攻势

a) Round progression, b) Economy button, c) Map button, d) Scoreboard, e) Money Distribution, f) Average Damage per Round

该仪表板是三次迭代的结果:一个纸质原型,一个使用 Figma 设计的非交互式数字原型,以及一个使用 React.js 和 D3.js 开发的全功能原型。14 名参与者参与了迭代的评估。仪表板由回合进程、经济、地图、记分牌、金钱分配和每回合平均伤害组成。

结果

通过半结构化采访和眼球追踪,我们设法进一步了解参与者在使用我们的仪表盘观看这些电子竞技游戏时的感知和体验。它产生了一个有趣的观众仪表盘设计目标列表,我们在澳大利亚墨尔本举行的 2018CHI PLAY 上发布并展示了该列表。

LoL and CS:GO eye tracking results from each participant after the evaluation. The attention heatmap indicates the areas of interest where participants focused more during the whole match.

我不会把这篇容易理解的博客文章变成一篇冗长的科学文章。但是如果你对指南感兴趣,你可以在这里找到的文章(或者在我的网站上给我发消息)。或者浏览下面的幻灯片!

如果有足够的兴趣,我将在 Medium 上发布指南的摘要;)就在评论里告诉我吧!

汉斯(全职)和我(兼职自由职业者)并没有止步于此,而是在为GRID eSports Gmbh工作,在那里,大量的电子竞技数据奇迹正在发生!

接下来,我是一名 自由职业数据可视化体验设计师/顾问 。我是被雇佣的,所以如果你有任何 dataviz 需求,来 svencharleer.com打个招呼吧!

基于 Python、Keras 和 OpenCV 的实时人脸活性检测

原文:https://towardsdatascience.com/real-time-face-liveness-detection-with-python-keras-and-opencv-c35dc70dafd3?source=collection_archive---------5-----------------------

Image by Jon Tyson from Unsplash.

你在互联网和研究论文上找到的大多数面部识别算法都遭受了照片攻击。这些方法在检测和识别来自网络摄像头的图像、视频和视频流中的人脸方面非常有效。然而,他们不能区分现实生活中的脸和照片上的脸。这种无法识别人脸的现象是由于这些算法是在 2D 框架下工作的。

现在让我们想象我们想要实现一个面部识别开门器。该系统将很好地区分已知和未知的面孔,以便只有授权的人才能访问。尽管如此,不怀好意的人很容易通过仅展示授权人的照片来进入。这就是 3D 探测器,类似于苹果的 FaceID,进入游戏的地方。但是如果我们没有 3D 探测器呢?

Example of photo attack with Obama face ❌ (Image by author)

本文的目的是实现一个基于眨眼检测的人脸活性检测算法来抵御照片攻击。该算法通过网络摄像头实时工作,只有当人们眨眼时才会显示他们的名字。通俗地说,程序运行如下:

  1. 检测网络摄像头生成的每一帧中的人脸。
  2. 对于每个检测到的面部,检测眼睛。
  3. 对于每个检测到的眼睛,检测眼睛是睁开还是闭上。
  4. 如果在某个时间点检测到眼睛是睁开的,然后闭上,再睁开,我们推断这个人已经眨眼,程序显示它的名字(在面部识别开门器的情况下,我们将授权这个人进入)。

对于人脸的检测和识别,你需要安装 face_recognition 库,它提供了非常有用的深度学习方法来查找和识别图像中的人脸。特别是, face_locations、face_encodingscompare_faces 函数是 3 个最有用的。**face _ locations方法可以使用两种方法检测人脸:梯度方向的历史程序(HoG) 和 C 选择性神经网络(CNN)。由于时间限制选择了 HoG 方法。 face_encodings 函数是一个预训练的卷积神经网络,能够将图像编码成 128 个特征的向量。这个嵌入向量应该代表足够的信息来区分两个不同的人。最后, compare_faces 计算两个嵌入向量之间的距离。它将允许算法识别从网络摄像头帧中提取的人脸,并将其嵌入向量与我们数据集中所有编码的人脸进行比较。最近的向量应该对应于同一个人。

1.已知人脸数据集编码

在我的例子中,算法能够识别我和巴拉克·奥巴马。我选择了大约 10 张图片。下面是处理和编码已知人脸数据库的代码。

既然我们知道了我们想要识别的每个人的编码,我们可以尝试通过网络摄像头来识别和辨认人脸。但是,在移动到这一部分之前,我们需要区分人脸照片和活人的脸。

2.人脸活性检测

提醒一下,我们的目标是在某个时刻检测一个睁开-闭上-睁开的眼睛模式。我训练了一个卷积神经网络来分类一只眼睛是闭着的还是睁开的。所选择的模型是 LeNet-5,该模型已经在【CEW】数据集上被训练。它由大约 4800 个大小为 24x24 的眼睛图像组成。

在评估模型时,我达到了 94% 的准确率。

每当我们检测到一只眼睛时,我们使用我们的模型预测它的状态,并且我们跟踪每个人的眼睛状态。因此,由于下面的函数,检测眨眼变得非常容易,该函数试图在眼睛状态历史中找到闭-开-闭模式。

3.活人的人脸识别

我们几乎拥有了设置我们的“真实”——人脸识别算法的所有元素。我们只需要一种实时检测人脸和眼睛的方法。我使用 openCV 预训练的 Haar-cascade 分类器来执行这些任务。关于 Haar-cascade 人脸和眼睛检测的更多信息,我强烈推荐你阅读 openCV 的这篇伟大的文章

上面的函数是用于检测和识别真实人脸的代码。它接受论点:

  • 模型:我们的睁眼/闭眼分类器
  • 视频捕获:一个流视频
  • 人脸检测器:一个哈尔级联人脸分类器。我用了Haar cascade _ frontal face _ alt . XML
  • 睁眼探测器:一个哈尔级联睁眼分类器。我用了Haar scade _ eye _ tree _ glasses . XML
  • 左眼检测器:一个哈尔级联左眼分类器。我用的是Haar cascode _ lefteye _ 2 splits . XML可以检测眼睛睁开还是闭上。
  • 右眼检测器:一个哈尔级联右眼分类器。我用了Haar scade _ righteye _ 2 splits . XML可以检测眼睛睁开还是闭上。
  • 数据:已知编码和已知名称的字典
  • eyes_detected:包含每个名字的眼睛状态历史的字典。

第 2–4 行,我们从网络摄像头流中抓取一帧,并调整其大小以加快计算速度。在第 10 行,我们从帧中检测人脸,然后在第 21 行,我们将它们编码成一个 128 维向量。在第 23–38 行中,我们将这个向量与已知的人脸编码进行比较,通过计算匹配的数量来确定这个人的名字。具有最大匹配数量的一个被选择。从第 45 行开始,我们试着从面部框中检测眼睛。首先,我们尝试用睁眼 _ 眼睛 _ 检测器检测睁开的眼睛。如果检测器成功,则在第 54 行1’被添加到眼睛状态历史中,这意味着眼睛是睁开的,因为 open_eye_detector 不能检测到闭着的眼睛。否则,如果第一分类器已经失败,(可能因为眼睛是闭着的或者仅仅因为它没有识别出眼睛),那么使用左眼右眼检测器。面部被分成左侧和右侧,以供相应的检测器进行分类。从行 92 开始,提取眼睛部分,并且训练的模型预测眼睛是否闭合。如果检测到一只眼睛闭上,则预测两只眼睛都闭上,并且将“0”添加到眼睛状态历史中。否则就断定是睁眼了。最后,在行 110** 处,使用 isBlinking() 函数检测眨眼,如果此人眨眼,则显示其姓名。**

注:完整代码可以在my github上找到。😃

Photo attack thwarted using eye-blink detection ✔️ (Image by author)

参考

CPU 实时人脸识别

原文:https://towardsdatascience.com/real-time-face-recognition-with-cpu-983d35cc3ec5?source=collection_archive---------1-----------------------

看完这篇文章,你就会明白如何利用预先训练好的模型,用 CPU 构建实时人脸识别系统。

Static face recognition with system described in this post

学术和工业领域都投入了巨大的努力来开发既快速又准确的人脸识别算法和模型。由于这些努力,现在可以用 CPU 完成多张人脸的准确、实时的人脸识别。

在这篇文章中,我们将使用林扎尔和 MobileFaceNet 的超轻型人脸检测器构建一个实时人脸识别系统。

人脸检测

为了识别人脸,我们首先需要从图像中检测人脸。有许多方法可以做到这一点。

我已经探索了多种面部检测器。其中包括人脸识别包(包含方向梯度直方图(HOG)和卷积神经网络(CNN)检测器) MTCNNYolofaceFaced ,以及最近发布的超轻人脸检测器。

我发现,虽然 Yoloface 具有最高的准确性和最一致的执行时间,但超轻人脸检测器在速度方面是无与伦比的,并产生了相对较好的准确性。

在这篇文章中,我们将使用超轻型探测器。但是如果你有兴趣应用提到的任何其他检测方法,你可以在这里参考我的 Github 库

要使用超轻模型,需要以下 python(python 3.6 版)包:

onnx==1.6.0``onnx-tf==1.3.0``onnxruntime==0.5.0``opencv-python==4.1.1.26

使用pip install安装所有的依赖项。

准备好环境后,我们可以通过以下代码使用 OpenCV 库从我们的网络摄像头获取帧馈送:

对于我们获取的每个帧,我们需要在模型训练阶段遵循精确的预处理流水线,以实现预期的性能。

由于我们将使用预训练的[ultra_light_640.onnx](https://drive.google.com/open?id=1EDOJtWE_rnotlHZBRoYvPotRHr9PghxY)模型,我们必须将输入图像的大小调整为 640x480。如果您使用的是 320 型号,请相应地重新设置。

代码如下所示:

在预处理图像之后,我们将必须准备 ONNX 模型并创建一个 ONNX 推理会话。想了解更多关于模型推断的内容,可以查看这里的链接

准备模型和创建推理会话的代码如下所示:

现在是时候用下面的代码检测一些人脸了:

变量confidences包含了boxes变量中每个框的置信水平列表。一个置信度对的第一和第二值分别指示包含背景和人脸的概率。

由于boxes值包含了所有生成的盒子,我们将不得不根据相应的 Jaccard 索引(也称为 Union 上的交集)来识别具有包含面部的高概率的盒子并移除重复的盒子。

获得正确框的代码如下所示:

predict函数将接受一个盒子数组,以及每个标签对应的置信度。然后,将执行置信度过滤,以保留所有包含人脸的概率较高的框。

之后,计算每个剩余盒子的交集(IOU)值。最后,使用具有硬 IOU 阈值的非最大抑制来过滤方框,以移除相似的方框。

一旦我们有了过滤框,我们就可以在视频流中绘制和显示:

英特尔酷睿 i7–8550 u CPU @ 1.80 GHz 笔记本电脑网络摄像头的结果:

检测部分的完整代码可以在这里找到。

人脸识别

检测到人脸后,下一步是识别它们。面部识别的技术有很多,包括 OpenFaceFaceNetVGGFace2MobileNetV2 等。本文中我们将使用的模型是 MobileFaceNet,它的灵感来自于 MobileNetV2。这个网络架构的细节以及如何训练可以在这里找到。

一般来说,识别一张人脸需要三个步骤:(1)数据预处理,(2)人脸特征提取,以及(3)比较目标人脸和数据库中人脸的特征。

预处理

我们将使用的数据是吉米·基梅尔采访詹妮弗·安妮斯顿的视频剪辑。我们将拍摄视频片段并提取詹妮弗·安妮斯顿的面部。您可以在相应的文件夹中添加自己的培训数据。

文件结构如下所示:

train.py
faces
  --training
    --rachel
      --rachel.mp4
    --...
  --temp
  --embeddings

一旦训练数据就绪,我们就可以使用下面的代码对视频剪辑执行人脸提取:

boxes里面抓拍人脸。现在,我们可以从人脸预处理开始。

我们将确定五个面部标志,通过适当的变换对齐面部,并将它们的大小调整为 112x112。

我们将使用dlibimutils来完成这些子任务。如果您还没有安装这两个软件包,请使用pip install进行安装。

满足要求后,我们需要用下面的代码启动shape_predictor(用于面部标志预测)和FaceAligner:

shape_predictor_5_landmarks.dat用过的可以在这里下载desiredLeftEye指定你想要提取的人脸的大小。通常该值的范围是从 0.2 到 0.4。值越小,脸就越大。

下面的代码说明了如何在提取的所有面上应用面对齐并写入文件:

结果:

Eyes are aligned and faces are of similar sizes.

为了使用 MobileFaceNet 模型,需要进一步的预处理。我们必须用 127.5 减去对齐的面,然后用 128 除结果,如论文中所述。

用于如上所述的更多预处理的代码:

计算面部嵌入

是时候从预处理过的人脸中获取面部特征了。我们将从加载张量流模型开始:

接下来,我们将定义网络输入,获取嵌入并保存到 pickle 文件:

认出一张脸

要识别人脸,只需加载带有相应标签的嵌入数据集。然后使用欧几里德距离和阈值来确定每个检测到的人脸属于谁。

代码如下所示:

最后

让我们看看我们的结果:

Embeddings acquired for six main characters from Friends series

同样,你可以在这里找到完整的代码。

摘要

据此,我们创建了一个可以用 CPU 进行实时人脸识别的系统。虽然它的运行速度只有大约 13 FPS,但它比使用复杂的 CNN 要快得多。

然而,我们仍然可以做很多事情来提高这个系统的性能(精度和速度)。潜在地,我们可以应用知识提取来压缩当前模型,并使用低位量化来进一步减小模型大小。此外,我们可以使用其他机器学习分类方法来提高嵌入的准确率。

感谢您的阅读!希望这对您有所帮助。

敬请期待,再见~

参考

【2】:桑德勒、马克等《Mobilenetv2:反向残差与线性瓶颈》。IEEE 计算机视觉和模式识别会议录。2018 年

docker+OpenCV:1 分钟实时面部识别

原文:https://towardsdatascience.com/real-time-facial-recognition-in-1-minute-docker-opencv-e89f281c8f01?source=collection_archive---------11-----------------------

集成 Docker、OpenCV.js 和 Nginx,快速部署实时面部识别机器学习模型。对于 Mac Docker 社区来说,这是一个方便的解决方案,他们正在努力获得网络摄像头的访问,因为 Docker hyper kit 支持的缺点在 Nginx 的帮助下。该解决方案可以很容易地扩展到包括 OpenCV、Keras、Tensorflow 等任何现成的机器学习模型..

动机:

  1. 虽然推荐从源代码构建 OpenCV.js,但是需要 LLVM-to-JavaScript 编译器和 CMAKE,这相当复杂。
  2. 由于 Docker 超级工具包支持的缺点,从 Docker 容器访问 Mac 网络摄像头是不可能的。因此,在 Mac 上部署实时面部识别模型是不可能的。

因此,我决定让任何人在 Docker 的帮助下在几秒钟内部署 OpenCV 模型变得尽可能容易。我通过使用夜间构建克服了1 ,通过使用 Nginx 克服了点 2 。这完全是为了让读者熟悉 Docker 的机器学习的部署方面,而不是为了建立面部识别的机器学习模型。

项目结构:Github repo 这里克隆项目

. 
├── Version1            
│ ├── Dockerfile                    #Building the image 
│ ├── docker-compose.yml            #Defining the files for mounting    
│ ├── CV                            #OpenCV.js soure code
|    ├──js_face_recognition.html
|    ├──opencv.js
|    ├──utils.js
  1. Dockerfile

2。docker-compose.yml

请更新此文件中项目文件夹的路径。注意 Nginx 服务器被设置为在端口 80 上运行。

docker-compose.yml

CV 文件夹驻留了该项目的源代码,包括 OpenCV.js 的夜间构建。我使用了 OpenCV.js 官方网站的教程中的面部识别代码,也可以从 OpenCV 的官方 GitHub repo 中获得。他们提供的教程真的很有帮助,也是我学习大多数 OpenCV.js 应用程序的地方。

第一步:

#Clone the repo 
git clone [git@github.com](mailto:git@github.com):gomesc166/MediumRepo.git#Go to ObjectDetection directory 
cd Version1

第二步:

#Build the image
docker build -t object-detection-image .

第三步:

#Start the Container
docker-compose up

注意:编辑主机上项目的路径。

第四步:

在浏览器上访问 localhost:80

单击下载模型按钮。模型下载完成后,您可以添加任意多的人进行识别。如果您想要添加自定义的 Keras/Tensorflow 模型,您必须调整 JS 脚本。

如果您对代码有任何疑问,请留下您的回复,我会尽快回复您。我使用了官方 OpenCV.js 教程中的 JS 脚本。请记住,这篇文章的主要目的是让用户了解如何使用 Docker 轻松部署现成的模型,并克服在 Mac 上使用 Docker hyper kit 的限制。干杯..

通过 AWS 上的用户反馈支持票证分类的端到端数据管道

原文:https://towardsdatascience.com/real-time-it-support-ticket-classification-with-aws-lambda-and-model-retraining-e4cb53814e9?source=collection_archive---------7-----------------------

在 AWS 上建模和部署票据分类器

团队——Abhilasha kanit kar、Jitender Phogat、Pankaj Kishore

在本文中,我们将尝试解决一个真实的业务问题。在 IT 界,大多数生产问题都是以 IT 支持票的形式处理的。我们将首先介绍我们用于解决问题的数据集以及我们使用的模型,然后介绍我们如何在 AWS 上部署模型并能够进行实时预测。让我们开始吧。

一.动机

有几个平台用于处理支持票并跟踪它们,如 BMC Remedy、ServiceNow 等。每当提出一个问题,就会有人把票分配给他所知道的最相关的团队。

大多数时间票证没有直接分配给负责解决该问题的正确团队,而是在团队之间不断滚动,在到达相关团队之前,其 SLA 就过期了。有时,问题很严重,需要立即补救,这时候就会影响工作效率。

因此,我们想到使用机器学习来解决这个问题,并建立一个平台,该平台将自动为团队分配门票,并具有随着时间的推移进行学习和改进的能力。

这是整个工作流程的样子。

二。数据

我们使用了微软的支持票数据集,你可以在这里找到。为了简单和计算限制,我们使用这个数据集的一个子集。想法是有一个完整的框架/工作流程准备就绪,然后我们可以增加系统的复杂性。

三。模型

该项目的下一步是建立一个分类器模型,可以将不同的票证分类。我们之前使用 RNN 和 LSTM 做了这个分类,但这次我们选择保持模型简单,因为我们也想将它与 AWS 集成。这是大多数公司遵循的最佳实践,也是从简单模型开始的良好实践。

我们选择多项式朴素贝叶斯模型进行分类。朴素贝叶斯是一组基于应用贝叶斯定理的算法,假设每个特征相互独立,以预测给定样本的类别。它们是概率分类器,因此将使用贝叶斯定理计算每个类别的概率,并且具有最高概率的类别将被输出。

但是,为什么朴素贝叶斯分类器呢?

我们在处理 NLP 问题时确实有其他的替代方案,比如支持向量机(SVM)和神经网络。然而,朴素贝叶斯分类器的简单设计使得它们对此类分类器非常有吸引力。此外,在自然语言处理的许多应用中,它们被证明是快速、可靠和准确的。

四。数据预处理

对于文本分类,如果你自己通过抓取来收集数据,那么你可能会有一个杂乱的数据集,在应用任何模型之前,你必须付出很多努力来清理它并使它保持良好的形式。在我们的例子中,数据集并没有那么乱,所以我们不需要在这方面投入太多精力。因此,我们执行了以下非常常见但至关重要数据预处理步骤-

  1. 小写并删除停用词 —将整个输入描述转换为小写并删除停用词,因为它们不会给分类添加任何内容
  2. 词汇归类 —这将相同词汇的不同变化组合在一起,如 organize、organizing、organizing 等。
  3. n-grams — 使用 n-grams,我们可以计算单词的序列,而不是计算单个单词

为了执行分类,我们必须使用单词包技术以向量的形式表示输入描述。有两种方法可以做到这一点。

  1. 计算每个单词在文档中出现的次数
  2. 计算每个单词在文档中所有单词中出现的频率

矢量化(计数矢量化器)

它对词的频率起作用,即计数记号的出现并建立一个文档记号的稀疏矩阵

TF-IDF 变压器

TF-IDF 代表术语频率和逆文档频率。TF-IDF 权重是一种统计度量,用于评估一个单词对集合或语料库中的文档有多重要。重要性与单词在文档中出现的次数成比例增加,但是被单词在语料库中的频率抵消。

词频是一个词在特定文档中的出现频率。

逆文档频率为我们提供了一个术语稀有程度的度量。术语越稀有,IDF 分数越高。

动词 (verb 的缩写)模型拟合

现在我们已经准备好了数据,并将多项式朴素贝叶斯拟合到数据中来训练模型。我们创建了一个包含所有预处理步骤的 sklearn 管道,因为我们希望以向量的形式表示新的传入票证描述,这是在模型经过训练后获得的,而不是基于新的描述创建新的票证描述。

来自 sklearn.pipeline 导入管道

text_clf = Pipeline([('vect ',CountVectorizer(ngram_range=(1,2),stop _ words = stop words . words(' English ')),(' tfidf ',TfidfTransformer()),(' clf ',MultinomialNB()),])

https://github . com/jitender 18/IT _ Support _ Ticket _ Classification _ with _ AWS _ Integration

创建模型后,我们在测试数据集上测试了模型性能,我们获得了相当好的 92.167%的准确率。然后,我们将模型导出到 pickle 文件中。

不及物动词与 AWS 集成

现在是项目最重要的部分,在 AWS 上部署模型并配置 AWS Lambda 函数进行实时预测。这是我们花了很多时间的地方。

首先,什么是 AWS Lambda,我们为什么要使用它?

AWS Lambda 是亚马逊提供的无服务器计算平台。它让我们可以运行代码,而不必担心服务器和资源的供应和管理。当你想运行 lambda 函数时,你必须定义事件触发器,只需上传你的代码,Lambda 就会处理好运行和缩放你的代码所需的一切。lambda 的一个优势是,你只需为代码的计算时间付费,也就是说,只有在代码运行时,你才需要付费,而在代码不运行时,你不需要支付任何费用。

让我们开始这个过程。

设置一个新的 EC2 实例

首先设置一个新的 EC2 实例,在这里你将安装所有你的代码(模型)在 Lambda 上运行时将会用到的库。设置新 EC2 实例的原因是,您将从头开始配置 python 环境并安装所有需要的库。

一旦你完成,你将压缩整个 python 环境以及你将在 Lambda 上运行的代码,并将其下载到你的本地机器,然后我们将把它上传到亚马逊 S3 桶。Lambda 函数将使用这个 zip 文件来执行。

每当发生调用 Lambda 函数的事件时,它将使用您指定的 zip 文件来执行。比方说,在事件上,我指定我将运行已经在 zip 文件中的 sample.py,然后 Lambda 函数将在该 zip 文件中寻找它需要的一切(python 环境和运行代码所需的库),如果缺少什么,那么代码的执行将会失败。

https://github . com/abhilasha 23/awsdata piline/blob/master/forlambdamlmodel . py

创建一个 Lambda 函数

一旦你准备好了 S3 水桶的压缩文件。然后你可以创建一个新的 Lambda 函数。

点击创建函数并提供一个有意义的名称,在运行时选择 Python 3.6,并可以选择最适合您需求的权限。

转到你的 lambda 函数,在函数代码部分,你必须上传一个 zip 文件,或者你可以指定在 S3 桶上存储的 zip 地址,如截图所示。

仅供参考—在屏幕截图中,函数是代码文件名(Function.py ),处理程序是将运行的文件中定义的方法名。

Specify the path of S3 link for the zip file

测试你的代码

您可以测试您的代码是否正确运行。单击右上角的测试选项卡,并配置一个测试事件。你可以传递你的代码需要的输入,然后你可以看到你的代码是否正在运行。

如屏幕截图所示,我们传递描述并运行代码。如果您使用我们的代码来尝试,那么您必须取消注释第 29 行,它将读取测试描述,并注释第 30 行,它从 AWS 队列读取输入,我现在将对此进行解释。

AWS SQS(简单队列服务)

通过从设计器选择框中选择 SQS 来创建 SQS 服务。这很简单。在这个 SQS 中,我们配置了两个队列。一个是将输入传递给 lambda 函数,我们在这个队列上有一个事件触发器,这意味着每当这个队列中有新消息时,它就会触发 Lambda 运行。

第二个是输出队列,它将显示输入消息的预测值。

Input and output queue

选择输入队列,并从队列操作中选择“发送消息”。单击提交按钮后,将触发 Lambda 函数,您的代码将运行并进行预测,然后将其写入输出队列。

正如您在屏幕截图中看到的,输出队列中可用的消息是 7,输入是 0,这意味着输入队列中没有新消息,您的 lambda 函数没有运行您的代码。

七。重新训练模型的用户反馈

我们创建了一个简单的 angular JS UI 来获取用户反馈。用户反馈的想法是,无论分类票正确与否,都要得到用户的认可。如果分类票是错误的类别,那么用户可以选择从下拉列表中选择正确的类别,并点击保存,这将把文件保存到 S3 桶。我们将使用这个文件定期重新训练我们的模型。

为此,我们设置了另一个 Lambda 函数,您可以根据需要安排它每天或每周运行。它将使用模型 pickle 文件来读取模型,重新训练模型并修改 pickle 文件。

结论

AWS Lambda 是可伸缩模型的一个非常好的选择,因为您不必担心服务器的供应和管理。它很容易部署模型,并根据您的需求自动扩展所需的资源,您只需在代码运行时付费,因此非常划算。

GitHub 链接:

https://github . com/jitender 18/IT _ Support _ Ticket _ Classification _ with _ AWS _ Integration

基于张量流的实时移动视频对象检测

原文:https://towardsdatascience.com/real-time-mobile-video-object-detection-using-tensorflow-a75fa0c5859d?source=collection_archive---------6-----------------------

全栈数据科学

向您的下一个移动应用程序添加对象检测的分步指南

Photo by GeoHey

随着人们对自动驾驶汽车、人脸识别、智能交通系统等计算机视觉用例的兴趣日益增加。人们正在寻求建立定制的机器学习模型来检测和识别特定的对象。

然而,从零开始构建定制模型需要大量的专业知识、时间和计算资源——从数据标注到模型服务。为了减少障碍,谷歌发布了开源工具,如tensor flow Object Detection APITensorflow Hub ,使人们能够利用那些已经广泛使用的预训练模型,如更快的 R-CNN、R-FCN 和 SSD,使用迁移学习快速构建定制模型。

本文将展示我们如何使用 TensorFlow 的对象检测 API 来训练实时视频对象检测器,并通过以下步骤将其快速嵌入到我们自己的移动应用程序中:

  1. 设置开发环境
  2. 准备图像和元数据
  3. 模型配置和培训
  4. 将定型模型转换为 TensorFlow Lite
  5. 在移动应用程序中测试模型

设置环境

本文中的所有代码都基于 macOS & Linux 系统。对于 Windows 用户,你可以在 docker 容器中工作:

或者安装 Windows 子系统用于 Linux (由于主机硬件隔离,这个不支持 TensorFlow GPU)。

对于 VS 代码用户来说,remote WSLContainers 的扩展也给出了更好的开发体验,应该完全兼容本文中的脚本。

设置项目目录

为了便于阅读,我们将在主项目目录中创建三个子文件夹:

数据— 存储模型数据的文件夹(如。记录,。csv 等。)

模型— 存储所有预训练模型及其配置文件的文件夹。

tf-models — 一个文件夹,其中包含来自 Tensorflow 的克隆模型代码,我们将在建模中使用这些代码。

使用下面的脚本复制上面的项目文件夹结构。

安装 Tensorflow 对象检测 API 和依赖项

一旦我们有了项目设置,Tensorflow 对象检测 API 现在应该位于rf-models/research/object_detection中,代码库目前由社区维护,稍后我们将从那里调用模块进行模型训练。

(可选)对于 Tensorflow 对象检测 API 代码基础之上的任何进一步工作,请查看model_main.pymodel_lib.py作为起点。

现在我们需要安装其余的依赖项。要安装所需的 python 库:

安装 COCO API

注意:如果您在编译 COCO API 时遇到问题,请确保在编译之前已经安装了 Cython 和 Numpy。

安装 Protobufs — Tensorflow 对象检测 API 使用 Protobufs 来配置模型和训练参数。

向 PYTHONPATH 添加 Tensorflow 库

在本地运行时,rf-models/research/rf-models/research/slim目录需要追加到 PYTHONPATH 中,以便将来自 TensorFlow 对象检测 API 的 python 模块添加到搜索路径中,它们将在稍后阶段从模型脚本中被调用。

注意:上述脚本需要在每个新的终端环境中运行。或者,您可以添加您的~/。以绝对路径作为永久解决方案的 bashrc 文件。

测试安装

要测试一切是否按预期运行:

您应该会看到如下测试输出:

准备图像和元数据

下载图像数据

我们使用的图像数据来自香港中文大学多媒体实验室创建的 DeepFashion 数据库。这是一个大规模的服装数据库,拥有超过 800,000 张不同的时尚图片,从造型优美的商店图片到无拘无束的消费者照片。

数据库中的所有图像都被标注了丰富的信息,包括 50 个不同的类别,1000 个描述性属性,边界框和服装标志。

特别地,我们使用“类别和属性预测基准”类别作为时尚对象检测任务的训练数据。

Photo by DeepFashion

在这里下载数据( Google Drive )并将它们解压到我们项目目录下的data文件夹中。完成后将有三个子文件夹:

彦俊 —标注包括包围盒标签、时尚地标标签、服装类别标签、服装属性标签。

Eval—分别用于训练、验证和测试集的图像名称。

img—289222 张多样的服装图片。(为了加快开发速度,我们在本文中使用低分辨率图像)

我们先来看看数据

我从数据集中随机挑选了一些图像,并用它们的边框打印出来。

注意:由于 DeepFashion 数据库已经提供了边界框标签,我们不需要标记数据,而如果你想为其他图像创建自己的标签,或者改进当前的标签(正如我们在上面的图像中看到的,一些边界框的质量并不完美。 LabelImg 将是那些工作的工具之一。

我们还将使用图像元数据的聚合视图为训练集和测试集创建汇总表。汇总表将在稍后阶段用于为模型训练生成建模数据。

summary table — training set

可视化上述图像并生成汇总表的 python 脚本可以在这里找到 Jupyter 笔记本。因此,我们现在在data文件夹中有了汇总表(train_labels.csv & test_labels.csv)。

注意:为了简化工作,您将在笔记本中看到我们只选择了前 6 个常用类别。

生成 TF 记录

为了高效地读取数据,TensorFlow 使用 TFRecord 格式,这是一种存储二进制记录序列的简单格式。它对数据进行序列化,使它们能够被线性读取,如果数据是通过网络传输的,这一点尤其正确。

为了将图像数据转换为 TFRecord 格式,我们将使用以下 python 模板,并将我们创建的汇总表作为参考:

注意:通过为新标签更新 class_text_to_int(),我们可以为其他数据集使用相同的模板。

一旦执行完成,你会在data文件夹下看到两个新文件,分别命名为test.recordtrain.record

生成标签地图

我们现在需要创建一个标签映射,即将每个使用的标签映射到一个整数值。训练和推理过程都将使用标签映射。

上面的脚本给了我们一个名为label_map.pbtxt的新文件。如果我们想引入额外的新标签,我们需要相应地更新它。

现在,我们已经在data文件夹中准备好了所有需要的文件。

模型配置和培训

下载预先训练的模型

正如我们在开始时提到的,我们将使用预训练模型,而不是从头开始设计模型,检测模型动物园收集广泛使用的预训练模型的列表。

例如,我们将使用 SSD mobilenet 量化模型,该模型针对移动设备性能进行了优化,降低了模型推理的复杂性(同时牺牲了一些模型性能)。

模型文件将保存在如下的models文件夹下。

我们需要了解的一些文件是:

  • model.ckpt —您的模型(预训练模型/部分训练模型)的检查点,带有用于进一步训练的估计器。
  • pipeline.config —模型、训练数据、评估数据等的配置。

更新模型管道配置

pipeline.config中有五个主要部分。**模型部分定义了网络的预设计架构。 train_config 部分定义模型训练参数,为我们提供调整参数的灵活性,如批量大小、学习速率、学习步骤等。

model {
(... Add model config here...)
}

train_config : {
(... Add train_config here...)
}

train_input_reader: {
(... Add train_input configuration here...)
}

eval_config: {
}

eval_input_reader: {
(... Add eval_input configuration here...)
}

对于我们的试验,我们将模型配置和超参数保留为默认值,仅更新以下配置:

  • 数量类 : 6
  • 微调检查点:检查点文件的路径model.ckpt
  • label_map_path :上面创建的label_map.pbtxt的路径
  • tf_record_input_reader :上面创建的train.recordtest.record的路径

模特培训

接下来,为了初始化训练,我们现在可以直接使用来自 TensorFlow 对象检测 API 的建模脚本:

训练开始后,我们应该会在下面的控制台中看到训练进度日志。

此外,我们还可以使用 tensorboard 根据可视化的性能指标和验证集对训练步骤的预测来持续监控进度。

1:如果在训练过程中出现内存不足错误,请尝试减少*pipeline.config*文件中训练步骤的批量。

注 2:我们可以随时停止训练,稍后通过更新*pipeline.config*中的*fine_tune_checkpoint*从任何检查点继续。作为一个例子,你可以在这里找到我部分训练的模型检查点

转换为 TensorFlow Lite

一旦我们有了一个经过训练/部分训练的模型,要为移动设备部署该模型,我们需要首先使用 TensorFlow Lite 将该模型转换为一个针对移动和嵌入式设备优化的轻量级版本。它支持设备上的机器学习推理,具有低延迟和更小的二进制大小。它使用像量化核这样的技术来实现更小更快的(定点数学)模型。

目前仅支持 SSD 型号。目前不支持 faster_rcnn 这样的模型。

安装 Bazel 并生成冻结图

我们需要首先安装 Bazel 构建工具(对于不同的操作系统,请参考安装指南)。

Bazel 安装完成后,我们将选择最新的检查点,以获得 TensorFlow 冻结图,该图具有兼容的操作,可以与 TensorFlow Lite 一起使用。要获得冻结图,我们可以直接从tf-models/research使用模板脚本export_tflite_ssd_graph.py

注意:这是为了简单起见,我们应该总是检查模型评估来决定最佳的检查点/步骤。

这将给我们指定输出目录(/tmp/tflite)中的两个文件(tflite_graph.pb & tflite_graph.pbtxt)。

之后,我们将使用 TensorFlow Lite 优化转换器从 TensorFlow 冻结图源文件(tflite_graph.pb)中获取优化的模型。我们将通过运行下面来自tensorflow目录的脚本,为更好的移动性能生成一个量化模型。

如果脚本运行成功,您现在应该会在/tmp/tflite目录下看到一个新文件— detect.tflite。该文件包含图表和所有模型参数,可通过 Andriod & iOS 设备上的 TensorFlow Lite 解释器运行。

在移动设备上运行 TensorFlow Lite 模型

现在,我们剩下的最后一步是将我们的模型嵌入到我们的移动应用程序中,这应该很简单,因为 TensorFlow 已经提供了示例应用程序,使人们更容易测试模型。

要下载示例应用程序代码并以 ios 为例:

注意:构建 iOS 应用程序超出了本文的范围,本质上,上面的脚本是安装 Podfile 中列出的 iOS 应用程序的所有依赖项。一旦脚本完成,就会在ios目录下创建一个*.xcworkspace文件。

实际模型文件保存在ios/ObjectDetection/Model下,其中包含模型文件(detect.tflite)和一个标签映射文件。我们需要从我们的模型中覆盖模型文件和标签映射。

接下来,要构建应用程序:

  1. 在 Xcode 中打开ObjectDetection.xcworkspace
  2. 首次编译应用程序时,请更新捆绑包标识符,并在“常规->签名”中选择您的开发团队。
  3. 将您的移动设备连接到笔记本电脑
  4. 在 Xcode 中构建并运行应用程序。

一旦项目建立,应用程序现在应该在您的移动设备上运行,并测试我们的模型执行得有多好!

下一步是什么

到目前为止,我们已经完成了使用实时视频对象检测的自定义模型创建 iOS 应用程序的过程,这也是一个很好的起点,可以通过利用一些现有的预训练模型来快速原型化这些想法。

可以通过以下方式进一步实施应用程序:

  • 手动标记原始图像数据以获得训练集的更好质量(例如,标记如下 )

  • 模型选择和超参数调整以获得更好的模型性能。
  • 将应用容器化,并利用云服务(例如 TPU)进一步扩展建模。

GitHub 资源库为教程。

参考

[## TensorFlow Lite 示例| TensorFlow

面向移动和嵌入式设备的 TensorFlow Lite

www.tensorflow.org](https://www.tensorflow.org/lite/examples) [## 培训自定义对象检测器- TensorFlow 对象检测 API 教程文档

所以,到目前为止你应该已经做了以下事情:现在我们已经做了以上所有的事情,我们可以开始做一些酷…

tensor flow-object-detection-API-tutorial . readthedocs . io](https://tensorflow-object-detection-api-tutorial.readthedocs.io/en/latest/training.html#training-the-model)

使用深度学习的人脸属性检测

原文:https://towardsdatascience.com/real-time-multi-facial-attribute-detection-using-transfer-learning-and-haar-cascades-with-fastai-47ff59e36df0?source=collection_archive---------11-----------------------

一个快速的 4 部分演练,通过使用深度学习进行实时多面部属性检测(ResNet50 与 FastAI & Pytorch),使用 Haar 级联进行面部检测和定位(OpenCV)。

The final output of the multi facial attribute detection project.

在这篇文章中,我们试图达到上述结果。这篇文章用一个端到端的过程来指导我如何构建它。复制项目的全部代码都在我的 GitHub 库中。

1 部分—数据采集和理解

对于任何深度学习模型来说,要给出合理的准确率,我们都需要依赖大量的标注数据。我发现大多数关于面部特征检测的报告都只集中在多类分类上,如情感检测、微笑检测等。我在寻找一个带有多个标签的面部图像数据集,这样我就可以实现一个谷歌视觉 API 实现的东西,如下所示—

Example of a facial detection output from Google vision API

为此,我在 Kaggle 数据集网站上找到了一个名为CelebA 属性(CelebA)数据集的数据集,其中包含-

  • 202,599 个各种名人的面部图像
  • 10,177 个独特的身份,但没有给出名人的名字
  • 每个图像 40 个二元属性注释
  • 5 个地标位置

对于处理计算机视觉中的各种令人兴奋的问题来说,这是一个相当不错的数据集,因为我只对面部图像和这些图像的 40 个二进制属性注释感兴趣。这里列出了 40 个二元属性(是/否)——5 点钟形阴影、拱形眉毛、迷人、眼袋、秃头、刘海、大嘴唇、大鼻子、黑发、金发、模糊、棕色头发、浓密的眉毛、胖乎乎的、双下巴、眼镜、山羊胡、灰色头发、浓妆、高颧骨、男性、嘴巴微张、小胡子、窄眼睛、无胡须、椭圆形脸、苍白的皮肤、尖鼻子、后移的发际线这里有一个例子-

Example from CelbeA dataset

上面的图片标注了这些特征——拱形眉毛,迷人,大嘴唇,浓妆,窄眼睛,没有胡子,尖鼻子,涂着口红,年轻。因为雄旗是假的,我们可以说标签是雌的。

第 2 部分—数据预处理

数据预处理的全部代码都在这个笔记本里。

2.1)在图像上-

当我为 CelebA 数据集进行数据处理时,我的主要想法是考虑如何使用建立在真实视频/网络摄像头流/图像上的模型。CelebA 数据紧密地裁剪在脸部周围,但是在视频/网络摄像头/图像中,脸部可以在任何地方,并且必须首先被检测到。有许多预先构建的工具可以在图像中定位人脸,例如人脸识别,它使用深度学习网络来检测人脸。我想保持这一步简单,所以我使用了哈尔级联,这是一种传统的计算机视觉方法来检测物体。Haar cascade 返回检测到人脸的图像上的边界框坐标,下面是使用 Haar cascade 的输出示例

An example of Haar Cascade output.

要了解更多关于哈尔瀑布的信息,请参考这篇博客OpenCV 中有预置的 haar 级联滤镜。我用其中一个进行正面人脸检测。因此,一旦决定了人脸检测的方法,下一步就是在 CelebA 数据集上应用相同的方法来检测人脸,并只裁剪图像的面部区域(增加一些边距),这一步将有助于确保

  • 我们使用 Haar 级联来移除正面人脸未被检测到的任何人脸,例如人侧脸的情况
  • 这将确保我们的训练图像符合模型的实际使用

Example of Haar cascade processing on CelebA dataset

请注意,在上面的例子中,在哈尔级联裁剪后,左边的图片被转换为右边的图片(看起来更放大了)。我们还从 202,599 张图像过滤到 175,640 张图像,因为过滤后的图像不包含正面人脸。过滤后的图像示例如下-

Example of a filtered image.

2.2)在标签文件上-

除了对图像进行预处理,我们还需要创建我们的标签文件,供 FastAI 数据集加载器使用。

Original label file

在原始标签文件中,多属性标签每 40 个属性包含 1 /-1 个值,其中 1 表示该特征是否存在,而-1 表示该特征不存在。我只是写了一个简单的函数来转换这个文件,这样我们只有一个标签列,用空格分隔标签(如下图)

Modified Label file

第 3 部分—模型培训

一旦我们预处理了我们的数据,下一步是建立一个模型,它可以检测给定面部图像的 40+个属性。为此,我们将使用由 Pytorch 1.0 编写的 FastAI v1 库。模特训练笔记本可以在我的 Github 这里找到。我根据对图像编号的建议划分,从 1–182637(用于训练)到 182638(用于验证)对训练和验证集中的数据进行了划分。在 FastAI 库中用几行代码训练世界级的模型是不可思议的容易,所以让我们来看看代码-

锅炉钢板库导入命令—

**import** **pandas** **as** **pd**
**import** **numpy** **as** **np**
**from** **fastai.vision** **import** *
**import** **matplotlib.pyplot** **as** **plt**

数据集加载

path = Path('../data/celeba/faces/')
*## Function to filter validation samples*
**def** validation_func(x):
    **return** 'validation' **in** xtfms = get_transforms(do_flip=**False**, flip_vert=**False**, max_rotate=30, max_lighting=0.3)src = (ImageItemList.from_csv(path, csv_name='labels.csv')
       .split_by_valid_func(validation_func)
       .label_from_df(cols='tags',label_delim=' '))data = (src.transform(tfms, size=128)
       .databunch(bs=256).normalize(imagenet_stats))

1 —定义数据集文件夹的路径。

第 2–4 行 —定义我们将如何找到训练和验证图像。

第 6–7 行 —定义我们想要对数据进行的变换,例如将图像随机旋转最大 30 度,以及最大 0.3 的光照调整。

第 8 行 —将图像定义为标签 CSV 中的项目列表

第 9 行 —使用第 2–4 行的验证函数拆分训练和验证中的数据

第 10 行 —帮助我们从 labels.csv 的 tags 列获取标签,并帮助我们定义它是一个多标签列,其中用空格分隔标签。

第 12 行 —传递第 6–7 行的转换函数,将图像大小调整为 3128128

第 13 行 —定义 256 张图像的批量大小,并使用 ImageNet 平均值对数据进行标准化

请注意,我们使用较小的图像大小进行模型的初始训练,稍后我们将图像大小增加到 3256256。这个技巧通过允许更大的批量帮助我们更快地训练我们的模型,并且更快地试验什么模型配置有效。

模型定义—

在本次建模练习中,我们将使用预先训练好的 ResNet 50 模型进行迁移学习。

arch = models.resnet50
acc_02 = partial(accuracy_thresh, thresh=0.2)
acc_03 = partial(accuracy_thresh, thresh=0.3)
acc_04 = partial(accuracy_thresh, thresh=0.4)
acc_05 = partial(accuracy_thresh, thresh=0.5)
f_score = partial(fbeta, thresh=0.2)
learn = create_cnn(data, arch, metrics=[acc_02, acc_03, acc_04, acc_05, f_score])

Line1 —下载预训练的 Resnet 50 模型

第 2–6 行 —在 FastAI 中,我们可以跟踪尽可能多的验证数据的准确性度量;这些指标仅用于监控,不用于训练模型。我们使用部分函数来定义不同阈值的准确性,并跟踪阈值为 0.2 时的 F 值

第 7 行 —通过使用 ResNet 50 模型的预训练卷积部分并在顶部添加两个新的全连接层,帮助创建 CNN 架构。

FastAI 的好处是,它通过为特定的兴趣练习找到理想的学习速度,节省了大量的训练时间。

learn.lr_find()
learn.recorder.plot()

Learning rate finder from FastAI

1 行——通过在数据样本上尝试多个学习率来找到理想的学习率

第 2 行— 让我们画出不同学习速率下的损失。

我们需要在上面的函数中选择一个斜率最大的学习率。在这种情况下,它是 1e-2。

lr = 1e-2
learn.fit_one_cycle(4, slice(lr))

Training snapshot

现在我们已经训练了最后一个全连接层。让我们解冻所有的层,并训练完整的模型。我们将使用学习率查找器再次确定理想的学习率。

learn.unfreeze()
learn.lr_find()
learn.recorder.plot()

Snapshot of learning rate finder in FastAI

线 1 —解冻所有层

第 2–3 行 —帮助我们找到理想的学习速度。

现在,我们将对模型中的每一层使用不同的学习速率,方法是当我们回到各层时,按指数规律衰减学习速率。

learn.fit_one_cycle(5, slice(1e-5, lr/5))
learn.save('ff_stage-2-rn50')

1 —以可变学习率使用一个周期学习

第 2 行 —用指定的名称保存我们的模型。

Training snapshot

现在,我们可以将输入图像大小增加到 3256256,并在上面训练的模型上使用迁移学习来适应新的输入图像大小。

data = (src.transform(tfms, size=256)
       .databunch(bs=64).normalize(imagenet_stats))acc_05 = partial(accuracy_thresh, thresh=0.5)
f_score = partial(fbeta, thresh=0.5)
learn = create_cnn(data, models.resnet50, pretrained=**False**,metrics=[acc_05, f_score])learn.load("ff_stage-2-rn50")

1–2 行 —创建一个新的数据加载器,将图像大小调整为 3256256,并将批量大小减少到 64。

第 4–6 行 —定义我们需要跟踪的指标,并创建一个与之前模型相似的 ResNet 50 模型。

第 8 行 —将权重从我们之前训练的模型加载到新创建的模型中。

现在,我们可以按照上面提到的类似步骤对模型进行更多的训练。培训笔记本还提供了可视化中间层激活的代码,以帮助理解图像的哪一部分驱动模型的最终结果。

Models Intermediate Activation layers heatmap over the actual image.

正如我们可以从上面的图像中看到的,该模型在图像中人脸所在的位置最活跃,这正是我们想要的,因为它是一个面部特征检测模型。

第 4 部分—组合一切

现在我们已经训练好了我们的模型,让我们写一个可以进行面部属性检测的脚本,最后一部分是把它们放在一起。这部分的代码在我的 Github 这里

Detection script process flow

该脚本执行以下任务-

  1. 使用 OpenCV 访问网络摄像头拍摄输入视频并转换成一系列图像帧。
  2. 对于每一帧,我们从 OpenCV 运行 Haar 级联模型来定位面部并将其从帧中裁剪出来。
  3. 将这些裁剪出来的检测到的人脸帧传递到我们训练过的模型中,以找到相关的面部特征
  4. 运行脚本时,显示边界框以及在帧上检测到的所有特征
  5. 可选地保存视频流

结论

在上面的博客中,我们看到了如何通过将从传统机器视觉到深度学习的各种技术结合在一起,来完成端到端的面部属性检测问题。

我希望你喜欢阅读,并随时使用我在 Github 上的代码来为你的目的进行试验。此外,如果对代码或博客有任何反馈,请随时联系 aayushmnit@gmail.com 的 LinkedIn 或给我发电子邮件。您也可以在 Medium 和 Github 上关注我,了解我将来可能会写的博客文章和探索项目代码。

无需机器学习的实时目标检测

原文:https://towardsdatascience.com/real-time-object-detection-without-machine-learning-5139b399ee7d?source=collection_archive---------7-----------------------

深度学习与启发式

今年早些时候,IBM 的软件开发人员 Nick Bourdakos 发布了一系列视频,演示在网络浏览器中进行实时物体检测。他早期的一个视频迅速走红,在 LinkedIn 上获得了超过 16000 个赞和 900 多条评论。以下是原帖:

[## LinkedIn 上的 Nicholas Bourdakos:“在您的浏览器中实时可定制的对象检测…

2019 年 1 月 30 日:尼古拉斯·布尔达科斯在 LinkedIn 上发帖

www.linkedin.com](https://www.linkedin.com/posts/nicholasbourdakos_machinelearning-javascript-activity-6496499508409561088-1M00)

视频显示,三个瓶子(可口可乐、百事可乐和激浪)被举到摄像机前,计算机实时识别。当检测到每个瓶子时,会给它一个文本标签,并在其周围绘制一个边界框。如果举起一个以上的瓶子,系统将正确标记不同的瓶子。

Nick 的系统现在已经进化成了 IBM cloud annotations ,但是上面的演示使用了 TensorFlow.js 以及 COCO-SSD 深度学习模型。SSD,或单次多盒探测器,是一种广泛使用的技术,用于检测一帧中的多个子图像,详细描述这里。这是深度学习擅长的任务,这些技术现在非常普遍,你可能在口袋里有一个深度学习网络,为照片或社交网络应用程序运行手机的对象检测。

“没有机器学习”的挑战

受到尼克帖子的启发,我决定挑战自己,探索是否可以在不使用机器学习的情况下取得类似的结果。我突然想到,最初演示中使用的瓶子可以根据它们的颜色或其他特征以及一些简单的匹配规则来检测。这被称为解决问题的启发式方法。

这样做的潜在优势包括:

  • 易于开发和概念化
  • 降低 CPU 和内存使用
  • 更少的依赖性

在 CPU 和内存方面,在我的 i5 MacBook Pro 上,IBM Cloud Annotations 演示使用了超过 100%的 CPU 和超过 1.5 GB 的 RAM。它还依赖于一个网络浏览器和一些严重的依赖,包括 Tensorflow,React.js,node.js 和 COCO-SSD 本身。

我自己定的规则是:

  1. 可口可乐、百事可乐和激浪瓶必须贴上正确的标签
  2. 当瓶子移动时,应该在每个瓶子周围画一个矩形
  3. 最小代码
  4. 没有机器学习技术!

最初的演示声称只使用了 10 行代码,然而包括样板文件,当前的演示是 107 行 JavaScript。我认为低于 100 行是这个任务的一个很好的目标。

方法和解决方案

首先,我决定将我的项目建立在 OpenCV 的基础上,因为我以前在工作项目中使用过它,它有相对简单的设置,并且是专门为计算机视觉设计的。OpenCV 是用 C++写的,有 Python 和 JavaScript 的绑定。为了方便起见,我决定使用 Python 版本。

我开始只是认出一个可乐瓶子。为此,一个简单的解决方案是分析视频帧中的颜色,并在发现可乐红的地方贴上标签。这里的一个问题是,根据照明条件和相机颜色精度,瓶子标签不太可能准确地为RGB 244 0 0。**

为了解决这个问题,我们可以使用一个 HSV 颜色表示以及 cv::inRange 来查找图像中给定范围内的颜色。想想“红色的深浅”。这给了我们一个图像遮罩,所有红色区域为白色,其他区域为黑色。然后,我们可以使用 cv::findContours 来提供一个定义框架内每个“红色区域”的点列表。基本代码如下所示:

*mask = cv2.inRange(hsv, colour.lower, colour.upper)
conts, heirarchy = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
biggest = sorted(conts, key=cv2.contourArea, reverse=True)[0]*

第三行代码对检测到的“红色”轮廓进行排序,并返回最大的轮廓。搞定了。…对吗?不幸的是没有。像这样,程序经常在图像中找到可乐,即使图像中没有可乐。

Coke false positive

为了解决这个问题,我们需要一个额外的启发。我发现简单地排除任何小于 50×50 的轮廓就足够了。

*if w < 50 or h < 50:
    continue*

最后,为了让我们的检测系统工作良好,我们需要排除在其他颜色“内部”的颜色。例如,百事可乐和激浪标签都含有红色,除非我们排除它,否则它会被检测为可口可乐。因此,我们为可乐添加了一个特殊的试探法,如果它在另一个瓶子的垂直边界内,则忽略检测。

*if name == "Coke":
    if any([contains_vertical(rects[n], rect) for n in rects]):
        continue*

示范

综上所述,这是最终系统的工作演示。

在我的 i5 MacBook Pro 上,它在 45%左右的 CPU 和略高于 50MB 的 RAM 下运行顺畅。完整的源代码有 85 行,可以在这里找到。

限制

这种基于颜色的方法的一个限制是,它不在瓶子周围放置边界框,而只在着色区域放置。我们可以定义额外的规则来考虑检测区域上方或下方的颜色,或者尝试猜测边界框应该在哪里,但是代码会很快变得复杂。

另一个限制是,虽然我们的系统可以同时识别可乐和百事可乐瓶,但它不能检测两个可乐瓶。我们可以添加进一步的启发式方法来处理这个问题,但是如果需要添加这么多的复杂性,我会质疑启发式方法是否是正确的选择。

深度学习 vs 启发式

我已经展示了为高度受限的任务构建一个与基于深度学习的系统精度相当的启发式检测器是很简单的。此外,启发式对象检测器在概念上更简单,具有更少的依赖性,占用更少的 CPU,并且使用更少数量级的存储器。

然而,启发式方法不像使用深度学习那样健壮或准确。深度学习系统可以很容易地识别同一物体在不同比例和旋转下的多个实例,这取决于它的训练方式。它还可以做一些事情,比如即使关键特征缺失也能识别部分物体。

结论

对我来说,这不是深度学习的明显胜利,我认为启发式方法仍然有一席之地。可以对检测条件(一致的背景和/或比例、受约束的对象类型、诸如颜色的区别特征)做出的假设越多,试探法就越有吸引力。作为一名开发人员,如果时间和资源紧张,并且输入约束明确,我会考虑基于启发式的解决方案。如果我想要增加健壮性和灵活性,我会选择机器学习。这两种方法肯定都有它们的位置,问题是要为工作选择正确的工具。

使用 TensorFlow、Raspberry Pi 和 Pan-Tilt HAT 进行实时对象跟踪

原文:https://towardsdatascience.com/real-time-object-tracking-with-tensorflow-raspberry-pi-and-pan-tilt-hat-2aeaef47e134?source=collection_archive---------1-----------------------

Pictured: Raspberry Pi 4GB, Pi Camera v2.1, Pimoroni Pan-Tilt HAT, Coral Edge TPU USB Accelerator

便携式计算机视觉和运动跟踪的预算。

1 部分—简介👋

你是刚入门机器/深度学习,TensorFlow,还是 Raspberry Pi?太好了,这篇博文是给你的!我创建了rpi-deep-pantilt作为野外物体检测的交互演示。🦁

更新— 新增人脸检测和跟踪!

我将向您展示如何复制下面的视频,它描绘了一个摄像机平移和倾斜来跟踪我在房间中的移动。

我将介绍以下内容:

  1. 建筑材料和硬件组装说明。
  2. TensorFlow Lite 对象检测模型 (MobileNetV3-SSD) 部署到 Raspberry Pi。
  3. 使用比例-积分-微分控制器(PID)控制器向平移/倾斜伺服电机发送跟踪指令。****
  4. 使用 Coral 的 USB Edge TPU 加速器Edge TPU 编译器加速任何 TensorFlow Lite 模型的推理。

术语和参考📚

树莓派——一款受教育者、硬件爱好者和机器人爱好者欢迎的小型平价电脑。🤖

Raspbian——树莓派基金会的官方操作系统为 Pi。Raspbian 源自 Debian Linux。

TensorFlow —用于数据流编程的开源框架,用于机器学习和深度神经学习。

tensor flow Lite—一个在移动和嵌入式设备上部署 TensorFlow 模型的开源框架。

卷积神经网络——一种非常适合图像分类和对象检测任务的神经网络架构类型。****

【SSD】—一种卷积神经网络 (CNN)架构,专门用于实时物体检测、分类、包围盒定位。

MobileNetV3一款最先进的计算机视觉模型,针对普通手机处理器的性能进行了优化。

MobileNet v3-SSD—基于 MobileNet 架构的单次探测器。本教程将使用通过 TensorFlow 的对象检测模型 zoo 提供的 MobileNetV3-SSD 模型。

Comparison of computer vision neural networks. Image Credit and Paper: Searching for MobileNetV3

边缘 TPU —张量处理单元(TPU)是一个集成电路,用于加速 **TensorFlow 执行的计算。边缘 TPU** 是为“在边缘”的移动和嵌入式设备开发的,占地面积小****

Cloud TPUv1, TPUv2 (left, middle) at Google Cloud Next ’18. Cloud TPUs accelerate TensorFlow model training and inference. Edge TPUs on a United States penny (right). Edge TPUs accelerate inferences in mobile devices. Image credit: Google)

第 2 部分—🛠构建列表

基本

可选

👋找一个动片少的项目 s?

查看便携式计算机视觉:树莓 Pi 上的 tensor flow 2.0以创建手持图像分类器。✨

第 3 部分— Raspberry Pi 设置

有两种方法可以将 Raspbian 安装到您的 Micro SD 卡上:

  1. NOOBS (新的开箱即用软件)是一个 GUI 操作系统安装管理器。如果这是你的第一个 Raspberry Pi 项目,我建议从这里开始。
  2. 将 Raspbian 图像写入 SD 卡

本教程及配套软件使用Raspbian(Buster)编写。如果您使用的是不同版本的 Raspbian 或另一个平台,您可能会经历一些痛苦。

在进行之前,您需要:

  • 将您的 Pi 连接到互联网( doc
  • SSH 到您的树莓 Pi ( doc )

第 4 部分—软件安装

  1. 安装系统依赖项
**$ sudo apt-get update && sudo apt-get install -y python3-dev libjpeg-dev libatlas-base-dev raspi-gpio libhdf5-dev python3-smbus**

2.创建新的项目目录

**$ mkdir rpi-deep-pantilt && cd rpi-deep-pantilt**

3.创建新的虚拟环境

**$ python3 -m venv .venv**

4.激活虚拟环境

**$ source .venv/bin/activate && python3 -m pip install --upgrade pip**

5.从社区构建的轮子安装 TensorFlow 2.0。

**$ pip install [https://github.com/bitsy-ai/tensorflow-arm-bin/releases/download/v2.4.0/tensorflow-2.4.0-cp37-none-linux_armv7l.whl](https://github.com/bitsy-ai/tensorflow-arm-bin/releases/download/v2.4.0/tensorflow-2.4.0-cp37-none-linux_armv7l.whl)**

6.安装rpi-deep-pantiltPython 包

**$ python3 -m pip install rpi-deep-pantilt**

第 5 部分—云台帽硬件组件

如果您购买了预组装的云台套件,您可以跳到下一部分。

否则,在继续之前,遵循装配云台中的步骤。

第 6 部分—连接 Pi 摄像机

  1. 关掉树莓派
  2. 找到 USB 模块和 HDMI 模块之间的摄像头模块。
  3. 向上(轻轻地)拉,打开黑色塑料夹
  4. 插入摄像头模块带状电缆(金属连接器朝向远离 Raspberry Pi 4 上以太网/ USB 端口的)
  5. 锁定黑色塑料夹

Image Credit: Getting Started with the Pi Camera

第 7 部分—启用 Pi 摄像机

  1. 打开树莓派
  2. 运行sudo raspi-config并从 Raspberry Pi 软件配置工具的主菜单中选择Interfacing Options。按回车键。

3.选择Enable Camera菜单选项并按下回车键。

4.在下一个菜单中,使用右箭头键高亮显示ENABLE并按 ENTER 键。

第 8 部分—测试云台

接下来,测试 Pan-Tilt HAT 模块的安装和设置。

  1. 嘘到你的树莓皮
  2. 激活你的虚拟环境:source .venv/bin/activate
  3. 运行以下命令:rpi-deep-pantilt test pantilt
  4. 用 Ctrl+C 退出测试

如果你安装了正确的帽子,你应该看到两个伺服移动在一个平稳的正弦运动,而测试正在运行。

第 9 部分—测试 Pi 摄像机

接下来,通过启动摄像机的预览覆盖来验证 Pi 摄像机是否安装正确。叠加将在 Pi 的主显示器(HDMI)上呈现。

  1. 将您的 Raspberry Pi 插入 HDMI 屏幕
  2. 嘘到你的树莓皮
  3. 激活你的虚拟环境:$ source .venv/bin/activate
  4. 运行以下命令:$ rpi-deep-pantilt test camera
  5. 用 Ctrl+C 退出测试

如果您正确安装了 Pi 摄像机,您应该会看到摄像机中的素材渲染到您的 HDMI 或复合显示器上。

第 10 部分—测试对象检测

接下来,验证您可以在您的 Raspberry Pi 上运行对象检测模型( MobileNetV3-SSD )。

  1. 嘘到你的树莓皮
  2. 激活你的虚拟环境:$ source .venv/bin/activate
  3. 运行以下命令:
**$ rpi-deep-pantilt detect**

您的 Raspberry Pi 应该检测对象,尝试对对象进行分类,并在其周围绘制一个边界框。

**$ rpi-deep-pantilt face-detect**

注意:使用默认的 MobileNetV3-SSD 模型,只能检测和跟踪以下对象。

**$ rpi-deep-pantilt list-labels
[‘person’, ‘bicycle’, ‘car’, ‘motorcycle’, ‘airplane’, ‘bus’, ‘train’, ‘truck’, ‘boat’, ‘traffic light’, ‘fire hydrant’, ‘stop sign’, ‘parking meter’, ‘bench’, ‘bird’, ‘cat’, ‘dog’, ‘horse’, ‘sheep’, ‘cow’, ‘elephant’, ‘bear’, ‘zebra’, ‘giraffe’, ‘backpack’, ‘umbrella’, ‘handbag’, ‘tie’, ‘suitcase’, ‘frisbee’, ‘skis’, ‘snowboard’, ‘sports ball’, ‘kite’, ‘baseball bat’, ‘baseball glove’, ‘skateboard’, ‘surfboard’, ‘tennis racket’, ‘bottle’, ‘wine glass’, ‘cup’, ‘fork’, ‘knife’, ‘spoon’, ‘bowl’, ‘banana’, ‘apple’, ‘sandwich’, ‘orange’, ‘broccoli’, ‘carrot’, ‘hot dog’, ‘pizza’, ‘donut’, ‘cake’, ‘chair’, ‘couch’, ‘potted plant’, ‘bed’, ‘dining table’, ‘toilet’, ‘tv’, ‘laptop’, ‘mouse’, ‘remote’, ‘keyboard’, ‘cell phone’, ‘microwave’, ‘oven’, ‘toaster’, ‘sink’, ‘refrigerator’, ‘book’, ‘clock’, ‘vase’, ‘scissors’, ‘teddy bear’, ‘hair drier’, ‘toothbrush’]**

第 11 部分—以约 8 FPS 的速度跟踪物体

这是我们期待已久的时刻!采用以下步骤,使用云台以大约 8 帧/秒的速度跟踪物体。

  1. 嘘到你的树莓皮
  2. 激活你的虚拟环境:$source .venv/bin/activate
  3. 运行以下命令:$ rpi-deep-pantilt track

默认情况下,这将跟踪标签为person的对象。您可以使用--label参数跟踪不同类型的物体。

例如,要跟踪一只香蕉,您需要运行:

$ rpi-deep-pantilt track --label=banana

在一台 Raspberry Pi 4 (4 GB) 上,我对我的模型进行了大约每秒 8 帧的基准测试。

**INFO:root:FPS: 8.100870481091935
INFO:root:FPS: 8.130448201926173
INFO:root:FPS: 7.6518234817241355
INFO:root:FPS: 7.657477766009717
INFO:root:FPS: 7.861758172395542
INFO:root:FPS: 7.8549541944597
INFO:root:FPS: 7.907857699044301**

第 12 部分—使用边缘 TPU 实时跟踪物体

我们可以用 Coral 的 USB 加速器来加速模型推理速度USB 加速器包含一个 Edge TPU,它是一个专用于 TensorFlow Lite 操作的 ASIC 芯片。欲了解更多信息,请查看开始使用 USB 加速器。

  1. 嘘到你的树莓皮
  2. 安装边缘 TPU 运行时
**$ echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list

$ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

$ sudo apt-get update && sudo apt-get install libedgetpu1-std**

3.插入 Edge TPU(最好是一个 USB 3.0 端口)。如果您的 Edge TPU 已经插入,移除并重新插入,以便 udev 设备管理器可以检测到它。

4.使用--edge-tpu选项尝试检测命令。你应该能够实时检测物体!🎉

**$ rpi-deep-pantilt detect --edge-tpu --loglevel=INFO**

注意: **loglevel=INFO** 将向您显示检测对象和将边界框渲染到 Raspberry Pi 相机覆盖图的 FPS。

您应该看到大约 24 FPS,这是帧从 Pi 相机采样到帧缓冲区的速率。

**INFO:root:FPS: 24.716493958392558
INFO:root:FPS: 24.836166606505206
INFO:root:FPS: 23.031063233367547
INFO:root:FPS: 25.467177106703623
INFO:root:FPS: 27.480438524486594
INFO:root:FPS: 25.41399952505432**

5.使用--edge-tpu选项尝试跟踪命令。

**$ rpi-deep-pantilt track --edge-tpu**

第 13 部分—检测和跟踪人脸(v1.1.x 中的新功能)

我在rpi-deep-pantiltv1.1.x 版本中添加了一个全新的人脸检测模型🎉

该模型来源于 TensorFlow 的研究模型 zoo 中的faces SD _ mobilenet _ v2 _ quantified _ 320 _ open _ image _ v4

新命令是rpi-deep-pantilt face-detect(检测所有人脸)和rpi-deep-pantilt face-track(戴着潘迪特帽子追踪人脸)。这两个命令都支持--edge-tpu选项,如果使用 Edge TPU USB 加速器,这将加速推理。

**rpi-deep-pantilt face-detect --help
Usage: cli.py face-detect [OPTIONS]

Options:
  --loglevel TEXT  Run object detection without pan-tilt controls. Pass
                   --loglevel=DEBUG to inspect FPS.
  --edge-tpu       Accelerate inferences using Coral USB Edge TPU
  --help           Show this message and exit.**
**rpi-deep-pantilt face-track --help
Usage: cli.py face-track [OPTIONS]

Options:
  --loglevel TEXT  Run object detection without pan-tilt controls. Pass
                   --loglevel=DEBUG to inspect FPS.
  --edge-tpu       Accelerate inferences using Coral USB Edge TPU
  --help           Show this message and exit.**

包扎🌻

恭喜你!你现在自豪地拥有了一个 DIY 对象跟踪系统,该系统使用单次检测器(一种卷积神经网络)来分类和定位对象。

PID 控制器

平移/倾斜跟踪系统使用 比例-积分-微分控制器(PID)控制器 来平滑地跟踪边界框的质心。

PID Controller Architecture, Leigh Johnson 2019

张量流模型动物园

本教程中的模型来源于 TensorFlow 检测模型 Zoo 中的SSD _ mobilenet _ v3 _ small _ cocoSSD _ mobilenet _ edge TPU _ coco。🦁🦄🐼********

我的模型可以通过 Github 发布说明@Leigh-Johnson/rpi-deep-pantilt下载。

我添加了自定义的TF lite _ Detection _ PostProcess操作,它在模型输出上实现了非最大抑制(NMS) 的变体。非最大抑制是使用 集合操作过滤许多包围盒提议的技术。

Image Credit: Non-maximum Suppression (NMS)

感谢您的阅读!

寻找更多针对 Raspberry Pi 和其他小型设备的机器学习实践示例?报名我的简讯

我发布了真实世界的 ML 应用程序的例子(带有完整的源代码)和漂亮的小技巧,如自动消除边框注释的痛苦

特别感谢和致谢🤗

撰稿人:熊云阳、、苏约格·古普塔、、加布里埃尔·本德、谭明星、伯金·阿金、、郭乐。

MobileNetV3 SSDLite 供稿人:、、Vivek Rathod、Jonathan Huang。

特别感谢 Adrian Rosebrock 用树莓 Pi 和 OpenCV编写了 云台人脸跟踪,这是整个项目的灵感来源!

特别感谢 Jason Zaman 审阅本文和提前发布候选人。💪

实时推荐系统:滚动特征矩阵

原文:https://towardsdatascience.com/real-time-recommendation-system-rolling-feature-matrix-f5ca701439df?source=collection_archive---------6-----------------------

在许多应用中,速度比质量更有价值。当一篇文章发表后,推荐系统没有时间提出完全相关的建议。流量高峰出现在最初几分钟。这里有一个如何应对这种情况的想法。

如今,很难找到一个新闻网站不会试图通过一些推荐系统来吸引你的注意力。

如果你碰巧在互联网上的任何地方阅读了一篇文章,那么“下一篇”、“最多人阅读”、“趋势”或类似的东西将不可避免地在下面遇到你。有时我们仍然会看到《编辑文摘》——不管上下文如何,推荐的文章都不会改变。更先进的将使用标签,基于内容或另一种手工制作的相似性。但是当一个人读到今天的火灾事故时,并不一定意味着“火灾”或“事故”是他或她的兴趣所在。比如说 11.3%可能是真的,但今天的其他新闻可能比一个月前的另一场火灾事故更有趣,比如说概率为 24.6%,其余的可能兴趣是过去三天的信息背景形成的思想和感觉的复杂组合。

当然,人们可以以某种方式理解和衡量所有可能因素的影响,并为排名函数列出非常精确的系数,但明天世界将会不同。一项实证研究表明,任何形式的协同过滤在推荐方面都更有效。也就是说,我们永远不应该试图把集体意识解释成人类可读的表达。现代推荐系统应该寻找的不是关键词和日期,而是行为模式。被证明有效的简单方法是依靠文章的余弦相似度

为了使用余弦相似度,你必须将文章表示为访问向量。为简单起见,当第 n 个读者访问了给定的文章时,假设第 n 个系数为 1,否则为 0。在浏览多篇文章时,您可以将这些向量堆叠成一个矩阵,其中每行代表一篇文章,每列代表一个读者。如果你在一个网站的访问日志中选择一个窗口,你可以用如下方式表示它。

d — document, p — person (which are more general terms for an article and a reader)

现在,要知道每对文章之间的余弦相似性,可以使用以下方法。

得到的对称矩阵具有 M 乘 M 的形状,其中 M 是项目的数量。每个系数表示第 I 篇和第 j 篇文章之间的相似性度量。不用说,当 i = j 时,系数是 1,因为这是一篇文章与其自身的相似性。

上面的例子是一种批处理。也就是说,当您加载一段适当的原始输入数据、进行计算并存储结果时,可以在以后请求推荐时检索它们。这种方法在推荐系统中广泛使用,因为它使您能够使用更复杂的数据表示和更精确的算法。它在新出版物频率较低、生命周期较长的应用程序中工作得非常好,比如在线商店或娱乐平台。但是对于一个新闻网站来说,间歇性的运行就成了一个大问题。

想象一下,一个病毒式的出版物在几分钟内被成千上万的人访问。如果这种波动恰好出现在每 10 分钟运行一次批处理的推荐系统的工作周期之间,该怎么办呢?为了充分利用高峰期的出席人数,你必须向那些人推荐一些东西,以便让他们留下来。当您试图在计算能力有限的情况下增加批处理的频率时,您可能需要减少批处理的大小,这反过来会降低结果的质量,并且仍然不能完全消除间歇性的负面影响。那么,如何让一个新闻网站的推荐系统持续工作呢?

关键思想是始终将文档/人员矩阵保存在内存中,当它到来时用数据填充它,并按需执行计算。同时,我们仍然希望能够控制矩阵的大小。因此,在任何给定时刻,矩阵必须只包含最重要的数据。就好像每次发送建议请求时都会加载批处理一样。我们想到的是利用一些缓存替换策略。

假设我们有一个由 document_id,person_id 对组成的输入流。当下一对到达时,我们将它的 document_id 放入缓存 1,将 person_id 放入缓存 2。当命中发生时,我们根据策略调整相应的缓存,并在矩阵中分配相应的系数。对于未命中的情况,我们替换高速缓存中最不重要的(例如,最近最不重要的)记录,并用除了该对的交集之外的全零来重新初始化矩阵中的相应行或列。胜过千言万语的 GIF 如下图。

在这个例子中,我使用了自适应替换缓存算法。该算法通过从驱逐历史中学习来考虑被缓存的元素的频率和新近度。最频繁元素与最近元素的比值是自适应的,是算法的核心知识。它有助于只将最重要的元素保留在内存中,也就是说,这些元素在不久的将来可能会再次被访问。我所使用的实现的关键特性是为缓存中的每条记录分配一个惟一的 ID,取值范围为 0 到 N - 1,其中 N 是缓存中记录的最大数量。这些 id 没有告诉我们任何关于记录顺序的信息,只是保证在缓存实例中是唯一的。因此,id 可以用作矩阵中行和列的索引。当一条记录被收回时,ID 被重用,我们知道哪一行或哪一列需要重新初始化。现在我们有了一个“滚动特征矩阵”。这意味着它包含准备用于实时计算推荐的输入数据的滑动批次。当然,这种方法可能有更多的应用。我只是用一个推荐系统给你一个思路。

实现的细微差别

使用 lil_matrix 加快计算速度,同时保持变异(稀疏度变化)的效率,在对某个文档执行推荐计算之前删除不需要的列。也就是说,切掉对应行有零的所有列。

如果您有一个 2k 乘 2k 的矩阵,其中大约有 10k 个非零值(这在许多情况下是足够的数据量),上述代码在任何现代 CPU 上的单个线程中每秒运行数百次,这使得这种方法适合于实时应用程序。

为了证明我的观点,我实现了 Recom.live ,这个推荐系统利用了“滚动特征矩阵”。这是一个生产就绪的实时推荐系统。您可以在 docker 容器中安装并运行它。请查看包含 Dockerfile 文件和说明的库。简而言之,安装非常简单:

这将启动一个 UDP 服务器(默认端口是 5005)。您可以开始将 document_id,person_id 对注入其中,并通过提供相同的上下文(这对 document_id,person_id )从其中检索推荐。API 非常简单,尽管为了让它更简单,我用 python 写了一个小小的客户端库

在该负载下,Recom.live 在英特尔酷睿 i5 CPU 上运行时,每秒钟可处理 700 个记录/推荐请求。使用默认的矩阵形状(2000 X 2000)时,Recom.live 服务器会消耗大约 100 Mb 的 RAM。Docker 镜像是从 debian:stretch-slim 构建的,需要大约 350 Mb 的磁盘空间。总而言之,它绝对不会让您的服务器停机。

所以,欢迎每个人使用,留下反馈,为 Recom.live 的发展做出贡献。祝你有一个美好的一天/周末/生活,永远不要犹豫去联系!

自然语言处理的基础和使用开源工具的实时情感分析

原文:https://towardsdatascience.com/real-time-sentiment-analysis-on-social-media-with-open-source-tools-f864ca239afe?source=collection_archive---------1-----------------------

Trinity College, Dublin | source: link

Image credit: Domo

Instagram 上每天有 5 亿条推文,每月有 8 亿活跃用户,其中 90%的人不到 35 岁。用户每天在 Reddit 上发表 280 万条评论,68%的 T2 人使用脸书。每时每刻都有数量惊人的数据生成,从这些杂乱的数据中获取相关的见解变得极其困难。有没有一种方法可以让你实时掌握这一点?如果您阅读了本文的其余部分,我将向您展示一种方法:)我还在我的社交收听网站上部署了一个简单的真实例子,供您试用…

什么是 NLP,为什么它很重要?

自然语言处理 (NLP) 是计算机科学、人工智能、语言学交叉的领域。目标是让计算机处理或“理解”自然语言,以执行各种类似人类的任务,如语言翻译或回答问题。

随着语音接口和聊天机器人的兴起,自然语言处理是第四次工业革命的最重要技术之一,并成为人工智能的一个热门领域。从 NLP 领域衍生出来的有用的应用程序正在快速增长。它们从简单到复杂。以下是其中的一些:

  • 搜索、拼写检查、关键字搜索、查找同义词、复杂问题回答
  • 从网站提取信息,例如:产品、价格、日期、地点、人物或姓名
  • 机器翻译(即谷歌翻译)、语音识别、个人助理(想想亚马逊 Alexa、苹果 Siri、脸书 M、谷歌助理或微软 Cortana)
  • 用于客户支持、控制设备、订购商品的聊天机器人/对话代理
  • 匹配网络广告, 情感分析 用于营销或金融/贸易
  • 识别财务风险或欺诈

NLP 是如何表示单词/句子的?

NLP 背后的天才是一个叫做 字嵌入 的概念。单词嵌入是将单词表示为向量,通过利用大量文本来学习。每个单词被映射到一个向量,向量值以类似于人工神经网络的方式被学习。

每个单词都由一个实值向量来表示,这个向量通常有几十或几百维。这里的 单词向量是一行实数值 ,其中每个数字是单词含义的维度,其中语义相似的单词具有相似的向量 女王公主会不会是更近的媒介物。

如果我们在一个假设的单词向量中用一些虚构的维度来标记 4 个单词(国王、王后、女人、公主),它可能看起来有点像下面这样:

Source: the morning paper

单词向量中的数字表示单词在各个维度上的分布权重。单词的 语义 都嵌入在这些 维度 的向量中。另一个跨越 4 个维度的简化示例如下:**

Source: medium / Jayesh Bapu Ahire

这些假设的向量值代表了一个词的抽象“意义”。将单词表示为向量的美妙之处在于,它们有助于数学运算符,因此我们可以对它们进行编码!然后它们可以被用作人工神经网络的输入!

我们可以通过将学习到的向量投影到简化的二维空间来可视化它们,如下所示,很明显,向量捕获了关于单词及其相互关系的有用语义信息。

Source: Google TensorFlow blog

这些是d 分布向量,基于出现在相似语境中的单词具有相似含义的假设。比如下图中,所有的大型猫科动物(即猎豹美洲豹黑豹老虎豹子)在向量空间中确实很接近。

Source: medium / Jose Camacho Collados

单词嵌入算法从大型文本语料库中获取输入,并产生这些向量空间,通常具有数百个维度。在大语料库(文本主体)上训练神经语言模型,并且网络的输出用于将每个唯一的单词分配给相应的向量。最流行的单词嵌入算法有谷歌的 Word2Vec ,斯坦福的 GloVe 或者脸书的 FastText 。****

单词嵌入代表了无监督学习最成功的人工智能应用之一。

潜在的缺点

也有缺点,比如不能区分一个词的不同意思。例如,单词“ bat ”至少有两个不同的意思:一个会飞的动物,和一件运动器材。另一个挑战是文本可能同时包含多种情感。例如()

“这部电影背后的意图很棒,但它本可以做得更好”。

上面这句话由正反两个极性组成。那么,我们如何断定该评论是正面的还是负面的呢?

好消息是,人工智能(AI)现在可以(几乎)实时地对复杂的人类语言及其细微差别进行足够好的理解。感谢 预训练 和深度学习驱动的算法,我们开始将 NLP 案例视为我们日常生活的一部分。

NLP 上最新最受欢迎的新闻

预先训练的 NLP 模型可以像人类一样行动,并且可以使用合理的计算资源更快地部署。比赛开始了!

source: the Verge

NLP 上最近的一条热门新闻是关于 OpenAI 发布了一个新的 GPT-2 语言模型的争议,但是他们拒绝开源完整的模型,因为它有潜在的黑暗用途。它通过 800 万个网页进行训练,GPT-2 可以生成长段类似人类的连贯文本,并有可能创建假新闻或欺骗在线身份。基本上是发现太危险不敢张扬。这只是开始。我们将会看到更多关于自然语言领域不受监管的人工智能方法的危险的讨论。

source: Vice — Chris Kindred

最近还有消息称谷歌已经开源了其自然语言处理(NLP)预训练模型,名为来自变形金刚的双向编码器表示(BERT) 。然后百度(有点像“中国的谷歌”)公布了自己预先训练好的 NLP 模型,名为“ERNIE”

最后,包括脸书或谷歌拼图 T21 在内的大型科技公司和出版商正试图找到消除互联网上大量辱骂和骚扰的方法。尽管在人工智能和 NLP 赶上来之前,仍然需要数千名人类主持人来避免丑闻。敬请关注 NLP 的更多进展&新闻!

社交媒体情感分析

source

一个人能读多少书或者能跟多少人走才能找到问题的关键?也许你正在看超级碗,好奇休息时间其他人对最新广告的看法。也许你想发现潜在的社交媒体危机,联系不满意的客户,或者帮助开展营销/政治活动。也许你想避免(网上)危机或确定最有影响力的人…

情感分析(也称为意见挖掘情感 AI** )是 NLP 的一个子领域,它试图在博客、评论、社交媒体、论坛、新闻等给定文本中识别和提取意见。使用 NLP 和开源工具,情感分析可以帮助将所有这些指数级增长的非结构化文本加工成结构化数据。例如,Twitter 是一个情感宝库,用户可以对世界上的每个话题发表自己的反应和意见。**

Source: talkwalker

好消息是,在人工智能驱动的新世界中,在几秒钟内分析这些文本片段是可能的,而且每天都在变得更好。实际上,有很多现成的类似商业工具可用,尽管你可以自己创建一个自己的应用程序,只是为了好玩!

在数据挖掘中,流式推文是一项有趣的练习。爱好者通常使用一个名为 tweepy 的强大 Python 库来实时访问(公共)推文。简单的想法是,我们首先(1)在线生成 Twitter API 凭证,然后(2)使用 tweepy 和我们的凭证,根据我们的过滤器设置来传输推文。然后,我们可以(3)将这些流推文保存在数据库中,以便我们可以执行自己的搜索查询、NLP 操作和在线分析。大概就是这样!

什么是 VADER?

source

好消息是,你不需要成为深度学习或 NLP 专家就可以开始为你的想法编码。其中一个现成的预训练算法叫做VADER(ValenceAwareDictionary 和 sEntimentR它的算法针对 Twitter、在线新闻、电影/产品评论等社交媒体中表达的观点进行了优化。VADER 可以给我们一个积极和消极的分数,可以在-11 的范围内标准化。VADER 能够包含来自表情符号(例如,😃、与情绪相关的首字母缩写词(例如 LoL)和俚语(例如 meh)的情绪,而算法通常会在这些地方挣扎。因此,维德是一个可怕的工具,新鲜的在线文本。

Source: Medium — David Oti

虽然 VADER 在社交媒体类型的文本上有优势,但它也不需要任何训练数据,因为它是基于化合价的、人类策划的标准情感词典。对我来说同样重要的是,它的速度足够快,可以在线使用实时流数据。VADER 的开发者使用了亚马逊的机械土耳其人来获得他们的大部分评分,该模型在一篇名为“ VADER:一个基于规则的社交媒体文本情感分析的简约模型”的学术论文中有完整描述。”。

输入的句子首先通过一个叫做“”的过程被拆分成几个单词。然后,通过在情感词典内进行比较,查看每个单词句子的情感值会容易得多。实际上,这里没有进行机器学习,但是这个库解析每个标记化的单词,与它的词典进行比较,并返回极性得分。这将显示推文的总体情绪得分。VADER 也有一个开源 python 库,可以使用常规的 pip 安装来安装。它不需要任何训练数据,并且可以足够快地处理几乎实时的流数据,因此对于我的手来说,它是一个简单的选择。****

基础数据清理

任何 NLP 代码都需要做一些实时清理,以删除停用词和标点符号,降低大写字母,并根据感兴趣的语言过滤推文。Twitter API (tweepy)有一个自动检测常用语言的功能,我只过滤了英语。还有一些其他流行的 NLP 技术可以进一步应用,包括(将单词转换为词典形式)或 词干 (将单词简化为其词根形式),以进一步改善结果。**

Source: hands on example — Vader sentiment for the “Game of Thrones”

使用实时 Twitter 数据的 MVP 实践示例:

最后,我在我的演示网站上部署了一个示例模型来展示预训练的 NLP 模型的威力,该模型只使用实时 twitter 数据和英语推文。这个最小可行的产品是只用开源工具完成的。灵感和原代码来自于 python 编程中的sendex这个环节。我添加了一些额外的功能,比如类似谷歌的搜索体验,美国各州情感地图,以捕捉带有用户位置元数据的推文,搜索词汇的词云,以及避免崩溃的错误处理。我发现 Twitter 用户不太维护他们的“位置”,因此美国地图包含的 tweets 更少。您可以从我的 GitHub 库下载修改后的代码,并按照这些指令在云上部署。代码是混乱的,因为我在有限的时间内编辑它,并开放任何帮助,使它看起来更好。

A wordcloud at my blog for “cobra kai”

依赖性:开源技术和云

工作的重要部分是安装所有这些组件并协同工作,清理数据并集成开源分析库,而 Vader 模型本身只有几行基本代码。

Example: location based sentiments for the tweets including the word “twitter” at a random time in mid-April

开源技术:我把 Python 3.7 和各种开源库一起用。主要的有(1) Tweepy : Twitter API 库,以 JSON 格式传输公共推文(2) SQlite3 :广泛使用的轻量级关系数据库(3) Panda :非常适合读取和操作数字表和 Twitter 时间序列(4) NLTK :自然语言工具包(5) wordcloud:显而易见哈!(6) Flask :用于 web 部署的微 web 框架。爱死了!(7) Dash :使您能够使用纯 python 构建令人惊叹的仪表盘(8) Plotly :流行的 Python 图形库,用于交互式和在线绘制折线图、散点图、面积图、条形图……首先,您需要注册 Twitter API,安装依赖项,编写代码,并将其部署到您的笔记本电脑或云上。

云部署:我使用 数字海洋 (声明:这是一个推荐链接)作为我的虚拟专用服务器(VPS)提供商。我使用了一个低层次的节俭服务器,因此我的演示的速度/性能不是超级快,但它的工作和 SSL 相对安全。最初我部署了 AWS Beantalks,但我不得不转向,因为可用的 Amazon Linux 发行版与我希望与我的代码集成的最新 SQlite3 数据库版本不兼容。实际上,当您处理开源工具时,这些都是典型的挑战,需要数据科学家以极大的耐心保持灵活性。有趣的是,在这种情况下,数字海洋给了我更多的控制权,而且很容易设置。另一个不错的选择是 Heroku。如果你使用 AWS,我建议使用 mySQL、MongoDB 等数据库服务(相对于 SQLite3)。如果有问题,请告诉我。

结论

维德模型表明,它并不完美,但安静的象征。尽管更先进、更精确的 ML 算法正在向我们走来,但任何算法都会有一些假阴性或假阳性。

Source: Michael could override KITT’s AI when needed 😃

这些预先训练的自然语言处理能力可以很容易地重新应用于电子邮件、脸书、推特、Instagram、YouTube、Reddit、IMDB、电子零售商评论、新闻博客和公共网络。这些见解可以通过位置、人口统计、受欢迎程度、影响来分析…测量网络脉搏或生成类似人类的内容从未如此简单!可怕的是,这些很容易被社交媒体机器人或其他人用于计算宣传…小心!

人工智能/机器学习实现了民主化,并使您能够实时获得针对您所在领域的关键见解。尽管如果你不打算根据洞察力采取行动,跟踪本身可能不值得。

未来的幸存者将需要转变他们的流程和资源,以适应这个数据和算法丰富的新时代。

2019 年快乐学习!还有…

不要忘记活在当下!

John Blanding/The Boston Globe via Getty Image

资源:

Source: Sentiment analysis video

**** [## 使用 Python 中的 VADER 简化情感分析(在社交媒体文本上)

一个易于使用的 Python 库,专为社交媒体文本的情感分析而构建。

medium.com](https://medium.com/analytics-vidhya/simplifying-social-media-sentiment-analysis-using-vader-in-python-f9e6ec6fc52f) [## 改变你未来沟通方式的 7 种 NLP 技术(上)

什么是 NLP?

heartbeat.fritz.ai](https://heartbeat.fritz.ai/the-7-nlp-techniques-that-will-change-how-you-communicate-in-the-future-part-i-f0114b2f0497) [## 深度学习 NLP 的十大趋势

2018 年是基于深度学习的自然语言处理(NLP)研究繁忙的一年。在此之前最高…

blog.floydhub.com](https://blog.floydhub.com/ten-trends-in-deep-learning-nlp/) [## 单词向量简介

词向量

medium.com](https://medium.com/@jayeshbahire/introduction-to-word-vectors-ea1d4e4b84bf) [## 使用 Python 中的 VADER 简化情感分析(在社交媒体文本上)

一个易于使用的 Python 库,专为社交媒体文本的情感分析而构建。

medium.com](https://medium.com/analytics-vidhya/simplifying-social-media-sentiment-analysis-using-vader-in-python-f9e6ec6fc52f) [## VADER 情绪分析解释-数据与媒体相遇

VADER(情感推理的效价感知词典)是一个用于文本情感分析的模型

datameetsmedia.com](http://datameetsmedia.com/vader-sentiment-analysis-explained/)****

实时声音事件分类

原文:https://towardsdatascience.com/real-time-sound-event-classification-83e892cf187e?source=collection_archive---------8-----------------------

我在之前的一篇文章中介绍了一种使用机器学习对声音事件进行分类的方法。在之前的帖子中,声音事件是作为小音频片段单独捕获的。因此,不需要分割过程。这些独立的音频片段被用来训练神经网络并对其进行测试。在这篇文章中,我将介绍一种对声音事件进行分类的方法,这些声音事件在一个音频片段(或一个音频流)中按顺序连接在一起。我们必须对事件进行分类,并给它们一个标签,以及相关音频片段或音频流的时间戳。让我们称之为时间标签。注意,这里将重复使用用于分类孤立声音事件的相同程序。所以我强烈推荐你先看完上一篇

让我们来看看一个样本音频片段的波形,我们将对其进行时间标记。

A sequence of sound events

时间标记的建议方法如下。

1.使用普通噪声样本降低噪声

2.将音频剪辑拆分成包含音频剪辑的单个声音事件

3.修剪单个声音事件音频片段的开头和结尾静音。

4.使用先前训练的神经网络对单个声音事件片段进行分类

5.输出时间标签。

该过程适用于没有两个声音事件同时发生的情况。这是因为我们在这里使用的预测模型只针对孤立的声音事件进行训练。让我们假设噪声在整个声音事件系列中保持不变。让我们来看看用单个声音事件连接片段执行上述步骤。然后,在文章的最后,我将介绍一种使用麦克风的音频流实时分类声音事件的方法。

您可以通过连接一些单个音频片段来准备样本,如下所示。

raw_audio = numpy.concatenate((raw_audio,data))

按如下方式降低均匀分布的噪声。

noisy_part = raw_audio[0:50000]  # Empherically selected noisy_part position for every sample
nr_audio = nr.reduce_noise(audio_clip=raw_audio, noise_clip=noisy_part, verbose=False)

分割音频剪辑

现在,我们已经到了连续声音事件识别的核心思想。对声音事件序列进行分类的挑战在于确定这些声音事件的起点和终点。几乎总是在两个声音事件之间有一个无声部分。请注意,在一些声音事件中,可能会有静默。我们可以用这些无声部分来分割一系列声音事件。看看下面用来完成任务的代码。注意到参数tolerence用于调整分割灵敏度。从而一个声音事件内的小无声部分不会被用来进一步分割相应的声音事件。

# Split a given long audio file on silent parts.
# Accepts audio numpy array audio_data, window length w and hop length h, threshold_level, tolerence
# threshold_level: Silence threshold
# Higher tolence to prevent small silence parts from splitting the audio.
# Returns array containing arrays of [start, end] points of resulting audio clips
def split_audio(audio_data, w, h, threshold_level, tolerence=10):
    split_map = []
    start = 0
    data = np.abs(audio_data)
    threshold = threshold_level*np.mean(data[:25000])
    inside_sound = False
    near = 0
    for i in range(0,len(data)-w, h):
        win_mean = np.mean(data[i:i+w])
        if(win_mean>threshold and not(inside_sound)):
            inside_sound = True
            start = i
        if(win_mean<=threshold and inside_sound and near>tolerence):
            inside_sound = False
            near = 0
            split_map.append([start, i])
        if(inside_sound and win_mean<=threshold):
            near += 1
    return split_map

该算法使用具有跳跃长度h的固定大小的窗口w。窗口在给定音频上滑动,检查窗口的平均振幅。如果振幅低于给定的threshold_level,算法会增加一个名为near的内部参数。当参数near获得大于参数tolerence的值时,确定音频剪辑结束分割点。同样,音频剪辑起始分割点也是使用窗口平均振幅来确定的。注意,内部布尔参数inside_sound被维护以区分开始和结束分割点。

修剪单个声音事件音频片段

现在,我们已经将我们的音频剪辑分成单个声音事件。小音频片段需要修剪它们的前导和拖尾无声部分。让我们使用librosa来完成任务。

sound_clips = split_audio(nr_audio, 10000, 2500, 15, 10)
for intvl in sound_clips:
    clip, index = librosa.effects.trim(nr_audio[intvl[0]:intvl[1]],       top_db=20, frame_length=512, hop_length=64)

注意split_audio仅提供时间标记间隔。我们需要在nr_audio[intvl[0]:intvl[1]]之前获得实际的音频剪辑。

对声音事件进行分类

为了对孤立的声音片段进行分类,我们可以使用来自先前帖子的经过训练的神经网络模型。

#Load segment audio classification model
model_path = r"best_model/"
model_name = "audio_NN3_grouping2019_10_01_11_40_45_acc_91.28"# Model reconstruction from JSON file
with open(model_path + model_name + '.json', 'r') as f:
    model = model_from_json(f.read())# Load weights into the new model
model.load_weights(model_path + model_name + '.h5')

创建该模型是为了使用标签编码器预测标签。我们还需要在这里复制标签编码器。

# Replicate label encoder
lb = LabelEncoder()
lb.fit_transform(['Calling', 'Clapping', 'Falling', 'Sweeping', 'WashingHand', 'WatchingTV','enteringExiting','other'])

为了使用加载的模型对音频剪辑进行分类,我们需要绝对平均 STFT 特征。看看下面完成这项任务的代码。注意,该函数接受标签编码器lb 作为输入,以产生一个有意义的标签作为声音事件。

def predictSound(X, lb):
    stfts = np.abs(librosa.stft(X, n_fft=512, hop_length=256, win_length=512))
    stfts = np.mean(stfts,axis=1)
    stfts = minMaxNormalize(stfts)
    result = model.predict(np.array([stfts]))
    predictions = [np.argmax(y) for y in result]
    return lb.inverse_transform([predictions[0]])[0]

现在,我们可以在上述修剪操作后立即对隔离的剪辑使用predictSound功能。访问 GitHub 获取完整代码和分类示例。

实时声音事件识别

到目前为止,我们一直在研究声音事件的记录序列。如果我们想做同样的事情,但不需要记录,而是实时的。为此,我们可以使用麦克风输入流缓冲到一个临时缓冲区,并在缓冲区上工作。IO 可以用 python 库轻松处理,比如 PyAudio (文档这里)。查看 GitHub 的实现。

希望这篇文章对你有用。

用于品牌提升和话题跟踪的实时 Twitter 情感分析(第 1/3 章)

原文:https://towardsdatascience.com/real-time-twitter-sentiment-analysis-for-brand-improvement-and-topic-tracking-chapter-1-3-e02f7652d8ff?source=collection_archive---------5-----------------------

行业中的数据科学

通过 Tweepy、MySQL 和 Python 使用流 Twitter API 收集 Twitter 数据

Photo by Riccardo Chiarini on Unsplash

这是一个全面的分步教程,教你如何建立一个端到端的实时 Twitter 监控系统,通过识别情绪波动,分析趋势话题和地理细分,检测丑闻的异常,跟踪客户对品牌的行为,并考虑提高品牌的客户参与度和保留率。

https://twitter-analysis-web-app.herokuapp.com

你可以试试这个很棒的网络应用并找到的完整代码

技术栈: Python,Tweepy,Numpy,Pandas,Seaborn,Plotly,Dash,Scala Kafka,Spark,MySQL,RE,TextBlob,NLTK,HTML,CSS,Flask,JavaScript,React.js 和 Git

由于这是一个全面的端到端 Twitter 监控系统,我将把它分成 3 章来解释引擎盖下的细节和行动背后的直觉。

  • 1 章(你来了!):通过 Tweepy、MySQL、& Python 使用流 Twitter API 收集 Twitter 数据
  • 第二章 : 使用 RE、TextBlob、NLTK 和 Plotly 的 Twitter 情感分析和交互式数据可视化
  • 第三章 : 使用 Python 中的 Dash & Plotly 在 Heroku 上部署一个实时的 Twitter 分析 Web App
  • 第 4 章(可选) : 使用 Scala、Kafka 和 Spark 流媒体实现流媒体 Twitter 情感分析的并行化

这个系统是什么?这个实时的端到端 Twitter 监控系统是为企业设计的,用于评估 Twitter 数据,为商业决策提供信息。正如我们所知,twitter 是一个实时高通量数据源的好地方,平均每秒 6000 条推文,我们可以用它来发现突发新闻故事,识别行业趋势,并及时采取行动。在实践中,实时跟踪关于某个品牌的所有相关 Twitter 内容,随着话题或问题的出现进行分析,并通过警报检测异常情况。通过监控 Twitter 上的品牌提及,品牌可以通知执行机构,并为全球客户提供更好的体验。

访问 Twitter API——成为一名出色的 Twitter 开发者

Apply for a developer account

为了开始使用 Twitter APIs,我们需要先申请一个开发者账户。它允许你访问 Twitter APIs 和其他工具。

Create an app

然后我们创建一个应用来生成两个 API 密匙和两个访问令牌。这是调用 Twitter APIs 最重要的部分。整个过程可能需要几分钟,但应该很容易完成。

Consumer API keys and Access token & access token secret

现在,在右上角您的 Twitter 名称下的应用程序中,点击您的应用程序右侧的详细信息按钮(这不是仪表板按钮)。然后点击副标题中的键和令牌。创建一个名为 credentials.py 的文件,并将&粘贴到该文件中。

#credentials.py
API_KEY = 'XXXXXXXXXX'
API_SECRET_KEY = 'XXXXXXXXXXXXXXXXXXXX'ACCESS_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXX'
ACCESS_TOKEN_SECRET = 'XXXXXXXXXXXXXXXXXXX'

Photo by Sebastian B on Unsplash

使用 Tweepy、MySQL 和 Python 流式传输 Twitter 数据

我们将使用一个名为 Tweepy 的 python 库来监听流 Twitter 数据。创建一个名为 Main.ipynb 的新文件,让我们开始吧。注:我用 Jupyter 笔记本是为了更好的开发探索,你也可以用。改为 py。如果你感兴趣,你可以通过 Tweepy 的 Tweepy 在线文档来查看这个流。你可以在这里查看我的全代码版本

首先,我们需要创建一个 Tweepy 的 StreamListener ,它具有用于接收 tweets 的 on_status 方法和用于由于速率限制而停止抓取数据的 on_error 方法。推文被称为“状态更新”。因此
Tweepy 中的状态类具有描述 tweet 的属性。

# Part of **MyStreamListener** in *Main.ipynb*
*# Streaming With Tweepy* 
*# Override tweepy.StreamListener to add logic to on_status*
**class** **MyStreamListener**(tweepy.StreamListener):

    **def** on_status(self, status):
 *# Extract info from tweets*
        id_str = status.id_str
        created_at = status.created_at
        user_created_at = status.user.created_at
        # ...... and more! 
        # I'll talk about it below! (Or check full-code link above) **def** on_error(self, status_code):
        *'''*
 *Since Twitter API has rate limits, 
        stop srcraping data as it exceed to the thresold.*
 *'''*
        **if** status_code == 420:
            *# return False to disconnect the stream*
            **return** **False**

然后,使用 Tweepy 中的 Oauth 进行认证,向 Twitter 注册我们的应用程序。

# **Oauth** part in *Main.ipynb* # *Import api/access_token keys from* credentials.pyimport credentials.py
auth  = tweepy.OAuthHandler(credentials.API_KEY, \
                            credentials.API_SECRET_KEY)
auth.set_access_token(credentials.ACCESS_TOEKN,  \
                      credentials.ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)

现在,用 Oauth 启动流线型监听器。在过滤器方法中,设置推文语言偏好和跟踪单词,后者是一个单词列表(例如[‘脸书’])。目前,我们使用 Twitter 的免费标准流。查看 Twitter 流 API 文档以了解不同的流具有不同的功能和限制。

myStreamListener = MyStreamListener()
myStream = tweepy.Stream(auth = api.auth, listener = myStreamListener)
myStream.filter(languages=["en"], track = settings.TRACK_WORDS)*# However, this part won't be reached as the stream listener won't stop automatically. Press STOP button to finish the process.*

然后,创建并连接 MySQL 本地数据库,以便进一步分析和存储。你可以在这里下载最新版本的。我们用的版本是 MySQL 社区版,非常流行的开源数据库。根据内置指南设置 MySQL 数据库,数据库信息如下。

mydb = mysql.connector.connect(
    host="localhost",
    user="root",
    passwd="password",
    database="TwitterDB",
    charset = 'utf8'
)

如果表不存在,我们需要创建一个新表。当然第一次的时候应该是不存在的。所以我们用下面的自动检查代码创建它。

**if** mydb.is_connected():
    mycursor = mydb.cursor()
    mycursor.execute("""
        SELECT COUNT(*)
        FROM information_schema.tables
        WHERE table_name = '**{0}**'
        """.format(TABLE_NAME))
    **if** mycursor.fetchone()[0] != 1:
        mycursor.execute("CREATE TABLE **{}** (**{}**)" \
            .format(TABLE_NAME, TABLE_ATTRIBUTES))
        mydb.commit()
    mycursor.close()

on_status 方法中指定接收和预处理 Twitter 数据的细节。状态中的属性与推文对象中的属性相同。

  • id_str 是 Tweets Id 的字符串格式
  • created_at 是创建推文的时间
  • 文字是推文的内容
  • 极性&主观性是使用 TextBlob NLP 库进行核心情感分析的情感值

user_created_atuser_locationuser_descriptionuser_followers_count 这样的属性在用户对象中,它是 Tweet 对象的一部分。此外,c 坐标包括经度纬度是 JSON 格式的另一个对象 Geo 对象

*# Extract info from tweets* **def** on_status(self, status):
    **if** status.retweeted:
        *# Avoid retweeted info, and only original tweets will 
        # be received*
        **return** **True**
    *# Extract attributes from each tweet*
    id_str = status.id_str
    created_at = status.created_at
    text = deEmojify(status.text)    *# Pre-processing the text* 
    sentiment = TextBlob(text).sentiment
    polarity = sentiment.polarity
    subjectivity = sentiment.subjectivity

    user_created_at = status.user.created_at
    user_location = deEmojify(status.user.location)
    user_description = deEmojify(status.user.description)
    user_followers_count =status.user.followers_count
    longitude = **None**
    latitude = **None**
    **if** status.coordinates:
        longitude = status.coordinates['coordinates'][0]
        latitude = status.coordinates['coordinates'][1]

     retweet_count = status.retweet_count
     favorite_count = status.favorite_count # Quick check contents in tweets
     print(status.text)
     print("Long: **{}**, Lati: **{}**".format(longitude, latitude))

     *# Store all data in MySQL*
     **if** mydb.is_connected():
         mycursor = mydb.cursor()
         sql = "INSERT INTO **{}** (id_str,created_at,text,polarity,\
            subjectivity, user_created_at, user_location,\
            user_description, user_followers_count, longitude,\
            latitude, retweet_count, favorite_count) VALUES \
            (**%s**, **%s**, **%s**, **%s**, **%s**, **%s**, **%s**, **%s**, **%s**, **%s**, **%s**, **%s**, **%s**)" \ 
            .format(TABLE_NAME)
          val = (id_str, created_at, text, polarity, subjectivity,\
             user_created_at, user_location, user_description,\ 
             user_followers_count, longitude, latitude,\ 
             retweet_count, favorite_count)
          mycursor.execute(sql, val)
          mydb.commit()
          mycursor.close()

最后,为了允许 tweet 文本存储在 MySQL 中,我们需要做一点处理,通过剥离所有非 ASCII 字符来删除表情符号,即使数据库的字符集是 utf8。

**def** deEmojify(text):
    **if** text:
        **return** text.encode('ascii', 'ignore').decode('ascii')
    **else**:
        **return** **None**

这是我的第一篇技术文章,我感谢任何反馈!

用于品牌提升和话题跟踪的实时 Twitter 情感分析(第 2/3 章)

原文:https://towardsdatascience.com/real-time-twitter-sentiment-analysis-for-brand-improvement-and-topic-tracking-chapter-2-3-1caf05346721?source=collection_archive---------6-----------------------

行业中的数据科学

使用 RE、TextBlob、NLTK 和 Plotly 进行 Twitter 情感分析和交互式数据可视化

Photo by Jonatan Pie on Unsplash

教程将教你如何一步一步地在 Twitter 数据上应用 1) 自然语言处理情感分析,2)利用 Plotly 构建一个交互式数据可视化

这是一个独立的组件,用于执行情绪分析和话题跟踪,并在 Jupiter Notebook 上构建分析仪表板,尽管它是我的综合实时 Twitter 监控系统教程的第二部分。在前一章中解释并实现了流 Twitter 数据收集。

  • 1 : 使用 Tweepy、MySQL、& Python 的流 Twitter API 收集 Twitter 数据
  • 第二章(你来了!):使用 RE、TextBlob、NLTK 和 Plotly 进行 Twitter 情感分析和交互式数据可视化
  • 第三章 : 使用 Python 中的 Dash & Plotly 在 Heroku 上部署一个实时的 Twitter 分析 Web App
  • 第 4 章(可选) : 使用 Scala、Kafka 和 Spark Streaming 实现流媒体 Twitter 情感分析的并行化

Data Visualization based on Plotly in this Chapter

上面的分析仪表板(带完整代码)就是我们今天要做的,它为下一章的 实时 Twitter 监控 Web App 奠定了基础,因为 Dash(python framework for analytical Web apps)是在 Plotly 之上编写的。查看我的 GitHub 回购 了解更多详情。

Web App based on Dash-Plotly in next chapter

****第章的技术栈:RE,NLTK,TextBlob,Plotly,MySQL,Python (time,datetime,math,itertools)

  • RE : 正则表达式识别给定字符序列中是否存在模式的操作
  • NLTK : 自然语言工具包,构建 Python 程序处理人类语言数据的领先平台
  • TextBlob : 自然语言处理库,用于处理文本数据,提供一个简单的 API** 用于潜入普通的 NLP。**
  • :一个交互式,开源的,基于浏览器的Python 图形库****

加载和准备 Twitter 数据

首先,我们需要从数据源中提取 Twitter 数据。简单起见可以直接从sample_data.csv开始读。

**df = pd.read_csv("sample_data.csv")**

或者以一种更正式的方式,从我们的 MySQL 数据库中提取数据,该数据库已经在第 1 章中建立并填充了实时 Twitter 数据。

**db_connection = mysql.connector.connect(
    host="localhost",
    user="root",
    passwd="password",
    database="TwitterDB",
    charset = 'utf8'
 )
time_now = datetime.datetime.utcnow()
time_10mins_before = datetime.timedelta(hours=0,minutes=10)) \
    .strftime('%Y-%m-%d %H:%M:%S'
time_interval = time_now - time_10mins_before**

读取过去 30 分钟内发布的数据,并通过 SQL 查询将其加载到 Pandas DataFrame 中。

**query = "SELECT id_str, text, created_at, polarity,          \
         user_location FROM **{}** WHERE created_at >= '**{}**'"     \
        .format(settings.TABLE_NAME, time_interval)
df = pd.read_sql(query, con=db_connection)**

然后把 DATETIME (MySQL 数据类型)转换成 Datetime (Pandas 数据类型)。

***# UTC for date time at default*
df['created_at'] = pd.to_datetime(df['created_at'])**

使用文本块进行情感分析

情感分析的核心是使用 TextBlob,以便从 tweet 文本中提取极性 & 主观性,这实际上是上一章为了更好地存储数据而进行的数据预处理。负面推文代表-1,正面推文代表+1,中性推文代表 0。

**from **textblob** import TextBlob
sentiment = TextBlob(tweet_text).sentiment
polarity = sentiment.polarity
subjectivity = sentiment.subjectivity**

将整个时间序列转换为 2 秒一组,并计算每个时间间隔组中每种极性(例如-1、0 和 1)的情绪数量。

应用拆栈技术以确保每组中的所有类别都被显示,即使其中一个类别没有任何值。因为我们只显示最近 30 分钟内发布的实时推文,所以在实践中,2 秒间隔的组最好显示在屏幕上。之后,重命名这些列,使它们能够自我解释。

***# Clean and transform data to enable time series*
result = df.groupby(                                        \
      [pd.Grouper(key='created_at', freq='2s'), 'polarity'] \
    ).count().unstack(fill_value=0).stack().reset_index()

result = result.rename(columns=                             \
    { "id_str": "Num of '{}' mentions".format(TRACK_WORD),  \
      "created_at":"Time in UTC" })**

以 2 秒的间隔记录时间序列,以便进一步使用索引。

**time_series = result["Time in UTC"][result['polarity']==0]  \ 
    .reset_index(drop=**True**)**

使用简单的Plotly Express快速可视化折线图。注意:Plotly Express 是一个简洁、一致、高级的plotly.graph_objects包装器,用于快速数据探索和图形生成。

**import **plotly.express** as px
fig = px.line(result, x='Time in UTC',                      \
    y="Num of '{}' mentions".format(TRACK_WORD),            \
    color='polarity')
fig.show()**

Line Chart for Sentiment Analysis

使用 RE 的自然语言处理的主题跟踪& NLTK

为了跟踪推文中最热门的词或最常用的符号,我们加入所有推文,删除 URL,清除“RT”和“T36”(也称为“T37”)amp;。)符号,并将所有字符转换成小写。

**content = ' '.join(df["text"])
content = re.sub(r"http\S+", "", content)
content = content.replace('RT ', ' ').replace('&amp;', 'and')
content = re.sub('[^A-Za-z0-9]+', ' ', content)
content = content.lower()**

第一次使用 python 脚本从 NLTK 下载这两个文件。 Punkt 句子分词器 用于通过使用无监督算法将文本分成一系列句子。

***import nltk
nltk.download('punkt')*
*nltk.download('stopwords')***

然后从所有推文中对整个文本进行分词,使用 停用词 去除常用词,并提取所有词的 频率分布 中最常见的 10 个词。

**from **nltk.probability** import FreqDist
from **nltk.tokenize** import word_tokenize
from **nltk.corpus** import stopwordstokenized_word = word_tokenize(content)
stop_words=set(stopwords.words("english"))
filtered_sent=[]
**for** w **in** tokenized_word:
    **if** w **not** **in** stop_words:
        filtered_sent.append(w)
fdist = FreqDist(filtered_sent)
fd = pd.DataFrame(fdist.most_common(10),                    \
    columns = ["Word","Frequency"]).drop([0]).reindex()**

再次使用简单的 图形表达 快速可视化条形图。

**import **plotly.express** as px
fig = px.bar(fd, x="Word", y="Frequency")
fig.update_traces(marker_color='rgb(240,128,128)',          \
    marker_line_color='rgb(8,48,107)',                      \
    marker_line_width=1.5, opacity=0.8)
fig.show()**

Bar Chart for Topic Tracking

文本处理中的地理分割识别

为了探索用户的地理分布,我们需要通过他们的用户资料来识别他们的位置,而不是附有推文的位置,因为只有不到 1%的人会附上他们的推文位置。然而,根据用户简档中的位置,它们可能包括一个或多个县、城市、州、国家或星球。因此,将这些数据过滤成美国州级位置是地理分段识别的核心。

将所有状态名及其缩写设置为常量,用于进一步的缩写-名称转换。

**STATES = ['Alabama', 'AL', 'Alaska', 'AK',                    \ 
    ...... # Text hided for readability                       \
    'WV', 'Wisconsin', 'WI', 'Wyoming', 'WY']STATE_DICT = dict(itertools.zip_longest(*[iter(STATES)] * 2, fillvalue=""))
INV_STATE_DICT = dict((v,k) **for** k,v **in** STATE_DICT.items())**

通过迭代州名列表和用户位置列表,从他们的位置提取州信息。

**is_in_US=[]
geo = df[['user_location']]
df = df.fillna(" ")
**for** x **in** df['user_location']:
    check = **False**
    **for** s **in** STATES:
        **if** s **in** x:
            is_in_US.append(STATE_DICT[s] **if** s **in** STATE_DICT **else** s)
            check = **True**
            **break**
    **if** **not** check:
        is_in_US.append(**None**)

geo_dist = pd.DataFrame(is_in_US, columns['State'])           \
    .dropna().reset_index()**

统计美国各州发布的推文数量,用对数数字避开极值(如加州 500+,北达科他州 3)更好的可视化。

**geo_dist = geo_dist.groupby('State').count().                 \ 
    rename(columns={"index": "Number"}).sort_values(          \
    by=['Number'], ascending=**False**).reset_index()
geo_dist["Log Num"] = geo_dist["Number"]                      \
    .apply(**lambda** x: math.log(x, 2))**

为稍后仪表板上的悬停文本添加说明性文本信息。

**geo_dist['Full State Name'] = geo_dist['State']               \
    .apply(**lambda** x: INV_STATE_DICT[x])
geo_dist['text'] = geo_dist['Full State Name'] + '<br>' +     \
    'Num: ' + geo_dist['Number'].astype(str)**

这一次,我们使用 Plotly (不是 Plotly Express)来可视化美国地图。

: plotly.graph_objects是 Plotly 库的核心,包含更多通用函数,用于更复杂的用途。locationmode是“仓位”中仓位匹配条目的集合。text是悬停文本。marker_line_color是状态间线条标记的颜色。设置geo_scope将地图范围限制在美国。

**import **plotly.graph_objects** as go
fig = go.Figure(data=go.Choropleth(
    locations=geo_dist['State'], *# Spatial coordinates*
    z = geo_dist['Log Num'].astype(float), *# Data to be color-coded*

    locationmode = 'USA-states', 
    colorscale = "Reds",
    text=geo_dist['text'],
    marker_line_color='white', *# line markers between states*
    colorbar_title = "Numbers in Log2"
))

fig.update_layout(
    geo_scope='usa', 
)

fig.show()**

********

Photo by Karsten Würth (@karsten.wuerth) on Unsplash

带有 Plotly 的交互式分析仪表板

现在我们可以使用Plotly.subplots将所有数据可视化部分集成到一个仪表板中。同时显示多个图形可以大大提高阅读效率,增强多个见解之间的可比性。

首先创建一个包含 2 个 × 2 个支线剧情剧情图,左边是线图,右上角是贴图,右下角是条形图

**from **plotly.subplots** import make_subplots
fig = make_subplots(
        rows=2, cols=2,
        column_widths=[1, 0.4],
        row_heights=[0.6, 0.4],
        specs=[[{"type": "scatter", "rowspan": 2}, 
                {"type": "choropleth"}],
               [**None**, {"type": "bar"}]]
        )**

使用add_tracego.Scatter在第一个子情节中添加三行负片、中性片和正片。另外,rowcol代表这个支线剧情在大图中的位置。

**fig.add_trace(go.Scatter(
    x=time_series,
    y=result["Num of '**{}**' mentions"                     \
        .format(settings.TRACK_WORDS[0])]               \
        [result['polarity']==0].reset_index(drop=**True**), \
    name="Neural",
    opacity=0.8), row=1, col=1) fig.add_trace(go.Scatter(
    x=time_series,
    y=result["Num of '**{}**' mentions"                     \
        .format(settings.TRACK_WORDS[0])]               \ 
        [result['polarity']==-1].reset_index(drop=**True**),
    name="Negative",
    opacity=0.8), row=1, col=1)fig.add_trace(go.Scatter(
    x=time_series,
    y=result["Num of '**{}**' mentions"                     \
        .format(settings.TRACK_WORDS[0])]               \
        [result['polarity']==1].reset_index(drop=**True**), \
    name="Positive",
    opacity=0.8), row=1, col=1)**

使用add_tracego.Bar添加主题频率分布的条形图。您可以使用rgb(xx,xx,xx)rgba(xx,xx,xx,x)改变图中某些元素的颜色。

**fig.add_trace(go.Bar(x=fd["Word"], y=fd["Frequency"],       \
    name="Freq Dist"), row=2, col=2)

fig.update_traces(marker_color='rgb(59, 89, 152)',          \
    marker_line_color='rgb(8,48,107)',                      \
    marker_line_width=0.5, opacity=0.7, row=2, col=2)**

然后在右上角插入地图,并设置位置和每个位置的编号。

**fig.add_trace(go.Choropleth(
    locations=geo_dist['State'], *# Spatial coordinates*
    z = geo_dist['Log Num'].astype(float), *# Data to be color-coded*
    locationmode = 'USA-states', 
    colorscale = "Blues",
    text=geo_dist['text'], *# hover text*
    showscale=**False**,
    geo = 'geo'
    ), row=1, col=2)**

在我们的图的布局中添加标题,缩小我们地图的地理范围,将模板主题变为暗,使用go.layout.Annotation为布局添加 标注

**fig.update_layout(
    title_text =                                            \
      "Real-time tracking '**{}**' mentions on Twitter **{}** UTC"  \
      .format(settings.TRACK_WORDS[0]        
        ,datetime.datetime.utcnow().strftime('%m-%d %H:%M') \
      ),
    geo = dict(
        scope='usa',
    ),
    template="plotly_dark",
    margin=dict(r=20, t=50, b=50, l=20),
    annotations=[
        go.layout.Annotation(
            text="Source: Twitter",
            showarrow=**False**,
            xref="paper",
            yref="paper",
            x=0,
            y=0)
    ],
    showlegend=**False**,
    xaxis_rangeslider_visible=**True** )**

最后,显示单一图形中的所有支线剧情。

**fig.show()**

作者的话:这一章有点复杂,因为它使用 NLP 和情感分析方法将数据点转化为洞察力。通过使用先进的自然语言处理方法,可以实现对主题跟踪的进一步改进。

下一章将是最激动人心的部分,使用 Dash 在 Heroku 服务器上集成和部署所有功能。一如既往,我感谢您的任何反馈!😃

9 月 20 日更新: 第三章已出版!

用于品牌改进和话题跟踪的实时 Twitter 情感分析(第 3/3 章)

原文:https://towardsdatascience.com/real-time-twitter-sentiment-analysis-for-brand-improvement-and-topic-tracking-chapter-3-3-3b61b0f488c0?source=collection_archive---------6-----------------------

行业中的数据科学

使用 Python 中的 Dash & Plotly 在 Heroku 上部署一个实时 Twitter 分析 Web 应用程序

Photo by Kalen Emsley on Unsplash

本教程将教你 1)如何在 Heroku 云应用平台上部署所有数据分析,以及 2)如何使用 Python 中的 Dash 将基于 Plotly 的数据可视化迁移到分析仪表板 web 应用

https://twitter-analysis-web-app.herokuapp.com

: 实时 Twitter 数据收集数据分析&情感分析在前面章节已经完成。

  • 1 : 使用 Tweepy、MySQL、& Python 的流 Twitter API 收集 Twitter 数据
  • 第二章 : 使用 RE、TextBlob、NLTK 和 Plotly 的 Twitter 情感分析和交互式数据可视化
  • 第三章(你来了!):使用 Python 中的 Dash & Plotly 在 Heroku 上部署一个实时 Twitter 分析 Web 应用程序
  • 第 4 章(可选) : 使用 Scala、Kafka 和 Spark Streaming 实现流媒体 Twitter 情感分析的并行化

为什么是 Dash?

  • Dash 是一个用于构建 web 应用程序的高效 Python 框架。Dash 基于 FlaskPlotly.jsReact.js 编写,非常适合用纯 Python 构建具有高度定制用户界面的数据可视化应用。
  • Dash 核心组件【DCC】为交互用户界面提供增压组件。
  • Dash Html 组件 (html) 围绕 Html、CSS、JavaScript 提供纯 Python 抽象。

为什么是 Heroku?

  • Heroku 是一个平台即服务(PaaS),使开发者能够完全在云中构建、运行和操作应用。

为了运行实时 twitter 监控系统,我们将使用两个脚本(或者两个 dynos,或者两个 app)。一个用于采集流数据,另一个用于数据分析和实时可视化。在处理高吞吐量的 Twitter 文本数据时,这种方法可以有效地减少数据管道的延迟。

创建 Heroku 账号&设置环境

这部分是写给初学者如何从头开始建立新的 Heroku 应用程序环境。如果你熟悉 Heroku 平台,你可以考虑跳过这一部分。

两份重要部署指南供参考:

Heroku:云应用平台 上注册你的账号

查看您的电子邮件确认您的帐户,然后登录 Heroku 平台。

点击新建按钮创建新的 app 。应用程序名称必须是唯一的,因为应用程序发布后,每个人都可以通过该名称访问 web 应用程序。

1.安装 Heroku CLI

首先下载并安装 Heroku CLI 。Heroku 命令行界面(CLI)是一个基本组件,允许我们通过终端创建和管理 Heroku 应用程序。

然后,登录您的 Heroku 帐户,按照提示创建一个新的 SSH 公钥。

$ heroku login

2.创建一个新的 Git 仓库

Heroku 使用 Git 对应用程序的开发进行版本控制。

$ mkdir Real-time-Twitter-Monitoring-System
$ cd Real-time-Twitter-Monitoring-System

2.用gitvirtualenv初始化文件夹

$ git init        *# initializes an empty git repo* 
$ virtualenv venv *# creates a virtualenv called "venv"* 
$ source venv/bin/activate *# uses the virtualenv*
$ Heroku git: remote -a **THIS-IS-YOUR-APP-NAME**

virtualenv创建一个新的 Python 实例。你将需要使用此虚拟重新安装你的应用的依赖项新:

$ pip install dash 
$ pip install plotly
$ pip install gunicorn

注意:gunicorn是部署 app 的新依赖项。

3.设置几个必需的文件

用一个示例应用程序(app.py)、一个.gitignore文件、requirements.txt和一个Procfile来初始化文件夹,以便进行部署

一、创建一个名为 **app.py** 的文件,填写样例演示代码。

# Simple demo app only
import dash
app = dash.Dash(__name__)
server = app.server # the Flask app

二。创建 **.gitignore**

venv
*.pyc
.DS_Store
.env

三世。创建**Procfile**

web: gunicorn app:server

(注意app指的是文件名app.pyserver是指该文件内的变量server

四。创建**requirements.txt**

然后让我们添加这个长依赖项。注意:其中一些可能不会直接使用,但在您尝试调整应用程序时会很有用。

Click==7.0
dash==1.1.1
dash-core-components==1.1.1
dash-html-components==1.0.0
dash-renderer==1.0.0
dash-table==4.1.0
Flask==1.1.1
Flask-Compress==1.4.0
gunicorn==19.9.0
itsdangerous==1.1.0
Jinja2==2.10.1
MarkupSafe==1.1.1
plotly==4.1.0
PyYAML==5.1.2
retrying==1.3.3
six==1.12.0
Werkzeug==0.15.5
pandas==0.25.0
nltk==3.4.4
textblob==0.15.2
tweepy==3.8.0
psycopg2-binary==2.8.3
Flask==1.1.1

4.部署应用程序

初始化 Heroku app,向 repo 添加并提交代码,使用 Git 推送到 Heroku cloud。

$ heroku create **THIS-IS-YOUR-UNIQUE-APP-NAME**
$ git add .
$ git commit -m 'Initial the app' 
$ git push heroku master # deploy code to heroku 

Heroku cloud 应该已经在一开始为你设置了一个 dyno ,一个运行你的应用的集群。如果没有,则手动创建一个 dyno。

$ heroku ps:scale web=1  # run the app with a 1 heroku "dyno"

5.更新代码并重新部署

为了将来在 Heroku cloud 上更新我们的应用程序,我们只需要添加、提交并再次推送我们的新代码。

$ git status # view the changes 
$ git add .
$ git commit -m 'a description of the changes' 
$ git push heroku master

现在我们需要写一些真正的代码。

Photo by Jace & Afsoon on Unsplash

将数据分析&可视化从 Plotly 迁移到 Dash

为了将我们上一章的数据可视化放到 Heroku 应用程序上,我们需要用 Dash 框架包装我们基于 Plotly 的仪表板。所有的数据分析和可视化都将在文件**app.py** 中进行处理,您可以在这里 查看我的完整代码

从一个新的应用服务器开始,使用 Dash 默认 CSS 表。注意:我推荐使用 Bootstrap 来改善 web app 的外观。

external_stylesheets=['https://codepen.io/chriddyp/pen/bWLwgP.css'] app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.title = 'Real-Time Twitter Monitor'server = app.server

Dash web app 的核心框架是使用 app.layout 作为背景布局。注意:点击下面的两个链接了解它们是如何工作的,并检查一些典型样品,因为它们对于使用 Dash非常重要

  • 破折号布局 允许我们显示集成的数据可视化以及其他文本描述。
  • 破折号回调 使应用程序能够用实时数据一致地更新一切。

仪表板布局

由于 Dash 构建在 HTML 之上,它以自己的方式使用 HTML(Dash HTML 组件)。但是一些 HTML 特性在 Dash 中是不允许的。

html.Div(id='live-update-graph')描述应用程序中仪表板的顶部部分,包括对推文数量和潜在印象的描述。html.Div(id='live-update-graph-bottom')描述 web app 中仪表板的底部部分。

dcc.Interval是允许应用程序定期更新信息的关键。虽然数据收集器、将在后面解释,但在另一个 dyno 上分析仪表板实时工作,由于利用聚合数据进行可视化,并考虑到的成本效益,所以只分析和可视化每 10 秒的数据。

app.layout = html.Div(children=[    

    *# Parts of Title hided*
    html.H2('This-is-your-tittle'), html.Div(id='live-update-graph'),   
    html.Div(id='live-update-graph-bottom'),

    # Parts of Summary hided
    html.Div( 
        dcc.Markdown("Author's Words: ...... ")
    ) # Timer for updating data per 10 seconds
    dcc.Interval(        
        id='interval-component-slow',
        interval=1*10000, # in milliseconds        
        n_intervals=0    
    )    

  ], style={'padding': '20px'})}

对于 Dash 的 HTML 中的每个 Div,它都有classNamechildrenstylechildrendcc.Graph(仪表板核心部件 中的图形)、dcc.Markdownhtml.Divhtml.H1以及其他交互按钮(如dcc.Dropdowndcc.Slider)的列表。

html.Div(
    className='row',        
    children=[             
        dcc.Markdown("..."),     
        dcc.Graph(...),
        html.Div(...)
    ],
    style={'width': '35%', 'marginLeft': 70}    
)

style对于构建良好的布局和确保几个可视化图形之间的适当距离很重要,但调整细节可能很耗时。

下面举一个dcc.Graph的例子( 仪表板核心部件 中的图形)。dcc.Graph有属性idfigure。在figure下有'data',包含 Plotly 中不同种类的图形(如go.Scattergo.Pie),'layout',它只是这个图形的布局而不是app.layout

# import dash_core_components as dcc
# import plotly.graph_objs as godcc.Graph(                            
  id='pie-chart',                            
  figure={                                
    'data': [                          
       go.Pie(                                        
         labels=['Positives', 'Negatives', 'Neutrals'],
         values=[pos_num, neg_num, neu_num],                                        
        )                              
     ],
     'layout':{
       'showlegend':False,
       'title':'Tweets In Last 10 Mins',
       'annotations':[
         # ...                                
       ]
     }                             
  }                        
)

'[**annotations**](https://plot.ly/python/text-and-annotations/)'是保证当前标签的另一个重要部分。注意:Dash 中标注 的引用相当由于参数可能需要表示为go.layout.Annotation、一个字典dict(...),有时还有一个列表。

破折号回调

在 Dash app 布局中,反应型功能型 Python 回调提供输入和输出之间的连接,允许可定制的声明型 ui。

:我们跳过了上一章解释的所有数据分析部分,尽管可能会有一点点差异(或改进)。因此,我们直接进入基于 Dash 的数据可视化部分,它是通过复杂的 Plotly graphs **plotly.graph_objs**实现的(又名 go )。

# Multiple components can update everytime interval gets fired.
@app.callback(
    Output('live-update-graph', 'children'),
    [Input('interval-component-slow', 'n_intervals')]
  )
def update_graph_live(n): # Lots of nested Div to ensure the proper layout
  # Graphs will be explained later
  # All codes are hided return children

三个线图都使用go.Scatter堆栈组来确保同一图形中线下的重叠区域

# import plotly.graph_objs as go
go.Scatter(
  x=time_series,
  y=result["Num of A-Brand-Name mentions",
  name="Neutrals",
  opacity=0.8,
  mode='lines',
  line=dict(width=0.5, color='rgb(131, 90, 241)'),
  stackgroup='one'
)

饼状图在上面dcc.Graph的例子中解释过。

对于文本描述(例如每 10 分钟的 Tweet 数量变化),我们使用两个 HTML 段落来嵌入数据信息。通过比较之前的 10 分钟间隔和当前的 10 分钟间隔,我们可以生成这样的结果。

html.P(
  'Tweets/10 Mins Changed By',
  style={'fontSize': 17}
),html.P(
  '{0:.2f}%'.format(percent) if percent <= 0        \
      else '+{0:.2f}%'.format(percent),
  style={'fontSize': 40}
)

对于今天的潜在印象,我们想知道最多有多少人有机会看到这些推文。通过计算发布这些推文的人的追随者数量的总和,我们可以得到潜在的印象。增加一个动态数字单元以更好地在非常大的范围内显示该值。

html.P(
  '{0:.1f}K'.format(daily_impressions/1000) \
  if daily_impressions < 1000000 else \
  ('{0:.1f}M'.format(daily_impressions/1000000) 
    if daily_impressions < 1000000000 \
    else '{0:.1f}B'.format(daily_impressions/1000000000)), style={'fontSize': 40}
)

通过在每次应用数据更新中存储和累加推文数量,计算每日推文数量是一种简单的方法。并且该值将在午夜重置为零。

html.P(
  '{0:.1f}K'.format(daily_tweets_num/1000),
  style={'fontSize': 40}
)

底部仪表盘的回调函数与第一个类似。

@app.callback(Output('live-update-graph-bottom', 'children'),
              [Input('interval-component-slow', 'n_intervals')])
def update_graph_bottom_live(n): # Lots of nested Div to ensure the proper layout
  # Graphs will be explained later
  # All codes are hidedreturn children

最热门话题追踪条形图。将orientation设置为水平,以便更好地显示条形和相关的单词名称

go.Bar(
  x=fd["Frequency"].loc[::-1],
  y=fd["Word"].loc[::-1],
  name="Neutrals",
  orientation='h',
  marker_color=fd['Marker_Color'].loc[::-1].to_list(),
  marker=dict(
    line=dict(
      color=fd['Line_Color'].loc[::-1].to_list(),
      width=1
    ),
  )
)

通过设置'layout': {'geo':{'scope':'usa'}}将范围聚焦在州级地图

go.Choropleth(
  locations=geo_dist['State'], # Spatial coordinates
  z = geo_dist['Log Num'].astype(float), # Color-coded data
  locationmode = 'USA-states',
  text=geo_dist['text'], # hover text
  geo = 'geo',
  colorbar_title = "Num in Log2",
  marker_line_color='white',
  colorscale = ["#fdf7ff", "#835af1"]
)

为了在一行中并行多个图形,您可以考虑使用以下。width应该是 1/N 百分比(N =图形数量),我们可以减去 1%以给出图形之间足够的间隙。

style={'display': 'inline-block', 'width': '33%'}

Photo by Banter Snaps on Unsplash

实现实时 Twitter 数据收集器

为了在不支付的情况下运行另一个与 web(用于互联网连接)连接的脚本,我们需要设置另一个应用,除了app.pygunicorn之外,配置完全相同。或者你可以花钱买一个新的 dyno 在原来的应用程序中运行。

注意:由于两个应用程序的消耗,免费计划每月只能运行大约 3 周,如果 30 分钟不活动,web 应用程序可能会休眠,尽管数据收集器不会。

  1. 在新应用程序中创建一个新的应用服务器scraping_server.py,并在下面添加。
from os import environ
from flask import Flaskapp = Flask(__name__)
app.run(environ.get('PORT'))

2.在新应用程序中创建一个数据采集器文件scraping.py,该文件与第 1 章中的文件非常相似。然而,这次我们将使用Heroku PostgreSQL而不是 MySQL,这也要求我们对 SQL 查询进行一点点更新。您可以在这里查看 代码

# Due to the similar code, check [Chapter 1](http://bit.ly/2Zohn01) for detailed explanation.

3.移除app.py,更新gunicorn如下。

worker: python scraping.py
web: python scraping_server.py

*注意:别忘了创建credentials.pysettings.py,就像第一章中的一样。

通过 Heroku PostgreSQL 连接两个服务器/脚本/dyno

在应用程序之间共享同一个 Postgres 数据库,请遵循本 指南 :

$ heroku addons:attach my-originating-app::DATABASE --app sushi

新方法:

Heroku 现在允许一个新的数据管道特性,所以你可以考虑利用这个优势,而不是使用我的两个应用程序连接一个 PostgreSQL 的方法。

作者的话:

感谢阅读!针对我的实时 Twitter 监控系统的这一系列文章已经结束,但是新技术的开发不会停止。第 4 章将在 10 月份作为独立文章发表。希望下次能见到你!

Apache Druid 中的实时数据—选择正确的策略

原文:https://towardsdatascience.com/realtime-data-in-apache-druid-choosing-the-right-strategy-cd1594dc66e0?source=collection_archive---------14-----------------------

为什么你应该使用卡夫卡索引而不是宁静

Photo by Luke Chesser on Unsplash

在实时数据流中存储数据一直是一个挑战。解决方案取决于您的使用案例。如果你想为每日或每月的分析存储数据,你可以使用分布式文件系统,并在其上运行 HivePresto 。如果你要运行一些简单的实时分析,你可以将最近的数据存储在 Elasticsearch 中,并运行 Kibana 来获取图表。

Apache Druid 是为了同时解决上述两种用例而设计的。它可以作为每日或每月分析的持久数据存储。它还可以作为快速可查询数据存储,允许您实时推送和检索数据。

然而,早期版本的 Apache druid 的问题是从数据库的流中获取数据。让我们来看看开发人员早先面临的挑战。

平静

宁静是 Apache Druid 提供的摄取实时数据的包。宁静并不完全等同于 JDBC 或卡珊德拉司机。它为您处理分区、复制、服务发现和模式翻转。用户需要关心他需要使用的数据和数据源。

Ingesting realtime data using Tranquility

宁静解决了用户可能面临的许多问题。然而,它也伴随着自身的一系列挑战。

不完全是一次

在某些情况下,宁静会创建重复的记录。它不提供任何一次性的保证。在某些情况下,比如 POST 请求数据超时或者没有收到 ack,宁静会产生重复的记录。

在这种情况下,用户需要承担消除重复数据的责任。如果您正在使用 Apache 超集,它甚至会导致其中的图形不正确。

数据丢失

宁静最关心的问题是数据丢失。有各种情况下,宁静故意或由于错误无法插入数据。官方文件中列出的一些案例是—

  • 时间戳超出您配置的窗口周期的事件将被丢弃。
  • 如果您遇到的 Druid 中级管理器故障多于您配置的副本数,一些部分索引的数据可能会丢失。
  • 如果有一个持续的问题阻止了与 Druid 索引服务的通信,并且重试策略在此期间用尽,或者此期间持续的时间超过了您的 windowPeriod ,一些事件将被丢弃。
  • 如果有一个问题阻止了宁静从索引服务接收确认,它将重试批处理,这可能导致重复的事件。

最糟糕的是,在大多数情况下,直到查询时,您才知道您的数据已经被删除。

错误处理

因为宁静守护进程运行在 JVM 内部,所以处理超时之类的错误是应用程序的责任。对于像 Apache Flink 这样的应用程序,如果不能有效地管理其中一个错误,就会导致不必要的重启。

在所有这些问题之上,宁静是为德鲁伊 0.9.2 构建的。将它与当前的 druid 版本 0.16.0 一起使用会产生无法识别的问题。

卡夫卡索引

为了解决上述所有问题,Apache druid 在 0.9.1 版本中添加了 Kafka Indexer。在版本 0.14 之前,索引器一直处于实验状态。

Kafka 索引服务首先根据您指定的配置启动一个管理程序。然后,管理员会定期启动新的索引任务,这些任务负责从 Kafka 消费数据,并将其发布到 Druid 中。

与宁静不同,Kafka 索引任务可以长期运行。在达到最小行数或字节数后,可以发布多个段,而无需启动新任务。

Kafka Indexer in Apache Druid

卡夫卡索引器旨在解决其前辈所面临的各种挑战。

恰好一次语义

Kafka 索引器为用户提供了一次精确的保证。这种保证是可能的,因为 Kafka 0.11.x 提供了对这种语义的现成支持。

发布延迟的数据

Kafka 索引器旨在发布延迟的数据。它不受宁静窗口期的影响。这种能力让用户可以自由地将 Kafka 中特定偏移量的数据回填到 Druid 中。

模式更新

尽管宁静也支持模式更新,但在 Kafka Indexer 中要容易得多。您只需要提交一个包含新模式的 POST 请求,主管将使用更新后的模式生成新任务。你不需要在生产者端做任何改变。
如果您添加了新的列,旧的行将在这些列中显示空值,但是这些行仍然是可查询的。

Kafka 索引器服务解决了开发人员在使用宁静时面临的许多问题。如果你想开始使用 Kafka 索引服务,你可以参考官方 Druid 文档中的 Apache Kafka 摄取

用概率和火焰推理——我的模型够好吗?

原文:https://towardsdatascience.com/reasoning-with-probability-is-my-model-good-enough-1cfd27d5aed9?source=collection_archive---------28-----------------------

在其核心,概率编程是为了回答关于不确定性的问题。一些非常受欢迎的在线例子讨论了使用概率编程来帮助神经网络,并使它们更有能力处理他们没有训练过的新例子。然而,在本教程中,我将介绍概率编程可以帮助的最基本的功能。

这里的例子在很大程度上摘自扎克·安临来的演讲,他在演讲中介绍了使用 PyMC3 的概率编程。我将使用 Pyro ,因为我看到这个库在未来会起飞,我想探索它更多一点。

示例场景

让我们考虑以下简单的工作流程:

  • 获取数据(在这种情况下是一个样本数据集)
  • 执行训练/测试分割
  • 根据训练数据训练模型
  • 测试模型的性能,决定性能好不好

Import required packages

Obtain our data

>>> (70000, 784)
>>> (70000,)

Split the data into train and test

>>> (56000, 784) (14000, 784)
>>> (56000,) (14000,)

Train a decision tree on our train data, and test its performance on the test data

>>> Accuracy is 87.06%

分析

我们可以尝试提高模型的准确性,使其达到 87%以上,甚至采用更强的模型,如 CNN,但有一个稍微不太明显的问题。想想我们如何知道我们有 87%的准确率。

我们的测试集是 14000 个带标签的例子。这是一种真正的奢侈,因为对于一些数据科学问题,我们可能不会遇到这么多标记良好的例子。如果我们只有 100 个例子,而不是 14000 个,会怎么样?

>>> (100, 784) (100,)

Check accuracy again, but only on 100 test observations

>>> Accuracy is 86.00%

我们得到了一个稍低的数字,但仍然是可比的。

也就是说,虽然数字很接近,但相信基于 100 个例子的模型要比相信基于 14000 个例子的模型更难。

直觉上,随着测试集大小的增加,我们对测试集分数的信心也增加了。Pyro 允许我们从数字上估计我们的信心以及我们有多少出错的空间。

烟火模型

Pyro 工作流程非常独特,需要三个组件

  1. 模拟我们底层模型的模型函数(不是决策树,而是给我们正确或不正确标签的过程)。该功能从先验分布开始
  2. 当观察到的例子由模型函数产生时,测量它们的似然性的核
  3. 构建后验分布的采样器

首先我们需要定义我们对 Pyro 的观察。在我们的例子中,我们的观察是我们看到正确和不正确分类的情况。让我们同时考虑小测试集(100 个观测值)和大测试集(14,000 个观测值)。

现在我们必须定义模型函数。该函数接受我们的观察值,并尝试从先验分布中取样,并根据我们的观察值计算先验的可能性。然后,内核会将先验更新为更可能的后验分布。

它看起来不太像,但是在这个模型中发生了两个重要的事件。

  • 首先,我们使用“pyro.sample”函数注册一个名为“p”的参数,作为 pyro 的可学习值。使用“pyro.sample”或“pyro.param”将结果值作为可学习值记录在 pyro 的内部存储器(一个特殊的类似字典的对象)中。在我们的例子中,我们已经说过“p”是一个可学习的分布。
  • 我们还将每个观察记录为一个可学习的值,它应该符合我们提供给它的观察。

我们将注册该模型的内核(哈密顿蒙特卡罗内核)将查看该模型中定义的所有可学习值,并将尝试调整可学习分布,以便它们增加所提供的观测值的可能性。

我们将使用的采样器(马尔可夫链蒙特卡罗)将运行 HMC 核来寻找后验分布。

>>> Sample: 100%|█████████████████████████████████████████| 200/200 [03:46,  1.13s/it, step size=1.51e+00, acc. prob=0.916]

现在我们已经运行了我们的采样器,我们可以用我们得到的后验概率做几件事。首先,我们可能想把我们定义的概率“p”形象化。我们可以通过从我们的取样器取样来做到这一点。

The posterior distribution for our accuracy score given 100 examples

>>>     mean    std    median    2.5%    97.5%     n_eff     r_hat
>>> p   0.86   0.04      0.86    0.79     0.93    185.83      1.00

>>> Number of divergences: 0

不是一个很好的结果… 100 次观察并不足以确定一个好的结果。该分布似乎并不集中在一个特定的值上,当我们要求 95%的可信区间时,我们的真实值可以在 79%和 93%之间。对于我们的目的来说,这可能足够准确,也可能不够准确。

让我们看看当我们使用全部 14,000 个观察值时,我们对我们的模型有多大的信心

修改我们的模型

如果我们通过同一个模型运行所有 14,000 个观察值,那么运行时间将会非常长。
这是因为我们在代码中循环遍历每个观察。

Pyro 包含一个更方便的、矢量化的方法来处理我们的模型。

首先,我们重新定义了模型函数,使其不接受任何观察值,而是返回自己的观察值

现在,我们定义了第二个函数,它将模型函数和观察值作为输入,并利用“pyro.poutine”在条件环境中运行模型函数。重要的是,我们在这里的观察值与它们在模型函数中的名称相同(“obs”)。

最后,我们重新运行 MCMC 采样器,但是现在使用我们的条件模型,我们发送我们的模型函数,以及我们的观察,作为参数

>>> Sample: 100%|█████████████████████████████████████████| 200/200 [01:47,  1.86it/s, step size=7.87e-01, acc. prob=0.984]

The posterior distribution for our accuracy score given 14,000 examples

>>>    mean    std    median      2.5%     97.5%     n_eff     r_hat
>>> p2 0.87   0.00      0.87      0.87      0.87      9.88      1.07

>>> Number of divergences: 0

现在,我们可以在 87%左右得到更紧密的配合。为了比较这两个分布,我们可以把它们画在一起。

The two posterior distributions for our accuracy based on the number of support examples

我希望你们都喜欢阅读这篇关于 Pyro 及其功能的简介。我当然期待尝试新的东西,更多地使用概率编程!

你不应该再考虑数据科学的理由。等等,我有说不应该吗!

原文:https://towardsdatascience.com/reasons-why-you-shouldnt-consider-data-science-as-an-option-anymore-wait-did-i-say-shouldn-t-22154bd492fd?source=collection_archive---------21-----------------------

“信息是 21 世纪的石油,分析是内燃机。”

大数据 和数据科学的力量正在从根本上改变世界。自从我们进入大数据时代以来,数据科学 已经成为增长最快、价值数百万美元的公司之一。如今一切都被数据淹没了。数据存在于每个数字和电子设备中。无论是电脑、手机、笔记本电脑、相机还是手表。

公司正在收集数据进行分析,并从中得出真知灼见。

当你在购物中心或任何商店购物,或者你去餐馆时,他们会给你一份反馈表让你填写。或者他们要求您对他们提供的产品和服务进行反馈。你提供的反馈或他们收集的反馈只不过是数据。

因此, 数据科学 就是收集数据,分析数据,并借助数据做出决策的过程。它是一个研究领域,涉及借助科学方法和算法从原始数据中提取有意义的见解,然后有效地传达这些见解,从而产生价值。

数据形式:

数据就像冰一样,就像三种形式的冰一样,它有三种状态(一个糟糕的笑话,但会帮助你理解)。😛

数据可以是结构化的、非结构化的和半结构化的:

1)结构化 -

它是用于分析过程的有组织的数据。它是经过处理的数据。例如:关系数据。

2)半结构化-

它有一些组织属性,但是不适合数据库系统。例如:XML/RDF 数据。

3)非结构化-

它是不以任何方式组织的数据,是最灵活的数据形式。例如:Word、PDF、Text。

我想这个形象是如此贴切和不言自明。数据科学是计算机科学、数学和统计学的混合体。一个愿意从事数据科学职业的人需要在数学、计算机编程和统计学方面有坚实的基础。优秀的教育背景,R 或 Python 等各种编程语言的知识,最重要的是,成为一名数据科学家需要时间和努力。

关键组件

随着对数据洞察力的需求不断增加,数据科学对于每个领域都是必要的。以下是数据科学角色的一些关键组成部分:

1)收集和查询数据:数据科学家在流程分析过程中收集、查询和消费数据。他们专注于数据的分析、预测和可视化。数据科学家必须查询数据,不管数据是如何存储的,也不管数据存储在哪里。查询数据包括编写命令从数据存储系统中提取信息。很多时候, SQL (结构化查询语言)就是用来做这个的。

2)从数学模型中获得洞察力:数据科学家的工作需要数学技能,因为理解数据需要数学技能。这些是用来进行预测和决策的技能。数学方法也用于建立模型和生成近似值。

3)将一些技能 和一些统计方法应用于数据科学任务:统计技能和方法对于验证假设和预测未来事件的预测是有用和必要的。了解一些基本的统计方法,如线性回归、相关性、贝叶斯定理和时间序列分析是必不可少的,有助于生成可能的数据结果。

4)编码是游戏的一部分:在使用数据科学时,编码是不可避免的。你需要能够编写代码来指示和指导计算机如何分析和可视化你的数据。虽然 SQL 对于查询数据是必要的,但是诸如【Python】R 等编程语言对于数据的分析和可视化是有用的。

****5)将数据科学应用于主题领域:数据科学家需要在他们工作的领域拥有主题专业知识。他们从给定的数据中产生深刻的见解,然后理解这些见解对于他们工作的领域意味着什么。主题专家正在使用数据科学来提高他们在各自行业中的表现:

a)IT 行业 - 工程师在现代建筑设计中使用机器学习。

b)医疗行业 - 临床数据科学家制定治疗计划,并使用医疗保健信息来预测处于风险中的患者未来的健康问题。

c)电子商务 - 营销数据科学家使用回归和相关来预测消费者偏好的变化或消费者从一种产品或服务流失到竞争对手的产品或服务。

****6)交流数据见解:作为一名数据科学家,你必须有很强的口头和书面交流技能,并且能够交流这些技能,否则所有的知识和见解对你的组织都没有好处。数据科学家需要在沟通方式和方法上具有创造性和实用性。

所有这些都是好的。但是,我将如何从学习数据科学中受益

1)它永远不会让你感到无聊 —在学习数据科学的过程中,你会被分配很多任务,让你专注于工作,很难对所有这些项目感到厌倦。

你有很多职业选择可以选择——数据管理在所有组织、所有级别都很重要。不仅大型 It 软件公司需要数据科学,银行和金融行业、零售行业、医疗保健行业等也需要数据科学。各种职位可以是分析工程师、分析经理、大数据工程师、业务分析师、数据架构师、数据分析师、数据工程师、数据科学家、数据可视化专家、统计学家。

3)有助于改善沟通 —学习数据科学也是学习如何向第三方传达结果和见解。沟通是你需要努力的事情,它不仅在数据科学领域,而且在任何地方都是一种伟大的品质!

4)巨大的需求 —数据科学是一个需要很多技能的领域,所以很难找到具备所有这些技能的人。数据科学专业人员很有价值,他们的需求也很高。

高薪——随着需求的增加,这是几乎所有国家中收入最高的职业之一。这个职业的工资范围(美国)在 65,000 美元到 150,000 美元之间。

等等!你知道一个数据科学家的 工资 吗?

结论:

所有的公司都有数据,他们只需要弄清楚如何利用这些数据来为自己谋利。利用这些数据的人越来越多,因为今天一切都围绕着客户,让他们能够获得内容是最重要的事情。

数据科学家利用他们在数学、统计、编程和不同学科领域的技能来组织大型数据集。他们运用自己的知识和专业技能来发现隐藏在数据中的解决方案,以应对业务挑战并实现目标。

接收我们的时事通讯

原文:https://towardsdatascience.com/receive-our-newsletters-681049ffa0cf?source=collection_archive---------24-----------------------

想要了解数据科学的最新动态,并在您的收件箱中收到我们提供的最佳信息吗?这里有几个你可能感兴趣的时事通讯选项。

Photo by Alejandra Cifre González on Unsplash

变量:

每周四,Variable都会带来最好的数据科学:从实践教程和前沿研究到你不想错过的原创功能。

我们的每周文摘:

我们的文摘为您提供个性化的推荐,每周五直接发送到您的收件箱订阅很简单。只需点击左侧矩形中的“关注”按钮,并在您的设置中打开“接收信件”即可关注我们的出版物。

Python 的新近性、频率、货币模型——以及丝芙兰如何使用它来优化他们的谷歌和脸书广告

原文:https://towardsdatascience.com/recency-frequency-monetary-model-with-python-and-how-sephora-uses-it-to-optimize-their-google-d6a0707c5f17?source=collection_archive---------1-----------------------

上次我们使用群组分析方法分析了我们的在线购物者数据集。我们围绕我们的队列数据集发现了一些有趣的观察结果。虽然群组分析为我们提供了长期的客户行为并了解了保留率,但我们还希望能够根据他们的行为对我们的数据进行细分。今天,我们将探索零售商使用的流行的 RFM 模式,如丝芙兰,将店内和网上购买相结合,以细分客户,获得更好的个性化广告内容。我强烈推荐关注丝芙兰博客的数据科学,以获得更深入的数据见解。你也可以看看这篇由 Jimmy Joe 撰写的文章,他在文章中深入探讨了利用 RFM 实现客户终身价值的秘密

什么是 RFM?

通过 3 个重要特征进行行为细分:

  1. 最近——自上次购买以来的天数
  2. 频率——特定时期内的交易数量
  3. 货币——在给定时间内花费的金额

然后,我们必须按以下方式对这些功能进行分组:

  1. 百分位数或分位数
  2. 帕累托法则——80/20
  3. 商业头脑

我们将对我们的方法实施百分位数分组。

现在让我们继续学习 Python。

这些是我们今天分析所需要的库。稍后,我们将使用 squarify 将我们的分割绘制成树形图。

# Import libraries
import pandas as pd
from datetime import timedelta
import matplotlib.pyplot as plt
import squarify

我们将再次分析我们的在线购物者数据集,但这次是用我们的 RFM 模型。

# Read dataset
online = pd.read_csv('../data.csv', encoding = "ISO-8859-1")# Convert InvoiceDate from object to datetime format
online['InvoiceDate'] = pd.to_datetime(online['InvoiceDate'])

让我们仔细看看我们需要处理的数据。

**Input:**
print('{:,} rows; {:,} columns'
      .format(online.shape[0], online.shape[1]))print('{:,} transactions don\'t have a customer id'
      .format(online[online.CustomerID.isnull()].shape[0]))print('Transactions timeframe from {} to {}'.format(online['InvoiceDate'].min(),
                                    online['InvoiceDate'].max()))**Output:**
541,909 rows; 8 columns
135,080 transactions don't have a customer id
Transactions timeframe from 2010-12-01 08:26:00 to 2011-12-09 12:50:00**Input:**
# Drop NA values from online
online.dropna()

我们需要做的第一件事是根据最近、频率和货币价值对客户进行分类。为了计算最近,我们将把数据集的最后一个发票日期之后的一天作为快照日期'2011–12–10 12:50:00 '。日期差异将告诉我们最近一次交易是什么时候完成的。这样,我们就可以根据客户 ID 对‘在线’数据框进行分组,并将其分配给‘数据处理’进行数据预处理。

# --Group data by customerID--# Create TotalSum column for online dataset
online['TotalSum'] = online['Quantity'] * online['UnitPrice']# Create snapshot date
snapshot_date = online['InvoiceDate'].max() + timedelta(days=1)
print(snapshot_date)# Grouping by CustomerID
data_process = online.groupby(['CustomerID']).agg({
        'InvoiceDate': lambda x: (snapshot_date - x.max()).days,
        'InvoiceNo': 'count',
        'TotalSum': 'sum'})# Rename the columns 
data_process.rename(columns={'InvoiceDate': 'Recency',
                         'InvoiceNo': 'Frequency',
                         'TotalSum': 'MonetaryValue'}, inplace=True)

让我们看看目前为止的进展。

# Print top 5 rows and shape of dataframe
print(data_process.head())
print('{:,} rows; {:,} columns'
      .format(data_process.shape[0], data_process.shape[1]))**Output:**
            Recency  Frequency  MonetaryValue
CustomerID                                   
12346.0         326          2           0.00
12347.0           2        182        4310.00
12348.0          75         31        1797.24
12349.0          19         73        1757.55
12350.0         310         17         334.40
4,372 rows; 3 columns

太好了,我们有 4,372 条客户记录,根据他们购买的最近时间、频率、数量和购买的货币价值进行分组。现在我们可以进入事物的内部,使用。qcut()方法将相对百分位数分配给他们的 RFM 特征。但在此之前,让我们检查一下我们的近因、频率和货币的分布。

**# Plot RFM distributions**
plt.figure(figsize=(12,10))# Plot distribution of R
plt.subplot(3, 1, 1); sns.distplot(data_process['Recency'])# Plot distribution of F
plt.subplot(3, 1, 2); sns.distplot(data_process['Frequency'])# Plot distribution of M
plt.subplot(3, 1, 3); sns.distplot(data_process['MonetaryValue'])# Show the plot
plt.show()

这张图为我们提供了一些非常有趣的见解,以及我们的数据是如何扭曲的。这里需要注意的重要一点是,我们将用分位数对这些值进行分组。然而,当我们在接下来使用 K-Means 检查我们的客户细分时,确保我们将数据调整到均值和标准差的中心是非常重要的。下次会有更多。让我们继续。qcut()为我们的 RFM。

# --Calculate R and F groups--# Create labels for Recency and Frequency
r_labels = range(4, 0, -1); f_labels = range(1, 5)# Assign these labels to 4 equal percentile groups 
r_groups = pd.qcut(data_process['Recency'], q=4, labels=r_labels)# Assign these labels to 4 equal percentile groups 
f_groups = pd.qcut(data_process['Frequency'], q=4, labels=f_labels)# Create new columns R and F 
data_process = data_process.assign(R = r_groups.values, F = f_groups.values)
data_process.head()

我们为 f_labels 创建了一个 4 标签,其中 4 是“最佳”分位数。我们为我们的 f_label 做同样的事情。然后,我们创建新的列“R”和“F ”,并分别为它们分配 r_group 和 f_group 值。

接下来,我们对货币值进行同样的操作,使用。qcut()方法。

# Create labels for MonetaryValue
m_labels = range(1, 5)# Assign these labels to three equal percentile groups 
m_groups = pd.qcut(data_process['MonetaryValue'], q=4, labels=m_labels)# Create new column M
data_process = data_process.assign(M = m_groups.values)

最后,有了这 3 个分数,R,F 和 M,我们可以通过将下面的值连接在一起来创建我们的第一个 RFM 线段。让我们将 data_process 数据帧分配给新创建的 rfm 数据帧。

# Concat RFM quartile values to create RFM Segments
def join_rfm(x): return str(x['R']) + str(x['F']) + str(x['M'])
data_process['RFM_Segment_Concat'] = data_process.apply(join_rfm, axis=1)rfm = data_process
rfm.head()

从输出中,您可以看到我们已经准备好将连接的数据段用于分段,但是,等等,还有一个问题…

# Count num of unique segments
rfm_count_unique = rfm.groupby('RFM_Segment_Concat')['RFM_Segment_Concat'].nunique()
print(rfm_count_unique.sum())**Output:** 62

使用 concatenate 方法拥有 62 个不同的段对于任何实际应用来说都很快变得不实用。我们需要一种更简洁的方式来定义我们的细分市场。

合计分数

最直接的方法之一是将我们的分数相加为一个数字,并为每个分数范围定义 RFM 等级。

**# Calculate RFM_Score** rfm['RFM_Score'] = rfm[['R','F','M']].sum(axis=1)
print(rfm['RFM_Score'].head())**Output:**CustomerID
12346.0     3.0
12347.0    12.0
12348.0     8.0
12349.0    10.0
12350.0     4.0
Name: RFM_Score, dtype: float64

我们可以发挥创意,假设每个分数范围意味着什么,但在这个练习中,我将从一些常见的部分名称中获得灵感。

# Define rfm_level function
def rfm_level(df):
    if df['RFM_Score'] >= 9:
        return 'Can\'t Loose Them'
    elif ((df['RFM_Score'] >= 8) and (df['RFM_Score'] < 9)):
        return 'Champions'
    elif ((df['RFM_Score'] >= 7) and (df['RFM_Score'] < 8)):
        return 'Loyal'
    elif ((df['RFM_Score'] >= 6) and (df['RFM_Score'] < 7)):
        return 'Potential'
    elif ((df['RFM_Score'] >= 5) and (df['RFM_Score'] < 6)):
        return 'Promising'
    elif ((df['RFM_Score'] >= 4) and (df['RFM_Score'] < 5)):
        return 'Needs Attention'
    else:
        return 'Require Activation'# Create a new variable RFM_Level
rfm['RFM_Level'] = rfm.apply(rfm_level, axis=1)# Print the header with top 5 rows to the console
rfm.head()

最后,我们可以根据客户的 RFM 级别对他们进行分组。

# Calculate average values for each RFM_Level, and return a size of each segment 
rfm_level_agg = rfm.groupby('RFM_Level').agg({
    'Recency': 'mean',
    'Frequency': 'mean',
    'MonetaryValue': ['mean', 'count']
}).round(1)# Print the aggregated dataset
print(rfm_level_agg)

从这里,我们可以看到很大比例(~60%)的客户处于顶级 RFM 级别。商店必须做一些正确的事情来维持他们的忠诚度!

其余的 40%将需要一些工作。让我们探索使用一些广告来重新定位他们:

  1. 潜在客户——很有可能进入我们的忠诚客户群,为什么不在他们下次购买时赠送一些赠品,以显示您对他们的重视!
  2. 有希望——对他们购买的数量和价值表现出有希望的迹象,但距离他们上次从你这里购买已经有一段时间了。让我们针对他们的愿望清单项目和限时优惠折扣。
  3. 需要关注—初次购买了一些商品,但之后就再也没有见过。是糟糕的客户体验吗?还是产品市场契合度?让我们花一些资源与他们一起建立我们的品牌意识。
  4. 需要激活——我们的 RFM 模式中表现最差的。他们现在可能已经选择了我们的竞争对手,需要不同的激活策略来赢回他们。

但是在我们结束之前,让我们为我们的数据创建一个漂亮的可视化。

rfm_level_agg.columns = rfm_level_agg.columns.droplevel()
rfm_level_agg.columns = ['RecencyMean','FrequencyMean','MonetaryMean', 'Count']#Create our plot and resize it.
fig = plt.gcf()
ax = fig.add_subplot()
fig.set_size_inches(16, 9)squarify.plot(sizes=rfm_level_agg['Count'], 
              label=['Can\'t Loose Them',
                     'Champions',
                     'Loyal',
                     'Needs Attention',
                     'Potential', 
                     'Promising', 
                     'Require Activation'], alpha=.6 )plt.title("RFM Segments",fontsize=18,fontweight="bold")
plt.axis('off')
plt.show()

自然语言处理的最新进展

原文:https://towardsdatascience.com/recent-advancements-in-nlp-2-2-df2ee75e189?source=collection_archive---------5-----------------------

注意了,变形金刚,伯特还有更多。

在之前的一篇帖子中,我写了 NLP 中最近的两个重要概念——单词嵌入RNN 。在这篇文章中,我将介绍 注意变压器 的概念,它们已经成为目前 NLP 中大多数最新模型的构建模块。我还将回顾 BERT 在 NLP 中使 的强大概念 的迁移学习变得更加容易

像我之前的帖子一样,我将跳过大部分数学内容,更多地关注直觉理解。原因是——使用过多的符号和等式会让包括我在内的许多人感到厌烦。这实际上对概念理解并不重要,我认为概念理解比理解每一个潜在的数学方程重要得多。

虽然像 Bi-LSTM 这样的 RNN 变体在各种 NLP 任务上表现相当稳定,但仍然存在以下一些关键挑战:

  1. 缺乏并行性会损害性能 — LSTM 需要按顺序处理给定序列中的输入令牌,因为当前步骤的输出取决于前一步骤的输出。没有办法将这种计算并行化,这带来了训练时间长、不能在非常大的数据集上训练等明显的缺点。
  2. 学习长期依存关系仍然是一个挑战—虽然与经典的 rnn 相比,LSTMs 更善于从序列中出现过的内容中记住上下文,但从长句子中更早出现的单词中记住上下文仍然是一个挑战,这就是为什么长句子/序列的性能不如短句子/序列的性能。
  3. 运算次数随距离线性增加— 将两个任意输入或输出位置的信号相关所需的运算次数随位置间的距离线性增加

上述挑战是 2017 年及以后大量工作的动力。注意力的概念解决了上面的挑战#2,而变压器架构解决了挑战# 1 和挑战#3。

需要注意的一点是,虽然注意力转换者的概念有助于打破 NLP 任务中的既定基准,但这些都是通用技术,可以广泛应用于任何序列到序列任务。例如,变形金刚架构也是打败顶级星际争霸 2职业玩家的 DeepMind 机器人 AlphaStar 的构建模块。

注意力

一般来说,注意力是深度学习中最有影响力的想法之一。虽然这个概念最初是为机器翻译开发的,但它的使用迅速扩展到了许多其他领域。这是由 Dzmitry Bahdanau 等人在这篇有影响力的论文中提出的。

其背后的核心思想是——当执行某个任务时,例如,将句子从一种语言翻译成另一种语言,比如从英语翻译成法语,输出法语句子中的每个单词将由原始输入英语句子中的所有单词(的相关上下文)以不同程度的关注或重要性来通知,而不是由处理整个英语句子生成的单一/恒定上下文。

考虑以下来自 谷歌博客 的优秀英语到法语的翻译例子。两个句子中的“它”指的是不同的名词,根据“它”指的是哪个名词,它翻译成法语也不同。

对人来说,很明显,在第一句话中“它”指的是动物,而在第二句话中是指街道

下图描绘了概念上与(自我)注意力发生的事情。不是获取整个句子的上下文向量并告知单词“它”的翻译,而是由输入句子中的不同单词告知翻译上下文不同的量,如颜色编码所示(越暗=越重要)

Source: Google Blog

需要注意的一点是——注意模型中的权重不是固定的,像神经网络模型学习的其他参数一样,而是作为输入/隐藏状态的函数来计算的——这就是模型如何知道如何对任何给定句子的输入句子中的相关单词进行适当的强调。

如上所述,注意力的概念通过在每一步使用更合适的上下文(而不是“恒定”上下文,例如基于 LSTM 的编码器-解码器)解决了长期依赖性的问题,但是计算中的非并行性问题仍然存在,因为计算仍然需要顺序进行。有了的关注,如果有什么不同的话,我们让计算比简单的 LSTMs 更复杂,这就是变压器架构来拯救的地方。

变压器

Transformer 于 2017 年在这篇开创性论文中推出,作者是来自谷歌的 Vaswani 等人。变压器的网络架构完全基于注意力机制,没有 RNN 或 CNN 单元。以下是该体系结构的一些主要优势:

  • 语言翻译任务的高质量结果,超越了以前的基准
  • 更高的并行性,需要的培训时间明显减少
  • 很好地推广到许多其他任务

Transformer Model Architecture. Source Transformer Paper

上图是变压器的整体架构,乍一看有点吓人。让我们看看架构的高级细节:

  • 编码器-解码器架构:它遵循著名的编码器-解码器范例,编码器将输入转换为有用的表示,解码器使用该表示生成输出。在上图中,编码器模块在左边,解码器模块在右边。
  • 自动回归:在每一步,模型消耗先前生成的输出作为附加输入
  • 没有 RNNs :没有 RNN 单位,只有一堆关注层。
  • 多层:每个编码器/解码器由 6 层(模型中的超参数)相同的层组成
  • 嵌入:输入/输出嵌入将文本或文字转换成数字。
  • 位置编码:位置编码是对原始序列的顺序进行编码,因为我们不再像在 RNN 那样按顺序处理输入,所以它保证了排序的信息不会丢失。
  • 多头注意力:有多个注意力层并行运行,以增加多样性(类似于计算机视觉中的多个卷积滤波器)。
  • 注意层次:有 3 种注意类型——编码器自我注意、编码器-解码器注意和解码器自我注意。
  • 自我关注:在编码器自我关注的情况下(图中左下方的关注块),编码器内的一层试图计算出它应该对(编码器的)前一层的输出给予多少关注,也就是说,试图学习输入中的每个单词与输入中的其他单词的关系/上下文。解码器自我关注(图中右下方的关注块)做了同样的事情,但超过了输出。
  • 编码器-解码器注意力:利用编码器-解码器注意力(图中右上角的注意力块),模型计算出输入中的每个单词与输出中的每个单词的相关程度。

有了这些细节,变压器取得的成果令人印象深刻,然而,也有一些需要改进的地方:

  • 它只能处理定长句子。
  • 需要将较大的句子分解成较小的句子以输入到模型中,这导致“上下文碎片

BERT —来自变压器的双向编码器表示

首先,一个诚实的坦白——我就是记不住 BERT 的完整形式,不管我读了多少遍,我认为完整形式是从首字母缩略词派生出来的,而不是相反:-)的意思

BERT 由 Google 的 Jacob 等人提出,是一种基于 Transformer 的语言表示模型。我认为 BERT 的主要贡献,除了它新颖的双向培训等,还在于它在 NLP 中推广了预培训/ 迁移学习的概念

在我们继续之前,先简单说一下迁移学习。与 NLP 相比,它是深度学习中最优雅的概念之一,在 ComputerVision 中更受欢迎。基本思想是——人们可以在一个通用但相关的任务上训练一个(深度的,即有多个层的)模型,只需在特定于任务的数据上微调最后几层就可以实现出色的性能。

**迁移学习的基本原理是——深度模型中的早期层学习更多的基本模式,例如,学习检测计算机视觉模型中的直线和曲线,而后面的层学习特定于任务的模式,例如学习图片中是否有猫。这种方法的主要好处是——即使在深度学习模型上有适量的数据,你也可以获得很好的性能,这些模型通常非常渴求数据。

以下是关于 BERT 的一些重要细节:

  1. 双向训练:通过从两个方向看单词来进行联合训练——从左到右和从右到左以获得更好的上下文,其他语言模型通常通过只从一个方向看上下文来进行训练
  2. 预训练:在巨大的文本尸体(~3B 单词)上进行预训练,因此您只需要微调一个额外的输出层,这是很少的参数(使用您的训练数据),以便在各种任务上获得非常好的性能,如句子分类、问答系统、命名实体识别等,而不必在模型架构中进行太多特定于任务的更改。
  3. 训练目标:典型地,语言模型以无监督的方式被训练,目标是在给定单词之前的单词的情况下预测该单词。BERT 接受了两项任务的联合训练——在给定单词左右两边的单词的情况下预测一个单词(有一些关于屏蔽的细节以避免泄漏),以及在给定一个句子的情况下预测下一个句子。后者是不标准的,语言模型通常不直接捕捉句子之间的关系,但这样做有助于像问答系统这样的应用。
  4. 模型尺寸:BERT 论文的作者试验了各种尺寸的 BERT,最著名的是基本型(110M 参数)和大型型(340M 参数)。他们发现,越大越好,即使有相似的模型架构和小的特定任务训练数据,这在很大程度上是由于在巨大的语料库上进行的预训练。

自 2018 年 10 月 BERT 的原始论文以来,已经提出了许多变体和修改。其中最著名的是——脸书·艾的 RoBERTa 和 mBERT,CMU 研究人员的 XLNet 和开放人工智能的 GPT-2。

这就结束了我对 NLP 后期一些令人兴奋的事情的总结,很明显,这个领域发生了如此多的事情,而且速度如此之快。如今,人们可以不费吹灰之力做很多事情,这要归功于该领域的巨头们,他们完成了繁重的工作,并使之变得更加容易。

额外资源

  1. 优秀的可视化RNN注意
  2. 从零开始建造一台变压器
  3. 优秀的用于使用各种变压器架构

现代计算机视觉的最新进展

原文:https://towardsdatascience.com/recent-advances-in-modern-computer-vision-56801edab980?source=collection_archive---------9-----------------------

超越物体分类的计算机视觉

在过去的 50 年里,计算机已经学会了计数和分类,但直到现在还看不见东西。今天,截至 2019 年,计算机视觉领域正在迅速发展,拥有巨大的潜力来缓解全球范围内从医疗保健差距到移动限制的一切问题。

近年来,我们已经看到在 AlexNet 或类似的基于 CNN 的架构基础上构建的计算机视觉取得了巨大成功。的确,就学习方式而言,这个过程是模仿人脑的;称为神经元的学习单元网络学习如何将输入信号(如房屋的图片)转换为相应的输出信号,如标签“房屋”。关于这方面的更多细节,请看我之前的博客。

在过去的 2-3 年里,我们已经开始在基于深度学习的视觉任务中取得巨大成就,超越了分类。我在这篇博客中提到了其中几个重要的问题。

目标检测

在现有的几种方法中,有两类物体检测技术在现代计算机视觉领域已经流行了 3-4 年

两阶段:基于区域提案

美国有线电视新闻网,快速美国有线电视新闻网,快速美国有线电视新闻网[ 吉尔希克等人 CVPR 2014

  • 将整个图像处理到 conv5
  • 计算物体的可能位置有些是正确的,大多数是错误的
  • 给定单个位置,ROI 汇集模块提取固定长度特征

一阶段:YOLO,固态硬盘,视网膜网

目标检测在这里被框定为一个回归问题。单个神经网络用于直接预测类别和边界框锚,而不需要第二阶段的每个提议的分类操作。

  • 不要生成对象建议!
  • 通过设计考虑输出空间的微小子集;直接将这一小组盒子分类
  • 快速推理,适用于实时目标检测

YOLO 的局限性

  • 损失函数在小边界框和大边界框中处理错误是一样的。
  • 大盒子里的小错误通常是良性的,但小盒子里的小错误对 IOU 的影响要大得多。

YOLO v3:增量改进

约瑟夫·雷德蒙,阿里·法尔哈迪- 2018

  • 这是一个完全卷积的网络
  • 没有池化图层,跨距为 2 的卷积图层用于对图像进行缩减像素采样。
  • 较新的架构改进了剩余跳跃连接和上采样。
  • 最佳部分—在三种不同的比例下进行检测,这有助于解决检测小物体的问题。
  • 与先前层连接的上采样层有助于保留有助于检测小对象的细粒度特征。

单级检测和多级检测之间的选择-

Performance on MS-COCO

  • 更快的 R-CNN 速度较慢,但更准确
  • 固态硬盘和 YOLO 要快得多,但没有那么准确
  • 更大/更深的主干/特征提取器网络工作得更好

要进行完整的比较,请查看此— 现代卷积物体检测器的速度/精度权衡 ,Jonathan Huang 等人。艾尔。,2017 年

图象分割法

将像素分组为有意义的或感觉上相似的区域。Keymakr 等公司为视频和图像的复杂分割提供同类最佳的工具和全套服务解决方案。

Mask R-CNN, Kaming He et. al. 2017 [ICCV 2017 Best Paper Award-Marr Prize]

用于实例分割的 Mask-R-CNN

  • MaskRCNN 是对更快的 R-CNN 的修改
  • 它为更快的 R-CNN 网络增加了一个单独的屏蔽“头”
  • 掩码“头”只是一个小的全卷积网络,它为每个区域建议输出一个 m × m 掩码。
  • RoIAlign 层已被 RoI Pooling 取代。
  • 可以与不同的架构,也 ResNet
  • 在 Nvidia Tesla M40 GPU 上以每幅图像 195 毫秒的速度运行
  • 也可以用于人体姿态估计

Mask R-CNN 不仅提供了他们的模型优于所有先前模型的证据,而且还进行了各种消融实验,以显示 RoIAlign、分段去耦和全卷积掩模头各自单独提高了准确性。检查纸张了解详情。

深度跟踪

简单地说,在视频的连续帧中定位一个对象称为跟踪。

经典的对象跟踪是通过诸如密集光流的技术实现的:这些算法有助于估计视频帧中每个像素的运动矢量。
稀疏光流:这些算法,如 KLT 特征跟踪器,跟踪图像中几个特征点的位置。
卡尔曼滤波:一种非常流行的信号处理算法,用于根据先验运动信息预测运动物体的位置。
Meanshift 和 Camshift:这些是定位密度函数最大值的算法。它们也用于跟踪。

大多数目标跟踪方法采用“在线”学习。在线方法是昂贵的,必须做出简化的假设来提高效率。由于诸如 Harris 角、HOG 或 SIFT 之类的经典图像特征在不同的自然图像属性变化中都被破坏,例如,Harris 角对于图像的尺度不是不可知的,所以这种经典方法有时会失败。

但最近,已经有作品试图探索使用深度学习功能进行跟踪的就业。
因为效率是关键,所以策略是从大量带标签的离线视频中学习。

D. Held, S. Thrun, and S. Savarese “Learning to Track at 100 FPS with Deep Regression Networks”, ECCV 2016.

它是如何工作的-
两个假设:
1。网络将前一帧与当前帧进行比较,以找到当前帧中的目标对象

2。这个网络就像一个本地通用的“目标探测器”,简单地
定位最近的“目标”

MOTS: Multi-Object Tracking and Segmentation — Paul Voigtlaender et. al., CVPR 2019

生成对抗网络

仅仅过了 5 年,人工智能的发展令人难以置信。特别是 2019 年出现的 GAN 架构,如 Google 的 BigGAN 和 NVIDIA 的 StyleGAN 能够生成与真实图像精确区分的图像,因此 眼见为实。

A Style-Based Generator Architecture for Generative Adversarial Networks, NVIDIA, 2019

GAN 由两个连续的网络组成

  1. 发电机网络
  2. 鉴别器网络

学习-

  • 样本噪声矢量 z
  • 使用 z,生成器产生样本 x
  • 制作一个批次,其中一半样品是真实的,一半是生成的
  • 鉴别者需要预测什么是真的,什么是假的

特别是谈到 StyleGAN,它不是专注于创建更真实的图像,而是提高了 GANs 对生成的图像进行精细控制的能力。
不在架构和损失函数上发展。取而代之的是一套技术,可以与任何 GAN 一起使用,让您可以做各种很酷的事情,如混合图像,在多个层次上改变细节,并执行更高级版本的风格转换。
它采用现有技术,如自适应实例标准化、潜在向量映射网络和恒定学习输入。

Samples for StyleGAN

如果有人说上面的图片都不是真实的,不要怀疑。这些是 StyleGAN 生产的。

关键要点

随着对该技术的进一步研究和完善,计算机视觉的未来将会看到它执行更广泛的功能。计算机视觉技术不仅更容易训练,而且能够比现在更好地识别图像。这也可以与其他技术或其他人工智能子集结合使用,以构建更有效的应用程序。例如,图像字幕应用程序可以与自然语言处理和语音识别相结合,使视觉智能具有交互性。计算机视觉还将在人工通用智能(AGI)和超级智能的发展中发挥重要作用,使它们具有与人类视觉系统一样甚至更好的处理信息的能力。

阅读我的新文章关于压缩大型深度神经网络而不损害准确性。如果你想了解更多关于计算机视觉模型的知识,请深入到 Neptune.ai 博客的主题中

使用机器学习的衰退预测

原文:https://towardsdatascience.com/recession-prediction-using-machine-learning-de6eee16ca94?source=collection_archive---------4-----------------------

“次级贷款被遏制住了”——伯南克(2007 年 3 月)

  • 要通过电子邮件接收模型预测的定期更新,请点击此处
  • 衰退预测图目前由主持在这里
  • Python 脚本和文档可以在这里找到

内容

简单地

该项目提出了一种机器学习方法,用于预测美国 6 个月、12 个月和 24 个月的衰退发生率。预测模型使用了一些就业、通胀、利率和市场指标。

定义问题

简单来说:

人们可以通过在经济和市场数据中寻找线索来预测美国未来衰退的时间吗?

这个问题的几个有趣的属性包括:

  • 罕见事件预测:衰退很少发生。
  • 小数据集:因为我用的是经济数据(更新频率是几个月或者几个季度),所以我只会有几百个数据点可以处理。
  • 不平衡类样本:虽然不平衡并没有严重到足以使这个项目成为一个异常检测练习,但是我们仍然必须认识到样本类不平衡,特别是对于误差计算。

This is the most extreme example of class imbalance in the exploratory data set

  • 时间序列:典型的涉及财务数据的项目。这影响了如何进行交叉验证(不应该进行简单的 K 重验证)。

为什么需要解决这个问题?

随着当前牛市的老去,这是一个适时的问题。带着对衰退可能性的良好感觉:

  • 政策制定者可以制定对策来降低经济周期下滑的严重程度。
  • 市场参与者可以通过采取防御性投资策略来省钱。

主要假设

有两个主要的理论假设在起作用:

1)美国经济衰退表现出标记/早期预警信号。

以单个经济或市场数据序列的形式存在大量衰退“信号”。虽然单独来看,这些信号具有有限的信息价值,但是当它们组合在一起时可能变得更加有用。

2)未来的衰退将与历史衰退相似。

这种假设很不可靠,但可以通过选择在经济形势不断变化的情况下仍保持重要性的功能来缓解。例如,关注制造业数据在历史上可能是相关的,但随着世界走向数字化,这种相关性可能会降低。

别人试过什么?

模型基准测试/比较

理想情况下,我会将我的模型性能与上面的每个备选方案进行比较。目前,我不能这样做,原因如下:

  • 古根海姆模型:模型性能数据不公开发布。
  • 纽约联邦储备银行模型:经过仔细观察,他们的模型被用来回答问题“从现在起 X 个月后美国陷入衰退的概率是多少?”,而我的模型是为了回答问题“美国在未来 X 个月内陷入衰退的可能性有多大?”。更多细节,请参见下面的如何标记类输出部分。
  • 荷兰合作银行模型:同样的原因,我不能把我的模型性能与纽约联邦储备银行模型进行比较。此外,Rabobank 模型涵盖了 17 个月的时间段,而我的模型涵盖了 6 个月、12 个月和 24 个月的时间段。
  • 富国银行经济模型:模型性能数据未公开发布。

获取数据

获取数据时,我必须考虑一些事情:

  • 经济数据以不同的频率发布(每周、每月、每季度等)。).为了对数据点进行时间匹配,我满足于只使用每月采样的数据。因此,所有预测必须每月进行一次。这意味着我不得不放弃使用 GDP 等有价值的数据序列,因为它每季度发布一次。
  • 即使只使用月度数据,不同的数据在一个月内也有不同的发布日期。为了对此进行控制,所有预测都使用截至每月 7 日的最新可用数据进行。佛瑞德 API 有一个参数可以设置这个限制。编辑(2021 年 1 月):代码现在从每个月的 8 号开始提取数据,以适应更多的时序边缘情况。
  • 改变数据历史长度。一些数据是从 1900 年开始发布的,而另一些数据只追溯到几年前。这意味着我必须排除那些没有足够历史记录的潜在有用数据。
  • 谈到历史,我需要足够的数据来涵盖尽可能多的衰退。最终,完整的数据集包括了自 1955 年以来的 9 次衰退。
  • 经济数据经常被修正。但是弗雷德没有提供原始数字。它只提供了修正后的数据(不管这些修正是在事后进行的)。另一种选择是 ALFRED ,它显示特定“年份”日期的可用数字,但 ALFRED 的致命缺陷是它没有时间序列中每个日期的年份。通过坚持弗雷德最新修订的数据,我做出了一个隐含的假设,即修订是无偏的(即修订同样有可能推动原始数据上升或下降)。

数据源

出于实际原因,我使用了通过 FREDYahoo Finance 获得的公共领域数据。我没有使用隐藏在付费墙后面的潜在有用的数据,比如美国经济咨询局领先经济指数。

特征选择

功能选择的一些项目特定考虑因素:

  • 维度的诅咒。由于数据集如此之小(只有几百个数据点),最终模型中不能包含太多特征。否则,模型将无法推广到样本外数据。因此,必须根据每个特性提供的增值来仔细选择特性。
  • 领域知识是关键。由于基础过程是复杂的时间序列,自动特征选择方法具有过度拟合先前数据的高风险。因此,特征选择必须以对经济基本面的深刻理解为指导。

首先,先睹为快最终的功能列表。注意它有多小:

Note that only 6 features made it to the final list

我的特征选择过程的概要

  1. 定义执行探索性数据分析的数据集(1955 年 8 月至 1972 年 1 月)以确保与交叉验证期间没有交集。
  2. 根据经济/理论特征(领域知识),将潜在特征组织成桶。
  3. 仅使用探索性数据集绘制每个单独特征和每个输出类型(未来 6 个月、未来 12 个月、未来 24 个月)之间的成对相关性(不要提前查看!).
  4. 按顺序从一个要素桶移动到另一个要素桶,以便每个桶在最终数据集中至少有一个要素。对于平局决胜法,选择与已经“接受”到最终数据集中的要素相关性较低的要素。

事情是这样的:

首先,选择 1 个就业特征

  • 平民失业率——通常情况下,直到事情开始变糟,企业才会开始裁员。因此,失业通常滞后于衰退。
  • ****—这是一个更好的起点。由于对更具挑战性的经济环境的预期,企业可能会放缓招聘步伐。

我考虑了 3 个月的非农就业变化(%),12 个月的非农就业变化(%),以及 3 个月变化和 12 个月变化的差异。事实证明,3 个月的变化和 12 个月的变化之间的差异是探索性数据集中的最佳预测器(在 3 个候选人中),所以我选择它作为我的就业特征。

选择 1 个货币政策特征

设定联邦基金利率上限是美联储使用的主要货币工具之一。我考虑了实际联邦基金利率,以及联邦基金利率 12 个月的变化。联邦基金利率的 12 个月变化是两个候选中最好的,所以我选择它作为我的货币政策特征。

一些人认为,美联储可以通过设定联邦基金利率的界限来影响经济活动。

选择 1 个充气特性

通货膨胀与商业周期的关系更加复杂,因为它可能发生在快速扩张时期,也可能发生在收缩时期(滞胀)。但在通货膨胀和其他特征之间可能存在更高阶的效应,因此无论如何都值得包括在内。

消费者价格指数(CPI)是一个常用的通货膨胀指标。我考虑了 3 个月的 CPI 变动(%),12 个月的 CPI 变动(%),以及 3 个月变动和 12 个月变动的差异。所有候选人与就业特征和货币政策特征的相关性都很低,因此我选择了CPI 的 3 个月变化作为我的通胀特征,因为它与探索性数据集中的输出标签的相关性稍高。

挑选债券市场特征

我很想在这里使用某种类型的信用利差指数(投资级或高收益),但找不到数据可以追溯到 1955 年的信用利差指数。

因此,我开始关注国债利率。国债作为“无风险”资产类别,在全球资产配置框架中扮演着重要角色。国债利率的变化可能表明对经济机会和市场风险的预期发生了变化。

我不受 10 年期国债和 3 个月期国债之间利差的影响,因为收益率曲线斜率在提前预测衰退方面有着良好的历史记录。这种现象有几种理论解释。其中一个解释是,如果投资者认为“糟糕的时期”即将到来,他们就会将资金从高风险资产转移到长期美国国债,以锁定更长时间内的“无风险”回报。

在选择 10 年期与 3 个月期国债利差作为我的第一个指标后,我考虑了 3 个月期国债利率(12 个月的变化)、10 年期与 3 个月期国债利差的 12 个月的变化、10 年期国债利率(12 个月的变化)。我拒绝了前两个候选,因为它们与货币政策特征高度相关(90%)。我决定选择 10 年期国债利率(12 个月变化)作为我的第二个债券市场特征,因为它可以衡量长期增长预期。

选择一个股票市场特征

股票市场由未来预期的当前贴现驱动,因此被认为是领先指标。我考虑了 S & P 500 指数的 3 个月变化,S & P 500 指数的12 个月变化,以及 S & P 500 指数 3 个月变化和 12 个月变化之间的差异。**后两个候选指标都与产出标签高度相关,但我选择了标准普尔 500 指数&的 12 个月变化,因为它更容易解释。**

设计测试流程

在设计测试时,我必须考虑一些事情:

时间序列?那么没有 K 倍交叉验证

由于潜在的预测是一个时间序列,因此必须实时进行模型交叉验证和预测(即,仅使用每个时间点的可用数据!).k 倍交叉验证会违反这个原则。

衰退是如何定义的?

美国国家经济研究局(NBER) 商业周期测定委员会命名商业周期的“高峰”和“低谷”日期。我把 NBER 定义的波峰和波谷之间的几个月视为美国的衰退期。但是这里有一个巨大的问题:

NBER 宣称“高峰”和“低谷”的日期是在事实发生几个月后(有时是几年后)!

这意味着不能一次标记一个周期的输出!因此,要部署任何类型的衰退预测器,人们必须在每次正式的 NBER“低谷”公告时(每次衰退结束后的)重新训练模型。因此,在回溯测试中也必须采用同样的方法!

如果按照这种方法,有 5 个可能的测试运行(峰谷对),每个测试都有 NBER 公告日期:

Link: https://www.nber.org/cycles.html

对于每个测试,训练集从 1955 年 8 月开始,并且随着每个后续测试变得更长。类似地,每个交叉验证集从 1972 年 1开始,并且随着每个后续测试变得更长。

我如何标记类输出?

乍一看,这似乎很容易:衰退= 1,不衰退= 0。这是真的,但是还不够,因为它属于期望的模型范围。为了确定贴标签的过程,人们必须弄清楚要回答的问题。

难道是:

从现在起 X 个月后,美国陷入衰退的概率有多大?

如果想回答这个问题,就必须预测衰退的开始和结束。在衰退真正结束之前,模型预测的概率应该开始下降。不用说,这是一个非常英勇的任务。

另一个问题是:

美国在未来 X 个月内陷入衰退的可能性有多大?

这个问题预测了衰退的开始,但只是“预测”了衰退的结束。只有在衰退结束后,模型预测的概率才会开始下降。这个任务不太理想,但它仍然允许市场参与者为市场顶部做准备。

因此,所有处于衰退期的月份都将被标记为“1”。此外,X 个月(其中 X = 6 表示 6 个月前的预测值,X = 12 表示 12 个月前的预测值,等等。)也将获得“1”标签。所有其他月份将获得“0”的标签。

试验结果

我考虑了几个模型,并在每个模型上运行了前面提到的 5 个测试。如前所述,所有的交叉验证和预测都是实时进行的(没有作弊!),仅使用在每个历史时间点可用的数据。

考虑的模型

我考虑了以下 6 个单独的模型:K 近邻、正则化线性回归(弹性网)、朴素贝叶斯、支持向量机、高斯过程和 XGBoost。我通过交叉验证错误的网格搜索来调整超参数。如前所述:

对于每次测试,训练集从 1955 年 8 月开始,并随着每次后续测试而变长。类似地,每个交叉验证集从 1972 年 1开始,并且随着每个后续测试而变长。

此外,我测试了上述 6 个独立模型中的 2 个整体模型:

  • 一个大平均模型,对每个模型的预测进行同等加权
  • 一个加权平均模型,根据每个模型的交叉验证误差对每个模型的预测进行加权

我还通过在每个模型的交叉验证预测上训练线性回归模型来测试堆叠集合。这种方法产生了恶劣的结果。我直观的解释是,数据集太小,无法训练出强大的堆叠系综。根本没有足够的交叉验证预测可用!

选择误差度量

我应该使用哪种误差度量来量化预测误差?因为这是一个分类问题,所以我想到了准确性、预测/召回率和 F1 分数等指标。然而,这些指标都不太适合这个特定的问题,因为预测的输出类别(“0”或“1”)不像预测的** 出现在每个类别中的概率那样相关!**

相反,我使用加权的 对数损失 作为我的误差度量。它考虑了 class =“1”的预测概率与实际类值(“1”或“0”)之间的距离。Log-loss 为预测概率和实际类输出之间的较大差异分配了指数级更重的惩罚。

针对阶层失衡进行调整

****模型训练时:对于部分模型(弹性网、支持向量机、XGBoost),有内置参数设置类权重。我设置这些参数,使得两个类对模型训练的损失函数具有相同的影响。

****在模型交叉验证期间:使用 scikit-learn 的对数损失实现,我可以调整样本类的不平衡(使用“sample_weight”参数),这样两个类对模型交叉验证的总体对数损失值具有相同的影响。

预测平滑

原始概率预测往往不稳定,就像这样:

Predictions before smoothing

因此,我对原始概率预测应用了指数平滑法。我选择了加权因子(用于指数平滑器),使得每个预测的半衰期为 3 个周期:

Predictions after exponential smoothing

最终模型

我最终选择了支持向量机作为最终部署模型。8 个模型(6 个独立模型和 2 个整体)在 3 个时间范围内的对数损失如下:

Remember: the smaller the log-loss, the better

敏锐的读者可能会注意到,支持向量机** (SVM)并没有在所有 3 个时间框架内取得最好的成绩。**

为什么我没有选择“表现最佳”的模式?

一个字:讲故事。

具体来说,观察 6 个月时间框架内弹性网、加权平均和支持向量机预测的并排比较:

****弹性净值和加权平均模型比 SVM 得分更高(基于加权对数损失),因为它们通常预测更高的衰退概率!本质上,它们的“假阳性”倾向高于 SVM,而“假阴性”倾向略低于 SVM。

****这种不对称是不选择“最佳表现”模式的关键。即使在长期经济增长期间,表明近期衰退概率较高的模型(弹性网、加权平均)也更容易被怀疑为“危言耸听”,并且更难销售。另一方面,一个模型(SVM)表明,在繁荣时期衰退几率接近 0%,但在衰退时期也会飙升至高水平(尽管没有“危言耸听”的模型那么高),这将更难让人怀疑。

所以我选择了 SVM 模型,不是因为从统计学的角度来看它是“表现最好的”模型,而是因为它讲述了一个更符合人类对经济状况认知的故事!

图表显示了 SVM 模型的预测,每月更新一次。

要通过电子邮件接收模型预测的定期更新,请点击此处

特别感谢 Jason Brownlee 关于应用机器学习过程的 文章

数据分布可视化的方法

原文:https://towardsdatascience.com/recipes-for-the-visualizations-of-data-distributions-a1527a0faf77?source=collection_archive---------18-----------------------

可视化

直方图、KDE 图、箱形图和小提琴图等

Photo by Toa Heftiba on Unsplash

作为一名初露头角的数据科学家,我意识到,在项目启动期间,编写第一段代码总是为了了解数据集中一个或几个变量的分布。可视化变量的分布对于立即掌握有价值的参数非常重要,如频率、峰值、偏斜度、中心、模态以及变量和异常值在数据范围内的表现。

带着分享知识的兴奋,我写了这篇关于单变量(单变量)分布的总结解释的博文,分享我从几篇文章和文档中得出的推论。我将提供绘制分布函数的步骤,而不深入理论,并保持我的帖子简单。

我将首先解释使用 Matplotlib 和 Seaborn 库用 Python 可视化数据分布的函数。可视化背后的代码可以在这个笔记本中找到。

为了便于说明,我使用了 Gapminder 寿命预期数据,清理后的版本可以在这个 GitHub 中找到。

数据集显示了 142 个国家在 1952 年至 2007 年间的出生时预期寿命、人口和人均 GDP。我将绘制出生时的预期寿命,使用:

  1. 柱状图
  2. 核密度估计和分布图
  3. 箱形图
  4. 博兴图
  5. 小提琴情节

1)直方图

直方图是显示数据分布的最简单方式。下面是制作直方图的方法:

  • 创建桶(箱)通过将数据区域划分成相等的大小,数据中子集的数量就是箱的数量。
  • 记录落入每个箱中的数据点的计数。
  • 在 x 轴上并排想象每个桶。
  • 计数值将显示在 y 轴上,显示每个箱子中有多少物品。

你有了一个全新的直方图!

这是最简单、最直观的方法。然而,一个缺点是决定必要的箱的数量。

在这个图中,我确定了 25 个 bin,这在使用 Matplotlib hist 函数中的bins 参数后似乎是最佳的。

# set the histogram
plt.hist(df.life_expectancy, 
         range=(df.life_expectancy.min(),
                df.life_expectancy.max()+1), 
         bins=25, 
         alpha=0.5) 
# set title and labels
plt.xlabel(“Life Expectancy”) 
plt.ylabel(“Count”) 
plt.title(“Histogram of Life Expectancy between 1952 and 2007 in the World”) 
plt.show()

Histogram with 25 bins

不同数量的容器会显著改变数据分布的外观。这是同样的数据分布,有 5 个箱,看起来像一个完全不同的数据集,对吗?

Histogram with 5 bins

如果您不想被箱数确定所困扰,那么让我们跳到核密度估计函数和分布图。

2)核密度估计和分布图

核密度估计 (KDE)图通过平滑直方图将您从决定面元大小的麻烦中解救出来。遵循以下逻辑创建 KDE 图:

  • 围绕每个数据点绘制一条高斯(正态)曲线
  • 将曲线相加,在每个点创建一个密度。
  • 归一化最终曲线,使其下方的面积等于 1,从而得到概率密度函数。以下是这 3 个步骤的直观示例:

Image Source: Histograms and Kernel Density Estimations

  • 你会发现 x 轴上的数据范围和 y 轴上的随机变量的概率密度函数。由威尔·科尔森在本中定义的概率密度函数如下:

您可能认为密度图上的 y 轴只是不同类别之间的相对比较值。

幸运的是,您不必记住并手动应用所有这些步骤。Seaborn 的 KDE 绘图函数为您完成所有这些步骤,只需将您的数据框或 Numpy 数组的列传递给它即可!

# set KDE plot, title and labels
ax = sns.kdeplot(df.life_expectancy, shade=True, color=”b”) 
plt.title(“KDE Plot of Life Expectancy between 1952 and 2007 in the World”) 
plt.ylabel(“Density”)

如果你想结合直方图和 KDE 图,Seaborn 有另一个很酷的方法在一个图形中显示直方图和 KDE 图:分布图,它绘制 KDE 图,通过改变函数中的hist 参数可以灵活地打开和关闭直方图。

# set distribution plot, title and labels
ax = sns.distplot(df.life_expectancy, hist=True, color=”b”)
plt.title(“Distribution Plot of Life Expectancy between 1952 and 2007 in the World”) 
plt.ylabel(“Density”)

Distribution plot with histogram and Kernel Density Estimation function

KDE 图也能够显示不同类别之间的分布:

# create list of continents 
continents = df[‘continent’].value_counts().index.tolist() # set kde plot for each continent 
for c in continents: 
   subset = df[df[‘continent’] == c]
   sns.kdeplot(subset[“life_expectancy”], label=c, linewidth=2) # set title, x and y labels 
plt.title(“KDE Plot of Life Expectancy Among Continents Between 1952 and 2007”) 
plt.ylabel(“Density”) 
plt.xlabel(“Life Expectancy”)

尽管与直方图相比,KDE 图或分布图需要更多的计算和数学,但通过观察连续的线,更容易理解分布的形态、对称性、偏斜度和中心。一个缺点可能是,缺少关于汇总统计的信息。

如果您希望直观地提供分布的汇总统计数据,那么让我们转到箱线图。

3)箱线图

箱线图显示了包含五个数字的汇总统计数据的数据分布(最小值、第一个四分位数 Q1、第二个四分位数中值、第三个四分位数 Q3、最大值)。下面是绘制它们的步骤:

  • 对数据进行排序,以确定最小值、四分位数(第一、第二和第三)和最大值。
  • 在第一个四分位数和第三个四分位数之间画一个方框,然后在对应于中间值的方框中画一条垂直线。
  • 在盒子外面画一条水平线,把盒子一分为二,把最小值和最大值放在边上。这些线条将成为你的胡须。
  • 胡须的末端等于数据的最小值和最大值,如果你看到任何数据,放在一边的小菱形被解释为“异常值”。

手动创建方框图的步骤很简单,但我更喜欢从 Seaborn 方框图功能中获得一些支持。

# set the box plot and title 
sns.boxplot(x=”life_expectancy”, data=df, palette=”Set3") plt.title(“Boxplot of Life Expectancy between 1952 and 2007 in the World”)

有几种不同的方法来计算胡须的长度,Seaborn box plot 函数默认从第一个和第三个四分位数延伸 1.5 倍的四分位数间距 (IQR)来确定胡须。因此,任何大于 Q3+(1.5IQR)或小于 Q1-(1.5IQR)的数据点都将被视为异常值。您可以通过调整whis 参数来改变胡须的计算。

像 KDE 图一样,箱线图也适合可视化类别间的分布:

# set the box plot with the ordered continents and title sns.boxplot(x=”continent”, y=”life_expectancy”, data=df,
            palette=”Set3", 
            order=[“Africa”, “Asia”, “Americas”, “Europe”,
                   “Oceania”]) 
plt.title(“Boxplot of Life Expectancy Among Continents Between 1952 and 2007”)

盒状图提供了统计数据的故事,一半的数据在那里,通过观察盒状和须状提供了整个范围的数据。另一方面,你不知道盒子外面的数据的故事。这就是为什么一些科学家发表了一篇关于 boxen 图的论文,被称为扩展盒图。

4)博兴图

Boxen 图,或字母值图或扩展盒图,可能是数据分布可视化中最少使用的方法,但它们传达了大型数据集的更多信息。

要创建一个博森情节,我们先来了解一下什么是字母值汇总。字母值汇总是关于连续确定一个排序数据的中间值。

首先,确定所有数据的中间值,并创建两个切片。然后,确定这两个切片的中值,并在达到停止标准或不再有数据需要分离时重复这个过程。

确定的第一个中间值是中值。在第二次迭代中确定的中间值称为四分之一,在第三次迭代中确定的中间值称为八分之一。

现在让我们画一个方框图,并在方框图之外可视化字母值摘要,而不是胡须。换句话说,绘制一个具有对应于切片中间值(八分之一、十六分之一等等)的延长盒边的盒图..)

# set boxen plot and title 
sns.boxenplot(x=”life_expectancy”, data=df,palette=”Set3") plt.title(“Boxenplot of Life Expectancy Among Continents Between 1952 and 2007”)

它们在讲述不同类别的数据故事方面也很有效:

# set boxen plot with ordered continents and title sns.boxenplot(x=”continent”, y=”life_expectancy”, data=df,
              palette=”Set3", 
              order=[“Africa”, “Asia”, “Americas”, “Europe”,
                     “Oceania”]) 
plt.title(“Boxenplot of Life Expectancy Among Continents Between 1952 and 2007”)

Boxen 图的出现是为了更有效地可视化较大的数据集,它显示了数据在主框之外的分布情况,并更加强调异常值,因为异常值和 IQR 之外的数据在较大的数据集中更为重要。

有两个视角提供了关于数据分布的线索,数据分布的形状和汇总统计。要同时从两个角度解释一个分布,我们先来学煮一些小提琴的剧情。

5)小提琴情节

小提琴情节是盒子情节和 KDE 情节的完美结合。他们提供的汇总统计数据内部是箱形图,分布形状的侧面是 KDE 图。

这是我最喜欢的图,因为数据表达了所有的细节。你还记得我们之前绘制的预期寿命分布图和汇总统计数据吗?Seaborn violin 的剧情功能现在将为我们融合它。

瞧啊!

# set violin plot and title 
sns.violinplot(x=”life_expectancy”, data=df, palette=”Set3") plt.title(“Violinplot of Life Expectancy between 1952 and 2007 in the World”)

你可以通过观察边上的分布来观察 70 左右的数据峰值,通过注意里面细长的方框来观察 50 到 70 之间聚集的一半数据点。

这些漂亮的小提琴可以用来可视化分类数据,如果您愿意,可以通过更改inner 参数用点、虚线或线条表示汇总统计数据。

Violin plots with inner set to quartile, point and stick respectively

好处是显而易见的:可视化的形状分布和汇总统计同时进行!

小提琴剧情加分:通过设置scale 参数进行计数,还可以显示你在每个类别中有多少数据点,从而强调每个类别的重要性。当我改变scale的时候,非洲和亚洲扩张了,大洋洲收缩了,结论是大洋洲的数据点较少,而非洲和亚洲的数据点较多。

# set the violin plot with different scale, inner parameter and title 
sns.violinplot(x=”continent”, y=”life_expectancy”, data=df,
               palette=”Set3", 
               order=[“Africa”, “Asia”, “Americas”, “Europe”,
                      “Oceania”], 
               inner=None, scale=”count”) 
plt.title(“Violinplot of Life Expectancy Among Continents Between 1952 and 2007”)

结论

所以,这些关于可视化分布的方法解释了每个图背后的核心思想。有很多选项可以显示单变量或单变量分布。

直方图、KDE 图和分布图很好地解释了数据形态。此外,分布图可以结合直方图和 KDE 图。

箱线图和 boxen 图最适合交流汇总统计数据,boxen 图更适合处理大型数据集,而 violin 图则完全胜任。

他们都是有效的沟通者,并且每个都可以用 Python 中的 Seaborn 库快速构建。您的可视化选择取决于您的项目(数据集)和您想要传递给观众的信息。如果你对这篇文章感到兴奋并想了解更多,你可以查看一下 SeabornMatplotlib 文档。

最后但同样重要的是,这是我对数据科学的第一篇贡献,我希望你喜欢阅读!我感谢您的建设性反馈,并希望在回复中或在 Twitter 上听到您对这篇博文的看法。

推荐系统第 1 部分——使用协同过滤和混合协同——在 Instacart 数据集上使用 LightFM 库的零售内容

原文:https://towardsdatascience.com/recommendation-system-part-1-use-of-collaborative-filtering-and-hybrid-collaborative-content-in-6137ba64ad58?source=collection_archive---------9-----------------------

介绍

Recommender systems shown in Amazon

声明:我在正文和代码中交替提到了项目产品。他们俩是一样的。

当你打开亚马逊等一些在线市场时,你会发现一些推荐,如经常一起购买,买了这个的客户也买了这个,类似的商品,等等。你会在网站上更容易找到你想要的东西。目前,推荐系统广泛用于在线市场,一些零售商正在使用这项技术来改善用户体验、用户保留率和转化率。

在本教程中,我将向您展示如何使用 Instacart 数据集创建一个模拟真实业务问题的产品推荐,适用于“交互”数据丰富的热启动问题。数据集可以在 Kaggle 上找到。我们还希望提供纯协作过滤方法与混合协作-基于内容的方法之间的比较,以解决我们的热启动问题。

在讨论细节之前,我们需要使用 pip 安装 LightFM 库

pip install lightfm

安装完成后,您可以导入所有必要的东西,包括交叉验证术语和指标

importing libraries including standard pandas, numpy, and the lightfm’s model and cross-validation stacks

如何为 LightFM 库准备数据

在使用 LightFM 库时,我们需要一个稀疏矩阵,称为用户-项目交互矩阵。对于混合协作内容推荐的情况,我们还可以考虑项目-特征矩阵:

  1. 用户-物品互动矩阵定义了用户(客户)与物品(产品)之间的互动,这可以显示为客户投票的电影评级。然而,在零售案例中,我们无法从历史数据中获得明确的评级。在这种情况下,我隐含地将“购买数量”作为评级考虑在内。如果顾客 A 购买了产品 B 10 次,那么我们可以说顾客 A 给产品 B 的评分是 10。您还可以考虑二进制评分,其中 1 表示客户 A 购买过产品 b,0 表示从未购买过产品 b。用户-项目交互矩阵表示协同过滤对模型的贡献。
  2. 物品-特征交互矩阵定义物品的特征。项目到功能可以表示为产品到它的元数据,例如产品的类别、子类别,甚至任何信息。使用 Instacart 的数据集,我会使用“过道”和“部门”作为产品的特征。如果产品 A 位于通道 B,那么我们可以说通道 B 中产品 A 的矩阵元素为 1,否则为 0。这个矩阵可以向模型添加基于内容的贡献。

User-item interaction matrix. User Id represents the customers and product rated represents how many times a specific user id bought the products. The matrix is sparse.

item-feature matrix. Item id represents the products and features refer to the metadata embedded to an item such as category, sub-category, and so on.

使用 Instacart 零售数据集构建矩阵

我们将从 Instacart 市场购物篮分析 Kaggle 竞争(https://www . ka ggle . com/c/insta cart-Market-Basket-Analysis/data)中创建两个矩阵,并形成适用于 LightFM 库的数据集。在此之前,我们需要从 Kaggle 下载所需的数据集,并为我们的推荐系统读取必要的数据集

数据集的显示如下所示:

datasets preview

我们还需要删除aislesdepartments中带有aisle == missingaisle == otherdepartment == missingdepartment == other的行:

  1. 构造一个用户-项目交互 矩阵。我们需要考虑到,LightFM 库只能读取一个稀疏的 coo 矩阵,可以使用scipy.sparse中的coo_matrix来构造,其中我们需要将item_id转换成integer index。因此,我构建了用户-项目交互矩阵,将user_id转换为表示矩阵的行的索引,将转换为列的索引。另外,不要忘记为 user_id 到 index、index 到 user_id、item_id 到 index 和 index 到 item_id 创建字典映射。
  2. 构建一个项目-特征矩阵。用户-项目交互矩阵也是同样的情况,通过将项目/产品功能映射到索引中,我们可以尝试将项目/产品 和功能交互转换成稀疏矩阵。

下面显示了矩阵生成器和一些用于索引等的辅助函数

将所有usersitemsfeatures分配到列表中

显示在usersitemsfeatures列表的下方

displaying users, items (products), and features (departments and aisles)

LightFM 库不能读取未索引的对象,因此我们需要为usersitemsfeatures创建映射到它们相应的索引中。

在生成交互矩阵之前,我将 t rain、test 和 product_features 数据准备成它们相应的名称

Showing the table of users with their corresponding purchased products/items. I also regard count as the ratings of the products/items or features

将每个表转换成交互矩阵

导致

Sparse matrices representing interactions of users to products/items and products to features. The non-zero elements consist of product count as the number of products a user has bought

模型选择和交叉验证

在这个问题中,我将通过测量测试数据集的 AUC(范围从 0 到 1)来尝试使用 LightFM 库进行交叉验证。我使用了“WARP”损失函数,它通常在 LightFM 库中提供最佳性能选项。通过使用 Instacart 数据集,我将prior数据集作为training dataset,将train数据集作为testing dataset.,通过拟合training dataset并在test dataset上测试,我们可以尝试评估测试数据集的 AUC 分数。

下面我们尝试使用 LightFM 库对纯协同过滤方法进行交叉验证

上面的输出是

time taken = 118.23 seconds
time taken = 1088.21 seconds
average AUC without adding item-feature interaction = 0.95

从上面的结果中,我们知道,使用我的 8 GB RAM 笔记本电脑,培训大约需要 1 分钟,验证需要 10 分钟。翘曲损失功能可以很慢,但性能非常好。AUC = 0.95 很神奇的告诉我们,Instacart 数据集是一个热启动问题,交易数据丰富。

混合协作——基于内容的,通过添加产品/项目和功能交互,代码如下

上面的输出是

time taken = 154.22 seconds
time taken = 1709.78 seconds
average AUC with adding item-feature interaction = 0.80

从混合情况下记录的 AUC 来看,AUC 比纯协作情况下的 AUC 差。这是一个具有丰富交易数据的热启动问题,纯协作过滤将提供更好的推荐。

请求产品/项目推荐

我们需要通过下面的函数将训练和测试数据集合并成一个

并创建用户到产品的交互矩阵

导致

回来了

time taken = 68.50 seconds

并且询问推荐的类对象由下式给出

使用最终模型调用建议

为用户 2 和用户 10 打印了一些建议

User 2
     Known positives:
                  Organic Turkey Burgers
                  Wild Albacore Tuna No Salt Added
                  Cherry Pomegranate Greek Yogurt
     Recommended:
                  Organic Garlic
                  Organic Baby Spinach
                  Organic Hass AvocadoUser 10
     Known positives:
                  Cantaloupe
                  Parsley, Italian (Flat), New England Grown
                  Seedless Red Grapes
     Recommended:
                  Organic Baby Spinach
                  Organic Strawberries
                  Bag of Organic Bananas

结论

LightFM library 可以为交易数据提供混合协作和基于内容的推荐系统。然而,对于热启动问题,纯协同过滤提供了更好的性能。

Github 上完整的 Jupyter 笔记本

https://github . com/danirisdiandita/light FM _ re commendation/blob/master/re commendation _ system _ part _ 01 . ipynb

文献学

[1] LightFM 文档—https://lyst.github.io/lightfm/docs/home.html

[2] Instacart Kaggle 比赛—【https://www.kaggle.com/c/instacart-market-basket-analysis

[2]推荐系统—学习数据科学的 Python # 3【https://www.youtube.com/watch?v=9gBC9R-msAk

推荐系统系列第 1 部分:构建推荐系统的执行指南

原文:https://towardsdatascience.com/recommendation-system-series-part-1-an-executive-guide-to-building-recommendation-system-608f83e2630a?source=collection_archive---------2-----------------------

RecSys 系列

学术界和工业界的推荐系统

更新: 本文是我探索学术界和工业界推荐系统系列文章的一部分。查看完整系列: 第一部分 第二部分 第三部分 第四部分 第五部分

简介

推荐系统的建立是为了预测用户可能喜欢什么,尤其是当有很多选择的时候。他们可以明确地向用户提供这些推荐(例如,亚马逊或网飞,经典的例子),或者他们可能在幕后工作,选择哪些内容浮出水面,而不给用户选择的机会。

不管是哪种方式,“为什么”都很清楚:它们对某些类型的企业至关重要,因为它们可以让用户接触到他们原本可能不会发现的内容,或者让用户保持更长时间的参与。虽然构建一个简单的推荐系统可能非常简单,但真正的挑战是实际构建一个有效的系统,并且企业可以从其输出中看到真正的提升和价值。

可以使用各种技术来构建推荐系统,从简单的(例如,仅基于来自同一用户的其他评级项目)到极其复杂的。复杂的推荐系统利用各种不同的数据源(一个挑战是使用非结构化数据,特别是图像作为输入)和机器学习(包括深度学习)技术。因此,它们非常适合人工智能领域,尤其是无监督学习;随着用户继续消费内容和提供更多数据,这些系统可以被构建来提供越来越好的推荐。

在这篇文章和接下来的文章中,我将介绍推荐系统的创建和训练,因为我目前正在做这个主题的硕士论文。第 1 部分提供了推荐系统的高层次概述,它们是如何构建的,以及它们如何用于改善跨行业的业务。

推荐系统的 2 种类型

有两种主要类型的推荐系统,每种都有不同的子类型。根据目标、受众、平台和您的建议,这些不同的方法可以单独使用,但通常情况下,最好的结果是将它们结合使用:

1 —协同过滤

它主要基于其他人(而不仅仅是被推荐的用户)的输入或动作来做出推荐。

这种类型的推荐系统的变体包括:

  • 通过用户相似性:这种策略包括通过比较用户的活动来创建用户组,并提供在该组其他成员中受欢迎的推荐。在拥有强大而多样的受众的网站上,为信息匮乏的用户快速提供推荐是很有用的。
  • 通过关联:这个是上面提到的一个的特定类型,也称为“看了 X 也看了 y 的用户”,实现这种类型的推荐系统就是查看购买序列或购买组,并显示类似的内容。这种策略对于捕捉与自然补充内容相关的推荐以及在用户生活中的某个时刻是有用的。

2 —基于内容的

基于内容的系统根据用户的购买或消费历史提出建议,通常用户采取的行动(输入)越多,系统就越准确。

更具体类型的基于内容的推荐系统包括:

  • 按内容相似度:作为最基本的基于内容的推荐系统,这种策略包括根据元数据推荐相近的内容。这种方法对于包含大量丰富元数据的目录以及与目录中的产品数量相比流量较低的目录很有意义。
  • 通过潜在因素建模:比内容相似性方法更进一步,这种策略的关键是通过假设以前的选择是某些品味或爱好的指示来推断个人的内在兴趣。以前的策略基于显式的、手动填充的目录元数据,而这种策略依赖于发现隐含的关系。这是通过使用用户的较大交互(例如,观看的电影、购买的物品等)的历史来完成的。)来学习这些口味。
  • 通过主题建模:这是潜在因素建模策略的一种变体,通过分析非结构化文本来检测感兴趣的特定主题,而不是考虑用户的更大动作,来推断用户的兴趣。这对于具有丰富但非结构化的文本信息的用例(比如新闻文章)来说尤其有趣。
  • 通过流行内容推广:这包括根据产品的内在特性突出产品推荐,这些特性可能会引起广泛受众的兴趣:价格、功能、流行度等。该策略还可以考虑内容的新鲜度或年龄,从而能够使用最流行的内容进行推荐。这通常用于新内容占大多数的情况。

建立推荐系统的 6 个步骤

如果您遵循从原始数据到预测的基本步骤,构建一个成功且健壮的推荐系统会相对简单。也就是说,当涉及到推荐系统时,需要考虑一些经常被忽视的细节,为了最有效的过程和最佳的预测,这些细节是值得介绍(或重申)的。

本节将介绍在构建推荐系统的背景下完成数据项目的六个基本步骤。

1 —了解业务

建立推荐系统的第一步是定义项目的目标和参数,这非常简单和关键,但经常被忽视。这肯定会涉及数据团队和业务团队(可能是产品经理、运营团队,甚至是合作伙伴或广告团队,取决于您的产品)之间的讨论和输入。

为了更深入地了解业务需求并在这些团队之间展开讨论,以下是一些需要考虑的特定主题:

  • 项目的最终目标是什么?建立推荐系统的目的是直接增加销售额/实现更高的平均购物篮大小/减少浏览时间并使购买更快发生/减少未消费内容的长尾/提高用户参与产品的时间吗?
  • 推荐信真的有必要吗?这可能是一个显而易见的问题,但由于它们的构建和维护成本高昂,因此值得一问。企业是否可以通过静态内容集(如员工/编辑选择或最受欢迎的内容)来推动发现,从而实现其最终目标?
  • 什么时候会出现推荐?如果推荐在多个地方都有意义(例如,在第一次访问应用程序或网站时,以及在购买或消费内容后,在主屏幕上),是否会在两个地方使用相同的系统,或者每个地方的参数和需求不同?
  • 有哪些数据可以作为推荐的依据?在推荐时,登录用户(在这种情况下可能有更多可用数据)与匿名用户(这可能会使构建推荐系统变得复杂)的比例大约是多少?
  • 是否有必须首先进行的产品变更?如果团队希望使用更强大的数据来构建推荐系统,是否必须首先进行产品更改,以便更早地识别用户(例如,邀请他们更快地登录),如果是,从业务角度来看,这些更改是否合理?
  • 是否应该对所有内容或产品一视同仁?也就是说,除了有机推荐之外,业务团队是否希望(或必须)推广特定的产品或内容?
  • 如何细分口味相近的用户?换句话说,如果采用基于用户相似性的模型,你将如何决定什么使用户相似?

2 —获取数据

最好的推荐系统使用万亿字节的数据。所以当涉及到为你的推荐系统收集数据时,一般来说,越多越好。如果当你试图为用户做推荐时,用户是未知的,这可能会很困难,例如,他们没有登录,或者更具挑战性的是,他们是全新的。如果你的业务中大多数用户都是未知的,你可能需要依赖外部数据源或与偏好没有明确联系的一般数据,如人口统计、浏览历史等。

当谈到用户偏好时,有两种反馈:显式和隐式。

  • 明确的用户反馈是任何需要用户努力的事情,比如留下一个评论/评级或者发起一个投诉或者产品退货(通常来自客户关系管理、CRM、数据)。
  • 相比之下,隐式用户反馈是可以收集的关于用户偏好的信息,而无需他们实际指定那些偏好。例如,过去的购买历史、查看某些优惠、产品或内容所花费的时间、来自社交网络的数据等。

好的推荐系统通常采用这些反馈类型的组合,因为它们各有优缺点。

  • 显式反馈可以非常清楚:用户已经如实陈述了他们的偏好、喜欢或不喜欢。但出于同样的原因,它天生就有偏见;用户不知道自己不知道什么(换句话说,他可能喜欢某样东西,但从未尝试过,因此不会将其列为偏好,也不会正常地与该类型的项目或内容进行交互)。
  • 相比之下,隐式反馈则相反——它可以揭示用户没有——或者不会——在个人资料中承认的偏好(或者他们的个人资料信息可能已经过时)。另一方面,隐性反馈可能更难理解;仅仅因为一个用户在一个给定的项目上花了时间并不意味着他(她)们喜欢它,所以最好依靠隐含信号的组合来确定偏好。

3 —探索、清理和扩充数据

尤其是在为推荐系统探索和清理数据时,要考虑的一件事是改变用户的口味。根据你的推荐,旧的评论,行动等。,可能不是最相关的推荐依据。考虑只查看更有可能代表用户当前口味的特征,并删除可能不再相关的旧数据,或者添加权重因子,以给予最近的动作比旧动作更大的重要性。

推荐系统的数据集很难处理,因为它们通常是高维的,但同时,许多特征没有任何值也很常见,这使得聚类和离群点检测很困难。

4 —预测排名

考虑到前面步骤中所做的工作,您可能已经构建了一个推荐系统,只需按用户对这些分数进行排名,您就可以推荐产品了。这种策略没有使用机器学习或预测元素,但这完全没问题。对于某些用例,这已经足够了。

但是,如果您确实想构建更复杂的东西,在用户使用推荐的内容之后,有许多子任务可以完成,这些内容可以用来进一步完善系统。有几种方法可以利用混合方法来尝试最高质量的推荐:

  • 并排展示来自不同类型系统的建议。
  • 并行维护多个算法,其中哪个算法优于另一个算法的决定本身受制于机器学习(例如,多臂 bandit)。
  • 使用纯机器学习方法来组合多个推荐系统(逻辑回归或其他加权回归方法)。一个具体的例子是使用不同技术的两个(或更多)推荐的加权平均值。

也有可能不同的模型在产品或网站的不同部分会工作得更好。例如,用户尚未采取行动的主页与用户已经以某种方式点击或消费内容之后的主页。

5 —可视化数据

在推荐系统的环境中,可视化有两个主要目的:

  1. 当仍处于探索阶段时,可视化可以帮助揭示关于数据集的事情,或者给出关于模型性能的反馈,否则很难看到。
  2. 将推荐系统放置到位后,可视化可以帮助向业务或产品团队传达有用的信息(例如,哪些内容做得很好但没有被发现,用户口味、内容或通常一起消费的产品之间的相似性等)。)以便他们可以根据这些信息做出更改或决策。

可视化这种类型的数据的主要问题是存在的数据量,这使得很难以有意义的方式消除干扰。但同样,良好的可视化将有助于从大量数据中理解意义,否则很难从中获得有意义的见解。

6 —迭代和部署模型

在开发环境或沙盒中工作的推荐系统没有任何好处。这一切都是为了将系统投入生产,这样您就可以开始看到对您在开始时制定的业务目标的影响。

此外,请记住,你拥有的用于推荐系统的数据越多,它就会变得越好。因此,对于这种类型的数据项目来说,评估性能并继续进行微调是至关重要的,比如添加新的数据源,看看它们是否有积极的影响。

事实上,通过定期监控其性能来确保您的推荐系统能够适应和发展是该过程中最重要的部分之一——一个不能随着时间的推移根据品味或新数据进行适当调整的推荐系统可能不会帮助您最终实现您最初的项目目标,即使该系统最初表现良好。建立一个反馈回路来了解用户是否关心推荐将会很有帮助,并为以后的改进和决策提供一个很好的衡量标准。

如果推荐是你业务的核心,那么不断尝试新事物和发展你创建的初始模型将是一项持续的任务;推荐系统不是你可以创建并抛弃的东西。

挑战

创建一个推荐系统是很重要的,这个系统会随着你拥有的数据量而扩展。如果它是为有限的数据集构建的,并且该数据集不断增长,计算成本将呈指数级增长,系统将无法处理如此大量的数据。为了避免以后不得不重新构建您的推荐系统,您必须从一开始就确保它是为扩展预期的数据量而构建的。

也有可能在花费时间、精力和资源建立推荐系统之后(甚至在拥有足够的数据和良好的初步结果之后),推荐系统只给出非常明显的推荐。避免这个陷阱的关键实际上可以追溯到七个步骤中的第一步:了解业务需求。如果没有足够的内容长尾或者不需要这个系统,也许你需要重新考虑是否需要首先建立一个推荐系统。

最后,人们的口味不会随着时间的推移而一成不变,如果一个推荐系统没有考虑这一事实,它可能永远不会像它应该的那样准确。同样,建立一个不会随着时间的推移而变得更好的推荐系统也存在风险。随着用户不断消费内容,更多的数据可用,你的推荐系统应该更多地了解用户,适应他们的口味。一个不够灵活的推荐系统很快就会过时,达不到它的目的。

未来工作

基本的推荐系统已经存在了一段时间,尽管它们继续变得更加复杂,并被零售和内容巨头完善。但是接下来呢?如果企业希望开发一个真正前沿的系统,他们应该考虑的最新趋势和发展是什么?

环境感知推荐系统代表了一个新兴的实验和研究领域,旨在根据用户在特定时刻的环境提供更加精确的内容。例如,用户是在家还是在路上?使用更大还是更小的屏幕?现在是早上还是晚上?给定关于特定用户的可用数据,上下文感知系统可能能够提供用户在那些场景中更可能采纳的建议。

深度学习已经被世界上一些最大、最强大的推荐系统所使用(比如 YouTube 和 Spotify)。但是,随着数据量继续飙升,越来越多的企业发现自己面对庞大的内容语料库,难以扩展,深度学习将成为事实上的方法,不仅适用于推荐系统,也适用于所有学习问题。

解决冷启动问题也是前沿研究人员开始关注的事情,以便可以对数据很少的项目提出建议。这是一个非常重要的领域,对于有大量内容周转的企业来说,这是一个非常重要的研究领域,这样他们就可以成功地推出销售良好的商品(甚至在他们知道该商品的表现之前)。

结论

推荐系统是向用户展示他们可能没有发现的内容的有效方式,这反过来可以推进更大的商业目标,如增加销售、广告收入或用户参与。但是推荐系统的成功有几个关键点。也就是说,推荐系统首先应该是必要的。

构建一个复杂的系统需要有经验的员工和持续的维护,而一个简单的解决方案就可以了,这是对数据团队资源的浪费,这些资源可以用在其他地方以产生更大的影响。挑战在于建立一个实际上会产生商业影响的系统;建立系统本身不应该是最终目标。

推荐系统也应该是敏捷的。也就是说,适应性强,能够像用户一样进化。将推荐系统投入生产并不是这个过程的最后一步;相反,这是一个持续的演变,看看什么有效,什么无效,思考可能有助于做出更好建议的额外数据源,等等。

现在继续上 推荐系统系列第二部

如果你想关注我在推荐系统、深度学习和数据科学新闻方面的工作,你可以查看我的 中的 GitHub,以及 https://jameskle.com/*的其他项目。你也可以在* 推特 直接发邮件给我 或者 在 LinkedIn 上找我。 注册我的简讯 就在你的收件箱里接收我关于数据科学、机器学习和人工智能的最新想法吧!

推荐系统系列之二:学术研究者应关注的 10 类深度推荐系统

原文:https://towardsdatascience.com/recommendation-system-series-part-2-the-10-categories-of-deep-recommendation-systems-that-189d60287b58?source=collection_archive---------3-----------------------

RecSys 系列

深度推荐系统的类别

更新: 本文是我探索学术界和工业界推荐系统系列文章的一部分。查看完整系列: 第一部分 第二部分 第三部分 第四部分 第五部分

介绍

近年来,基于深度学习的推荐系统的研究出版物数量呈指数级增长。特别是,国际领先的推荐系统会议 RecSys 从 2016 年开始定期组织深度学习研讨会。例如,在几周前在哥本哈根举行的 2019 年会议上,有一个关于深度学习的整类论文,它促进研究并鼓励应用这种方法。

在这篇文章和接下来的文章中,我将介绍推荐系统的创建和训练,因为我目前正在做这个主题的硕士论文。在第 1 部分中,我提供了一个关于推荐系统的高级概述,它们是如何构建的,以及它们如何被用来改善各行各业的业务。第 2 部分很好地回顾了正在进行的关于这些模型的优点、缺点和应用场景的研究活动。这里的大部分评论来自张帅等人进行的令人难以置信的综合调查。艾尔,所以如果你想知道更多细节,请去看看!

为什么深度学习求推荐?

与传统的基于内容和协作过滤的方法相比,基于深度学习的推荐系统有 4 个关键优势:

  • 深度学习可以用 ReLU、Sigmoid、Tanh 等非线性激活对数据中的非线性交互进行建模… 这一属性使得捕捉复杂而错综复杂的用户-项目交互模式成为可能。传统的方法如矩阵分解和因式分解机本质上是线性模型。作为许多传统推荐器的基础,这种线性假设过于简单,将极大地限制它们的建模表现力。众所周知,通过改变激活选择和组合,神经网络能够以任意精度逼近任何连续函数。这一特性使得处理复杂的交互模式和精确地反映用户的偏好成为可能。
  • 深度学习可以高效地从输入数据中学习底层的解释因素和有用的表示。一般来说,在现实世界的应用中,可以获得大量关于物品和用户的描述性信息。利用这些信息提供了一种方法来提高我们对项目和用户的理解,从而产生更好的推荐器。因此,将深度神经网络应用于推荐模型中的表示学习是一种自然的选择。使用深度神经网络来辅助表示学习的优点有两方面:(1)减少了手工特征设计的工作量;以及(2)它使得推荐模型能够包括不同种类的内容信息,例如文本、图像、音频甚至视频。
  • 深度学习对于顺序建模任务来说是强大的。在机器翻译、自然语言理解、语音识别等任务中。,rnn 和 CNN 扮演着关键的角色。它们在挖掘数据序列结构方面具有广泛的适用性和灵活性。对序列信号建模是挖掘用户行为和项目演化的时间动态的一个重要课题。例如,下一件商品/购物篮预测和基于会话的推荐就是典型的应用。因此,深度神经网络非常适合这种序列模式挖掘任务。
  • 深度学习具有高度的灵活性。现在流行的深度学习框架有很多,包括 TensorFlow、Keras、Caffe、MXnet、DeepLearning4j、PyTorch、the ano……这些工具都是模块化开发的,有活跃的社区/专业支持。良好的模块化使得开发和工程更加高效。例如,很容易将不同的神经结构结合起来,形成强大的混合模型,或者用其他模块替换一个模块。因此,我们可以轻松地构建混合和复合推荐模型,以同时捕捉不同的特征和因素。

为了提供该领域的鸟瞰图,我将根据所采用的深度学习技术的类型对现有模型进行分类。

1 >基于多层感知器的推荐

MLP 是一个前馈神经网络,在输入层和输出层之间有多个隐藏层。您可以将 MLP 解释为非线性变换的堆叠图层,了解等级要素制图表达。这是一个简洁而有效的网络,可以将任何可测量的函数近似到任何期望的精度。因此,它是许多高级方法的基础,并被广泛应用于许多领域。

MLP 可以将非线性转换添加到现有的推荐系统方法中,并将其解释为神经扩展。

  • 推荐可以被看作是用户偏好和项目特征之间的双向互动。例如,矩阵分解将评级矩阵分解成低维的用户/项目潜在因素。神经协同过滤是一个代表性的工作,它构建了一个双神经网络来对用户和物品之间的这种双向交互进行建模。
  • 深度因式分解机是一个端到端的模型,无缝集成了因式分解机和 MLP。它可以通过深度神经网络对高阶特征交互进行建模,并通过因子分解机器对低阶交互进行建模。

使用 MLP 进行特征表示非常简单且高效,尽管它可能不如自动编码器、CNN 和 RNNs 那样有表现力。

  • 广度和深度学习是一个很好的模型,可以解决回归和分类问题,最初是为了 Google Play 中的应用推荐而引入的。宽学习组件是单层感知器,其也可以被视为广义线性模型。深度学习组件是一个 MLP。结合这两种学习技术使得推荐器能够捕获记忆和概括。
  • 用于 YouTube 推荐的深度神经网络将推荐任务分为两个阶段:候选生成和候选排名。候选生成网络从所有视频语料库中检索子集。排名网络基于来自候选的最近邻居的分数生成前 n 名列表。
  • 协同度量学习用欧氏距离代替矩阵分解的点积,是因为点积不满足距离函数的三角不等式。通过最大化用户和他们不喜欢的项目之间的距离和最小化用户和他们喜欢的项目之间的距离来学习用户和项目嵌入。

2 >基于自动编码器的建议

AE 是一种无监督模型,试图在输出层中重建其输入数据。通常,瓶颈层用作输入数据的显著特征表示。它的几乎所有变体(表示 AE、变化 AE、连接 AE 和边缘化 AE)都可以应用于推荐任务。

AE 可以用来学习瓶颈层的低维特征表示。

  • 协同深度学习是一种分层贝叶斯模型,将堆叠去噪自动编码器(SDAE)集成到概率矩阵分解(PMF)中。为了无缝结合深度学习和推荐模型,提出了一个通用贝叶斯深度学习框架,该框架由两个紧密相连的组件组成:感知组件(SDAE)和特定任务组件(PMF)。这使得模型能够平衡边信息和交互历史的影响。
  • 协作深度排名是针对前 n 名推荐在成对框架中专门设计的。论文表明,成对模型更适合于排行榜的生成。
  • 深度协同过滤是一个用协同过滤模型统一深度学习方法的通用框架。该框架使得利用深度特征学习技术来构建混合协作模型变得更加容易。

AE 可以用来直接在重建层填充用户-物品交互矩阵的空白。

  • AutoRec 将用户/项目部分向量作为输入,目的是在输出层重建它们。
  • 协同去噪自动编码器主要用于排序预测。CDAE 的输入是用户部分观察到的隐式反馈,可以看作是反映用户对项目兴趣的偏好向量。本文还提出了一种负采样技术,从负集合(用户没有与之交互的项目)中采样一个小的子集,这在不降低排序质量的情况下大大降低了时间复杂度。
  • 多 VAE 和多 DAE 提出了一种用于隐式数据推荐的变分自动编码器的变体。本文介绍了一种用于参数估计的原理性贝叶斯推理方法,并显示了比常用的似然函数更好的结果。

3 >基于卷积神经网络的推荐

CNN 基本上是一个具有卷积层和池操作的前馈神经网络。它可以捕捉全局和局部特征,从而大大提高模型的效率和准确性。它在处理非结构化多媒体数据方面非常强大。

CNN 可以用来从图像中提取特征。

CNN 可以用来从文本中提取特征。

  • DeepCoNN 采用 2 个并行 CNN 对评论文本中的用户行为和项目属性进行建模。该模型利用 CNN 对评论文本丰富的语义表示,缓解了稀疏性问题,增强了模型的可解释性。它利用单词嵌入技术将评论文本映射到一个低维语义空间,同时保留了单词序列信息。然后,提取的评论表示连续通过具有不同内核的卷积层、最大池层和全连接层。
  • 卷积神经网络学习资源自动推荐技术构建 e-learning 资源推荐模型,使用 CNN 从学习资源的文本信息中提取项目特征,如学习材料的介绍和内容。

CNN 可以用来从音频和视频中提取特征。

  • 基于深度内容的音乐推荐使用 CNN 从音乐信号中提取特征。卷积内核和池层允许在多个时标上操作。这种基于内容的模型可以缓解音乐推荐的冷启动问题。
  • 用于视频理解的协作深度度量学习使用基于 CNN 的著名模型 ResNet 提取音频特征。推荐是在协作度量学习框架中执行的,类似于前面提到的 CML。

CNN 可以应用于香草协同过滤。

  • 基于外积的神经协同过滤使用 CNN 来改进神经协同过滤。所谓的 ConvNCF 模型使用外积而不是点积来建模用户-项目交互模式。本文将细胞神经网络应用于外积结果,从而可以捕捉嵌入维度之间的高阶相关性。
  • 通过卷积序列嵌入的个性化 Top-N 顺序推荐使用 CNN 呈现顺序推荐,其中一个层次和一个垂直 CNN 用于建模联合级顺序模式和跳过行为,以进行顺序感知推荐。

基于图的 CNN 可以处理推荐任务中的交互。

  • 图卷积矩阵完成把推荐问题看作是一个带图 CNN 的链接预测任务。这个框架可以很容易地将用户/项目方面的信息(如社交网络和项目关系)集成到推荐模型中。
  • 用于网络规模推荐系统的图形卷积神经网络使用图形 CNN 在 Pinterest 上进行推荐。该模型利用随机游走和图 CNN 从图结构和项目特征信息中生成项目嵌入,非常适合大规模的 web 推荐系统。

4 >基于递归神经网络的推荐

RNN 适用于对序列数据建模。它有循环和记忆来记住以前的计算。包括 LSTM 和 GRU 的 rnn 的变体被部署来克服消失梯度问题。

在基于会话的推荐任务中,RNN 可以处理交互的时间动态和用户行为的序列模式。

  • GRU4Rec 是一个基于会话的推荐模型,其中输入是采用 1-of-N 编码的会话的实际状态,其中 N 是项目的数量。如果相应的项目在此会话中处于活动状态,则坐标为 1,否则为 0。输出是每个项目成为会话中下一个项目的可能性。
  • 网易中使用深度 R ecurrent 神经网络的个人推荐是一个现实世界电子商务网站的基于会话的推荐模型。它利用基本的 RNNs 根据点击历史来预测用户下一步会买什么。为了最小化计算成本,它只保留有限数量的最新状态,同时将较旧的状态折叠成单个历史状态。这种方法有助于平衡计算成本和预测精度之间的权衡。
  • 递归推荐网络是一个基于递归神经网络的非参数推荐模型。它可以模拟商品的季节性演变和用户偏好随时间的变化。它使用两个 LSTM 网络作为构建模块来模拟动态用户/项目状态。

用序列模式学习边信息,RNN 也是一个不错的选择。

  • 连续时间的循环协同进化潜在特征过程提出了一个协同进化潜在模型来捕捉用户和项目潜在特征的协同进化本质。用户和项目之间的交互在驱动用户偏好和项目状态的变化中起着重要的作用。为了对历史交互进行建模,作者提出使用 RNNs 来自动学习来自用户和项目特征的漂移、进化和共同进化的影响的表示。
  • 询问 GRU 提出使用 GRUs 将文本序列编码到潜在因素模型中。这种混合模式解决了热启动和冷启动问题。此外,作者采用了多任务正则化方法来防止过拟合和缓解训练数据的稀疏性。主要任务是评级预测,而辅助任务是项目元数据(例如标签、流派)预测。
  • 面向百万用户的基于嵌入的新闻推荐提出使用 GRUs 对用户浏览历史学习更具表达性的聚合,并使用潜在因素模型推荐新闻文章。与传统的基于单词的方法相比,结果显示了显著的改进。该系统已全面部署到在线生产服务中,每天为超过 1000 万独立用户提供服务。

5 >受限玻尔兹曼机基础推荐

RBM 是一个两层神经网络,由一个可见层和一个隐藏层组成。它可以很容易地堆叠到深层网络中。术语受限表示在可见或隐藏层中没有层内通信。

  • 用于协同过滤的受限玻尔兹曼机器是第一个建立在 RBM 上的推荐模型。RBM 的可见单位仅限于二进制值,因此,评级得分以一个热码向量表示,以适应这种限制。每个用户都有一个唯一的 RBM 和一个共享参数,这些参数可以通过对比散度算法来学习。这里的本质是用户通过给出评分来暗示他们的偏好,而不管他们如何给项目评分。
  • 一个基于 RBMs 的非 IID 协同过滤框架在一个统一的框架中结合了基于用户和基于项目的 RBM-CF。在这种情况下,可见单位由用户和项目隐藏单位共同决定。
  • 项目类别感知的条件限制波尔兹曼基于机器的推荐设计了一种混合 RBM-CF,它结合了项目特征并基于条件 RBM。这里,条件层用二进制项目类型建模,因此用不同的连接权重影响隐藏层和可见层。

6 >基于神经注意力模型的推荐

注意力模型是基于输入序列或输入图像上的软内容寻址来操作的可区分的神经架构。它们受人类视觉注意力的激励,可以从原始输入中过滤掉不含信息的特征,并减少噪声数据的副作用。这种注意机制普遍存在于计算机视觉和自然语言处理领域。

在推荐系统中,我们可以利用注意力机制来过滤掉嘈杂的内容,并选择最具代表性的项目,同时提供良好的可解释性。

  • 注意力协同过滤使用注意力协同过滤模型,在潜在因素模型内有两级注意力机制。该模型包括项目级和组件级注意:其中项目级注意选择最具代表性的项目来表征用户;而组件级从多媒体辅助信息中为每个用户捕获最具信息性的特征。
  • 基于话题关注度的 LSTM 标签推荐使用基于关注度的 LSTM 模型进行标签推荐。该模型利用 RNNs 和注意机制来捕捉序列属性,并识别微博帖子中的信息词。
  • 使用基于注意力的卷积神经网络的 Hashtag 推荐对微博中的同一 hashtag 推荐使用基于注意力的 CNN 模型,作为多标签分类问题处理。该模型由一个全局通道和一个局部注意通道组成:其中全局通道具有卷积和最大池层来编码所有的单词;并且本地频道具有给定窗口大小和阈值的关注层来选择信息词。

7 >神经自回归 基础推荐

神经自回归分布估计(NADE)是建立在自回归模型和前馈神经网络之上的无监督神经网络。它是一个易处理和有效的估计器,用于建模数据分布和密度,可以被认为是一个理想的替代限制玻尔兹曼机器。

根据我的评论,协作过滤的神经自回归方法是唯一一篇提出基于 NADE 的协作过滤模型(CF-NADE)的论文,该模型可以模拟用户评级的分布。

8 >深度强化学习 B 基于推荐

强化学习(RL)基于试错范式,由 5 个部分组成(主体、环境、状态、动作和奖励)。深度神经网络和强化学习的结合形成了深度强化学习,它已经在多个领域(如游戏和自动驾驶汽车)实现了人类水平的性能。深度神经网络使代理能够从原始数据中获取知识,并在没有手工特征和领域试探法的情况下导出有效的表示。

传统上,大多数推荐模型认为推荐过程是静态的,这使得捕捉用户的时间意图和及时响应变得很困难。近年来,深度强化学习已经被应用到个性化推荐中。

  • 带有负面反馈的建议通过成对深度强化学习提出了一种称为 DEERS 的东西,用于在顺序交互设置中提供负面和正面反馈的建议。
  • 针对页面式推荐的深度强化学习探索了一个名为 DeepPage 的框架,它可以根据用户的实时操作来自适应地优化一个页面的项目。
  • DRN:新闻推荐的深度强化学习框架是一个新闻推荐系统,它使用深度强化学习来检测新闻内容和用户偏好的动态变化,融入用户的返回模式,增加推荐的多样性。

9 >敌对网络 基础推荐

对抗网络是一种生成型神经网络,由鉴别器和生成器组成。这两个神经网络通过在极小极大博弈框架中相互竞争来同时训练。

10 >深混动车型 基础推荐

利用深度神经网络的良好灵活性,可以集成许多神经构建块,以形式化更强大和更具表现力的模型。最近的研究趋势表明,混合模型应该为特定的任务进行合理和仔细的设计。

  • 协作式基于知识的嵌入将 CNN 与自动编码器相结合,以提取图像中的特征。它利用不同的嵌入技术利用结构化内容、文本内容和可视内容。
  • 使用深度神经网络的对话中的引语推荐是一种 RNNs 和 CNN 的混合模型,用于推荐引语,这需要在给定查询文本或对话的情况下生成一个排序的引语列表。它应用 CNN 从推文中学习重要的本地语义,并将它们映射到分布向量。这些向量然后由 LSTM 处理,以计算目标引用与给定推文对话的相关性。
  • 个性化关键帧推荐集成 CNN 和 RNNs 进行视频内的个性化关键帧推荐,其中 CNN 用于从关键帧图像中学习特征表示,RNNs 用于处理文本特征。
  • 用于上下文感知引用推荐的神经引用网络在用于引用推荐的编码器-解码器框架中集成了 CNN 和 RNNs。CNN 是从引用上下文中捕获长期依赖关系的编码器,而 RNNs 是在给定所有先前单词以及 CNN 获得的表示的情况下学习被引用论文标题中单词的概率的解码器。
  • 协作递归自动编码器利用集成 RNNs 和去噪自动编码器来克服局限性,例如缺乏鲁棒性和缺乏对文本信息序列建模的能力。本文设计了一种称为鲁棒递归网络的广义递归神经网络,并提出了一种称为 CRAE 的分层贝叶斯推荐模型。该模型由编码和解码部分组成,并使用带有 RNNs 的前馈神经层来捕获项目内容的顺序信息。
  • 使用递归神经网络的监督强化学习用于动态治疗建议将监督深度强化学习与 RNNs 相结合,用于治疗建议。该框架可以从指示信号和评估信号中学习处方策略。

结论

深度学习在许多领域变得越来越流行,包括自然语言处理、图像和视频处理、计算机视觉和数据挖掘,这是一个显著的现象,因为以前没有这样一种通用的方法用于解决不同类型的计算问题。通过深度学习技术的这些方面,它们不仅能够很好地解决许多领域的复杂问题,而且还形成了这些研究领域的共享词汇和共同基础。深度学习方法甚至有助于这些子领域相互合作,而在过去,由于所用技术的多样性和复杂性,这有点成问题。

本文回顾了基于深度学习的推荐系统方法的现有文献,以帮助新的研究人员建立对该领域的全面理解,这些文献收集在张帅等人的“ 【基于深度学习的推荐系统:调查和新观点 ”调查论文中。主要是,它根据所采用的深度学习技术的类型将当前的文献分为 10 类,我相信这有助于读者建立一个整体的理解。我强烈建议您阅读调查报告,深入了解这些类别。

现在继续上 推荐系统系列第三部

如果你想关注我在推荐系统、深度学习和数据科学新闻方面的工作,你可以查看我的 中的 GitHub,以及 https://jameskle.com/*的其他项目。你也可以在* 推特 直接发邮件给我 ,或者 在 LinkedIn 上找我。 注册我的简讯 就在你的收件箱里接收我关于数据科学、机器学习和人工智能的最新想法吧!


  1. ↩︎

posted @ 2024-10-14 11:49  绝不原创的飞龙  阅读(257)  评论(0)    收藏  举报