TowardsDataScience-博客中文翻译-2019-二十一-

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

TowardsDataScience 博客中文翻译 2019(二十一)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

揭开 Python 中虚拟环境的神秘面纱

原文:https://towardsdatascience.com/demystifying-virtual-environments-in-python-7c0a0b255928?source=collection_archive---------19-----------------------

为什么要使用虚拟环境和安装步骤

Photo by João Silas on Unsplash

自从我开始用 Python 编码以来,我一直在用 Jupyter Notebook 进行我所有的 Python 编码。它非常强大,可以一次测试一行代码,添加 markdown 注释,并且有一个很好的界面。

Python 包允许在编程时访问各种要实现的功能,因此是 Python 编程的日常部分。唉,导入已安装的软件包时确实会出现问题。

我最近遇到了一个问题,我安装了一个特定的包(googletrans),但一个错误说这样的包不存在,不断弹出。

有几件事需要注意:

  • 使用命令which python来确认您处于什么 Python 环境中。
  • Jupyter 笔记本中运行的 Python 内核版本必须与你在site-packages中安装包的版本相匹配。简而言之,您用来安装包的pip必须对应正确的 Python 内核(Python 2 或 Python 3)。你应该使用 Python 3+,因此对所有安装命令使用**pip3**
  • 使用sys.path检查内核正在使用的所有当前路径,并确保考虑中的软件包下载文件夹的路径包括在内。

尽管如此,一个人可能会卡住。这些问题可能有很多潜在的原因。绕过他们的一种方法? 虚拟环境

默认情况下,所有的包和依赖项都下载到站点包的同一个目录中。因此,为了将每个项目的依赖性从系统中分离出来,并且相互分离,我们应该使用虚拟环境。

使用pip:

  • 确保你已经安装了virtualenv。如果没有,输入你的终端:pip3 install virtualenv。这将被下载到您的python3.7目录下的site-packages中。
  • 接下来,cd到您想要创建虚拟环境的目录。建议在一个地方存储所有虚拟环境。
  • 接下来,创建一个虚拟环境:virtualenv name-of-virtualenv
  • 上述命令将设置虚拟环境并安装libbininclude文件夹。

Virtual environment installation

  • cd进入环境并激活:source bin/activate
  • 现在输入jupyter notebook。在你想存放笔记本的文件夹中打开一个新的 Python3 笔记本。
  • 要确认 Jupyter 内核使用的是什么 Python:
  1. 在你的 Jupyter 笔记本上输入并执行!which python。该路径应该指向新创建的当前活动虚拟环境的 bin 中的 python。它应该是这样的:/path/to/created/virtual/environment/name-of-virtualenv/bin/python
  2. 您还可以使用import osos.getcwd()来检查您当前的工作目录,并确保该路径与您的虚拟环境的路径相匹配。
  • 使用pip3开始安装软件包,一切都准备好了!所有这些包都将在name-of-virtualenv/lib/python3.7/site-packages中安装
  • [EDIT]要导入已安装的包,我们必须将site-packages路径添加到系统路径列表中。
    import syssys.path.insert(1, './lib/python3.7/site-packages')。这将在索引“1”处插入路径,并确保在导入包时检查包的路径。./指向你当前的工作目录。请注意,每次内核重启时都必须执行这一步。
  • 还要注意,一旦您关闭了 Jupyter 笔记本和deactivate您的虚拟环境(通过在终端中键入命令),然后您在与上面相同的位置打开了一个 Jupyter 笔记本,!which python命令将返回 Python 的默认“全局”版本。

基于 GAN 的图像彩色化

原文:https://towardsdatascience.com/deoldify-gan-based-image-colorization-d9592704a57d?source=collection_archive---------9-----------------------

找回丢失的颜色…

Photo by Vladimir Perelman (1975, Kirillo-Belozersk), colorized by DeOldify (2019)

B B 缺乏和白色摄影承担其情感冲击。你摆脱了民粹主义的干扰或俗气的色彩刻板印象。天空是蓝色的,玫瑰是红色的。那是肯定的。很明显的事情。但是我们内心是什么呢?灯光,阴影,对比。富裕的世界。这就是黑&白摄影直接表达的。在你的皮肤下,进入你的心和灵魂。"

这是我爸爸以前告诉我的。他更了解这一点,因为他一生都在拍照。他是心理照片肖像大师。然而,他记录了一切——从 20 世纪 50 年代到 20 世纪 90 年代,苏联的日常生活、文化和荒谬。

我同意 B&·w 的情感力量,但同时,我想知道,当他永远记住他的世界的对比和细微差别时,他的世界是什么样子的。幸运的是,深度学习可以有所帮助。

#解密

这个模型是由 Jason Antic 创造并发布的。他立即着手于 deol dify(GitHub)——带来了惊人的成果和伟大的使命:

这个项目的任务是着色和恢复旧图像和电影胶片。(来源)

DeOldify 正在使用生成对抗网络以及两个神经网络生成器鉴别器之间的迭代相互作用(就像《T21》中的艺术培育者)。但与上一个模型不同的是,DeOldify 中的图像不会以它们的形式被修改或生成。甘的力量带来颜色——生成器将颜色应用到他训练过的已识别对象上,鉴别器尝试对颜色选择进行批评。DeOldify 基于 fast.ai 库——为深度学习开发者带来了更多的能力和优化。

在这种情况下,天空是蓝色的。玫瑰是红色的。(但也不尽然。“视情况而定”,正如 Discriminator 用来宣称的那样)。

Jason 在这个模型上工作了很长一段时间——有失败也有成功——这是一段充满情感高峰的个人旅程。令人惊叹的时刻。

在 Hacker Noon 的采访中,他讲述了他对模型结果的第一次影响,在这张解密照片中,他看到了 Evely Nesbit 手中的奖杯:

Source: @citnaj

我承认这张照片有瑕疵。但看到这个之后,我知道我找到了一些东西。

所以他继续挖掘,这样他可以给老照片上色:

给画重新着色:

甚至为历史视频片段添加色彩:

对于研究人员来说,这是一个令人兴奋的功能,他们应该记住,结果不一定代表原始颜色。

给历史图像和视频带来色彩,给了我们一个以单色再现世界的绝佳机会。

你可以在 GitHub 中找到这个模型,也可以在两个笔记本中找到:图像( Colab 笔记本)和视频( Colab 笔记本)——试试吧!

以下是使用 DeOldify 笔记本的简短视频教程:

B&W 还是色彩?

我有自己的惊叹时刻,给我父亲的黑白照片上色。看看这些花——它们颜色的多样性,在黑白照片中看不到:

在这篇文章标题的照片中,你也可以看到画上的颜色——用 AI 重新想象想象力。绿草——和女孩们画的画中修道院的颜色相呼应。

我仍然赞同黑白肖像的心理能量。但是从我个人的角度来说,我很感激 DeOldify 能让我们回到过去。我父亲记忆的重生。颜色总是很鲜艳。在我们的记忆中——现在,在过去的不朽文献中。借助深度学习。

在推特上关注杰森·安蒂奇的# deol dify-新闻和色彩:https://twitter.com/citnaj/

更新。

使用#DeOldify 和其他 ML 模型可以创造奇迹:

[## 重现历史

正在使用的深度学习模型

towardsdatascience.com](/re-animated-history-6b5eb1a85efa)

依存解析器或如何找到一个单词的语法邻居

原文:https://towardsdatascience.com/dependency-parser-or-how-to-find-syntactic-neighbours-of-a-word-a9e7d17ffe8?source=collection_archive---------10-----------------------

本文将通过理论来揭开 NLP 中这一不为人知的部分。然后,在第二篇文章中,我们将推荐一些工具来帮助您理解如何轻松地实现依赖解析器。

当我们考虑一个单词的邻居时,我们可以把邻居看作是他们在句子中的位置,他们与其他单词的关系(主语,行列式,等等。),称之为句法,或者称之为它们意义的相似性,称之为语义。这里我们感兴趣的是句法上的邻域。

词汇

首先,我们来定义一些词汇,让大家更清楚。

  • 语义学是研究意义和解释的语言学和哲学领域。它非常依赖单词之间的联系来理解句子,并分析意思的变化。在编程中,语义是程序的预期输出。
  • 句法是语言学领域的语法。它是对句子中单词模式规则的研究。众所周知,在编程中,语法错误通常会导致错误,因为规则通常比口头语言要严格得多。

什么是依赖解析器?

依存关系树是一种可以被定义为有向图的结构,具有对应于单词的|V|个节点(顶点),以及对应于它们之间的句法依存关系的|A|个弧。我们可能还想将标签归属于依赖关系,称为关系。这些关系给出了依赖类型的细节(如主语、直接宾语补足语、决定因素……)。你可以通过下面的链接找到所有来自通用依赖的关系:【https://universaldependencies.org/u/dep/index.html】T4。

Example of Dependency Tree : “What is a parser ?”

在弧 h → d 中,h 是,d 是从属。中心是一个短语中最重要的节点,而词根是整个句子中最重要的节点:它直接或间接地是所有其他节点的中心。

依存解析器只是将一个句子转换成一棵依存树。

度量:如何识别一个好的解析器?

一个准确的依存解析器能够很好地识别单词之间的依存关系。两个度量(分数)对此是有用的:
-未标记的附件分数(UAS),其对应于在可能性的数量上正确预测的依赖性的数量;
-标记的附件分数(LAS),其对应于在可能性的数量上正确预测的依赖性和关系的数量。

LAS 始终小于或等于 UAS,因为不正确的依赖关系会导致次优的 UAS 和 LAS,而不正确的关系(或标注)只会导致 LAS 下降。

算法:它是如何工作的?

正如您可能已经想到的,我们可以通过语言学家开发的规则创建一个依赖解析器。这些解析器被称为理性主义者。它们一点也不高效,因为语言非常复杂,而且会随着时间而变化。语言的任何微小变化都会导致解析器的巨大变化。机器学习允许开发数据驱动的经验解析器。通过许多句子,可以得出依赖或关系的概率。语言学知识可能会用到,但没有定论,如果你像我一样忘记了小学的功课,这是一个很好的观点…

创建依赖解析器需要几个步骤。我们的输入是句子的单词及其属性(索引、词性标签、词条、特征);然后,我们必须为句子中所有可能的弧线计算特征。由于这些特性,我们为每种可能性计算一个分数,最后用一个解码器解码分数。

功能和评分

句子中的每个单词都有一些属性,比如词性标签或词条。如果你已经读过 NLP,你可能知道他们。如果没有,您可以在这里查看:

  • https://universaldependencies.org/u/pos/all.html
  • https://universaldependencies.org/u/feat/index.html

利用这些特征,我们训练一个机器学习回归模型,该模型返回将被解码器利用的分数。

特征选择至关重要,一些模型允许我们通过深度学习部分绕过这一部分。我们将在下一节介绍的算法就是这种情况。

解码器

已经开发了许多不同的解码器。然而,我们可以将它们分为两类:基于转换的解码器和基于图的解码器。基于转换的解码器速度更快,解码乐谱需要的内存更少,但通常不如基于图形的解码器准确。在本文中,我将只介绍基于图的模型原理。

其他算法可以应用不同的过渡,但这一个允许我们理解主要的原理。

基于图形的解码器

要理解这些算法,需要处理图论。

图 G=(V,A)是表示记号的顶点 V(也称为节点)和弧(I,j)∈ A 的集合,其中 I,j ∈ V。弧表示两个单词之间的依赖关系。

在基于图的依赖解析器中,图是有向的,这意味着链接有不同的方向,节点之间可以有多条弧线,这被称为多向图

Weighted Multi Directed Graph (G)

你可以注意到有些箭头比其他的粗。这代表弧的权重。弧线的权重越大,两个节点之间的联系就越紧密。我们可以把这解释为解析器的语法依赖性的强度。比如 C 和 A 看起来很依赖 B,但是 B 看起来不太依赖 C 和 A。

图 G 太连通了。为了得到依赖树,我们需要:

  • 仅将每个单词与其从属词链接,而不是与所有单词链接。弧的总数应该等于节点数减 1 (|A| = |V|-1)。
  • 保持相同的节点(或记号或单词)。
  • 让它成为非循环的:我们不希望一个头依赖于它的一个从属(直接或间接)。

幸运的是,所有这些都已经有了名字:我们想要的是一棵生成树!

Example of Spanning Tree from the graph G

An other example of Spanning Tree

如果我清楚什么是生成树,你应该知道有多种可能性,因为我们只有几个条件来得到一个。这里有一个窍门:我们当然想要最好的,但是我们如何确定“最好”的呢?

这里有 3 个节点,我们想保留它们。然而,我们有 6 个弧,我们只想保留 2 个。“最佳”依赖树是具有最高权重的树:这被称为最大生成树(MST)。

Maximum Spanning Tree of G

Minimum Spanning Tree of G

这个最大生成树给了我们依赖树,我们将使用它来寻找句子中最接近的语法邻居。

结论

与不同的现有算法相比,这里给出的见解是非常轻的。然而,在开发依赖解析器时,这应该会提高您的直觉。

使用 Terraform 和 Ansible 部署 Kafka 集群

原文:https://towardsdatascience.com/deploy-a-kafka-cluster-with-terraform-and-ansible-21bee1ee4fb?source=collection_archive---------3-----------------------

供应、部署和管理 Kafka 平台的简单方法

Photo by Luca Bravo on Unsplash

概观

在我之前的帖子——在 AWS 中的 Ubuntu 上安装 Kafka 集群中,我已经详细描述了在 AWS 中手动设置消息传递主干的步骤。这是理解卡夫卡如何工作的伟大一步,但这需要很长时间,并且不可扩展。

一个 Kafka 集群有几个组件,如代理、动物园管理员、运行在多个实例上的工人,如下例所示。供应、部署和管理您的平台的最简单方法是使用可自动执行此任务的工具。

在这篇文章中,我将解释如何使用 Terraform 快速提供多个实例,然后使用 Ansible 在这些实例上安装 Kafka 来设置您的集群。

from AWS: https://aws.amazon.com/quickstart/architecture/confluent-platform/

首先,让我们从高层次的角度快速理解什么是 Terraform 和 Ansible

将(行星)地球化(以适合人类居住)

Terraform 是开源 基础设施 as code 软件工具,由 HashiCorp 打造。它使用户能够使用被称为 Hashicorp 配置语言(HCL)的高级配置语言或可选的 JSON 来定义和配置基础设施。

Terraform 支持许多云基础设施提供商,如亚马逊网络服务、谷歌云平台、微软 Azure 。

Terraform 生成一个执行计划,描述它将做什么来达到期望的状态,然后执行它来构建所描述的基础设施。随着配置的变化,Terraform 能够确定发生了什么变化,并创建可以应用的增量执行计划。

使用高级配置语法来描述基础结构。这允许对数据中心的蓝图进行版本控制,并像对待任何其他代码一样对待它。此外,基础架构可以共享和重复使用。

Ansible

Ansible 是一个非常简单的 IT 自动化平台,使您的应用程序和系统更容易部署。避免编写脚本或自定义代码来部署和更新您的应用程序——使用一种接近简单英语的语言,使用 SSH 来实现自动化,无需在远程系统上安装代理。

我们开始吧

首先,让我们安装 Terraform 和 Ansible

地形

您可以按照下面的说明进行操作,或者如果您使用的是 Mac,最简单的方法是使用 brew:

brew install terraform

[## 安装 Terraform

Terraform 必须首先安装在您的机器上。Terraform 以二进制包的形式发布,适用于所有受支持的…

learn.hashicorp.com](https://learn.hashicorp.com/terraform/getting-started/install.html)

确认 Terraform 正确安装了:

terraform -v

from: Marcos Lombog console Screenshot

可回答的

使用 pip 命令安装 Ansible。PIP 是 Python 包的一个package manager。 macOS 默认没有安装 pip。你必须先安装它。

sudo easy_install pip

使用 pip 安装 Ansible

sudo pip install ansible

让我们验证是否安装了 Ansible

ansible --version

from: Marcos Lombog console Screenshot

对于其他操作系统,请使用下面的参考:

[## 安装指南-翻译文档

欢迎使用 Ansible 安装指南!默认情况下,Ansible 通过 SSH 协议管理机器。一旦 Ansible 是…

docs.ansible.com](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html)

恭喜你!安装完成!

使用 Terraform 调配您的基础架构

现在,让我们使用 Terraform HCL 构建 Kafka 基础架构。

该设置基于使用公共 VPC 和子网的企业汇合 Kafka。

所有代码都可以在我的 GitHub 中找到

git clone [git@github.com](mailto:git@github.com):mlomboglia/kafka-cluster-infra.git

在 terraform 文件夹中,有以下文件:

from: Marcos Lombog console Screenshot

gateway.tf →互联网网关创建。没有必要更改这个文件

instances.tf →要创建的实例。没有必要更改这个文件

有五种类型的实例在括号中有一个短名称:

  • Kafka Brokers (broker) →托管 Kafka broker 服务并维护主题数据
  • zookeeper(zookeeper)→托管定额管理服务并管理主题元数据
  • Kafka Connect REST API(Connect)→Kafka Connect 是 Kafka 的一个开源组件,是连接 Kafka 与数据库、键值存储、搜索索引、文件系统等外部系统的框架。
  • REST 代理(rest) → REST 和对附加融合平台服务的 HTTP/HTTPS 访问
  • KSQL 服务器 REST API (ksql) →KSQL 是支持实时数据处理的流 SQL 引擎
  • Schema Registry REST API(Schema)→Schema Registry REST 服务器使用请求和响应的内容类型来指示数据的序列化格式以及正在使用的 API 的版本
  • 控制中心(control_center) →汇合控制中心是一个基于 web 的工具,用于管理和监控 Apache Kafka。控制中心有助于构建和监控生产数据管道和流式应用程序。

public.tf →子网创建。对于本例,我使用的是公共子网

route.tf →路由表信息

security_group.tf →允许必要的网络流量进入实例的安全组设置。对于这个例子,不需要修改这个文件。

请记住,ingress 允许 0.0.0.0/0,所以这是对公共互联网开放的。您需要将其限制在生产环境中使用。

vpc.tf → VPC 创作

variables.tf 包含我们的地形的参数。您可以对此进行修改。对于我的例子,我将在 AWS 中提供 7 个实例。

" rest " = 1
" connect " = 1
" ksql " = 1
" schema " = 1
" control _ center " = 1
" broker " = 1
" zookeeper " = 1

前缀为“staging”

实例类型“t2.small”。

重要提示:Confluent 推荐一个最小实例类型“t2.large”来运行 Kafka,因此如果您修改它,它将超出 AWS 免费层,并且会花费您的钱

密钥对。

您将需要一个 AWS 密钥对来创建您的实例。如果您还没有,请登录您的 AWS 帐户

EC2 - >创建密钥对

from: Marcos Lombog AWS

给一个名字,点击创建。

下载您的密钥,复制到安全文件夹并更新权限

chmod 400 ~/.ssh/<Key Name>.pem

用您的键名更新 variables.tf 下面的部分

variable "key_name" {
  description = "Key Pair"
  default     = "<Your Key Name>"
}

现在,我们可以走了。

Terraform init 将下载您的依赖项

cd kafka-cluster-infra
terraform init

from: Marcos Lombog console Screenshot

Terraform plan 将创建您的部署计划

terraform plan

现在,小心下一步。根据您的配置,这将花费您一些钱。

terraform apply

from: Marcos Lombog console Screenshot

用“是”确认

如果出现错误:找不到 ami,请转到 EC2 控制台,启动实例并使用最新的 ami 标签进行更新:

from: Marcos Lombog AWS

现在,您已经在 AWS 中提供了所有实例。

from: Marcos Lombog console Screenshot

进入 AWS,查看所有正在运行的实例,并记下每个实例的公共 DNS (IPv4)。在下一节中,您将需要用到它。

from: Marcos Lombog AWS

现在,让我们继续使用 Ansible 安装 Kafka

使用 Ansible 安装 Kafka

安装卡夫卡,我就用合流版。

1.创建一个hosts_example.yml文件的副本。

cd ..
cd cp**-**ansible

cp hosts_example**.**yml hosts**.**yml

2.使用您最喜欢的 IDE 并编辑 hosts.yml 文件,按照每个实例类型的标签,从上面的 AWS Terraform 安装中输入主机,看起来与您的公共 DNS 类似。

非常小心地在 YML 文件上使用正确的缩进:

from: Marcos Lombog console Screenshot

取消 hosts.yml 文件中以下行的注释,添加您的密钥路径

ansible_ssh_private_key_file: '~/.ssh/<Key Path>.pem'

3.确认 Ansible 可以通过 SSH 连接

ansible **-**i hosts**.**yml all **-**m ping

from: Marcos Lombog console Screenshot

键入“是”信任所有服务器。

如果连接到实例时出现问题,请尝试使用以下命令手动 SSH:

ssh -i <Key Path> [ec2-user@<](mailto:ec2-user@ec2-63-33-204-58.eu-west-1.compute.amazonaws.com)Instance Public DNS>

4.运行all.yml行动手册

ansible**-**playbook **-**i hosts**.**yml all**.**yml

from: Marcos Lombog console Screenshot

Ansible playbook 将在您的所有实例上执行 Kafka 安装。

一段时间后,您应该会看到上面的这条消息。所有东西都装好了!

现在,让我们测试安装:

  1. 您可以使用 SSH 连接到您的任何实例,以检查服务是否正在运行:
systemctl status confluent*

恭喜你!

要继续,你可以用我的另一篇文章构建你的第一个 Kafka 应用程序:

[## 你的第一个 Kafka 应用

创建您的第一个生产和消费消息的 Kafka 应用程序

towardsdatascience.com](/your-first-kafka-application-9b1358ccb870)

(可选)销毁集群

不要忘记销毁您的群集并终止您的实例,运行以下命令:

terraform destroy

快乐短信!

在 AWS Elastic Beanstalk 上部署一个机器学习模型作为 API

原文:https://towardsdatascience.com/deploy-a-machine-learning-model-as-an-api-on-aws-43e92d08d05b?source=collection_archive---------8-----------------------

现实世界中的数据科学

循序渐进的教程

Sorry, I don’t use Instagram, so I have to post pictures of my dog here.

每天都有几十篇很棒的文章和教程在讨论如何开发各种机器学习模型。但是,我很少看到解释如何将模型投入生产的文章。如果你想让你的模型对现实世界产生影响,它需要对其他用户和应用程序是可访问的。

这个分步指南将向您展示如何将模型部署为 API。为您的模型构建一个 API 是将您的工作集成到您公司系统中的一个很好的方式——其他开发人员只需要学习如何与您的 API 交互来使用您的模型。对于有抱负的数据科学家来说,这也是让他们的投资组合项目脱颖而出的绝佳方式。

本教程面向数据科学家和有抱负的数据科学家,他们在将应用程序和 API 部署到 web 方面没有什么经验。到最后,你会知道如何:

  1. 使用 Python 的 web 微框架 Flask 开发一个模型 API。
  2. 使用 Docker 将 API 容器化为微服务。
  3. 使用 AWS Elastic Beanstalk 将模型 API 部署到 web 上。

为什么要构建 API?

在深入研究代码之前,让我们讨论一下为什么我们更喜欢这种方法,而不是将模型代码放在主应用程序中。构建一个可以被主应用程序调用的独立服务有几个优点:

  • 更新更加简单,因为每个系统的开发人员不需要担心破坏其他系统。
  • 更具弹性,因为主应用程序中的故障不会影响模型 API,反之亦然。
  • 易于扩展(当对 API 使用微服务架构时)。
  • 易于与多个系统集成,即网络和移动系统。

模型

如果你正在开发一个项目组合,最好使用不太传统的数据集来帮助你在雇主面前脱颖而出。然而,为了本教程,我将使用著名的波士顿房价数据集。该数据集包含几个可用于预测 1980 年前后波士顿住宅价值的要素。

我选择使用随机森林来处理这个回归问题。我任意选择了一个特征子集来包含在模型中。如果我正在开发一个“真实世界”的模型,我会尝试许多不同的模型并仔细选择特性。

查看我的 GitHub repo 获取快速构建和保存模型的说明。跟着做,然后为您的建模项目构建一个 API!

API

app/目录下创建脚本app.py。如果你遵循了回购中的说明,这个目录也应该包含保存的模型(model.pkl)。

app/app.py中的前几行从 Flask、NumPy 和 pickle 导入了有用的功能。我们也从下面包含的app/features.py进口FEATURES。接下来,我们初始化应用程序并加载模型。

# app/app.py# Common python package imports.
from flask import Flask, jsonify, request, render_template
import pickle
import numpy as np# Import from app/features.py.
from features import FEATURES# Initialize the app and set a secret_key.
app = Flask(__name__)
app.secret_key = 'something_secret'# Load the pickled model.
MODEL = pickle.load(open('model.pkl', 'rb'))

特征

我将特性列表存储在一个单独的脚本中,以保证 API 中模型训练和预测的一致性。

# app/features.pyFEATURES = ['INDUS', 'RM', 'AGE', 'DIS', 'NOX', 'PTRATIO']

端点

我们的 Flask app 对象(上面定义为app = Flask(__name__))有一个有用的 decorator 方法,使得定义端点.route()变得容易。在下面的代码中,@app.route('/api')告诉服务器每当 http://{your_ip_address}/api 接收到一个请求时,就执行直接在它下面定义的api()函数。

# app/app.py (continued)[@app](http://twitter.com/app).route('/api', methods=['GET'])
def api():
    """Handle request and output model score in json format."""
    # Handle empty requests.
    if not request.json:
        return jsonify({'error': 'no request received'}) # Parse request args into feature array for prediction.
    x_list, missing_data = parse_args(request.json)
    x_array = np.array([x_list]) # Predict on x_array and return JSON response.
    estimate = int(MODEL.predict(x_array)[0])
    response = dict(ESTIMATE=estimate, MISSING_DATA=missing_data) return jsonify(response)

解析请求

我们需要包含parse_args()函数来解析 JSON 请求中的特性。

# app/app.py (continued)def parse_args(request_dict):
    """Parse model features from incoming requests formatted in    
    JSON."""
    # Initialize missing_data as False.
    missing_data = False# Parse out the features from the request_dict.
    x_list = []
    for feature in FEATURES:
        value = request_dict.get(feature, None)
        if value:
            x_list.append(value)
        else:
            # Handle missing features.
            x_list.append(0)
            missing_data = True
    return x_list, missing_data

启动应用程序

最后,在 Flask 的开发服务器上运行应用程序,确保它能够正常工作。

# app/app.py (continued)if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

$ python app.py启动服务器。在另一个终端窗口中,使用curl向 API 发送请求。以 JSON 格式传递带有--data标志的特性。

$ curl -X GET "[http://0.0.0.0:5000/api](http://0.0.0.0:5000/api)" -H "Content-Type: application/json" --data '{"INDUS":"5.9", "RM":"4.7", "AGE":"80.5", "DIS":"3.7", "NOX":"0.7", "PTRATIO":"13.6"}'{
  "ESTIMATE": 18,
  "MISSING_DATA": false
}

生产 Web 堆栈

Flask 的开发 web 服务器非常适合测试,但是由于我不在这里讨论的原因,我们需要在其他地方寻找我们的生产栈。你可以在这里阅读更多关于这个的内容。我们将使用 Gunicorn 作为应用服务器,使用 Nginx 作为 web 服务器。幸运的是,AWS Elastic Beanstalk 默认为我们处理 Nginx 部分。要安装 Gunicorn,运行$ pip install gunicorn。创建脚本app/wsgi.py并添加两行:

# app/wsgi.pyfrom app import app
app.run()

现在,运行$ gunicorn app:app --bind 0.0.0.0:5000。您应该能够执行与上面相同的curl命令来从 API 获得响应。

$ curl -X GET "[http://0.0.0.0:5000/api](http://0.0.0.0:5000/api)" -H "Content-Type: application/json" --data '{"INDUS":"5.9", "RM":"4.7", "AGE":"80.5", "DIS":"3.7", "NOX":"0.7", "PTRATIO":"13.6"}'{
  "ESTIMATE": 18,
  "MISSING_DATA": false
}

码头工人

Docker 现在非常流行,关于它的好处已经写了很多。如果你有兴趣学习更多关于 Docker 的知识并获得更深入的介绍,请阅读这个。

对于本教程,您需要在您的计算机上设置 Docker,按照这里的说明进行操作。你还需要一个 Docker Hub 账户。

一旦你都设置好了,让我们开始吧!构建 Docker 映像需要两个主要文件,Dockerfilerequirements.txt

Dockerfile包括创建环境、安装依赖项和运行应用程序的说明。

# app/Dockerfile# Start with a base image
FROM python:3-onbuild# Copy our application code
WORKDIR /var/app
COPY . .
COPY requirements.txt .# Fetch app specific dependencies
RUN pip install --upgrade pip
RUN pip install -r requirements.txt# Expose port
EXPOSE 5000# Start the app
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:5000"]

requirements.txt包含我们的应用程序所需的所有 Python 包。

# app/requirements.txtFlask==1.0.2
itsdangerous==1.1.0
Jinja2==2.10.1
MarkupSafe==1.1.1
simplejson==3.16.0
Werkzeug==0.15.2
numpy==1.16.4
pandas==0.24.2
scikit-learn==0.19.1
scipy==1.0.0
requests==2.22.0
gunicorn==19.9.0

app/目录中,运行:

$ docker build -t <your-dockerhub-username>/model_api .$ docker run -p 5000:5000 blemi/model_api

您的应用程序现在运行在 Docker 容器中。重新运行curl命令,会得到同样的输出!

$ curl -X GET "[http://0.0.0.0:5000/api](http://0.0.0.0:5000/api)" -H "Content-Type: application/json" --data '{"INDUS":"5.9", "RM":"4.7", "AGE":"80.5", "DIS":"3.7", "NOX":"0.7", "PTRATIO":"13.6"}'{
  "ESTIMATE": 18,
  "MISSING_DATA": false
}

运行$ docker push <your-dockerhub-username>/model_api将图像推送到您的 Docker Hub 帐户。在部署到 AWS Elastic Beanstalk 时,这最后一步会非常方便。

AWS 弹性豆茎

是时候把我们的 API 放到网上了,这样我们的朋友和同事就可以访问它了!创建一个 AWS 帐户并登录控制台。 注意:您需要提供一张信用卡来创建您的帐户。如果您按照下面的说明操作,不修改任何选项,您的应用程序将符合自由层资格,并且成本将最低。一旦你启动了你的应用程序,导航到你的账单仪表板,在那里你可以看到你估计的每月费用。

接下来,我们将创建一个文件,告诉 AWS 在哪里访问我们的图像。这叫Dockerrun.aws.json。这里的关键部分是“名称”值。我的 Docker Hub 用户名是“blemi ”,我将图像命名为“model_api ”,所以我将把blemi/model_api:latest作为“name”值。

{
  "AWSEBDockerrunVersion": "1",
  "Image": {
    "Name": "<your-dockerhub-username>/model_api:latest",
    "Update": "true"
  },
  "Ports": [
    {
      "ContainerPort": "5000"
    }
  ],
  "Logging": "/var/log/nginx"
}

在 AWS 控制台中,搜索“Elastic Beanstalk”并选择它。

选择右上角的“创建新应用程序”,为您的应用程序添加名称和描述,然后单击“创建”

点按“立即创建一个”

保持“Web 服务器环境”处于选中状态,然后单击“选择”继续。

如果愿意,为“域”和“描述”填写一个自定义值。对于“平台”,选择“预配置的平台”,并在下拉列表中选择“Docker”。对于“应用程序代码”,选择“上传您的代码”并单击“上传”按钮。

点击“选择文件”按钮,打开我们在上面创建的Dockerrun.aws.json文件。 注意:只有当你把你的 Docker 镜像推送到 Docker Hub 时,这个功能才会起作用。

单击“上传”,然后单击“创建环境”来部署应用程序。

注意:如果您正在创建一个生产级 API,在选择“创建环境”之前,您可能需要在这里选择“配置更多选项”——如果您有兴趣了解其他一些增强安全性和可伸缩性的选项,请联系我。我的信息在这篇文章的底部。

该应用程序需要几分钟的时间来部署,但部署完成后,您可以通过屏幕顶部提供的 URL 进行访问:

现在,让我们在 web 上托管的 API 上运行curl命令。

$ curl -X GET "[http://api-demo-dattablox.us-west-2.elasticbeanstalk.com/api](http://api-demo-dattablox.us-west-2.elasticbeanstalk.com/api)" -H "Content-Type: application/json" --data '{"INDUS":"5.9", "RM":"4.7", "AGE":"80.5", "DIS":"3.7", "NOX":"0.7", "PTRATIO":"13.6"}'{"ESTIMATE":18,"MISSING_DATA":false}

总结和最终想法

我们用 Python Flask 构建了一个简单的模型 API,用 Docker 将其容器化,用 AWS Elastic Beanstalk 将其部署到 web 上。您现在可以利用这些知识为您的模型和项目开发 API 了!这使得与其他开发人员的合作变得更加容易。他们只需要学习如何使用你的 API 将你的模型集成到他们的应用和系统中。

要使这个 API 可以投入生产,还需要做更多的工作。在 AWS 和 Flask 应用程序本身中,您可以设置许多配置来增强安全性。如果使用量很大,还有许多选项可以帮助提高可伸缩性。Flask-RESTful 是一个 Flask 扩展,使得符合 REST API 最佳实践变得容易。如果你对使用 Flask-RESTful 感兴趣,可以看看这个伟大的教程。

取得联系

如果您有任何反馈或批评,请分享。如果您觉得本指南有用,请务必关注我,这样您就不会错过未来的文章。

如果你想联系,LinkedIn上联系我。感谢阅读!

在 Python 中的 Kubernetes 上使用 NGINX 和 Docker 部署机器学习 Web API

原文:https://towardsdatascience.com/deploy-machine-learning-web-api-using-nginx-and-docker-on-kubernetes-in-python-3abcf5c0026f?source=collection_archive---------14-----------------------

Photo by Fotis Fotopoulos on Unsplash

几天前,我正在谷歌云平台(GCP) Kubernetes 引擎上部署机器学习预测 web API,并浏览了许多技术博客来完成我的任务。因此,我想写一步一步的指南来部署任何机器学习预测 web API,使用 Flask,Gunicorn,NGINX 在 GCP Kubernetes 引擎上的 Docker 中封装。

我把这个循序渐进的教程分成了 3 个部分:

  1. 在第 1 节中,我们将简要讨论 Flask、Gunicorn、NGINX、Docker 和 Kubernetes 等组件,以及项目搭建和在开发机器上的设置。
  2. 在第 2 节中,我们将讨论 Gunicorn、supervisor、NGINX 的设置、Docker 文件的创建和 Docker 映像。
  3. 在第 3 节中,我们将讨论 Kubernetes 并在 Google Kubernetes 引擎上部署 web API。

第一节:

组件描述

我假设读者对 Python,Flask,Gunicorn,NGINX,Docker,Kubernetes,最后但并非最不重要的机器学习有基本的了解。以下是本教程中使用的组件的基本介绍,有关更多详细信息,请参考嵌入的链接:

  • 烧瓶 是用 Python 写的一个微型 web 框架。它被归类为微框架,因为它不需要特殊的工具或库。它没有数据库抽象层、表单验证或任何其他组件,而现有的第三方库提供了通用功能。
  • Gunicorn 是众多 WSGI 服务器实现中的一个,是 web 应用部署的常用部分,为世界上一些最大的基于 Python 的 web 应用提供动力,如 Instagram。
  • NGINX 常用作 web 服务器,为 web 浏览器客户端提供图片、CSS、JavaScript 等静态资产。NGINX 通常还被配置为反向代理,它将适当的传入 HTTP 请求传递给 WSGI 服务器。WSGI 服务器通过运行 Python 代码生成动态内容。当 WSGI 服务器传递它的响应(通常是 HTML、JSON 或 XML 格式)时,反向代理将结果响应给客户机。
  • Docker 是一个开源项目,它通过在 Linux 上提供一个额外的抽象层和操作系统级虚拟化的自动化来自动化容器内软件应用程序的部署。
  • Kubernetes 是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化的应用程序。它是一个可移植的、可扩展的平台,用于管理容器化的工作负载和服务,促进了声明式配置和自动化。

项目脚手架

Project folder structure to create a docker image

  • app 文件夹:主文件夹包含所有 python 代码,如:

a.机器学习逻辑,例如数据预处理、将保存的模型加载到存储器中以及机器学习模型预测。

b.requirement.txt 中所有必需的 python 包

c.main.py 中的所有 Flask 代码和路由

  • Dockerfile: 定义了容器内部环境中发生的事情。在此环境中,对网络接口和磁盘驱动器等资源的访问是虚拟化的,与系统的其他部分隔离开来,因此您需要将端口映射到外部世界,并明确要将哪些文件“复制”到该环境中。然而,这样做之后,您可以预期在 docker 文件中定义的应用程序的构建无论在哪里运行都是一样的。
  • 这个配置文件将为机器学习 flask 应用程序定义一个服务器块。
  • gunicorn.conf: 这个配置文件将执行命令在后台运行 gunicorn 应用服务器。
  • supervisord.conf: 这个配置文件将照看 Gunicorn 进程,并确保它们在出现问题时重新启动,或者确保这些进程在引导时启动。
  • Makefile: 该 Makefile 将包含所有命令,如创建和运行 docker 映像、创建 Kubernetes 集群和部署 web API。

在开发机器上设置项目

  • 在开发机器上安装所需的包:
$ sudo apt-get install -y python python-pip python-virtualenv nginx gunicorn supervisor
  • 创建并激活 Python 虚拟环境:

Python 虚拟环境帮助我们用所需的 python 包创建特定于应用程序的环境。

安装虚拟环境包:

$ pip install virtualenv

创建虚拟环境:

$ virtualenv mypython

激活 Python 虚拟环境:

$ source mypython/bin/activate
  • 打造机器学习预测的 Flask app:

安装 Flask 和其他依赖项:

$ pip install Flask
$ pip install -r requirements.txt

创建机器学习推理代码:

Flask 主要是为应用程序开发服务器创建的。我们可以在开发机器上测试 Flask API。

$ python main.py

不建议在生产环境中使用 Flask development server 来处理并发性和安全性。我们将使用 Gunicorn 作为 Python HTTP WSGI 服务器网关接口。

第二节

Architecture Diagram

  • 安装 Gunicorn Python 包:
$ pip install gunicorn

配置 gunicorn.conf 文件以配置 Gunicorn web 服务器。

我们已经将 Gunicorn web 服务器配置为监听端口 5000,并从 app 目录运行 main.py 文件。

  • 配置 supervisord 为监控进程:

Supervisord 允许用户在类似 UNIX 的操作系统上监视和控制几个进程。Supervisor 将负责 Gunicorn 进程,并确保它们在出现任何问题时重新启动,或者确保这些进程在引导时启动。

它将运行 NGINX 反向代理服务器,并在其上保持一个监视器。如果有任何失败,它会自动重启服务器并运行 NGINX 命令。

  • 设置 NGINX 服务器:

打开一个服务器块,设置 NGINX 监听默认端口80。用户可以设置服务器名称来处理请求。

  • 创建 Dockerfile:

我把 Dockerfile 分成了 5 个部分。让我们简单介绍一下每一部分:

  1. 创建一个 Ubuntu 环境。安装 Ubuntu,更新必要的包。安装 python、pip、虚拟环境、NGINX、Gunicorn、supervisor。
  2. 设置烧瓶应用程序。做一个目录“/deploy.app”。将所有文件从“app”文件夹复制到“/deploy/app”文件夹。安装所有需要的 python 包。
  3. 设置 NGINX。删除默认 NGINX 配置。将烧瓶配置复制到 NGINX 配置。为 NGINX 烧瓶配置创建一个符号链接。
  4. 设置主管。做一个目录“/var/log/supervisor”。将 Gunicorn 和 supervisord 配置复制到新创建的目录中。
  5. 启动监控程序进行监控。
  • 构建并运行 docker 映像来测试生产就绪的 ML web API:

我已经创建了一个 makefile 来运行所有的命令。

下面的 Makefile 执行两个操作:

  1. 创建 docker 图像
  2. 在端口 80 上运行 docker 映像

运行 Makefile:

deploy-local:#build docker image
docker build -t gcr.io/${project_id}/${image_name}:${version} .#run docker image
docker run -d --name ${image_name} -p $(port):$(port) gcr.io/${project_id}/${image_name}:${version}
  • 在开发机器上使用 Postman 测试生产就绪的 web API,网址:http://127 . 0 . 0 . 1/predict

在上一节中,我们已经学习了如何在开发机器上构建和运行 ML web API docker 映像。

第三节

在本节中,我们将学习如何在 GCP Kubernetes 引擎上部署这个容器化的 NGINX,并为生产环境公开 API。

  1. 构建机器学习应用程序的容器映像,并对其进行标记以便上传
#Set variables value as per your project
$ docker build -t gcr.io/${project_id}/${image_name}:${version} .

2.使用 gcloud 命令行工具,安装 Kubernetes CLI。Kubectl 用于与 Kubernetes 通信,Kubernetes 是 GKE 集群的集群编排系统

$ gcloud components install kubectl

3.使用 gcloud 命令行工具,安装 Kubernetes CLI。Kubectl 用于与 Kubernetes 通信,Kubernetes 是 GKE 集群的集群编排系统

$ gcloud components install kubectl

4.配置 Docker 命令行工具以向容器注册表进行身份验证

$ gcloud auth configure-docker

5.使用 Docker 命令行工具将图像上传到容器注册中心

#Set variables value as per your project
$ docker push gcr.io/${project_id}/${image_name}:${version}

6.使用 gcloud 命令行工具并设置项目 id

$ gcloud config set project ${project_id}

7.使用 gcloud 命令行工具并设置区域

$ gcloud config set compute/zone ${zone}

8.在 GCP 上创建一个名为 ML-API-cluster-nginx 的单节点 Kubernetes 集群

$ gcloud container ${cluster_name} create machine-learning-api --num-nodes=1

9.部署机器学习应用程序,监听端口 80

$ kubectl run ${image_name} --image=gcr.io/${project_id}/${image_name}:v1 --port 80

10.将机器学习应用程序暴露给来自互联网的流量

$ kubectl expose deployment ${image_name} --type=LoadBalancer --port $(port) --target-port $(port)

使用 curl 命令或 Postman 测试部署的机器学习 Web API。

我希望这能给你一个说明性的指南,用 Python 在 Kubernetes 上使用 NGINX 和 Docker 部署机器学习 Web API。

来源:

  1. https://opensource.com/article/18/4/flask
  2. 【https://www.fullstackpython.com/green-unicorn-gunicorn.html
  3. https://www.fullstackpython.com/nginx.html
  4. https://docker-curriculum.com/
  5. https://www . digital ocean . com/community/tutorials/an-introduction-to-kubernetes
  6. https://cloud . Google . com/kubernetes-engine/docs/how-to/exposure-apps
  7. https://cloud . Google . com/kubernetes-engine/docs/tutorials/hello-app

快乐学习!!!

通过 Panini 将 ML/DL 模型部署到生产中

原文:https://towardsdatascience.com/deploy-ml-dl-models-to-production-via-panini-3e0a6e9ef14?source=collection_archive---------14-----------------------

https://paniniai.com是一个以低延迟为 ML/DL 模型提供服务的平台,可以将 ML 模型部署到生产环境的时间从几天缩短到几分钟。

帕尼尼是什么?

Panini 是一个以低延迟为 ML/DL 模型提供服务的平台,使 ML 模型从几天到几分钟内部署到生产环境。一旦部署在 Panini 的服务器中,它将为您提供一个 API 密钥来推断模型。Panini 查询引擎是用 C++开发的,它在模型推理过程中提供了非常低的延迟,Kubernetes 集群用于存储模型,因此它可扩展到多个节点。Panini 还负责在模型推断期间缓存和批处理输入。

我们目前支持 Python 中的框架,但是我们计划将来扩展到其他语言。我来演示一下上传经典迁移学习 Pytorch CNN 模型对狗和猫进行分类。源代码可从 https://github.com/avinregmi/Panini_Tutorial 的获得。确保您安装了 Pytorch 1.0 和 Python 3.6。

传统方法

传统的方法是将 Flask 和 Gunicorn 与 Nginx 一起使用,这需要大量的设置时间。此外,用 Flask 推断模型很慢,并且需要定制代码来进行缓存和批处理。使用烧瓶在多台机器中结垢也会导致许多复杂情况。
大多数人都在使用 Flask 向互联网公开 ML 模型并进行 API 调用。因为 Flask 不是服务于 ML 模型的合适平台。使用烧瓶的一些显著缺点包括:

  1. 它不支持缓存和批处理。
  2. 高延迟。有时需要预先计算预测。
  3. 维护。
  4. 难以在多个集群中扩展。

为了解决这些问题,我们开发了帕尼尼。

安装所需的包

Panini 需要 python 3.6 所以确保安装了 3.6 的环境。另外,如果你使用 Pytorch,确保你已经安装了 Pytorch 1.0

部署经典的狗与猫

完整的源代码可以从

https://github . com/avinregmi/Panini _ Tutorial/blob/master/py torch _ CNN _ Production/Panini _ Transfer _ Learning _ Demo _ YouTube . ipynb

我将使用迁移学习来修改 DenseNet 的最后一层。

保存模型时,确保只保存权重,而不是整个模型架构。推荐的方法是通过调用 state_dict()来保存权重。训练模型的代码非常简单,可以通过打开上面的链接来检索。我已经包括了 Jupyter 笔记本和一个 YouTube 教程。我已经预先训练了 DenseNet 模型来对狗和猫进行分类。我将权重保存为“last_layers.pth”

为帕尼尼准备文件

你需要上传至少三个文件到帕尼尼

  • predict.py
  • requirements.txt
  • 我们保存的模型权重(last_layers.pth)

最重要的文件是 predict.py,这个文件告诉 Panini 加载您的模型并进行预测。如果您有额外的软件包,如 numpy 和 pandas,它可以通过在 requirements.txt 文件中指定 pip 软件包来安装。我们需要的最后一个文件是保存的权重模型。该文件可以命名为任何名称,但扩展名必须是. pth。

Predict.py 脚本里面需要有两个方法。它们是 load()和 predict()

  • load(path): 当您的模型被加载到 Panini 的 Kubernetes 集群中时,第一次执行 load。它必须接受一个名为 path 的参数,并返回一个对模型的引用。您需要在这里指定您的模型架构,并将 weights.pth 文件加载回您的模型。在您的模型加载了预先训练的权重之后,它需要返回对您的模型的引用。
  • predict(model,input_from_client): 每次向 API 链接发送 POST 请求时,都会执行 predict。它需要模型和 input_from_client 的参数。第一个参数是由 load 函数返回的对模型的引用。下一个参数是客户端通过 POST 请求发送的数据。另外,input_from_client 是一个数组,所以我们必须使用 for 循环来访问每个图像。一旦我们有了每个图像,我们可以应用一些预处理,并将我们的图像转换成张量。一旦我们的图像被转换成张量,我们就可以输入到我们的模型中。我们的模型将返回一个对数概率,这也是一个列表,我们可以将它返回给我们的客户端。确保值 predict()返回一个数组。此外,数组的长度必须等于模型中最后一层的长度。我们用神经网络修改了上面模型的最后一层。线性(256,2)。因此,predict()需要返回一个长度为 2 的数组。

部署时间到了

登录https://paniniai.com并创建一个账户。您可以使用 Google 帐户或 GitHub 登录。

Panini Dashboard

登录后,您将看到一个仪表板,并被要求填写一些信息。首先,给你的模型起个名字。名称必须少于或等于 10 个字符,并且只能是(a-z/0–9)。对于框架选择,PyTorch。目前,您有三种不同的选择。

  • PyTorch :如果需要使用深度学习。目前,我们支持 Pytorch 1.0
  • Python 函数:任意自定义 Python 函数。这包括 SciKit-Learn 和传统的机器学习,如 SVM 和回归。
  • 快速 AI :如果你用的是快速 AI 库。

我们还需要指定模型期望的输入类型。因为我们将发送一张狗/猫的图片,并且将被编码为 base64 字节,所以让我们选择字节作为输入类型。点击浏览并选择你的三个文件。

  • predict.py
  • r equirements.txt
  • last_layers.pth

额外的文件是可选的,不是必需的。有些型号需要额外的文件,如用于 RNNs 的 vocab 到整数映射 pickle 文件。在我们的例子中,我们没有额外的文件,所以我们可以把它留为空白。

选择三个文件后,单击“部署!”并等待文件上传达到 100%。目前,模型大小限制为 2GB。如果您的型号超过 2GB,请给我们发电子邮件。

日志输出

一旦页面显示 100%,您可以刷新页面以查看最新的日志输出。

最后的日志输出应该是“完成部署您的模型!你可以走了!”出现此消息后,您应该会在控制台上方看到一个 API 链接。

如何使用我们的 API 进行推断?

我们将对一只可爱的猫的图片进行 base64 编码,并发送给帕尼尼进行预测。

Let’s send this cute picture to Panini for Prediction.

现在,我们需要做的就是向我们的 API URL 发送一个 POST 请求。要发送图像,我们需要用 base64 编码,并用 JSON 格式包装。此外,关键标签应该是“输入”,值将是我们的图像的 base64 编码字节格式。

Prediction result from Panini

我们也可以使用邮递员

最后

我们已经使用 Panini 成功地将 DL 模型部署到生产中。随着我们模型的流量增加,panini 会自动将其复制到几个节点中。如果我们想将它合并到 web 应用程序中,我们可以从 javascript/NodeJs 发出 POST 请求。我们可以专注于开发我们的模型,而不用担心 DevOps。如果您在上传模型时遇到问题,请发送电子邮件给我们!

YouTube 教程:https://www.youtube.com/watch?v=tCz-fi_NheE&t =

源代码:【https://github.com/avinregmi/Panini_Tutorial】

大规模部署 ML 模型

原文:https://towardsdatascience.com/deploy-ml-models-at-scale-151204549f41?source=collection_archive---------6-----------------------

第 1 部分:ML 模型的 API 服务

ML Model Deployment (Source)

让我们假设您已经构建了一个 ML 模型,并且您对它的性能感到满意。然后下一步是将模型部署到生产中。在这个博客系列中,我将介绍如何使用 AWS 和 docker 容器服务在可扩展的基础设施中部署大规模消费模型。

在这篇博客中,我将从构建 ML 模型的 API 框架的第一步开始,并在您的本地机器上运行它。出于这篇博客的目的,让我们考虑在这里建立的情感分类模型。为了部署该模型,我们将遵循以下步骤:

  1. 将模型转换成 .hdf5 文件或 。pkl 文件
  2. 实现 Flask API
  3. 运行 API

将模型转换成" .hdf5" 文件或'。“pkl”文件

如果模型是基于 sklearn 构建的,最好将其保存为。“pkl”文件。或者,如果它是深度学习模型,那么建议将模型保存为“HDF”文件。'之间的主要区别。pkl '和'。“hdf”是,pickle 需要大量的内存来保存数据结构到磁盘,而 HDF 是为了有效地存储大型数据集而设计的。

将模型保存在泡菜中(。pkl):

from sklearn.externals import joblib  *# Save to file*# Fit the model (example of a model in sklearn)
model = LogisticRegression()
model.fit(X_train, Y_train)#*working directory* joblib_file = "best_model.pkl"   
joblib.dump(model, joblib_file)

在 HDF 保存模型(. hdf5):

一旦在 keras 或 tensorflow 中训练了深度学习模型,就可以使用. hdf5 文件系统保存模型架构及其权重。

# save the best model and early stoppingsaveBestModel = keras.callbacks.ModelCheckpoint('/best_model.hdf5', monitor='val_acc', verbose=0, save_best_only=True, save_weights_only=False, mode='auto', period=1)

实现 Flask API

步骤 1: 根据文件类型,通过以下方法之一加载保存的模型(根据上一节),即“hdf5”或“pkl”。

HDF5:

from keras.models import load_model
import h5py
prd_model = load_model('best_model.hdf5')

PKL:

from sklearn.externals import joblib
loaded_model = joblib.load('best_model.pkl')

第二步:导入 flask,创建 flask 应用对象,如下图所示:

from flask import Flask, url_for, requestapp = Flask(__name__)

步骤 3: 下一步是构建一个测试 API 函数,它返回“ API working”字符串。这可以用来确保 API 在生产中部署时的健康。这里我们使用' @app.route ',这是一个 python 装饰器(装饰器是一个函数,它接受另一个函数并扩展后一个函数的行为,而不显式修改它)

[@app](http://twitter.com/app).route(‘/apitest')
def apitest():
    return ‘API working’

步骤 4: 下一步是构建一个“POST”请求 api,用于处理对我们的情感模型的请求。我们使用的是路径名“/情绪”。该函数读取 json 输入并将其转换为 pandas 数据帧。它从 json 中提取相关字段,并调用“get _ opinion _ DL”函数进行处理。“get _ opinion _ DL”函数包含已通过“hdf5”文件加载的训练模型。它最终将以 json result 的形式返回模型的结果。

# main API code
[@app](http://twitter.com/app).route(‘/sentiment’, methods=[‘POST’])
def sentiment():
   if request.method == ‘POST’:
   text_data = pd.DataFrame(request.json)
   text_out = get_sentiment_DL(prd_model, text_data, word_idx)

   text_out = text_out[[‘ref’,’Sentiment_Score’]] #Convert df to dict and then to Json
   text_out_dict = text_out.to_dict(orient=’records’)
   text_out_json = json.dumps(text_out_dict, ensure_ascii=False) return text_out_json

第五步:详细的模型处理步骤将由“get _ sensation _ DL”函数执行。在我们的深度学习情感模型中,我们通过了:

  1. best_model:加载的模型

2.text_data:用于情感分类的输入文本

3.word_idx:手套文件中的 word 索引(型号详情此处)。

def get_sentiment_DL(best_model, text_data, word_idx):'''Modle Processing''' return sentiment_score

第 6 步:添加下面的部分来运行应用程序。这里主机被设置为“0.0.0.0 ”,因为我们在本地服务器上托管。但是,您可以根据您的网络设置对其进行配置。调试可以在构建 API 功能时设置为真。端口设置为 5005,但是这可以根据您的要求进行配置。

if __name__ == “__main__”:
  app.run(host=”0.0.0.0", debug=False, port=5005)

运行 API

要运行 API,请打开命令行窗口并转到存储代码的目录。通过运行下面的命令来运行 python 脚本(“情绪. py”是上面的 API 实现的文件名)。

python sentiment.py

运行上述命令时,您将能够在命令行窗口中看到以下结果:

API 运行后,您可以在浏览器中输入“0.0.0.0:5005/apitest”来测试 API。你将会在你的浏览器中得到下面的结果。

Browser — API Test

现在,您可以使用 python 将任何数据传递给 API,如下所示。我们这里的地址是“http://0 . 0 . 0 . 0:5005/情操”。模型的结果将被返回并存储在“响应”字段中。

import requests
import json
import urllib.parsedata_json = '''{"ref":[1], "text":["I am well"]}'''head= {“Content-type”: “application/json”}response = requests.post(‘[http://0.0.0.0:5005/sentiment'](https://www.seelabs.app/face_rec_train'), json = data_json, headers = head)result = response.content.decode(‘utf8’)

结论

总之,我们已经介绍了将模型部署到本地计算机的 api 服务中的步骤。

下一步是将它作为微服务部署在云服务器中。在接下来的博客中,我将介绍 docker 等容器服务的使用,并在 AWS 中部署它。

在 Kubernetes 上使用 Istio 部署 TensorFlow 模型

原文:https://towardsdatascience.com/deploy-tensorflow-models-with-istio-on-kubernetes-dd0b2bd3e388?source=collection_archive---------10-----------------------

部署、版本控制、扩展和监控的典型云应用需求也是机器学习(ML)服务的常见运营挑战。

这篇文章将关注于构建一个 ML 服务基础设施来持续更新、版本化和部署模型。

基础设施堆栈

在构建我们的 ML 服务基础设施时,我们将在云环境中设置一个 Kubernetes 集群,并利用 Istio 来处理服务级别操作。接下来,我们将使用 TensorFlow Serving 来部署和服务托管在 S3 存储桶上的 ResNet 模型。最后,我们将看看如何执行新模型版本的阶段性 canary 部署,并最终使用 Flagger 自动化部署过程。

概括地说,我们的基础架构包括:

  • Kubernetes :面向应用基础设施和管理的开源容器编排系统。
  • Istio :开源“service-mesh”实现分布式环境下微服务的运营管理。
  • tensor flow Serving:开源的高性能 ML 模型服务系统。
  • S3 存储 : AWS 云对象存储。
  • Flagger :作为 Kubernetes 操作员的开源自动化金丝雀部署管理器。

库伯内特星团

Kubernetes 在重塑云基础架构格局方面创造了奇迹。多种环境都支持构建集群,几乎所有主要的云提供商都提供托管 Kubernetes 作为托管解决方案。

在这篇文章中,我们将借此机会测试一个最新的解决方案,DigitalOcean 的托管 Kubernetes 解决方案。首先在选定的数据中心和节点池配置上创建一个新的 DigitalOcean Kubernetes 集群。

下载配置文件并将其添加到 bash 会话中。

export KUBECONFIG=k8s-1-13-5-do-1-sfo2-1555861262145-kubeconfig.yaml

检查节点的状态,并验证它是否运行正常,是否准备好接受工作负载。

kubectl get nodesNAME                                        STATUS    ROLES     AGE       VERSIONk8s-1-13-5-do-1-sfo2-1555861262145-1-msa8   Ready     <none>    57s       v1.13.5

伊斯迪奥

Istio 是一个开源的“服务网格”,它将自己透明地分层到现有的分布式基础设施上。

“服务网格”是相互连接的服务相互交互的抽象。这种抽象有助于降低分布式环境中管理应用程序的连接性、安全性和可观察性的复杂性。

Istio 通过提供一个完整的解决方案来帮助解决这些问题,该解决方案对“网格”内的连接服务进行洞察和操作控制。Istio 的一些核心功能包括:

  • HTTP、gRPC、TCP 连接上的负载平衡
  • 具有路由、重试和故障转移功能的流量管理控制
  • 包括度量、跟踪和可观察性组件的监控基础架构
  • 端到端 TLS 安全性

在现有的 Kubernetes 集群上安装 Istio 非常简单。关于安装指南,看看 @nethminiromina 的这篇精彩帖子:

[## Istio 分步指南第 2 部分—开始使用 Istio

嗨!欢迎来到我的 Istio 循序渐进教程系列。通过这个教程,我会告诉你如何安装 Istio 在…

medium.com](https://medium.com/devopslinks/istio-step-by-step-part-02-getting-started-with-istio-c24ed8137741)

从下载的 Istio 包目录创建自定义资源定义(CRD ):

kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml

接下来,从打包的“一体化”清单中将 Istio 运营商资源部署到集群:

kubectl apply -f install/kubernetes/istio-demo.yaml

部署完成后,我们应该会在istio-system名称空间中看到以下服务列表:

确保所有吊舱都处于Running状态,并且上述服务可用。根据安装设置,启用对default名称空间的侧车注入:

kubectl label namespace default istio-injection=enabled --overwrite

Istio 交通管理

Istio 提供简单的规则和流量路由配置来设置服务级别属性,如断路器、超时和重试,以及部署级别任务,如 A/B 测试、canary 部署和分阶段部署。

Istio 交通管理的核心是飞行员和特使。Pilot 是管理服务发现和所有服务之间的智能流量路由的中心运营商,它通过翻译高级路由规则并将它们传播到必要的特使侧车代理。

Envoy 是一个高性能代理,用于协调网格中服务的所有入站和出站流量。它被部署为一个侧车集装箱,所有 Kubernetes 豆荚都在网格内。Envoy 的一些内置功能包括:

  • 服务发现
  • 负载平衡
  • HTTP 和 gRPC 代理
  • 基于%流量分割的分阶段部署
  • 丰富的指标
  • TLS 终端、断路器、故障注入等等!

我们将使用 Istio 的流量管理和遥测功能在我们的集群中部署、服务和监控 ML 模型。

出口和入口

Istio 通过简单的规则配置将流量管理从基础设施中分离出来,以管理和控制服务之间的流量。

为了让流量流入和流出我们的“网格”,我们必须设置以下 Istio 配置资源:

  • Gateway:在“网格”边缘运行的负载均衡器,处理传入或传出的 HTTP/TCP 连接。
  • VirtualService:管理“网格”内 Kubernetes 服务之间流量路由的配置。
  • DestinationRule:路由后服务的策略定义。
  • ServiceEntry:内部服务配置附加条目;可以为内部或外部端点指定。

配置出口

默认情况下,支持 Istio 的应用程序无法访问集群外部的 URL。由于我们将使用 S3 存储桶来托管我们的 ML 模型,我们需要设置一个 ServiceEntry 来允许从我们的 Tensorflow 服务部署到 S3 端点的出站流量:

创建ServiceEntry规则以允许出站流量通过定义的端口到达 S3 端点:

kubectl apply -f resnet_egress.yamlserviceentry "aws-s3" created

配置入口

为了允许传入流量进入我们的“网格”,我们需要设置一个入口 [Gateway](https://istio.io/docs/tasks/traffic-management/ingress/#configuring-ingress-using-an-istio-gateway)。我们的Gateway将通过公开端口31400接收流量来充当负载平衡代理:

通过指定标签选择器istio=ingressgateway使用 Istio 默认控制器,这样我们的入口网关 Pod 将是接收该网关配置并最终公开端口的设备。

创建我们上面定义的Gateway资源:

kubectl apply -f resnet_gateway.yamlgateway "resnet-serving-gateway" created

张量流服务

Tensorflow 服务提供灵活的 ML 服务架构,旨在为 gRPC/REST 端点上的 ML 模型提供服务。

在这篇文章中,我们将使用一个预先训练好的、导出的 ResNet 模型作为我们在服务基础设施上部署的例子。

S3 模型库

为了访问 ML 模型,Tensorflow Serving 将任意文件系统路径的加载器抽象为接口,并提供 GCS 和 S3 云存储文件系统的开箱即用实现。

使用 AWS 控制台创建ml-models-repository S3 桶,在桶上设置 IAM 用户和角色。

NHWC模型架构上传到ml-models-repository桶中,目录结构如下:

resnet/  
  1/
    saved_model.pb
    variables/
      variables.data-00000-of-00001
      variables.index

为了安全地从我们的桶中读取,使用 S3 访问凭证创建一个 Kubernetes 秘密:

kubectl create secret generic s3-storage-creds \
  --from-literal=access_id=$AWS_ACCESS_KEY_ID \
  --from-literal=access_key=$AWS_SECRET_ACCESS_KEYsecret "s3-storage-creds" created

Kubernetes 部署

以下清单将 Tensorflow 定义为 Kubernetes Deployment,以Service为前端,以公开服务器的 gRPC 和 REST 端点:

上面清单定义中的一些要点需要注意:

  • 展开有两个标签app=resnet-servingversion=v1
  • 该服务选择并公开 gRPC 端口9000和 REST 端口9001app=resnet-serving标签上的部署。
  • ConfigMap 中的model_config_list protobuf 可用于定义模型路径和版本策略;在我们的例子中,我们已经将模型固定在版本1上进行加载。

将 Tensorflow 服务资源部署到集群中:

kubectl apply -f resnet_serving_v1.yamldeployment "resnet-serving" created
service "resnet-serving" created
configmap "tf-serving-models-config" created NAME                              READY     STATUS    RESTARTS   AGE
resnet-serving-65b954c449-6s8kc   2/2       Running   0          11s

正如所料,Pod 应显示有两个集装箱在其中运行,主tensorflow-serving集装箱和istio-proxy侧车。

检查 Pod 中的tensorflow-serving容器日志,以验证服务器正在运行,并且已经成功加载了从我们的 S3 存储库中指定的模型:

kubectl logs resnet-serving-65b954c449-6s8kc -c tensorflow-serving2019-03-30 22:31:23.741392: I external/org_tensorflow/tensorflow/contrib/session_bundle/bundle_shim.cc:363] **Attempting to load native SavedModelBundle in bundle-shim from: s3://ml-models-repository/resnet/1**2019-03-30 22:31:23.741528: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:31] **Reading SavedModel from: s3://ml-models-repository/resnet/1**2019-03-30 22:31:33.864215: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:285] **SavedModel load for tags { serve }; Status: success. Took 10122668 microseconds.**2019-03-30 22:31:37.616382: I tensorflow_serving/core/loader_harness.cc:86] **Successfully loaded servable version {name: resnet version: 1}**2019-03-30 22:31:37.622848: I tensorflow_serving/model_servers/server.cc:313] **Running gRPC ModelServer at 0.0.0.0:9000 ...**2019-03-30 22:31:37.626888: I tensorflow_serving/model_servers/server.cc:333] **Exporting HTTP/REST API at:localhost:9001 ...**

Tensorflow 服务中 S3 客户端的错误导致大量垃圾警告日志。这可以通过设置*TF_CPP_MIN_LOG_LEVEL=3*环境变量来关闭。

模型部署和 Canary 推广

到目前为止,我们已经用 Kubernetes、Istio 和 Tensorflow 服务建立了我们的基础设施。现在,我们可以开始对我们的模型进行版本控制,设置到指定部署的路由,然后利用 Istio 的流量分割规则执行模型服务器部署的阶段性 canary 部署。

设置 V1 路由

我们需要设置流量规则,以便Gateway在接收请求时知道路由到什么服务。

该规则由一个VirtualService定义,它允许路由到目的地“网状”服务,而无需了解基础设施中的底层部署。下面的VirtualService连接到我们之前定义的Gateway上,将 100%的流量路由到端口9000.v1子集的resnet-servingDestinationRule资源用于定义VirtualService的路由策略。

应用以下VirtualServiceDestinationRule清单:

kubectl apply -f resnet_v1_routing.yamlvirtualservice "resnet-serving" created
destinationrule "resnet-serving" created

在这篇文章中,我们没有公开任何公共负载平衡器或者在我们的集群上设置 TLS。因此,目前可以在端口转发网关端口上发送测试流量:

kubectl -n istio-system port-forward istio-ingressgateway-5b64fffc9f-xh9lg 31400:31400Forwarding from 127.0.0.1:31400 -> 31400

使用以下 Tensorflow 服务 python gRPC 客户端对输入图像进行预测请求:

python tf_serving_client.py --port=31400 --image=images/001.jpgname: "resnet"
version {
  value: 1
}
signature_name: "serving_default"dtype: DT_INT64
tensor_shape {
  dim {
    size: 1
  }
}
int64_val: 228

运行一个小负载测试,并在 Istio Mesh Grafana dashboard 上观察 p50、p90 和 p99 服务器端延迟:

这种延迟时间非常糟糕,原因有几个:

  • (相对)低计算配置文件—每个节点 2 个 CPU。
  • Vanilla Tensorflow 服务二进制文件未针对底层 CPU 平台进行优化。

在我们的 Mux 工程博客的以下帖子中,解释了构建 CPU 优化 Tensorflow 服务二进制的技术,以及针对延迟/吞吐量的性能调整。

[## 我们如何将 Tensorflow 服务性能提高 70%以上

Tensorflow 已经发展成为事实上的 ML 平台,在行业和研究领域都很受欢迎。需求和支持…

mux.com](https://mux.com/blog/tuning-performance-of-tensorflow-serving-pipeline/)

模型部署 V2

比方说,我们的v1模型表现不佳,我们希望部署新的模型版本以及优化的 TensorFlow 服务二进制文件。对模型部署的更改应该始终以迭代的方式进行,以便新模型的行为和性能可以在作为 GA 推广到所有客户端之前得到适当的测试和验证。

我们的新模型部署将使用新的Resnet-50 v2模型和更新的 CPU 优化 Tensorflow 服务映像。

ResNet-50 v2 保存的模型上传到resnet/2/路径下的 S3 桶中,目录层次与之前相同。然后,创建一个新的部署和配置图,它将加载并提供resent模型的2版本。

与以前的清单相比,更改如下:

diff --git a/tf_serving.yaml b/tf_serving_v2.yaml
index 90d133d..05047a3 100644
**--- a/tf_serving.yaml
+++ b/tf_serving_v2.yaml**@@ -1,10 +1,10 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
**-  name: resnet-serving
+  name: resnet-serving-v2**
@@ -13,7 +13,7 @@ spec:
   metadata:
     labels:
       app: resnet-serving
**-        version: v1
+        version: v2** spec:
      containers:
       - name: tensorflow-serving
**-        image: tensorflow/serving:latest
+        image: masroorhasan/tensorflow-serving:cpu**@@ -55,32 +55,15 @@ spec:
       volumes:
       - name: tf-serving-models-config
         configMap:
**-          name: tf-serving-models-config
+          name: tf-serving-models-config-v2**
___
apiVersion: v1
kind: ConfigMap
metadata:
**-  name: tf-serving-models-config
+  name: tf-serving-models-config-v2**
@@ -90,19 +73,8 @@ data:
         model_platform: "tensorflow",
         model_version_policy: {
           specific: {
**-            versions: 1
+            versions: 2**

在这里可以找到v2部署和配置图的完整清单。这里需要注意一些重要部分:

  • 新部署更新了版本标签version=v2
  • 更新 Docker 镜像masroorhasan/tensorflow-serving:cpu 是预建的 CPU 优化二进制。
  • ConfigMap 还与新版本策略相冲突,以专门获取模型的版本2

将部署应用到群集:

kubectl apply -f resnet_serving_v2.yamldeployment "resnet-serving-v2" created
configmap "tf-serving-models-config-v2" created

请注意,我们不需要更新resnet-serving服务,它在标签选择器app=resnet-serving上位于两个部署的前面。

设置 V2 金丝雀路由

现在我们已经有了新的模型部署,我们希望逐步向一部分用户推广它。

这可以通过更新我们的VirtualService来实现,将一小部分流量路由到v2子集。

我们将保持谨慎,更新我们的VirtualService以将 30%的传入请求路由到v2模型部署:

kubectl replace -f resnet_v2_canary.yamlvirtualservice "resnet-serving" replaced
destinationrule "resnet-serving" replaced

运行另一个负载测试,观察 Istio Mesh 仪表板,了解两个版本的resnet-serving工作负载的延迟指标。

按目的地划分的请求显示了类似的模式,流量在resnet-servingresnet-serving-v2部署之间分流。

设置 V2 路由

一旦 canary 版本满足模型行为和性能阈值,部署就可以升级为面向所有用户的 GA。下面的VirtualServiceDestinationRule被配置为将 100%的流量路由到我们的模型部署的v2

更新路由规则,以将v2提升为所有传入流量的 GA:

kubectl replace -f resnet_v2_routing.yamlvirtualservice "resnet-serving" replaced
destinationrule "resnet-serving" replaced

当一个负载测试正在运行时,网格仪表板将显示流量完全从v1转移,而是流入我们部署的v2

自动化金丝雀释放

到目前为止,我们已经对集群监控的模型性能进行了新模型版本的逐步、分阶段部署。然而,手动更新流量规则不符合操作可扩展性的精神。

Istio 流量路由配置可用于通过编程调整下游服务版本之间流量的相对权重来执行 canary 发布。在本节中,我们将使用 Weaveworks 的开源渐进式金丝雀部署工具来自动化金丝雀部署: Flagger 。

Flagger 是一家 Kubernetes 运营商,它使用 Istio 和 App Mesh 流量路由功能,基于自定义的 Prometheus 指标,自动迭代部署和推广 canary 版本。

让我们克隆 Flagger 存储库并创建服务帐户、CRD 和 Flagger 操作员:

git clone git@github.com:weaveworks/flagger.git

按照以下顺序创建服务帐户、CRDs 和操作员:

# service accounts
kubectl apply -f flagger/artifacts/flagger/account.yaml# CRD
kubectl apply -f flagger/artifacts/flagger/crd.yaml# Deployment
kubectl apply -f flagger/artifacts/flagger/deployment.yaml

应该在istio-system名称空间中创建 Flagger 部署。这是将对标有kind: Canary的客户资源进行操作的主要操作员。

Flagger 采用了 Kubernetes 部署,如resnet-serving,并创建了一系列资源,包括 Kubernetes 部署(初级 vs 金丝雀)、ClusterIP服务和 Istio 虚拟服务。

由于大量手动流量路由服务将由 Flagger 运营商负责,我们需要清理之前 Istio 流量路由相关资源和v2服务部署的集群。

# clean up routing
kubectl delete -f resnet_v1_routing.yaml
kubectl delete -f resnet_serving_v2.yaml
kubectl delete -f resnet_v2_routing.yaml# clean up svc
kubectl delete svc/resnet-serving

定义一个将引用我们的resnet-serving模型部署的 Flagger Canary 定制资源:

应用清单来创建 Canary 资源:

kubectl apply -f flagger_canary.yamlcanary "resnet-serving" created

如上所述,这将在创建一系列 Kubernetes 资源的同时初始化金丝雀。

要触发自动 canary 升级,请通过更新容器映像来触发部署:

kubectl set image deployment/resnet-serving \
  tensorflow-serving=masroorhasan/tensorflow-serving:cpu

此时,Flagger 操作员将检测到部署修订中的更改,并对新的部署进行排队:

当 canary 部署升级为 GA 时,Flagger 将自动缩减旧部署。在部署期间应用对部署的更改将触发 Flagger 重新开始分析和重新部署。

包扎

在这篇文章中,我们通过在 Kubernetes 基础设施上部署 TensorFlow 服务来构建一个 ML 服务环境。然后,我们利用 Istio 的智能流量路由功能,以分阶段部署的方式管理模型部署。最后,我们在集群上部署了 Flagger operator,以自动化分阶段部署 canary 的过程。

虽然我们选择关注 ML 模型的服务方面,但是有许多框架和工具可以帮助整合端到端的 ML 管道。其中一些包括(除其他外):

  • Kubeflow :在 Kubernetes 上提供内聚培训和服务基础设施的工具和框架的集合。
  • SeldonCore :提供一个运行时 ML 图形引擎来管理 Kubernetes 上的服务 ML 模型。
  • Clipper :一个预测服务系统,供数据科学家在 Docker-only 或 Kubernetes 环境中使用。
  • Pipeline.ai :汇集了许多流行的开源工具来构建、实验端到端的机器学习管道。
  • 云 ML 服务: [Google ML 引擎](https://cloud.google.com/ml-engine/)、 AWS SageMaker 和 Azure ML 服务

感谢您的阅读,我希望这篇文章有助于在 Kubernetes 上构建 TensorFlow 模型部署。我很想听听你对 ML 服务基础设施的设置——请随意联系 Twitter。感谢阅读!

参考文献

[## 数字海洋上的 Kubernetes

在云中部署和管理容器工作负载的最简单方式。

www.digitalocean.com](https://www.digitalocean.com/products/kubernetes/) [## 服务模型| TFX | TensorFlow

TensorFlow 服务是一个灵活、高性能的机器学习模型服务系统,专为生产…

www.tensorflow.org](https://www.tensorflow.org/tfx/guide/serving) [## 伊斯迪奥

连接、保护、控制和观察服务。

istio.io](https://istio.io/) [## 云对象存储|随处存储和检索数据|亚马逊简单存储服务

亚马逊简单存储服务(亚马逊 S3)是一种对象存储服务,提供行业领先的可扩展性、数据…

aws.amazon.com](https://aws.amazon.com/s3/) [## 将 Tensorflow 性能提高 70%

Tensorflow 已经发展成为事实上的 ML 平台,在行业和研究领域都很受欢迎。需求和支持…

mux.com](https://mux.com/blog/tuning-performance-of-tensorflow-serving-pipeline/) [## 介绍

Flagger 是一家渐进式交付 Kubernetes 运营商

docs.flagger.app](https://docs.flagger.app)

部署您的数据科学模型

原文:https://towardsdatascience.com/deploy-your-data-science-model-7b81eea6c98?source=collection_archive---------7-----------------------

第 1 部分:用 Pickle 或 Joblib 从笔记本上删除

Photo by SpaceX on Unsplash

作为一名初学数据科学的学生,到目前为止,我的大部分训练都是在选择、训练和评估许多有监督的机器学习方法。大部分是在 Jupyter 笔记本上。

Jupyter 笔记本电脑是数据科学的天赐之物,它在一个方便的开发环境中促进了分段评估和建模,这一点怎么说都不为过。很难想象,如果数据科学家不得不执行并寻找错误,那么训练他们会有多困难。py 可执行文件。

然而,Jupyter 笔记本并不适合部署。在我最近参加的一次黑客马拉松中,我可以开发建模对象,但是我的 Python 代码迫使全栈开发人员使用 Django 来适应它(及其依赖项)。我觉得自己是个不必要的负担。从那以后,我一直在寻找方法来部署我的模型,并在我的模型和生产环境之间建立更多的桥梁。为什么让那些家伙独享乐趣?这是系列文章的第一部分,将记录我在部署模型时遇到的困难。希望我能让你一路上不那么伤心。

所以,首先要做的是。你在笔记本上建立了一个模型。除非您想在生产中每次都运行笔记本,否则您需要从笔记本中取出建模对象,以便它可以在*中运行。py 可执行文件。

一般来说,有两种我们称之为模型持久性的方法。pickle 方法和更面向数据的 Joblib 方法。Pickle 方法或通常所说的“Pickle”是将一个对象转换成字节流以便保存和加载。由于编程中的几乎所有东西在其核心都被表示为一个对象,所以您可以看到这是多么有用。

然而,Joblib 库被开发成更适合 python 对象(通常是 numpy 类型)。如果对象是大量基于 numpy 数组的,这将大大节省保存和加载的时间。您可以看到 Joblib 在数据科学中的价值,并从中推断出它可能是建模持久性的更好途径。你可以两者兼得。但总的来说,更大的数据集将从使用 Joblib 中受益。pickle 正在更新,以便更好地适应基于 numpy 的对象,但这是以后的事了。不过今天不用担心,我将向您展示这两种方法,因为它们都相对简单。

首先,让我从心爱的虹膜数据集建立一个快速模型。

我们得分吧。

唉。不是最高分。但这不是重点。现在我们有了模型,并且知道它可以工作,让我们保存并加载 Pickle。

用泡菜塑造坚持。

Pickle 是 Python 2 和 3 的原生版本,所以不需要 pip 安装。我们首先想出一个要保存的文件名,然后用 pickle 启动 dump()方法,将我们的模型对象(上面的 km)写入二进制文件。注意这里的“wb”很重要,它不能和“w”(只写)一起使用。它需要转换成二进制形式。文件名是任意的,也是任意的。我使用的 sav "扩展名。它可以是任何东西,也不需要有扩展名。在你方便的时候给它起个名字,什么对你的目的起作用。

Huzzah, it’s off the notebook!

恭喜你。您已经成功保存了您的第一个模型以供将来使用。您可以使用这个 load 命令在将来的笔记本中调用它,或者出于演示的目的,我们可以在同一个笔记本中进行调用。我们对 pickle 使用 load()方法,对 read-binary 使用参数“rb”。现在,km_loaded_pickle 是我们之前的 km 模型对象。它应该有和以前一样的属性和方法。

It works!

另一件有趣的事情是——加载的模型维护了模型的所有方法。您不需要再次导入库来运行它的方法,例如运行预测。整洁!

用 Joblib 建模持久性

用 Joblib 实现模型持久性的过程或多或少是相同的,但是在我看来稍微简单一些。但是,您需要导入 sklearn.externals.joblib 包。我们以与前面相同的方式设置文件名,并使用我们刚刚定义的文件名在 km 模型上执行 joblib.dump。

嘣,保存了同一个模型,已经用了两种方法了!我们在这里好运连连。让我们强有力地结束。现在使用之前的文件名,用 joblib.load()重新加载它。

现在我们有了它,重新加载它并使用它的属性。像以前一样,我们也可以运行模型的方法,比如 predict(),而不需要导入库。这些都是内置在对象中的。

警告:不要加载任何你自己都不信任的 pickle 或 Joblib 二进制文件。两者都无法抵御恶意代码。

Photo by Japheth Mast on Unsplash

这就是了。从起点到最终部署的第一步。我希望能在一周内完成这个系列的每一个连续部分。接下来,我想我们可能会将所有这些都放入 docker 容器中。如果您有任何问题、评论或担忧,请告诉我,或者我如何才能将这个系列变成我们都可以使用的有用的东西。

直到下一部分,编码快乐!

部署您的第一个分析项目

原文:https://towardsdatascience.com/deploy-your-first-analytics-project-9280ea31b0ac?source=collection_archive---------30-----------------------

数据专业人员权威指南(数据分析)

用 Heroku 部署 Lazada 的 Web 抓取仪表板

Source: Unsplash

问题陈述:

对于数据科学家来说,将您的应用程序部署到云中,让任何技术或非技术用户都可以访问它是非常重要的。根据我的工作经验,数据科学家创建机器学习模型,而工程师部署它们的期望已经不复存在。大多数时候,数据科学家需要同时做两件事:设计他们的数据模型和部署他们的数据应用程序(开发-运营)。

如果我们可以轻松自由地为我们的用户部署我们的数据应用程序,那该有多好。

进入 Heroku

Source Heroku

Heroku 是一个广泛使用的商业软件平台(PaaS ),它使数据专业人员更容易构建、管理和部署各种规模的应用程序。这意味着您现在可以专注于开发分析应用程序,而无需担心部署基础架构。Heroku 为您处理所有部署的繁重工作!

简而言之,无论您在本地 Jupyter 服务器上运行什么,您都可以将其部署到云上,供用户使用!

Source: Giphy

Heroku 在行动

Our Application in Big Picture, today we are going to learn how to deploy our application with Heroku

在本教程中,您将学习如何使用 Heroku 部署您的 Python Dashboard Web 应用程序。我们将部署仪表板来查看 Lazada 产品的价格下降并生成警报。

请随意欣赏这篇文章或访问我的 Github Repo 获取完整代码。或者向下滚动,欣赏这篇文章。

对于不熟悉我提到的仪表板 Web 应用程序的人来说。我正在建立一个基于 Lazada 报废产品价格变化的仪表板。每当用户修改下拉输入时,如果产品价格下降,应用程序会提醒用户。

我们的任务是用 Heroku 在云上部署这个应用程序。最终结果是一个链接,你可以分享给你的朋友或同事,以访问和监控 Lazada 产品的价格趋势。

Price Optimization Dashboard Scraped from Lazada over 3 days

以下是实现这一目标的关键步骤:

  1. 注册 Heroku 帐户
  2. 创建新应用程序
  3. 设置部署配置和库
  4. 使用 Heroku Toolbelt 部署您的第一个应用程序
  5. 调试和故障排除

注册 Heroku 帐户

访问 Heroku 并注册。然后,您会收到一封电子邮件通知,确认您的帐户创建。

一旦你准备好了,进入你的账户,你就可以访问你的个人应用主页。

Heroku Main Application Pages

创建新应用程序

继续点击页面右上角的新应用。输入您的应用程序名称,然后单击创建应用程序。

Creating new app

设置部署配置和库

Heroku 的第一页需要两个文件:requirements.txt 和 Procfile。

  1. requirements.txt 将在您运行应用程序时存储您的 Python 环境中的所有 Python 库和依赖项。您可以运行pip freeze > **requirements**.**txt** 将 Python 库转储到一个文件中
  2. Procfile 将指定部署标准,例如您使用的 dynos 类型。Dynos是在 Heroku 平台上运行和缩放 app 的容器模型。这是一种非常可扩展和可靠的方式来平衡流量,并让您的应用程序在小引擎单元内运行。在这种情况下,我们将使用 gunicorn 作为我们与 dynos 交互的接口。

Gunicorn 作为 Web 应用服务

Source

Gunicorn 是一个 WSGI 接口,这意味着它可以托管任何 Python 可编程 web 应用程序,并确保与我们的 Dash Python 和 Flask 库进行适当的通信。

Gunicorn 负责 web 服务器和 web 应用程序之间的任务。它还可以帮助您运行 web 应用程序的多个实例,检查实例的健康状况,并在负载平衡这些实例时根据需要重置它们。我们已经做了很多努力来优化它,所以我们可以很容易地使用它。酷!

只需将这一行代码放在 Procfile 中,指示 dynos 使用 gunicorn web 界面。

web: gunicorn app:server

使用 Heroku Toolbelt 部署您的第一个应用程序

使用 Heroku 有很多部署方式。但是我发现的最简单的方法之一是使用 Heroku Toolbelt。参考此链接下载工具箱。

然后我们将使用 git 和 heroku 命令来部署我们的应用程序。

Initiating git in your code repos and deploying it with heroku

然后一旦你把它推入 heroku,你会看到你的主机将安装你在 requirements.txt 中指定的所有库。

Installing libraries from requirements.txt

在服务器完成它的任务后,你将获得链接来访问我们的应用程序。

恭喜你,你刚刚在 Heroku 上部署了你的第一个应用!

YAY!! Source: Giphy

调试和故障排除

在大多数情况下,您会遇到一些部署问题。因此,要对此进行调试,您可以插入命令**heroku logs -tail.**

该命令将返回以下日志,这些日志将告诉您应用程序崩溃的原因。

Heroku Logs to debug

这里说我仪表盘上的模块不叫 app。这是因为我将我的主应用程序命名为 dashboard.py,而不是 app.py。这导致了错误,因为 Flask 找不到要运行的主应用程序脚本。因此,我们可以重命名为 app.py,然后再次推送应用程序。

如果你遇到更多的问题,只需谷歌日志错误,堆栈溢出或破折号文件。如果没有,请在这里随意评论,我会尽快回复。干杯:)

最终结果

恭喜你!!您已经部署了第一个数据应用程序。如果你做得正确,你将能够在你的 链接上访问应用程序。如果没有,请随意查阅我的 Github 代码或者在这里提出你的问题。

Price Optimization Dashboard Scraped from Lazada over 3 days

现在,使用 Heroku 释放和部署您的分析应用程序

更多参考

如果你需要更多的例子和更好的见解,Heroku 可以提供一些引擎。请随意访问以下链接。

  1. H eroku 主站点
  2. 将 Dash 部署到 Heroku
  3. Heroku 定价和服务

最后…

Source: Unsplash

我真的希望这是一本很棒的读物,是你发展和创新的灵感来源。

请在下面评论出来建议和反馈。就像你一样,我也在学习如何成为一名更好的数据科学家和工程师。请帮助我改进,以便我可以在后续的文章发布中更好地帮助您。

谢谢大家,编码快乐:)

关于作者

Vincent Tatan 是一名数据和技术爱好者,拥有在 Google LLC、Visa Inc .和 Lazada 实施微服务架构、商业智能和分析管道项目的相关工作经验。

Vincent 是土生土长的印度尼西亚人,在解决问题方面成绩斐然,擅长全栈开发、数据分析和战略规划。

他一直积极咨询 SMU BI & Analytics Club,指导来自不同背景的有抱负的数据科学家和工程师,并为企业开发他们的产品开放他的专业知识。

文森特还在 best top 上开设了他的一对一导师服务,指导你如何在谷歌、Visa 或其他大型科技公司获得你梦想中的数据分析师/工程师职位。 如果你正在寻找良师益友,请在这里预约他

最后,请通过 LinkedIn Medium或** Youtube 频道 联系文森特**

将您的机器学习模型部署为 REST API

原文:https://towardsdatascience.com/deploy-your-machine-learning-model-as-a-rest-api-4fe96bf8ddcc?source=collection_archive---------9-----------------------

部署机器学习模型对初学者来说可能听起来有些吓人,甚至对那些有一些经验的人来说也是如此。这就是为什么我决定花一整篇文章来谈论它。

Photo by Franck V. on Unsplash

读完这篇文章后,你将能够部署机器学习模型,并根据你想要的任何编程语言进行预测。没错,你可以坚持使用 Python,或者你可以通过 Java 或 Kotlin 直接在你的 Android 应用中进行预测。此外,您可以在您的 web 应用程序中直接使用该模型——选项是无限的。为了简单起见,我将使用邮递员。

然而,我不会解释如何将模型放在一个活动的服务器上,因为选项是无穷无尽的,这可能是另一个帖子的好主意。该模型将在您的本地主机上运行,所以不,您将无法从不同的网络访问它(但是可以随意谷歌如何将模型部署到 AWS 或类似的东西)。

我已经创建了下面的目录结构:

ML-展开

  • model / Train.py
  • app.py

现在如果你已经通过 Anaconda 安装了你的 Python,那么你可能已经预装了所有的库,除了 Flask 。因此,启动终端并执行以下命令:

pip install Flask
pip install Flask-RESTful

进展顺利吗? 好。现在让我们开始研究一些好东西吧。

制作一个基本的预测脚本

如果您正在按照目录结构进行操作,现在应该打开model/train . py文件。目标是载入 Iris 数据集,并使用简单的决策树分类器来训练模型。一旦训练完成,我将使用 joblib 库来保存模型,并且我还将向用户报告准确度分数。

这里没有什么复杂的,因为机器学习不是本文的重点,只有模型部署。以下是完整的脚本:

from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.externals import joblib

def train_model():
    iris_df = datasets.load_iris()

    x = iris_df.data
    y = iris_df.target

    X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
    dt = DecisionTreeClassifier().fit(X_train, y_train)
    preds = dt.predict(X_test)

    accuracy = accuracy_score(y_test, preds)
    joblib.dump(dt, 'iris-model.model')
    print('Model Training Finished.\n\tAccuracy obtained: {}'.format(accuracy))

部署

现在你已经准备好打开 app.py 文件并进行一些导入。你需要 os 模块,一些来自 FlaskFlask-RESTful的东西,10 秒钟前创建的模型训练脚本,以及 joblib 来加载训练好的模型:

import os
from flask import Flask, jsonify, request
from flask_restful import Api, Resource
from model.Train import train_model
from sklearn.externals import joblib

现在你应该从 Flask-RESTful 中创建一个 FlaskApi 的实例。没什么复杂的:

app = Flask(__name__)
api = Api(app)

接下来要做的是检查模型是否已经训练好了。在 Train.py 中,您已经声明了模型将被保存在文件iris-model . model中,如果该文件不存在,则应该先对模型进行训练。一旦训练完毕,你就可以通过 joblib 加载它:

if not os.path.isfile('iris-model.model'):
    train_model()

model = joblib.load('iris-model.model')

现在,您需要声明一个用于进行预测的类。Flask-RESTful使用这个编码约定,所以你的类需要从Flask-RESTful Resource模块继承。在类内部,可以声明 get()post() ,或者其他任何处理数据的方法。

我们将使用 post() ,因此数据不会直接通过 URL 传递。您需要从用户输入中获取属性(根据用户输入的属性值进行预测)。然后,可以调用 预测()加载模型的功能。仅仅因为这个数据集的目标变量是以( 0,1,2 )的形式而不是( 'Iris-setosa ',' Iris-versicolor ',' Iris-virginica' )的形式,您还需要解决这个问题。最后,您可以返回预测的 JSON 表示:

class MakePrediction(Resource):
    @staticmethod
    def post():
        posted_data = request.get_json()
        sepal_length = posted_data['sepal_length']
        sepal_width = posted_data['sepal_width']
        petal_length = posted_data['petal_length']
        petal_width = posted_data['petal_width']

        prediction = model.predict([[sepal_length, sepal_width, petal_length, petal_width]])[0]
        if prediction == 0:
            predicted_class = 'Iris-setosa'
        elif prediction == 1:
            predicted_class = 'Iris-versicolor'
        else:
            predicted_class = 'Iris-virginica'

        return jsonify({
            'Prediction': predicted_class
        })

我们就要到了,坚持住!您还需要声明一个路由,这是 URL 中用于处理请求的部分:

api.add_resource(MakePrediction, '/predict')

最后,告诉 Python 让在调试模式下运行应用:

if __name__ == '__main__':
    app.run(debug=True)

仅此而已。您已经准备好启动模型并进行预测,无论是通过 Postman 还是其他工具。

以防你遗漏了什么,这里有完整的 app.py 文件:

import os
from flask import Flask, jsonify, request
from flask_restful import Api, Resource
from model.Train import train_model
from sklearn.externals import joblib

app = Flask(__name__)
api = Api(app)

if not os.path.isfile('iris-model.model'):
    train_model()

model = joblib.load('iris-model.model')

class MakePrediction(Resource):
    @staticmethod
    def post():
        posted_data = request.get_json()
        sepal_length = posted_data['sepal_length']
        sepal_width = posted_data['sepal_width']
        petal_length = posted_data['petal_length']
        petal_width = posted_data['petal_width']

        prediction = model.predict([[sepal_length, sepal_width, petal_length, petal_width]])[0]
        if prediction == 0:
            predicted_class = 'Iris-setosa'
        elif prediction == 1:
            predicted_class = 'Iris-versicolor'
        else:
            predicted_class = 'Iris-virginica'

        return jsonify({
            'Prediction': predicted_class
        })

api.add_resource(MakePrediction, '/predict')

if __name__ == '__main__':
    app.run(debug=True)

好了,准备好了吗?

太好了。导航到根目录(其中app . py),启动终端并执行以下操作:

*python app.py*

大约一秒钟后,您会得到一个输出,显示应用程序正在本地主机上运行。

现在我将打开邮递员并执行以下操作:

  • 将方法更改为 POST
  • 输入 localhost:5000/predict 作为 URL
  • 在 Body 选项卡中,选择 JSON
  • 输入一些 JSON 进行预测

然后,您可以点击发送:

瞧啊。几乎立刻你就能从你的模型中得到预测。

最后的话

我希望你已经设法看完了这篇文章。如果你只是复制粘贴所有的东西,只要你安装了所有必要的库,你就可以开始了。

我强烈建议将这些新获得的知识用于您自己的数据集和您自己的业务问题。如果你在用 Python 之外的其他语言编写应用程序,并且只是将 Python 用于数据和机器学习相关的东西,这就很方便了。

感谢阅读,保重。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

* [## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)*

使用 tensorflow 服务和 kubernetes 部署您的机器学习模型

原文:https://towardsdatascience.com/deploy-your-machine-learning-models-with-tensorflow-serving-and-kubernetes-9d9e78e569db?source=collection_archive---------6-----------------------

机器学习应用正在蓬勃发展,但数据工程师没有很多工具可以将这些强大的模型集成到生产系统中。在这里,我将讨论 tensorflow-serving 如何帮助您在产品中加速交付模型。这篇博文是关于服务机器学习模型的— 什么意思?

服务是你如何在训练后应用一个 ML 模型——从事 tensorflow 服务的 Noah Fiedel 软件工程师

为了说明 tensorflow 服务于的能力,我将介绍服务于对象检测模型的步骤。在我的 GitHub 上找到与本文相关的所有代码:https://github.com/fpaupier/tensorflow-serving_sidecar

Summary of a machine learning pipeline — here we focus on serving the model

张量流简而言之

Tensorflow 服务使您能够无缝地服务于您的机器学习模型。

  • 部署新版本的模型,让 tensorflow 服务优雅地完成当前请求,同时开始使用新模型服务新请求。
  • 分开考虑,数据科学家可以专注于构建出色的模型,而运营部门则可以专注于构建可服务于这些模型的高度灵活且可扩展的架构。

第 1 部分—预热:设置本地 tensorflow 服务器

在上线之前,最好确保你的服务器在本地工作。我在这里给出了大的步骤,在项目readme中找到更多的文档。
看看设置步骤以确保您能从本教程中获得最大收益:

  1. git 克隆https://github.com/fpaupier/tensorflow-serving_sidecar,创建 python3.6.5 虚拟环境并安装requirements.txt
  2. 获取 tensorflow 服务 docker 图片docker pull tensorflow/serving
  3. 得到一个模型来服务→我用这个,它执行对象检测更快 _rcnn_resnet101_coco
  4. 转到模型目录,用版本号重命名saved model子目录,因为我们在这里做的是 v1,让我们称它为00001(它必须是数字)。我们这样做是因为 tensorflow serving docker image 在搜索要提供的模型时会搜索以该约定命名的文件夹。
  5. 现在运行 tensorflow 服务器:
# From tensorflow-serving_sidecar/
docker run -t --rm -p 8501:8501 \
   -v "$(pwd)/data/faster_rcnn_resnet101_coco_2018_01_28:/models/faster_rcnn_resnet" \
   -e MODEL_NAME=faster_rcnn_resnet \
   tensorflow/serving &

在继续之前,请注意:

docker -v arg in our use case

这里我们绑定了容器的端口和本地主机。因此,当我们在localhost:8501上调用推断时,我们实际上将调用 tensorflow 服务器。

您还会注意到我们将本地主机目录faster_rcnn_resnet101_coco_2018_01_28——存储模型的地方——与容器/models/faster_rcnn_resnet路径链接起来。

请记住,此时savedModel.pb只在您的机器上,而不在容器中。

6.执行客户呼叫:

# Don't forget to activate your python3.6.5 venv

# From tensorflow-serving_sidecar/
python client.py --server_url "http://localhost:8501/v1/models/faster_rcnn_resnet:predict" \
--image_path "$(pwd)/object_detection/test_images/image1.jpg" \
--output_json "$(pwd)/object_detection/test_images/out_image1.json" \
--save_output_image "True" \
--label_map "$(pwd)/data/labels.pbtxt"

去查看--output_json 指定的路径,享受结果。(提供 json 和 jpeg 输出)

expected inference with our object detection model

很好,现在我们的模型运行良好,让我们将它部署到云上。

第 2 部分—在具有 tensorflow 服务的 kubernetes 集群上服务您的机器学习应用程序

在生产环境中,您希望能够随着应用程序负载的增加而扩展。你不希望你的服务器不堪重负。

An exhausted tensorflow server directly exposed over the network

为了避免这个问题,您将使用 kubernetes 集群来服务您的 tensorflow-server 应用程序。预期的主要改进:

  • 负载将在您的副本之间平衡,您无需考虑这一点。
  • 您是否希望在不停机的情况下部署新模型?没问题,kubernetes 支持你。执行滚动更新,逐步为您的新模型提供服务,同时适度终止旧模型上的当前请求。

a tensorflow server application running on many replicas in a k8s cluster, ensuring high availability to users

我们开始吧

首先,我们想要创建一个嵌入了对象检测模型的完整 docker 图像。一旦完成,我们将在 kubernetes 集群上部署它。我在谷歌云平台上运行我的例子,因为免费层使得免费运行这个教程成为可能。为了帮助你在 GCP 建立云环境,你可以点击这里查看我的教程。

创建自定义 tensorflow 服务 docker 图像

  1. 将服务映像作为守护程序运行:
docker run -d --name serving_base tensorflow/serving

2.将faster_rcnn_resnet101_coco模型数据复制到容器的models/文件夹中:

# From tensorflow-serving_sidecar/
docker cp $(pwd)/data/faster_rcnn_resnet101_coco_2018_01_28 serving_base:/models/faster_rcnn_resnet

3.提交容器以服务于faster_rcnn_resnet模型:

docker commit --change "ENV MODEL_NAME faster_rcnn_resnet" serving_base faster_rcnn_resnet_serving

注意:如果您使用不同的型号,相应地更改--change参数中的faster_rcnn_resnet

faster_rcnn_resnet_serving将成为我们新的服务形象。您可以通过运行docker images来检查这一点,您应该会看到一个新的 docker 图像:

docker images result after creating a custom tensorflow-serving image

4.停止服务基本容器

docker kill serving_base
docker rm serving_base

太好了,下一步是测试我们全新的faster_rcnn_resnet_serving 形象。

测试定制服务器

在 kubernetes 上部署我们的应用程序之前,让我们确保它正常工作。

  1. 启动服务器:
docker run -p 8501:8501 -t faster_rcnn_resnet_serving &

注意:确保您已经停止(docker stop <CONTAINER_NAME>)之前运行的服务器,否则端口8501可能会被锁定。

2.我们可以使用相同的客户端代码来调用服务器。

# From tensorflow-serving_sidecar/
python client.py --server_url "http://localhost:8501/v1/models/faster_rcnn_resnet:predict" \
--image_path "$(pwd)/object_detection/test_images/image1.jpg" \
--output_json "$(pwd)/object_detection/test_images/out_image2.json" \
--save_output_image "True" \
--label_map "$(pwd)/data/labels.pbtxt"

我们可以检查我们是否有相同的好的,现在让我们在kubernetes集群上运行它。

在 kubernetes 上部署我们的应用

除非你已经在 GCP 上运行了一个项目,否则我建议你检查一下谷歌云设置步骤。

我假设你已经创建并登录了一个名为tensorflow-servinggcloud项目

您将使用之前构建的容器映像faster_rcnn_resnet_serving在 Google 云平台中部署带有 Kubernetes 的服务集群。

  1. 登录您的项目,首先用gcloud projects list列出可用的项目,选择项目的PROJECT_ID并运行
# Get the PROJECT_ID, not the name
gcloud projects list # Set the project with the right PROJECT_ID, i.e. for me it is tensorflow-serving-229609
gcloud config set project tensorflow-serving-229609
gcloud auth login

2.创建一个容器集群

  • 首先,我们为服务部署创建一个 Google Kubernetes 引擎集群。由于免费试用的限制,您在这里不能使用超过 2 个节点,您可以升级或使用两个节点,这对我们的用例来说已经足够好了。在你的免费试用中,你的限额是 8 个 CPU。)
gcloud container clusters create faster-rcnn-serving-cluster --num-nodes 2 --zone 'us-east1'

您可以更新zone arg,您可以在中选择,例如 : europe-west1asia-east1 -您可以使用gcloud compute zones list检查所有可用的区域。你应该有这样的东西:

kubernetes cluster creation output

3.为 gcloud container 命令设置默认集群,并将集群凭证传递给 kubectl 。

gcloud config set container/cluster faster-rcnn-serving-cluster
gcloud container clusters get-credentials faster-rcnn-serving-cluster --zone 'us-east1'

之后您应该会看到这样的内容:

gcloud container clusters get-credentials output

4.上传我们之前构建的自定义 tensorflow 服务 docker 图像。让我们将我们的图像推送到 Google 容器注册表,这样我们就可以在 Google 云平台上运行它。

使用容器注册表格式和我们的项目 id 标记faster_rcnn_resnet_serving图像,用您的PROJECT_ID更改tensorflow-serving-229609。最后还要修改标签,这是我们的第一个版本,所以我把标签设为v0.1.0

docker tag faster_rcnn_resnet_serving gcr.io/tensorflow-serving-229609/faster_rcnn_resnet_serving:v0.1.0

如果你运行docker images,你现在会看到一个额外的gcr.io/tensorflow-serving-229609/faster_rcnn_resnet_serving:v0.1.0图像。

这个gcr.io前缀允许我们将图像直接推送到容器注册中心,

# To do only once
gcloud auth configure-dockerdocker push gcr.io/tensorflow-serving-229609/faster_rcnn_resnet_serving:v0.1.0

您已经成功地将您的图像推送到 GCP 集装箱注册中心,您可以在线查看:

docker image successfully pushed on Google Container Registry

5.创建 Kubernetes 部署和服务

该部署由一个由 Kubernetes 部署控制的 fast-rcnn 推理服务器的单一副本组成。副本通过 Kubernetes 服务和外部负载平衡器对外公开。

使用单个副本实际上没有意义。我这样做只是为了在自由层内通过。如果您只有一个实例来指导您的查询,那么负载平衡是没有用的。在生产设置中,使用多个副本。

我们使用示例 Kubernetes configfaster _ rcnn _ resnet _ k8s . YAML来创建它们。您只需要更新 docker 图像以在文件中使用,用您的实际图像全名替换行image: <YOUR_FULL_IMAGE_NAME_HERE>,看起来像这样:

image: gcr.io/tensorflow-serving-229609/faster_rcnn_resnet_serving@sha256:9f7eca6da7d833b240f7c54b630a9f85df8dbdfe46abe2b99651278dc4b13c53

您可以在容器注册表中找到它:

find your docker full image name on google container registry

然后运行以下命令

# From tensorflow-serving_sidecar/
kubectl create -f faster_rcnn_resnet_k8s.yaml

要检查部署和 pod 的状态,请使用kubectl get deployments来监视整个部署,使用kubectl get pods来监视部署的每个副本,使用kubectl get services来监视服务。

sanity check for deployment

一切正常运行可能需要一段时间。服务外部IP地址列在负载平衡器入口的旁边。您可以使用kubectl describe service命令来检查它:

kubectl describe service faster-rcnn-resnet-service

find the IP address to query upon to perform inference

查询您的在线模型

最后,让我们来测试一下。我们可以使用相同的客户端代码。简单地将前面使用的--server-url参数中的localhost替换为上面指定的负载平衡器入口的IP地址。

# From tensorflow-serving_sidecar/
python client.py --server_url "http://34.73.137.228:8501/v1/models/faster_rcnn_resnet:predict" \
--image_path "$(pwd)/object_detection/test_images/image1.jpg" \
--output_json "$(pwd)/object_detection/test_images/out_image3.json" \
--save_output_image "True" \
--label_map "$(pwd)/data/labels.pbtxt"

外卖食品

Tensorflow 服务提供了一个很好的基础,您可以依靠它以很少的开销在生产中快速部署您的模型。

  • 机器学习应用程序的容器化部署能够分离运营和数据科学家之间的关注点
  • Kubernetes 等容器编排解决方案与 tensorflow-serving 相结合,为不熟悉分布式计算的人提供了在几分钟内部署高可用性模型的可能性。

资源📚

  • Tensorflow 服务由谷歌的软件工程师 Noah Fiedel 解释,他从事 Tensorflow 服务。它让我们深入了解它是如何建造的以及建造的目的是什么https://www.youtube.com/watch?v=q_IkJcPyNl0
  • 免费提供预训练模型库https://github . com/tensor flow/models/blob/master/research/object _ detection/g3doc/detection _ model _ zoo . MD
  • Tyler Labonte medium post 将 tensorflow 模型导出为保存的检查点https://medium . com/@ tmlabonte/serving-image-based-deep-learning-models-with-tensor flow-servings-restful-API-d 365 c 16 a7 DC 4
  • 提供一个没有合适框架的 ML 模型是多么麻烦的例子https://towardsdatascience . com/how-to-build-and-deploy-a-lyrics-generation-model-framework-agnostic-589 f 3026 FD 53
  • Cloud ML,用于部署 ML 模型的 Google 托管解决方案:https://cloud . Google . com/ML-engine/docs/tensor flow/deploying-models

使用 Docker 在本地部署您的 RShiny 应用程序

原文:https://towardsdatascience.com/deploy-your-rshiny-app-locally-with-docker-427386010eba?source=collection_archive---------10-----------------------

我最喜欢在本地部署 RShiny 的方式是简单地将它打包成一个 docker 映像并运行它。在 docker 中运行任何应用程序都使其易于移植,并且是 2019 年普遍接受的分发应用程序的方式。

这个解决方案不需要 rshiny-server 或 shinyapps.io,这并不是因为我反对这些解决方案。我只是倾向于坚持一些最喜欢的部署方法,以防止我的头从身体上直接旋转下来。;-)

如果你不熟悉 docker,那么我有一个免费课程可供选择。第一个模块足以让你在一两个小时内启动并运行。在大多数情况下,如果你能使用命令行,你可以使用 docker。

在 Docker 中打包你的闪亮应用

现在我们已经介绍了一些日常工作,让我们开始建立你的 docker 形象。像任何项目一样,您希望将所有相关代码放在一个目录中。这样 docker 构建过程就可以访问它。

项目目录结构

➜ 2019-11-rshiny-app-docker tree
.
├── Dockerfile
├── README.md
├── app.R
└── environment.yml

0 directories, 4 files

这是一个非常简单的例子,一个 R 文件服务于我们的 RShiny 应用程序,应用程序。RDockerfile 有我们的构建指令, environment.yml 列出了我们的 conda 包,即 r-shiny 和 r-devtools。

我个人喜欢用康达安装我所有的科学软件。如果你喜欢用另一种方式安装你的软件,那就试试吧。重要的是,您的依赖项已经安装好,可以运行您的 RShiny 应用程序了。

RShiny 应用程序

这是一个非常简单的例子,直接取自 RShiny examples github repo,只做了一些修改。

Dockerfile 文件

docker 文件有我们的 docker 构建指令。它的语法相当简单。使用 FROM 选择基础映像,使用 run 在构建期间运行命令,使用 copy 复制文件,使用 CMD 定义启动命令。

确保您已经制作了应用程序。chmod 777 应用程序的可执行文件。否则下一步就没用了。

Conda 环境定义文件

同样,用 conda 安装您的软件是可选的。简直是我最喜欢的安装方式。;-)

name: r-shiny
channels:
  - conda-forge
  - defaults
dependencies:
  - python=3.6
  - r-devtools
  - r-shiny

构建 Docker 容器

现在我们已经准备好了所有的文件,让我们构建并运行 docker 容器!

docker build -t r-shiny-app .

运行我们的 RShiny 应用程序

现在我们已经构建了我们的应用程序,我们可以运行它了!

docker run -it -p 8080:8080 r-shiny-app

你应该看到一条消息说监听http://0 . 0 . 0 . 0:8080。一旦你看到一切都准备好了!在 localhost:8080 上打开您的浏览器,查看您的应用程序的运行情况!

最初发表于【https://www.dabbleofdevops.com】

在 AWS 系列— Lightsail 上部署您的 RShiny 应用程序

原文:https://towardsdatascience.com/deploy-your-rshiny-app-on-aws-series-lightsail-d56a05f85ad9?source=collection_archive---------40-----------------------

快速轻松地部署您的 RShiny 应用程序

如果您正在考虑为您的 RShiny 应用选择哪种部署场景,请不要再犹豫了!我已经为您计划了一整个系列的各种部署选项,以及为什么您应该选择每一个。

如果你像我一样,喜欢看视频而不是看博客,那就去我的 YouTube 频道看看这篇文章吧!

为什么应该使用 AWS Lightsail 进行 RShiny 部署?

部署场景像雪花一样。没有两个人是完全一样的!;-)对于不同的部署场景,您需要不同级别的电源和控制。这里我们将讨论 RShiny 部署,但它适用于几乎所有情况。

Lightsail 是整个 AWS 部署生态系统中相对较新的成员。与其他一些更强大的解决方案相比,它使部署 web 应用程序变得更加简单和高效。

如果符合以下条件,Lightsail 将是您部署的好选择:

  • 部署 web 应用程序或配置 web 服务器(Apache、NGINX)会让你感觉不舒服。
  • 你可以配置 web 服务器,但是你需要一些快速简单的东西。
  • 你有一个很小的应用程序,你不希望流量出现大的峰值。

现在,每一点都有其例外。对我自己来说,我知道如何配置 web 服务器,但我仍然喜欢让我的生活更轻松的工具。如果我需要一个快速启动并运行的演示,或者一个不会存在很长时间的小应用程序,我不会花时间去计划一些复杂的部署场景,这些场景包含可伸缩的节点。虽然这很有趣,但也有点矫枉过正。

简单地说,许多 AWS 部署工具是弹性的或自动伸缩的,这意味着您可以根据需求进行伸缩。Lightsail 非常简单,没有任何弹性。

不使用 AWS Lightsail 部署 RShiny 应用程序的理由

如果预计流量会出现大峰值,您就不要使用 Lightsail。那么您将需要一个具有自动扩展能力的更强大的解决方案。更强大通常意味着更复杂。由于 Lightsail 将创建您的 EC2 实例,您可以随时从 Lightsail 开始,然后在需要更多功能时进行迁移。

创建您的 RShiny 基本实例

本教程的其余部分将假设您有一个 AWS 帐户。

前往AWS light sail 主页。

选择实例位置和实例类型。我建议选择 NGINX 来证明你未来的生活。这可能是不必要的,取决于你的设置,但我喜欢它。更多关于 NGINX vs 无 NGINX 的稍后!

接下来点击 Change SSH key pair 来下载您的 SSH key pair。我知道它奇怪的措辞,但只要点击它。

一旦你点击它,你可以选择改变密钥对或者下载默认的。选择其中一个场景,并确保保存它!

最后,为您的实例命名,然后单击“创建实例”。

现在您已经准备好了实例,我们可以进入下一部分,实际上是运行 RShiny!

连接到您的 RShiny 实例

点击左上角返回 AWS Lightsail 主页。从那里,您将有一个实例列表。找到您之前创建的实例。我的名字叫 RShiny。

使用 web 界面连接

实际上,您可以单击 3 个垂直的橙色点,然后单击 connect,这将在 web 浏览器中显示一个终端。相当整洁!只需按连接,你的浏览器将启动一个终端。

使用终端连接

你也可以使用终端连接,这也是我想做的。我对自己的热键很挑剔!在该框的第二行中,它应该在左侧显示“正在运行”,并在右侧显示 IP 地址。IP 地址是您的公共 IP 地址。

chmod 600 ~/.ssh/LightsailDefaultKey-us-east-1.pem ssh -i ~/.ssh/LightsailDefaultKey-us-east-1.pem [bitnami@54.163.72.140](mailto:bitnami@54.163.72.140)

确保使用 ssh 密钥和实例的 IP 地址。我总是把我的从下载移到~/.ssh。

安装 RShiny 并运行一个示例

现在,我用康达安装了几乎所有的科学软件。如果你有其他的安装方法,那就试试吧。只要你把它安装好,你就万事俱备了!

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh chmod 777 *sh ./Miniconda3-latest-Linux-x86_64.sh -bexport PATH=$HOME/miniconda3/bin:$PATH # Conda forge has sooooo many packages conda config --add channels conda-forge # Create a conda environment called r-shiny and install the package r-shiny (add whatever packages you want here too) conda create -y -n r-shiny r-shiny

完成所有这些后,您应该会看到类似这样的内容。现在,如果您使用-b 安装了 Miniconda3,您将没有正确的 shell 别名来运行“conda activate”。使用旧的“source activate”语法,你就可以了。

source activate r-shiny

就是这样。现在我们准备开始玩一些代码!

从一个例子开始

即使你已经准备好了一个现实世界的应用程序,我还是建议你从最简单的场景开始。然后,当事情出错时,你就知道是哪里出错了。

这段代码主要摘自闪亮的 github repo 示例。

**#!/usr/bin/env Rscript**
library(shiny)

# Define UI for app that draws a histogram ----
ui <- fluidPage(

  # App title ----
  titlePanel("Hello Shiny!"),

  # Sidebar layout with input and output definitions ----
  sidebarLayout(

    # Sidebar panel for inputs ----
    sidebarPanel(

      # Input: Slider for the number of bins ----
      sliderInput(inputId = "bins",
                  label = "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)

    ),

    # Main panel for displaying outputs ----
    mainPanel(

      # Output: Histogram ----
      plotOutput(outputId = "distPlot")

    )
  )
)
# Define server logic required to draw a histogram ----
server <- function(input, output) {

  # Histogram of the Old Faithful Geyser Data ----
  # with requested number of bins
  # This expression that generates a histogram is wrapped in a call
  # to renderPlot to indicate that:
  #
  # 1\. It is "reactive" and therefore should be automatically
  #    re-executed when inputs (input$bins) change
  # 2\. Its output type is a plot
  output$distPlot <- renderPlot({

    x    <- faithful$waiting
    bins <- seq(min(x), max(x), length.out = input$bins + 1)

    hist(x, breaks = bins, col = "#75AADB", border = "white",
         xlab = "Waiting time to next eruption (in mins)",
         main = "Histogram of waiting times")

    })

}
# If you want to automatically reload the app when your codebase changes - should be turned off in production
options(shiny.autoreload = TRUE)
options(shiny.host = '0.0.0.0')
options(shiny.port = 8080)
# Create Shiny app ---- 
shinyApp(ui = ui, server = server)

我创建了一个文件夹 ~/rshiny-app/并将这段代码粘贴到 app.R. chmod 777 你的应用程序中。r 文件并运行它!

打开端口

如果你在端口 8080 上访问你的公共 IP 地址,它将不起作用,如果你不习惯 AWS 默认锁定端口,这将非常令人沮丧。

你要做的是进入你的 Lightsail 主页,点击右上角的 3 个垂直的橙色圆点。然后单击管理。

一旦有点击网络。

在防火墙下,单击添加另一个并添加端口 8080。确保点击保存!

给它几秒钟然后去公-ip:8080。

您应该看到您的 RShiny 实例启动并运行了!

后续步骤

根据您的需要,本教程的下一步是完全可选的。如果我正在部署一个演示,或者甚至是一个内部使用的非常小的应用程序,我可能会在这里停止它。

在 PM2 的进程管理器下运行你的应用

如果你以前从未使用过进程管理器,它听起来很像。流程管理器是你的应用程序的包装器,在这里是我们的应用程序。R RShiny 应用程序。它负责启动、停止、记录等等。

我最喜欢的进程管理器是 pm2 。它最初是为 Node.js 应用程序编写的,但实际上它适用于所有应用程序。我已经将它用于 bash 脚本(是的,我知道)、perl、python 和 R 以及 Node.js 应用程序。

顺便提一下,我认为学习一些可以跨多个部署场景使用的工具是非常有益的。我知道 RShiny 有自己的部署策略,但是我真的不想为每一种应用程序类型都学习一种新方法。我部署了很多应用程序,这对我来说不是一个合理的目标。相反,我知道如何使用一些不同的工具,主要是 pm2 和 NGINX,来运行我的 web 应用程序。(好了我说完了我和我的观点!)

Ctrl / Cmd + C 才能杀死你的 app.R。

conda install -y nodejs npm install -g pm2 pm2 start --name rshiny-example-app app.R --interpreter="Rscript"

如果你运行“pm2 日志应用程序名称”,你会看到你的日志

pm2 logs rshiny-example-app

您可以做许多其他有趣的事情,甚至将您的应用程序集群化以运行多个实例,以及创建启动脚本。PM2 甚至可以检测你在什么系统上,并相应地创建一个启动脚本!

使用 NGINX 服务您的应用

一旦我们的 RShiny 应用程序在我们的流程管理器下运行良好,就该用 NGINX 来服务它了。

在各种网络服务器下配置你的 RShiny 应用的最终权力(据我所知)是这里的。这里我只讨论一个 NGINX 场景。

sudo su - 
# Or nano or whatever you want
vi /opt/bitnami/nginx/conf/bitnami/bitnami.conf

在“服务器”块的正上方放入这段代码

map $http_upgrade $connection_upgrade { default upgrade; '' close; }

然后,在您的服务器块中,放置以下位置块:

location / { 
   proxy_set_header Host $host; 
   proxy_set_header X-Real-IP $remote_addr; 
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
   proxy_set_header X-Forwarded-Proto $scheme; 
   proxy_set_header Host $http_host; proxy_pass http://localhost:8080/;   proxy_redirect / $scheme://$http_host/; 
   proxy_http_version 1.1; 
   proxy_set_header Upgrade $http_upgrade; 
   proxy_set_header Connection $connection_upgrade; 
   proxy_read_timeout 20d; proxy_buffering off; 
}

这就是它看起来的样子。

重新启动 bitnami nginx 服务。

/opt/bitnami/ctlscript.sh restart nginx

去你的公共 IP 地址没有端口,你会看到你闪亮的应用!

总结性的新闻报导

这个帖子到此为止!在本系列即将发布的文章中,我将介绍如何使用更复杂的 RShiny 部署方法,包括 EC2、使用自动伸缩组、Swarm 和 Kubernetes。

【https://www.dabbleofdevops.com】最初发表于

在 Google 计算引擎上部署 ML 模型

原文:https://towardsdatascience.com/deploying-a-custom-ml-prediction-service-on-google-cloud-ae3be7e6d38f?source=collection_archive---------5-----------------------

简单的指南

使用 Flask 在 Google Compute Engine 上部署一个对象检测模型作为 API,并使用 NGINX 和 Gunicorn 设置一个生产服务器

from Unsplash

介绍

将机器学习模型作为 web 服务来部署和维护可能是昂贵且棘手的。我最近开始在我的项目中使用 Compute Engine,并发现 Google Cloud 非常像 AWS,有一个相当陡峭的学习曲线。在这篇文章中,我将讨论如何在 Google Compute Engine 上用 Flask 部署一个对象检测模型作为 API。

这篇教程的代码可以在这里找到。

您将在本教程中学到的内容:

  • 使用预训练的对象检测模型来检测和注释图像内的各种对象。
  • 构建一个简单的 Flask API,通过 POST 请求接收图像,并提供预测的标签、边界框坐标、框颜色和检测对象的置信度。
  • 设置 Google 云项目并配置计算引擎实例。
  • 使用 Miniconda 安装和设置虚拟环境。
  • 部署一个 Flask 应用程序并设置一个稳定的生产服务器,该服务器可以使用 NGINX 和 Gunicorn 处理大量请求。

Sample Model Output

要求:物体检测、Flask 和启用计费的谷歌云账户的基本知识。

注意:谷歌云有一个免费的等级项目,为新用户提供 300 美元的积分。

应用引擎 vs 计算引擎

App Engine 和 Compute Engine 是两个可以用来部署 ML 模型的 Google 云产品。这两种服务的主要区别在于,计算引擎是基础架构即服务(IaaS),而应用引擎是构建在计算引擎之上的平台即服务(PaaS)。

这基本上意味着计算引擎是一种基本服务,而应用引擎提供额外的服务来简化 web 应用的部署、维护和扩展,尽管每小时的成本更高。App Engine 的好处在于,它会根据传入请求的数量自动伸缩,让您专注于应用程序,而不是系统管理。然而,如果您有持续的 API 请求负载,保持计算引擎实例运行会更便宜。

from Ruby Garage

对象检测器项目结构

在本教程中,我不会深入研究对象检测代码的细节。我将使用的代码是阿德里安·罗斯布鲁克关于 YOLO 物体探测的优秀教程的编辑版本,打开 CV ,可以在这里找到。我们将使用在 COCO 数据集上训练的 YOLOv3 模型,这是一个大规模的对象检测、分割和字幕数据集,包含 80 个对象类别的 33 万张图像。

.
├── yolo-coco              # Pre-trained model files
    └── coco.names         # Object labels (person, car, etc.)
    └── yolov3.cfg         # Model configuration
    └── yolov3.weights     # Model weights              
├── app.py                 # Flask app serving predictions
├── yolo.py                # Functions to generate predictions
├── requirements.txt       # Dependencies
└── README.md

yolo.py 中的两个主要函数是 download_model_weightsget_predictions,期望一个单独的编码图像作为输入。**get _ predictions函数处理编码的输入图像,加载并运行模型,并返回每个检测到的对象的方框坐标、方框显示颜色、标签和置信度。首次在本地或 GCE 上运行应用程序时,会自动下载模型权重。

烧瓶 API

我们的 Flask 应用程序位于 app.py 中,有一个端点 /predict。在更高的层面上,我们希望我们的应用程序能够:

  • 可被其他计算机访问(您的客户!)
  • 在端点接受带有编码图像的 POST 请求 /predict
  • 调用 yolo.py 中的对象检测函数,并将预测作为响应返回
  • 始终保持活力,能够处理大量请求
from flask import Flask, jsonify, request
from yolo import get_predictionsapp = Flask(__name__)[@app](http://twitter.com/app).route(“/predict”, methods=[‘POST’])
def predict():
   predictions = get_predictions(request) return jsonify(predictions)if __name__ == “__main__”:
   app.run(host=’0.0.0.0', port=5000, debug=True)

默认情况下,Flask 在 127.0.0.1 上托管应用程序,该应用程序指的是您计算机的本地 IP 地址,只能由与您暴露的服务器运行在同一台计算机上的程序访问。显然,我们需要我们的应用程序能够在部署它的计算引擎实例之外被访问。将主机地址更改为 0.0.0.0 允许我们使用 GCE 实例的外部 IP 地址从其他计算机访问应用程序。

第 1 部分:设置 Google 项目和计算引擎实例

我们需要做的第一件事是创建一个项目。你可以使用现有的谷歌云项目,也可以在这里创建一个新的项目。

Creating a new project

我将我的项目命名为 demo1 并将计算引擎实例命名为 flask-demo ,但是项目和实例名称可以是您喜欢的任何名称。一旦您创建和/或选择了一个项目,您就可以前往计算引擎>虚拟机实例来创建一个新的 GCE 实例。

Creating a GCE VM instance

我们现在可以配置我们的虚拟机实例了,我选择了 europe-west2 作为区域,但是对于本教程,任何区域都可以。计算引擎还允许您更改和自定义 CPU 内核、内存、GPU 和引导磁盘的数量。

按照教程,选择 g1-small(或更大的)实例,将引导盘更改为 Ubuntu 18.04 LTS,并将防火墙设置为允许 HTTP 流量。不同地区的价格可能不同,但这种特殊的配置让我每月的估计成本为 17.04 美元。

单击“创建”后,启动虚拟机实例可能需要几分钟时间。

Configuring a new VM instance

我们为 GCE 实例启用了 HTTP 流量,但是我们还需要做一件事。我们的 Flask 应用程序将在端口 5000 上运行,默认情况下,谷歌云不监听端口 5000。项目中的默认网络带有默认防火墙规则“default-allow-http”和“default-allow-https ”,以允许端口 80 和 443 上的流量。

我们需要前往 VPC 网络>防火墙规则并创建一个新的防火墙规则来接受我们的应用程序将要运行的端口上的传入连接和请求。

Firewall rules

点击创建防火墙规则并配置设置,如下所示。确保将 http-server 添加到目标标签,将 0.0.0.0/0 添加到源 IP 范围,并将 5000 设置为指定端口。

Creating a new firewall rule

第 2 部分:配置计算引擎实例

是时候配置我们的 GCE 实例了!您可以在计算引擎>虚拟机实例中列出您的计算引擎实例。

确保记下您的实例的外部 IP 地址,您将需要它来访问您的应用程序并在 GCE 实例外部发送 API 请求。单击 SSH 按钮从浏览器登录到实例。

List of Compute Engine instances

注意:复制/粘贴命令时要小心。某些字符可能不会完全按照预期进行传输。如果所有其他方法都失败,请手动写出该命令。

我们现在已经准备好设置我们的生产环境。我们将使用 Miniconda 来管理依赖项和环境。在实例的 SSH 终端上,运行:

# update system packages and install the required packages
sudo apt-get update
sudo apt-get install bzip2 libxml2-dev libsm6 libxrender1 libfontconfig1# clone the project repo
git clone [https://github.com/alaradirik/google-cloud-flask-tutorial.git](https://github.com/alaradirik/google-cloud-flask-tutorial.git)# download and install miniconda
wget [https://repo.anaconda.com/miniconda/Miniconda3-4.7.10-Linux-x86_64.sh](https://repo.anaconda.com/miniconda/Miniconda3-4.7.10-Linux-x86_64.sh)
bash [Miniconda3-4.7.10-Linux-x86_64.sh](http://Miniconda3-4.7.10-Linux-x86_64.sh)

按照说明并同意安装 Miniconda 的条款。保留默认安装位置,并对“您希望安装程序通过运行 conda init 来初始化 Miniconda3 吗?”回答“是”。

一旦安装完毕,我们将需要导出 Miniconda 的完整路径,使其可由 conda 命令执行。然后,我们可以继续创建一个新的 conda 环境。

运行 conda init 后,您可能需要关闭并重新打开 SSH 终端,以使更改生效。

export PATH=/home/<your name here>/miniconda3/bin:$PATH
rm [Miniconda3-4.7.10-Linux-x86_64.sh](http://Miniconda3-4.7.10-Linux-x86_64.sh)# confirm installation
which conda# create and activate a new environment
conda create -n flask-tutorial python=3.7
conda activate flask-tutorial

第 3 部分:部署和测试 Flask 应用程序

有趣的部分来了!我们已经安装了 Miniconda 并克隆了项目 repo,接下来我们需要做的是安装项目依赖项,启动应用程序并确保它可以接收来自其他计算机的请求。

# go to project root and install the requirements
cd google-cloud-flask-tutorial
pip install -r requirements.txt# run the app
python app.py

您可以通过使用实例的外部 IP 地址从本地计算机终端向 API 发送 POST 请求来测试您的应用程序。如果你没有外部 IP,去计算引擎>虚拟机实例找到它。

Github 上的项目 repo 包括一个名为 request.py 的示例请求脚本和一个包含示例图像的 images 文件夹,用于测试应用程序。您可以将 repo 克隆到您的本地计算机,或者使用设置>下载文件按钮从实例的 SSH 终端下载文件。

request.py 通过对实例的 POST 请求向我们的 API 的/predict 端点发送编码图像。您应该将实例的外部 IP 插入到 url 中,并创建一个具有执行 request.py. 的依赖项的虚拟环境

我们的应用程序发送每个检测到的对象的盒子坐标、盒子显示颜色、标签和置信度作为响应。 request.py 使用这些值在客户端创建并保存图像的注释版本。

# request.py dependencies
import requests
import json
import cv2 url = "http://<external IP address>:5000/predict"
headers = {"content-type": "image/jpg"}# encode image
image = cv2.imread('images/baggage_claim.jpg')
_, img_encoded = cv2.imencode(".jpg", image)# send HTTP request to the server
response = requests.post(url, data=img_encoded.tostring(), headers=headers)
predictions = response.json()# annotate the image
for pred in predictions:
   # print prediction
   print(pred) # extract the bounding box coordinates
   (x, y) = (pred["boxes"][0], pred["boxes"][1])
   (w, h) = (pred["boxes"][2], pred["boxes"][3]) # draw a bounding box rectangle and label on the image
   cv2.rectangle(image, (x, y), (x + w, y + h), pred["color"], 2)
   text = "{}: {:.4f}".format(pred["label"], pred["confidence"])
   cv2.putText(
       image, 
       text, 
       (x, y - 5), 
       cv2.FONT_HERSHEY_SIMPLEX,
       0.5, 
       pred["color"], 
       2
   )# save annotated image
cv2.imwrite("annotated_image.jpg", image)

Flask app running on the instance

第一次发送请求时,收到响应的时间会稍长一些,这是因为需要先下载模型权重。

Output on the client side

第 4 部分:用 Gunicorn 和 NGINX 设置生产服务器

Flask 不是网络服务器。这是一个微型 web 应用程序框架:一组工具和库,使得构建 web 应用程序更加容易和美观。

回顾一下,客户端和服务器之间的通信是通过请求和响应来完成的:

  1. 一个客户端向网络发送一个 HTTP 请求
  2. 网络服务器接收该请求
  3. 服务器运行应用程序来处理请求
  4. 服务器向客户端返回一个 HTTP 响应(输出)
  5. 客户端收到响应

Flask 本身不能处理 HTTP 请求和响应,但是它附带了 Werkzeug,这是一个 WSGI 实用程序库,为开发目的提供了一个简单的 web 服务器。虽然 Flask 的开发服务器足以测试应用程序的主要功能,但我们不应该在生产中使用它。正如官方文件所述:

虽然 Flask 的内置服务器轻巧易用,但它并不适合生产,因为它不能很好地扩展,并且默认情况下一次只能服务一个请求。

在本教程中,我们将使用 Gunicorn 和 NGINX 创建一个生产服务器,它可以处理多个用户和大量的传入请求,而用户/客户端不必等待太长时间。

from Real Python

Gunicorn 是一个可以执行 Python 代码的 web 服务器(也称为 WSGI 服务器),我们需要将 Gunicorn 与另一个 web 服务器 NGINX 耦合,因为我们希望利用非基于 Python 的服务器(非 WSGI 服务器)的一些特性:我们可以通过 NGINX 将请求分发到多个 Gunicorn 实例,提供静态内容而不必与 Flask 应用程序通信,高效地处理高连接级别等。

回到 GCE 实例终端,我们需要做的第一件事是安装并启动 NGINX。

cd
sudo apt-get install nginx-full
sudo /etc/init.d/nginx start

接下来,我们需要删除默认配置文件,并为 flask 应用程序创建一个新的站点配置文件。“站点-可用”中的配置文件在启用之前是不活动的,因此我们需要为“站点-启用”中的新配置文件创建一个链接。

# remove default configuration file
sudo rm /etc/nginx/sites-enabled/default# create a new site configuration file
sudo touch /etc/nginx/sites-available/flask_project
sudo ln -s /etc/nginx/sites-available/flask_project /etc/nginx/sites-enabled/flask_project

现在,我们可以通过使用 nano 或 vim 等编辑器打开文件来编辑应用程序的配置文件:

sudo nano /etc/nginx/sites-enabled/flask_project

复制并粘贴下面的代码,并保存配置文件。

server {
    location / {
        proxy_pass [http://0.0.0.0:5000](http://0.0.0.0:5000);
    }
}

重启 NGINX 服务器。

sudo /etc/init.d/nginx restart

我们快完成了!我们需要做的最后一件事是回到项目文件夹,将 Flask 应用程序绑定到 Gunicorn 服务器。

需要记住的一件重要事情是,我们希望服务器和 Flask 应用程序在我们关闭终端窗口后继续运行。添加守护进程标志保持进程在后台运行。

cd google-cloud-flask-tutorial
gunicorn --bind [0.0.0.0:5000](http://0.0.0.0:5000) app:app --daemon

结论

就是这样!您在计算引擎上部署了一个对象检测模型作为 API,并设置了一个生产服务器。您可以随时关闭计算引擎终端并向 API 发送请求。

希望你喜欢这个教程!如果您有任何问题或意见,请使用下面的评论部分或通过 Linkedin 联系我们。

使用 Flask 和 Python 在 Heroku 上部署深度学习模型

原文:https://towardsdatascience.com/deploying-a-deep-learning-model-on-heroku-using-flask-and-python-769431335f66?source=collection_archive---------5-----------------------

在我的上一篇文章中,我们已经看到了如何使用 Python 和 Flask(下面的链接)在 web 上部署机器学习模型

[## 使用 Flask 和 Python 在 Web 上部署机器学习模型

创建一个机器学习模型并对现实世界的问题进行预测听起来很酷。但是,那不是很…

medium.com](https://medium.com/analytics-vidhya/deploying-a-machine-learning-model-on-web-using-flask-and-python-54b86c44e14a)

通过 CLI 进行预测很酷,但也存在一些问题,比如手动启动服务器和缺少简单的 GUI(图形用户界面)。

在本帖中,我们将尝试通过在 Heroku 服务器上部署我们的模型来解决上述问题,并因此为最终用户建立一个简单的全天候运行的 HTML 网站来进行预测。

让我们从创建深度学习模型的最基础开始旅程,然后逐步完成部署过程并学习新概念。

深度学习模型的创建

步骤 1。为虹膜数据集创建一个简单的 Keras 模型

R.A. Fisher 在 1936 年的经典论文中使用了 Iris 数据集。它包括三种鸢尾,每种有 50 个样本,以及每种花的一些特性。

该数据集中的列是:

  • 身份
  • SepalLengthCm
  • SepalWidthCm
  • PetalLengthCm
  • PetalWidthCm
  • 种类

让我们导入必要的库,然后将 iris.csv 中的数据加载到 pandas 数据框架中,以便更好地理解。

import numpy as np
import pandas as pdiris = pd.read_csv(“../DATA/iris.csv”)iris.head()

第二步。为训练目的定义 X 和 y

现在,一旦我们加载了我们的数据,我们就可以为训练目的定义我们的 X 和 y,我们最初的四列将贡献 X,物种将被标记为 y,这表示我们来自数据集的真实标签。

X = iris.drop(‘species’,axis=1)
y = iris[‘species’]

第三步。二值化物种标签

正如我们在数据集 【物种】 中看到的,包含字符串格式的数据,因此我们应该将其编码成数字,为此我们可以通过下面的代码使用 sklearn .预处理库中的 LabelBinarizer

from sklearn.preprocessing import LabelBinarizer
encoder = LabelBinarizer()
y = encoder.fit_transform(y)

现在,如果我们检查我们的"y"它应该被二值化如下,其中[1,0,0]表示花“Setosa”,[0,1,0]表示“Virginica”,而[0,0,1]表示“Versicolor”。

步骤四。缩放数据

在输入模型之前缩放我们的数据总是很重要的,以确保所有列的值都在同一范围内,您可以使用 scikit-learn 中的任何缩放器,如 StandardScaler 或 MinMaxScaler,下面我们使用的是 MinMax scaler

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaled_X = scaler.fit_transform(X)

请注意,我们正在缩放我们的整个 X,这将用于训练我们的深度学习模型,您可以根据自己的建模步骤纳入更多步骤,如 train_test_split

第五步。创建 Keras 模型

让我们通过导入下面的库并调用顺序 API 来创建一个简单的 Keras 模型

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Densemodel = Sequential()
model.add(Dense(units=4,activation=’relu’))
model.add(Dense(units=32,activation=’relu’))
model.add(Dense(units=16,activation=’relu’))
# Last layer for multi-class classification of 3 species
model.add(Dense(units=3,activation=’softmax’))model.compile(optimizer=’adam’,loss=’categorical_crossentropy’,metrics=[‘accuracy’])

在上面的代码中,我们已经开始创建一个连续的 Keras 模型,第一层的是密集的,在 X 轴上有 4 个输入(萼片长度,萼片宽度,花瓣长度,花瓣宽度)。

之后,我们添加了 2 个隐藏层,并使用“relu”作为除最后一层之外的所有层的激活函数。

最后一层包含 3 个单元,分别用于 3 类花 ( Setosa、Virginica 和 Versicolor),具有soft max激活函数,因为我们正在处理多类分类问题,而且在编译模型时,我们使用了【亚当优化器以及****

第六步。训练和保存模型

最后,让我们开始在大约 100+个时期上训练我们的 Keras 模型,如果您想减少训练的运行时间,您可以添加回调机制,例如 EarlyStopping。

***model.fit(scaled_X,y,epochs=150)Epoch 1/150
150/150 [==============================] - 0s 1ms/sample - loss: 1.1053 - accuracy: 0.3333
Epoch 2/150
150/150 [==============================] - 0s 93us/sample - loss: 1.0953 - accuracy: 0.3467
Epoch 3/150
150/150 [==============================] - 0s 86us/sample - loss: 1.0864 - accuracy: 0.5667
Epoch 4/150
150/150 [==============================] - 0s 100us/sample - loss: 1.0770 - accuracy: 0.6200
Epoch 5/150
150/150 [==============================] - 0s 86us/sample - loss: 1.0669 - accuracy: 0.4867***

训练完成后,我们将达到大约 95%的准确率,而不会过度拟合数据。现在让我们保存我们的模型,以便稍后在部署过程中使用。

***model.save(“final_iris_model.h5”)***

这将把模型保存在您的当前工作目录中。**

第七步。保存定标器

我们还将在当前的工作目录中保存 scaler,这样我们就可以在将用户输入数据传递给我们的模型并在我们的网站上显示结果之前对其进行缩放。

**import joblib
joblib.dump(scaler,’iris_scaler.pkl’)**

部署通过烧瓶,Python 对 Heroku

将我们的模型与 scaler 一起保存真是太好了,现在让我们深入了解设置我们自己的 flask 应用程序并将其部署在 Heroku 服务器上的步骤。

让我们开始创建我们的 app.py 文件,稍后将用于 Heroku 服务器上的部署。

步骤一。导入所需的库

**from flask import Flask, render_template, session, redirect, url_for, session
from flask_wtf import FlaskForm
from wtforms import TextField,SubmitField
from wtforms.validators import NumberRange
import numpy as np 
from tensorflow.keras.models import load_model
import joblib**

第二步。定义返回模型预测的函数

**def return_prediction(model,scaler,sample_json):

 s_len = sample_json[‘sepal_length’]
 s_wid = sample_json[‘sepal_width’]
 p_len = sample_json[‘petal_length’]
 p_wid = sample_json[‘petal_width’]

 flower = [[s_len,s_wid,p_len,p_wid]]
 flower = scaler.transform(flower)

 classes = np.array([‘setosa’, ‘versicolor’, ‘virginica’])
 class_ind = model.predict_classes(flower)

 return classes[class_ind][0]**

在上面的函数中,我们传递了 三个参数,我们的 model、scaler 和 sample_json 用于从 HTML 页面输入数据。

JSON (JavaScript Object Notation)是网络上最广泛使用的数据交换格式。这种数据交换可以在不同地理位置的两个计算机应用程序之间进行,也可以在同一台硬件机器上运行。

首先,JSON 构建在类似 python 字典的结构之上

  • 名称/值对的集合。
**"employee": {
"id":           1,
"name":         "Admin",
"location":     "USA"
}**

以类似的方式,我们从传入的请求中捕获了 sepal_length/width、petal_length/width 的数据

**s_len = sample_json[‘sepal_length’]
 s_wid = sample_json[‘sepal_width’]
 p_len = sample_json[‘petal_length’]
 p_wid = sample_json[‘petal_width’]**

完成上述步骤后,我们缩放了我们的花卉列表,并使用了model . predict _ classes()****函数来获取对应于以下代码中花卉数据的类标签,有关此函数的更多详细信息,请参见下面的链接。

https://kite . com/python/docs/tensor flow . keras . sequential . predict _ classes

**flower = [[s_len,s_wid,p_len,p_wid]]
flower = scaler.transform(flower)
classes = np.array([‘setosa’, ‘versicolor’, ‘virginica’])
class_ind = model.predict_classes(flower)
return classes[class_ind][0]**

第三步。定义 app 路线并完成 app.py 文件

在下面的代码中,为了更好的理解,每个代码块上面都定义了代码注释,如果你需要更多的了解 flask 的基本架构,也可以通过下面的链接访问我的上一篇文章。

https://medium . com/analytics-vid hya/deploying-a-machine-learning-model-on-web-using-flask-and-python-54 b 86 c 44 e 14 a

****app = Flask(__name__)**
**# Configure a secret SECRET_KEY**
app.config[‘SECRET_KEY’] = ‘someRandomKey’**# Loading the model and scaler**
flower_model = load_model(“final_iris_model.h5”)
flower_scaler = joblib.load(“iris_scaler.pkl”)**# Now create a WTForm Class**
**class FlowerForm(FlaskForm):**
 sep_len = TextField(‘Sepal Length’)
 sep_wid = TextField(‘Sepal Width’)
 pet_len = TextField(‘Petal Length’)
 pet_wid = TextField(‘Petal Width’)
 submit = SubmitField(‘Analyze’)

[**@app**](http://twitter.com/app)**.route(‘/’, methods=[‘GET’, ‘POST’])**
 def index():
  # Create instance of the form.
  form = FlowerForm()
  # If the form is valid on submission
  if form.validate_on_submit():
  # Grab the data from the input on the form.
  session[‘sep_len’] = form.sep_len.data
  session[‘sep_wid’] = form.sep_wid.data
  session[‘pet_len’] = form.pet_len.data
  session[‘pet_wid’] = form.pet_wid.datareturn redirect(url_for(“prediction”))return render_template(‘home.html’, form=form)[**@app**](http://twitter.com/app)**.route(‘/prediction’)**
def prediction():
 #Defining content dictionary
 content = {}content[‘sepal_length’] = float(session[‘sep_len’])
 content[‘sepal_width’] = float(session[‘sep_wid’])
 content[‘petal_length’] = float(session[‘pet_len’])
 content[‘petal_width’] = float(session[‘pet_wid’])

 results = return_prediction(model=flower_model,scaler=flower_scaler,sample_json=content)return render_template(‘prediction.html’,results=results)**if __name__ == ‘__main__’:
 app.run(debug=True)****

让我们一点一点来理解上面的代码。

我们正在配置一个密钥需要密钥来保证 Flask 中客户端会话的安全。您可以生成任何您选择的随机密钥。**

我们正在使用@app.route 装饰主页和预测页面 ,详情请参考我上一篇文章。

****另外,我们正在创建 WT 表单。使用 Flask-WTF我们可以在 Python 脚本中定义表单字段,并使用 HTML 模板 呈现它们

TextField 表示<输入 type = 'text' > HTML 表单元素

请通过下面的脚本安装 Flask-WTF

**pip install flask-wtf**

第四步。定义我们的 HTML 表单,从终端用户那里获取输入。

现在让我们进入最后一步,为部署做好一切准备。

我们将为最终用户的输入创建两个基本的 HTML 表单,即prediction.html

你也可以在 第三步 查看代码,通过@app.route decorator 定义两者,将 Flask 与 HTML 模板连接起来。

home.html

**<h1>Welcome to IRIS prediction</h1>
<h2>Please enter your flower measurements below:</h2>
<form method=”POST”>
 {# This hidden_tag is a CSRF security feature. #}
 {{ form.hidden_tag() }}
 {{ form.sep_len.label }} {{form.sep_len}}
 <br>
 {{ form.sep_wid.label}} {{form.sep_wid}}
 <br>
 {{form.pet_len.label}}{{form.pet_len}}
 <br>
 {{form.pet_wid.label}}{{form.pet_wid}}
 <br>
 {{ form.submit() }}
</form>**

在上述表格中,每一项如─

form.sep_len、form.sep_wid 等 是我们在 FlowerForm 类中的 STEP 3中定义的文本字段,这样一旦用户输入数据,这些数据就会被传递给 FlaskSession。

Prediction.html

**<h1>Thank You. Here is the Information You Gave:</h1>
<ul>
 <li>Sepal Length: {{session[‘sep_len’]}}</li>
 <li>Sepal Width : {{session[‘sep_wid’]}}</li>
 <li>Petal Length: {{session[‘pet_len’]}}</li>
 <li>Petal Width : {{session[‘pet_wid’]}}</li>
</ul>
<h2>Your Predicted Flower Class is: {{results}}</h2>**

然后我们将相同的数据传递到步骤 3 中预测函数内部定义的内容字典中, 进一步使用相同的数据作为我们模型的输入。最后,我们将显示步骤 3 的结果变量。我们的 prediction.html 页面。

收拾好一切,部署到 Heroku

现在我们已经到了最后一步,那就是在 Heroku 号上部署一切。

步骤一。请按照下面的方式建立你的项目工作目录,有一个单独的模板文件夹包含你的 home.html 和 prediction.html 文件。

此外,请添加以下代码的 Procfile(无扩展名)作为一行代码

**web: gunicorn app:app**

****“guni corn”,是一个 Web 服务器网关接口(WSGI)服务器实现,常用于运行 Python web 应用, 这里 app 是我们的 app.py 文件名。

第二步。创建一个 conda 虚拟环境来设置所有的库

导航到项目目录后,在 Anaconda 提示符下运行下面的代码,然后激活环境。

**Step1\. conda create — name mydevenv python=3.7
Step2\. activate mydevenv**

为您新创建的环境安装以下库,并为 Heroku 生成 requirements.txt

**Step1\. pip install flask
Step2\. pip install flask-wtf
Step3\. pip install tensorflow2.0.0a0
Step4\. pip install scikit-learn
Step5\. pip install gunicorn
Step6\. pip freeze > requirements.txt**

现在您的工作目录应该已经为 Heroku 部署创建了 requirements . txt。

第三步。创建 Heroku 帐户并安装 Heroku CLI 进行部署

注册一个新的 Heroku 账号https://www.heroku.com/

根据您的操作系统安装 Heroku CLI 和 GIT

https://dev center . heroku . com/articles/heroku-CLI #下载并安装

https://git-scm.com/downloads

完成后请重启系统,在命令提示符下键入 heroku如果没有“Heroku not found”的错误,您就可以进入下一步

第四步。将应用部署到 Heroku 服务器

通过打开一个新的命令提示符并键入以下内容来登录 Heroku。

**heroku login**

按任意键,一旦完成,你将被重定向到浏览器的登录页面,在那里完成登录过程。

现在转到 Heroku 主页,点击创建一个新的应用程序,如下所示

完成上述步骤后,执行最后几个步骤来部署到服务器。

打开 GitBash 并导航到您的项目目录

初始化目录中的 git 存储库。用您自己的应用程序名称替换 ml-deployment-app。

**$ cd my-project/
$ git init
$ heroku git:remote -a ml-deployment-app**

部署应用程序

将您的代码提交到存储库,并使用 Git 将其部署到 Heroku。

**$ git add .
$ git commit -am "adding files"
$ git push heroku master**

最后,您应该能够在 CLI 上看到如下所示的成功消息以及您的应用程序的 URL。

****祝贺你拥有了自己的网络直播应用。

****

在下面的网址上查看正在运行的应用程序。

https://ml-deployment-app.herokuapp.com/

如果你错过了什么或面临问题,所有的代码文件都在下面的 Github 链接中。

https://github.com/guptasoumya26/ml-deployment-app-heroku

在这篇文章中,我们学习了 Flask with Web,如何将它与 HTML 网站集成,最重要的是如何应用这些知识在 Web 服务器上部署它,以便最终用户可以随时与我们的 ML 模型交互,而无需任何外部依赖。

我希望你觉得这个教程有用,谢谢你读到这里。我很好奇你是怎么想的,所以给我一些建议吧。
您也可以直接通过邮箱与我取得联系,或者通过 LinkedIn 与我联系。

通过 CLI 在 AWS Elastic Beanstalk 上部署一个烧瓶应用程序

原文:https://towardsdatascience.com/deploying-a-flask-application-on-aws-elastic-beanstalk-via-cli-c0e93548472e?source=collection_archive---------8-----------------------

使用带有烧瓶和弹性豆茎的易于使用的 API 展示后端数据分析。

可以在 AWS 上用 EC2 实例托管商业级烧瓶应用程序。启动 EC2 实例很容易,但是资源管理是一项开销。为了更好地利用资源, Lambda 和 API Gateway 是一个替代方案。但是它带来了资源配置开销。

AWS 弹性豆茎 (EB)在不限制选择或控制的情况下降低了管理复杂性。我们需要做的只是上传应用程序,EB 本身会处理以下细节:

  • 容量供应
  • 负载平衡
  • 缩放比例
  • 应用健康监控

AWS 确实提供了关于 EB 的详细文档。浏览这些页面是很棘手的,通常不会提到陷阱。在这里,我分享使用 EB CLI 设置和启动 Flask 应用程序的过程。

先决条件:

  • 我使用运行 Python 3.7 的 Linux 系统,假设你有类似的设置。
  • AWS 的工作知识。
  • 烧瓶的工作知识。

步骤 1:安装 EB CLI

按照 中提到的步骤,在虚拟环境中安装 EB CLI。

**# Quick Reference****$ pip install** **— user virtualenv****$ virtualenv *~/ebtest*****$ source** ***~/ebtest*/bin/activate****$ pip install awsebcli — upgrade****$ eb — version**

第二步:烧瓶应用

您可以按照下面提到的过程创建一个测试瓶应用程序。

用 Flask 建立 Python 虚拟环境

创建烧瓶应用

EB 默认期望文件名为 application.py 。如果您使用任何其他名称,应用程序加载将会失败。此外,EB 希望 flask 应用程序对象实例是应用程序。要更改这些默认值,您需要使用 EB 配置。

**# Quick Reference****$ pip install flask==1.0.2****$ pip freeze > requirements.txt****$ python application.py**

在 EB 上部署 flask 应用程序之前,确保在其上执行本地测试。

步骤 3: AWS API 密钥和机密

从 AWS 控制台的我的安全凭证下获取 API 密钥和密码。将 API 密钥和密码放在手边,以便配置 EB。

注意:请确保这些信息的安全。

EB 配置会将这些信息存储在 ~/下。aws/config 如下所示。

**[profile eb-cli]****aws_access_key_id = KEY****aws_secret_access_key = SECRET**

步骤 4:在弹性豆茎上部署烧瓶应用程序

按照 中提到的步骤,使用 EB CLI 部署您的站点

使用。ebignore 文件,避免上传不需要的文件。创造这些下的 config** 文件。ebextensions** 在 EB 上设置环境变量。

**# Quick Reference****$ eb init -p python-3.6 flask-tutorial — region us-east-2****$ eb init****$ eb create flask-env****$ eb open**

步骤 5:在弹性豆茎上使用端瓶

为此,您可以使用 Beanstalk 控制台或 EB CLI。

**# Quick Reference****$ eb terminate flask-env**

学分:

这篇博文是 LiveSafe 项目的成果。Live Safe 汇集了美国特定地区灾害风险的相关信息,以帮助潜在房主做出购买和租赁决定。

Manjula Mishra 、 Daniel Martin-Alarcon 和我一起从事该项目的数据科学部分。你可以在这里找到数据科学相关的代码。

在 Google 云平台中部署一个生产 Druid 集群

原文:https://towardsdatascience.com/deploying-a-production-druid-cluster-in-google-cloud-platform-43a7f1e15336?source=collection_archive---------28-----------------------

本文的目的是通过使用 GCP 来指导 Apache Druid 集群的设置过程

阿帕奇德鲁伊(孵化中)

Druid 是一个开源的分析数据存储,设计用于商业智能( OLAP )对事件数据的查询。Druid 提供了低延迟(实时)数据接收、灵活的数据探索和快速的数据聚合。

可扩展的架构

要求

  • 对于基本 Druid 集群:每个节点 8 个 8vCPUS、30GB RAM 和 200GB 磁盘大小(例如 custom-6–30720 或 n1-standard-8)。
  • 启用谷歌云存储
  • 激活 MySQL 实例或云 SQL

安装

用你的 GCP 帐户登录,用 SO Debian 创建三个虚拟机。

下载德鲁伊:

为每个节点运行

wget https://www-us.apache.org/dist/incubator/druid/0.15.1-incubating/apache-druid-0.15.1-incubating-bin.tar.gz
tar -xzf apache-druid-0.15.1-incubating-bin.tar.gzexport $PATH_GCP = /path/druid/

安装组件

使用 SSH 输入每个节点并运行:

#Update libraries 
sudo apt-get update#Install Java JDK 
sudo apt install default-jdk -y #Install Perl 
sudo apt-get install perl -y #Donwload MySQL JAR 
sudo apt install libmysql-java #Install MySQL server 
sudo apt-get install mysql-server -y #Move MySQL JAR to Druid folder 
cp /usr/share/java/mysql-connector-java-5.1.42.jar $PATH_GCP/apache-druid-0.15.1-incubating/extensions/mysql-metadata-storage

安装动物园管理员

Zookeeper 可能安装在一个独立的节点上,尽管在这种情况下,我们打算安装在主节点上。使用 SSH 登录并运行以下脚本。

#Download
wget https://www-eu.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz tar -zxf zookeeper-3.4.14.tar.gz #create folder and move
sudo mkdir -p /usr/local/zookeeper
sudo mv zookeeper-3.4.14 /usr/local/zookeeper#create folder
sudo mkdir -p /var/lib/zookeeper #create config file 
vi /usr/local/zookeeper/conf/zoo.cfg #add properties inside config file
tickTime=2000 
dataDir=/var/lib/zookeeper clientPort=2181

编辑公共运行时属性

编辑位于路由:apache-druid-0.15.1-incubating/conf/druid/cluster/_common/common.runtime.properties中的文件,为每个节点复制建议的更改。

使用sudo vi编辑文件

sudo vi apache-druid-0.15.1-incubating/conf/druid/cluster/_common/common.runtime.properties

以下改动按顺序写。

启用基本安全性

如果需要设置一个基本的身份验证系统,请在每个节点的公共文件中添加这些属性。这样做之后,您将拥有一个密码为[PASSWORD_1]admin用户,可以访问集群中的所有网段。

在文件中添加以下属性:Apache-druid-0 . 15 . 1-孵化器/conf/druid/cluster/_ common/common . runtime . properties

运行 Apache Druid

启动动物园管理员

在您下载的节点中运行

sudo /usr/local/zookeeper/bin/zkServer.sh start

启动主机

export PATH_GCP=[PATH_GCP]
sudo nohup $PATH_GCP/apache-druid-0.15.1-incubating/bin/start-cluster-master-no-zk-server &#See log
tail -f $PATH_GCP/apache-druid-0.15.1-incubating/var/sv/coordinator-overlord.log

启动数据服务器

export PATH_GCP=[PATH_GCP]
sudo $PATH_GCP/apache-druid-0.15.1-incubating/bin/start-cluster-data-servertail -f $PATH_GCP/apache-druid-0.15.1-incubating/var/sv/historical.log

启动查询服务器

export PATH_GCP=[PATH_GCP]
sudo $PATH_GCP/apache-druid-0.15.1-incubating/bin/start-cluster-query-servertail -f $PATH_GCP/apache-druid-0.15.1-incubating/var/sv/broker.log

访问 Druid UI

在访问您的本地机器之前,您需要打开端口:8888、8081、8082 和 8083。作为一种快捷方式,您可以在项目云 shell 中运行此代码。

export LOCAL_IP=[LOCAL_IP]
gcloud compute --project=$PROJECT_ID firewall-rules create druid-port --direction=INGRESS --priority=1000 --network=default --action=ALLOW --rules=all --source-ranges=$LOCAL_IP

现在,你可以和德鲁伊一起工作。在我的下一篇文章中,我将展示一个如何使用它的真实案例。如果你需要关于德鲁伊的介绍,你可以在这里看到我的合作伙伴的文章安东尼奥·卡川:https://towards data science . com/a-gentle-introduction-to-Apache-druid-in-Google-cloud-platform-c1e 087 c 87 BF 1

PS 如果您有任何问题,或者想要澄清一些事情,您可以在 LinkedIn 上找到我。

PS2:你可以在我的 github 里看到代码

PS3:如果你想了解更多关于数据工程的知识,请关注:【https://datahacks.ai/】T4

在 Heroku 上部署 React 应用程序:Python 视角

原文:https://towardsdatascience.com/deploying-a-react-app-on-heroku-the-python-perspective-256deeec788f?source=collection_archive---------14-----------------------

如何部署与 Flask 后端配对的 React 前端

Heroku 来自 Python 背景,是一个非常适合部署的地方。我有各种各样的静态和基于 Flask 的网站,这些网站配置起来很简单,并且很容易与 Github 集成,以实现平稳的持续部署。这篇文章是而不是关于使用烧瓶部署的——Heroku 指南对此很有帮助,你可以在这里和这里和看到一些例子。

在我最近的项目中,我学习了 Javascript——特别是, React (如果你想做同样的事情,我发现 Flavio Copes 博客很有帮助)。这带来了一系列令人眼花缭乱的新单词要学习,许多不同的方法来做同样的事情(与 Python 的法则相反),以及让我迷惑不解的异步范例。

我正在用 Flask 后端构建一个 React 应用程序。在黑进了本地看起来合理的东西并部署了后端之后,我开始和我信任的朋友 Heroku 一起部署 React 部分。这就是麻烦开始的地方。

我用什么来服务一个 React app?

我是数据科学家,不是开发人员,所以我和服务器的关系是功利的。Flask 给了我一个轻量级的 Python 服务器,如果我误以为我的网站会有大流量,我可以升级到gunicorn。当我部署到 Heroku 时,我可以使用一个[Procfile](https://devcenter.heroku.com/articles/procfile)来告诉 Heroku 运行什么命令来服务我的应用程序——通常是一个命令行程序。幸运的是,我用来在本地运行我的应用程序的命令和 Heroku 使用的命令是相同的:

python app.py

但是 React 的等价词是什么呢?

当您在本地开发时,您可以使用类似以下的内容:

npm run start

来运行您的开发服务器,但是稍微搜索一下就会发现没有人用它来为生产服务。相反,有很多关于所谓的Express.js的讨论。

express . js 到底是什么?

Express 将自己描述为“Node.js 的快速、非个性化、极简主义的网络框架”。所有这些听起来对我来说都很好,但我真的不在乎——我只是想要一些允许其他人看到我在本地运行npm run start 时看到的东西。

事实证明,对此使用 Express 是完全没有必要的,尽管有许多关于它的博客文章。

困惑的产生是因为很多人也对基于 Javascript 部署后端感兴趣,所以很多关于部署 JS 的普通建议都是基于可以服务前端和后端资产的服务器。但是你,我的朋友,已经有了一个后端,由可信的 Flask 提供服务:所以我们可以坚持一些更简单的东西。

服务一个反应前端

React 中大多数旅程的实际起点create-react-app建议,如果你在提供一个“静态应用”,你可以使用一个叫做serve的东西,这相当于一个两行程序:

npm install -g serve
serve -s build

这对我来说听起来相当不错,除了我不确定我是否在服务一个“静态应用程序”,在我看来这是由几个 HTML 页面组成的,而不是一个所有人都在唱歌所有人都在跳舞的 React 应用程序,在商店里到处都有旋转的小发明和跳跃的模态。

但是仔细想想,我的应用程序确实是静态的。如果你在 Flask 中创建一个后端,而你的 React 应用仅仅是一个前端,那么你的应用是静态的。从部署的角度来看,这是个好消息。

旁白:serve是来自 ZEIT 的一个库,他们实际上有一个 Heroku 的竞争对手叫now,它已经获得了一些非常有利的写写 ups ,可能值得仔细看看。

最后一公里

需要一些小的修正来让这个在本地工作:

  1. serve将服务于已经构建的任何东西,而不是您的开发代码,所以请确保您已经运行了npm run build来将您的 Javascript 编译成部署版本。如果您像我一样来自 Python 背景,您会忘记这样做,并且想知道当您在本地测试系统时,为什么对代码的更改没有反映在您的浏览器中。
  2. 如果您使用npm遵循了 create-react-app 框架,您可能已经向您的package.json添加了一个proxy字段,这允许您通过类似/api/v1的路径访问您的 API,而不是显式地指定主机。虽然显然在serve中有一些功能来复制它,但我无法让它工作,所以我只是定义了一个环境变量并使用它(见本指南)。

最后,让 Heroku的东西飞起来(如果你不熟悉 Heroku 的 Github 工作流程,我真的推荐你,看看他们的快速入门):

  1. 来自create-react-app的文档将servenpm install -g serve一起安装,但是您实际上想要使用npm install serve --save将其添加到您的生产依赖项中(我花了一段时间试图弄清楚为什么 Heroku 会因为缺少serve依赖项而崩溃)。
  2. 一旦 Heroku 意识到你已经获得了一个 NPM 应用程序(由检测到一个package.json触发),它将尝试用npm run build构建你的应用程序,然后用npm run start运行它。为了让后者工作,您需要将默认的create-react-app
“scripts”: {“start”: “react-scripts start”, ...

“scripts”: {“dev”: “react-scripts start”, “start”: “serve -s build”,

然后,您可以使用npm run dev在本地运行您的开发服务器,但是 Heroku 将能够在调用npm run start时运行您的生产服务器。

最后,如果你按照我的建议用ENV来设置你的后端 URL,确保通过Settings > Config Vars在 Heroku 中设置 env。

理论上就是这样!你可以在 this repo 的 React 应用中看到这是什么样子。如果您对此工作流程有任何问题,或者您找到了在 Heroku 上部署 React 应用程序的更简单方法,请告诉我🤖🎉👯‍♀️

使用 Azure 应用服务部署 Streamlit Web 应用

原文:https://towardsdatascience.com/deploying-a-streamlit-web-app-with-azure-app-service-1f09a2159743?source=collection_archive---------4-----------------------

继微软官方文档之后。

Photo by Daniil Silantev on Unsplash

细流

Streamlit 是一个开源的 python 库,非常适合显示图表和使用小部件与可视化仪表板进行交互。凭借简单的语言和直观的控件,Streamlit 可以帮助您快速创建能够显示文本、数据帧、图表、地图和更多内容的 web 应用。将 Streamlit web 应用部署到实际互联网的第一步是编写 app.py 脚本并在本地启动,以确保它看起来像预期的那样。

您可以通过从我的 GitHub repo 克隆来部署这个 docker 容器!

通过在 shell 中从保存 app.py 文件的文件夹运行streamlit run app.py来启动您的 streamlit 应用程序。每当保存 app.py 文件时,本地 web 应用程序都会自动更新。Streamlit 有一个广泛的图形 API,允许 Seaborn/Matplotlib,Plotly 和 Altair 图表。结合 Streamlit 的复选框和其他小部件,您可以构建一个交互式绘图仪表板,而无需了解前端或后端 web 开发。这使得它成为研究人员和数据科学家的一个优秀工具,他们希望快速将研究结果发布到互联网上,或者在互联网上的可访问 web 应用程序中创建演示文稿。

Streamlit 的入门教程是学习 API 的最佳途径,所以我将直接跳到 Streamlit web 应用程序的部署。对于这个例子,我将发表对美国人口普查局收集的美国 5 年调查数据的探索性分析。下面是我的 streamlit 应用程序文件。使用 CensusData pip 包查询数据。

Azure 容器注册表

当你准备好发布一个 web 应用时,你将创建一个托管在 Azure 容器注册中心的 docker 容器。这个容器将包含 web 应用程序运行所需的一切。

首先,登录到https://portal.azure.com/。另外,安装 Azure CLI 。

在您的电脑上,打开存储应用程序的文件夹中的 shell。通过键入以下内容登录 Azure

az login

接下来,创建一个资源组来存放容器注册中心和我们将在下面的步骤中创建的 Web App 服务。

az group create -l eastus -n CensusApp

在 CensusApp 资源组下创建一个容器注册表。

az acr create --name CensusAppRegistry --resource-group CensusApp --sku basic --admin-enabled true

Dockerfile、配置文件和 requirements.txt

对于此应用程序,有 6 个文件是此应用程序运行所必需的。census_app.py 文件是 streamlit 应用程序文件。Censusimg.jpg 是网站顶部图像的文件。您需要创建一个 Docker 文件,它给出了容器构建的说明,一个 config.toml 文件用于应用程序设置,一个 credentials.toml 文件用于防止 Docker 容器在启动时崩溃,还有一个 requirements.txt 文件用于 app.py 文件所需的 python 包。

您可以访问我的 GitHub 查看完整的项目。

files that complete the docker build

Dockerfile 文件

FROM python:3.7-slim
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 80
RUN mkdir ~/.streamlit
RUN cp config.toml ~/.streamlit/config.toml
RUN cp credentials.toml ~/.streamlit/credentials.toml
WORKDIR /app
ENTRYPOINT ["streamlit", "run"]
CMD ["census_app.py"]

和 credentials.toml

我推荐从他的 awesome-streamlit 存储库中复制 MarcSkovMadsen 的 config.toml 文件。

requirements.txt

streamlit
pandas
numpy
seaborn
matplotlib
psycopg2-binary

构建 docker 映像并保存到 Azure 容器注册表

在 shell 中保存文件的文件夹中,运行:

az acr build --registry CensusAppRegistry --resource-group CensusApp --image census-app .

如果构建成功,您应该会看到带有 sha256 的映像描述,输出类似于: Run ID: ca1 在 2m36s 秒后成功。通过登录 Azure 门户并导航到您的资源组,仔细检查以确保图像在您的容器注册表中,单击您的容器注册表,在服务刀片下,单击存储库。

从容器映像部署 Web 应用程序

为您的 web 应用创建应用服务计划。这将决定运行 docker 映像的虚拟机的大小。在这里,我选择了 B1 的 sku,这是 free 上面的第一层。在写这篇文章的时候,B1 服务计划是 12.41 英镑/月。在门户内创建应用服务计划或运行:

az appservice plan create -g CensusApp -n CensusAppServicePlan -l eastus --is-linux --sku B1

通过运行下面的命令从容器注册表中的 docker 容器创建 Azure web app ,或者从门户创建。

az webapp create -g CensusApp -p CensusAppServicePlan -n census-web-app -i censusappregistry.azurecr.io/census-app:latest

若要查看您的新网站,请转到您的新 web 应用程序资源并选择“浏览”。第一次查看时,会有冷启动延迟,大约 5 分钟后可能会没有响应。回到资源并再次单击 browse,您的 web 应用程序应该会出现在您的浏览器中!

现在,您应该可以在资源组中看到 3 个资源。

重新部署您的 web 应用程序

这种 web 应用交付方法的美妙之处在于,您可以通过重新构建容器来重新部署应用。

只需对您的 streamlit app.py 文件进行更改,并通过运行我们之前运行的命令在容器注册表中构建初始映像来重新构建您的容器。

az acr build --registry CensusAppRegistry --resource-group CensusApp --image census-app .

浏览器地址栏中将显示新 web 应用的链接。看看那个漂亮的应用程序!现在您已经完成了部署,您可以重新访问应用程序,进行更改并添加功能。干得好!

请访问我的 GitHub 获取用于构建这个容器化 web 应用程序的文件!

感谢您的阅读!

**编辑:将 SQL 请求更改为实际的 CensusData API 请求!

用 Gunicorn 3 展开烧瓶

原文:https://towardsdatascience.com/deploying-flask-with-gunicorn-3-9eaacd0f6eea?source=collection_archive---------5-----------------------

应用程序部署经常会带来意想不到的后果和错误。部署可能是决定最终期限的步骤,也可能是决定应用程序成败的步骤。许多数据科学家害怕这种部署,因为它可能非常乏味,并且需要我们许多人不一定精通的技能(开发-运营。)在我的“数据科学的软技能”文章中,我提到了数据科学家在某些方面是如何实践开发-运营技能的。这是有充分理由的,因为我发现自己对“系统管理员活动”越来越感兴趣了

我真正喜欢的一项服务是基于 Linux 的 VPS 主机服务。Linode 非常棒,因为它拥有我想要的极简主义,以及我喜欢的安全性和功能。因此,我们首先假设您有一个想要托管的域(或 IP),并且有一个 Linode 或类似的虚拟专用服务器正在运行,准备好通过 SSH 连接。

进去吧。

第一步当然是知道你的主机和根密码。您的主机将是 Linode 提供给您的 IPV4 地址,例如:

48.87.54.01

为了 SSH 到我们的服务器,我们可以使用一个 SSH 工具,比如 PuTTy(主要针对 Windows 用户),或者只是通过我们的终端使用 SSH。然后就像对你的根用户一样简单了。万一这个命令返回“ssh: command not found ”,您可能需要安装 openssh。

ssh root@your.ip.address

太好了!现在我们进来了,我们必须创建一个新用户!当然,这取决于你的发行版…

我要戴上红帽:

useradd *username*

但是如果你选择了 Ubuntu:

adduser username

现在,如果您想让您的新帐户能够使用超级用户的密码访问他们的命令:

usermod -aG sudo username

安装目录(NGINX)

设置您的用户帐户后,您可以使用 root 的“login”命令登录,或者您可以使用您的用户名替换 root,通过 SSH 登录您的用户帐户:

ssh username@your.ip.address

第一步是获取 NGINX。你可以把 NGINX 想象成一个巨大的路由器,NGINX 使得从一个网站服务多个域和监听端口变得非常容易。所以打开你的终端,通过你的包管理器安装它。

sudo dnf install nginx

您的操作系统的软件包管理器(如果您不知道)也在下面。(只需运行 sudo {包管理器}安装 nginx)

Distro      |     Package Manager
---------------------------------
Ubuntu      |        apt-get
RedHat      |      dnf / yum
Opensuse    |          man
Arch        |         pacman

现在我们需要在 HTTP 协议中为 www 建立一个域或位置。无论是购买的域名,还是你的服务器的 IP 地址,都没有那么重要。接下来,我们必须编辑 NGINX 的配置文件:

sudo nano /etc/nginx/sites-enabled/flask_app

这将打开一个文本编辑器,文件有可能是旧的,但很可能是新的。结果应该是这样的:

**server** {
    **listen** 80;
    **server_name** your.ip.here;

    **location** / {
        **proxy_pass** http://127.0.0.1:8000;
        **proxy_set_header** Host $host;
        **proxy_set_header** X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

现在我们只需要取消默认配置文件的链接:

sudo unlink /etc/nginx/sites-enabled/default

现在向上移动到根目录(不是您的用户主目录。)

cd ..

现在我们需要在 var/www/your.ip.here 中创建一个目录。

sudo mkdir var/www/your.ip.here

然后给我们自己超级用户特权,这样我们就不需要使用 sudo 来访问我们的文件系统。

sudo chown var/www/your.ip.here

基本上就是这样了!恭喜你,你的静态文件将正式在这个目录中工作!但是弗拉斯克呢?我们只需要一个快速的服务器设置!

设置服务器(Gunicorn)

将您的文件克隆、SSH 或安全复制到我们在文件系统设置中创建的 var/www 目录中。现在我们需要重新安装 Gunicorn 3。

sudo dnf install gunicorn3

并且和 supervisor 做同样的事情(如果需要可以像上次一样参考包管理器图表!)

sudo dnf install supervisor

现在我们必须创建一个主管,所以准备在 Nano 中打开更多的文本吧!

sudo nano /etc/supervisor/conf.d/flask_app.conf

并用您的设置进行配置!:

[program:flask_app]
directory=/var/
command=gunicorn3 -workers=3 flask_app:app
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
stderr_logfile=/var/log/appname/lognameerr.log
stdout_logfile=/var/log/appname/lognamestdout.log

然后为你的日志创建目录(当然这不是完全必要的,但是绝对是一个好的实践。)

sudo mkdir /path/to/logs (/var/log for me)
sudo touch outputpath
sudo touch stderrpath

恭喜你!

你已经用“传统的方式”部署了你的 Flask 应用程序这允许更多的扩展能力和多功能性,特别是与 Heroku 等其他替代方案相比。我认为这是一种非常有趣的方式,但有些人可能会说这有点乏味。当然,这些通常不是 DS 的职责,但是如果你发现你的团队陷入困境,这肯定是你很高兴学到的东西!

使用 FastAPI 和 Docker 部署 Iris 分类

原文:https://towardsdatascience.com/deploying-iris-classifications-with-fastapi-and-docker-7c9b83fdec3a?source=collection_archive---------15-----------------------

TLDR;

我们使用 Docker 部署了一个 FastAPI 应用程序,根据虹膜的测量值对其进行分类。所有的代码都可以在这里找到。

虹膜数据集

Iris 数据集是一个简单但广泛用于统计建模和机器学习的例子。该数据包含均匀分布在 3 个鸢尾亚类之间的 150 个观察值: setosa,versicolor,virginica。每个观察值包含相应的子类以及这些测量值:萼片宽度、萼片长度、花瓣宽度、花瓣长度(所有单位均为厘米)。

FastAPI

FastAPI 是一个现代、快速(高性能)的 web 框架,用于基于标准 Python 类型提示用 Python 3.6+构建 API。

FastAPI 网站提供了关于 FastAPI 如何工作以及使用 FastAPI 的优势的更多细节。顾名思义,FastAPI 就是 fast 。最重要的是,设置非常简单,框架带有一个 Swagger UI,它记录了 API 并使测试交互更加容易。

步骤 0:先决条件

  1. 安装对接器
  2. 按照自述文件上的说明,确保安装了所有依赖项(pip install requirements.txt

我们将使用 Docker 和 FastAPI 将我们的模型部署为 REST API。API(应用程序编程接口)是一组定义其他应用程序如何与您的代码交互的函数和过程。REST APIs 利用 HTTP 方法如GET, POST, PUT, DELETE来管理这种交互。

在本例中,我们将只使用两种 HTTP 方法:

  • GET:用于从应用程序中检索数据
  • POST:用于向应用程序发送数据(推理所需)

当我们发送一个 HTTP 请求时,服务器发出一个状态码。状态代码通知请求的状态。我们可以根据第一个数字对状态代码进行分类:

  • 1xx:信息回应
  • 2xx:请求成功
  • 3xx:需要进一步的操作来完成请求
  • 4xx:由于客户端错误(即语法错误),请求失败
  • 5xx:由于服务器问题(即功能未实现),请求失败

对于我们的应用程序,我们只会看到 2xx、4xx 和 5xx 代码。200 OK状态代码是我们希望看到的代码。

创建一个名为iris的新目录。该目录将包含用于构建应用程序的所有代码。

步骤 1:训练一个简单的分类器

为了简单起见,让我们使用逻辑回归作为我们的算法。我们可以使用sklearn来提供虹膜数据集并进行建模。

为了可读性,我将分类器构造为一个train_model用于训练分类器,classify_iris用于按照以下格式对新观察值进行分类:

{'sepal_w': <sepal width>, 'sepal_l': <sepal length>, 'petal_w': <petal_width>, 'petal_l'l: <petal length>}

我整理的这个分类器有很多缺点。抛开简单性不谈,每次调用classify_iris时都会训练一个新的分类器。这是对时间的不必要的利用,也使得审核之前的预测更加困难。一个更好的选择是将模型文件保存为应用程序的一部分,并加载它进行推理。

步骤 2:定义路由器

在与我们在步骤 1 中编写的分类器脚本相同的目录中,创建一个名为routers的文件夹来存放我们的路由器。路由器用于将复杂的 API 分解成更小的部分。每台路由器都有自己的前缀来标记这种分离。

routers目录中,创建一个名为iris_classifier_router.py的脚本。这将/classify_iris路由到其相应的函数。响应与IrisClassifier.classify_iris()生成的响应相同

步骤 3:定义应用程序

在与routers文件夹相同的目录下,创建另一个脚本app.py。在此脚本中,定义应用程序并指定路由器。

我们还定义了一个healthcheck函数。健康检查 API 返回应用程序的运行状态。我们的健康检查返回了令人愉快的短语虹膜分类器一切就绪!应用健康时。请注意,这将调用一个200状态代码。

步骤 4:包含依赖项,Dockerfile

到这一步,文件结构应该如下所示:

├──iris
│├──iris _ classifier . py
│├──app . py
│└──路由器
│└──——iris _ classifier _ router . py

转到上一个目录,创建一个requirements.txt文件,指定构建这个应用程序所需的所有依赖项。

我的requirements.txt长这样:

fastapi==0.38.1
numpy==1.16.4
scikit-learn==0.20.1
uvicorn==0.9.0

我们还需要创建一个Dockerfile,它将包含组装图像所需的命令。一旦部署,其他应用程序将能够从我们的虹膜分类器进行消费,以做出关于花的酷推论。

Dockerfile也可以在上面链接的 GitHub repo 中找到。

第一行为我们的应用程序定义了 Docker 基本图像。python:3.7-slim-buster 是一个受欢迎的图片——它很轻量级,构建起来非常快。第二行指定维护者。使用docker inspect可以发现维护者信息。

我们的 Dockerfile 以一个CMD结束,它用于将默认命令设置为uvicorn --host 0.0.0.0 --port 5000 iris.app:app。默认命令在我们运行容器时执行。

步骤 5:运行 Docker 容器

使用docker build . -t iris构建 docker 图像。这一步需要一段时间才能完成。

构建完映像后,使用docker run -i -d -p 8080:5000 iris生成 docker 容器。这将应用程序暴露给端口 8080。运行容器还会启动我们之前设置的默认命令——这有效地启动了应用程序!

与 API 交互

使用curl 'http://localhost:8080/healthcheck'进行健康检查

要获得推论,请使用以下请求。-d之后的 JSON 字符串是传递给classify_iris.的模型输入

curl 'http://localhost:8080/iris/classify_iris' -X POST -H 'Content-Type: application/json' -d '{"sepal_l": 5, "sepal_w": 2, "petal_l": 3, "petal_w": 4}'

前往localhost:8080/docs查看 Swagger UI。这使得测试请求变得更加容易。

如果您有兴趣阅读更多关于模型部署的内容,我写了另一篇关于使用 TensorFlow 服务部署 Keras 文本分类器的文章。

感谢您的阅读!

如果你喜欢这篇文章,可以看看我关于数据科学、数学和编程的其他文章。通过 Medium 关注我的最新动态。😃

作为一个业余爱好项目,我还在www.dscrashcourse.com建立了一套全面的免费数据科学课程和练习题。

如果你想支持我的写作,下次你报名参加 Coursera 课程时,可以考虑使用我的会员链接。完全公开—我从每一次注册中获得佣金,但不会对您产生额外费用。

再次感谢您的阅读!📕

使用 TensorFlow 服务部署用于文本分类的 Keras 模型(第 1 部分,共 2 部分)

原文:https://towardsdatascience.com/deploying-kaggle-solution-with-tensorflow-serving-part-1-of-2-803391c9648?source=collection_archive---------10-----------------------

注: 这是在 TensorFlow 1.0 中完成的

更新:抱歉,不会有第二部了。这里使用的许多函数在 2.X 中不再受支持。相反,我写了这篇文章,介绍如何在 TensorFlow 2.0 中提供类似的分类器。

下面是附带的 Github 回购。

大约两年前,我使用 Keras 库为 Kaggle 的有毒评论分类挑战构建了一个解决方案。该解决方案集成了多个深度学习分类器,实现了 98.6%的平均 ROC。

像我提交的大多数 Kaggle 文件一样,这份文件是 Jupyter 笔记本中的一堆杂乱的代码,除了生成一个非常随意的 csv 文件之外,几乎没有其他用途。为了使我的提交更有用,我选择了 ensemble 解决方案中使用的一个模型,对其进行了清理,并使用 TensorFlow 为模型推理公开了一个 HTTP 端点。

比赛背景

在这场比赛中,你面临的挑战是建立一个多头模型,能够比 Perspective 的当前模型更好地检测不同类型的毒性,如威胁、淫秽、侮辱和基于身份的仇恨。你将使用维基百科谈话页面编辑的评论数据集。对当前模式的改进将有望帮助在线讨论变得更有成效和尊重。

该数据集包含大量被评估为有毒行为的维基百科评论。每个注释被分配一个二进制指示符,指示它们是否:

  • 有毒的
  • 剧毒
  • 猥亵的
  • 威胁
  • 侮辱
  • 身份仇恨

问题陈述

为简单起见,我们将只关注基本的有毒类。给定一条文本评论,我们的分类器能确定这条评论是否有毒吗?

模型部署

模型部署是将机器学习模型与生产环境相集成的过程,通常是为了使推理可用于其他业务系统。数据被发送到模型服务器,在那里进行预处理并用于生成推理结果。推断结果随后被返回给消费应用程序。

真实生活应用

想象一下,我们正在运行一个聊天平台,它促进了文本消息的交换。根据设计,我们的系统会过滤掉所有有害信息。

我们系统中的数据流可能如下所示:

  • 用户写了一条消息
  • 我们的应用程序服务接收消息。应用程序服务通过 POST 请求将消息(以及任何相关的元数据)发送到我们的模型服务器
message_payload = {
    'message': 'got plans today?',
    'region': 'CA'
}
  • 模型服务器使用消息和元数据作为预测器返回推理输出
inference_payload = {
    'toxic': False,
    'probability': 0.93,
    'version': 'toxicity-detector-3.0'
}
  • app 系统接收推理有效载荷,并决定是否应该发送消息。app 系统还可以将推断结果写入数据库。

数据获取和管理

数据采集是每个建模过程中最重要的步骤之一,也是最具挑战性的步骤。冷启动问题是每个数据科学家都会遇到的头疼问题。这是 Kaggle 竞赛不总是代表真实生活数据科学项目的最大原因之一。

在生产环境中工作还会给数据获取和数据管理带来额外的注意事项。为了让我们的模型可以通过本地机器访问,我们需要构建管道来检索我们的数据,而不是在机器之间传递平面文件。

Kaggle API

记住最后一点,我们转向 Kaggle API 。Kaggle API 允许以编程方式/通过命令行界面下载 Kaggle 数据集。

  1. 如果您还没有 Kaggle 帐户,请创建一个
  2. kaggle.com/USERNAME/accounts.生成新令牌这将提示您下载一个kaggle.json文件,其中包含访问 API 的凭证
  3. 确保您接受竞赛规则(这是下载数据的要求)

4.将凭证从 json 文件导出为环境变量:

export KAGGLE_USERNAME = [kaggle username]

export KAGGLE_KEY = [generated key]

数据管道

导出 Kaggle 凭证后,我们可以构建一个简单的数据管道来从 Kaggle API 获取数据,并执行任何功能工程/数据清理步骤。

数据管道包含在类结构中。训练数据和测试数据将作为类变量存储。入口点是preprocess方法,它用预处理的训练和测试返回一个实例化的DataPipeline类。

预处理步骤序列包含在preprocessing_steps变量中。在preprocess()调用期间,每个步骤都按照它们出现的顺序应用于两个数据集。

这个模型使用的预处理步骤非常简单:缺失的注释用UNKNOWN文本进行估算,所有注释都转换成小写。

建模过程

文本分类器是使用 Keras 库构建的。

对文本进行标记

标记化是提取每个唯一标记(这里,我们基于空格分隔来确定标记)并将其映射到唯一数字/向量的过程。

这个模型使用的标记化非常简单。每个令牌被任意分配给一个整数。虽然保留了令牌的序列,但是没有映射提供关于令牌的显式信息。使用预先训练的 GloVe/word2vec 嵌入可能会给我们带来性能优势,但它会增加这些嵌入存储位置的复杂性。

在本例中,记号赋予器也被限制为前 10,000 个最常用的记号(这是由max_features参数设置的)。

考虑一个玩具例子:

tokenizer.word_index = {
    'the': 1,
    'brown': 2,
    'fox': 3,
    'jumped': 4,
    'over': 5,
    'lazy': 6,
    'dog': 7,
    'quick': 8}

短语快速的棕色狐狸跳过懒惰的狗将被映射到[1, 8, 2, 3, 4, 5, 1, 6, 7]

填充标记化的文本

可变长度序列必须转换成相同的长度。我们通常选择0来填充每个标记化的向量,使得每个输入都是相同的长度。

在我们的模型中,我们设置了max_len = 100,它将每个观察限制为 100 个令牌。少于 100 个标记的观察值将被填充,多于 100 个标记的观察值将被截断。

默认是从前面(注释的开头)截断/填充。

如果max_len = 10.,我们之前的标记化短语将被填充为[0, 1, 8, 2, 3, 4, 5, 1, 6, 7]

用于分类的递归神经网络

让我们一次看完每一层。

嵌入层

model.add(Embedding(self.max_features, self.embed_size))

嵌入层只能用作第一层。标记化的文本被传递到这一层,并作为密集向量输出。我们将输入的形状定义为(词汇特征的数量,每个嵌入的大小)。除非另有说明,否则初始嵌入权重作为训练过程的一部分被随机化和细化。

轮回层

注意:我减少了原始解决方案中的单元数量,以便在没有 GPU 的情况下更容易训练这个模型

model.add(Bidirectional(LSTM(100, return_sequences=True)))

来自嵌入层的密集向量被传递到递归层。该循环图层使用 LSTM 单位。LSTM 单元使用三个门来调节来自新观测的信息:输入门调节传递到单元中的信息的范围,存储门调节保留多少信息,输出门调节从单元输出的信息。

顺序模型在每个时间步消耗一个令牌。第一个令牌(或本例中的单词)在第一个时间步长消耗,第二个令牌在第二个时间步长消耗,依此类推。

如果我们设置return_sequences=True,那么将返回每个时间步长的输出。当此参数设置为 false 时,将仅返回最后一个时间步长的输出(在整个观察被处理后)。

全局最大池层

model.add(GlobalMaxPooling1D())

池是一种降采样技术,通过只保留最重要的信息来降低维数。全局最大池常用于自然语言处理的神经网络中。

在这里,全局最大池层吸收每个时间步长的输出,并选择每个步长的最大值来组合维数减少的输出。

密集层(输出)

model.add(Dense(2, activation='softmax'))

密集层使用 softmax 激活函数来输出类别概率。

在本地部署模型

TensorFlow 服务是部署 TensorFlow/Keras 模型的最简单方法之一。服务器使用SavedModel API 来公开模型预测的推理端点。要了解更多关于 TensorFlow 服务的信息,我建议阅读以下资源:

  • https://medium . com/tensor flow/serving-ml-quickly-with-tensor flow-serving-and-docker-7df 7094 aa 008
  • https://github.com/tensorflow/serving

SavedModel API

[SavedModel](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/saved_model/README.md) API 将整个 TensorFlow 会话导出为包含在单个目录中的语言不可知格式。

该目录具有以下结构:

assets/
assets.extra/
variables/
    variables.data-?????-of-?????
    variables.index
saved_model.pb
  • saved_model.pb 包含了MetaGraphDef类,定义了数据流结构
  • 资产子目录包含所有辅助模型文件
  • assets.extra 子目录包含其他库生成的资产
  • 变量子目录包含用于恢复推理模型的权重

构建张量流图

完整的代码可以在这里找到。

张量流图包含训练模型所需的所有计算。这包括用于预处理输入的任何步骤。通过在图形定义中定义标记化和填充步骤,客户机将能够向模型输入原始文本。

虽然将标记化步骤合并到图中非常方便,但是在其他预处理步骤中这样做有几个缺点:

  • 由于选项非常有限,并不是所有的预处理步骤都是可行的(我们实现的那些步骤经常会变得杂乱无章)
  • 预处理变得难以并行化
  • 代码变得非常混乱

部署我们的 Keras 模型

在使用 Keras 库训练模型之后,我们可以提取模型权重并将它们加载到 TensorFlow 会话中定义的非常相似的模型中。可以使用get_weights()方法提取重量。

我们需要创建一个查找表来标记原始文本。当令牌不存在于我们的词汇表中时,我们将它映射到 0。

然后,我们为客户端输入定义一个占位符。输入被标记化(由单个空格分隔的标记)、整形并评估填充/截断。

InputLayer.重新定义模型

我们定义了代表输入和模型输出的x_info, y_info

x_info = tf.saved_model.utils.build_tensor_info(x_input)        y_info = tf.saved_model.utils.build_tensor_info(serving_model.output)

可选地,我们可以将元数据作为模型有效负载的一部分。在这里,我们将模型版本包装成一个张量。

model_version_tensor = tf.saved_model.utils.build_tensor_info(tf.constant(version))

我们用它来创建预测签名:

要在本地设置 TensorFlow 服务器:

  1. 安装对接器
  2. 使用docker pull tensorflow/serving:latest获取 TensorFlow 服务 docker 映像的最新版本
  3. 导出包含SavedModel文件的目录。这应该是/model目录:ModelPath="$(pwd)/model"
  4. 通过公开 REST API 端点的端口 8501 来启动服务器
docker run -t --rm -p 8501:8501 \
    -v "$ModelPath/:/models/toxic_comment_classifier" \
    -e MODEL_NAME=toxic_comment_classifier \
    tensorflow/serving

会出现一堆日志。每个日志中的第一个字符将指示进程的状态。

  • E =错误
  • W =警告
  • I =信息
docker run -t --rm -p 8501:8501    -v "$ModelPath/:/models/toxic_comment_classifier"    -e MODEL_NAME=toxic_comment_classifier    tensorflow/servingI tensorflow_serving/model_servers/server.cc:82] Building single TensorFlow model file config:  model_name: toxic_comment_classifier model_base_path: /models/toxic_comment_classifierI tensorflow_serving/model_servers/server_core.cc:461] Adding/updating models.

如果每个日志都以 I、开头,那么恭喜您——该模型已经成功提供了!

版本控制

TensorFlow 服务基于子目录名称管理模型版本。子目录名称必须是整数值。默认情况下,它将总是获取最新版本。

有用的 Docker 命令

TensorFlow Serving 拥有自己的 Docker 映像,用于打包模型及其依赖项。这里有两个有用的 Docker 命令,在使用服务器时可能会派上用场:

  • docker ps -这显示哪些 Docker 容器当前正在运行;这对于获取容器 id 以便进一步操作非常有用
  • docker kill [container id] -如果您构建了错误的模型,您可以终止当前容器来释放端口并重启服务器

发布请求

既然我们的模型服务器已经在本地机器上启动并运行,我们就可以发送一个示例 POST 请求了。发布请求可以通过 curl 发送,这是一个用于在服务器之间传输数据的简单工具,也可以通过 Python 中的request库发送。

样本卷曲命令:

curl -d '{"signature_name": "predict","inputs":{"input": "raw text goes here"}}' \
  -X POST [http://localhost:8501/v1/models/toxic_comment_classifier:predict](http://localhost:8501/v1/models/division_inference:predict)

输出将如下所示。预测输出是一个概率列表。第一个索引将始终对应于第一类,第二个索引对应于第二类,依此类推。在这种情况下,第一个指数 0.996 表示评论为 0 级/无毒的概率。

{
    "outputs": {
        "prediction": [
            [
                0.996692061,
                0.00330786966
            ]
        ],
        "model_version": "20191005180917"
    }

后续步骤(第 2 部分的路线图)

预处理输入

我们当前实现的一个最大缺陷是,客户端输入的处理方式不同于训练数据。没有特征工程步骤应用于客户端输入。

我们可以使用辅助服务器来应用这些处理步骤。辅助服务器将接收输入,对其进行处理,调用张量流服务器进行预测,并返回处理后的张量流输出。

TensorFlow 服务配置

我们可以选择包含一个yml文件来配置我们的服务器。这个配置文件可以用来指定模型名称、模型路径、版本策略(我们是想使用特定的版本还是总是最新的版本?),记录配置以及服务器检查新型号版本的频率。这一步在每个生产环境中都是绝对重要的。

模型改进

第 1 部分为部署构建了一个快速模型,但没有关注性能改进。在第 2 部分中,我们将探索早期停止、预训练向量的有效性以及模型改进的其他潜在领域。

张量板

TensorBoard 是一套用于可视化和理解机器学习实验的 web 应用程序。它非常容易设置,但是解释起来有点棘手。

敬请关注第二部分

感谢您的阅读!

如果你喜欢这篇文章,可以看看我关于数据科学、数学和编程的其他文章。通过 Medium 关注我的最新动态。😃

作为一个业余爱好项目,我还在 www.dscrashcourse.com建立了一套全面的免费数据科学课程和练习题。

如果你想支持我的写作,下次你报名参加 Coursera 课程时,可以考虑使用我的会员链接。完全公开—我从每一次注册中获得佣金,但不会对您产生额外费用。

再次感谢您的阅读!📕

将机器学习模型部署为数据,而不是代码——更好的匹配?使用 omega|ml 的 MLOps

原文:https://towardsdatascience.com/deploying-machine-learning-models-as-data-not-code-omega-ml-8825a0ae530a?source=collection_archive---------20-----------------------

数据科学界的使命是找到部署机器学习解决方案的最佳方法。我的 MLOps 开源框架 omega|ml 通过将模型部署为数据来实现一种新颖的方法,提高了速度和灵活性,同时降低了工具链的复杂性。

Photo by Stephen Dawson on Unsplash

用于机器学习的 DevOps:不完全匹配

当涉及到部署机器学习模型时,mlflow 和 kubeflow 等工具促进了 DevOps 原则的使用,即像代码一样打包模型,将它们作为软件发布的一部分进行部署。乍一看,这种方法提供了几个期望的属性:

  • 模型和其他代码一起被版本化
  • 模型发布是作为一个单元构建、打包和部署的
  • 部署是可重复的,回退是可能的

然而,当我们将这种 DevOps 方法应用于机器学习时,我们的部署缺少运行有效的机器学习解决方案所需的其他关键属性。

特别是,在任何协作环境中,更重要的是在多产 ML 系统中,我们希望:

  • 立即共享和部署新模型
  • 在生产中自动重新训练模型
  • 捕获运行时模型输入,供以后在质量保证中使用
  • 运行多个模型版本(rendezvous 架构)

关键观察:模型本质上是数据

机器学习模型本质上由给定的算法+权重+超参数组成。权重和参数是数据,而不是代码,而任何特定模型的算法都是对静态库的引用。从这个角度来看,将模型视为数据比围绕权重+超参数创建包装语义更自然。

实现这一点的一种方法是构建额外的工具和基础设施,在更传统的 DevOps CI/CD 流程之上获得这些属性。然而,我建议重新思考这个问题,将模型视为数据,而不是代码。

使用 omega|ml,将模型作为数据进行部署是非常简单的

将模型视为数据而非代码是什么意思?在 omega|ml 中,可以直接从 Python 代码中部署模型:

clf = LogisticRegression() # scikit learn model
om.models.put(clf, 'mymodel') # store the model

这将模型clf存储为 joblib-pickle 文件,并在 omega|ml 的内置分析存储中创建一个Metadata条目。它还在/api/v1/model/mymodel创建了一个 REST API 端点,以便可以从任何应用程序、任何编程语言访问该模型。部署是即时的,没有延迟,不需要打包或 CI 过程,也没有任何显式的部署步骤:不需要构建、部署和启动容器。

在集群中本地或远程安装模型

“等待”,你说,“我们还没有拟合模型,那么部署模型有什么用?”。omega|ml 可以部署未安装和安装的型号。如果模型不合适,我们可以远程训练模型,即使用 omega|ml 的计算集群:

om.runtime.model('mymodel').fit(X, Y)

这将选择一个计算节点,将 X 和 Y 数据加载到内存中,并运行clf.fit(X, Y)方法。完成后,它将以相同的名称存储现在适合的模型,有效地用适合的版本替换先前不适合的模型。我们可以随时在集群中重新运行fit方法。也可以运行任何其他建模方法,如partial_fit, score, gridsearch等。

传递给fit方法的X,Y参数或者是内存中的数据对象(如 Pandas DataFrames、Series 或 Numpy ndarrays),或者是之前保存的命名对象,例如:

# save data, a pd.DataFrame
om.datasets.put(data, 'mydata')# assuming data has several feature columns with a target variable om.runtime.model('mymodel').fit('mydata[^Y]', 'mydata[Y]')

开发与生产分离

分离开发和生产在任何软件系统中是重要的,这些软件系统在被有效使用的同时经历了积极的开发。机器学习系统也是如此。omega|ml 通过对象提升的概念支持环境分离:

# om_prod is the production instance
om.models.promote('mymodel', om_prod.models)

生产实例可以是 omega|ml 在生产集群中的单独部署,也可以利用内置的 bucket 功能:

# here the production-bucket is a logical namespace 
om_prod = om['production-bucket']

它是如何工作的?

omega|ml 的任何实例都提供并运行数据科学团队所需的所有组件,无论是在开发中还是在生产中:

  • 多用户 Jupyter 笔记本:数据科学家可以在共享的 Jupyter 主机上工作,或者在用户特定的实例上工作。笔记本可以通过一个简单的命令和类似人类的时间表轻松安排,例如“每天早上 6 点”。
  • 分析商店:内置的分析商店提供结构化和非结构化存储(由 MongoDB 支持),包括可扩展的分布式文件系统。使用 omega|ml 的插件机制可以添加任何存储后端。内置的分析存储意味着团队可以立即高效地开始工作,而无需从/向其笔记本电脑或从/向一些外部托管的对象存储进行耗时且低效的文件复制。这也意味着公司可以重新集中安全地组织用于机器学习的数据,降低由于无意中复制到潜在不安全的位置(如笔记本电脑的硬盘)而导致数据泄露的风险。
  • 计算集群:虽然今天的台式机和笔记本电脑甚至有足够的资源用于机器学习,但利用云在许多情况下是有用的,如果不是必要的话。例如,数据集处理和模型训练可以异步、整夜运行,或者使用仅由云提供商提供的 GPU 运行,而无需持续连接或保持本地工作站运行。omega|ml 专为云设计,内置了强大的可扩展运行时架构。它支持训练模型和有效处理大型核外数据集,连接 GPU 或其他资源是一个配置问题。

此外,omega|ml 提供了各种 API 来满足不同的需求。

  • 模型、数据集和 lambda 风格/无服务器脚本的 REST API (部署和运行任意 Python 模块)
  • 可扩展的 Python API 利用 Flask、Django 或 Plotly Dash 等构建后端应用和 web 应用。
  • 命令行客户端(cli) 支持任何开发和脚本环境。cli 还支持使用本地 ide,如 Pycharm 或 Jupyter Notebook 的本地实例,并将笔记本和自动构建的 PIP 包部署到 omega|ml 运行时。

请注意,对于 omega|ml 支持的任何模型,部署方式都是相同的,例如任何 scikit-learn 模型(包括管道)、Tensorflow 和 Keras 模型。此外,omega|ml 提供了一种易于扩展的插件机制,以完全相同的方式支持任何其他机器学习框架。

一种方法,多种好处

将模型部署为数据意味着数据科学团队可以同时完成几件事情:

  • 协作:一旦模型被保存到数据存储中,其他团队成员可以很容易地检索模型,并在本地或远程使用它:
# retrieve the model locally 
clf = om.models.get('mymodel')
=> clf is the last saved LogisticModel# score the model remotely, using some new in-memory data in X, Y
om.runtime.model('mymodel').score(X, Y)# run a gridsearch remotely, saving the best model
om.runtime.model('mymodel').gridsearch(X, Y, parameters=...)
  • 生产中重新训练:由于模型作为对象存储在数据库中,生产中的重新训练和部署就像运行一个作业一样简单,该作业在模型上重新运行fit方法:
# assuming the new data is in saved objects newX, newY
om.runtime.model('mymodel').fit('newX', 'newY')
  • 捕获用于预测的数据:通过 REST API 传递到模型中的任何数据都会在预测之前自动保存(这个特性还有改进的空间,相应的插件正在开发中)。或者,我们可以通过 REST API 或 Python API 存储预测后的数据
# store the input and output data after prediction from Python
om.datasets.put(inout, 'predicted-upondata')
# use the REST API
PUT /api/v1/datasets/predicted-upondata/ (+ JSON body
  • run-multiple model versions:将模型视为代码,使用一个命名约定来部署多个模型版本是很容易的,然后并行运行模型,并通过一些聚集来选择最佳结果。
# store
om.models.put(model1, 'mymodel-1')
om.models.put(model2, 'mymodel-2') # run in parallel, note each call is asynchronous
y1 = om.runtime.model('mymodel-1').predict(X)
y2 = om.runtime.model('mymodel-2').predict(X)# aggregate y1 or y2 in some way once results are available
...

请注意,这只是 omega|ml 支持多模型版本的一种方式,其他方式包括虚拟对象处理程序(将多个模型组合在同一名称下)或使用脚本/lambda 模块(使用om.runtime.job('script-name').run())运行任意代码)

结论

当将模型视为代码时,使用 DevOps 原则部署模型是一个显而易见的选择。然而,它在几个期望的属性上有所欠缺,如即时部署、协作、生产中再培训、用于质量保证的运行时数据收集以及以 rendevouz 风格运行多个模型版本。因此,将 DevOps 方法应用于机器学习——实际上是数据科学——需要额外的投资和工具来实现这些特性。

omega|ml 认为模型是数据,而不是代码。这实现了从实验室到生产的开发和操作数据科学和机器学习系统的所有期望属性。也就是说,omega|ml 帮助数据科学团队高效利用云资源,在机器学习模型和数据上进行合作,并轻松实施他们的 ml 解决方案。事实上,使用 omega|ml,部署机器学习模型只需一行代码。

更多信息请访问 http://get.omegaml.io

将模型部署到 Flask

原文:https://towardsdatascience.com/deploying-models-to-flask-fb62155ca2c4?source=collection_archive---------10-----------------------

Photo by Agence Olloweb on Unsplash

关于如何使用 Python 和 Flask 为用户交互部署机器学习模型的演练

这个项目的代码可以在这里找到。

你已经用熊猫、Sci-kit Learn 和 Jupyter 笔记本建立了一个模型。结果在您的笔记本上看起来很棒,但是您如何与他人分享您的成果呢?

为了共享模型,我们需要部署它们,最好是部署到某个网站,或者至少使用 Python 文件。今天,我将以我的聊天室毒性分类器模型为例,向您介绍使用 Python 和 Flask 将模型部署到网站的过程。本文假设您知道如何编写 Python 代码,了解 HTML 的基础知识,并且安装了 Flask】或conda install flask)。我们将从文件结构开始!

Flask 文件结构

Flask 希望东西在一个特定的文件夹布局中,以便正确加载。我为这个项目的文件结构拍了一个快照,但是下面只列出了几个重要的元素:

Example of deployed Flask and Heroku file structure

必要的要素是:

  1. 静态文件夹—存在于根目录中。这包含了所有的静态资产,如 css 文件、图像、字体和压缩模型。
  2. 模板文件夹——存在于根目录中。这是模板 HTML 文件必须在的默认位置,以便 Flask 正确地渲染它们。任何与你的模型交互的页面都会在这里。
  3. predictor.html—这是用户可以与之交互的前置 HTML 文件,您的模型将向其输出结果。这是一个需要放在 Templates 文件夹中的文件示例。
  4. predictor_api.py —存在于根目录中。该文件包含运行模型和数据预处理的函数。
  5. predictor_app.py —存在于根目录中。这个文件充当调用模型的 API 文件和显示结果并接受用户输入的 HTML 文件之间的链接。

上图中的所有内容对于 Flask 的正常运行都不是必需的,在本文的其余部分可以忽略。让我们来看看你是如何设置这些文件的!

设置 API.py 文件

首先,您需要创建一个 API Python 文件。这是一个包含所有方法的文件,这些方法预处理您的数据,加载您的模型,然后根据用户提供的数据输入运行您的模型。请注意,这是独立于 Flask 的,因为这只是一个 python 文件,运行您的模型,没有 Flask 功能。下面是我的 predictor_api.py 文件的框架,其中包含运行我的模型的所有函数:

# predictor_api.py - contains functions to run modeldef clean_word(text):
    # Removes symbols, numbers, some stop words    
    return cleaned_textdef raw_chat_to_model_input(raw_input_string):
    # Converts string into cleaned text, converts it to model input
    return word_vectorizer.transform(cleaned_text)def predict_toxicity(raw_input_string):
    # Takes in a user input string, predict the toxicity levels
    model_input = raw_chat_to_model_input(raw_input_string)
    results = []
    # I use a dictionary of multiple models in this project
    for key,model in model_dict.items():
        results.append(round(model.predict_proba(model_input)))
    return resultsdef make_prediction(input_chat):
    '''
    Given string to classify, returns the input argument and the    
    dictionary of model classifications in a dict so that it may be
    passed back to the HTML page.
    ''' # Calls on previous functions to get probabilities of toxicity
    pred_probs = predict_toxicity(input_chat) probs = [{'name': list(model_dict.keys())[index], 'prob': \    
            pred_probs[index]} \
            for index in np.argsort(pred_probs)[::-1]]    
return (input_chat, probs)

这是个人偏好,您的数据处理步骤将因您正在做的模型类型以及您正在处理的数据而异,但我将这个有毒聊天分类器中的功能分为:

  1. 字符串清洗
  2. 对字符串进行矢量化,以将其输入到模型中
  3. 使用步骤 2 的输出建立预测模型
  4. 最终make_predictions函数,在一次函数调用中调用从原始输入到模型预测的管道中的所有先前步骤。

旁注:您将希望以字典格式传递您的预测,因为这是 Flask 在其模板和 python 文件之间传递信息的格式。

测试 API.py 文件

一旦你设置好了你的函数,你需要一些方法来测试它们。这是我们为脚本设置主要部分的时候:

if __name__ == '__main__':
    from pprint import pprint
    print("Checking to see what empty string predicts")
    print('input string is ')
    chat_in = 'bob'
    pprint(chat_in)x_input, probs = make_prediction(chat_in)
    print(f'Input values: {x_input}')
    print('Output probabilities')
    pprint(probs)

只有当我们使用python script_name.py在命令行上启动脚本时,__name__=='__main__'部分才会运行。这允许我们调试我们的功能,并在一旦我们的应用程序或网站启动就不会运行的文件区域中添加任何单元测试。这部分代码纯粹是给程序员看的,以确保你的函数正常工作

设置 Flask Python app.py 文件

现在您的 API 文件应该可以工作了。酷,我们怎么把它放到网站上?这就是弗拉斯克的用武之地。Flask 是一个 Python 框架,它使用 Jinja2 HTML 模板来允许你使用 Python 轻松地创建网页。Flask 框架处理大量的后端 web 内容,因此您只需几行 Python 代码就可以做更多的事情。首先,您需要创建应用程序 Python 文件:

# predictor_app.py
import flask
from flask import request
from predictor_api import make_prediction# Initialize the appapp = flask.Flask(__name__)# An example of routing:
# If they go to the page "/" (this means a GET request
# to the page [http://127.0.0.1:5000/](http://127.0.0.1:5000/))[@app](http://twitter.com/app).route("/", methods=["GET","POST"])
def predict():
    # request.args contains all the arguments passed by our form
    # comes built in with flask. It is a dictionary of the form
    # "form name (as set in template)" (key): "string in the    
    # textbox" (value)
    print(request.args)
    if(request.args):
        x_input, predictions = \   
            make_prediction(request.args['chat_in'])
        print(x_input)
        return flask.render_template('predictor.html',
                                     chat_in=x_input,
                                     prediction=predictions)
    else: 
        #For first load, request.args will be an empty ImmutableDict
        # type. If this is the case we need to pass an empty string
        # into make_prediction function so no errors are thrown.

        x_input, predictions = make_prediction('')
        return flask.render_template('predictor.html',
                                     chat_in=x_input,
                                     prediction=predictions)# Start the server, continuously listen to requests.if __name__=="__main__":
    # For local development, set to True:
    app.run(debug=False)
    # For public web serving:
    #app.run(host='0.0.0.0')
    app.run()

这里发生了很多事情,所以我会试着把它分成容易理解的部分。

进口

首先我们导入 flask,并明确地导入request以提高生活质量。接下来,我们有

from predictor_api import make_prediction

这将转到我们之前编写的 API 文件并导入make_prediction函数,该函数接收用户输入并运行所有数据预处理,然后输出我们的预测。

托管网页

我将简单地跳到底层代码。如前所述,

if __name__=="__main__":

通过命令行运行 Python 脚本时运行。为了托管我们的网页,我们需要运行python your_app_name.py。这将调用app.run()并在本地运行我们的网页,托管在您的计算机上。

按指定路线发送

初始化应用程序后,我们必须告诉 Flask 当网页加载时我们要做什么。行@app.route("/", methods = ["GET","POST"]) 告诉 Flask 当我们加载我们网站的主页时该做什么。GET 方法是 web 浏览器在访问网页的 URL 时向网站发送的请求类型。不要担心 POST 方法,因为它是用户想要更改网站时通常使用的请求,在这个部署过程中它与我们没有太大的相关性。如果您想在网站上添加另一个页面,您可以添加:

@app.route("/page_name", methods = ["GET","POST"])
def do_something():
    flask.render_template('page_name.html',var_1 = v1, var_2 = v2)

路由下的函数名没有任何意义,它只包含用户到达该页面时运行的代码。

运行模型

在路由下面的函数中,我们有request.args。这是一个 dictionary ( JSON )对象,它包含当有人单击我们表单上的“提交”按钮时提交的信息。下面我将展示我们如何分配request.args 对象中的内容。一旦我们有了参数,我们就使用从其他文件导入的函数将它传递给我们的模型,然后使用我们的模型通过返回的预测值来呈现模板:

return flask.render_template('predictor.html',
                              chat_in=x_input,
                              prediction=predictions)

这个函数接收我们的网站运行的 html 文件,然后传入从模型x_input, predictions输出的变量,并将它们作为chat_in, prediction发送到 HTML 模板。从这里开始,模型的工作就完成了,现在我们只需要担心向用户显示结果!

烧瓶模板

将用户输入传递到 app.py 文件

首先,我们需要为用户提供一种方法,将他们的输入传递给我们的模型。因为我们接受聊天输入,所以让我们创建一个文本框和一个提交按钮。

HTML Code
<input type="text" name="chat_in" maxlength="500" ><!-- Submit button -->
<input type="submit" value="Submit" method="get" >

当用户输入一个值并点击 submit 按钮时,它将向模板发送一个 get 请求,并用文本框中的name标志填充request.args 字典。为了访问用户的输入,我们将在 Python 应用程序文件中使用request.args['chat_in']。我们可以将它传递到模型中,如上面这行所示:

make_prediction(request.args['chat_in'])

将模型输出传递给 HTML 模板

因此,我们已经使用 python 文件做出了预测,但现在是时候使用 HTML 模板显示它们了。模板只是改变 HTML 代码的一种方式,这样我们就可以用新的值(比如我们的预测)来更新用户。我的目标不是在这里教你 HTML,所以我不打算详细说明 HTML 代码(但是如果你好奇,你可以在 github 链接中找到它),但是基本上你会使用下面的语法显示传递的变量:

<!-- predictor.html file -->
<!DOCTYPE html>
<html lang="en"><p> Here are my predictions!<br>
{{ chat_in }}
{{ prediction[0]['prob'] }} </p>

在这个例子中,我显示了在上面的render_template函数中传递的chat_in变量。我还显示了传递给模板的字典prediction中的第一个元素,它包含多个模型。从功能的角度来看,我们完成了!从这里开始,你可以专注于让你的应用程序看起来漂亮,反应灵敏。

Website example using chat toxicity classifier

烧瓶到此为止!通过一些额外的 HTML 代码和可能的 JavaScript,你可以拥有一个在你的电脑上运行的漂亮的交互式网站。从这里,你可以将网站部署到你选择的平台上,可以是 Heroku、Amazon Web Services 或 Google Cloud。

感谢阅读,请关注我的下一篇关于部署到 Heroku 的文章!

使用 Mlflow 和 Amazon Sagemaker 将模型部署到生产环境中

原文:https://towardsdatascience.com/deploying-models-to-production-with-mlflow-and-amazon-sagemaker-d21f67909198?source=collection_archive---------4-----------------------

2019 年 8 月 21 日更新:更改了参数和一些硬编码变量,以便与 mlflow 1.2.0 一起使用

随着数据科学在 2019 年继续成熟,对数据科学家超越笔记本电脑的需求越来越多。一些绩效指标不再足以交付商业价值。模型需要以可伸缩的方式部署和使用,实时模型推理应该是容错和高效的。

Is Naruto in Sage Mode too nerdy even for this post? Probably…the SageMaker pun is weak as hell too but whatever — Source

传统上,模型部署是由工程团队处理的。数据科学家将模型交给工程师进行代码重构和部署。然而,数据科学家缺乏标准化和良好的开发/运营会在两个团队之间产生摩擦,使部署变得繁琐和低效。作为对这一趋势的回应,Databricks 公司(由 Apache Spark 的创始人创立)一直致力于 ml flow——一个用于模型跟踪、评估和部署的开源机器学习平台。参见介绍发布帖。

Mlflow 与 Amazon SageMaker 或 AzureML 等托管部署服务配合得很好。你甚至可以用它来构建定制的开源部署管道,比如 Comcast 的这个。鉴于最近发布的 mlflow 1.0.0,我想为数据科学家提供一些关于部署和管理他们自己的模型的最低限度的指导。

设置

对于本教程,您需要:

  • AWS 帐户
  • 安装在本地机器上的 Docker
  • 安装了mlflow>=1.0.0的 Python 3.6

让我们开始吧。

配置亚马逊

您需要做的第一件事是在您的本地机器上配置 AWS CLI,以便您可以通过编程方式与您的帐户进行交互。如果你还没有,在这里创建一个账户然后从终端运行下面的命令。

pip install awscli --upgrade --user
aws configure

第二个命令将提示您输入您的密钥和区域,您可以在登录到控制台时从您的帐户获得。在此处查看完整指南。如果您愿意,您还可以创建具有更具体和有限权限的 IAM 用户,如果您有多组凭证,请确保将AWS_DEFAULT_PROFILE环境变量设置为正确的帐户。

View of the AWS Console

最后,您需要一个能够访问 SageMaker 的角色。在 AWS 上,转到 IAM 管理控制台并创建一个新角色。然后,将“AmazonSageMakerFullAccess”策略附加到角色,稍后您将需要它来与 SageMaker 进行交互。

其他安装

按照正确的步骤在你的操作系统上安装 Docker 。然后确保你启动了 Docker 守护进程(在你的菜单栏里查看有趣的小鲸鱼)。

不打算解释如何安装 Python——我们必须超越这个权利?只要确保你已经用pip install mlflow安装了最新的 mlflow。如果您与团队合作,您也可以运行远程 mlflow 服务器,只需确保您指定了 mlflow 记录模型的位置(S3 存储桶)。请参见下面的服务器命令:

mlflow server --default-artifact-root s3://bucket --host 0.0.0.0

该服务应该在端口 5000 上启动。只需确保启动 mlflow 的主机和您的本地机器都具有对 S3 存储桶的写访问权限。如果只是在本地工作,不需要启动 mlflow。

使用 Mlflow 进行模型跟踪

酷,现在我们准备好开始实际建模了。Mlflow 允许您记录参数和指标,这对于模型比较来说非常方便。在您的代码中创建一个实验将会创建一个名为“mlruns”的目录,其中存储了您的实验的所有信息。

不要恨我,但我将使用 iris 数据集,因为它非常简单,这里的目的是说明 mlflow 如何与 SageMaker 一起使用。下面,我们可以看到一个记录我们的超参数、模型性能度量和实际模型本身的例子。

现在还不清楚发生了什么,但是如果你打开另一个终端,在你当前的工作目录中输入mlflow ui,你可以在一个方便的应用程序中检查我们刚刚登录的所有内容。Mlflow 允许您通过参数和指标进行过滤,并查看您可能已经记录的任何工件,如模型、环境、元数据等...

Look at the Mlflow UI (not our models) — Source

当 mlflow 记录模型时,它还会生成一个conda.yaml文件。这是您的模型需要运行的环境,它可以根据您的需要进行大量定制。使用 mlflow 模型可以做更多的事情,包括自定义预处理和深度学习。这个库有各种各样的模型“风格”,所以你不会被 sklearn 束缚住,还可以使用 Pytorch 或 TF。点击查看文件。

亚马逊 ECR 图像

既然我们已经保存了我们的模型工件,我们需要开始考虑部署。第一步是向 Amazon 的弹性容器注册中心提供一个 Docker 映像,我们可以用它来服务我们的模型。如果你对 Docker 不熟悉,请查看文档。

Amazon ECR — Source

mlflow Python 库有用于这一部分的函数,但我在编写时遇到了一些问题,所以我使用了 CLI。打开一个新终端,并在命令行中键入以下内容:

mlflow sagemaker build-and-push-container

如果您已经使用适当的权限正确地设置了 AWS,这将在本地构建一个映像,并将其推送到 AWS 上的映像注册表中。要检查它是否正常工作,请转到 AWS 控制台,并单击“服务”下拉菜单中“计算”下面列出的“ECR”服务。您应该看到一个名为mlflow-pyfunc的存储库,其中应该列出了一个图像。

部署到 Sagemaker

现在,在部署供消费的模型端点之前,我们只剩下有限的事情要做了。基本上,我们所要做的就是向 mlflow 提供我们的图像 url 和所需的模型,然后我们可以将这些模型部署到 SageMaker。

Amazon SageMaker Workflow — Source

您需要的是您的 AWS ID,您可以从控制台或通过在终端中键入aws sts get-caller-identity --query Account --output text来获得它。此外,您将需要在设置 Amazon 时创建的 SageMakerFullAccess 角色的 ARN。转到 IAM 管理控制台,单击角色并复制 ARN。如果您的模型托管在本地系统之外的其他地方,您还必须编辑模型路径。

如果您的 AWS 凭证设置正确,这应该会连接到 SageMaker 并部署一个模型!可能需要一点时间才能达到“使用中”状态。一旦完成,您就可以使用boto3库或通过进入控制台,以编程方式检查您的模型是否已经启动并运行。这段代码改编自这里的数据块教程。

输出应该如下所示:

Application status is: InService
Received response: [2.0]

现在您正在调用您的端点,您可以通过 AWS 控制台查看使用情况的统计数据,方法是转到 SageMaker 服务。使用 SageMaker 还可以做更多的事情,但是我将把这些留给大量其他可用的教程。一旦你玩完了新的机器学习模型,你就可以删除端点了。

mfs.delete(app_name=app_name, region_name=region)

就是这样!这是一个非常简单的教程,但希望这能让你一窥生产级机器学习的各种可能性。请记住,永远不要将 AWS 密钥发布或上传到 Github 这样的地方——有人会偷走它们,并在你的硬币上挖掘一堆比特币。玩得开心!

用 JavaScript 部署您的数据科学项目

原文:https://towardsdatascience.com/deploying-your-data-science-projects-in-javascript-b873df6c2450?source=collection_archive---------22-----------------------

一小时内将 React 客户端、Python JSON API 和 SSL 证书从 Let's Encrypt 推送到 DigitalOcean

Photo by Daniel Mayovskiy on Unsplash

对于我最新的项目,我决定使用 React 进行大部分探索性数据分析(EDA ),并需要一个非常简单的 JSON API 来提供必要的数据,以避免加载+70 MB 的页面。在本教程中,我将带你在 DigitalOcean 上使用 create-react-app 、 fastapi 和 Nginx 部署一个示例应用的过程。您可以探索真正的应用程序,因为它目前位于 https://ecce.rcd.ai 。这种产品部署过程有点手动,但是如果需要的话,当然可以自动化。

以下是实现这一目标的顶级步骤:

  1. 用 fastapi 创建 Python API
  2. 使用 create-react-app 创建客户端应用程序(并将请求传递给 API)
  3. 创建 DigitalOcean droplet 并安装依赖项
  4. 配置 Nginx(将 React 和 Python 统一为一个 web 服务)
  5. 构建客户端应用程序并拷贝到 droplet
  6. 克隆客户端 API 并作为 cronjob 安装
  7. 设置域并从 Let's Encrypt 获取 SSL 证书
  8. 为出色完成的工作拿一杯咖啡☕!🎉

Python API 和 fastapi

据我所知, fastapi 是创建 Python API 最简单、最快的方法。这是一个单一文件服务器,可以根据需要轻松扩展和配置。对于这个例子,我们将提供来自 ESV 的诗句(法律允许,因为这是一个非商业项目)。我们将使用这些命令从头开始项目:

*# Create directory and jump into it* mkdir -p fastapi-react-demo/app cd fastapi-react-demo *# Download data source* curl -LO [https://github.com/honza/bibles/raw/master/ESV/ESV.json](https://github.com/honza/bibles/raw/master/ESV/ESV.json)
mv ESV.json app/esv.json *# Install dependencies* pip install fastapi uvicorn toolz *# Save dependencies for later use* pip freeze | grep "fastapi\|uvicorn\|toolz" > requirements.txt*# Create server file* touch app/server.py

app/server.py中:

from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
import json
import os
from toolz import memoizeapp = FastAPI() *# TODO: Change origin to real domain to reject Ajax requests from elsewhere* app.add_middleware(CORSMiddleware, allow_origins=['*'])@memoize
def data():
    with open(os.path.join(os.path.dirname(__file__), 'esv.json')) as f:
         return json.load(f) @app.get('/api/verse/{book}/{chapter}/{verse}')
def load_text(book: str, chapter: int, verse: int):
     try:
         return {'text': data()[book][str(chapter)][str(verse)]}
     except KeyError as e:
         return {'error': str(e), 'type': 'KeyError'}

从这个简单的文件中,我们有了 JSON API、CORS、参数验证等等。让我们继续在开发模式下运行它来检查一下:

# Start app
uvicorn app.server:app --reload# Send API request (in separate window)
curl [http://localhost:8000/api/verse/Genesis/1/1](http://localhost:8000/api/verse/Genesis/1/1)
# => {"text":"In the beginning, God created the heavens and the earth."}

随着服务器的运行,我们不仅在开发中拥有完全可操作的 JSON API,而且如果我们改变了文件中的任何内容,它甚至会实时重新加载。让我们谈谈客户。

具有创建-反应-应用的客户端应用

API 在开发模式下运行,让我们继续创建一个客户端应用程序。如果你在 React 中做数据科学可视化,我假设你熟悉 JavaScript 生态系统。

npx create-react-app client

在添加我们的 ajax 代码之前,我们需要为create-react-app配置代理,以将它不能处理的请求转发给运行在端口 8000 上的 API 服务器。

client/package.json

 ...
},
"proxy": "http://localhost:8000",
"scripts": ...

我们将继续从客户端进行一个简单的 API 调用:

client/src/App.js

import React, { Component } from 'react';class App extends Component {
  constructor(props) {
    super(props);
    this.state = { verse: 'Loading...' };
  } componentDidMount() {
    fetch('/api/verse/Genesis/1/1')
      .then(r => r.json())
      .then(data => this.setState({ text: data.text }));
  } render() {
    return (
      <div>
        <h1>fastapi-react-demo</h1>
        <p>Result of API call: {this.state.text}</p>
      </div>
    );
  }
}export default App;

有了更新的文件,我们就可以开始启动服务器了。

cd client && yarn start

万岁!它肯定不会赢得任何设计奖项,但我们现在有两个应用程序互相交谈。我们来谈谈如何实际部署这些应用程序。

请确保您已经将它上传到一个 Git 存储库,以便我们稍后可以轻松地克隆它。(如果没有,不要担心——你可以只使用 https://github.com/rcdilorenzo/fastapi-react-demo 的样本库)。

随着应用程序的启动和运行,我们现在必须为世界部署我们的代码!我们将从创建一个数字海洋水滴开始。在这种情况下,我将选择 Ubuntu 18 的最小磁盘大小来为应用程序服务。

有了 SSH 键,我们就可以进入设置中描述的 droplet 了。

ssh root@<DROPLET_IP xxx.xxx.xxx.128># (on server)
apt-get update apt-get install -y nginx-full

配置 Nginx

我们现在需要设置 Nginx 来完成三项任务。

  1. 每当路线以/api开始时提供 Python 应用
  2. 对于任何特定资产或未找到路线,可退回到 React 应用程序
  3. 强制 SSL 并使用来自“让我们加密”的证书

我不会跳过此配置的所有细节,但它应该可以实现我们的目标,稍后您将了解更多细节。对于编辑,继续使用您最喜欢的命令行编辑器。(我的是 vim,用于快速编辑;最简单的是纳米。)确保用您的自定义域替换demo.rcd.ai

/etc/nginx/sites-available/demo.rcd.ai.conf

server {
    listen [::]:80;
    listen 80;
    server_name demo.rcd.ai;
    location / {
        return 301 [https://$host$request_uri](/$host$request_uri);
    }
}server {
    listen [::]:443 ssl http2;
    listen 443 ssl http2;
    server_name demo.rcd.ai;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log; ssl_certificate /etc/letsencrypt/live/demo.rcd.ai/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/demo.rcd.ai/privkey.pem; root /var/www/demo/; index index.html; location / {
      try_files $uri $uri/ /index.html;
    } location /api {
      proxy_pass [http://localhost:1234](http://localhost:1234); # Port of Python server
    } # JavaScript/CSS
    location ~* \.(?:css|js)$ {
        try_files $uri =404;
        expires 1y;
        access_log off;
        add_header Cache-Control "public";
    } # Any file route
    location ~ ^.+\..+$ {
        try_files $uri =404;
    }
}

让我们将这个文件符号链接到sites-enabled文件夹中,这样 Nginx 在收到来自域demo.rcd.ai的请求时就会知道要服务它。

ln -s /etc/nginx/sites-available/demo.rcd.ai.conf /etc/nginx/sites-enabled/demo.rcd.ai

虽然我们可以让 Nginx 重新加载,但是在它正常工作之前,我们还有一些事情要做。

  1. 用我们的域名注册商添加demo.rcd.ai来指向这个 IP 地址
  2. 将客户端的生产版本复制到/var/www/demo
  3. 克隆 Python 服务器,并在端口 1234 上启动它
  4. 请求让我们加密证书

我不会过多讨论设置子域记录的细节,因为这取决于你的提供商。这是我添加到 NameCheap 的内容,因为那是我的注册商。

请注意,这可能需要一段时间才能将变化反映到“互联网”上您总是可以通过简单的 ping 命令来检查它:

❯ ping demo.rcd.ai
# PING demo.rcd.ai (159.89.130.128) 56(84) bytes of data.
# 64 bytes from 159.89.130.128 (159.89.130.128): icmp_seq=1 ttl=48 time=88.4 ms
# 64 bytes from 159.89.130.128 (159.89.130.128): icmp_seq=2 ttl=48 time=85.4 ms
# ^C
# --- demo.rcd.ai ping statistics ---
# 2 packets transmitted, 2 received, 0% packet loss, time 1000ms
# rtt min/avg/max/mdev = 85.411/86.921/88.432/1.539 ms

构建和部署客户端

回到开发机器上的client/文件夹,创建一个产品版本就像发出一个命令一样简单。然后我们将它打包并发送到/var/www/demo目录中的 DigitalOcean droplet。

# Build production-optimized assets
yarn build# Zip contents
zip -r build.zip build/# Upload with scp
scp build.zip root@<DROPLET_IP>:/var/www/

然后在水滴上:

# Unzip and rename folder
apt-get install -y unzip
cd /var/www && unzip build.zip
mv build demo

此时,Nginx 应该适当地服务于资产。然而,因为证书还没有到位,它甚至不允许我们加载配置。

来自“让我们加密”的 SSL 证书

虽然我们可以设置 Python 服务器,但最好能得到一些反馈,以确保至少我们的客户端得到了正确的服务。本着快速迭代的精神,让我们首先设置证书。从 https://certbot.eff.org很容易获得说明。在 droplet 上,继续安装 certbot。

apt-get update
apt-get install software-properties-common
add-apt-repository universe
add-apt-repository ppa:certbot/certbot
apt-get update apt-get install certbot python-certbot-nginx

在这里,可以通过一个命令获得证书。

certbot certonly --standalone \
  --pre-hook "service nginx stop" \
  --post-hook "service nginx start" \
  --preferred-challenges http -d demo.rcd.ai
# ...
# Running pre-hook command: service nginx stop
# Obtaining a new certificate
# Performing the following challenges:
# http-01 challenge for demo.rcd.ai
# Waiting for verification...
# Cleaning up challenges
# Running post-hook command: service nginx start
# # IMPORTANT NOTES:
# - Congratulations! Your certificate and chain have been saved at:
# /etc/letsencrypt/live/demo.rcd.ai/fullchain.pem
# Your key file has been saved at:
# /etc/letsencrypt/live/demo.rcd.ai/privkey.pem
# Your cert will expire on 2019-06-26\. To obtain a new or tweaked
# version of this certificate in the future, simply run certbot
# again. To non-interactively renew *all* of your certificates, run
# "certbot renew"
# - Your account credentials have been saved in your Certbot
# configuration directory at /etc/letsencrypt. You should make a
# secure backup of this folder now. This configuration directory will
# also contain certificates and private keys obtained by Certbot so
# making regular backups of this folder is ideal.
# ...

因为这个命令停止并重启 Nginx,所以我们应该可以直接进入应用程序,看到一些东西( https://demo.rcd.ai )。我们还可以特别请求 Nginx 重新加载配置。

nginx -s reload

部署 API

Nginx 配置需要一个内部服务器监听端口 1234,剩下的就是在 droplet 上运行 Python 服务器。因为我们将代码推送到 GitHub,所以剩余的命令可以从 droplet 运行。

# Clone code to folder
cd /var/www
git clone https://github.com/rcdilorenzo/fastapi-react-demo.git demo-server# Install Python-3.6 based virtualenv (to avoid version conflicts)
apt-get install -y python3.6-venv python3-venv python3.6-dev# Jump into server folder
cd demo-server# Create virtual environment in /var/www/demo-server/demo_3.6
python3.6 -m venv demo_3.6# Install a couple of prerequisites for compiling some dependencies
./demo_3.6/bin/pip install wheel
apt-get install -y gcc# Install dependencies
./demo_3.6/bin/pip install -r requirements.txt

安装完依赖项后,可以内联启动服务器进行测试。

./demo_3.6/bin/uvicorn app.server:app --port 1234
INFO:uvicorn:Started server process [9357]
INFO:uvicorn:Waiting for application startup.
INFO:uvicorn:Uvicorn running on http://127.0.0.1:1234 (Press CTRL+C to quit)

重新访问页面,我们可以看到诗句现在正确加载。

然而,只有当我们打开 SSH 会话时,这个 Python 服务器才会运行。为了让它在重启后仍然存在,我们可以添加到crontab中。我们必须运行的唯一命令是切换到服务器根目录并运行uvicorn。用CTRL-c杀死服务器,用crontab -e打开 crontab。

@reboot cd /var/www/demo-server && ./demo_3.6/bin/uvicorn app.server:app --port 1234

保存并关闭该文件。用reboot重启服务器。一旦 droplet 重新启动,应用程序应该会自动启动。

如果你已经走到这一步,那么恭喜你。🎉去喝杯咖啡吧!这个过程可能看起来有点乏味,但它表明,只需每月$ 5美元,您就可以拥有一个生产级的、交互式的数据项目 web 应用程序,而无需通过一组更狭窄的可视化工具来强制数据科学过程。这种程度的灵活性在很多情况下肯定是不必要的,但是现在你知道如何为自己设置一切了。

关于这些步骤中的每一步,还有很多可以说的,但是我想把重点放在主要的工作流程上。当然,更新客户机或服务器需要几个命令,但这很容易实现自动化。如果你真的想要一个长期的、生产就绪的系统,和一个团队一起部署一个 CI/CD 过程当然是值得花时间投资的。

部署您的第一个深度学习模型:生产环境中的 MNIST

原文:https://towardsdatascience.com/deploying-your-first-deep-learning-model-mnist-in-production-environment-510bfdc4808d?source=collection_archive---------19-----------------------

让你的深度学习模型飞起来

如何在生产环境中部署您的 MNIST 模型

Photo by Ravi Roshan on Unsplash

数据集对于像我们这样的大多数 ML 爱好者来说是一个 hello world 数据集。在某个时候,每个已经开始这个领域的旅程或愿意开始的人都会遇到这个数据集,并肯定会得到它。

对于那些希望在真实世界数据上尝试学习技术和模式识别方法,同时花费最少精力进行预处理和格式化的人来说,这是一个很好的数据集。——扬·勒昆

MNIST

我们在建造什么?

在这篇文章中,我将讲述每个完成 MNIST 的人如何在生产环境中使用 Django 和 Heroku 将训练好的模型部署为漂亮的 web 应用程序。

MNIST Web App Demo

先决条件

您应该具备以下基本知识:

  1. Python 编程语言
  2. Django — Web 应用框架
  3. Heroku——平台即服务(可选:你将在这篇文章中学习如何使用它)

并且你应该有一个基于 KerasMNIST 的模型文件;或者你可以马上开始用的小本子整理文件。****

准备好您的后端

首先,让我们使用 CMD 或 bash 终端安装 Django 如果你还没有这样做。

如果你以前没有 Django 的经验,网上有很多免费的资源。请考虑看看。对于使用 Python 构建 Web 应用程序来说,这是一个非常棒的框架。没什么可失去的。

启动项目

SOURCE

****pip install django****

这将为您安装 Django,您将可以访问 Django CLI 来创建您的项目文件夹。

****django-admin startproject digitrecognizer****

我将把我的项目命名为 digitrecognizer 你可以随意命名。一旦你这样做了,你会看到一个文件夹,里面有一些文件。

让我们使用 mange.py cli 在该文件夹中创建我们的新应用程序 main

**python manage.py startapp main**

这将为您创建一个名为 main 的新应用程序。现在我们可以在 views.py 文件中编写我们的主要代码了。

代码部分

让我们在 views.py 文件中编写一些代码:

**## Views.pyfrom django.shortcuts import render
from scipy.misc.pilutil import imread, imresize
import numpy as np
import re
import sys
import os
sys.path.append(os.path.abspath("./model"))
from .utils import *
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
global model, graph
model, graph = init()
import base64OUTPUT = os.path.join(os.path.dirname(__file__), 'output.png')from PIL import Image
from io import BytesIOdef getI420FromBase64(codec):
    base64_data = re.sub('^data:image/.+;base64,', '', codec)
    byte_data = base64.b64decode(base64_data)
    image_data = BytesIO(byte_data)
    img = Image.open(image_data)
    img.save(OUTPUT)def convertImage(imgData):
    getI420FromBase64(imgData)[@csrf_exempt](http://twitter.com/csrf_exempt)
def predict(request):imgData = request.POST.get('img')convertImage(imgData)
    x = imread(OUTPUT, mode='L')
    x = np.invert(x)
    x = imresize(x, (28, 28))
    x = x.reshape(1, 28, 28, 1)
    with graph.as_default():
        out = model.predict(x)
        print(out)
        print(np.argmax(out, axis=1))
        response = np.array_str(np.argmax(out, axis=1))
        return JsonResponse({"output": response})**

看起来很多,其实不是!😂相信我。

我们来分解一下

在代码的最开始,我们导入每个需要的库和模块。

进口

每一个导入都是不言自明的,我也评论了重要的部分,考虑看看它。

**from django.shortcuts import render
from scipy.misc.pilutil import imread, imresize
import numpy as np
import re
import sys## Apending MNIST model path
import os
sys.path.append(os.path.abspath("./model"))## custom utils file create for writing some helper func
from .utils import *from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt## Declaring global variable
global model, graph## initializing MNIST model file (It comes from utils.py file)
model, graph = init()import base64
from PIL import Image
from io import BytesIO## Declaring output path to save our imageOUTPUT = os.path.join(os.path.dirname(__file__), 'output.png')**

什么是 utils.py 文件?

导入所需的库之后,让我们编写一些助手函数来处理一个 utils.py 文件中的 MNIST 模型。

**## utils.pyfrom keras.models import model_from_json
from scipy.misc.pilutil import imread, imresize, imshow
import tensorflow as tf
import osJSONpath = os.path.join(os.path.dirname(__file__), 'models', 'model.json')
MODELpath = os.path.join(os.path.dirname(__file__), 'models', 'mnist.h5')def init():
    json_file = open(JSONpath, 'r')
    loaded_model_json = json_file.read()
    json_file.close()
    loaded_model = model_from_json(loaded_model_json)
    loaded_model.load_weights(MODELpath)
    print("Loaded Model from disk")
    loaded_model.compile(loss='categorical_crossentropy',
                         optimizer='adam', metrics=['accuracy']) graph = tf.get_default_graph() return loaded_model, graph**

这个文件包含了 init 函数,它基本上初始化了我们使用 Keras 保存的 MNIST 模型文件。它抓取或模型文件加载它们,并使用 adam optimizer 编译它们,使它们为预测做好准备。

这里,我们使用分类交叉熵作为我们的损失函数, adam 作为我们的优化器,而准确性作为我们的性能测量指标。

你可以从 这里 学习如何使用 Keras 保存模型。

继续查看. py

这里我们有另一个帮助函数来帮助我们转换我们的 BASE64 图像文件;它是从客户端抓取到一个 PNG 文件;并保存为输出变量中的任何内容;即在当前目录下保存为 output.png 文件。

**def getI420FromBase64(codec):
    base64_data = re.sub('^data:image/.+;base64,', '', codec)
    byte_data = base64.b64decode(base64_data)
    image_data = BytesIO(byte_data)
    img = Image.open(image_data)
    img.save(OUTPUT)def convertImage(imgData):
    getI420FromBase64(imgData)**

编写我们的 API

现在让我们把主要的 API 写到:

  1. 获取客户端提交的 base64 图像文件
  2. 将其转换成 png 文件
  3. 处理它以适应我们的训练模型文件
  4. 使用我们之前的帮助函数预测图像,并获得相应的性能指标
  5. 将其作为 JSON 响应返回
**[@csrf_exempt](http://twitter.com/csrf_exempt)
def predict(request):imgData = request.POST.get('img')convertImage(imgData)
    x = imread(OUTPUT, mode='L')
    x = np.invert(x)
    x = imresize(x, (28, 28))
    x = x.reshape(1, 28, 28, 1)
    with graph.as_default():
        out = model.predict(x)
        print(out)
        print(np.argmax(out, axis=1))
        response = np.array_str(np.argmax(out, axis=1))
        return JsonResponse({"output": response})**

它使用 csrf_exempt decorator,因为 Django 对安全性非常严格。通过使用它,我们只是禁用 CSRF 验证。

现在,我们已经完成了应用程序后端代码的编写,可以对给定图像的标签进行分类。

提供路线

现在,让我们为我们的主要功能提供一条路线。

转到 settings.py 和 urls.py 文件所在的项目文件夹。

在 INSTALLED_APPS 数组下的 settings.py 文件中,安装我们之前创建的用于编写函数的主应用程序。

**INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles', ## our main application
    'main'
]**

之后,返回 urls.py 文件,编写一条到达我们的 predict 函数的路径。

**from django.contrib import admin
from django.urls import path, include
from main.views import predicturlpatterns = [
    path('', include('main.urls')),
    path('api/predict/', predict)
]**

保存所有东西,现在我们的后端 API 已经准备好了。

前端部分

现在是时候写我们的前端代码,使我们能够与我们的后端 API 进行交互。

我们使用 Django 的模板来编写我们的前端。

让我们在主文件夹中创建一个模板文件夹,然后在里面创建一个index.html文件。

在 HTML 文件中,让我们编写一些代码来创建一个画布,并提交用户在该画布中绘制的图像。

**<canvas
          id="canvas"
          width="280"
          height="280"
          style="border:2px solid; float: left; border-radius: 5px; cursor: crosshair;"
        ></canvas><p id="result" class="text-center text-success"></p>
<a href="#" class="btn btn-success btn-block p-2"  id="predictButton">
            Predict
</a>
<input
        type="button"
        class="btn btn-block btn-secondary p-2"
        id="clearButton"
        value="Clear"
 />**

你可以随心所欲地设计你的前端,并在里面创建画布。

显示画布后,让我们用一些 JS(Jquery)使它变得难以处理。

**(function()
{
 var canvas = document.querySelector( "#canvas" );
 canvas.width = 280;
 canvas.height = 280;
 var context = canvas.getContext( "2d" );
 var canvastop = canvas.offsetTopvar lastx;
   var lasty;context.strokeStyle = "#000000";
   context.lineCap = 'round';
   context.lineJoin = 'round';
   context.lineWidth = 5;function dot(x,y) {
     context.beginPath();
     context.fillStyle = "#000000";
     context.arc(x,y,1,0,Math.PI*2,true);
     context.fill();
     context.stroke();
     context.closePath();
   }function line(fromx,fromy, tox,toy) {
     context.beginPath();
     context.moveTo(fromx, fromy);
     context.lineTo(tox, toy);
     context.stroke();
     context.closePath();
   }canvas.ontouchstart = function(event){
     event.preventDefault();lastx = event.touches[0].clientX;
     lasty = event.touches[0].clientY - canvastop;dot(lastx,lasty);
   }canvas.ontouchmove = function(event){
     event.preventDefault();var newx = event.touches[0].clientX;
     var newy = event.touches[0].clientY - canvastop;line(lastx,lasty, newx,newy);lastx = newx;
     lasty = newy;
   }var Mouse = { x: 0, y: 0 };
 var lastMouse = { x: 0, y: 0 };
 context.fillStyle="white";
 context.fillRect(0,0,canvas.width,canvas.height);
 context.color = "black";
 context.lineWidth = 10;
    context.lineJoin = context.lineCap = 'round';debug();canvas.addEventListener( "mousemove", function( e )
 {
  lastMouse.x = Mouse.x;
  lastMouse.y = Mouse.y;Mouse.x = e.pageX - this.offsetLeft;
  Mouse.y = e.pageY - this.offsetTop;}, false );canvas.addEventListener( "mousedown", function( e )
 {
  canvas.addEventListener( "mousemove", onPaint, false );}, false );canvas.addEventListener( "mouseup", function()
 {
  canvas.removeEventListener( "mousemove", onPaint, false );}, false );var onPaint = function()
 {
  context.lineWidth = context.lineWidth;
  context.lineJoin = "round";
  context.lineCap = "round";
  context.strokeStyle = context.color;context.beginPath();
  context.moveTo( lastMouse.x, lastMouse.y );
  context.lineTo( Mouse.x, Mouse.y );
  context.closePath();
  context.stroke();
 };function debug()
 {
  /* CLEAR BUTTON */
  var clearButton = $( "#clearButton" );clearButton.on( "click", function()
  {context.clearRect( 0, 0, 280, 280 );
    context.fillStyle="white";
    context.fillRect(0,0,canvas.width,canvas.height);});/* COLOR SELECTOR */$( "#colors" ).change(function()
  {
   var color = $( "#colors" ).val();
   context.color = color;
  });/* LINE WIDTH */$( "#lineWidth" ).change(function()
  {
   context.lineWidth = $( this ).val();
  });
 }
}());**

这基本上是我们的 JS 函数,允许用户在我们的画布内绘图。它抓住用户的鼠标+触摸笔划,并根据他们的绘图在画布内绘制线条。

之后,让我们编写一个代码,将这些绘制的线条作为 base64 图像文件提交到后端。

**<script type="text/javascript">
      $("#predictButton").click(function() {
        var $SCRIPT_ROOT = "/api/predict/";
        var canvasObj = document.getElementById("canvas");
        var context = canvas.getContext( "2d" );
        var img = canvasObj.toDataURL();
        $.ajax({
          type: "POST",
          url: $SCRIPT_ROOT,
          data: { img: img },
          success: function(data) {
            $("#result").text("Predicted Output is: " + data.output);context.clearRect( 0, 0, 280, 280 );
            context.fillStyle="white";
            context.fillRect(0,0,canvas.width,canvas.height);}
        });
      });
    </script>**

这里我们使用 jquery 来:

  1. 收听我们的按钮点击事件
  2. 定义我们的 API 路由路径
  3. 抓住我们的画布元素
  4. 以 base64 图像的形式获取画布的上下文
  5. 使用 ajax 请求将其提交到我们的后端
  6. 从我们的后端获得一个响应,并显示在我们的输出部分。

现在最后,让我们添加一个路由到我们的前端,并编写一个函数来服务我们的主应用程序中的 HTML 文件。

**# views.pydef index(request):
    return render(request, 'index.html', {})# urls.py
from django.urls import path
from .views import indexurlpatterns = [
    path('', index, name="index")
]**

就是这样!我们已经成功地完成了我们的后端+前端开发,以识别手写数字。

现在让我们部署它。

部署

我们将使用 Heroku 来部署我们的 Django 项目,因为它很棒而且免费!

你可以从 heroku 的官方文档页面了解更多。它很漂亮,一切都有据可查。

在你的笔记本电脑上安装 Heroku CLI,让我们开始吧。

为了准备好我们的 Django 项目 Heroku,让我们在根目录中编写一个 Procfile

**# Procfileweb: gunicorn digitrecognizer.wsgi --log-file - --log-level debug**

现在让我们在 Heroku 中创建新的应用程序存储库,并获取该应用程序的远程 URL。

之后,git 初始化我们的项目目录,将 git 远程 URL 添加到 Heroku url,并将我们的项目文件夹推送到 Heroku,其中包含 requirements.txt 文件。

这就是部署😊。我们已经成功地在云中部署了我们的应用程序,现在它已经上线了。您可以使用 Heroku 在您的应用仪表板中提供的 URL 来访问该应用。

最后的想法

在真实环境中部署您的项目以展示您的项目是非常重要的。这对你的项目组合很有帮助。

我希望您已经学到了一些东西,尝试构建自己的手写数字分类器,并将其部署到生产环境中。你可以从 这里 查看我的演示 app。

参考

[1] 熊伟·弗莱塔斯,如何在 Heroku 上部署 Django 应用,2016 年 8 月 9 日[ 在线 ]

[2] 扬·勒库恩, MNIST 数据库,1998 [ 在线 ]

揭秘机器学习模型的部署(第 1 部分)

原文:https://towardsdatascience.com/deployment-of-machine-learning-model-demystified-part-1-1181d91815d2?source=collection_archive---------4-----------------------

如何设计预测贷款违约率的算法

source: https://blogs.oracle.com/r/data-science-maturity-model-deployment-part-11

这是由两部分组成的系列文章的第一部分。你可以读一下 第二部分在这 之后

想象一下,建立一个受监督的机器学习(ML)模型来决定是否应该批准贷款申请。有了模型在成功应用中的置信水平(概率),我们就可以计算无风险可贷金额。部署这样的 ML 模型是这个项目的目标。

请和我一起经历我在尼日利亚数据科学公司的实习项目,在那里我有幸与数据科学家、软件工程师和人工智能研究人员中的精英一起工作。我们的目标是在 10 年内培养 100 万人工智能人才,我很自豪能成为其中的一员。

数据科学家在 jupyter lab、google colab 等公司建立机器学习模型,而机器学习工程师将建立的模型投入生产。

ML 模型的部署简单地意味着将模型集成到现有的生产环境中,该环境可以接收输入并返回输出,该输出可用于做出实际的业务决策。

为了揭开部署过程的神秘面纱,我写了这篇文章,分为四章。在第一章中,我们介绍了构建基线模型的过程,在第二章中,我们将这个模型引入生产就绪代码。第 3 章和第 4 章包含在本系列的第 2 部分中。

第一章:建立基线模型

在这种情况下,基线模型指的是具有最小可能数量的特征但具有良好评估测量的 ML 模型。当构建用于部署目的的 ML 模型时,您必须始终考虑您的最终用户。一个拥有数千个特征的模型要达到 90%以上的评估准确率可能不够好,因为以下几个原因:

  • 可移植性:软件从一台机器或系统转移到另一台机器或系统的能力。一个可移植的模型减少了代码的响应时间,并且当你的目标发生变化时,你必须重写的代码量将是最小的。
  • 可伸缩性:是一个程序伸缩的能力。当一个模型不需要被重新设计来保持有效的性能时,它就被认为是可伸缩的。
  • 可操作化:业务应用使用的模型的部署,用于预测分类/回归问题的目标值。
  • 测试:对过程输出和输入的验证。健壮的模型将不必要地难以测试。

点击下载将用于本项目的数据集、笔记本和独家摘要,其中包含探索性数据分析、数据预处理、特征工程、特征选择、训练 ML 模型和模型评估。

作为第一步,我们使用 pandas 导入我们的测试和训练数据。

train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")

数据预处理:这包括将原始数据转换成适合训练模型的可理解格式。它需要处理缺失值、异常值、编码分类变量。

出于部署的目的,您希望始终保留您用来填充缺失值的值的记录,并且该方法必须是可复制的。具有缺失值的特性可以通过下面的代码片段一目了然

The horizontal white stripes indicate the locations of missing values.

有许多方法可以处理数字特征中的缺失值,但为了简单起见,我将尝试平均值和中值。

对于每个具有缺失值的数值特征,计算平均值和中值,估算该值并拟合数据模型,以查看每种情况对验证集的影响。例如,在试验 applicant_income 功能时,我们可以定义一个简单的 python 函数,它接受数据帧、感兴趣的变量、平均值和中值,并用平均值和中值填充功能的缺失部分。

split into training and testing sets and defined a function to fill in missing values

在填充缺失值时,可以执行一个简单的要素工程,即创建一个表示缺失(0 或 1)的二元要素,您可以判断缺失是否具有正面的预测效果。

#addition missingness features# create variable indicating missingness in applicant_income
X_train['applicant_income_NA'] = np.where(X_train.applicant_income.isnull(),1,0)
X_test['applicant_income_NA'] = np.where(X_test.applicant_income.isnull(),1,0)

现在,我们可以使用一个简单的逻辑回归模型来确定填充缺失值的最佳方法。

kindly download the notebook to see the full code snippets

the output of the code snippet above

对所有具有缺失值的要素重复此方法,并根据模型结果做出最佳决策。

特征工程 : 这是使用数据的领域知识来创建使机器算法工作的特征的过程。我将创建的唯一特性是 income_loan_ratio,以避免部署过程中的复杂性。

特征选择:自动或手动选择对预测变量贡献最大的特征的过程。数据中包含不相关的要素会降低模型的准确性。

有几种为最终模型选择特征的方法,包括

过滤方法如恒定特征消除、准恒定特征消除、重复特征消除、fisher 评分、单变量法、互信息、相关性等。

包装方法如向前一步选择、向后一步选择和穷举搜索等。

嵌入方法如 LASSO、决策树导出重要性、回归系数等。

训练 ML 模型:这个项目的机器学习算法的类型是监督的,它是一个分类模型。在训练模型之前,我们需要从目标变量中分离出特征。

我选择使用 sklearn 的 GradientBoostingClassifier 进行部署,但在实验过程中也探索了其他算法,如 xgboost、Microsoft LGBM。

kindly check the notebook for the output

车型评测

从上述训练模型的输出来看,测试数据的准确率为 70.3%,ROC-AUC 为 77.2%。由于这个项目的目标是预测抵押贷款申请的接受状态,以及预测接受的贷款申请的安全金额,70%的准确性对于问题案例场景来说已经足够好了。该模型可以在以后进行改进,但我们不会专注于此,因为我们现在希望尽可能简单地部署。

第 2 章:采用 ML 系统架构并编写生产就绪代码

根据 ISO/IEC 42010 和我的解释,架构可以被定义为软件组件的排列方式以及它们之间的交互。

ML 系统架构是指组成系统的软件组件的排列方式,以及它们之间在实现预定目标时的交互方式。ML 模型的开发和部署相对快速和便宜,但是随着时间的推移有效地维护它们是困难和昂贵的。根据贵公司的能力和目标,选择最佳架构可能有点困难,因为它需要业务、数据科学、工程和开发运维的同步。

这是两部分系列的第一部分。你可以在此 之后阅读 第二部分

设计 ML 系统架构时,应牢记以下几点。

  • 模块性:预处理/特征工程中使用的代码要安排在综合流水线中。
  • 再现性:每一个组件的输出必须能在任何时间版本上再现。
  • 可伸缩性:模型必须能够以最短的响应时间服务于大量的客户。
  • 可扩展性:应该很容易为将来的任务修改。
  • 测试:测试模型版本之间差异的能力。
  • 自动化:尽可能消除手动步骤,减少出错几率。

ML 架构概述

  • 批量训练,动态预测,通过 REST API 服务:离线训练和持续,实时预测。
  • 分批训练,分批预测,通过共享数据库服务:训练和持续离线完成,而预测在分布式队列中完成,几乎类似于实时预测
  • 通过流进行训练和预测:训练和预测都是在不同但相连的流上进行的。
  • 批量训练,在移动(或其他客户端)上预测:类似于类型 1,但预测是在客户小工具上进行的。

架构对比

Source: https://www.udemy.com/course/deployment-of-machine-learning-models/

对于这个项目,将使用模式 1,预测可以是单个的,也可以是批量的,也就是说,我们将在本地训练模型,并通过 flask 公开预测功能,我们可以在 flask 中上传我们的测试批量进行预测。

Source: Building a Reproducible Machine Learning Pipeline, Surgimura and Hart

Source: https://www.udemy.com/course/deployment-of-machine-learning-models/

上图可以看出,整个系统分为开发和生产。在开发中,训练数据、特征提取器和模型构建器部分是离线完成的,而生产是在线的。

Training Phase

训练数据:该单元处理用于将模型训练到训练环境中的数据集的提取和用于训练的格式化。这个单元可以是复杂的,也可以是简单的,这取决于你正在处理的 ML 架构。这可能包括从多个续集、Hadoop 分布式文件系统中提取数据或进行 API 调用,出于本项目的目的,将编写一个简单的 python 脚本,以将已经下载到文件夹/目录中的数据集提取到训练环境中,然后通过数据管道传递,在训练前将在该管道中进行若干预处理。

特征提取器:选择/生成训练模型所需的基本特征的单元。注意,这是管道使用 sklearn 的一部分。除了 sklearn 库之外,另一个可以用来完成相同任务的流行库是 TensorFlow Extended(TFX ),这超出了本文的范围。

模型构建器:这是对已训练模型进行序列化和持久化、版本化和格式化以进行部署的单元。在 python 上下文中,这可能是使用 setuptools 构建包或简单地将模型保存为 pickle 格式的单元,这取决于您采用的架构。这些方法之间有很大的不同,但本文不会讨论。虽然我尝试了这两种方法,但是为了简单起见,我将和你分享后一种方法。

训练模型:这是上面讨论的三个子主题的输出,可以通过 REST API 轻松部署。

Prediction Phase

这是两部分系列的第一部分。你可以读一下 第二部分在此之后

在生产中,通过 REST API 批量发送请求,由特征提取器进行清理和预处理,然后使用加载的训练模型预测贷款申请是否被接受。然后,在通过我们的端点返回预测之前,接受的贷款将进一步分析无风险可贷金额。

在第 2 部分(第 3 章和第 4 章),我将讨论如何将笔记本转换为生产就绪代码,以及如何创建可复制的管道、API 端点、通过 Postman 测试端点、CI/CD 在 ML 系统架构中的意义和使用、部署到 Pass、Docker 容器、部署到 Lass、无服务器部署等。

这是两部分系列的第一部分。你可以在此 之后阅读 第二部分

你可以通过下面的链接克隆 Github 库:

[## opeyemibami/机器学习-抵押部署-批准-状态-模型

有助于 opeyemibami/machine _ learning-Deployment-of-mortgage-Approval-Status-Model 的开发

github.com](https://github.com/opeyemibami/machine_learning-Deployment-of-Mortage-Approval-Status-Model)

包扎

有许多方法可以将 ML 模型部署到生产中,有许多方法可以存储它们,还有不同的方法可以在部署后管理预测模型。为用例选择最佳方法可能具有挑战性,但随着团队技术和分析的成熟,整体组织结构及其交互可以帮助选择正确的方法来将预测模型部署到生产中。

联系我上 推特 领英

一定要抽出时间来看看我的其他文章和参考资料部分的进一步阅读。请记得关注我,以便获得我的出版物的通知。

[## 揭秘机器学习模型的部署(第二部分)

具有无风险可贷金额的贷款接受状态预测

medium.com](https://medium.com/@opeyemibami/deployment-of-machine-learning-models-demystified-part-2-63eadaca1571) [## 用 NLTK 和 TensorFlow 构建对话聊天机器人(第 1 部分)

用卷积神经网络构建的网球聊天机器人

heartbeat.fritz.ai](https://heartbeat.fritz.ai/building-a-conversational-chatbot-with-nltk-and-tensorflow-part-1-f452ce1756e5) [## 用 NLTK 和 TensorFlow 构建对话聊天机器人(第 2 部分)

用卷积神经网络构建的网球聊天机器人

heartbeat.fritz.ai](https://heartbeat.fritz.ai/building-a-conversational-chatbot-with-nltk-and-tensorflow-part-2-c67b67d8ebb) [## 将机器学习模型部署为 Web 应用程序(第 1 部分)

具有 Streamlit 的机器学习支持的 Web 应用程序

heartbeat.fritz.ai](https://heartbeat.fritz.ai/deploy-a-machine-learning-model-as-a-web-application-part-1-a1c1ff624f7a) [## 将机器学习模型部署为 Web 应用程序(第 2 部分)

具有 Streamlit 的机器学习支持的 Web 应用程序

heartbeat.fritz.ai](https://heartbeat.fritz.ai/deploy-a-machine-learning-model-as-a-web-application-part-2-2f590342b390) [## 在谷歌云平台上部署机器学习模型(GCP)

在 Kaggle 上训练;部署在谷歌云上

heartbeat.fritz.ai](https://heartbeat.fritz.ai/deploying-machine-learning-models-on-google-cloud-platform-gcp-7b1ff8140144) [## 主题建模开源工具

使用 python 和 streamlit 构建的主题建模工具

medium.com](https://medium.com/towards-artificial-intelligence/topic-modeling-open-source-tool-fbdcc06f43f6)

对于建模部署策略的其他方法,您可以通过下面的链接查看 NeptuneAi 帖子:

海王星部署策略:https://neptune.ai/blog/model-deployment-strategies

参考文献

  • [1] Julien Kervizic ,将机器学习(ML)模型投入生产的不同方法概述。
  • [2] Mark Hornick ,数据科学成熟度模型—部署(第 11 部分)
  • [3] 索莱达·加利 & 克里斯托弗·萨米乌拉,部署机器学习模型

特别感谢我的导师(Olubayo Adekanmbi 博士、James alling ham)**Wu raola oye wus 和尼日利亚数据科学公司的全体员工。

# 100 万年

干杯!

基于 DenseNets 的相机图像深度估计

原文:https://towardsdatascience.com/depth-estimation-on-camera-images-using-densenets-ac454caa893?source=collection_archive---------10-----------------------

用数据做很酷的事情!

介绍

当观看二维场景时,人脑具有推断深度的非凡能力,即使是单点测量,就像观看照片一样。然而,从单幅图像进行精确的深度映射仍然是计算机视觉中的一个挑战。来自场景的深度信息对于增强现实、机器人、自动驾驶汽车等许多任务都很有价值。在这篇博客中,我们探索如何在 NYU 深度数据集上训练深度估计模型。该模型在该数据集上获得了最先进的结果。我们还添加了代码,以在用户收集的图像+视频上测试该模型。

经过训练的模型在来自野外的数据上表现非常好,如下面的视频所示。

Actual Image on left and predicted depth map on the right

完整代码在我的 Github repo 上开源。

深度信息是什么样的?深度可以存储为图像帧中每个像素到相机的距离,单位为米。下图显示了单一 RGB 图像的深度图。深度图在右边,实际深度已经用这个房间的最大深度转换成了相对深度。

RGB Image and its corresponding depth map

数据集

为了建立深度估计模型,我们需要 RGB 图像和相应的深度信息。深度信息可以通过像 Kinect 这样的低成本传感器来收集。对于这个练习,我使用了流行的 NYU v2 深度数据集来建立一个模型。该数据集由超过 400,000 幅图像及其相应的深度图组成。我在训练任务中使用了全部数据集中的 50,000 幅图像的子集。

模型概述

我阅读了几篇执行深度估计任务的论文,其中许多论文使用了编码器解码器类型的神经网络。对于深度估计任务,模型的输入是 RGB 图像,输出是深度图像,该深度图像或者是与输入图像相同的维度,或者有时是具有相同纵横比的输入图像的缩小版本。用于该任务的标准损失函数考虑了实际深度图和预测深度图之间的差异。这可能是 L1 或 L2 的损失。

我决定使用来自 Alhashim 和 Wonka 的密集深度模型。这个模型的简单性和准确性令人印象深刻。很容易理解,训练起来也比较快。它使用图像增强和自定义损失函数来获得比更复杂的架构更好的结果。该型号使用功能强大的 DenseNet 型号,带有预先调整的砝码,为编码器提供动力。

密集深度模型

本文介绍的编码器是一个预训练的 DenseNet 169。
编码器由 4 个密集块组成,出现在 DenseNet 169 模型中完全连接的层之前。它不同于其他深度模型,因为它使用非常简单的解码器。每个解码器模块由单个 bi-
线性上采样层和两个卷积层组成。遵循编码器解码器架构中的另一标准实践,上采样层与编码器中的相应层连接。下图更详细地解释了该架构。关于层的更多细节,请阅读原文。写得非常好!

Encoder Decoder model from Dense Depth Paper

训练和测试深度估计模型

在 NYU-v2 数据集的 50K 样本上训练密集深度。输入是 640×480 分辨率 RGB 图像,输出是 320×240 分辨率的深度图。使用 Adam optimizer 在 Keras 中训练该模型。我利用密集深度作者的回购开始。

训练了三种不同的模型架构:

  1. 原代码提供了 DensetNet 169 en-
    编码器的实现。这个模型被训练了 8 个纪元(9 个小时在
    NVIDIA 1080 Ti 上)
  2. 原始代码被修改以实现 DenseNet 121 编码器,其具有比 DenseNet 169 更少的参数。该模型被训练了 6 个时期(在 GPU 上 5 个小时),因为验证损失在此
    点已经稳定
  3. 修改了原始代码以实现 Resnet
    50 编码器,该编码器具有比 DenseNet 169 更多的参数。
    我试验了连接编码器和解码器的不同方式。这个模型被训练了
    5 个时期(在 GPU 上 8 个小时),并且训练是不连续的,因为模型已经开始过度拟合。

所有这些代码修改都被推送到 github repo 上,并附有如何进行培训、评估和测试的解释。

评估不同的模型

我们使用三种不同的指标来比较模型性能——预测深度和实际深度的平均相对误差(rel)、RMSE (rms) —实际深度和预测深度的均方根误差以及两个深度之间的平均对数误差(log)。所有这些指标的值越低,表示模型越强。

Model Comparison

如上表所示,DenseNet 169 型号的性能优于 DenseNet121 和 ResNet 50。此外,我训练的 DenseNet 169 在性能上与原作者(Alhashim 和 Wonka)的非常接近。

结论

我们希望这篇博客能成为理解深度估计工作原理的一个好的起点。我们提供了一个管道来使用一个强大的、简单的和易于训练的深度估计模型。我们还分享了代码,可用于从您收集的室内图像或视频中获取深度图像。希望您自己尝试一下这些代码。

我有自己的深度学习咨询公司,喜欢研究有趣的问题。我已经帮助许多初创公司部署了基于人工智能的创新解决方案。请到 http://deeplearninganalytics.org/来看看我们吧。如果你有一个我们可以合作的项目,那么请通过我的网站或在 info@deeplearninganalytics.org联系我

你也可以在 https://medium.com/@priya.dwivedi的看到我的其他作品

参考文献:

  • 密集深度原始 Github
  • 密集深度纸
  • NYU V2 数据集

自动驾驶中的深度识别

原文:https://towardsdatascience.com/depth-prediction-autonomous-driving-18d05ff25dd6?source=collection_archive---------19-----------------------

本文将介绍一些在车辆捕获的图像序列中进行深度预测的先进方法,这些方法有助于在不使用额外摄像头或传感器的情况下开发新的自动驾驶模型。

正如我在之前的文章《中提到的,自动驾驶是如何工作的?SLAM 介绍,有许多传感器用于在车辆行驶时捕捉信息。捕获的各种测量值包括速度、位置、深度、热量等。这些测量值被输入到一个反馈系统中,该反馈系统训练并利用车辆要遵守的运动模型。本文主要关注深度预测,这通常是由激光雷达传感器捕获的。激光雷达传感器使用激光捕捉与物体的距离,并使用传感器测量反射光。然而,激光雷达传感器对于日常司机来说是负担不起的,那么我们还能如何测量深度呢?我将描述的最先进的方法是无监督的深度学习方法,它使用一帧到下一帧的像素差异来测量深度。

  • 请注意图片说明,因为大部分图片取自引用的原始论文,而不是我自己的产品或创作。

单深度 2

[1]中的作者开发了一种方法,该方法使用深度和姿态网络的组合来预测单个帧中的深度。他们通过在一系列帧和几个损失函数上训练他们的结构来训练两个网络。这种方法不需要地面真实数据集进行训练。相反,它们使用图像序列中的连续时间帧来提供训练信号。为了帮助约束学习,他们使用了一个姿势估计网络。根据输入图像和从姿态网络和深度网络的输出重建的图像之间的差异来训练该模型。稍后将更详细地描述重建过程。[1]的主要贡献是:

  1. 去除不重要像素焦点的自动遮罩技术
  2. 用深度图修正光度重建误差
  3. 多尺度深度估计

体系结构

本文的方法使用了深度网络和姿态网络。深度网络是一个经典的 U-Net [2]编码器-解码器架构。编码器是预训练的 ResNet 模型。深度解码器与之前的工作类似,将 sigmoid 输出转换为深度值。

Sample image of U-Net [2].

6-DoF. Image from Wikipedia.

作者使用 ResNet18 中的姿势网络,该网络经过修改,可以将两幅彩色图像作为输入来预测单个 6 自由度相对姿势,或者旋转和平移。姿态网络使用时间帧作为图像对,而不是典型的立体图像对。它从序列中另一个图像的视点预测目标图像的外观,无论是前一帧还是后一帧。

培养

下图说明了该架构的培训过程。

Images taken from KITTI and [1].

光度重建误差

目标图像位于第 0 帧,用于我们预测过程的图像可以是前一帧或后一帧,因此是第+1 帧或第-1 帧。该损失基于目标图像和重建的目标图像之间的相似性。重建过程从使用姿态网络从源帧(帧+1 或帧-1)计算变换矩阵开始。这意味着我们正在使用关于旋转和平移的信息来计算从源帧到目标帧的映射。然后,我们使用从目标图像的深度网络预测的深度图和来自姿态网络的变换矩阵投影到具有固有矩阵 K 的相机中,以获得重建的目标图像。该过程需要首先将深度图转换成 3D 点云,然后使用相机固有特性将 3D 位置转换成 2D 点。产生的点被用作采样网格,从目标图像对进行双线性插值。

这种损失的目的是减少目标图像和重建的目标图像之间的差异,其中姿态和深度都是需要的。

Photometric Loss function from [1].

Benefit of using minimum photometric error. Pixel area circled are occluded. Image from [1].

典型地,类似的方法将重新投影误差一起平均到每个源图像中,例如帧+1 和帧-1。然而,如果一个像素在这些帧之一中不可见,但是因为它靠近图像边界或被遮挡而在目标帧中,则光度误差损失将不公平地高。为了解决与此相关的问题,他们在所有源图像上取最小光度误差。

自动遮罩

最终的光度损失乘以一个遮罩,该遮罩解决了与相机在静态场景中移动的假设中的变化相关的问题,例如,一个对象以与相机相似的速度移动,或者当其他对象正在移动时相机已经停止。这种情况的问题是深度图预测无限的深度。作者用一种自动蒙版方法解决了这个问题,这种方法可以过滤掉从一帧到下一帧外观不变的像素。它们使用二进制生成它们的掩模,其中如果目标图像和重建的目标图像之间的最小光度误差小于目标图像和源图像的最小光度误差,则为 1,否则为 0。

Auto-masking generation in [1] where Iverson bracket returns 1 if true and 0 if false.

当相机静止时,结果是图像中的所有像素都被遮蔽。当物体以与相机相同的速度移动时,会导致图像中静止物体的像素被遮蔽。

多尺度估计

作者结合了每个尺度下的个体损失。它们将较低分辨率的深度图上采样到较高的输入图像分辨率,然后以较高的输入分辨率重新投影、重新采样并计算光度误差。作者声称,这限制了每个比例的深度图朝着同一目标工作,即目标图像的精确高分辨率重建。

其他损失

作者还使用平均归一化的逆深度图值和输入/目标图像之间的边缘感知平滑度损失。这鼓励模型学习尖锐的边缘并平滑掉噪声。

最终损失函数变为:

The final loss function in [1] which is averaged over each pixel, scale and batch.

结果

作者在包含驾驶序列的三个数据集上比较了他们的模型。在所有的实验中,他们的方法胜过了几乎所有其他的方法。下图显示了它们的性能示例:

Image from [1] GitHub repository: https://github.com/nianticlabs/monodepth2/

有关他们的结果的更多细节,请参见原始论文“深入研究自监督单目深度估计

Monodepth2 扩展:Struct2Depth

物体运动建模

Google brain 的作者发表了进一步扩展 Monodepth2 的文章[3]。他们通过预测单个物体的运动来改进之前的姿态网络,而不是将整个图像作为一个整体。因此,重建的图像不再是单一的投影,而是一系列的投影,然后被组合起来。他们通过两个模型来做到这一点,一个对象运动模型和一个自我运动网络(类似于前面章节中描述的姿态网络)。步骤如下:

Sample output for Mask R-CNN [2]. Image from [2].

  1. 应用预训练的掩模 R-CNN [2]来捕获潜在移动对象的分割。
  2. 二进制掩模用于从静态图像(帧-1、帧 0 和帧+1)中去除这些潜在的运动物体
  3. 掩蔽的图像被发送到自运动网络,并且输出帧-1 和 0 以及帧 0 和+1 之间的变换矩阵。

The masking process to extract the static background followed by the ego-motion transformation matrix without objects that move. Equation from [3].

  1. 使用步骤 3 中得到的自我运动变换矩阵,并将其应用于第 1 帧和第+1 帧,以获得扭曲的第 0 帧。
  2. 使用从步骤 3 得到的自运动变换矩阵,并将其应用于潜在移动对象到帧-1 和帧+1 的分割蒙版,以获得帧 0 的扭曲分割蒙版,所有都针对每个对象。
  3. 使用二进制掩模来保持与扭曲的分割掩模相关联的像素。
  4. 屏蔽的图像与扭曲的图像相结合,并被传递到输出预测的对象运动的对象运动模型。

The object motion model for one object. Equation from [3].

结果是为了“解释”物体外观的变化,照相机必须如何移动的表示。然后,我们希望根据从对象运动建模过程的步骤 4 得到的运动模型来移动对象。最后,我们将扭曲的对象运动与扭曲的静态背景相结合,以获得最终的扭曲:

Equation from [3].

Image from [5]

学习目标量表

虽然 Monodepth2 通过其自动遮罩技术解决了静态对象或以与相机相同的速度移动的对象的问题,但这些作者建议实际训练模型来识别对象比例,以改善对象运动的建模。

Image from Struct2Depth. Middle column shows the problem of infinite depth being assigned to objects moving at the same speed of the camera. The third column shows their method improving this.

他们根据对象的类别(如房屋)来定义每个对象的比例损失。其目的是基于对物体尺度的了解来约束深度。损失是图像中对象的输出深度图与通过使用相机的焦距、基于对象类别的高度先验以及图像中被分割对象的实际高度计算的近似深度图之间的差,两者都由目标图像的平均深度来缩放:

The formulation for the loss that helps the model learn object scale. Equations from [3].

结果

[3]中描述的扩展直接与 Monodepth2 模型进行比较,显示出显著的改进。

The middle row shows the results from [3] while the ground truth is shown in the third row. Image from [5].

摘要

自动驾驶中深度估计的常用方法是使用一对立体图像,需要两个摄像头或一个激光雷达深度传感器。然而,这些都是昂贵的,并不总是可用的。这里描述的方法能够训练深度学习模型,该深度学习模型在一幅图像上预测深度,并且仅在一系列图像上训练。它们表现出良好的性能,在自动驾驶研究方面有着广阔的前景。

为了亲自尝试这些模型,这两份报纸都有位于下面的存储库:

单部门 2:https://github.com/nianticlabs/monodepth2

struct 2 depth:https://github . com/tensor flow/models/tree/master/research/struct 2 depth

参考

[1]戈达尔,c .,麦克奥德哈,o .,菲尔曼,m .,&布罗斯托,G. (2018)。深入研究自我监督的单目深度估计。 arXiv 预印本 arXiv:1806.01260

[2]奥拉夫·龙内贝格、菲利普·费舍尔和托马斯·布罗克斯。U-Net:生物医学图像分割的卷积网络。InMICCAI,2015。

[3] 文森特·卡塞尔、苏伦·皮尔克、礼萨·马赫茹里安、阿内莉亚·安杰洛娃:没有传感器的深度预测:利用结构从单目视频进行无监督学习。第三十三届 AAAI 人工智能会议(AAAI'19)。

[4] He,k .,Gkioxari,g .,Dollár,p .,& Girshick,R. (2017 年)。屏蔽 r-cnn。IEEE 计算机视觉国际会议论文集(第 2961–2969 页)。

[5] Vincent Casser , Soeren Pirk , Reza Mahjourian , Anelia Angelova :无监督单目深度和自我运动学习,具有结构和语义。CVPR 视觉里程计研讨会&基于位置线索的计算机视觉应用(VOCVALC),2019

描述人工智能

原文:https://towardsdatascience.com/describing-ai-f17dd90646fa?source=collection_archive---------22-----------------------

公司正在投资数百万英镑开发人工智能(AI)技术。许多人每天都在使用人工智能技术,让他们的生活变得更加轻松。但是在谷歌上搜索“人工智能”的图片,你会看到一片发光的、亮蓝色的、相互连接的大脑的海洋。用来说明人工智能的图像与人工智能在用户眼中的更平凡的现实相去甚远,在用户眼中,人工智能为导航、语音助手和人脸识别等服务提供支持。这种脱节让人们很难把握人工智能的现实。

用来描述人工智能的语言可能和使用的图像一样有问题。随着人工智能越来越多地影响如此多的人的日常生活,准确地描述它,而不是模糊设计系统的人的责任是非常重要的。

“人工智能自学”

大部分关于 AI 的文章都在说机器学习(ML)。那是一套从数据中训练模型的算法。训练后,模型对训练数据中存在的模式进行编码。机器学习是我们所知的让计算机执行复杂任务的最佳方式,比如理解语音,这是我们无法明确编程让它们去做的。

我们谈论 ML 模型学习,所以写“AI 教自己……”做一些事情是很有诱惑力的。例如,AI 已经自学了偏好男性候选人、玩游戏、、解魔方等等。短语“自学是有问题的,因为它暗示计算机和机器学习模型有代理。它隐藏了机器学习的现实,即科学家或工程师仔细构建数据集和模型,然后花大量时间构建和调整模型,直到它们表现良好。该模型仅从训练数据中学习,训练数据通常以某种方式受到约束。也许只有有限数量的数据可用,或者有限的时间和计算能力来运行训练。无论约束条件如何,模型最终学到的东西都受到其创造者的设计选择的强烈影响。

“人工智能作弊”

机器人还教自己作弊,可能通过隐藏数据或利用电脑游戏中的漏洞。然而,欺骗是一个情绪化的词,也暗示了欺骗背后的意图。

欺骗(动词):“为了获得利益而不诚实或不公平地行事”

ML 模型被训练完成的任务是由它的创建者很好地定义的。通常,不完美的模拟或视频游戏被用来模仿现实世界,因为在外面太昂贵或太危险。在这些模拟中,计算机可以比人重复相同的动作更多次,并且行动更快,因此它们可以发现和利用人无法发现的错误。他们不会因为点击鼠标或按下按钮的物理行为而慢下来。发现和利用任务中的错误是机器学习模型的完美合理的预期结果。我们有一个默契,利用模拟或电脑游戏中的漏洞是作弊。然而,计算机不知道这不符合游戏的精神。他们看不到游戏规则和执行过程中的错误之间的区别。

"这个机器人无视物理定律!"

在现实世界中,没有什么能违背物理定律。当一个模拟违反物理定律时,就有问题了。机器学习模型可以利用模拟中的错误来发明行为,我们直观地知道这些行为是错误的,但这些行为满足任务的约束。尽管如此,结果可能很有趣,并告诉我们一些关于机器学习如何工作的事情:

“当他们对算法没有任何限制,并要求它穿过一个充满障碍的路线时,人工智能建造了一个极高的两足动物,它只需摔倒就可以到达出口。”

新科学家

“人工智能可以判断你是不是罪犯”

已发表的研究表明,人工智能可以从你的脸部照片判断你是罪犯还是你的性取向,从你的声音判断你是否在撒谎,或者从你的步态识别你的情绪。但是,即使是表现最好的人工智能也不能完成不可能的事情。

用于训练机器学习模型的数据集必须被准确标记。如果人们不能准确地标记数据集,那么机器就不太可能学习这项任务。有时需要专家来标记数据集——几乎任何人都可以转录音频,但很少有人有专业知识来标记 MRI 扫描——但准确的数据标签对机器学习任务来说是必不可少的。对任何人来说,正确标记性取向,你是否在说谎,你是否是一个罪犯,或者你处于什么样的情绪状态都是一项不可能的工作。

有一些场景,机器学习可以揭示人们看不到的模式。例如,可以使用来自活检的附加信息来标记 MRI 扫描。也许做标记的医生不能从图像中确定肿块是否是癌性的,但是来自活检的额外信息可以帮助标记图像。然而,在这种情况下,您必须额外注意设置和评估,以确保模型确实在学习新的和新奇的东西。

关于用于训练 ML 模型的数据集,需要注意的另一点是,它们是由在约束内工作的人构建的。这些限制可能与时间、金钱、标签工作或其他事情完全相关。例如,在对性取向的研究中,研究人员从约会网站上搜集了个人资料照片。用户从他们自己的许多照片中选择约会简档照片,以向世界传达特定的图像。从这些照片中预测性取向告诉我们的更多的是性别表述的文化规范,而不是你是否可以从一个人的面部预测他的性取向。有时,在实验室环境中完成一项任务的令人印象深刻的结果并不能转移到现实世界中。

机器学习和人工智能最近显示了一些令人印象深刻的结果——包括语言之间的翻译,过滤掉你的垃圾邮件,回答问题,检测欺诈,驾驶汽车等等。去掉夸张并不会减损它的成功,最终会让每个人更容易理解。

** NB:不能,也不应该。关于性取向研究的更深入的探讨,请看这篇* 文章

原载于 2019 年 9 月 18 日http://mycomputerdoesntlisten.wordpress.com。你可以雇用我!如果我能帮助你的组织使用 AI &机器学习,请 取得联系

时间序列建模中的描述统计学

原文:https://towardsdatascience.com/descriptive-statistics-in-time-series-modelling-db6ec569c0b8?source=collection_archive---------8-----------------------

有各种统计测试可以用来描述时间序列数据。时间序列建模要求数据以某种方式存在,这些要求因模型而异。这些模型一旦符合数据,就需要通过统计测试进行某种验证。

但最常见的是,我们在时间序列中寻找的是平稳性、因果性、相关性、季节性等属性。ARMA、ARIMA、SARIMA、Holt Winters 等模型处理不同类型的时间序列数据。需要检查数据的底层属性,statsmodels 有各种测试来探索和处理这些属性。以下是这些属性的简要概述。

平稳性

如果时间序列不随时间线性或指数增加或减少(无趋势),并且不显示任何类型的重复模式(无季节性),则称其为平稳的。在数学上,这被描述为随着时间的推移具有恒定的平均值和恒定的方差。同样,对于方差,自协方差也不应该是时间的函数。如果你已经忘记了什么是均值和方差:均值是数据的平均值,方差是距离均值的平均平方距离。

Stationary data: Total number of daily female births

Non- stationary data: Number of airlines passengers over the years

一些模型对时间序列的平稳性做了一般性的假设,但大多数模型如 ARMA、ARIMA、SARIMA、VARMA 等。,需要数据是平稳的。但是,我们如何确定给定的数据是否是平稳的呢?

理解这一点的最基本的方法是绘制数据,并检查是否有任何潜在趋势或季节性的迹象。这种视觉练习很少有帮助,而且通常人眼很难分辨出来。因此,我们可以将滚动统计(如移动平均)添加到具有固定窗口大小的数据中,以检查平稳性。

Rolling mean with a window size of 12

有时,甚至很难直观地解释滚动平均值,因此我们借助统计测试来确定这一点,一个这样的增强 Dickey Fuller 测试。ADCF 检验是使用 python 中的 statsmodels 实现的,它执行经典的零假设检验并返回 p 值。

原假设检验的解释:如果 p 值小于 0.05 (p 值:低),我们拒绝原假设,假设数据是平稳的。但是,如果 p 值大于 0.05 (p 值:高),那么我们无法拒绝零假设,并确定数据是非平稳的。

一旦确定了数据集的稳定性,我们就根据需求执行转换。如果发现数据是稳定的,我们继续对其进行建模,但是如果发现数据不是稳定的,那么我们必须在拟合模型之前对其进行转换。“差分”是一种将数据转换为静态数据的常用方法,它只不过是找到连续数据项之间的差异,并将它们移动 1。首先,我们尝试对数据进行一阶差分,然后是二阶、三阶等等,直到数据变得稳定。但是每一步的差异都是以丢失一行数据为代价的。(因为我们每一步都将行/数据点移动 1)如果数据显示季节性,则差异是按季节进行的。例如,如果我们有具有年度季节性的月度数据,那么我们用时间单位 12 来区别数据。

因果关系

因果关系与因果现象有关:如果一个时间序列可以用来预测另一个时间序列,那么这两个时间序列被认为有某种因果关系。如何检验因果关系?格兰杰因果关系检验无疑是检验它的最佳方法。也可以使用 python 中的 statsmodels 来实现。

从视觉上看,确定数据中是否存在因果关系变得很困难。正如我们在下面的例子中看到的,我们很难理解因果关系。

The two time series ‘a’ and ‘d’ have causality

在上图中,两个时间序列有某种因果关系;如果你把 a 向前移动两个单位,就会得到 d 值。

格兰杰因果关系检验的解释:当 p 值大于 0.05 时,没有因果关系,当 p 值较低,即小于 0.05 时,数据中有因果关系的迹象。

评估预测

时间序列建模包括通过绘制数据与某些时间单位的滞后版本来查看数据中的相关性。当我们将时间序列与其自身的滞后版本进行比较时,很难看出任何与时间显著增加的相关性。为了评估模型拟合度和预测质量,我们使用了 MAE、MSE、RMSE、AIC 和 BIC 等指标。

平均绝对误差、均方误差和均方根误差是我们用于回归问题的几种误差,因此也用于基于回归的时间序列模型。

我们想了解的是 AIC 和 BIC 指标。

AIC:1971 年开发的 Akaike 信息标准评估了一组模型——它评估了每个模型相对于其他模型的质量,并将这些模型相互比较。

AIC 专门用于基于 ARIMA 的模型,以确定 p、d、q 参数。所以,如果你要用不同的 p,d 和 q 阶来运行 ARIMA 模型,你需要一个指标来比较这些模型。AIC 是做这项工作的最佳人选。这种度量的优点是,它提供了用于努力阻止过拟合的多个参数的惩罚。假设您有一个性能相对较好的简单模型和一个性能略好于前一个模型的复杂模型。如果这两个模型之间有微小的性能改进,那么 AIC 会考虑这一点,并告诉你选择简单的模型,而不是复杂的模型。在这种情况下,复杂模型将比简单模型具有更低的信息标准值。在某种程度上,AIC 惩罚了使用太多参数的模型。

感谢您阅读文章!

带 Spotifyr 的荒岛光盘()

原文:https://towardsdatascience.com/desert-island-discs-with-spotifyr-f3539b7aa0b0?source=collection_archive---------45-----------------------

使用 R 中的 Spotify API 来可视化我们的朋友和家人最喜爱的音乐

介绍

一年多前,我最好的朋友、室友兼音乐势利者“山姆”突发奇想。我可能稍微夸大了这个概念,但考虑到他有限的认知能力,我认为他的提议非常简洁。两人都是 BBC 荒岛唱片系列的狂热粉丝,他指出,他认为知道他所爱的人最喜欢的音乐会比知道名人更多。对我来说,这非常有意义。我们对我们的朋友和家人有一种实际的亲近感,一种崇拜和理解,这是我们永远无法与在电视上见过但从未见过面的人联系在一起的。假设是,通过了解我们所爱的人最喜欢的音乐,我们可能会明白是什么让他们这样做。

首先,山姆让我们所有的朋友和家人给他发送他们各自的荒岛光盘,他将这些光盘整理成单独的 Spotify 播放列表。在听完每个播放列表后,萨姆来找我,问我是否可以帮助他拼凑一个片段——书面的或其他形式的——可以显示他收到的关于荒岛光盘的所有信息;既相互比较,又确定汇编之间是否存在共性。我同意帮忙,在 Spotify API 和他们的开发者文档的大力帮助下,我们能够收集到一些关于朋友和家人的播放列表的真正有趣的信息。

这篇文章将展示在我们的发现中获得信息的步骤,同时也讨论我们合成的实际结果。虽然你可能不知道我们为这首曲子所用的人,但它向你展示了 Spotify API 的一些功能,以及如何用它来比较你喜欢的人的音乐品味。

享受吧。

仅供参考: 这篇文章的一部分涉及技术设置和用于计算这项研究结果的代码。对于那些不太关心这些技术方面并且对分析结果感兴趣的人(尽管这首先是一个数据科学博客),您可以跳到“发现”部分。

方法

Spotify API

进行这种分析所需的几乎所有繁重工作都由 Spotify API 完成,我发现它具有惊人的可塑性。你不仅可以用很多有趣又酷的方式来操作和组织数据,Spotify 对你可以访问的元数据也相当开放,每个音轨都有各种各样的性能指标(见下面的“指标”)。

这一节将分解为我们朋友的所有汇编创建一个数据框架的步骤,以便进行探索性分析,这可以很容易地复制和开发。

软件包安装/帐户创建

首先,你需要安装所有用于从 Spotify API 中提取、格式化、排列和绘制数据的软件包。

要访问 Spotify Web API,您首先需要 设置一个开发帐户 。这将给你你的客户 ID 和客户秘密。一旦你有了这些,你就可以用get _ Spotify _ access _ token()把你的访问令牌拉入 R。最简单的认证方式是将您的凭证设置为sys . setenv:SPOTIFY _ CLIENT _ ID 和 SPOTIFY_CLIENT_SECRET 中的输入。get _ Spotify _ access _ token()(以及这个包中的所有其他函数)的默认参数将与这些相关。用您唯一的客户 ID 和 Spotify 生成的密码填充散列值:

# Install packages/load librariesinstall.packages('spotifyr')
install.packages('ggstatsplot')
library(spotifyr)
library(ggjoy)
library(lubridate)
library(tidyr)
library(dplyr)
library(ggplot2)
library(ggstatsplot)
library(yarrr)# Create access tokenSys.setenv(SPOTIFY_CLIENT_ID = ‘####’)
Sys.setenv(SPOTIFY_CLIENT_SECRET = ‘####’)
access_token <- get_spotify_access_token()
access_token

数据格式编排

如前所述,Spotify API 提供了多个有用的功能,我强烈建议您去看看。但是这篇文章是关于荒岛唱片的,所以会涉及到多个播放列表的组织和绑定。如前所述,我们让朋友和家人把他们的歌曲发过来,我们在 Spotify 上把它们组合成单独的播放列表。然后我们使用了get _ playlist _ audio _ features()函数,使用 playlist_uri(可以在任何公共播放列表中找到)。最佳实践是将每个 API 调用分配给一个新的向量,并创建一个名为“$curator”的新列,这将允许您按照每个单独的播放列表及其创建者来划分搜索结果。然后,您可以 rbind() 所有播放列表创建一个新的数据框(DID_project ),您可以稍后使用它来浏览数据:

# Frank Musicfrank_playlist <- get_playlist_audio_features(playlist_uris = '5s9tAnjcHVagUHtN9YXoC0')
frank_play$curator <- paste("Frank")# Joe Musicjoe_playlist <- get_playlist_audio_features(playlist_uris = '6mvg2kNHyxZ6Jgr11TuQv8')
joe_play$curator <- paste("Joe")# Sam Musicsimon_playlist <- get_playlist_audio_features(playlist_uris = '3UNv39UZ29o7dCpdXzHdUw')
simon_play$curator <- paste("Sam")DID_project <- rbind(frank_playlist, joe_playlist, sam)

韵律学

现在,这就是酷的地方。Spotify 会在每首曲目上附上大量元数据,包括:曲目时长、曲目受欢迎程度、曲目和专辑的发布日期、节奏以及歌曲创作的基调。除此之外,Spotify 还提供了许多与每首歌曲相关的指标,用于后续分析。你可以在他们的 开发者文档 中查看 Spotify 如何计算他们所有的指标。

这是我们的新数据帧,包含所有相关的音频功能和指标:

排列数据

现在,我们可以根据这些指标排列数据,并开始查看每个曲目和播放列表的表现。你必须通过曲目名称、指标,然后是馆长(这样我们可以评估每张荒岛唱片相对于其他播放列表的“性能”)。您可以将 arrange() 参数换成任何感兴趣的指标,并相应地进行选择。因为我们总共收到了 129 首曲目,所以我将范围缩小到每个音频功能的前 25 首表演曲目:

top_25_loudness <- DID_project %>% 
 arrange(-loudness) %>% 
 select(track.name, loudness, curator) %>% 
 head(25)

可视化数据

下面是在下面讨论的发现中使用的许多有用图的语法。

分别绘制所有策展人与曲目流行度(使用密度脊)和 pirateplot() 的关系图:

# Density plotggplot(DID_project, aes(x = DID_project$track.popularity, y = DID_project$curator, fill = DID_project$curator)) + 
  geom_joy() + 
  xlab("Track Popularity (0-100)")+
  ylab("Curator")+
  ggtitle("Desert Island Disc Popularity by Curator")# Pirate plotpirateplot(DID_project$track.popularity ~ DID_project$curator, DID_project,
           xlab = "Curator", ylab = "Track Popularity",
           theme = 0, point.o = 0.7, avg.line.o = 1, jitter.val = .05, 
           bty = "n", cex.axis = 0.6)# Pirate plot to calculate "DID Score"pirateplot(DID_project$track.popularity + DID_project$energy + DID_project$valence + DID_project$danceability  ~ DID_project$curator, DID_project,
           xlab = "Curator", ylab = "DID Score",
           theme = 0, point.o = 0.7, avg.line.o = 1, jitter.val = .05, 
           bty = "n", cex.axis = 0.6)

根据轨道持续时间绘制所有策展人:

ggplot(DID_project, aes(x = DID_project$track.duration_ms, y = DID_project$curator, fill = DID_project$curator)) + 
  geom_joy() + 
  xlab("Track Duration (ms)")+
  ylab("Curator")+
  ggtitle("Desert Island Disc Track Duration by Curator")

绘制与这些音频特征相关的指标和前 25 首曲目:

ggplot(top_25_loudness, aes(x = loudness, y = track.name, col = curator, size = loudness)) + 
  geom_point()+
  geom_joy() + 
  theme_joy()+
  ggtitle("Top 25 - Loud Songs")

使用 ggstatsplot() 绘制相关图,以评估指标/音频特征之间的统计关系:

ggstatsplot::ggcorrmat(
 data = DID_project,
 corr.method = “robust”,
 sig.level = 0.001,
 p.adjust.method = “holm”,
 cor.vars = c(energy, danceability, liveness, acousticness,    loudness, instrumentalness, track.popularity), 
 matrix.type = “upper”,
 colors = c(“mediumpurple3”, “violet”, “blue”),
 title = “Correlalogram for all Spotify Performance Metrics”
)

调查的结果

追踪受欢迎程度

Spotify 是这样对他们文档中的歌曲流行度进行分类的:

曲目的受欢迎程度是一个介于 0 和 100 之间的值,100 是最受欢迎的。流行度是通过算法计算的,并且在很大程度上基于该曲目的总播放次数以及这些播放的最近时间。一般来说,现在经常播放的歌曲会比过去经常播放的歌曲更受欢迎。重复曲目(例如单曲和专辑中的同一首曲目)被独立评级。艺术家和专辑的受欢迎程度是从曲目的受欢迎程度中数学推导出来的。请注意,流行度值可能会滞后实际流行度几天:该值不会实时更新

由于播放次数似乎是评估曲目受欢迎程度的主要指标,可以说每个人在这一指标上的得分越高,他们的品味相对于 Spotify 的其他部分就越受欢迎。根据这一理论,分数越低,他们的品味就越小众。(我可以向你保证,作为本次分析中大多数策展人的密友,Spotify 在评估曲目受欢迎程度方面做得很好)。总的来说,最受欢迎的歌曲来自瑞秋、海伦和喷火战机乐队。不出所料,特里斯坦最没有流行音乐品味(或者说最小众,取决于你怎么看)。如果你认识特里斯坦,这就说得通了。他得分最低的歌曲包括:阿兹特克摄像机的《在我心中的某个地方》、恐惧之泪的《给心中的年轻人的忠告》和新秩序的《奇异的三角恋》。看起来,尽管这些 80 年代后期的新浪潮流行歌曲在特里斯坦心中有着特殊的地位,但在 Spotify 的眼中,它们仍然是一首未雨绸缪的歌曲(或肖尔迪奇的家庭聚会)。

有趣的是, Joe 就其受欢迎程度而言拥有最多样的音乐品味,歌曲从 11 首到 72 首不等;这可能意味着乔愿意听流行音乐的两端。这很有趣,因为我们家一直流传着一个笑话“乔只听摩城”。(虽然应该提到的是,这一指标的方差是衡量歌曲在 Spotify-universe 中的受欢迎程度,而不是歌曲选择的多样性,因此这一假设仍有待否定)。

这可以通过一些巧妙的方式来可视化(方法中引用的代码):

Figure 1. Desert island disc popularity (0–100) by curator

Figure 2. Track popularity (0–100) by curator

持续时间

这是一个有趣的问题。每个人的荒岛光盘似乎落在平均 3-6 分钟的区域,这是可以预期的。如果不是因为西蒙在他的播放列表中包含了两首导致数据倾斜的歌曲,这些数据会被认为是正态分布的。西蒙收录了我们收到的所有荒岛唱片中最长的两首歌曲:Yes 的《谵妄之门》(约 22 分钟)和米勒·戴维斯的《嘘/和平——LP 混音》(约 18 分钟)。两首歌加起来足足有 40 分钟,有人可能会说这对于它自己的播放列表来说已经足够了(如果你喜欢 40 分钟的摇滚和爵士乐的话!).

Figure 3. Desert island disc track duration (ms) by curator.

拍子

似乎威尔在他的播放列表中拥有最大范围的节奏——以每分钟的节拍来衡量。这可能很好地反映了他在早上举重到他最喜欢的北方摇滚乐队的能力,同时能够在作为一名工料测量师的艰难一天后放松下来。(或者更有可能的是,由于本分析中使用的名义样本量,这是一种统计上的巧合)。

似乎卡哈尔更喜欢快节奏的歌曲。也许这就是他在房子里跺着脚听的音乐,而没有考虑到他沉重的脚步对周围环境的影响?

海伦的播放列表在 120 bpm 左右形成了一个几乎完美的分布。鉴于这是“流行歌曲”的典型节奏,这些发现得到了如上所述的曲目流行度数据的支持,其中海伦的歌曲是 Spotify 上最受欢迎的歌曲之一。

Emily 的数据也形成了一个很好的钟形曲线,但是在 110 bpm 左右。也许她对慢节奏歌曲的偏好决定了她在为 M 和 s 设计典型的英国桌布时总是镇定自若,举止放松。

Figure 4. Desert island disc track tempo (bpm) by curator.

25 首充满活力的歌曲

Spotify 是这样确定活力音乐的:

能量是一种从 0.0 到 1.0 的度量,代表强度和活动的感知度量。通常,高能轨道感觉起来很快,很响,很嘈杂。例如,死亡金属具有高能量,而巴赫前奏曲在音阶上得分较低。对该属性有贡献的感知特征包括动态范围、感知响度、音色、开始速率和一般熵。该特性的值分布如下所示:

Figure 5. How Spotify determine energetic music

下面展示了策展人在这次荒岛唱片分析中选出的 25 首最响亮的歌曲:

Figure 6. Top 25 most energetic songs by curator

前 25 首响亮的歌曲

Spotify 是这样确定活力音乐的:

轨道的整体响度,以分贝(dB)为单位。响度值是整个轨道的平均值,可用于比较轨道的相对响度。响度是声音的质量,是与体力(振幅)相关的主要心理因素。值的典型范围在-60 和 0 db 之间。该特性的值分布如下所示:

Figure 7. How Spotify determine loud music

下面展示了策展人在这次荒岛唱片分析中选出的 25 首最响亮的歌曲。Spotify 是如何确定这一指标的:

Figure 8. Top 25 most loud songs by curator

统计分析

尽管这个项目使用了名义上的样本量,我还是忍不住尝试了一些统计分析。本节将简要讨论我对我们收集的所有播放列表数据进行的两项分析。

"得分了"

我在 yarrr() 包的 pirateplot() 函数中发现了一个非常酷的功能,您可以在其中创建一个包含多个其他指标的组合效果的自定义变量。考虑到荒岛唱片是指当你被困在荒岛上时你会听的实际音乐,我创建了一个名为“DID Score”的变量,我觉得它最能反映如果你真的独处了很长一段时间你可能会选择听的音乐类型。此输出是从 Spotify API 中提取的以下变量的综合得分:

人气:先前定义(见上图)

能量:先前定义的(见上文)

效价:从 0.0 到 1.0 的量度,描述一首曲目所传达的音乐积极性。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。该特性的值分布如下所示:

Figure 9. How Spotify determine valence

可跳舞性:根据音乐元素的组合,包括速度、节奏稳定性、节拍强度和整体规律性,描述一首曲目适合跳舞的程度。值 0.0 最不适合跳舞,1.0 最适合跳舞。该特性的值分布如下所示:

Figure 10. How Spotify determine danceability

下面反映了所有策展人如何为他们的 DID 评分(对不起特里斯坦!):

Figure 11. DID Score for all curators

相关分析

我尝试了一下,看看从 Spotify API 中提取的任何音频功能/指标之间是否有任何相关的关联。有趣的是,没有独立变量与跟踪受欢迎程度相关。响度和能量显著相关(0.74)。精力和跳舞能力也是如此(0.36)。毫不奇怪,能量和声音(-0.71)以及响度和声音(-0.54)之间存在负相关。这比什么都重要,是一个相当好的指标,表明 Spotify 对这些音频功能的分类相当严格。然而,值得一提的是,这种分析只在我们收到的荒岛光盘播放列表中使用的 129 个数据点上进行。很有可能通过增加样本量,Spotify 的音频功能——无论是独立的还是作为多元线性模型的一部分——能够预测歌曲的受欢迎程度。然而,这仍有待阐明。

结论

音乐是我们生活中极其重要的一个方面。我们可能与电车上邻座的男人、地铁上的女人品味不同,当然也不会与在合作社花很长时间结账的老太太品味相同,但我们确实有一个共同的理解,那就是音乐能够带我们去某个地方。一些音乐激励我们在周六踢足球,一些音乐让我们反思我们希望能够收回的时间,一些音乐带我们回到我们最喜欢的海滩,在任何酷玩唱片的情况下,一些音乐让我们真诚地沮丧或想睡觉。

为了了解我们的朋友和家人喜爱的音乐,Sam 和我不仅能够实际聆听我们收到的播放列表,解读它们与馆长的相关性,还能想象它们对更广泛的音乐社区以及与其他人的播放列表的关系的重要性。在 Spotify 和他们的公共 API 的帮助下,以及这与 R 的良好集成,我能够对我们收到的播放列表所附的数据进行一些真正有趣的探索性分析,如果你对音乐或数据的热爱甚至只有我的一半,我真诚地推荐这个练习。

为您的变革管理设计实验

原文:https://towardsdatascience.com/design-of-experiments-for-your-change-management-8f70880efcdd?source=collection_archive---------9-----------------------

实验设计的逐步指南

数据科学专业人员,您是否曾经面临过以下任何挑战?

故事一:机器学习不等于实验设计

由于你的统计专业知识,你被要求设计一个实验,但是你意识到你的机器学习工具不能帮助你设计一个实验。

故事二:观测数据不可重复

你的团队观察到了与几个因素相关的销售趋势。你的团队想要提出新的商业策略。但是团队不能决定复制该过程的正确因素。

故事 3:相关性不是因果关系

你的团队发现了两个因素之间的强相关性,并提出了业务变革计划。你的团队得到了客户的认可,在一个有希望的试点测试中实现了商业提议。测试期过后,你没有得到声称的结果

如果是这样,你可能犯了用相关性来证明因果关系的错误。在我的岗位"机器学习还是计量经济学?“我分享过很多解析题都是关于因果的。这些因果问题需要数据生成的设计,不能从大数据中导出。今天,机器学习和统计实验的分歧似乎汇聚到了大数据科学的保护伞下。然而,这两个不同的学科可以而且应该交叉融合来解决众多的业务计划。

使用实验设计是做这件事的正确方法。实验设计已经在制造业、临床试验和医院服务中实践了几十年。在这篇文章中,我将带你经历建立一个成功的 DoE 的步骤,从而引导你进行变革管理。我将用银行业的一个服务操作来介绍 DoE 的思路。

什么是实验设计(DoE)?

实验设计是对受控测试进行适当的计划、实施、分析和解释,以评估影响结果的因素。

DoE 有什么好处?

实验的设计能够真正识别因果洞见。结果使您能够为您的变更管理提出可行的策略。DoE 成本更低。它使用统计学来设计有效测试结果的最小样本量。您可以同时处理多个输入因素,并识别可能会错过的重要交互。

[## 通过我的推荐链接加入 Medium-Chris Kuo/data man 博士

阅读 Chris Kuo/data man 博士的每一个故事。你的会员费直接支持郭怡广/戴塔曼博士和其他…

dataman-ai.medium.com](https://dataman-ai.medium.com/membership)

它是如何工作的?

DoE 在以下七个步骤中有其成熟的程序。第一,目标是什么?您应确定目标的衡量标准。二、考什么?你将确定测试的因素。第三,如何进行?你将决定指导和衡量的方式。第四,如何衡量?你会选择正确的统计分析。第五,结果是否可信?您将确定所需的样本量。六、如何分析数据?应用统计分析。第七,接下来是什么?在统计分析的帮助下,你可以做出结论和可行的项目。

案例研究:银行业服务运营的 DoE

以下是美国能源部指导变革管理的成功案例。

一家零售银行需要重新设计其账户申请流程。虽然可以在线申请,但仍然需要无需预约的申请。该银行的不完整申请比例很高,需要重新处理申请。再加工工作也减缓了其他操作,导致整体效率低下。银行需要实施正确的行动改变,以消除再加工中的浪费。

步骤 1:确定目标的衡量标准

可量化的目标总是起点。项目团队决定将完成应用程序的百分比作为目标。该团队排除了其他有趣但不太相关的指标,如平均存款额。

步骤 2:确定测试的因素

项目团队怀疑有四个因素可能会影响应用程序是否完整。该团队为四个因素中的每一个设计了两个级别:(I)申请类型(贷款账户或储蓄账户),(ii)分行位置(中西部和东北部),(iii)申请表的说明(中级或高级描述),以及(iv)有无示例。

步骤 3:确定指导和衡量的方式

实验在两个分支进行了两个月。自行管理的申请表继续在前台展示,因此展示方式没有变化。每个地点只有一种类型的申请表。表(A)中列出了这些因素的不同组合。

Exhibit (A)

步骤 4:选择正确的统计分析

项目团队需要了解各种因素水平的所有可能组合的影响。图表(A)被称为全因子设计。这样的实验允许研究者研究每个因素对目标变量的影响,以及因素之间的相互作用对目标变量的影响。

步骤 5:确定所需的样本量

如何确定析因分析的最小样本量?这是一个棘手的问题,因为它不仅取决于因素的数量,还取决于每个因素的“负载”或系数。正如“探索性和验证性因子分析”( Bruce Thompson,2004 )所解释的,如果一个因子有四个以上的水平,并且每个水平的系数小于 0.60,那么 N = 60 就足够了。如果一个因子有十个以上的水平,每个水平的系数在 0.40 左右,那么样本量至少应该是 150。任何超过 300 的样本量都被认为是足够的。项目组决定在每个因素组合中收集至少 300 份申请。

步骤 6:进行统计分析

该项目的目标是确定哪个因素组合显示出具有统计显著性的最高平均值。“统计显著性”是关键,这意味着这种差异足以保证下次的可重复性。研究小组使用了一种叫做 ANOVA(方差分析)的技术来比较“平均”。%完成”来验证差异是否具有统计学意义。

图表(B)显示了五个因素之间的差异。只有“描述”和“示例”中的差异在统计上具有显著性,置信度为 95%。这意味着高水平的描述和申请表中的例子将导致高完成率。

Exhibit (B)

一个因素可以影响另一个因素。这是通过因素之间的相互作用捕捉到的。申请表中的一个“例子”预计会降低中西部的毕业率,但会提高东北部的毕业率。

步骤 7:结论和可行策略

基于这些结果,项目团队总结了几个可行的策略:

  • 两种账户类型的申请表格相同
  • 提供更多描述
  • 在申请表中为东北地区提供了一个示例,但没有为中西部地区提供示例

新的申请表将完成率从 60%提高到 95%以上。这一改变大大缩短了申请时间,并消除了重新处理的时间。

这里值得注意的是,在“识别因果关系”系列文章中,我涵盖了旨在识别因果关系的计量经济学技术。这些文章涵盖了回归不连续性、差异中的差异、面板数据分析和因子设计的随机对照试验:

  • 机器学习还是计量经济学?(见“机器学习还是经济学?
  • 回归不连续(见通过回归不连续识别因果关系),
  • (DiD)(见)【通过差异鉴别因果关系】
  • 固定效应模型(参见通过固定效应模型识别因果关系)
  • ****采用析因设计的随机对照试验(参见“您的变更管理实验设计”)。

您还可以将“ Dataman 学习路径——培养技能,推动职业发展”加入书签,了解更多信息。

** [## 通过我的推荐链接加入 Medium-Chris Kuo/data man 博士

阅读 Chris Kuo/data man 博士的每一个故事。你的会员费直接支持郭怡广/戴塔曼博士和其他…

dataman-ai.medium.com](https://dataman-ai.medium.com/membership)**

R 的实验设计

原文:https://towardsdatascience.com/design-of-experiments-with-r-e54167fac490?source=collection_archive---------4-----------------------

r 代表工业工程师

构建 2^k 析因设计

Image by Hans Reniers available at Unsplash

实验设计

实验设计是六适马方法中最重要的工具之一。这是 DMAIC 循环中改进阶段的精髓,也是稳健流程设计的基础。

实验设计被定义为应用统计学的一个分支,它处理计划、实施、分析和解释受控试验,以评估控制一个参数或一组参数值的因素。DOE 是一个强大的数据收集和分析工具,可用于各种实验情况。它允许操纵多个输入因素,确定它们对期望输出(响应)的影响。

-美国质量协会

充分利用 DOE 将导致过程的改进,但是糟糕的设计会导致错误的结论,并产生相反的效果:效率低下,成本更高,竞争力更弱。

2^ k 析因设计

2^ k 析因设计是一般析因设计的特例; k 因子正在研究中,都在 2 个级别(即高,称为“+”或“+1”,低,称为“-”或“--1”)。这种析因设计广泛用于工业实验中,并且由于筛选大量可能在实验中有意义的因素的过程,通常被称为筛选设计,目的是选择它们用于测量响应。如果试验考虑了 n 次重复,那么试验总数为 n * 2^ k

因子通常用大写拉丁字母(A、B、…)表示,而主效应通常用与因子的拉丁字母相对应的希腊字母(α、β、…)表示,交互作用的效应用字母组合表示,这些字母代表其效应相互作用的因子。对于具有 3 个因子和 n 次重复的 2^ k 析因实验,统计模型为

对于下面的例子,我们将考虑一个 2 次重复的 2 全因子设计实验(即 222*2 = 16 次运行)。我们将这些因素命名为 ABC ,它们将有两个级别,分别为“ + ”和“-”。

让我们看看 R 代码!

第一步是导入 SixSgima R 包,设计 2 因子实验,将其随机化以消除未知或不可控变量的影响,定义一组重复,并为每个因子设计指定相应的响应。

设计好实验后,接下来的步骤包括聚合不同的析因设计,并从模型的汇总表中获得结果。

查看p-值,我们可以很有把握地得出,因子 CA 的影响是显著的,而因子 B 的影响则不显著。这些因素之间的相互作用既不是双向的,也不是三向的,因此它们并不重要。获得这些统计信息后,我们可以通过排除所有不显著的影响来简化模型,获得模型的系数,获得所有实验条件的估计量,并计算每个因素的置信区间。

同样,我们也可以在单个地块中可视化每个因素对模型结果的影响。让我们用下面几行代码来绘制因子 A 的对模型结果的影响。

根据前面的图,我们可以观察到,当因子 A 设置在“+”级别(即 1.0)时,结果的值大于设置在“-”级别时的值(即-1.0)。此外,我们可以通过使用 ggplot2 包中的 facet_grid 来绘制单个图中重要因素的影响。

根据上面的图,与因子 A 对模型结果的影响相比,当因子 C 设置在“+”级别时(即 1.0),结果的值低于设置在“-”级别时(即-1.0)。同样,我们可以在一个图中绘制两个因素的相互作用,以可视化它们对模型结果的影响。

如上图所示,由于两条线不相交,这两个因素之间没有相互作用。为了使结果值最大化,因子 A 应设置在“+”级,因子 C 应设置在“-”级;另一方面,为了最小化结果值,因子 A 应设置在“-”级,因子 C 应设置在“+”级。最后,我们可以绘制残差图,并使用正态性检验验证它们是否遵循正态分布。

Residuals Plots

根据上面的残差图,残差中没有清晰的模式。但是,正常的 Q-Q 图不够直。

总结想法

给出的实际案例是一个非常有代表性的例子,说明了如何在一个使用 R 软件的六适马项目中使用 DOE。从工程的角度来看,可以用来减少时间来设计/开发新产品和新工艺;提高现有流程的性能;提高产品的可靠性和性能;实现产品和流程的稳健性;并执行评估材料、设计方案、设置组件和系统公差。然而,DOE 本身并不是一种改进。工程师有责任充分利用这一工具来实现多个目标和更好的结果。

— —

如果你觉得这篇文章有用,欢迎在GitHub上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的介质 简介 来探索我以前的文章。感谢阅读。

-罗伯特

设计模式:简介

原文:https://towardsdatascience.com/design-patterns-an-introduction-4e7668d3dff9?source=collection_archive---------26-----------------------

最近,我在一个由 Net Objectives 提供的 3 天沉浸式课程中了解到了设计模式的概念。虽然这门课教得很好,概念也很深刻,但我一直被教室里的每个人分心,除了我和我的队友是软件开发工程师。事实上,我记得在准备数据科学面试时很少阅读关于这个问题的博客帖子,因为这是一个高级话题。因此,在这篇文章中,我想探索设计模式的概念以及它们如何与数据科学相关。

什么是设计模式?

设计模式是一组模板(或正式的最佳实践),用于解决编程世界中经常出现的问题。

想象一下,这是一个慵懒的周六下午的中午,你很渴;人类常见的问题。所以,你不情愿地从沙发上起来,抓起一个空杯子,从水龙头里倒满水,喝光,把杯子放回晾衣架上,然后回到沙发上。30 分钟后,由于你在看你最喜欢的节目的大结局时吃的咸爆米花,你又渴了。现在,你比以前更不情愿地从沙发上起来,经历和上面一样的步骤。也许你可以使用由有经验的饮水者制定的设计模式,来帮助使这个过程更有效。

如果受你妈妈设计模式的启发,你用一个过滤器装满一大罐自来水,会怎么样?这种设计模式做了几件重要的事情:

首先,它遵循了重要的“不要重复自己”(干)原则。手边有一壶水,你就不必重复这个过程中的几个步骤,比如从沙发上站起来,找到一个玻璃杯,然后装满自来水。

第二,它封装了自来水系统的脏乱和杂质,并允许您以您期望的形式获得水——无杂质且易于倾倒。

最后,它将玻璃杯(它只是水壶和嘴之间的水传送器)与水壶(它关注的是存储)和过滤器(它关注的是净化)分开。早些时候,你可能会考虑买一个更大的杯子,既能储存水,又能让你喝水,而完全忽略了净化的问题。类似地,编程中的设计模式可以帮助解决一些关于冗余、关注点分离和代码可重用性的问题。

对于这个例子,设计模式的概念深受物质世界的影响。建筑师兼设计理论家克里斯托弗·亚历山大(Christopher Alexander)在他的书《永恒的建筑之道》(The Timeless Way of Building)中谈到了建筑中的设计模式。这启发了 Gamma、Helm、Johnson 和 Vlissides(被亲切地称为四人组)在《设计模式:可重用面向对象软件的元素》一书中提出的现代软件开发中设计模式的概念。这两本书为这一领域的所有从业者形成参考材料。

概括地说,有三种被普遍接受的设计模式:

1.创造性设计模式——这些模式与新类、对象或实例的创建有关。

2.结构设计模式——这些属于类和对象的结构。

3.行为设计模式——这些模式与类的对象之间的交流有关。

随着新语言的发展,一些设计模式变得过时了。例如,由于 Python 是一种动态语言,它不需要称为“工厂”的创造性设计模式,这种模式与对象的创建有关。此外,遵循“模式不是被发明的,而是被发现的”这句格言,新的设计模式可能会从开发用例中出现。这就是数据科学和机器学习及其蓬勃发展的用例将有助于发现新的设计模式的地方。

设计模式如何对数据科学家有用?

作为一名数据科学家,我大部分时间都在用 Python (70%)、SQL (20%)或 R (10%)编写代码。我为数据收集和探索性数据分析编写简短的脚本。我也为模型原型编写更长的脚本。最后,我为我们的数据科学团队开发软件工具。这个过程有几个部分可以用设计思维来改进:

脚本 —该领域迫切需要遵循编码标准,如 PEP-8 格式指南,以确保脚本可供其他数据科学团队甚至您以后阅读和重用。我的 Python 脚本倾向于放在 Jupyter 笔记本中,这可能很难浏览。在这里, Chelsea Troy 谈论笔记本电脑的最佳实践。由于这些脚本大多很短,并且使用来自不同包的可重用命令,我看不出有必要大规模重构我的代码。

构建工具 —这是风格和设计模式都可以产生最大影响的地方,因为这类似于软件开发。在这里,我发现重构大师的插图非常有见地。

在这堂课后,我确信在每个数据科学家的工作流程中融入一定程度的设计思维是非常重要的。首先,设计将提升由数据科学家产生的代码的质量。其次,但对产品团队顺利工作非常重要的是,它将使数据科学家和软件工程师(或机器学习工程师)之间的沟通更容易,他们经常负责扩展我们的代码。

大数据性能的设计原则

原文:https://towardsdatascience.com/design-principles-for-big-data-performance-cd2c0e9e92bd?source=collection_archive---------11-----------------------

过去 20 年来,大数据技术的发展呈现了一部与不断增长的数据量进行斗争的历史。大数据的挑战尚未解决,这一努力肯定会继续,未来几年数据量将继续增长。原始的关系数据库系统(RDBMS)和相关联的 OLTP(在线事务处理)使得在所有方面使用 SQL 处理数据变得如此容易,只要数据大小足够小以便管理。然而,当数据达到相当大的数量时,处理起来就变得非常困难,因为成功地读取、写入和处理数据需要很长时间,有时甚至是不可能的。

总的来说,处理大量数据是数据工程师和数据科学家的普遍问题。这个问题在许多新技术(Hadoop、NoSQL 数据库、Spark 等)中都有体现。)在过去十年中蓬勃发展,这一趋势将继续下去。本文致力于在设计和实现大数据量的数据密集型流程时要记住的主要原则,这可能是为您的机器学习应用程序准备数据,或者从多个来源提取数据并为您的客户生成报告或仪表板。

事实上,处理大数据的根本问题是资源问题。因为数据量越大,就内存、处理器和磁盘而言,所需的资源就越多。性能优化的目标是减少资源的使用,或者提高充分利用可用资源的效率,从而减少读取、写入或处理数据的时间。任何优化的最终目标应该包括:

  1. 最大限度地利用可用内存
  2. 减少了磁盘 I/O
  3. 最小化网络上的数据传输
  4. 并行处理,充分利用多处理器

因此,在处理大数据性能时,一个好的架构师不仅仅是一名程序员,还应该具备服务器架构和数据库系统方面的知识。考虑到这些目标,让我们看看设计或优化您的数据流程或应用程序的 4 个关键原则,无论您使用哪种工具、编程语言或框架。

原则 1。基于您的数据量进行设计

在开始构建任何数据流程之前,您需要知道您正在处理的数据量:从什么数据量开始,以及数据量将增长到什么程度。如果数据总是很小,那么设计和实现会更简单、更快。如果数据开始时很大,或者开始时很小但会快速增长,则设计需要考虑性能优化。对于大数据表现良好的应用程序和流程通常会给小数据带来过多的开销,并导致负面影响,从而降低流程速度。另一方面,对于大数据来说,为小数据设计的应用程序需要太长时间才能完成。换句话说,对于小数据和大数据,应用程序或流程的设计应该有所不同。下面详细列出了原因:

  1. 因为从端到端处理大型数据集非常耗时,所以中间需要更多的分解和检查点。目标是双重的:首先,在整个流程结束之前,允许用户检查即时结果或在流程的早期提出异常;第二,在作业失败的情况下,允许从最后一个成功的检查点重新开始,避免从头重新开始,这是更昂贵的。对于小数据,相反,由于运行时间短,通常 1 次执行所有步骤的效率更高。
  2. 在处理小数据时,流程中任何低效率的影响也往往很小,但同样的低效率可能会成为大数据集的主要资源问题。
  3. 并行处理和数据分区(见下文)不仅需要额外的设计和开发时间来实现,而且还会在运行时占用更多的资源,因此,对于小数据应该跳过这些。
  4. 当处理大量数据时,性能测试应该包含在单元测试中;这通常不是小数据的问题。
  5. 利用可用的硬件可以快速完成小数据的处理,而当处理大量数据时,由于耗尽内存或磁盘空间,相同的过程可能会失败。

底线是同一流程设计不能同时用于小数据和大数据处理。大数据处理需要不同的思维方式、以前处理大数据量的经验,以及在初始设计、实现和测试方面的额外努力。另一方面,不要对为大数据设计的流程采取“一刀切”的做法,这可能会损害小数据的性能。

原则 2:在流程的早期减少数据量。

当处理大型数据集时,在处理过程的早期减小数据大小始终是获得良好性能的最有效方法。无论投入多少资源和硬件,都没有解决大数据问题的灵丹妙药。因此,在开始真正的工作之前,一定要尽量减少数据量。根据不同的用例,有许多方法可以实现这一点。下面列出了一些常见的技术,以及其他一些技术:

  1. 当字段为空值时,不要占用存储空间(例如,空间或固定长度字段)。
  2. 经济地选择数据类型。例如,如果一个数从不为负,则使用整数类型,但不使用无符号整数;如果没有小数,就不要用浮点数。
  3. 使用整数中的唯一标识符对文本数据进行编码,因为文本字段会占用更多的空间,应该避免在处理中使用。
  4. 当不需要较低粒度的数据时,数据聚集总是减少数据量的有效方法。
  5. 尽可能压缩数据。
  6. 减少字段的数量:只阅读那些真正需要的字段。
  7. 利用复杂的数据结构减少数据重复。一个例子是使用数组结构将一个字段存储在同一个记录中,而不是在字段共享许多其他公共键字段时将每个字段存储在单独的记录中。

我希望上面的列表能给你一些关于如何减少数据量的想法。事实上,相同的技术已经在许多数据库软件和物联网边缘计算中使用。您对数据和业务逻辑理解得越好,在处理数据之前尝试减少数据的大小时,您就越有创造力。最终的结果是,利用可用的内存、磁盘和处理器,工作效率会高得多。

原则 3:根据处理逻辑合理划分数据

启用数据并行是快速数据处理的最有效方式。随着数据量的增长,并行进程的数量也在增长,因此,添加更多硬件将扩展整体数据处理,而无需更改代码。对于数据工程师来说,一个常用的方法是数据分区。关于数据分区技术有很多细节,这超出了本文的范围。一般来说,有效的分区应该导致以下结果:

  1. 允许下游数据处理步骤(如连接和聚合)在同一个分区中进行。例如,如果数据处理逻辑在一个月内是独立的,那么按时间段划分通常是一个好主意。
  2. 每个分区的大小应该是均匀的,以确保处理每个分区所需的时间相同。
  3. 随着数据量的增长,分区的数量应该增加,而处理程序和逻辑保持不变。

此外,根据需要对数据执行的操作,应该考虑在处理的不同阶段更改分区策略以提高性能。例如,在处理用户数据时,用户 ID 的散列分区是一种有效的分区方式。然后,在处理用户的事务时,按时间段(如月或周)进行划分可以使聚合过程更快、更具可伸缩性。

Hadoop 和 Spark 将数据存储到数据块中作为默认操作,这使得并行处理能够在本机进行,而不需要程序员进行自我管理。然而,因为他们的框架非常通用,以同样的方式对待所有的数据块,所以它阻止了一个有经验的数据工程师在他或她自己的程序中可以做的更好的控制。因此,了解本文中陈述的原则将有助于您基于可用的工具和您正在使用的工具或软件来优化流程性能。

原则 4:尽可能避免不必要的耗费资源的处理步骤

如原则 1 所述,为大数据设计流程与为小数据设计流程有很大不同。设计的一个重要方面是尽可能避免不必要的耗费资源的操作。这需要高技能的数据工程师,他们不仅要很好地理解软件如何与操作系统和可用的硬件资源一起工作,还要全面了解数据和业务用例。在本文中,我只关注为了提高数据处理效率,我们应该避免的前两个过程:数据排序和磁盘 I/O。

当 1)与另一个数据集连接时,通常需要将数据记录按一定顺序排列;2)聚合;3)扫描;4)重复数据删除等。但是,当输入数据集远大于可用内存时,排序是最昂贵的操作之一,需要内存和处理器以及磁盘。为了获得良好的性能,按照以下原则非常节俭地进行排序是很重要的:

  1. 如果数据已经在上游或源系统中排序,则不要再次排序。
  2. 通常,两个数据集的连接需要对两个数据集进行排序,然后合并。将大数据集与小数据集联接时,将小数据集更改为哈希查找。这可以避免对大型数据集进行排序。
  3. 仅在数据大小减小后(原则 2)并在一个分区内(原则 3)进行排序。
  4. 设计流程时,将需要相同排序的步骤放在一起,以避免重新排序。
  5. 使用最佳排序算法(例如,合并排序或快速排序)。

另一个普遍考虑的因素是减少磁盘 I/O。这方面有许多技术,超出了本文的范围。下面列出了这方面需要考虑的 3 个常见原因:

  1. 数据压缩
  2. 数据索引
  3. 在写入磁盘之前,在内存中执行多个处理步骤

在处理大数据时,数据压缩是必不可少的,因为它允许更快的读写以及更快的网络传输。快速数据访问需要数据文件索引,但代价是写入磁盘的时间更长。仅在必要时对表或文件进行索引,同时牢记它对写入性能的影响。最后,在将输出写入磁盘之前,尽可能在内存中执行多个处理步骤。这种技术不仅用于 Spark,还用于许多数据库技术。

总结

设计具有良好性能的大数据流程和系统是一项具有挑战性的任务。本文中阐述的 4 个基本原则将为您提供一个指南,让您在处理大数据和其他数据库或系统时,积极主动地和创造性地思考。最初的设计往往不会带来最佳性能,这主要是因为开发和测试环境中的硬件和数据量有限。因此,在生产中运行流程后,需要多次反复进行性能优化。此外,优化的数据流程通常是为特定的业务用例定制的。当使用新特性增强流程以满足新用例时,某些优化可能会变得无效,需要重新考虑。总而言之,提高大数据的性能是一项永无止境的任务,它将随着数据的增长以及发现和实现数据价值的持续努力而不断发展。

为适当的互动而设计

原文:https://towardsdatascience.com/designing-for-appropriate-interaction-dcaaeffb7fb5?source=collection_archive---------15-----------------------

如果我们把机器设计成更体贴的社会角色会怎么样?

all images by author

我们的设备被设计成在社交上很笨拙。尽管如此,在过去十年里,没有什么比智能手机及其引发的二次效应对社会的影响更大了。在未来十年,随着技术变得更加亲密,同时通过传感器和人工智能的进步,我们作为设计师和技术专家有一个独特的机会来塑造技术作为社会行为者的角色。

人们经常引用迪特·拉姆斯的话说,他努力把产品设计得像“一个优秀的英国管家”。这是对拉姆斯的第五个原则“好的设计不引人注目”的一个很好的比喻。而在实体产品领域,这与他的第二个原则“好的设计让产品有用”明显不同——随着产品变得越来越相互关联,同时越来越深入我们的生活,如果它们在根本上不是为了不引人注目而设计的,它们很容易变得无用。
人们已经可以感觉到,在今天的智能手机使用中,人们对他们收到的大量通知是多么不知所措。现在,想象一下一套增强现实护目镜,它不知道什么时候适合显示信息,什么时候必须清除视野。

从更广泛的意义上来说,在现实世界中,产品是“英国管家”的理念和产品“在你需要的时候出现在你面前,但一直在后台”的要求通常被转化为审美品质。然而,数字产品在很长一段时间内都无法满足这种期望。有限的感知能力,但更重要的是电池寿命和计算能力的缺点,导致了交互设计中基于“拉”的模型,这种模型主要需要用户手动询问要采取的动作。随着智能手机的出现,以及无处不在的连接的出现,“推送通知”系统成为我们日常生活中根深蒂固的一部分,随之而来的是不断努力跟上这种新的基于“推送”的交互方式。虽然拟人化的数字管家(软件)在很长一段时间内从未预测到我们的需求,并且总是不得不被要求为我们执行一项行动,但它最近转向不断要求我们的注意,并对我们施加任何琐碎的干扰,同时不仅为他们的雇主(“我们”——用户)服务,还为任何其应用程序以某种方式出现在我们主屏幕上的公司的利益服务。

在 2006 年的论文“魔法墨水”中,Bret Victor 已经得出结论,当涉及到信息软件的人机界面设计时,“交互”将被“认为是有害的”——或者用一种更“拉姆齐”的说法——软件设计师应该努力做到“尽可能少的交互”。

Victor 提出了一个策略来减少与系统交互的需要,他建议“信息软件的设计最初应该主要作为一个图形设计项目来处理”,把任何界面设计项目首先作为图形设计的一个练习,只有在最后才使用操作。虽然这对于基于“拉”的信息软件来说是一种有效的方法,但对于通信软件(Victor 将其描述为“操纵软件和粘在一起的信息软件”)来说却是不够的,因为如今通信软件将信息强加给我们,而大多数通信软件根本没有多少图形界面。

另一种策略是通过环境、历史和用户交互来推断上下文。维克多写道,软件可以

1.推断出需要其数据的上下文,
2。筛选数据,排除不相关的和
3。生成一个直接针对当前需求的图形

12 年后,随着技术的进步,尤其是硬件和软件的集成,其推断上下文和筛选数据的能力变得更强,因此可以用于生成“图形”(或任何其他输出),以更好地满足当前用户的需求,但更重要的是在时间、空间和方式上适合用户及其环境。

但是适当对(交互)行为意味着什么呢?韦氏词典将合适定义为“特别适合或合适的品质或状态”。在这里,我认为任何行为或互动都是适当的,如果它不能通过自动化或预期来避免,并且符合特定社会的道德模式。这在不同的社会之间变化很大,但也取决于一个人与特定人群的个人关系——无论是整个文化还是一群朋友。

随着移动电话的广泛使用和铃声的出现,电影院决定制定一份合同,规定在他们提供的环境中如何恰当地使用这项技术。直到今天,每部电影都以一个通知开始,要求人们将手机设置为“静音模式”。公共交通也采取了类似的措施。智能手机的出现甚至导致了设备的家庭手工业,试图让人们更难使用智能手机,更难在演出时分心。

然而,通过计算模拟适当性并不是一件容易的事情。在我们目前的设备中解决这个问题的尝试都是非常战术性的。人机礼仪的整个领域在今天的大多数软件中仍然被忽视——有时仅仅是因为的法律要求才被考虑。

但即使是更通用的建模方法,如苹果 iOS 的“请勿打扰”功能,也需要用户在设置时非常谨慎,缺乏灵活性和流动性,因为它们都是模仿他们的祖先“飞行模式”的设计蓝图。

在交互设计或人机交互研究中,机器作为社会参与者的探索并不新鲜。传感器和计算的进步,加上更有能力的机器学习,自然导致了一场让计算机更具情境或社会意识的运动。

这篇文章是基于在情感计算和人机礼仪以及 CASA (计算机作为一个社会角色)领域所做的大量工作。

我从探索工作的未来开始了我的设计过程。办公室一直是交互设计的沃土。在“所有演示之母”中,道格拉斯·恩格尔巴特通过讲述一个发生在知识工作者(或当时的“知识分子”)办公室的场景,开始解释观众将要看到的内容:

“…如果在您的办公室里,作为一名脑力劳动者,为您提供一台由计算机支持的计算机显示器,它整天为您工作,并对您的每个动作做出即时(…)响应,您能从中获得多少价值?”

从那以后,办公室发生了很大的变化,这在很大程度上要归功于 Engelbart 和 Licklider 通过 SRI 所做的贡献。许多人再也不在办公室工作了——所有最终变成思维工具和大脑自行车的技术,真正帮助增强了我们大脑的能力、生产力和创造力,但同时也最小化了我们思维的空间——我们大脑的容量。

在以人为中心的设计过程中,我首先围绕当今的知识工作是什么样子采访人们,然后构思出超越知识工作者办公室的概念,无论是小隔间、开放式办公室还是任何地方。

最终出现的框架为其个别应用程序奠定了基础,即“API”,它建立在一个传感器和智能系统的基础上,该系统具有推断上下文和筛选数据的能力,以建立一个仅在适当时发生的最小交互模型,该模型基于用户的环境、精神状态和道德模型,该模型基于系统与用户在给定上下文中的先前交互的反馈进行训练。

Conceptual ‘API’ graph for appropriate machine behaviour

现在,我们将把这个系统应用于从目前包含“不适当”行为的研究中出现的场景,并尝试将涉及的机器想象为更体贴的社会行为者。

每一个原型都伴随着一个宽泛的‘我们怎么可能?’旨在作为一个松散原则的问题,以便其他设计师和技术人员在设计他们的产品或服务时可以问自己同样的问题——将原型视为许多可能的实施策略之一。

1 →人机礼仪

我们怎样才能设计出能够恰当对待用户的机器?

如果一个导航系统能够尊重对话会怎么样?

想象一下,开着你的车。与你的副驾驶进行深入的交谈。当你说话时,你的副驾驶会听你说话,反之亦然。这是一个引人入胜的讨论,每个懂自然语言的人都能看出来。

Prototype → a simple iOS app that doesn’t interrupt the user when it hears them speak, but uses short audio signals to make itself heard.

导航系统也是如此,它使用语音识别自然语言处理来通知其“道德模型”。因此,只有在对话自然中断时,它才会说出下一个方向。当信息变得更紧急时,它会使用更具侵入性的信号。只有当紧急程度达到最大时,系统才会发出大声说话这样的干扰信号。在眼球追踪和其他传感设备的帮助下,它甚至可以判断你是否已经识别了指令。

使用“API”的同一个系统甚至可以与 Apple Music 或 Spotify 等应用程序集成,在你最喜欢的播客中的对话出现自然中断时,或者就在你正在听的当前歌曲中你最喜欢的部分之后,完美地定时中断。

2 →可协商的环境

我们怎样才能设计出意识到并关注周围环境的机器?

一般来说,“谈判环境”是指机器和它的主人之间的互动对周围的人产生影响的环境。这通常与公共空间相关,例如在火车上或公园里,但更重要的是在更私密的空间,由同一批人共享,如在开放式办公室、电影院甚至飞机上。

如果机器能够礼貌地对待它们影响的每一个人,会怎么样?

Prototype → A new take on the brightness slider that contains a subtle gradient to visualize how others set brightness around you to nudge you to set it similarly.

只有少数人还在使用他们的设备。当第一批人调低他们笔记本电脑的亮度进入睡眠模式时,附近设备的平均亮度开始下降,其他没有调整亮度的设备也相应地自动适应。如果他们的用户不重置它(并因此应用负面强化),他们各自的“道德模型”会接受这种行为的训练,并被他们的用户接受。

3 →一致性

我们如何设计能够在新的未知环境和情况下适应适当行为的机器?

最后一个故事带来了一个有趣的问题:设置是否应该自动适应环境?当人们来到一个不熟悉的地方,他们会观察其他人的行为,以弄清楚“这个地方是如何运作的”。只有当他们对环境有信心时,他们才会开始做出调整,或者对自己在规则之外的行为感到自信。

如果机器能够理解并动态适应不同的习俗和新环境会怎样?

Prototype A settings app in which the settings change based on the user’s location or context (represented through proximity to different iBeacons).

想象一下,日本的一个家庭正在当地的餐馆享用美食。一名商人(似乎是他第一次来日本)在进入餐厅时,正大声录制语音信息发送给一名同事。他的智能手机识别新的环境,查看其他手机(都切换到“请勿打扰”)并复制它们的设置,因为他已经将自己对不熟悉环境的“符合性”级别设置为“高”。一旦他离开餐厅,他就会收到同事的回复,因此可以尽情享受他的用餐。

4 →增强

当我们通过数字方式交流时,我们如何利用机器成为更好的社会参与者?

既然我们已经看了关于系统如何使机器成为更好的社会行为者的多个例子,我们可能会问自己,这个系统如何帮助我们成为更好的社会行为者——特别是在数字通信中,即使是人类也经常缺乏我们用来判断中断是受欢迎还是具有破坏性的常见社会线索。

如果我们一直都知道可以问同事一个“快速问题”会怎么样?

Prototype iOS App that uses Face ID eye-tracking and networks with another iPhone running the same app detecting when both people pay attention (or not) and then signaling between them.

想象一下在一个开放式的办公室里。现在是上午 10 点,通常是一天中最忙的时候。马克有一个紧迫的问题,但他的同事劳拉似乎很忙。马克知道劳拉今天某个时候有一个截止日期。他不确定是否应该马上问这位同事,还是等到午餐时间,甚至是傍晚,这样才省点事。

马克使用“我的同事”应用程序,劳拉用它来表示她是否高度集中注意力或者是否为一点点分散注意力而高兴。该应用程序使用眼球追踪和其他参数来区分这两者。Laura 看起来确实很专注,所以 Mark 可以在她不再专注并且乐于聊天时请求通知。当系统检测到劳拉可能需要一点休息时,它会问她是否想和马克聊天。劳拉同意,她会感谢一点休息,并接受了邀请。马克收到通知,他们聊了一会儿。

这个系统的一个重要元素是它从头学习的能力。每一个配备了这个框架的系统都可以从一个非常基本的“道德模型”开始——一个“白板”。随着它从环境中学习,主要是从它的用户那里学习,它将根据自己的经验——根据它在现实世界中采取的行动获得的反馈——对什么是适当的行为形成独特的观点。因此,一个被一位法国时尚博主“社会化”的系统,对于它认为合适的东西,会有一个略微不同的想法,这个系统是由一位日本老年妇女通过使用训练出来的,她刚刚得到了她的第一部智能手机。只有当这些设备在相同的附近时,它们才会开始相互影响,如果博主曾经去过日本,出于对他们不熟悉的文化的尊重,他们甚至会将设备的“一致性设置”更改为更高的级别,包括人对人和设备对设备。

这种“在情境伦理中的计算方法”与如今科技公司在判断对错时采用的更像“圣经法则”的方法截然不同。如今,互联网的大量使用由脸书控制,当谈到平台上允许或不允许什么内容时,它有一种非常典型的硅谷方式。硅谷的工程师、设计师和产品经理定义了使用他们产品的整个世界的道德标准。一旦脸书(或其子公司)不断进入新的市场并超越其 20 亿用户,或者来自其他文化的网络在技术世界中占据主导地位,今天已经形成的紧张局势只会进一步加剧,必须开始开发一种更具可扩展性、动态性和包容性的解决方案。

我很想听听你对我们如何让机器成为更体贴的社会角色的想法。请在这里或在推特上告诉我 @sarahmautsch 。

释文

[1]想想通知(其设计大多由操作系统的创造者规定)或语音用户界面,如 Siri 或 Alexa。

[2]在这篇文章中,伦理一词是在狭义上使用的,基于其字面上的原始含义,来自希腊民族精神/έθος/,在牛津词典中被定义为“一种文化、时代或社会的特有精神,表现在其态度和愿望中”。当考虑到环境来对其进行伦理评价时,它被称为情境伦理。相反,圣经法律类型的方法是基于绝对的道德学说来判断。由于这个项目关注的是让机器根据它们从环境中的(交互)行动中学习到的知识做出适当的行为,所以这个作品培养了情境伦理的思想。

[3]API 代表应用程序编程接口,是‘一套规则,允许程序员为特定的操作系统开发软件,而不必完全熟悉那个操作系统’—这里我们将把它看作是系统的一个概念(包括所有的输入、输出和核心功能),在此基础上我们可以开始设计。

应用商店搜索广告系统的拍卖机制设计

原文:https://towardsdatascience.com/designing-the-auction-mechanism-for-the-app-store-search-advertising-system-4aae53ce9e32?source=collection_archive---------39-----------------------

The Microcosm of London (1808), an engraving of Christie’s auction room. Taken from here.

这个故事分享了我为伊朗第三方 Android market placeCafe Bazaar的搜索广告系统设计拍卖机制的经历。

在深入研究该机制的细节之前,我需要解释一下该机制所针对的搜索广告模型。

搜索广告模型

简单地说,Search-ads——app store 搜索广告系统,会在用户使用 app store 搜索系统搜索到的查询关键词【q】的搜索结果的第一行显示安卓应用【a】,作为广告。

如果【u】点击广告上的安装底部,【a】将被收取从对(【q】【u】)对进行的拍卖中确定的价格金额。

综上所述,可以推断 S earch-ads 是一个点击付费广告系统,其成功因素依赖于两个方面:

  1. 使用 app store 搜索系统,并希望找到自己想要的 android 应用程序的用户
  2. 投资他们的钱为他们的 android 应用做广告的开发者

从现在开始,我将把使用 app store 下载自己想要的安卓应用的用户称为用户,把自己的安卓应用放到 app store 的安卓开发者称为开发者

Two different ways that an ad can be shown in the search results of a query.

Search-ads 是一个先进的广告系统,这意味着每个想要为他们的应用做广告的 android 应用开发者都应该创建一个活动,包括开始和结束日期、预算金额和其他一些标识符。在创建活动之后,他们对他们想要的搜索查询进行竞价,并可能使用额外的搜索广告功能,如查询建议、广泛竞价等。

Search-ad 对任何用户搜索的每个搜索查询进行拍卖;并且进一步选择最多一个获胜者应用作为广告显示在搜索结果的第一行中。

这个系统是针对开发商的复杂投标。他们应该准确地知道什么目标查询,并相应地管理他们的出价。

拍卖

拍卖是搜索广告的核心。思考设计拍卖机制将导致人们考虑其特点。因此,对于应用程序商店的广告目标,机制设计过程在其设计者肩上奠定了一套具体的政策。

搜索广告‘拍卖必备特征’是:

  • 首先,搜索广告的广告模式高度依赖用户——广告点击是最重要的赚钱行为。
    要交付像样的用户体验,搜索结果必须符合用户查询。此外,搜索广告,作为最突出的查询结果,在传递这种体验方面发挥了重要作用。如果有任何东西干扰这样做,用户对搜索结果的忠诚度就会丧失。这可能有不同的解释。有些人可能会说,获奖的应用程序应该具有高质量,其他人可能会说,它应该尽可能与查询相关,等等。然而,第一个特征告诉我们首先来自用户
  • 第二,模型需要有开发者作为不同拍卖的参与者。开发者正在投资一个出售安装点击的广告系统。因此,可以有把握地假设,他们的第一个也是最重要的动机是让新的可靠用户安装他们的 android 应用程序,从而促进他们业务的增长。考虑到这一点,拍卖机制应该是简单和健壮的,也就是说,对博弈论有幼稚理解的每个人都可以使用它。开发者对使用搜索广告的满意度将导致更多的参与和投资。因此,第二个特征告诉我们第二个来自开发者
  • 最后但同样重要的是,这种模式为应用商店创造了收入。因此,设计一个在创收方面最优或接近最优的拍卖机制是合理的。这最后一个特征告诉我们最后出现在 app store 中。

不仅这些特征的定义很重要,它们的顺序也很重要。他们的命令为设计拍卖机制强加了一套政策。

机械设计

为简单起见,固定查询关键字【q】。让我们假设有 n 个开发者想要使用搜索广告【q】上为他们的 android 应用做广告。说第八个开发者愿意支付搜索广告高达Vi——估价,每点击【q】。理想情况下,该机制希望每次点击获得的最大收入是 MAXi{Vi} 。然而,问题是点击是随着用户的动作发生的。为了更好地理解这一点,记住这两个概念是有帮助的:

  1. 印象:
    当一个应用在【q】的搜索结果中显示为广告时,就会产生印象。
  2. 点击率(CTR):app【a】查询【q】
    点击率,是【a】【q】的搜索结果上显示为广告时被点击的 id 概率。

给定上面的定义,让我们假设第个开发者的应用在【q】上有 CTR Pi 。解释这些 CTR 的一种方法是将它们视为来自用户的直接反馈。因此,使用 CTRs 并在该机制中引入期望将使得每次印象的期望最大收入为 MAXi{Pi * Vi} 。具体来说,如果拍卖机制知道投标人的估价和 CTR,则该值是可实现的。但是,可能无法准确地拥有这两个变量。首先,开发商是在战略环境下投标。因此,他们可能不会在拍卖中使用他们的真实估价,并可能操纵他们的出价。其次,评估一个真正的点击率本质上是一项艰巨的任务,我们应该估计相关的点击分布。

在讨论提议的拍卖机制之前,让我们首先考虑一种估计点击率的有效方法。

CTR 估计

存在许多方式来考虑统计和机器学习方法,以估计点击的概率,例如用足够和可靠的数据训练模型等。

解决 CTR 估计问题的一种方法是将其视为强化学习(RL)设置。处理探索与开发的权衡是 RL 优化的独特之处之一。准确地说,多臂 bandit (MAB)算法有助于平衡 CTR 估计问题中的探索和利用。

要估算 app【a】【q】上的点击概率,可以把它想象成 MAB 设定中的一只手臂。每当作为广告在【q】【a】上显示给用户时,用户对【q】有了印象,并通过他们在【q】上的动作接收是否点击的信号,这完全取决于用户。这个点击率可以用【a】【q】上获得的点击数来估算,方法如下:

  • P = 1*——点击的概率,在开始时被初始化——假设某个常数因子 c 使得T5【a】**已经得到 c 的印象和点击数,这导致了 c/c 的概率*
  • 每当在拍卖中被宣布为获胜者并作为广告显示给用户时,其在【q】上的印象数增加 1,因此如果用户点击该广告,其在【q】上的点击数也增加 1。 P 是利用点击次数对印象数的上限置信区间估计——转化率重新估计的。**

上限置信区间估计可以被解释为好像 Search-ads 把它的信任放在开发者——arm 的 MAB 设置上,并且为每个开发者使用最高可能的点击概率。

拟议机制

我们假设用户【u】搜索【q】。假设第 i 个开发商在【q】的那一轮拍卖中出价 BiSearch-ads,估算完第 i th 开发者的 app CTR Pi,会对 BiPi 值进行降序排序。让我们假设 B1P1 是拍卖中最高的,而 B2P2* 是第二高的值。具有与 B1P1* 匹配的 BP* 值的开发者是拍卖的获胜者。再者,他们的 app 显示为【u】的广告。如果【u】点击广告,拍卖的获胜者被收取价格金额,计算如下:**

机理分析

关于搜索广告的拍卖机制政策,让我们来看一下提议的机制。首先,该机制使用用户的直接反馈来估计点击率,点击率在确定广告的预期收入方面起着关键作用。毫无疑问,在这种设置中存在探索的成本,然而,该机制通过用户的反馈学会准确地估计点击率,从而在未来导致更好的广告分配。第二,该机制信任开发者——投标人,估计他们的 CTR 的上界置信区间。此外,它将获胜者的出价降低到他们可能出价但仍赢得拍卖的最小金额,并在点击发生时向他们收取该价值的费用——这类似于维克瑞(第二价格)拍卖背后的哲学。最后,该机制试图获得每个广告印象的最高预期收入。这三个分析与搜索广告三大政策是一致的。我鼓励读者进一步阅读[1]中介绍的拍卖机制,并仔细分析适用于搜索广告拍卖机制的差异和相似之处。

结论

在这篇文章中,我试图说明在应用商店中为搜索广告系统设计拍卖机制时的重要因素,并介绍了基于这些因素的拍卖机制。我希望读者会觉得这段经历有用。

参考

[1] Nikhil Devanur 和 Sham M. Kakade。点击付费拍卖的真实价格。在第十届 ACM 会议上。关于电子商务,第 99–106 页,2009 年。

设计 ML 产品的用户体验

原文:https://towardsdatascience.com/designing-the-user-experience-of-ml-products-8aef5afb510b?source=collection_archive---------24-----------------------

三个原则:期望、错误和信任!

之前,我谈到了管理机器学习(ML)产品的挑战,因为它涉及更多的实验、迭代,因此有更多的不确定性。作为一名项目经理,在决定前进的道路之前,您需要给工程师和数据科学家足够的空间和灵活性来探索。但是你也需要清晰地定义目标函数和鼓励团队尽早并经常进行测试,这样你就不会迷失方向。

[## 如何管理机器学习产品—第 1 部分

为什么管理机器学习产品这么难?为什么你应该关心?

towardsdatascience.com](/how-to-manage-machine-learning-products-part-1-386e7011258a)

当你为你的 ML 产品设计用户体验(UX)时,同样的挑战也适用。在过去的几个月里,我一直在与我们的 UX 团队合作,收集客户意见并改进我们产品的 UX。这里是我们学到的三个最重要的教训。

设定正确的期望值

机器学习模型的性能随着它们用更多的数据训练而提高。模特会不断提升自己,这很棒。但这也意味着他们的表现从第一天起就不会完美。

帮助用户理解机器学习产品的本质至关重要。更重要的是,我们需要与用户合作,事先就一套验收标准达成一致。只有当机器学习模型符合接受标准时,我们才会推出它们。

在设定验收标准时,您可以查看系统的基准性能或替代/现有解决方案的性能,例如人工或当前软件程序的性能。

有时,你可能有不止一个用户组,他们在利益上有冲突。或者您的用例要求特定区域的零错误。您可能还需要根据您的业务案例,在精度和召回之间做出权衡。

source: Bastiane Huang

对于用户需要模型从发布的第一天起就表现良好的情况。预先训练的模型可能是有用的。但是,即使有了预先训练的模型,边缘情况仍然会发生。您需要与用户一起工作,提出风险缓解计划:如果模型不起作用,备用计划是什么?如果用户想要装载新的项目或添加新的用例,重新训练模型需要多长时间?当不允许模型更新时,用户可以设置封锁期吗?

通过设定正确的用户期望,你不仅可以避免客户失望,还可以让客户高兴。亚马逊的智能音箱 Alexa 就是一个很好的例子。我们对类人机器人有很高的期望:我们希望它们像人类一样说话和行动。因此,当 Pepper 无法与我们进行明智的对话时,我们感到沮丧。相比之下,Alexa 被定位为降低客户期望的智能扬声器。当我们了解到它不仅仅可以演奏音乐时,我们很高兴。

透明度是增进沟通和信任的另一个重要因素。ML 比软件工程更具有概率性。因此,显示每个预测的置信水平是设定正确预期的一种方式。这也有助于用户理解算法是如何工作的,从而与用户建立信任。

建立信任

ML 算法通常缺乏透明度,就像一个黑匣子,接受输入(例如图像)并输出预测(例如图像中的物体/人是什么/谁)。这就是为什么向用户解释机器学习模型如何建立信任和获得认同至关重要。

如果做不到这一点,就会疏远用户。例如,优步的司机报告说他们感觉失去了人性,他们质疑算法的公平性,尤其是当他们在没有明确解释的情况下受到处罚的时候。这些司机觉得应用程序对他们了解很多,但他们对算法如何工作和做出决策却知之甚少。

另一方面,亚马逊的网页告诉我们他们为什么推荐这些书。只是简单的一行解释。但它有助于用户理解算法是如何工作的,因此用户可以更好地信任系统。

同一个优步司机研究还发现,司机们觉得他们不断被监视,但他们不知道这些数据将被用于什么目的。除了遵守 GDPR 或其他数据保护法规之外,还要让用户容易知道他们的数据是如何被管理的。

优雅地处理错误

“…但也有未知的未知——我们不知道我们不知道的……后一类往往是困难的。”——唐纳德·拉姆斯菲尔德

当你在设计系统时,通常很难预测系统会如何出错。这就是为什么用户测试和质量保证对于识别失败状态和边缘情况是极其重要的。在实验室和现场进行广泛的测试有助于最大限度地减少这些错误。

同样重要的是对错误进行分类,并根据它们的严重程度和频率进行处理。存在需要通知用户并要求立即采取措施的致命错误。但是也有一些小错误并不会真正影响系统的整体运行。如果你把每一个小错误都通知给用户,那将会非常具有破坏性。如果不立即解决致命错误,这可能是灾难性的。

您也可以将错误视为用户期望和系统假设之间的意外交互:

用户错误一般由系统设计者在用户“误用”系统导致错误时定义。

系统错误发生在系统不能提供用户期望的正确答案的时候。它们往往是系统固有的局限性造成的。

当系统按预期工作,但用户察觉到错误时,就会发生上下文错误。这通常是因为我们设计系统的假设是错误的。

例如,如果用户一直拒绝来自某个应用程序的建议,产品团队可能想要看一看并了解原因。例如,应用程序可能会根据用户的信用卡信息错误地假设用户住在亚洲。在这种情况下,也许用户的实际位置数据将是做出这种建议的更好的数据点。

最棘手的错误是未知的未知:系统检测不到的错误。解决这个问题的一个方法是回到数据中,分析不寻常的模式,比如我们刚刚谈到的持续拒绝。

另一种方法是允许用户提供反馈:方便用户随时随地提供他们想要的反馈。让用户帮你发现未知的未知。您还可以利用用户反馈来改进您的系统。比如说。Youtube 允许用户告诉系统他们不想看到某些推荐。它还利用这一点来收集更多的数据,使他们的建议更加个性化和准确。

将你的机器学习模型预测框定为建议也是管理用户预期的一种方式。你可以给用户选项来选择,而不是命令用户应该做什么。但是请注意,如果您的用户没有足够的信息来做出正确的决定,这就不适用。

我们在之前谈到的许多一般原则在这里仍然适用。你可以在我之前的文章中找到更多的细节。

[## 如何管理机器学习产品——第二部分

最佳实践和我一路走来学到的东西。

towardsdatascience.com](/how-to-manage-machine-learning-products-part-ii-3bdabf91eae4)

  • 很好地定义问题,并尽早和经常地进行测试:如果你听到有人说“让我们构建模型,看看它能做什么”,要小心了。
  • 知道什么时候应该或者不应该使用 ML。
  • 从第一天开始就考虑你的数据策略。
  • 构建 ML 产品是跨学科的。超越 ML 思考。

C 想看更多这样的文章就点这里吧!

Bastiane Huang 是 OSARO 的产品经理,OSARO 是一家总部位于旧金山的初创公司,致力于开发软件定义的机器人技术。她曾在亚马逊的 Alexa 小组和哈佛商业评论以及该大学的未来工作倡议中工作。她写关于人工智能、机器人和产品管理的文章。跟着她到这里 。

本帖已在www.productschool.com社区发布。

设计你的神经网络

原文:https://towardsdatascience.com/designing-your-neural-networks-a5e4617027ed?source=collection_archive---------3-----------------------

逐步演练

训练神经网络可能会非常混乱!

什么是好的学习率?你的网络应该有多少隐藏层?退学其实有用吗?为什么你的渐变消失了?

在这篇文章中,我们将揭开神经网络的一些更令人困惑的方面,并帮助你对你的神经网络架构做出明智的决定。

我强烈推荐分叉 这个内核 并且玩不同的积木来磨练你的直觉。

如果你有任何问题,随时给我发信息。祝你好运!

1.基本神经网络结构

输入神经元

  • 这是你的神经网络用来进行预测的特征数量。
  • 输入向量的每个特征需要一个输入神经元。对于表格数据,这是数据集中相关要素的数量。您需要仔细选择这些特征,并删除任何可能包含无法超出训练集(并导致过度拟合)的模式的特征。对于图像,这是你的图像的尺寸(MNIST 的尺寸是 28*28=784)。

输出神经元

  • 这是你想做的预测的数量。
  • 回归:对于回归任务,可以是一个值(如房价)。对于多变量回归,每个预测值对应一个神经元(例如,对于边界框,可以是 4 个神经元,每个神经元对应边界框的高度、宽度、x 坐标和 y 坐标)。
  • 分类:对于二元分类(垃圾邮件-非垃圾邮件),我们对每个肯定类别使用一个输出神经元,其中输出表示肯定类别的概率。用于多类分类(例如,在对象检测中,实例可以被分类为汽车、狗、房子等。),我们每个类有一个输出神经元,并在输出层使用soft max activation函数来确保最终概率总和为 1。

隐藏层和每个隐藏层的神经元

  • 隐藏层的数量高度依赖于问题和你的神经网络的结构。你实际上是在尝试进入完美的神经网络架构——不要太大,不要太小,刚刚好。
  • 一般来说,1-5 个隐藏层可以很好地解决大多数问题。当处理图像或语音数据时,您可能希望您的网络有几十到几百个层,但并非所有层都是完全连接的。对于这些用例,有预先训练好的模型(【YOLO】【ResNet】【VGG】),允许你使用它们网络的大部分,在这些网络之上训练你的模型,只学习高阶特征。在这种情况下,您的模型仍然只有几层需要训练。
  • 一般来说,对所有隐藏层使用相同数量的神经元就足够了。对于某些数据集,拥有一个较大的第一层并随后拥有较小的层将会带来更好的性能,因为第一层可以学习许多较低级别的要素,这些要素可以输入到后续层中的一些较高级别的要素中。

  • 通常,添加更多的层比在每层中添加更多的神经元会获得更大的性能提升。
  • 我建议从 1-5 层和 1-100 个神经元开始,慢慢增加更多的层和神经元,直到你开始适应过度。您可以在您的 权重和偏差 仪表板中跟踪您的损失和准确性,以查看哪个隐藏层+隐藏神经元组合导致最佳损失。
  • 选择较小数量的层/神经元时要记住的一点是,如果这个数量太小,您的网络将无法学习数据中的潜在模式,因此是无用的。抵消这一点的方法是从大量的隐藏层+隐藏神经元开始,然后使用放弃和早期停止让神经网络为你缩小自己的规模。同样,我建议尝试一些组合,并在您的 权重和偏好 仪表板中跟踪性能,以确定针对您的问题的完美网络规模。
  • 安德烈·卡帕西还推荐了 过度拟合然后正则化的方法——“首先获得一个足够大的模型,它可以过度拟合(即专注于训练损失),然后适当地正则化它(放弃一些训练损失,以改善验证损失)。”

损失函数

  • 回归:均方差是最常见的优化损失函数,除非有大量异常值。在这种情况下,使用平均绝对误差或胡贝尔损失或。
  • 分类: 交叉熵 在大多数情况下都会很好的为你服务。

批量大小

  • 大批量可以很好,因为它们可以利用 GPU 的能力,每次处理更多的训练实例。 OpenAI 已经发现 更大的批量(对于 图像分类语言建模 为数万,对于 RL 代理 为数百万)很好地服务于缩放和并行化。
  • 然而,小批量也是有道理的。根据 Masters 和 Luschi 的本文 中的 所述,通过运行大批量而增加的并行性所获得的优势被较小批量所实现的更高的性能概括和更小的内存占用所抵消。他们表明,增加批量大小会降低提供稳定收敛的学习速率的可接受范围。他们的观点是,事实上,越小越好;并且最佳性能是由 2 到 32 之间的小批量获得的。
  • 如果您没有大规模操作,我建议您从较低的批量开始,慢慢增加规模,并在您的 重量和偏差 仪表板中监控性能,以确定最合适的。

历元数

  • 我建议从大量的历元开始,并使用早期停止(参见第 4 节)。消失+爆炸梯度)以在表现停止改善时停止训练。

缩放您的特征

  • 简要说明:在将所有特征用作神经网络的输入之前,请确保它们具有相似的比例。这确保了更快的收敛。当您的要素具有不同的比例时(例如,以千为单位的工资和以十为单位的经验年数),成本函数将看起来像左边拉长的碗。这意味着与使用归一化要素(右侧)相比,您的优化算法将需要很长时间来遍历山谷。

2.学习率

  • 选择学习速度是非常重要的,你要确保你得到这个权利!理想情况下,当你调整网络的其他超参数时,你需要重新调整学习率。
  • 要找到最佳学习率,从一个非常低的值(10^-6)开始,然后慢慢乘以一个常数,直到达到一个非常高的值(如 10)。在你的权重和偏差仪表盘中测量你的模型表现(相对于你的学习率的对数),以确定哪个学习率对你的问题最有效。然后,您可以使用这个最佳学习率来重新训练您的模型。
  • 最佳学习速率通常是导致模型发散的学习速率的一半。在附带的代码中随意为 learn_rate 设置不同的值,并查看它如何影响模型性能,以发展您对学习率的直觉。
  • 我还推荐使用莱斯利·史密斯提出的 学习率查找器 方法。对于大多数梯度优化器(SGD 的大多数变体)来说,这是找到一个好的学习率的极好方法,并且适用于大多数网络架构。
  • 此外,请参见下面的学习率计划部分。

3.动力

  • 梯度下降 朝着局部最小值采取微小的、一致的步骤,当梯度很小时,可能需要很长时间才能收敛。另一方面,动量考虑了先前的梯度,并通过更快地越过山谷和避免局部最小值来加速收敛。
  • 一般来说,你希望你的动量值非常接近 1。对于较小的数据集,0.9 是一个很好的起点,随着数据集变得越来越大,您可能希望逐渐向 1(0.999)靠拢。(设置 nesterov=True 让 momentum 在当前点之前几个步骤考虑成本函数的梯度,这使它稍微更准确和更快。)

4.消失+爆炸渐变

  • 就像人一样,不是所有的神经网络层都以相同的速度学习。因此,当反向投影算法将误差梯度从输出层传播到第一层时,梯度变得越来越小,直到它们到达第一层时几乎可以忽略不计。这意味着第一层的权重在每一步都不会显著更新。
  • 这就是 消失渐变 的问题。(当某些层的梯度逐渐变大时,会出现类似的爆炸梯度问题,导致一些层的权重相对于其他层发生大规模更新。)
  • 有几种方法可以抵消消失渐变。现在就让我们来看看它们吧!

激活功能

隐藏层激活 一般来说,使用不同 激活函数 的性能按此顺序提高(从最低→最高性能):逻辑→ tanh → ReLU →泄漏 ReLU → ELU → SELU。

ReLU 是最流行的激活功能,如果你不想调整你的激活功能,ReLU 是一个很好的起点。但是,请记住,与 eLU 的或葛鲁的相比,热卢的效果越来越差。****

如果你更喜欢冒险,你可以尝试以下方法:

  • 对抗神经网络过拟合:RReLU
  • 减少运行时的延迟:泄漏 ReLU
  • 对于大规模训练集:PReLU
  • 对于快速推理时间:漏 ReLU
  • 如果你的网络不能自我正常化:ELU
  • 对于整体鲁棒的激活函数:SELU

一如既往,不要害怕尝试一些不同的激活功能,转向您的 权重和偏好 仪表盘,帮助您选择最适合您的功能!

这篇 是一篇优秀的论文,深入比较了神经网络的各种激活函数。

输出层激活
回归:
回归问题不需要针对其输出神经元的激活函数,因为我们希望输出呈现任何值。在我们希望 out 值被限制在某个范围内的情况下,我们可以对-1→1 值使用 tanh,对 0→1 值使用逻辑函数。在我们只寻求正输出的情况下,我们可以使用 softplus 激活。

分类:使用 sigmoid 激活函数进行二进制分类,确保输出在 0 和 1 之间。使用 softmax 进行多类分类,以确保输出概率总和为 1。

权重初始化方法

  • 正确的权重初始化方法可以大大加快收敛时间。初始化方法的选择取决于激活函数。一些可以尝试的事情:
  • 当使用 ReLU 或漏 RELU 时,使用 He 初始化
  • 当使用 SELU 或 ELU 时,使用 LeCun 初始化
  • 当使用 softmax、logistic 或 tanh 时,使用 Glorot 初始化
  • 大多数初始化方法都是统一的和正态分布的。

批次号

  • BatchNorm 只是学习每一层输入的最佳方法和规模。它通过对其输入向量进行零居中和归一化,然后对其进行缩放和移位来实现这一点。它也像一个正则化,这意味着我们不需要辍学或 L2 注册。
  • 使用 BatchNorm 可以让我们使用更大的学习速率(这将导致更快的收敛),并通过减少消失梯度问题在大多数神经网络中带来巨大的改进。唯一的缺点是它稍微增加了训练时间,因为每一层都需要额外的计算。

渐变裁剪

  • 减少渐变爆炸的一个很好的方法,尤其是在训练 rnn 的时候,就是在它们超过某个值的时候简单地修剪它们。我建议尝试 clipnorm 而不是 clipvalue,这样可以保持渐变矢量的方向一致。Clipnorm 包含 l2 范数大于某个阈值的任何梯度。
  • 尝试几种不同的阈值,找到最适合您的阈值。

提前停止

  • 早期停止让您可以通过训练具有更多隐藏层、隐藏神经元和比您需要的更多时期的模型来体验它,并且当性能连续 n 个时期停止改善时停止训练。它还会为您保存性能最佳的型号。您可以通过在适合您的模型时设置回调并设置 save_best_only=True 来启用提前停止。

5.拒绝传统社会的人

  • Dropout 是一种奇妙的正则化技术,它为您提供了一个巨大的性能提升(对于最先进的模型来说,性能提升约 2%),因为该技术实际上非常简单。dropout 所做的只是在每一层、每一步训练中随机关闭一定比例的神经元。这使得网络更加健壮,因为它不能依赖任何特定的输入神经元来进行预测。知识分布在整个网络中。在 2^n 周围(其中 n 是架构中神经元的数量),在训练过程中会生成略微独特的神经网络,并将其集合在一起进行预测。
  • 好的辍学率在 0.1 到 0.5 之间;RNNs 为 0.3,CNN 为 0.5。对较大的图层使用较大的速率。增加退出率会减少过度拟合,而降低退出率有助于克服欠拟合。
  • 您希望在网络的早期层中试验不同的辍学率值,并检查您的 权重和偏差 仪表板,以选择表现最佳的一个。您肯定不想在输出图层中使用 dropout。
  • 在与 BatchNorm 一起使用 Dropout 之前,请先阅读 本文
  • 在这个内核中,我使用了 AlphaDropout,这是一种香草味的 Dropout,通过保留输入的均值和标准差,它与 SELU 激活函数配合得很好。

6.优化者

  • 梯度下降不是唯一的优化游戏!有几种不同的可供选择。 这篇文章 很好地描述了一些你可以选择的优化器。

  • 我的一般建议是,如果你非常关心收敛的质量,并且时间不是最重要的,那么就使用随机梯度下降。
  • 如果您关心收敛时间,接近最佳收敛点就足够了,请尝试 Adam、Nadam、RMSProp 和 Adamax 优化器。您的 权重和偏好 仪表盘将引导您找到最适合您的优化器!
  • Adam/Nadam 通常是很好的起点,并且往往对糟糕的后期学习和其他非最佳超参数相当宽容。
  • 根据安德烈·卡帕西 的说法,在 ConvNets 的情况下,“一个调优的 SGD 几乎总是略胜亚当一筹”。
  • 在这个内核中,我从 Nadam 获得了最好的性能,它只是一个常规的带有内斯特罗夫技巧的 adam 优化器,因此比 Adam 收敛得更快。

7.学习率调度

  • 我们已经讨论了良好学习率的重要性——我们不希望它太高,以免成本函数在最佳值附近波动并发散。我们也不希望它太低,因为这意味着收敛将需要很长时间。
  • 照看学习率可能很困难,因为较高和较低的学习率都有其优势。好消息是我们不必承诺一个学习率!通过学习速率调度,我们可以从较高的速率开始,以更快的速度通过梯度斜坡,并在到达超参数空间中的梯度谷时减慢速度,这需要采取较小的步骤。
  • 有许多方法可以安排学习率,包括指数降低学习率,或者使用阶跃函数,或者在性能开始下降时调整学习率,或者使用 1 周期安排。在这个内核中,我将向您展示如何使用 ReduceLROnPlateau 回调函数,在 n 个时期内性能下降时以一个常数因子降低学习率。
  • 我强烈建议您也尝试一下 1 周期计划。
  • 使用恒定的学习速率,直到你训练完所有其他的超参数。最后实现学习率衰减调度。
  • 与大多数事情一样,我建议用不同的调度策略进行一些不同的实验,并使用你的 权重和偏好 仪表板来挑选出一个最佳模型。

8.还有几件事

  • 尝试 EfficientNets 以最佳方式扩展您的网络。
  • 阅读 本文 了解一些额外的学习率、批量大小、动量和重量衰减技术的概述。
  • 还有 这个 上的随机加权平均(SWA)。它表明,可以通过沿 SGD 的轨迹对多个点进行平均,以循环或恒定的学习速率来实现更好的泛化。
  • 阅读安德烈·卡帕西的 优秀指南 ,让你的神经网络发挥最大效用。

结果

在这篇文章中,我们已经探索了神经网络的许多不同方面!

我们已经了解了如何建立一个基本的神经网络(包括选择隐藏层数、隐藏神经元、批量大小等)。)

我们已经了解了动量和学习率在影响模型性能中的作用。

最后,我们探讨了渐变消失的问题,以及如何使用非饱和激活函数、批处理、更好的权重初始化技术和早期停止来解决这个问题。

通过访问您的 权重和偏差 仪表盘,您可以在一个图表中比较我们尝试的各种技术的准确性和损失性能。

神经网络是强大的野兽,它给你很多杠杆来调整,以获得你试图解决的问题的最佳性能!他们提供的定制的庞大规模甚至会让经验丰富的从业者不知所措。像 权重和偏差 这样的工具是你在超参数领域导航、尝试不同实验和挑选最强大模型的最好朋友。

我希望这本指南能成为你冒险的良好开端。祝你好运!我强烈推荐分叉 这个内核 并尝试不同的构建模块来磨练你的直觉。

如有任何问题或反馈,欢迎随时 推特我

四种主要慢性病和过早死亡

原文:https://towardsdatascience.com/detailed-findings-of-4-groups-of-major-chronic-disease-indicators-53fdeb487155?source=collection_archive---------28-----------------------

详细分析人口健康指标、健康的社会决定因素以及对性别和种族的影响

Photo by CMDR Shane on Unsplash

在我们的 CDC 慢性病指标数据集的第 2 部分中,我们的分析揭示了几个具有高度相关的相互关系的领域——心血管疾病、慢性肾病、糖尿病中的指标,以及总体条件“社会决定因素”类别中的选择指标。虽然在癌症和慢性阻塞性肺病等其他领域也有高度相关的关系,但在最后这篇博文中,我们将主要关注前者。

上一篇文章中的图 1 显示了所有指标之间的关系,而上一篇文章中的表 5 显示了许多顶级相关对。通过按特定主题查看指标的重复出现模式,我们可以缩小感兴趣主题的范围。之前使用的相同代码用于构建以下六幅图中的相关性热图(红色—相关性更高):

Correlation Heatmap by Topic Pairs (from top left to bottom right): 1) Chronic Kidney (CKD) and Cardiovascular (CVD), 2) CKD and Diabetes (DIA), 3) CKD and Overarching Conditions (OVC), 4) CVD and DIA, 5) CVD and OVC, and 6) DIA and OVC. Red/pink indicates higher positive correlation while green indicates higher negative correlation. See Figures 1 to 6 below for in depth views and descriptions.

下面,我们将一对一对地浏览每个关联热图。在第 6 部分的末尾,将会有一个实际问题和问题 ID (QIDs)的参考。如果这有助于理解主要的具体指标问题,请随意跳过。

详细调查结果汇总:

当我们按主题深入到每个高度相关的人群健康慢性病指标时,现在通过代表个体指标的个体问题 ID 对,相互关联的慢性病的主题得到加强。糖尿病、心血管疾病和慢性肾脏疾病之间的共病模式显示在一般指标和一些更具体的指标中。例如,一般指标是宽泛的指标,似乎涵盖了总体情况,如 DIA1_2“作为任何列出的死亡原因报告的糖尿病死亡率”这些具有高度正相关性的高水平指标也必然会导致更离散的死亡率结果,这虽然显而易见,但对个人采取可操作的下一步措施的能力提出了质疑。相反,它意味着实用路线强调预防是人口健康的一个关键方法。

有趣的是,各种总体状况(OVC)指标不断出现,如 ov C5 _ 0“45-64 岁成年人的过早死亡率”我们看到 OVC5_0 与所有前 5 名心血管疾病指标、前 3 名慢性肾病指标和前 4 名糖尿病指标配对。这种关系倾向于说明这三个相关问题的共病和 45-64 岁成年人的过早死亡率。

请看下面两人的发现,或者跳到下面两个部分,我们转而分析性别和种族的分层,以及相应的可视化。

1。慢性肾脏疾病和心血管疾病

Figure 1. Correlation Heatmap for Chronic Kidney Disease and Cardiovascular Disease

Table 1. Top Correlation of Chronic Kidney Disease and Cardiovascular Disease, descending

top_corr_pair[(top_corr_pair['Topic1'] == ('CKD')) & (top_corr_pair['Topic2'] == ('CVD'))].head()

慢性肾病指标 CKD1_0 代表“终末期肾病死亡率”在心血管疾病方面,CVD1_1 至 CVD1_5 分别是“总心血管疾病死亡率”、“心脏病死亡率”、“冠心病死亡率”、“心力衰竭死亡率”和“脑血管疾病(中风)死亡率”。

2。慢性肾病和糖尿病(CKD x DIA)

Figure 2. Correlation Heatmap for Chronic Kidney Disease and Diabetes

Table 2. Top Correlation of Chronic Kidney Disease and Diabetes, descending

慢性肾病指标 CKD2_1 和 CKD2_2 分别是“治疗的终末期肾病的发病率”和“归因于糖尿病的治疗的终末期肾病的发病率”。在糖尿病方面,DIA1_1 和 DIA1_2 分别是“作为任何列出的死亡原因报告的糖尿病死亡率”和“作为任何列出的死亡原因报告的糖尿病酮症酸中毒死亡率”。DIA9_0 是“以糖尿病为列明诊断的住院治疗”DIA4_0 是“由于糖尿病导致的下肢截肢”

3。慢性肾病和总体状况(慢性肾病 x OVC)

Figure 3. Correlation Heatmap for Chronic Kidney Disease and Overarching Conditions

Table 3. Top Correlation of Chronic Kidney Disease and Overarching Conditions, descending

总体状况指标 OVC5_0 和 OVC6_1 分别是“45-64 岁成年人的过早死亡率”和“18 岁以上成年人的一般或较差自测健康状况”。这些指标与相同的糖尿病指标 DIA1_1、DIA1_2、DIA4_0 和 DIA9_0 高度相关。此外,我们看到 dia 2 _ 1“18-24 岁成年人的高中毕业率”和 OVC6_1 与那些自我评估健康状况一般或较差的人之间存在相对较高的相关性。

4。心血管疾病和糖尿病

Figure 4. Correlation Heatmap for Cardiovascular Disease and Diabetes

Table 4. Top Correlation of Cardiovascular Disease and Diabetes, descending

当比较心血管和糖尿病指标时,最相关的指标从 DIA1_1 开始,dia 1 _ 1 是任何糖尿病死亡率的一般问卷,并且在诊断中还包括 DIA9_0 糖尿病住院。相关的心血管指标包括 CVD1_4(心力衰竭)、CVD3_1(住院治疗)、CVD1_5(中风死亡率)、CVD1_1(心血管总死亡率)和 CVD1_2(心脏病死亡率)。

5。心血管疾病和总体状况(CVD x OVC)

Figure 5. Correlation Heatmap for Cardiovascular Disease and Overarching Conditions

Table 5. Top Correlation of Cardiovascular Disease and Overarching Conditions, descending

当比较高度相关的心血管疾病和总体状况指标 ov C5 _ 0“45-64 岁成人的过早死亡率”时,最相关的指标属于 CVD1_X 问题 id(qid 1)组,范围从心脏病到中风。

6。糖尿病和总体状况(直径 x OVC)

Figure 6. Correlation Heatmap for Diabetes and Overarching Conditions

Table 6. Top Correlation of Diabetes and Overarching Conditions, descending

总体状况指标 OVC5_0 和 OVC6_1 分别是“45-64 岁成年人的过早死亡率”和“18 岁以上成年人的一般或较差自测健康状况”。这些指标与相同的糖尿病指标 DIA1_1、DIA1_2、DIA4_0 和 DIA9_0 高度相关。此外,我们看到 dia 2 _ 1“18-24 岁成年人的高中毕业率”和 OVC6_1 与那些自我评估健康状况一般或较差的人之间存在相对较高的相关性。

问题标识代码参考

由于图/表 1 至 6 显示或列出了这些关系,再次查看问题 id(qid 1/qid 2)的相应问题将有助于更好地理解具体指标。在 df_new 数据帧上使用 groupby()方法,然后。loc[]拉出各自的主题,我可以查看一个问题列表和问题。

df_new_QTQLY = df_new[['QuestionID','Topic','Question','LocationAbbr','YearStart']].groupby(['Topic','QuestionID','Question']).count()df_new_QTQLY.loc['Cardiovascular Disease']

Table 7a. QuestionID for Chronic Kidney Disease Indicators

Table 7b. QuestionID for Cardiovascular Disease Indicators

Table 7c. QuestionID for Overarching Condition Indicators

Table 7d. QuestionID for Diabetes Indicators

成人过早死亡分层分析—性别

由于 OVC5_0 指标“45-64 岁成年人的过早死亡率”反复出现,让我们通过性别和种族的分层来看看这个指标能告诉我们什么。我们将根据以下参数基于 df_new 创建 df_new_OVC5_0_gender 数据帧:

df_new_OVC5_0_gender = df_new[ (df_new['QuestionID'] == 'OVC5_0') & (df_new['StratificationCategory1'] == 'Gender') & 
(df_new['DataValueUnit'] == 'cases per 100,000')]df_new_OVC5_0_gender.info()

在上面的数据框架中,df_new['QuestionID'] == 'OVC5_0 '获取与我们的特定指标相关的数据子集。然而,这包括种族和性别的分层。要看性别分层,包括 df _ new[' strategification category 1 ']= ' Gender '。剩余的数据帧在数据值类型中显示为包括“数字”或“年龄调整率”“数字”代表了一个粗略的比率,即“一个社区健康结果的总负担”“年龄调整率”用于在年龄、性别或种族等群体之间进行更公平的比较。(更详细的解释在这里)。似乎当 DataValueType = '年龄调整率,' DataValueUnit = '每 100,000 个案例'时,我包含了 df_new['DataValueUnit'] = '每 100,000 个案例'该计数显示 OVC 主题和分层类别 1 没有像预期的完整数据集那样填充:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 1020 entries, 268047 to 403039
Data columns (total 16 columns):
YearStart                    1020 non-null int64
LocationAbbr                 1020 non-null object
Topic                        1020 non-null object
Question                     1020 non-null object
DataValueUnit                1020 non-null object
DataValueType                1020 non-null object
DataValueAlt                 1020 non-null float64
StratificationCategory1      1020 non-null object
Stratification1              1020 non-null object
LocationID                   1020 non-null int64
TopicID                      1020 non-null object
QuestionID                   1020 non-null object
DataValueTypeID              1020 non-null object
StratificationCategoryID1    1020 non-null object
StratificationID1            1020 non-null object
QuestionAbbr                 1020 non-null object
dtypes: float64(1), int64(2), object(13)df_new_OVC5_0_gender.head()

Table 8a. Stratification by Gender Dataframe

使用 groupby 汇总,我们看到可用数据运行了 5 年,而不是整个数据集的整个 15 年。下面还将绘制出趋势图和一个 seaborn 柱状图。

df_new_OVC5_0_gender1 = df_new_OVC5_0_gender.groupby(['Stratification1','YearStart'])
df_new_OVC5_0_gender1.mean().drop('LocationID',axis=1).round()plt.figure(figsize=(16, 6))
sns.barplot(x='YearStart',y='DataValueAlt',data=df_new_OVC5_0_gender,hue='Stratification1',ci=None,saturation=0.7)

Table 8b. Groupby on the Stratification Gender dataset

Figure 8. 2010–2014 Trends on Premature Mortality by Gender, per 100K cases

2010 年至 2014 年期间,数据显示,45-64 岁人口的过早死亡率逐年略有上升。女性人口过早死亡率上升了 5.4%,男性人口过早死亡率上升了 3.4%。纵轴对应于以 100K 为单位的 DataValueAlt。例如,2014 年女性有 48.5 万例(38%),而同年男性有 78.4 万例(62%)。令人惊讶的是,我预计男性的过早死亡率会比女性增长得更快。

虽然相关对给出了总体情况,但让我们以与相关对相同的方式比较男性和女性人口之间的指标。在最初的 df_new['QuestionID']中,整个数据集中有 201 个唯一的指标。由于我们关注的是年龄调整组,我们的 df_new_gender2['QuestionID']显示有 13 个独特的指标。牢记这一点,以下分析显示了指标的子集。我们将开始为下面的性别和潜在位置分析修改数据帧 df_new_gender,从而删除几个对此没有用的列。

df_new_gender2 = df_new_gender.drop(columns=['Question','Topic','DataValueUnit','DataValueType','StratificationCategory1','TopicID','DataValueTypeID','StratificationCategoryID1','StratificationID1','QuestionAbbr'])
df_new_gender2.head()

Table 9a. Working Dataframe with Stratification1 (Gender) and Location

为了创建一个表来可视化性别相关对,让我们使用表 9a 并应用 pivot_table 方法。让我们创建一个名为 df_new_gender2_loc_qid 的数据帧,其中行代表每个位置,列代表每个指示器。因为我们想按性别查看数据(分层 1),所以每个位置需要有一个标签为男性或女性的列。此外,由于我们按位置查看每一行,因此将每个指标的 DataValueAlt 值汇总为平均值是有意义的,因此我们将把参数 aggfunc=np.mean 传入 pivot_table。

创建这个数据透视表时,我遇到了 LocationIDs 或 QuestionIDs 没有数据的问题,导致 NA 值。当这种情况发生时,我们可以通过删除所有具有 NA 值的行和/或列来评估是否只保留具有值的行/列。当我这样做时,产生的数据帧被大大缩减了。相反,通过使用。使用 df_new_gender_loc_qid.mean()使用平均值填充 na(),NA 值将替换为平均值。表 9b 是调整后的数据透视表的前 5 行。

df_new_gender2_loc_qid = df_new_gender2.pivot_table(values='DataValueAlt',index=['LocationID','Stratification1'],columns=['QuestionID'],aggfunc=np.mean)
# Create pivot table with rows by Location, columns of each QuestionID, values - DataValueAlt mean by Locationdf_new_gender2_loc_qid.reset_index(level='Stratification1',inplace=True)
df_new_gender2_loc_qid.fillna(df_new_gender2_loc_qid.mean(),inplace=True)
df_new_gender2_loc_qid.head()

Table 9b. Pivot Table by Location and Gender Across 13 Indicators (QuestionIDs)

使用 df_new_gender2_loc_qid 上的 seaborn pairplot,hue 参数允许我们按性别渲染绘图。类似于来自第二部分博客的图 1 ,我们有一个沿着相同 X 和 Y 轴的 13 个指标的图表。我们使用的不是相关性,而是按性别和状态(LocationID)划分的 DataValueAlt 中这 13 个指标的平均值:ALC6_0(酒精:慢性肝病死亡率)、CKD1_0(慢性肾病:终末期肾病死亡率)、2 个慢性阻塞性肺病(COPD)、5 个心血管疾病(CVD)、2 个糖尿病(DIA)、OLD1_0 和 OVC5_0(总体情况:45-64 岁的过早死亡率)。在前面的章节中,OVC5_0 是一个高度相关的指标。

sns.pairplot(df_new_gender2_loc_qid,hue='Stratification1',palette='RdBu_r')

Figure 9. Pairplot Across 13 Indicators Comparing Gender (Blue — Female, Orange — Male)

如上文图 9 所述,OVC5_0 是 45-64 岁人群的过早死亡率指标。沿着图 9 的底行,配对图通常显示雄性(橙色)和雌性(蓝色)种群之间的明显分布。在几乎所有情况下,当我们沿着底部行比较每个图(OVC5_0 与其他指标)时,我们看到大多数位置的男性人口具有较高的平均数据值 Alt 值,这反映了各州男性人口健康状况普遍较差。

成人过早死亡分层分析—种族

与按性别分层相似,按种族分层的分析将使用以下条件过滤数据。我们将基于 OVC5_0 创建一个新的数据框架 df_new_OVC5_0_race,使用“每 100,000 人中的病例数”和“种族/民族”的分层类别 1 基于年龄的患病率

df_new_OVC5_0_race = df_new[ (df_new['QuestionID'] == 'OVC5_0') & (df_new['DataValueUnit'] == 'cases per 100,000') &(df_new['StratificationCategory1'] == 'Race/Ethnicity')]df_new_OVC5_0_race1 = df_new_OVC5_0_race.groupby(['Stratification1','YearStart']).mean().round(0)
df_new_OVC5_0_race1

Table 10. Stratification by Race with Average DataValueAlt Values

此外,我们将使用。groupby()方法根据种族、年份和数据值 Alt 将子集数据帧 df_new_OVC5_0_race 汇总到一个表中。《分层》中的种族类别给了我们 5 个类别:美洲印第安人或阿拉斯加土著人;亚洲人或太平洋岛民;黑人,非西班牙裔;西班牙裔;白人,非西班牙裔。对于 YearStart,我们有 5 年的数据,因为这是可用的分层数据和使用基于年龄的患病率的结果。DataValueAlt 是位置的平均值,四舍五入为整数。例如,2010 年,西班牙裔人口中每 10 万人中有 348 名 45-64 岁的人过早死亡。

为了可视化表 10,seaborn barplot 将显示每个种族分层和 DataValueAlt 的值。条形图的参数包括从 data=df_new_OVC5_0_race 传递 x=YearStart、y=DataValueAlt 和 hue = Stratification1。使用 plt.legend(),我们能够微调图例的渲染位置,我更喜欢使用 bbox_to_anchor 参数的外部绘图。

plt.figure(figsize=(16, 7))
sns.barplot(x='YearStart',y='DataValueAlt',data=df_new_OVC5_0_race,hue='Stratification1',ci=None,saturation=0.7)
plt.legend(loc='best',bbox_to_anchor=(0.5, 0,.73, .73))

Figure 10. 2010–2014 Premature Mortality Trends Across Race Stratification

从表 10 和图 10 可以看出,数据显示,过早死亡率逐年略有上升。45-64 岁成年人的过早死亡对“黑人、非西班牙裔”和“美国印第安人或阿拉斯加土著”人口的影响最为严重。另一方面,我们认为“亚洲人或太平洋岛民”和“西班牙人”是最不严重的。相比之下,我们看到“黑人,非西班牙裔”人口的过早死亡率是“西班牙裔”人口的两倍多。

虽然可以假设每一层的过早死亡率之间的相关性,但将描述性因素与因果关系联系起来超出了该数据集的范围。图 10 给出了对影响总体人口的因素的严重性的总体理解,这些因素可能是复杂的和多方面的。

观察种族分层的另一种方式是通过堆积条形图。同样,具有来自 df_new_OVC5_0_race 的相同数据的 pivot_table()是条形图的起点,如表 11 所示。

df_new_OVC5_0_race2 = df_new_OVC5_0_race.pivot_table(values='DataValueAlt',index='YearStart',columns='Stratification1').round()
df_new_OVC5_0_race2 

Table 11. Stratification by Race and Year

基于表 11,我们希望创建累积值的列,而不是每个分层的特定值。我将修改 df_new_OVC5_0_race2,将后续列的值更新为前面列的总和。例如,“亚裔或太平洋岛民”列中的值将是美洲印第安人或阿拉斯加土著人与亚裔或太平洋岛民的总和。对接下来的三列重复此操作。通过删除列以保留新的累积列并重置索引的一些额外调整,新的数据帧 df_new_OVC5_0_race2c 可用于以下柱状图。

sns.set_style('darkgrid')
plt.figure(figsize=(8, 8))
sns.barplot(x='YearStart', y='cum_White', data=df_new_OVC5_0_race2c, color='blue',ci=None,saturation=0.7)
sns.barplot(x='YearStart', y='cum_Hispanic', data=df_new_OVC5_0_race2c, color='purple',ci=None,saturation=0.7)
sns.barplot(x='YearStart', y='cum_Black', data=df_new_OVC5_0_race2c, color='red',ci=None,saturation=0.7)
sns.barplot(x='YearStart', y='cum_Asian', data=df_new_OVC5_0_race2c, color='green',ci=None,saturation=0.7)
sns.barplot(x='YearStart', y='cum_AmIndianAK', data=df_new_OVC5_0_race2c, color='orange',ci=None,saturation=0.7)

Figure 11. Stacked Bar Chart of Stratification by Race and Year

由于每个种族分层的年与年之间的变化没有显著的不同,所以条形基本上是相似的。然而,这个柱状图提供了从 2010 年到 2014 年整体过早死亡率增长的另一个视角。该图表还显示了不同种族中过早死亡的比例。色调的颜色使用与图 10 中相同的图例:蓝色(白色,非西班牙裔)、紫色(西班牙裔)、红色(非西班牙裔黑人)、绿色(亚太岛民)和黄色/橙色(美洲印第安人或阿拉斯加土著)。

我希望你喜欢阅读美国疾病预防控制中心的美国慢性指标人群数据集。这就结束了我们的系列。关注我,了解更多数字健康数据科学相关主题。随时提出任何想法或建议!

一步一步:构建您的自定义实时对象检测器

原文:https://towardsdatascience.com/detailed-tutorial-build-your-custom-real-time-object-detector-5ade1017fd2d?source=collection_archive---------0-----------------------

附有详细的笔记本:使用 Tensorflow API、Google Colab 和 GDrive 从现场摄像机中检测枪支。

Model Inference on the Equilibrium, 2002 Video Clip

当事故发生时,政策响应时间非常关键。在美国,警察的平均反应时间约为 18 分钟。[](http://1. https://www.policemag.com/341042/quicker-response-to-active-shooters)
在我的上一个项目中,我试图通过在现场闭路电视摄像机中检测武器来最大限度地缩短警方的反应时间,作为一种一旦检测到枪支就向他们发出警报的方法。这个项目的主要动机是因为美国校园枪击事件越来越多

在本教程中,我们将:

  • 使用 Tensorflow 对象检测 API 对自定义图像执行对象检测
  • 使用 Google Colab 免费的 GPU 进行训练,使用 Google Drive 保持一切同步。
  • 使用本地网络摄像头调整、训练、监控和使用模型进行推理的详细步骤。

如果你想开始探索,我已经创建了这个 Colab 笔记本 。它有一些这里没有提到的步骤和注意事项。建议看完这个教程再看

Model Inference on the Equilibrium, 2002 Video Clip

我们开始吧,好吗?

路线图:

1.采集图像和标签。
2。建立环境。
3。导入并安装所需的软件包。
4。预处理图像和标签。
5。下载 Tensorflow 模型。
6。生成TF records
7。选择并下载预先训练好的模型。
8。配置培训管道。
9。张量板。
10。训练。
11。导出训练好的模型。
12。网络摄像头推断。

1.收集图像和标签。

我会用手枪的照片。原始数据集由西班牙格拉纳达大学收集并标记。该数据集包含 3000 张不同位置、旋转、背景等的枪支照片。枪也已经贴好标签了(不是最好的)。你可以使用你自己的图片或者我在这里使用的数据集!

➊.收集图像:

如果你已经收集了你的图片,那太好了!如果没有,根据你的问题,你可以从手机拍照或从谷歌上搜索图片。

记住:垃圾进=垃圾出。选择图片是最重要的部分!
以下是收集图像时可能会有所帮助的一些提示:

  1. 每节课至少 50 张图片。越多越好!如果您只检测一个类,甚至可以获得更多。
  2. 背景中有随机对象的图像。
  3. 各种背景条件;黑暗、明亮、室内/室外等。

收集图片最简单的方法之一就是使用 谷歌-图片-下载 您也可以使用下载图片。本教程提供了多种从谷歌收集图片的方法。

将您的图像保存在名为images的文件夹中

注意 :确保所有图像都是 。jpg ,如果图像在不同的扩展名中,您可能会在训练时出错。

➋.标记图像:

一旦你收集了你的图片,是时候给它们贴上标签了。有许多工具可以帮助你标记你的图像。也许, LabelImg 是最受欢迎也是最容易使用的。使用 github repo 中的说明,下载并安装到您的本地机器上。

使用标签很简单,只要记住:

  1. 为标签创建一个新目录,我将其命名为annotations
  2. 标签框中,点击更改保存目录并选择annotations文件夹。这是保存标签/注释的位置。
  3. 点击打开目录并选择图像文件夹。
  4. 使用快捷方式可以加快速度。

Shortcuts for MacOS:
_____
| CMD + s | Save the label
_
|    w    | Create a box
_
|    d    | Next image
|    a    | Previous image
_
| CMD + + | Zoom in
| CMD + - | Zoom out
_____

默认情况下,标签将采用 PascalVOC 格式。每个图像将有一个。有标签的 xml 文件。如果一幅图像中有不止一个类或一个标签,那。xml 文件将包括它们全部。

2.设置环境。

➊.设置 Google Colab 笔记本:

  1. 创建一个新的笔记本。
  2. 从左上角菜单:进入运行时 > 更改运行时类型 >从硬件加速器中选择 GPU 。一些预训练的模型支持 TPU。我们在这个项目中选择的预训练模型只支持 GPU。
  3. (强烈推荐)将 Google Drive 安装到 Colab 笔记本上:

当训练开始时,将创建检查点、日志和许多其他重要文件。当内核断开连接时,如果这些文件没有保存在你的 Google Drive 或其他地方,它们和其他所有文件都会被删除。在你的电脑睡眠后或使用 Colab GPU 12 小时后,内核会立即断开连接。如果训练的模型没有被保存,则需要从零重新开始训练。我也高度推荐下载谷歌备份和同步应用程序,这样移动和编辑文件就更容易了,也能让一切保持同步。

  • 打开你的谷歌硬盘,创建一个名为object_detection的文件夹
  • 在本地机器上打开谷歌备份和同步应用程序,选择object_detection文件夹,

注意:这种方法很大程度上取决于你的网络连接速度。

.

在 Colab 笔记本上,挂载 gdrive 并导航到项目的文件夹,会要求您输入授权代码:

from google.colab import drive

drive.mount('/gdrive')# the project's folder
%cd /gdrive/'My Drive'/object_detection

➋.上传您的图像和标签:

object_detection文件夹中,创建一个包含图像和标签的文件夹data。选择以下方法之一上传您的数据。

  1. 使用谷歌备份和同步应用程序:

上传imagesannotations文件夹很容易;只需将它们从您的计算机移动到data/object_detection 文件夹中。

.

.

2.直接从笔记本上传:

:这种方法最慢。

使用以下内容直接上传到笔记本。你必须压缩images文件夹或者单独上传它们(不支持上传文件夹到 Google Colab)。组织和拥有相同的文件结构非常重要。

from google.colab import filesuploaded = files.upload()

3.直接从来源上传:

您也可以使用curlwget直接从信号源下载

到目前为止的工作目录:

object_detection
             └── data
                   ├── images
                   │      ├── image_1.jpg
                   │      ├── image_2.jpg
                   │      └── ...
                   │
                   └── annotations
                          ├── image_1.xml
                          ├── image_2.xml
                          └── ...

提示:你可以在 Google Colab 笔记本上查看完整的工作目录,方法是:点击左上角的箭头打开左侧面板。或者使用/ctrl+alt+p 然后点击左上角菜单中的文件

➌.将图像分为训练和测试:

根据数据集的大小,您可能需要手动分割数据。如果你有很多图片,你可能想用这样的东西来随机分割你的数据。

注意:*images*里面的图像不需要拆分,只需要* 。xml 文件。*

此时的工作目录:

*object_detection
             └── data
                   ├── images
                   │      ├── image_1.jpg
                   │      └── ...
                   │
                   ├── annotations
                   │      ├── image_1.xml
                   │      └── ...
                   │
                   ├── train_labels //contains the labels only
                   │      ├── image_1.xml
                   │      └── ...
                   │
                   └── test_labels //contains the labels only 
                          ├── image_50.xml
                          └── ...*

3.导入和安装所需的软件包。

➊.安装所需的软件包:

Google Colab 已经预装了大部分软件包;Python,Tensorflow,熊猫等。

这些是我们需要的软件包,默认情况下不会预装。通过运行以下命令来安装它们:

*!apt-get install -qq protobuf-compiler python-pil python-lxml python-tk!pip install -qq Cython contextlib2 pillow lxml matplotlib pycocotools*

➋.导入库:

其他导入将在以后需要时完成。

我们需要 Tensorflow 版本 1.15.0。通过运行以下命令检查 Tensorflow 版本:

*print(tf.__version__)*

4.预处理图像和标签。

我们需要为创建两个 csv 文件。 xml 文件中的每一个train_labels/test_labels/

这两个 csv 文件将包含每个图像的文件名、标签/盒子位置等。此外,如果同一张图片有多个类别或标签,则会为其创建多个行。

除了 CSV s,我们还需要创建一个 pbtxt 文件来包含每个类的标签映射。这个文件将通过定义类名到类 ID 号的映射来告诉模型每个对象是什么。

您不必手动执行这些操作,下面的操作会将 xml 文件转换成两个 csv 文件,并创建.pbtxt文件。只要确保:

  • 匹配 xml 所在的相同文件夹的名称:train_labels/test_labels/(或者更改为下面的代码)
  • 当前目录是object_detection/data/
  • 图像在。jpg 格式

此时的工作目录:

*object_detection/
             └── data/
                   ├── images/
                   │      └── ...
                   ├── annotations/
                   │      └── ...
                   ├── train_labels/
                   │      └── ...
                   ├── test_labels/
                   │    └── ...
                   │
                   ├── label_map.pbtxt
                   │
                   ├── test_labels.csv
                   │
                   └── train_labels.csv*

5.正在下载张量流模型。

Tensorflow 模型包含了我们感兴趣的对象检测 API。我们会从官方回购中得到。

  • 导航到object_detection/目录,然后:
*# downloads the models
!git clone --q [https://github.com/tensorflow/models.git](https://github.com/tensorflow/models.git)*

接下来,我们需要编译 proto buffers——理解这个项目并不重要,但是你可以在这里了解更多。此外,PATH var 应该添加以下目录:models/research/models/research/slim/

  • 导航至object_detection/models/research/目录,然后:
*# compils the proto buffers
!protoc object_detection/protos/*.proto --python_out=.# exports PYTHONPATH environment var with research and slim paths
os.environ['PYTHONPATH'] += ':./:./slim/'*

最后,运行一个快速测试来确认模型构建器工作正常:

*# testing the model builder
!python3 object_detection/builders/model_builder_test.py*

如果你在测试结束时看到一个OK,那么一切都很好!

6.正在生成 TFRecords。

Tensorflow 接受数据作为 TFRecords data.record。TFRecord 是一个二进制文件,运行速度快,内存使用率低。它在一个文件中包含所有的图像和标签。点击阅读更多相关信息。

在我们的例子中,我们将有两个 TFRecords 一个用于测试,另一个用于培训。要做到这一点,我们需要确保:

  • 匹配 CSV s 文件名:train_labels.csvtest_labels.csv(或者在下面的代码中更改)
  • 当前目录是object_detection/models/research
  • 通过改变row_label变量,在下面的函数class_text_to_int中添加您的自定义对象文本(这是将出现在被检测对象上的文本)。如果有多个对象,请添加更多标签。
  • 检查到data/目录的路径是否与下面的data_base_url相同。

7.选择和下载预先训练的模型。

➊.选择预先训练的模型:

预训练模型仅仅意味着它已经在另一个数据集上被训练过。这个模型已经看到了成千上万的图像和物体。
COCO (上下文中的常见对象)是一个包含 33 万幅图像的数据集,其中包含 80 个不同类别的 150 万个对象。比如,狗,猫,车,香蕉,…在这里勾选所有类别。

从头开始训练一个模型是极其耗时的;完成训练可能需要几天或几周的时间。一个预先训练好的模型已经看到了大量的物体,并且知道如何对它们进行分类。所以,为什么不直接用它呢!

因为我们的兴趣是干扰实时视频,我们将选择一个具有低 ms 推理速度和相对高地图的模型。

本项目使用的型号为 ssd_mobilenet_v2_coco 。从到此处到查看其他型号。你可以使用任何你喜欢的预先训练的模型,但我建议先用SSD’single shot detector’模型进行实验,因为它们在实时视频 [⁴](http://4. https://towardsdatascience.com/review-ssd-single-shot-detector-object-detection-851a94607d11) 上的表现比任何类型的 RCNN 都要快。

解释对象检测技术之间的区别超出了本教程的范围。你可以从这篇博客文章中读到更多关于它们的信息,或者从这里了解它们的速度和准确性。

让我们从选择一个预训练模型开始:

我们将下载选定的模型。我创建了这两个模型配置来使它更容易。这里选择的是 ssd_mobilenet_v2 ,如果你愿意的话,可以稍后尝试使用**faster _ rcnn _ inception _ v2。只需改变上面的selected_model

➋.下载预训练模型:

  • 导航至models/research/
  • DEST_DIR是下载模型的地方。如果您有不同的工作目录,请更改它。

在训练时,默认情况下,模型会每 600 秒自动保存一次。日志和图形,如损失AR、也会不断保存。让我们为它们创建一个文件夹,以便在培训期间保存:**

  • object_detection/model/research/里面创建一个名为training的文件夹

此时的工作目录:

***object_detection/
           ├── data/
           │    ├── images/
           │    │      └── ...
           │    ├── annotations/
           │    │      └── ...
           │    ├── train_labels/
           │    │      └── ...
           │    ├── test_labels/
           │    │      └── ...
           │    ├── label_map.pbtxt
           │    ├── test_labels.csv
           │    ├── train_labels.csv
           │    ├── test_labels.records
           │    └── train_labels.records
           │
           └── models/           
                ├── research/
                │      ├── training/
                │      │      └── ...
                │      ├── pretrained_model/

                │      ├── frozen_inference_graph.pb
                │      └── ...
                └── ...***

8.配置培训渠道。

这是开始训练模型前的最后一步,终于!也许,在这一步,您可能会花一些时间来调整模型。

我们下载的 Tensorflow 对象检测 API 模型附带了许多示例配置文件。对于每个型号,都有一个“几乎”可以使用的配置文件。

配置文件位于以下位置:

***object_detection/models/research/object_detection/samples/configs/***

SSD _ mobilenet _ v2 _ coco . config是我们正在使用的预训练模型的配置文件。T22 如果你选择了另一个型号,你需要使用&编辑相应的配置文件。****

因为我们可能必须不断地调整配置,所以我建议执行以下操作:

  • 通过运行以下命令查看示例配置文件的内容:

  • 复制配置文件的内容

  • 使用以下命令编辑它

或者,如果您使用任何文本编辑器同步了所有内容,您可以直接从本地机器打开并编辑配置文件。

以下是示例配置文件中需要更改的必要编辑,以及一些用于提高模型性能的建议编辑。

需要对配置文件进行的编辑:

  1. 型号{} > ssd {} :把num_classes改成你拥有的班级数。

2. train_config {} :将fine_tune_checkpoint改为检查点文件路径。

:确切的文件名model.ckpt不存在。这是模型在训练期间将被保存的地方。这是它的相对路径:

***/object_detection/models/research/pretrained_model/model.ckpt***

3. train_input_reader {} :设置train_labels.record和标签映射pbtxt文件的路径。

4. eval_input_reader {}: 设置test_labels.record和标签映射pbtxt文件的路径。

就是这样!您可以跳过可选的编辑,直接参加培训!

。建议 编辑配置文件:

首先,您可能想开始训练模型,看看它做得有多好。如果你过拟合,那么你可能想做一些更多的图像放大。

  • 在示例配置文件中:默认添加random_horizontal_flip & ssd_random_crop。您也可以尝试添加以下内容:

来自列车配置{}:****

注意 :每一次图像放大都会大幅增加训练时间。

您可以添加许多数据扩充选项。从官方代码点击查看完整列表。

  • 模型{ }>SSD { }>box _ predictor { }:设置use_dropouttrue这将有助于对抗过拟合。**
  • eval_config : {} 设置num_examples中的测试图像的数量,并移除max_eval以无限期评估**

:提供的笔记本解释了更多关于调整配置文件的内容。 检查一下

完整的工作目录: (包括后面会创建和使用的一些文件/文件夹)

***object_detection/
      ├── data/
      │    ├── images/
      │    │      └── ...
      │    ├── annotations/
      │    │      └── ...
      │    ├── train_labels/
      │    │      └── ...
      │    ├── test_labels/
      │    │      └── ...
      │    ├── label_map.pbtxt
      │    ├── test_labels.csv
      │    ├── train_labels.csv
      │    ├── test_labels.records
      │    └── train_labels.records
      │
      └── models/           
           ├─ research/
           │    ├── fine_tuned_model/
           │    │      ├── frozen_inference_graph.pb
           │    │      └── ...
           │    │         
           │    ├── pretrained_model/
           │    │      ├── frozen_inference_graph.pb
           │    │      └── ...
           │    │         
           │    ├── object_detection/
           │    │      ├── utils/
           │    │      ├── samples/
           │    │      │     ├── configs/             
           │    │      │     │     ├── ssd_mobilenet_v2_coco.config
           │    │      │     │     ├── rfcn_resnet101_pets.config
           │    │      │     │     └── ... 
           │    │      │     └── ...                                
           │    │      ├── export_inference_graph.py
           │    │      ├── model_main.py
           │    │      └── ...
           │    │         
           │    ├── training/
           │    │      ├── events.out.tfevents.xxxxx
           │    │      └── ...               
           │    └── ...
           └── ...***

9.张量板。

Tensorboard 是我们可以想象训练中发生的一切的地方。您可以监控lossmAPAR等等。

你也可以在训练中监控图片和注释。在每一次评估step中,你可以看到你的模型在探测物体方面有多好。
注意:还记得我们上面设置num_visualizations: 20的时候吗?Tensorboard 将在这里显示大量测试图像的图片。

要在 Colab 上使用 Tensorboard,我们需要通过 ngrok 来使用。通过运行以下命令获得:

接下来,我们指定日志文件的存储位置,并配置一个链接来查看 Tensorboard:

当您运行上面的代码时,在输出的最后会有一个 url,您可以通过它访问 Tensorboard。

注意事项:

  1. 运行上述代码时,您可能不会得到 url,而是得到一个错误。只需再次运行上面的单元格。不需要重新安装 ngrok。
  2. 在训练开始之前,Tensorboard 不会记录任何文件。
  3. 使用 ngrok 时,每分钟最多允许 20 个连接,当模型正在登录时,您将无法访问 tensorboard。(经常发生)

如果您将项目同步到本地机器,您将能够不受任何限制地查看 Tensorboard。

转到本地机器上的终端并运行:**

***$ pip install tensorboard***

运行它并指定日志目录的位置:

***# in my case, the path to the training folder is:
tensorboard --logdir=/Users/alaasenjab/Google\ Drive/object_detection/models/research/training***

10.训练…终于!

训练模型就像运行下面的代码一样简单。我们只需要给它:

  • 运行培训流程的
  • 管道 _ 配置 _ 路径=路径/至/配置/文件/模型.配置
  • 型号 _ 目录 =路径/至/培训/

注意事项:

  1. 如果内核死亡,训练将从最后一个检查点恢复。除非你没有把training/目录保存在某个地方,比如:GDrive。
  2. 如果您正在更改以下路径,请确保等号=和路径之间没有空格。

现在退后,在 Tensorboard 上观看你的火车模型。

11.导出训练好的模型。

默认情况下,该模型将每 600 秒保存一个检查点,同时训练多达 5 个检查点。然后,随着新文件的创建,旧文件将被删除。

通过运行以下代码,我们可以找到最后一个定型的模型:

然后通过执行export_inference_graph.py将模型转换成一个冻结的模型frozen_inference_graph.pb,我们可以用它来进行推理。这个冰冻的模型不能用来恢复训练。然而,saved_model.pb也被导出,它可以用来恢复训练,因为它拥有所有的权重。

  • 管道 _ 配置 _ 路径=路径/至/配置/文件/模型.配置
  • 输出目录 =保存模型的位置
  • trained _ check point _ prefix=路径/到/a/检查点

您可以从该目录访问所有导出的文件:

***/gdrive/My Drive/object_detection/models/research/pretrained_model/***

或者,你可以直接从 Google Colab 下载推理所需的冻结图:

***#downloads the frozen model that is needed for inference
# output_directory = 'fine_tuned_model' dir specified above.files.download(output_directory + '/frozen_inference_graph.pb')***

我们还需要标签图.pbtxt文件:

***#downlaod the label map
# we specified 'data_base_url' above. It directs to
# 'object_detection/data/' folder.files.download(data_base_url + '/label_map.pbtxt')***

12。网络摄像头推断。

要在本地机器上使用您的网络摄像头来推断型号,您需要安装以下软件:

***Tensorflow = 1.15.0
cv2 = 4.1.2***

您还需要在本地机器上下载 Tensorflow 模型(上面的步骤 5 ),或者如果您在本地机器上同步了 GDrive,您可以跳过这一步并导航到模型。

  • 转到本地机器上的终端并导航到models/research/object_detection

在我的例子中,我导航到 GDrive 中的文件夹。

***$ cd /Users/alaasenjab/Google\ Drive/object_detection/models/research/object_detection***

您可以从 jupyter 笔记本或通过创建一个.py文件来运行以下内容。但是,更改PATH_TO_FROZEN_GRAPHPATH_TO_LABEL_MAPNUM_CLASSES

运行代码微笑:)

结论:

从图像和视频中检测物体比实时检测要简单一些。当我们有一个视频或图像,我们想从其中检测对象时,我们不太关心模型检测对象可能需要的推理时间。在实时对象检测中,我们可能希望牺牲一些精度来获得更快的推理时间。
在检测枪支以通知警方的情况下,我们并不太关心检测枪支的确切位置。相反,我们可能会对这两种情况进行优化:
假阴性:当有枪时没有检测到枪。
真否定:没有枪的时候检测到枪。

我希望你觉得这篇关于如何使用 Tensorflow 检测自定义对象的教程简单而有用。别忘了查看 Colab 笔记本了解更多详情。

如果你有任何问题,请告诉我,我会尽力帮助你的!

资源:

⋆ Tensorflow 对象检测 API。by:tensor flow
⋆的灵感来自:免费火车物体检测。由: 程维
⋆浣熊探测器数据集。by:
Dat Tran

⋆使用 Colab 训练 Yolov3。作者:* 大卫·伊瓦涅斯 ***

使用 Docker 检测文本中的希腊语,并在没有 Boto3 的情况下存储在 S3。

原文:https://towardsdatascience.com/detect-greek-language-in-text-using-docker-store-in-s3-without-boto3-3c6d6b220639?source=collection_archive---------34-----------------------

嗨,你好!在这篇文章中,我们将构建一个小的“应用程序”,它能够检测文本中的希腊语并在 AWS S3 中存储一些结果。

更详细地说,该应用程序将是一个 docker 容器,它将接受输入文件路径,将能够获取文件(例如,从 AWS S3 桶),使用 python 脚本来处理它,检测文本中的希腊语,仅保留希腊语文本,并最终上传结果。希腊文本的 csv 文件放回 AWS S3 桶。

作为第一步,我们将构建一个 Docker 映像&确保语言检测、文本处理和 AWS 通信所需的所有模块都安装在映像的虚拟 OS 中,只要保存 AWS 凭证的环境变量被正确地传递到 Docker 映像中。

更有趣的是:

  • 我们将不使用 boto3 库,因为当 AWS S3 的访问权限严格时,它并不总是与 AWS CLI 功能相同。
  • 我们将使用 fastText 文本分类库,它实际上将是我们的语言检测工具,因为它提供了微小的 lid.176.ftz 模型;其对应主模型的压缩版本,文件大小仅为 917kB!

需要的文件

在设置我们的流程之前,我们需要准备一些文件:

  • 。:在目录中创建一个本地文件夹,docker 文件将放在其中并用于构建映像。
  • 。/init/:在上面的主文件夹中,创建一个' init '文件夹,该文件夹将包含所有需要复制到 docker 映像中的文件。
  • 。/init/envs.py:环境变量文件:
envs = {
    "LOCAL_FILE": 'temp.csv',
    "LOCAL_OUT_FILE": 'output.csv',
    "AWS_S3_PROFILE": 'my_aws_s3_profile_name'
}
  • 。/init/s3.py:主要功能的脚本。
  • 。/init/lib _ process . py:S3 . py 文件导入和使用的帮助器库。
  • 。/init/lid.176.ftz:语言检测模型。
  • 。/init/credentials:AWS 凭据文件:
[my_aws_s3_profile_name]
aws_access_key_id = ABCDE
aws_secret_access_key = 12345
  • 。/init/config:AWS 配置文件:
[my_aws_s3_profile_name]
output=json
region=us-east-2

其中我们假设我们的 AWS 区域是 us-east-2。

  • Dockerfile:用于构建 docker 映像的 docker 指令。

Docker 图像

让我们一起逐行解析docker 文件:

1 FROM python:3.6.6-slim
2 WORKDIR .
3 COPY ./init/envs.py .
4 COPY ./init/s3.py .
5 COPY ./init/lib_process.py .
6 COPY ./init/lid.176.ftz .
7 RUN mkdir -p /.aws/
8 RUN apt-get update && apt-get install -y \
9         python-dev \
10        python-numpy \
11        python-scipy \
12        && rm -rf /var/cache/apk/*
13 COPY ./init/credentials /.aws/
14 COPY ./init/config /.aws/
15 ENV AWS_CONFIG_FILE=/.aws/config
16 ENV AWS_SHARED_CREDENTIALS_FILE=/.aws/credentials
17 RUN pip3 install --upgrade awscli
18 RUN pip3 install fasttext
19 RUN chmod u+x s3.py
20 ENTRYPOINT ["python3","s3.py"]
21 CMD ['']

按大小构建最佳 docker 图像超出了范围;在《走向数据科学》中有许多关于这方面的好文章:-)

  • 第一行:我们从一个 python3.6 小图开始。
  • 第 2 行:我们将当前目录设置为构建映像时看到的目录。
  • 第 3 行:将 env 移动到映像的操作系统中。
  • 第 4 行& 5: 用 python 脚本做同样的事情。
  • 第 6 行:对语言检测模型做同样的操作。
  • 第 7 行:创建 AWS-CLI 设置目录。
  • 第 8–12 行:通过 docker 镜像的 Ubuntu OS 安装一些基本的 python 模块,但是不保留它们的安装文件。
  • 第 13 行& 14: 将 AWS 设置文件(包括 AWS-CLI 凭证)移动到映像的操作系统默认 AWS-CLI 设置目录中。✧:这很重要。我们在构建时注入凭证,而不是在 docker 文件或相关源代码(共享代码)中硬编码凭证。
    让运行中的容器要求凭证作为输入参数会更安全。以上是我们通过 envs.py 文件传递凭证的例子。
  • 第 15 行& 16: 刷新(设置)显示设置文件路径的 AWS 环境变量。
  • 第 17 行:通过 python 的 pip 安装 AWS-CLI。
  • 第 18 行:通过 python 的 pip 安装 fasttext 库。
  • 第 19 行:使 s3.py 文件可执行。
  • 第 20 行& 21: 默认情况下,上面的映像创建的任何容器都将使用虚拟操作系统的 python3 来运行 python 可执行文件 s3.py。

使用 docker 图像

我们可以运行以下命令,例如在 Ubuntu 中:

  • 建立形象:
docker build --no-cache -t <image_name> .
  • 创建并运行图像的容器:
docker run --rm -t --name <container_name> <image_name> \
"s3://<bucket_name>/<relative path to file>/input.csv" \ "s3://<bucket_name>/<relative path to file>/output.csv"

在我们的例子中,上面的意思是我们创建并运行一个容器,它将在第一个 s3 路径中找到输入文件,并将处理后的结果文件存储在第二个 s3 路径中。

  • 通过打开虚拟操作系统进行手动探索来调试映像:
docker run --entrypoint "/bin/bash" -it \ 
--name <container_name> <image_name>

内部流动

正如我们在上面看到的,容器使用一些给定的参数执行 s3.py 脚本。剧本:

  • 读取参数。
  • 通过其主机操作系统(即 docker 映像操作系统)运行 aws-cli 命令,并从 aws s3 获取输入。csv 文件。
  • 处理输入文件并生成输出文件。
  • 再次运行 aws-cli 命令,并将其上传到 s3 输出中。csv 文件。
  • 对于本教程。csv 文件是 utf-8 编码的,用逗号分隔。

s3.py 脚本:

#!/usr/bin/python3import os
import sys
from envs import envs
from lib_process import processingif __name__ == '__main__':
    print(os.uname())
    print("This is the name of the script: ", sys.argv[0])
    print("Number of arguments: ", len(sys.argv))
    print("The arguments are: ", str(sys.argv))
    REMOTE_IN_FILE = sys.argv[1]
    LOCAL_FILE = "./" + envs["LOCAL_FILE"]
    LOCAL_OUT_FILE = "./" + envs["LOCAL_OUT_FILE"]
    REMOTE_OUT_FILE = sys.argv[2]
    print("Entered the python script.")
    print("Envs: REMOTE_IN_FILE:", REMOTE_IN_FILE)
    print("Envs: LOCAL_FILE:", LOCAL_FILE)
    print("Envs: REMOTE_OUT_FILE:", REMOTE_OUT_FILE)
    print("Envs: AWS_S3_PROFILE:", envs['AWS_S3_PROFILE']) down_command = "aws s3 cp " + "--profile " + 
        envs['AWS_S3_PROFILE'] + " " + REMOTE_IN_FILE + " " 
        + LOCAL_FILE
    print(down_command)
    os.system(down_command) processing(LOCAL_FILE, LOCAL_OUT_FILE) up_command = "aws s3 cp " + "--profile " + 
        envs['AWS_S3_PROFILE'] + " " + LOCAL_OUT_FILE + " " 
        + REMOTE_OUT_FILE
    print(up_command)
    os.system(up_command)

处理

s3.py 脚本使用包含执行处理的函数的助手库 python 文件。

假设输入文件的行是这样的格式:"< text_id >,< text > \n"

lib_process.py 库:

import fasttext def is_greek(txt, model):
    # Predict only the most dominant language in the text:
    pred = model.predict(txt, k=1)
    # Fetch the found language
    pred_langs = pred[0]
    pred_lang = pred_langs[0]
    # Compare the predicted language with the greek lang label:        
    return False if pred_lang != '__label__el' else True def processing(local_file, out_file):
    # Open the file readers:        
    fin = open(local_file, mode='r')
    fout = open(out_file, mode='a') # Load the language detection model, once:
    model = fasttext.load_model('lid.176.ftz') line_count = 0    
    while True: # Loop over all input lines
        # Split text by sentence
        line = fin.readline()
        if not line:
            break # File ended
        line_count += 1 # Split line(sentence) into tokens & keep the text
        txt = line.strip().split(",")[1]

        # Keep Greek sentences
        if is_greek(txt, model):
            # Store in the output file the found greek sentence:            
            fout.write(line + '\n') # Close the files:
    fin.close()
    fout.close()

原来如此!我希望你喜欢它!

感谢阅读,请不要犹豫留下任何评论或分享意见。

检测用于电子邮件分类的简单神经网络结构

原文:https://towardsdatascience.com/detecting-a-simple-neural-network-architecture-using-nlp-for-email-classification-f8e9e98742a7?source=collection_archive---------14-----------------------

邮件分类中的超参数优化。

大约十年前,垃圾邮件使电子邮件濒临毁灭。到 2015 年,谷歌称其垃圾邮件率下降到 0.1%,误报率下降到 0.05%。这一显著下降在很大程度上是由于其垃圾邮件过滤器中引入了神经网络,可以通过分析大量收集的内容来学习识别垃圾邮件和钓鱼邮件。

神经网络是强大的机器学习算法。它们可用于变换特征,以便形成相当复杂的非线性决策边界。它们主要用于分类问题。完全连接的层从 CNN 到 RNN/LSTM 获取深层表示,并将其转换为最终的输出类或类分数。

这篇文章解释了基于以下因素的垃圾邮件分类。

单词嵌入法在电子邮件主题行中的应用。

在层和节点层数量方面的超参数调整,以及对电子邮件主题行的优化。

基于邮件主题行比较 CNN 和 RNN 方法的性能。

垃圾邮件过滤器:

企业可以选择不同类型的垃圾邮件过滤器。一些过滤器针对电子邮件的内容,以确定这些内容是否与业务相关,而一些过滤器检查邮件的电子邮件标题。您还可以设置一些过滤器来限制接受来自特定地址的电子邮件,以及一些允许您设置参数来阻止哪些类型的电子邮件。甚至有一些可以让你阻止任何来自黑名单上地址的邮件。在这项研究中,垃圾邮件过滤器是根据电子邮件的主题开发的。

Example of email subject lines used in this study

数据集的基数:

该数据集基于清理后的安然语料库,共有属于 158 个用户的 92188 条消息,平均每个用户 757 条消息。该数据集的垃圾邮件和垃圾邮件分布几乎相等。由 ham 和 spams 组成的 19997 封电子邮件被用作 20%分割的训练和验证集。 17880 封电子邮件然后被用作测试集来识别准确性和误报。

Table 1: Neural Network Architecture used for hyper parameter tuning.**

层的超参数调整和节点层数

人工神经网络有两个主要的超参数来控制网络的结构或拓扑:(a)层数和(b)每个隐藏层中的节点数。

为特定预测建模问题配置这些超参数的最可靠方法是通过稳健测试的系统实验。多层感知器由一个节点组成,也称为神经元或感知器,是一个计算单元,具有一个或多个加权输入连接、以某种方式组合输入的传递函数以及输出连接。节点然后被组织成层以构成网络。

MLP 中的图层类型如下:

1.输入层:输入变量,有时称为可见层。

2.隐藏层:输入层和输出层之间的节点层。可能有一层或多层这样的层。

3.输出层:产生输出变量的节点层。

4.大小:模型中节点的数量。

5.宽度:特定层中节点的数量。

6.深度:神经网络的层数。

7.架构:网络中各层和节点的具体安排。

检测超参数是必不可少的,原因有三个:( a)针对特定问题找到简单的神经网络架构。(b)从超参数的无数组合中找到正确的参数组,以及(c)复制神经网络结构以供将来使用。

表 1 给出了使用隐藏层的三个预训练深度神经网络(DNN)模型(双向 LSTM、非嵌入 CNN 和嵌入 CNN)的细节,在第一、第二和第三层中包含 16、32、64 和 128 个神经元以及 16、32、64 和 128 个滤波器。除了激活为“tanh”的致密层之外,所有层中的激活都是 ReLu。这里给出了 CNN 和嵌入双向 LSTM 网络的代码。所有模型都使用 16 的批量和 2 的纪元。

**def** embeddings(fl1=32, fl2=32, fl3=64, dl=16, optimizer= 'RMSprop', kl = 5, layer =1 ):
    sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
    embedded_sequences = embedding_layer(sequence_input)
    **if** (layer == 1):
        x = Conv1D(filters = fl1, kernel_size = kl, activation='relu')(embedded_sequences)
        x = MaxPooling1D(pool_size = kl)(x)
    **elif** (layer == 2):
        x = Conv1D(filters = fl1, kernel_size = kl, activation='relu')(embedded_sequences)
        x = MaxPooling1D(pool_size = kl)(x)
        x = Conv1D(filters = fl2, kernel_size = kl, activation='relu')(x)
        x = MaxPooling1D(pool_size = kl)(x)

    **else**:
        x = Conv1D(filters = fl1, kernel_size = kl, activation='relu')(embedded_sequences)
        x = MaxPooling1D(pool_size = kl)(x)
        x = Conv1D(filters = fl2, kernel_size = kl, activation='relu')(x)
        x = MaxPooling1D(pool_size = kl)(x)
        x = Conv1D(filters = fl3, kernel_size = kl, activation='relu')(x)
    x = GlobalMaxPooling1D()(x)
    x = Dense(units = dl, activation='relu')(x)
    preds = Dense(1, activation='tanh')(x)
    model = Model(sequence_input, preds)
    model.compile(loss= 'binary_crossentropy',optimizer= optimizer,
              metrics=['acc'])

    **return** model

神经网络的两个重要技术是丢失和激活。超参数调整也可以基于这些技术完成,但这里不使用。为了改善大型神经网络的泛化误差,采用了丢包技术。在这种方法中,噪声使给定层中神经元激活的固定部分为零或消失。整流线性单元(ReLU)使用激活函数 max(0;x)。ReLUs 被结合到标准的前馈神经网络中,以保持概率模型具有最大(0;x)。

**def** embedding_LSTM(fl1=16, fl2=16, fl3=16, dl=16, optimizer= 'RMSprop', kl = 5, layer =1): 
    sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
    embedded_sequences = embedding_layer(sequence_input)
    x = Bidirectional(LSTM(units = fl1, return_sequences=**True**))(embedded_sequences)
    x = GlobalMaxPool1D()(x)
    x = Dense(units=dl, activation="relu")(x)
    x = Dropout(0.1)(x)
    preds = Dense(1, activation='tanh')(x)
    model = Model(sequence_input, preds)
    model.compile(loss= 'binary_crossentropy',
              optimizer= optimizer,
              metrics=['acc'])
    **return** model

嵌入:

这里使用的 GloVe(全局向量)是将每个单词映射到 100 维向量的方法之一。这些向量可以用来学习单词的语义,如男人是女人,国王是女王。或者男+女=女。这种嵌入在许多应用中起着重要的作用。这是一种迁移学习,从大型数据语料库中学习单词嵌入,然后可以用于较小的数据集。向量由无监督学习算法(PCA)生成。在来自语料库的聚集的全局单词-单词共现统计上执行训练,并且所得的表示展示单词向量空间的线性子结构。该模型的主要直觉是简单的观察,即单词-单词共现概率的比率有可能编码某种形式的意义。手套数据集有 400000 个单词。

使用单词袋方法作为特征向量。对记号(单词)的分析揭示出,24.80%的词汇和 43.05%的文本出现在嵌入矩阵中。****

结果和分析:

Figure 1. Results of hyperparameters vs validation loss in CNN models.

图 1 的结果显示,密集层中神经元的数量不是很确定,但是第一层中的 64 个过滤器给出了较低的验证损失。此外,很难分别预测第二层和第三层中的过滤器数量和低验证损失。

Figure 2. 3D visualization of hyperparameters based on validation loss, trainable parameters and dense layers in CNN models.

图 2 给出了简单模型(低可训练参数)和复杂模型(高可训练参数)的可视化效果。在参数空间的左下角,具有单个神经元层和范围从 20k 到 70k 的可训练参数的模型给出了较低的验证损失,并且是良好的架构。

Figure 3. Results of hyperparameters vs validation loss in bi-directional LSTM models.

图 3 的结果显示,密集层中的 64 个神经元是一个很好的近似值,第一层中的 128 个过滤器也是验证损失较低的可接受结果。然而,双向 LSTM 表明,可训练参数越多,验证损失越小。

Figure 4. 3D visualization of hyperparameters based on validation loss, trainable parameters and dense layers in bi-directional LSTM models.

图 4 给出了双向 LSTM 模型中简单(低可训练参数)和复杂模型(高可训练参数)的良好可视化。至少需要 64/128 个密集层神经元来生成低验证损失的结果。此外,具有较高的可训练参数的模型具有较低的验证损失,并且是良好的架构。然而,与 CNN 模型相比,LSTMs 的验证损失较小。

Table 2: Detailed results of top 5 models from three different types of architecture.

表 2 的定性分析显示了具有和不具有全局向量嵌入的 CNN 和双向 LSTM 网络的结果。选择基于最小验证损失的前五个最佳模型。嵌入 CNN 产生的最大准确率为 58%。73%的最佳准确度和灵敏度是对于具有 66226 个可训练参数的 CNN 模型。平均准确率为 50%,无嵌入的 CNN 模型准确率低于 50%。模型的灵敏度在 50%以上,最高可达 73%。应该注意的是,没有嵌入的模型具有非常低的灵敏度。没有嵌入的模型具有较高的真阴性率。另外,那达慕优化器最适合处理这类问题。

结论:

回到问题上来:

  • 事实证明,在电子邮件主题行中使用单词嵌入方法比不嵌入要好。
  • 我们进行了广泛的研究,以寻找在训练集中产生低验证损失的最佳架构。
  • 具有更多可训练参数的 LSMT (RNN)模型给出了最低的一组总验证损失。CNN 的简单一层模型会产生稍高的验证损失。具有嵌入的 CNN 模型具有最高的准确性和真阳性率。

未来的研究将包括处理词汇外单词的方法和使用基于字符的模型,如由谷歌大脑团队设计的 lm_1b 模型,该模型包括 256 个向量(包括 52 个字符,特殊字符),维度仅为 16。

我欢迎反馈和建设性的批评。可以通过 LinkedIn 联系到我。这项研究的代码可以在这里找到。


    • CNN 模型中 hyper 参数的总组合为 3072,但仅考虑带有 Adam 和 Nadam 优化器的模型,因为它们产生的验证损失最小。类似的,只有亚当和那达慕优化是考虑为 LSTM。

使用数据科学工具检测异常天气模式

原文:https://towardsdatascience.com/detecting-abnormal-weather-patterns-with-data-science-tools-5fae48586469?source=collection_archive---------22-----------------------

世界各国都在努力应对更多的极端天气事件。但是你如何准确地指出这些异常值呢?

A large waterspout spotted off the east coast of Singapore on August 6 2016. Photo: Chua Chin Hon

在世界各地,极端天气事件正变得越来越强烈和频繁。

其中一些重大的天气异常不容忽视,例如山洪爆发或持续干旱,它们会影响一个国家的大部分人口。

但是,并不是每一个天气异常值都能被轻易观察到,尤其是在新加坡,那里的季节变化对肉眼来说不那么明显。然而,这些“较温和”的异常对于理解未来天气模式的变化同样重要。

数据可视化,比如我之前关于主题的文章中的图表范围,提供了一种快速发现数据集中异常值的方法。经典的 Seaborn pair 情节是做到这一点的一种方式。

但当你有 36 年的天气数据时,依靠图表来准确挑出异常值并不容易或有效。

在使用来自新加坡的历史天气数据的多部分数据科学项目的第三部分中,我将使用 Scikit-learn 的隔离森林模型以及 PyOD 库(Python 离群点检测)来尝试查明数据集中的离群点。

看看这些异常天气模式发生的确切日期会很有趣。这也是项目第四部分(时间序列预测)的重要前期工作,在该部分中,剔除异常值是更准确预测的关键。

数据和回购

本项目气象数据的原始来源可以在这里找到。这篇文章的 Jupyter 笔记本是这里,你可以下载交互式 Plotly 图表这里来探索更详细的异常数据。

结果概述

对于那些可能对详细的数据工作流程不感兴趣的人,我将从结果的快速概述开始。

  • 下图是从 1983 年 1 月 1 日至 2019 年 6 月 30 日新加坡日常天气中挑出异常值的两个 PyOD 模型的结果片段。我总共汇总了 4 个模型的结果,从包含 13,330 行的数据集中得到了 816 个唯一的异常值。换句话说,异常值约占数据的 6%。你可以在这里下载并探索天气异常值的子集。

Slice of PyOD results. Scroll down for the full version.

  • 2010 年 3 月、1991 年 12 月和 1987 年 1 月并列一个月内异常天气发生次数最多的三个月——10 次。
Year  Month    Number of days with outlier weather 
2010  3        10
1987  1        10
1991  12       10
1983  4         9
1992  12        9
1983  12        8
2006  12        8
1998  12        8
2008  3         7
1986  1         7
  • 1998 年出现异常天气的次数最多,其次是 1983 年和 2013 年。1998 年 3 月 26 日录得最高气温 36.0 度。

  • 在新加坡过去的 36 年里,12 月和 1 月是异常天气最多的月份——考虑到年底和年初更强烈的风暴,这并不奇怪。

  • 正如所料,天气数据集中的一些异常值比其他异常值更极端。将 816 个异常值绘制在一起,我们可以在中间看到一个清晰的集群,最高温度在 26–34°C 之间,最大风速在 20–50 公里/小时之间。较大的圆圈代表降雨量较大的日子。

更极端的异常值位于图表的右侧、左下角和顶部。以下是异常值中主要聚类的详细信息。点击下载并探索互动版。

Zoomed in detail of main cluster in outlier weather data set for Singapore, 1983–2019.

接下来,我将详细说明我是如何得出异常数据的,并绘制更多图表。

单变量(单变量)异常检测

凭直觉,我们知道试图孤立地挑出天气异常值是没有意义的。例如,一场大风暴显然会导致极端降雨、强风和低温。

但我很想知道对单个变量的异常分析会发现什么。我认为这将有助于有一些比较的基础,以及与多变量 PyOD 技术。

因此,让我们看看当隔离森林模型应用于新加坡 36 年的日降雨量数据时,我们能发现什么。但是首先,让我们检查一下日降雨量柱的偏度和峰度分数。

Skewness: 5.140533
Kurtosis: 40.778205

偏斜度是对数据集中失真程度的度量。具有正态分布的对称数据集的偏斜度值为 0。

峰度是对分布中异常值的度量。请点击此处的文章获取一个读者友好的解释。

在“每日降雨量”列的情况下,我们看到数据高度向右倾斜(偏斜度得分大于 1 ),这是因为有些日子的降雨量不同寻常。大约一半的时间也没有下雨(因此在 0 处有一个尖柱)。

日降雨量变量的峰度得分也很高(正态分布的峰度为 3),表明存在大量异常值。

我在隔离森林模型上运行了降雨数据,这是一种广泛用于识别异常值的基于树的模型。详见这两篇文章(此处和此处)进行深入解释。

这里要调整的关键参数是“污染”,即异常值的比例。我选择了旧的缺省值 0.1,而不是新的缺省值“auto”,这会给我一个高得多的离群值比例。

粉红色的主要异常区域始于大约 19.4 毫米的降雨量。在我们的数据集中,有 1,300 个条目的降雨量高于 19.4 毫米。这似乎是一个非常大的离群值数量,我不知道如何最好地重新调整污染水平。

我对日最高温度列重复了相同的步骤,最终得到了同样多的异常值——1223 个。我不会在这里详述,但是图表和代码可以在我的笔记本中找到。

总的来说,试图孤立地去除如此大量的异常值似乎是不正确的。让我们看看 PyOD 方法是否更好。

基于 PYOD 的多元异常检测

在新加坡的情况下,与异常天气关系最密切的两个变量是最高日温度和日降雨量,这使它们成为 PyOD 模型中异常值检测的明显选择。您可以使用两个以上的变量,但是这样做显然会使结果的可视化变得复杂。

PyOD 有超过 20 种检测算法,其中许多你可以混合搭配在一起。我觉得有用的是,该工具包允许轻松组合来自多个检测器的结果(更多细节见本文这里)。

对于天气数据集,我选择了 4 种算法——基于聚类的局部异常值因子、基于直方图的异常值检测、隔离森林和经典的 K 近邻。如下图所示,4 个模型的结果略有不同。

然后我汇总了结果,并通过《熊猫》中的几个简单步骤过滤掉重复的。

PyOD 库开箱即用,但挑战仍然是领域知识。与前面的单变量分析一样,您必须为 PyOD 设置的一个关键参数是污染/异常值分数-您期望在数据集中找到的异常值的百分比。

默认值为 0.1 或 10%,这可能是高估或低估了。没有更好的气象知识,很难说什么是“正确的”离群分数设置。

由于我没有这方面的专业知识,我使用了一个试错过程来查看模型识别的异常值是否与极端天气(如山洪暴发)报告的特定关键日期相匹配。例子包括 2010 年、2011 年和 2018 年的山洪。

最终,我选择了 0.04 的异常值分数。任何更低的价格都会错过报告异常天气模式的关键日期。任何更高的值都会导致数据集的很大一部分被移除。

总之,PyOD 模型从总共 13,330 个数据点中挑出了 816 个独特的异常值,约占数据集的 6%。

通过检查,这些模型成功地选出了过去 36 年中降雨量最大的一天——2011 年 1 月 30 日,降雨量为 216.2 毫米。PyOD 模型还成功地选出了 1998 年 3 月 26 日测得的最高日温度——36℃。

对异常值的进一步检查

让我们在 notebook2.0 中的一些可视化技术的基础上,在这里应用它们,通过年、月和年月组合来更仔细地观察异常值模式。

正如前面的结果概述中提到的,2010 年 3 月、1991 年 12 月和 1987 年 1 月并列为一个月中异常天气发生次数最多的月份——10 次。以下是 2010 年 3 月的 10 个异常天气:

Weather outliers spotted by PyOD’s algorithms for March 2010.

最高温度和日降雨量列清楚地显示了为什么这些日期的天气被认为是异常值。例如,3 月 3 日、4 日、6 日、7 日和 9 日的日最高气温非常高,达到 35°C 或更高。

过去 36 年的日平均最高气温为 31.5 摄氏度,标准偏差为 1.6 摄氏度。另一方面,PyOD 的算法在 2010 年 3 月 20 日捕捉到了一个有趣的异常值,当时日最高气温仅为 25.9 摄氏度——按照新加坡的标准来看,这是非常低的。

2010 年 3 月还下了几天大雨,特别是 3 月 23 日(57.6 毫米)和 3 月 31 日(49.1 毫米)。过去 36 年的平均日降雨量为 5.85 毫米

1987 年 1 月的 10 个异常值也一目了然:

看看 1987 年 1 月 11 日 127.4 毫米的大暴雨记录。一天的降雨量大约是新加坡过去 36 年月平均降雨量(160.1 毫米)的 80%。

Plotly Express 交互式图表使探索异常值变得更加容易。我分别绘制了 2010 年 3 月和 1987 年 1 月的异常值。

不幸的是,Medium 不便于将交互式图表嵌入帖子中,所以你在上面和下面看到的是 screen-caps-gif。点击下载的完整互动图表。

矩阵面板比较

我们还可以按年份分解异常天气数据,并查看哪一年的异常记录最多。1998 年出现异常天气的次数最多,其次是 1983 年和 2013 年。1998 年 3 月 26 日录得最高气温 36.0 度。

**Year  Number of outlier weather days** 
1998    38
1983    34
2013    31
2006    29
1984    29
1986    29
2010    29
2007    29
2008    28
1988    28

使用我在 notebook2.0 中尝试过的格式,我选择了异常天气模式数量最多的 3 年——2013 年、1998 年和 1983 年——并将它们分解成一系列矩阵面板,以便于比较。

在下方的面板中,较大的圆圈代表降雨量较高的日子。圆圈越暗、位置越高,当天的最高温度和最高风速就越高。

1998 年看起来具有最有趣的异常值分布,除了通常在 1 月和 12 月出现的暴雨之外,从 4 月到 9 月出现了一段明显的异常天气。

离群值中的离群值

一些异常值显然比其他异常值更极端。让我们试着从“标准异常值”中分离出极端异常值。在下方的图中,较大的圆圈表示降雨量较大。阴影较暗的圆圈表示最近的异常点。

我们可以在中心看到一个清晰的星团,最高温度在 26–34 摄氏度之间,最大风速在 20–50 千米每小时之间。较大的圆圈代表降雨量较大的日子。

更极端的异常值位于图表的右侧、左下角和顶部。在接下来的几十年里,观察中央星团是否会向右上方移动将会很有趣。

异常值的分析可以有十几个不同的方向,这取决于您所做的选择和假设。如果您在类似的项目中使用相同的数据集,请分享您的见解。

像往常一样,如果您发现任何错误,请 ping 我@

推特: @chinhon

领英:www.linkedin.com/in/chuachinhon

这是我早期的一个项目,展示新加坡不断变化的天气模式。

用 PyOD 检测异常值

原文:https://towardsdatascience.com/detecting-and-modeling-outliers-with-pyod-d40590a96488?source=collection_archive---------11-----------------------

顾名思义,异常值是与您的观察结果明显不同的数据点。换句话说,它们远离你的数据的平均路径。

在统计学和机器学习中,检测异常值是关键的一步,因为它们可能会影响模型的性能。也就是说,假设您希望根据售出的单位数量来预测公司的回报。

为此,您希望用简单的线性回归来拟合您的数据,因此您继续使用 OLS 策略来找到您的参数 alphabeta (要了解更多关于线性回归的信息,您可以在这里阅读我以前的文章):

很好,但是如果在你的数据中,有一个异常值呢?

如您所见,回归线更陡,因为它还想捕捉异常值的影响。但结果是,它在拟合所有其他数据点时不太准确。一种可能的解决方法是,一旦检测到所有的异常值(我们将在后面看到如何做),简单地删除它们,或者更复杂一点,用该特征的平均值或中值替换它们。

然而,在这个过程中有一个陷阱。的确,离群值(至少不是全部)未必是坏事。事实上,它们可以包含偏离平均模式的相关信息,这种偏离在未来可能会重复。因此,一个没有捕捉到这些信息的模型将不能防止或至少在预测时模拟这些偏差。

也就是说,想象一个有许多机器工作的工厂。后者需要随着时间的推移进行监控:假设你只需要记录他们的压力。它可能会遵循一个给定的模式,这取决于一天中的时刻和工作流的数量。然后,你突然检测到压力值的峰值,然后一切恢复正常。直觉上,你是要忽略你刚刚看到的,还是要沉湎于这个高峰?也许这个峰值预测到了一个技术问题,因此你最好结合这个信息,并使用它来防止潜在的故障。

因此,在异常值检测中需要特别注意,尤其是在那些一旦遗漏就会产生高昂代价的领域(想想欺诈检测、网络安全等等)。这就是为什么有必要使用特定的算法进行异常检测,而不是简单的可视化方法,如直方图和箱线图。

这就是 PyOD 来帮忙的地方。

PyOD 离群点检测算法

PyOD 是一个 Python 包,你可以通过控制台上的 pip install pyod 轻松安装。它提供了多种功能或算法来以有效的方式检测异常值,每个功能或算法都返回一个所谓的异常值:它将为每个数据点标记一个数字,该数字将与内部阈值进行比较,以确定该数据点是否为异常值。让我们检查其中的一些。

  • 基于角度的异常值检测(ABOD):它考虑每个点与其邻居之间的关系,而不考虑这些邻居之间的关系。它的加权余弦值相对于所有邻居的方差可以被视为异常值。ABOD 方法对于高维数据特别有用,因为在高维空间中,角度是比距离更稳健的度量。
  • k-最近邻:它使用分类算法 KNN 背后的数学。事实上,对于任何数据点,到其第最近邻居的距离都可以被视为离群值。PyOD 支持三种 KNN 检测器:最大值、平均值和中值,它们分别使用第 k 个邻居的距离、所有 k 个邻居的平均值和到 k 个邻居的中值距离作为离群值。
  • 隔离森林:它是遵循决策树和随机森林的理论建立的。在这种情况下,根是随机选择的,其思想是离群值应该位于根附近。这是因为正常点需要许多分区来识别,而离群点将很容易通过较少的分区来识别。
  • 局部相关积分(LOCI):对于检测异常值和异常值组非常有效。它为每个点提供了一个轨迹图,总结了该点周围区域的大量数据信息。

让我们看看 KNN 的 Python 实现。

异常值检测的 KNN

首先,让我们简单回顾一下 KNN 的实际工作原理。

KNN 可能是分类任务中最简单的算法。它的核心思想是相似的观测值应该彼此靠近。具体是什么意思?假设我们有以下两类观察结果:

我们的班级是正方形和三角形。现在,我们面临一个新的事件(带圆圈的观察),我们想确定它是三角形还是正方形:

正如预期的那样,KNN 根据“相似性”进行推理,而“相似性”在数学术语中可以翻译为“距离”。例如,在这里我们可以计算我们的绿色观察和一些最近的观察之间的欧几里德距离(后者的数量是我们在训练模型之前必须设置的值,通常用 K 表示)。然后,我们简单地计算每个类的最近邻的数量:最高的数量决定了新观察的成员。

也就是说,如果我们设置 K=3,我们将面临以下情况:

我们可以计算两个正方形和一个三角形,因此新的数据点应该是一个正方形。一个很好的经验法则:试着把你的 K 设为奇数,这样你就可以避免一半一半的计算。

现在让我们用 Python 实现它。首先,PyOD 提供了一些嵌入式函数来创建一个包含少量异常值的随机数据集:

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
from pyod.models.knn import KNNfrom pyod.utils.data import generate_dataoutlier_fraction = 0.1  
n_train = 200 
n_test = 100X_train, y_train, X_test, y_test = generate_data(n_train=n_train, n_test=n_test, contamination=outlier_fraction)#let's plot our train and test setfeature_1_train = X_train[:,[0]].reshape(-1,1)
feature_2_train = X_train[:,[1]].reshape(-1,1)
feature_1_test = X_test[:,[0]].reshape(-1,1)
feature_2_test = X_test[:,[1]].reshape(-1,1)# scatter plot 
plt.scatter(feature_1_train,feature_2_train)
plt.scatter(feature_1_test,feature_2_test)
plt.xlabel('feature_1')
plt.ylabel('feature_2')

现在让我们用我们的 KNN 模型进行训练和预测。

knn=KNN(contamination=outlier_fraction)
knn.fit(X_train)# get the prediction labels and outlier scores of the training data
y_train_pred = knn.labels_  
y_train_scores = knn.decision_scores_ # get the prediction on the test data
y_test_pred = knn.predict(X_test)  
y_test_scores = knn.decision_function(X_test)# no of errors in test set
n_errors = (y_test_pred != y_test).sum()
print('No of Errors in test set: {}'.format(n_errors))
#accuracy in test set
print('Accuracy in test set: {}'.format((n_test-n_errors)/n_test))

不错,我们的算法能够正确地分类几乎所有的异常值。让我们也想象一下装配过程:

from pyod.utils import example
example.visualize(knn, X_train, y_train, X_test, y_test, y_train_pred, y_test_pred, show_figure=True, save_figure=False)

正如预期的那样,一旦正确地检测到我们的异常值,我们必须决定如何处理它们,或者换句话说,如何整合其中包含的信息。对异常值建模远非易事,它是统计学和数据科学中的一个开放话题。举个例子,一个有趣的研究领域是极值理论或极值分析(EVA)。它是统计学的一个分支,处理概率分布中值的极端偏差。它试图从给定随机变量的给定有序样本中,评估比任何先前观察到的更极端的事件的概率。

这篇文章是关于检测程序的,我不打算详述“建模”步骤。然而,如果你对这个话题感兴趣,我推荐这些进一步的阅读材料:

  • http://manuals . mikepoweredbydhi . help/2017/General/EVA _ scidoc . pdf
  • https://www.ncl.ucar.edu/Applications/extreme_value.shtml

使用图像识别检测红外无人机镜头中的动物

原文:https://towardsdatascience.com/detecting-animals-in-infrared-drone-footage-using-image-recognition-bfdd8da30ba3?source=collection_archive---------31-----------------------

今年早些时候,我设计了一个系统,能够在红外无人机镜头中找到并计数动物。我开始测试一些不同的技术,以证明它是可靠的。

与往常一样,我的解决方案是松散耦合和模块化的,如果有更好或更具成本效益的选项可用和/或未能满足预期,则允许轻松更换组件。在这个过程中,我提出并测试了三种我认为可以完成这项工作的不同架构。

探测动物

我还没有我需要的所有无人机镜头,所以我从 YouTube 上获得了一些野猪的样本红外镜头进行测试。YouTube 上的一些镜头是从直升机上拍摄的,一些是从地面拍摄的。我想给我的模型最好的机会来发现猪,所以我收集了尽可能多的例子,从我收集的视频中抓取截图。很多镜头里也有郊狼,所以我也趁机收集了它们的照片。

总的来说,我会说我使用的数据很低。很多图像都很模糊,最终图像非常小,有些只有大约 100x100 像素。我使用了大约 200 个样本进行测试,这也是一个很小的数字,但我决定从那里开始,继续进行乏味的谈话,只在我需要的时候收集更多的截图。

以下是我收集的一些图片类型的例子…

Wild Hogs in Infrared

Wild Coyotes in Infrared

Examples of some of the testing images I used

张量流

我仔细阅读了莱奥·博科特的文章《使用 Tensorflow、OpenCV 和 Docker 进行实时和视频处理对象检测》并以此为基础建立了我的张量流模型。我选择了 Tensorflow ,因为我已经知道目标检测已经在这个平台上被广泛研究过,而且我已经很熟悉它了。

TensorFlow 是一个为高性能计算而构建的开源机器学习库。其灵活的架构允许跨各种平台轻松部署计算,从台式机到服务器集群,再到移动和边缘设备。

Ubuntu 上的定制 TensorFlow 实现在许可方面不需要任何成本,但是在基础设施和开发时间方面需要成本。好处是,你得到了一个专门构建的人工智能,它有可能产生更好的结果,规模更便宜,可以扩展和定制。

优点:

  • 使用成本低廉。
  • 可以根据需要无限修改。
  • 可以对模型进行微调,以获得所需的结果。
  • 可以受益于其他数据以及图像数据;该模型可以使用诸如位置或天气数据之类的附加特征进行训练,

缺点:

  • 在图像分类方面可能比现成的商业系统慢,这取决于基础设施。
  • 将需要维护一个托管服务器。
  • 模型需要开发,增加了开发成本和时间。
  • 需要更多的镜头才能像商业模型一样精确。
  • 训练这个模型需要更多的时间。

实施步骤:

1-设置 Ubuntu 服务器

2-安装 Python 和 Tensorflow 以及服务器。

3-用相关图像训练模型。

4 —测试模型中的预测。

这个模型的一个很大的优点是,我已经为解析视频设置了它,它可以在一帧中标记多个结果。其他 API 端点系统会要求我一帧一帧地发送镜头,只有微软认知服务可以在一幅图像中给我多个结果的详细边界框信息。

微软认知服务

认知服务是 Azure 中的一组仪表板和 API,允许开发人员访问智能流程,如图像识别和语音以及应用程序的语言理解。

Azure Custom Vision 是计算机视觉认知服务的一部分,它允许您构建、部署和改进您自己的图像分类算法,这些算法构建在 Azure 图像识别 GUI 中。所提供的人工智能服务可以在接受监督训练后,根据图像的视觉特征将标签应用于图像。可以通过 REST API 调用将图像发送给训练好的模型进行分类,并以 JSON 格式返回结果。

优点:

  • 易于使用和培训。
  • 不需要拥有强大的高端服务器或强大的高端电脑或手机来使用这项服务。
  • 这个系统是微软改进的。

缺点:

  • 不能修改模型,只能训练它。
  • 必须连接到互联网才能使用该模型。
  • 只能受益于图像数据;无法使用位置或天气数据等附加功能来训练模型。

使用该模型非常简单,结果可以返回包围盒信息,这正是我所需要的。正如我之前提到的,认知服务的主要优势是我能够一次标记多个图像。这对于我的用例来说至关重要,因为一幅图像中很可能同时出现不止一只动物。

西米拉尔

捷克公司 Ximilar 提供计算机视觉服务,这是为挑战图像识别领域的谷歌和微软而建立的。我发现它是一个非常有能力的选择,而且非常容易上手。Ximilar 团队与我进行了很多交流,他们给我提供了手动培训模型,并就如何充分利用他们的平台向我提供了建议。我强烈推荐和这个团队一起工作,因为我发现他们的高度开放和服务令人耳目一新。

为了使用该平台,我将我的训练图像上传到 Ximilar,并使用 GUI 标记它们。GUI 允许我配置训练服务来自动翻转和旋转我的图像,并随机改变它们,添加静态和改变它们的颜色。这是完美的,因为它允许我模拟不同类型的红外和图像,可以从空中的无人机以各种角度拍摄。

Some of my Training Images Tagged in Ximilar

我尝试了一些不同的场景,如下图所示,只用了少量的图片就获得了非常有希望的结果。我未来的测试将会让模型在更大的图片中找到动物。

Detection Rates for a Hog or Coyote Comparer

Detection Rates for a Comparer that Differentiates Between Hog Tops or Sides and Coyotes

下面的测试表明需要更多的数据和更高质量的图像。我用一张不相关的图片进行了测试,但模型觉得它仍然需要对一些东西进行分类…要么是这样,要么是火影忍者看起来像一只跃起的猪?

Naruto Runner or Hog?

调试该问题的尝试显示了一个局限性。结果返回的图像上没有坐标,平台仅返回图像中有结果以及结果是什么:

Ximilar JSON Sample

这是一个限制,如果我后来在实现过程中问了 Ximilar 团队,他们也许能够帮助我纠正。

设计系统

为了补充关键的人工智能组件,并为该领域提供一个可用的系统,我需要一个围绕它的系统,允许无人机向模型发送信息,并让用户获得有关镜头的信息。这将意味着无人机必须在 TensorFlow 的情况下发送视频,或者将图像作为帧发送给我基于网络的模型。其他数据,如飞行遥测数据,需要从无人机上提取。DAT 文件,如果我想在未来使用它。其中一个就是用它来产生。可以直观地查看航班 KML 映射文件。

外围组件

Azure Blob Storage 是微软面向云的对象存储解决方案。Blob 存储针对存储大量非结构化数据进行了优化。非结构化数据是不符合特定数据模型或定义的数据,如文本或二进制数据。我想从无人机和气象网站上尽可能多地收集这些信息,因为我认为温度、天气和月相有可能在我们尚不了解的动物位置中发挥作用。

Xamarin 是一个跨平台的框架和工具包,允许开发人员高效地创建可以在 iOS、Android 和通用 Windows 平台之间共享的原生用户界面布局和应用。我计划用它作为我的应用框架,因为它是基于 C#的,可以很容易地部署到 Azure,这意味着我只需要为 iOS 和 Android 开发一个应用。

Azure Functions 是一个在云中轻松运行小块代码的解决方案。您可以只为手头的问题编写所需的代码,而不必担心整个应用程序或运行它的基础结构。我认为这是一个不错的解决方案,可以处理 WebAPI 请求,并将不同的数据和结果发送到需要的地方。

Ubuntu 是一个免费开源的 Linux 发行版。我计划将 Tensoflow 实现放在 Ubuntu 服务器上,而不是放在运行 Ubuntu 的 docker 容器中。

使用张量流的系统

Animals in IR Drone Footage Detector Using TensorFlow

训练步骤 1 红外视频镜头和飞行数据由开发者从无人机上下载。

训练步骤 2
开发人员获取图像数据和飞行数据,并将其发送到 Ubuntu 服务器,在那里可以使用这些数据来训练自定义 Tensorflow 模型。

训练步骤 3 开发者获取图像数据和飞行数据,并基于飞行数据和来自镜头的每一帧的图像的组合特征,使用它来训练定制 Tensorflow 模型。

训练步骤 4 模型产生,转换成可用于自定义 Tensorflow 预测服务的格式,并冻结导出。

训练步骤 5 将冻结的模型加载到自定义 Tensorflow 预测服务中,用于预测。

预测步骤 1 用户使用无人机进行监视/侦察飞行,收集红外图像和无人机飞行数据。

预测第二步 从无人机上下载数据,并发送给跨平台的 Xamarin app。这款应用可以在 iOS 或 Android 设备上使用。

预测步骤 3 用户使用应用程序选择要发送给人工智能进行预测的视频。用户可以修剪镜头的开头或结尾,以避免发送不相关的起飞和着陆镜头。该应用程序自动将数据文件与视频文件相结合,并对数据进行适当的修剪/清理。

使用步骤 1 App 取裁剪好的素材,分离成每秒 5 帧的视频,并将每一帧发送给 Azure Function App。同时,该应用程序将数据和镜头上传到 Azure Blob 存储中,以供存档和未来使用。

使用步骤 2 功能 app 调用 Ubuntu 服务器上的 AI,为每张图片预测内容。预测结果返回到功能应用程序,然后将每一帧的预测结果传递回 Xamarin 应用程序,Xamarin 应用程序从这些预测结果中组装一个缩短的视频,其中只有包含动物的帧,并将其保存到 Xamarin 应用程序中的用户视频库中。包含动物的帧的时间被识别并用于从中提取位置数据。DAT 文件,并生成一个. KML 文件的地图可视化。

使用认知服务的系统

Animals in IR Drone Footage Detector Using Microsoft Cognitive Services

训练步骤 1 红外视频镜头和飞行数据由开发者从无人机上下载。

训练步骤 2
开发人员仅从素材中提取图像,并将其上传至自定义视觉训练仪表板。

训练第三步 开发者使用上传的镜头,通过微软的定制视觉训练仪表盘来训练模型。

训练步骤 4 然后将训练好的模型附加到定制视觉预测服务,以供 Xamarin 应用程序通过 API 调用使用。

预测步骤 1 用户使用无人机进行监视/侦察飞行,收集红外图像和无人机飞行数据。

预测步骤 2 从无人机上下载数据,并发送给跨平台的 Xamarin app。这款应用可以在 iOS 或 Android 设备上使用。

预测步骤 3 用户使用 app 选择想要发送给 AI 进行预测的视频。用户可以修剪镜头的开头或结尾,以避免发送不相关的起飞和着陆镜头。

使用步骤 1 该应用程序获取经过修剪的镜头,将其分成每秒 5 帧的视频,并将每一帧发送给 AI。同时,该应用程序将数据和镜头上传到 Azure blob 存储中,以供存档和未来使用。

每一帧的预测结果都会返回给应用程序,应用程序会根据这些结果汇编一个缩短的视频,其中只有包含动物的帧,并将其保存到应用程序中用户的视频库中。

包含动物的帧的时间被识别并用于从中提取位置数据。DAT 文件,并生成一个. KML 文件的地图可视化。

使用 Ximilar 的系统

Animals in IR Drone Footage Detector Using Ximilar

训练步骤 1
红外视频镜头和飞行数据由开发者从无人机上下载。

培训步骤 2
开发人员仅从素材中提取图像,并将其上传至 Ximilar 仪表盘。

训练步骤 3 开发人员使用上传的素材,通过 Ximilars Training dashboard 训练模型。

训练步骤 4 然后,Xamarin 应用程序可以通过 API 调用访问训练好的模型。

预测步骤 1 用户使用无人机进行监视/侦察飞行,收集红外图像和无人机飞行数据。

预测步骤 2 从无人机上下载数据,并发送给跨平台 Xamarin app。这款应用可以在 iOS 或 Android 设备上使用。

预测第三步 用户使用 app 选择想要发送给 AI 进行预测的视频。用户可以修剪镜头的开头或结尾,以避免发送不相关的起飞和着陆镜头。

使用步骤 1 应用程序获取修剪后的素材,将其分成每秒 5 帧的视频,并将每一帧发送给 AI。同时,该应用程序将数据和镜头上传到 Azure blob 存储中,以供存档和未来使用。

每一帧的预测结果都会返回给应用程序,应用程序会根据这些结果组装一个缩短的视频,其中只包含包含动物的帧,并将其保存到应用程序中用户的视频库中。

包含动物的帧的时间被识别并用于从中提取位置数据。DAT 文件,并生成一个. KML 文件的地图可视化。

结论

设计完系统后,Ximilar 告诉我他们的平台经历了一次重大升级,现在该平台可以标记图像,允许一个以上的标记被分配给一个图像。根据这些信息,我会选择 Ximilar 作为这个系统,因为它简单,价格也比认知服务便宜。后来,如果我想包括无人机或天气数据等补充数据,我会将 Ximilar 替换为 TensorFlow。

为了使该解决方案的人工智能/机器学习(AI/ML)组件准确,我认为在我将它用于生产之前,每只动物至少需要 4000 个不同的训练示例。根据我的简单测试,我认为该系统能够达到大约 70%的准确率。

关于西澳大利亚的野猪

在我的例子中,我主要是试图检测野猪。在西澳大利亚,野猪是由定居者引入的,是许多本地物种自然栖息地被破坏的原因。这是因为它们成群结队地移动,并在移动时翻动土地,挖掘土壤和树根,践踏植被。

佤邦政府发布了一份关于他们如何计划解决生猪问题的战略文件,可以在这里找到。政府最近为这个问题拨款 30 万美元,但是到目前为止,技术的使用仍然是基本的,仅仅依靠静态摄像机和 GPS 对一些猪进行监控。

利用深度学习检测多发性硬化患者的病变

原文:https://towardsdatascience.com/detecting-brain-lesions-in-multiple-sclerosis-patients-with-deep-learning-dc7e32950d1f?source=collection_archive---------16-----------------------

临床数据科学

医学图像分析中的卷积神经网络导论。

Photo by National Cancer Institute on Unsplash

介绍

深度学习的应用

深度学习 是基于 人工神经网络机器学习 方法的更广泛家族的一部分。深度学习最有前景的应用之一是图像分析,例如用于图像分割或分类。尽管分割为每个类别(即,每个像素属于 K 个类别中的一个)产生每个像素的概率分布(也称为掩模),但是分类为整个图像产生概率分布(即,每个图像属于 K 个类别中的一个)。如今,软件解决方案几乎随处可见,例如在 医学成像 中。在测试新药的临床研究中,人们感兴趣的是检查新药是否能改变组织的状况,例如减少炎症。这些都可以通过医学图像来监控,这些医学图像是通过成像技术创建的,如X 射线计算机断层摄影(CT) ,甚至是常规的光学显微镜。然而,对生成的图像进行分割或分类是困难的,即使对于专家来说,这也是一项耗时且昂贵的任务;问题是这是否可以自动化以节省时间和金钱。这篇文章旨在为基于深度学习的医学图像分析提供一些直觉(重点是使用来自前挑战的数据在多发性硬化症患者中进行病灶分割)。

多发性硬化

多发性硬化(MS)是一种脱髓鞘疾病,其大脑和脊髓中神经细胞的绝缘套受损。MS 的三个主要特征是中枢神经系统 病变 的形成(也叫斑块)、炎症、神经元髓鞘的破坏。这种损伤破坏了部分神经系统的交流能力,因为信号转导被扭曲。 磁共振成像 (MRI) 大脑和脊柱可能出现脱髓鞘区域(病变或斑块)。虽然原因尚不清楚,但潜在的机制被认为是免疫系统的破坏或产生髓鞘的细胞的失败。对此提出的原因包括遗传和环境因素,如由病毒感染引发。这种疾病的名称是指在神经系统中形成的疤痕(巩膜——更好的说法是斑块或病变)。尽管目前还没有治愈多发性硬化症的方法,但几种疗法已经被证明是有帮助的。治疗的主要目的是恢复发作后的功能,防止新的发作,并防止残疾。当磁共振成像上出现两个以上的病变时,一般建议在首次发作后开始药物治疗。正在进行的研究正在寻找更有效、方便和可耐受的复发-缓解型 MS 治疗方法,为进展型亚型创造疗法,神经保护策略和有效的对症治疗(但为了评估新疗法的疗效,廉价和标准化的疾病进展检查将是有帮助的)。****

医学成像

如上所述的医学成像技术通常基于不可见光,即人眼可见光谱之外的光(380-750 纳米)。例如,核磁共振扫描仪利用无线电波(波长 1 毫米到 10 公里)生成人体器官的图像。与 MRI 相反,CT 和常规 X 射线成像使用波长为 250 pm 至 10 nm 的光(称为 X 射线,因此得名)。(注意,X 射线能量丰富,会造成细胞损伤,玩的时候要小心。)其他诊断方法如 脑电图 不产生经典图像作为主要输出,而是产生纯电信号(技术上,每种数字诊断方法都在某个点产生电信号,但在成像中,它们通过 傅立叶变换 映射以产生图像)。x 射线成像和超声波生成 2D 图像,而 CT 和 MRI 生成图像体(3D 图像),这使得它们更难以分析以发现病变组织,例如大脑中的病变组织。然而,单个切片的行为类似于常规图像。下面是不同成像模式/设置(例如质子密度(PD)液体衰减反转恢复(FLAIR) 等)下的大脑样本 MRI 切片( 神经成像 )。)显示。

Example of different MRI imaging methods (top left to bottom right: FLAIR, MPRAGE, PD, T2) with a sample Gaussian-filtered version of a T2 weighted image, and a mask/label with white lesion pixels. (images by author)

上图(右图)显示了多发性硬化症患者的三个病变区域。一个病变是通常由多发性硬化症等疾病引起的机体组织的任何损伤或异常变化。为了检查针对多发性硬化症的治疗效果,必须随着时间的推移观察这些区域,以评估治疗是否可以实现任何身体改善,例如通过测量图像体积中病变的总体积。请注意蒙版中的黑色像素比白色像素多得多。黑白图像被表示为秩二 张量 (在术语 矩阵 下更为人所知),其中每个条目表示一个 像素 的强度。值的范围从 0 到 255,因为其表示形式为 8 位,但是在输入网络之前,条目被归一化到范围[0,1]——值越高,像素越亮。彩色图像是三阶张量,其中一维在不同颜色通道上迭代(例如 RGB 颜色空间 )。类似地,3D 彩色图像体积是秩 4 张量。然而,颜色通道可以包含不同的成像模式(PD、T2 等。)或者甚至是所述模式的高斯滤波图像。MR 图像体积的尺寸为:

**[nx_voxels, ny_voxels, nz_voxels, n_channels]**

体素 是一个图像体的 像素 的类似物。典型的 MR 图像大约有 200 个 x 200 个 x 200 个体素。这产生每个通道总共 8.000.000 个体素。假设有 4 个通道(针对 4 种不同模式),则得出 32.000.000(!)体素。包含所有类的所有掩码的输出具有维度:

**[nx_voxels, ny_voxels, nz_voxels, n_classes]**

映象分析

卷积神经网络

通过卷积神经网络已经建立了图像分析的黄金标准,并且发现良好的网络架构已经成为最近研究的主要目的。CNN 由 卷积层 组成,这些卷积层由 内核 (也称为滤波器)定义,对于 2D 图像来说是二阶张量,对于填充了权重的 3D 图像来说是三阶张量。卷积是一种映射,它通过悬停在输入上并使用所有通道的核条目对图像张量条目进行加权来生成新图像。这些新图像被称为特征地图。********

Convolution operation on a 7x7x3 image (three input channels) with two 3x3 filters (source). Note how every input channel has different weights for each filter.

通常,在 CNN 的单个层中使用许多过滤器,这些过滤器是在训练(推断)阶段学习的,即以感兴趣的区域比不相关的区域更明显的方式设置权重。在一个卷积层之后,一些激活函数 ( sigmoid , rectifier )被应用于特征图,其后面还可以跟随一个 汇集层 。在 CNN 中,计算卷积层(有时是汇集层)与激活函数的顺序映射,这放大了网络过程中的某些模式,因为每个操作的输出又是一个特征图。

****### convolutional layer (vertical line detector)****from** scipy.signal **import** convolve2d
kernel = np.array([
[1,0,-1],
[1,0,-1],
[1,0,-1]])feature_map = convolve2d(image, kernel, mode='same')**### pooling layer****def** pool2d(X, pool_size, mode='max'):
   p_h, p_w = pool_size
   Y = np.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1))
   **for** i **in** range(Y.shape[0]):
       **for** j **in** range(Y.shape[1]):
           **if** mode == 'max':
               Y[i, j] = X[i: i + p_h, j: j + p_w].max()
           **elif** mode == 'avg':
               Y[i, j] = X[i: i + p_h, j: j + p_w].mean()
   **return** Ypool_size = (3, 3)
pooled_image = pool2d(feature_map, pool_size, mode='max')**

下面,一个 3 x 3 卷积和一个用于垂直边缘检测步距为 1(上面的例子)以及一个 3 x 3 最大池被可视化。请注意垂直线在滤镜贴图中是如何变得更加明显的(分隔形状的垂直边缘比其他边缘更清晰,即不那么模糊)。此外,池化操作会使图像变得更粗糙。

Left: Original MR image. Mid: Convolved image. Right: Convolved and maximum-pooled image. (images by author)

从上面的图像来看,病变无论如何都很难被发现,因为它们与周围的区域融合在一起。必须以某种方式设计滤波器(在训练阶段学习),使得损伤是特征图中的明显纹理。您也可以认为,使用其他 MR 成像模式可以改善结果,但最终需要不同模式的组合和额外的高斯滤波版本来唯一识别病变。不同的图像模式堆叠在一起,充当输入中的单独通道。因此,卷积层的一般形状为:

**[nx_filter, ny_filter, nz_filter, n_input_channels, n_filters]**

因此,单个卷积层的参数数量为:

****### parameters for kernels/filters**
p_f = n_in * (nx_f * ny_f * nz_f) * n_f**### parameters for biases (each filter has one bias term)**
p_b = n_f**### total number of parameters**
p_total = p_f + p_b**

假设有 3 个输入通道和 16 个形状滤波器(5 x 5 x 5),该层的参数总数为:

**p_total = 3 * 16 * (5 * 5 * 5) + 16 = **6016****

An example of selective random sampling. (image by author)

注意,对于体积图像,使用三维过滤器。如上所述,体积由几百万个体素组成,这使得当前处理整个体积是不可行的,并且必须使用子样本来代替(例如 80 x 80 x 80 个体素)。它在边界区域提供较少的上下文,这将导致较差的性能,但是它需要较少的计算能力。但是,最好以随机方式执行;由于类别的不平衡,通过选择性随机采样控制子体积中的类别分布很重要,即偶尔丢弃没有损伤的子体积。

模型架构

根据问题(例如,是否执行分类或分割)和图像维度(2D 或 3D),有不同的 CNN 架构(也称为拓扑); U-Net3D-U-NetV-Net 是分割任务中比较知名的,而 ResNet 在分类任务中被证明是高性能的。它们由数百万个(10+以上)可训练参数组成。当前病灶分割的最高分在 91.7–93.4%的范围内。

Scheme of the V-Net for volumetric image segmentation (source).

V-Net 由具有规则卷积的部分组成,在这种情况下也称为向下卷积,其生成特征图。在网络的另一部分, up 卷积(也称为转置卷积)则相反。一个卷积是一个卷积的逆运算(卷积)——点击阅读更多关于的内容。在网络的末端,1 x 1 x 1 卷积移除剩余通道,并根据类别数量使用 sigmoidsoftmax 激活函数为每个像素/体素分配类别标签。****

Left: Original T2-weighted image. Mid: Original mask. Right: Prediction. (images by author)

如上所述,肿瘤分割是不平衡数据集问题的一个例子,这使得开发适当的解决方案更加困难。在这种情况下,模型通常会将数据集中样本较少的类错误分类,在这里它将是一个病变像素。这个问题可以通过在损失函数的计算中给每个类的贡献分配权重来解决,该损失函数通常被公式化为(二元)交叉熵 。校正不平衡的其他损失函数是可能的,例如 骰子损失

****### dice loss****def** dice_loss(output, target, axis=[1, 2, 3], smooth=1e-5):
   inse = tf.reduce_sum(tf.multiply(output, target), axis=axis)
   l = tf.reduce_sum(tf.multiply(output, output), axis=axis)
   r = tf.reduce_sum(tf.multiply(target, target), axis=axis)
   dice = (tf.constant(2.0) * tf.cast(inse, dtype=tf.float32) +
   tf.constant(smooth)) / (tf.cast(l + r, dtype=tf.float32) +
   tf.constant(smooth))                           
   dice = tf.reduce_mean(dice)                           
   **return** tf.constant(1.0) - dice**

除了纯卷积神经网络之外,还有受视频图像分割启发的发展。视频由在时域中相关的图像(也称为帧)组成,即单个帧在可能的许多时间步长上相互依赖。为了处理任何种类的序列数据(文本、音频、时间序列),使用递归神经网络,例如作为长短期记忆(LSTM) 单元,或门控递归单元(GRU) 。通过将 MR 体积中的三维之一视为时间坐标,卷积 LSTM 和 GRU 实现已经被开发用于医学图像分析。

数据扩充和规则化

虽然探索网络架构的空间很重要,但通过在模型中集成(即时) 数据增强正则化 技术,也可以实现更好的性能,这减少了方差并避免了过拟合( 偏差-方差权衡 )。数据扩充和正则化方法的目标是避免过度拟合,并开发一个概括良好的模型,即以高准确度/精确度/召回率预测以前没有见过的数据。一方面,可以通过从数据集中采样并对其应用变形、缩放或旋转等变换来创建合成数据;加上选择性随机采样,标记的训练数据量可以增加(如果你需要一个实现了这些特性的,我可以把你带到我的 GitHub。另一方面,drop connect(是 DropOut )有助于单个神经元的不相关。********

Photo by Ali Yahya on Unsplash

检测语言共现网络中的社区

原文:https://towardsdatascience.com/detecting-communities-in-a-language-co-occurrence-network-f6d9dfc70bab?source=collection_archive---------9-----------------------

用 Python 实现 Igraph 中的社区发现算法

Photo by Perry Grone on Unsplash

在这篇文章中,我们将在 python 包 Igraph 中进行社区检测,尝试检测语言共现网络中的社区。这将使用两种流行的社区检测算法来实现:Walktrap 和标签传播

背景

全球语言共现网络(GLCNs)链接可能共同使用的语言。将语言共现表示为一个网络可以推断国际信息共享和知识转移。这包括该语言使用者接收信息的多样性、接收信息的速度以及母语使用者在全球传播信息的能力。

让我们从建立网络交换的正式基础开始。这是一个基本图形的思想,它由一组节点(或顶点)以及它们之间的一组链接(或边)组成。图可以是有向的(边表示单向关系)或无向的(边表示双向关系,因为每条边都可以双向遍历)。此外,一个图可以是双重的,在这种情况下,两个集线器之间的任何连接要么存在,要么不存在。另一方面,图可以是加权的,在这种情况下,任何连接都被赋予特定的权重或尊重,这通常是一个(正)数。这里的目的是展示关于复杂网络假设(和非正式社区调查)的网络形式概念的早期和简要交流,并描绘(大部分通过模型)通常用于在图论基础上识别网络的众多计算系统中的几个。在这里,我们通过使用现有的算法来发现图中的社区结构,来描绘全球语言共现网络中的语言共现的思想

步行陷阱

Walktrap 由 Pascal Pons 开发,是图论中的一种算法,用于通过随机行走来识别大型网络中的社区。这些随机行走然后被用于计算节点之间的距离。然后通过自底向上的分层聚类将节点分配到具有较小的社区内距离和较大的社区间距离的组中。当然,应该注意,该算法只考虑每个节点一个社区,这在某些情况下可能是不正确的假设。

标签传播

标签传播,或 LPA,由 U.N.Raghavan 提出,是一种近线性社区检测解决方案,受益于相当简单的实现。该算法的工作原理如下:

  1. 网络的特征是图 G(V,E),其中 V 是节点的全集,E 是边的全集。
  2. 对于节点 i(i ∈ V),设 Li 表示 I 的标号,N(i)表示其邻居的集合
  3. 在过程开始时,每个节点被分配一个唯一的标签,例如 Li = i
  4. 然后,这些标签在整个网络中传播,每个节点在每次迭代中将其标签更新为由大多数邻居共享的标签。
  5. 重复该过程,直到每个节点具有其邻居的最频繁标签之一,即,没有节点需要改变它们的标签。

6.最后,社区由共享相同标签的节点构成

资料组

麻省理工学院(MIT)的图书翻译全球语言网络将用于这篇文章。该数据集是一个有向网络,来自 1979 年至 2011 年全球出版的超过 220 万本书籍的翻译。翻译数据来自联合国教科文组织的翻译索引——印刷书籍翻译的国际索引。在网络中,节点代表不同的语言,而边代表一本书从一种语言到另一种语言的翻译。数据集中平移的频率(共现频率)可用于加权边。

Properties of the obtained graph

履行

我们选择的算法(Walktrap 和 Label Propagation)将使用 iGraph 包在 Python 中实现,测试准备工作相当简单。首先,iGraph 只需要 SourceNode、DestinationNode 和 Weight,幸运的是我们的数据集默认提供这 3 列。首先,我们可以使用 iGraph 函数将网络加载到工作区:Read_Ncol,如下所示:

import cairocffi
import igraphg = igraph.Graph.Read_Ncol('books.txt', directed = True)

我们可以简单地使用

igraph.plot(g)

要获得网络的图形表示:

Book Translation Network implemented in igraph

iGraph 中的 Community_walktrap 带两个可选参数;权重和步数,其中权重是包含要执行的随机行走长度中的边权重和步数的列表。使用 Read_Ncol 将权重自动分配为第三列,因此要在函数中指定权重,简单如下

weights=g.es[“weight”]

其中“g”是读入的图表。一般来说,在实施中使用 3、4 或 5 个步骤。在这篇文章中,我们将使用 4。

运行 community_walktrap 将返回一个 VertexDendrogram 对象,该对象最初是以最大模块性切割的。在这个对象上运行 as_clustering()会返回一个 VertexClustering 对象,它描述了一个图的顶点集的聚类情况。

wtrap = g.community_walktrap(weights=g.es["weight"], steps = 4)
clust=wtrap.as_clustering()

A sample of the VertexClustering object from the walktrap algorithm

虽然这很好,但看起来并不特别有趣!然后,我们可以使用 plot()在 iGraph 中绘制该结果,其中有两个参数 mark_groups 和**visual_style,其中 mark_groups 指定是否通过彩色多边形高亮显示某些顶点组,visual_style 指定视觉属性。我们可以简单地设置一个 python 字典,其中包含我们希望传递给 plot()的关键字参数,在本例中,plot()标记顶点标签。

visual_style = dict()
visual_style["bbox"] = (700, 600)
visual_style["vertex_label"] = g.vs["name"]igraph.plot(clust,mark_groups = True,**visual_style)

Plotting the output of the walktrap algorithm on our dataset

输出显示形成了两个主要社区,分别包含 71 和 94 个节点,以及第三个更小的社区,只有 3 个成员。剩余的 100 个节点(37.3%)每个都被分配到它们自己的集群(即 n=1),这在我们的社区定义中不计算在内。然而,这两个主要社区似乎围绕着英语和俄语,我们可以通过回顾顶点群集对象并查看每个社区的成员来进一步验证这一点。

标签传播是一种更简单的方法,不需要参数,但是有一些可选的参数;权重、初始权重和固定权重,其中权重与 walktrap 方法中的结构相同。然而,initial 可以是初始顶点标签的列表,而 fixed 是每个顶点的布尔列表,其中 True 对应于在算法期间标签不应改变的顶点。这最后两个参数在我们的测试中不是必需的,只有权重在参数中指定。与 walktrap 不同,标签传播不返回树图对象,而是直接返回顶点聚类对象,然后可以用与 walktrap 方法相同的方式绘制该对象。

labelProp = g.community_label_propagation(weights=g.es["weight"])
igraph.plot(labelProp,mark_groups = True,**visual_style)

Plotting the output of the Label Propagation algorithm on our dataset

正如 Walktrap 算法所发现的,在加权数据集上运行标签传播识别出两个大小相似的主要社区,分别有 70 个和 102 个成员。然而,还有两个小社区,分别有 3 名和 8 名成员。同样,由于该方法的聚集性,约三分之一的节点没有被分类到社区中(n=85,数据集的 31.7%)

值得注意的是,图的高权重和密集性质对算法在此分析中的工作方式有相当大的影响。例如,对于 walktrap,在一个未加权的图中,一个与邻居有 3 条未加权边的节点将有 1/3 的机会随机遍历每条边。然而,当考虑到权重时,选择高权重边(主要是英语和俄语)的概率变得极高,导致行走被卡在单个边上来回。标签传播的情况略有不同;每次迭代后,节点标签更新为其大多数邻居共享的标签。由于俄语和英语具有如此高的入度和出度,大多数节点在其邻域集中具有这两种语言中的一种,这意味着这些节点很可能会更新标签以匹配上述两种语言的标签,当考虑边权重时更是如此。

不使用边缘权重重新运行

尽管移除权重不会对标签传播的社区结构产生太大影响,但它会对 Walktrap 算法的结果产生很大影响。因此,我们可以重新运行算法,不指定权重:

wtrapnoweights = g.community_walktrap(steps = 4)
clustnoweights=wtrapnoweights.as_clustering()

VertexClustering object from Walktrap using an unweighted graph

我们已经可以看到更多的社区已经形成,这看起来是一个更有趣的结果。所以我们来策划一下吧!

wtrapnoweights = g.community_walktrap(steps = 4)
clustnoweights=wtrapnoweights.as_clustering()igraph.plot(clustnoweights,mark_groups = True, **visual_style)

Output of the walktrap algorithm on our dataset with no weights

重复测试,这一次给所有的边相同的权重产生了非常不同的结果。检测到十个社区,只有一个节点被分配到自己的集群。在已确定的社区规模方面也不太不平衡(平均 22.4 个节点成员;最低 3;最大 54)。这个结果实际上非常有趣,如果你看看 VertexClustering 对象,再看看 community 9,它表明所有的斯堪的纳维亚语言已经形成了一个社区,还有 community 7,它已经将许多亚洲语言聚集在一起,如朝鲜语和日语。

结论

在这篇文章中,我们使用图书翻译全球语言网络比较了两种聚集社区检测算法。我们发现,当使用加权网络时,两种方法都不会在数据集中生成许多不同的社区。相反,一般来说,形成了两个主要群体。这表明没有明显的语言群体,相反,在这个网络中,信息共享发生在国际一级。这一结论得到了以下事实的支持:通过定性地考虑社区成员的语系,我们确定了两种方法确定的两个主要社区在规模和组成方面的相似性。表明这些发现不是所用方法的产物。通过移除边权重,我们发现基础数据集的这一属性在社区形成中非常重要。然而,还不知道在这项工作中使用的边缘权重是否真正代表语言共现频率。边缘权重来自许多不同的国际图书馆向联合国教科文组织报告的数据。这些数据可能会受到不同地点的报告偏差的影响,不同的地点遵循不同的做法,并具有不同的完整性水平,而且它们也可能不是最新的。这需要进一步调查。

一个有趣的扩展可能是在图上重新运行算法,但是没有英语和俄语节点。我们预计这将返回一组更有趣的社区,它们不会受到对高度连接的节点和权重较大的边的较大偏好的影响。

感谢您查看这篇文章!虽然这不是我通常会创造的那种东西,但我发现社区检测的想法很吸引人。完整的信息和代码可以在下面的我的 Github 上找到

[## 哈里比特-概述

HarryBitten 有 4 个存储库可用。在 GitHub 上关注他们的代码。

github.com](https://github.com/HarryBitten)

下次再见!

利用机器学习检测信用卡欺诈

原文:https://towardsdatascience.com/detecting-credit-card-fraud-using-machine-learning-a3d83423d3b8?source=collection_archive---------3-----------------------

用数据科学抓坏人

这篇文章描述了我关于信用卡欺诈的机器学习项目。如果你对代码感兴趣,可以在这里找到我的笔记本。

Source: https://giphy.com/gifs/glitch-money-shopping-d3mmdNnW5hkoUxTG

介绍

E 自从开始我的数据科学之旅,我就一直在思考如何善用数据科学,同时创造价值。因此,当我在 Kaggle 上看到这个处理信用卡欺诈检测的数据集时,我立刻就被吸引住了。该数据集有 31 个特征,其中 28 个已被匿名,并被标记为 V1 到 V28。剩下的三个特征是交易的时间和金额,以及该交易是否是欺诈性的。在上传到 Kaggle 之前,匿名变量已经以 PCA(主成分分析)的形式进行了修改。此外,数据集中没有缺失值。有了对数据的基本描述,让我们开始一些探索性的数据分析。

探索性数据分析

由于几乎所有的预测因素都被匿名化了,在我的 EDA 中,我决定将重点放在未匿名化的预测因素交易时间和交易量上。数据集包含 284,807 项交易。所有交易的平均值为 88.35 美元,而该数据集中记录的最大交易金额为 25,691.16 美元。然而,正如你现在根据平均值和最大值所猜测的那样,所有交易的货币价值的分布是严重向右倾斜的。绝大多数事务相对较小,只有极小一部分事务接近最大值。

从数据集中的第一次交易开始,时间以秒数记录。因此,我们可以得出结论,这个数据集包括两天内记录的所有交易。与交易的货币价值分布相反,它是双峰的。这表明,在第一笔交易后大约 28 小时,交易量显著下降。虽然没有提供第一笔交易的时间,但有理由假设交易量下降发生在夜间。

班级分布呢?有多少交易是欺诈性的,有多少不是?可以预料,大多数交易都是非欺诈性的。事实上,该数据集中 99.83%的交易不是欺诈性的,而只有 0.17%是欺诈性的。下面的图像强调了这种显著的对比。

最后,知道我们的预测因子之间是否有任何显著的相关性,特别是关于我们的类别变量,将会很有趣。确定这一点的最直观的方法之一是使用热图。

正如你所看到的,我们的一些预测器看起来确实与类变量相关。尽管如此,对于如此大量的变量来说,似乎没有什么显著的相关性。这可能归因于两个因素:

  1. 数据是使用 PCA 准备的,因此我们的预测因子是主成分。
  2. 巨大的阶级不平衡可能会扭曲某些与我们的阶级变量相关的重要性。

数据准备

在继续我们的分析之前,重要的是不要忘记,虽然匿名化特征已经被缩放并且似乎以零为中心,但是我们的时间和数量特征却没有。如果不对它们进行缩放,将导致某些机器学习算法对特征进行加权(逻辑回归)或依赖于距离度量(KNN ),性能会差得多。为了避免这个问题,我对时间和数量列进行了标准化。幸运的是,没有缺失值,因此我们不需要担心缺失值插补。

为严重不平衡的数据集创建训练集

现在是具有挑战性的部分:创建一个训练数据集,让我们的算法能够挑选出使交易更有可能或更不可能是欺诈的具体特征。使用原始数据集不会被证明是一个好主意,原因很简单:因为我们 99%以上的交易都是非欺诈性的,所以总是预测交易是非欺诈性的算法将实现高于 99%的准确性。然而,这与我们想要的正好相反。我们不希望通过从不将交易标记为欺诈来实现 99%的准确性,我们希望检测欺诈交易并将其标记为欺诈交易。

有两个关键点可以帮助我们解决这个问题。首先,我们将利用随机欠采样来创建一个具有平衡类别分布的训练数据集,这将迫使算法检测欺诈交易,从而实现高性能。说到性能,我们不打算依赖准确性。相反,我们将利用受试者操作特征-曲线下面积或 ROC-AUC 性能测量(我在本文下面链接了进一步的阅读)。本质上,ROC-AUC 输出 0 到 1 之间的值,其中 1 是满分,0 是最差。如果一个算法的 ROC-AUC 得分高于 0.5,则它比随机猜测获得了更高的性能。

为了创建我们的平衡训练数据集,我对数据集中的所有欺诈交易进行了计数。然后,我随机选择了相同数量的非欺诈性交易,并将两者连接起来。在重组了这个新创建的数据集之后,我决定再次输出类分布,以直观显示差异。

异常检测和去除

离群点检测是一个复杂的话题。减少事务数量从而减少算法可用的信息量,以及让极端异常值扭曲预测结果,这两者之间的权衡并不容易解决,并且高度依赖于您的数据和目标。在我的例子中,我决定专门关注与异常值移除的类变量的相关性为 0.5 或更高的特性。在实际剔除异常值之前,让我们先来看看这些特性的可视化效果:

箱线图为我们提供了一个很好的直觉,即我们是否需要担心异常值,因为所有超出 1.5 倍 IQR(四分位间距)的交易通常都被认为是异常值。然而,删除 1.5 倍 IQR 之外的所有交易将显著减少我们的训练数据大小,这本来就不是很大。因此,我决定只关注 2.5 倍 IQR 之外的极端异常值。

基于 t-SNE 的可视化降维方法

可视化我们的类将被证明是非常有趣的,并向我们展示它们是否是明显可分的。然而,不可能使用我们所有的预测值来绘制一个 30 维的图。相反,使用 t-SNE 等降维技术,我们能够将这些高维分布投射到低维可视化中。对于这个项目,我决定使用 t-SNE,一种我以前没有用过的算法。如果你想知道更多关于这个算法是如何工作的,请看这里。

将我们的数据集投影到一个二维空间中,我们能够生成一个散点图,显示欺诈性和非欺诈性交易的聚类:

分类算法

到了你可能一直在等待的部分:训练机器学习算法。为了能够测试我们算法的性能,我首先执行了 80/20 的训练测试分割,将我们平衡的数据集分割成两部分。为了避免过度拟合,我使用了非常常见的 k-fold 交叉验证的重采样技术。这只是意味着您将训练数据分成 k 个部分(折叠),然后在对第 k 个保持折叠进行预测之前,在 k-1 个折叠上拟合您的模型。然后,对每一个折叠重复这一过程,并对结果预测进行平均。

为了更好地了解哪种算法最适合我们的数据,让我们快速抽查一些最流行的分类算法:

  • 逻辑回归
  • 线性判别分析
  • k 最近邻(KNN)
  • 分类树
  • 支持向量分类器
  • 随机森林分类器
  • XGBoost 分类器

抽查的结果如下所示:

正如我们所见,有几个算法明显优于其他算法。现在,我们选择什么算法?如上所述,该项目不仅注重实现最高的准确性,还注重创造商业价值。因此,选择 Random Forest 而不是 XGBoost 可能是一种合理的方法,这样可以在稍微降低性能的同时实现更高程度的全面性。为了进一步说明我的意思,这里有一个我们的随机森林模型的可视化,可以很容易地用来非常简单地解释为什么做出某个决定:

结论和未来工作

欺诈检测是一个复杂的问题,需要在使用机器学习算法之前进行大量的规划。尽管如此,这也是数据科学和机器学习的良好应用,确保客户的钱是安全的,不容易被篡改。

未来的工作将包括我前面提到的随机森林算法的全面调优。具有非匿名化特征的数据集将使这一点特别有趣,因为输出特征重要性将使人们能够看到哪些具体因素对于检测欺诈性交易最重要。

一如既往,如果您有任何问题或发现错误,请不要犹豫,联系我。本文开头提供了包含我的代码的笔记本的链接。

参考文献:

[1] L.J.P. van der Maaten 和 G.E. Hinton,使用 t-SNE 可视化高维数据 (2014),机器学习研究杂志

[2]机器学习小组— ULB,信用卡欺诈检测 (2018),Kaggle

[3] Nathalie Japkowicz,从不平衡数据集中学习:各种策略的比较 (2000),AAAI 技术报告 WS-00–05

在 iOS 上检测可爱的动物:续

原文:https://towardsdatascience.com/detecting-cute-animals-on-ios-a-continuation-a5fd6beec1d9?source=collection_archive---------36-----------------------

在 iOS 上构建自定义图像分类器应用程序

Photo by Austin Kirk on Unsplash

之前写过为一部手机做一个带机器学习的可爱动物探测器。当时,我必须只为 Android 开发,因为 iOS 工具与我用来训练模型的工具不兼容。但是现在 iOS 工具更新了,我有了一些时间,所以下面是我在 iOS 上实现我的可爱动物检测器所做的事情。

转换模型

在 iOS 上,CoreML 是用于机器学习模型的格式。苹果提供了工具,能够以一种简单明了的方式将我拥有的 Keras 模型转换成 CoreML 。

Converting the trained model to be used on iOS

与 Android 的情况一样,转换器需要提供输入形状。然而,在这种情况下,输入张量中的第一个维度必须为零,而不是设置为 1。需要 image_input_names 和 class_labels,以便 iOS 应用程序知道模型 1)处理图像,2)是分类器。这使得编写应用程序代码更加容易,因为有专门用途的 API 可用。

在 iOS 上读取相机

该应用需要在 iOS 和 Android 上做同样的事情:

  1. 在屏幕上显示相机预览
  2. 让用户按下按钮来捕捉当前图像
  3. 将捕获的图像输入分类器
  4. 分类完成后显示结果

图像捕捉的 Android 实现实际上没有使用相机。相反,当用户按下按钮时,它会以位图的形式获取预览内容,并生成图像进行分类。在 iOS 上,我没有找到将预览内容提取为位图的方法,所以我选择了指示相机拍摄正确图片的路线。

Photo by Amy Chen on Unsplash

在应用程序可以访问摄像机之前,用户必须授予它权限。还有其他可能的授权状态,当被询问时,用户可能会拒绝许可,但是对于一个仅关于使用相机的示例应用程序,我认为假设许可已经或将要被授予是没问题的。

Checking for permission to use the camera, and requesting it if needed

对于相机的自定义使用,如在这个应用程序中,AVKit 是要使用的平台库。需要创建并启动摄像机会话。在会话中,有输入和输出,输入连接到输出。在这种情况下,输入设置为来自后置摄像头的视频输入,以便屏幕可以显示实时预览,输出是一张照片,因为该应用程序处理单张照片。

Creating and starting the camera session

照片输出是用来拍照的。evaluate 按钮的 target 方法创建一个 settings 对象,其中默认设置适合此用途,并指示要捕获的照片。

Callback method to take a photo

裁剪照片

在 Android 应用程序中,应用程序正在处理位图,这使得裁剪和缩放变得容易。在 iOS 上,AVKit 将产生一个 AVCapturePhoto 对象,它需要更多的工作来匹配屏幕,因为屏幕分辨率与照片分辨率不同。

Cropping a captured photo to include only the part shown on screen

在这种情况下,支持裁剪的最佳图像类型是 CGImage。与用于屏幕显示的 UIImage 不同,CGImage 不知道它的方向,因此需要从 AVCapturePhoto 对象中提取。方向用于确保屏幕边界的方向与照片的方向相同,以便可以正确计算缩放因子。(宽度和高度尺度不同;使用身高是正确的,但我不知道为什么。)

要提取用于分类的图片是照片中心的 299x299 区域。因此,代码将一个 299x299 的矩形缩放到照片分辨率,将其居中,并进行裁剪。最后,返回一个具有适当的屏幕缩放因子和方向的 UIImage,因为使用 UIImage 比使用 CGImage 更方便。

Photo by Liliya Lisa on Unsplash

运行分类器

创建模型最好在启动时完成,因为它不会在应用程序运行时改变,并且需要一段时间来创建。创建的模型类型来自 Vision framework,这是一个很好的用于图像分类的库。

Creating a model object to run classification

当试图用默认配置运行模型时,我遇到了一个溢出错误,显然意味着模型对于神经引擎来说太大了。这就是为什么它仅限于 CPU 和 GPU 的原因。

从 Vision 框架开始分类非常简单。使用模型和回调方法创建分类请求,从(裁剪的)图像创建处理程序,并使用请求调用处理程序。

Starting classification of the image

分类器完成后,将使用结果调用完成方法。该方法验证结果是分类结果。由于模型被转换为一个带有适当输出标签的图像分类器,代码可以查找标识符“cute ”,而不需要知道哪个索引对应于哪个类。

摘要

构建 iOS 应用比构建 Android 应用要简单一些,部分原因是我已经有了一些 Android 应用的经验。最大的障碍是需要对捕获的照片进行图像处理,因为我对 UIImage、CGImage 和 AVCapturePhoto 的复杂性不是很熟悉。正如在制作了 Android 应用程序之后,我现在对自己在真正的 iOS 应用程序中应用机器学习的能力更有信心了。

Screenshot of the app evaluating a dog

是的,还能用。

用机器学习检测可爱的动物

原文:https://towardsdatascience.com/detecting-cute-animals-with-machine-learning-d39a511bd144?source=collection_archive---------17-----------------------

培训和构建自定义图像分类器移动应用程序

Photo by Álvaro Niño on Unsplash

当我的一位数据科学家同事最近发现我有移动应用开发背景时,他让我向他展示如何在移动应用中使用机器学习模型。我认为一个图像分类应用程序,比如经典的 Not Hotdog ,将是一个很好的例子,因为它也需要连接到手机的摄像头,而不仅仅是一个运行在手机而不是桌面上的模型。

我花了一段时间来拼凑我需要的所有东西,以制作一个完整的应用程序。这就是为什么我认为写一个帖子会很有用,这样整个旅程都可以在一个地方记录下来。我写的所有代码,获取训练图像,训练模型,以及应用程序本身,都可以在 Github 上获得。代码经过了全面的注释,因为我希望它对数据科学家和移动应用程序开发人员都有用。

建什么?

起初我以为我只是建立一个热狗探测器,并发现了一个职位,通过模型建立部分。但是我身边没有很多热狗,所以演示这样一个应用程序会很困难。因为我喜欢可爱的动物,所以我决定做一个可爱探测器,作为一个更抽象的概念,它可以在许多日常环境中演示。

对于训练数据的来源,我挑了 ImageNet 。我决定将小狗和小猫的图片作为我的“可爱”训练数据,并有点武断地将爬行动物和有蹄动物作为我的“不可爱”训练数据。在过滤掉不可用的图片后,我剩下了 1718 个可爱的图片和 1962 个不可爱的图片。视觉上验证我有好的数据肯定验证了爬虫的选择是“不可爱”。Brrrrr…

利用初始迁移学习

对于自定义图像分类,迁移学习是必由之路。从头开始训练一个图像分类器需要很长时间,我能想到的任何网络架构都不会比当前的技术水平更好。我选择了 InceptionV3,因为我找到了一篇关于如何用它制作一个自定义图像分类器的示例代码为的好文章。

建立模型的关键点是以 InceptionV3 模型为基础,增加一个新的分类层,并将训练限制在新的分类层。由于训练数据来自 ImageNet,因此 InceptionV3 构造函数被告知使用这些权重。另一个参数表示排除顶层,顶层进行实际的分类,因为我将使用我自己的层进行分类。

Building an image classifier out of the Inception model

如今,图像分类已经从在每个卷积层之后使用池化,转移到在最后使用全局平均池化。因此,基本的 InceptionV3 模型扩展了一个 GAP 层,最后是一个具有两个节点的 softmax 分类层,因为有两个类要预测,可爱和不可爱。在最后一步中,来自基本 InceptionV3 模型的所有层都被标记为不可训练,因此训练仅适用于添加的自定义层。

Photo by Liudmyla Denysiuk on Unsplash

用于培训的数据

我已经下载了我的训练图像,现在需要做一点工作来为训练做准备。为 Keras 设置数据的一个好方法是为每个训练、验证和测试数据集创建目录。然后,在每个目录中,为每个标签创建一个子目录,并将每个标签的图像放在相应的子目录中。所以我有目录“可爱”和“不可爱”。这使得 Keras 在训练过程中自动拾取标签。

在进行影像分类时,扩充数据总是一个好主意。Keras 配备了现成的 ImageDataGenerator ,可用于通过不同的转换自动增加图像数据。

Making a generator to augment the training data dynamically

ImageDataGenerator 用参数初始化,参数是它应该执行哪种类型的转换。我没有选择任何会引入失真的,因为失真可能会删除可爱。InceptionV3 期望像素在范围[-1,1]内,它提供了函数preprocess_input来对该范围执行最小-最大缩放。这个函数被传递给生成器,这样生成的图像将是适当的格式。

然后设置生成器从图像目录中产生图像。参数数据集可以是“训练”或“测试”,这取决于是生成训练数据还是验证数据。图像大小 299x299 是 InceptionV3 所期望的。

构建模型

用生成器训练模型非常简单。五个纪元似乎适合这项任务。事实上,在第三个纪元之后,我没有看到任何改进。有了这些参数,我在 Macbook 上的训练大概花了 2.5 个小时,我觉得还是挺合理的。

Training the model

上面的最后一行model.save('iscute.h5'),以 Keras 使用的 HDF5 格式保存模型。这不是用于移动应用程序的格式。对于 Android,我选择使用 tensorflow-lite。(我想用 CoreML 做一个 iOS 应用,但是我用的是 Python 3.7,CoreML 工具还不支持那个版本。)Tensorflow 自带合适的转换器,所以这里没有太多代码。我得到的 HDF5 文件大小为 84 MB,而 tensorflow-lite 文件为 83 MB,因此大小没有太大的减少。

Converting the trained model to be used on Android

这里唯一令人头痛的是发现对input_shapes 参数的需求。在没有该参数的情况下第一次运行时,我得到了错误消息“ValueError: None 仅在第一维中受支持。张量“input_1”具有无效的形状“[无,无,无,3]”。所需的尺寸是图像尺寸 299x299,错误消息指出使用什么张量名称作为字典参数中的键。

Photo by Ricky Kharawala on Unsplash

在 Android 上读取摄像头

现在我已经准备好在应用程序中使用我的模型,所以是时候构建应用程序了。它需要执行以下操作:

  1. 在屏幕上显示相机预览
  2. 让用户按下按钮来捕捉当前图像
  3. 将捕获的图像输入分类器
  4. 分类完成后显示结果

我还不知道如何做的部分是 1 和 3。此外,Android 相机 API 已经改变,我能找到的许多教程仍然是为旧的、过时的版本编写的。幸运的是,我确实找到了一个详细列出了所有需要做的事情的帖子。访问相机图像需要相当多的代码,所以我不会在这里展示其中的大部分。检查存储库中的完整代码。

准备图像捕捉需要获得一个CameraManager,请求用户允许使用相机(除非已经被授权),并获得一个包含预览的TextureView的引用。一个真正的应用程序将需要为相机许可不被授予做好准备。

Preparing for using the Android camera

TextureView可用之前,相机无法显示任何内容,因此应用程序可能需要通过设置监听器来等待。之后,该应用程序需要找到一个合适的相机(这里的背面)并打开它。

Waiting until the camera is available before starting to use it

Finding a backwards-facing camera

Opening the discovered backwards-facing camera

openCamera()方法传入一个状态回调。当相机打开时,将通知该回调,它可以触发创建相机预览会话,以便当用户按下评估按钮时相机图像可用。

Creating a session with the camera to capture the image

Photo by Jairo Alzate on Unsplash

在 Android 上进行分类

为了弄清楚如何进行分类,我简要地看了一下 Tensorflow-lite 指南。虽然它有助于开始,但它对代码的实际细节帮助很小。对于细节,我浏览了进行图像分类的示例应用程序,并从非常一般的代码中提取出我需要的特定位。

初始化分类器意味着将模型从应用程序的资产加载到内存中,并从中创建 Tensorflow Interpreter对象。图像分类器的输入被有效地作为一个ByteBuffer给出,它是如此之大,以至于在初始化过程中预分配它是有意义的。

Initializing the Tensorflow-lite classifier

当在图像上运行分类器时,在后台线程中执行它是很重要的。它需要几秒钟的时间来运行,让 UI 线程等待那么长时间是不可接受的。首先要做的是在缓冲区中以正确的格式创建输入:将图像缩放到 299x299,并运行最小-最大缩放以获得范围[-1,1]的像素值,如 InceptionV3 所预期的。

Preprocessing the captured image into suitable input for InceptionV3

最后,可以运行分类器。run()方法的类型不是很有帮助,因为它只需要一个Object作为输入和输出。如上所述,对于图像分类,ByteBuffer是一种很好的输入格式。这个分类案例的输出是一个单元素数组,它的元素是一个浮点数组,其大小是类的数量。运行之后,这个浮点数组将被每个类的概率填充。所以在我的例子中,它是一个两元素的数组,元素是“可爱”和“不可爱”的概率。

Running the Tensorflow-lite classifier

在这个阶段,我没有找到一种方法来确定哪个类对应于数组中的哪个索引。因此,需要从 Keras 模型中提取类到索引的映射,并可能作为数据包含在应用程序中,以防不同训练运行之间的映射不稳定。

摘要

最终,构建一个图像分类器应用程序并不太困难。它跨越了几个领域,所以信息并不都在一个地方,但是当你看的时候,它们都在某个地方。我构建的应用程序当然只是一个演示,但现在知道了原理和方法,我有信心我也可以在真正的应用程序中添加这种功能。

Screenshot of the app evaluating a dog

是的,我认为我的模型工作得很好。

用 Python 和 OpenCV 人脸检测神经网络检测人脸

原文:https://towardsdatascience.com/detecting-faces-with-python-and-opencv-face-detection-neural-network-f72890ae531c?source=collection_archive---------5-----------------------

Cool Kids of Death Off Festival

现在,我们都知道人工智能正变得越来越真实,它正在一天天填补人类和机器之间的能力差距。它不再只是一个花哨的词了。多年来,它在许多领域取得了许多进展,其中一个领域就是计算机视觉。

就计算机视觉而言,它的目标是训练机器像人类一样看待和识别世界。并且还收集足够大的知识来执行图像和视频识别、图像分析和分类、媒体再现、自然语言处理等。

卷积神经网络

随着时间的推移,计算机视觉的进步已经逐渐实现并完善,主要是通过一种特定的算法,卷积神经网络(CNN 或 ConvNets),这是一种特殊类型的前馈网络,主要用于分析视觉图像。卷积神经网络非常类似于普通的神经网络,但是由具有可学习的权重和偏差的神经元组成。

由于其独特的过程,ConvNets 比其他深度神经网络架构性能更好。ConvNets 不是一次看一个像素,而是将几个像素组合在一起,这样他们就可以了解时间模式。另一方面,ConvNets 可以“看到”形成直线或曲线的一组像素。由于深度神经网络的深层性质,在下一个级别中,他们将看到的不是像素组,而是形成一些形状的线条和曲线组。如此等等,直到它们形成完整的画面。

迁移学习

然而,CNN 需要大数据集和大量的计算时间来训练。有些甚至需要跨多个 GPU 花费 2-3 周的时间。如果你想了解 CNN,你需要学习很多东西,从最基本的东西开始,像内核、池层等等。但是现在,你可以直接潜水,使用这项技术的很多开源项目。

这实际上是真的,因为有一种叫做迁移学习的技术。迁移学习是一种非常实用和强大的技术,它利用经过训练的模型,而不是从头开始训练网络。迁移学习利用不同数据集上的训练模型,并使其适应我们试图解决的问题。

为了构建我们的应用程序,我们将遵循迁移学习技术,并使用一个经过训练的模型,该模型是使用 Caffe 框架训练的,Caffe 框架是一个考虑到表达、速度和模块化的深度学习框架。Caffe 附带了一个存储库,供研究人员和机器学习从业者用来共享他们训练过的模型。这个图书馆叫做模型动物园。你可以通过浏览他们的文档来了解所有相关信息。

入门指南

python 代码、经过训练的 caffe 模型和 prototxt 文件(包括网络的文本描述和一些用于我们的应用程序的示例图像)可以在 github 资源库中找到,如果您想看一看的话。

在我们的应用程序中,我们将使用以下库:

  1. OpenCV 支持许多与计算机视觉和机器学习相关的算法,更不用说它内置于我们将在应用中使用的深度神经网络中。
  2. Numpy,这是一个用于 python 科学计算的包。
  3. OS,它提供了一种使用操作系统相关功能的可移植方式

因此,为了安装它们,您可以在命令提示符窗口中运行以下命令。pip install opencv-python要安装 OpenCV,pip install numpy要安装 Numpy,您不需要专门安装 OS 库,因为它随 Python 安装一起提供,但是您仍然必须导入它。

构建应用程序

首先,让我们创建一个名为 faceDetection.py 的文件,并导入我们的库。

#import libraries
import os   
import cv2
import numpy

现在,我们将获得工作目录的绝对路径,在那里我们将放置所有的图像,

#import libraries
import os   
import cv2
import numpy#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))

现在,我们将创建一个名为“输出”的文件夹来存放我们的最终图像,如果它还不存在的话。

#import libraries
import os   
import cv2
import numpy#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')

之后,我们将从当前工作目录加载我们预先训练好的模型和 prototxt 文件。

#import libraries
import os   
import cv2
import numpy#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')

然后,我们将遍历当前文件夹中可用的文件,检查是否有扩展名为的文件。png,。jpg 和. jpeg。

#import libraries
import os   
import cv2
import numpy#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')for file in os.listdir(dir_path):
  #split the file name and the extension into two variales
  filename, file_extension = os.path.splitext(file) #check if the file extension is .png,.jpeg or .jpg 
  if (file_extension in ['.png','.jpg','.jpeg']):

如果找到具有上述扩展名的图像,我们将使用 OpenCV 读取该图像,并通过访问 image.shape 元组获得其高度和宽度,然后使用前两个元素在脸部周围绘制矩形。

#import libraries
import os   
import cv2
import numpy#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')for file in os.listdir(dir_path):
  #split the file name and the extension into two variales
  filename, file_extension = os.path.splitext(file) #check if the file extension is .png,.jpeg or .jpg
  if (file_extension in ['.png','.jpg','.jpeg']):
    #read the image using cv2
    image = cv2.imread(file) #accessing the image.shape tuple and taking the elements
    (h, w) = image.shape[:2]

然后,我们将使用cv2.dnn.blobFromImage函数得到我们的斑点,将图像作为输入。使用cv2.dnn.blobFromImage函数,我们将图像的尺寸调整为 300x300,1.0 是比例因子,此处我们使用默认值,因此没有缩放,之后是卷积神经网络预期的空间尺寸,最后的值是元组中的平均减法值,它们是 RGB 平均值,最后,函数返回一个“blob”,这是调整大小、平均减法和归一化后的输入图像。

之后,我们将把斑点输入到模型中,并使用model.foreward函数得到检测结果。

#import libraries
import os   
import cv2
import numpy#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')for file in os.listdir(dir_path):
  #split the file name and the extension into two variales
  filename, file_extension = os.path.splitext(file) #check if the file extension is .png,.jpeg or .jpg 
  if (file_extension in ['.png','.jpg','.jpeg']):
    #read the image using cv2
    image = cv2.imread(file) #accessing the image.shape tuple and taking the elements
    (h, w) = image.shape[:2] #get our blob which is our input image 
    blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0)) #input the blob into the model and get back the detections 
    model.setInput(blob)
    detections = model.forward()

然后,我们将遍历所有检测到的人脸,并提取它们的起点和终点。我们将提取置信度并将其与置信度阈值进行比较,以便我们可以过滤掉弱检测。如果算法有超过 16.5%的把握检测到的是人脸,我们会在上面显示一个绿色的矩形。

#import libraries
import os   
import cv2
import numpy#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')for file in os.listdir(dir_path):
  #split the file name and the extension into two variales
  filename, file_extension = os.path.splitext(file) #check if the file extension is .png,.jpeg or .jpg 
  if (file_extension in ['.png','.jpg','.jpeg']):
    #read the image using cv2
    image = cv2.imread(file) #accessing the image.shape tuple and taking the elements
    (h, w) = image.shape[:2] #get our blob which is our input image 
    blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0)) #input the blob into the model and get back the detections 
    model.setInput(blob)
    detections = model.forward()
    #Iterate over all of the faces detected and extract their start and end points
    count = 0
    for i in range(0, detections.shape[2]):
      box = detections[0, 0, i, 3:7] * numpy.array([w, h, w, h])
      (startX, startY, endX, endY) = box.astype("int") confidence = detections[0, 0, i, 2]
      #if the algorithm is more than 16.5% confident that the      detection is a face, show a rectangle around it
      if (confidence > 0.165):
        cv2.rectangle(image, (startX, startY), (endX, endY), (0, 255, 0), 2)
        count = count + 1

最后,我们将输出图像保存在我们创建的输出文件夹中,并打印出一条成功消息,让用户知道已经完成了。

#import libraries
import os   
import cv2
import numpy#get the absolute path of the working directory
dir_path = os.path.dirname(os.path.realpath(__file__))#create the Output folder if it doesn't already exist
if not os.path.exists('Output'): 
  os.makedirs('Output')#Reads the network model stored in Caffe framework's format.
model = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'weights.caffemodel')for file in os.listdir(dir_path):
  #split the file name and the extension into two variales
  filename, file_extension = os.path.splitext(file)#check if the file extension is .png,.jpeg or .jpg 
  if (file_extension in ['.png','.jpg','.jpeg']):
    #read the image using cv2
    image = cv2.imread(file)#accessing the image.shape tuple and taking the elements
    (h, w) = image.shape[:2]#get our blob which is our input image 
    blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0))#input the blob into the model and get back the detections 
    model.setInput(blob)
    detections = model.forward()
    #Iterate over all of the faces detected and extract their start and end points
    count = 0
    for i in range(0, detections.shape[2]):
      box = detections[0, 0, i, 3:7] * numpy.array([w, h, w, h])
      (startX, startY, endX, endY) = box.astype("int")confidence = detections[0, 0, i, 2]
      #if the algorithm is more than 16.5% confident that the      detection is a face, show a rectangle around it
      if (confidence > 0.165):
        cv2.rectangle(image, (startX, startY), (endX, endY), (0, 255, 0), 2)
        count = count + 1 #save the modified image to the Output folder
    cv2.imwrite('Output/' + file, image) #print out a success message
    print("Face detection complete for image "+ file + " ("+ str(count) +") faces found!")

我希望你喜欢这个结果!现在,您总是可以稍微摆弄一下代码,以了解每个函数的作用。如果你想阅读并获得更多信息,OpenCV 提供了很好的文档和教程。

结论

在本文中,我们走过了,

  1. 卷积神经网络的概念,以及我们如何通过迁移学习和预训练模型节省大量时间和精力。
  2. Caffe 模型以及我们将如何使用预先训练的 Caffe 模型来实现我们的应用程序。
  3. 安装所需的库并设置环境。

最后,我们实现了一个 python 程序,可以使用图像检测人脸。

如有任何问题,欢迎在下方留言。谢谢!

检测网上虚假政治新闻

原文:https://towardsdatascience.com/detecting-fake-political-news-online-a571745f73dd?source=collection_archive---------21-----------------------

了解如何使用 NLP 和被动攻击算法来识别网上的假新闻。

Photo by Lieu Cap on Unsplash

近年来,在线社交网络的蓬勃发展使得许多在线平台上出于各种商业和政治目的的假新闻数量激增。

我们都曾偶然发现政客死亡的假新闻,一些领导人发表关于寺庙和清真寺之类的声明。

误导性的新闻极大地影响了读者,并且已经给线下社会带来了非常负面的影响。

因此,提高在线社交网络上信息的可信度的一个重要目标是及时和正确地识别假新闻。

在这篇文章中,我将指导你使用被动攻击算法构建一个假新闻检测分类器。

用于分类器的数据集可以在这里下载。

数据集包含三列,即:

  1. 标题:新闻文章的标题
  2. 文本:新闻文章的内容
  3. 标签:两个标签——假的和真的。

A subset of the data-set

简而言之,使用 sklearn,可以在数据集上构建 TfidfVectorizer。然后,初始化被动主动分类器并拟合模型。最后,准确度分数和混淆矩阵定量地解释了模型的表现。

专业术语太多?好吧,让我们一步一步地把它们都弄清楚。

让我们了解一下像 TfidfVectorizer 和被动主动分类器这样的术语。

tfidf 矢量器将原始文档的集合转换成 TF-IDF 特征的矩阵。

让我们再深入一点..

TfidfVectorizer 是由什么构成的?

  1. TF(词频):一个词在文档中出现的次数就是它的词频。较高的值意味着某个术语比其他术语出现得更频繁,因此,当该术语是搜索术语的一部分时,该文档是一个很好的匹配。
  2. IDF(逆文档频率):在一个文档中多次出现,但在很多其他文档中也多次出现的词,可能是不相关的。 IDF 是衡量一个术语在整个语料库中的重要性的指标。

被动主动分类器

被动攻击算法是在线学习算法。这种算法对于正确的分类结果保持被动,而在误算、更新和调整的情况下变得主动。与大多数其他算法不同,它不收敛。其目的是进行修正损失的更新,使得权重向量的范数变化很小。

让我们开始吧。

首先导入所有必需的库。

Loading the data-set and analyzing the distribution of predicting label

既然数据集已经加载,接下来我们将把它分成测试集和训练集。

数学模型只理解数字。因此,我们将使用 TFIDF 矢量器将训练集和测试集转换成模型的可解释形式。

现在我们已经万事俱备了。我们现在将构建被动主动分类器,并使用 sklearn 的 accuracy_score 指标对数据集进行评估。

在测试集上实现了 92.58%的准确率。接下来,我们将使用混淆矩阵评估结果,并计算 F1 得分。

这里 F1 的分数是: 0.9283。

这里是各种度量的汇编,帮助我们定量评估分类器的性能。

Various metrics used to evaluate the performance of PAssive agressive classifier

Jupyter 笔记本的完整代码可以在我的 GitHub 库中找到。

检测仇恨推特——推特情绪分析

原文:https://towardsdatascience.com/detecting-hate-tweets-twitter-sentiment-analysis-780d8a82d4f6?source=collection_archive---------2-----------------------

一项综合研究,旨在确定预处理和模型选择的哪种组合能够提供最佳的仇恨言论过滤器

供稿人 : Vedant Kshirsagar、Adwait Toro、Sushrut Shendre、Sneha Lakshmikanthaiah、Rishab Ballekere Narayana Gowda、Tanvir Brar、Chavi Singal

我们所有的代码都可以在 GitHub 上找到

【https://github.com/vedant-95/Twitter-Hate-Speech-Detection

摘要

由于不同文化和教育背景的人对互联网的使用呈指数增长,有毒在线内容已成为当今世界的一个主要问题。区分仇恨言论和攻击性语言是自动检测有毒文本内容的关键挑战。在这份报告中,我们提出了一种方法来自动将 Twitter 上的推文分为两类:仇恨言论和非仇恨言论。使用 Twitter 数据集,我们通过利用单词包和术语频率-逆文档频率(TFIDF)值对多个机器学习模型进行实验。考虑到这两种方法,我们对模型进行了比较分析。在调整给出最佳结果的模型之后,我们在应用逻辑回归模型时实现了 89%的准确率和 84%的召回率。我们还使用 flask 创建了一个模块,作为我们模型的实时应用程序。

概述

我们的目标是将推文分为两类,仇恨言论或非仇恨言论。我们的项目分析了来自 Kaggle 的包含 31,935 条推文的数据集 CSV 文件。数据集严重扭曲,93%的推文或 29,695 条推文包含非仇恨标签的推文数据,7%或 2,240 条推文包含仇恨标签的推文数据。构建我们模型的第一步是平衡仇恨和非仇恨推文的数量。我们的数据预处理步骤包括两种方法,单词包词频逆文档频率(TFIDF)。

单词袋方法是自然语言处理和信息检索中使用的简化表示。在这种方法中,一个文本(如一个句子或一个文档)被表示为它的单词的包(多集合),不考虑语法甚至词序,但保持多样性。

TFIDF 是一个数字统计量,旨在反映一个单词对集合中的文档有多重要。在信息检索、文本挖掘和用户建模的搜索中,它被用作加权因子。

在我们将这些数据输入各种算法之前,我们必须清理这些数据,因为推文中包含许多不同的时态、语法错误、未知符号、标签和希腊字符。

我们通过使用词汇化、词干化、删除停用词和省略来解决这个问题。词汇化删除单词的屈折词尾,并将单词返回到其本身的基本形式或词典形式。词干化类似于词干化,因为它将屈折词或派生词简化为词干。停用词是一个常用词,如“the”、“a”、“an”、“in”,我们编程忽略它,因为它不重要。最后一步是省略任何外国字符和希腊符号。

灵感

探索这一主题的灵感来自仇恨言论实例的增加和仇恨言论意识。据《纽约时报》报道,“由偏见或成见引发的人身攻击在 2018 年达到了 16 年来的最高水平,针对拉丁美洲人的暴力事件大幅上升,超过了针对穆斯林和阿拉伯裔美国人的袭击事件的下降。”这种上升也可归因于数字社交媒体平台的兴起,这些平台为仇恨言论的传播提供了便利。大多数(59.6%)仇恨犯罪事件涉及种族和族裔偏见。其次是宗教偏见,占所有事件的 18.7%。当我们观察到仇恨推特中最常见的负面词汇与种族或宗教有关时,我们的研究验证了这些结果。这些尖酸刻薄的例子会下意识地在我们的社会中煽动仇恨,尤其是在我们易受影响的年轻一代的头脑中。根据公共研究,22%的受访者表示,由于网上的仇恨言论,他们在自己的社区感到不太安全,超过 85%的人支持建立一个工作组来监控网络欺凌。这个问题现在已经变得如此普遍,以至于美国第一夫人梅兰妮·特朗普已经把打击网络欺凌和网上仇恨言论作为她的主要目标。统计数据显示,在减少仇恨言论传播方面做得还不够。

数据

(来源:【https://www.kaggle.com/vkrahul/twitter-hate-speech )

数据字典

可视化和文字云

创建单词云是为了了解 tweets 中最常用的单词。这是针对仇恨和非仇恨两类推文进行的。接下来,我们创建了一个条形图,来可视化积极情绪和消极情绪中最常见单词之间的使用频率。

正面推文

负面推文

数据架构

如前所述,我们拥有的数据是不平衡的。我们总共有 31935 行,其中仇恨推文仅占推文总数的 7%。在不平衡的数据集上建模并不理想,因为模型无法学习哪些文本或信息导致该推文被归类为仇恨推文。

如果我们在不平衡的数据上训练一个模型,结果将是误导性的。在这样的数据集中,由于缺乏学习,该模型会简单地将每条推文预测为好推文。在这种情况下,尽管准确率很高,但它实际上并没有做好分类工作,因为它无法准确地对仇恨推文进行分类。

更简单地说,即使模型预测所有的推文都是非仇恨的,它仍然有 93%的准确率。

因此,我们执行策略抽样,并将数据分成临时集和测试集。请注意,由于我们已经执行了战略抽样,对于临时和测试数据集,好推文与讨厌推文的比例是 93:7。

在临时数据上,我们首先尝试使用 SMOTE(合成少数过采样技术)对仇恨推文进行上采样。由于 SMOTE 包不能直接处理文本数据,我们为它编写了自己的代码。流程如下:

我们创建了一个语料库,收录了临时数据集的仇恨推文中出现的所有独特词汇。一旦我们有了包含仇恨推文中所有可能单词的矩阵,我们就创建了一个空白的新数据集,并开始用新的仇恨推文填充它。这些新推文是通过从语料库中随机选择单词合成的。这些新推文的长度是根据组成语料库的推文的长度确定的。

然后,我们多次重复这个过程,直到合成数据中仇恨推文的数量等于临时数据中非仇恨推文的数量。然而,当我们使用单词袋方法生成特征时,特征的数量增加到了 100,000。由于特性数量非常多,我们面临硬件和处理能力的限制,因此不得不放弃 SMOTE 过采样方法。

由于不可能对仇恨推文进行上采样以平衡数据,我们决定对非仇恨推文进行下采样以使其平衡。我们从临时数据集中提取了一部分非仇恨性的推文。从这个子集中,我们选择了 n 条随机推文,其中 n 是临时数据中仇恨推文的数量。然后我们在临时数据中加入了仇恨推特的子集。这个数据集现在是我们用于特征生成和建模目的的训练数据。

测试数据仍然是好的推文和讨厌的推文之比为 93:7,因为我们没有对它进行任何采样。由于真实世界的数据是以这个比率出现的,所以没有进行采样。

逼近

我们已经研究了两种主要的特征生成方法:单词袋(BOW)和词频逆文档频率(TFIDF)。

1.一袋单词

2.术语频率逆文档频率

一袋话

词袋模型(bag-of-words model)是一种从文本中提取特征以用于建模的方法,例如使用机器学习算法。

它被称为单词的“,因为任何关于文档中单词的顺序或结构的信息都被丢弃了。该模型只关心已知单词是否出现在文档中,而不关心它在文档中的位置。直觉是,如果文档有相似的内容,它们就是相似的。此外,仅从内容上,我们就可以了解文件的含义。

目标是将自由文本的每个文档转换成一个向量,我们可以使用它作为机器学习模型的输入或输出。因为我们知道词汇表有 10 个单词,所以我们可以使用 10 的固定长度的文档表示,用向量中的一个位置来给每个单词打分。最简单的评分方法是将单词的存在标记为布尔值,0 代表不存在,1 代表存在。

使用词汇表中上面列出的任意单词顺序,我们可以遍历第一个文档(“这是最好的时代”),并将其转换为二进制向量。

文档的评分如下所示:

●“它”= 1

●“曾经”= 1

● "the" = 1

●“最佳”= 1

● "of" = 1

●“时代”= 1

●“最差”= 0

●“年龄”= 0

●“智慧”= 0

●“愚蠢”= 0

作为一个二进制向量,它将如下所示:

[1, 1, 1, 1, 1, 1, 0, 0, 0, 0]

其他三个文档如下所示:

1.“这是最坏的时代”= [1,1,1,0,1,1,1,0,0,0]

2.“那是智慧的时代”= [1,1,1,0,1,0,0,1,1,0]

3.“那是愚蠢的时代”= [1,1,1,0,1,0,0,1,0,1,1]

如果您的数据集很小,并且上下文是特定于领域的,BoW 可能比单词嵌入更好。上下文是非常领域特定的,这意味着你不能从预先训练的单词嵌入模型(GloVe,fastText 等)中找到相应的向量。)

TFIDF

TFIDF 是一种信息检索技术,它衡量术语的频率(TF)及其逆文档频率(IDF)。每个单词或术语都有其各自的 TF 和 IDF 得分。一项的 TF 和 IDF 得分的乘积称为该项的 TFIDF 权重。

简单来说,TF*IDF 得分(权重)越高,该术语越稀有,反之亦然。

TFIDF 算法用于对任何内容中的关键字进行加权,并根据该关键字在文档中出现的次数为其分配重要性。更重要的是,它检查关键字在整个网络中的相关性,这被称为语料库*。

对于文档 d 中的项 t,文档 d 中的项 t 的权重 Wt,d 由下式给出:

Wt,d = TFt,d log (N/DFt)

其中:

● TFt,d 是 t 在文档 d 中出现的次数。

● DFt 是包含术语 t 的文档数。

● N 是语料库中的文档总数。

TF*IDF 是如何计算的?一个词的 TF(词频)是一个词在文档中出现的频率(即出现的次数)。当你知道它的时候,你就能看到你使用一个术语是过多还是过少。

例如,当一个 100 个单词的文档中包含 12 次术语“cat”时,单词“cat”的 TF 为

TFcat = 12/100,即 0.12

一个词的 IDF(逆文档频率)是该词在整个语料库中的重要性的度量。

数据清理

我们说的和写的语言是由几个单词组成的,这些单词通常来源于另一个单词,并且可以包含一些不增加意义或上下文的单词。为了清理数据,我们实施了 5 种方法。

  1. 停用词移除:停用词通常是冠词或介词,它们不能帮助我们找到上下文或句子的真正含义。这些单词可以被删除,而不会对您正在训练的最终模型产生任何负面影响。英语中常用的语言包括“is”、“and”、“are”等。
  2. 希腊字符:我们接下来删除特殊字符和数字。数字很少包含有用的意义。特殊字符会扩大我们的词频矩阵。
  3. 俚语词汇:俚语词汇包括通常在演讲中使用的非正式短语。由于缺乏现有的字典,我们将一些俚语映射到它们的原始形式,例如“luv”到“love”,“thx”到“thanks ”,举几个例子。
  4. 词干化:使用词干化,考虑到在一个屈折词中可以找到的常见前缀和后缀的列表,通过切断单词的结尾或开头,单词被缩减为它们的词干。一个单词被查看并通过一系列决定如何删减的条件句。对于我们的数据集,使用波特词干算法。
  5. 词汇化:词汇化是将一个单词的不同屈折形式组合在一起的过程,这样它们就可以作为一个单独的项目进行分析。词汇化类似于词干化,但它给单词带来了上下文。所以,它把意思相近的单词连接成一个单词。比如 runs,running,ran 都是单词 run 的形式,因此 run 就是所有这些单词的引理。

造型

对于单词袋和 TFIDF,我们运行 5 种分类算法,即逻辑回归、朴素贝叶斯、决策树、随机森林和梯度提升。此外,我们还在这两种方法中执行维数减少,并再次运行这 5 种算法。

我)包话

我们在训练数据集上实现了用于特征生成的单词包。在这种方法中,我们试图找出一条推文是否是仇恨推文的概率,给定某些词的存在及其在推文中的频率。

我们的训练数据是总共 4480 条推文,生成了 12566 个独特单词的语料库。在实现单词包特征工程之后,结果是包含 4480 行和 12566 列的数据帧,其中每一列对应于一个唯一的单词。然后,我们将标签连接成一列。

在运行分类算法时,获得了以下结果:

为了更好地显示这些结果,我们绘制了下面的聚类柱形图。

Preprocessing: Bag of Words

我们现在讨论将准确率和召回率作为我们的衡量标准的理由,以及它们将如何帮助我们选择冠军模型。乍一看,梯度增强似乎是最好的模型,因为它的精度最高。但是正如《数据架构》中所讨论的,我们的测试数据包含了 93:7 的好推文和讨厌推文的比例。因此,具有高精度可能不是最好的度量。因此,我们考虑召回,这是我们能够正确识别的仇恨推文的比例。如果这个指标很高,这将相当于大量的仇恨推文被归类为仇恨推文,从而实现我们的目标。如果我们只看回忆,朴素贝叶斯似乎是最好的模型。然而,另一个需要考虑的因素是,我们捕获的所有仇恨推文将被转发给运营团队,该团队将单独审查这些推文。因此,有大量的误报将意味着分析师将不得不不必要地审查更多的推文,这些推文实际上不是仇恨推文。这将导致时间、资源和人员的利用效率低下。我们的建议是拥有高召回率,同时确保假阳性的数量保持在最低水平。这将是理想的前进模式,给予高评分的准确性和召回率。因此,我们选择逻辑回归和随机森林作为冠军模型。

ii)词频逆文档频率(TFIDF)

有些词被认为是俚语或骂人的话,但它们太常见了,人们在日常生活中经常使用。因此,如果有一条包含这些词的推文,它实际上可能不是一条仇恨推文。为了区分一个俚语/辱骂性的词是否意在表达仇恨,我们尝试了 TFIDF 方法,因为它给这样的词分配了较低的权重。因此,我们不再使用单词包模型来计算这个单词在 tweet 中出现的次数,而是使用 TFIDF 权重。运行算法后,我们获得以下结果。

Preprocessing: TF-IDF

同样,逻辑回归和随机森林为我们提供了最好的准确性和召回结果。

iii)1000 个最常用单词的单词包

由于特征的数量等于唯一单词的数量,因此是巨大的(12566),我们假设到目前为止我们讨论的两个模型可能是过度拟合的。因此,我们试图通过选取 1000 个最常用的单词(以及变量)来降低维度。在这个变量选择之后,我们再次实现分类算法。我们对单词包和 TFIDF 都这样做。获得的结果列表和绘图如下:

Bag of Words for 1000 most frequent words

iv)1000 个最常用词的 TF-IDF

TF-IDF for 1000 most frequent words

运行降维模型后获得的结果与未降维的结果一致。梯度推进再次给出了高准确度,朴素贝叶斯给出了好的回忆,逻辑回归和随机森林给出了这两个度量的最佳结果。

然而,这些模型没有显著的改进。虽然一些算法的指标有所改进,但另一些算法的指标却有所下降,并且改进/降低的幅度可以忽略不计。

最后,我们来看 ROC 曲线。以下是单词袋方法(所有单词)的曲线:

ROC Curve for all the classifiers

下表显示了各种算法的曲线下面积(AUC)

AUC of all the classifiers

现在,让我们看看 TFIDF 方法的 ROC 曲线和 AUC 表(所有单词)

ROC curve and AUC for all the classifiers

如我们所见,逻辑回归给出了最好的 AUC。此外,如果我们看它的 ROC 曲线,我们可以看到它相等地覆盖了假阳性率(FPR)和真阳性率(TPR)区域。将其与朴素贝叶斯进行比较,朴素贝叶斯表现出较差的假阳性性能,这也通过其先前的准确度得分而明显可见。类似地,梯度推进具有较差的真实积极表现,这从其较低的回忆分数可以明显看出。

此外,逻辑回归本质上是直接的,即可以借助简单的指数方程来解释该模型,并且可以可视化和比较其系数。因此,我们推荐逻辑回归作为我们案例的最佳模型。

MVP

在所有的数据清理、特性工程和建模之后,我们决定部署这个模型,以便从这个项目中获得一些有用的东西。这个项目的主要目标是开发一个可以检测仇恨推文的系统,以便 Twitter 可以采取适当的行动,减少社交欺凌的原因。因此,我们使用 Flask 技术部署了我们的机器学习模型。

以下是该网站的快照:-

该网站是使用 HTML 和 CSS 建立的,人们可以在网站的文本框中输入推文。

考虑我们提出的模型的两个用例

1-用户输入一条正面推文,然后被正确分类为正面推文。

2-用户输入一条仇恨推文,然后正确地被归类为仇恨推文。

关键见解和经验

政治、种族和性的推文构成了仇恨推文的主要部分。

当我们摆弄不平衡的数据集时,得到的结果是不准确的。由于训练数据的偏斜性质,该模型预测新数据属于训练集中的主要类。

在评估模型的性能时,分类器的加权精度不是唯一要考虑的度量。商业环境也扮演着重要的角色。

挑战和未来步骤

仇恨言论自动检测系统面临的一个挑战是随着时间和历史背景对话题的态度的改变。例如,在下面的摘录中:

“……残忍的印第安野蛮人,他们的战争规则是不分年龄、性别和条件一律格杀勿论……”

直觉表明这是仇恨言论;它将美洲原住民称为“无情的印第安野蛮人”,并暗示他们低人一等,使他们失去人性。事实上,该文本符合大多数仇恨言论定义中使用的条件。然而,这段文字实际上是引自《独立宣言》的。鉴于该文本的历史背景,发布该文本的用户可能并不打算获得仇恨言论的结果,而是为了其他目的而引用该历史文档。这表明用户意图和上下文在仇恨言论识别中起着重要作用。

作为另一个例子,考虑短语“纳粹组织是伟大的。”这将被视为仇恨言论,因为它显示了对仇恨团体的支持。然而,“纳粹的组织是伟大的”并不是支持他们的理想,而是在评论这个组织有多好。在某些情况下,这可能不被视为仇恨言论,例如,如果作者正在比较一段时间内的组织效率。这两个短语的区别很微妙,但足以区分是否是仇恨言论。

另一个挑战是,仇恨言论自动检测是一个闭环系统;个人意识到它正在发生,并积极试图逃避检测。希望传播仇恨信息的用户很快找到了规避这些措施的方法,例如,将内容发布为包含文本的图像,而不是文本本身。虽然可以采用光学字符识别来解决这一特殊问题,但这进一步表明了仇恨言论检测的难度。在那些试图传播仇恨内容的人和那些试图阻止它的人之间,这将是一场持续的战斗。

结论

随着仇恨言论继续成为一个社会问题,对仇恨言论自动检测系统的需求变得更加明显。在这份报告中,我们提出了一种通过使用单词袋和 TF IDF 值的机器学习来检测 Twitter 上仇恨言论和攻击性语言的解决方案。我们对多组特征值和模型参数进行了逻辑回归、朴素贝叶斯、决策树、随机森林和梯度推进的比较分析。结果显示逻辑回归与 TF IDF 方法相比表现更好。

我们提出了当前的问题,这个任务和我们的系统达到了合理的准确率(89%)和召回率(84%)。鉴于仍然存在的所有挑战,有必要对这一问题进行更多的研究,包括技术和实际问题。

参考文献

[1]ncbi.nlm.nih.gov/pmc/articles/PMC6701757/[在线]

[2] A. Gaydhani,V. Doma,S. Kendre 和 L. Bhagwat,“使用机器学习检测 Twitter 上的仇恨言论和攻击性语言:基于 N-gram 和 TF IDF 的方法”。

[3]https://www . nytimes . com/2019/11/12/us/hate-crimes-FBI-report . html

[4]https://www . daily prince tonian . com/article/2018/10/hate-speech-words-a second-look

使用深度学习在 Keras 中检测心律失常,包括 Dense、CNN 和 LSTM

原文:https://towardsdatascience.com/detecting-heart-arrhythmias-with-deep-learning-in-keras-with-dense-cnn-and-lstm-add337d9e41f?source=collection_archive---------4-----------------------

让我们从单个心电信号中检测异常心跳!

介绍

最近,我在回顾吴恩达团队(https://stanfordmlgroup.github.io/projects/ecg/)在卷积神经网络(CNN)心律失常检测器方面的工作。我发现这非常有趣,尤其是随着可穿戴产品(例如 Apple Watch 和便携式 EKG 机器)的出现,这些产品能够在家里监测你的心脏。因此,我很好奇如何建立一个可以检测异常心跳的机器学习算法。这里,我们将使用 ECG 信号(心脏的连续电测量)并训练 3 个神经网络来预测心律失常:密集神经网络、CNN 和 LSTM。

在本文中,我们将探讨 3 个教训:

  1. 分割患者数据集,而不是样本数据集
  2. 学习曲线可以告诉你获得更多的数据
  3. 测试多种深度学习模型

你可以跟随我的 github(【https://github.com/andrewwlong/deep_arrhythmias】)上提供的 Jupyter 笔记本。

资料组

我们将使用来自 https://physionet.org/content/mitdb/1.0.0/的 MIH-BIH 心律失常数据集,该数据集在 ODC 授权许可下可用。这是一个数据集,包含 20 世纪 70 年代以 360 Hz 测量的 48 个半小时双通道 ECG 记录。这些记录有心脏病专家对每次心跳的注释。注释符号可在https://archive.physionet.org/physiobank/annotations.shtml找到

项目定义

根据 ECG 信号预测心跳是否在以心跳峰值为中心的每 6 秒窗口内出现心律失常。

为了简化问题,我们假设 QRS 检测器能够自动识别每次心跳的峰值。由于数据减少,我们将忽略记录的前 3 秒或最后 3 秒中的任何非心跳注释和任何心跳。我们将使用一个 6 秒的窗口,这样我们就可以将当前节拍与之前和之后的节拍进行比较。这个决定是在与一位医生交谈后做出的,这位医生说,如果你有与之比较的东西,就更容易识别。

数据准备

让我们从列出 data_path 中的所有患者开始。

这里我们将使用 pypi 包 wfdb 来加载 ecg 和注释。

让我们加载所有注释,并查看心跳类型在所有文件中的分布。

我们现在可以列出非心跳和异常心跳:

我们可以按类别分组,并查看数据集中的分布情况:

看起来这个数据集中大约有 30%是不正常的。如果这是一个真正的项目,最好查阅文献。鉴于这是一个关于心律失常的数据集,我想这比正常情况要高!

让我们编写一个函数来加载单个患者的信号和注释。注意注释值是信号数组的索引。

让我们来看看患者的心电图中有哪些异常心跳:

我们可以用以下公式绘制异常心跳周围的信号:

制作数据集

让我们制作一个数据集,它以前后相差+- 3 秒的节拍为中心

def make_dataset(pts, num_sec, fs, abnormal):
    # function for making dataset ignoring non-beats
    # input:
    # pts - list of patients
    # num_sec = number of seconds to include before and after the beat
    # fs = frequency
    # output: 
    #   X_all = signal (nbeats , num_sec * fs columns)
    #   Y_all = binary is abnormal (nbeats, 1)
    #   sym_all = beat annotation symbol (nbeats,1)

    # initialize numpy arrays
    num_cols = 2*num_sec * fs
    X_all = np.zeros((1,num_cols))
    Y_all = np.zeros((1,1))
    sym_all = []

    # list to keep track of number of beats across patients
    max_rows = []

    for pt in pts:
        file = data_path + pt

        p_signal, atr_sym, atr_sample = load_ecg(file)

        # grab the first signal
        p_signal = p_signal[:,0]

        # make df to exclude the nonbeats
        df_ann = pd.DataFrame({'atr_sym':atr_sym,
                              'atr_sample':atr_sample})
        df_ann = df_ann.loc[df_ann.atr_sym.isin(abnormal + ['N'])]

        X,Y,sym = build_XY(p_signal,df_ann, num_cols, abnormal)
        sym_all = sym_all+sym
        max_rows.append(X.shape[0])
        X_all = np.append(X_all,X,axis = 0)
        Y_all = np.append(Y_all,Y,axis = 0)
    # drop the first zero row
    X_all = X_all[1:,:]
    Y_all = Y_all[1:,:]

    # check sizes make sense
    assert np.sum(max_rows) == X_all.shape[0], 'number of X, max_rows rows messed up'
    assert Y_all.shape[0] == X_all.shape[0], 'number of X, Y rows messed up'
    assert Y_all.shape[0] == len(sym_all), 'number of Y, sym rows messed up' return X_all, Y_all, sym_alldef build_XY(p_signal, df_ann, num_cols, abnormal):
    # this function builds the X,Y matrices for each beat
    # it also returns the original symbols for Y

    num_rows = len(df_ann) X = np.zeros((num_rows, num_cols))
    Y = np.zeros((num_rows,1))
    sym = []

    # keep track of rows
    max_row = 0 for atr_sample, atr_sym in zip(df_ann.atr_sample.values,df_ann.atr_sym.values): left = max([0,(atr_sample - num_sec*fs) ])
        right = min([len(p_signal),(atr_sample + num_sec*fs) ])
        x = p_signal[left: right]
        if len(x) == num_cols:
            X[max_row,:] = x
            Y[max_row,:] = int(atr_sym in abnormal)
            sym.append(atr_sym)
            max_row += 1
    X = X[:max_row,:]
    Y = Y[:max_row,:]
    return X,Y,sym

第 1 课:对患者而非样本进行分割

让我们从处理所有病人开始。

num_sec = 3
fs = 360
X_all, Y_all, sym_all = make_dataset(pts, num_sec, fs, abnormal)

想象一下,我们天真地决定按照样本将我们的数据随机分成一个训练集和一个验证集。

现在,我们准备建立我们的第一个密集神经网络。为了简单起见,我们将在 Keras 中这样做。如果你想看密集神经网络和另一个样本项目的方程,请参见我的另一篇文章这里,这是我在这里写的关于糖尿病再入院项目的深度学习后续。

我们可以为度量报告构建一些函数。有关数据科学分类指标的更多讨论,请参见我之前的帖子这里。

我们可以用predict_proba从 Keras 模型中得到预测

为简单起见,让我们将阈值设置为异常心跳的发生率,并计算我们的报告:

太神奇了!没那么难!但是等等,这对新病人有用吗?如果每个病人都有独一无二的心脏信号,也许就不会了。从技术上讲,同一个患者可以同时出现在训练集和验证集中。这意味着我们可能无意中泄露了数据集的信息。我们可以通过对病人而不是样本进行分割来测试这个想法。

并训练一个新的密集模型:

正如您可以看到的,验证 AUC 下降了很多,证实了我们之前有数据泄漏。经验教训:在病人身上而不是在样本上分开!

第二课:学习曲线可以告诉我们,我们应该得到更多的数据!

鉴于训练和验证之间的过度拟合。让我们做一个简单的学习曲线,看看我们是否应该去收集更多的数据。

aucs_train = []
aucs_valid = []n_pts = [1,18,36]
for n_pt in n_pts:

    print(n_pt)
    pts_sub = pts_train[:n_pt]
    X_sub, y_sub, sym_sub = make_dataset(pts_sub, num_sec, fs,abnormal)# build the same model
    # lets test out relu (a different activation function) and add drop out (for regularization)
    model = Sequential()
    model.add(Dense(32, activation = 'relu', input_dim = X_train.shape[1]))
    model.add(Dropout(rate = 0.25))
    model.add(Dense(1, activation = 'sigmoid'))# compile the model - use categorical crossentropy, and the adam optimizer
    model.compile(
                    loss = 'binary_crossentropy',
                    optimizer = 'adam',
                    metrics = ['accuracy']) model.fit(X_sub, y_sub, batch_size = 32, epochs= 5, verbose = 0)
    y_sub_preds_dense = model.predict_proba(X_sub,verbose = 0)
    y_valid_preds_dense = model.predict_proba(X_valid,verbose = 0)

    auc_train = roc_auc_score(y_sub, y_sub_preds_dense)
    auc_valid = roc_auc_score(y_valid, y_valid_preds_dense)
    print('-',auc_train, auc_valid)
    aucs_train.append(auc_train)
    aucs_valid.append(auc_valid)

经验教训:更多的数据似乎有助于这个项目!

我怀疑吴恩达的团队也得出了同样的结论,因为他们花时间注释了来自 29163 名患者的 64121 份心电图记录,这比任何其他公共数据集都多两个数量级(见https://stanfordmlgroup.github.io/projects/ecg/)。

第三课:测试多种深度学习模型

美国有线新闻网;卷积神经网络

先做个 CNN 吧。这里我们将使用一维 CNN(相对于 2D CNN 的图像)。

CNN 是一种特殊类型的深度学习算法,它使用一组过滤器和卷积算子来减少参数的数量。这种算法引发了图像分类的最新技术。从本质上讲,1D CNN 的工作方式是从第一个时间戳开始获取一个大小为kernel_size的过滤器(内核)。卷积运算符采用过滤器,并将每个元素乘以第一个kernel_size时间步长。然后对神经网络下一层中的第一个细胞的这些乘积求和。然后过滤器移动stride时间步长并重复。Keras 中默认的stride是 1,我们将使用它。在图像分类中,大多数人使用padding,它允许你通过添加“额外”的单元格来提取图像边缘的一些特征,我们将使用默认填充 0。卷积的输出然后乘以一组权重 W 并加到偏差 b 上,然后像在密集神经网络中一样通过非线性激活函数。然后,如果需要,您可以使用其他 CNN 图层重复此操作。这里我们将使用 Dropout,这是一种通过随机删除一些节点来减少过拟合的技术。

对于 Keras 的 CNN 模型,我们需要对我们的数据进行一点改造

在这里,我们将是一个一层 CNN 与辍学

CNN 的性能似乎比密集神经网络更高。

RNN: LSTM

由于该数据信号是时间序列,因此测试递归神经网络(RNN)是很自然的。这里我们将测试一种双向长短期记忆(LSTM)。与密集的神经网络和有线电视新闻网不同,RNN 在网络中有环路来保存过去发生的事情的记忆。这允许网络将信息从早期时间步骤传递到后期时间步骤,这在其他类型的网络中通常会丢失。本质上,在通过非线性激活函数之前,在计算中对于该存储器状态有一个额外的项。这里我们使用双向信息,这样信息可以双向传递(从左到右和从右到左)。这将有助于我们获得关于中心心跳左右两侧正常心跳的信息。

如下图所示,这花了很长时间来训练。为了使这个项目成为一个周末项目,我将训练集减少到 10,000 个样本。对于一个真正的项目,我会增加历元的数量,并使用所有的样本。

似乎该模型需要从额外的时期进行正则化(即删除)。

最终 ROC 曲线

这是这三个模型的最终 ROC 曲线

给更多的时间,这将是很好的尝试优化超参数,看看我们是否可以得到密集或 CNN 甚至更高。

限制

因为这只是一个周末项目,所以有一些限制:

  • 没有优化超参数或层数
  • 没有按照学习曲线的建议收集额外的数据
  • 没有研究心律失常患病率的文献,以了解该数据集是否代表一般人群(可能不是)

感谢阅读!

使用深度学习检测疟疾。

原文:https://towardsdatascience.com/detecting-malaria-using-deep-learning-fd4fdcee1f5a?source=collection_archive---------6-----------------------

构建卷积神经网络以快速预测薄血涂片中疟疾寄生细胞的存在。

Nightmare: Malaria (Source)

答虽然疟疾病毒没有以变异蚊子的形式出现,但肯定觉得这是一个变异问题。这种致命的疾病在世界不同地区已经达到流行病甚至地方病的比例——每年杀死大约 40 万人[1]。在世界上的其他地方,它几乎不存在。一些地区特别容易爆发疾病——某些因素使得一个地区更容易感染疟疾[2]。

  • 高度贫困
  • 缺乏适当的医疗保健
  • 政治不稳定
  • 疾病传播媒介的存在(例如蚊子)〔6〕

由于这些问题的混合,我们在构建模型时必须记住一些事情:

  • 可能缺少一个可靠的电源
  • 电池供电的设备具有较少的计算能力
  • 可能缺少互联网连接(所以在云上训练/存储可能很难!)

虽然我们希望获得尽可能高的精确度,但我们也必须考虑让模型尽可能小,计算效率尽可能高,并且能够部署到边缘和物联网设备。

目前对该病的诊断方法繁琐费时。

Thin film of red blood cells. Stained parasites are deep purple. (Source)

最广泛使用的方法(到目前为止)是在显微镜下检查薄血涂片,并目测寻找受感染的细胞。患者的血液涂在载玻片上,用造影剂染色,以便更好地识别红细胞中受感染的寄生虫。

然后,临床医生手动计数寄生红细胞的数量有时高达 5000 个细胞(根据世卫组织协议)【3】。

为什么是卷积神经网络?

卷积神经网络具有自动提取特征和学习过滤器的能力。在以前的机器学习解决方案中,特征必须手动编程——例如,大小、颜色、细胞的形态。利用卷积神经网络(CNN)将大大加快预测时间,同时反映(甚至超过)临床医生的准确性。

我们将使用 Keras、Tensorflow 后端,如果你还没有安装的话,请继续安装。一定要同时安装 NumpyScikit-learnMatplotlib、imutils(Adrian rose Brock 创建的一个图像处理和深度学习便利功能包)。

资料组

幸运的是,我们有一个巨大的标签和预处理图像数据集来训练和评估我们的模型。NIH 拥有 27,558 个细胞图像的疟疾数据集,其中寄生和未感染细胞的数量相等。应用基于水平集的算法来检测和分割红细胞。这些图像是由医学专业人员收集和注释的;更多信息可在这里找到。此外,从页面下载数据:文件被命名为 cell_images.zip

源代码

我用 Keras 复制了 Adrian Rosebrock 的博文深度学习和医学图像分析,这里可以找到。按照他的代码,我在 GitHub 上发布了我的版本。你可以在这里下载项目的源代码来跟进或者创建你自己的项目。

我们开始吧!

设置

首先,创建一个文件夹/目录来存储项目。然后,在名为 malaria 的目录中创建一个目录,将数据集下载到该目录中并打开它。

$ cd whatever-you-named-your-directory
$ mkdir malaria
$ cd malaria
$ wget [https://ceb.nlm.nih.gov/proj/malaria/cell_images.zip](https://ceb.nlm.nih.gov/proj/malaria/cell_images.zip)
$ unzip cell_images.zip

我们将切换回我们的父目录,并创建另一个名为 cnn 的目录,在那里我们存储我们的配置文件和网络架构。

$ cd ..
$ mkdir cnn
$ cd cnn

配置文件

cnn 里面创建一个模块,命名为 config.py. 这是我们的配置文件,它会存储我们所有的常量变量。

我们的配置文件初始化所有的路径到我们的

  • 原始数据集(第 4 行)
  • 包含培训和测试之间划分的目录(第 8 行)
  • 以及我们新分离的训练、验证和测试数据集(第 11–13 行)。

80% 的数据被留出用于原始数据集中的训练(第 16 行)。然后,在训练数据之外,另一个 10% 百分比将被用作验证数据(第 20 行)。

构建数据集

创建一个名为 build_dataset.py 的模块,它应该位于您的原始目录中。 build_dataset.py 将用于在文件系统中创建路径。打开它并插入下面的代码。

导入所有必要的包(第 3–5 行)后,我们将打乱原始数据集中的所有图像(第 8–10 行)。

首先,让我们使用从我们的配置文件(第 2–4 行)中设置的值定义的索引来分割训练数据和测试数据;然后,我们使用索引来执行数组切片。

通过用另一个值覆盖索引,并重复相同的过程,留出一些训练数据用于验证(第 7–9 行)。

之后,我们将定义新分离的训练、验证和测试数据集。列表数据集包含 3 元组,其中包含:

  1. 拆分的名称
  2. 分割的图像路径
  3. 拆分的输出目录的路径

现在,我们可以在数据集上循环。

第 4 行将打印它正在创建哪个数据分割,第 7–9 行将创建一个输出目录,如果它不存在的话。

在第 12 行,我们开始遍历输入图像路径。第 14 行将提取输入图像的文件名,第 15 行将提取相应的类标签(寄生,未寄生)。

然后,构建子目录的路径(第 18 行),如果它们不存在就创建它们(第 21–23 行)。每个子目录(测试、验证和培训)被分成寄生和未寄生的映像。

最后,我们将构建实际图像的路径,并将其复制到子目录中(第 27–28 行)。

我们现在可以建立我们的目录了!打开终端,执行以下命令:

$ python build_dataset.py

输出应该如下所示:

[INFO] building 'training' split
[INFO] 'creating malaria/training' directory
[INFO] 'creating malaria/training/Uninfected' directory
[INFO] 'creating malaria/training/Parasitized' directory
[INFO] building 'validation' split
[INFO] 'creating malaria/validation' directory
[INFO] 'creating malaria/validation/Uninfected' directory
[INFO] 'creating malaria/validation/Parasitized' directory
[INFO] building 'testing' split
[INFO] 'creating malaria/testing' directory
[INFO] 'creating malaria/testing/Uninfected' directory
[INFO] 'creating malaria/testing/Parasitized' directory

现在我们已经处理了数据,让我们开始训练我们的模型。在我们开始之前,让我们快速看一下我们将使用的网络架构:Adrian Rosebrock 在他的书 中使用 Python 复制的一个 ResNet 模型。他的模型是基于何等人 2015 年学术出版物 用于图像识别的深度残差学习。艾尔。【6】,但更小更紧凑*(我们正试图为我们的型号减小存储空间)。*

模型架构(ResNet)

首先,我们为什么选择 ResNet ?在 Rajaraman 等人完成的一项研究中,他们使用预训练的卷积神经网络对我们正在使用的同一数据集中的图像进行分类。他们比较了六个模型:AlexNet、VGG-16、ResNet-50、Xception、DenseNet-121,以及他们建造的一个定制模型。他们的结果显示ResNet-50 模型在这个特定的数据库上始终显示出最准确的结果* —它在 MCC 和 F-1 评分(这些在医疗保健应用中很重要)等指标上也具有最高的性能[4]。***

Source: [4]

然而,当他们在最佳层(使用特征提取)而不是最终层上运行时,DenseNet-121 在灵敏度(这可以说是医疗保健设置中最重要的指标之一)方面胜过它。**

Source: [4]

你可以从这里下载代码,但是如果你已经有了源代码,它就在 cnn 下的文件夹里。关于如何从头开始实现的详细解释(以及为什么它如此有效的基本解释),你可以在这里查看我的文章。**

训练模型

在您的原始目录中创建一个名为 train_model.py 的文件。

看看我们要导入的包:

  • keras 训练我们的模型(第 1-3 行)
  • 我们的自定义 ResNet 模型类(第 4 行),和配置文件(第 5 行)
  • sklearn 打印分类报告(第 6 行)
  • 在第 7 行从我们的数据集中抓取路径(使用 imutils )
  • Matplotlib 用于绘制我们的图表(第 8 行)
  • numpy 进行数值加工(第 9 行)
  • argparse 用于命令行参数解析(第 10 行)

请注意,我们使用“Agg”后端来处理 matplotlib ,因为我们正在将我们的绘图保存到磁盘。

我们唯一需要解析的命令行参数是" — plot " 。它将默认放置在当前工作目录中(在这种情况下,它将是您的父目录),并命名为“plot.png”。执行程序时,可以在命令行重命名该文件。**

训练参数和学习率衰减函数

首先,让我们将我们想要训练的段数 设置为 50 (第 2 行)我们的学习率将被初始化为 0.1 (第 3 行),它将根据我们的衰减函数(第 9–20 行上的 poly_decay )进行衰减。批处理大小将被设置为 32 (第 4 行),如果你在 CPU 上运行它,这是一个好数字,但是如果你使用 GPU,你可以将它增加到 64。****

我们的多项式衰减函数将使我们的学习率在每个时期后衰减(第 9 行)。我们将幂初始化为 1.0(第 14 行),这将我们的多项式衰减变成了线性衰减。这是为了在我们的模型上减少过度配合****

接下来,让我们获取测试/验证/测试集(第 2-4 行)中的图像路径总数,以确定验证&训练的每个时期的总步骤数。**

数据增强

数据扩充应用到我们的图像有助于规则化(这有助于减轻过度拟合)。我们的网络将更好地概括验证数据(这可能意味着在训练集上表现更差)。**

首先,让我们通过初始化 ImageDataGenerator 对我们的训练数据进行数据扩充。我们将把像素值重新调整到范围[0,1](第 4 行),并对每个训练示例执行随机变换(第 5–11 行)。

对于我们的验证和训练数据,我们只是将像素值重新调整到范围[0,1]。

培训/测试/验证生成器

现在让我们初始化我们的训练生成器,它将从我们的输入目录加载图像。

Kerasflow _ from _ directory函数有两个先决条件:一个用于数据拆分的基本输入目录,以及基本输入目录内的 N 个子目录,其中每个子目录对应一个类标签(在我们的例子中,N = 2;寄生和未寄生)。**

看一下输入到每台发电机的参数:

  • class_mode 被设置为“分类,以对类别标签执行一键编码(第 4/13/22 行)**
  • target_size :图像被调整到 64 x 64 像素(第 5/14/23 行)
  • 颜色模式设置为“ rgb 通道排序(第 6/15/24 行)
  • 混洗图像路径仅设置为训练发生器的(第 7 行)**
  • batch_size 被设置为 BS = 32(我们已经在前面的学习率部分进行了初始化)(第 8/17/26 行)

正在初始化 ResNet 模型

在第 2–3 行,我们用以下参数初始化 ResNet。

  • 图像为 64 x 64 x 3(长度、宽度和深度—三通道 RGB 图像)
  • 2 类(寄生和未寄生)
  • 阶段= (3,4,6)
  • 过滤器= (64,128,256,512)

这意味着第一 CONV 层(在减少空间维度之前)将具有 64 个总滤波器。

首先,我们将堆叠 3 组残差模块,每个残差模块中的 3 个 CONV 层将分别学习 32、32 和 128 滤波器。应用维数缩减。

然后,应用 4 组剩余模块。三个 CONV 层将学习 64、64 和 256 过滤器——再次应用维度缩减。**

最后, 6 组剩余模块再次堆叠,其中每个 CONV 层学习 128、128 和 512 滤波器。空间维度最终被缩减(查看我的文章这里关于阶段和过滤器的解释)。

我们将使用的优化器是随机梯度下降(第 4 行)。我们的学习率设置为 0.1动量*项为 0.9。***

最后,我们在第 5–9 行编译我们的模型。我们的损失函数被设置为二进制交叉熵,因为我们正在执行二进制、二类分类。**

现在,让我们定义我们的一组回调——在每个时期结束时执行。为了在每个时期后衰减我们的学习率,我们应用了poly _ decaylearning rate scheduler(第 2 行)。**

第 3–9 行的 model.fit_generator 调用告诉我们的脚本开始我们的训练过程。 trainGen 生成器自动从磁盘加载我们的图像,并解析图像路径中的类标签。 valGen 对验证数据做同样的事情。

既然我们已经完成了训练部分,我们可以在我们的测试集上评估它。我们将对测试数据(第 4–5 行)进行预测,并为数据集中的每幅图像找到概率最大的标签(第 10 行)。

然后,我们将在终端中打印一份分类报告(第 13–14 行)。

最后,我们将绘制我们的测试验证损失,以及我们的验证测试准确性的图表,以查看我们做得如何。**

结果

通过参考 GitHub 上的我的知识库,确保你的项目结构正确。现在,打开一个终端并执行以下命令:

*$ python train_model.py*

在你的模型完成训练后,看看分类报告。

你应该获得

  • 训练数据的准确率为 96.50%
  • 96.78%准确率上验证数据
  • 测试数据上有 97%的准确度

总的来说,序列化的模型文件只有17.7 MB。量化模型本身的权重将允许我们获得 10MB 的模型 <。**

现在您拥有了一个完整的端到端疟疾分类系统!

现在,您可以将该模型保存到磁盘上,并加载新的图像进行预测。您也可以在您的网站或应用程序上部署它。

如果您有任何问题,请在评论中或通过以下方式联系我们:

  • 领英:https://www.linkedin.com/in/gracelynshi/
  • 给我发电子邮件到gracelyn.shi@gmail.com****

特别感谢 PyImageSearch 的 Adrian Rosebrock 博士就此发表的博客文章和附带的代码[6]。

参考文献

[1]:世界卫生组织,概况介绍:2016 年世界疟疾报告,https://www . who . int/Malaria/media/World-Malaria-Report-2016/en/(2016 年 12 月 13 日)。**

[2]世界卫生组织,疟疾,https://www.who.int/news-room/fact-sheets/detail/malaria(2018 年 11 月 19 日)。**

[3]: 卡洛斯·阿蒂科·阿里扎,疟疾英雄:一个用于更快诊断疟疾的 web 应用https://blog . insightdatascience . com/https-blog-insightdatascience-com-Malaria-Hero-A 47 D3 D5 fc 4 bb(2018 年 11 月 6 日)**

[4]: Rajaraman 等人,预训练卷积神经网络作为特征提取器,用于改进薄血涂片图像中疟原虫的检测(2018) 。PeerJ 6:e 4568;DOI 10.7717/peerj.4568**

[5]何国光,张,任,孙,【2015】****

[6] A. Rosebrock,深度学习和医学图像分析 (2017),https://www . pyimagesearch . com/2018/12/03/Deep-Learning-and-Medical-Image-Analysis-with-keras/**

[7] A. Rosebrock, 用 Python 进行计算机视觉的深度学习 (2017)

用深度学习检测疟疾

原文:https://towardsdatascience.com/detecting-malaria-with-deep-learning-9e45c1e34b60?source=collection_archive---------4-----------------------

人工智能造福社会系列—第一部分

人工智能促进社会公益——医疗保健案例研究

Photo by Hal Gatewood on Unsplash

本文内容改编自我之前在 opensource.com发表的 自己的文章

介绍

欢迎来到 AI for Social Good 系列,在这里我们将关注人工智能(AI)与流行的开源工具、技术和框架如何被用于发展和改善我们的社会的不同方面。“健康就是财富”也许是一句老掉牙的名言,但却是千真万确的!在这篇特别的文章中,我们将看看如何利用人工智能来检测疟疾这一致命疾病,以及建立一个低成本、有效而准确的开源解决方案的前景。这篇文章的目的是双重的——理解致命疾病疟疾的动机和重要性,以及深度学习在检测疟疾方面的有效性。我们将在本文中讨论以下主要话题。

  • 该项目的动机
  • 疟疾检测方法
  • 用于疟疾检测的深度学习
  • 从零开始训练的卷积神经网络
  • 用预训练模型转移学习

在我们开始之前,我想指出,我既不是医生,也不是医疗保健研究员,我远不如他们有资格。不过,我确实对将人工智能应用于医疗保健研究感兴趣。本文的目的不是深入宣传人工智能将取代工作岗位并接管世界,而是展示人工智能如何有助于疟疾检测、诊断并通过低成本有效且准确的开源解决方案减少人工劳动。

Python and TensorFlow — A great combo to build open-source deep learning solutions

由于 Python 和深度学习框架(如 TensorFlow)的强大功能,我们可以构建健壮、可扩展和有效的深度学习解决方案。这些工具的额外好处是开源和免费的,使我们能够构建真正具有成本效益的解决方案,并且每个人都可以轻松采用和使用。我们开始吧!

动机

疟疾是一种致命的传染性蚊媒疾病,由疟原虫寄生虫引起。这些寄生虫通过受感染的雌性按蚊的叮咬传播。虽然我们不会深入了解这种疾病的细节,但疟疾有五种主要类型。现在让我们看看这种疾病在下面的情节中有多致命的意义。

Malaria Estimated Risk Heath Map (Source: treated.com)

很明显,疟疾在全球流行,尤其是在热带地区。然而,该项目的动机是基于这种疾病的性质和致命性。最初,如果被感染的蚊子叮咬,蚊子携带的寄生虫会进入你的血液,并开始破坏携氧的红细胞。通常情况下,疟疾的最初症状类似于流感或病毒,通常在蚊子叮咬后几天或几周内开始感到恶心。然而,这些致命的寄生虫可以在你的身体里存活一年以上,没有任何问题!因此,延误正确的治疗会导致并发症甚至死亡。因此,疟疾的早期有效检测可以拯救生命。

世界卫生组织(世卫组织)发布了一些关于疟疾的重要事实,你可以在这里查看。简而言之,近一半的世界人口面临疟疾的威胁,每年有超过 2 亿的疟疾病例和大约 40 万人死于疟疾。这给了我们更大的动力,让疟疾的检测和诊断变得快速、简单和有效。

疟疾检测方法

有几种方法和测试可用于疟疾的检测和诊断。我们的数据和分析所基于的原始论文是 S Rajaraman 等人的 【预训练卷积神经网络作为特征提取器用于改进薄血涂片图像中疟原虫的检测】 。艾尔。向我们简要介绍了其中的一些方法。这些包括但不限于厚薄血涂片检查、聚合酶链反应(PCR)和快速诊断测试(RDT)。虽然我们不会在此详细介绍所有方法,但需要记住的重要一点是,后两种测试是替代方法,通常在无法提供高质量显微镜服务的情况下使用。

我们将简要讨论基于典型血液涂片工作流程的标准疟疾诊断,这要感谢 Carlos Ariza 关于洞察数据科学的精彩文章,这是我从 Adrian Rosebrock 关于疟疾检测的精彩文章pyimagesearch中了解到的,所以我衷心感谢他们两位提供了如此优秀的资源,让我在这个领域有了更多的视角。

A blood smear workflow for Malaria detection (Source)

根据《世卫组织议定书》的指导原则,这一程序包括以 100 倍的放大倍数对血液涂片进行强化检查,在此过程中,人们从 5000 个细胞中人工计数含有寄生虫的红细胞。事实上拉贾拉曼等人的论文。艾尔。我们之前提到的,谈到了完全相同的事情,为了使事情更清楚,我引用了这篇论文中的一个例子。

厚血涂片有助于检测寄生虫的存在,而薄血涂片有助于识别引起感染的寄生虫的种类(疾病控制和预防中心,2012 年)。诊断的准确性很大程度上依赖于人的专业知识,并可能受到观察者之间的变异性和疾病流行/资源受限地区大规模诊断所带来的责任的不利影响(Mitiku,Mengistu & Gelaw,2003)。使用聚合酶链式反应(PCR)和快速诊断测试(RDT)等替代技术;然而,PCR 分析的性能有限(Hommelsheim 等人,2014 年),而快速诊断技术在疾病流行地区的成本效益较低(Hawkes,Katsuva & Masumbuko,2009 年)。

因此,疟疾检测肯定是一个密集的手动过程,也许可以使用深度学习实现自动化,这是本文的基础。

用于疟疾检测的深度学习

对于常规的手工诊断血涂片,这是一个密集的手工过程,需要适当的专业知识来分类和计数被寄生和未被感染的细胞。通常情况下,这可能无法很好地扩展,如果我们在全球特定地区没有合适的专业知识,可能会带来问题。在利用最先进的(SOTA)图像处理和分析技术来提取手工设计的特征和建立基于机器学习的分类模型方面,已经取得了一些进展。然而,这些模型是不可扩展的,因为有更多的数据可用于训练,并且考虑到手工设计的特征需要大量时间的事实。

深度学习模型,或者更具体地说,卷积神经网络(CNN)已经被证明在各种各样的计算机视觉任务中非常有效。虽然我们假设你对 CNN 有所了解,但如果你不了解,请点击这里的查看这篇文章。简而言之,CNN 模型中的关键层包括卷积层和池层,如下图所示。

A typical CNN architeture (Source: deeplearning.net)

卷积层从数据中学习空间层次模式,这也是平移不变的。因此,他们能够学习图像的不同方面。例如,第一卷积层将学习小的和局部的图案,例如边缘和拐角,第二卷积层将基于来自第一层的特征学习更大的图案,等等。这允许 CNN 自动化特征工程并学习在新数据点上概括良好的有效特征。合并图层有助于缩减采样和降维。

因此,CNN 帮助我们进行自动化和可扩展的特征工程。此外,在我们的模型末尾插入密集层使我们能够执行像图像分类这样的任务。使用深度学习模型(如 CNN)的自动化疟疾检测可能非常有效、廉价和可扩展,特别是随着迁移学习和预训练模型的出现,这些模型即使在数据较少等限制下也能很好地工作。

Rajaraman 等人的论文,' 预训练卷积神经网络作为特征提取器,用于改进薄血涂片图像中的寄生虫检测 ' 利用他们论文中提到的数据的总共六个预训练模型,在检测疟疾与未感染样本方面获得了令人印象深刻的 95.9%的准确性。我们的重点是从头开始尝试一些简单的 CNN 模型和几个使用迁移学习的预训练模型,看看我们在同一数据集上得到的结果!我们将使用包括 Python 和 TensorFlow 在内的开源工具和框架来构建我们的模型。

数据集详细信息

让我们讨论一下我们将在分析中使用的数据集。我们很幸运,李斯特山国家生物医学通讯中心(LHNCBC)的研究人员(国家医学图书馆(NLM)的一部分)仔细收集并注释了健康和感染血液涂片图像的数据集。你可以从 官网 下载这些图片。

事实上,他们开发了一个移动应用程序,可以在连接到传统光学显微镜的标准 Android 智能手机上运行(Poostchi 等人,2018 年)。在孟加拉国吉大港医学院医院收集 150 名恶性疟原虫感染患者和 50 名健康患者的吉姆萨染色薄血涂片并拍照。智能手机的内置摄像头可以获取每个微观视野的幻灯片图像。这些图像由泰国曼谷的玛希多-牛津热带医学研究中心的专家幻灯片阅读者手工注释。让我们简单地检查一下我们的数据集结构。我们首先根据正在使用的操作系统安装一些基本的依赖项。

我在云上使用基于 Debian 的系统,它有一个 GPU,所以我可以更快地运行我的模型!安装树依赖项,以防您没有它,这样我们可以查看我们的目录结构(**sudo apt install tree**)。

看起来我们有两个文件夹,里面有被感染和健康细胞的图像。使用下面的代码,我们可以获得图像总数的更多细节。

看起来我们有了一个平衡的数据集,包括 13779 疟疾非疟疾(未感染)细胞图像。让我们以此为基础构建一个数据框架,它将在我们开始构建数据集时对我们有用。

构建和浏览影像数据集

为了建立深度学习模型,我们需要训练数据,但我们也需要在看不见的数据上测试模型的性能。我们将分别对训练、验证和测试数据集使用 60:10:30 的分割。我们将在训练期间利用训练和验证数据集,并在测试数据集上检查模型的性能。

显然,由于血液涂片和细胞图像会因人、测试方法和照片拍摄方向的不同而有所不同,因此图像的尺寸会有所不同。让我们获取一些训练数据集的汇总统计数据,以确定最佳图像尺寸(请记住,我们根本不接触测试数据集!).

我们应用并行处理来加速图像读取操作,并且基于汇总统计数据,我们决定将每个图像的大小调整为**125x125**像素。让我们加载所有的图像,并调整它们的大小到这些固定的尺寸。

我们再次利用并行处理来加速与图像加载和大小调整相关的计算。最后,我们得到了前面输出中描述的所需维数的图像张量。我们现在可以查看一些样本细胞图像,以了解我们的数据是什么样子的。

根据上面的样本图像,我们可以注意到疟疾和健康细胞图像之间的一些细微差异。我们基本上会让我们的深度学习模型在模型训练的时候尝试学习这些模式。在开始训练我们的模型之前,我们设置一些基本的配置设置。

我们固定我们的图像尺寸、批量大小、时期并编码我们的分类标签。TensorFlow 2.0 的 alpha 版本于 2019 年 3 月发布,就在本文撰写的几周前,它给了我们一个完美的借口来尝试它!

深度学习模型训练阶段

在模型训练阶段,我们将建立几个深度学习模型,并在我们的训练数据上训练它们,并在验证数据上比较它们的性能。然后,我们将保存这些模型,并在稍后的模型评估阶段再次使用它们。

模型 1: CNN 从零开始

我们的第一个疟疾检测模型将从头开始构建和训练一个基本的卷积神经网络(CNN)。首先让我们定义我们的模型架构。

基于前面代码中的架构,我们的 CNN 模型有三个卷积和池层,后面是两个密集层和正则化丢弃层。现在就来训练我们的模型吧!

我们得到了一个95.6%的验证精度,这已经很不错了,尽管我们的模型看起来有点过拟合,看看我们的 训练精度99.9%。我们可以通过绘制训练和验证准确性和损失曲线来清楚地了解这一点。**

Learning Curves for Basic CNN

因此,我们可以看到,在第五纪元后,事情似乎并没有整体改善很多。这个模型还是留着以后评估吧。

****model.save('basic_cnn.h5')****

深度迁移学习

正如人类具有跨任务转移知识的固有能力一样,转移学习使我们能够利用以前学习的任务中的知识,并将它们应用到更新的相关任务中,即使是在机器学习或深度学习的背景下。对迁移学习的全面介绍可以在我的文章和我的书中找到,供有兴趣深入研究的读者参考。**

Ideas for deep transfer learning

就本文的目的而言,我们的想法是,我们能否利用预先训练的深度学习模型(在大型数据集上训练——如 ImageNet )通过在我们的问题背景下应用和转移其知识来解决疟疾检测的问题?

我们将应用两种最流行的深度迁移学习策略。

  • 作为特征提取器的预训练模型
  • 经过微调的预训练模型

我们将使用牛津大学视觉几何小组(VGG)开发的预训练 VGG-19 深度学习模型进行实验。像 VGG-19 这样的预训练模型是在具有许多不同图像类别的巨大数据集(ImageNet)上已经预训练的模型。考虑到这一事实,该模型应该已经学习了特征的健壮层次,这些特征相对于由 CNN 模型学习的特征是空间、旋转和平移不变的。因此,该模型已经学习了超过一百万幅图像的特征的良好表示,可以作为新图像的良好特征提取器,适用于计算机视觉问题,就像疟疾检测一样!在针对我们的问题释放迁移学习的力量之前,让我们简要讨论一下 VGG-19 模型架构。

了解 VGG-19 模型

VGG-19 模型是建立在 ImageNet 数据库上的 19 层(卷积和全连接)深度学习网络,其建立的目的是图像识别和分类。这个模型是由卡伦·西蒙扬和安德鲁·齐泽曼建立的,并在他们题为‘用于大规模图像识别的超深度卷积网络’的论文中提到。我推荐所有感兴趣的读者去阅读这篇文章中的优秀文献。下图描述了 VGG-19 模型的架构。

VGG-19 Model Architecture

您可以清楚地看到,我们共有使用**3 x 3**卷积滤镜的**16**卷积层,以及用于缩减采样的 max pooling 层,并且共有两个完全连接的隐藏层,每个层中有**4096**个单元,后面是一个密集的**1000**个单元层,其中每个单元代表 ImageNet 数据库中的一个图像类别。我们不需要最后三层,因为我们将使用我们自己的完全连接的密集层来预测疟疾。我们更关心前五个模块,这样我们可以利用 VGG 模型作为有效的特征提取器。

对于其中一个模型,我们将通过冻结所有五个卷积块来将其用作简单的特征提取器,以确保它们的权重不会在每个时期后更新。对于最后一个模型,我们将对 VGG 模型进行微调,其中我们将解冻最后两个块(块 4 和块 5),以便在我们训练自己的模型时,它们的权重在每次迭代(每批数据)中得到更新。

模型 2:作为特征提取器的预训练模型

为了构建这个模型,我们将利用 TensorFlow 加载 VGG-19 模型,并冻结卷积块,以便我们可以将其用作图像特征提取器。我们将在最后插入我们自己的密集层来执行分类任务。

因此,从前面的输出中很明显,我们的模型中有许多层,我们将只使用 VGG-19 模型的冻结层作为特征提取器。您可以使用以下代码来验证我们的模型中有多少层确实是可训练的,以及我们的网络中总共有多少层。

现在,我们将使用与之前模型相似的配置和回调来训练我们的模型。参考 我的 GitHub 库 获取训练模型的完整代码。我们观察到下面的曲线显示了模型的准确性和损失。

Learning Curves for frozen pre-trained CNN

这表明我们的模型并没有像我们的基本 CNN 模型那样过度拟合,但是性能并没有真的更好,事实上比我们的基本 CNN 模型略差。现在让我们保存这个模型,以便将来评估。

****model.save('vgg_frozen.h5')****

模型 3:带有图像增强的微调预训练模型

在我们的最终模型中,我们将微调预训练 VGG-19 模型的最后两个块中存在的层的权重。除此之外,我们还将介绍图像增强的概念。图像增强背后的想法就像它的名字一样。我们从训练数据集中加载现有图像,并对其应用一些图像变换操作,如旋转、剪切、平移、缩放等,以产生现有图像的新的、改变的版本。由于这些随机变换,我们每次得到的图像并不相同。我们将利用**tf.keras**中一个名为**ImageDataGenerator**的优秀工具,它可以帮助我们构建图像增强器。

除了缩放图像(这是强制性的)之外,我们不对验证数据集应用任何变换,因为我们将使用它来评估每个时期的模型性能。对于迁移学习环境中图像增强的详细解释,如果需要,请随意查看我的文章。让我们来看看一些来自一批图像增强变换的样本结果。

Sample Augmented Images

在前面的输出中,您可以清楚地看到图像的细微变化。我们现在将建立我们的深度学习模型,确保 VGG-19 模型的最后两个模块是可训练的。

我们降低了模型中的学习率,因为我们不想在微调时对预训练层进行大的权重更新。该模型的训练过程将略有不同,因为我们使用数据生成器,因此我们将利用**fit_generator(…)** 函数。

这看起来是我们迄今为止最好的模型,给了我们几乎 96.5%的验证准确度 ,并且基于训练准确度,看起来我们的模型没有我们的第一个模型那样过度拟合。这可以用下面的学习曲线来验证。****

Learning Curves for fine-tuned pre-trained CNN

让我们现在保存这个模型,以便我们可以很快在我们的测试数据集上使用它进行模型评估。

******model.save('vgg_finetuned.h5')******

这就完成了我们的模型训练阶段,我们现在准备在实际的测试数据集上测试我们的模型的性能!

深度学习模型性能评估阶段

我们现在将评估我们刚刚在训练阶段构建的三个不同的模型,方法是使用它们对来自我们测试数据集的数据进行预测,因为仅仅验证是不够的!我们还构建了一个名为**model_evaluation_utils**的漂亮实用模块,我们将使用它来评估我们的深度学习模型和相关分类指标的性能。这里的第一步显然是扩展我们的测试数据。

下一步涉及加载我们保存的深度学习模型,并对测试数据进行预测。

最后一步是利用我们的**model_evaluation_utils**模块,用相关的分类指标检查每个模型的性能。

看起来我们的第三个模型在测试数据集上的表现是我们所有三个模型中最好的,给出了模型 准确性 以及f1-分数***96%,这非常好,与我们之前提到的研究论文和文章中提到的更复杂的模型相当!***

结论

在本文中,我们看到了一个有趣的疟疾检测的真实世界医学成像案例研究。疟疾检测本身并不是一个简单的过程,全球各地是否有合适的人员也是一个严重的问题。我们研究了利用人工智能的易于构建的开源技术,这些技术可以为我们提供检测疟疾的最先进的准确性,从而使人工智能造福社会。我鼓励每个人查阅本文中提到的文章和研究论文,没有它们,我就不可能构思和写这篇文章。让我们期待医疗保健行业更多地采用开源人工智能功能,让世界各地的每个人都可以更便宜地使用它!

本文改编自我之前在 opensource.com发表的 自己的文章

如果您有兴趣运行或采用本文中使用的所有代码,可以在my GitHub repository上找到。

记得从 官网 下载数据。

用 Jetson Xavier 在无人机上探测行人和骑车人

原文:https://towardsdatascience.com/detecting-pedestrians-and-bikers-on-a-drone-with-jetson-xavier-93ce92e2c597?source=collection_archive---------18-----------------------

rones 是每个制造商和发烧友都想拥有的最酷的技术之一。与此同时,随着无人机变得越来越普遍,人工智能正在快速发展,我们现在正处于一个可以在无人机上进行物体检测和语义分割的状态。在这篇博文中,我将分享如何对无人机拍摄的图像进行物体检测。

手头问题的一些基础知识

  • 首先,重要的是要认识到,我们无法在通用嵌入式硬件(如 raspberry pi)上实际运行对象检测,因此需要为人工智能推理构建专用硬件。
  • 第二,如果你运行常用的对象检测模型,如在 COCO 和 Pascal VOC 数据集上训练的 YOLO 或 SSD,它们根本不会做得很好。这是因为从高处看一个物体和在地面上看是完全不同的。因此,推理数据的分布将与模型在训练期间遇到的分布非常不同,这将导致它失败。

一些解决方案

  • 正如这篇文章的标题中提到的,我将使用目前自主机器人可用的最高端嵌入式处理器,来自 Nvidia 的 Jetson AGX Xavier。如果你想使用 Jetson TX2 或 nano,我会在文章末尾提供一些改进它们性能的建议。
  • 为了解决不同数据分布的问题,斯坦福大学的研究人员发布了一个名为斯坦福无人机数据集的数据集,其中包含几个从无人机上拍摄的视频,以及每个视频每一帧的标签。被检测的有六个等级:BikerCarBusCartSkaterPedestrian

任何经过斯坦福数据集训练的像样的对象检测模型都应该能够很好地检测这六个对象。在这篇文章中,我们将使用 RetinaNet ,这是一个由脸书(FAIR)发布的非常好的对象检测模型,它以这样一种方式塑造损失函数,即模型在训练期间学习专注于困难的例子,从而学习得更好。更多关于 RetinaNet 的细节可以在这里找到。

获取模型并转换为 fp16

答虽然 FAIR 的 Detectron 2 model zoo 有几个模型可以下载和使用,但它们都是在 COCO 和 Pascal 数据集上训练的,正如我们所讨论的,这对我们的任务没有用。在斯坦福数据集上从头训练一个模型将是一项艰巨的任务。幸运的是,我发现 Nvidia 提供了一个在这个数据集上训练的模型,作为他们在 DeepStream SDK 上的一个网络研讨会的一部分。我并不想在这篇博文中支持 Nvidia,但是如果你想在没有训练自己的模型的情况下开始,最快的方法是注册网上研讨会并下载模型作为网上研讨会资源的一部分。你要找的文件是大约 150 MB 的stanford_resnext50.onnx

一旦你有了这个文件,你就可以使用 GitHub 的retinanet-examples库的 C++ API 将onnx文件转换成一个引擎plan文件,这个文件是专门为你正在使用的 Jetson 设备编译的。以下是这些步骤的演练:

git clone [https://github.com/NVIDIA/retinanet-examples.git](https://github.com/NVIDIA/retinanet-examples.git)
cd retinanet-examples/extras/cppapi
mkdir build && cd build
cmake -DCMAKE_CUDA_FLAGS="--expt-extended-lambda -std=c++11" ..
make
cp /path/to/onnx/file . #copy onnx file to this directory./export stanford_resnext50.onnx engine.plan

成功创建engine.plan后,您可以使用infer实用程序在图像上测试模型的性能:

./infer engine.plan image.jpg

这将编写一个名为detections.png的文件,该文件将包含图像中检测到的对象的边界框。我给了斯坦福数据集中的一个视频图像作为模型的输入,下面是它输出的结果:

我们可以看到,该模型已经检测到几个行人在人行道上行走。这对于 Pascal 或 COCO 训练的模型是不可能的。这个图像的纵横比看起来很奇怪,因为 infer 实用程序将图像的大小调整为 1280x1280,这是模型的输入大小。

对视频的推断

既然我们可以在单个图像中检测行人,那么通过编辑cppapi目录中的infer.cpp文件,就可以直接将其扩展到视频中。我想到了这个:

要使用这个脚本,将其保存为cppapi目录中的infervideo.cpp,并编辑CMakeLists.txt以添加添加infervideo可执行文件的行,并将其链接到retinanet和其他库。

完成后,您可以切换到build目录,并像以前一样调用cmakemake:

cmake -DCMAKE_CUDA_FLAGS="--expt-extended-lambda -std=c++11" ..
make

一旦构建了目标,您将在构建目录中看到一个名为infervideo的新可执行文件,它可以用作:

./infervideo engine.plan input.mov output.mp4

这将创建一个名为output.mp4的新视频,显示每个对象的边界框。如果您想要对来自无人机的实时视频流执行对象检测,您可以简单地提供摄像机的 gstreamer 管道作为脚本的第二个参数,它也会处理摄像机。

我用上面的脚本对我的母校新德里 IIT 德里校区拍摄的一段视频进行了推理。我使用了 0.2 的低阈值来绘制边界框,这就是为什么下面的视频中有一些误报。

提高性能

如果您在 Xavier 上运行上面提供的脚本,您会发现视频的每一帧都需要 150 ms 来进行推断。这在 Xavier 上非常慢,在 TX2 或 nano 这样的小型 Jetsons 上就更慢了。以下是我们可以提高性能的一些方法:

  • 我们在这篇文章中创建的引擎是用于 fp16 precision 的。您可以在整数精度上运行该模型,这将显著提高其性能。为此,您可以使用斯坦福数据集的一小部分数据和 tensorRT 的trtexec实用程序来创建 INT8 校准文件,并将该文件提供给我们构建目录中的export实用程序。
  • 实际上,任何实时对象检测管道都不会对每一帧执行完整的推断,而是通常将其与计算成本低廉的跟踪器(如卡尔曼滤波器或光流)混合在一起。可以使用 opencv 的 KalmanFilter 类跨帧跟踪对象,每 4 或 5 帧只进行一次推断。如果无人机在推理过程中没有突然的抖动,这在实践中会很好。
  • 我们正在使用的模型非常大,因为它需要 1280x1280 的图像。您可以在较低分辨率的图像甚至自定义数据集上训练模型,以显著改善模型的延迟和吞吐量。训练模型的说明在retinanet-examples存储库中,但是最好在一个配备支持 CUDA 的 GPU 的 x86 工作站上完成。

结论

这篇博客旨在为那些在 Jetson Xavier 上部署 retinanet 模型有困难的人提供帮助,并记录我为在无人机上运行良好的对象检测管道所做的努力。虽然我们得到了比 Coco/Pascal 模型更好的结果,但要使模型在 Jetson 设备上实时运行,还需要做许多改进。请将此作为您自己项目的起点,如果您有任何其他改进性能的建议,请在下面发表评论。

使用 RaspberryPi、热感相机和机器学习来检测人

原文:https://towardsdatascience.com/detecting-people-with-a-raspberrypi-a-thermal-camera-and-machine-learning-376d3bbcd45c?source=collection_archive---------3-----------------------

这个故事的更新版本可以在 Platypush 博客 上免费获得。

一段时间以来,基于人的存在触发事件一直是许多极客和 DIY 机器人的梦想。例如,让你的房子在你进出客厅时开灯或关灯是一个有趣的应用。大多数解决这类问题的解决方案,甚至更高端的解决方案,如飞利浦色调传感器,检测运动,而不是实际的人的存在——这意味着一旦你像树懒一样躺在沙发上,灯就会关闭。当你离开房间去你的卧室时,能够关掉音乐和/或电视,而不用麻烦地关掉所有的按钮,这也是一个有趣的推论。当你不在家时,检测你房间里的人是另一个有趣的应用。

热感相机与深度神经网络相结合是一种更强大的策略,可以实际检测人的存在。与运动传感器不同,即使人不动,它们也能探测到人的存在。此外,与光学相机不同,它们通过测量人体以红外辐射形式释放的热量来检测人体,因此更加耐用——它们的灵敏度不取决于照明条件、目标的位置或颜色。在探索热感相机解决方案之前,我尝试了一段时间来建立一个模型,而不是依赖于传统网络摄像头的光学图像。差异是惊人的:我用一周内在不同照明条件下拍摄的 1 万多张 640x480 图像训练光学模型,而我用一天内拍摄的 900 张 24x32 图像训练热感相机模型。即使使用更复杂的网络架构,光学模型在检测人的存在方面也不会达到 91%以上的准确度,而热模型在更简单的神经网络的单个训练阶段内将达到大约 99%的准确度。尽管潜力很大,但市场上并没有太多东西——已经有一些关于这个主题的研究工作(如果你在谷歌上搜索“人物检测热感相机”,你会发现大多数研究论文)和一些用于专业监控的高端和昂贵的产品。由于我的房子缺乏现成的解决方案,我决定承担起自己的责任,构建自己的解决方案——确保任何人都可以轻松复制它。

五金器具

  • 一个 RaspberryPi(价格:35 美元左右)。理论上,任何模型都应该工作,但使用单核 RaspberryPi Zero 来执行机器学习任务可能不是一个好主意——任务本身并不昂贵(我们将只使用 Raspberry 来对经过训练的模型进行预测,而不是训练模型),但它可能仍然会在 Zero 上遭受一些延迟。任何更多的表演模式应该做得很好。
  • 热感相机。对于这个项目,我使用了mlx 90640Pimoroni breakout 相机(价格:55 美元),因为它相对便宜,易于安装,并且提供了良好的效果。这款相机有标准(55)和广角(110)两种版本。我使用广角模式,因为相机监控一个大客厅,但考虑到两者具有相同的分辨率(32x24 像素),因此更宽的角度以较低的空间分辨率为代价。如果你想使用不同的热感相机,你不需要做太多改变,只要它带有 RaspberryPi 的软件接口,并且与 platypush 兼容。
  • 如果你用的是突破相机,我个人建议把它安装在类似于突破花园的东西上(价格:10-14 美元),因为它很容易安装在你的 RaspberryPi 上,不需要焊接。

在您的 RaspberryPi 上设置 MLX90640 如果您有一个突破性的花园,这很容易。将突破花园放在你的覆盆子上。将摄像机分接头安装到 I2C 插槽中。启动 RaspberryPi。完成了。

软件

我在 Raspbian 上测试了我的代码,但是经过一些小的修改,它应该很容易适应安装在 RaspberryPi 上的任何发行版。

热感相机的软件支持需要做一些工作。MLX90640(还)没有 Python 现成的接口,但是为它提供了一个 C++开源驱动。安装说明:

# Install the dependencies
[sudo] apt-get install libi2c-dev# Enable the I2C interface
echo dtparam=i2c_arm=on | sudo tee -a /boot/config.txt# It's advised to configure the SPI bus baud rate to
# 400kHz to support the higher throughput of the sensor
echo dtparam=i2c1_baudrate=400000 | sudo tee -a /boot/config.txt# A reboot is required here if you didn't have the
# options above enabled in your /boot/config.txt# Clone the driver's codebase
git clone [https://github.com/pimoroni/mlx90640-library](https://github.com/pimoroni/mlx90640-library)
cd mlx90640-library# Compile the rawrgb example
make clean
make I2C_MODE=LINUX examples/rawrgb

如果一切顺利,您应该会在examples目录下看到一个名为rawrgb的可执行文件。如果你运行它,你应该会看到一堆二进制数据——这是相机捕捉的帧的原始二进制表示。记住它的位置或将它移动到自定义 bin 文件夹,因为它是 platypush 将用来与相机模块交互的可执行文件。

本文假设您已经在系统上安装并配置了 platypush。如果没有,请到我在开始使用 platypush 、 readthedocs 页面、 GitHub 页面或 wiki 上的帖子。

您还需要 RaspberryPi 上的以下 Python 依赖项:

# For machine learning image predictions
pip install opencv opencv-contrib-python# For image manipulation in the MLX90640 plugin
pip install Pillow

在这个例子中,我们将在捕获和预测阶段使用 RaspberryPi,在训练阶段使用一个更强大的机器。在用于训练模型的计算机上,您需要以下依赖项:

# For image manipulation
pip install opencv# Install Jupyter notebook to run the training code
pip install jupyterlab
# Then follow the instructions at [https://jupyter.org/install](https://jupyter.org/install)# Tensorflow framework for machine learning and utilities
pip install tensorflow numpy matplotlib# Clone my repository with the image and training utilities
# and the Jupyter notebooks that we'll use for training
git clone [https://github.com/BlackLight/imgdetect-utils](https://github.com/BlackLight/imgdetect-utils)

捕获阶段

现在你已经有了所有的硬件和软件,是时候开始用你的相机捕捉帧,并用它们来训练你的模型了。首先,在 platypush 配置文件中配置 MLX90640 插件:

camera.ir.mlx90640:
    fps: 16      # Frames per second
    rotate: 270  # Can be 0, 90, 180, 270
    rawrgb_path: /path/to/your/rawrgb

重启 platypush。如果您启用了 HTTP 后端,您可以测试是否能够拍照:

curl -XPOST -H 'Content-Type: application/json' \
     -d '{"type":"request", "action":"camera.ir.mlx90640.capture", "args": {"output_file":"~/snap.png", "scale_factor":20}}' \
      [http://localhost:8008/execute](http://localhost:8008/execute)?token=...

热图像应该存储在~/snap.png下。在我的例子中,当我在传感器前面时,它看起来像这样:

注意右下角的辉光——这实际上是我的 RaspberryPi 4 CPU 发出的热量。它在我拍摄的所有图像中都存在,如果你将相机安装在树莓上,你可能会看到类似的结果,但这对于你的模型训练来说应该不是问题。

如果您打开 webpanel ( [http://your-host:8008](http://your-host:8008)),您还会注意到一个由太阳图标表示的新标签,您可以使用它从 web 界面监控您的相机。

您也可以将浏览器指向http://your-host:8008/camera/ir/mlx90640/stream?rotate=270&scale_factor=20.,直接在网络面板外监控摄像机

现在向 platypush 配置添加一个 cronjob,以便每分钟拍摄一次快照:

cron.ThermalCameraSnapshotCron:
    cron_expression: '* * * * *'
    actions:
        -
            action: camera.ir.mlx90640.capture
            args:
                output_file: "${__import__(’datetime’).datetime.now().strftime(’/img/folder/%Y-%m-%d_%H-%M-%S.jpg’)}"
                grayscale: true

图像将以格式YYYY-mm-dd_HH-MM-SS.jpg存储在/img/folder下。没有应用比例因子——即使图像很小,我们也只需要它们来训练我们的模型。此外,我们将把图像转换成灰度——神经网络将更轻,实际上更准确,因为它将只需要依赖每个像素一个变量,而不会被 RGB 组合欺骗。

重启 platypush,验证每分钟在你的图片目录下创建一张新图片。让它运行几个小时或几天,直到你对样本数量满意为止。试着平衡房间里没有人和有人的照片数量,试着覆盖尽可能多的情况,例如,坐在、站在房间的不同位置等等。正如我前面提到的,在我的例子中,我只需要不到 1000 张足够多样的图片就可以达到 99%以上的准确率。

标记阶段

一旦你对你采集的样本数量感到满意,就把图像复制到你用来训练你的模型的机器上(它们应该都是小的 JPEG 文件,每个小于 500 字节)。将它们复制到您克隆了我的imgdetect-utils库的文件夹中:

BASEDIR=~/git_tree/imgdetect-utils# This directory will contain your raw images
IMGDIR=$BASEDIR/datasets/ir/images# This directory will contain the raw numpy training
# data parsed from the images
DATADIR=$BASEDIR/datasets/ir/datamkdir -p $IMGDIR
mkdir -p $DATADIR# Copy the images
scp pi@raspberry:/img/folder/*.jpg  $IMGDIR# Create the labels for the images. Each label is a
# directory under $IMGDIR
mkdir $IMGDIR/negative
mkdir $IMGDIR/positive

一旦复制了图像并创建了标签目录,运行存储库中提供的label.py脚本来交互式地标记图像:

cd $BASEDIR
python utils/label.py -d $IMGDIR --scale-factor 10

每个图像将在一个新窗口中打开,您可以通过键入 1(负)或 2(正)来标记它:

在程序结束时,图像目录下的negativepositive目录应该已经被填充。

培训阶段

一旦我们得到了所有标记的图像,就该训练我们的模型了。在notebooks/ir下提供了一个[train.ipynb](https://github.com/BlackLight/imgdetect-utils/blob/master/notebooks/ir/train.ipynb) Jupyter 笔记本,它应该是相对不言自明的:

如果您成功地正确执行了整个笔记本,您将在models/ir/tensorflow下拥有一个名为ir.pb的文件。那是你的 Tensorflow 模型文件,你现在可以把它复制到 RaspberryPi,并用它来做预测:

scp $BASEDIR/models/ir/tensorflow/ir.pb pi@raspberry:/home/pi/models

探测房间里的人

使用 platypush [MlCv](https://platypush.readthedocs.io/en/latest/platypush/plugins/ml.cv.html) 插件,将我们之前创建的ThermalCameraSnapshotCron的内容替换为按预定时间间隔拍照的逻辑,并使用我们刚刚训练的模型来预测房间中是否有人。

你可以在procedure.people_detectedprocedure.no_people_detected中实现任何你喜欢的逻辑。这些程序仅在先前观察的状态发生变化时才会被调用。例如,当有人进入/离开房间时,打开或关闭灯的简单逻辑:

procedure.sync.people_detected:
    - action: light.hue.onprocedure.sync.no_people_detected:
    - action: light.hue.off

下一步是什么?

这是你的电话!随意试验更复杂的规则,例如,当有人进入房间时,使用 platypush 媒体插件改变房间中播放的音乐/视频的状态。或者早上第一次进房间的时候说一句自定义的早安短信。或者建立你自己的监视系统,当你不在家的时候跟踪别人的存在。或者增强模型以检测房间中的人数,而不仅仅是存在。或者你可以将它与光学流量传感器、距离传感器、激光测距传感器或光学相机(platypush 为其中一些提供了插件)结合起来,构建一个更加强大的系统,该系统还可以检测和跟踪传感器的移动或接近,等等。

使用深度学习检测 API 通信中的个人数据

原文:https://towardsdatascience.com/detecting-personal-data-within-api-communication-using-deep-learning-9e52a1ff09c6?source=collection_archive---------6-----------------------

概观

有没有想过有多少个人数据分散在各个组织中?大量的个人数据——你的、我的、每个人的——从模糊的个人信息到极其具体的信息,都在四处漂浮。大多数情况下,它是未被发现的。几乎总是,它被你给它的组织使用,有很好的理由。有时,出于可疑的原因。经常(非常,非常经常)它被第三方出售和使用,或者被误用。).太多时候,个人数据被劫持并用于邪恶的目的。鉴于在线个人数据的使用和滥用机会呈指数增长,难怪欧盟最近通过了《通用数据保护条例》(GDPR),该条例于 2018 年 5 月 25 日生效。一个月后,加州紧随其后,颁布了《加州消费者隐私法》(CCPA)。如果你想知道有多少组织掌握着你的个人数据,你并不孤单。但是那些组织本身呢?监控这些数据既困难又耗时。这种个人数据噩梦最可怕的部分可能是,组织本身往往不知道你的个人数据存储在哪里,它可能流经哪些应用程序,或者它可能最终会在哪里。监管个人数据的流动和使用的趋势正在上升,但你如何监管你无法检测到的东西?

GDPR 法规的支柱之一是,任何处理个人数据的应用程序都应该“嵌入”隐私,通常称为隐私设计(PbD)。这远不是一个新的定义:

“隐私设计方法的特点是采取主动措施,而不是被动措施。它可以在隐私侵犯事件发生之前预测并阻止它们。PbD 不会等待隐私风险的出现,也不会在隐私侵害发生后提供补救措施来解决隐私侵害——它旨在防止隐私侵害的发生。简而言之,隐私是事先设计好的,而不是事后的”

A.卡沃金。设计隐私——7 项基本原则,2011 年 1 月。

这遵循了类似于安全设计的原则(不幸的是,我认为我们离安全设计还很远)。隐私和安全的设计听起来都很棒。但是,如何处理已经发布并投入生产、传输和接收个人数据的数十亿行代码呢?我们是否要等待数据泄露发生,然后应用修复程序?对我来说,这听起来太少,太晚了。

为了寻找灵感,我开始研究一个相关领域:网络安全。我了解得越多,就越发现个人数据共享和网络安全问题之间的相似之处。在必须应对应用程序和基础架构中的新旧未知威胁方面,挑战是相似的。一种常见的缓解机制是持续监控网络流量,检测可能转化为实质性威胁的潜在恶意模式。

我认为,涉及个人数据处理的威胁与网络安全威胁一样重要。在这两种情况下,它都归结为暴露,这总是以这样或那样的方式转化为财务损失,影响负责处理个人数据记录的组织。这反过来影响他们如何处理这些个人记录;这对我们所有人都有影响,有时影响非常大。

但是说够了,是时候动手了。

训练数据集生成

为了通过深度学习获得相当不错的结果,训练需要大量的正面和负面例子。这些例子越真实,预测就越准确。

我面临的第一个挑战是如何获得如此庞大的样本集,因为根据定义,个人数据是保密的,因此不会公开。

有许多方法可以获得这种数据来检测应用程序安全异常,例如利用动态应用程序安全测试(DAST)工具,该工具包括生成和捕获恶意流量,然后基于此训练分析模型。然而,在我们的案例中,包含个人数据流的流量并不意味着安全威胁,因此 DAST 工具或它们通常生成的流量数据不提供覆盖范围。

第二个挑战?除了包含虚构的个人数据之外,我还需要对个人数据在 API 通信(例如 REST)中通常是如何传递的进行编码,因为这是我们将要运行预测的对象。例如,个人数据属性通常只代表整个 REST API 有效负载的一个子集。

最后,我还需要网络来了解个人数据和有效载荷的规律。简而言之,它不仅要学习不同形式的个人记录,更重要的是,还要学习通过网络交换的个人数据是什么样的。

我应对这些挑战的方法是使用模式作为主要来源,精心制作我自己的机器生成数据集,也称为合成数据集。

好消息是大多数流行的 REST APIs 都附带了一个 OpenAPI(以前称为 Swagger)描述符。

OpenAPI 规范,最初被称为 Swagger 规范,是用于描述、产生、消费和可视化 RESTful web 服务的机器可读接口文件的规范。

因此,给定一个 OpenAPI 描述符,我只需基于这个蓝图实例化一个 RESTful 请求,在给定数据类型的情况下,用虚构但格式良好的值填充空白。最新的 OpenAPI 描述符目录可在 https://github.com/APIs-guru/openapi-directory 获得。数据集生成器扫描该目录,并基于该目录实例化合成请求有效载荷的集合,该集合随后用于训练网络。

下面是综合请求生成器的核心部分:

REST APIs 的局限性之一是尽可能避免传递个人信息。取而代之的是,使用一个或多个不太敏感的标识符,以便服务可以解析到相应的 PII,而无需公开完整的记录。这是在有两个少数正面例子(即包含 PII)导致高度不平衡的数据集的情况下得出的。我采取的缓解此问题的方法(见第 21-30 行)是通过使用最近的正面示例(PII 请求有效负载)作为模板进行过采样,以生成包含一些其他随机选择的 PII 属性(如 SSN、电话号码等)的其他正面示例。).

该项目捆绑了一个预生成的训练数据集,位于 data/training.csv 下。

以下是我们的“假”有效载荷的摘录:

现在,让我们获取我们生成的数据集的一些指标:

0 19278
1 22607
数据集中包含 PII 的请求:53.97%

我们已经能够生成足够大且平衡的训练数据集。

不错吧?让我们使用它。

选择 DNN 发动机

正如您可能已经知道的,有几个很棒的 DNN 堆栈,支持多种网络拓扑结构。我们将选择 TensorFlow,它最近受到了很多关注,因为到目前为止,该领域的大多数研究都是在这里进行的。

为了保持人工智能相关的复杂性,以及能够快速迭代,我们将抽象特定的堆栈(TensorFlow)并使用 Keras,Keras 将负责设置网络层所需的繁重工作。

因为我们的 DNN 堆栈是用 Python 实现的,所以我们的解决方案需要使用相同的语言来实现,以实现无缝的互操作性。

了解“个人”的含义

我们应该使用哪种可用的神经网络拓扑结构?

很明显,我们在按照一套既定的规则处理信息。例如,一个有效的 JSON 文档遵循特定的约定——在其语法中指定——这是我们需要考虑的。这方面的一个例子是数据由逗号分隔,花括号包含对象,等等。

此外,值可以遵循各种各样的格式,其中许多是位置相关的。例如,社会安全号码不同于电话号码。让网络学会在这一水平上进一步辨别将提高预测的准确性。继续前面的例子,如果属性名是“ssn ”,但是对应的值与学习到的 SSN 格式不匹配,那么它的得分将低于遇到格式良好的 SSN 值时的得分。

总之,我们必须学习序列,包括 JSON 文档的术语和其中定义的值的字符模式。到目前为止,这种情景的最佳匹配是 LSTM(长短期记忆)。这种类型的 RNN(递归神经网络)带来的主要特征是状态性。简而言之,在处理输入时,它会考虑之前看到的内容。它有记忆。例如,如果它看到下面的 JSON 键/值对:

在学习值部分的序列(即“744–22–5837”)时,它将考虑之前看到的密钥(即“ssn”),从而在提取其处理的令牌背后的正确含义方面增加了更多信心。

这里是实现位。LSTM 隐藏层输入单词 embedding——很像一个从有效载荷中提取文本的字典——并有单独的丢弃层以减少过度拟合;和最后的输出层,以产生 PII 分类。我们将使用 100 个历元,因为这是模型与我们的合成数据集聚合的地方。我强烈建议使用体面的 GPU,以便通过这一点明显更快。

现在是训练神经网络的时候了。默认情况下,它将使用项目附带的数据集(training.csv)。

$ python privapi/train.py

超过 99% 的准确率!到目前为止,一切似乎都很有希望。接下来呢。现实检查。

检测个人数据

我们训练好的网络模型现在可以预测一个给定的 JSON 有效载荷中是否有 PII。

我们的分类器将遍历包含示例请求有效负载的文件夹,并将使用先前生成的神经网络模型获得的预测输出到 CSV 文件中:

在“预测”文件夹中,我们有两个要对其运行预测的示例。

注册 webhook 的示例非敏感 Slack API 有效负载:

和一个敏感的请求有效载荷——因此包含 PII——用于 Magento 电子商务解决方案:

让我们运行预测器:

$ python privapi/predict.py

该命令将遍历包含示例请求有效负载的文件夹,并将预测输出到名为 predictions.csv 的 CSV 文件中,如下所示:

这表明,至少在这两个例子中,我们的预测器做得非常好。

首先,它检测到 Magento 有效载荷确实很敏感,得分几乎是 100%。其次,它将松弛有效载荷归类为不敏感,准确率约为 40%。

有趣的是,这个有效载荷包含了可能被错误地认为是 PII 的内容(例如,名字和姓氏),但是它并没有强烈地影响分类,以至于选择了错误的类。

我建议您尝试使用您喜欢的请求有效负载,看看您会得到什么结果。

带回家的体验

老实说,我对当前最先进的人工智能如何在隐私领域做出贡献印象深刻,主要是通过让处理和传输我们个人数据的组织产生意识。我相信机器有很多机会来学习如何帮助保护我们的个人数据安全。我将这个项目命名为 PrivAPI,并在 Github 上公开。请随意查看、体验,并做出贡献。

我们将何去何从

PrivAPI 还有很大的改进空间。主要领域包括:

  • 流式传输:从事件流式传输平台获取 REST API 有效负载,并将神经网络模型应用于新事件,以推断结果(即有效负载是否保密)。最后,将预测推给任意的消费者,让他们据此采取行动。
  • 在线学习:不要将训练和推理分开,而是允许从接收到的 REST API 有效负载中进行训练,这样解决方案的整体有效性就会得到提高,因为它正在学习特定组织内的 API 流量模式。
  • 神经网络监控和警报:监控神经网络模型的准确性、分数、SLA 和其他指标,并实时提供自动警报。最后,反馈度量以改进或替换神经网络模型。
  • 额外的有效载荷格式:处理使用另一种符号表示的 API 流量应该非常简单,因为神经网络与此无关。例如,支持 XML API 有效负载将允许我们监控 SOAP 流量,这在企业环境中仍然非常普遍。

你想在 PrivAPI 中看到什么?欢迎在下面发表评论,贡献一个 Github pull 请求。

查看 GitHub 上的代码:

[## Veridax/privapi

使用深度神经网络检测敏感的 REST API 通信- Veridax/privapi

github.com](https://github.com/veridax/privapi)

从 OCT-视网膜图像中检测视网膜损伤

原文:https://towardsdatascience.com/detecting-retina-damage-from-oct-retinal-images-315b4af62938?source=collection_archive---------14-----------------------

光学相干层析成像(OCT) 是一种利用相干光捕捉生物组织高分辨率图像的成像技术。眼科医生大量使用 OCT 来获得眼睛视网膜的高分辨率图像。眼睛的视网膜功能更像照相机中的胶片。OCT 图像可用于诊断许多视网膜相关的眼病。

OCT 是一种新兴的生物医学成像技术,可以对高度散射的组织进行非侵入式实时高分辨率成像。它被眼科医生广泛用于对眼前部和视网膜的结构进行诊断成像。

在这篇文章中,我们将看到如何分类光学相干断层扫描来分类视网膜疾病。我们将讨论基于卷积神经网络(CNN)对视网膜 OCT 图像进行自动分类的分类方法,所述卷积神经网络基于使用迁移学习的 2 个预训练模型和 1 个定制 CNN 模型。

关于数据集

获取自:视网膜 OCT 图像

1。脉络膜新生血管(CNV): 脉络膜新生血管是在眼的脉络膜层产生新的血管。脉络膜新生血管是新生血管变性性黄斑病变(即“湿性”黄斑变性)【1】的常见原因,通常会因极度近视、恶性近视变性或年龄相关发展而加剧。

Choroidal neovascularization (CNV)

2。糖尿病黄斑水肿(DME):

DME 是糖尿病的一种并发症,由黄斑中的液体积聚引起,可影响视网膜中央凹。黄斑是视网膜的中心部分,位于眼睛的后部,是视觉最敏锐的地方。DME 导致的视力丧失会持续数月,使人无法清晰聚焦。

Diabetic Macular Edema (DME)

3。德鲁森:

玻璃疣是视网膜下的黄色沉积物。玻璃疣是由脂质,一种脂肪蛋白质组成的。玻璃疣可能不会导致老年性黄斑变性。但是患有玻璃疣会增加一个人患 AMD 的风险。玻璃疣由蛋白质和钙盐组成,一般出现在双眼中。

Drusen

4。正常

当光线直接聚焦在视网膜上,而不是在它的前面或后面时,就会出现正常的视觉。视力正常的人能清楚地看到远近的物体。

Normal

迁移学习

微调我们的模型

微调实施包括截断预训练网络的最后一层(softmax 层)并用与我们的问题相关的新 soft max 层替换它。

1)MobileNet

MobileNet 是一种架构,更适合缺乏计算能力的基于移动和嵌入式的视觉应用。这个架构是 Google 提出来的。

使用预训练的 imagenet 权重加载 MobileNet,并排除顶层(即最后三层)用新的可训练层替换完全连接的层,并使用 include_top=False 显示模型中的其他层

冻结一层或一组层意味着防止它们的权重在训练期间被更新。如果不这样做,那么卷积基先前学习的表示将在训练期间被修改。

所有的卷积级别都是预先训练的,所以我们在完整的训练过程中冻结这些层,这样当新的完全连接的层试图学习模型时,它们的权重不会改变。因此,我们将可训练层设置为假。

GlobalAveragePooling2D 用于将输入转换为正确的形状,以便密集图层进行处理。它将前一层的 3D 输出展平为 1D 层,通过平均适合我们的全连接层。

num_classes=4,activation="softmax "通过推理将单个类别赋予样本—这是通过计算每个可能类别的概率来完成的。然后,我们可以选择概率最高的类别进行最终分类。

添加 mobilenet 层和全连接层,用于使用卷积基进行训练。

模型摘要

13 Conv Layers(Mobile Net)

可训练参数(权重)是在反向传播的反向过程中得到更新的所有参数。这些权重包含网络从训练数据中学习到的信息。

图像增强

图像增强背后的思想是,我们遵循一个设定的过程,从我们的训练数据集中获取现有图像,并对它们应用一些图像变换操作,如旋转、剪切、平移、缩放等,以产生现有图像的新的、改变的版本。

该增强生成 4 类 34464 幅训练图像和 3223 幅验证图像

培训模式

在模型的每次训练迭代期间,即在每个时期结束时,将调用回调机制。

检查点是一个定期保存应用程序状态快照的过程,因此如果出现故障,应用程序可以从上次保存的状态重新启动。这在深度学习模型的训练过程中很有用,这通常是一项耗时的任务。

提前停止减少神经网络中的过拟合就是利用提前停止。如果没有真正学到任何东西,提前停止可以通过终止训练过程来防止模型过度训练。

val_loss 没有从 0.70965 提高到最近 3 个时期的较低值,这是早期停止回调中的耐心。

测试准确率为 71.2%

混淆矩阵

正常图像很容易识别。

我们可以通过研究其他模型来提高更多。

Github 代码: Retinal-MobileNet.ipynb

2)VGG16

来自牛津视觉几何小组,或简称为 VGG 的研究人员开发了 VGG 网络,该网络的特点是简单,只使用 3×3 的卷积层堆叠在彼此的顶部,深度不断增加。减少卷大小是由最大池处理的。最后,两个完全连接的层,每个层有 4,096 个节点,然后是 softmax 层。

池化是由 max pooling 层执行的,它位于某些卷积层之后。并非所有卷积层都遵循最大池。最大池是在一个 2×2 像素的窗口上执行的,步长为 2。ReLU 激活用于每个隐藏层。在大多数 VGG 变型中,过滤器的数量随着深度而增加。16 层架构 VGG-16 如下图所示。

与 mobilenet 类似,步骤几乎没有变化

展平层处理尺寸。因为我们有一个三维像素输入图像,所以我们使用 Flatten 将其转换为一个长的一维数字字符串。

13 Conv Layers(Vgg16)

与 MobileNet 相比,可训练参数更多。它标志着更多的功能都学到了模型。

混淆矩阵

与其他视网膜疾病相比,正常的玻璃疣被正确识别

Github 代码: RetinalVGG16.ipynb

3)五隐层 CNN 模型

我们应用 5 CNN(卷积层)和 3*3 内核以及“relu”激活。

模型

可训练参数

与预训练模型相比,可训练性似乎更低。但是与预训练的模型相比,它仍然表现得更好。

测量精度

混淆矩阵

混淆矩阵在预测正常,玻璃疣和 DME 方面表现更好。

Github 代码: Retinal5CNN.ipynb

4)定制 VGG 模型

可训练参数

更多的可训练参数相比,这两个模型。与对比模型相比,不可训练参数也明显较少。

混淆矩阵

该模型已经正确地预测了大多数 OCT 视网膜疾病。上述推论可以在下面的预测中看到。

预言

Normal Prediction

Drusen Prediction

CNV Prediction

DME Prediction

从上面我们可以看到,所有的视网膜疾病都被正确地分类了。

Github 代码: OCT-Retinal-VGG.ipynb

结论

具有 16 个隐藏层的 CNN 模型,即类似于 VGG 模型,给出了 96%测试准确度的最佳结果。

参考资料:

  1. https://www.appliedaicourse.com

2.https://www.kaggle.com/paultimothymooney/kermany2018

3.http://www . cell . com/cell/full text/s 0092-8674(18)30154-5

使用人工智能检测骗局,真的

原文:https://towardsdatascience.com/detecting-scams-using-ai-for-real-6c96e712cf09?source=collection_archive---------30-----------------------

历时一年的旅程,开发市场上最好的欺诈防范系统之一

Photo by Po-Ying Chen on Unsplash

根据 2019 年 3 月发表的一项研究——我特意寻找只是为了给这篇帖子找一个很酷的介绍——欧洲 40%的自定义人工智能初创公司实际上并不使用人工智能。我看到他们在那里做什么,利用普通人(和投资者)对这个领域鲜有的熟悉,在市场上将自己定位为酷黑魔法专家。我不为人工智能初创公司工作(我的意思是,我们不直接出售任何人工智能驱动的服务),但几天前我们终于在发表了一篇内容广泛的帖子,向公众介绍了我们的第一款人工智能驱动的产品。我认为分享我们实际部署它所经历的所有步骤以及我们为什么决定以这种方式进行部署会非常有趣。

没有重复,只是作为一个介绍性的术语:佩内洛普是我们检测骗局的内部工具。在我们的平台( HousingAnywhere ,一个在全球 400 多个城市都有房源的住宿市场)上发布的每个新房源都被归类为诈骗或非诈骗,在某些情况下,我们的客户解决方案 (CS)部门会对其进行人工检查。它已经使用过去三年中收集的数据进行了训练,并作为一个集成来实现,其中每个模型独立地关注不同的特征或数据集的不同时间子集。

佩内洛普之前的欺诈预防

HousingAnywhere 不是 Penelope 生来就有的,提供信任和安全的市场一直是该公司的首要目标。多年来,欺诈预防系统在没有任何人工智能的情况下表现良好(难以置信,不是吗?)并且它几乎完全依赖于由一些静态 SQL 规则组成的触发器系统。一些被查询的数据结构和查询本身一点也不简单,但是一个简单的系统,如果设计和维护得好,往往可以胜过非常复杂的解决方案。问题是情况并不完全如此。当一家公司开始快速扩张,并且必须快速解决问题时,它可能会忽略一些好的实践。

最初的系统由大约 50 条规则组成,缺乏适当的文档,并且范围重叠。我们没有收集任何关于他们表现的统计数据,我们也不知道最初的设计者为什么要创造这些规则。我们有一种感觉,一些触发因素几个月来都没有导致任何检测,导致大量时间浪费在无用的检查上,但我们没有任何指标来证明这一假设,我们最终没有删除任何东西,在现有规则的基础上添加新规则,因为系统正在工作-在 3 年内没有一个骗子成功过!——我们很害怕碰任何东西。设计新规则本身也很棘手。有时,描述一个可疑的行为并不容易,对于一个人来说,可能很容易得到的东西可能需要数百行 SQL 语句,将可能存储在不同位置的表连接在一起。就在那时,我们开始考虑使用机器学习来取代规则系统:停止明确定义所有规则,让算法直接从我们的数据中学习它们。这是一个相当雄心勃勃的目标,我们花了 6 个多月的时间才实现,但那时我们已经有了一个非常具体的使用案例和一个定义良好的流程。我们不是简单地开始将随机数据扔给学习算法,看看会发生什么。此外,目标是替换已经被人们成功使用的现有产品(有点儿),这允许我们有一个真实世界的框架来可靠地测试我们的替代产品(我已经在这里写了这个)。但是,如果我们不能衡量我们现有产品的性能,如何定义成功呢?

我们不是简单地开始将随机数据扔给学习算法,看看会发生什么。

我们在佩内洛普项目上花费了大量的精力,从一开始,就在永远扼杀它之前,对以前的规则系统进行合理化和改进。我们设计并实施了一个监控基础设施,能够跟踪每个触发器的性能(主要是精度),我们还开始为客户解决方案部门收集一些指标,以检查我们的瓶颈在哪里,以及我们是否需要在技术基础设施的基础上改进我们的内部流程。我们最终两者都做了:如果人们遵循的过程一开始就没有效率,那么改进人们使用的技术基础设施就没有意义。人工智能是一种改善事物的工具,但它只是拼图中的一块。它的用处不在于单独使用它,而在于用它来改进整个过程。实现机器学习不是最容易的事情,最重要的是,这是一项结果非常不可预测的工作。先从简单的事情做起。

如果人们遵循的过程一开始就没有效率,那么改进人们使用的技术基础设施是没有意义的。

实际上是佩内洛普

一旦我们有了一个可靠的防欺诈基础设施(大约一个月的工作),我们就开始构建一个替代方案来消除它。从一开始,我们从未考虑过完全取代人类主持人,我们也从未追求过类似学术论文的表现。我们总是不把精确度看做一个数字,而是看 CS 为检查标记的列表而浪费的无用工作的数量,并回忆为留在野外的诈骗列表的数量。规则系统也有助于为我们提供一组初始的工作特性。除此之外,我们还调查了其他一些人,这主要归功于每天与骗子打交道的人提供的信息。不过,我们没有浪费时间去研究那些在创建列表的前 5 分钟内无法获得的功能,同样,在早期阶段就有产品愿景在这方面非常有帮助。

我们在训练模型时面临的真正挑战是生成数据的平台的进化性质。我们最终组装了 5 个 LightGBMs (性能相当,但训练时间比 XGBoost 短),每个都用不同的数据集进行了垂直(样本数量)或水平(特征数量)大小的训练。每个模型都被加权以在新数据上具有最高性能(90-10 次验证,按时间顺序排列样本;探索权重空间的贝叶斯优化)。最终的模型已经被部署为一个 web API (Flask ),为一个异步调度预测任务的 Celery 实例提供数据。每个作业的结果在不同的通道上发送,并且部署不知道正在使用它的客户端。平台上发布的每一个新列表(唯一的例外是由可信的广告商创建的列表)都会发送给 Penelope 进行检查。或者被接受,被标记为诈骗,或者被发送进行人工审核。每个预测作业持续 3-4 秒,但需要其中的一小部分时间来通过第三方来源收集一些数据。

在第一次成功部署后(大约 2019 年 1 月),我们必须决定如何处理系统的再培训过程以及我们数据的进化性质。我们运行了一些离线模拟,并比较了不同的再培训场景,发现对于我们的特定领域,每两周再培训 Penelope 会导致性能的显著提高(基本上,更多的骗子)。不足为奇的是,用集合中的所有最近特征训练的模型的重要性每次都与新列表的分类更相关。在未来,我们期望摆脱一些模式,并可能增加新的模式。在这个阶段,我们非常有信心做到这一点,我们有一个坚实的管道来发现新的换档功能,以训练我们的模型。

绩效和后续步骤

在 Penelope 之前,CS 部门每周花费 80 小时对可疑列表进行人工审核,目前大约是 15 小时(80%的改进)。大多数规则本身不会立即生效,需要 1 到 6 个小时来识别欺诈行为。这一限制将访问者置于风险之中,因为列表可以被联系几个小时。Penelope 能够在列表发布后立即对其进行分类,这使得这个窗口几乎为 0,并且实际上为 CS 提供了一个非常方便的指标来评估它们的性能。我们的防欺诈系统(作为一家公司)的质量现在与客户解决方案部门在检查 Penelope 标记的列表时的响应能力密切相关。 Mes2Det 是我们衡量这一点的内部指标,计算方法是在我们的系统上通知骗子后,报告骗子所需的时间。很容易注意到,自从 Penelope 上线以来,Mes2Det 改进了很多(从 10 小时减少到 2 小时),现在已经稳定了几个月。

目前,我们正在对 Penelope 进行不断的迭代,尽我们所能对其进行改进。我们已经学到的一些教训是,要追求的研究方向是缩小模型的范围,可能是用更小的数据集组装更简单的组件,而不是试图建立一个具有数百个复杂功能的更大的架构。在 6 月份,我们已经部署了第二个版本的 Penelope,即使它使用的数据集几乎是原始版本的一半,精度也提高了约 10%。

使用迁移学习检测集卡

原文:https://towardsdatascience.com/detecting-set-cards-using-transfer-learning-b297dcf3a564?source=collection_archive---------22-----------------------

如何从深度卷积网络中生成强大的特征

在美丽的法国度假期间,我和我的家人玩了很多,一种简单而优雅的卡牌游戏。目标是在别人发现之前找到特定的卡片组合。玩游戏的时候,我们经常盯着牌,想知道是否还有一组我们没有看到的牌。这开始了一个有趣的个人兼职项目,我应用机器学习来寻找集合组合。

在这篇文章中,我将分享我的方法,代码的结果和亮点。要获得完整的源代码,请查看 Github 上的笔记本。

“我不能创造的,我不理解”

理查德·p·费曼

首先,让我们把事情搞清楚。对于当今最先进的机器学习模型来说,检测设置卡是一项简单的任务。像 YOLO 这样的物体检测算法可以从视频中实时检测许多物体,因此从图像中找到带有简单彩色符号的卡片应该不会太难。

比起使用 YOLO,我会发现从头开始更有趣也更有挑战性。

Example of realtime object detection with YOLO

总体方案如下:

1。从图像中提取卡片使用计算机视觉提取单张卡片。

2。使用深度卷积网络对每个单独图像进行分类 以生成用于(线性)分类器的特征。

3。寻找有效集合组合 使用组合学来寻找有效集合。有趣的是,有一种优雅的方法只用几行代码就可以做到。

关于游戏

在我们深入细节之前,让我解释一下这个游戏。

SET 游戏是一种流行的纸牌游戏,挑战你的模式识别技能。游戏的目标是找到一个“套”,这是三张牌的特殊组合。

共有 81 种独特的卡片,具有四种属性:颜色、形状、填充和数量。每个属性可以有三个不同的值。如果就四个属性中的每一个而言,三张牌或者是相同的或者是都不同的,则这三张牌被称为一组**

Example for a valid and invalid SET combination

总共有 12-21 张牌放在桌子上,玩家实时收集尽可能多的牌。

游戏有不同的版本。我在这个项目中使用的版本是 2001 年的 Ravensburger 版本,具有以下特点:

  • 颜色:红色,绿色,紫色
  • 形状:方形,波浪形,圆形
  • 填充:实心、虚线、空心
  • 数量:一、二、三

1974 年玛莎·让·法尔科发明了成套游戏。作为一名遗传学研究者,她研究了德国牧羊犬的癫痫症是否是遗传的。为了代表狗的基因信息,她开始在卡片上画符号。不同的属性(即颜色)代表了狗的不同特征。她意识到这可能是一个具有挑战性的难题,在朋友和家人的鼓励下,她开发并推广了这款纸牌游戏。SET 在数学界内外都变得非常流行。【1】

1.从图像中提取卡片

有一个很棒的帖子详细解释了如何使用 OpenCV 从图像中提取规则扑克牌。附带的代码对于提取器械包卡片也非常有用。因此,我不再重复这个解释,我将参考发布的获取详细信息,并且我将坚持这里的主要步骤。

Steps to extract the cards: find contours of cards in the preprocessed image (identify), warp them to a landscape orientation (register) and crop them to separate images.

  • 识别卡片——为了在图像中找到卡片,我们利用了白色卡片与背景截然不同的事实。为了放大这种效果,首先对图像进行预处理。然后通过分组相似的像素来找到轮廓。最后,与典型卡片(如卡片上的符号)不匹配的轮廓被过滤掉。
  • 图像配准—将找到的轮廓转换到一个单一的坐标系中,这叫做图像配准。这样,所有卡片都以横向结束,并且可以从图像中裁剪。

Example of finding the contours in an image

如果卡片和背景之间有足够的对比度,这种算法就能很好地工作。如果卡片重叠,它将无法找到所有的卡片,所以我不建议在实际应用中使用该代码,但对于这篇博客来说,它会做得很好。

2.对每个单独的图像进行分类****

既然我们可以找到单张卡片,我们就可以开发一个将卡片分类的模型。

创建数据集

第一步是为此任务创建数据集。我在略有不同的光线条件下,从不同的角度为每张卡片拍了四张照片。我分离出一系列图片,并将其用作验证集来测试模型的表现。

Example of the generated augmented card images

每堂课只有三个例子不足以成功训练一个模型。通过使用 Keras 中的[ImageDataGenerator](https://keras.io/preprocessing/image/#imagedatagenerator-class) API,您可以从基本数据集创建人工样本。这样你就可以创建一个任意大小的数据集,其中卡片可以旋转、缩放、翻转等。真实样本比人工样本好,但如果你不想自己拍成千上万张照片,这是一个很好的替代选择。

测试基线模型

作为基线,我训练了一个逻辑回归模型,并使用增强的图像作为输入。在下面的结果中,您可以看到该模型对于不同数据集大小的性能。对于 8100 幅增强图像的训练集,验证准确率刚刚超过 43%。

相比较而言,随机选择类的模型只会得到 1.23%的分数,所以线性 logistic 回归模型至少学到了一些有用的东西。

对于我们的目的来说,准确度高非常重要。如果我们想找到一幅图像中的所有集合组合,我们需要正确分类 12+张卡片。91%或更低的准确度意味着平均而言,在每张图片中有一张卡片被错误分类,这将破坏集合检测。

让我们看看如何通过使用深度学习来提高这种性能。

选择迁移学习策略

对于我们的任务,我可以尝试从头开始训练一个深度卷积神经网络(DCNN ),但由于我的(基础)数据集很小,该模型可能会过拟合。

一种流行的方法是使用转移学习,你拿一个为某项任务训练过的模型,你在另一项任务中重用

有许多方法可以应用迁移学习,为某项任务和数据集找到最佳策略可能会令人望而生畏。我发现有一篇有趣的文章提供了一些指导:选择迁移学习策略的两个最重要的因素是新数据集 的大小和与原始数据集的相似度。**

  • 如果你的新数据集很大: 对于一个大的数据集,过度拟合的机会很小,所以你可以微调整个网络* k 或者如果你的数据非常不同,从头开始训练一个 DCNN。实际上,即使数据集是不同的,用预训练模型的权重初始化网络可能仍然是有帮助的。*
  • 如果您的新数据集很小: 不要训练或微调 DCNN,因为它会过拟合。相反,根据数据集与原始数据集的相似程度,使用来自早期或后期层的 CNN 特征训练一个线性分类器** 。
    如果您的数据集不同,请从网络中较早的某处选择更为通用的要素。如果是相似的,来自更多特定于数据集的最终图层的特征是最有用的。*

*线性模型使用特征的线性组合,正因为如此,它们比可以学习各种非线性模式的神经网络更受限制。这种限制有助于减少过度拟合。通过使用线性模型和非线性特征表示,我们可以说是两全其美。

对于集合检测任务,我们有一个非常小的数据集,该数据集也与 ImageNet 的图像非常不同,因此该项目的转移学习策略将是从网络中的某个更早的处的训练一个线性分类器。下一步就是找出哪一层会带来最好的性能。**

Setup for the classification: use mid-level image embeddings from a pre-trained Deep Convolutional Network as input for a linear model

寻找最佳图层

根据上面的指导方针,我们知道我们需要从网络中的“更早的某个地方”选择一个层,但是我们如何知道哪一个层具有最好的结果呢?为了找到我们的集合分类任务的最佳层,我决定测试每一层并在验证集合上比较性能。实验设置如下。

对于深度卷积网络中的每个层* i 😗

  • 将纸牌的输入图像通过预先训练好的网络(进行预测),得到第一层的输出
  • 使用图层输出作为输入特征来训练逻辑回归模型。
  • 根据验证集评估模型。

验证精度最高的图层将用于最终模型。

我对不同数量的训练样本重复了这个实验,以观察训练数据量的影响。

resnet 50 的结果

ResNet50 模型【2】的 50 个卷积层中每一层的验证精度如下图所示。

我发现什么有趣:

  • 在网络的第一个卷积层(层 1* )之后,验证准确度与基线分数相当。例如,对于 8100 幅图像,验证准确率为 48.1%。这比基线(43.2%)有了小小的提高。*
  • 当深入到网络中时,验证准确性会变得更好,但分数根本不会单调增加。存在高峰和深谷,在这些地方,不知何故,特征表示对于检测集卡不是最佳的。
  • 许多层使其达到 100%的验证准确性。最佳层位于网络的中层和高层。尽管满分看起来令人印象深刻,但我们需要考虑到验证集非常小(每个类只有一个样本)。即便如此,我认为良好的验证准确性可以为哪一层的性能最好提供一些指导。
  • 正如所料,用于训练的数据量对性能非常重要。增加样本数量可以提高性能,但某些层有例外。

比较不同深度卷积模型

我还比较了一些不同架构的性能:resnet 50【2】,MobileNet【3】和MobileNet V2【4】。

残差神经网络(ResNets) 微软的一个团队在 2015 年引入了深度残差学习,作为处理消失梯度的新方法,这是一个阻止非常深度的网络有效工作的问题。通过使用跳过连接,来自先前层的激活可以被重用并提供基本性能,直到附加层得到改进。这使得在不影响性能的情况下增加层数成为可能[2]。
本实验使用的模型是 ResNet50,有 50 个卷积层。

The ResNet50 uses skip connections (denoted by arrows) to jump over some layers. By reusing activations from earlier layers, it helps to fight the notorious vanishing gradients problem. This made it possible to create really deep networks.

MobileNet 架构 由谷歌开发的 MobileNet 架构经过优化,可以非常高效地在手机上运行。主要思想是使用不同类型的卷积,称为深度方向可分离卷积。它与常规卷积运算的结果大致相同,但速度要快得多[3]。
随着 MobileNetV2 的推出,最初的 MobileNet 架构通过应用残差学习(的一种变体)和许多其他创新得到了进一步改进【4】。

不同网络的验证结果 在下图中,针对 8100 个图像的数据集绘制了每个模型的结果。

Performance on the validation set for three different architectures. Note that the number of convolutional layers is different for each architecture.

我发现什么有趣:

  • 对于 ResNet50 架构,第 23 层的精度下降是一个有趣的异常现象。我真的不能解释是什么导致了它,但有趣的是它发生在第四阶段的开始。在每个阶段,过滤器的数量加倍。
  • 这两个 MobileNet 模型看起来更稳定,因为它们对后续层显示出更少的变化。MobileNet 模型稳步增长,在第 10 层表现出最高性能(92.6%)。当到达更高层时,性能逐渐下降。
  • MobileNet V2 性能最好的层是第 32 层,它具有 100%的验证分数。网络中较高层的性能较低。

在数据量相同的情况下,ResNet50 拥有最多具有完美验证分数的层,对于最终模型,我将使用该架构。如果你想为 SET 检测创建一个移动应用程序,我想 MobileNetV2 也是一个有趣的选择。

分类结果
经过一点调整以改进模型后,我发现最大的增益是通过调整增强设置brightness_rangefill_mode获得的。经过几次迭代后,该模型现在可以正确地对所有测试图像进行分类。

我知道在你看到测试集的结果后调整一个模型,它变得更像一个验证集,并且有过度拟合的风险,但是为了博客的目的,我想我可以接受。

Example of found contours, registered images and predictions from the best model for each card

3.查找集合组合

现在我们可以对卡片进行分类了,接下来是最后一步,找到所有可能的集合组合。

请记住,为了有一个集合,三张卡的每个属性需要有相同的值或者不同的值。一个简单的解决方案是考虑所有可能的三元组,并检查集合规则是否适用于三元组。对于 12 张卡,有 12 除以 3 = 220 个可能的三元组,检查所有的三元组不会花费太多的计算。**

首先,让我们将特征转换成数值。

“设定的诡计”

我发现有一个有趣的方法来确定一个三连音是否是一个集合。考虑以下两个三胞胎:

当您查看这些有效和无效集合的示例时,您会发现:

  • 对于有效集合,每个属性的值之和是三的倍数。
  • 对于无效集合,一些属性的值之和不是三的倍数。

这个规则适用于所有可能的组合,它使得我们的集合寻找算法相当优雅。

Finding SETs, by checking if the sum of the attributes mod 3 is zero

有限域

有趣的是,这个技巧不适用于任意的数字表示,但是只要我们选择模 3 不同的数字值,它就会起作用。

更深层次的原因是,模函数是一个有限域。字段是具有特定属性的数字集合,其行为有点像有理数或实数。基本的运算如加、减、乘、除都有定义,每个数都有乘法逆运算,这意味着如果你把它和那个逆运算相乘,你会得到 1。这也意味着设定的自然数不是一个字段。

因为模函数是一个有限域,所以它有一些特殊的性质,这些性质对于集合游戏是很重要的。

你可以把一张集合卡想象成一个四维空间中的一个点,其中每个特征都是一个不同的维度(颜色、形状、填充和数量)。例如,具有特征值绿色、正方形、虚线、两个的卡片可以表示为 4D 点 [1,0,2,1]。因为每个特征只能取三个值中的一个,我们可以定义集卡的空间是一个大小为 3 的有限域。【1】

Example for two features (2D space). All points that are co-linear are valid SET combinations

现在,可以表明对于有效集合,有限域内的点是共线的,这意味着这些点在一条线上。此外,如果点不是共线的,它不是一个有效的集合组合。

所以基本上,寻找集合的,其实就是在 4 维有限空间中寻找共线点![1]

将这一切结合在一起

当所有的事情都凑在一起,你真的看到你的模型做了你希望的事情时,会有这种令人满意的(有时是叛逆的)感觉。

通过结合纸牌的提取 、纸牌类型的分类集合检测算法,最终我们可以从一幅图像中找到集合组合!

Final result of finding SET combinations from an image

参考

  • [1] 《纸牌游戏集》
    本杰明·斋戴维斯,黛安·麦克拉根,2003 年
  • [2] 深度残差学习用于图像识别,
    何,,,任,,2014
  • [3] MobileNets:用于移动视觉应用的高效卷积神经网络
    Andrew G. Howard,朱梦龙,,Dmitry Kalenichenko,,Tobias Weyand,Marco Andreetto,Hartwig Adam,2017
  • [4] MobileNetV2:反向残差与线性瓶颈
    马克·桑德勒,,朱梦龙,安德烈·朱莫金诺夫,陈良杰,2018

用视网膜网探测足球运动员和球。

原文:https://towardsdatascience.com/detecting-soccer-palyers-and-ball-retinantet-2ab5f997ab2?source=collection_archive---------18-----------------------

用于体育运动的计算机视觉

直截了当的指南,建立一个计算机视觉模型,以检测球员和球在架空摄像机图像。

我们将使用 RetinaNet 模型,如宗-林逸、普里亚戈亚尔、罗斯·吉希克、明凯·何、彼得·多拉的论文中所述。

我们还将使用 Fizyr 对 keras-retinanet 的出色实现,将其应用于 Haizaha 的足球运动员和球检测免费数据集。

要求:

首先,确保安装了 TensorFlow 和 Keras。

如果您需要 GPU 支持,请遵循tensorflow.org上的说明。

接下来,您将需要克隆、构建和安装 keras-retinanet 项目。

数据

安装完所有依赖项后,下一步是下载标记为的图片。

预训练重量

我已经公开了我的训练重量。如果您想立即运行模型,以下是下载它们的方法。

进口

我们需要导入 TensorFlow、Keras、keras_retinanet,以及其他一些模块。

实用程序

  • 查看注释:

我们将使用下面的 view_annotations 函数来显示带有相关边界框注释的图像。

如果您运行以下命令:

您应该会得到如下图像:

Output of view_annotations()

  • 加载模型:

  • 用模型对图像进行检测

推论

既然我们已经创建了助手函数,我们需要做的就是调用它们来加载模型并在图像上运行它。

加载模型:

使用模型检测球员和球:

Run_detection 采用我们使用权重“pre-trained/resnet 50 _ CSV _ last _ inference . H5”创建的模型,并在“soccer/images/frame_0100.jpg”上运行该模型

您应该得到这样的结果:

Output of run_detection()

训练

要训练您的模型,您需要做的就是执行 train.py 脚本:

模型训练应该开始,您应该会看到类似这样的内容:

Screenshot: training progress in the terminal

监测培训进展

TensorBoard 提供了一个简洁的网络界面来监控你的模型学习。要运行它,您只需在终端中运行以下代码:

tensorboard --logdir logs/fit

您希望确保 logs/fit 指向

现在,您可以在浏览器上访问以下 URL:

http://you_ir_address:6006

Screenshot: TensorBoard

转换培训模式

训练完模型后,您需要将训练模型转换为推理模型,然后才能使用它来检测对象。

下面是如何将训练模型转换为推理模型:

运行新训练的模型

现在,您可以加载新训练的模型并再次运行检测:

您应该会从上面的代码中得到以下输出:

Output of run_detection() after re-training the model

优化:检测小物体具有挑战性

在过去的几年里,我们在物体探测任务上取得了令人印象深刻的进展。尽管如此,与检测大对象相比,今天的模型仍然难以检测图像中的小对象。

Small Objects Detection, on PapersWithCode.com

RetineNet 在第一阶段使用特征金字塔网络(FPN)来识别不同尺度上的对象。你可以使用不同的比例比例值来帮助网络更好地识别小物体。

您需要做的是为您的模型创建一个 config.ini :

[anchor_parameters] 
sizes   = 32 64 128 256 512 
strides = 8 16 32 64 128 
ratios  = 0.5 1 2 3 
scales  = .5 1.2 1.6

训练模型时,请确保包含配置文件:

python keras-retinanet/keras_retinanet/bin/train.py --config config.ini csv soccer/train.csv soccer/labels.csv --val-annotations soccer/valid.csv

项目存储库

这个项目的所有代码都可以在 GitHub 上免费获得:

[https://github.com/ramarlina/retinanet-player-ball-detection](https://github.com/ramarlina/retinanet-player-ball-detection)

检测时间序列数据中的平稳性

原文:https://towardsdatascience.com/detecting-stationarity-in-time-series-data-d29e0a21e638?source=collection_archive---------1-----------------------

平稳性是时间序列分析中的一个重要概念。关于这个话题的简明(但全面)介绍,以及让这个话题变得重要的原因,请看一下我之前关于这个话题的博客文章。无需重复太多,只需指出:

  1. 平稳性意味着一个时间序列的统计特性(或者说产生它的过程)不会随着时间而改变。
  2. 平稳性很重要,因为许多有用的分析工具、统计测试和模型都依赖于它。

因此,确定时间序列是否平稳的能力非常重要。这通常意味着能够以很高的概率确定一个序列是由一个平稳过程生成的,而不是在两个严格的选项之间做出决定。

在这篇简短的文章中,我将介绍几种方法来做到这一点。

形象化

平稳性检测的最基本方法依赖于绘制数据或其函数,并直观地确定它们是否呈现平稳(或非平稳)数据的某些已知属性。

在看数据

试图通过观察一个时间序列的图表来确定它是否是由一个平稳过程产生的是一个可疑的冒险。然而,我们可以寻找非平稳数据的一些基本属性。让我们以[hynd man&Athanasopoulos,2018 ]中的以下美好情节为例:

Figure 1: Nine examples of time series data; (a) Google stock price for 200 consecutive days; (b) Daily change in the Google stock price for 200 consecutive days; (c) Annual number of strikes in the US; (d) Monthly sales of new one-family houses sold in the US; (e) Annual price of a dozen eggs in the US (constant dollars); (f) Monthly total of pigs slaughtered in Victoria, Australia; (g) Annual total of lynx trapped in the McKenzie River district of north-west Canada; (h) Monthly Australian beer production; (i) Monthly Australian electricity production. [Hyndman & Athanasopoulos, 2018]

[Hyndman & Athanasopoulos,2018]给出了几种用于排除上述图中平稳性的试探法,对应于平稳过程的基本特征(,我们之前已经讨论过):

  • 在系列(d)、(h)和(I)中可以观察到显著的季节性。
  • 在系列(a)、(c)、(e)、(f)和(I)中可以看到明显的趋势和变化水平。
  • 系列(I)显示方差增加。

作者还补充说,尽管系列(g)中的强周期可能看起来使其不稳定,但这些周期的时间使其不可预测(由于潜在的动态主导猞猁种群,部分由可用饲料驱动)。这使得系列(b)和(g)成为唯一的固定系列。

如果你和我一样,在看上面的图时,没有发现这些观察中至少有一些是微不足道的,你不是唯一一个。事实上,这不是一个非常可靠的检测平稳性的方法,它通常用于获得数据的初步印象,而不是做出明确的断言。

查看自相关函数(ACF)图

自相关是信号与自身延迟副本或滞后的相关性,作为延迟的函数。当绘制增加滞后的 ACF 值时(称为相关图的图),对于平稳时间序列,这些值往往会迅速降为零(见图 1,右),而对于非平稳数据,降级会发生得更慢(见图 1,左)。

Figure 2: The ACF of the Google stock price (left; non-stationary), and of the daily changes in Google stock price (right; stationary).

或者,【 Nielsen,2006 】建议,绘制基于自相关和比例自协方差的相关图,并对其进行比较,提供了区分平稳和非平稳数据的更好方法。

参数测试

另一种更严格的方法,检测时间序列数据中的平稳性,是使用统计测试来检测特定类型的平稳性,即由生成随机过程的简单参数模型产生的平稳性详见我之前的帖子。

我将在这里介绍最突出的测试。我还将为每个测试命名 Python 实现,假设我已经找到了。有关 R 实现,请参见 CRAN 任务视图:时间序列分析(此处也是)。

单位根检验

Dickey-Fuller 检验
Dickey-Fuller检验是第一个为检验零假设而开发的统计检验,假设给定时间序列的自回归模型中存在单位根,因此该过程不是平稳的。最初的测试处理简单的 lag-1 AR 模型的情况。该测试有三个版本,它们测试的单位根过程的模型不同;

  1. 单位根检验:∆yᵢ = δyᵢ₋₁ + uᵢ
  2. 有漂移的单位根检验:∆yᵢ = a₀ + δyᵢ₋₁ + uᵢ
  3. 具有漂移和确定性时间趋势的单位根检验:
    ∆yᵢ = a₀ + a₁*t + δyᵢ₋₁ + uᵢ

选择使用哪个版本—这可以显著影响测试的规模和功效—可以使用一系列有序测试的先验知识或结构化策略,从而发现最合适的版本。

开发了测试的扩展,以适应更复杂的模型和数据;这些包括增强的迪基-富勒(ADF) (使用任意阶的 ARp并支持时间趋势的建模)菲利普-佩伦检验(PP) (对未指定的自相关和异方差增加稳健性)和 ADF-GLS 检验(处理恒定和线性趋势的局部去趋势数据)。

Python 实现可以在 statsmodels 和 ARCH 包中找到。

KPSS 测试
另一个针对单位根存在的著名测试是 KPSS 测试。[科维亚特科夫斯基等人,1992 年]与迪基-富勒检验家族相反,零假设假设围绕一个均值或线性趋势平稳,而另一个是单位根的存在。

测试基于线性回归,将序列分成三部分:确定性趋势( βt )、随机游走( rt )和平稳误差( εt ),回归方程为:

并且其中 u ~(0,σ)和都是 iid 。因此,零假设被表述为 H₀: σ =0 ,而备选项为 Hₐ: σ > 0 。通过分别设置 β=0 (在这种情况下 x 在均值 r₀附近是稳定的)或 β≠0 来确定零假设中的平稳性是围绕均值还是趋势。

KPSS 检验通常用于补充迪基-富勒型检验。我将在以后的文章中谈到如何解释这样的综合结果。

Python 实现可以在 statsmodels 和 ARCH 包中找到。

Zivot 和 Andrews 测试 上述测试没有考虑到结构突变的可能性——涉及过程的平均值或其他参数变化的突然变化。假设断裂的时间是一个外生现象,Perron 表明,当静态选择为真且结构断裂被忽略时,拒绝单位根的能力下降。

[Zivot 和 Andrews,1992]提出了一个单位根检验,其中他们假设断点的确切时间是未知的。根据 Perron 对结构突变形式的描述,Zivot 和 Andrews 继续用三个模型来检验单位根:

  • 模式 A:允许一次性改变系列级别。
  • 模型 B:允许趋势函数斜率的一次性变化。
  • 模型 C:结合了系列趋势函数的水平和斜率的一次性变化。

因此,为了针对一次性结构突变的替代方案测试单位根,Zivot 和 Andrews 使用了以下与上述三个模型相对应的回归方程:[Waheed 等人,2006]

Python 实现可以在 ARCH 包和这里中找到。

半参数单位根检验

方差比检验
【Breit ung,2002】提出了一种基于方差比统计的单位根存在性的非参数检验。零假设是过程 I(1)(一阶积分),而备选项是 I(0)。我将这个测试列为半参数测试,因为它测试的是一个特定的、基于模型的平稳性概念。

非参数检验

由于参数检验的局限性,以及人们认识到它们只涵盖真实数据中可能遇到的情况的一个狭窄的子类,一类针对平稳性的非参数检验在时间序列分析文献中出现了。

自然,这些测试为调查时间序列数据开辟了一条有希望的途径:你不再需要假设非常简单的参数模型碰巧适用于你的数据,以确定它是否是平稳的,或者冒着发现这些模型没有捕捉到的现象的复杂形式的风险。

然而,它的现实要复杂得多;目前,还没有任何广泛适用的非参数测试来涵盖生成时间序列数据的所有真实场景。相反,这些测试仅限于特定类型的数据或流程。此外,我无法找到以下任何测试的实现。

我将在这里提到我遇到的几个例子:

连续时间马尔可夫过程平稳性的非参数检验

[ Kanaya,2011 ]建议对单变量 时齐马尔可夫过程进行这种非参数平稳性检验,构造基于核的检验统计量并进行蒙特卡罗模拟,以研究该检验的有限样本容量和功效特性。

函数时间序列平稳性的非参数检验

[Delft et al,2017]提出了一种非参数平稳性检验,仅限于函数时间序列——通过将一个连续的(在自然界中)时间记录分成自然的连续间隔(例如天数)获得的数据。请注意,[Delft 和 Eichler,2018]已经提出了对函数时间序列的局部平稳性的测试(参见我以前的帖子中关于局部平稳性的一些参考)。此外,[Vogt & Dette,2015]提出了一种非参数方法来估计局部平稳框架中的平滑变化点。

基于局部傅立叶分析的平稳性非参数检验

[ Basu 等人,2009 ]提出了最适用于平稳性的非参数检验,因为它适用于任何零均值离散时间随机过程(我在这里假设离散过程的任何有限样本都可以很容易地转换为零均值)。

最后的话

就是这样。我希望上面的评论能让你对如何检测数据中的平稳性有所了解。我也希望它能让你了解这项任务的复杂性;由于缺乏对少数非参数检验的实现,你将被迫对你的数据做出强有力的假设,并以必要的怀疑来解释你得到的结果。

至于一旦在数据中检测到某种类型的平稳性,该怎么办的问题,我希望在以后的文章中涉及到这个问题。像往常一样,我喜欢听我错过或做错的事情。干杯!

参考

学术文献

  • Basu,p .,Rudoy,d .,和 Wolfe,P. J. (2009 年 4 月)。基于局部傅立叶分析的平稳性非参数检验。在 2009 年 IEEE 国际声学、语音和信号处理会议(第 3005–3008 页)。IEEE。
  • j . Breit ung(2002 年)。单位根和协整的非参数检验。计量经济学杂志,108(2),343–363。
  • Cardinali 和 g . p . Nason(2018 年)。二阶平稳性的实用有效小波包测试。应用和计算谐波分析44 (3),558–583。
  • Hyndman,R. J .,& Athanasopoulos,G. (2018 年)。预测:原理与实践。OTexts。
  • Kanaya,S. (2011 年)。连续&时间马尔可夫过程平稳性的非参数检验。牛津大学就业市场论文。
  • 科维亚特科夫斯基,菲利普,施米特,和申(1992)。用单位根检验平稳性的零假设:我们有多确定经济时间序列有单位根?。计量经济学杂志54(1–3),159–178。
  • 尼尔森,B. (2006 年)。非平稳自回归的相关图。英国皇家统计学会杂志:B 辑(统计方法论)68 (4),707–720。
  • m .瓦希德、t .阿拉姆和 S. P .加利(2006 年)。结构突变和单位根:来自巴基斯坦宏观经济时间序列的证据。可从 SSRN 963958* 处获得。*
  • 范·代尔夫特(2017 年)。函数时间序列平稳性的非参数检验。 arXiv 预印本 arXiv:1708.05248
  • 范·代尔夫特和艾希勒(2018)。"局部平稳函数时间序列."电子统计杂志,12:107–170。
  • Vogt,m .,& Dette,H. (2015 年)。检测局部平稳过程中的渐变。统计年鉴43 (2),713–740。
  • Zivot,e .和 D. Andrews,(1992),大崩盘的进一步证据,石油价格冲击和单位根假说,商业和经济统计杂志,* 10,251–270。*

在线参考

  • 数据转换和预测模型:使用什么以及何时使用
  • 预测流程图
  • egcm R 包的文档
  • “非平稳时间序列和单位根检验”Heino Bohn Nielsen
  • 如何解读 Zivot &安德鲁斯单位根检验?

用拓扑数据分析检测股市崩盘

原文:https://towardsdatascience.com/detecting-stock-market-crashes-with-topological-data-analysis-7d5dd98abe42?source=collection_archive---------7-----------------------

由 Wallyson Lemes De Oliveira、 Lewis Tunstall 、Umberto Lupo 和 Anibal Medina-Mardones 撰写

只要有金融市场,就会有金融崩溃。当市场下跌时,大多数人都会遭受损失……那些能够预见到下跌的人可以保护他们的资产,或者持有高风险的空头头寸来获利(这种情况尽管令人紧张,正如的大空头中所描述的那样)。

市场上的资产与一个动态系统相关联,其价格随可用信息的变化而变化。金融市场上的资产价格是由广泛的信息决定的,在有效市场假说中,信息的一个简单变化将立即被定价。

金融系统的动态可以与物理系统的动态相媲美

就像固体、液体和气体之间发生相变一样,我们可以区分市场上的正常状态和混乱状态。

观察显示,金融崩溃之前会有一段资产价格波动加剧的时期【1】。这种现象转化为时间序列几何结构的异常变化。

在这篇文章中,我们使用拓扑数据分析(TDA)来捕捉时间序列中的这些几何变化,以便为股市崩盘提供一个可靠的检测器。代码实现了吉迪亚和卡茨给出的想法,这要归功于乔托-TDA 一个用于拓扑数据分析的开源库。

对于金融崩溃的确切定义,人们几乎没有共识

直觉上,股市崩盘是资产价格的快速下跌。价格下跌是由大规模出售资产引起的,这是在价格进一步下跌之前试图平仓。

意识到一个巨大的投机泡沫(就像次贷危机),或者一个灾难性的事件,将会导致市场崩溃。在过去二十年里,我们目睹了两次大崩盘:2000 年的互联网崩盘和 2008 年的全球金融危机。

我们的结果一言以蔽之

我们分析了从 1980 年至今标准普尔 500 指数的每日价格。S&P 是一个常用来衡量金融市场状况的指数,它衡量 500 家大型美国公司的股票表现。

与简单的基线相比,我们发现拓扑信号往往对噪声具有鲁棒性,因此不容易产生假阳性。

这突出了 TDA 背后的一个关键动机,即拓扑和几何可以提供一个强大的方法来抽象复杂数据中的微妙结构。

Detection of stock market crashes from baseline (left) and topological (right) models, discussed in detail below.

让我们更详细地描述这两种方法。

一个简单的基线

鉴于市场崩盘代表股价的突然下跌,检测这些变化的一个简单方法是跟踪滚动窗口内平均价格值的一阶导数。事实上,在下图中,我们可以看到这种天真的方法已经捕捉到了黑色星期一崩盘(1987 年)、网络泡沫破裂(2000-2004 年)和金融危机(2007-2008 年)。

Magnitude of the first derivative of mean close prices between successive windows.

通过归一化这个时间序列,取[0,1]区间内的值,我们可以应用一个阈值来标记原始时间序列上发生崩溃的点。

Crash probability for baseline model (left), with points above threshold shown on original time series (right).

显然,这种简单的方法相当嘈杂。

随着许多点被贴上崩溃的标签,遵循这个建议将导致过度恐慌和过早出售你的资产。让我们看看 TDA 是否能帮助我们降低信号中的噪声,并获得一个更强大的检测器!

TDA 管道

TDA 背后的数学很深奥,不在本文讨论范围内——我们建议这个概述。出于我们的目的,将 TDA 视为提取可用于下游建模的信息特征的手段就足够了。

我们开发的流水线包括:2)将时间序列嵌入到点云中,并构建点云的滑动窗口,3)在每个窗口上构建过滤,以具有编码每个窗口的几何形状的进化结构,4)使用持久性同源性提取那些窗口的相关特征,5)通过测量这些特征从一个窗口到下一个窗口的差异来比较每个窗口,6)基于该差异构建碰撞指示器。

TDA pipeline

时间序列作为点云— Takens 嵌入

TDA 流水线的典型起点是从点云生成单纯复形。因此,时间序列应用中的关键问题是如何生成这样的点云?离散时间序列,就像我们正在考虑的,通常被可视化为二维散点图。这种表示使得通过从左到右扫描图来跟踪时间序列的 局部 行为变得容易。但是在传达可能在更大的时间尺度上发生的重要影响时,它常常是无效的。

一组众所周知的捕捉周期行为的技术来自傅立叶分析。例如,时间序列上的时间窗口的离散傅立叶变换给出了关于该窗口中的信号是否作为几个简单周期信号的总和出现的信息。

为了我们的目的,我们考虑一种不同的编码时间演化过程的方式。它基于动力学的一些关键性质可以在更高维度中被有效地揭示的想法。我们首先说明一种将单变量时间序列表示为 点云 的方式,即任意维度的欧几里德空间中的一组向量。

过程如下:我们选择两个整数 dτ 。对于每一次 tᵢ ∈ (t₀,t₁…),我们收集变量 yd 不同时间的值,以 τ 均匀间隔,从 tᵢ 开始,将它们表示为具有 d 条目的向量,即:

结果就是一组 d 维空间的向量! τ 称为延时参数, d 为嵌入尺寸。

这种延时嵌入技术也称为塔肯斯嵌入,以芙罗莉丝·塔肯斯命名,他用一个著名的定理在 非线性 动力系统的背景下证明了它的重要性。

最后,在整个时间序列上对滑动窗口分别应用该程序,得到一个具有可能有趣拓扑的点云时间序列(每个滑动窗口一个)。下面的 GIF 显示了这样的点云是如何在二维空间中生成的。

Illustration of the Taken’s embedding with embedding dimension d=2 and time delay τ=1

从点云到暂留图

现在我们知道了如何生成时间序列的点云,我们可以用这些信息做什么呢?输入持久同调,它在单纯复形中寻找在某个参数值范围内持续存在的拓扑特征。通常,某个特征(如孔)最初不会被观察到,然后会出现,在某个参数值范围后会再次消失。

Point clouds from two successive windows and their associated persistence diagram

持久图之间的距离

给定两个窗口及其对应的持久性图,我们可以计算各种距离度量。在这里,我们比较了两个距离,一个基于持久性景观的概念,另一个基于贝蒂曲线。

Magnitude of the landscape (left) and Betti curve (right) distances between successive windows.

从这些图中,我们可以推断,基于景观距离的度量比 Betti 曲线的噪声小。

一个拓扑指示器

使用窗口之间的景观距离作为我们的拓扑特征,就像我们对基线模型所做的那样,对其进行归一化是一件简单的事情。下面我们展示了网络泡沫和全球金融危机导致的股市崩溃的检测结果。与我们的简单基线相比,我们可以看到,使用拓扑特征似乎可以降低目标信号中的噪声。

Crash probabilities and detections using topological features. The time ranges correspond to the dot-com bubble in 2000 (upper) and the global financial crisis in 2008 (lower).

结论

我们的结果表明,崩盘前的高波动期会产生几何特征,使用拓扑数据分析可以更有力地检测到这些特征。然而,这些结果只涉及一个特定的市场和一段很短的时间,所以人们应该进一步调查该程序对不同市场和不同阈值的稳健性。然而,结果是令人鼓舞的,并为未来的发展打开了一些有趣的思路。

更多带代码的文章:

图形嵌入

  • 入门,预测分子键的例子,其笔记本
  • 化学函数的形状及其笔记本:图形嵌入图形波

时间序列

  • 检测股灾及其笔记本:TDA 股灾时间序列分析
  • 噪音背后的形状和它的笔记本:用 TDA 进行时间序列分析,产生对大量噪音具有鲁棒性的信号

可视化

  • Mapper 入门,可视化高维数据以找到其粗略结构
  • 与选举结果相关的美国社会经济研究(笔记本):使用 Mapper。

持久性

  • 足球的形状和它的笔记本:带有持续性图表的团队表现特征

乔托

  • Github 上的 Giotto-tda 库
  • 更多学习资料请访问网站
  • 推特
  • 松弛进行支撑

使用异常检测技术检测机器故障的开始

原文:https://towardsdatascience.com/detecting-the-onset-of-machine-failure-using-anomaly-detection-techniques-d2f7a11eb809?source=collection_archive---------10-----------------------

Source: mc.ai

介绍

影响产品质量的因素很多,但并非所有这些因素都在制造商的控制之下。质量问题最常见的来源之一是没有得到适当维护的故障设备。因此,监控机器和部件(如冷却风扇、轴承、涡轮机、齿轮、皮带)的状态并保持理想的工作状态变得非常重要。

当机器或部件出现故障时,执行纠正性维护,以确定故障原因,并确定维护和重新启动机器至正常工作状态所需的维修程序。然而,因为机器已经在没有任何预先警告的情况下发生故障,所以需要时间来采购和修理故障部件。因此,需要考虑一种维护策略来最大限度地减少服务停机时间。但是机器和它们的部件会随着时间而退化,并且故障的时间是无法提前知道的。因此,基于时间的维护策略主要用于维护机器和设备的状态。

在这篇文章中,我将讨论各种可以用来检测机器中发生的故障的技术。

异常检测

在一个教室里,总有一些学生要么比其他学生表现得更好,要么在确保科目分数方面甚至以最低分数不及格。大多数时候,学生的分数除了刚才提到的,一般都是正态分布的。这些标记可以分别称为极端高点和极端低点。在统计学和机器学习等其他相关领域,这些值被称为异常值或异常值。

异常检测(或异常值检测)是对罕见项目、事件或观察结果的识别,这些项目、事件或观察结果因与大多数数据显著不同而引起怀疑。通常,异常数据可能与某种问题或罕见事件有关,例如银行欺诈、医疗问题、结构缺陷、设备故障等。这种联系使得挑选出哪些数据点可以被视为异常变得非常有趣,因为从业务角度来看,识别这些事件通常非常有趣。

Anomaly Detection

这引发了一个问题:我们如何识别数据是正常的还是异常的?有各种技术可以帮助我们识别这一点。

异常检测技术

存在许多异常检测方法。其中一些方法的粗略分组包括统计算法、基于聚类的方法、基于最近邻的方法、基于分类的方法、基于频谱的方法、基于空间二次采样的方法和深度学习方法。

基于统计的方法

基于统计的方法假设数据遵循特定的分布,因此模型是根据指定的概率分布创建的。检测数据异常的最简单方法是标记偏离分布共同统计特性的数据点。例如,可以根据偏离平均值的某个标准偏差来定义异常。这些模型的优点是它们输出一个概率作为离群值的度量。

Statistical based methods

基于聚类的方法

在基于聚类的异常检测中,假设相似的数据点属于相似的组。这由到群集质心的距离决定。然后通过为聚类的大小或到聚类质心的距离设置阈值来计算异常分数;如果聚类具有小于阈值的数据点,则它们被标记为异常,或者如果数据点到聚类中心的距离超过设置的阈值,则它被标记为异常。k 均值聚类就是这种方法的一个例子。

Clustering-based method (K Means Clustering)

基于最近邻的方法

基于最近邻的异常检测通常假设正常数据样本出现在看似密集的邻域中,而异常数据样本远离它们最近的邻居。最近邻方法通常可以分为基于距离的方法和基于密度的方法。这两种方法都需要相似性或距离度量来决定数据实例的异常程度。一些例子包括 k-NN、马氏距离和局部异常因子(LOF)。

Nearest Neighbor method (KNN)

基于分类的方法

根据标签的可用性,基于分类的异常检测可以分为单类(仅正常标签)和多类(多类)分类。基于分类器的异常检测包括两个步骤:

  1. 在训练阶段,使用可用的标记训练数据来学习分类器。
  2. 然后,使用在初始步骤中训练的分类器将测试实例分类为正常或异常。

单类支持向量机(OCSVM)和神经网络方法是这种检测方法的例子。

Classification based method (One class SVM)

基于频谱或子空间的方法

基于谱或子空间的方法试图提取最能描述训练数据可变性的特征。这些方法假设正常数据可以表示在一个低维子空间中,在这个子空间中正常数据与异常数据是有区别的。主成分分析(PCA)被认为是一种基于子空间的异常检测方法。

Subspace based method (PCA)

基于子采样的方法

许多离群点检测方法遭受维数灾难;随着给定数据集维度的增加,基于距离的方法会失败,因为任何一对点之间的相对距离都会变得相对相同。为了克服这个问题,基于子采样的方法将高维空间划分成更小的子空间,并且监视不同子空间中的异常值排序。离群点是在较小的子空间中始终排名较高的点。隔离森林是一种算法,它将高维空间划分为更小的维度,并尝试在低维空间中发现异常。

Subsampling based methods (Isolation forest)

高斯分布方法

高斯分布也称为正态分布。我们将使用高斯分布来开发异常检测算法,也就是说,我们将假设我们的数据是正态分布的。这是一个假设,不能适用于所有的数据集,但当它适用时,它证明了一个发现异常值的有效方法。

椭圆包络是一种方法,通过假设我们的整个数据是基础多元高斯分布的表达式,试图找出我们数据的总体分布的关键参数。

Gaussian based methods (Elliptic Envelope)

履行

我已经从 Numenta 异常基准(NAB)下载了数据集。NAB 是评估流实时应用中异常检测算法的新基准。具体来说,我将使用环境温度数据集,该数据集包含来自办公室环境的实时观测数据。

该数据集包含从 2013 年 12 月 2 日到 2014 年 2 月 19 日间隔 5 秒的 22695 次观测。数据集不包含空值。建筑物的温度是华氏温度,后来被转换成摄氏温度。

以下是一段时间内温度读数的图形表示。

Temperature Distribution

特征工程

我对数据集进行了特征工程,这将有助于建立一个更好的模型。

  1. 一天分为白天和晚上,这对于确定故障是发生在白天还是晚上非常有用。

白天—早上 7 点到晚上 10 点

夜间——晚上 10.01 到早上 6.59

2.一周分为工作日或周末,如果故障发生在大多数员工在办公室(工作日)或其他时间,这将是有用的信息。

3.四个不同的类别将观察结果分为“工作日夜晚”、“工作日光亮”、“周末光亮”、“周末夜晚”

正如我们所见,工作日白天的温度更加稳定。

模型

k 表示聚类

k-均值聚类旨在将 n 个观测值划分为 k 个簇,其中每个观测值属于具有最近均值的簇,作为该簇的原型。这里 k 是一个超参数,使用弯头方法选择。

用肘法,k 被发现是 15。然后,数据被分成 15 个不同的组,如图所示。

K means clustering with k=15

下一步是得到每个点和它最近的质心之间的距离。最大的距离被认为是异常的。下面是聚类视图中异常的可视化表示。

Anomalies (Red color) and normal readings (Blue color)

我们可以清楚地看到,K 表示聚类能够成功地将异常(红色)与正常(蓝色)区分开来。异常也可以随着时间的推移而可视化。

Anomalies visualized throughout time (K Means)

异常也可以通过温度再分配来可视化。

Anomaly detection using temperature repartitioning (K Means)

使用 K 均值聚类的一个缺点是,它会将记录末尾附近的低温检测为异常,但不会检测高温附近的异常。

隔离森林

使用隔离林方法检测到以下异常。

Anomalies visualized throughout time (Isolation Forest)

Anomaly detection using temperature repartitioning (Isolation Forest)

一等 SVM

Anomalies visualized throughout time (One Class SVM)

Anomaly detection using temperature repartitioning (One Class SVM)

椭圆形信封

Anomalies visualized throughout time (Elliptic Envelope)

Anomaly detection using temperature repartitioning (Elliptic Envelope)

结果

一类 SVM 在所有算法中表现最好,能够发现高温和低温范围内的异常。

博客的代码可以在这里找到。

参考

[## 如何使用机器学习进行异常检测和状态监控

在这篇文章中,我将介绍机器学习和统计的一些不同的技术和应用…

towardsdatascience.com](/how-to-use-machine-learning-for-anomaly-detection-and-condition-monitoring-6742f82900d7) [## sklearn .协方差. elliptic envelope-sci kit-learn 0 . 21 . 2 文档

如果为真,则计算稳健位置和协方差估计的支持,并且重新计算协方差估计…

scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.covariance.EllipticEnvelope.html) [## Python 中的异常检测技术

DBSCAN、隔离森林、局部异常因子、椭圆包络和一类 SVM

medium.com](https://medium.com/learningdatascience/anomaly-detection-techniques-in-python-50f650c75aaf) [## Scikit-Learn 中的异常检测

所有 AD 的核心是你想为正常点拟合一个生成分布或决策边界,然后…

sdsawtelle.github.io](http://sdsawtelle.github.io/blog/output/week9-anomaly-andrew-ng-machine-learning-with-python.html?source=post_page---------------------------)

利用深度学习对血细胞进行检测和分类(第 2 部分—训练和评估)

原文:https://towardsdatascience.com/detection-and-classification-of-blood-cells-with-deep-learning-part-2-training-and-evaluation-53381dbbc565?source=collection_archive---------18-----------------------

使用 Tensorflow 对象检测 API 处理 BCCD 数据集

训练

我们现在终于为训练做好了准备。

# directory = ...YOUR_DIRECTORY/models/research/object_detection 
# type the following into Anaconda Promptpython train.py --logtostderr --train_dir=training/ --pipeline_config_path=training/faster_rcnn_inception_v2_pets.config

大约 30 秒到 1 分钟后,训练过程应该开始。如果代码运行顺利,您应该会看到全局步数以及显示的每一步的损失。为了更好地监控训练,我们推出了 Tensorboard。

# directory = ...YOUR_DIRECTORY/models/research/object_detection 
# type the following into Anaconda Prompttensorboard --logdir=training

将 http://localhost:6006/ 复制到浏览器中,打开 Tensorboard。我对我的模型进行了大约 30 分钟的训练,但你的训练时间可能会根据你的系统配置而有所不同。

导出推理图

一旦你对训练损失感到满意,你可以在训练窗口中按 Ctrl + C 来中断训练。我们现在将导出推理图,以便可视化结果并对模型进行评估。

# directory = ...YOUR_DIRECTORY/models/research/object_detection 
# type the following into Anaconda Promptpython export_inference_graph.py --input_type image_tensor --pipeline_config_path training/faster_rcnn_inception_v2_pets.config --trained_checkpoint_prefix training/model.ckpt-**YOUR_CHECKPOINT_NUMBER(e.g.2859)** --output_directory inference_graph

应该在…YOUR _ DIRECTORY/models/research/object _ detection/inference _ graph 下创建推理图文件夹。

可视化结果

用 Jupyter 笔记本打开 models/research/object _ detection/文件夹中的object _ detection _ tutorial . ipynb笔记本。为了适应我们的情况,我对笔记本做了一些修改。请随意将编辑过的代码复制到相应的部分。我没有对下面没有讨论的部分做任何修改。

# Importsimport numpy as np
import os
import six.moves.urllib as urllib
import sys
import tarfile
import tensorflow as tf
import zipfilefrom distutils.version import StrictVersion
from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from matplotlib import patches
from PIL import Image# This is needed since the notebook is stored in the object_detection folder.
sys.path.append("..")
from object_detection.utils import ops as utils_opsif StrictVersion(tf.__version__) < StrictVersion('1.12.0'):
  raise ImportError('Please upgrade your TensorFlow installation to v1.12.*.')

注释掉“变量”和“下载模型”部分。

#Load a (frozen) Tensorflow model into memoryPATH_TO_FROZEN_GRAPH = r"...**YOUR_DIRECTORY**\models\research\object_detection\inference_graph\frozen_inference_graph.pb"
detection_graph = tf.Graph()
with detection_graph.as_default():
    od_graph_def = tf.GraphDef()
    with tf.gfile.GFile(PATH_TO_FROZEN_GRAPH, 'rb') as fid:
        serialized_graph = fid.read()
        od_graph_def.ParseFromString(serialized_graph)
        tf.import_graph_def(od_graph_def, name='')

为了显示预测,我们需要对测试图像目录进行更改。我在 images 文件夹中创建了一个名为“test_samples”的单独文件夹,并选择了前 3 个图像(BloodImage_00333 到 00335)来运行测试。

# DetectionPATH_TO_TEST_IMAGES_DIR = r"...**YOUR_DIRECTORY**\models\research\object_detection\images\test_samples"
FILE_NAME = 'BloodImage_00{}.jpg'
FILE_NUMBER = range(333,336)
TEST_IMAGE_PATHS = [ os.path.join(PATH_TO_TEST_IMAGES_DIR, FILE_NAME.format(i)) for i in FILE_NUMBER]

我计划在地面实况旁边显示预测,因此我们需要参考“test_labels.csv”。

import pandas as pd
train = pd.read_csv(r"...**YOUR_DIRECTORY**\models\research\object_detection\images\test_labels.csv")
train.head()

下面的代码将在左边显示真实的图像,在右边显示预测。

for image_path in TEST_IMAGE_PATHS:
    image = Image.open(image_path)
  # the array based representation of the image will be used later in order to prepare the
  # result image with boxes and labels on it.
    image_np = load_image_into_numpy_array(image)
  # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
    image_np_expanded = np.expand_dims(image_np, axis=0)
  # Actual detection.
    output_dict = run_inference_for_single_image(image_np_expanded, detection_graph)
  # Visualization of the results of a detection.
    vis_util.visualize_boxes_and_labels_on_image_array(
        image_np,
        output_dict['detection_boxes'],
        output_dict['detection_classes'],
        output_dict['detection_scores'],
        category_index,
        instance_masks=output_dict.get('detection_masks'),
        use_normalized_coordinates=True,
        line_thickness=5)
    figure, (ax2, ax1) = plt.subplots(1, 2, figsize=(20,18))
# plots prediction
    ax1.set_title("Predictions (" + image_path[-20:] + ")", size=25)
    ax1.imshow(image_np)

# plots ground truth
    original = image
    ax2.set_title("Ground Truth (" + image_path[-20:] + ")", size=25)
    ax2.imshow(original)
    for _,row in train[train.filename == image_path[-20:]].iterrows():
        xmin = row.xmin
        xmax = row.xmax
        ymin = row.ymin
        ymax = row.ymaxwidth = xmax - xmin
        height = ymax - ymin# assign different color to different classes of objects
        if row["class"] == 'RBC':
            edgecolor = 'lawngreen'
            ax2.annotate('RBC', xy=(xmax-40,ymin+20), size=25)
        elif row["class"] == 'WBC':
            edgecolor = 'cyan'
            ax2.annotate('WBC', xy=(xmax-40,ymin+20), size=25)
        elif row["class"] == 'Platelets':
            edgecolor = 'aquamarine'
            ax2.annotate('Platelets', xy=(xmax-40,ymin+20), size=25)# add bounding boxes to the image
        rect = patches.Rectangle((xmin,ymin), width, height, edgecolor = edgecolor, facecolor = 'none', lw=6)
        ax2.add_patch(rect)

    plt.tight_layout()
    plt.show()

如果一切运行正常,您应该看到以下内容:

仅通过视觉检查,该模型仅用 30 分钟的训练时间就表现良好。边界框很紧,它检测到了大部分血细胞。值得注意的是,该模型能够检测大(白细胞)和小(血小板)细胞。在某些情况下,它甚至检测出了未被标记的红细胞。这预示着该模型的可推广性。

评估

由于对预测的肉眼观察似乎令人满意,我们现在将使用 COCO 指标进行正式评估。

首先,我们必须 git clone COCO Python API。

# directory = ...YOUR_DIRECTORY/models/research
# type the following into Anaconda Promptgit clone https://github.com/cocodataset/cocoapi.git

这将下载“coco”文件夹,你应该在你的 _DIRECTORY/models/research 中看到它。

# directory = ...YOUR_DIRECTORY/models/research
# type the following into Anaconda Promptcd coco/PythonAPI

这将把目录更改为 YOUR _ DIRECTORY/models/research/coco/python API。在这个阶段,官方指令要求在 Anaconda 提示符下键入“make”。然而,我无法让它工作,在 github 和 stackoverflow 中搜索给了我解决方法。

首先,你需要按照这里“Jason246”的回答安装 Microsoft Visual C++构建工具:https://stack overflow . com/questions/48541801/Microsoft-Visual-C-14-0-is-required-get-it-with-Microsoft-Visual-C-Build-t

接下来,使用代码编辑器在您的 _ DIRECTORY/models/research/coco/python API 下打开“setup.py”文件,并进行以下更改。

# change thisext_modules = [
    Extension(
        'pycocotools._mask',
        sources=['../common/maskApi.c', 'pycocotools/_mask.pyx'],
        include_dirs = [np.get_include(), '../common'],
        **extra_compile_args=['-Wno-cpp', '-Wno-unused-function', '-std=c99']**,
    )
]# to thisext_modules = [
    Extension(
        'pycocotools._mask',
        sources=['../common/maskApi.c', 'pycocotools/_mask.pyx'],
        include_dirs = [np.get_include(), '../common'],
        **extra_compile_args={'gcc': ['/Qstd=c99']}**,
    )
]

接下来,运行“setup.py”文件。

# directory = ...YOUR_DIRECTORY/models/research/coco/PythonAPI
# type the following into Anaconda Promptpython3 setup.py build_ext --inplace

之后,将您的 _DIRECTORY/models/research/coco/PythonAPI 中的 pycocotools 文件夹复制到您的 _ DIRECTORY/models/research 中。

现在,转到您的 _ DIRECTORY/models/research/object_detection/legacy,将“eval.py”文件复制到“object _ detection”文件夹。我们终于可以运行评估脚本了。

# directory = ...YOUR_DIRECTORY/models/research/object_detection
# type the following into Anaconda Promptpython eval.py --logtostderr --pipeline_config_path=training/faster_rcnn_inception_v2_pets.config --checkpoint_dir=training/ --eval_dir=eval/

这将把评估结果保存到 eval/目录中。就像训练一样,我们可以用 Tensorboard 来可视化评价。

# directory = ...YOUR_DIRECTORY/models/research/object_detection 
# type the following into Anaconda Prompttensorboard --logdir=eval

“eval.py”还将基于 COCO 指标生成一份报告。我的模型的结果如下:

精度(阳性预测值)是真阳性与真阳性+假阳性的比例。回忆(敏感度)是真阳性与真阳性+假阴性的比例。

在宽松交集超过并集(IOU)为 0.5 的情况下, 96.7% 的模型的阳性预测是真阳性。当我们以 0.05 的步长对 IOU 0.5 至 0.95 的 APs 取平均值时,该百分比降低为 64.5% 。值得注意的是,该模型在较小的物体上表现不佳,对于小型和中型物体,AP 分别为 23.4%52.5%

从召回率来看,该模型平均检测到 71.9%的真阳性,对于小物体的性能较差。

总结

总之,我们使用 Tensorflow 目标检测 API 建立了一个模型,以在 BCCD 数据集中定位和分类 3 种类型的血细胞。未来的工作包括增加训练时间,提高小对象的性能,以及将模型扩展到其他数据集。

感谢阅读。

Photo by Sergei Akulich on Unsplash

使用 Pose2Seg 和 PyTorch 的免检测人体实例分割

原文:https://towardsdatascience.com/detection-free-human-instance-segmentation-using-pose2seg-and-pytorch-72f48dc4d23e?source=collection_archive---------10-----------------------

考虑到人类的独特性

Photo by Jezael Melgoza on Unsplash

近年来,由于现实生活应用的高需求,计算机视觉领域中与“人”相关的研究变得越来越活跃,其中之一就是实例分割。

图像实例分割的标准方法是首先执行对象检测,然后从检测包围盒中分割对象。最近,像 Mask R-CNN 这样的深度学习方法联合执行它们。然而,随着与人类相关的任务变得越来越普遍,如人类识别、跟踪等。有人可能想知道为什么“人类”这一类别的独特性没有被考虑进去。

“人类”类别的独特性可以由姿势骨架很好地定义。此外,与使用包围盒相比,人类姿态骨架可以用于更好地区分具有严重遮挡的情况。

Figure 1: Heavily occluded people are better separated using human pose than using bounding-box.

在这篇文章中,我将回顾“pose 2 seg:无检测人体实例分割”,它提出了一种新的基于姿势的人体实例分割框架,该框架基于人体姿势来分离实例。

在这篇文章中,我将介绍两件事:第一,实例分割任务的概述。二、“Pose2Seg”概述。

代码提示:
我们在这里分享代码。包括数据集和训练模型。跟着走!

1.什么是实例分段?

实例分割是一项任务,我们希望在像素级别识别每个对象。这意味着标签是类感知和实例感知的。例如,图 2(d)显示了绵羊 1、绵羊 2 等的单独标记。

实例分段被认为是常见用例中最具挑战性的:

Figure 2. Common computer vision use cases

  • 分类:此图中有一个人。图 2(a)
  • 目标检测:在该图像中的这些位置有 5 只羊。图 2(b)
  • 语义分割:有羊、人、狗像素。图 2(c)
  • 实例分割:在这些位置有 5 只不同的羊、1 个人和 1 只狗。图 2(d)

2.Pose2Seg:无检测人体实例分割

2.1 直觉

Pose2Seg 背后的主要思想是,虽然通用对象实例分割方法工作良好,但大多数都基于强大的对象检测基线。即首先生成大量的建议区域,然后使用非最大抑制(NMS)来移除冗余区域,如图 3 所示。

Figure 3. (Left) Before non-max suppression, (Right) After Before non-max suppression

但是,当同一类别的两个对象有很大的重叠时,NMS 会将其中一个对象视为多余的建议区域,并将其删除。这意味着几乎所有的对象检测方法都不能处理大重叠的情况。

但是,当处理大多数“人类”类别时,它可以由姿势骨架很好地定义。如图 1 所示,人体姿态骨架更适合于区分两个纠缠在一起的人,因为它们可以提供比边界框更清晰的个人信息,如不同身体部位的位置和可见性。

自底向上方法的主要思想是首先检测所有人的每个身体部位的关键点,然后将这些部位分组或连接以形成人体姿态的几个实例,这使得可以分离具有大重叠的两个缠绕的人体实例

2.2 网络结构

总体网络结构如下图 4 所示。网络的输入是存在的所有人体实例的 RGB 图像和人体姿态。首先,使用主干网络提取图像的特征。然后,名为仿射对齐的模块用于根据人体姿态将感兴趣区域对齐到统一的大小(为了一致性)。此外,为每个人体实例生成骨架特征。

现在,RoI 和骨架特征被融合并被传递到称为 S egModule 的分割模块,以产生每个 RoI 的实例分割。最后,对估计矩阵进行仿射对齐操作,对每个实例进行反向对齐,得到最终的分割结果。

网络子模块将在下面的小节中详细描述。

Figure 4. Overview of our network structure. (a) Affine-Align operation. (b) Skeleton features. (c) Structure of SegModule

2.3 仿射对齐操作

仿射对齐操作主要受快速 R-CNN 中呈现的 RoI 汇集和掩模 R-CNN 中的 RoI 对齐的启发。但是,虽然这些根据它们的包围盒来对齐人类,但是仿射对齐用于基于人类姿态来对齐。

为此,最频繁的人体姿态被离线存储,稍后在训练/推断时与每个输入姿态进行比较(参见下面的图 5)。这个想法是为每个估计的姿势选择最佳模板。这是通过估计输入姿态和模板之间的仿射变换矩阵 H 并选择产生最佳分数的一个来实现的。

这里 P_u 表示姿势模板,而 P 表示单人姿势估计。矩阵 H*是为最适合的每姿态模板选择的仿射变换。最后,将产生最佳分数的变换 H* 应用于图像或特征,并将其变换到期望的分辨率。关于仿射对齐操作还有更多细节,请参考论文了解更多细节。

Figure 5. Affine-Align operation

2.4 骨骼特征

Figure 6. Skeleton feature module

图 6 显示了 s keleton 的特征。对于该任务,采用零件亲缘关系字段(PAF)。PAF 的输出是每个骨架的 2 通道矢量场图。PAF 用于表示人类姿势的骨架结构以及身体部位的部位置信度图,以强调身体部位关键点周围的那些区域的重要性。

2.5 秒模块

SegModule 是一个简单的编码器-解码器架构。一个主要的考虑是它的感受野。由于骨架特征是在对齐后引入的,因此 SegModule 需要有足够的感受野,以便不仅完全理解这些人工特征,而且学习它们与基础网络提取的图像特征之间的联系。因此,它是基于对准的 ROI 的分辨率来设计的。

网络从一个 7 × 7、步长为 2 的卷积层开始,其后是几个标准残差单元,以便为感兴趣区域提供足够大的感受野。然后,双线性上采样层用于恢复分辨率,另一个残差单元与 1 × 1 卷积层一起用于预测最终结果。这样一个具有 10 个剩余单元的结构可以实现大约 50 个像素的感受野,对应于 64 × 64 的对准尺寸。单元越少,网络的学习能力越差,单元越多,学习能力的提高越小。

3.实验和结果

Pose2Seg 在两个数据集上进行了评估:(1) OCHuman,这是本文提出的最大的验证数据集,主要针对严重遮挡的人;以及(2) COCOPersons(可可的人称类别),包含日常生活中最常见的场景。

该算法主要与常用的基于检测的实例分割框架 Mask-RCNN 进行比较。

在使用 OCHuman 数据集对遮挡数据的测试中,如表 1 所示,Pose2Seg 框架实现了比 Mask R-CNN 高近 50%的性能。

Table 1. Performance on occlusion. All methods are trained on COCOPersons train split, and tested on OCHuman

在一般情况下的测试中,在 COCOPerson 验证集 Pose2Seg 上的实例分割任务获得了 0.582 AP(平均精度),而 Mask R-CNN 获得了 0.532。见表 2。

Table 2. Performance on general cases.

要从基于边框的框架中更好地理解 Pose2Seg 的优势,请参见下面的图 7。看看“开箱即用”的器官在 Mask R-CNN 中是如何不分段的。

Figure 7. Pose2Seg method’s results vs. Mask R-CNN on occlusion cases. Bounding-boxes are generated using predicted masks for better visualization and comparison.

4.结论

如果你对源代码感兴趣,可以在我的 Pose2Seg GitHub 库中找到。

一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。

在那之前,下一篇文章再见!😄

基于深度学习的混凝土结构表面裂缝检测

原文:https://towardsdatascience.com/detection-of-surface-cracks-in-concrete-structures-using-deep-learning-f8f85cd8ac8b?source=collection_archive---------6-----------------------

用数据做酷事!

Crack in Concrete Building

介绍

表面裂缝的检测是混凝土结构健康监测中的一项重要任务。如果裂缝发展并继续扩展,它们会减少有效的承载表面积,并且随着时间的推移会导致结构的失效。裂纹检测的手动过程费时费力,并且受到检查员主观判断的影响。在高层建筑和桥梁的情况下,人工检查也很难进行。在这篇博客中,我们使用深度学习来建立一个简单但非常准确的裂缝检测模型。此外,我们在真实世界数据上测试该模型,并且看到该模型在检测混凝土和非混凝土结构示例道路中的表面裂缝方面是准确的。代码在我的 Github 的链接上是开源的。

原文全文刊登在我的网站 这里。

数据集

对于这个博客,我们使用公开可用的混凝土裂缝图像数据集。Ozgenel 和 Gonenc 在论文中公开了该数据集。

数据集由 20,000 幅有裂缝的混凝土结构图像和 20,000 幅无裂缝的图像组成。该数据集由 458 幅高分辨率图像(4032x3024 像素)生成。数据集中的每个图像都是 227 x 227 像素的 RGB 图像。一些有裂缝和无裂缝的样本图像如下所示:

Sample images with cracks

Sample images without cracks

可以看到,数据集有各种各样的图像——不同颜色的石板,不同强度和形状的裂缝。

模型构建

针对这个问题,我们用 Pytorch 搭建一个卷积神经网络(CNN)。由于我们的图像数量有限,我们将使用预训练的网络作为起点,并使用图像增强来进一步提高准确性。图像增强允许我们进行变换,如垂直和水平翻转、旋转和亮度变化,从而显著增加样本并帮助模型泛化。

对于以下步骤,请跟随我在 Github 上的代码。

将输入数据混洗并分割成训练和赋值

下载的数据将有两个文件夹,一个用于正极,一个用于负极。我们需要把这个分成 train 和 val。下面的代码片段将为 train 和 val 创建新的文件夹,并将 85%的数据随机放入 train,将 rest 放入 val。

Split into train and val

应用变换

Pytorch 使应用数据转换变得容易,这可以增加训练数据并帮助模型一般化。我选择的变换是随机旋转、随机水平和垂直翻转以及随机颜色抖动。此外,每个通道除以 255,然后归一化。这有助于神经网络训练。

Transforms

预训练模型

我们使用在 ImageNet 上预先训练的 Resnet 50 模型来启动该模型。要了解更多关于 ResNet 模型的信息,请阅读我的博客。如下所示,ResNet50 模型由 5 个阶段组成,每个阶段都有一个卷积和单位块。每个卷积块有 3 个卷积层,每个单位块也有 3 个卷积层。ResNet-50 拥有超过 2300 万个可训练参数。我们将冻结所有这些权重和 2 个更完全连接的层,第一层在输出中有 128 个神经元,第二层在输出中有 2 个神经元,这是最终的预测。

ResNet50 Model

ResNet model layers

如模型摘要所示,该模型具有 2300 万个不可训练参数和 262K 个可训练参数

Model Parameters

我们使用 Adam 作为优化器,对模型进行 6 个时期的训练。

真实图像上的模型训练和预测

我们使用迁移学习,然后在训练数据集上训练模型,同时在验证集上测量损失和准确性。正如下面的损失和准确性数字所示,模型训练非常快。在第一个历元之后,训练准确率为 87%,验证准确率为 97%!。这就是迁移学习的力量。我们的最终模型的验证准确率为 98.4%。

Model Training Stats

在真实世界图像上测试模型

现在最有趣的部分来了。是的,该模型对验证数据起作用,但我们想确保它也对来自互联网的看不见的数据起作用。为了测试这一点,我们随机拍摄了开裂的混凝土结构和路面裂缝的图像。这些图像比我们的训练图像大得多。请记住,该模型是在 227,227 像素的作物上训练的。我们现在将输入图像分成小块,并对其进行预测。如果模型预测有裂缝,我们就把补丁涂成红色(有裂缝),否则就把补丁涂成绿色。下面的代码片段可以做到这一点。

Prediction on crops

该模型在以前从未见过的图像上表现得非常好。如下图所示,该模型能够通过处理图像上的数百个补丁来检测混凝土中非常长的裂缝。

Crack Detection on Concrete. Left-Original Image. Right-Red regions are predictions with crack and green regions are predictions of no crack

此外,我还在路面裂缝上测试了该模型。这个模型不是在路面上训练出来的,但它在挑选路面裂缝方面也做得很好!

Crack Detection on Roads. Left-Original Image. Right-Red regions are predictions with crack and green regions are predictions of no crack

更多真实世界的图像和模型预测在这个项目的 github link 上分享。

结论

这篇博客展示了使用深度学习和开源数据来构建现实世界的应用程序是多么容易。整个工作花了半天时间,并输出了一个实用的解决方案。我希望您亲自尝试这些代码,并在更多真实世界的图像上进行测试。

我对计算机视觉和深度学习充满热情。我有自己的深度学习咨询公司,喜欢研究有趣的问题。我已经帮助许多初创公司部署了基于人工智能的创新解决方案。请到 http://deeplearninganalytics.org/.的来看看我们吧

你也可以在 https://medium.com/@priya.dwivedi的看到我的其他作品

如果你有一个我们可以合作的项目,请通过我的网站或 info@deeplearninganalytics.org 联系我

参考

  • 2018—zgenel,f .,nenç Sorguç,a .“预训练卷积神经网络对建筑物裂缝检测的性能比较”,ISARC 2018,柏林。
  • 关于裂纹检测重要性的好论文—https://www.hindawi.com/journals/ace/2018/3924120/
  • 关于 Pytorch 中图像分类的好博客。博客中使用的几个代码片段来自这里。
  • 另一个关于 Pytorch 中图像分类的好博客。博客中使用的几个代码片段来自这里。

使用 Mann-Whitney U 检验确定两个分布是否显著不同

原文:https://towardsdatascience.com/determine-if-two-distributions-are-significantly-different-using-the-mann-whitney-u-test-1f79aa249ffb?source=collection_archive---------14-----------------------

使用 Python 的速成课程

如果您在日常工作中使用统计学,很可能在某个时候会遇到分布比较问题。比较分布以确定它们是否不同可以带来许多有价值的见解;特别是,如果与数据集相关联的不同属性导致不同的(统计上显著的)结果。

为了更好的说明这个问题,我们来做一个例子。我们将从通过 UCI 机器学习知识库获得的'成人'数据集中提取数据。这个存储库包含来自 1994 年美国人口普查的数据样本,包括个人工资(> $50K,<= 50K)、年龄、教育、婚姻状况、种族和性别等信息。

Snapshot of the UCI data set, uploaded directly into a pandas dataframe.

现在我们有了一些数据,让我们把它形象化。首先,我们使用 matplotlib hist()函数查看美国人口的年龄分布:

根据上面的直方图,大部分样本集中在 30 至 40 岁之间,在 35 岁左右达到高峰,之后开始下降。

但是,当我们根据收入水平对数据进行分组时,年龄分布是如何变化的呢?让我们再次可视化分布,这一次将数据分成> 50K 美元和<=$50K categories:

Age Distribution, subset by salary level (<=$50K, >$50K)

As you can see in the visual above, the distribution changes when we subset the data by salary level. For the population making less than $50K a year, the distribution peaks around 25 years of age. For the population making greater than $50K a year, the peak occurs around 45 years of age. This intuitively makes sense, as people earlier on in their career make less money than those later on, who are more established.

Now that we’ve graphed the different age distributions based on salary, is there a way to statistically prove that the two differ? Yes — using the Mann-Whitney U Test.

So, what does the Mann-Whitney U Test do exactly?

The Mann-Whitney U Test is a null hypothesis test, used to detect differences between two independent data sets. The test is specifically for non-parametric distributions, which do not assume a specific distribution for a set of data. Because of this, the Mann-Whitney U Test can be applied to any distribution, whether it is Gaussian or not.

Example of a non-parametric distribution, which doesn’t follow a standard Gaussian distribution (see line as example). Image courtesy of https://www.statistixl.com/features/nonparametric-tests/ .

Specifically, the null hypothesis of the Mann-Whitney U Test states that the distributions of two data sets are identical. If the null hypothesis is correct, there is a 50 percent chance that an arbitrarily selected value in one distribution is greater than another arbitrarily selected value in the second distribution ( 2 。

与 Mann-Whitney U 检验相关的检验统计量定义为 U,其中 U 是 U1 和 U2 两个值中较小的一个,通过以下方程组( 3 )定义:

其中 R1 指的是第一组的等级总和,而 R2 指的是第二组的等级总和。n1 和 n2 分别指第一组和第二组的样本总体。

有关如何计算 U 的分步说明,请查看以下链接,该链接涵盖非参数测试,可通过波士顿大学公共卫生学院获得:http://SPH web . bumc . bu . edu/otlt/mph-modules/bs/bs 704 _ nonparametric/bs 704 _ nonparametric 4 . html

对数据应用曼-惠特尼 U 检验

对分布应用 Mann-Whitney U 检验很简单,只需使用 scipy.stats 包中的 mannwhitneyu()函数。我们应用代码,比较两种分布,如下所示:

我们收到以下测试输出:

第一个输出,即 U 统计量,在上一节中被定义为 Mann-Whitney U 检验的检验统计量 U。使用双尾测试表解释 U 统计量,该表包含 U 的临界值。为了拒绝α=0.05 的零假设,从测试中获得的 U 必须低于测试表中的 U 临界值。

当两个样本量都很大时,u 往往很大。这就解释了为什么本例中的 u 统计量(61203011.5)如此之大。

第二个 Python 输出是与测试相关联的 p 值。p 值越低,反对零假设的证据越强。根据一般经验,当 p 值低于 0.05 时,可以拒绝零假设。这个具体例子的 p 值非常低,以至于记录为 0,因此我们可以明确拒绝零假设。这一结果从统计学意义上证实了年收入超过 5 万美元的人的年龄分布不同于年收入低于 5 万美元的人的年龄分布。

我的曼-惠特尼 U 检验教程到此结束。本教程的完整 Python 代码可以在下面的 Github repo 中找到:【https://github.com/kperry2215/mann_whitney_comparison

另外,看看我的一些其他数据科学教程:

[## 使用 Python - Tech Rando 中的 AutoML 自动调整和选择 ML 模型

在同一数据集上测试不同的 ML 方法以评估模型性能可能是一项单调乏味的任务。此外…

techrando.com](https://techrando.com/2019/10/21/automate-your-ml-model-tuning-and-selection-a-review-of-different-python-automl-packages/) [## 时间序列中离群点检测的无监督机器学习方法

在这篇文章中,我将介绍一些我最喜欢的检测时间序列数据中异常值的方法。有许多不同的…

techrando.com](https://techrando.com/2019/08/23/unsupervised-machine-learning-approaches-for-outlier-detection-in-time-series/) [## 使用 Python - Tech Rando 进行变化点检测简介

我的很多工作都大量涉及时间序列分析。我使用的一个很棒但不太为人所知的算法是…

techrando.com](https://techrando.com/2019/08/14/a-brief-introduction-to-change-point-detection-using-python/)

来源

  1. https://www.statistixl.com/features/nonparametric-tests/
  2. https://www . graph pad . com/guides/prism/7/statistics/how _ the _ Mann-Whitney _ test _ works . htm?toc=0 &打印窗口
  3. http://SPH web . bumc . bu . edu/otlt/mph-modules/bs/bs 704 _ nonparametric/bs 704 _ nonparametric 4 . html

原载于 2019 年 11 月 21 日 https://techrando.com**的

使用 Reddit 情绪分析确定总统支持率

原文:https://towardsdatascience.com/determining-presidential-approval-rating-using-reddit-sentiment-analysis-7912fdb5fcc7?source=collection_archive---------12-----------------------

NLP 调查 Reddit 的聚合情绪如何预测美国总统的支持率

在过去的一个学期里,我和其他 5 名杜克大学的本科生一起从各种子数据中提取信息,以预测和确定总统的支持率。在 Reddit 上,有人赞美总统,有人厌恶总统。我们的团队量化了这种情绪,计算了平均值,得出了一些有趣的结果。我们的分析只关注总统的支持率,但我们的方法很容易推广到计算任何人、政策或产品的支持率。值得注意的是,我们在这个项目中关注巴拉克·奥巴马总统,因为在他担任总统期间有最多的可用数据。

团队

如前所述,这个问题是由 6 名杜克大学本科生解决的——电气和计算机工程专业的大二学生米兰·巴特、经济学和计算机科学专业的大四学生安德鲁·库夫、计算机科学专业的大三学生 凯瑟琳·达纳 、计算机科学专业的大三学生 梅兰妮·法费尔 、经济学和计算机科学专业的大四学生亚当·斯诺登、生物学和计算机科学专业的大三学生我自己

动机和问题定义

Reddit 已经被广泛用于分享观点和想法。讨论一个主题有特定的论坛;这些被称为子编辑。我们看了 3 个子主题:r/政治r/民主党r/共和党 。正如你可能猜到的,第一个致力于围绕所有政治的讨论。共和党/民主党共和党/共和党都是民主党和共和党成员讨论政策、议题和候选人的论坛。

每个子编辑都有数百万条评论和数千条帖子。我们使用包含这些帖子的数据集进行分析。我们也非常依赖情感分析。情感分析是利用自然语言处理系统地量化书面语言表达的态度。比如那句“最悲惨的事就是在车流中等待。”是否定句。然而,这句话“这是美妙的击败高峰时间的交通和快速回家。”是肯定句。

我们可以对关于总统的帖子进行情感分析,看看用户是否对总统赞不绝口,如果是的话,有多赞。我们在子网站上的帖子的总体情绪和总统的支持率之间建立了联系。

数据源

我们的主要数据源是 2011 年至 2016 年 Reddit 评论 的一个 大型 JSON 对象,其中包括所有公开评论的评论、评分和子编辑。这是一个压缩了 250GB 的海量数据集。我们使用了拉斯姆森报告中的总统支持率数据集,这些数据是由国家调查生成的。

使用 Google BigQuery,我们从提到的三个子条目中提取了所有包含单词“Obama”的评论。我们用一个详尽的正则表达式清除了每个注释,替换了所有非字母数字值。我们按月份和年份汇总了评论。我们的基本对象有 3 个值:发表评论的日期、子编辑和评论本身。

BigQuery 上的查询结果是一个 CSV 文件。我们使用 Python 来访问和分析 CSV 文件中的信息。我们根据评论发表的月份和年份对它们进行了分类。

情感分析

对于我们的情感分析,我们非常依赖于 TextBlob ,这是一个用于处理和分析文本的 Python 库。我们主要使用他们的情感分析方法,该方法返回[-1,1]范围内的一个数字,其中-1 完全是负数,1 完全是正数。有两种主要的情感分析方法——语义方法机器学习方法

语义方法获取句子中各个单词的情感总和(或平均值)。输入句子中的单词被词条化,这意味着它们由一个共同的词根分组。这是因为生气、愤怒、愤然、都指代同一个负面想法。然后将每个单词的情感相加,为句子生成一个值。我们也可以在使用而非反转情绪。“不开心”这个短语可以类似于“心烦”来量化。此外,如果使用像非常非常难以置信这样的修饰语,我们可以更重视的情感。

第二种方法是有监督的 机器学习方法。在机器学习中,监督算法被赋予两个参数:(1)输入和(2)预期输出。该算法然后推断出将输入映射到输出的函数。然后,该函数可用于新的输入,以产生输出。这种方法是典型的分类问题。有兴趣了解更多的,看这里。

分析方法

在我们的方法中,我们对给定月份和年份的所有类别的情绪进行了平均。在 4 年的时间里,这产生了 48 个数据点。然后,我们将这些数据点标准化为实际支持率的范围。我们最小的数据点成了 4 年来最低的支持率。我们最大的变成了最大的。所有其他值以类似方式映射。这可能扭曲了我们的基本数据,但它让我们更清楚地看到趋势和轨迹。

结果

第一个结果来自 r/politics 。我们发现相关系数为 0.495,这表明这两条线是正相关的。然而,我们发现最有趣的趋势。我们发现,在实际支持率适度上升和下降的同时,我们计算出的支持率也呈双曲线上升和下降。鉴于 Reddit 的性质,这一结果是直观的。发帖的人往往观点比较夸张。这导致了更多的两极分化的帖子,更大的情绪值,和更多的双曲线趋势。

在上图中,我们看了一下的支持率。对于共和党人共和党人,我们决定分析支持率的趋势。这是通过计算我们计算值的斜率(一阶导数)来实现的。我们又一次看到了更加夸张和放大的变化。出于与上述类似的原因,这是有意义的。下图显示了共和党/民主党的结果。**

然而,这是而不是共和党/共和党的情况。我们再次关注了支持率的趋势,我们看到了更多停滞不前的结果。实际上,支持率的趋势并没有什么有意义的变化。**我们的团队查看了共和党人/共和党人情绪分析的原始值,发现帖子的聚合几乎总是负面的。我们假设这是党派政治的副产品,在党派政治中,每个政党都强烈批评对方的任何行动或政策。在 subreddits 上尤其如此,因为用户可能更倾向于党派。**

结束语

从网络资源中提取情感已经成为一个有趣的问题,尤其是在政治领域。对于那些感兴趣的人来说,这里是一篇有趣的文章,它使用 Twitter 的情绪分析来观察 2016 年的选举。这种方法代表了一种相对较新的方式来预测公众对从政策到人民的任何事情的反应。对于那些对复制结果或使用我们的代码感兴趣的人,请看这里的。

感谢阅读!

有问题吗?评论?给我发电子邮件到andrew.oliver.medium@gmail.com!

开发人员构建持久产品的技巧

原文:https://towardsdatascience.com/developer-tips-for-building-products-that-last-e2fab8047ad4?source=collection_archive---------17-----------------------

你会感谢未来的自己

Photo by Naveen Raj Dhanapal on Unsplash

当你想到伟大的设计时,你会想到什么?是手艺吗?设计本身的某种优雅?你欣赏设计师还是制作者?

不管你的答案是什么,有一件事是肯定的:你需要接触这个设计来欣赏它。

我们今天欣赏的大部分伟大作品都是为了维护而设计的。例如,想想建于中世纪的欧洲大教堂。几百年后它们并没有崩溃。相反,他们仍然巍然屹立,欢迎游客。

但是,如果他们的建筑师只专注于开发新的想法,很有可能,我们今天就无法访问他们。他们早就被遗忘,埋在尘土里了。

这和软件架构有什么关系?挺多的,真的!

Photo by Danny van Dijk on Unsplash

你为了什么而优化?

让我们停下来回答一下本节标题中的问题:开发软件时,你优化的目的是什么?是开发成本吗?基础设施成本?还是维护费用?

根据我的经验,许多公司倾向于选择前两个选项。维护很少得到优先考虑。这种做法有什么问题?好吧,即使你设法在预算内按时交付产品,很可能在它的生命周期内,它会产生巨大的成本。

规格变更;合规问题出现;当然,还有一些错误——一些在你的应用程序中,一些在你使用的第三方组件中。停机和崩溃也会让你的生活更加艰难。听起来很激烈?嗯,你可以为所有这些灾难做好准备!这篇文章会给你一些提示。

没人喜欢维护

库尔特·冯内古特写道,“人类性格中的另一个缺陷是,每个人都想建造,却没有人想维护。”在软件开发中尤其如此。让软件工作——即准备架构和实现——被视为一项光荣的工作。然而之后的一切——QA、部署、维护、错误修复等等。—不分享荣耀。有时这些任务甚至被认为是“肮脏的”

但是我们越不注重维护,生产系统的改变就越困难,代价也就越大。这些变化几乎肯定是必要的。世界上没有比临时解决方案更长久的了。

我参与了维护一项服务的斗争,这项服务本应上线不超过两个月。距离最初的部署已经一年多了,我们缺少文档、工作部署脚本和一些试用期已过的外部服务。没有人关心他们,因为他们知道这个项目几周后就会失败。但事实并非如此。

浪费的极端案例?不得不对你的团队创建的项目进行逆向工程,因为没有人记得它应该如何工作。请不要让这种事发生。实际上可能是你在做维护工作。让未来的自己更轻松。怎么会?一会儿我给你看。

一些奇怪的技巧使维护变得更容易

不幸的是,没有一个完美的技巧可以让维护变得更容易。你能做的最好的事情就是遵循一些能降低未来成本的最佳实践。

也许软件工程师最头疼的事情是调试。为了找到为什么事情没有像预期的那样工作,你可能需要测试多个假设,并仔细观察算法的流程。

当您有一个调试器连接到您的开发环境,并且您自己控制环境时,这很容易。但是在一个每分钟服务成千上万个客户机的生产系统中,仅仅为了观察而停止执行是不可取的。

Photo by Martin Stoppler on Unsplash

可观察性

确保事情按计划运行的一个流行方法是可观察性。如果你没有听说过这个术语,你可能想读一读 IOD 专家约翰·法赫尔的《那么到底什么是可观测性》。简而言之,它融合了监控、日志记录、跟踪、分析和警报功能。

然而,拥有每一个都是不够的;他们一起工作是很重要的。这样,在任何时间点,你都可以检查事情是否按计划进行,或者是否有火开始了,你还有时间去扑灭。

可观察性有什么了不起的?如果你有,你是第一个知道潜在问题的人,而不是客户。通常,您可以在问题变得具有破坏性之前解决它们。或者在别人注意到之前。

回到我们的大教堂类比:你可以在付费游客注意到之前修好漏水的屋顶。

自动化部署

一旦你弄清楚需要做什么,你也必须发货。手动部署过程存在风险,并且容易出错。您的发布过程的自动化程度越高,就越容易将必要的变更推进到生产系统中,或者在事情出错的情况下回滚它们。这就是持续集成/持续部署(CI/CD)发挥作用的地方。一个好的部署管道将在每次更新时节省您的时间,一个非常好的部署管道将在不导致停机的情况下做到这一点。

在我们的大教堂,这意味着在游客参观时修理漏水的屋顶——不要被打扰!

Photo by Lanju Fotografie on Unsplash

混沌工程

这比前面的技巧更进一步。可观察性侧重于早期发现,CI/CD 侧重于不间断部署,而混沌工程侧重于问题预防。

与我们之前的对策不同,在建筑领域没有简单的类比来解释这一点。相反,它有点像分割的军事基地。一个片段中的爆炸只会损害该特定片段的内容。它不会影响任何其他部分。人们可以在没有被击中的部分继续他们的任务。

更妙的是,混沌工程公开寻求危险并玩弄它们。你可能听说过网飞的猿军。网飞认为,当其基础设施不断受到各种攻击时,每次事件发生时,设计都会变得更加强大。

混沌工程不仅需要各种级别的冗余,还需要巧妙的测试来确保每天都在实践对可能出现的最坏情况的反应。结果呢?由于网飞经常进行这种自我毁灭,到目前为止没有外部威胁能够伤害它。

尝试适合你的方法

在本文中,我已经向您展示了为什么从第一天开始就关注维护非常重要。我还提出了一些解决方案,可以帮助你实现这个目标。但是正如我所提到的,没有一个简单的技巧每次都能奏效。

每个服务都是不同的,有不同的需求和用例。有些可以处理停机,而对其他人来说,这意味着数千美元的收入损失。当与客户讨论工作范围(外部或内部)时,确保计划适当的维护策略。毕竟,如果您的应用程序每个月要处理 100 个请求,开发一个适当的自我修复集群可能有点太多了。

当然,除非你是为了好玩(也是为了学习)。

原载于 2019 年 3 月 7 日【https://www.iamondemand.com

开发者:放弃你的完美主义

原文:https://towardsdatascience.com/developers-drop-your-perfectionism-f5792c29cf5e?source=collection_archive---------20-----------------------

完成比完美更好

Photo by Ethan Hu on Unsplash

人们可以在 IT 业人士和音乐家或其他艺术家之间找到一些相似之处。保罗·格拉厄姆在他的名著 黑客&画家中提到了其中一些。例如,两个群体都从(看似)无中创造出一些东西;我们在创作中留下自己个性的痕迹;而我们往往追求完美主义。

做美术的和做代码的区别主要在于我们开发的产品和我们创造的受众。一部音乐作品或一幅画最有价值的是它的美学价值。然而,IT 专业人士通常在商业环境中工作,在那里,为了让你的艺术达到“完美”而尽可能长时间地工作是一种奢侈。我们经常有严格的期限和预算要遵守。此外,我们在团队中工作。为了方便协作,我们需要走一些捷径。

然而,我认识的许多工程师都成了完美主义的牺牲品。我们希望我们创造的美丽产品和我们在开发过程中做出的明智选择能被人们记住。但是完美主义经常导致拖延,更糟糕的是,瘫痪。为了在市场中生存,我们需要意识到我们的完美主义倾向,并考虑采取不同方法的好处。

一路黑客

你知道什么是黑客吧?不,不是那个戴着酷酷的墨镜,看着随机字符在他的显示器上弹出,最后组合成一个密码,允许访问成千上万个银行账户的人。这就是好莱坞。真正的黑客文化围绕着寻找向客户提供有意义的体验的最简单可行的方法。它包含了各种各样的想法,比如自己动手的方法、懒惰或者创新思维。

这种极简主义可以以各种方式表现出来:最小的代码库,最低的预算,或者最快的上市时间。最小代码库的最好例子是 T2 Perl golf T3。高尔夫球手们相互竞争,以便给出最短的 Perl 脚本来产生期望的结果。最低预算通常意味着以非传统的方式重新利用现有的产品和解决方案。你的汽车音响坏了?你可以尝试修理它,更换它,或者简单地在咖啡杯里安装一个备用的蓝牙扬声器。最后,最快的上市时间意味着利用足够的“胶水”重新利用现有资源,以创造对潜在客户有吸引力的附加值。(拿一个干包来说,把内表面弄得凹凸不平,并在上面加一个透视窗。你得到了什么?当然是一台便携式洗衣机!)

巨大的影响带来巨大的进步

黑客的方法通常是完美主义的反面。黑客的目标是只投入向公众展示结果所需的工作。最终产品看起来漂亮吗?很少。会一直有效吗?不。但是它不需要看起来很漂亮,也不需要每次都有效。第一次迭代只是为了检查市场的反应。它也被称为最小可行产品(简称 MVP)。你知道卡尔·本茨的专利汽车吗?它可能看起来不像那个时代的一些马车那么复杂,但它确实做到了!对这个想法的进一步改进导致了今天汽车的豪华和舒适。

你可以在其他行业观察到类似的模式。它不仅仅局限于开发原型。想象一下构建一个 web 应用程序。你可以做出市场上最漂亮的 web 应用程序,但这需要一些时间。与此同时,你可能会错过最后期限,然后你的客户会拒绝付款。情况不太妙,对吧?

相反,想象你自己快速勾画出最基本的用户交互,实现逻辑,并向你的客户展示简单但有效的 MVP。她可能不喜欢粗糙的界面,但由于产品已经达到了预期的效果,你可以提议多花一点时间和预算让它变得更漂亮(甚至可能导致你或你的公司得到更高的报酬)。)结果可能会也可能不会达到你对完美的定义,但这次有积极的结果。你得到了报酬,你按时交货,你获得了经验,这些经验可能会帮助你在下一次尝试你的巨著时发挥得更大。

不要埋没自己的理想

你可能认为阅读上面的内容,我认为收入比美学更重要。但这不是真的。和我认识的大多数人一样,我为自己的工作感到自豪。我希望我所有的作品都尽可能的漂亮。我花时间自学,努力提高自己的技能,希望这能反映在我创造的产品中。是的,和你们中的一些人一样,我仍然是完美主义和拖延症的牺牲品。

但是当你意识到自己的完美主义倾向时,你可以选择不这样做。你不必每次都选择完美主义路线。在某些情况下,极简主义方法实际上可能是更好的选择。重新思考你现在面临的问题。然后,问问你自己,一个黑客方法是否可以帮助你前进,而不会在你自己的理想上妥协太多。

如果你喜欢我创造的考虑订阅 Bit 更好。这是一个社区时事通讯,推荐书籍、文章、工具,有时还有音乐。

原载于 2018 年 4 月 19 日https://www.iamondemand.com

在 Tensorflow 2.0 中开发 DCGAN 模型

原文:https://towardsdatascience.com/developing-a-dcgan-model-in-tensorflow-2-0-396bc1a101b2?source=collection_archive---------6-----------------------

介绍

2019 年 3 月初,TensorFlow 2.0 发布,我们决定基于 Taehoon Kim 的 DCGAN 实现创建一个图像生成器。下面是如何在 TensorFlow 2.0 中开发 DCGAN 模型的教程。

“为了避免 D(鉴别器)网络的快速收敛,G(生成器)网络每更新一次 D 网络就更新两次,与原论文不同。”

—金泰勋

先决条件

  • Jupyter 笔记本
  • 张量流 2.0
  • 访问高性能 GPU

DCGAN 架构

下图显示了 DCGAN 论文中引用的生成器。本质上,该网络接收一个 100x1 噪声矢量,标记为 100z ,并将其映射到 64x64x3 的 G(Z)输出。

100 x 1→1024 x 4 x 4→512 x 8 x 8→256 x 16 x 16→128 x 32 x 32→64 x 64 x 3

第一层通过在每一步投影和整形来扩展随机噪声

Source: carpedm20

大步

跨距指定了卷积沿高度和宽度的“步数”。这里有一个动画示例:

An example of strides

输入噪声

generator = make_generator_model()noise = tf.random.normal([1,100]) # shape is 1, 100
generated_image = generator(noise, training = False)plt.imshow(generated_image[0, :, :, 0], cmap =”gist_rainbow”)

致密层

在 Keras 中,您可以创建层来开发模型。模型通常是层的网络,其中最常见的类型是层的堆叠

将密集连接的图层添加到模型将接受 shape (,100)的输入数组。第一层之后数据的形状将为(,441024)。在这种情况下,由于自动形状推断

批处理标准化功能类似于网络每一层的预处理,您不需要指定向前移动的输入的大小。

ReLU 对于所有正值都是线性的,对于所有负值都设置为零。泄漏 ReLU 对于负值具有较小的斜率,而不是完全为零。

例如,当 x < 0

def **make_generator_model**():

 model = tf.keras.Sequential()

 model.add(layers.Dense(4*4*1024, use_bias = False, input_shape = (100,)))

 model.add(layers.BatchNormalization())

 model.add(layers.LeakyReLU())

First Layer

The generator uses a transposed convolutional layer (upsampling) to produce an image from seed (random noise).

  • 512 是输出空间的维度时,泄漏 ReLU 可以具有 y = 0.01x
  • (5,5) 指定 2D 卷积窗口的高度和宽度
  • 步幅= (2,2)
model.add(layers.Conv2DTranspose(512, (5, 5), strides = (2,2), padding = “same”, use_bias = False))

assert model.output_shape == (None, 8, 8, 512)
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())

第二层

生成器使用转置卷积层(上采样)从前一层生成图像。

  • 256 是输出空间的维数
  • (5,5) 指定 2D 卷积窗口的高度和宽度
  • 步幅= (2,2)
model.add(layers.Conv2DTranspose(256, (5,5), strides = (2,2), padding = “same”, use_bias = False))assert model.output_shape == (None, 16, 16, 256)
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())

第三层

生成器使用转置卷积层(上采样)从前一层生成图像。

  • 128 是输出空间的维数
  • (5,5) 指定 2D 卷积窗口的高度和宽度
  • 步幅= (2,2)
model.add(layers.Conv2DTranspose(128, (5,5), strides = (2,2), padding = “same”, use_bias = False))assert model.output_shape == (None, 32, 32, 128)
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())

最后一层

生成器使用转置卷积层(上采样)从前一层生成图像。

  • 64 是输出空间的维数
  • (5,5) 指定 2D 卷积窗口的高度和宽度
  • 步幅= (2,2) 指定卷积沿高度和宽度的步幅
model.add(layers.Conv2DTranspose(3, (5,5), strides = (2,2), padding = “same”, use_bias = False, activation = “tanh”))assert model.output_shape == (None, 64, 64, 3)
 return model

价值函数

发电机的损耗量化了它欺骗鉴别器的能力。直观地说,如果生成器运行良好,鉴别器会将假图像分类为真实图像(或 1)。

这里,我们将把鉴别器对生成的图像的决定与 1 的数组进行比较。

def **generator_loss**(fake_output):
 return cross_entropy(tf.ones_like(fake_output), fake_output)

【计算机】优化程序

鉴别器和生成器优化器是不同的,因为我们将分别训练两个网络。Adam 优化算法是随机梯度下降的扩展。

随机梯度下降为所有权重更新保持单一学习率(称为 alpha ),而学习率在训练期间不变。
为每个网络权重(参数)保持一个学习速率,并随着学习的展开而调整。

generator_optimizer = tf.keras.optimizers.Adam(1e-4)
discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)

结果— MNIST

首先,我们在 MNIST 数据集(28 x 28 灰度图像)上使用 3 个反卷积层来训练我们的 DCGAN 模型,这产生了更清晰的渲染,如下所示:

结果— CelebA

使用在 CelebA 数据集(25,600 / 202,599 张图像)的子集上训练的具有 4 个 DC 层的 DCGAN 模型,我们能够生成运行 100 个时期的类似人脸的图像。

工具/资源

纸张空间

  • TensorFlow 1.5 — GPU — Py3 — P5000
  • TensorFlow 2.0 — GPU — Py3 — P5000
  • tensor flow 2.0—GPU—Py3—Tesla V100

MNIST 数据集

  • 60,000 张图片
  • 128 x 128

CelebA 数据集

  • 202,599 张图片
  • 从 218 x 178 转换为 64 x 64

挑战

  • 了解使用 Tensorflow 创建的 GAN 模型
  • 利用 Tensorflow 2.0 开发 DCGAN 模型
  • 将数据集图像从 218 x 178 调整/裁剪为 64 x 64
  • 训练新模型时 Jupyter 笔记本出现内存泄漏
  • 与 TensorFlow 1.3 和 2.0 不兼容
  • 12 小时后纸张空间自动关闭

未来的工作

  • 将模型迁移到可以使用 CelebA 数据集完整计算 100 个历元的环境中
  • 调整模型架构以生成更好的图像
  • 开发一种解决方案来更有效地调整图像大小

[## skywall34/BabyGan

带 DCGAN 的图像发生器。在 GitHub 上创建一个帐户,为 skywall34/BabyGan 开发做贡献。

github.com](https://github.com/skywall34/BabyGan)

参考

没有互联网的伟大人们,我们不可能完成这个项目。请为您的下一个数据科学项目查阅以下资源:

  • 深度卷积生成对抗网络的无监督表示学习——https://arxiv.org/abs/1511.06434
  • 使用生成模型的压缩感知——【https://arxiv.org/pdf/1703.03208.pdf
  • 在 TensorFlow 中使用深度学习的图像完成—http://bamos.github.io/2016/08/09/deep-completion/

从头开始开发音乐推荐系统

原文:https://towardsdatascience.com/developing-a-music-recommendation-system-from-scratch-91d92b47a47f?source=collection_archive---------23-----------------------

概观

新学期已经开始了,我的新课程也开始了。我特别兴奋,因为这学期我可以从头到尾开发自己的项目。

你可能知道,我不久前开始了我的机器学习之旅,所以这是在该领域获得一些实际动手经验的绝佳机会。我选择从零开始开发自己的音乐推荐系统。

在这篇博文中,我将简单介绍一下我的想法,到目前为止我所做的事情以及一些目标。

在接下来的几周和几个月里,我会定期发布我正在研究的主题,也会发布一些关于如何做事的教程。

TL;大卫:如果你只是想看看回购协议,它在 GitHub 上是开源的。正在进行的工作

[## Hyferion/SpotifyRec

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/Hyferion/SpotifyRec)

这个想法

主要原理非常简单。我想开发一个机器学习模型,可以根据我之前的喜好简单的分类我是喜欢一首歌还是不喜欢一首歌。此外,我还添加了该模型可能具有的一些其他功能。

  • 后处理播放列表,这意味着删除我肯定不喜欢的歌曲。
  • 创建推荐的播放列表,类似于“Spotify Discover”
  • 探索新的流派和国家。这意味着搜索你通常喜欢的相似音乐,但是例如来自另一个地理区域的音乐

这是怎么回事?我使用一种叫做基于内容过滤的方法。基本上,我从歌曲的基本成分和特征(速度、可跳舞性、声音)来看歌曲,并让我的机器学习模型来决定这首歌是否符合我以前喜欢的歌曲。

到目前为止我所做的

创建了一个数据集。我创建了一个数据集,目前包含大约 500 首歌曲,分为两类(“喜欢的”、“不喜欢的”)。我在分类应用程序的帮助下做到了这一点,你可以在这里了解更多信息:

[## 机器学习:让二进制注释不那么无聊

标注数据集的新方法

towardsdatascience.com](/machine-learning-making-binary-annotations-a-little-less-boring-51537497af3b)

编写脚本从 Spotify API 获取数据。幸运的是,Spotify 为每首歌提供了我们需要的所有参数的 API(速度、可跳舞性等)。).我创建了不同的脚本来获取这些数据,并将其集成到我现有的数据集中。

已清理数据集。首先,我定义了相关参数,准备了我的数据集。在那之后,我不得不清理和准备它。这意味着打乱数据,分成测试集和训练集。此外,我不得不欠采样我的数据集,以平衡类。

玩转不同算法。有很多算法可供选择(如随机森林、SVC、SGD)。以及超参数调谐。

分析比较结果。最后,我弄明白了结果。计算不同的指标,如准确度、精确度和召回率。此外,一个混乱矩阵,看看我的猜测是正确的是非常有帮助的。

接下来会发生什么

还有很多事情要做。目前面临的主要挑战之一是获得一个包含 Spotify 上 3000 万首歌曲的可搜索数据库。这通常需要建议新的标题,但特别是发现新的流派。

当然,我也在想办法改进我现在的模式。目前,我正在探索以下选择:

  • 添加更多数据。例如,从欠采样到过采样或收集更多数据。
  • 功能工程,创造额外的功能或更好地选择功能。
  • 尝试不同的算法。尝试深度神经网络,例如 Tensorflow,看看我是否能获得更好的结果。
  • 调整超参数

结论

在这篇文章中,我想告诉你一些我正在做的项目。下一篇文章将更详细地介绍如何实现不同的步骤。

通过矩阵分解开发一个规范的推荐系统

原文:https://towardsdatascience.com/developing-a-prescriptive-recommender-system-through-matrix-factorization-8b0c69cce611?source=collection_archive---------16-----------------------

作者——拉温德拉·舒克拉(人工智能/人工授精从业者)

摘要— 矩阵分解是一种非常强大的算法,在多个行业中有许多有价值的用例。矩阵分解的一些众所周知的应用是——网飞 100 万美元的电影推荐奖和亚马逊在线应用(非常精炼的版本),用于向各种读者推荐书籍。虽然这是一种非常流行的方法,但它有一些局限性。我们在本文中的重点是了解潜在的因素,以及如何使其更具规范性。当集合中的产品已经被少数用户评价或者每个用户已经评价了少数产品时,该算法工作得很好。然而,如果我们在集合中包括没有被任何用户评级的新产品或者集合中对产品的偏好未知的新用户,那么将很难为未评级的产品和新用户创建推荐。基于关键特征将产品的潜在特征和用户偏好相关联是一个挑战。下面的文章提出了解释与产品和用户特征相关的潜在因素的挑战。一旦我们对产品和用户特性有了清晰的认识——我们就可以走向规定性的旅程。这将有助于设计具有更受欢迎功能的未来产品,或为某一特定产品找到市场。

背景— 对于基本术语和背景的理解,我一般会引用维基百科。

矩阵分解是推荐系统中使用的一类协同过滤算法。矩阵分解算法通过将用户-项目交互矩阵分解成两个低维度矩形矩阵的乘积来工作。

https://en . Wikipedia . org/wiki/Matrix _ factorization _(recommender _ systems)

我们总是需要将身边的两个实体联系起来。想想各种场景——病人对疾病,用户对产品,男人对女人,用户对电影偏好,求职者对空缺职位。我们可以将这个概念扩展到日常生活中的许多其他场景,并找到相关性。当我们试图寻找两个实体之间的相关性时,矩阵分解非常方便。

矩阵分解的使用案例-

市场战略

交叉销售和追加销售

计算产品倾向和客户倾向

推荐引擎/个性化

推出新产品

了解客户 360

求职网站的筛选和推荐

婚姻或约会网站中的过滤和推荐

上面的场景只是几个例子,这个概念是非常通用的,并且有广泛的使用范围。

创新使用 —事实上,在我们之前的一个项目中,我们使用矩阵分解来填充数据集中缺失的值。这个练习是为了计算健康分数(一个非常类似于信用分数的概念——健康分数越高表示健康状况越好)。假设我们缺少一个患者(P1)的 A1C 读数,我们可以将其他具有类似特征(年龄、性别、身体质量指数、人口统计学、血压、胆固醇、生活方式等)的患者与患者 P1 相关联,并相应地估计 P1 的 A1C 读数。

机器学习基础——矩阵和向量的使用

在我们深入研究矩阵分解和如何解释潜在因素之前,让我们先了解一些机器学习的基础知识。

机器学习是基于数学的,它涉及基于梯度下降(【https://en.wikipedia.org/wiki/Gradient_descent】)的迭代优化,以最小化预测中的误差。存储在数据库中的数据不能作为输入传递给算法,它需要用矩阵来表示。矩阵是不同向量的组合,在定义数学运算时很有用。

用户可能具有以下特征——用户 id、用户名、地址、年龄、性别、收入、教育、对产品特征的偏好、用户类型(学生、工人、IT 工人、销售人员)

类似地,我们可以根据患者的生物特征来定义他/她的基本特征。

像笔记本电脑这样的产品将具有诸如触摸屏、RAM、CPU、品牌、颜色、成本(范围)等特征。像一本书这样的产品将具有诸如作者、主题、时期写作、流派、诗歌与散文、小说与非小说、长篇与短篇、精装与软装、纸质书与电子书、技术书籍等特征

但是,我们不能像在机器学习算法中那样使用上述数据。数据需要以向量和矩阵的形式排列,以便我们在数学运算中可以将它们作为矩阵传递。

用数学术语表示实体的实例— 让我们看看如何用关键特征在 N 维中表示患者

患者可能具有以下主要特征(样本)–

患者 id —这是数据库中有用的唯一标识符。然而,机器学习和算法基于关键特征工作是不相关的。ID 只是数据库系统中的一个标识符。

姓名—类似于患者 id,在 ML 中没有意义

其他人口统计信息(种族、民族、婚姻状况、收入、教育和就业)

年龄—0 到 120 岁之间

性别——男性或女性

位置(州、国家)

生物计量读数(血压—收缩压(范围—0–200,舒张压—0–200),血糖 0–400,A1C(0–10),胆固醇(0–400),吸烟—是或否,慢性病—是或否,共病—是或否)

它可以有更多的特性,但是上面的细节对于我们的讨论来说已经足够了。

Epic 系统数据库中的患者记录-

患者的实例(记录)将存储在常规数据库中,如下所示-

A patient record in regular database

在 N 维中将患者表示为向量(P ),以便我们将其作为 ML 算法中的输入——

patient record with numeric values only

我们需要将所有文本数据转换成数字,并使其有意义,以便可以在计算中使用。有一种特殊的方法来扩展分类变量(例如,性别、州、共病等)。这个过程被称为 Onehotencoder。在数据预处理中还有许多其他活动,但是我们在这里不涉及这些细节(比如在调用 ML 算法之前归一化所有的值、清除丢失的数据等)。

患者实例的上述表示被称为 P 向量。我们组合患者向量的所有实例来创建患者矩阵 p。

向量乘法是什么意思——

将一个已知矩阵(评分矩阵)分解成两个未知矩阵(用户特征和产品特征)是矩阵分解的关键。让我们来理解两个矩阵(用户矩阵和乘积矩阵)相乘的意义是什么

A = a1.i + a2.j + a3.k —三维向量 A(假设—这是用户特征向量)

B = b1.i + b2.j + b3.k —三维向量 B(假设这是产品特征向量)

A x B = a1 . B1+a2 . B2+a3 . B3—A 和 B 向量的乘积

假设 I 代表安全性,j 代表家用车辆,k 代表产品和用户向量的性能系数。对于喜欢具有良好安全特性的高性能家用车辆的用户来说,( AxB)的值会更高。对于喜欢跑车且维护成本较高的用户来说,相同车辆的 AxB 值较低。我们可以清楚地看到,较高的 AxB 值将表明用户 A 对产品 b 的亲和力更好。让我们举个例子来理解——两个向量相乘的意义是什么。

尼鲁喜欢经典的动作片,由黑泽明执导,有很好的剧本、剪辑和背景音乐。她不喜欢恐怖、喜剧、悬疑或故事情节糟糕的电影。

User vector — Neeru — P1

Product vector Q1

Product vector — Q2

如果我们将两个向量相乘

P1(用户的 Neeru 实例)x Q1(七武士—产品实例)=(. 8x 1+. 1x 1.2+. 3x 5+. 9x 8+1x1+. 4x 0+. 4x 8+. 2x 2+. 7x 1)= 3.75

P1(用户的 Neeru 实例)x Q2(布莱尔女巫-产品的实例)=(. 8x . 2+. 1x . 8+. 3x . 3+. 9x . 4+1x 0+. 4x . 2+. 4x . 6+. 2x . 6+. 7x 0)= 1.13

这清楚地表明,比起布莱尔女巫,尼鲁更喜欢看七武士。

解读潜在因素-

矩阵分解基于下面的等式

R = P x QT

r 是不同用户对产品评级的矩阵

p 是用户矩阵

q 是乘积矩阵

QT 是矩阵 Q 的转置

我们没有产品和用户功能的细节。我们只有用户对各种产品的偏好(评分)(来自历史数据)。基本方法是—从假设产品和用户矩阵的某些系数开始,导出评级的预测值,找出预测值与实际值之间的差异作为误差,对误差求和,计算梯度以改变系数值,并再次重新计算预测值和误差。不断迭代,直到收敛到某个最小误差。所有这些都可以用 Python 中的 50 行代码来完成。

同样,上述带有量纲的方程可以写成-

R [M,N] = P[M,K] x QT[K,N]

R[i,j] —来自用户 i (Pi)的额定产品 j (Qj)的值

Q [i][1,2,3,…。k] =具有 k 个关键特征的乘积 Qi 向量
P[j][1,2,3,…。k] =由 k 个关键特征定义的用户 Pi 向量

我们假设在上面的等式中有 K 个潜在特征。

潜伏因素有哪些?

在矩阵分解中,我们的工作是将两个实体(例如产品和用户)。每个产品都有一些关键特征,每个喜欢该产品的用户都将取决于他/她对这些关键特征的偏好。

这些相关性中的许多可以通过矩阵分解来建立。当我第一次读到矩阵分解以及如何使用梯度下降来实现预测时,我很兴奋。用 python 写 50-60 行基本代码就能完成这么多事情。当我开始思考——如何让它更规范时,兴奋是短暂的。除非我们找到一种实用的方法来解释和扩展数学美,否则数学美就会消失。

我们做一个基本假设,两个实体通过 K 个潜在因素相关联。k 只是一个数字。我们不知道这些 K 因子代表什么。这就是为什么他们也被称为潜伏。这在使矩阵分解更规范方面造成了关键障碍。

我尝试了不同的组合来推导一些潜在因素的含义。其中之一是——不断增加 K 值,看看在某个数字之后,K 值的增加是否不会对用户和产品系数产生影响。用户系数和产品系数收敛,进一步增加 K 将无关紧要。它没有成功。

事实上,当我增加 K 值并尝试多次积分时,我开始得到矩阵 P 和 Q 系数的不同组合。

破译矩阵分解-

让我们用一个例子来分析一下细节。

r 矩阵—8 名用户对 4 种不同产品的评分。

Rating Matrix — R

让我们假设——我们有四个潜在因素。换句话说,产品有 4 个主要特征,用户会根据这些关键特征对产品产生偏好。

R [8x4] = P[8x4] X Q[4x4]

P(用户矩阵)——扩展为四个潜在特征

Users Matrix — P

QT(乘积矩阵转置— Q) —扩展为四个潜在因子

Product Matrix Transpose — QT

这是一个纯数学练习,其中我们知道 matrix-R 的值(并非所有评级都是已知的)。我们首先用随机值初始化用户矩阵和乘积矩阵。

用户 u4 对产品 P2 (u4P2)的评级是两个向量的乘积——用户(U4)和产品(p2)。

u4p 2 = u41 . p21+u42 . p22+u43 . p23+u44 . p24

如果我们注意到上面的等式——特定用户对任何产品的偏好与两个向量的不同维度的系数之和成正比。

让我们再来看看矩阵分解方程

R = P x Q

这里 P 和 Q 都是未知的。只有几个 R(用户评价产品)值的系数是已知的。

当 P 和 Q 都是变量时,R 有多个解对(P,Q)。

u4p 2 = u41 . p21+u42 . p22+u43 . p23+u44 . p24

原始矩阵 R —

Original Rating Matrix — R

高亮显示的单元格是没有被用户评级的单元格。它们变成了测试细胞。

不发光的单元格是我们已经知道产品等级的地方。

我尝试了多次迭代求解 P 和 Q 矩阵的值,每次都得到不同的结果 Q。

迭代 1:

Predicted rating Matrix — X after iteration-1

Users Matrix — P after iteration 1

Product Matrix Q after iteration 1

X —用户产品评级的预测值(R 是原始矩阵)

P —分解后的用户矩阵

Q —分解后的乘积矩阵

迭代 2:迭代 2 的输出

Matrices after iteration 2

迭代 3:迭代 3 的输出

Matrices after iteration 3

迭代 4:迭代 4 的输出

Matrices after iteration 4

简而言之,我们有 8x4 + 4x4 = 48 个变量,但不到 32 个方程。很明显,我们会有多对 P 和 Q 矩阵。

除了解释 k1,k2,k3,k4 意味着什么之外,这是为了得到 P 和 Q 的一致值而进行的斗争?除非我们在获得 P 和 Q 的收敛值时具有一致性,否则我们对未评级产品的预测将继续波动。

当前模型的问题—

去因子分析有助于我们理解——我们如何预测尚未评价/或使用某些产品的其他用户的偏好。基于预测的偏好,我们可以决定更好销售的营销策略(交叉销售和追加销售)。

1.潜在因素的数量是未知的

2.每次迭代都会给出不同的用户矩阵和产品矩阵——这意味着预测不一致

3.潜在的因素是未知的——这就产生了一个使模型具有规定性的问题。这意味着——假设我们要推出一款新产品,但我们不确定——我们应该更多地关注哪些功能以获得更好的销售。

解决方案-

当我们只有一个等式 R = P x Q 时,解决这个问题的一种方法是固定变量 Q(产品特性),这样我们就只需要处理一个变量(P —用户特性)。

凭经验思考——这是个不错的选择。如果我们在销售某些产品,我们最好知道产品的特性是什么,以及我们有多少关键特性。

让我们理解固定 K 的值和矩阵 Q 将如何帮助获得 P 的一致结果和 r 值的收敛预测。

当我们分析上述等式时

产品等级(u4p 2)= u41 . p21+u42 . p22+u43 . p23+u44 . p24

用户特征向量— u4 = u41.i + u42.j + u43.k + u44.t

产品特征向量— p2 = p21.i + p22.j + p23.k + p24.t

其中 I,j,k,t 是向量的四个不同维度。每个维度对应一个独特的特征。

当我们将 Q 值固定为–

Product Matrix Q (fixed one)

我们开始在 P 值和等级(X)的预测值以及用户矩阵-P-中获得一致性

迭代 1:

Rating Matrix X and User Matrix P after iteration 1

用户矩阵(P)开始收敛。请查看迭代 2、3 和 4 的值。

迭代 2:

Matrices after iteration 2

迭代 3:

Matrices after iteration 3

迭代 4:

Matrices after iteration 4

基于上述数据,我们可以确定代表用户偏好的用户特征向量。

现在关键问题仍然是——如何修正产品矩阵?

选项 1:

特征的数量——K——必须根据对产品特征的理解来估计。

产品矩阵的系数值—范围从 0 到 1 (0 表示功能对产品没有任何影响,1 表示功能对产品影响最大)。

一旦我们知道了什么特性(k1,k2,…Kn)意味着,我们可以根据它们对产品质量的贡献来分配从 0 到 1 的系数。

业务 SME 和技术团队都需要一起工作来确定初始关键特征和确定系数的权重。

选项 2:

特征的数量——K——必须根据对产品特征的理解来估计(类似于选项 1)。

现在分解矩阵 R,并在几次迭代中确定矩阵 P 和 Q。根据 Q 值的两次迭代和对产品特性的理解做出最佳猜测。

固定 Q 的值并求解矩阵 P。一旦矩阵 Q 固定,矩阵 P 的系数将收敛。

事实上,确定 K 值和乘积系数是很好的方法。这样,我们可以计算用户矩阵的等效系数。

比方说,我们决定根据 5 个关键特征对产品进行分类,并确定每个系数在整体产品偏好中的重要性,这将有助于确定用户矩阵中的相关特征,其中哪个系数对应于哪个特征也是已知的。

关键步骤总结—

1.假设 K —基于对产品特性的理解

2.从 P 和 Q 系数的随机值开始

3.迭代并确定第一组 P 和 Q 值

4.查看 Q 系数—尝试将 Q 与产品特性联系起来(产品/项目特性应该是已知的)

5.固定 Q 值和关键特征数量(K —潜在因素)

6.调整 Q 矩阵(产品特性)

7.使用 Q 的调整值来确定 P 的值

需要牢记的关键事项—

我忽略了用户对产品评分的偏见(只是为了让计算更简单)。

产品特征与个体维度相对应。尺寸相互垂直。特征向量中不应该有共线性。

当我们确定产品特征时,假设 k1、k2、k3、k4…我们可以根据系数的相对值解释不同潜在因素的初始含义(较高的主导特征将具有较高的系数)。

用户特征将对应于同一组产品特征。假设如果产品 k1 代表产品安全特征,用户 k1 将指示用户对安全的偏好。

结论—

最近我在看谷歌 CEO(桑德尔·皮帅)在谷歌 2018 I/O 上的演讲,他谈到了基于眼睛扫描图像预测心血管事件。

许多过去事件(病史、环境、习惯、药物等)的影响将会影响许多其他事件(健康状况——心血管事件)和眼睛内部。

过去发生了一系列事件。现在,他们正在影响心脏骤停的几率以及眼睛内部。

通过测量眼部扫描的变化/情况,我们可以关联心脏骤停的可能性。

Understanding common factors which impact heart and Eyes conditions

类似地,我们可以找到许多其他用途——疾病相关性与不同位置的水质。

上述关系,我们也可以根据深度学习中的神经网络层进行映射。

实体 1 (E) —不同类型的扫描眼睛图像

实体 2 (H) —不同类型的心脏疾病

潜在因素——不同组的活动、既往病史、人口统计学等是特征向量。它们在深度学习模型中充当输入。我们可以收集病人的各种数据记录——眼睛扫描和心脏状况。使用矩阵分解——我们可以确定两个实体之间的相关性。

Representation in neural network term

我最近了解到——前列腺癌在东部非常普遍。我们只需要收集不同地点与该地区流行疾病的数据,了解可能的潜在因素,并深入处方医学。这在人口健康管理(ACO)的背景下非常有用。

同样,我们可以研究水质、空气质量、工业存在、污染水平、土壤质量对不同地理区域各种疾病的影响。

受众— 实施数据科学项目需要业务团队和技术团队(数据工程和数据科学团队)的协作。数据科学组开发算法来为数据建模并评估性能,而业务组帮助理解产品功能并收集建模所需的相关数据。

在初始化用户和产品矩阵时,利用业务 SME 的经验来理解产品特性的相关性、将它们放入正确的序列、分配正确的权重将是至关重要的。因此,两个团队需要紧密合作来创建健壮的/规范的系统。

参考文献—

【https://www.youtube.com/watch?v=MSpF84kevyU

http://www . quux labs . com/blog/2010/09/matrix-factorization-a-simple-tutorial-and-implementation-in-python/

https://en . Wikipedia . org/wiki/Matrix _ factorization _(recommender _ systems)

https://www.youtube.com/watch?v=XkY2DOUCWMU&list = plzhqobowt qd D3 mizm 2 xvfitgf 8 he _ ab&index = 5&t = 0s

http://infolab.stanford.edu/~ullman/mmds/ch9.pdf

为艺术品的视觉相似性比较开发艺术风格嵌入

原文:https://towardsdatascience.com/developing-art-style-embeddings-for-visual-similarity-comparison-of-artworks-7a9d4ade2045?source=collection_archive---------15-----------------------

这项任务是作为一个高清历史图片在线图书馆的概念验证的一部分。

本练习的目的是找到一个将图像转换为嵌入向量的函数,其中向量之间的欧几里德距离表示图像在视觉上的相似程度。这允许对一个图像的嵌入进行最近邻搜索,以返回视觉上相似的图像,从而实现图像推荐和聚类。

这项任务因图像是插图而不是照片而变得复杂。虽然照片是主题的真实表现,因此相似的主题和构图会产生视觉上相似的图像,但插图包括风格的额外维度。

风格:“绘画、写作、作曲、建筑等的一种方式。某一特定时期、地点、人物或运动的特征

为了创建图像嵌入,使用了两种方法:

  • 卷积神经网络嵌入
  • 3D 色彩空间最近邻

卷积神经网络嵌入

用于将图像转移到嵌入的模型借鉴了来自神经类型转移电子商务图像内容相似性工作的发现。 一种艺术风格的神经算法 由Gatys et。al 和@Raghul Asokan 撰写的被用来研究神经类型转移。使用 TensorFlow 创建图像相似性函数及其在电子商务中的应用作者 Nina Pakhomova 用于开发对相似图像检索技术的理解。

风格转移和图像相似性技术都利用预先训练的卷积(CNN)图像分类模型来从图像中提取和抽象信息。这些模型已经被训练来提取用于分类目的的信息,随着网络深度的增加,中间卷积层捕获关于图像内容的越来越复杂的信息。

source

为此,我将使用在 image-net 数据库上训练的 VGG-19 模型,其架构如上图所示。为了利用这个网络提取艺术风格,我们必须首先做出一些主观假设,在手头任务的背景下是什么定义了风格。

  • 我们假设一种风格可以被描述为各种纹理和颜色的组合。
  • 我们还假设子特征,即整体图像中重复出现的小部分,对我们体验的风格很重要。例如,一幅建筑物和一幅风景的铅笔画可能具有相似的纹理,但是建筑物的锐角和窗户赋予了建筑图一种与风景截然不同的风格。

幸运的是,我们知道 CNN 在每个卷积层捕获并提取这些信息,每个核“搜索”纹理或子特征。当纹理或子特征存在于底层图像中时,内核在对图像该区域进行采样时输出较高的值。单个内核的激活过程如下所示。

https://www.mdpi.com/1996-1073/12/15/2846/xml

当一个层的所有内核都通过输入时,深度等于内核数量 k 的 3D 矩阵被输出。

这些内核越深入网络,提取的纹理就越复杂,最深的内核激活整个结构,如眼睛或窗户。这种行为在深层梦境的图像中得到了证明。

使用我们上面关于什么定义艺术风格的假设,并且知道每个核捕获艺术风格的不同元素,我们可以使用来自特定区域的所有核的激活的组合作为该区域的艺术风格的数学描述。为了总结所有地区的这些发现,人们可以简单地将每一次激活整合成一个嵌入向量,就像在电子商务图像内容相似度中所做的那样。然而,这种方法效率低,因为它需要存储每个激活,并且对图像上的空间变化敏感。这将导致下面的两幅图像被评为风格非常不同,尽管只是在空间上有所不同。

为了克服这些问题 Gatys et。al 在他们的神经风格转印纸中使用 gram 矩阵。Gram 矩阵计算每个内核的输出之间的相关性。在其输出中显示高相关性的核组合被认为是图像风格的描述。例如,在上面的《星夜》中,两幅图像中的单个笔触和漩涡的纹理高度相关,因此图像的克矩阵是相似的。

在计算上,通过将卷积输出展平为 2D 数组来计算格拉姆矩阵,每个内核为列,每个激活为行,a。该数组与其转置的点积作为格拉姆矩阵 G 输出。此处 G(i,j)给出了内核 I 和 j 的激活之间的相关性。注意,术语“相关性”的使用相当宽松,因为这不是统计意义上的真实相关性。潜在地,术语累积共活化将更准确。

产生的 gram 矩阵的大小是 k,它被展平成一个向量用于存储。从哪个(些)中间层提取内核输出是通过反复试验确定的,重点放在性能上,因为使用的层越深,所需的计算和计算时间就越多。

3D 色彩空间最近邻

哪些颜色是显而易见的视觉描述符,也是我们不想忽视的。虽然 gram matrices 将提取颜色信息,但我们使用了二次采样方法来明确编码当前的主色。色彩降维已经被很好地记录下来,通常为了提取图像中的主色,我会使用聚类方法,比如 K-means。然而,在这种情况下,我希望将图像的颜色表示为一个向量,其中每个元素总是对应于相同的颜色,从而允许图像之间的比较。

为了实现这一点,图像的 3D RGB 色彩空间被分成 n 个互斥的立方体,每个立方体的边长为 255/n。对每个立方体内的像素数量进行计数,并将计数存储在长度为 n 的向量中。

嵌入结构

最后,将展平的 gram 矩阵与颜色嵌入连接起来,形成维数为 N = k + n 的嵌入。

Model Architecture

结果

10,000 幅图像的样本集用于测试该模型。由于这种方法是无人监督的,不需要进一步的训练,这个小集合是足够的。

如果你正在读这封信,感谢你能走这么远!随着这个项目的继续,请随时关注。

用数值和矩阵运算发展单纯形法

原文:https://towardsdatascience.com/developing-the-simplex-method-with-numpy-and-matrix-operations-16321fd82c85?source=collection_archive---------10-----------------------

与本帖相关的代码可以在 要点中找到链接。

在这篇文章中,我试图从矩阵运算的角度来解决描述和实现单纯形法的资源匮乏的问题。特别是,单纯形法的大多数计算实现是通过直接实现单纯形 tableau 方法开发的。

因此,在这篇文章中,我试图通过开发一个利用矩阵运算而不是 tableau 方法的单纯形法程序来给出单纯形法的替代实现。为了保持这篇文章的简洁,我避开了特定矩阵运算实现的数学,但是如果读者希望了解更多关于这个特定实现的数学,他们可以参考 Stephen Nash 和 Ariela Sofer 的书 【线性和非线性编程 】,该书对单纯形法和实现它的许多方法进行了很好的介绍。Bazaraa、Jarvis 和 Sherali 的书Linear Programming and Network flow也是一个很好的深入资源,涉及到本文中提到的许多观点。我在本帖末尾给出了完整的线性编程书籍参考列表。

由已故数学科学家乔治·丹齐格发明的单纯形法是一种用于求解约束线性优化问题的算法(这类问题被称为线性规划问题)。线性规划问题经常出现在运筹学的相关问题中,比如在给定时间和资源约束的情况下寻找利润最大化的方法。

线性规划问题包括两个关键要素:一个目标函数和一个线性不等式系统。解决这种线性规划问题的基本目标是在给定解的线性约束的情况下最大化或最小化目标函数。线性不等式组创建了一个可行区域,因此最优解必须位于可行区域内。由线性不等式形成的这个可行区域是一个凸多面体,下面给出了这样一个区域的可视化。

A Convex Polytope

如图所示,约束是线性的,因此凸多面体具有平坦的边,可行区域是多面体的内部和边界。

一个关键的见解是,任何约束线性优化问题的最优解总是在凸多面体的一个角上。正是有了这种认识,我们才能推动单纯形法的发展。

单纯形法从可行区域内的某个点开始,然后随着算法的每次迭代,从凸多面体的一个相邻角(代表问题的可能解决方案)映射到另一个相邻角,使得每一步都给出比前一步更好或等价的解决方案。

这很难令人满意地描述单纯形法,所以如果读者想要对该方法有更深刻的直觉,我推荐访问这篇文章,或者观看 PatrickJMT 的单纯形法视频系列的前两个简短的视频,它们很好地介绍了该方法解决的各种问题以及它是如何工作的。

在选修运筹学或最优化课程(尤其是在大学本科水平)并复习了涵盖单纯形法的网上可用资源后,几乎可以肯定的是,人们将会接触到用单纯形法求解线性规划问题的 tableau 方法。用 tableau 方法解决线性规划问题的一些例子在这里这里和这里给出。

不幸的是,tableau 法通常是在涉及单纯形法的课程或课本中提到的唯一方法。因此,许多实现单纯形法的计算机程序直接实现了 tableau 法。tableau 方法是用来用笔和纸手工解决线性规划问题的。因此,它在计算上效率不高,并且在以计算形式实现单纯形法时不应该被选择。

在 Jupyter 笔记本中,我实现了单纯形法的一个版本,它使用 NumPy 中的矩阵运算代替 tableau 方法来解决线性约束优化问题。这样,我们得到了单纯形法的一个更加有效、简洁和自然的实现。

如果读者希望遵循以下程序中使用的精确数学和符号,请参考 Nash 和 Sofer 的线性和非线性规划的第 5 章。

单纯形法在今天的实践中很少使用,已经被更快的内点法所克服。然而,当单纯形法在实践中实现时,它通常是用矩阵分解来开发的,矩阵分解提供了一种甚至比本文给出的矩阵运算方法更快的单纯形法实现。对于低维线性规划问题,这里给出的矩阵运算方法是好的,然而,当开始解决具有数百或数千个变量的问题时,使用矩阵分解实现单纯形法更有意义。

我希望这篇文章能给读者一个高层次的直觉,让他们了解那些很少被提及但最终实现单纯形法的更好的方法,并且所提供的程序可以作为使用 tableau 方法的单纯形法的其他效率较低的实现的一个有用的替代。

书单

  1. 线性规划与网络流, Bazaraa
  2. 线性和非线性规划, 纳什
  3. 线性与非线性规划,伦伯格
  4. 凸优化

利用 Matlab 开发三维人耳识别系统

原文:https://towardsdatascience.com/development-of-3d-ear-recognition-system-using-matlab-c2fab95e874b?source=collection_archive---------18-----------------------

处理 3D 耳朵图像的初学者指南

人脸、虹膜和指纹已被广泛用于个人身份验证的生物特征。在计算机视觉和图像处理中使用最先进的深度学习技术,使开发的系统的准确性提高了近 100%。然而,基于这些特点的生物特征识别系统很容易被伪造,尤其是基于指纹的身份认证,并且很难获取虹膜样本。因此,研究人员正在尝试开发新的身份验证特征。最近的研究表明,人类的耳朵代表了某种独特的形状和模式,可以用来识别一个人。

  1. 据报道,一个人的双耳的结构和形状几乎相同,但与其他人严格不同,这使其成为一种适合于个人识别的特征。
  2. 与面部不同,它不受年龄影响,即耳朵的形状不会随着年龄和时间而改变。
  3. 与指纹和虹膜不同,基于耳朵的生物特征识别系统不需要用户合作来获取样本,并且可以在不受限制的环境中无需用户的确认而被捕获。

可用于开发基于耳朵的生物特征识别系统的几何形状特征如图 1 所示。

Figure 1: Key components of ear (source)

图 1 显示了主要的形态学组成部分,包括外耳轮(即耳朵的外部结构)、对耳轮、耳垂、对耳屏、外耳和耳轮脚。

从 2D 图像中提取特征相对容易,因为存在对应于颜色、形状和纹理的灰度值。在三维图像中,我们只有(X,Y,Z)点和深度值,这使得很难分析关键部件的几何形状。在从 3D 人耳图像中提取特征之前,我将讨论开发人耳生物识别系统的预处理步骤。其中一个困难的部分是找到耳朵的位置,并从整个图像中裁剪出来。在本文中,我使用鼻尖的深度值从整个侧面人脸图像中裁剪出耳朵。

关于数据库

我们使用了圣母大学(UND)的数据库,这些数据库免费供公众使用。如下所述,所获得的数据库属于几个集合:

  • 集合 E : 114 个人,464 张可见光侧脸(耳)图像,拍摄于 2002 年。
  • 收藏 F : 302 个人体对象,942 张 3D (+对应 2D)侧面(耳)图像,拍摄于 2003 年和 2004 年。
  • 收集 G : 235 个人类对象,738 张 3D (+对应的 2D)侧面(耳朵)图像,拍摄于 2003 年至 2005 年。
  • 收集 J2 : 415 名人类受试者,1800 张 3D (+对应的 2D)侧面(耳)图像,拍摄于 2003 年至 2005 年之间。

然而,在我们的实验中,我们使用了集合 F 和集合 G 样本。

读取 3D 深度图像

数据库的示例图像是. abs.gz 格式。不过,UND 也提供了相应的 RGB 图像,但我只使用了 3D raw 图像进行实验。您可以读取原始图像并可视化 X、Y 和 Z 的每个平面,如这里讨论的。整个过程与三维人脸可视化的过程相同。但是,耳朵区域的裁剪与面部部分的裁剪略有不同。接下来,我将讨论如何从整个 3D 图像中裁剪耳朵区域。

耳朵检测和裁剪

在裁剪 ROI(感兴趣区域)之前,让我们先看看图像在数据库中的方向。

Figure 2: 3D visualization of database image.

Figure 3: Visualization in Meshlab

图 2 和图 3 是同一主题的不同角度的视图。你可以使用 Matlab 旋转并使其方向一致。从上面的图中可以清楚地看到,数据库图像带有侧脸,只有整个脸部的耳朵部分对我们来说是重要的。因此,我们必须从整个面部只修剪耳朵。要裁剪耳朵区域,首先让我们了解每个图像中可用的深度信息。如果用于获取图像的相机被放置在面向原点的 z 轴处,并且人正看着 y 轴的递增值,则耳尖将具有最小深度值,鼻尖将具有最大深度值。如果仔细观察图 2,您会注意到深度值从 1900 增加到 2000。这意味着它的耳尖离相机很近。要了解更多关于耳尖深度的信息,请看这篇文章的图 5。唯一的区别是,我计算的是鼻尖,而我们讨论的是耳尖。从图 3 中可以看出,耳尖具有最小的 z 值,而鼻子具有最大的 y 值

参见图 2,我们可以说鼻尖在 y 方向上的值约为-55 单位。耳朵和鼻尖之间的距离大约为 25 个单位,并且对于每张图像来说几乎是固定的,除非图像没有捕捉到除此之外的角度。我们将在这篇文章的后面讨论它,现在,我凭经验发现 50 个单位高度和 25 个单位宽度的矩形形状足以覆盖整个耳朵区域,如果这个矩形形状距离鼻子点+/- 25 个单位。这里,鼻尖为负值时考虑+25,即要捕捉右耳图像(如图 2 所示),当 y 值(鼻尖)为正时考虑-25,人正看着 y 值的增加值。这是传感器对左耳成像的情况。要理解 ROI 的裁剪过程,请参见图 4。

Figure 4: Cropping ROI

然而,一些图像样本是在不同的方向收集的,如图 5 所示。对于这样的图像,我没有发现耳朵和鼻尖之间有任何关系

Figure 5: Image captured at different angle.

因此,我没有选择这些图像进行进一步的处理。(如能对这些图像的处理提供任何帮助,我们将不胜感激)。考虑图 4 所示的 ROI 裁剪方法,得到的图像如图 6 所示。

Figure 6(a)

Figure 6(b)

图 6(a)和 6(b)表示以不同角度示出的被裁剪的耳朵区域。这些图像可能有孔洞、噪声;因此,有必要对其进行仔细的预处理。在下一节中,我们将讨论去除尖峰、孔洞填充和去噪的方法。

去尖峰、填洞和去噪

去尖峰:3D 面有噪声,包含尖峰,因此需要应用平滑技术。在我们的研究中,我们将 2D 加权中值滤波技术的概念扩展到三维人脸图像。所研究的技术使用网格中值滤波的加权中值实现来执行 3D 数据集的滤波。

补洞:去除尖刺会导致孔洞的产生,因此有必要对这些孔洞进行补洞。为此,我们使用了 3D 插值。在所有的插值技术中,我们使用了''立方'。在三次插值方法中,查询点处的插值基于每个维度中相邻网格点处的值的三次插值。这种插值基于三次卷积。

去噪:我用 3D 高斯滤镜去噪。

用于预处理步骤的代码如下所示。

最后,预处理后的人耳图像如图 7 所示。我们发现一些孔在预处理步骤后仍然存在,这意味着进一步改进是可能的。为此,您可以使用其他方法来生成更好的特征。

Figure 7: Pre-processed ear image

最后,我从云点生成网格,用于从 3D 裁剪的耳朵图像中提取特征,这将在下一篇文章中讨论。完整的代码可以在我的 GitHub 库中找到。您可以下载并使用它对 3D ear 数据集进行预处理。如果你觉得这篇文章有帮助,请随意投赞成票。

我要感谢 Jayeeta Chakraborty ,他同样为开发这个项目做出了贡献。在下一篇帖子里,我将分享 3D 人耳识别的迭代最近点 (ICP)方法。[编辑:由于一些权限问题,我现在不被允许分享 ICP 的代码。]我希望这篇文章可以帮助初学者开始使用 3D 数据库。

利用 Matlab 开发三维人脸识别系统

原文:https://towardsdatascience.com/development-of-3d-face-recognition-using-matlab-a54ccc0b7cdd?source=collection_archive---------25-----------------------

处理 3D 人脸图像的初学者指南

在过去的十年中,已经提出了几种用于图像处理和计算机视觉应用的机器学习算法。LBP、HAAR 是一些流行的算法,它们被广泛地用于人脸识别,并且产生极好的结果。但是,这些算法大多不适合无约束环境下的实时识别。最近,最新的深度学习技术已经成为超越传统机器学习算法的新宠。人脸识别应用程序处理的图像只不过是范围(0–255)内像素值的组合。算法在这些灰度值中找到一个有区别的模式,并将其视为一个特征,该特征被认为对于每幅图像是唯一的。然而,在 3D 图像中,不存在像素信息,而只有每个点的位置(x,y,z)可用。这使得很难在 3D 图像中找到图案。

最近,我开始研究 FRGC2.0 3D 人脸数据集,最初,我无法找到足够的资源来处理 3D 图像。终于,过了一段时间,我看到了一篇基于 3D 人脸识别的论文,作者是阿杰马勒·米安,在此感谢他提供的有益建议和参考。我还想提一下我的同事 Jayeeta Chakraborty,他同样为开发这个项目做出了贡献。在这篇文章中,我将讨论开发三维人脸识别系统的预处理步骤,以便其他寻找类似工作的人可以有一个良好的开端。

读取 3D 深度图像

物体的 3D 图像包含物体中每个点的高度、宽度和深度。通常,3D 原始数据集,例如 FRGC 2.0 人脸数据库、集合 F 和集合 G 的 3D 人耳数据库中具有图像文件。abs、. abs.Z 或. abs.gz 格式。图 1 显示的是 FRGC 2.0 三维人脸数据库的图像样本。

这些图像是压缩的 ASCII 文本文件。建议不要预先解压缩数据集,因为扩展这些文件可能需要很大的磁盘空间。每个图像文件都有一个三行标题,给出行数和列数。接下来是四幅图像。第一个是所谓的“标志”图像,其中像素值为 1 意味着该像素的相应(x,y,z)值有效。如果标志值为零,您应该忽略该像素的(x,y,z)分量。跟随旗帜图像的是 X 坐标图像、Y 坐标图像和 Z 坐标图像。都是浮点图像。您可以使用每个范围像素的 3D 坐标,也可以丢弃 X 和 Y 图像,只关注 Z 值。请注意,图像的“纵横比”不一定是 1。以下代码部分可用于获取 x、y、z 和标志值。

您可以使用 imshow()函数打印 x,y,z,这将显示相机朝向 x 轴、y 轴和 z 轴时拍摄的图像。连接所有你能看到的图像,如图 2 所示。

我们提取了云点,将其转换成。ply 文件,并显示它可视化三维形状的图像。下图 3 显示了人脸的 3D 视图。因为原始图像包含包括颈部和肩部的面部图像,这对于特征提取过程是不需要的。因此,我们必须从整个图像中只裁剪人脸区域,这将在下一节中讨论。

(a)

(b)

图 3:以上数字是同一主题。图(a)表示使用 Matlab 的 3D 可视化,而图(b)是在 Meshlab 工具中显示时产生的。

人脸检测

为了从整个图像中只提取人脸区域,我们利用了深度信息。如果您注意到图 4 中所示的图像,可以观察到对象面向 z 轴,传感器捕捉到正面。因此,噪声提示点距离摄像机的深度最小。

Figure 4: Subject is facing towards camera in z-axis

如果你仔细观察图 3,你会注意到深度值从 1500 增加到 1700,当我们从鼻子点到耳朵。如果仍然不清楚鼻尖的概念,请看图 5。

Figure 5: Nose tip detection

你会注意到黑点显示的鼻尖( P )的 z 值(深度)在 1450 到 1480 左右,假设是 1460。现在考虑以鼻尖' P '为中心,我们画了一个尺寸为 140 单位的正方形,如图 6 所示。

Figure 6: Face region cropping

经验上发现正方形的大小适合于覆盖面部区域。唯一的要点在于,选择正方形来表示人脸区域。最后,从整幅图像中裁剪出面部部分,我们得到了如图 7 所示的人脸。

Figure 7 (a): Cropped facial region

Figure 7 (b) : Cropped face image

图 7 (a)和 7(b)表示当在不同角度可视化时裁剪的面部图像。一旦你得到了裁剪后的人脸区域,下一步就是去尖峰,孔洞填充和去噪。

去尖峰、填洞和去噪

去尖峰:3D 面有噪声,包含尖峰,因此需要应用平滑技术。在我们的研究中,我们将 2D 加权中值滤波技术的概念扩展到三维人脸图像。所研究的技术使用网格中值滤波的加权中值实现来执行 3D 数据集的滤波。

补洞:去除尖刺会导致孔洞的产生,因此有必要对这些孔洞进行补洞。为此,我们使用了 3D 插值。在所有的插值技术中,我们使用了''立方'。在三次插值方法中,查询点处的插值基于每个维度中相邻网格点处的值的三次插值。这种插值基于三次卷积。

噪声去除:数字图像易受不同种类噪声的影响。噪声是图像采集方法错误的结果,所产生的值不能代表实际场景的真实强度。再次有许多方法来消除噪声,我们使用三维高斯滤波器。

这是经过所有预处理步骤后的最终图像,如图 8 所示。

Figure 8: Pre-processed image.

下面显示了用于人脸区域检测、人脸裁剪、去尖峰、孔洞填充和去噪的源代码。

经过所有的步骤,我们得到的最终输出是一个网格图像。该网格图像可以根据应用要求用于特征提取技术。在我们的例子中,我们提取了 PCA 特征,以及线、点和面特征,我将在下一篇文章中讨论。在另一个实验中,我们将 ICP 应用于网格图像,以匹配产生更好结果的图像。如果要运行 ICP 算法,建议有 GPU。

完整的代码可以在 GitHub 库获得。您可以下载并使用它来预处理您自己的 3D 人脸数据集。如果你觉得这篇文章有帮助,请随意投赞成票。

在下一篇帖子中,我将分享使用主成分分析 (PCA)和迭代最近点 (ICP)的基于特征级和得分级融合的人脸识别【编辑:由于一些权限问题,我暂时不分享 PCA 和 ICP 的代码。].

社交聊天机器人的发展

原文:https://towardsdatascience.com/development-of-social-chatbots-a411d11e5def?source=collection_archive---------22-----------------------

社交聊天机器人设计简介

Image credit pixabay.com

社交聊天机器人或智能对话系统有能力与人类进行对话。模仿人类对话并通过图灵测试一直是人工智能(AI)运行时间最长的目标。即使在电影中,许多电影,如《T4》、《她的 T5》和《钢铁侠 T7》都展示了聊天机器人技术如何给人类和机器的互动方式带来革命性的变化。

在 20 世纪 70 年代初,有许多人试图创建智能对话系统,但这些系统是基于手工制作的规则设计的。2016 年,聊天机器人被认为是“下一件大事”。包括谷歌、微软、脸书和亚马逊在内的主要 IT 公司都发布了自己版本的聊天机器人平台。由于性能、设计问题和糟糕的用户体验,这些聊天机器人非常糟糕。

Google search trend of term“chatbot” from 1 Jan 2015 to 26-Dec 2018 source

但是由于最近在自然语言处理(NLP)方面的进步( BERT 、 ELMo 、 ULMFiT 和 OpenAI transformer ),谷歌已经能够将文档检索性能提高 50–100%。因此,我们可以假设 NLP 的 ImageNet 时刻即将到来。在未来几年,聊天机器人很可能会变得更加广泛可用。

应用程序

Image source: Woebot website

如果设计得当,聊天机器人可以改变许多领域,如教学、电子商务、法律实践、个人助理、管理等。

让我们来介绍一下 Woebot ,一个真正的 AI 治疗师。它为用户提供情感支持,并以自然的方式交流。这个过程有助于缓解压力,人们喜欢和它交谈。

XiaoIce 是社交聊天机器人的另一个很好的例子。它是由微软开发的,被认为是世界上最流行的聊天机器人。它有一个 18 岁女孩的个性,有趣,可靠,有同情心,深情。

你知道在 messenger 上有超过 5 个 AI 法律助理和 195 个人助理吗?让我们简单讨论一下,如何设计这些社交聊天机器人的方法之一。这篇文章旨在对 XiaoIce 的设计做一个基本的介绍,在论文中有描述。

基本设计

对于社交聊天机器人系统,需要高情商(EQ)和高智商(IQ),因为这些系统应该帮助用户完成特定的任务,并提供情感支持。聊天机器人的独特个性使其更加用户友好。一个社交聊天机器人必须有能力根据用户的兴趣领域来个性化回答,使之令人鼓舞、激励和适合。

小冰已经发展了超过 230 种不同的技巧,包括电影推荐、安慰、讲故事等。它还通过产生社交上有吸引力的反应来展示情商,并根据情况改变谈话的话题。它被设计成一个 18 岁的女孩,有创造力,有趣,可靠,有同情心。

社交聊天机器人评估指标:CPS

测量社交聊天机器人的性能是很困难的,因为过去使用图灵测试来评估性能。XiaoIce 是使用每次会话的会话次数(CPS)作为指标进行评估的。因为图灵测试不能测量用户的情感投入。CPS 是会话中聊天机器人和用户之间的平均对话次数。预期的 CPS 对应于长期合约。

作为分层决策过程的社交聊天

为了实现设计目标,人机交互被认为是一个决策过程。然后,聊天机器人会针对长期参与进行优化。

Human-XiaoIce chat sample (source)

XiaoIce 可以通过使用各种技能使对话模式多样化来保持用户的兴趣。每个对话模式都由一个技能维护。顶层流程通过转换技能来处理整体对话模式。由当前所选技能控制的低级流程处理响应,以生成聊天片段或完成任务。例如,顶层流程可以从核心聊天技能切换到歌曲推荐。歌曲推荐技能可以推荐一首歌曲或选择采取类似切换到音乐会门票预订技能的动作,以预订用户喜爱的乐队的未来音乐会活动。

这种决策可以在称为马尔可夫决策过程(MDPs) 的数学框架中进行。所以聊天机器人通过 MDP 导航,与用户互动。在每一轮谨慎的对话中,聊天机器人观察当前的聊天状态,并选择一个技能发送响应。然后聊天机器人会收到用户的奖励。聊天机器人找到最佳策略和技能,以最大化 CPS。

系统结构

System Architecture of XiaoIce (source)

用户体验层:这一层将小冰连接到所有主要的消息平台,通过两种方式进行沟通。全双工模式是一种基于流的会话模式,支持语音呼叫。在基于消息的对话模式下,用户和聊天机器人轮流发送消息。这一层还包括语音识别、图像理解和文本规范化。

对话引擎层:该层由对话管理器、移情计算和对话技巧组成。对话管理器跟踪对话状态,选择对话技能或核心聊天。移情计算模块旨在从对话中理解人类的情感和兴趣。该模块帮助小冰获得社交技能,并根据小冰的个性生成个性化的响应。

数据层:该层由各种数据库组成,这些数据库以文本-文本对和文本-图像对的形式存储对话数据,非对话数据,如知识图表、用户资料、聊天机器人资料等。

数据科学家现在应该使用的开发实践。

原文:https://towardsdatascience.com/development-practices-that-data-scientists-should-use-now-7c4f54d6b92?source=collection_archive---------31-----------------------

我曾与经验丰富的开发人员、专家数据科学家、新人、非程序员一起工作,所有这些人都有一个共同点:他们必须编写代码。

正常情况下,这篇文章应该是非常笼统的,大多数程序员都是这样工作的,但是由于一些数据科学或数据工程实践固有的实验性质,我发现,有时候,这些建议中的一些,呃…被忽视了。因此,这里是{科学家|工程师}应该知道的关于编码实践的绝对最低数据。

你从来不为自己写代码,而是为别人写。

这是我告诉编码数据科学家的第一条基本规则:永远不要为自己写代码,而要为别人写。

而且,请注意,“其他”人可能是…你。如果不为同事写,至少为未来的自己写。

这意味着什么?

  • 注释您的代码。是现在的两倍:)实际上,在编写代码之前进行注释也是一个很好的实践:)
  • 礼貌地写。使用显式的变量名,文件名(我看见你了,untitled09.ipynb 先生)。删除/注释你不再使用的代码。
  • 记录你的代码(不完全等同于注释)。放一篇自述,助读者一臂之力。
  • 收集你正在使用的模块的版本,以便在一年内(谁知道一年内会创建多少 JS 框架),当你不得不匆忙运行项目时,你会找到你需要的模块版本。

不推入回购的代码是不存在的。

我很惊讶有这么多数据科学家在他们自己的 GPU 包装的机器上工作,所有的铃铛和哨子,以及一个非常脆弱的硬盘驱动器,他们所有的生命都装在一个小小的空间里。

比如说,硬盘的密度是每平方英寸 500 千兆比特。这意味着我微小的动作会导致灾难。考虑到我自己撞上家具的能力,对于这么小的空间来说,这是很大的信任。

因此,对待你电脑上的代码,就像它不存在一样。它没有版本控制,没有审核,没有 CIed,没有备份。它。只是。不会。存在。

哦,你知道 Jupyter 笔记本实际上是版本的文件吗?

在选择架构时尽可能保守

你是数据科学家?太好了。你想使用最新的框架,它在 Github 知识库上有半颗星,发布于 3 年前,从那以后再也没有接触过(抱歉,没有链接)。不要。

你将有很多不确定性要处理,所以请避免在薄冰上滑冰,使用一个废弃大学的不起眼的 Pytorch 叉子。

一行代码花费的时间是编写时间的 10 倍

…说到这里…你必须意识到,一行代码的成本远远超过了编写它所花费的时间。甚至是死代码。

因此,当你添加一个没有人要求你的新功能时,当你训练你的模型来检测不属于规格的模式时,你只是在建立技术债务。

成功的编码会议通常包括修剪代码中不必要的部分。这是管理复杂性的一个简单方法。

Trim your code.

你也从来不为自己训练。

机器学习通常涉及训练数据,评估你的训练,并建立一个可扩展的、强大的推理机。

第一部分涉及大量的实验。总会有一个更好的人来改进你的机器学习设计。我是说,即使是你,伊恩·古德菲勒,如果你在读这封信,相信我,有人比你更好。比如你未来的自己!

所以,根据经验,永远不要为自己训练,而是为别人训练。这意味着,记录,评论,和两件主要的事情:

  • 向其他人提供根据您的原始数据进行训练的方法(例如,将您的数据版本化并给出其 URL!)
  • 给其他人一些方法来根据你的测试数据评估

似乎很明显?去读一些深度学习的论文,你会明白并不总是那么明显:)

错误的编码者复制/粘贴。伟大的程序员无耻地偷窃。

程序员做的事情有一半是在谷歌上查找答案。啊,堆栈溢出的帖子来了,解释如何解决你的问题!

现在,一旦你复制并粘贴了解决方案,请参考原始的堆栈溢出帖子,例如作为注释。虽然不多,但当你试图弄清楚你为什么这么做时,它真的很有帮助。

Even Microsoft does that!

当你以后查看你的代码时,这会节省很多时间。

不要用 Python 2(拜托)

Don’t scare the python

啊,来吧…现在是 2019 年,真的。Python 3 带来了如此多的东西。另外,你不喜欢 UnicodeErrors,对吧?

总而言之,遵循这些简单的规则会让你成为一个更好的程序员、更好的数据工程师和更好的数据科学家。如果你做的事情有目的,至少让其他人分享它!

你呢?你的最佳实践是什么?在评论里告诉我!

设计零射击学习

原文:https://towardsdatascience.com/devise-zero-shot-learning-c62eed17e93d?source=collection_archive---------2-----------------------

Completely unrelated apart from the fact that people are ‘learning’ in this beautiful fresco: The School of Athens by Raffaello Sanzio

由 Fromme 等人(2013) 撰写的《设计:深度视觉语义嵌入模型》是一篇真正漂亮的论文。作者提出了一种新的图像分类方法,利用语言模型学习语义知识。该方法能够对训练期间观察到的数万个图像标签而非进行零拍摄预测。我将向您详细解释这种方法,并且我使用 Docker 在 AWS 上部署了一个 device model,以便您可以对其进行试验。

本文组织如下:

首先,我将向您解释“传统”图像分类器的潜在问题,以及如何通过结合计算机视觉和语言建模来解决这些问题。为了可视化模型的能力,我将向你展示一些由部署在 AWS 上的模型 I 做出的零炮预测的很酷的例子。最后,如果您想自己培训和部署这样一个模型,我将为您介绍一些有用的资源。

在经典编程中,你可能会定义一组规则,允许你从你的数据中计算答案规则和数据进,答案出。

如果我要求你写下一组规则,在给定像素值的情况下,判断任意图像是否包含汽车,你肯定会失败。这个任务太复杂了,无法手工表达这样的规则。所以我们做的就是“参数化规则”,从数据和答案中学习参数。数据和答案在,排除。 原则上,这是所有(监督)机器学习背后的思想。

卷积神经网络形式的“传统”图像分类器(相对于设计而言是传统的)是参数化函数,其学习为输入图像的 n 个可能类别中的每一个计算有意义的概率。概率分布通常用网络顶部的 softmax 层计算。

这种神经网络已经被证明在图像识别任务中表现出色,那么为什么还需要改进的方法呢?

最大的问题是,我们被限制在数据集的 n 个类别,我们在这些类别上训练我们的图像分类器。ImageNet 的精简版(1000 类)包含 90 多种不同品种的狗。因此,在这个数据集上训练的训练有素的分类器可以比我更成功地区分更多的狗品种,但它永远无法将图像分类为狗,因为“狗”这个词本身不是一个类别。

另一方面,设计模型预测接下来的四张照片非常像“狗”,即使它从来没有被展示过“狗”类别的训练对。

免责声明:如果你为一个受限的设置训练一个模型,例如医疗诊断,带有 softmax 输出层的分类器当然是一个完全有效的好方法。你的模型不需要归纳成无数在训练中没有看到的不同类别。

回到我们的狗身边。原则上,您可以构建一个手工制作的层次结构,确定如果一个图像包含一只“德国牧羊犬”,它就自动包含一只狗。但是手动为所有现有的单词构建这样一个层次结构是大量的工作,这是我们在机器学习中极力想要避免的。毕竟,你选择将我们的世界划分为越严格定义的类别,构建标签数据集就越复杂和昂贵。

让我们仔细看看图像分类器返回的类别概率:

使用 softmax 输出图层,每张图片只能属于一个类别,因为 softmax 旨在将高概率分配给一个类别。这意味着你不应该引入一个额外的类别“狗”,因为网络将很难决定是将图像归类为“狗”还是特定的狗品种。

原则上,这个问题可以通过在输出层中使用 sigmoid 激活函数而不是 softmax 来解决,并允许不同的标注适用于单个图像。然后,您将不会预测图像的 n 个类别概率的总和为 1,而是预测每个类别的一个独立概率,即该类别的对象是否可能包含在图像中。这允许你引入额外的类别,如“狗”,而不与狗的品种竞争。

我这么说是什么意思?

如果在网络顶部使用 softmax 图层,您可能会得到类似“该图像包含一只德国牧羊犬的概率为 87%”的答案。所有其他 999 类加起来占 13%。

如果您在输出图层中使用 sigmoid 并允许不同的类别包含在图像中,您可能会得到类似于“图像包含德国牧羊犬的概率为 87%,狗的概率为 89%,法国斗牛犬的概率为 67%,…,核潜艇的概率为 0.13%,飞机的概率为 1%”的答案。请注意,概率的总和不再是 100%。

使用这种方法,分类器不必决定是否应该将高概率分配给“dog”或“German shepherd dog”,因为它必须使用 softmax 输出层。它决定每个类别是否可能被检测到,而不考虑其他类别。

那么问题解决了吗?

比方说,你为 ImageNet 找到或创建了包含成千上万个附加类别的标签,即“狗”,并实际上成功训练了一个卷积神经网络,允许预测成千上万个类别概率。网络现在可能会说“这个图像包含一只德国牧羊犬和一只狗”。网络能否回答这个图像中是否包含“小狗”、“小狗”或“猎犬”的问题?不,它不能,因为当你添加像“狗”这样的类别到数据集中时,你没有包括“小狗”、“小狗”或“猎犬”这样的类别。那么接下来,我们应该把这些词也作为潜在的标签吗?

问题是,这些分类器都不能预测它们在训练中没有遇到的类别,它们不能将关于它们已经被训练的类别的语义信息转移到看不见但相似的类别。

像 DeViSE 这样的模型为这个问题提供了一个真正优雅的解决方案,它将图像识别任务与从在未标注文本上训练的语言模型中学习到的关于单词/类别相似性的语义信息相结合。

基本上,目标是开发一个能够推断图像包含“狗”、“小狗”、“小狗”或“猎犬”的模型,因为这些词与“德国牧羊犬”相似。我们希望我们的模型能够归纳出在训练过程中从未遇到过的类别,因为这些类别在语义上与模型被训练的类别相似。这就是所谓的零射击分类。

设计

建立一个设计模型始于在一个未标注的文本语料库上训练一个语言模型。

每个单词(或令牌)都被表示为高维空间中的一个点,或者用简单的英语来说,表示为一个向量,比如说 300 个浮点数(当然也可以是 400 或 500 或 1325,但在本文的其余部分,我们假设是 300)。这样的向量被称为单词向量,单词向量包含的数字是模型的参数。这意味着,随着模型的学习,优化器可以更改这些值。接下来,你需要一个神经网络,一个参数化的函数,它可以根据过去的 m 个单词来预测句子的下一个单词。简单地说,这就提出了一个问题“如果你有这个由 m 个单词组成的句子,下一个单词会是什么?”。问这个问题的好处在于,你不必对你的数据集做任何标记,你只需浏览任何文本语料库,并反复询问你的神经网络下一个单词是什么。网络通过调整其参数来学习预测下一个单词,这些参数包括代表单词的所有单词向量中的数字。

300 个元素向量指向高维嵌入空间中的一个点,并且相似的单词在该空间中彼此接近,因为同义词倾向于出现在相似的上下文中。这个高维空间中代表“狗”的点会接近代表“doggy”的点。(在这个高维空间中“接近”的一种可能解释将在后面解释。)

我知道这一切对你来说可能听起来非常吓人,但不要担心,此时我希望你知道的是,在训练语言模型后,代表单词“dog”的 300 个数字更接近于代表“doggy”的 300 个数字,而不是代表“train”的 300 个数字。

如果你自己还没有训练过语言模型,但有兴趣这样做,我强烈推荐你跟着这个一起编码,我保证,我在这里写的一切对你来说会更有意义。

目前,我们需要的只是语义上有意义的单词向量。幸运的是,我们可以在这里简单地下载经过训练的嵌入/词向量。

现在到了第二部分:将图像映射到这个丰富的高维嵌入空间。听起来很困惑?别担心,这比听起来容易。

我们采用基于预训练的 softmax 输出层的图像分类器,在网络的顶部截断最终的分类层,并用几个层来代替它们,这些层不预测 n 类的 n 类概率,而是简单地预测 300 个数字,这代表一个词向量。我们将分类问题转化为回归问题。

将图像映射到高维单词向量嵌入空间中,然后允许我们在这个高维嵌入空间中找到与其接近的单词——或者用英语来说:我们预测图像的单词向量,并找到具有相似单词向量的单词。

来自报纸:

我们的模型的一个明显的优点是,它能够对它从未观察到的候选标签做出合理的推断。例如,一个在标记为虎鲨、牛鲨和蓝鲨的图像上训练的设备模型,但从来没有标记为鲨鱼的图像,将可能具有概括为这种更粗粒度的描述符的能力,因为语言模型已经学习了与所有特定鲨鱼相似的鲨鱼的一般概念的表示。

例如,使用余弦距离与虎鲨最接近的 9 个术语是牛鲨、黑顶鲨、鲨鱼、大洋白顶鲨、沙洲鲨、灰鲨、蓝鲨、安魂鲨和大白鲨。与汽车最接近的 9 个术语是轿车、肌肉车、跑车、小型车、汽车、赛车、皮卡、经销商和轿车。

训练设计模型的主要步骤是:

  1. 下载字向量。
  2. 下载带标签的图像数据集,即 ImageNet。完整的 ImageNet 数据集可以从这里下载(不过大约 170GB)。ImageNet 的一小部分可以从这里下载。部署在 AWS 上的模型是在完整的 170GB 数据集上训练的,但子集也工作得相当好。
  3. 找到你有一个词向量的 ImageNet 的类别。构建包含图像-单词向量训练对的数据集。
  4. 在预训练的图像分类网络的顶部截断最终分类图层,并用自定义图层替换它们以预测 300 个数字。在 PyTorch 中,可以这样做:

5.定义一个损失函数。也就是说,你可以使用余弦相似性的适应。记住,单词的数字表示是矢量。在学校里,你可能被教导过,你可以把向量想象成箭头。当两个箭头指向同一个方向时,它们是相似的(我们忽略箭头的长度)。余弦相似度计算两个向量之间角度的余弦。如果角度为 0,余弦相似度为 1,如果角度为 90,余弦相似度为 0。对于损失,当向量彼此更相似时,我们想要更小的数字,因此,当它们之间的角度更小时。因此,我们简单地将损失计算为两个向量的 1 -余弦相似度:

6.训练网络。

如果你想自己做这件事,我建议你按照 fast.ai 第 2 部分的这一部分编写代码。正式课程笔记本来了。我的笔记本稍微没那么杂乱/评论更多。它还使用 PyTorch 从头开始构建模型,而不是调用 fast.ai 便利函数来构建它。也可以随意借鉴。

让我们总结一下我们讨论的内容:我们不是建立一个返回 n 个类别的 n 个类别概率的模型,而是建立一个预测给定图像的单词向量的模型。然后我们简单地寻找具有相似单词向量的单词(近似最近邻搜索)。这允许模型利用语义知识来概括和预测在训练期间没有看到的类(零射击学习)。

这种方法还有一个额外的巨大好处:

  1. 语言模型的数据集根本不需要标记!我们使用的单词向量是在维基百科文本语料库上训练的,但理论上,你可以在所有书面文本的整体上训练大型语言模型。以这种方式学习到的语义相似性知识很可能比任何手工制作的语义相似性层次结构都要好!
  2. 您使用的数据集不必像使用传统图像分类器时那样维护良好!来自报纸:

也许更重要的是,虽然我们在这里训练的是一个精选的学术图像数据集,但我们的模型的架构自然适合于在所有可用的图像上进行训练,这些图像可以用(更大的)词汇表中包含的任何文本术语进行注释。我们相信,训练这种形式的大规模“开放”图像数据集将极大地提高视觉对象分类系统的质量。

好了,理论够了,让我们来玩玩模型吧!我使用 Docker 将它部署在 AWS 上,这样您也可以使用它。(免责声明:该应用程序在 AWS 上的单个 t2.micro 实例上运行,因此它在一年内保持在新客户获得的 AWS 免费层内。我的故事通常每天有大约 100 名观众,所以我不希望有太多的读者同时使用它。)

[## 设计

Fromme 等人的深度视觉语义嵌入模型(2013 年)](http://ec2-18-195-116-70.eu-central-1.compute.amazonaws.com:8000/apidocs/)

我们将使用该模型进行三种不同的零炮预测:

  1. 通过首先预测输入图像的单词向量,然后从大约 50.000 个存储的单词向量中找到近似的最近邻居,来计算输入图像的前五个零镜头预测(类别)。

我向该应用程序提供了大约 5000 张随机图片,这些图片来自我在培训期间创建的验证数据集。该应用程序为每张存储的图片预测一个单词向量。这使我们能够:

2.给定输入图像,预测语义相似的图像。这是通过预测输入图像的单词向量,然后对为存储图像预测的单词向量执行近似最近邻搜索来完成的。

3.给定一个输入单词,预测语义相似的图像。这是通过将输入单词翻译成其相应的单词向量,然后对存储图像的预测单词向量执行近似最近邻搜索来完成的。

让我们从 3 号开始。还有试试“鸟”这个词。ImageNet 中有几种鸟,即“信天翁”、“雪鸟”、“靛雀”、“美洲鹰”、“秃鹰”或“鸵鸟”,但没有“鸟”这一类别。

该模型预测以下图像最像“鸟”:

“昆虫”也一样(不是 ImageNet 中的一个类别):

包含类别“curch”。显然,该模型可以概括为“大教堂”类别:

单词“measure”没有出现在任何 ImageNet 类别中(事实上,没有一个动词是一个类别)。然而,该模型能够预测用于“测量”的以下图像:

“服装”一词也是如此:

单词“连衣裙”也不属于 ImageNet 中的任何类别,但是该模型预测了以下图片:

“跑车,跑车”是唯一包含“运动”一词的品类。该模型为“运动”预测了以下图片:

“武器”不是一个范畴:

“植物人”也不是:

让我们试试别的:

函数wordvec_2_image需要一个,但接受两个单词作为输入。如果你传递两个单词,单词向量被平均(相加并除以 2)。让我们看看语言模型是否学会了平滑过渡,这意味着我们可以在词向量之间进行插值,并找到一些有意义的东西。

(Mikolov 等人,2013)证明了简单的算术运算揭示了表征空间中丰富的线性结构。一个典型的例子证明了向量(“国王”)—向量(“男人”)+向量(“女人”)产生了一个向量,它的最近邻居是皇后的向量。(引自拉德福德等人,2016 )

存储的数据集中预测单词“ship”的前四个图像:

有两艘旧帆船和两艘现代船。让我们检查一下模型对单词“船”+“帆”的预测:

好了,现代的船都走了,现在所有的船都有帆了。这是否意味着有意义的插值在这种模型中是可能的?嗯,我们只看了四张照片,所以我对这样的声明要小心。第五艘可能是现代船。帆只出现在船上,所以矢量这个词可能一开始就很接近。对它们进行平均会返回一个与“ship”和“sail”都非常相似的单词向量,我们看到的结果可能是一个巧合,而不是有意义的插值。

不出所料,单单“帆”就给出了类似的选择:

最后一段相当含糊。让我们试着量化其中的一些:

我们用np.corrcoef(wordvectors.get_word_vector("ship"), wordvectors.get_word_vector("boat"))[0,1]计算两个词向量的皮尔逊相关系数来估计两个词的相似度(见笔记本)。数字越大意味着它们可能越相似。向量与其自身的相关系数是 1。

“Ship”和“bug”显然非常不相似,相关系数为 0.08。

可以算作同义词的“船”和“舟”给 0.56,“船”和“帆”给 0.59,“舟”和“帆”给 0.57。所以“帆”确实和“船”和“舟”都很相似。我们试着用一个与“船”不太相似的向量来插值,即“发动机”。

有些船有发动机,但不是所有的发动机都在船上。“船舶”和“发动机”的相关系数为 0.31。

“船”+“引擎”给出:

好了,现在有帆的船都走了。我们交叉核对一下。仅“引擎”的结果是:

所有这些东西都有引擎,但显然“引擎”并不自动意味着“带引擎的船”。看来有意义的插值原则上可能有这种视觉语义嵌入模型。注意我写出现可能。请记住,我们只看到了几张图片。

不过我不得不承认,我尝试的大多数两个单词的组合都没有产生任何有意义的结果。这可以归因于这样一个事实,我只为模型提供了大约 5000 张图片,以保持在 AWS 自由层内。你能找到其他很酷的组合吗?如果你有,请在评论中告诉我!

让我们试试 API 的另外两个函数。我们传递一张图片,并从存储的数据集中获得前五个零镜头预测和前四个语义最相似的图片。

“虾”和“对虾”都不是 ImageNet 中的类别:

Source

这张图片的前五个零镜头预测是:

***crayfish mosquitofish needlefish goosefish ladyfish***

谷歌“小龙虾”,我能理解为什么模型认为它们和虾语义相似。该应用程序的所有存储图像都来自 ImageNet,因此,该模型不能返回一只虾的图像。我认为四个中的三个在语义上是相似的。孩子在那里做什么,我一点线索都没有…

最后一次尝试是 ImageNet 中不包含的类别的图像。让我们尝试一个被包含的模型,看看这个模型是否在原则上是精确的,而不仅仅是找到相似的类。下图显示了一只蓝色松鸦,ImageNet 中存在类别“松鸦”,

Source

前五个零射击预测是:

***jay Jay bobby Starr Shawn***

并且来自存储的数据集中语义上最相似的图像是:

我是一名天体物理学家,不是鸟类学家,但对我来说,其中三只鸟的蓝白色羽毛位置正确,所以我认为这是一个成功。

到目前为止,我只给你们展示了成功的例子,但是当然,我也发现了几个预测是错误的例子。让我们试试这张图片:

Source

该模型返回以下前五个预测

***dog beagling poodle kelpie turnspit***

而下面这四张图即使“北极熊”是 ImageNet 类别!

当被要求展示“猫”类别的图片时,这个模型也会展示狗。

Source

然而,对于这张猫的图片,零命中率的预测是

***tabby fawn kitten cat grizzle***

并且该模型返回以下四幅语义相似的图片:

当要求图片语义上与单词“虎斑猫”相似时,我也会得到猫的图片…

如果您尝试其他单词或图片,并想找出某个特定单词是否属于 ImageNet 的任何类别,请下载该文件并在命令行中运行cat imagenet1000_clsidx_to_labels.txt | grep word

在这个资源库中,你可以找到一个笔记本来训练模型(基于 fastai),这是一个预训练的模型,以防你不想自己训练它,但想尝试应用程序,flask-app 将模型作为 API,关于如何使用 flask 开发服务器尝试应用程序的说明,以及关于如何在 Docker 容器中运行应用程序的说明。如果有兴趣学习 Docker 部署机器学习模型,可以考虑这门课。这要花几美元(我不是附属机构),英语也不完美,但我知道我到底在寻找什么来开始。

我发现这个视频对于在 AWS 上部署容器非常有帮助。只是一个警告:如果你试图在 AWS 上部署一个应用程序,并有资格获得 AWS 免费层服务(针对新客户),请确保使用 ec2 t2.micro 实例,因为其他实例没有资格免费使用。此外,请记住,没有“仅自由层帐户”,一旦您超出自由层限制,您将被计费。**

如果这篇论文发表在 2019 年,而不是 2013 年,我可以很好地想象一些媒体的标题:“谷歌科学家创造了一个能看、能说、能描述从未教过的东西的人工智能……机器人将杀死我们所有人。”好吧,我在这里故意夸大其词,但在所有这些宣传中,向人们解释什么是机器学习,什么不是机器学习是很重要的,特别是如果你属于那些能够理解的人。最终归结为以下几点:

[……]机器学习和深度学习的核心问题是有意义地转换数据:换句话说,学习手头输入数据的有用表示——这些表示让我们更接近预期的输出。[……]所有机器学习算法都包括自动寻找这种转换,将数据转化为对给定任务更有用的表示。[……]从技术上来说,这就是深度学习:一种学习数据表示的多阶段方法。这是一个简单的想法——但是,事实证明,非常简单的机制,如果规模足够大,最终可能看起来像魔术一样。(引自 Chollet,Franç ois,用 Python 进行深度学习)

将输入图像转换为单词向量而不是 n 类概率的想法非常简单,但它允许我们做令人惊讶的事情,因为单词嵌入是连续的,并允许我们测量图像与未知类别的相似性——只需将数据转换为更有用的形式!此外,与“传统的”深度学习图像分类器(只要能够找到描述图像的词)相比,该算法能够利用更大和更不精确的真实生活数据集,这可以显著提高视觉对象分类方法的质量。

我希望你能从这篇文章中得到乐趣,并且我能教你一些东西。如果你有问题,请在评论中告诉我,我很乐意帮助你理解:)

机器学习研究工作流程的开发运维

原文:https://towardsdatascience.com/devops-for-machine-learning-research-workflows-bfd054da9f9e?source=collection_archive---------24-----------------------

我从独自研究中学到的一些东西

第一次做机器学习研究?或者也许你已经在一家大型机构中这样做过,现在你正试图自己解决这个问题?这篇文章送给你!

近年来,我一直在从事几个项目,这些项目需要专注和严格的实证研究。我的大部分工作都是独自完成的,不同程度地受到其他人的间接影响。因此,我有机会完全从零开始建立我的研究工作流程。

因为大量的研究都花在了运行受控实验和快速迭代想法上,所以拥有一个有组织的和健壮的研究环境是至关重要的。从我花费的大量时间(以及我犯的许多错误)中,我发现改进我的研究工作流程需要问自己以下两个问题:

  1. 我能做些什么来提高我对工作结果的信心?
  2. 我如何缩短我的反馈周期,以便我可以更快地迭代?

下面介绍的三个想法都回答了上面的一个或两个问题。

使开发与生产相匹配

你一直在做一个项目,它在你的笔记本电脑上运行良好。但是现在是时候扩大规模了。您可能想要运行更强大的机器,或者您可能想要运行更多的机器,或者您可能只想在代码运行时玩英雄联盟。像正常人一样,你决定开始在云上运行你的代码。

The Cloud. (For the screenreaders, literal clouds in the sky.)

虽然使用云计算提供商可以让您在水平和垂直方向上扩展您的实验,但代价是您的反馈周期通常会变长。其中一个很大的原因是你几乎立即开始调试“它在我的机器上工作”的问题。

对此的处理是确保您的开发环境与您的“生产”环境紧密匹配[1]。这通过减少由于环境不匹配而发生的错误数量,缩短了您的反馈周期。

为了使您的环境相匹配,我建议创建一个 Docker 映像,您可以在您的开发机器上和云中使用它。或者,您可以在云中的专用计算实例上进行开发,并将该实例的克隆作为生产机器启动。你可以在【GCP】和 AWS 中使用磁盘快照来完成这项工作。

使用通用部署脚本

我在自己的设置中做的一件比较另类的事情是,我有一个通用的部署脚本。该脚本的目标是能够获取您在开发机器上运行的任何 shell 命令,并在生产机器上运行它。

该脚本有两个参数:一个标识符**job-name**和一个 shell 命令**cmd**。然后,它执行以下操作:

  1. **<cmd>**以及其他一些设置命令写到我的工作目录中的一个名为**run.sh**的文件中。
  2. 将我当前的工作目录(包含我所有的脚本和代码)打包到一个名为**<job-name>.zip**的文件中。
  3. 上传**<job-name>.zip**到云端。
  4. 启动一个实例,a)下载并解压**<job-name>.zip**,b)执行**run.sh**,c)自行关闭。

The deploy script in action. (Please ignore the fact that I’m trying to use Python to run a shell script here.)

这有两个主要好处:

  • 我可以确定在我的开发机器上运行的确切代码现在正在生产中运行。这减少了错误的发生,并且让我迭代得更快
  • 为了更好的再现性,我现在可以审计和重新运行任何曾经在生产机器上运行过的代码。这增加了我对结果的信心

处理数据

许多机器学习工作流(例如,任何涉及监督学习的工作)也涉及从大型数据集读取。要使数据集在开发和生产环境中保持同步,您可以做几件事:

  • 将数据包含在您的工作目录中。如果您有大量数据,这就不太好了,因为您必须在每次部署时将数据上传作为工作的一部分。
  • 在每台机器上维护单独的数据副本。如果您的数据不经常更改,这种方法还可以,但是如果您的数据经常更改,这种方法就很麻烦了。每次数据发生变化时,您都需要更新 Docker 映像或磁盘快照。
  • 将数据存储在对象存储器(如 S3)中,并在每个任务开始时下载数据。如果作业的执行时间不是由最初的数据传输决定的,那么这种方法非常有效。
  • 使用 NFS 在开发和生产机器之间同步数据。如果您不想编写用于访问文件的 S3 客户端代码,这是一个很好的选择。

下一节将讨论最后两种选择,并解释为什么我更喜欢后者。

使用 NFS 存储数据

在一个个人项目中,我用 GCS (GCP 的 S3 等价物)存储了一段时间的数据。使用 GCS 有很多好处:

  • 存储很便宜
  • 您可以存储数 Pb 的数据,而不会增加延迟
  • 通过向他人发送 URL,您可以轻松地与其他人共享数据
  • 您可以从任何地方访问 GCS

不幸的是,GCS 缺乏文件系统的易用性。这表现在几个方面[2]:

  • 浏览文件和目录是一件痛苦的事情。像“计算一个目录中文件的数量”这样的操作在文件系统中非常简单,但是在 GCS 中却非常困难。(这是因为 GCS 本身没有目录结构的概念。)
  • 编写代码很麻烦。任何涉及数据的操作都需要与 GCS 客户端库或gsutil命令行工具接口。
  • 大文件可能会带来问题。GCS 支持逐段流式文件,但是如果您的研究代码不支持,您需要首先将整个文件下载到您的本地系统。

我的研究工作流程非常适合使用文件系统,而不是像 GCS 这样的对象存储,所以我硬着头皮在 GCP 上建立了一个 NFS 服务器。之后,我配置了 Docker 实例和 Kubernetes 集群,以便在启动时挂载 NFS 服务器。

在切换到 NFS 之后,操作通常是这样的:

def load_model_state_from_path(path):
  fd, name = get_tmp_filename()
  logger.info('Downloading %s -> %s', path, name)
  blob = get_blob(path)
  with os.fdopen(fd, 'w') as ofd:
    blob.download_to_file(ofd)
  rv = torch.load(name)
  os.unlink(name)
  return rv

现在看起来像这样:

def load_model_state_from_path(path):
  return torch.load(path)

我在编写新代码中获得的便利使得快速迭代变得更加容易。通过一点点关于如何处理数据文件的训练(例如,使用版本控制方案,避免覆盖数据),你还可以对你的结果建立信心

建立 NFS

那么,我该如何在我的工作流程中设置 NFS 呢?您有两个主要选项:

使用交钥匙解决方案。这将是 AWS 上的 EFS 或 GCP 上的云文件存储。此解决方案易于设置,但维护成本很高(存储成本约为 0.20 美元至 0.30 美元/ GB /月)。

滚动你自己的 NFS 服务器。如果你有成本意识,这个解决方案是最好的。设置您自己的 NFS 服务器的成本是:

  • 每月 0.04 美元/ GB(比云文件存储节省 80%),此外
  • 大约每月 50 美元的开销(运行为 NFS 服务器提供动力的计算实例)

至少在 GCP,建立一个单节点文件服务器相当容易。

不管怎样,一旦 NFS 启动并运行,您需要将它连接到您的开发和生产机器。

  • 如果你在 GCP 上运行 Kubernetes(即谷歌 Kubernetes 引擎),本指南提供了你将 NFS 安装到豆荚上所需的一切。
  • 如果您在裸计算实例上启动作业(并且在 Linux 上),您将需要编辑您的/etc/fstab文件以将您的 NFS 挂载到实例上。这里有一个关于如何做的指南。
  • 另一个指南是专门针对 AWS 的,它将帮助您将 EFS 挂载到 EC2 实例上。

给自己发送电子邮件

A picture of my Gmail inbox, with many email notfications from various jobs.

当检查我过去的实验时,我会:

  • 强迫性地刷新 GCP 仪表盘,从而浪费时间,或者
  • 忘记我的实验几天(有时甚至几周)。

我对这个问题的解决方案非常简单:我让我的工作在达到令人满意的检查点时给我发电子邮件(例如,完成一次迭代培训)。这使得我的反馈周期尽可能的短,而不用我花任何时间检查我的实验。

你可以更进一步,在邮件中加入有用的信息。有一段时间,每当一个实验结束,我就手工绘制损耗曲线。为了让自己轻松一些,我现在让我的工作以编程方式生成损失曲线,并将它们附在我的电子邮件中。

当然,如果你发送的太多,电子邮件通知可能会适得其反。为了减少收件箱的混乱,我遵循以下两条原则:

  • 偏向于发送太少的邮件,而不是太多的邮件。
  • 如果有必要,利用你的电子邮件客户端的对话线程功能,给你自己发送相同主题的邮件。

对于个人项目,我会推荐 Mailgun 。集成到您的代码中非常简单,如果您每月发送的电子邮件少于 10,000 封,它也是 100%免费的。

最后的话

虽然我认为我在过去的几年里进步了很多,但我仍然认为我还有很多要学的。我很想听听你对这些技巧的想法,或者对你自己的环境有什么想法!

最初发表于www.yuzeh.com。感谢@ no diraZack阅读本帖的早期草稿。

脚注

  1. 这里我滥用了开发环境和生产环境的术语。我的开发环境是我编辑和测试代码的地方;通常,我会手动启动我的笔记本电脑或专用计算实例。我的生产环境是代码无需修改就能运行的地方;它通常是以编程方式启动的计算实例。
  2. 这里的难点描述了 GCS,但通常适用于许多存储系统,如 HDFS 或任何类型的数据库。虽然我不愿意说“文件系统”是轻松导航和存储数据的最终方式,但我确实认为大多数懂计算机的人在使用计算机的早期就接触到了文件系统,并且它最终成为一种非常熟悉的做生意的方式。

DevOps 安全性既令人不安又具有破坏性

原文:https://towardsdatascience.com/devops-security-is-as-disruptive-as-it-is-uncomfortable-670f19c916a0?source=collection_archive---------28-----------------------

各种规模的企业都越来越关注安全性。从小网点到大企业组织。在了解 DevOps 如何在这一领域产生影响时,重要的是要记住 DevOps“是什么”和“不是什么”DevOps 安全可能是一个重要的焦点,但必须以正确的方式进行。

DevOps 安全是什么样子的?

DevOps 就是很多东西。当然,这是一个工具,但不是“a”工具。它不是一个程序或一个软件。确切地说,是很多人。还有更多。在这个世界上,很多高层管理人员想知道“它是什么”“它要花多少钱”“要花多长时间”等等,这可能很难理解。

事实是所有这些事情,没有这些事情。从根本上说,DevOps 是人和过程的组合,包括将软件工程策略、技能、模式等渗透到生产环境中应用程序的操作中。

总之就是很多东西。

毫无疑问,安全性是 DevOps 开始涉足的一个领域。我们必须在运营基础上构建的相同模式和流程,也需要引入到安全领域。

为什么?首先,这样做对企业有利。我们生活在一个快节奏的环境中。只会越来越快。能够迭代地、快速地、迅速地开发和部署操作,意味着所有的领域都需要效仿。

这种情况下的安全性不能被视为事后的想法。也不能将其视为一个不考虑其他因素而无所不在的组成部分。我们不能把安全简单地看成一扇锁着的门。不管里面发生了什么,门都是锁着的,就是这样。

不,整个过程必须改变。因此,也需要改变思维。

不仅仅是新工具。当然,这可能是一部分。然而,我们还必须改变我们对安全形势的一些基本假设。

观念和期望的改变

这里有一个例子来说明我们所说的改变方法和假设是什么意思。我们曾经跟踪服务器的登录。有道理,对吧?因为“我们一直都是这样做的。”然而,我们不再需要这样做了。现在有许多方法可以接近 access。许多产品更高效、更安全、更快,等等。

我们需要交互式登录作为安全向量管理的基本假设的想法已经过时了。尽管如此,直觉上继续使用它是有意义的,那么为什么要改变呢?

毕竟我们只是想控制访问,对吗?如果这是我们安全设备的第一道防线,我们就跟踪登录。很简单。然而,事情并不一定是那样的。

这不是工具的问题

或者更准确地说,不仅仅是工具的问题。DevOps 安全性从提出“我首先真的需要它们吗?”明确一点:我们并不提倡无政府技术的环境,在这种环境中,没有什么是重要的,也没有什么是不重要的。当然,有些工具总是需要的。

然而,在交互式登录的情况下,这一基本功能已经不再需要了。只要承认并继续前进,事情就会朝着正确的方向发展。它从复杂的试探法和来自年复一年的工具和学习的规则转变为“让我们停止它。”

登录?谁需要登录?没有人。我们不需要他们。不再是了。

改变是艰难的

然而,这种关键的改变很难推进,因为你在与学习和已建立的工具做斗争。你在与“我们一直都是这样做的”和“嗯,这行得通”的心态作斗争。

你也在与通常回避破坏性变革的组织哲学作斗争。最终,这不仅仅是购买产品或使用工具的问题。这是一个过程,一种方法,以及让它发生的人。更重要的是,它是关于将所有这些东西整合在一起,让它们协调工作,同时采用一种新的整体方法。

这不仅仅是工程如何升级,或者运营和管理如何升级。更重要的是,所有这些学科在历史上是如何分裂成这些孤岛的,我们允许它这样做,因为我们无法再为业务做出足够快的变化。

这正是 DevOps 安全方法,一般来说,DevOps 就是要解决这个问题。安全性至关重要。它需要从看门人转变为推动者,以便与其他领域一起发展。

这是一个很难实现的转变。然而,在当今的环境中,它可以成就一个组织,也可以毁灭一个组织。

原载于 2019 年 10 月 11 日【https://introspectdata.com】

使用 TensorFlow.js 的逻辑回归预测糖尿病

原文:https://towardsdatascience.com/diabetes-prediction-using-logistic-regression-with-tensorflow-js-35371e47c49d?source=collection_archive---------10-----------------------

了解如何使用 TensorFlow.js 构建逻辑回归模型,并用于预测患者是否患有糖尿病

TL;DR 使用高层 API 在 TensorFlow.js 中构建逻辑回归模型,并预测患者是否患有糖尿病。了解如何可视化数据、创建数据集、训练和评估多个模型。

你已经在这个被遗忘的城市生活了 8 个多月了。除了家,你在任何地方都不会感到舒服。然而,这个地方树立了一个新的标准。干热和湿热之间的不断变化会很快杀死你。

网络连接时断时续,你已经超过两周没有收到你的家人的消息了。你不知道你的伴侣怎么样,你的孩子怎么样。你有时会质疑对国家的爱。

今天早上你感觉更糟。不断的饥渴。你已经尿了四次了,而且你的视力有些模糊。不仅仅是今天,至少一个星期以来你都有这种感觉。

你去看医生,她说你可能有糖尿病。你的父母都患有这种病,所以看起来很有可能。她不太确定,做了葡萄糖测试。不幸的是,你被叫到,应该在结果出来之前离开。

你要离开两周。只有几个人和你的笔记本电脑!你有几分钟时间下载糖尿病患者数据集。您已经安装了 TensorFlow.js 和整个 API 的副本。你能建立一个模型来预测你是否有糖尿病吗?

在你的浏览器中运行本教程的完整源代码:

糖尿病数据

糖尿病(Diabetes mellitus,DM)俗称糖尿病,是一组以长期高血糖为特征的代谢紊乱性疾病。高血糖的症状包括尿频、口渴和饥饿。如果不治疗,糖尿病会导致许多并发症。急性并发症包括糖尿病酮症酸中毒、高渗性高血糖状态或死亡。严重的长期并发症包括心血管疾病、中风、慢性肾病、足部溃疡和眼睛损伤。

截至 2017 年,全球估计有 4.25 亿人患有糖尿病(约 5.5%)

我们的数据来自 Kaggle 但在论文中首次介绍:使用 ADAP 学习算法预测糖尿病的发病

这项研究的人群是亚利桑那州凤凰城附近的皮马印第安人。自 1965 年以来,国家糖尿病、消化和肾脏疾病研究所一直对该人群进行持续研究,因为其糖尿病发病率高。每个 5 岁以上的社区居民被要求每两年进行一次标准化检查,包括口服葡萄糖耐量试验。根据世界卫生组织标准诊断糖尿病;也就是说,如果在任何调查检查中 2 小时后血浆葡萄糖至少为 200 mg/dl (11.1 mmol/l),或者如果服务于该社区的印度健康服务医院在常规医疗护理过程中发现葡萄糖浓度至少为 200 mg/dl。

以下是数据汇总:

  • Pregnancies -怀孕次数
  • Glucose -口服葡萄糖耐量试验中 2 小时的血浆葡萄糖浓度
  • BloodPressure -舒张压(毫米汞柱)
  • SkinThickness -三头肌皮褶厚度(mm)
  • Insulin - 2 小时血清胰岛素(μU/ml)
  • BMI——身体质量指数(\frac{weight}{height^2} 身高 2 体重单位为千克/米)
  • DiabetesPedigreeFunction -糖尿病谱系功能(DPF)
  • Age -年龄(岁)
  • Outcome -等级变量(0 -健康或 1 -糖尿病)

根据使用神经网络估计糖尿病概率的论文,DPF 提供:

亲属中的糖尿病史以及这些亲属与受试者的遗传关系的综合。DPF 使用来自父母、祖父母、兄弟姐妹、叔叔阿姨和堂兄妹的信息。它提供了受影响和未受影响的亲属对受试者最终糖尿病风险的预期遗传影响的测量。

皮马印第安人是谁?

皮马人(或 Akimel Oʼ odham,也拼写为 Akimel Oʼ otham,“河民”,以前被称为皮马)是一群居住在现在亚利桑那州中部和南部地区的美洲土著人。aki Mel o odham 幸存的两个部落的大多数人口居住在两个保留地:Gila 河印第安人社区(GRIC)的 Keli Akimel Oʼ otham 和 Salt 河 Pima-Maricopa 印第安人社区(SRPMIC)的 On 'k Akimel Oʼ odham。

读取数据

我们将使用 Papa Parse 库来读取 csv 文件。不幸的是,Papa Parse 不能很好地与await/async一起工作。让我们改变这一点:

我们使用dynamicTyping参数来指示 Papa Parse 从字符串转换数据集中的数字。让我们定义一个加载数据的函数:

并使用它:

干得好!我们有数据,让我们熟悉一下!

探测

虽然 tfjs-vis 很好,并且与 TensorFlow.js 很好地集成在一起,但它缺少(在撰写本文时)大量您可能需要的功能——覆盖图、颜色变化、比例定制等。这就是为什么我们将使用 Plotly 的 Javascript 库为我们的数据探索制作一些美丽的情节。

让我们来看看健康人和糖尿病人的分布情况:

在我们的数据集中,65%多一点的病人是健康的。这意味着我们的模型应该在 65%的时间里更加准确,这样才是好的。接下来——胰岛素水平:

请注意,这两个分布之间有很大的重叠。此外,数据集中有很多 0。似乎我们有很多缺失的价值观。NaNs 被替换为 0。

另一个重要因素是测试后的葡萄糖水平:

虽然有一些重叠,但这项测试似乎很好地区分了健康人和糖尿病患者。

让我们看看年龄:

一般来说,老年人似乎更容易患糖尿病。

也许我们应该看看年龄和血糖水平之间的关系:

这两者的结合似乎可以很好地区分健康和糖尿病患者。这可能会给我们的模型带来奇迹。

你可能想尝试的另一个组合是皮肤厚度与身体质量指数:

是的,这是可怕的,并没有告诉我们太多:)

预处理

目前,我们的数据位于一个对象数组中。不幸的是,TensorFlow 不能很好地处理这些问题。幸运的是,有 tfjs-data 包。我们将从我们的 CSV 文件中创建一个数据集,并使用它通过createDatasets()函数训练我们的模型:

features参数指定哪些列在数据集中。testSize是将用于测试的数据部分。batchSize当数据集被分割成块(批)时,控制数据点的数量。

让我们从提取数据中的特征开始:

我们将要素中缺失的值替换为 0。你可以试着不用这一步来训练你的模型,看看会发生什么?

让我们准备标签:

oneHot 的定义如下:

一键编码将分类变量(健康— 0 和糖尿病— 1)转换为一个数组,其中 1 对应于类别的位置,所有其他变量为 0。以下是一些例子:

1; // diabetic =>
[0, 1];

和健康:

0; // healthy =>
[1, 0];

让我们从我们的数据中创建一个数据集:

请注意,我们还使用 42 的种子来混洗数据:)

最后,让我们将数据分成训练和验证数据集:

我们使用 take 来创建训练数据集, skip 来省略验证数据集的训练示例,最后,使用批处理将数据分割成块。

此外,我们返回数据来测试我们的模型(稍后将详细介绍)。

逻辑回归

逻辑回归(与其名称相反)允许您从数据中获得二元(是/否)答案。此外,它给出了每个答案的概率。像这样的问题:

  • 这是垃圾邮件吗?
  • 我应该向老板要求更高的薪水吗?
  • 这个病人有糖尿病吗?
  • 这个人是真正的朋友吗?
  • 我的伴侣欺骗我吗?
  • 我对我的伴侣不忠吗?
  • 你明白我的意思吗?

如果有足够的数据,并且你足够幸运地相信所有这些问题都有答案,用逻辑回归是可以回答的吗?

但是我跑题了,让我们来看看逻辑回归的数学公式。首先,让我们从线性模型开始:

其中 x 是我们要用来训练模型的数据, b 1 控制斜率, b 0 控制与 y 轴的交点。

我们将使用 softmax 函数从线性模型中获取概率,并获得逻辑回归的广义模型。 Softmax 回归允许我们创建一个具有两个以上输出类别的模型(二元响应):

其中 b 1 定义曲线的陡度,而 b 0 左右移动曲线。

我们想利用我们的数据 X 和一些训练魔法来学习参数 b 1 和 b 0。让我们使用 TensorFlow.js 来实现它!

请注意,这个模型将给我们一个概率性的答案,而不仅仅是一个二元的反应。如果模型对某个预测不确定(例如低于 80%),您可能会决定忽略该预测。

预测糖尿病

让我们通过在 TensorFlow.js 中构建一个模型来将理论付诸实践,并预测患者的结果。

模型

请记住,构建逻辑回归模型的关键是线性模型,并对其应用 softmax 函数:

请注意,我们有 2 个输出,因为根据我们为训练模型而选择的功能,存在一次性编码和动态输入计数。是的,在 TensorFlow.js 中建立逻辑回归模型就是这么简单。

下一步是编译模型:

我们模型的训练过程包括最小化损失函数。这由我们提供的亚当优化器来完成。请注意,我们提供的学习率是0.001

学习率被称为超参数,因为它是您提供给模型使用的参数。它控制每个新的更新应该“覆盖”您的模型已经知道的内容的程度。选择“正确的”学习速度有点像巫术。

我们使用交叉熵损失(被称为对数损失)来评估我们的模型做得有多好。它(严厉地)惩罚分类模型给出的错误答案,基于它们给每一类的概率。定义如下:

其中 C 是类的数量, y 是二进制指示器,如果类标签是观察的正确分类,并且 po 是类 c 的预测概率。

请注意,我们请求 TensorFlow 记录准确性指标。

培养

让我们使用 fitDataset 使用我们准备的训练和验证数据集来训练我们的模型:

我们对我们的模型进行 100 个时期的训练(整个训练集显示给模型的次数),并使用 onEpochEnd 回调来记录可视化的训练日志。

我们将把所有这些打包到一个名为trainLogisticRegression的函数中,其定义为:

估价

让我们用目前为止我们已经建立的一切来评估我们的模型做得有多好:

请注意,我们仅使用葡萄糖水平来训练我们的模型。结果如下:

一点都不好。我们的模型比一个在 65%的时间里预测健康的假人表现更差。此外,损失从未真正开始下降。让我们尝试更多的数据:

更好的是,在训练期间损失值显著降低,并且我们在验证集上获得了大约 79%的准确度。让我们用一个混淆矩阵来仔细看看分类性能:

使用模型预测和测试集可以获得混淆矩阵:

即使我们的模型可能已经获得了更好的准确性,结果仍然是可怕的。与患糖尿病相比,健康被大大高估了。如果我们尝试一个更复杂的模型会怎么样:

这是该模型的混淆矩阵:

我们现在不研究这个模型,但是请注意,通过增加模型的复杂性,我们可以获得更好的结果。

结论

恭喜你!你建立并训练了不止一个,而是几个模型,包括逻辑回归,来预测病人是否患有糖尿病。你也遇到了现实世界——处理数据、训练和建立模型是很难的事情。此外,无论你有多少数据点,也不是一切都是可以预测的。

在你的浏览器中运行本教程的完整源代码:

也就是说,有一些方法可以改进构建和训练模型的过程。我们知道,在特定的环境下,使用某些技术比其他技术更好。嗯,机器学习是细致入微的:)

参考

  • 【Saed Sayad 博士的逻辑回归
  • tensor flow . js 简介

最初发表于https://www.curiousily.com

建立机器学习模型(特别是深度神经网络),可以轻松地与现有或新的 web 应用程序集成。想想您的 ReactJs、Vue 或 Angular 应用程序通过机器学习模型的强大功能得到了增强:

[## JavaScript 黑客的深度学习

建立机器学习模型(特别是深度神经网络),您可以轻松地与现有或新的网络集成…

leanpub.com](https://leanpub.com/deep-learning-for-javascript-hackers)

DialogFlow:构建语音机器人和聊天机器人的简单方法

原文:https://towardsdatascience.com/dialogflow-a-simple-way-to-build-your-voicebots-chatbots-27949a1ac443?source=collection_archive---------31-----------------------

了解 DialogFlow 的基础知识

如今,无论是 B2B 还是 B2C,企业都在很大程度上依赖聊天机器人来实现流程自动化和减少人工工作量。有各种各样的 NLP 聊天机器人平台被聊天机器人开发公司用来构建聊天机器人,其中最好的平台之一是 DialogFlow。该平台此前名为 API.AI,2016 年被谷歌收购,更名为 DialogFlow。

DialogFlow 是谷歌旗下的自然语言处理平台,可用于构建聊天机器人和语音机器人等对话应用。这是一个由人工智能驱动的平台,提供特定用途、引人入胜的语音和基于文本的对话。人类对话的复杂性仍然是机器缺乏的艺术,但特定领域的机器人是我们能够克服这些复杂性的最接近的东西。它可以与多个平台集成,包括 Web、脸书、Slack、Twitter 和 Skype。

对话流术语:

了解 DialogFlow 的基础知识

1.代理人:

DialogFlow 代理处理与最终用户的对话流。要开始使用 DialogFlow,首先,我们需要使用 Dialogflow 控制台创建一个代理。

它是意图、实体、集成和知识的顶级容器。代理将终端用户对话期间的文本或音频转换为应用和服务可以理解的结构化数据。

2.意图:

意图用于理解和处理用户意图和上下文,以指导与最终用户的对话流程。

意图包含一些训练短语及其相应的响应。

当一个意图的训练短语与用户输入相匹配时,它就会被调用。并向最终用户提供其响应中定义的输出。如果输入有多个响应,那么响应将随机显示给用户。

如果我们有多个具有相同训练短语的意图,那么或者更高优先级的意图将匹配,或者具有活动输入上下文的意图将匹配。

意向优先级:

如果用户输入有可能与多个意图匹配,则可以设置意图优先级。具有较高优先级的意图将被调用。

回退意图:

当用户输入与任何意图都不匹配时,调用回退意图。

当我们创建一个代理时,代理中会添加两个默认意图。

欢迎意图和默认回退意图。

上下文用于理解自然语言用户上下文。也就是用户想要信息的环境。

例如:

一个人可以输入“橙色是我最喜欢的。”

现在,这种橙色可以与颜色或水果搭配。那么在这种情况下应该匹配哪个意图呢?

为了解决这个问题,在 DialogFlow 中使用了上下文。

上下文生命周期:

上下文有一个保持活动的生命周期。默认的生命周期是 5 次请求,但是可以更改。

这意味着在接下来的五个匹配的意图中,上下文将存在更长时间。

上下文有两种类型:

a)输入上下文:

只有当具有一些输入上下文的意图的所有输入上下文都是活动的时,才可以匹配该意图。

比如:

我们有两个相同的训练短语“橙色是我最喜欢的。”

但是这两种意图有不同的输入环境。一个包含颜色作为输入上下文,而另一个包含水果作为输入上下文。

输入上下文活动的意图将与用户输入相匹配。

b)输出语境:

如果具有一些输出上下文的意图与用户输入匹配,则其所有输出上下文将被激活。

例如:

用户输入“你了解颜色吗?”的颜色意图匹配

它会回答用户“你最喜欢的颜色是什么?”输出上下文“颜色”可以由意图设置为活动的。

当用户说“橙色是我的最爱”时,输入上下文“颜色”的意图将与用户输入相匹配。

4.实体:

实体用于从最终用户输入中提取一些有用的信息和参数。实体可以是系统定义的,也可以是开发人员定义的。

DialogFlow 提供了许多预定义的实体,如日期、时间、颜色、温度,称为系统实体,以处理最流行的常见概念。

然而,自定义实体也可以由开发人员根据他们的需求来定义。

从用户输入中提取的参数可以在意图之间传递,以引导对话流。

5.回应:

代理可以向最终用户提供两种类型的响应。

a)默认响应。

b)丰富的回复。

a)默认响应:

默认响应也称为平台未指定响应。这些响应是显示给最终用户的简单文本响应。这些可以用于任何平台,包括网络,脸书,松弛。

b)丰富的响应:

丰富响应也称为特定于平台的响应。丰富的响应被用来显示按钮,卡片,快速回复,通过脸书,slack 平台到用户的链接。

然而,要在 web 应用程序中使用丰富的响应,聊天机器人需要定制。

丰富的响应可以通过 DialogFlow 控制台进行配置,也可以在 webhook 响应中发送。

6。Webhook:

可以集成一个 Webhook 来给出我们的应用程序的响应。Webhook 集成很简单,可以使用履行选项来实现。可以在那里配置一个 URL,并且对于您想要调用 webhook 的意图,webhook 调用需要被设置为活动的。

结论:

DialogFlow 是一个非常简单的平台,可以用最少的编码工作构建快速聊天机器人和语音机器人。它可以很容易地处理自然语言错误,并且可以与多种平台集成。它基本上是一个工具,允许建立聊天机器人,清楚地理解人类的对话,并在用相关参数解析对话后用适当的答案回复它们。更多了解可以参考这个链接。

原载于https://www . signity solutions . com/blog/dialog flow-voice bots-chatbots/2019 年 10 月 1 日。

80 年代真的有最多的昙花一现的奇迹吗?

原文:https://towardsdatascience.com/did-the-80s-really-have-the-most-one-hit-wonders-356d3c545f43?source=collection_archive---------10-----------------------

还是看数据会偷走我们的阳光?

注意:如果你对阅读我的想法或发现不感兴趣,只想直接跳到结果,点击这里。

所以在最近的一次公路旅行中,当我们听着保罗的《T2》时,我和我的家人都在问自己这个问题。

这让我想到——当我问我的朋友、同事或街上的陌生人时,每个人似乎都同意 80 年代是昙花一现的黄金时代。但事实真的是这样吗?80 年代真的有最多的一炮走红的奇迹吗?或者这只是那些我们都认为是真的事实之一,尽管事实并非如此,就像口香糖在你的胃里呆了 7 年?

显然这是一个我们必须解决的问题——用科学!

我最初的计划是在 BigQuery 中完成这一切,因为这是我的 jam 中的类 ,但是当我开始以容易查询的形式搜索 Billboard top 100 数据时,我在 data.world 上偶然发现了这个数据集,它似乎拥有我需要的一切。所以我最后用的就是这个。

请注意,我与这家公司没有任何关系,但我喜欢他们写得很好的服务条款,这很了不起。

获得每首歌曲的最高位置

因此,第一步是获取这个数据集(每周有一行是 Billboard Hot 100 中列出的歌曲),并将其压缩为一个列表,其中包含每首歌曲在排行榜中的最高位置以及它们达到最高位置的日期。

我最初有一个关于我如何做到这一点的更详细的分解,但我将跳过它,因为坦率地说,它并不那么有趣。

现在我们已经有了一个很好的数据集,让我们问自己一个更有趣的问题…

是什么让一击成名?

我最初的想法是,如果你只有一次进入公告牌百强,你就有资格成为一个昙花一现的奇迹。这里的问题是,进入热门 100 是一个真正的“击中”的慷慨定义。

你还记得,例如,80 年代的经典"夜脉"由重影(排行榜第 92 名)?我猜不会,除非你真的是“双重影像”乐队的前成员。

It’s as if Tommy Wiseau decided to direct music videos

同样,我认为 Kajagoogoo 是他们的歌曲“太害羞”的昙花一现。但是他们的第二首歌“坚持住”达到了 78 分。从技术上来说,他们会把两连击算作奇迹吗?大概不会。如果一次成功的奇迹的定义不包括 Kajagoogoo,这可能不是一个好的定义。哦,太好了。让我们把它放在引用中。

如果一次成功的奇迹的定义不包括 Kajagoogoo,这可能不是一个好的定义。

所以我决定,一个同样简单,但可能更准确的衡量一个热门奇迹的方法是简单地找到任何一个有一首歌达到 40 或更好排名的乐队。这似乎是一个很好的截止日期,因为前 40 名是美国文化的主要组成部分。

因此,让我们列出所有只有一首热门歌曲进入前 40 名的乐队,以及他们的热门歌曲名称、年代和排名:

好吧,这看起来很有希望。

然后,当然,很容易将这些按年代分组并计数。

十年来最大的轰动奇迹(初步发现)

那么,当我把这个列表按十年分组时,我们发现了什么呢?

没错。根据我们的数据,实际上 20 世纪 80 年代的昙花一现最少,而 2000 年代的昙花一现最多。我们完事了吗?我们能不能简单的指着我们的数据,喊 Whoomp!(就是它),继续前进?

好吧,等一下,因为我想解决两个数据问题。

眨眼 182 问题

根据我们的初步调查结果,Blink-182 被认为是一个昙花一现的奇迹,因为他们的歌曲中只有一首(“所有的小事”)实际上进入了前 40 名。其他一切都徘徊在 40 到 60 岁之间。我觉得这很奇怪。

我认为这很大程度上是因为,到了 90 年代,另类音乐变得更加主流。因此,有可能有一张五次获得白金的流行朋克专辑几乎没有进入前 100 名排行榜,因为这些单曲在 Billboard 替代排行榜上获得了成功。我猜有很多乡村和 R&B 的艺术家也属于这一类。

但这一切都不能真正原谅这样一个事实,即有许多乐队在技术上被认为是基于这一定义的昙花一现,只是感觉不对。这包括威泽,奥兹·奥斯朋,梅西·埃丽奥特,贝克,拉什和柏树山。

所以我决定将我对昙花一现的定义修改为:

如果一个艺术家有一首歌进入前 25 名,但没有其他歌曲进入前 75 名,那么他就被认为是一个成功的奇迹。

这很好地解决了 Weezer、Blink-182 等不再被认为是昙花一现的奇迹。但是,最重要的是,Kajagoogoo 仍然是。

所以,做了一点工作,我就可以重新运行我的查询来查找有一首歌在前 25 名,没有其他歌在前 75 名的乐队。

这产生了一个更小的每十年一次的奇迹列表(如果你仔细想想,这是有道理的),但当你把它们都分组在一起时,你仍然会看到 80 年代的一次奇迹最少。

同样有趣的是,2000 年有着最多的轰动奇迹。这实际上给我们带来了下一个问题…

二重唱的问题,以小客串为特色

如果你浏览这些结果,你会开始注意到有许多由二重唱组成的昙花一现的奇迹。

就拿“乌木和象牙来说吧。这首歌在排行榜上排名第一,从技术上来说,这是一个成功的奇迹,因为表演者“保罗·麦卡特尼和斯蒂维·旺德”再也没有一首歌登上排行榜。《肯尼·罗杰斯与多莉·帕顿对唱》也是如此,该片发行了《群岛在流》。但我不会把这些艺术家称为昙花一现的奇迹。除非我想被永远禁止进入好莱坞。

Ohh… on second thought, I might be okay with that.

所以让我们来看看名字中有“&”、“和”或“与”的艺术家,以及名字中有“特色”的艺术家。

我们可以看到,这个问题在大多数十年中相当一致(尽管在 20 世纪 60 年代“和”艺术家有少量增加)。也就是说,直到你达到 90 年代中期。从那里开始,加速到 2000 年及以后,你会看到大量的艺术家“扮演”另一个表演者。

所以,如果我们看一下早期的结果,你会发现《50 美分》和《阿肯》都多次被认为是昙花一现的奇迹(我知道这有点多余),因为他们的每首热门歌曲都有稍微不同的艺术家名字。

Both 50 Cent and Akon shouldn’t be on my one-hit wonder list. Afroman, you can stay.

现在,我可以通过使用一个小的正则表达式魔术来解决这个问题,将任何包含单词“Featuring”的艺术家姓名减少到首先列出的表演者。这意味着“以奈特·道格为特色的 50 美分”只是被认为是“50 美分”的点击率。

这个问题伴随着那个棘手的小词“And”(或“与”符号,或其他一些变体)。在某些情况下,将这些浓缩到首先列出的执行者可能是有意义的。这意味着你可以拿“大卫·鲍依&米克·贾格尔”的《在街上跳舞》来完全归功于大卫·鲍依——不管他愿不愿意。

问题是,没有办法仅凭名字来区分一个乐队名称中碰巧有一个&符号(如“船长与坦尼尔”)和一个真正的二重唱(如“阿撒·富兰克林与乔治·迈克”)。

在大多数情况下,这没什么大不了的。你只会得到一些奇怪的乐队名字。胡蒂&河豚现在只是“胡蒂”。但是在一些情况下,你最终会把两个完全不同的波段浓缩成一个。例如,80 年代的乐队“爱与火箭”和 70 年代的乐队“爱与吻”现在都被认为是同一个名为“爱”的艺术家。

好消息是,这种情况似乎非常罕见——我只发现了少数两个完全不同的波段合并成一个波段的例子。也许如果我真的在乎,我会想办法把这些非二重唱乐队从真正的二重唱中分离出来。但那比我现在想处理的工作要多得多。我认为就目前而言,结合这些艺术家的好处超过了少量的误报

十年来最大的轰动一时的奇迹(最终结果)

也就是说,这是我对 one hit wonders 的查询,其中一个 one hit wonders 至少有一首歌进入前 25 名,但没有其他歌曲进入前 75 名,任何二重唱或歌曲“主打”别人都归功于首先列出的艺术家。

最终的统计结果是什么样的?

你可以看到二重唱和客串的结合严重减少了 2000 年代的昙花一现的数量。在 20 世纪 60 年代有所减少,但没有你想象的那么多,因为有很多艺术家的名字中带有“和”的字样。我怀疑(但无法证明)这是因为这些艺术家很少是真正的二重唱,而更多的是像“兰迪&彩虹这样的名字的乐队

昙花一现的奇迹

由于篇幅原因,我不能在这里列出所有轰动一时的奇迹,但这里列出了按十年细分的轰动一时的奇迹:60 年代, 1970 年,80 年代,90 年代,2000 年代

但在这一切之后,我们最初的结果基本上仍然成立。20 世纪 80 年代的一次性奇迹最少,而 20 世纪 60 年代仍然最多。

这就引出了我们的下一个大问题…

为什么每个人都认为 80 年代有最多的轰动一时的奇迹?

那么,如果 80 年代的昙花一现最少,为什么看起来他们最多呢?我真的不知道,但这里有一些理论:

理论 1:80 年代是我们第一次接触流行音乐的时代

也许我们都认为 80 年代是最热门的奇迹,因为那是我们最初接触流行音乐的时代。也许如果我伴随着 60 年代的音乐长大,我会回忆起“我是一个女孩观察家”,就像我现在回忆“来吧艾琳”一样。

…or maybe not. I don’t think that song aged well.

但是,正如我的朋友萨姆指出的那样,他也认为 80 年代是昙花一现的巅峰,而他在 80 年代并不活跃。这大大削弱了我的理论。也让我觉得自己真的老了。谢谢你萨姆。

理论 2:80 年代有最好的昙花一现的奇迹

因此,如果你曾经查看过“有史以来最受欢迎的单曲榜”,你会发现它们通常都是 80 年代的歌曲。会不会是 80 年代简单地创造出了更好的昙花一现的奇迹?因此,这十年与昙花一现的奇迹联系在一起,因为它有太多太棒的奇迹了?

To be fair, nobody can pull off a bagpipe solo like The Church

这里我有点怀疑。我可能把因果关系搞混了。如果我们走来走去都认为 80 年代是昙花一现的年代,那么当有人投票给我们列出最伟大的昙花一现的奇迹时,我们可能会自然而然地想到我们最喜欢的 80 年代的热门歌曲。

Photo by israel palacio on Unsplash

但仍然值得研究。显然,要客观地判断出哪一个创造的奇迹是“最好的”是很难的。但是作为一个次要特征,我们可以看看这些昙花一现的奇迹在公告牌百强榜上停留了多长时间,以及它们的顶峰有多高。如果一首歌很好(或至少令人难忘),你会希望它在排行榜上停留更长时间或达到更高的最高评级。

那么,当我们按十年细分这些统计数据时,会发生什么呢?

哼。嗯,看起来数据并不能真正支持我的理论。说到平均排名,这几十年是非常相似的。说到昙花一现的歌曲在排行榜上停留的时间更长,的确,60 年代和 70 年代的热门歌曲更短暂,但 90 年代的歌曲似乎在排行榜上停留的时间最长。

哦,如果你好奇的话,那是在最长的一段时间里排名前 100 的昙花一现的奇迹吗?邓肯·谢克的《勉强呼吸》,在排行榜上呆了整整 55 周。

Also, if you haven’t ever listened to the acoustic version of Barely Breathing, you really should.

理论三: 视频杀了电台明星

我的最后一个理论是,MTV 在某种程度上对这一切负有责任。

仔细想想,80 年代是 MTV 在音乐视频影响力上如日中天的时代。网络变得越来越受欢迎,但真人秀还没有接管,所以大多数节目是实际的音乐视频。还有(嗨,小朋友们!)这一切都发生在 YouTube 出现之前。

这意味着,与 60 年代和 70 年代不同,我们更多地注意到了一个奇迹,因为我们不仅仅是在收音机里听到它们;我们每天都在客厅里看到他们,接触到音乐背后的乐队——不仅仅是歌曲。

但与 90 年代末和 21 世纪初不同的是,看音乐视频没有其他选择,更不用说选择你要看的视频了。如果你想看音乐视频,你真的只有一个选择(好吧,如果算上 VH-1 的话是两个),而且主要是流行音乐。

所以,也许我们都记得 80 年代是昙花一现的时代的原因是因为那时它们是我们客厅的焦点,这种现象变得更加明显。然后,这一名称就流传下来并影响了后代。

It’s probably also the reason we all think A-ha was a one-hit wonder, even though they’re not (see below)

我不知道这是否正确——但这是我迄今为止最好的理论。

其他有趣的事实

有史以来最大的昙花一现的奇迹是什么?

历史上有许多伟大的昙花一现的奇迹,但谁是最昙花一现的呢?我决定列出一份艺人名单,a)有一首歌在排行榜上排名第一,但 b)再也没有另一首歌出现在前 100 名中。

他们在这里,按时间顺序排列在图表上…

不是我认为的昙花一现的乐队

有几个乐队不是昙花一现,因为他们还有其他一些我忘记的小热门:

  • 阿哈有"承担 M e" (#1),但他们也有"太阳永远照在电视上 " (#20)和"狼来了 " (#50)
  • 梦幻学院有北方小镇的生活,但是他们也有爱情游行
  • 卡特里娜和海浪有"走在阳光下 " (#9),但他们也有"就是这样 " (#16)和"你要哭吗 " (#37)
  • 大国有“在一个大国里”(#17),但他们也有“战场”(#52)
  • 极端有"多于文字 " (#1),但他们也有"空洞的心 " (#4)
  • 《生死时速》有“让我围着转”(#11),但他们也有“全新的情人”(# 15)

同样,有几个乐队不是昙花一现,因为他们的歌曲没有我想象的那么成功

  • “视频杀死了电台明星”的 Buggles 仅在第 40 名达到顶峰
  • “与你融为一体”到了现代英语顶峰才排在第 76 位
  • 她又来了,洛杉矶的巅峰时期只有第 49 位(但是六便士的版本并没有变得更富有,它的巅峰时期是第 32 位,这阻止了这个乐队的昙花一现)
  • 原始人的《撞车》、Semisonic 的《T2》【关门时间】、原始人电台大神的《站在破电话亭外手里拿着钱的 T4》甚至都没进热门 100 强。听到这个消息让我…沮丧,宝贝。

解释为什么 90 年代为我们提供了惊人相似的昙花一现的奇迹。“经 95 南”嗖!(就是它)”的标签团队,以及为什么后者被证明在长期内更令人难忘

我发现了这个命题的一个真正不可思议的证明,这个中等的文章太窄了,无法包含。

已经结束了,为什么不呢?

所以你去吧,伙计们;所有你想知道但又不敢问的关于一次性奇迹的事情。如果您有兴趣进一步研究数据,请继续查看该项目!也许你会发现一些我没有发现的见解。毕竟,每个人都得在某个时候学习。

[## 一击即中的奇迹 toddarooski 的项目

让我们弄清楚——80 年代真的是一炮走红奇迹最多的十年吗?

数据世界](https://data.world/toddarooski/one-hit-wonders)

你遇到谷歌数据集搜索了吗?

原文:https://towardsdatascience.com/did-you-meet-google-dataset-search-2d04858de20f?source=collection_archive---------14-----------------------

谷歌搜索引擎搜索来自世界各地的数据集

几周前,我写了一篇文章,讲述了当开始一个新的 DS/ML 项目时,我们通常会面临的那种决定

  • 话题
  • 难度水平
  • 项目的目标
  • 我们会有观众吗?
  • 时间和期限

这五点当然很重要,但除此之外,如果我们没有任何数据,我们就没有任何项目。数据为王。如果你不知道如何得到它,那么你就一无所有。除此之外,在我以前的文章中,我强调了一些你应该问自己的重要问题,关于来源、格式和必要的行动,以使自己掌握数据。

现在…如果我告诉你,有一个,在那里你可以搜索成千上万的数据集,而且仅仅是来自世界各地的数据集,有几种格式,并且你可以很容易发现和访问?除了谷歌还有谁能提供这样的东西呢?欢迎来到数据集搜索…这不是什么新东西,但仍处于测试阶段——谷歌的数据集搜索引擎。

现在,如果你正在读这篇文章,并且在想:好吧,数据已经可以在网上获得了,这实际上并没有提供什么新的东西。公平地说,这实际上是真的。但是搜索数据可能会很麻烦,有时很难区分好的/真实的/完整的/可靠的和坏的/错误的/不完整的/不可靠的数据。这就是为什么,正如谷歌在推出该工具时所说,数据集搜索的诞生是为了方便访问网络上成千上万的数据仓库,提供对数百万数据集的访问;世界各地的地方和国家政府也发布他们的数据。

数据集搜索在移动和桌面上都可用,它已经在几种语言中工作,并且很快会有更多语言,除了搜索引擎之外,它没有任何科学。如果你知道如何使用谷歌主搜索引擎,那么你就会知道如何使用数据集搜索。只需键入您要查找的内容,Google 就会提供出版商提供的尽可能多的信息,包括:

  • 源代码中下载页面的直接链接
  • 谁在提供数据集
  • 可用下载格式
  • 涵盖的时间段
  • 覆盖面积
  • 测量的变量
  • 以及数据集的简要描述

例如,我来自乌拉圭,所以我搜索“乌拉圭互联网渗透率”得到 37 个结果(有趣的是:自从我写了这篇文章并发表后,这个数字从 36 变成了 37)。考虑到我们谈论的是南美洲的一个小国,我个人认为这个数字相当可观。如果我们对英国进行同样的搜索,数据集搜索已经显示+100 个可用结果。

在 The Verge 不久前发表的一篇文章中,开放数据研究所的首席执行官林洋·坦尼森说:

“谷歌的参与应该有助于该项目取得成功(……)数据集搜索一直是一件难以支持的事情,我希望谷歌的介入将使它变得更容易”

当然,数据集搜索仍然有其局限性。正如你可以看到的权利时,进入它仍处于测试阶段。尽管谷歌还没有给出任何更新,但像高级搜索或过滤数据大小或列数这样的功能可能很快就会出现。

现在,如果你正在阅读这篇文章,并且你在网上某处有一个已发布的数据集,请仔细阅读下面几行:正如任何搜索引擎一样,数据集搜索将会变得越来越有用,因为人们可以获得越来越多的数据集。为此,谷歌正在遵循一种基于描述信息的开放标准(schema.org)的方法,任何发布数据的人都可以这样描述他们的数据集。此外,Google 还定义了一些标准来描述数据并使用户能够找到数据。因此,如果你想让你的数据出现在数据集搜索中,请访问谷歌关于数据集提供者指南的说明,以及开发者网站,其中也包括提问和提供反馈的链接。

以下是一些谷歌称之为数据集的例子:

  • 包含一些数据的表格或 CSV 文件
  • 一组有组织的桌子
  • 包含数据的专有格式的文件
  • 共同构成一些有意义的数据集的文件集合
  • 一种其他格式的数据对象,使用特殊工具进行处理
  • 图像捕捉数据
  • 与机器学习相关的文件,如训练参数或神经网络结构定义

总而言之,无论你是一名经验丰富的研究人员还是像我一样热衷于数据科学家,你都应该对这一举措感到兴奋,并愿意传播消息,扩大当前可用数据集的数量。这非常好,不仅对数据科学界,而且对任何寻找数据集的人都是如此。我已经在着手发布我的一些数据,尤其是一个数据集,其中有我前段时间构建的数百名足球运动员的统计数据,当时我试图预测他们的市场价值。与此同时,请随意查看我的 GitHub 库并下载该数据,或者您可能找到的任何其他数据:)

别忘了看看我最近写的一些关于 6 个业余错误的文章,这些错误是我在使用火车测试分割、5 分钟内抓取网页或其他任何在我的个人资料中可以找到的。另外,如果你想直接在你的邮箱里收到我的最新文章,只需 订阅我的简讯 😃

jupytext——随心所欲地改变你的 Jupyter 笔记本

原文:https://towardsdatascience.com/diff-your-notebook-as-you-want-jupytext-e5df4db682f7?source=collection_archive---------13-----------------------

Jupyter 笔记本已经成为许多数据科学家的首选工具,由于能够逐个运行单元,它已经广泛用于教育。事实上,笔记本是一个巨大的 JSON 文件,这使得它很难与 git 等工具一起工作,如果你想看看 Jupyter 笔记本的输出,nbdime 是一个很好的替代选择,我在大约六个月前写了一篇关于 nbdime 的帖子。

nbdime 很棒,但是它不能很好地与像 VS Codes 和 PyCharm 这样的 ide 一起工作。如果有一个工具可以让你使用笔记本,但你可以像脚本一样不同,那该怎么办?有一个简单的解决方案——Jupytext。Jupytext 的神奇之处在于,它可以自动将您的笔记本与. py 脚本配对(您也可以与。html/。md 等……)。这是一个简单而有效的解决方案,让你享受双方的利益。这一对笔记本-脚本解锁了一些很酷的东西。

  1. 像笔记本一样打开一个. py 脚本
  2. 版本控制简单
  3. Jupyter 笔记本的完整 IDE 重构功能

1.像打开笔记本一样打开. py 脚本

你可以用这个命令很容易地安装 Jupytext,它会安装 Jupytext 和笔记本扩展。

pip install jupytext

You can open a py script like a .ipynb file with Jupyter notebook

如果你注意了文件名,它实际上是一个. py 文件,但是你可以把它当作一个笔记本。您可以以各种方式交互处理该文件,只是它仍然是一个. py 文件,因此输出不会缓存在脚本文件中,它只存在于您的浏览器中。

将你的笔记本与脚本配对

使用笔记本扩展,只需点击一下鼠标即可配对您的笔记本。在这里,我把我的笔记本和轻型脚本配对。如果你不在乎它是什么格式,就使用轻量级脚本。根据 Jupytext 文档,这些是当前支持的格式。

Markdown 和 R Markdown 文档,Julia,Python,R,Bash,Scheme,Clojure,Matlab,Octave,C++和 q/kdb+脚本。

File → Jupytext →Pair Notebook with script

2.版本控制很容易

它将您的笔记本与脚本配对的事实意味着,嗯,您可以对。py 文件。笔记本不必再添加到存储库中,只要您想要显示输出。

Simply diff the .py file instead of the .ipynb file !

3。笔记本电脑的全面重构功能

Jupytext 非常努力地想弄清楚你们配对的笔记本和脚本的变化。如果您在笔记本上进行更改,脚本将同时更新。

Sync Notebook with the script!

这是我正在做的事情的描述。

  1. 在 VS 代码中进行重构
  2. 保存脚本文件。
  3. 按 F5 刷新笔记本以获取新的更改

Refactor in IDE -> Refresh in Notebook and continue

结论

这是我使用 Jupytext 最常见的用例,但是它可以做更多的事情。请查看他们的 Github 页面,了解更多高级用法。Marc 自己也写了一篇关于 Jupytext 1.0 发布的博客,他在博客中详细解释了该功能。让我们对笔记本进行更多的重构。

局部响应标准化和批量标准化的区别

原文:https://towardsdatascience.com/difference-between-local-response-normalization-and-batch-normalization-272308c034ac?source=collection_archive---------2-----------------------

深度神经网络中使用的不同规范化技术的简短教程。

为什么要正常化?

归一化对于深度神经网络已经变得很重要,深度神经网络补偿某些激活函数的无界性质,例如 ReLU、eLU 等。使用这些激活函数,输出层不会被限制在一个有限的范围内(例如[-1,1]代表 tanh ),而是可以增长到训练允许的高度。为了限制无限制激活增加输出图层值,在激活函数之前使用了归一化。深度神经网络中使用了两种常见的规范化技术,并且经常被初学者误解。在本教程中,将讨论这两种规范化技术的详细解释,突出它们的主要区别。

局部响应标准化

本地响应规范化(LRN)首先在 AlexNet 架构中引入,其中使用的激活函数是 ReLU ,而不是当时更常见的 tanhsigmoid 。除了上述原因,使用 LRN 的原因是为了促进侧抑制。它是神经生物学中的一个概念,指一个神经元降低其邻居活动的能力[1]。在 DNNs 中,这种横向抑制的目的是执行局部对比度增强,使得局部最大像素值被用作下一层的激励。

LRN 是一个不可训练层,它在局部邻域内对特征图中的像素值进行平方归一化。基于所定义的邻域,有两种类型的 LRN,如下图所示。

通道间 LRN: 这是 AlexNet paper 最初使用的。定义的邻域是穿过通道的。对于每个(x,y)位置,归一化是在深度维度上进行的,并由以下公式给出

LRN used in AlexNet [2]

其中 i 表示滤波器 I 的输出, a(x,y),b(x,y) 分别为归一化前后 (x,y) 位置的像素值,N 为通道总数。常数 (k,α,β,n) 是超参数。 k 用于避免任何奇点(被零除), α 用作归一化常数,而 β 是对比常数。常数 n 用于定义邻域长度,即在执行归一化时需要考虑多少个连续的像素值。( k,α,β,n)=(0,1,1,N) 的情况为标准归一化)。在上图中,当 N=4 时,N 等于 2。

让我们看一个通道间 LRN 的例子。请看下图

不同的颜色表示不同的通道,因此 N=4。假设超参数为( k,α,β,n)=(0,1,1,2)。**n = 2的值意味着在计算位置 (i,x,y) 的归一化值时,我们考虑上一个和下一个滤波器在相同位置的值,即 (i-1,x,y)(i+1,x,y) 。对于 (i,x,y)=(0,0,0) 我们有值(I,x,y)=1值(i-1,x,y) 不存在,值(i+,x,y)=1 。因此 normalized_value(i,x,y) = 1/( + ) = 0.5 ,可以在上图的下半部分看到。其余的标准化值以类似的方式计算。

信道内 LRN: 在信道内 LRN 中,邻域仅在同一信道内扩展,如上图所示。该公式由下式给出

其中(W,H)是特征图的宽度和高度(例如上图中的(W,H) = (8,8))。通道间和通道内 LRN 的唯一区别是归一化的邻域。在通道内 LRN 中,在所考虑的像素周围定义了 2D 邻域(与通道间的 1D 邻域相反)。例如,下图显示了在 n=2(即大小为(n+1)x(n+1)的 2D 邻域以(x,y)为中心)的 5×5 特征图上的通道内归一化。

批量标准化:

批量标准化(BN)是一个可训练层,通常用于解决 内部协变量移位(ICF)【1】的问题。 ICF 的产生是由于隐藏神经元分布的改变/激活。考虑下面这个二元分类的例子,我们需要对玫瑰和非玫瑰进行分类

Roses vs No-roses classification. The feature map plotted on the right have different distributions for two different batch sampled from the dataset [1]

假设我们已经训练了一个神经网络,现在我们从数据集中选择两个明显不同的批次进行推断(如上所示)。如果我们对这两个批次进行正向传递,并绘制隐藏层(网络深处)的特征空间,我们将看到分布的显著变化,如上图右侧所示。这称为输入神经元的 协变移位 。这在训练时有什么影响?在训练期间,如果我们选择属于不同分布的批次,那么它会减慢训练,因为对于给定的批次,它会尝试学习某个分布,而该分布对于下一批次是不同的。因此,它不断地在分布之间来回跳跃,直到它收敛。这个 协变偏移 可以通过确保一个批次内的成员不属于相同/相似的分布来减轻。这可以通过随机选择批量图像来完成。隐藏神经元也存在类似的协变量移位。即使这些批次是随机选择的,隐藏的神经元也可能最终具有某种分布,从而减慢训练速度。隐藏层的这种协变量移位称为内部协变量移位。问题是我们不能像对输入神经元那样直接控制隐藏神经元的分布,因为它会随着训练更新训练参数而不断变化。批处理规范化有助于缓解这个问题。

在批量标准化中,隐藏神经元的输出在被馈送到激活函数之前以下面的方式被处理。

  1. 将整批 B 标准化为零均值和单位方差
  • 计算整个小批量产量的平均值: u_B
  • 计算整个小批量产量的方差:s igma_B
  • 通过减去平均值并除以方差来标准化小批量

2.引入两个可训练参数( Gamma: scale_variable 和 Beta: shift_variable)来缩放和移动标准化小批量输出

3.将该缩放和移位的标准化小批量馈送到激活功能。

BN 算法可以在下图中看到。

Batch Normalization Algorithm [2]

在一批所有激活中对每个像素进行归一化。考虑下图。让我们假设我们有一个 3 号的小批量。隐藏层产生大小为(C,H,W) = (4,4,4)的激活。由于批量大小是 3,我们将有 3 个这样的激活。现在,对于激活中的每个像素(即,对于每个 4x4x4=64 像素),我们将通过找到所有激活中该像素位置的平均值和方差来对其进行归一化,如下图的左部所示。一旦找到平均值和方差,我们将从每次激活中减去平均值,然后除以方差。下图的右半部分描述了这一点。减法和除法是逐点进行的。(如果你习惯 MATLAB,除法就是点分。/ )。

步骤 2(即缩放和移位)的原因是让训练决定我们是否需要归一化。在某些情况下,不进行规范化可能会产生更好的结果。因此,BN 不是预先选择是否包括归一化层,而是让训练来决定。当 Gamma = sigma_BBeta = u_B 时,不进行归一化,恢复原始激活。吴恩达在 BN 上的一个非常好的视频教程可以在这里找到

比较:

LRN 有多个方向来跨(通道间或通道内)执行归一化,另一方面,BN 只有一种执行方式(针对所有激活中的每个像素位置)。下表比较了这两种标准化技术。

参考文献:

[1]https://www . learnopencv . com/batch-normalization-in-deep-networks/

[2]约菲、谢尔盖和克里斯蒂安·塞格迪。"批量标准化:通过减少内部协变量转移加速深度网络训练." arXiv 预印本 arXiv:1502.03167 (2015)。

奖金:

可以在下面的链接中找到这个主题和机器学习中许多其他重要主题的紧凑备忘单

[## 机器学习面试主题的备忘单

ML 面试的视觉备忘单(www.cheatsheets.aqeel-anwar.com)

medium.com](https://medium.com/swlh/cheat-sheets-for-machine-learning-interview-topics-51c2bc2bab4f)

如果这篇文章对你有帮助,欢迎鼓掌、分享和回复。如果想了解更多关于机器学习和数据科学的知识,请关注我@Aqeel an war或者在LinkedIn上与我联系。

用 Python 代码解释 NFD、NFC、NFKD 和 NFKC 之间的区别

原文:https://towardsdatascience.com/difference-between-nfd-nfc-nfkd-and-nfkc-explained-with-python-code-e2631f96ae6c?source=collection_archive---------6-----------------------

Unicode 规范化形式之间的区别

Photo by Joel Filipe on Unsplash

最近我在做一个日文的 NLP 任务,其中一个问题是将特殊字符转换成标准格式。所以我做了一些调查,为有同样需求的人写了这篇文章。

日语包含不同形式的字符,例如,拉丁语有两种形式,全角形式和半角形式。

在上面的例子中,我们可以看到全幅形式是非常丑陋的,也很难利用后续的处理。所以我们需要把它转换成规范化的形式。

TL;速度三角形定位法(dead reckoning)

使用NFKC方法。

>>> from unicodedata import normalize
>>> s = "株式会社KADOKAWA Future Publishing"
>>> normalize('NFKC', s)
株式会社 KADOKAWA Future Publishing

Unicode 规范化形式

from Wikipedia

有 4 种 Unicode 规范化形式。这篇文章给出了非常详细的解释。但我会用一种简单易懂的方式解释其中的区别。

首先,我们可以看到下面的结果以获得直观的理解。

アイウエオ ==(NFC)==> アイウエオ
アイウエオ ==(NFD)==> アイウエオ
アイウエオ ==(NFKC)==> アイウエオ
アイウエオ ==(NFKD)==> アイウエオ
パピプペポ ==(NFC)==> パピプペポ
パピプペポ ==(NFD)==> パピプペポ
パピプペポ ==(NFKC)==> パピプペポ
パピプペポ ==(NFKD)==> パピプペポ
パピプペポ ==(NFC)==> パピプペポ
パピプペポ ==(NFD)==> パピプペポ
パピプペポ ==(NFKC)==> パピプペポ
パピプペポ ==(NFKD)==> パピプペポ
abcABC ==(NFC)==> abcABC
abcABC ==(NFD)==> abcABC
abcABC ==(NFKC)==> abcABC
abcABC ==(NFKD)==> abcABC
123 ==(NFC)==> 123
123 ==(NFD)==> 123
123 ==(NFKC)==> 123
123 ==(NFKD)==> 123
+-.~)} ==(NFC)==> +-.~)}
+-.~)} ==(NFD)==> +-.~)}
+-.~)} ==(NFKC)==> +-.~)}
+-.~)} ==(NFKD)==> +-.~)}

这 4 种形式有两种分类方法。

# 1 original form changed or not
- A(not changed): NFC & NFD
- B(changed): NFKC & NFKD# 2 the length of original length changed or not
- A(not changed): NFC & NFKC
- B(changed): NFD & NFKD

1 .是否改变了原来的形式

abcABC ==(NFC)==> abcABC
abcABC ==(NFD)==> abcABC
abcABC ==(NFKC)==> abcABC
abcABC ==(NFKD)==> abcABC# 1 original form changed or not
- A(not changed): NFC & NFD
- B(changed): NFKC & NFKD

第一种分类方法是基于原始形式是否改变。更具体地说,A 组不包含K,但是 B 组包含KK是什么意思?

D = Decomposition 
C = Composition
K = Compatibility

K意为兼容,用来与原始形态相区别。因为K改变了原来的形式,所以长度也改变了。

>>> s= '…'
>>> normalize('NFKC', s)
'...'>>> len(s)
1
>>> len(normalize('NFC', s))
1
>>> len(normalize('NFKC', s))
3
>>> len(normalize('NFD', s))
1
>>> len(normalize('NFKD', s))
3

2 原始形式的长度是否改变

パピプペポ ==(NFC)==> パピプペポ
パピプペポ ==(NFD)==> パピプペポ
パピプペポ ==(NFKC)==> パピプペポ
パピプペポ ==(NFKD)==> パピプペポ# 2 the length of original length changed or not
- A(not changed): NFC & NFKC
- B(changed): NFD & NFKD

第二种分类方法是基于原始格式的长度是否改变。一组包含C(构图),不会改变长度。b 组包含D(分解),会改变长度。

你可能想知道为什么长度是变化的?请看下面的测试。

>>> from unicodedata import normalize
>>> s = "パピプペポ"
>>> len(s)
5
>>> len(normalize('NFC', s))
5
>>> len(normalize('NFKC', s))
5
>>> len(normalize('NFD', s))
10
>>> len(normalize('NFKD', s))
10

我们可以发现“分解”法使长度加倍。

from Unicode 正規化とは

这是因为NFD & NFKD将每个 Unicode 字符分解成两个 Unicode 字符。比如ポ(U+30DD) = ホ(U+30DB) + Dot(U+309A)。所以长度从 5 变到 10。NFC & NFKC将分开的 Unicode 字符组合在一起,因此长度不变。

Python 实现

您可以使用 unicodedata 库获得不同的表单。

>>> from unicodedata import normalize
>>> s = "パピプペポ"
>>> len(s)
5
>>> len(normalize('NFC', s))
5
>>> len(normalize('NFKC', s))
5
>>> len(normalize('NFD', s))
10
>>> len(normalize('NFKD', s))
10

长度

拿走

通常,我们可以使用NFKC or NFKD中的任何一个来获得规范化形式。只有当你的 NLP 任务对长度敏感时,长度才不会带来麻烦。我一般用NFKC的方法。

查看我的其他帖子 中等 一分类查看
GitHub:
bramble Xu LinkedIn:徐亮 博客:bramble Xu

参考

  • https://unicode.org/reports/tr15/#Norm_Forms
  • https://www . wiki wand . com/en/Unicode _ equivalence #/Normal _ forms
  • http://nomenclator.la.coocan.jp/unicode/normalization.htm
  • https://maku77.github.io/js/string/normalize.html
  • http://tech.albert2005.co.jp/501/

套索、脊和漏失正则化—它们对共线性的影响

原文:https://towardsdatascience.com/different-forms-of-regularization-and-their-effects-6a714f156521?source=collection_archive---------11-----------------------

介绍

这是我上一篇业余的、晦涩的文章的续篇——关于正规化的简短说明。这篇文章提供了它所承诺的东西,但它不足以回答这些问题——正则化做了什么,为什么它可以工作,而相应的没有正则化的模型却不能?本文的目的是试图用线性代数(正规方程)和统计学(估计量的偏差-方差权衡)来回答这些问题。

让我们假设感兴趣的隐藏层的工程变量为 X 或 X,这是输入特征 Z 或 Z 的函数。在本文中,我们假设截距为 0,因为在一般情况下截距不会缩小。为简单起见,我们将导出线性回归的分析结果并将结果推广到逻辑回归,假设 真实模型在(工程)特征的空间中是线性的

重要

Collinearity problem in linear regression. Image source: https://medium.com/@rrfd/what-is-ridge-regression-applications-in-python-6ed3acbb2aaf

我有意以机器学习中正则化的重要性开始这篇文章。这一部分可能含义模糊;本文的其余部分将从头开始构建思路,试图理解这些模糊的陈述。

  • 沿着具有 h 个神经元的全连接隐藏层对深度神经网络进行切片,得到具有 h 个特征的更小的下游神经网络
  • 如果上面选择的隐藏层是输出层之前的层,则生成的神经网络相当于逻辑回归
  • 可以应用于线性/逻辑回归的简单线性代数可以扩展到深度神经网络,该深度神经网络在完全连接的隐藏层被切片

线性回归

模型定义

True model, unknown

估计的

Estimated

损失函数

Square loss in terms of matrix product

解决办法

ML / OLS estimate for coefficients

阅读:线性回归中极大似然估计和 OLS 的等价性

解析

Normal equation — MLE by analytical method

L2 正则化线性回归

模型定义

True model, unknown

估计的

Estimated

损失函数

Loss in terms of matrix product

解决办法

Solution

解析

Ridge estimate using analytical method

理解差异

考虑一种设计矩阵不是满秩的情况(我上一篇文章中定义的几种情况:正则化的简短说明)。因此协方差矩阵是不可逆的。因此,MLE 不存在。

在这种情况下,考虑两种极端情况:λ = 0 和λ = ∞

Case 1

Case 2

在这两种极端情况之间,修正的协方差矩阵由下式给出

Modified covariance matrix for ridge regresion

将随着λ的增加而成为对角优势。所以保证是可逆的。这证明了即使设计矩阵不是满秩的,非零λ的岭估计总是存在的(在这篇 StackExchange 文章中提供了严格的证明)。

因此,我们得出结论,使用 L2 正则化解决了共线性问题。与岭回归不同,Lasso (L1 正则化)回归没有解析解。在存在共线性的情况下,预计其行为类似于岭回归。Lasso 回归也是随着λ(小于∞)的增大,将变量的系数收缩到 0 来进行剪枝,这在 ridge 中是观察不到的(lasso 对剪枝的严谨分析可以在我的 Quora 答案上找到)。为方便起见,L1 正则化线性回归公式如下所示:

L1 正则化线性回归

模型定义

True model, unknown

估计的

Estimated

损失函数

Loss in terms of independent variables

解决办法

Solution

我们假设 lasso 的行为在协方差矩阵的可逆性方面类似于 ridge 的行为(严格的分析可以在这篇论文 —第 5 页中找到,也解释了使用坐标下降的原因)。lasso 的解析解不存在,除了一个简单的情况-当协方差矩阵是对角矩阵时。

对角协方差注意:参数估计变得类似于轮廓似然性——在一次坐标下降迭代中所选β的变化不会影响其他β。因此,坐标下降在一次迭代中收敛。

注意:我将在两篇独立的文章中用几何解释以更严格的方式讨论 L1 和 L2 正则化。

拒绝传统社会的人

辍学通常被视为调整神经网络的一种实用方式。很难以完全分析的方式处理辍学问题,因为:

  1. 它涉及到一些随机化—只有期望值是已知的,实际上各个实现会根据种子而变化
  2. 对(随机)梯度下降的每个样品/小批量/批量进行测试

该模型可以被视为:

Masking variables in X at random; excluding intercept/bias

Linear regression on M vs y

在实践中,为了避免权重之间的相关性,已经使用了丢弃。实际上,这是通过随机化掩码来实现的,从而减少变量的同现。理论上,当相应的预测值相关时,权重是相关的。因此,使用压差进行掩蔽有助于减少过拟合。

把东西放在一起

让我们在输出层之前选择隐藏层。对于 h << n (sample size) we observe that the problem of overfitting occurs when variables are collinear. L2 regularization explicitly removes the effect of collinearity by modifying the covariance matrix; L1 regularization affects the covariance matrix indirectly. Dropout affects the covariance between the weights by sampling from the set of features and masking the features that are not chosen (similar to random forest) during each update based on gradients.

Conclusion

Linear models and deep neural networks are related through linear algebra. Over determined systems (number of predictors >个样本)和共线系统(秩< number of predictors) lead to unstable solutions and overfitting that can be resolved using regularization. The 3 most common forms of regularization — ridge, lasso and droupout — reduce overfitting by reducing the collinearity among predictors (or hidden layer in deep neural networks). But it is important to note that collinearity is not the only cause of overfitting. There are other forms of regularization that penalize the curvature in each dimension (check smoothing splines).

A more rigorous analysis with geometric interpretation of ridge and lasso will be published in the future.

Further reading

Research paper: 通过去相关表示减少深度神经网络中的过拟合

研究论文:用基于集成的去相关方法正则化深度神经网络

相关研究论文:神经网络解释和对称破缺的权重集去相关训练算法

相关研究论文:多层感知器网络剪枝的去相关方法

将单词表示为向量的不同技术(单词嵌入)

原文:https://towardsdatascience.com/different-techniques-to-represent-words-as-vectors-word-embeddings-3e4b9ab7ceb4?source=collection_archive---------4-----------------------

从计数矢量器到 Word2Vec

Photo by Romain Vignes on Unsplash

目前,我正在做一个 Twitter 情感分析项目。在阅读如何向我的神经网络输入文本时,我发现我必须将每条推文的文本转换成指定长度的向量。这将允许神经网络对推文进行训练,并正确地学习情感分类。

因此,我简要地分析了将文本转换成向量的各种方法——通常称为单词嵌入。

单词嵌入是自然语言处理(NLP)中一套语言建模和特征学习技术的统称,其中词汇表中的单词或短语被映射到实数向量。— 维基百科

在本文中,我将探索以下单词嵌入技术:

  1. 计数矢量器
  2. TF-IDF 矢量器
  3. 哈希矢量器
  4. Word2Vec

示例文本数据

我正在创造 4 个句子,我们将在上面应用这些技术并理解它们是如何工作的。对于每种技术,我将只使用小写单词。

计数矢量器

Photo by Steve Johnson on Unsplash

将文本转换为矢量的最基本方法是通过计数矢量器。

步骤 1: 在完整的文本数据中识别唯一的单词。在我们的例子中,列表如下(17 个单词):

['ended', 'everyone', 'field', 'football', 'game', 'he', 'in', 'is', 'it', 'playing', 'raining', 'running', 'started', 'the', 'towards', 'was', 'while']

步骤 2: 对于每个句子,我们将创建一个长度与上面(17)相同的零数组

第三步:一次看一个句子,我们将阅读第一个单词,找出它在句子中的总出现次数。一旦我们知道了这个词在句子中出现的次数,我们就可以确定这个词在上面列表中的位置,并在那个位置用这个计数替换同一个零。对所有的单词和句子重复这一过程

例子

就拿第一句话来说吧, 他在打野战。 其向量为[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

第一个词是He。它在句子中的总数是 1。还有,在上面的单词列表中,它的位置是从开始算起的第 6 位(都是小写)。我将更新它的向量,现在它将是:

[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

考虑第二个词,也就是is,向量变成:

[0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]

类似地,我也将更新其余的单词,第一句话的向量表示将是:

[0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0]

同样的情况也会在其他句子中重复出现。

密码

sklearn提供了 CountVectorizer()方法来创建这些单词嵌入。导入包后,我们只需要在完整的句子列表上应用fit_transform(),就可以得到每个句子的向量数组。

上述要点中的输出显示了每个句子的向量表示。

TF-IDF 矢量器

Photo by Devin Avery on Unsplash

虽然计数矢量器将每个句子转换成它自己的矢量,但它不考虑单词在整个句子列表中的重要性。例如,He出现在两个句子中,它不能提供区分这两个句子的有用信息。因此,它在句子的整个向量中应该具有较低的权重。这就是 TF-IDF 矢量器的用武之地。

TF-IDF 由两部分组成:

  1. TF(词频) —定义为一个词在给定句子中出现的次数。
  2. IDF(逆文档频率) —它被定义为总文档数除以单词出现的文档数的以 e 为底的对数。

步骤 1: 识别完整文本数据中的唯一单词。在我们的例子中,列表如下(17 个单词):

['ended', 'everyone', 'field', 'football', 'game', 'he', 'in', 'is', 'it', 'playing', 'raining', 'running', 'started', 'the', 'towards', 'was', 'while']

步骤 2: 对于每个句子,我们将创建一个长度与上面(17)相同的零数组

步骤 3: 对于每个句子中的每个单词,我们将计算 TF-IDF 值,并更新该句子的向量中的相应值

例子

我们将首先为所有句子组合中的所有 17 个唯一单词定义一个零数组。

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

我就拿第一句的he这个词, 他在打野战 为它申请 TF-IDF。然后,该值将在句子的数组中更新,并对所有单词重复。

Total documents (N): 4
Documents in which the word appears (n): 2
Number of times the word appears in the first sentence: 1
Number of words in the first sentence: 6Term Frequency(TF) = 1Inverse Document Frequency(IDF) = log(N/n)
                                = log(4/2)
                                = log(2)TF-IDF value = 1 * log(2)
             = 0.69314718

更新的向量:

[0, 0, 0, 0, 0, 0.69314718, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

对于所有其他单词,情况也是如此。但是,有些库可能使用不同的方法来计算该值。例如,sklearn,计算逆文档频率为:

IDF = (log(N/n)) + 1

因此,TF-IDF 值为:

TF-IDF value = 1 * (log(4/2) + 1)
             = 1 * (log(2) + 1)
             = 1.69314718

重复时,该过程将第一句的向量表示为:

[0, 0, 1.69314718, 0, 0, 1.69314718, 1.69314718, 1.69314718, 0, 1.69314718, 0, 0, 0, 1, 0, 0, 0]

密码

sklearn提供了计算 TF-IDF 值的方法TfidfVectorizer。但是,它对其应用了l2规范化,我会忽略使用标志值None并保持smooth_idf标志为假,因此上面的方法被它用于 IDF 计算。

上述要点中的输出显示了每个句子的向量表示。

哈希矢量器

Photo by Nick Hillier on Unsplash

这个矢量器非常有用,因为它允许我们将任何单词转换成它的散列,并且不需要生成任何词汇。

第一步:定义为每个句子创建的向量的大小

步骤 2: 对句子应用哈希算法(比如 MurmurHash)

步骤 3: 对所有句子重复步骤 2

密码

由于这个过程只是一个散列函数的应用,我们可以简单地看一下代码。我将使用来自sklearnHashingVectorizer方法。将规范化设置为“无”会将其删除。鉴于以上讨论的两种矢量化技术,我们在每个矢量中都有 17 列,我也将这里的要素数量设置为 17。

这将生成必要的散列值向量。

Word2Vec

Photo by Mahesh Ranaweera on Unsplash

这些是一组神经网络模型,其目的是在向量空间中表示单词。这些模型在理解语境和词与词之间的关系方面是高效的。相似的单词在向量空间中被放置得很近,而不相似的单词被放置得很远。

描述单词是如此令人惊奇,它甚至能够识别关键关系,例如:

King - Man + Woman = Queen

它能够解释男人对于国王,女人对于王后的意义。通过这些模型可以确定各自的关系。

该课程有两种模式:

  1. CBOW(连续单词包):神经网络查看周围的单词(比如左边 2 个和右边 2 个),并预测中间的单词
  2. 跳跃图:神经网络接受一个单词,然后尝试预测周围的单词

神经网络有一个输入层、一个隐藏层和一个输出层,用于对数据进行训练和构建向量。由于这是神经网络如何工作的基本功能,我将跳过一步一步的过程。

密码

为了实现word2vec模型,我将使用gensim库,它提供了模型中的许多特性,比如找出奇怪的一个,最相似的单词等等。然而,它没有小写/标记句子,所以我也这样做了。然后将标记化的句子传递给模型。我已经将 vector 的size设置为 2,window设置为 3,这定义了要查看的距离,sg = 0 使用 CBOW 模型。

我用most_similar的方法找到所有和football这个词相似的词,然后打印出最相似的。对于不同的培训,我们会得到不同的结果,但在我尝试的最后一个案例中,我得到了最相似的单词game。这里的数据集只有 4 个句子。如果我们同样增加,神经网络将能够更好地找到关系。

结论

我们找到了。我们已经了解了单词嵌入的 4 种方式,以及如何使用代码来实现这一点。如果你有任何想法,想法和建议,请分享并告诉我。感谢阅读!

Pytorch 神经网络的不同类型正则化

原文:https://towardsdatascience.com/different-types-of-regularization-on-neuronal-network-with-pytorch-a9d6faf4793e?source=collection_archive---------14-----------------------

py torch 中正则化工具的实现

Image by Gerd Altmann from Pixabay

我在做一些关于神经元网络框架中的稀疏性的研究,我看到了文章“ 深度神经网络的组稀疏正则化 ”。本文解决了同时优化(I)神经网络的权重,(ii)每个隐藏层的神经元数量,以及(iii)活动输入特征子集(即特征选择)的挑战性任务。他们基本上提出了在神经元网络的正则化框架中整合套索惩罚。关于正规化的定义和重要性,有大量的帖子和广泛的研究。比如这些帖子【1】**【2】都是对正规化的快速介绍。****

为了重现深度神经网络中的实验,我决定使用众所周知的深度学习框架 PyTorch 来构建我的项目。据 Medium 称,这是第第四最佳深度学习框架。它在学术层面越来越受欢迎,因为它易于模块化,比大多数竞争对手更快地测试新想法。****

我意识到没有这样的工具可以做任何类型的正则化,除非 L2 正则化。在 pyTorch 中,L2 是在优化器的“权重衰减选项中实现的,不同于 千层面 (另一个深度学习框架),在其内置实现中提供了 L1 和 L2 正则化。您可以找到许多 建议的解决方案 解释如何使用 pyTorch 框架实现 L1 正则化,但是没有简单的实现工具来插入您的实验。

为了弥补这种缺失,我决定使用 pyTorch 框架构建一些“随时可用”的正则化对象。实现可以在 这里找到 。我实现了 L1 正则化、经典 L2 正则化、 ElasticNet 正则化(L1 + L2)、 GroupLasso 正则化和一个更具限制性的惩罚 SparseGroupLasso ,这是在组稀疏正则化中为深度神经网络引入的。**

类对象被构建为将 pyTorch 模型作为参数。我们可以对特定的参数权重或模型中每一层的所有权重应用正则化惩罚。

Base model of regularizer object

Example of implementation of the L1 regularizer

我将这些实现应用于完全连接的神经元网络。这是最简单的模型架构,用于查看不同类型的正则化对模型性能的影响。

像最初的文章一样,我在代表图像分类问题的数字数据集上测试了实现。它由从几十个不同的人那里收集的 1797 个 8 × 8 的手写数字灰度图像组成。我使用了一个简单的全连接神经网络,它有两个隐藏层,分别有 40 和 20 个神经元。

Results Performances with different type of regularization applied to the simple FC model

从结果可以看出, L2 正则化模型和权重衰减正则化模型在测试集上具有相同的性能。这很好,也是我们所期望的,因为重量衰减是 pyTorch 已经提出的 L2 实现。较稀疏的方法(L1 正则化和 GL 正则化模型)也表现得相当好,但它们并不比权重衰减正则化模型更好。我们现在可以看看模型的真正稀疏性。为了对此进行研究,我们将绝对值低于 10e-3 的权重设置为 0。然后我们分析了每个模型中神经元的所有稀疏百分比。稀疏度百分比的计算方法是,取所有权重总和为 0 的神经元的数量,并将该数量除以每层的大小。正如所料, L1 正则化模型比 L2 正则化模型具有更稀疏的密度。但是在这种情况下,性能仍然很好。有时候,太多的稀疏对模型也不好。

总之,我提供了一个不同类型正则化选项的内置和自适应实现。我在 Digits 数据集上的一个更简单的全连接模型上测试了所有正则化,以查看不同正则化之间的性能。我们可以看到稀疏性在这些情况下仍然可以很好地执行任务。下一步是看看我们如何将 pyTorchReg 模块扩展到其他模型架构。

用 fastai 寻找 RNN 的差异化建筑

原文:https://towardsdatascience.com/differentiable-architecture-search-for-rnn-with-fastai-a5e247aeb937?source=collection_archive---------29-----------------------

刘韩啸等人提出的可微分结构搜索( DARTS )是一种使神经网络结构设计过程自动化的算法。它最初是在纯 pytorch 中实现的。这篇文章触及了飞镖背后的关键思想,并展示了我如何使用 fastai 重新实现飞镖,以达到清晰和易用的目的。

代码在https://github.com/tinhb92/rnn_darts_fastai。

飞镖

Overview of DARTS — from the paper

使用 AWD-LSTM 作为主干,目标是找到一个好的 rnn 单元来填充模型的“递归”部分(RNNModel.rnns)。尝试不同的配置以最终提取最合适的 rnn 小区。

DARTS Algorithm — from the paper

我们来解释一下算法:

  1. train_search:搜索好的 rnn 细胞基因型
  2. 训练:导出基因型,训练其收敛并在测试集上评估

第一部分,搜索好的 rnn 细胞基因型,包括连续松弛(即创建混合操作)和使用梯度下降交替更新架构α和权重θ

在 rnn 单元的一个节点上,我们不仅仅使用 1 运算 (tanh,sigmoid …),而是应用几个运算,并获得这些运算的加权和。实验中有 5 种运算 : none,tanh,relu,sigmoid,identity。在每个节点给予这些 5 操作中的每一个的权重是可学习的参数。

在 Pytorch 中,我们使用 torch.rand() 对此进行初始化,并设置 requires_grad = True 。作者称此为α/架构参数以区别于θ/网络的正常参数。更新θ需要通常的向前和向后传递。

α的梯度在论文的等式(7)中描述:

Eq (7) in paper: Gradient for alpha

“ω”表示一步向前模型的权重。

ω’

等式(7)的第一部分通过使用ω’对验证数据进行 1 次正向和 1 次反向传递来计算。等式(7)的第二部分使用有限差分近似来计算:

Finite difference approximation

ω+和ω-定义为:

ω+ and ω-

评估有限差分只需要对权重进行 2 次向前传递,对α进行 2 次向后传递。复杂度从 O(|α| |θ|)降低到 O(|α|+|θ|)。

训练后,我们选择概率最高的操作(忽略无)将连续松弛转换为单元的 1 个离散规格。然后,这种基因型被训练收敛并在测试集上进行评估

用 fastai 实现

在最初的实现中, train_seachtrain 这两个阶段的训练循环用纯 pytorch 编码。如果循环不太复杂,这是没问题的,但是它会很快变得混乱,使代码难以破译。fastai 已经开发了一个回调 系统来将训练循环的组件归类为独立的部分,以保持清晰。

callbacks at a glance — thanks to Jeremy’s tweet — full notebook

您可以指定在训练的每个阶段做什么:on_train_begin、on_epoch_begin、on_batch_begin、on_loss_begin …等等,而不会弄乱代码。阅读文档了解更多信息!

在最初的实现之后,我还有 DartsCell、DartsRnn 模块(用于 train 阶段)和它们各自的子类 DartsCellSearch、DartsRnnSearch(用于 train_search 阶段)。不同的是,为了便于理解,其他有趣的附加组件被放入它们自己的回调中。

train search loop — link

上面的大 train_search 循环被一个带回调的学习者所取代,在回调中你可以快速看到所需内容的概述。

learner with callbacks — link

Train_search 有自己的 ArchParamUpdate 回调函数,上面提到的更新 alpha/architecture 参数的所有逻辑都存储在那里。
alpha(代码中的 arch_p)的优化器(arch_opt)是这个回调的一部分。

类似地,训练阶段有一个单独回调来触发 ASGD 优化器,且触发条件在回调中,与训练循环分开。 traintrain_search 共享的其他任务如正规化隐藏初始化保存恢复训练也有各自的回调。

更多细节,你可以查看我的代码并运行提供的笔记本。

可微智能体学习解决囚犯开关之谜

原文:https://towardsdatascience.com/differentiable-inter-agent-learning-to-solve-the-prisoners-switch-riddle-6b03f14ded7d?source=collection_archive---------24-----------------------

跨代理反向传播梯度以学习消息传递协议

强化学习是一个热门的研究领域。这主要是因为它旨在模拟那些看起来难以处理的系统。从 Deepmind 著名的 Atari 论文开始,我们已经走了很远。以下帖子来自我从以下文章中了解到的内容:

https://arxiv.org/pdf/1605.06676.pdf

强化学习中一个有趣的研究途径是交流代理:一种代理可以互相发送消息以进行合作的设置。通信必不可少的一个好例子是每个代理只能部分观察到的环境,而代理需要更多的信息来合作完成任务。这些代理必须相互传递有意义的消息,其中“有意义”代表与它们自己的环境或它们将要采取的行动相关的有用信息有某种关联。

这样一个传递消息的环境将有一些重要的要求。考虑一个代理 A 发送消息 m 给另一个代理 b。他们开发的用于通信的协议,正如他们所了解的,将必须具有某些属性。

  1. 给定系统的架构,这个消息协议应该是最佳的。一个代理人互相发送随机向量的系统显然是没有用的。这些被交换的向量( m )必须包含丰富的信息
  2. A 发出的信息必须被 B 理解

考虑到我们有多个代理,我们可以采用以下选项(甚至可能是中途退出):

  1. 参数共享:为所有代理获取一组公共参数。也就是说,对所有代理使用单个网络,但是在执行期间单独使用这些参数,每个代理将自己的观察和接收的消息插入到网络中。这种方法通常更稳定且易于学习,因为如果提取了有用的特征,这些特征将用于所有代理。它们不必单独学习。
  2. 没有参数共享:对每个网络使用不同的权重,让它们独立学习特征。这比前一个选项更不稳定。

一个早期设计的算法是 RIAL。RIAL 背后的思想很简单:只需在每个代理的动作选择器中提供消息作为动作选择。该消息被传递给其他代理。就这样。每个代理都单独接受培训。该框架遵循分散执行以及参数的独立更新,即梯度独立地通过每个代理并被更新。它们不会端到端地通过多个代理。

这种不通过多个代理传递梯度的实践在几个方面受到限制。很难找到最佳策略,因为消息类似于行动选择。

然后是拨(差分内部代理学习)。让我们为每个代理中的专用消息引入一个输出。添加与其他代理发送的消息相对应的输入。使用这个框架,在训练时,将所有网络与每一步连接在一起,并让梯度端到端地流过所有代理,同时最小化损失函数(这是我们从贝尔曼方程得到的通常的 Q 学习损失函数)。我们最终得到的是一个交换消息的最佳协议。在训练时,每个代理学习构建有意义的消息,并理解其他代理给出的消息。这种设置遵循集中学习和分散执行。每个代理在执行时在环境中单独行动,但在训练阶段一起学习。

Source: https://arxiv.org/pdf/1605.06676.pdf

这里需要注意的一点是,每条消息可以是离散的,也可以是连续的。问题定义可能会施加限制,只允许传递离散消息,如一位消息。我们如何将消息离散化?让我们介绍一个被称为 DRU(离散化/正则化单元)的单元,定义为:

我们将通过这个单元传递消息,而不是直接将消息从一个代理插入到另一个代理。由于噪声,该单元可以离散化消息。当我们在训练期间添加噪声时,我们迫使消息( m )朝向决策边界的最右边或最左边,以便添加噪声不会影响消息所在的一侧(即,正面或负面)。

让我们尝试实现这一点。考虑一下百名囚犯之谜。我直接引用论文中的谜语陈述:

一百名囚犯刚刚被带进监狱。典狱长告诉他们,从明天开始,他们每个人都将被安置在一个隔离的牢房里,彼此之间无法交流。每天,典狱长会统一随机选择一名囚犯替换,并把他放在一个中央审讯室,里面只有一个带拨动开关的灯泡。囚犯将能够观察到灯泡的当前状态。如果他愿意,他可以打开灯泡。他还可以选择宣布他认为所有的囚犯都在某个时间点参观过审讯室。如果这个公告是真的,那么所有的囚犯都被释放,但如果是假的,所有的囚犯都被处决。典狱长离开了,囚犯们聚在一起讨论他们的命运。他们能就保证他们自由的协议达成一致吗

显然,解决方案必须将信息编码到随时间变化的转换模式中,而且很可能需要无限多的步骤来执行。

现在让我们来解开这个谜。我们将使用 TensorFlow,特别是 2.0。我们将不得不为少数囚犯解决这个问题,例如 3 或 4 个,因为策略空间随着代理的数量呈指数增长。这个问题可以建模为每天从他们的牢房中随机选择囚犯,并允许他们向下一个囚犯传递 1 位信息。这个一位囚徒就是灯泡的状态。因此,房间中的囚犯从前一个囚犯处接收 1 位(如果是第一个囚犯,则为随机位),并被允许向下一个囚犯发送一位。记下天数,并用这一位发送给下一个囚犯,他们将不得不解决这个问题。

对于这篇文章,请参考我的实现。

环境

参考类 Jail ,它实现了我们将要使用的环境。每一步都随机选择囚犯。可以通过调用 step()方法来执行操作。采取“申报”行动时,根据申报正确与否,给予每个犯人 0.5 或-0.5 的奖励。

定义 DRU

以下代码片段显示了 DRU 的定义,该定义将仅在训练阶段中使用(我已经为测试直接进行了离散化):

代理网络

播放一集

现在核心部分。首先是一些重要的变量和初始化:

使用这些,让我们运行一个循环,直到我们没有完成:

第一部分通过代理运行消息。如果代理在房间中,则当前灯泡状态被给予代理,否则,DUMMY_MESSAGE 指示代理在其房间中,并且一天过去了。在不知道一天已经过去的情况下,代理将无法跟踪时间,当我们推送这个 DUMMY_MESSAGE 时,时间会被编码到 GRU 的隐藏状态中。我们将所有有用的变量记录到列表中,这样我们以后可以简单地通过迭代它们来计算损失。使用相同的、熟悉的、著名的贝尔曼方程计算目标,在损失函数中给出一项:

Link: https://i.stack.imgur.com/XBsvH.png

请注意,主 Q 网络和目标 Q 网络使用的协议会略有不同,因此我们也必须通过目标网络传递一组不同的消息,以便使用此更新规则。目标网络给出的 Q 值只有在我们让它们遵循之前设计的协议时才有意义。

主训练循环

想播多久就播多久。在一个 tf 下。GradientTape()对象,调用 play_episode 方法。然后,我们简单地计算梯度并更新权重,这是通常的做法。

请注意,我不得不从这些片段中删除一些细节来展示这个想法。您可以在实现中获得所有这些细节。一个重要的细节是,在上面的循环中,我们必须运行测试循环,其中我们使用离散消息 DRU,没有探索(没有随机动作选择)。它们反映了该系统运行得有多好。我们还必须更新目标网络,建议间隔为 100 集,如本文所述。

微分编程—逆向图形自动编码器

原文:https://towardsdatascience.com/differentiable-programming-inverse-graphics-autoencoder-e1b0fabe67bf?source=collection_archive---------16-----------------------

编程的未来是向量化的、可逆的和可微分的

介绍

深度学习分类器、LSTM、YOLO 检测器、变分自动编码器、甘——这些家伙是真正意义上的元程序架构,还是只是关于如何解决特定优化问题的想法的明智实现?机器学习工程师实际上是决策系统的开发人员,还是仅仅是具有预定义参数化优化程序的支持 GPU 的计算机的操作员?可微分编程可以回答这些问题和其他一些问题,如解释模型和停止使用蛮力端到端 DNNs 加热我们的星球。数据科学家已经做了大量定制编程,在将数据传递到标准神经网络块或堆叠模型以获得更好的结果之前,对数据进行清理、过滤和标准化。现在是时候做自定义编程的标准神经网络块和这个编程必须是可微分的。

想法

让我们考虑使用 MNIST (EMNIST)的手写字符识别。经典的方法是标记数千个样本,并让它们通过卷积或密集神经网络。结果将是一些可以预测字母的模型。这种有监督的方法需要标记大量数据(有半监督的方法,如主动学习https://towards data science . com/Active-Learning-on-mnist-saving-on-labeling-f 3971994 C7 ba可以减少标记工作),它创建了一个无法解释数据本身和结果的模型。只有以相同的方式识别相同的分布式数据才有意义

如果我们勇敢地离开监督学习的安全港,使用 AutoEncoder 通过自回归来学习嵌入空间,我们会发现我们不是在标记数据,而是在检查 Z 空间中隐藏的特征和见解。这个过程的真正结果不是再现的图像,而是学习的嵌入,这些嵌入可以被聚类并用于识别、特征解释和操作。但是我们仍然不能使用自动编码器的瓶颈来将其连接到数据转换管道,因为所学习的特征可以是线条粗细和角度的组合。每次我们重新训练模型时,我们都需要重新连接瓶颈 z 空间中的不同神经元。

如果要求神经网络块从一开始就产生一些有用的东西,比如拿一支记号笔,画一个符号,会怎么样?这将更像是人类在学习。我们可以将 DNN 输出解释为用不同的标记大小(压力)和颜色强度绘制的点的列表,或者甚至将输出用作必须绘制手写符号的单个手势。在这种情况下,我们将把输出解释为一组速度记录(作为位置的一阶导数)。

为了使这些标记命令产生可完全微分的输出,并且因此对于反向传播是透明的,我们需要使用 DiffProg 方法。经典编程倾向于使用太多“数字”运算符,这些运算符无法传递梯度,例如阶跃函数无法用于调整初始参数,我们需要使用 sigmoid 来代替:

同样,我们可以使用高斯曲线来模拟标记点,只需将其呈现在 2D 空间中:

这里,𝜎可以用作反向标记尺寸, xy 是标记点的坐标,颜色强度可以由附加的放大系数驱动:

为了将多个标记点组合在一起,我们可以使用 max 功能。然后可以将生成的图像传递给损失函数——相同的 MSE:

作为一个实际的结果,我们会收到一个可以在空间和时间上分解图像信息的模型(!),创建一个程序,它将在一个简单的动作中,比如说,机械臂,画出所需的符号。

履行

我们将不关注神经网络块的细节,因为这篇文章是关于 DiffProg 的概念。我们只是使用一些具有密集层的 DNN 作为统计估计量。实施的详细信息可以在参考资料部分列出的笔记本中找到。让我们关注 TensorFlow 实现的细节。

静态点

加载 MNIST 数据后,我们创建模型。这里我们从一些参数开始。需要 varcoef 参数将标记的大小(以像素为单位)转换为公式中的方差。

points = 10 #number of points to fit the image in
varcoef = 0.01 #coefficient of the point size
epsilon = 0.0001 #fixing dividing by zero

我们使用输入数据点作为地面真值:

X = tf.placeholder(tf.float32, [None, dim]) #input
Y_ = X #autoregression labels
L = X

神经网络用于将 728 个 MNIST 像素翻译成 10 个标志点。每个都有垂直和水平的位置和大小。我们使用 sigmoid 函数来激活所有三点参数。这是一个简化的变体,结果应该不会让我们吃惊。

#two layers of fully connected NN
L = tf.layers.Dense(units=300, activation=tf.nn.sigmoid)(L)L = tf.layers.Dense(units=200, activation=tf.nn.sigmoid)(L)
#three output nodes (hor, ver and size) as logits to use with possibly different activations
LOGITS = tf.layers.Dense(units=points * 3, activation=None)(L)
#reshape and activations
LOGITS_ver, LOGITS_hor, LOGITS_size = tf.split(tf.reshape(LOGITS, [-1, points, 3]), 3, axis=2)
POS_ver = tf.nn.sigmoid(LOGITS_ver)
POS_hor = tf.nn.sigmoid(LOGITS_hor)
POS_size = tf.nn.sigmoid(LOGITS_size)

在这里,DiffProg 部分开始了——我们需要将高斯公式转化为矢量化形式,并通过批量大小、10 个标记点和图片的两个维度进行传播。为此,我们需要在公式中准备 GRAD_𝑥 ,MEAN_𝜇 和 VAR2 为 2 𝜎 :

结果,我们将得到具有形状的标记张量:[批量大小,点,垂直,水平]。

#constant grid with gradients over coordinates
GRAD_ver = tf.tile(tf.expand_dims(tf.range(0., 1., 1\. / dim_ver), axis=1), [1, dim_hor])
GRAD_hor = tf.tile(tf.expand_dims(tf.range(0., 1., 1\. / dim_hor), axis=0), [dim_ver, 1])
#broadcasted marker point centers (gaussian means)
MEAN_ver = tf.tile(tf.expand_dims(POS_ver, axis=-1), [1, 1, dim_ver, dim_hor])
MEAN_hor = tf.tile(tf.expand_dims(POS_hor, axis=-1), [1, 1, dim_ver, dim_hor])
#broadcasted marker point size (gaussian variation)
VAR2 = tf.tile(tf.expand_dims(POS_size * varcoef + epsilon, axis=-1), [1, 1, dim_ver, dim_hor])
#gaussian marker points vector
MARKER = tf.exp((tf.square(GRAD_hor - MEAN_hor) + tf.square(GRAD_ver - MEAN_ver)) / -VAR2)

头部部分非常经典,除了我们将使用 max 函数来连接一个字形中的标记点:

#head of the model - predict, loss, train step
Y = tf.reshape(tf.reduce_max(MARKER, axis=1), [-1, dim])
LOSS = tf.losses.mean_squared_error(Y_, Y)
TRAIN = tf.train.AdamOptimizer().minimize(LOSS)
#we set two points accurate if their absolute error is less than 0.5
ACC = tf.reduce_mean(tf.cast(tf.less(tf.abs(Y_ - Y), 0.5), tf.float32))

在 10 个时期的训练之后,对于训练和测试数据集,准确度度量将为大约 97%。

复制的训练数据集图片:

复制的测试数据集图片:

培训过程的可视化:

动态手势

现在,我们将从静态点的集合转到可以再现字形的线。为此,我们将稍微更改代码,以便将点位置计算为速度的积分,由神经网络预测。我们正在增加点数,因为现在不是所有的点数都可见。我们还需要一个参数来表示两点之间的最大步长。

points = 25 #number of points to fit the image in
step_size = 3 #maximum velocity in pixels to move the marker
varcoef = 0.01 #coefficient of the point size
epsilon = 0.0001 #fixing dividing by zero

使用更深的 NN 块并引入颜色强度作为附加标记点参数。

#four layers of fully connected NN
L = tf.layers.Dense(units=600, activation=tf.nn.sigmoid)(L)
L = tf.layers.Dense(units=500, activation=tf.nn.sigmoid)(L)
L = tf.layers.Dense(units=400, activation=tf.nn.sigmoid)(L)
L = tf.layers.Dense(units=300, activation=tf.nn.sigmoid)(L)
#four output nodes (hor, ver velocity, size and intensity) as logits to use with possibly different activations
LOGITS = tf.layers.Dense(units=points * 4, activation=None)(L)

对于每一步标记的速度,我们现在需要-1:1 的输出范围,因此我们将使用 tanh 激活并在 step_size 上乘以它们。为了计算最终点的位置,我们需要所有先前的速度值加上初始点(左中)的累积和。

#reshape and activations
LOGITS_ver, LOGITS_hor, LOGITS_size, LOGITS_color = tf.split(tf.reshape(LOGITS, [-1, points, 4]), 4, axis=2)
#velocity in range -1:1
VELO_ver = tf.nn.tanh(LOGITS_ver) / dim_ver * step_size
VELO_hor = tf.nn.tanh(LOGITS_hor) / dim_hor * step_size
#position as an integral of velocity (we start from the middle left point)
POS_ver = 0.5 + tf.math.cumsum(VELO_ver, axis=1, exclusive=True)
POS_hor = 0.1 + tf.math.cumsum(VELO_hor, axis=1, exclusive=True)
#size and color intensity in range 0-1
POS_size = tf.nn.sigmoid(LOGITS_size)
POS_color = tf.nn.sigmoid(LOGITS_color)

标记现在用表示每个点的颜色强度的附加 AMP 张量来计算。

#broadcasted marker point color (gaussian amplitude)
AMP = tf.tile(tf.expand_dims(POS_color, axis=-1), [1, 1, dim_ver, dim_hor])
#gaussian marker points vector
MARKER = AMP * tf.exp((tf.square(GRAD_hor - MEAN_hor) + tf.square(GRAD_ver - MEAN_ver)) / -VAR2)

在训练 50 个时期时,我们将实现训练和测试数据集的 98%的准确性。这些是通过训练数据集的一个手势再现的字形:

测试数据集:

培训过程可视化:

结果

正如我们已经讨论过的,实际的结果是能够像人类一样学习绘制符号字形。这些是带有标记大小和颜色的手势轨迹的图片。请注意,颜色强度对于绘制需要多条线的更复杂的符号至关重要。

如果我们对训练进行多次实验,我们将观察到每次的风格都会不同,这取决于随机种子。

让我们转向更实际的结果——如何使用这种新技术进行符号分类。首先,让我们在测试数据集上对整个 728 像素的 MNIST 数据进行聚类。这将产生以下结果:

Errors: 4113 of 10000\. Accuracy: 58.87 on 10 clusters(labeled samples).

我们为每个聚类分配一个主导样本标签,并将其用于分类错误和准确性度量。当我们对学习的反向图形命令空间的速度和颜色强度进行相同的聚类时,我们将得到:

Errors: 1883 of 10000\. Accuracy: 81.17 on 10 clusters(labeled samples).

如我们所见,错误数量减少了两倍多。准确率提高了 81%以上。这意味着使用这种无监督学习,我们能够更好地理解数据,并比一组不相连的点更好地对 10 个手写数字进行分类。

EMNIST 测试

使用相同数量的训练/测试数据快速检查 EMNIST 数据集— 60K/10K。

为训练数据复制的字形:

对于测试数据:

训练动态可视化:

结论和下一步措施

这只是一个例子,说明如果我们停止简单地重用现有的香草神经网络块,并开始做一些具体的问题。端到端网络不能以有效的方式工作,因为效率是智能的指示,不能是人工的。它只是一种智能,数据科学家或未来的差分编程开发人员可以将它添加到解决方案中。如果我们用建造世界的方式来建造模型,我们需要让一切都联系起来,就像一个量子场,这种联系就是求导的能力。一点的多重导数给出了整个宇宙的信息。

此特定模型的后续步骤可能包括:

  • 由于多重不平衡损失,差分规划模型可能不稳定。这必须通过正则化和更好的初始化来解决。
  • 在该模型中,我们为手势选择了一个初始点,但我们没有强制在图片的反面完成,以使手写符号连接成一个单词。这样的修改可以解决单词级的手写识别问题。
  • 用实线反推图形会更好,但需要高级的数学模型。
  • 预测命令链需要更好的 NN 块,可能需要使用特殊的 r NN 块。

参考

代码和示例

https://github . com/Andy-bosyi/articles/blob/master/DiffProg-MNIST-position . ipynb
https://github . com/Andy-bosyi/articles/blob/master/DiffProg-MNIST-velocity . ipynb
https://github . com/Andy-bosyi/articles/blob/master/DiffProg-EMNIST-velocity . ipynb

关于 DiffProg 的文章

https://skymind.ai/wiki/differentiableprogramming
https://flux ml . ai/2019/02/07/what-is-differentiable-programming . html

附言(同 postscript);警官(police sergeant)

如果你有私人问题,请在 Linkedin 或脸书联系我,有时我会在那里发布关于人工智能的简短新闻和想法。

我要感谢我的同事们亚历克斯·西姆基夫、米科拉·科兹连科、沃洛季米尔·森德茨基、维亚奇·博西和纳扎尔·萨维琴科富有成效的讨论、合作和有益的建议,以及整个 MindCraft.ai 团队的持续支持。
Andy Bosyi,
mind craft . ai 首席执行官
信息技术&数据科学

微分方程—基础

原文:https://towardsdatascience.com/differential-equations-basics-c72db0a8c42a?source=collection_archive---------8-----------------------

订单概述和标准符号

Originally Published On https://www.setzeus.com/

微分方程 (DFQs)的优美分支中,存在着许多、多种已知的 类型的 微分方程。事实上,加深对 DFQ 的理解的最好方法之一是首先解决基本分类系统。为什么?因为你可能永远不会遇到一个完全陌生的 DFQ。大多数 dfq 已经解决了,因此很可能已经存在一个适用的、通用的解决方案。

除了描述方程本身的性质之外,分类和识别差异的真正附加值来自于提供起点的地图。解微分方程的诀窍是 不是 创造原创方法,而是分类&应用已证明的解决方案;有时,可能需要一些步骤来将一种类型的方程转换成另一种类型的等价方程,以便得到可实施的、通用的解决方案。

虽然有数百个附加类别和子类别,但用于描述 dfq 的四个最常见的属性是:

  • 普通 vs 部分
  • 线性与非线性
  • 同质与非同质
  • 微分指令

虽然这个列表并不详尽,但它是一个很好的垫脚石,通常在 DFQ 学期课程的前几周复习;通过快速回顾这些分类类别,我们将具备解决常见 DFQ 问题的基本入门工具。

普通与部分

第一,在野外发现的 dfq 的最常见的分类源于在手边的问题中发现的 衍生 的类型;简单来说,方程是否包含任何偏导数

如果不是,那就是一个常微分方程 ( ODE )。如果是,那就是一个偏微分方程 ( PDE )

ODEs 包括单个独立变量,微分基于该单个变量。一个常微分方程有一组离散的(有限的)变量;他们经常模拟一维动力系统,比如钟摆随时间的摆动。

另一方面,偏微分方程要复杂得多,因为它们通常包含不止一个自变量和多个偏导数,这些偏导数可能基于也可能不基于某个已知的自变量。偏微分方程在 STEM 中非常受欢迎,因为它们被用来描述自然界中各种各样的现象,如热、流体流动或电动力学。这些看似不同的物理现象被形式化为偏微分方程;他们在随机偏微分方程中找到它们的推广。

下面是几个例子,有助于识别 DFQ 方程包含的导数类型:

Originally Published On https://www.setzeus.com/

线性与非线性

第二个共同的性质,线性,是二元的&直截了当:一个方程中的变量&导数乘以常数&仅仅是常数吗?

如果是这样,那就是线性 DFQ。否则,它被认为是非线性的。变量及其导数必须 总是 以简单的一次幂出现。考虑到它们天生的简单性,求解线性方程的理论得到了很好的发展;很可能你已经在物理 101 课上遇到过他们。

不过,为了清晰起见,还是有几个例子值得回顾一下——下表列出了 dfq 中的线性度:

Originally Published On https://www.setzeus.com/

同质与非同质

对微分方程进行分类的第三种方式,DFQ 被认为是齐次的如果&只有当 被加法或减法运算符分隔的所有 项包括相关的变量;否则就是非齐次。检验这一性质的一个简单方法是将包含因变量的所有项移到等号的左边,如果右边不是零,则它是非齐次的。

下面是一个更正式的定义。参考微分方程的定义,由左侧的下图表示:

如果图的右边 g(x)等于零,则认为 DFQ 是齐次的。以下是一些例子:

Originally Published On https://www.setzeus.com/

在现实生活场景中,g(x) 通常对应一个动态物理模型中的 强迫项 。例如,在电动摆中,驱动摆&的电机将会导致 g(x)!= 0.

一阶,二阶

最后一个基本分类,这肯定是你在数学预备分支中已经确定的性质:微分方程的 。与多项式中描述最高 n 次的阶不同,对于微分,函数的阶等于等式中的 最高导数 。最基本的是:

Originally Published On https://www.setzeus.com/

最后

我们走吧!用于识别和分类微分方程的四个最常见的性质。正如你现在可能知道的,DFQ 巷的道路与植物学相似;当你第一次学习微分方程时,培养一种识别和分类 dfq 到它们适当的组的眼光是很实际的。一旦确定了,很有可能你就离找到通用的、适用的解决方案很远了。

诚然,我们只是为深入探索 STEM 每个领域背后的驱动分支搭建了舞台;要彻底了解解决方案,可以从研究更简单的设置开始,比如齐次一阶微分方程!

最初发表于

https://www.setzeus.com/

来源

微分方程

微分方程——简明教程

微分方程——历史与概述

原文:https://towardsdatascience.com/differential-equations-history-overview-a1d45ebc1a8b?source=collection_archive---------2-----------------------

第一部分——它是什么,为什么与今天相关?

Originally Published On Setzeus

数学家和物理学家往往在很多问题上意见不一致。一个不容置疑的事实似乎渗透到每一个 STEM 主题&统一双方,然而,主要的信念是分析单个组件之间的动态关系会导致对系统作为一个整体的更好理解。与本系列探索的更抽象的主题形成鲜明对比,如逻辑理论、数论、& 集合论我们现在正前往普遍适用的测量世界、解释变化的&

微分方程是数学的一个分支,以一个或多个记录的变化观察开始,&以一个或多个预测未来结果的函数结束。一个代数方程,如二次方程,用一个值或一组值求解;相比之下,微分方程是用一个函数或一类函数求解的。简称“DFQ ”,几乎所有 STEM 本科项目都将其作为核心要求,原因很简单:DFQ 是任何领域或行业模拟情况的绝佳工具。

Originally Published On Setzeus

在实际应用中,模型通常涉及对象&记录它们之间的变化率(导数/微分)——DFQ 的目标是定义两者之间的一般关系。这种系统在自然现象中极其常见,这也正是为什么 DFQ 在从物理学到经济学再到生物学的课题中扮演着重要角色。

站在巨人的肩膀上——牛顿和莱布尼茨

考虑到它作为任何数学家或科学家的基础部分的长寿和持久的影响,DFQ 的历史相当丰富也就不足为奇了。正如我们很快会看到的,现代 DFQ 是几个世纪以来进步的顶点——许多是家喻户晓的名字。然而,这种朝向既定分支的公共渐进过程,只有两位数学巨人才成为可能:艾萨克·牛顿 & 戈特弗里德·莱布尼茨。

历史告诉我们,两个人都有争议地声称在同一时期独立发明了微积分。这是关键,因为微积分,随着积分和导数的文字发展,为未来的数学家奠定了基础。

确定起源的确切时间的模糊性是多种因素的结果,例如竞争性/隐秘性的一般氛围,以及私人出版物的时间(一些笔记几十年后才被发现)。有一点是肯定的:它们既是理所当然地归功于 DFQ 的起源,下面的例子就说明了这一点。

据说早在 1671 年,牛顿在未发表的草稿中提出了以下三种“类型”的微分方程:

上面的前两个方程只包含一个或多个因变量的普通导数;今天,这些被称为 常微分方程 。最后一个方程包含因变量的偏导数,因此,命名为注意,这两个术语都是现代的;当牛顿最终发表这些方程时(大约在 1736 年),他最初将它们命名为“通量”。

大约在同一时期(~1675 年),德国数学家戈特弗里德·莱布尼茨也在未发表的笔记中,介绍了两个关键的观点:他自己的微分&第一次记录了整数符号的实例:

尽管这些现在发现的草稿起源很早,但更大的数学界第一次听说这个话题还是在 20 年以后。具体来说,在 1693 年,莱布尼茨&牛顿最终都正式发表了&他们的微分问题的分布式解决方案——标志着 1693 年微分方程作为一个独特的数学领域的开端。

Gottfried Wilhelm Leibniz & Isaac Newton

随着基础的奠定,通往 DFQ 的道路是缓慢而稳定的——解决物理问题的尝试逐渐产生了模型,而模型又需要创新的解决方案。这些问题及其解决方案导致了一门独立学科的发展。社区的努力迅速加速了该领域的发展,超越了牛顿和莱布尼茨的贡献。

以下是历史上重要的 DQF 问题和发表了令人满意的解决方案的归因数学家的列表:

上面的列表只是所有造成 DFQ 问题的一小部分;然而,即使是这个删节的列表也凸显了数学家们的才能,他们为这个被认为是 STEM 基础之一的分支做出了贡献。从可识别的名字如拉格朗日、欧拉和伯努利,以及最初的牛顿和莱布尼茨,显而易见数学家对 DFQ 的持续发展有多么重要。

关于这个系列

当谈到现实世界的分析,DFQ 是真正的交易。用半衰期方程预测化学反应,用人口增长预测生态系统的文化数量,或者描述波浪的轨迹——对于任何对 stem 职业感兴趣的人来说,对 DFQ 的基本了解是的必备

接下来我们去哪里?首先,探索 DFQ 符号&回顾不同类型的订单。接下来,我们将回顾拉格朗日力学&运动方程。之后,我们将讲述应用数学中最重要的公式之一:拉普拉斯变换。最后,我们将通过约瑟夫·傅立叶的眼睛探索热流的领域。

来源

微分方程

Setzeus 个人网站

微分方程——简明教程

差异隐私注释 2:来自隐私圣经的强有力的概要

原文:https://towardsdatascience.com/differential-privacy-note-2-a-powerful-synopsis-from-the-bible-of-privacy-51e2f99d3900?source=collection_archive---------16-----------------------

“告诉我,我会忘记的。教我,我会记住。让我参与,我学习。”
—班哲明

好吧,对于那些不知道差分隐私博客系列第 1 部分的人,只需阅读这篇博客“差分隐私注释 1:来自隐私圣经的强大概要”,让自己完全了解隐私的新定义,以及这个新定义(即差分隐私)如何在解决隐私保护数据分析的竞争中脱颖而出。

在这篇博文中,我将阐明

  1. 关于为什么私有数据分析系统有缺陷,以及为什么将一个语义安全密码系统与私有数据分析进行比较是不可行的。

然后在后面的部分

2.将给出差分隐私的更正式的定义,特别是如何通过引入随机性来提供隐私。

3.差别隐私承诺了什么

4.差异隐私不能承诺什么

5.微分隐私的定性性质

私人数据分析:由于辅助信息导致的有缺陷的系统

私有数据分析的一个形式化目标是,分析者在分析完成后对数据集中任何个体的了解不会比分析开始前多。

同样,对手(对手)关于个人的之前和之后的观点(即,在访问数据库之前和之后)不应该“太不同,”或者对数据库的访问不应该改变对手关于任何个人的观点“太多”。

此外,如果分析师或对手对一个人一无所知,那么这个人就不会受到分析的伤害。此后,这种直觉被普遍地称为“无所不知”的方法,由于辅助信息,这种方法被证明是错误的。

因此,各种各样的研究人员试图提出一个观点,即在标准计算可用的情况下,我们为什么不能建立语义安全的私有数据库机制,在对查询产生答案的同时对单个行保密呢?

但是事实证明,语义安全密码系统(SSC) 和私有数据分析之间的类比也是有缺陷的,在某些方面并不完美。

在 SSC 中有三方:

  1. 消息发送者(加密明文消息的人)
  2. 消息接收者(解密密文)
  3. 窃听者(她因无法了解任何关于明文的信息而感到沮丧,因为她在发送之前并不知道这些信息)。

然而,在私有数据分析的环境中,只有两方:

1.馆长,运行隐私机制(类似于发送者)

2.数据分析师,他接收对查询的信息性响应(就像消息接收者一样),并且还试图挤出关于个人的隐私泄露信息(就像窃听者一样)。

因为合法接收者与窥探对手是同一方。因此,SSC 和私有数据分析之间的类比是错误的,因为拒绝向对手提供所有信息意味着拒绝向数据分析师提供所有信息。

差分隐私的正式定义

让我们听听这个领域的先驱之一“辛西娅·德沃克”关于差分隐私和为什么随机性是必不可少的。

现在,是时候从数学上引入差分隐私的正式定义了,

差分隐私:一个具有域 N |X |的随机化算法 m 是(ε,δ)-差分隐私的,如果对于所有的 S ⊆范围(m)和对于所有的 x,y ∈ N |X |使得∨x y∨1≤1:
pr[m(x)∈s]≤exp(ε)pr[m(y)∈s]+δ,

其中(∨x y∨1)衡量 x 和 y 之间有多少记录不同,如果δ = 0,我们说 M 是ε差分私有的。

通常,研究人员对小于数据库大小中任何多项式的倒数的 δ(delta) 的值感兴趣。特别是, δ 的值在 1/∨x∨1 的数量级上是非常危险的:它们允许通过公布少量数据库参与者的完整记录来“保护隐私”,这被精确地称为“仅仅几个”哲学。

什么差别隐私承诺?

从一个非常基本的意义上来说,差分隐私的想法承诺保护个人免受由于其数据在私有数据库(x)中而可能面临的任何额外伤害,如果他们的数据不是 x 的一部分,他们就不会面临这些伤害。尽管一旦差分私有机制 M 的结果 M(x)被发布,个人确实可能面临伤害,但差分隐私承诺伤害的概率不会因他们选择参与而显著增加。

因为当一个人决定是否将他/她的数据包含在一个以不同的私人方式使用的数据库中时,他/她考虑的正是这种差异:他/她参与的伤害概率,与他/她不参与的伤害概率相比。

鉴于差别隐私的承诺,从未来伤害的角度来看,个人确信他/她的存在在参与和不参与之间应该是几乎无关紧要的。

有哪些差分隐私不承诺?

简而言之,差别隐私并不保证无条件免于伤害,更一般地说,差别隐私并不保证一个人认为是自己的秘密将保持秘密。它只是确保个人参与调查本身不会被披露,也不会导致个人参与调查的任何细节被披露。从调查中得出的结论很可能反映了个人的统计信息。但是,如果调查告诉我们,特定的私人属性公共可观察属性密切相关,这并不违反差分隐私,因为这种相同的相关性几乎以相同的概率被观察到,而不管任何个人是否存在。

微分隐私的定性性质

因此,在对这个有缺陷的系统、它所包含的差别隐私、承诺和非承诺的正式定义感到恐惧之后,我们来到了这篇博文的最后一节,在这里我将列举它的一些关键属性。

  1. 防范任意风险。
  2. 链接攻击的自动中和:包括所有那些
    试图用所有过去、现在和未来的数据集和其他
    形式和来源的辅助信息。
  3. 隐私损失的量化:差别隐私不是二元
    概念,有隐私损失的衡量标准。这允许在不同的技术之间进行比较:对于隐私损失的固定界限,哪种技术提供更好的准确性?对于固定的精度,哪种技术提供更好的隐私?
  4. 组成:也许最关键的是,损失的量化还允许通过多次计算对累积隐私损失进行分析和控制。理解组合下差分私有机制的行为使得能够从较简单的差分私有构建块设计和分析复杂的差分私有算法。
  5. 后处理下的闭包:差分隐私不受
    后处理的影响:数据分析师在没有关于私有数据库的额外知识的情况下,无法计算差分私有算法 M 的输出的函数并使其不那么差分私有。也就是说,无论是在正式的定义下,还是在任何直观的意义上,数据分析师都不能仅仅通过坐在角落里思考算法的输出来增加隐私损失,无论有什么辅助信息可用。

这就是差分隐私的最后一个属性,《差分隐私的算法基础》这本书的另一章的总结到此结束。我希望你在总结第二章中提到的概念时,已经学到了和我一样多的东西。

感恩角:

非常感谢 Udacity 和 Akshit Jain 为我提供了这个成长和学习人工智能这一新领域的机会,特别感谢 Trask 为像我这样的学习者提供最新、可靠的知识资源。最后,我很高兴成为这个充满活力的年轻社区的一员。

感谢您的关注

你用你的时间阅读我的作品对我来说意味着一切。我完全是这个意思。

如果你喜欢这个故事,疯狂鼓掌吧👏 ) 按钮!这将有助于其他人找到我的工作。

此外,如果你愿意,可以在 Medium、LinkedIn 或 Twitter 上关注我!我很乐意。

[## 纳文·曼瓦尼培养基

阅读纳文·曼瓦尼在媒介上的作品。一个机器学习工程师,一个深度学习爱好者|谷歌印度…

medium.com](https://medium.com/@naveenmanwani) [## 纳文·曼瓦尼

纳文·曼瓦尼的最新推文(@纳文·曼瓦尼 17)。机器学习工程师@ AIMONK Labs Pvt ltd,深…

twitter.com](https://twitter.com/NaveenManwani17) [## Naveen Manwani -机器学习工程师- AIMonk Labs Private Ltd | LinkedIn

计算机软件加入 LinkedIn siddaganga 理工学院学士学位,电气,电子和…

www.linkedin.com](https://www.linkedin.com/in/naveen-manwani-65491678/)

挖掘深层数据:真实世界的全球寻宝

原文:https://towardsdatascience.com/digging-on-deep-data-a-real-world-global-treasure-hunt-b0ab4329b51c?source=collection_archive---------12-----------------------

深度挖掘数据:一场真实的全球寻宝

数据科学家能让地质学成为真正的科学吗?

地质学家经常被其他科学家(和电视角色)认为地质学更多的是一门艺术而不是一门科学;解开为什么揭示了数据科学家的巨大机遇。

一场令人难以置信的 45 亿年的混乱创造了我们今天所知的地球——所以矿藏的位置和类型是由于史诗般的空间碰撞、大规模移动的岩石和岩浆板块,以及太阳中心的发电机以某种方式产生稳定的磁场。

回到基础,大多数现代科学遵循科学方法来测试和修改假设;观察、测量、实验、分析、报告等等。嗯,在地质学中,这并不容易。例如,包括造山运动、地震活动和地下水流在内的矿化过程是一个紧密耦合的因果网络,从纳米级到地球半径,时间尺度从微秒到数十亿年。这使得为矿体的形成建立一个严格的、定量的物理模型变得非常困难(除了我们居住的星球这个昙花一现的奇迹)。在某种程度上,地质学家是被动的科学家,仅仅是围绕着我们同一个地球发生的惊人过程的见证者。

由于我们无法使用物理模型在我们需要的比例下轻松解释矿体,因此数据科学家有巨大的机会用数据来解释它!

现行的矿产勘查标准是:一个收集不同数据集并对已知矿床类型进行主观描述性地质解释的迭代过程,一点一点地进行,得到的有价值的结果少之又少。这很像盲人遇到他们的第一只大象,每个人只调查动物的一部分,但声称有一个整体。由于对数据的解释是由地质学家主观进行的,因此有大量的例子(如西澳大利亚的 Mt 显著的)表明探险者错过了摆在他们面前的事情,因为他们在寻找不同的矿床类型,或者因为他们对地球物理的解释不正确而钻错了地方,或者仅仅是因为地质学家更擅长用二维切片而不是三维体积可视化矿床模型。

这种整体解释和测试的现状,猜测地球深处的秘密,导致发现任何矿床所需的时间延长。

所有这些都使矿产勘探成为数据科学家的一个有趣领域,同时也使数据科学家成为勘探公司的无价资产。

有如此大量的领域要覆盖,数据要处理,故事要讲述,这是机器学习再次证明自己的完美领域。

机器学习已经推动我们在几个领域向前发展,这些领域在挑战和机遇方面与矿产勘探没有什么不同——例如,遥感和农业。

深度学习和深度递归网络已被应用于遥感,以执行图像处理、解释、数据融合和时间序列分析——如去除云层、对物体进行分类、检测和跟踪目标。

近年来,遥感技术的进步甚至影响了地质学界;例如,澳大利亚地球科学与 CSIRO(澳大利亚最高公共研究机构,联邦科学与工业研究组织)合作,开发了生成覆盖深度预测的算法。

在农业领域,同样的机器学习方法有应用于检测杂草和疾病,预测产量和作物质量,以及管理动物、水和土壤。

但是,即使在这些领域取得了长足的进步,数据科学仍然有很多机会应用于矿产勘探。

那么,怎么做,为什么呢?

您可能已经从本文的“地质学 101”前半部分中了解到,识别经济矿藏并不容易。因为很少有正面的结果,数据科学的应用不像简单的剪切和粘贴那样简单,传统的机器学习算法——反演的物理模型也不可用。该领域需要更复杂的深度学习应用,而不是简单的人工智能或初级的机器学习。

Deep learning in the broader field of AI — Goodfellow et al 2016

正确的方法可以克服一些特殊的挑战。

例如,虽然识别不同的地质数据标志对机器来说很容易,但每个矿床都是不同的。因此,寻找矿床并不像在大型训练数据集中根据确定的正面和负面进行训练那么简单——因为每一个可识别的过去情景都可能永远不会再次发生。然而,机器可以在强有力的先验知识的指导下,在数据集中识别有用的信息,这些信息可能聚集在一起,暗示着一个矿床。

地质数据也很复杂,维度很高,但通常也很有限。例如,我们知道基于岩石成分、温度和压力,某些矿物质总是会一起形成。流形学习旨在降低非线性数据集的维度,有助于解决将数据集中存在的大规模地质过程(如区域变质梯度)与指示矿床的小规模过程(如含金矿脉周围的局部化学变化)分离的挑战。

在矿产勘探中使用人工智能技术的 OreFox 的创始人 Warwick Anderson 同意这一观点,他告诉我们“机器和深度学习显示出巨大的潜力。”

“我认为地质学家和数据科学家需要合作的地方是标准化、变换和异常值检测(或去除)等方面!”安德森说。

"地质图可以被大量外推,那么我们能对从中得到的数据赋予什么价值呢?"这里可以引入多尺度方法来处理数据的多样性和稀疏性——在巨大的、嘈杂的数据集下构建矿产勘探中有用的模型。

作为一个额外的奖励,应用数据科学也将把这个领域从描述性的、主观的分析转向一种经验的、可再创造的科学。

“地质学是混乱的,”安德森说。“[它]可能会非常有偏差……[使用]视觉方法来确定岩石类型。岩石类型可以在一米的空间内变成其他类似的类型;例如花岗岩到花岗闪长岩,这可能有统计学差异。”

但随着数据科学方法中反馈循环的创建,它将确保当正确的地质学家没有在正确的时间查看正确的数据时,没有知识被遗忘或忽略。

数据科学当然不是万能的,没有一种方法能够一次性解决资源发现的问题。要向前发展,减少域名是至关重要的,以便朝着可管理的问题前进,并改善现状。

为此,一个澳大利亚项目正在开放一个大型勘探项目的多年数据,供数据科学家研究,作为众包竞赛的一部分,奖金池为 100 万澳元。

Data scientists and geoscientists working together on data (photo courtesy Unearthed Solutions)

然而,对地质学家的回报不仅仅是经济上的回报。几个世纪以来,地球结构的全部历史一直困扰着人类,矿物和金属需要通讯设备、运输、能源和医疗技术。

寻找急需的经济矿藏就像在大海捞针一样困难。

在数据科学领域,这有点像大海捞针的比喻,但它很适合。这同样适用于地球科学。我们实际上可以抛开整个干草和针的例子,说数据科学通常就像寻找所需材料的经济矿化,反之亦然,但它并不那么简洁。

数据科学找到针的速度比矿物勘探快得多,并在这个过程中在干草中找到更多丢失的宝藏。地理世界有许多真正的宝藏有待发掘!

感谢 Holly Bridgwater、Jess Robertson 和 Warwick Anderson 对本文的贡献。

数字鸟类夜间飞行第一部分:人工智能模拟环境

原文:https://towardsdatascience.com/digital-birds-fly-at-night-part-i-ai-simulation-environment-242fac9d67d8?source=collection_archive---------20-----------------------

在这一系列中,我将讲述我创造人工智能驾驶的固定翼飞机的努力。

在去现场之前,我们将在模拟环境中训练一个神经网络。我们可以从简单的东西开始,随着时间的推移提高模拟质量和飞行模型的准确性,最终在无人机拍摄的空中镜头上训练我们的神经网络。

对于模拟环境,我选择使用 V-Rep 进行初步实验,因为它有 Python 绑定和非常方便的 API 远程接口,但主要是因为 Unity 和 Unreal Engine 占用了太多的空间和资源,而 V-Rep 是一个简单的 tarball,笔记本电脑可以轻松运行它的多个无头实例。

创建了一个基本的“飞机”,并将其放置在由西蒙·d·利维创建的这个可爱的英国乡村场景中。

与大多数流行的模拟环境一样,V-Rep 实际上并不考虑空气阻力,因此不需要空气动力学模型。这个身体只不过是一个框架,当接收控制输入时,力被施加到四肢。

也没有飞行模型——模拟飞机飞行行为的数学模型,所以我对飞机施加了固定的推力和升力。

由于上述原因,该飞行器比固定翼飞机更像无人机或直升机——没有空气阻力意味着它可以转弯,漂移并失去所有动力。它在飞行中的表现也非常不稳定,这使得它极难用键盘控制。

从一个简单的任务开始——尽可能靠近目标飞行。为此,我创建了一个模拟,在这个模拟中,我将一个目标物体放在水面上,在鸟的视野范围内,让它自由飞行 3 秒钟。

期望——训练后,鸟会尽可能飞近目标区域。

现实——嗯,还没有完全实现,但已经有所改善。

我们将在本系列的下一篇文章中更多地讨论人工智能,但是在这个阶段我们已经被迫做出了一些设计决策:

监督学习与强化学习

当训练一个神经网络时,我们通常从一个大的数据集开始——过去的输入和与之相关的输出的例子。如果我们要训练一个对象分类器网络,我们会给它看很多狗和猫的图片,并附上“猫”/“狗”的标签,让网络“学习”什么是狗。

在我们希望人工智能驾驶我们的飞行器的情况下,我们将从视觉传感器捕捉图像,并与所需的控制输入配对。例如,如果我们看到我们将要撞上一棵树,输入将是“左转”。

这种训练方法非常有效,你的训练数据越多——你的模型就越精确。为了生成所述训练数据,人们将手动驾驶鸟,同时记录给定的控制输入。

然而,如前所述——我的模拟飞机是不可能控制的。我甚至不能用键盘保持它在空中飞行,更不用说让它接近目标了..

另一方面,强化学习假设不存在训练数据。取而代之的是,一个代理人执行一个动作,并因期望的结果而被奖励。在我们的例子中,一个成功的人工智能将是飞得离目标最近的那个。

为此,我们将培育多个候选人工智能模型,并让它们在我们的模拟世界中自由活动,只挑选冠军,并从其神经网络的权重中培育出略有变异的下一代。

但下一次会更多;)

直到那时!

轻松实现数字营销

原文:https://towardsdatascience.com/digital-marketing-made-easy-6c19dc597f6?source=collection_archive---------17-----------------------

我们将扮演营销顾问的角色,专注于在 Udacity 、数字营销纳米学位项目和 Tableau 中的免费课程 数据可视化两个 B2C 产品的营销。我们将一步一步地利用各种渠道开展活动,为这些项目吸引潜在的学生。更具体地说,我们的目标是收集可能对纳米学位课程或免费课程感兴趣的潜在学生的线索。

Photo by Reza Rostampisheh on Unsplash

目录

在了解这些活动之前,我们将一步一步地做以下事情:

1 |营销策略

假设
营销目标& KPI
价值主张
移情地图和客户角色
营销策略

2 |预算分配

媒体上的成本与回报
t31】ⓑ建议

3 |展柜作品

营销我们的内容 : 博客和社交帖子 s
运行 Facebook 广告活动 : Facebook 广告图片和结果
进行 SEO 审核 : 审核和建议
运行 AdWords 活动

1 |营销策略

Photo Courtesy by Udacity

我们将专注于应用基于客户旅程的营销计划。在制定营销策略之前,我们将陈述我们的假设以及我们的营销目标和 KPI。我们将阐明我们活动的营销目标和 KPI,同时确保我们的目标是 SMART。

SMART 目标是:
Sspecific、Mmeasurable、Aachievable、 R ealistic、TI bound。

ⓐ假设

  • 预算**::5 万美元
  • 利润 : 纳米学位项目的成本是 999 美元,我们假设利润率为 30%,也就是说 Udacity 每个报名的学生可以获得 299 美元的利润。
  • 活动 : 我们希望大力发展该项目,但是,我们希望在不赔钱的情况下实现。

未来的学生可以下载免费的电子书,如果他们通过这个登陆页面向我们提供他们的电子邮件地址;这本电子书——社交媒体广告指南——是数字营销纳米学位项目的简短摘录。

ⓑ营销目标和关键绩效指标

总体营销目标是在三个月内获得至少 200 名报名参加我们数字营销纳米学位的新生,总预算为 5 万美元。

营销目标的总体主要关键绩效指标(KPI) 是在保持正投资回报的同时,当月注册课程的客户总数。

ⓒ价值主张

利用杰弗里·摩尔的模板得出的T21 的价值主张是:****

对于希望进入数字营销领域
的学生和营销人员来说,他们渴望利用社交媒体营销、搜索营销和电子邮件营销等在线营销策略,我们的数字营销 Nanodegree 是一个项目让你学习如何创建营销内容,使用社交媒体放大你的信息,使内容在搜索中可被发现,在脸书上开展广告活动和做广告。

****与Udemy 提供的完整数字营销课程不同,我们的课程将让您在向该领域顶级专家学习的同时,获得现场营销活动的实际经验。以对数字营销的 360 度理解开启你的职业生涯。

ⓓ移情图和顾客角色

接下来,我们将关注我们的客户是谁来帮助我们编写内容、开展活动和审核网站。这可以通过创建移情图采访潜在客户来实现。****

移情图用于理解和总结客户研究。因此,在采访了至少三个潜在客户来为我们的移情图收集信息后,我们将有四个象限,分为思考、观察、行动和感受。

客户角色是一个虚构的角色,它总结并传达了我们目标客户的关键特征。当创建人物角色时,我们将使用移情图中的信息来告知我们的虚构人物将具有什么样的特征。

营销策略

在这里,我们将概述并提供客户旅程每个阶段的营销策略,包括信息传递和渠道。

登陆页面**:一个目的页面,或者一个独立的网页,开发来引导流量以采取行动,达到营销或广告活动的目的。当客户点击谷歌 AdWords 或社交媒体上的任何广告时,就会登陆这个网站。

有机社交媒体:这完全是关于社交媒体上出现的东西,没有付费推广。通常,有机社交媒体与用户在任何社交媒体网络上发布的任何内容相关联。

****展示广告:一种吸引网站、社交媒体平台受众注意力以采取特定行动的技术。这是一种在线付费广告的方式,可以是设计好的图像或照片和广告文案。

****反向链接:反向链接,或入站链接,是一个网站上的超链接
,指向另一个外部网站。

****搜索引擎营销**:显示在搜索引擎结果页面上的付费广告。另一方面,在搜索引擎优化(SEO)中,一家企业不会为流量和点击量向谷歌付费;更确切地说,他们在搜索结果中获得了一个免费的位置,因为他们拥有与给定关键词搜索最相关的内容。

关键词:根据 MOZ 的说法,“关键词是定义你的内容是关于什么的想法和主题。就 SEO 而言,它们是搜索者输入搜索引擎的单词和短语,也称为搜索查询。**

****重定向广告:重定向广告是一种在线定向广告,是为已经访问过我们网站的人制作的。这有助于在网站访问者离开页面后将他们转化为顾客。

97%第一次访问你网站的人什么都没买就离开了,然后他们就永远消失了。除非你能把他们带回来。——Mailchimp.com****

2 |预算分配

营销成本将分几个阶段下降:

  • 创意: 广告文案、图片、视频等
  • 媒体:
  • 时间和资源 : 管理社交媒体营销渠道需要大量的时间。

在这里,我们将只关注媒体:T2 媒体的成本和回报。

ⓐ媒体的成本和回报

准确、有效的数字营销预算在任何活动中都扮演着重要的角色,同时还能保持积极的投资回报。下面,我们将针对客户旅程的认知、兴趣和需求阶段,对媒体进行预算分配。

****

ⓑ建议

在认知阶段,我们应该把重点放在脸书和 Adwords 上的展示广告上,尽可能多地吸引客户,帮助他们了解这个项目。我们需要优秀的创意来反映项目的目标。在 desire 阶段,我们需要应用更多的重新定位的广告来再次推动该计划的流量。脸书在任何阶段的每次点击费用都是最低的,我们建议增加计划支出,因为它比其他渠道产生更多的销售。

3 |展示作品

陈述完营销目标和我们活动的关键绩效指标后,我们将通过在脸书InstagramLinkedInTwitterGoogle上的短期广告、**、活动一些*细节然后,通过与 MailChimp 进行电子邮件营销 战略来完成我们的工作。*****

每个活动广告都有其营销目标KPI ,所有这些都与我们之前陈述的总体营销目标和 KPI 相关。

这些广告广告将短时间播放,以便在本文中展示它们的表现。

Photo by Prateek Katyal on Unsplash

营销目标和 KPI

营销目标是通过在一个月内让大约 300 人访问这篇文章来建立意识和兴趣。

文章营销目标的主要 KPI 是当月的访客总数。

Sharing a post in Twitter to reach prospective students

Sharing a post in Linkedin to reach specific target students and analysts who may want to learn marketing

Sharing a post in Instagram to reach prospective students

Photo by NeONBRAND on Unsplash

这项活动的主要焦点将集中在年龄在 25 岁到 35 岁之间的男性身上,他们认为自己是企业家或初创公司的创始人,并希望将他们的业务提升到一个新的水平。处于旅程的开始表明目标客户想要省钱和削减开支。因此,提供一个项目来学习社交媒体广告和数字营销的整体概念是至关重要的,并且可以为客户提供许多机会来将这些概念应用到他们的业务中。

下载免费电子书是客户旅程的第一步,他们可以更进一步,考虑参加完整的计划。因此,广告文案和广告创意与边做边学的理念有关。这些图片显示了通过不同的数字设备在线学习并在现实世界的项目中应用所学是多么的纵容。

所有人一起传递信息;阅读,学习,然后应用。你可以通过在 Udacity 学习社交媒体营销和广告的概念来增强自己的能力。

我们不是针对对数字营销或社交媒体营销/广告感兴趣的普通人,而是试图专注于那些希望将这些概念应用到自己业务中的自雇人士。

营销目标和 KPI

营销目标是建立知名度和兴趣,在 3 天内使用 100 美元的总预算获得至少 50 次免费电子书下载。

活动营销目标的主要 KPI 是三天内的下载量。

A summary that shows the target criteria, ad placement, and schedule.

Here is the goal of the campaign (conversions) with a budget of $100

我们想告诉观众为什么他们应该下载电子书,阅读它,并在考虑学习数字营销和社交媒体广告时将该计划作为首选。

有一个清晰的行动号召让我们简洁而直接,例如,通过下载电子书了解更多。此外,添加引人入胜的图像来反映广告文本,同时代表目标受众,这一点至关重要。

这是两个广告的例子和活动的最终结果。

The results that show the number of conversions and the costs per each

  • 这场运动没有达到我们的营销目标。在过去的 4 天里,只有 11 次点击,9 次下载和 1982 次点击。然而,考虑到整体正投资回报率,它赚了 3.54 美元。
  • 尽管广告五有 6 个结果,但它的投资回报率为 4.81 美元,低于广告二有 3 个结果的投资回报率。
  • 总体印象不是很好,但是,这将有助于推动我们想要的意识。
  • 我们建议使用不同的图片,因为印象/接触结果显示一些创意对客户更有吸引力;图 2 和图 5 是相似的创意,也是唯一有结果的。
  • 有了额外的预算,我们可以制作更少的广告,并应用 A/B 测试在两幅图像中进行选择;一个用特定性别反映标题,另一个没有特定性别。
  • 我们会调整目标受众,针对所有性别,而不仅仅是男性。我们相信没有什么不同,努力接触普通客户可以让我们获得更多的结果,从而实现我们的营销目标。

An overall view of the ads performance where we can see the best ad with 6 leads and costs $2.60 each

An overall view of the ads engagement with customers

An overall view of the ads delivery where the best ad reached 985 people

A chart that shows the demographics as all men mostly between 25–34 years old

Facebook Audience Network is an off-Facebook, in-app advertising network for mobile apps. Advertisers can serve up their ads to customers who are using mobile sites and apps other than Facebook, extending their reach beyond the platform (adespresso)

Photo by Stephen Dawson on Unsplash

搜索引擎优化(SEO) :优化有机搜索引擎结果,以提高我们网站流量的质量和数量。

营销目标和 KPI

营销目标是建立知名度和兴趣,让至少 100 名访客在 7 天内访问登录页面。

活动营销目标的主要 KPI 是这三天的访客数量。

内容审核:关键词

首先,我们将使用 Moz Keyword Explorer 工具来识别我们可能会将用户导向登录页面的关键词。我们应该确保混合使用品牌和非品牌关键词。

然后,我们将确定最有潜力的头尾关键词。最后,我们将编写三个博客主题,其中包含了最有潜力的关键词。关键词可以是广泛而深远的(这些通常被称为“头部关键词”),或者它们可以是几个术语的更具体的组合——这些通常被称为“长尾关键词”

Photo Courtesy by Moz

头部关键词:一两个词 尾部关键词:非常有针对性的搜索短语

优先级得分:根据 MOZ 的说法,关键词优先级是“通过查看所有其他指标(数量、难度和有机点击率)计算出的满分 100 分。较高的优先级代表了较高容量和较低难度的最佳点”。

Based on the priority scores, digital marketing is the best head keyword with a score of 78%, and digital marketing certificate is the best tail keyword with a score of 64%

技术审核:元数据

我们将通过创建一个包含我们选择的页面的当前元数据和我们建议的修订的表格,对元数据进行技术审核。

技术审计:反向链接审计

使用 Moz OpenSite Explorer 工具,我们将对我们选择的网页执行反向链接审计。

然后,我们将列出我们为网站发现的三个顶级反向链接 URL。这些反向链接应该增加网站的价值,而不是垃圾邮件。

域名权威:根据 MOZ 的说法,域名权威(DA)是“由 Moz 开发的一种搜索引擎排名分数,可以预测一个网站在搜索引擎结果页面上的排名。一个领域权威的分数范围从 1 到 100,分数越高,对应的排名能力越强。”

链接构建

使用 SEMRush 工具和研究,我们将策划一个链接建设活动。我们将确定三个我们认为相关的高流量网站,我们希望从这些网站获得反向链接,以帮助提高我们网站的流量。

现场性能审计:性能测试

  • 使用Pingler Google Indexed Pages Checker工具,我们将研究有多少数字营销 Nanodegree 的页面被 Google 索引。解释为什么索引的页数很重要。

基本上,没有它谷歌不能索引我们的页面,页面不会在搜索引擎上显示。不幸的是,平勒显示 dmnd.udacity.com 和udacity.com都不适用。无论如何,我们应该确保谷歌蜘蛛捕捉尽可能多的链接,为我们的网站带来更多的流量。

Google spider 又称网络爬虫,是一种抓取网站并存储信息供搜索引擎索引的互联网机器人。

WordStream.com

  • 使用Google Page Speed Insights工具,我们将对登录页面的移动显示进行速度测试。然后,我们将解释为什么评估页面速度很重要。

页面的速度与客户的购买行为相关,也就是说,页面速度慢不会引起客户的兴趣,他们会在几秒钟内离开网站。不需要很长时间来显示内容的更快的页面效率更高。结果表明,我们需要提高手机的登陆页面速度

  • 使用 Think with Google 工具,我们将评估登陆页面的移动友好性。然后,我们将解释为什么拥有手机优化版很重要。

拥有一个移动友好页面可以让我们接触到更多的客户。它表明页面将考虑客户访问页面时使用的每个设备,从而改善用户体验。结果显示装载速度很慢,这会让我们的客户付出代价。

推荐

  • 首先需要调整的是页面元数据,添加 alt-tag 和描述,允许我们添加和优化更多的关键字。这让我们进入下一步,使用 MOZ 来监测和识别新的和更有效的关键字。利用 MOZ 的力量可以帮助我们根据客户的习惯和趋势来优化头尾关键词。
  • 正如我们从性能测试的结果中看到的,我们需要优化页面加载速度,并通过拥有一个移动友好的页面来改善用户体验。我们需要一个速度和响应页面,考虑到不同的设备。页面速度很重要,优化页面速度的一个方法是删除所有不必要的代码、图片等。此外,增加离开页面可能性的最令人沮丧的因素之一是弹出窗口。我们需要避免在页面中使用它们。如前所述,我们需要优化元描述,然而,当我们试图拥有一个移动友好的页面时,我们需要简洁,因为它没有桌面的大空间。
  • 我们应该调查页面索引问题。这可能是 Pingler 的一个错误,因此,我们应该使用另一个工具来评估我们的页面索引。如果页面不在谷歌的索引中,我们就不会获得有机的流量!我们需要专注于我们的 SEO 策略,优化页面,让谷歌的蜘蛛索引页面,然后建立排名,吸引流量,达到我们的网站目标。提高页面索引的重点是确保我们考虑了谷歌关于信任、权威和质量的指导方针。

Photo by Arthur Osipyan on Unsplash

营销目标和 KPI

营销目标是在 5 天内建立对印度的认知和兴趣,通过 4 个广告获得至少 3 个报名关于免费课程:Tableau中的数据可视化。

活动营销目标的主要 KPI 是五天内的注册转换率。

重点是为 Tableau 中的免费课程数据可视化创建两个针对印度客户的广告组。两组代表客户旅程中的两个不同客户: 认知度兴趣

处于旅程的开始表明处于认知阶段的目标客户想要了解更多关于数据可视化的知识以及他们可以使用哪种工具。因此,引入一门免费课程来学习数据可视化的概念,然后在 Tableau 中应用它们,可以为学生提供许多将这些概念应用到职业生涯中的机会。关键词范围很广,重点关注客户在搜索数据可视化时可能遇到的问题。

另一方面,对数据可视化和 Tableau 特别感兴趣的客户需要知道如何使用 Tableau 中的工具或部分工具。也就是说,我们添加了更具体的关键字来反映他们的关注点,如如何在 tableau 中创建图表,或创建仪表板等。

总的来说,认知组的关键字包括关于数据可视化和 Tableau 的信息,而兴趣组的关键字针对的是对 Tableau 有一定了解的客户的问题。

设置我们的广告

  1. 竞价 策略:手动每次点击费用(增强 CPC)
  2. 预算:每天 10 美元
  3. 时间 : 5 天

A summary that shows and summerizes the ads for each target

An overview evaluation per ad group; as we can see that we have only 2 conversions from the interest ads

Overview of each ad; while one ad performed well with 36 clicks, it didn’t lead to any conversions

The tail keyword “business certificate online” lead to having the only 2 conversions with cost of $5.43 each

评估活动绩效

  • 在两个广告组中,只有“兴趣广告”产生了 2 的转化率。因此,每条线索的成本为 9.75 美元,转化率为 16.67%。
  • 尽管“认知广告”总共有 55 次点击和更高的点击率;与“兴趣广告”的 12 次点击和 3.54%的点击率相比,它的转化率为零。
  • 导致 have 转化的唯一关键词是“网上商业证书”。CTR 为 5.15%,CR 为 28.57%,每次转换的成本为 5.35 美元。
  • 我们的营销目标是至少招收 3 名学生,然而,在五天的时间里,该活动只产生了 2 次转化,每次成本为 30.39 美元。只要课程是免费的,投资回报率就会是负数。一旦我们有了更多关于这些线索质量的信息,他们是否为纳米学位项目付费。如果 2 次转化产生的收益超过 60.74 美元(成本),那么我们将获得正的投资回报。
  • 虽然我们假设转化率为 5%,但我们得到的转化率为 2.99%,低于我们的预期。
  • 在总共 1638 次展示中,我们总共收到了 67 次点击。这使我们的点击率(CTR)为 4.09%,平均每次点击成本(CPC)为 0.91 美元,低于我们的最高出价 3.00 美元。

推荐

  • 由于“意识广告”有更好的点击率,我们将专注于优化我们对目标受众的信息,以鼓励学生采取下一步行动并加入课程。
  • 我们将改变广告的标题“Tableau for 初学者|查看和理解您的数据”,因为它的点击率最低。
  • 分析产生两条线索的广告:“免费在线 tableau 培训|提升您的技能”。虽然它的印象最差,但它的点击率最高。为此,我们将应用一个 A/B 测试并一次改变一个元素。然后,我们将转换表现不佳的广告,使其在头部关键词、尾部关键词等方面具有相似的广告文案。

An overall view of each ad group performance where we can see a total of 67 clicks with 4.09% CTR and a total cost of $60.79

An overview analysis of the ads by gender

An overview analysis of the ads by age

A comparison between male and female with respect to the number of clicks and impressions; overall, males have seen the ads and click on one them more than females.

An overall view of each ad’s performance where we can see that we paid only for one add as it was the one with 2 conversion.

An overall view of each keyword performance

Photo by Alex Holyoake on Unsplash

这一部分包括评估三个不同的活动。陈述完假设后,我们将回顾每个活动的结果。

Evaluating the first ad that shows a positive ROI of $597.4

Evaluating the second ad that shows a positive ROI of $67.01

Evaluating the third ad that shows a positive ROI of $363.5

到目前为止,我们已经关注了客户获取漏斗的第一个方面,例如建立意识和收集潜在线索。这些营销漏斗顶端的活动包含了从设计优秀的内容并通过社交渠道分发这些内容,到通过搜索引擎优化提高我们网站的知名度,或者付费在搜索引擎上做广告的所有内容。现在,我们将把重点转移到电子邮件营销,这是转化率较高的营销渠道之一。

特别是,电子邮件营销是营销中使用的最佳手段之一,其重点是在客户获取和购买漏斗中加强参与、提高转化率和保留率。

现在,我们已经收集了销售线索(电子邮件地址),并成功获得了客户的兴趣,是时候创建一个电子邮件营销活动来吸引这些销售线索,并最终将其转化为客户旅程中的后续阶段。

就当是礼貌好了。当有人开始听的时候,你应该说你好,对吗?当有人要求更多时,给他们你最好的。我认为欢迎系列既是聪明的营销,也是普通的礼貌。”——安迪·克雷斯托迪纳, 轨道传媒

既然我们已经在上面规划了我们的电子邮件内容和活动日历,我们将使用上面的模板通过电子邮件服务提供商 MailChimp 创建我们的第一封电子邮件。

Photo used in the email by Austin Distel on Unsplash

测试是提高转化率的一个有效方法。实现这一点的方法之一是通过对我们的电子邮件内容进行 A/B 测试。

现在我们已经创建了序列中的第一封电子邮件,并对其进行了测试,是时候发送了!分析电子邮件营销活动的结果是电子邮件营销活动的重要组成部分。检查对电子邮件营销活动很重要的指标有助于指导我们为未来的电子邮件发送提出建议。

对电子邮件二和三的建议

我们应该考虑到我们有 225 封退回的电子邮件和 30 个未订阅的客户。首先,我们应该确保取消订阅的电子邮件从邮件列表中删除。然后,我们需要通过处理被退回的电子邮件来调整列表,并根据需要通过归档错别字或删除它们来找到解决方案。

根据 A/B 测试的结果,我们应该调整邮件正文、主题行、CTA、视觉效果等元素。然后,我们可以对这两封邮件进行 A/B 测试。我们应该留出一些时间来发送每封电子邮件。分析完邮件二,我们需要一些时间来分析,然后调整邮件三。

无论是你的盛大开业还是你的公司已经建立,一个有效的电子邮件营销计划是促进和发展你的业务、增加收入和销售更多东西的关键。—Mailchimp.com

最终想法— 2019 年及以后

第四次工业革命代表了由于采用信息物理系统和物联网,人们生活、工作和相互交往方式的逐步改变。

信息物理系统是一种由基于计算机的算法管理的机制,该算法随着网络连接(互联网)及其用户而增强。

Infographic by Andrew Churchill at Raconteur

我们应该承认机器学习(ML)和人工智能(AI)促使我们进行更有效的数据分析的方式。人工智能使数字营销人员更易于管理,可以向客户提供更相关的内容、产品和服务信息,也称为“超个性化”。

第五次工业革命,或称工业 5.0,将聚焦于人与机器的合作,因为人类智能与认知计算和谐相处。通过协作机器人将人类重新投入工业生产,工人将获得更高技能,在生产中提供增值任务,从而为客户带来大规模定制和个性化。本·罗西

Infographic by Joydeep Bhattacharya at Single Grain

数字技能即服务(DSaaS)

原文:https://towardsdatascience.com/digital-skills-as-a-service-dsaas-1c5a7878b6be?source=collection_archive---------38-----------------------

你有没有想过,以你有生之年所获得的经验和技能,未来会是怎样?

第 1 章——知识是死资产

你有没有想过,以你有生之年所获得的经验和技能,未来会是怎样?

我们平均工作 40-50 年,在此期间,我们每天都获得新的知识。当我们谈论 IT 行业时,这个行业的人正在使用一些特定的软件或技术,因此他们在某个时间点成为专家。

在 40-50 年内,我们所有的技能对我们来说都变成了死资产。当然,我们可以培养新人,我们可以把一部分知识转移给他们。我找不到任何关于这方面的研究,但是我相信如果我们把我们所有的知识和技能作为 100%,那么最有可能的是我们最多可以转移其中的 0.000001%。其余的都是无用的资产。

几年前,我开始问自己,是否有办法将我的知识转化为数字资产,以便专业知识在未来发挥作用,而不会成为死资产。我知道这在今天是不可能的,当然,也没有办法将我们的大脑数字化。前一段时间,我决定尝试转换我的知识的一小部分。

第 2 章——挫折

我曾经做过八年的 SAP 顾问。我为不同的客户实施过新的 SAP 项目,也在 SAP 支持部门(服务台)工作过。

SAP 服务台的工作很糟糕,因为我的主要职责是解决终端用户的问题,所以我的大脑专注于维护现有的东西,而不是创造新的东西,这是一个遗憾。在工作中,我发现服务台收到的所有问题中有高达 40%是相同的;他们直截了当,我觉得自己是一只猴子。

我需要做的是每个月重复同样的行动来解决问题。这让我好心疼。从一个方面来说,这是好的,我收到了钱,我甚至不需要思考和强调我的大脑。另一方面,我工作的动力是零以下。

第 3 章—机会

服务台的工作成果非常好。即使是不好的经历也可以变成好的经历。

我开始思考:如果我在一家特定的公司工作,在服务台做同样重复的工作。那么最有可能的是,有成千上万像我一样的人在全球所有其他公司做着同样的事情。

我的下一个想法——“如何复制我并卖给世界上所有的公司来覆盖重复的工作?”

更重要的是,我开始不仅考虑服务台,还考虑一般的企业软件和企业软件的用户。我会解释的。在一家大型国际公司(FMSG)的销售部门,销售人员不是每天都在 ERP(例如 SAP)中工作,他们也没有在桌面前花费太多时间。但是他们使用来自 ERP 的信息,并且每次他们都需要关于客户信用限额的信息。

关于如何获得信贷限额,他们有两种选择。第一个选项是记住 SAP 在哪里,如何登录 SAP,凭证,交易,并找到具有所需信用限额的字段。第二种选择是给财务部门写一封邮件,因为财务部门的男生女生可以很快查到这些信息。每次他们选择第二个选项。为什么?他们更容易使用自然语言来获取信息;他们不想使用图形用户界面,因为这需要更多的努力。他们忘记了,对财务部的同事提出这样的要求,他们会花费更多的时间,他们自己的时间和同事的时间。

同样,如果在一个特定的公司存在这样的问题,那么很可能在所有其他公司,销售人员都面临着类似的问题。

新想法——如何复制我并销售给世界上所有的公司,让他们检查企业软件中的简单信息并提供答案?

第 4 章—解决方案

三年前,第一次看到 AI 解决方案的 demo——IP Soft 的 Amelia。我意识到了人工智能技术的能力,尤其是在处理自然语言方面。这改变了我的想法。

如果机器可以理解自然语言和请求的上下文,那么我们可以通过使用公式 If This Then That 来对流程流(对话树)进行编程以执行一些操作。

然后,市场上没有太多的人工智能服务(NLP,语法分析)允许一个没有任何人工智能/ML 知识的人开始构建聊天机器人解决方案。

第 5 章—数字技能

一方面,我们有商业面临的问题,另一方面,人工智能技术的能力。

为了从技术和问题中提取协同效应,我开始思考我们如何回答这个主要问题:如何复制我自己并出售给世界上所有的公司来覆盖重复的工作?

答案很简单——数字技能!

所以我试着把我在 SAP 中的知识分割成最小的片段(原子),每一个小片段都变得等同于数字技能。

一个简单的例子,我知道如何在 SAP 中重置密码,我可以在世界上任何一家使用 SAP 的公司开始工作,我可以从工作的第一秒开始重置密码。这是我的知识,如何在 SAP 中重置密码只有一种方法。因此,在 SAP 中重置密码的过程正在成为一项数字技能。

因此,通过使用人工智能技术,我们可以理解自然语言和上下文。另一方面,通过使用我们在 SAP 中的知识,我们可以构建 API 来重置密码。最后,通过结合人工智能技术和技术专业知识,我们可以与最终用户创建一个对话对话框来重置密码。

通过这种方法,我们已经回答了最初的问题。当然,这是一个高层次的回答,还有许多关于网络集成、安全性等问题。但是方法是明显的。

最后,我们建立了一个平台,允许我们创造数字技能并发布它们。

第 6 章—知识的数字化

我也非常喜欢亚马逊 Alexa 的整体概念。对终端客户来说,真正的价值不是设备或技术,而是 Alexa 技能和即插即用安装。你需要在家里花五分钟安装 Alexa,然后你就可以开始用你的声音获取天气或播放音乐等。对我来说,作为一个 Alexa 客户,真正的价值是技能,因为它们可以简化我的生活。

我们决定使用同样的方法。如果世界各地的人们可以创造企业软件或 IT 产品/程序的技能,并在市场上发布它们,会怎么样?

这将意味着任何人/开发者/顾问都可以通过创造数字技能来转移他们的知识,并在市场(技能商店)上发布它们,指定技能的价格并出售它们。

现在我们可以回到最初的问题:

" 你有没有想过,以你有生之年所获得的经验和技能,未来会是怎样??”

答案将是:

“你的经历可以造福世界,甚至在你退休后也能给你带来金钱。”

…或者您可以将这些技能传授或分配给孩子,让他们从中受益!

问候,

Andrii Rudchuk,首席执行官@ Hala.ai

数字部落:用 K 均值进行客户聚类

原文:https://towardsdatascience.com/digital-tribes-customer-clustering-with-k-means-6db8580a7a60?source=collection_archive---------16-----------------------

使用 PYTHON 进行客户细分

了解如何使用强大的机器学习技术来更好地细分您的客户群

Photo by Perry Grone on Unsplash

这篇文章是 分而治之:使用 RFM 分析 故事细分你的客户的后续,在这里我们开始使用经典的 RFM 分析细分我们的用户群。

这一次,我们将探索一些机器学习技术,以获得更多定制和微调的分组。一种方法是使用聚类算法,例如 K-Means

什么是集群?

聚类模型是无监督机器学习算法组的一部分。在无监督学习问题中,没有明确的目标变量,例如,我们不试图将客户分为我们事先知道存在的不同类别。相反,该算法使用数据本身的模式来识别和分组相似的观察结果,并找到这些类别。

K-Means 模型的工作原理是寻找数据集中具有相似属性的不同数据点组(聚类)。它通过以最小化所有点到包含它们的聚类的质心的距离的方式对点进行分组来做到这一点。

换句话说:该算法的主要目标是找到聚类,使得同一聚类中的数据点之间的距离小于不同聚类中任意两点之间的距离。这样,属于同一组的成员往往具有相似的特征,而与其他组的成员不同。

解决了这个问题,让我们回到数据分析上来,好吗?

一些特征工程和预处理

由于我们试图了解更多关于客户行为模式的信息,我们可以使用这些行为的指示性特征来训练 K-Means 模型。例如,我们可以从使用我们在上一篇文章中计算的新近度频率货币值任期开始。

这样,我们可以将志同道合的客户聚集在一起,然后分析这些不同的群体,以获得模式和趋势方面的见解,从而帮助制定未来的业务决策。

让我们首先从我们在上一篇文章中生成的客户数据集中抽取必要的列,并查看特性之间的相关性:

# retain only the recency, frequency, tenure and monetary columns
rfm = customer[['customer_id', 'recency', 'frequency', 'tenure', 'mean_value', 'total_value']]
rfm.set_index('customer_id', inplace=True)# build a feature correlation matrix
rfm_corr = rfm.corr()fig, ax = plt.subplots(1, 2, figsize=(12,6))# create a heatmap to display the correlations
sns.heatmap(rfm_corr, annot=True, ax=ax[0], square=True)
ax[0].set_ylim([5, 0])
ax[0].set_title('Correlation heatmap')
ax[0].set_xlabel('Variables')# plot the regrassion line to highlight the strong correlation
sns.regplot(rfm.frequency, rfm.total_value, ax=ax[1])
ax[1].set_title('Frequency x Total value')
ax[1].set_xlabel('Frequency')
ax[1].set_ylabel('Total Value')
# Turn off tick labels
ax[1].set_yticklabels([])
ax[1].set_xticklabels([])fig.suptitle('Feature correlations', fontsize=20)
plt.show()

Figure 1: Feature correlations

可以清楚地看到, total_valuefrequency 列是非常强相关的(系数为 0.9)。事后看来,你可能会认为这是显而易见的:从长远来看,购买越频繁的客户往往会花更多的钱。虽然,这表明在试图训练任何机器学习模型之前,仔细检查你的数据是多么重要!

丢弃高度相关的要素是一种很好的做法,因为它们会给数据增加一些冗余,并且可能会影响模型的最终结果。从现在开始,我们将删除 total_value ,并在分析中使用 mean_value 列。

rfm.drop('total_value', axis=1, inplace=True)

我们必须采取的另一个步骤是从数据集中移除离群值。由于 K-Means 算法依赖于点与点之间距离的计算(大部分时间是简单的欧氏距离),因此受离群点存在的影响较大。让我们从检查我们的四个特征的盒图开始。

fig, ax = plt.subplots(2, 2, figsize=(12,6))sns.boxplot(rfm.recency, orient='v', ax=ax[0][0])
ax[0][0].set_title('Recency')
ax[0][0].set_ylabel('Values')
ax[0][0].set_yticklabels([])
ax[0][0].set_xticklabels([])sns.boxplot(rfm.frequency, orient='v', ax=ax[0][1])
ax[0][1].set_title('Frequency')
ax[0][1].set_ylabel('Values')
ax[0][1].set_yticklabels([])
ax[0][1].set_xticklabels([])sns.boxplot(rfm.mean_value, orient='v', ax=ax[1][0])
ax[1][0].set_title('Monetary')
ax[1][0].set_ylabel('Values')
ax[1][0].set_yticklabels([])
ax[1][0].set_xticklabels([])sns.boxplot(rfm.tenure, orient='v', ax=ax[1][1])
ax[1][1].set_title('Tenure')
ax[1][1].set_ylabel('Values')
ax[1][1].set_yticklabels([])
ax[1][1].set_xticklabels([])plt.tight_layout()
plt.show()

Figure 2: boxplot of features before outlier removal

我们可以看到在平均值频率列的分布中明显存在异常值,其中一些异常值距离其余的点非常远。我们将根据 Z 分数移除这些异常值:分数大于 3 的任何点都将被移除,即距离平均值超过 3 个标准偏差的任何点。

from scipy import stats# remove outliers based on the Z-score# For each column, first it computes the Z-score of each value in the column, relative to the column mean and standard deviation. 
# Then is takes the absolute of Z-score because the direction does not matter, only if it is below the threshold. 
# The .all(axis=1) ensures that for each row, all column satisfy the constraint. 
# Finally, result of this condition is used to index the dataframe.
is_inliner = (np.abs(stats.zscore(rfm)) < 3).all(axis=1)rfm = rfm[is_inliner]

然后我们可以重复箱线图来检查新的数据分布

Figure 3: boxplot of features after outlier removal

好多了!一些异常值将会保留,因为它们没有下降到均值的足够远的位置而被去除。但是,比较有攻击性的都没有了。

我们必须采取的最后一个预处理步骤是标准化数据。 K-Means 算法更适合正态分布的数据。考虑到这一点,我们将使用一个 log 函数来尝试消除一些数据的偏斜,然后使用来自 scikit-learn标准定标器来转换分布,使均值接近 0,而标准差接近 1。

# standardize variables
from sklearn.preprocessing import StandardScaler# take the log to unskew the data
log_rfm = np.log(rfm)
# use fit_transfome from StandardScaler to standardize the data (mean=0, std=1)
scaler = StandardScaler()
scaled_rfm_array = scaler.fit_transform(log_rfm)
scaled_rfm = pd.DataFrame(
    scaled_rfm_array,
    columns=rfm.columns,
    index=rfm.index,
)

让我们通过最后看一下我们的数据分布来完成预处理

fig, ax = plt.subplots(2, 2, figsize=(12,6))sns.distplot(scaled_rfm.recency, ax=ax[0][0])
ax[0][0].set_title('Recency')
ax[0][0].set_xlabel('Values')sns.distplot(scaled_rfm.frequency, ax=ax[0][1])
ax[0][1].set_title('Frequency')
ax[0][1].set_xlabel('Value')sns.distplot(scaled_rfm.mean_value, ax=ax[1][0])
ax[1][0].set_title('Monetary')
ax[1][0].set_xlabel('Value')sns.distplot(scaled_rfm.tenure, ax=ax[1][1])
ax[1][1].set_title('Tenure')
ax[1][1].set_xlabel('Value')plt.tight_layout()
plt.show()

Figure 4: feature distributions

那看起来足够好了!让我们开始你们期待已久的精彩部分吧。

最后,真正的交易

我们终于准备好安装 K-Means 模型了!然而,K-Means 算法的一个缺点是,您必须预先提供您希望它生成的聚类数。该算法不能从数据中学习该参数。

我们可以从任意设置集群数为 3 开始。这是我们在上一篇文章中用来进一步细分 RFM 得分的层级数,感觉这是一个很好的经验法则。

K-Means 是一种迭代算法。预先确定聚类数后,该模型将每个数据点分配给质心最近的聚类。然后重新计算质心,并重复该过程,直到数据点分配没有变化。这意味着我们有效地缩短了距离。

# import kmeans from sklearn
from sklearn.cluster import KMeans# run kmeans
kmeans = KMeans(n_clusters=2, random_state=1)
kmeans.fit(scaled_rfm)# extract the cluster labels from thte fitted model
cluster_labels = kmeans.labels_

搞定了。这就是训练一个 K-Means 模型所要做的一切。但是等等,我们已经根据经验将聚类数设置为 3,但是我们如何发现这个数是否最适合我们的数据呢?

我们可以看看各种 K-Means 模型拟合不同数量的 K误差平方和(SSE)SSE 是每个观察值与其聚类平均值之间的平方差之和。它可以用来衡量一个集群内的变化。

SSE 函数将随着集群数量的增加而单调递减。然而,下降最初非常陡峭,在达到某个值K后,下降开始放缓,形成我们所说的肘形曲线。图的“肘”上的值 K (即下降开始减缓的 K 的值)为我们提供了给定数据集的最佳聚类数的指示。这种方法可以与特定领域的问题和需求知识相结合,以决定要使用的集群数量。

*# find the ideal number of clusters
# Fit KMeans and calculate SSE for each k
sse = {}
for k in range(1, 11):
    kmeans = KMeans(n_clusters=k, random_state=1)
    kmeans.fit(scaled_rfm)
    sse[k] = kmeans.inertia_ # sum of squared distances to closest cluster center

# Plot SSE for each k
plt.title('The Elbow Method')
plt.xlabel('k')
plt.ylabel('SSE') 
sns.pointplot(x=list(sse.keys()), y=list(sse.values()))
plt.show()*

Figure 4: Elbow plot

看起来 3 或 4 个分类将是更好地代表数据集的分类数。只是为了比较,我们将再运行 K-Means 3 次,使其适合 2、3 和 4 个集群。

*# fit kmeans with 2 clustes
kmeans = KMeans(n_clusters=2, random_state=1)
kmeans.fit(scaled_rfm)
# extract the lables
cluster_labels_k2 = kmeans.labels_
# assing the cluster labels to the dataset
rfm_k2 = rfm.assign(cluster = cluster_labels_k2)# fit kmeans with 3 clustes
kmeans = KMeans(n_clusters=3, random_state=1)
kmeans.fit(scaled_rfm)
# extract the lables
cluster_labels_k3 = kmeans.labels_
# assing the cluster labels to the dataset
rfm_k3 = rfm.assign(cluster = cluster_labels_k3)# fit kmeans with 4 clustes
kmeans = KMeans(n_clusters=4, random_state=1)
kmeans.fit(scaled_rfm)
# extract the lables
cluster_labels_k4 = kmeans.labels_
# assing the cluster labels to the dataset
rfm_k4 = rfm.assign(cluster = cluster_labels_k4)*

我们最终得到 3 个不同的数据集: rfm_k2rfm_k3rfm_k4 ,每个数据集都包含每个不同值 o K 的聚类信息。

从集群中构建客户角色

我们可以做的第一件事是创建汇总表来检查每个集群中包含的样本的基本信息。与我们在上一篇文章中所做的类似,我们将包括一些汇总统计数据,比如每个特征的均值值,以及分配给每个聚类的样本数。

*# group the rfm_k2 dataset by the clusters
rfm_k2_summary = rfm_k2.groupby('cluster').agg(
    recency=('recency',  'mean'),
    frequency=('frequency', 'mean'),
    tenure=('tenure', 'mean'),
    monetary=('mean_value', 'mean'),
    samples=('mean_value', 'count')
).round(0)# group the rfm_k3 dataset by the clusters
rfm_k3_summary = rfm_k3.groupby('cluster').agg(
    recency=('recency', 'mean'),
    frequency=('frequency', 'mean'),
    tenure=('tenure', 'mean'),
    monetary=('mean_value', 'mean'),
    samples=('mean_value', 'count')
).round(0)# group the rfm_k4 dataset by the clusters
rfm_k4_summary = rfm_k4.groupby('cluster').agg(
    recency=('recency',  'mean'),
    frequency=('frequency', 'mean'),
    tenure=('tenure', 'mean'),
    monetary=('mean_value', 'mean'),
    samples=('mean_value', 'count')
).round(0)*

另一种更好地理解和比较分段的方法是创建所谓的蛇形图。该图来自市场研究技术,用于比较不同的细分市场,并提供每个细分市场属性的可视化表示。

要创建此图,我们需要归一化数据(中心和刻度),然后绘制每个属性的每个聚类的平均归一化值。

*# assign the cluster labes for the scaled rfm
scaled_rfm_k2 = scaled_rfm.copy()
scaled_rfm_k2['cluster'] = rfm_k2.clusterscaled_rfm_k3 = scaled_rfm.copy()
scaled_rfm_k3['cluster'] = rfm_k3.clusterscaled_rfm_k4 = scaled_rfm.copy()
scaled_rfm_k4['cluster'] = rfm_k4.cluster# melt the dataframes to get the required format
rfm_k2_melt = pd.melt(
    scaled_rfm_k2.reset_index(), 
    id_vars=['customer_id', 'cluster'],
    value_vars=['recency', 'frequency', 'mean_value', 'tenure'], 
    var_name='attribute',
    value_name='value'
)
rfm_k3_melt = pd.melt(
    scaled_rfm_k3.reset_index(), 
    id_vars=['customer_id', 'cluster'],
    value_vars=['recency', 'frequency', 'mean_value', 'tenure'], 
    var_name='attribute',
    value_name='value'
)
rfm_k4_melt = pd.melt(
    scaled_rfm_k4.reset_index(), 
    id_vars=['customer_id', 'cluster'],
    value_vars=['recency', 'frequency', 'mean_value', 'tenure'], 
    var_name='attribute',
    value_name='value'
)# plot the snakeplot for each dataset
fig, ax = plt.subplots(1, 3, figsize=(15,5))sns.lineplot(
    x="attribute",
    y="value",
    hue='cluster',
    data=rfm_k2_melt,
    ax=ax[0],
)
ax[0].set_title('2 Clusters')
ax[0].set_xlabel('Variables')sns.lineplot(
    x="attribute",
    y="value",
    hue='cluster',
    data=rfm_k3_melt,
    ax=ax[1],
)
ax[1].set_title('3 Clusters')
ax[1].set_xlabel('Variables')sns.lineplot(
    x="attribute",
    y="value",
    hue='cluster',
    data=rfm_k4_melt,
    ax=ax[2],
)
ax[2].set_title('4 Clusters')
ax[2].set_xlabel('Variables')fig.suptitle('Snake plot of standardized variables', fontsize=20)
plt.show()*

Figure 6: Snakeplot

有了这个蛇形图,就更容易看出生成的集群之间的差异。

最后,我们可以看到聚类之间差异的最后一件事是检查聚类属性相对于总体的相对重要性。由此,我们可以看出哪个特征在集群的形成中起了更重要的作用。首先,我们需要计算每个聚类的平均值,然后将它们除以总体平均值减 1。

*# relative importance of segment attributes
cluster_avg_k2 = rfm_k2.groupby(['cluster']).mean()
cluster_avg_k3 = rfm_k3.groupby(['cluster']).mean()
cluster_avg_k4 = rfm_k4.groupby(['cluster']).mean()population_avg = rfm.mean()
relative_imp_k2 = cluster_avg_k2 / population_avg - 1
relative_imp_k3 = cluster_avg_k3 / population_avg - 1
relative_imp_k4 = cluster_avg_k4 / population_avg - 1fig, ax = plt.subplots(1, 3, figsize=(11,5))sns.heatmap(
    data=relative_imp_k2,
    annot=True,
    fmt='.2f',
    cmap='RdYlGn',
    linewidths=2,
    square=True,
    ax=ax[0],
)
ax[0].set_ylim([0, 2])
ax[0].set_title('2 Clusters')
ax[0].set_xlabel('Variables')sns.heatmap(
    data=relative_imp_k3,
    annot=True,
    fmt='.2f',
    cmap='RdYlGn',
    linewidths=2,
    square=True,
    ax=ax[1],
) 
ax[1].set_ylim([0, 3])
ax[1].set_title('3 Clusters')
ax[1].set_xlabel('Variables')sns.heatmap(
    data=relative_imp_k4,
    annot=True,
    fmt='.2f',
    cmap='RdYlGn',
    linewidths=2,
    square=True,
    ax=ax[2],
) 
ax[2].set_ylim([0, 4])
ax[2].set_title('4 Clusters')
ax[2].set_xlabel('Variables')fig.suptitle('Relative importance of attributes', fontsize=20)
# plt.tight_layout()
plt.show()*

Figure 7: Relative importance of the attributes

这里,离 0 越远,该片段的特定特征就越重要。

可视化我们的结果

这一切都很酷,但是除了查看每个集群的指标之外,我们如何检查我们的结果呢?如果我们能有办法在空间上可视化这些星团会怎么样?但是我们的特征矩阵有 4 个特征,我们不能在一个 4 维空间里画出一些东西…我们能吗?

是也不是!实际上,您不能在 4 维上绘图,但是您可以使用一些巧妙的技巧将数据集的维度减少到 2,然后在常规平面上绘图!

其中一项技术是古老的主成分分析(PCA) 。有了它,我们可以围绕最高方差的轴旋转和变换数据,然后选择只保留我们需要的 k 主成分。在我们的例子中,我们将使用它来旋转多维数据集并将其转换为二维数据集。

*from sklearn.decomposition import PCApca = PCA(n_components=2)pca_array = pca.fit_transform(scaled_rfm)
pca_data = pd.DataFrame(pca_array, columns=['x', 'y'], index=scaled_rfm.index)pca_data['k2'] = rfm_k2.cluster
pca_data['k3'] = rfm_k3.cluster
pca_data['k4'] = rfm_k4.clusterfig, ax = plt.subplots(1, 3, figsize=(15,5))sns.scatterplot(x='x', y='y', hue='k2', data=pca_data, ax=ax[0])
ax[0].set_title('2 Clusters')
ax[0].set_xlabel('X')
ax[0].set_ylabel('Y')sns.scatterplot(x='x', y='y', hue='k3', data=pca_data, ax=ax[1])
ax[1].set_title('3 Clusters')
ax[1].set_xlabel('X')
ax[1].set_ylabel('Y')sns.scatterplot(x='x', y='y', hue='k4', data=pca_data, ax=ax[2])
ax[2].set_title('4 Clusters')
ax[2].set_xlabel('X')
ax[2].set_ylabel('Y')fig.suptitle('PCA plot of clusters', fontsize=20)
plt.show()*

Figure 8: Dimensionality reduction with PCA

正如我们在上面的图中看到的,看起来 3 毕竟是理想的集群数。

另一种可视化高维数据的技术是t-分布式随机邻居嵌入(t-SNE) 。它是一种更复杂的非线性技术,涉及联合概率。对该过程内部工作的详细解释超出了本文的范围。然而,由于它也包含在 scikit-learn 库中,使用它就像我们迄今为止使用的其他模型一样简单。

*from sklearn.manifold import TSNEtsne = TSNE(learning_rate=300, perplexity=80, early_exaggeration=20)tsne_array = tsne.fit_transform(scaled_rfm)
tsne_data = pd.DataFrame(tsne_array, columns=['x', 'y'], index=scaled_rfm.index)tsne_data['k2'] = rfm_k2.cluster
tsne_data['k3'] = rfm_k3.cluster
tsne_data['k4'] = rfm_k4.clusterfig, ax = plt.subplots(1, 3, figsize=(15,5))sns.scatterplot(x='x', y='y', hue='k2', data=tsne_data, ax=ax[0])
ax[0].set_title('2 Clusters')
ax[0].set_xlabel('X')
ax[0].set_ylabel('Y')sns.scatterplot(x='x', y='y', hue='k3', data=tsne_data, ax=ax[1])
ax[1].set_title('3 Clusters')
ax[1].set_xlabel('X')
ax[1].set_ylabel('Y')sns.scatterplot(x='x', y='y', hue='k4', data=tsne_data, ax=ax[2])
ax[2].set_title('4 Clusters')
ax[2].set_xlabel('X')
ax[2].set_ylabel('Y')fig.suptitle('t-SNE plot of clusters', fontsize=20)
# plt.tight_layout()
plt.show()*

Figure 9: Dimensionality reduction with PCA

结论

这就是我们的客户细分之旅!我希望你喜欢它,并希望在这个过程中学到一些东西。如果你看到了,不要忘记留下一些掌声,请继续关注下一个系列。

数字图灵测试

原文:https://towardsdatascience.com/digital-turing-test-94532434292b?source=collection_archive---------27-----------------------

人工智能是如何变得与人类无法区分的

在人类历史的这个阶段,几乎每个人都听说过图灵测试——与一个我们会误认为是人类的机器人进行对话。

虽然我一直在通过机器学习自动化不同的数字任务——从分类电子邮件到获取数据——但我突然发现这不再相关了。以客户服务聊天为例,每个人都会时不时地进行聊天。你能确定你在和一个机器人还是一个人说话吗?或者你是否在和远方的人交换电子邮件——对方是一个真实的人吗?我再也不知道了。

我对你能生成或自动化的东西了解得越多,我就越不相信我在互联网上看到的东西。如果你知道 GANs、GPT-2 或 GROVE,你就不能像以前那样消化网络内容。50%看起来是合成的(最终也没那么糟糕)。

这就是为什么我提出了一个数字图灵测试(简称 DTT),一个更广泛的概念,将包括上述情况。

我们会说,一个给定的工具集——有前端可以与之交互的 AI/ML 算法——通过了 DTT,如果与它交互的大多数人认为它是另一边的一个真人,或者不能肯定地说它不是。通过售后服务调查进行基准测试相对容易,虽然> 95%肯定表明它与人一样好,但它与我们正在自动化的手头任务密切相关。因此,有时甚至超过 50%可能是一个很好的指标,表明我们的算法做得很好。

何必呢?因为我们想测量我们接近 AGI 的速度——一种人工通用智能——它能够在所有数字任务中 95%以上与人类无法区分。最终,AGI 的 MVP 将是一堆连接起来的超高效工具集,完美地通过 DTT。

到那时,我们的经济和世界将会彻底改变。

用 AI 和 ML 数字化尼日利亚手写疫苗接种记录

原文:https://towardsdatascience.com/digitizing-handwritten-vaccination-records-in-nigeria-with-artificial-intelligence-and-machine-cff7721b177a?source=collection_archive---------26-----------------------

简介

作为小儿麻痹症数据科学家,我在联合国儿童基金会尼日利亚办事处工作时,遇到了由 20,000 名小儿麻痹症志愿者分发的疫苗接种卡存在错误的问题,甚至需要检查更大数量的疫苗接种卡。简单的数字化和给每个人一个平板电脑不是一个选项。经过研究,我决定使用 AI/ML 和计算机视觉从卡片上“读取”信息,然后提供关于最常见错误的反馈机制,并预测正确的信息。

在本教程中,您将看到如何实现这一点,以及未来优化的结果和建议。我将主要使用 python 库 TensorFlow 和 OpenCV 以及一些支持库。

安装

使用 TensorFlow 的安装因您要使用的操作系统和硬件而异。参考本文的一般说明 此处

对于本教程,我将使用以下软件包:

OS:Linux _ X64(Arch Linux)
Python 包管理器:Anaconda 或 Miniconda(安装说明 此处)
CUDA 10 . 1 . 105
cud nn 7 . 5 . 0
Python tensor flow Api V1
Opencv-Python

使用 miniconda(或 anaconda),按照以下步骤安装所需的 python 库

创造康达环境

conda create -n pyocr
conda activate pyocr

安装所需的软件包

conda install tensorflow
conda install opencv
conda install -c lightsource2-tag pyzbar
pip install editdistance

为将来的复制保留库版本

conda env export > <environment-name>.yml

在另一台机器上重新创建环境

要在另一台计算机上重新创建环境,请在另一台计算机上创建并激活环境后使用此方法

conda env create -f <environment-name>.yml

使用张量流识别文本

首先要理解的是,该模型的准确性取决于您将用于训练的样本。需要更多的样本来获得更高的精度。这也意味着如果你需要识别多人写的文本,你必须包含足够多的他们写的文本样本

整个教程代码都上传到 GitHub 存储库中。如果您需要最终代码,可以使用 git clone 来克隆这个存储库

git clone git@github.com:PiotrKrosniak/ocrbot.git pyocr

输入

查看上面文件夹中的输入文件夹。将您想要运行脚本的图像保存在这里(以便更好地组织)

Fig 1: Github folder structure for input folder

获取训练数据

  1. 获取 IAM 数据集
  2. 报名地点:http://www . fki . INF . unibe . ch/databases/iam-手写-数据库
  3. 下载 ascii/words.txt。
  4. 将 words.txt 放入数据/目录中。
  5. 下载 words/words.tgz.
    。创建目录 data/words/。

a.将 words.tgz 的内容(目录 a01、a02、…)放入 data/words/
i.
对于 linux 终端—在文件夹 data 中,运行 linux 命令 tar xvf words.tgz -C words)

  1. 运行 checkDirs.py 对文件进行粗略检查

检查目录结构是否如下所示:

data
— test.png
— words.txt
— words
— — a01
— — — a01–000u
— — — — a01–000u-00–00.png
— — — — …
— — — …
— — a02
— — …

训练模型

首先提取模型。将 model.zip fil 解压到同一个文件夹( /model)中,然后在 src 目录下运行训练。此处的脚本将基于之前训练的模型,并根据您的数据提高其准确性

python main.py — train

这可能需要很长时间来运行培训,如果没有 GPU,可能需要 16 到 18 个小时。该脚本运行称为 epochs 的训练批次,直到连续批次之间的文本识别准确性没有明显提高。完成后,您将看到在模型文件夹下生成的文件。

Fig 2: The Model folder with the TensorFlow trained models

快照和检查点将如上生成

运行 OCR 脚本

既然模型是在 code 文件夹中生成的,让我们运行代码从我们的图像中获取文本。确保您的输入文件在输入文件夹中

Fig 3: Input folder with your images

运行 src 文件夹中的代码(在终端内部)

Python Demo.py

代码将在输入图像上运行。您将在终端中看到如下输出

Fig 4: Sample Terminal output on running inference

代码运行完成后,输出将出现在输出文件夹中:

Fig 5: Output folder after running OCR script

文件夹将包含表格单元格,每个单元格作为一个单独的图像。在下一节中,我们将使用这些生成的图像来进一步提高我们的准确性

但是,基于您当前的模型,识别的文本将以与输入图像相同的名称保存在 CSV 文件中。这些 CSV 文件可以在 Microsoft Excel 或 google sheets 等电子表格软件中打开

提高精度

图像中的单个表格单元格作为单独的图像存储在输出文件夹中。这些图像可以帮助模型识别您自己数据集的手写->文本映射。通常,如果您有许多不常用的英文单词,如姓名,或者图像中的手写风格与训练模型的 IAM 默认数据集有很大不同,则这是必要的

要使用这些表格单元格图像来训练数据集,请按照以下步骤操作:

  1. 预处理图像,使其符合 IAM 数据集。这对于脚本正确训练你的图像是绝对必要的。在更高的级别上,执行以下步骤:

a.加粗文本中模糊的线条

b.用分词去掉单词周围多余的空格(参考 这段 代码)

c.通过阈值技术提高对比度

  1. 以 Dataloader.py 模块使用的格式重命名并复制数据文件夹中的图像:

例如,文件 c01–009–00–00.png 应该保存在以下文件夹层次结构中

| Words
| — a01
| — — c01–009
| — — — c01–009–00–00.png

但是,您可以通过编辑 DataLoader.py 模块来更改这些文件夹层次结构/文件命名约定

3.编辑数据模块中的 words.txt 文件以包含这些图像

以下代码执行操作 1a 和 b

import numpy as np
import cv2# read
img = cv2.imread(‘in.png’, cv2.IMREAD_GRAYSCALE)# increase contrast
pxmin = np.min(img)
pxmax = np.max(img)
imgContrast = (img — pxmin) / (pxmax — pxmin) * 255# increase line width
kernel = np.ones((3, 3), np.uint8)
imgMorph = cv2.erode(imgContrast, kernel, iterations = 1)# write
cv2.imwrite(‘out.png’, imgMorph)

要编写 words.txt 文件,请遵循以下适用于您的图像的格式:

样本线:a01–000 u-00–00 ok 154 1 408 768 27 51 AT A

  • a01–000 u-00–00->表格 a01–000 u 中第 00 行的 word id。这也是您正在映射的图像的文件名
  • 确定->分词结果
  • 好:单词是正确的
  • 呃:词的切分可能不好
  • 154 -> graylevel 对包含这个单词的行进行二值化。这是对比度拉伸/阈值处理步骤。
  • 1 ->该词的成分数
  • 4087682751-->以 x,y,w,h 格式围绕该单词的边框
  • 在->这个词的语法标签,见

文件 tagset.txt 获得解释

  • 描述图像文本内容的这个词的转录

以上将为您的图像定制模型。为了提高模型本身的精度,请参考本页 中 的提高精度部分

方法的解释

该代码执行三个主要步骤:

  1. 匹配模板并旋转图像
  2. 识别表格中的行并进行裁剪
  3. 使用 python-tensorflow 识别文本

该识别算法基于简化版本的 HTR 文本识别系统。如果对机理感兴趣,可以参考这篇 论文

它由 5 个 CNN 层、2 个 RNN (LSTM)层和 CTC 丢失和解码层组成

  • 输入图像是灰度值图像,大小为 128×32
  • 5 个 CNN 层将输入图像映射到大小为 32×256 的特征序列
  • 具有 256 个单元的 2 个 LSTM 层通过该序列传播信息,并将该序列映射到大小为 32×80 的矩阵。每个矩阵元素代表 80 个字符中的一个在 32 个时间步长中的一个的分数
  • CTC 层或者在给定矩阵和基本事实文本的情况下计算损失值(训练时),或者利用最佳路径解码或波束搜索解码将矩阵解码为最终文本(推断时)
  • 批量大小设置为 50

图 5:使用张量流的 OCR 步骤中涉及的机制

结论

遵循本教程,您现在有了一种自动数字化表格格式的手写文本的方法。一旦你训练模型识别你的笔迹并根据你的需求进行定制,就可以节省无数的时间。但是,要小心,因为识别不是 100%准确的。因此,在您准备好共享最终的电子表格之前,可能需要在电子表格生成之后进行一轮高级别的校对

参考:

  1. 代码参考:https://github.com/PiotrKrosniak/ocrbot
  2. 使用 google TensorFlow 进行手写识别:https://towards data science . com/build-a-handled-text-recognition-system-using-tensor flow-2326 a 3487 cd5
  3. 处理边缘案件:https://towards data science . com/FAQ-build-a-handled-text-recognition-system-using-tensor flow-27648 FB 18519
  4. 数据集开始:http://www . fki . INF . unibe . ch/databases/iam-手写-数据库
  5. https://github.com/githubharald/SimpleHTR

Python 的降维技术

原文:https://towardsdatascience.com/dimension-reduction-techniques-with-python-f36ca7009e5c?source=collection_archive---------0-----------------------

实践用户实用指南

(2021 年 10 月 12 日修订)

为什么我们需要降维?

高维数据集是具有大量列(或变量)的数据集。这样的数据集提出了许多数学或计算挑战好消息是变量(或称为特征)通常是相关的——高维数据“表面上”由少量简单变量支配。我们可以找到变量的子集来表示数据中相同级别的信息,或者将变量转换为一组新的变量,而不会丢失太多信息。虽然高性能计算可以处理高维数据,但在许多应用中仍然需要降低原始数据的维数。

当我们想到降维时,主成分分析(PCA)可能是最流行的技术。在本文中,我将从 PCA 开始,然后介绍其他降维技术。Python 代码将包含在每项技术中。

降维也能发现离群值

数据科学家可以使用降维技术来识别异常。为什么?我们不就是想降维吗?直觉在于离群值本身。D.M .霍金斯说:“异常值是一个与其他观测值相差如此之大的观测值,以至于让人怀疑它是由不同的机制产生的。”一旦维度被减少到更少的主维度,模式被识别并且然后离群值被揭示。我们可以说离群点检测是降维的副产品,如文章“使用自动编码器的异常检测变得简单”中所述。

我写过关于各种数据科学主题的文章。为了方便使用,你可以将我的总结文章“数据人学习之路——培养你的技能,推动你的职业发展”加入书签,其中列出了所有文章的链接。

值得一提的是,现实生活中很多分类问题都是多类的。如果你曾经面临对多类问题建模的需求,请参见我的帖子“多类分类的各种模型”。

主成分分析

主成分分析(PCA)的思想是降低由大量相关变量组成的数据集的维度,同时尽可能多地保留数据中的方差。PCA 找到一组新变量,原来的变量只是它们的线性组合。新的变量被称为主成分(PCs) 。这些主成分是正交的:在三维情况下,主成分彼此垂直。x 不能用 Y 表示或者 Y 不能用 z 表示。

图(A)显示了 PCA 的直觉:它“旋转”轴以更好地与您的数据对齐。第一个主成分将捕获数据中的大部分差异,然后是第二个、第三个,依此类推。因此,新数据的维度会更少。

Figure (A): PCA

让我们使用 iris 数据集来说明 PCA:

# Use the iris dataset to illustrate PCA:
import pandas as pd
url = “[https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data](https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data)"
# load dataset into Pandas DataFrame
df = pd.read_csv(url, names=[‘sepal length’,’sepal width’,’petal length’,’petal width’,’target’])
df.head()

IRIS dataset

注意这个 IRIS 数据集带有目标变量。在 PCA 中,只转换 X 变量,而不转换目标 Y 变量。

标准化:在应用 PCA 之前,所有变量应该在相同的尺度上,否则,具有大值的特征将支配结果。这一点在我的文章“避免这些致命的建模错误,这些错误可能会让你失去职业生涯”中有进一步的解释。下面我使用 scikit 中的 StandardScaler 来学习将数据集的特征标准化到单位尺度上(均值= 0,方差= 1)。

from sklearn.preprocessing import StandardScaler
variables = [‘sepal length’, ‘sepal width’, ‘petal length’, ‘petal width’]
x = df.loc[:, variables].values
y = df.loc[:,[‘target’]].values
x = StandardScaler().fit_transform(x)
x = pd.DataFrame(x)

Standardized features

原始数据中有四个特征。因此 PCA 将提供相同数量的主成分。

from sklearn.decomposition import PCA
pca = PCA()
x_pca = pca.fit_transform(x)
x_pca = pd.DataFrame(x_pca)
x_pca.head()

The Principal Components for the IRIS Dataset

每个主成分解释的差异是什么?使用pca.explained_variance_ratio_返回方差的向量:

explained_variance = pca.explained_variance_ratio_
explained_variancearray([0.72770452, 0.23030523, 0.03683832, 0.00515193])

结果表明,第一主成分解释了 72.22%的方差,第二、第三和第四主成分分别解释了 23.9%、3.68%和 0.51%的方差。我们可以说 72.22 + 23.9 = 96.21%的信息被第一和第二主成分捕获。我们通常希望只保留重要的特性,而放弃不重要的特性。一个经验法则是保留捕捉显著差异的顶部主成分,忽略小的主成分。

我们可以使用前两个组件来绘制结果。让我们将目标变量 y 附加到新数据 x_pca 上:

x_pca[‘target’]=y
x_pca.columns = [‘PC1’,’PC2',’PC3',’PC4',’target’]
x_pca.head()

结果显示数据在新的空间中是可分的。

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(1,1,1) 
ax.set_xlabel(‘Principal Component 1’) 
ax.set_ylabel(‘Principal Component 2’) 
ax.set_title(‘2 component PCA’) 
targets = [‘Iris-setosa’, ‘Iris-versicolor’, ‘Iris-virginica’]
colors = [‘r’, ‘g’, ‘b’]
for target, color in zip(targets,colors):
 indicesToKeep = x_pca[‘target’] == target
 ax.scatter(x_pca.loc[indicesToKeep, ‘PC1’]
 , x_pca.loc[indicesToKeep, ‘PC2’]
 , c = color
 , s = 50)
ax.legend(targets)
ax.grid()

我们如何使用 PCA 来检测异常值?让我给你一个直觉。变换后,“正常”数据点将沿着具有小特征值的特征向量(新轴)对齐。离群点远离特征值大的特征向量。因此,每个数据点到特征向量之间的距离成为离群值的度量。大距离表示异常。有关更多信息,请参见“使用 PyOD 的异常检测”。

[## 通过我的推荐链接加入 Medium-Chris Kuo/data man 博士

阅读 Chris Kuo/data man 博士的每一个故事。你的会员费直接支持郭怡广/戴塔曼博士和其他…

dataman-ai.medium.com](https://dataman-ai.medium.com/membership)

内核 PCA (KPCA)

PCA 应用线性变换,这正是它的局限性。内核 PCA 将 PCA 扩展到非线性。它首先将原始数据映射到某个非线性特征空间(通常是一个更高的维度),然后应用 PCA 提取该空间中的主成分。这可以从图(B)中理解。左侧的图表显示,使用任何线性变换都无法分离蓝点和红点。但是如果所有的点都投影到一个 3D 空间,结果就变成线性可分了!然后我们应用主成分分析来分离这些成分。

直觉从何而来?为什么在更高维度的空间中,组分分离变得更容易?这还得回到 Vapnik-Chervonenkis (VC)理论。它说,映射到更高维度的空间通常会提供更大的分类能力。

Figure (B)

以下 Python 代码制作了一个由红色和蓝色圆点组成的圆形图。没有办法用一条线把红点和蓝点分开(线性分离)。

print(__doc__)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA, KernelPCA
from sklearn.datasets import make_circlesnp.random.seed(0)
X, y = make_circles(n_samples=400, factor=.3, noise=.05)plt.figure(figsize=(10,10))
plt.subplot(2, 2, 1, aspect='equal')
plt.title("Original space")
reds = y == 0
blues = y == 1plt.scatter(X[reds, 0], X[reds, 1], c="red",s=20, edgecolor='k')
plt.scatter(X[blues, 0], X[blues, 1], c="blue",s=20, edgecolor='k')
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")

然而,当我们将圆投影到一个更高维的空间并使用 PCA 分离时,针对第一和第二主成分的数据观察是可分离的!下面是点相对于第一和第二主成分绘制的结果。我画了一条线来区分红色和蓝色的点。在 KernelPCA 中,我们指定 kernel='rbf ',这是径向基函数,或者欧几里德距离。RBF 通常用作机器学习技术的核心,例如支持向量机(SVM) 。

kpca = KernelPCA(kernel=”rbf”, fit_inverse_transform=True, gamma=10)
X_kpca = kpca.fit_transform(X)
pca = PCA()
X_pca = pca.fit_transform(X)plt.scatter(X_kpca[reds, 0], X_kpca[reds, 1], c=”red”,s=20, edgecolor=’k’)
plt.scatter(X_kpca[blues, 0], X_kpca[blues, 1], c=”blue”,s=20, edgecolor=’k’)
x = np.linspace(-1, 1, 1000)
plt.plot(x, -0.1*x, linestyle=’solid’)
plt.title(“Projection by KPCA”)
plt.xlabel(r”1st principal component in space induced by $\phi$”)
plt.ylabel(“2nd component”)

如果我们把核指定为“线性的”,如下面的代码(KernelPCA(kernel='linear '),就变成了只有线性变换的标准 PCA,红蓝点不可分。

kpca = KernelPCA(kernel=”linear”, fit_inverse_transform=True, gamma=10)
X_kpca = kpca.fit_transform(X)
pca = PCA()
X_pca = pca.fit_transform(X)plt.scatter(X_kpca[reds, 0], X_kpca[reds, 1], c=”red”,s=20, edgecolor=’k’)
plt.scatter(X_kpca[blues, 0], X_kpca[blues, 1], c=”blue”,s=20, edgecolor=’k’)
x = np.linspace(-1, 1, 1000)
plt.plot(x, -0.1*x, linestyle=’solid’)
plt.title(“Projection by KPCA”)
plt.xlabel(r”1st principal component in space induced by $\phi$”)
plt.ylabel(“2nd component”)

线性判别分析

LDA 的起源不同于 PCA。PCA 是一种无监督的学习方法,它将原始特征转换成一组新的特征。我们不关心新的特征集是否能为目标变量提供最好的区分能力。相比之下,线性判别分析(LDA)寻求尽可能多地保留因变量的判别能力,同时将原始数据矩阵投影到低维空间。LDA 是一种监督学习技术。它利用因变量中的类别将预测器空间划分为个区域。所有的区域都应该有线性边界。线性的名称由此而来。该模型预测一个区域内的所有观测值都属于同一类因变量。

LDA 通过三个主要步骤实现了上述目标。首先,它计算因变量的不同类之间的可分性,称为类间方差,如图 LDA 的(1)所示。其次,计算每一类的均值与样本之间的距离,称为类内方差,如(2)所示。然后以最大化类间方差和最小化类内方差为准则构造低维空间。这个标准的解决方案是计算特征值和特征向量。得到的特征向量代表新空间的方向,相应的特征值代表特征向量的长度。因此,每个特征向量代表 LDA 空间的一个轴,特征值代表该特征向量的长度。

Figure: LDA

直觉是这样的:如果两个阶级能真正分开,那么两个阶级尽可能远,同时每个阶级尽可能同质,这将是理想的。这种直觉可以用三个步骤来表达:

  • 第一步:找到不同阶层之间的分野。这也被称为类间方差。是不同阶级手段之间的距离。见上图(1)。
  • 第二步:求类内方差。这是每个类的平均值和样本之间的距离。见上图(2)。
  • 第三步:在低维空间中最大化第一步(类间方差),最小化第二步(类内方差)。这也被称为费雪准则。

我将在 Kaggle 比赛中使用“红酒质量”数据集。该数据集有 11 个输入变量和一个输出变量“质量”。

import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
wine = pd.read_csv(‘winequality-red.csv’)
wine.head()

为了简单起见,我将输出变量重新分组为三个值。wine[‘quality2’] = np.where(wine[‘quality’]<=4,1, np.where(wine[‘quality’]<=6,2,3)).

下面的代码执行 PCA 和 LDA。

X = wine.drop(columns=[‘quality’,’quality2'])
y = wine[‘quality2’]
target_names = np.unique(y)
target_namespca = PCA(n_components=2)
X_r = pca.fit(X).transform(X)lda = LinearDiscriminantAnalysis(n_components=2)
X_r2 = lda.fit(X, y).transform(X)

然后绘制 PCA 和 LDA 的结果:

# Percentage of variance explained for each components
print(‘explained variance ratio (first two components): %s’
 % str(pca.explained_variance_ratio_))plt.figure()
colors = [‘navy’, ‘turquoise’, ‘darkorange’]
lw = 2for color, i, target_name in zip(colors, target_names, target_names):
 plt.scatter(X_r[y == i, 0], X_r[y == i, 1], color=color, alpha=.8, lw=lw,
 label=target_name)
plt.legend(loc=’best’, shadow=False, scatterpoints=1)
plt.title(‘PCA of WINE dataset’)plt.figure()
for color, i, target_name in zip(colors, target_names, target_names):
 plt.scatter(X_r2[y == i, 0], X_r2[y == i, 1], alpha=.8, color=color,
 label=target_name)
plt.legend(loc=’best’, shadow=False, scatterpoints=1)
plt.title(‘LDA of WINE dataset’)plt.show()

LDA 适用于多类分类问题。如果你甚至需要对一个多类问题建模,请看我的文章“多类分类的多种模型”。

奇异值分解

SVD 是一种类似于 PCA 的数据汇总方法。它从数据中提取重要特征。但是 SVD 还有一个优点:将原始数据集重构为一个小数据集。奇异值分解在图像压缩中有着广泛的应用。例如,如果您有一个 3232 = 1,024 像素的图像,SVD 可以将其总结为 66 像素。66 个像素可以代表 3232 像素的图像,而不会丢失任何重要信息。奇异值分解是线性代数的基础,但它似乎“并不像它应该的那样有名”。这个伟大的评论是在经典教科书“线性代数及其应用”由吉尔伯特斯特朗。

为了正确地介绍奇异值分解,让我们从矩阵运算开始。如果 A 是对称实矩阵 n × n ,则存在正交矩阵 V 和对角矩阵 D 使得

V 是 A 的特征向量, D 的对角元素是 A 的特征值,这个过程被称为矩阵 A特征值分解EVD 。它告诉我们如何选择标准正交基,使变换用一个尽可能简单的矩阵表示,即对角矩阵。(对于想浏览对角化矩阵步骤的读者来说,这里的是一个很好的例子。)术语正交的意味着两个向量是垂直的。

扩展对称矩阵,SVD 可以处理任何实矩阵m×nA。给定一个实 m × n 矩阵 A ,存在一个正交 m × m 矩阵 U,一个正交矩阵 m × m V,和一个对角 m × n 矩阵σ使得

注意,正交矩阵是方阵,使得其自身与其逆矩阵的乘积是单位矩阵。对角矩阵是指对角线以外的元素都为零的矩阵。

下面我将再次使用 iris 数据集向您展示如何应用奇异值分解。

from numpy import *
import operator
import matplotlib.pyplot as plt
import pandas as pd
from numpy.linalg import *url = “[https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data](https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data)"
# load dataset into Pandas DataFrame
df = pd.read_csv(url, names=[‘sepal length’,’sepal width’,’petal length’,’petal width’,’target’])# Only the X variables
data = df[[‘sepal length’,’sepal width’,’petal length’,’petal width’]]#calculate SVD
n = 2 # We will take two Singular Values
U, s, V = linalg.svd( data )# eye() creates a matrix with ones on the diagonal and zeros elsewhere
Sig = mat(eye(n)*s[:n])
newdata = U[:,:n]
newdata = pd.DataFrame(newdata)
newdata.columns=[‘SVD1’,’SVD2']
newdata.head()

你可以比较奇异值分解和主成分分析的结果。两者的结果相似。

# Add the actual target to the data in order to plot it
newdata[‘target’]=df[‘target’]fig = plt.figure()
ax = fig.add_subplot(1,1,1) 
ax.set_xlabel(‘SVD 1’) 
ax.set_ylabel(‘SVD 2’) 
ax.set_title(‘SVD’) 
targets = [‘Iris-setosa’, ‘Iris-versicolor’, ‘Iris-virginica’]
colors = [‘r’, ‘g’, ‘b’]
for target, color in zip(targets,colors):
 indicesToKeep = newdata[‘target’] == target
 ax.scatter(newdata.loc[indicesToKeep, ‘SVD1’]
 , newdata.loc[indicesToKeep, ‘SVD2’]
 , c = color
 , s = 50)
ax.legend(targets)
ax.grid()

Figure: SVD

t-分布式随机邻居嵌入(t-SNE)

t——SNE 由劳伦斯·范·德·马滕和乔治·辛顿开发。它是一种可视化的机器学习算法,将高维数据嵌入到二维或三维的低维空间中。

把上面的三维瑞士卷呈现为二维的最好方法是什么?直觉上,我们想把瑞士面包卷“展开”成一块扁平的蛋糕。在数学中,这意味着相似的点将成为附近的点,不同的点将成为遥远的点。

图(C)显示了另一个例子。它是一个三维四面体,数据点聚集在顶点角上。如果我们只是像面板(A)那样将 3 维图形折叠成 2 维图形,效果并不好,因为组(A)变成了中心聚类。相比之下,画面(B)可能是更好的 2d 展示,其保留了聚类(A)-(E)之间的远距离,同时保持了每个聚类中的点的局部距离。SNE,一种非线性降维技术,旨在保持局部邻域。如果 t-SNE 图上的一组点聚集在一起,我们可以相当确定这些点彼此靠近。

Figure (C): t-SNE

SNE 为点之间的相似性建模。它是如何定义相似性的?首先,它由点 XiXj 之间的欧几里德距离定义。第二,它被定义为“数据点 i 到点 j 的相似度是条件概率 p 如果在高斯分布下根据其概率挑选其他邻居,则点 i 将挑选数据 j 作为其邻居。”在下面的条件表达式中,如果点 j 比其他点更靠近点 i ,那么它被选中的概率更大(注意负号)。

t-SNE 的目的是通过点 Yi 和点 Yj,之间的低维空间 q 尽可能匹配上述条件概率 p ,如下图所示。概率 q 遵循厚尾 Student-t 分布,因此 t-SNE 中的“ t ”由此而来。

下一步是找到 Yi ,使分布 q 尽可能接近分布 p 。t-SNE 使用梯度下降技术,一种优化技术,来找到这些值。

下面我演示了 t-SNE 技术是如何用于虹膜数据集的。

from sklearn.manifold import TSNE
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
iris = load_iris()
X_tsne = TSNE(learning_rate=100).fit_transform(iris.data)
X_pca = PCA().fit_transform(iris.data)
plt.figure(figsize=(10, 5))
plt.subplot(121)
plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=iris.target)
plt.subplot(122)
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=iris.target)

更多信息,这篇文章“如何更有效地使用 t-SNE”提供了更多的讨论。

[## 通过我的推荐链接加入 Medium-Chris Kuo/data man 博士

阅读 Chris Kuo/data man 博士的每一个故事。你的会员费直接支持郭怡广/戴塔曼博士和其他…

dataman-ai.medium.com](https://dataman-ai.medium.com/membership)

维度数据建模

原文:https://towardsdatascience.com/dimensional-data-modeling-49038b96d95a?source=collection_archive---------4-----------------------

为什么需要维度数据建模,如何实现?

什么是维度数据建模?

维度建模 (DM)是由 Ralph Kimball 开发的业务维度生命周期方法的一部分,其中包括一套用于数据仓库设计的方法、技术和概念。该方法侧重于识别业务中的关键业务流程,并在添加其他业务流程之前首先建模和实现这些流程,这是一种自下而上的方法。[1]

数据仓库建模的目标是什么?

罗斯和金博尔提出的目标很简单:

  • 让信息易于获取
  • 一致地呈现信息
  • 适应性强,易于接受变化
  • 及时展示信息
  • 保护信息资产
  • 作为改进决策制定的权威和可信赖的基础(数据工程语言中的唯一真实来源)
  • 贵宾必须接受你的系统

如果您从事或使用过 ETL 系统,您会注意到信息一致性是通过一致性度量来实现的,ETL 周期提供的及时性和适应性也很大程度上取决于 ETL 设计。

为什么要做模特?

作为一名数据工程师,您非常了解 SQL,可能会整天编写 SQL 查询。但是您不能假设典型的最终用户是编写 SQL 查询的专家。因此,我们的目标是构建一个数据仓库,以便分析师快速有效地编写分析查询。

您不希望您的分析师做的事情:

  • 基于 ID 的查询
  • 级联外部连接(即使您不想这样做)
  • 分组或连接多个子查询
  • 递归子查询(只需访问 Hackerrank SQL,您就会理解这种痛苦)
  • 子查询关联:在不同的子查询中跨多个列提取数据
  • 没有 PK/FK 的加入:即使对我来说(1.5 年的 DE 经验),也很难想象。

您可以并且应该从您的分析师那里期待的事情:

  • 简单连接
  • 带有名称和综合文本的列
  • 简单聚集
  • 分析窗口函数
  • 明显的

请注意,以上几点并不容易,您的系统应该具有足够的可伸缩性来处理所有这些类型的查询。

由于上述目标,OLTP 数据库被转换成事实和维度。

从事务数据库过渡到事实

大多数企业通过测量特定类型的数据来衡量他们的成功和效率。这些数据捕捉真实的业务活动和进展。这个数据被称为事实

面向 OLTP 的数据库一次记录事务,有点像事件流,但以事务为中心。DW 是不同的。DW 不需要在事务级别记录细节。数据仓库需要你的业务的不同标准的事实。DW 需要聚集(或让分析师聚集)改进业务所需的信息。因此,冗余在 DW 中是不可饶恕的罪过。

什么是度量,为什么要在事实表中填入度量?

在数据仓库中,度量是可以进行计算的属性。[2]

我们从运营数据存储中获得的事实伴随着一些额外的数据,这些数据通常会在我们的分析中进行汇总。这些是一个事实的各个方面,允许分析师或查看分析的主管看到事实中的价值。

保持一致的颗粒

为什么需要保持一致的纹路?

以便您可以确保您的系统能够合理地关联和聚合事实。

但是并不总是有原子级别的数据。因此,要弥合这一差距,有两种方法:

  • 定期快照事实表
  • 累积快照事实表

定期快照事实表

顾名思义,它们是定期收集的。气体消耗、审计和检查是为其启用了定期快照的一些数据收集实例。

累积快照事实表

当业务绩效指标是完成多步骤业务流程的比率时,您可能希望捕获流程的整体的粒度,并记录开始、完成以及中间的步骤。这可能是事务粒度的,但是在这两者之间有很多度量。因此,您使用累积快照事实表来回答商业智能中的复杂问题,其中事实之间存在时间流逝。一个很好的例子是你点了一份鸡肉三明治的事实表行,以及在麦当劳的汽车窗口递过来的袋子的事实表行。

通过维度定位事实

您和您的分析师需要知道如何查询和过滤事实,以便从中获得商业智能。维度服务于这个目的。

从参考和原始元数据中绘制尺寸

维度几乎总是用代理键创建的;事实表中的外键(或)自然会引用代理键。我们通过搜索我们感兴趣的维度来搜索该表。描述我们的事实的所有其他数据,如时间戳、客户代理、商店位置、产品和客户,都是我们转化为维度的内容。

维度建模的美妙之处在于,事实不是由主键或任何类型的唯一标识符定义的,而是由维度的组合定义的。这就产生了星型模式。

我们在维度上的独特性是非常重要的。当我们跨事实进行查询时,维度组合中的重复将变成一场灾难。如果不能,那么添加或聚合维度以使它们唯一。

维度中的层次

考虑下面两个图像。

[3]

[3]

如果你为他/她设置第二维表,分析师将会过得很轻松。

因此,对于第二个表,您有以下层次结构:

[3]

有各种各样的层次结构——多层次结构、单层次结构等。我不打算在这篇博文中解决这些问题。

我想指出的一点是,时间维度是一个真正的难题。你必须考虑神奇的日子、财政日历、时区、周期(季度利润类型)。不要对此感到糟糕或过于自信,如果你的 ETL 搞砸了,即使时间序列数据库也不会在层次结构中帮助你。你可能想看看舷外支架的尺寸。也有一个维度自然依赖于另一个维度的情况。在这种情况下,设计人员可能会将一个外键放在另一个外键中。这就是“外延维度”的构成。在日历维度中,这很常见。

您不能在 outrigger 中使用与您在事实表中使用的日期不同的日期。您不能允许外伸支架维度上的聚合。如果需要,用文本前缀或后缀来屏蔽支架中的数值。[4]

尺寸缓慢变化

尽管我很想写它,但我仍然认为我的读者最好从这里彻底理解这个概念。

我不是在讨论雪花维度,只是想指出,它们仍然在 OLAP 数据库中使用。

将大数据集成到 ETL 系统中

您将把表格形式的大数据视为通过标准提取阶段之一获得的。因此,您将对其应用与在 transform 中相同的步骤:

  1. 数据清理
  2. 符合单位和格式
  3. 重复数据删除
  4. 重组
  5. 脚手架

摘要

我想了解数据库设计的理论方面,这促使我读了《Ross 和 Kimball》这本书。然后,我开始好奇,想找出他们的方法与当今领先的数据驱动型公司(如网飞、Airbnb、优步等)的方法之间的差异和相似之处。

在这个探索中,我可以公平地说,维度建模的结构化格式比硬核 ETL 更受欢迎。因为通过这种方式,您消除了对您的依赖,您的 BI 团队不会让您在空闲时为每个其他洞察创建新的 DAG,相反,通过正确的建模,您使他们能够在没有您的需要的情况下自由地行动和探索。

请留下我如何改进的反馈,我相信这不是你最好的阅读。谢谢你的时间。

脚注

[1]https://en.wikipedia.org/wiki/Dimensional_modeling

[2]https://en . Wikipedia . org/wiki/Measure _(data _ warehouse)

[3]罗斯和金博尔,第 2 章和第 18 章

[4]金博尔/罗斯,第 103-109 页

机器学习中的降维初学者指南

原文:https://towardsdatascience.com/dimensionality-reduction-for-machine-learning-80a46c2ebb7e?source=collection_archive---------2-----------------------

这是我第一篇关于媒介的文章。在这里,我将快速概述什么是降维,为什么我们需要它,以及如何做到这一点。

什么是降维?

简而言之,降维就是降低特征集的维数的过程。您的特征集可以是一个包含 100 列(即特征)的数据集,也可以是一个由点组成的数组,这些点构成了三维空间中的一个大球体。降维是将列的数量减少到比如说 20 列,或者将二维空间中的球体转换为圆形。

这一切都很好,但我们为什么要在乎呢?当我们可以直接将 80 列输入到我们的机器学习算法并让它完成剩下的工作时,我们为什么要从我们的数据集中删除 80 列呢?

维度的诅咒

我们关心是因为维度的诅咒要求我们这样做。维数灾难指的是在高维度中处理数据时出现的所有问题,这些问题在低维度中并不存在。

随着特征数量的增加,样本数量也成比例增加。我们拥有的特征越多,我们需要的样本数量就越多,以便在我们的样本中很好地代表特征值的所有组合。

The Curse of Dimensionality

随着特征数量的增加,模型变得更加复杂。特征的数量越多,过度拟合的可能性就越大。根据大量特征训练的机器学习模型越来越依赖于它被训练的数据,进而过度拟合,导致在真实数据上的表现不佳,达不到目的。

避免过度拟合是执行降维的主要动机。我们的训练数据的特征越少,我们的模型做出的假设就越少,就越简单。但这还不是全部,降维还有很多优点,比如

  1. 更少的误导性数据意味着模型准确性的提高。
  2. 更少的维度意味着更少的计算。数据越少意味着算法训练越快。
  3. 更少的数据意味着需要更少的存储空间。
  4. 较小的维度允许使用不适合大量维度的算法
  5. 移除多余的特征和噪声。

面向降维的特征选择和特征工程

降维可以通过特征选择方法和特征工程方法来完成。

特征选择是为您的样品识别和选择相关特征的过程。特征工程是通过对现有特征应用某种变换或执行某种操作,从现有特征手动生成新特征。

功能选择可以手动或编程完成。例如,假设您正在尝试构建一个预测人们体重的模型,并且您已经收集了大量数据,这些数据对每个人都进行了全面的描述。如果你有一个描述每个人衣服颜色的专栏,对预测他们的体重会有很大帮助吗?我想我们可以有把握地同意不会。这是我们可以不再费周折就放弃的事情。描述他们身高的专栏怎么样?那是肯定的。当某些特征的相关性或不相关性是显而易见的或公知常识时,我们可以进行这些简单的手动特征选择并降低维度。当不明显时,我们可以使用许多工具来帮助我们选择特征。

  1. 显示要素之间相关性的热图是一个好主意。
  2. 通过对照目标变量绘制每个特征来可视化特征和目标变量之间的关系也是如此。

现在让我们看看流行的机器学习库 sci-kit learn 中的一些用于特征选择的编程方法,即,

  1. 方差阈值和
  2. 单变量选择。

方差阈值是特征选择的基本方法。顾名思义,它会删除沿列变化不超过阈值的所有要素。前提是一个本身变化不大的特征几乎没有预测能力。

**>>>** X = [[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]]
**>>>** selector = VarianceThreshold()
**>>>** selector.fit_transform(X)
array([[2, 0],
       [1, 4],
       [1, 1]])

单变量特征选择使用统计测试来选择特征。单变量描述了一种仅由单一特征或属性的观察值组成的数据类型。单变量特征选择单独检查每个特征,以确定该特征与响应变量的关系强度。可用于评估特征相关性的统计测试的一些例子是皮尔逊相关、最大信息系数、距离相关、方差分析和卡方检验。卡方用于发现分类变量之间的关系,当变量是连续的时,方差分析是优选的。

Scikit-learn 将 SelectKBest、SelectPercentile 或 GenericUnivariateSelect 等功能选择例程作为实现基于 anova、chi2 或交互信息的转换方法的对象。Sklearn 提供 f_regression 和 mutual_info_regression 作为回归的评分函数,提供 f_classif 和 mutual_info_classif 作为分类的评分函数。f 检验检查并仅捕获特征和标签之间的线性关系。高度相关的特征被给予较高的分数,而不太相关的特征被给予较低的分数。相关性具有很强的欺骗性,因为它不能捕捉强非线性关系。另一方面,互信息方法可以捕捉任何类型的统计相关性,但由于是非参数的,它们需要更多的样本来进行精确估计。

特征选择是最简单的降维方法。稍后,我们将研究一些用于降维的特征工程方法。

线性降维方法

最常见和众所周知的降维方法是应用线性变换的方法,如

  1. PCA(主成分分析) :普遍用于连续数据的降维,PCA 是沿着方差递增的方向旋转和投影数据。方差最大的特征是主成分。
  2. 因素分析:一种技术,用于将大量变量减少为较少数量的因素。观察数据的值被表示为许多可能原因的函数,以便找出最重要的原因。观察结果被认为是由低维潜在因素的线性变换和添加的高斯噪声引起的。
  3. LDA(线性判别分析):以最大化类别可分性的方式投影数据。来自同一类的例子通过投影紧密地放在一起。来自不同类别的例子被投影放置得相距很远

PCA orients data along the direction of the component with maximum variance whereas LDA projects the data to signify the class separability

非线性降维方法

当数据不位于线性子空间上时,使用非线性变换方法或流形学习方法。它基于流形假设,即在高维结构中,大多数相关信息集中在少数低维流形中。如果线性子空间是一张平的纸,那么卷起的纸就是非线性流形的一个简单例子。非正式地,这被称为瑞士卷,非线性降维领域中的一个典型问题。一些流行的流形学习方法是,

  1. 多维标度(MDS):一种用于分析数据在几何空间中的相似性或不相似性的技术。将数据投影到较低的维度,使得在较高维度中彼此接近的数据点(根据欧几里德距离)在较低维度中也是接近的。
  2. 等距要素映射(Isomap):将数据投影到较低的维度,同时保留测地线距离(而不是 MDS 中的欧几里德距离)。测地线距离是曲线上两点之间的最短距离。
  3. 局部线性嵌入(LLE):从线性拟合中恢复全局非线性结构。在给定足够数据的情况下,流形的每个局部面片可以写成其邻居的线性加权和。
  4. Hessian 特征映射(HLLE):将数据投影到一个较低的维度,同时保留像 LLE 这样的局部邻域,但使用 Hessian 算子来更好地实现这一结果,因此得名。
  5. 频谱嵌入(拉普拉斯特征映射):通过将附近的输入映射到附近的输出,使用频谱技术来执行维数减少。它保持局部性而不是局部线性
  6. t-分布式随机邻居嵌入(t-SNE):计算高维空间中数据点对相关的概率,然后选择产生相似分布的低维嵌入。

Shows the resulting projection from applying different manifold learning methods on a 3D S-Curve

自动编码器

另一种产生惊人结果的流行降维方法是自动编码器,一种旨在将输入复制到输出的人工神经网络。他们将输入压缩成一个潜在空间表示,然后从这个表示中重建输出。自动编码器由两部分组成:

  1. 编码器:将输入压缩成潜在空间表示。
  2. 解码器:从潜在空间表示中重建输入。

在随后的文章中,让我们更深入地研究线性和非线性降维方法。

python 中的降维工具箱

原文:https://towardsdatascience.com/dimensionality-reduction-toolbox-in-python-9a18995927cd?source=collection_archive---------8-----------------------

这篇文章来源于我和我的朋友 Hervé Trinh 的工作。

近年来,数据量爆炸式增长了 80%以上。这导致了许多机器学习模型的出现,因为用一个重要的数据集来训练这些模型更容易。

然而,数据的权重会对算法的执行时间产生显著影响,因为复杂度随着数据的大小而增加。同时,维度会使查看数据库中包含的信息变得复杂。

降维是使用特征选择或特征提取等策略减少特征集中特征总数的过程。

例如,包含汽车特征的底座很难查看,因为它们数量众多。人们可以想象将里程和车龄结合起来形成特征磨损,只要它们是相关的。

降维算法有很多种,主要有两类,线性方法和非线性方法。

我将分享的技术是关于 python 的。确保您的机器上安装了 python。

首先,我们导入必要的库。

让我们导入 mnist 数据进行处理。

从高维到低维的线性数据转换的一种非常流行的技术是主成分分析,也称为 PCA。在接下来的几节中,让我们试着了解更多关于 PCA 的知识,以及如何使用它进行特征提取。

主成分分析

主成分分析是一种统计方法,使用线性正交变换过程将可能相关的高维特征集转换为线性不相关的低维特征集。这些转换和新创建的特征也称为主要组件或 PCs。在任何 PCA 变换中,PC 的总数总是小于或等于特征的初始数量。第一主成分试图捕捉原始特征集的最大方差。

前面的代码将减小 mnist 数据库的大小,并以其原始维度重新构建它。我们现在可以绘制小尺寸的数据。

增量 PCA

增量主成分分析是 ACP 的一种变体,它只保留最重要的奇异向量,以将数据投影到一个空间中以
缩减大小。

核主成分分析

KPCA 使执行复杂的非线性投影降维成为可能。

例如,下面的代码使用 Scikit-Learn 的 KernelPCA 类对一个 RBF 内核执行 kPCA。

稀疏主成分分析

稀疏 PCA 使用 ACP 和 SVD 之间的链接,通过求解低阶矩阵近似问题来提取主要分量。

奇异值分解

奇异值分解甚至可以应用于矩形矩阵;然而,特征值只为方阵定义。通过 SVD 方法获得的特征值的等价物被称为奇异值,而获得的与特征向量等价的向量被称为奇异向量。然而,由于它们在本质上是矩形的,我们需要为它们的维数分别有左奇异向量和右奇异向量。

高斯随机投影

在随机投影中,具有非常大的维度(d)的数据被投影
到具有随机矩阵的二维空间(kd)中。

稀疏随机投影

分段随机矩阵是使用传统降维方法的密集随机投影矩阵的替代方案。它确保类似的嵌入质量,同时最大限度地提高存储效率,并允许更快地计算投影数据。

多维标度[MDS]

MDS 是一种将样本之间的二相似性可视化的方法。MDS 返回一个最佳解决方案,在一个更小的维度空间中表示数据,如果维度的数量 k 是预先定义的。

ISOMAP

它是一种基于谱理论的非线性降维方法,试图在低维中保持大地距离。

迷你批处理词典学习

基于字典的学习解决了矩阵分解的问题,这相当于找到一个字典,该字典可以在代码简约的条件下给出好的结果。

独立成分分析

独立分量分析是一种主要用于信号处理以线性分离混合数据的方法。

T-分布随机邻居嵌入[T-SNE]

T-SNE 减少维数,同时试图保持相似的实例接近,不相似的实例分开。它主要用于可视化,特别是可视化高维空间中的实例集群。

局部线性嵌入[LLE]

LLE 的工作方式是,首先测量每个训练实例如何与其最近的邻居(c.n .)线性相关,然后寻找训练集的低维表示,其中这些局部关系得到最佳保留(稍后将有更多详细信息)。这使得它特别擅长展开扭曲的流形,尤其是在没有太多噪声的时候。

自动编码器

自动编码器是人工神经网络,能够学习输入数据的有效表示,称为编码,而无需任何监督(即,训练集是无标签的)。

基于潜在狄利克雷分配的降维方法

原文:https://towardsdatascience.com/dimensionality-reduction-with-latent-dirichlet-allocation-8d73c586738c?source=collection_archive---------11-----------------------

在性能下降不到 3%的情况下,将训练数据的维度减少了 99.7%以上。

降维是一种无监督的机器学习技术,通常与监督模型结合使用。虽然降低维度通常会使基于特征的模型更难解释,但它总是非常有效地防止过度拟合,并通过减少特征的数量来缩短训练时间。最流行的降维技术无疑是主成分分析(PCA)及其变体。然而,当涉及到文本数据时,我发现潜在的狄利克雷分配(LDA)非常有效。

潜在狄利克雷分配

潜在狄利克雷分配的概念最早是在 2003 年由大卫·布雷、吴恩达和迈克尔·乔丹撰写的研究论文中提出的。作者将其描述为“语料库的生成概率模型”LDA 广泛用于执行主题建模——一种可以从语料库中提取潜在主题/主题的统计技术。

在用于文本特征提取的传统单词包方法中,我们通过文档术语矩阵将每个文档直接映射到所有单词标记。这种方法通常会产生一个巨大、稀疏的矩阵,其中大多数条目等于 0,当我们使用这样的矩阵作为模型输入时,我们需要估计许多参数,但其中许多参数提供的信息有限,有时甚至是“有噪声的”。在 LDA 方法中,不是直接建模每个文本文档和每个单词标记之间的关系,而是引入“潜在变量”作为“桥梁”语料库中的每个文档由潜在变量(主题)上的狄利克雷分布来表征,并且每个主题由所有单词标记上的另一个狄利克雷分布来表征。

Figure on the left represents a traditional Bag-of-Words approach where each document is directly mapped to the tokens (Usually in the form of a Document-Term or Term-Document Matrix). Figure on the right represents the LDA approach. The two latent variables represent topics regarding soccer and basketball. LDA is able to map each document to its corresponding topic and each topic to its corresponding tokens. Although in practice, we usually don’t have the number of topics or the “meaning” of each topic as prior information.

假设文档数为 N,我们选择主题数为 k,用 LDA 降维的思路就是把重点放在上面提到的第一个狄利克雷分布上。对于每个文档,我们可以获得一个长度为 K 的向量,它表示文档在 K 个主题上的概率分布。为所有文档添加这样的向量,我们可以得到一个 N 乘 K 的特征矩阵,该矩阵可以用某些标签输入到我们的监督模型中。

最近,受上面引用的原始研究论文的启发,我做了一个小实验,探索 LDA 在降维方面的性能。在实验中,我能够将训练数据的维度减少 99%以上,而原始准确性的下降不到 3%。接下来,让我更详细地说明这个实验。

毒性评论分类

我用的数据来自毒评分类 Kaggle 挑战赛的训练数据。因为我的目标是探索 LDA 的降维,所以我以下列方式对数据进行子集化和过滤以简化过程:

  1. 原始数据的每个注释有 6 个不同的标签。我只关注了“有毒”标签。就这样,我把问题从多标签分类变成了单标签分类。
  2. 欠采样:原始数据极不平衡,超过 90%的评论被标为“无毒”通过欠采样,我获得了一个平衡的数据集,其中 15294 条评论被标记为“有毒”,另外 15294 条没有被标记为“有毒”。

Sorry about the toxic comments. They are indeed very toxic

作为第一步,我使用标准的 uni-gram 方法和 TF-IDF 矢量器构建了一个 XG-boost 分类模型:

  1. 培训和测试拆分:
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(data.comment_text, data.toxic, test_size = 0.25,random_state = 23)X_train.reset_index(drop = True,inplace = True)X_test.reset_index(drop = True,inplace = True)y_train.reset_index(drop = True,inplace = True)y_test.reset_index(drop = True,inplace = True)

2。为 n_gram 模型安装 TF-IDF 矢量器。请注意,我过滤了标记,使标记出现在少于 15 个文档中,超过 90%的文档被删除。tokenizer _ XM是一个定制的记号化器,包括记号化、词条化和词干化

from sklearn.feature_extraction.text import TfidfVectorizervec_tfidf = TfidfVectorizer(ngram_range =(1,1),tokenizer=tokenizer_xm,min_df = 15, max_df = 0.9)vec_tfidf_f = vec_tfidf.fit(X_training)

3。获得 n-gram 模型的文档-术语矩阵,并用训练数据拟合。

train_dtm_ngram = vec_tfidf_f.transform(X_training)from xgboost import XGBClassifierxgbc = XGBClassifier(n_estimators=200)xgbc_ngram = xgbc.fit(train_dtm_ngram,y_training)

接下来,我开始用 LDA 建立模型。为了使用 LDA,我们需要首先获得文档-术语-矩阵。因为 LDA 是基于原始计数的,所以最好使用计数矢量器,而不是 TF-IDF。

from sklearn.feature_extraction.text import CountVectorizervec_count = CountVectorizer(ngram_range = (1,1),tokenizer=tokenizer_xm,min_df = 15, max_df = 0.9)vec_count_f = vec_count.fit(X_train)

为 LDA 权重创建培训文档-术语矩阵

vec_f = vec_count_ftrain_dtm = vec_f.transform(X_train)topic_num = 5from sklearn.decomposition import LatentDirichletAllocationlda = LatentDirichletAllocation(n_components = topic_num)lda_f = lda.fit(train_dtm)lda_weights = lda_f.transform(train_dtm)
# The lda_weights is a n by k matrix where n is the number of documents and k is the number of topics# Fit the xgb-model with lda weightsfrom xgboost import XGBClassifierxgbc = XGBClassifier(n_estimators=200)xgbc_lda = xgbc.fit(lda_weights,y_train)

和上面的代码一样,LDA 需要一个“n_components”参数,它实际上是主题的数量。然而,我们通常不知道语料库中有多少“主题”。因此,我用等于 1、2、3、4、5、6、12、24、50 的主题数重复了上述过程 9 次,并根据测试数据对模型进行评分,试图找到一个相对最优的值。下面是结果。

看起来最好的题数是 5,准确率在 84%左右。以下是基于狄利克雷分布的五个主题中每个主题的前 10 个“显著”标记。

在这篇文章中,我们不会深入探讨 LDA 主题建模的性能。但有趣的是注意到不同主题之间的差异。主题 1 看起来是最中性的,而主题 5 毒性极大。狄利克雷分布实际上有助于从语料库中分离出无毒的评论。

接下来,我用 1%、25%、50%、75%和 100%的训练数据运行了上述整个过程,记录了基于 N-gram(xgbc _ ngram)和基于 LDA(xgbc _ LDA)的极限梯度提升分类器的性能(注意,这两个模型都用 200 个估计器初始化,所有其他超参数都保留为默认值),并比较了它们的精度、召回率和准确度分数。

下面是上图的原始表格:

如上图所示,虽然基于 N-gram 的模型的准确性总是略高于基于 LDA 的模型,但它最终在 100%的训练数据下达到 3367 个不同的特征,而基于 LDA 的模型的特征数仍然保持为 5,这是一个显著的差异!有趣的是,基于 LDA 的模型实际上在召回率方面优于 n-gram 模型,而在精确度方面则没有那么好。也就是说,基于 LDA 的模型更善于发现所有有毒的例子,但不太善于防止无毒的评论被标记为有毒的。一般来说,基于 LDA 的模型似乎在精确度和召回率之间具有更好的平衡。

使用 LDA 进行降维,我们无法绕过 n-gram 特征提取过程。因此,我们在缩短端到端模型构建时间方面没有得到太多的推动。然而,虽然 LDA 在降维方面似乎至少与 PCA 一样有效,但它非常容易解释。在基于特征的文本分类/回归模型中,这是一种很有前途的技术,因为我们可以将文本中的所有信息压缩到一个低维的密集矩阵中,以便我们能够添加许多其他特征来帮助提高模型性能,而不用担心过拟合。

维度和自由度

原文:https://towardsdatascience.com/dimensions-and-degrees-of-freedom-365461abcd5f?source=collection_archive---------23-----------------------

特征数量与维度数量

一个数学对象的维数是完全描述它所需的个独立 个变量的个数。一个点有 0 个维度。直线有一维,正方形有二维,立方体有三维。在一条直线上,我们需要一个变量,比如说从起点到终点的距离,来确定我们的位置。在正方形上,我们至少需要两条信息(x 和 y)。在一个立方体中,我们需要 3 个坐标(x,y,z)

source

物体的维度是物体的内在属性,独立于其嵌入的空间

基本上一条线本质上有一维,即使我们把它放在二维、三维或十维空间中。例如,如果我们在一个二维平面的一条直线(y=2x)上有一些点,我们仍然需要一个信息,例如离原点的距离,来唯一地识别这条线上的任何点。即使这些点有两个笛卡尔坐标,坐标 x 和 y 依赖于线的方程(y=2x),因此它们是多余的,因为它们中的任何一个都可以由另一个推导出来(x=y/2,或 y=2x)。

机器学习和数据分析中的一个大误解是混淆了两个完全不同的概念:特征数量维度数量。说明这种差异的最佳方式是想象三个不同尺寸的管道,它们都由同一个阀门控制。每一个都具有在其中流动的具有不同属性的不同流体和计数体积的仪表。因此,我们数据集中的特征数量为 3(流体体积 1、流体体积 2、流体体积 3)。

3 pipes controlled by the same valve. Image rendering by Alexy Frangieh

*+---------+---------+---------+
| Meter 1 | Meter 2 | Meter 3 |
+---------+---------+---------+
| 1       | 10      | 100     |
+---------+---------+---------+
| 2       | 20      | 200     |
+---------+---------+---------+
| 3       | 30      | 300     |
+---------+---------+---------+
| 4       | 40      | 400     |
+---------+---------+---------+
| 5       | 50      | 500     |
+---------+---------+---------+
| 2.5     | 25      | 250     |
+---------+---------+---------+
| 0       | 0       | 0       |
+---------+---------+---------+
A sample of the data collected*

虽然我们在这个数据集中有 3 个特征,但我们可以很容易地看出它们之间存在比例或相关性(即 1x: 10x: 100x)。这种相关性的存在是因为我们只有一个控制点。主要是一个阀门以相同的速率同时控制所有三种流量。因此,即使表面上我们有 3 个不同的变量,3 米和 3 个特征,对机器学习和数据分析真正重要的是数据集中的自由度。我们可以独立控制多少不同的管道。我们能让第一根管子完全打开,而第二根完全关闭吗?在这个系统中,我们不能,通过设计。所以即使我们收集了 3 个流的数据,也没有关系,这是一个冗余信息。一个流信息就足够了。其余的可以通过比例/相关性推导出来。

只有当我们在每个管道上使用独立的阀门时,我们才能说尺寸的数量等于特征的数量。但是,在我们可以说我们“覆盖”了整个探索空间之前,我们需要尝试所有管道上所有阀门的所有状态之间的所有不同组合。

What matters is how many independent knobs we have.

如果我们考虑每个阀门只有两种状态:完全打开和完全关闭。系统中每增加一个阀门,我们就有两倍多的组合可以探索。例如,对于 3 个阀门,我们得到以下 8 种组合:

  • [关门,关门,关门]
  • [关闭,关闭,打开]
  • [关闭,打开,关闭]
  • [关闭,打开,打开]
  • [打开、关闭、关闭]
  • [打开,关闭,打开]
  • [打开,打开,关闭]
  • [打开,打开,打开]

每个额外的管道,一个额外的阀门(或旋钮)将增加一个额外的空间,并增加一倍所需的数据。我们需要更多的数据来涵盖所有可能的组合。这是数据分析中一个众所周知的问题,称为“维度的诅咒”。

Too many variables!

我打算写一些数学工具,这些工具允许从不同的特征中发现独立维度的数量(比如主成分分析 PCA)。但是我找到了这篇关于这个话题的优秀博文。

原载于 2019 年 3 月 6 日data things

探索数据科学——一个“商业”人士的一些想法

原文:https://towardsdatascience.com/dipping-into-data-science-a-few-thoughts-from-a-business-guy-8c4f1ab538b?source=collection_archive---------32-----------------------

unsplash.com

我两年前写了这篇文章,但从未公开发表过。我通过电子邮件把它发给了感兴趣的朋友和同事,许多人告诉我,他们发现它很有帮助,越来越多的人要求我在网上发表。在这里!

作为一名“商业”人士,我从未想过自己会探索数据科学。但在一年前加入一家医疗保健分析初创公司后,我很快意识到,我越是能够超越 3 万英尺的视角来理解分析(是的,我曾经是一名管理顾问,你怎么知道的?),我就越能通过将数据分析学科与业务决策和管理联系起来,帮助推动我们公司的业务向前发展。麦肯锡将这些人称为“翻译”。

我在网上找到了许多直接学习编程语言和统计学的资源,但没有一个真正谈到如何接近学习数据科学,特别是作为一个对如何编码毫无经验的人来说。在经历了太多的谷歌兔子洞和数周的反复试验后,我学到了以下几点:

1。在开始任何在线课程之前,重要的是要想好你在数据科学生态系统中的角色。这会让你更专注于你想学的东西,更重要的是,学什么编程语言。(查看:六类数据科学家、了解数据科学中不断变化的职位角色、你能在工作中学习数据科学吗?)

在与我的数据科学朋友和同事交谈后,我很快意识到数据科学家的大量时间都花在清理、操作和争论数据上,只是为了让数据达到可用的程度。我很惊讶地得知,数据科学家花了高达 60%的时间清理数据,而普遍的共识是,他们并不真正喜欢它。如果您在一个环境或项目中工作,可以通过帮助格式化和操作数据来减轻一些数据科学家的负担,这是一个很好的开始方式。

2。一旦你对如何融入更广阔的生态系统有了一个基本的想法,选择一门语言来学习。

许多数据科学家用 R 和 Python 编写代码。有些人信誓旦旦地说一个对另一个(例如,观点:“为什么 R 对你不好”)——我不打算深入探讨。我选择 Python 是因为我公司的数据科学家正在使用 Python,我希望能够依靠他们的帮助。

我没有选择纯粹的 Python 在线课程(又名“MOOC”),而是决定选择基于 python 的数据科学 MOOC。(点击此处查看一篇对数据科学课程进行排名的酷炫文章)。这让我能够在上下文中学习 python,并能够将它与我可以想象解决的真实业务问题联系起来,而不是在孤立的环境中学习 python 的基础知识。

我梳理了几门课程,决定选两门:

  • Python 数据科学入门——Coursera/密歇根大学——这是一堂很棒的入门课,但对我这样的完全初学者来说很有挑战性。它的节奏相对较快,能让你迅速思考并投入 python。这门课程让你自己解决很多问题,而不是从头到尾握着你的手。),但在我看来那是乐趣的一部分。任务很难,但有一点让我印象深刻,就像有多种方法可以构建 excel 模型以获得相同的结果一样,在编码中也有多种方法可以获得相同的结果。你学得越多,看到别人是如何编码的,你就越能建立起你的“库”来完成一些事情。
  • 用于数据科学和机器学习的 Python—Udemy——我现在还在上这门课但是强烈推荐。Jose 是一位优秀的讲师,从基础 python 开始,到在 python 中应用机器学习(ML)技术。该课程首先从 python bootcamp 开始(与 Coursera / UMich 课程相比,更具结构化和指导性,这取决于你的学习风格),以及 matplotlib 和 seaborn 等包的数据可视化技术。提前学习这些东西真的很有用,很有帮助,你可以马上把它应用到你的日常生活中。Jose 然后使用 sklearn 和其他技术深入 ML 应用程序。我现在正在研究这些。本课程主要侧重于数据科学的应用,以帮助人们起步,但也很好地将一些高层次的统计概念与统计书籍结合在一起(下文将详细介绍)。

旁注:如果你曾经在尝试编码时遇到困难,那就谷歌一下。你可能会发现一个堆栈溢出链接,链接上有人问了和你相同/相似的问题,有来自世界各地的 17 个不同的回答。这是我学习编码最喜欢的事情之一——有一个完整的社区在努力互相帮助,你总能找到问题的答案。

许多这些纯数据科学 MOOCs(包括上面的那些)主要专注于数据科学应用,并没有真正进入这些技术背后的数学或推理。这让我想到了下一个要点:

****3。在某种程度上,您可能应该从概念上理解数据科学背后的一些基础数学和统计学。我并不是在说要达到开发奇特算法的地步;我说的是对统计学习的基本理解,以帮助你理解解释数据的细微差别(例如,何时使用这种类型的回归与分类模型,为什么,以及这如何影响你的分析?).网上有很多关于这些主题的课程,我还没有去探索,但同时我拿起了 Jose 在他的课程中使用的书:

  • 【R 中的应用】 —有人告诉我这是数据科学家的圣杯书籍(我不是数据科学家,所以我不能确认)。Udemy 类大量引用这本书;Jose 并没有试图深入研究数据科学背后的数学,而是要求他的学生在感兴趣的时候阅读这本书。警告:这是一本教科书,毫无疑问,但它是一本精彩的读物。虽然标题是“R 中的应用程序”,但是如果您正在学习 Python,请不要担心,主要的统计概念是与语言无关的。大部分 R 应用程序是针对书中的实验部分/练习。这本书在网上是免费的,尽管我确实买了一本二手的硬拷贝,因为我想支持作者,而且我讨厌在屏幕上阅读东西,尤其是教科书

好了,这些是我在这次旅程中得到的两分钱。希望这在某种程度上有所帮助。如果您有任何问题、反馈或意见,请告诉我!总是寻求联系和了解更多。

狄利克雷分布

原文:https://towardsdatascience.com/dirichlet-distribution-a82ab942a879?source=collection_archive---------2-----------------------

激励 LDA

几个月前,我构建了一个推荐系统,采用主题建模向员工显示相关任务。使用的算法是潜在的狄利克雷分配(LDA),这是一种自 21 世纪初就存在的生成模型。当然,我没有从头开始重写 LDA,而是使用了 Python 的 scikit-learn 中的实现。但这让我开始思考导致 LDA 模型产生的一系列研究。这种库的问题是,在代码中包含几行代码并继续前进太容易了,所以我翻出了我的旧机器学习书籍,目的是了解足够多的知识,以便能够解释 LDA 所有血淋淋的概率细节。一度有人担心它会变成一个无限的回归,但最终理性占了上风,这一系列的文章被构建出来。按照相反的顺序,我们有:

五:潜在狄利克雷分配(LDA)
四:潜在语义索引(LSA)
三:混合模型和 EM 算法
二:贝叶斯生成模型
一:狄利克雷分布

希望到我们到达终点时,目标已经实现了。我们将从狄利克雷分布开始。

狄利克雷分布——它是什么,为什么有用?

在任何教科书中查找狄利克雷分布,我们都会遇到以下定义:

狄利克雷分布 Dir( α )是一族由正实数的向量 α 参数化的连续多元概率分布。它是贝塔分布的多元推广。狄利克雷分布是贝叶斯统计中常用的先验分布。

一个直接的问题是为什么狄利克雷分布被用作贝叶斯统计中的先验分布?一个原因是它是许多重要概率分布的共轭先验:分类分布和多项式分布。用它做先验会让数学变得容易很多。

共轭先验

在贝叶斯概率论中,如果后验分布p(θ|x)和先验分布p(θ)来自同一个概率分布族,那么这个先验和后验就叫做共轭分布,先验就是似然函数的共轭先验

如果我们考虑从给定的一组数据 x 中推断一个分布的参数θ的问题,那么贝叶斯定理说后验分布等于似然函数θp(x|θ)和先验 p ( 的乘积**

Bayes’ theorem. To calculate the posterior we need to normalise by the integral.

由于似然函数通常是在数据生成过程中定义的,我们可以看到,先验的差异选择会使积分或多或少地难以计算。如果先验具有与似然相同的代数形式,那么我们通常可以得到后验的封闭形式的表达式,避免了数值积分的需要。

激励狄利克雷分布:骰子制造

我们展示了如何使用狄利克雷分布来描述多项分布的随机可变性。我从一篇关于可视化狄利克雷分布的博客文章中借用了这个例子。

假设我们要制造 6 面骰子,但允许一次投掷的结果只有 1、2 或 3(这是为了后面的可视化更容易)。如果骰子是公平的,那么三种结果的概率将是相同的,等于 1/3。我们可以用向量θ=(θ₁, θ ₂, θ ₃).)来表示结果的概率

θ 有两个重要的性质:第一,每个条目的概率之和必须等于 1,并且任何一个概率都不能为负。当这些条件成立时,与骰子滚动相关的结果可以用多项式分布来描述。

换句话说,如果我们观察到 n 掷骰子, D ={x₁,…,x_k},那么似然函数具有以下形式

其中 N_ k 是值 k ∈{1,2,3}出现的次数。

我们预计我们生产的骰子的特征会有一些变化,因此即使我们试图生产公平的骰子,由于生产过程中的变化,我们也不会期望特定骰子的每个结果的概率都是 1/3。为了从数学上描述这种可变性,我们想知道给定制造过程中的每个可能值的概率密度。要做到这一点,让我们把 θ 的每一个元素看作一个独立变量。即对于θ=(θ₁、 θ ₂、 θ ₃),我们可以把 θ ₁、 θ ₂、 θ ₃各自作为一个自变量。由于多项式分布要求这三个变量之和为 1,所以我们知道 θ 的允许值被限制在一个平面内。此外,由于每个值 θ ᵢ必须大于或等于零,所以 θ 的所有允许值的集合被限制在一个三角形内。

我们想知道的是这个三角形上每一点的概率密度。这就是狄利克雷分布可以帮助我们的地方:我们可以用它作为多项式分布的先验。

狄利克雷分布

狄利克雷分布定义了与我们的多项式参数 θ 具有相同特征的向量值输入的概率密度。它有支持(有非零值的点的集合)

其中 K 是变量的个数。其概率密度函数具有以下形式:

狄利克雷分布由向量 α 参数化,其元素 K 的数量与我们的多项式参数 θ 相同。所以你可以把p(θ|α)解读为回答“什么是与多项分布 θ 相关的概率密度,给定我们的狄利克雷分布有参数 α

可视化狄利克雷分布

我们看到狄利克雷分布确实具有与多项式似然分布相同的形式。但是它实际上看起来像什么呢?

要看到这一点,我们需要注意,这是贝塔分布的多元推广。β分布定义在由两个正形状参数α和β参数化的区间[0,1]上。正如所料,它们是二项式(包括伯努利)分布的共轭先验。该图显示了具有多个α和β值的β分布的概率密度函数。

正如我们所见,β密度函数可以根据α和β采用各种不同的形状。当α和β都小于 1 时,分布呈 U 型。在α = β → 0 的极限下,它是一个两点伯努利分布,在每个狄拉克δ函数端点 x =0 和 x =1 处概率相等 1/2,其他地方概率为零。当α=β=1 时,我们有均匀的[0,1]分布,这是具有最大熵的分布。当α和β都大于 1 时,分布是单峰的。这种通过仅改变两个参数的形状多样性使得它对于模拟实际测量特别有用。

对于狄利克雷分布 Dir( α )我们将这些形状概括为一个 K 单形。对于 K =3,可视化分布要求我们做以下事情:1 .在我们的三角形上生成一组 x-y 坐标,2。将 x-y 坐标映射到 2-单纯形坐标空间,3。计算每个点的方向( α )。下面是一些例子,你可以在我的 Github 库中找到代码。

Dirichlet distribution on a 2-simplex (equilateral triangle) for different values of α.**

我们看到现在是参数 α 决定了分布的形状。特别是,α₀=∑αᵢ总和控制着分布的强度(峰值有多高)。如果对所有的Iαᵢ为 1,我们在单纯形的角上得到“尖峰”。对于αᵢ > 1 的值,分布趋向于单纯形的中心。随着α₀的增加,分布越来越紧密地集中在单形的中心。

在我们最初的骰子实验中,当αᵢ → ∞时,我们会产生一致公平的骰子。对于αᵢ > 1 的对称狄利克雷分布,我们将平均产生一个公平的骰子。如果目标是生产有负荷的骰子(例如,以更高的概率掷出 3),我们会想要具有更高α₃.值的非对称狄利克雷分布

我们现在已经看到了什么是狄利克雷分布,它看起来像什么,以及在骰子制造示例的上下文中使用它作为多项式似然函数的先验的含义。在下一篇文章中,我们将深入探讨贝叶斯生成模型以及如何进行推理。

参考

Blei,D.M .,Ng,A.Y .,Jordan,MI (2003) 潜在狄利克雷分配。《机器学习研究杂志》,* 3 (Jan),第 993–1022 页。*

使用有序数据的 Spearman 等级相关系数

原文:https://towardsdatascience.com/discover-the-strength-of-monotonic-relation-850d11f72046?source=collection_archive---------17-----------------------

统计数字

发现单调关系的力量

Photo by Fabio Ballasina on Unsplash

**Table of Contents**[**Introduction**](#e6af)1\. [Simplified formula](#a7ee)
2\. [General formula](#1852)
3\. [Pandas corr](#cde9)
4\. [Finding mathematically using the formula (1–1)](#4fa8)
5 [Finding mathematically using the formula (1–2)](#177a)
6\. [Real-life example](#e68a)[**Conclusion**](#d193)

介绍

斯皮尔曼等级相关系数, 𝑟𝑠 显示两个有序数据之间的相关性。一个序数数据如何随着另一个序数的变化而变化。

有序集之间的函数称为单调函数。

在这篇文章中,我探索了使用不同等级的数据来寻找 Spearman 等级相关系数的不同方法。

Spearman 的等级相关需要序数数据。序数数据的例子有:

  • 第一、第二、第三、
  • 小号,中号,大号,加大码,
  • 强烈同意、同意、中立、不同意、强烈不同意
  • 经常,经常,不经常,一点也不

简化公式

当所有等级都是不同的整数时,Spearman 相关系数由以下公式计算。

如果数据是有序和单调的,并且数据中没有联系,则此公式是皮尔逊相关性的替代方法。

值为 1 意味着数据集严格增加,值为-1 意味着严格减少。值为 0 表示数据不显示单调行为。当观察值在两个变量之间具有相似的等级时,两个变量之间的 Spearman 相关性将会很高。

[## 斯皮尔曼等级相关系数的微妙性

单调关系的未知部分

towardsdatascience.com](/the-subtlety-of-spearmans-rank-correlation-coefficient-29478653bbb9)

通式

Spearman 相关系数被定义为使用等级变量的 Pearson 相关系数。在原始数据 x 和 y 被转换成分级数据 𝑟𝑥𝑟𝑦 之后,斯皮尔曼相关系数被定义为:

让我们找出 5 公里跑的等级与 10 公里跑的等级之间的相关性。所有等级都是不同的整数,没有相同的数字。求系数有不同的方法。

  1. [scipy.stats.spearmanr](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.spearmanr.html)用相关的 p 值计算斯皮尔曼相关系数。
  2. 熊猫 corr
  3. 使用公式(1–1)
  4. 使用公式(1–2)

我们开始吧。
我们需要导入必要的库。

以下是我们的样本数据。

我们使用scipy.stats.spearmanr找到 𝑟𝑠 和 p 值。

correlation=0.428571, p-value=0.337368

p 值是显著性水平。它决定了相关性偶然发生的概率。

correlation=0.428571, p-value=0.337368
At 5% level of significance, the final rankings is not significant or independent

熊猫角

Pandas corr 返回相关矩阵。我们需要从[0,1]中选择值。

0.42857142857142855

使用公式(1–1)进行数学计算

1-(6*(0+4+1+16+1+9+1)/(7*(7**2-1)))=0.4285714285714286

使用公式(1–2)进行数学计算

我们求出 𝑟𝑥𝑟𝑦 的协方差, 𝜎𝑟𝑥𝜎𝑟𝑦 的标准差。

正如我们所料,我们得到了同样的结果。

严格递增

值为 1 意味着数据集在严格增加。当等级不变时会发生这种情况。在这种情况下,你会发现 p 值为 0。

correlation=1.000000, p-value=0.000000

严格递减的

值-1 意味着它在严格减少。排名是逆序的。

correlation=-1.000000, p-value=0.000000

非单调行为

非单调行为的值为 0。

correlation=0.000000, p-value=1.000000

[## 线性关系的度量

皮尔逊与 Jupyter 笔记本的积矩相关性

towardsdatascience.com](/a-measure-of-linear-relationship-5dd4a995ee7e)

现实生活中的例子

我们将使用 BIXI Montréal 的数据。BIXI Montréal 是一个公共自行车共享系统,服务于加拿大魁北克省的 Montréal。这是一个很大的文件,所以需要时间来处理数据。我们用shape()head()来看尺寸和头部。

六列七万九千余行。列有开始数据、开始站代码、结束日期、结束站代码、持续时间和成员。

我们按终点站代码分组,并对持续时间(秒)求和。我们用终点站代码的号码来分配 n 次乘车。

打印导入的数据

让我们绘制导入的数据。

排名数据

请注意,大多数数据都在低端。我们可以用scipy.stats.rankdata通过排名来看数据。

让我们找到斯皮尔曼的 𝑅𝑠

correlation, pval = spearmanr(by_end_station)
print(f'correlation={correlation:.6f}')

输出是:

correlation=0.964881

自行车停靠点的乘车次数几乎与通勤时间成正比。

结论

我们探索了使用有序数据寻找 Spearman 相关系数。四种不同的方法都很有效。在第 2 部分中,我们将使用具有相同数据的不同数据集。这将需要额外的谨慎,以找到斯皮尔曼的相关系数。

通过 成为 的会员,可以完全访问媒体上的每一个故事。

https://blog.codewithshin.com/subscribe

使用斯皮尔曼相关的例子

  • 一个人的智商与花在游戏上的小时数
  • 免费的大学餐和他们的 CGPA 分数
  • 物理和数学排名

参考

  • 要比较 Spearman 相关性和 Pearson 相关性,请在此阅读Pearson 和 Spearman 相关性的比较
  • https://statistics . laerd . com/statistical-guides/spearmans-rank-order-correlation-statistical-guide-2 . PHP
  • https://www . ka ggle . com/resident Mario/spearman-correlation-with-Montreal-bikes/data
  • https://seaborn.pydata.org/generated/seaborn.jointplot.html