TowardsDataScience-博客中文翻译-2019-二十-
TowardsDataScience 博客中文翻译 2019(二十)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
基于深度学习的 web 应用:从数据收集到部署
原文:https://towardsdatascience.com/deep-learning-based-web-application-from-data-collection-to-deployment-9e89f29b67df?source=collection_archive---------19-----------------------
从头开始构建图像分类器 web 应用程序,不需要 GPU 或信用卡。
这篇文章描述了如何在不需要 GPU 或信用卡的情况下为图像分类、构建一个基于深度学习的网络应用!
尽管有很多文章描述这种东西,但我找不到完整的指南来描述从数据收集到部署的所有步骤,而且一些细节也很难找到(例如,如何在 Google Drive 上克隆 Github repo)。
文章很大程度上基于 fast.ai 的程序员实用深度学习课程(简直太神奇了)。它分为以下几个部分:
- 数据采集
- 培训
- 部署
本指南面向已经具备基本编码和深度学习经验的人;如果有些概念是全新的,你最好从更具体的文章开始。
我们将看到一个如何构建猫科动物分类器的例子。完整代码在这里有,你可以在这里 测试 web 应用(如果不行说明我已经关机了;可以看看 fast.ai 玩具模型这里)!
1.数据收集
第一个问题是数据收集。虽然在像 Kaggle 这样的网站上有许多预先存在的数据集,但你可能会对构建我们自己的数据集感兴趣。在这种情况下,我们对区分斑点猫科动物感兴趣,如下图所示。
Cheetah, Jaguar, Leopard and … Other
因此,给定一幅图像,我们的分类器应该告诉我们它是否包含一只猎豹、一只美洲豹、一只豹或其他什么。是的,我知道这完全没用。然而,这有利于练习和娱乐:)。
第一件事是收集每个班级的图像样本。有几种方法可以从网上抓取图像;我们将利用 fast.ai 提供的 image_cleaner 模块 。其他的选择可能是Google _ images _ download包,或者你可以试着从浏览器使用 javascript 控制台,就像这里的一样。
image _ cleaner提供可从 Jupyter 笔记本使用的应用程序。你需要做的就是安装 fastai 库并在 Jupyter 笔记本中运行以下代码:
****Warning: to be run in Jupiter Notebook, it doesn’t work in Jupyter Lab and CoLab
这将导致类似这样的结果:
You need to set the keywords for the search, the number of images and the minimum quality.
比你想象的容易,对吧?我们只需要注意几个细节:
- 在你的搜索中要精确;可能值得使用特殊字符来强制包含("")或排除(-)。例如:猫科动物“美洲虎”——汽车。
- 要下载超过 100 张图片,你需要安装 selenium 和 chromedriver。
- 有不同的方法来训练分类器 理解图像是否不对应于任何考虑的类别。 一种方法是创建一个"其他"类包含随机图像。对于“other”类,我们的搜索是:动物-美洲虎-猎豹-豹。
- 您的数据集中很可能会有一些噪声图像;应该“用手”将它们移除。拥有一个相对较小的干净数据集比拥有一个巨大的嘈杂数据集要好。
现在我们有了一个全新的干净的数据集。训练时间到了!
2.培养
现在呢?每个人都知道,为了能够训练一个图像分类器,你需要大量的图像和图形处理器!或者……也许不是?
我们不需要收集这么多图像,这是因为两个惊人的技术:数据增强和迁移学习。第一种技术是通过从现有图像开始构建新图像来自动扩充数据集,如下图所示:
Example of Data Augmentation
第二种技术是使用预先训练好的模型,在我们的例子中是 ResNet34 。这个网络已经在 ImageNe t 数据集上进行了训练,可以检测数千个类别。因此,我们可以预期由最后一个隐藏层给出的图像表示“捕捉”了大量复杂的图案,即它提供了智能特征。
即使这些概念可能看起来不完全清楚,这也不应该阻止我们部署我们的应用程序。事实上, fast.ai 库使得这些技术变得非常容易使用。
为了在不需要信用卡的情况下免费访问 GPU,我们可以使用 Google Colab,这是 Google 提供的一项服务,因此与 Google Drive 高度集成。
在谷歌实验室中创建和运行一个 Jupyter 笔记本相当简单。要启用 GPU,请按“运行时”、“运行时类型,并将“硬件加速器”设置为 GPU。
然而,我们还需要:
- 连接驱动
- 与 Git/GitHub 通信
一旦我们将数据放入 Google Drive,要从 Colab Notebook 访问它,我们只需运行以下代码:
现在我们可以从“路径”加载数据。
要从 Drive 使用 Github,我们基本上使用 Colab 笔记本作为命令行,如这里的所述。就我个人而言,我在我称为git _ communicator . ipynb .的项目之外使用过一个 Colab 笔记本
因此,要克隆 Github 存储库,我们只需在 Colab 的笔记本上运行以下代码:
一旦我们完成了修改,我们就可以运行通常的 git 命令(以“!”开头)提交和推送修改)来自 Colab 笔记本手机。
一旦我们为我们的项目创建了一个 GitHub 库,我们就能够在 Google Drive 上克隆,利用一个免费的 GPU在 Colab 上运行现有的笔记本,然后提交修改!
既然我们已经解决了技术问题,是时候训练我们的分类器了。还是那句话, fast.ai 让它超级简单。首先,让我们加载数据:
这段代码创建了一个 DataBunch 对象:
- 保留 20%的数据进行验证
- 应用标准数据扩充技术
- 应用 ImageNet 数据集规范化
很好,现在我们将使用带有预训练权重的 ResNet34 网络架构,并且仅训练最后一个隐藏层与输出层的连接。这可以通过两行代码来完成:
该代码使用了fit-one-cycle策略,这是一种智能技术,通过使用开始时逐渐增加,后来逐渐减少的学习速率,在短时间内训练网络。这使我们得出以下结果:
在不到 6 分钟的时间里,我们在验证集上达到了几乎 93%的准确率。然而,我们可以观察到培训损失仍然大于验证损失。这意味着仍有改进的空间!
现在也许值得对整个网络进行训练,不仅仅是最后一层。这也可以通过两行代码来实现:
在策略中为最大学习速率设置一个片而不是单个值允许用不同的学习速率训练网络。第一层将用较小的学习率来训练,因为它们“检测”在不同图像数据分布中不应该改变太多的简单模式。
让我们看看我们现在得到的混淆矩阵:
哇,这是验证集上 98.73 %的准确率!
如果我们将它作为专业应用,我们将不得不提供一个单独的测试集来评估我们的分类器的性能。然而,对于像我们这样的玩具项目来说,这个结果已经足够了!
由于我们对模型感到满意,我们可以通过运行以下命令将其导出以进行部署:
learn.export()
运行模型所需的一切都将存储在一个名为 export.pkl 的文件中,在我们的例子中放在“data”目录中。
3.部署
如果说训练很容易,那么部署就更容易了,多亏了Docker 和 Render 。
Docker 是一个允许使用容器轻松部署和运行应用程序的工具。简而言之,它是一种虚拟机,而不是虚拟化整个操作系统,使用与运行系统相同的 Linux 内核,从而提高性能。
Render 是一个 web 服务,允许非常容易地构建和运行 web 应用程序(以及其他)。
同样,我们甚至不需要理解这些东西实际上是如何工作的。我们可以简单地使用 fast.ai 提供的示例代码(这里是),把它添加到我们的存储库中(或者从头开始分支)。
要在渲染时部署,只需:
- 创建一个渲染帐户,并将其连接到 Github
- 将训练好的模型文件 export.pkl 上传到 Google Drive 并使其可下载
- 用 URL 编辑
model_file_url
变量到 export.pkl 和更新文件server.py
中的行classes
**** - 编辑index.html以更改网站文本和布局(可选)
- 启动新服务
所有这些步骤在和中详细描述。
最后,你现在应该有一个基于深度学习的 web 应用程序!它应该是这样的:
结束语
- 数据决定一切。整个过程最重要的是得到一个像样的数据集。
- 在这个应用程序中,我们只对动物的图像进行训练。网络可能会对其他主题的图像表现出意想不到的行为。
- 我们基于验证集来评估性能。在现实世界的应用中,我们应该使用测试集来避免有偏见的估计。
- fast.ai 库非常酷,它让复杂的高级技术变得非常容易使用。然而,如果你需要更多地控制正在发生的事情,直接使用它的后端 PyTorch 可能会更好。
深度学习基础:速成课程
原文:https://towardsdatascience.com/deep-learning-basics-a-crash-course-3213aa9e477c?source=collection_archive---------17-----------------------
了解什么是深度学习,以及深度学习算法在现实应用中是如何使用的!
机器学习 (ML)和深度学习 (DL)技术正在被应用于各个领域,数据科学家在许多不同的行业都受到追捧。
通过机器学习,我们可以识别出我们获取知识的过程,而这些知识并不是从数据中显而易见的,从而做出决策。机器学习技术的应用可能会有很大的不同,可以在医学、金融和广告等不同的学科中找到。
深度学习利用了比 20 世纪 80 年代使用的更先进的神经网络。这不仅是理论发展的结果,也是计算机硬件进步的结果。
在这个速成课程中,我们将学习深度学习和深度神经网络 (DNNs),即具有多个隐藏层的神经网络。我们将讨论以下主题:
- 深度学习简介
- 深度学习算法
- 深度学习的应用
我们开始吧!
这个速成课程改编自 Next Tech 的 Python 深度学习项目(第一部分:基础)课程,该课程探索了深度学习的基础知识,建立了一个 DL 环境,并构建了一个 MLP。它包括一个浏览器内沙盒环境,预装了所有必要的软件和库。这里可以开始!
深度学习简介
给定通用近似定理,你可能想知道使用多个隐藏层有什么意义。这绝不是一个天真的问题,在很长一段时间里,神经网络都是这样使用的。
使用多个隐藏层的一个原因是,逼近一个复杂的函数可能需要隐藏层中大量的神经元,这使得它不实用。使用深度网络的一个更重要的原因是,深度网络不仅仅学习在给定输入 X 的情况下预测输出 Y,它还理解输入的基本特征,深度网络与隐藏层的数量没有直接关系,而是与学习的水平有关。
让我们看一个例子。
在 H. Lee、R. Grosse、R. Ranganath 和 A. Ng 于 2009 年发表的《机器学习国际会议记录》(ICML)(Proceedings of the International Conference on Machine Learning)中,作者用不同类别的物体或动物的图片训练了一个神经网络。在下图中,我们可以看到网络的不同层如何学习输入数据的不同特征。在第一层中,网络学习检测一些基本特征,例如所有类别中所有图像共有的线条和边缘:
The first layer weights (top) and the second layer weights (bottom) after training
在接下来的图层中,如下图所示,它将这些线和边组合在一起,以构成特定于每个类别的更复杂的要素:
Columns 1–4 represent the second layer (top) and third layer (bottom) weights learned for a specific object category (class). Column 5 represents the weights learned for a mixture of four object categories (faces, cars, airplanes, and motobikes)
在最上面一行,我们可以看到网络如何检测每个类别的不同特征。人脸的眼睛、鼻子和嘴巴,汽车的门和轮子,等等。这些特征是的抽象。也就是说,网络已经学习了特征的一般形状,例如嘴或鼻子,并且可以在输入数据中检测该特征,尽管它可能有变化。
在上图的第二行中,我们可以看到网络的深层是如何将这些特征组合成更复杂的特征的,比如人脸和整辆汽车。深度神经网络的优势在于,它们可以通过从训练数据中推导出这些高级抽象表示来自己学习这些表示。
深度学习算法
我们可以将深度学习定义为一类机器学习技术,其中信息在分层中进行处理,以理解越来越复杂的数据的表示和特征。在实践中,所有的深度学习算法都是神经网络,它们共享一些共同的基本属性。它们都由相互连接的神经元组成,这些神经元被组织成层。它们的不同之处在于网络架构(神经元在网络中的组织方式),有时还在于它们的训练方式。
考虑到这一点,让我们看看神经网络的主要类别。下面的列表并不详尽,但它代表了当今使用的绝大多数算法。
多层感知器
一种具有前馈传播、全连接层和至少一个隐藏层的神经网络。
该图展示了一个具有两个隐藏层的 3 层全连接神经网络。输入层有 k 个输入神经元,第一隐层有 n 个隐神经元,第二隐层有 m 个隐神经元。在这个例子中,输出是两个类 y ₁和 y ₂.上面是永远开启的偏置神经元。一层中的一个单元连接到上一层和下一层中的所有单元(因此是完全连接的)。
卷积神经网络
CNN 是一种前馈神经网络,具有几种特殊的层。例如,卷积层对输入图像(或声音)应用一个滤波器,方法是在输入信号上滑动该滤波器,以产生一个 n 维的激活图。有一些证据表明,中枢神经系统中的神经元的组织方式类似于大脑视觉皮层中生物细胞的组织方式。今天,在大量的计算机视觉和自然语言处理任务上,它们优于所有其他的 ML 算法。
递归神经网络
这种类型的网络有一个内部状态(或内存),它是基于所有或部分已输入网络的输入数据。递归网络的输出是其内部状态(以前输入的记忆)和最新输入样本的组合。同时,内部状态发生变化,以合并新输入的数据。由于这些特性,递归网络是处理序列数据(如文本或时间序列数据)的任务的理想选择。
自动编码器
一类无监督学习算法,其中输出形状与输入形状相同,允许网络更好地学习基本表示。它由输入层、隐藏层(或瓶颈层)和输出层组成。虽然这是一个单一的网络,但我们可以将其视为两个组件的虚拟组合:
- 编码器:将输入数据映射到网络的内部表示。
- 解码器:试图从网络的内部数据表示中重建输入。
强化学习
强化算法学习如何通过许多步骤实现一个复杂的目标,当它们做出错误的决定时使用惩罚,当它们做出正确的决定时使用奖励。这是一种经常用来教机器如何与环境互动的方法,类似于人类行为由负面和正面反馈形成的方式。RL 通常用于构建电脑游戏和自动驾驶汽车。
深度学习的应用
机器学习,特别是深度学习,在预测质量、特征检测和分类方面产生了越来越多令人惊讶的结果。许多最近的结果甚至成为了新闻!以下是这些技术在今天或不久的将来可以应用的几种方式:
自动驾驶汽车
如今,新车有一套安全和便利的功能,旨在使驾驶体验更安全,压力更小。其中一个功能是当汽车遇到障碍物时自动紧急制动。另一个是车道保持辅助系统,它允许车辆停留在当前车道上,而无需驾驶员用方向盘进行校正。为了识别车道标志、其他车辆、行人和骑自行车的人,这些系统使用一个前向摄像头。我们可以推测,未来的自动驾驶汽车也将使用深度网络进行计算机视觉。
图像和文本识别
谷歌的视觉 API 和亚马逊的 Rekognition 服务都使用深度学习模型来提供各种计算机视觉能力。这些包括识别和检测图像中的对象和场景、文本识别、人脸识别等等。
医学成像
医学成像是各种创建身体内部视觉表示的非侵入性方法的总称。其中一些包括磁共振图像 ( MRIs )、超声波、计算机轴向断层扫描 ( CAT )扫描、X 射线和组织学图像。典型地,这样的图像由医学专业人员分析以确定患者的状况。机器学习,特别是计算机视觉,正在实现计算机辅助诊断,它可以通过检测和突出图像的重要特征来帮助专家。
例如,为了确定结肠癌的恶性程度,病理学家必须使用组织学成像来分析腺体的形态。这是一项具有挑战性的任务,因为形态学可以有很大的不同。深度神经网络可以自动从图像中分割出腺体,让病理学家来验证结果。这将减少分析所需的时间,使其更便宜和更容易获得。
病史分析
另一个可以受益于深度学习的医疗领域是病历记录的分析。在医生诊断病情和开出治疗处方之前,他们会查阅患者的病史以获得更多的信息。深度学习算法可以从这些大量记录中提取最相关和最重要的信息,即使它们是手写的。这样,医生的工作可以变得更容易,同时也降低了出错的风险。
语言翻译
谷歌的神经机器翻译 API 使用——你猜对了——深度神经网络进行机器翻译。
语音识别和生成
Google Duplex 是深度学习的另一个令人印象深刻的真实世界演示。这是一个新系统,可以通过电话进行自然对话。例如,它可以代表用户预订餐馆。它使用深度神经网络来理解对话,并生成现实的、类似人类的回复。
Siri、谷歌助手和亚马逊 Alexa 也依靠深度网络进行语音识别。
赌博
最后,AlphaGo 是一台基于深度学习的人工智能 ( AI )机器,它在 2016 年 3 月因击败世界围棋冠军 Lee Sedol 而成为新闻。AlphaGo 在 2016 年 1 月已经成为新闻,当时它击败了欧洲冠军范辉。虽然,在当时,它似乎不太可能继续击败世界冠军。几个月后,AlphaGo 以 4 比 1 的比分横扫对手,实现了这一非凡的壮举。
这是一个重要的里程碑,因为围棋比国际象棋等其他游戏有更多可能的游戏变化,而且不可能事先考虑到每一步可能的棋。此外,与国际象棋不同,在围棋中,甚至很难判断棋盘上单个棋子的当前位置或价值。2017 年,DeepMind 发布了名为 AlphaZero 的 AlphaGo 更新版本。
在这个速成课程中,我们解释了什么是深度学习,以及它与深度神经网络的关系。我们讨论了不同类型的网络和深度学习的一些现实应用。
这只是一个开始——如果你想了解更多关于深度学习的信息,Next Tech 有一个 Python 深度学习项目系列,探索跨计算机视觉、自然语言处理(NLP)和图像处理的真实世界深度学习项目。本系列的第 1 部分涵盖了 DL 的基本概念,如何建立 DL 环境,以及如何构建 MLP。这里可以开始!
深度学习丛书 3.1 到 3.3 概率质量和密度函数
原文:https://towardsdatascience.com/deep-learning-book-series-3-1-to-3-3-probability-mass-and-density-functions-fe7e41ca6539?source=collection_archive---------16-----------------------
该内容是古德费勒(Goodfellow,I .)、本吉奥(Bengio,y .)和库维尔(a .)(2016 年)的深度学习书籍中关于概率的第三章系列的一部分。它旨在提供关于数学理论的直觉/绘图/python 代码,并作为我对这些概念的理解而构建。
Github :相应的 Python 笔记本可以在这里找到。
我很高兴在这里展示我的深度学习系列(Goodfellow 等人的书)的以下内容。这是根据第三章概率制作的第一个帖子/笔记本。对于那些已经知道我关于线性代数第二章的帖子/笔记的人来说,目标和结构是一样的。目的是让没有深厚数学背景的人更容易理解这本书。更多信息可以参考入门帖。
我认为通过使用代码(这里是 Python)和可视化来获得对数学概念更好的直觉是可能的。该结构遵循书的子章节,它可以作为额外的内容,给出例子和细节。
这第一部分是关于第 3.1 至 3.3 章。第 3.1 章是对概率的介绍,不包含任何技术难度。因此,您可以在此处直接阅读。第 3.2 章实际上只是一个定义,所以主要部分是 3.3 关于概率质量函数和概率密度函数。看完之后,随机变量及其概率分布(对于离散和连续变量)对你来说就没有秘密了🏄🏾♂️.
为了理解它,我们还将学习一些非常有用的数学工具:
🔧离散变量与连续变量
🔧衍生
🔧积分
🔧曲线下面积
这些概念对于一般数据科学和机器学习来说非常重要。
3.2 随机变量
概率的目标是处理不确定性。它给出了描述随机事件的方法。随机变量是一个可以根据随机事件的结果取多个值的变量。可能的结果是变量可能取的值。
如果结果是有限的(例如掷骰子事件中的 6 种可能性),则称随机变量为离散的。
如果可能的结果不是有限的(例如,在 0 和 1 之间画一个数可以给出无穷多个值),则称随机变量为连续。
和书中一样,我们将使用下面的符号:一个小写的普通字体字母代表一个随机变量:x。
例 1。
假设变量 x 是一个随机变量,表示掷骰子的结果🎲。变量可以取值 1、2、3、4、5 或 6。它是一个离散的随机变量。
3.3 概率分布
所以一个随机变量可以取多个值。很重要的一点是,要知道某些值是否会比其他值更经常遇到。一个随机变量可以取的每一个可能值的概率的描述叫做它的概率分布。
离散变量和连续变量的概念很重要,我们将研究两种情况下概率分布的概念。即使它们是相关的,也存在一些差异。
反正一个随机变量 x 的概率分布描述的是每一个结果的概率(概率 1 表示变量会一直取这个值,概率 0 表示永远不会遇到)。这个函数叫做概率分布。更具体地说,它被称为离散变量的概率质量函数和连续变量的概率密度函数。
3.3.1 离散变量和概率质量函数
概率质量函数是描述与随机变量 x 相关的概率的函数,为避免混淆,该函数被命名为 P (x)或 P (x = x )。 P (x = x )对应随机变量 x 取值 x 的概率(注意字体不同)。
例 2。
说明离散随机变量和概率质量函数的骰子实验
让我们把一个骰子掷无限次,看看 1 的比例,2 的比例等等。我们称 x 为随机变量,它对应于掷骰子的结果。因此,随机变量 x 只能取下列离散值:1、2、3、4、5 或 6。因此它是一个离散随机变量。
概率质量函数的目的是描述每个可能值的概率。在我们的例子中,它描述了得到 1 的概率,得到 2 的概率等等。在骰子滚动实验的情况下,我们有相同的概率获得每个值(如果我们假设骰子是完美的)。这意味着我们可以写:
P(x = 1)=P(x = 2)=P(x = 3)=P(x = 4)=P(x = 5)=P(x = 6)
现在,我们如何计算概率 P (x = 1), P (x = 2)等等。?因为我们有 6 种可能的结果,并且它们是等概率的,所以我们有:
P(x = 1)=P(x = 2)=P(x = 3)=P(x = 4)=P(x = 5)=P(x = 6)= 1/6
顺便说一下,这个分布显示了每个值的相同概率:它被称为均匀分布。
概率质量函数可能看起来像这样:
骰子实验的概率质量函数
y 轴给出概率,x 轴给出结果。
让我们用代码重现第一个例子,以确保一切都很清楚:
我用 Numpy 函数zeros()
创建了一个填充了 0 的数组。每次投掷时,我从 6 种可能性中选择一个值。然后,我使用参数return_counts
设置为True
的 Numpy 函数unique()
来获得每个可能结果的数量。我画出了每个可能值的比例。
我们可以看到,分布看起来像均匀分布,每个结果的概率约为 1/6(约为 0.17)。
联合概率分布
现在让我们看看如果掷两个骰子会发生什么。对于每个骰子,结果都与某个概率相关联。我们需要两个随机变量来描述这个博弈,假设 x 对应第一个骰子,y 对应第二个骰子。我们还有两个与随机变量相关的概率质量函数: P (x = x )和 P (y = y )。这里,对于两个骰子,随机变量(1、2、3、4、5 或 6)和概率质量函数的可能值实际上是相同的,但不需要如此。
在我们对 x 取一个特定值而 y 取另一个特定值的概率感兴趣的情况下,联合概率分布很有用。例如,第一次掷骰子得到 1,第二次掷骰子得到 2 的概率是多少?每对值对应的概率写成 P (x = x, y = y )或 P (x,y)。这就是我们所说的联合概率。
例 3。
例如,让我们计算第一个骰子为 1,第二个骰子为 2 的概率:
P (x = x, y = y ) = 1/6。1/6 = 1/36 = 0.028
概率质量函数的性质
一个函数是概率质量函数,如果:
∀这个符号的意思是“为了任何人”。
这意味着对于 x 范围内的每个可能值 x (在掷骰子实验的例子中,所有可能值为 1、2、3、4、5 和 6),结果对应于该值的概率在 0 和 1 之间。概率为 0 表示事件不可能发生,概率为 1 表示您可以确定结果将符合该值。
在骰子的例子中,每个可能值的概率是 1/6,介于 0 和 1 之间。此属性已实现。
这意味着与每个可能值相关联的概率之和等于 1。
在骰子实验的例子中,我们可以看到有 6 种可能的结果,每种都有 1/6 的概率,总共是 1/6 * 6 = 1。此属性已实现。
3.3.2 连续变量和概率密度函数
有些变量不是离散的。它们可以在一定范围内取无限多的值。但是我们仍然需要描述与结果相关的概率。连续变量的概率质量函数的等价物被称为概率密度函数。
在概率质量函数的情况下,我们看到 y 轴给出了一个概率。例如,在我们用 Python 创建的图中,得到 1 的概率等于 1/6 = 0.16(查看上面的图)。它是 1/6,因为它是 6 种可能性中的一种。
但是,对于连续变量,我们不能这样做,因为可能性的总数是无限的。例如,如果我们画一个介于 0 和 1 之间的数字,我们有无限多种可能的结果(例如 0.320502304……)。在上面的例子中,我们有 6 种可能的结果,导致大约 1/6 的概率。现在,我们有每个概率等于 1/+ ∞ = 0。这样的功能不会很有用。
因此,概率密度函数的 y 轴不代表概率值。为了得到概率,我们需要计算曲线下的面积(我们将在下面看到关于曲线下面积的一些细节)。这样做的好处是,它导致了根据一定范围(在 x 轴上)的概率:如果范围增加,曲线下的面积也增加。让我们看一些例子来澄清这一切。
例 4。
假设我们有一个随机变量 x,可以取 0 到 1 之间的值。这是它的概率密度函数:
概率密度函数
我们可以看到,0 似乎是不可能的(概率在 0 左右),1 也不是。pic 约为 0.3,这意味着将在该值附近获得很多结果。
通过计算该范围的曲线下面积,可以从某个范围的值之间的概率密度函数中找到概率。例如,绘制 0.5 到 0.6 之间的值的概率对应于以下区域:
概率密度函数和曲线下面积在 0.5 到 0.6 之间。
我们很容易看到,如果我们增加范围,概率(曲线下的面积)也会增加。例如,对于 0.5–0.7 的范围:
概率密度函数和曲线下面积在 0.5 到 0.7 之间。
我们一会儿会看到如何计算曲线下的面积,并得到与特定范围相关的概率。
概率密度函数的性质
概率质量函数和概率密度函数之间的这些差异导致概率密度函数的不同性质:
在这种情况下, p (x)不一定小于 1,因为与概率不对应(概率本身仍需在 0 和 1 之间)。
例 5。
例如,假设我们有一个连续的随机变量,取值范围在 0 到 0.5 之间。该变量由均匀分布描述,因此我们将得到以下概率分布函数:
概率密度函数(均匀分布)。曲线下的面积等于 1 (2 * 0.5),y 值大于 1。
我们可以看到 y 值大于 1。概率由曲线下的面积给出,因此它也取决于 x 轴。
🤨如果您想亲自看看,我们将用 Python 再现这个例子。为此,我们将创建一个随机变量 x,它可以随机取 0 到 0.5 之间的值。由于 Numpy 函数random.uniform()
,将使用均匀分布。该函数的参数是最低值(包括)、最高值(不包括)和样本数。因此np.random.uniform(0, 0.5, 10000)
将创建 10000 个随机选择为> 0 且≤0.5 的值。
看起来不错!🏄🏽♀️
我们可以看到,这个形状看起来像我上面画的那样,所有的 x 在 0 到 0.5 之间,y 轴值都在 2 左右。
然而,在这个情节中有一件事很耐人寻味。我们讨论过连续变量,这里我们用条形表示分布。解释和之前一样:我们需要离散化函数来统计每个区间的结果数。实际上,间隔的数量是函数distplot()
的一个参数。让我们试着使用许多箱子:
我们可以看到,我们仍然在 2 左右,但可变性比以前更大(条形可以从 1 到 4,而在上一个图中不是这种情况)。知道为什么吗?🤔
💡这是因为由于我们采用了更多的箱,每个箱中的值数量较少,导致估计不太准确。如果这个假设是真的,我们可以通过增加样本数量来减少这种可变性。让我们试试:
太好了🤸🏼♂️
我们现在可以去第二处房产了!
对于概率质量函数,我们已经看到概率之和必须等于 1。这不是概率密度函数的情况,因为概率对应于曲线下的面积,而不是直接对应于 y 值。然而,这意味着曲线下的面积必须等于 1 。
我们在上一个例子中看到,面积实际上等于 1。由于均匀分布的平方形状,它可以很容易地获得和可视化。因此,可以将高度乘以宽度:2 * 0.5 = 1。
然而,在许多情况下,形状不是正方形,我们仍然需要计算曲线下的面积。让我们看看如何做到这一点!
🔧曲线下面积
特定数值范围的函数曲线下的面积可通过函数的积分计算。我们会看到,计算函数的积分与计算导数是相反的。这意味着如果你得到一个函数 f ( x )并计算结果函数f’(x)的积分,你将得到 f ( x )。😮
函数在某一点的导数给出了它的变化率。描述另一个函数(导数)变化率的函数和曲线下面积之间有什么联系🤔?
先说一个关于导数的点!然后,通过下一个图形示例,它将变得非常清晰。🔮
例 6。
我们想模拟车辆的速度。假设函数 f ( x ) = x 在时间(x 轴)的函数中定义了它的速度(y 轴)。
首先,我们将绘制函数 f (x)= x it 以查看其形状:
形状是抛物线!它表明速度在开始时缓慢增加,但在恒定的持续时间内增加得越来越多。
我已经创建了一个包含 x 轴所有点的变量 x (使用 Numpy 的函数arange()
)。所以它只是从-10 到 10 的所有值,步长为 0.1。让我们看看前 10 个值。
array([-10\. , -9.9, -9.8, -9.7, -9.6, -9.5, -9.4, -9.3, -9.2, -9.1])
这里是 Numpy 的arange()
函数的文档。
在我们的例子中,函数定义了车辆的速度与时间的函数关系,因此负值没有意义。让我们只取 x 轴的正的部分,以避免负的时间(我们会说 0 是实验的开始)。
好,这样更好!
这个函数的导数是 f '(x)=2 x 。欲了解更多关于衍生规则的信息,请点击查看。
下面是一个f’(x)的情节:
🔧导数
导数的这个表示表示加速度。 f ( x )描述了车辆的速度与时间的函数关系,导数 f '( x )表示速度与时间的函数关系的变化率,即加速度。
我们可以看到车辆的加速度随时间线性增加。导数告诉我们,车速的变化率是 2 x 。例如,当 x =0 时,变化率等于 2 * 0 = 0,因此速度不变。当 x =3 时,变化率为 2 * 3 = 6。这意味着此时,时间增加 1,速度增加 6。
总而言之,函数的导数给出了它的变化率。在我们的例子中,变化率是另一个函数( f '( x ) = 2 x ),但是它可以是常数(变化率总是相同的,例如 f '( x )=2)或者是二次函数(例如f'(x)=x)。
🔧积分
能够计算导数是非常强大的,但是有没有可能反过来:从变化率到变化本身😮。哇,太酷了!答案由函数的积分给出。
对 f '( x )的积分还给我们 f ( x )。符号如下:
这意味着我们拿 f '( x )去拿回 f ( x )。这里的符号 dx 意味着我们对 x 进行积分,也就是说,我们对由 y 加权的切片求和(参见这里的和)。
如果我们再举一个例子:
我们可以看到有一个区别:增加了一个常数 c 。这是因为无穷多个函数可以给出导数 2 x (例如 x + 1 或者x+294……)。我们丢失了一些信息,而且无法恢复。
现在,图形解释(我喜欢这个💛):我们已经看到 2 x 是描述函数 x 的变化率(斜率)的函数。现在如果我们从 f '( x )到 f ( x )我们可以看到 f '( x )曲线下的面积对应于 f ( x ):
f’(x)的曲线下面积对应 f(x)。这说明了积分和导数是如何逆向运算的。
该图显示了函数f'(x)= 2x,我们可以看到曲线下的面积呈指数增长。该区域代表不同的范围([0–0]、[0–1]、[0–2]、[0–3])。我们可以计算曲线下的面积(使用勾股定理并除以 2,因为面积是半平方)并找到以下值:0,1,4,9…这对应于原函数f(x)=x!🎺
结论
总而言之,我们已经看到了什么是随机变量,以及离散变量(概率质量函数)和连续变量(概率密度函数)的概率分布是如何表示的。我们还学习了联合概率分布的概念和基础数学工具,如导数和积分。
现在,您拥有了深入研究概率的所有工具。下一部分将是 3.4 到 3.8 章。我们将看到我们称之为边际和条件概率、链式法则和独立性的概念。
如果你想继续关注: Twitter , Github , Linkedin 。
我希望这能帮助你对这一切有更好的直觉!如有任何问题/注意事项/更正,请随时联系我!😀
最初发布于https://hadrienj . github . io/posts/Probability-Mass-and-Density-Functions/
深度学习丛书 3.4 和 3.5 边际和条件概率
原文:https://towardsdatascience.com/deep-learning-book-series-3-4-and-3-5-marginal-and-conditional-probability-8c6239e453b8?source=collection_archive---------21-----------------------
The sum rule allows to calculate marginal probability from joint probability.
该内容是古德费勒(Goodfellow,I .)、本吉奥(Bengio,y .)和库维尔(a .)(2016 年)的深度学习书籍中关于概率的第三章系列的一部分。它旨在提供关于数学理论的直觉/绘图/python 代码,并作为我对这些概念的理解而构建。
Github :相应的 Python 笔记本可以在这里找到。
我们已经在上一篇 / 笔记本关于深度学习书的 3.1 到 3.3 章学习了概率的基础知识。我们已经学习了什么是随机变量,概率质量函数或概率密度函数。我们的目标也是为了获得对非常常用的工具的更多直觉,比如导数、曲线下面积和积分。
在这第二篇关于边际和条件概率的文章/笔记中,你将学习离散和连续变量的联合和边际概率。然后,我们会看到条件概率的概念,以及相依事件和独立事件的区别。这些都对应了深度学习这本书的 3.4 章和 3.5 章。
我们将坚持概率中使用的数学符号。你会发现这是一种表达思想的富有表现力和综合性的方式!
3.4 边际概率
在前面的文章中,我们已经看到了一次一个随机变量的概率。在某些情况下,查看多个事件的概率可能会很有趣。例如,我们会问:“如果我掷硬币两次,恰好得到一个‘正面’和一个‘反面’的概率是多少?要回答这类问题,我们需要考虑多个事件。
注释
让我们从符号的一些细节开始。像往常一样,确保每一个数学符号都清晰明了是很重要的。下图总结了我们将在本文中使用的符号🔧:
Dictionary of mathematical expressions and their corresponding English traductions.
上一篇帖子我们已经看到,P(x= x ,y= y )是指 x 取特定值x和 y 取特定值 y 的联合概率。关于符号的详细信息,您也可以参考上一篇文章。你也可能遇到交集符号:∩。例如,P(x ∩ y)对应于 x 和 y 同时出现的概率。
例 1。
让我们从一个处理边际概率概念的例子开始。
在这个实验中,我们抛硬币(第一个事件)和掷骰子(第二个事件)。我们看每个事件的概率。例如,得到“正面”的概率是 1/2。掷出 1 的概率是 1/6。下图分别显示了每个事件的每个结果的概率:
The probabilities of two events (tossing a coin and throwing a dice) are represented individually.
你可能会对我在表格中显示概率感到惊讶。实际上,我把问题倒过来了:这些概率就是边际概率。“marginal”这个名字提醒我们可以把它们写在表格的空白处。
问题是:我们可以写在表格中间的其他概率是什么?它们是联合概率。它是获得两种特定结果的概率:
Marginal probability. The probabilities of two events (tossing a coin and throwing a dice) are represented. The marginal probabilities are in the ‘margin’ and correspond to the probabilities of each event alone.
例如,我们可以看到,得到 1 和“头”的概率等于 1/6 * 1/2 = 1/12。边际概率表示在边际上,对应于变量子集的概率分布。
求和规则
有时,您知道事件的联合概率,并需要从中计算边际概率。边际概率是用求和规则计算出来的。如果你回头看最后一张表,你可以看到写在页边空白处的概率是相应行或列的概率之和。
从数学上来说,我们有:
我们将研究这个方程的细节。
第一,提醒字体重要,表示不同的东西。x 是离散随机变量(例如,对应于掷骰子),x是随机事件的结果(例如,一个可能的骰子结果:1、2、3、4、5 或 6)。同样,y 是随机变量(假设对应于掷硬币),而 y 是 y 的结果(“正面”或“反面”)。
-第一个蓝色部分可以读作“对于 x 中的所有 x ”。这里,这是方程为真的一个条件。因此,只有当结果 x 在 x 的可能结果中时,表达式才为真。例如,如果随机变量 x 对应于掷骰子,我们知道 x 可以取值 1、2、3、4、5 或 6。只有当 x 实际上取这些值中的一个时,该等式才成立。
-绿色部分是 x 取特定值 x 的概率。例如,仍然在骰子实验中,P(x=6)对应于掷出 6 的概率。
-橙色的 sum 符号表示我们将对该符号之后的元素求和(这里 P(x= x ,y= y ))。sum 符号下的小 y 表示我们对 y (P(x= x ,y=1),P(x= x ,y=2 等所有可能的值求和。).
-红色部分是 x 取值xy 取值 y 的概率。
那么这个方程说明了什么呢?
这意味着 x= x 的概率等于在每个可能的 y 上对应于 x= x 的概率之和。下面的例子将阐明这种说法。
例 2。
和上一个例子一样,我们将做一个投掷骰子和硬币的实验。上表的中间给出了 x 和 y 取特定值的概率,也就是说,我们得到了投掷和投掷的特定结果。例如,掷出 1 并掷出“正面”的概率是 P(x=1,y=“正面”)= 1/12。
Joint probability to toss a head and to throw a 1.
我们可以使用前面的等式
假设我们想计算掷出 1 的概率:
这是 x=1 时 y 上的概率之和。有两种可能:我们可以有 x=1 和 y= '正面'或者 x=1 和 y= '反面'。用更数学的术语来说,我们可以说:
这有意义吗?由于 y 的每一种情况都被考虑在内,这只是掷出 1 的概率。这叫做边际概率。
我希望现在注释清楚了。如果你还没有掌握这些数学符号,不要担心:这只是一个习惯问题💪🏼。你会发现这是一种有用的综合思维方式。
连续变量
同样的技巧可以用于连续变量,但是我们需要用积分代替求和。提醒一下,对于连续变量,变量取某个特定值的概率接近\(0\)因为有无限的可能性(参见上一篇 / 笔记本)。
例 3。
假设我们有两个变量 x 和 y 的联合概率密度函数,我们想计算一个边际概率。首先,我们需要三个维度来表示概率密度函数:变量 x 的值、变量 y 的值以及与获得这两个值相关联的概率。
例如,让我们用正态分布来表示两个变量 x 和 y。Numpy random.normal()
(参见 doc )中的函数创建一个从正态分布中提取的值的向量。第一个参数是分布的平均值,第二个是标准偏差,第三个是样本数。
例如,np.random.normal(0, 1, 1000)
创建一个长度为 1000 的向量:
np.random.seed(123)
x = np.random.normal(0, 1, 1000)
x.shape
这返回(1000,)
。
如果我们取这个向量中所有值的平均值,我们会得到一个接近 0 的值:
标准差告诉我们单个值是否或多或少偏离了平均值。
让我们创建两个连续分布:
np.random.seed(123)
x = np.random.normal(0, 1, 1000)
y = np.random.normal(0, 1, 1000)sns.distplot(x)
plt.title(‘x’)
plt.xlim(-4, 4)
plt.show()sns.distplot(y)
plt.title(‘y’)
plt.xlim(-4, 4)
plt.show()
让我们试着理解这些图到底代表了什么。我使用了 Seaborn 包中的函数distplot
。y 轴给出了变量取 x 轴给出的值的概率密度。你可以在上一篇文章 / 笔记本中找到更多关于概率密度函数的细节。简而言之,对于 x 轴的某个范围,必须计算曲线下的面积,以获得在该范围内获得值的概率。
那么,边际概率呢?如果想得到 x 的边际概率,需要得到概率密度函数的曲线下沿 y 轴的面积。您可以想象我们只从 y 轴(或该轴上的投影)看 3D 图,并获得曲线下的面积。
对于离散变量 x 和 y,我们已经看到边际概率 P(x)是 y 的每个值的概率之和。现在我们的变量是连续的,我们必须使用积分,但原理是相同的:
-为了计算边际概率 P(x),我们计算变量在 x 轴上投影的曲线下的面积。
-为了计算边际概率 P(y),我们计算变量在 y 轴上投影的曲线下的面积。
Probability density functions of two gaussian variables — source.
当我们知道联合概率分布时,这用于恢复一个变量的概率分布。
这可以用下面的等式来表示:
和
关于整合的更多解释,你可以看看这个帖子 / 笔记本。方程式末尾小 d 后面的变量表示用于积分的变量。在第一个方程中,我们对 y 积分,这意味着我们把 x 看作一个常数。我们在第二个等式中做相反的事情。
3.5 条件概率
条件概率是指给定一个事件发生另一个事件的概率。
从属和独立事件
首先,区分依赖事件和独立事件非常重要!这两种情况下的直觉都有点不同。
独立事件的例子:骰子和硬币
在这个例子中,我们做了一个扔骰子和硬币的实验。我们将调用两个随机变量来描述这些事件,x 对应于掷骰子,y 对应于掷硬币。
我们可以问的一个问题是:掷骰子得到 3,掷硬币得到 1 的概率是多少?
我们可以看到这两个事件是独立的,因为我们不期望一个事件对另一个事件有任何影响。
相关事件示例:一副牌中的两张牌
在这个例子中,我们将得到一副牌中的两张牌而不替换。当我们拿第一张牌(所有 52 张牌都在这副牌中)和拿第二张牌(现在有 51 张牌,少了一张)时,概率是不同的。这意味着事件是相关的:第一次抽奖的结果将影响第二次抽奖的概率。
我们可以问的一个问题是:当我们第一次抽中 6 时,第二次抽中 6 的概率是多少?
注释
Conditional probability.
下面介绍一些新的记法:P(y= y | x= x 描述了条件概率:是给定随机变量 x 取特定值 x 的情况下,随机变量 y 取特定值y的概率。它不同于 P(y= y ,x= x )对应的是随机变量 y 得到结果 y 和随机变量 x 得到结果 x 的概率,在条件概率的情况下,与随机变量 x 相关联的事件已经产生了它的结果( x )。
在数学上,条件概率和联合概率之间有一个方便的关系:
我们来啰嗦一下,用通俗易懂的英语把等式转换一下:
假定随机变量 x 取值 x ,随机变量 y 取值 y 的概率是两个事件发生的概率(y 取值yx 取值 x )与 x 取值 x 的概率之比。
换个方向看可能更直观:
可以这样理解:要计算两个事件发生的概率,我们得取第一个事件发生的概率(P(x=x)乘以给定第一个事件发生的情况下第二个事件发生的概率(P(y= y | x= x) )。清楚了吗?
概率倍增
这最后一个解释引出了一个问题。我们用概率乘法(P(x= x )乘以 P(y= y | x= x ))来表示多个事件发生的概率(P(y= y ,x= x )。让我们看看为什么这是有意义的。
The probability is the ratio between the number of successful outcomes over the total number of outcomes.
以两个独立的事件为例:我们投掷硬币两次(第一次对应于第一个事件,第二次对应于第二个事件),我们希望计算得到两个“正面”的概率。我们知道,每次试验得到“正面”的概率是 1/2。
为了理解为什么必须使用概率乘法,我们需要理解每个事件的概率是多少。先来关注第一个事件,第一次抛硬币。概率 1/2:1 对应于“成功”结果的数量(即得到一个“头”)。分母(2)对应于可能性的总数。可能的结果是“正面”或“反面”,所以有两种结果。这就导致了我们的概率 1/2。
如果我们考虑这两个事件,这是所有可能的结果:
- 头和头
- 正面和反面
- “反面”和“正面”
- “尾巴”和“尾巴”
我们仍然有 1 个成功结果(“正面”和“正面”),并且有 4 个可能的结果。因此,得到“正面”和“正面”的概率是 1/4。
诀窍就在这里。要得到可能结果的总数,我们只需将每个事件的结果数相乘。在这种情况下是 2 * 2。如果我们将事件概率相乘,我们得到:1/2 * 1/2 = 1/4。
为了确保条件概率非常清楚,我们将举一个独立和相关事件的例子。此外,独立概念的更多细节将在 3.7 中解释。
我们将从独立事件的情况开始。
例 4。
首先,让我们回顾一下我们需要的所有数学符号。P(x= x )是变量 x 取状态 x 的概率。例如,P(x=3)对应于在骰子上掷出 3 的概率。同理,P(y= y )是随机变量 y 取值 y 的概率。例如,P(y='heads ')对应于得到' head '的概率。
P(y= y ,x= x )是这些事件的联合概率。例如,P(x=3,y=“正面”)是在骰子上掷出 3 并在硬币上得到“正面”的概率。对于这个例子,假设我们知道 P(x=3,y='heads')=1/12。
P(y= y | x= x )对应于给定 x= x 时 y= y 的概率。因此,这是一个条件概率。例如,P(y= '正面' | x=3)对应于我们已经在骰子上掷出 3 的情况下得到正面的概率。
注意 P(y='heads' | x=3) = P(y='heads '),因为这些事件是独立的。这意味着 x 的概率对于 y 的任何结果都是一样的。
在我们的示例中,我们有:
我们可以看到确实 P(y = ' heads ' | x = 3)= P(y = ' heads ')= 0.5。
我们将用一个依赖事件的例子来结束这篇文章。
例子
在这个例子中,我们抽取两张没有替换的卡片。第一步是运用我们所学的知识,用数学符号写出问题。我们称 x 为对应于第一次抽取的变量,y 为对应于第二次抽取的变量。随机变量 x 和 y 都可以取值 1、2、3、4、5 或 6。这些是变量的可能结果。
我们已经看到,计算条件概率的一般公式是:
假设我们在第一次抽牌时抽了 6,我们想知道在第二次抽牌时抽 6 的概率。我们可以这样写:P(y=6 | x=6)。
我们需要:
-第一次抽中 6 的概率(P(x=6))
-在第一次和第二次中均抽到 6 的概率(P(y=6,x=6))
在第一次抽牌时,抽到 6 的概率是 4/52(52 张牌中有 4 张 6),所以 P(x=6)=4/52。抽对 6 的概率是:
我们要计算的条件概率是:
这意味着,一旦我们已经拿到了一张 6,我们有 13 次机会(几乎是 6%)拿到 6。我们可以注意到它对应的是 3/51(更多细节在下一章)。
结论
我们已经看到,边际概率是指在多个事件的实验中,单个事件发生的概率。在这些边际概率和表示两个事件发生的概率的联合概率之间存在关系。
我们也谈到了条件概率。它对应于特定条件下的概率,例如,在一副牌中得到一个 6 的概率,知道我们已经得到一个 6 并且没有替换它。我们研究了非独立事件和独立事件的情况。
我希望这篇文章能帮助你使用和阅读这些概念背后的数学符号。
2020 年你应该读的深度学习书籍
原文:https://towardsdatascience.com/deep-learning-books-you-should-read-in-2020-7806048c1dc5?source=collection_archive---------11-----------------------
现在关于深度学习最好的书是什么?
随着机器学习和数据科学的兴起,它们被应用到每一个地方,并改变着每一个行业,难怪机器学习方面的专家会获得丰厚的报酬和很多关注。如果你已经读过几本数据科学和机器学习书籍,那么是时候关注深度学习了:神经网络、Keras、Tensorflow、Scikit-learn 等。
Deep Learning books to read in 2020
入门水平
如果你刚刚进入机器学习领域,有一本书是我不能不推荐的。简直太棒了!
用 Python 介绍机器学习是机器学习和深度学习的顺利入门。它没有假设任何关于编码和 Python 的知识,它介绍了机器学习的基本概念和应用,通过例子讨论了各种方法。那是我见过的最适合入门级深度学习工程师的书。
中间能级
如果你已经完成了几个机器学习项目,你对 Keras 或 Tensorflow 有所了解,你使用过 scikit-learn,那么我有两条建议给你。
使用 Scikit-Learn 和 TensorFlow 的动手机器学习涵盖了深度学习的所有基础知识,工作代码和充满色彩的惊人可视化。读起来真的很有趣,它是一个完整的 400+页的指南,通过分类,聚类,神经网络和其他方法,有很多例子可以自己尝试。
使用 Python 进行深度学习就是使用 Keras 作为深度学习的主要框架。Keras 的创建者 Francois Chollet 对这种易于使用且高效的框架做了很好的概述。从 MNIST 到 CNN,从计算机视觉到 NLP。都在一个地方,以简洁的形式给出。
深度学习和围棋游戏的目标是使用围棋作为指导示例,向您教授神经网络和强化学习。在这本书的过程中,你将学习如何创建你自己的机器人/代理人来玩这个游戏,这非常棒。
专家级
如果你对深度学习很认真,深度学习是必读书。它没有给出代码,假设您在这个阶段能够自己编写所有代码,但是它给出了为什么某些层工作得更好、如何优化超参数、使用什么网络架构等等的解释。它给出了深度学习的最新描述。
机器学习:概率视角是关于机器学习的数学视角。很难阅读,但当你建立深度学习模型时,对于你可能遇到的任何数学问题来说,这是一个很好的参考。作为百科全书式的参考资料,它非常有用。仅供专家使用。
如果您想要更多书籍推荐,请参阅以下列表:
- 人工智能书籍
- 数据科学书籍
- 机器学习书籍
- 启动书
[## 加入我的深度学习时事通讯
让我们保持联系。每周或双周电子邮件。](https://creative-producer-9423.ck.page/c3b56f080d) 
Data Science Job
最后,如果你想了解成为一名数据科学家意味着什么,那么看看我的书数据科学工作:如何成为一名数据科学家,它将指导你完成这个过程。
深度学习:如何使用 CNN 构建狗检测器和品种分类器?!
原文:https://towardsdatascience.com/deep-learning-build-a-dog-detector-and-breed-classifier-using-cnn-f6ea2e5d954a?source=collection_archive---------4-----------------------
这项工作是 Udacity 的数据科学顶点项目的一部分。
概述:
你可能会认为在图像中识别狗的品种对你来说是一件容易的事情。你是对的!找到具有最小类间差异的犬种配对可能并不困难,例如,卷毛寻回犬和美国水猎犬。
但是,这两个呢?!
哼,没那么容易!
在最近十年,使用深度学习技术和几行 python 代码来区分图像中的狗品种要容易得多。在这篇博客中,我将带你从头开始创建卷积神经网络(CNN ),并利用 ImageNet 上最新的图像分类技术。这个模型可以作为现实世界和用户提供的图像的移动或 web 应用程序的一部分。给模型一个图像,它确定是否有狗,并返回估计的品种。如果图像是人类,它将返回最相似的狗品种。你可以在我的 GitHub repo 里找到代码。
人体探测器
我使用 OpenCV 的实现的基于 Haar 特征的级联对象分类器来检测人脸。级联函数是一种基于机器学习的方法,在许多带有正面(有人脸)和负面(没有任何人脸)标签的图像上进行训练。detectMultiScale 获取所有面的坐标,然后将它们作为矩形列表返回。但是不要忘记在使用之前将 RGB 图像转换成灰度。
下面的 face_detector 函数计算照片中有多少张人脸:
def face_detector(img_path):
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray)
return len(faces) > 0
人脸检测器的性能在 100 个人和狗的图像样本上进行评估。这个检测器从人类数据中识别所有的人脸,但是在狗数据集上表现不佳。它有大约 11%的假阳性。
狗探测器
是时候使用另一个在狗数据集上表现更好的检测器了。我在 Keras 的 ImageNet 上使用了预训练的 ResNet50 权重,该权重在包含 1000 个标签的超过 1000 万张图像上进行训练。
在下面的代码中,paths_to_tensor 获取图像的路径,并返回一个可用于 ResNet50 的 4D 张量。但是,Keras 中的所有预训练模型都需要额外的处理,如归一化,这可以通过使用 preprocess_input 来完成。如果在存储于 img_path 的图像中检测到狗,dog_detector 函数返回“True”。
from keras.preprocessing import image
from tqdm import tqdm
from keras.applications.resnet50 import preprocess_input, decode_predictionsdef path_to_tensor(img_path):
img = image.load_img(img_path, target_size=(224, 224)
return np.expand_dims(x, axis=0)def paths_to_tensor(img_paths):
list_of_tensors = [path_to_tensor(img_path) for img_path in tqdm(img_paths)]
return np.vstack(list_of_tensors)def ResNet50_predict_labels(img_path):
img = preprocess_input(path_to_tensor(img_path))
return np.argmax(ResNet50_model.predict(img))def dog_detector(img_path):
prediction = ResNet50_predict_labels(img_path)
return ((prediction <= 268) & (prediction >= 151))
为了评估狗检测器,我检查了 ImageNet 上 RestNet50 的预测类别是否属于狗品种类别。狗检测器表现良好,没有任何假阴性。
既然我们在图像中认出了狗,那么是时候预测狗的品种了。但首先我们应该更详细地分析训练数据集:
数据集
该数据集共有 133 个不同品种的 8,351 幅图像。可供模型学习的图像数量大约是每种 62 张,这对于 CNN 来说可能还不够。在这个现实世界的设置中,图像有不同的分辨率,大小,照明条件,也有一些图像有一只以上的狗。通过比较相同标签图像的像素强度分布,我注意到,例如,American_staffordshire_terrier 的照片在对比度、大小和亮度方面有所不同。这两幅图像中的红色、绿色和蓝色通道的强度值分布不同。数据的这种变化使得给狗分配品种的任务变得更加具有挑战性。
训练数据中品种标签的分布显示数据略有不平衡,平均每类 53 个样本。大多数品种在训练、有效和测试数据集中具有几乎相同的分布。
此外,作为数据处理的一部分,我通过将每个图像中的每个像素除以 255 来对图像进行去标度。
指标
由于我们在这里处理的是一个多分类问题,并且数据略有不平衡,所以我使用了准确性评估度量和分类交叉熵成本函数。但是,首先,标签必须是分类格式。目标文件是与这种格式的图像相关的编码狗标签列表。如果预测的概率导致与实际不同的标签并导致更高的准确性,则这种多类对数损失会惩罚分类器。一个完美的分类器的损失为零,准确率为 100%。
对狗的品种进行分类
这里我用 Relu 激活功能在 Keras 中创建了一个 4 层 CNN。该模型从 224 2243 个颜色通道的输入图像开始。这个输入图像很大但很浅,只有 R、G 和 b。卷积层通过减少宽度和高度来挤压图像,同时逐层增加深度。通过添加更多的过滤器,网络可以学习照片中更重要的特征,并更好地进行归纳。
我的第一层产生 16 个特征通道的输出,作为下一层的输入。过滤器是 16 个方阵的集合,输出特征图是输入特征和内核的加权和。在训练过程中,通过 ImageNet 数据计算内核的权重,它所做的是滑过输入特征映射并产生输出特征。因此,输出特征的形状取决于内核和输入特征的大小。
查看本页可以更好地理解 CNN 是如何工作的。
我认为输入和输出特征具有相同的大小是最理想的。所以,我决定使用相同的填充去图像的边缘,所有的层都用零填充,步幅为 2。我还使用了 max-pooling 操作来确保我不会丢失图片中的信息,同时降低过度拟合的可能性。最大池取一个位置周围的最大像素。经过四个卷积层和最大池,然后是两个完全连接的层,我训练了分类器。卷积层提取图像特征,分类器根据之前获得的特征进行分类。下图显示了顶部的特征块序列和分类器如何从原始图像传输信息并预测所需的目标值。
CNN 的模型架构是:
from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D
from keras.layers import Dropout, Flatten, Dense
from keras.models import Sequential# Model Architecture
model = Sequential()model.add(Conv2D(filters=16, kernel_size=2, padding='same', activation='relu', input_shape=(224,224,3)))
model.add(MaxPooling2D(pool_size=2)) model.add(Conv2D(filters=32, kernel_size=2 , padding='same' , activation='relu'))
model.add(MaxPooling2D(pool_size=2))model.add(Conv2D(filters=64 , kernel_size=2 , padding='same' , activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Dropout(0.4))model.add(Conv2D(filters=128 , kernel_size=2 , padding='same' , activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Dropout(0.4))model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.4))
model.add(Dense(133,activation='softmax'))model.summary()
由于没有足够的图像数据来训练模型,从头开始创建的模型表现不佳,精度为 12%。一个潜在的改进是数据扩充,以添加更多的数据。该策略通过随机填充、裁剪和旋转图像来修改图像。它还使模型能够更好地概括,而不会过度拟合,当然,使用适当的参数。
正如前面提到的,在这样的小数据上训练从头制作的 CNN 分类器会导致欠拟合,并且有这么多层,参数调整经常会导致过拟合。因此,是时候利用迁移学习预训练网络来创建 CNN 品种分类器了,尽管这些模型并不是为这项任务而明确创建的。但是这些网络的一个优点是,它们是在大数据集上训练的,ImageNet 有数百万张带标签的图像,并且达到了 90%的准确率。此外,它们可以推广到 ImageNet 之外的其他图像。
我在 Keras 中实现了预训练的模型,如 VGG、Inception V3 和 ResNet,并比较了它们的准确性。我将它们用作固定的特征提取器,并通过使用随机梯度下降、0.001 的学习率和内斯特罗夫动量最小化交叉熵损失函数来微调全连接层。同样,最后一个完全连接的层被更改为狗的品种数,133。然后,每个模型被训练 25 个时期,每批 20 个样本。
# model Architecture
Xception_model = Sequential()
Xception_model.add(GlobalAveragePooling2D(input_shape=(train_Xception.shape[1:])))
Xception_model.add(Dense(133, activation='softmax'))checkpointer = ModelCheckpoint(filepath='saved_models/weights.best.Xception.hdf5', verbose = 0, save_best_only=True)sgd = SGD(lr= 1e-3 , decay=1e-6, momentum=0.9 , nesterov = True)# compile the model
Xception_model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])# Training the model
Xception_model.fit(train_Xception , train_targets,
validation_data = (valid_Xception, valid_targets),
shuffle = True,
batch_size = 20,
epochs = 25,
verbose = 1)
Xception 模型优于所有其他模型,准确率为 86%,测试数据损失为 0.4723。总的来说,基于盗梦空间的模型在 ImageNet 上略胜 VGG 和雷斯网;此外,它的计算效率更高。可以通过应用更合适的微调技术来提高模型性能。例如,训练与特定狗特征相关的几个顶层,并冻结检测更一般特征的其他层。因为它们已经在 ImageNet 权重中被捕获。
结果
现在,是时候将检测器和异常预测繁殖结合起来,并在不同大小和分辨率的几幅图像上测试它们了。如前所述,准确性被选为该分类器的模型评估指标。该代码获取一个图像路径,首先确定图像是狗、人还是两者都不是,然后返回预测的相似品种:
def Xception_predict_breed (img_path):
bottleneck_feature = extract_Xception(path_to_tensor(img_path))
predicted_vector = Xception_model.predict(bottleneck_feature)
return dog_names[np.argmax(predicted_vector)]def display_img(img_path):
img = cv2.imread(img_path)
cv_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
imgplot = plt.imshow(cv_rgb)
return imgplotdef breed_identifier(img_path):
display_img(img_path)
prediction = Xception_predict_breed(img_path)
if dog_detector(img_path) == True:
print('picture is a dog')
return print (f"This dog is a {prediction}\n")
if face_detector(img_path) == True:
print('picture is a human')
return print (f"This person looks like a {prediction}\n")
else:
return print('The picture is neither dog nor human')
结果表明,该模型运行良好。例如,它可以在测试数据中预测 American_staffordshire_terrier,同时对不同亮度、大小和缩放级别的图像进行训练。
下面是在人类图像上的结果:
测试数据预测的混淆矩阵如下所示。但是,很难想象哪些品种被错误分类。
为了更好地理解错误分类的情况,我将预测值和实际值配对。该模型无法在大白熊和库瓦斯之间进行分类,这两种动物都是白色、体型大且毛茸茸的。它也分不清獒和牛獒,后者是牛头犬和獒的混种。通过添加更多的数据,该模型将能够学习更多的具体特征,并区分这些相似的品种,这甚至让人类感到困惑。
潜在的改进
由于模型存在轻微的不平衡,可以通过数据扩充和增加更多的训练标记数据来提高模型的精度。随着获取更多数据,Convnet 模型将更有能力从图像中学习更多相关和特定的狗特征。但是,它需要大量的时间和内存使用。另一种提高模型准确性的可能方法是对几个网络的预测进行平均,以获得最终的预测,称为集成技术。正如我之前提到的,一个改进可以是应用更合适的微调策略来根据数据调整权重。此外,对最终模型的正确分析是给图像添加一些噪声,并观察它的表现。
结论
在这项工作中,我实现了 haar 级联分类器和 ResNet50 预训练的权重来检测人脸和狗。我还花了一些时间探索数据,以找到图像特征,这有助于我应用更合适的技术。对于犬种分类,我已经开始使用一些卷积层数作为基线网络。该模型的表现比随机猜测要好,133 分之一,但仍然不足。
在给定的时间和内存能力下,我决定利用几个迁移学习架构来增强 CNN 的性能,这导致了显著的改进。我使用预先训练的模型作为固定特征提取器,并改变了全局平均池层、完全连接层,并应用了其他微调方法。Xception 和 ResNet50 产生了比其他更高的准确率,大约 86%。由于混合品种之间存在一些相似性,这类数据集非常复杂,因此要获得更高的准确性是非常具有挑战性的。
最后,我在不同强度分布的相同标记照片上测试了该模型,它的性能相当好。
这个项目最令人兴奋的部分是现代通信网络如何通过几行代码让我们轻松完成甚至人类都觉得具有挑战性的任务。但是在给定的时间和记忆能力下,很难对模型进行改进。我计划探索上述的改进方法,并将更新这个博客以获得更好的结果。
如果你觉得有趣,请随意使用我的代码。
深度学习、计算机视觉和自动光学检测
原文:https://towardsdatascience.com/deep-learning-computer-vision-and-automated-optical-inspection-774e8ca529d3?source=collection_archive---------10-----------------------
热轧带钢表面缺陷分类实例研究
自动光学检测常用于电子工业和制造业,在生产过程中检测产品或部件的缺陷。从概念上讲,图像分类、对象检测和语义分割的深度学习中的常见实践都可以应用于自动光学检查。图 1 显示了图像识别中的一些常见任务,图 2 显示了钢零件表面缺陷的一些示例,以供交叉参考。
Figure 1. Different tasks in image recognition. [source]
Figure 2. NEU Surface Defect Dataset: Image Classification (left) and Object Detection (right). [source]
本文介绍了深度学习在热轧带钢表面缺陷图像分类中的应用研究。这篇文章的其余部分组织如下。首先,我们将讨论数据和任务。其次,我们将讨论三种用于评估的深度学习模型:基线模型、InceptionV3 和 MobileNet。最后,我们将介绍实验,然后评估结果。
NEU 表面缺陷数据库
NEU 表面缺陷数据库 收集了六种典型的热轧带钢表面缺陷。该数据集由 1800 张 200x200 的灰度图像组成,均匀标记在 6 个类别上,即滚入比例、补丁、龟裂、麻面、内含物和划痕。图 3 显示了数据库中的示例图像。
Figure 3. Sample images in NEU Surface Defect Database. [source]
我们在这里的任务是探索这种多类分类问题的深度学习模型。注意,根据数据库的来源,该数据集对图像分类提出了两个困难的挑战,即类内变异和类间相似度:
- 类内变异,即同一类中可能出现不同的模式。例如划痕(图 3 最后一栏)的类别包括水平划痕、垂直划痕、倾斜划痕等。此外,由于照明和材料变化的影响,类内缺陷图像的灰度是变化的。
- 类间相似度,即相似的方面可能出现在不同的类下。例如,滚入比例、龟裂和麻面中的一些图像可能看起来很像。
虽然类内变异和类间相似性已经在不同的应用中得到解决,但在这种情况下,这些问题肯定会成为一个问题。
模型选择和微调
Keras 2.2.2(以 Tensorflow 1.10.0 为后端)实现了三个深度学习模型进行评估:
- 一个简单的卷积神经网络作为基线模型 : 3 个Conv2D/MaxPooling2D对作为特征提取器,3 个密集层作为分类器;(图 4)
- InceptionV3 : Keras 应用 InceptionV3 使用 1 个globalaveragepool2d层和 2 个 Dense 层对分类器进行微调;(图 5)
- MobileNet : Keras 应用 MobileNet 使用 1 个globalaveragepooli2d层和 2 个 Dense 层对分类器进行微调;(图 6)
更多关于数据处理和模型训练的共同工程决策:
- 没有数据增强;
- 培训/验证分成 90/10;
- 没有预先训练的重量;
- 20 个时期没有提前停止;
Figure 4. simple convolutional neural network.
Figure 5. InceptionV3 Fine-Tuning.
Figure 6. MobileNet Fine-Tuning.
实验和评估
- 图 7 简单卷积神经网络(基线):验证准确率高达 52.78%;
- 图 8 InceptionV3 微调:验证准确率高达 98.89%。这个模型似乎在 14 个时代后过度拟合;
- 图 9 MobileNet 微调:验证准确率高达 100.00%。该模型在时期 4 达到 99.44%,然后在时期 10 和时期 14 达到 100.00%。(好得不像真的?!查看这里的完整日志
Figure 7. training/validation history of the simple convolutional neural network.
Figure 8. training/validation history of InceptionV3 Fine-Tuning.
Figure 9. training/validation history of MobileNet Fine-Tuning.
结论
本文对热轧带钢表面缺陷的分类进行了研究。为自动光学检测实施缺陷分类解决方案实际上类似于在图像分类的深度学习中进行常见实践。显然,知道如何对 MNIST 数据集进行分类并从 Keras 应用程序中导入/调整模型的人应该能够完成这项工作。然而,我仍然想写下这个帖子,原因有几个。
- 虽然自动光学检测在工业中非常重要,但是自动光学检测的公共数据集相对较少,因为大多数拥有这些数据的公司可能不想公开这些数据。因此,研究人员和从业人员可能缺乏数据集和调查基准。NEU 表面缺陷数据集为图像分类和目标检测提供数据,这无疑是一个很好的实践设置。
- 一般来说,自动光学检测数据集的大小小于教科书数据集(如 MNIST 或 CIFAR)和流行数据集(如 ImageNet 或 COCO)。)在NEU 表面缺陷数据集的情况下,每类只有 300 幅图像用于训练和验证。此外,由于要考虑类内差异、类间相似性和受检产品/组件/材料的性质,正确应用数据扩充可能是一个挑战。
- 一些深度学习模型适用于自动光学检查的任务,但一些模型可能不是好的选择。然而,模型选择和微调没有金科玉律。使用从 ImageNet 学习的权重进行迁移学习(或者应该使用多少预先训练的权重)是否可以帮助我们执行自动光学检测的任务,这是事先未知的。
最后评论:如果读者想知道深度学习方法和机器学习方法在这项任务中的区别,请查看英特尔人工智能学院下的这篇博客。
感谢阅读。如果您有任何意见或问题,请随时留言。
深度学习的可解释性:来自物理学的提示
原文:https://towardsdatascience.com/deep-learning-explainability-hints-from-physics-2f316dc07727?source=collection_archive---------7-----------------------
Image by Ralf Kunze from Pixabay.
内部 AI
从物理学角度看深层神经网络
如今,人工智能几乎存在于我们生活的每一个部分。智能手机、社交媒体、推荐引擎、在线广告网络和导航工具是基于人工智能的应用的一些例子,它们已经影响到我们的日常生活。在诸如语音识别、自动驾驶、机器翻译、视觉对象识别等领域的深度学习已经系统地提高了艺术水平有一段时间了。
然而,使深度神经网络(DNN)如此强大的原因仅仅是启发式地 [理解](https://arxiv.org/pdf/1608.08225.pdf),即我们仅从经验中知道,我们可以通过使用大型数据集并遵循特定的训练协议来实现出色的结果。最近,有人提出了一种可能的解释,这种解释基于一种基于物理学的概念框架,称为重整化群 (RG)和一种被称为受限玻尔兹曼机器 (RBM)的神经网络之间的显著相似性。
RG 和 RBMs 作为粗粒化过程
重正化是一种用于研究物理系统在微观部分信息不可用时的行为的技术。这是一种“粗粒化”的方法,它展示了当我们缩小并检查不同长度尺度的物体时,物理规律是如何变化的,“戴上模糊的眼镜”。
When we change the length scale with which we observe a physical system (when we “zoom in”), our theories “navigate the space” of all possible theories (source).
RG 理论的巨大重要性来自于它提供了一个强有力的框架,从本质上解释了为什么物理学本身是可能的。
To describe the motion of complex structures such as satellites, one does not need to take into account the motions of all its constituents. Picture by 3Dsculptor/Shutterstock.com.
RG 理论提供了一个强有力的框架来解释为什么物理学本身是可能的。
例如,要计算绕地球运行的卫星的轨道,我们只需要运用牛顿运动定律。我们不需要考虑卫星微观成分极其复杂的行为来解释它的运动。我们在实践中所做的是对系统基本组件(在这种情况下是卫星)的详细行为进行某种“平均”。RG 理论解释了为什么这个过程如此有效。
此外,RG 理论似乎表明,我们目前关于物理世界的所有理论都只是一些未知的“真实理论的近似(用更专业的术语来说,这种真实理论“生活”在物理学家所谓的标度变换的固定点附近)。
RG 理论似乎表明,我们目前关于物理世界的所有理论都只是一些未知的“真实理论”的近似。
当被研究的系统处于临界点时,RG 工作良好,并表现出自相似性。一个自相似系统在它被观察的任何长度尺度下都是"完全或近似地类似于它自身的一部分。显示自相似性的系统的例子有分形。
Wikipedia animation showing the Mandelbrot set and we zoom in (source).
处于临界点的系统在相距甚远的部分之间表现出很强的相关性。所有的子部分影响整个系统,系统的物理性质变得完全独立于其微观结构。
人工神经网络也可以被视为一个粗粒度的迭代过程。人工神经网络由几个层组成,如下图所示,早期的层仅从输入数据中学习较低级别的特征(如边缘和颜色),而较深的层将这些较低级别的特征(由早期的特征提供)组合成较高级别的特征。用 Geoffrey Hinton 的话来说,深度学习社区的领军人物之一:“你首先学习简单的特性,然后在此基础上学习更复杂的特性,这是分阶段进行的。”此外,与 RG 工艺的情况一样,更深的层只保留被认为相关的特征,不强调不相关的特征。
Convolutional neural network (CNN). The complexity level of the forms recognized by the CNN is higher in later layers (source).
确切的联系
物理学和机器学习都处理具有许多成分的系统。物理学研究包含许多(相互作用的)物体的系统。机器学习研究包含大量维度的复杂数据。此外,类似于物理学中的 RG,神经网络设法对数据进行分类,例如动物的图片,而不管它们的组成部分(例如大小和颜色)。
在 2014 年发表的一篇文章中, Pankaj Mehta 和 David Schwab 两位物理学家基于重整化群理论对深度学习的性能进行了解释。他们表明 dnn 是如此强大的特征提取器,因为它们可以有效地“模仿”粗粒化过程,这是 RG 过程的特征。用他们的话说“DNN 架构[……]可以被视为一种迭代的粗粒度方案,其中神经网络的每个新的高级层从数据中学习越来越抽象的高级特征”。事实上,在他们的论文中,他们设法证明了在 RG 和受限玻尔兹曼机器 (RBM)之间确实有一个精确的映射,这是一个构成 DNN 积木的双层神经网络。
From the 2014 paper by Mehta and Schwab where they introduced the map between RG and DNNs built by stacking RBMs. More details are provided in the remaining sections of the present article (source).
文献中还有许多其他工作将重正化和深度学习联系在一起,遵循不同的策略,具有不同的目标。尤其是基于信息瓶颈方法的 Naftali Tishby 及其合作者的工作引人入胜。另外, Mehta 和 Schwab 只解释了一种神经网络的图谱,后续的工作已经存在。然而,为了简洁起见,我在这里将重点放在他们的原始论文上,因为他们的见解导致了该主题的大量相关后续工作。
在给出这种关系的一个相对详细的描述之前(参见这篇文章中一个很好的,虽然不太专业的描述),我将提供一些 RG 理论和 RBM 的一些事实。
重整化群理论:鸟瞰
如上所述,重正化包括将粗粒化技术应用于物理系统。RG 理论是一个通用的概念框架,因此人们需要方法来操作这些概念。变分重整化群(VRG)就是这样一种方案,由 Kadanoff,Houghton 和 Yalabik 于 1976 年提出。
为了阐述清楚,我选择集中在一个特定类型的系统来说明 RG 是如何工作的,即量子自旋系统,而不是进行全面的概括。但在钻研数学机械之前,我要给出一个“手挥动”的解释自旋在物理学中的意义。
物理学中的自旋概念
在物理学中,自旋可以被定义为“基本粒子、复合粒子和原子核所携带的角动量的一种内在形式。”尽管根据定义,自旋是一个没有经典对应物的量子力学概念,但具有自旋的粒子通常(尽管不正确)被描述为围绕自身轴旋转的小陀螺。自旋与磁现象密切相关。
The particle spin (black arrow) and its associated magnetic field lines (source).
重整化的数学
让我们考虑一个由 N 个自旋组成的系统或系综。出于可视化的目的,假设它们可以放在一个网格上,如下图所示。
A 2-dimensional lattice of spins (represented by the little arrows). The spheres are charged atoms (source).
因为自旋可以向上或向下,所以它们与二进制变量相关联
索引 i 可以用来标记晶格中自旋的位置。为了方便起见,我将用矢量 v. 来表示自旋的构型
对于处于热平衡的系统,与自旋组态 v 相关的概率分布具有以下形式:
这就是无处不在的玻尔兹曼分布(为方便起见,温度设为 1)。物体H(v)就是系统所谓的哈密顿量,其中可以定义为“系统中所有粒子的动能[和]势能之和对应的算符”。分母 Z 是一个归一化因子,称为配分函数
系统的哈密顿量可以表示为对应于自旋之间相互作用的项的总和:
该组参数
被称为耦合常数,它们决定了自旋之间(第二项)或自旋和外部磁场之间(第一项)的相互作用强度。
我们需要考虑的另一个重要的量是自由能。自由能是一个最初来自热力学的概念,在热力学中,自由能被定义为物理系统中可以被转换来做功的能量。数学上,在我们的情况下,它由下式给出:
符号“tr”代表迹(来自线性代数)。在本上下文中,它表示可见自旋 v 的所有可能配置的总和。
在重正化过程的每一步,系统在小尺度下的行为被平均化。粗粒度系统的哈密顿量用新的耦合常数表示
并且获得新的粗粒度变量。在我们的例子中,后者是块自旋 h 而新的哈密顿量是:
为了更好地理解什么是块自旋,考虑下面的二维晶格。每个箭头代表一次旋转。现在把晶格分成正方形块,每块包含 2×2 个自旋。块旋转是对应于这些块中的每一个的平均旋转。
In block spin RG, the system is coarse-grained into new block variables describing the effective behavior of spin blocks (source).
注意,新的哈密顿量与原来的哈密顿量具有相同的结构,只是用自旋的块的配置代替了物理自旋。
Both Hamiltonians have the same structure but with different variables and couplings.
换句话说,模型的形式不会改变,但是当我们缩小时,模型的参数会改变。通过系统地重复这些步骤,可以获得理论的完全重正化。在几次 RG 迭代之后,一些参数将被丢弃,一些将被保留。剩下的被称为相关运营商。
这些哈密顿量之间的联系是通过自由能(上面描述的几行)在 RG 变换后不变的要求获得的。
变分重整化群(VRG)
如上所述,为了实现 RG 映射,可以使用变分重整化群(VRG)方案。在这个方案中,映射是由一个操作符实现的
其中 λ 是一组参数。该算子对隐藏自旋和输入(可见)自旋之间的耦合进行编码,并满足以下关系:
其定义了上面给出的新的哈密顿量。尽管在精确的 RG 变换中,粗粒度系统将具有与原始系统完全相同的自由能,即
这相当于以下条件
在实践中,这个条件不能完全满足,变分方案被用来寻找使自由能之间的差异最小化的 λ
或者等效地,近似精确的 RG 变换。
成果管理制概述
我已经在以前的文章中详细描述了受限玻尔兹曼机器的内部工作原理。这里我将提供一个更简洁的解释。
[## 神经量子态
神经网络如何解决量子力学中高度复杂的问题
towardsdatascience.com](/neural-quantum-states-4793fdf67b13)
受限玻尔兹曼机器(RBM)是生成式的,基于能量的模型。用于非线性无监督特征学习。它们最简单的版本只包含两层:
- 一层可见单元,用 v 表示
- 一个隐藏层,单位用 h 表示
Illustration of a simple Restricted Boltzmann Machine (source).
我将再次考虑一个二进制可见数据集 v 以及从一些概率分布中提取的 n 元素
Eq. 9: Probability distribution of the input or visible data.
RBM 中的隐藏单元(由矢量 h 表示)耦合到可见单元,其相互作用能量由下式给出
能量子指标 λ 代表变分参数的集合{ c , b,W } 。 其中前两个元素是矢量,第三个是矩阵。RBMs 的目标是输出一个依赖于 λ- 的概率分布,它尽可能接近输入数据P(v)的分布。
与配置( v , h )和参数 λ 相关的概率是该能量泛函的函数:
根据这个联合概率,通过对隐藏单元求和,可以容易地获得可见单元的变分(边缘化)分布。同样,隐藏单元的边缘化分布通过对可见单元求和来获得:
我们可以将 RBM 哈密顿量定义如下:
可以选择 λ 参数来优化所谓的 Kullback-Leibler (KL)散度或相对熵,其测量两个概率分布的不同程度。在目前的情况下,我们感兴趣的是真实数据分布和 RBM 产生的可见单位的变化分布之间的 KL 散度。更具体地说:
当两个分布相同时:
准确映射 RG 和 RBM
Mehta 和 Schwab 表明,为了建立 RG 和 RBMs 之间的精确映射,可以为变分算子选择以下表达式:
回想一下,哈密顿量 H ( v )包含编码在其中的输入数据的概率分布。通过这种变分算子的选择,可以快速证明隐藏层上的 RG 哈密顿量和 RBM 哈密顿量是相同的:
此外,当可以实现精确的 RG 变换时,真实的和变分的哈密顿量是相同的:
于是我们看到,具有自旋 v 和的重整化群的一步——块自旋可以精确地映射成由可见单元 v 和隐藏单元构成的双层 RBM。**
随着我们堆叠越来越多的 RBM 层,我们实际上正在执行越来越多轮的 RG 转换。
伊辛模型的应用
根据这个原理,我们得出结论,RBMs,一种无监督的深度学习算法,实现了变分 RG 过程。这是一个非凡的对应,梅塔和施瓦布通过在一个广为人知的伊辛自旋模型上实现堆叠 RBM 来展示他们的想法。他们将从伊辛模型中取样的自旋组态作为输入数据输入到 DNN 中。他们的结果表明,值得注意的是,DNNs 似乎正在执行(Kadanoff) 块自旋重正化。
用作者的话说,“令人惊讶的是,这种局部块自旋结构从训练过程中出现,表明 DNN 正在自组织实施块自旋重整化……我对我们感到震惊的是,你不用手动输入,它就会学习”。
他们的结果表明,值得注意的是,DNNs 似乎正在执行块自旋重正化。
在他们的论文、和的下图中,展示了 DNN 的建筑。在 B 中,学习参数 W 被绘制以显示隐藏和可见单元之间的交互。在 D 中,当我们沿着 DNN 层移动时,我们看到了块自旋的逐渐形成(图中的斑点)。在 E 中,显示了再现三个数据样本宏观结构的 RBM 重建。
Deep neural networks applied to the 2D Ising model. See the main text for a detailed description of each of the figures (source).
结论和展望
2014 年 Mehta 和 Schwab 表明,一种受限玻尔兹曼机器(RBM),一种神经网络,与重正化群有关,重正化群是一个最初来自物理学的概念。在本文中,我回顾了他们的部分分析。正如之前所认识到的,RG 和深度神经网络都具有显著的“哲学相似性”:都将复杂的系统提取为相关的部分。这种 RG-RBM 映射是这种相似性的一种形式化。
由于深度学习和生物学习过程有许多相似之处,因此假设我们的大脑也可能使用某种“类固醇上的重整化”来理解我们感知的现实并不算过分。
正如其中一位作者建议的那样,“也许对于如何从数据中挑选出相关的特征有一些普遍的逻辑,我会说这是一个暗示,也许有类似的东西存在。”
假设我们的大脑也可能使用某种“类固醇上的重整化”来理解我们感知的现实,这并不是太夸张。
这方面的问题是,与 RG 工作良好的自相似系统(具有类似分形的行为)相比,自然界中的系统通常不是自相似的。正如神经科学家 Terrence Sejnowski 所指出的,突破这一限制的一种可能方式是,如果我们的大脑以某种方式在临界点运行,所有神经元都影响整个网络。但是那是另一篇文章的主题!
感谢您的阅读,再见!一如既往,我们随时欢迎建设性的批评和反馈!
我的 Github 和个人网站 www.marcotavora.me 有(希望)一些关于数据科学和物理学的其他有趣的东西。
阿拉伯语词性标注的深度学习
原文:https://towardsdatascience.com/deep-learning-for-arabic-part-of-speech-tagging-810be7278353?source=collection_archive---------21-----------------------
用 LSTM 和 Keras 构建 postagger 的一种简单方法
Pixabay
介绍
在本帖中,我将解释 长短期记忆网络 (又名。【LSTM】)以及如何将其用于中解决 序列建模任务 同时建立基于 通用依存树库 的阿拉伯语词性标注器。本文是构建用于阿拉伯语自然语言处理的 python 包系列文章的一部分。你可以点击查看之前的帖子。
问题
语境无知
处理文本数据时,文本的上下文很重要,不能忽略。事实上,单词根据上下文有不同的意思。如果我们看看机器翻译的任务。上下文在这里很重要,而传统方法会忽略它。
如果我们要写一个翻译方法,把一个英语句子翻译成阿拉伯语再返回。天真的方法是从原句中提取每个单词,并将其转换为目标句。这种方法是可行的,但是它不考虑任何语法和上下文。
词性标注
词性标注的任务是用标签来标记句子中的每个单词,该标签定义了该单词在该句子中的语法标注或词类消歧。
这里的问题是确定一个句子中一个单词的特定实例的 POS 标签。
这个标签可以用来解决 NLP 中更高级的问题,比如
- 语言理解,因为知道标签意味着帮助获得对文本的更好理解,因为不同的单词基于它们在句子中的位置可以具有不同的意思。
- 文本到语音和自动语音音调控制。
当标记单词时忽略上下文将仅导致接受的基线,因为该方法将使用与训练集中的单词相关联的最常见标签来标记每个单词。
因此,我们在这里试图完成的是克服这个问题,并找到一种不忽略数据背景的方法。
深度学习方法
序列建模和 RNNs
更具体地说,我们试图解决的问题被称为序列建模。我们试图对文本或声音等连续数据进行建模,并学习如何建模。
序列建模或序列到序列建模首先由 Google 翻译团队引入。
一般来说,神经网络是模式识别模型,它通过迭代数据集来学习和增强,并在识别数据中的模式方面变得更好。
递归神经网络被设计成通过使用反馈回路来防止神经网络衰退。正是这些反馈回路让 RNN 更擅长解决序列学习任务。
与前馈网络相比,RNNs 的工作方式更类似于人脑。因为人脑是坚持思考的。所以,当你读这篇文章的时候,每个单词都会影响你对文章的理解,你不会为了读一个新单词而抛弃以前的单词。
递归神经网络的机理
rnn 通过使用存储单元来处理上下文的上下文。RNN 在步骤产生的输出受该步骤输出的影响。所以总的来说,RNN 有两个输入来源。一个是实际输入,两个是来自先前输入的上下文(内存)单元。
数学上,
**前馈网络由公式定义。
新状态是权重矩阵乘以输入向量的函数
该乘法的结果然后被传递给称为激活函数的方法。产生最终结果。
相同的过程应用于循环网络中,只需简单修改。
先前的状态首先乘以一个矩阵
名为 的隐藏状态到隐藏状态 矩阵然后添加到激活函数的输入端
所以不会只受之前所有隐藏状态的影响,这将确保记忆的持久性。
一个正常的 RNN 网络将包含一个单神经网络层,这使得它不能学习连接长信息。这个问题也被称为长期依赖。
长短期记忆结构
rnn 很棒。他们在解决 NLP 中的许多任务时帮了大忙。然而,他们有长期依赖的问题。
你可以在 Colah 的博客文章中读到更多关于 LTD 的信息
LSTMs 通过比 RNN 记忆信息更长的时间来解决 LTD 问题。
RNN 和 LSTM 的唯一区别是 RNN 没有单一的神经网络层。我们在 LSTM 有 4 层以一种特殊的方式相互作用。
循序渐进的 LSTM
LSTM 层由一系列单元状态组成,其中每个状态由 4 个主层和 3 个栅极组成。
现在让我们一步一步地走过一个 LSTM 细胞状态
Source: Google photos
一个单元状态的核心是连接和之间的水平线。这一行是数据流抛出单元状态链的地方。数据很容易以最小的线性运算或不变的方式流动,整个过程由门控制。
门是控制数据变化的。他们用一个 sigmoid 神经层和一个向量 乘法运算可选地改变数据。
**Sigmoid layer是一种生成浮点值的方法,该值控制有多少数据将通过 gate。表示无而$ 1 $表示全部。
第一步是 sigmoid 层决定从乘以的结果中传递什么信息。我们可以用数学方法表示这种操作,如下所示:
前一步确实决定了哪些数据将被遗忘,哪些数据将被保留。第二步,我们需要真正做到这一点。
我们将之前的结果乘以旧状态。
使用 Tanh 激活功能计算旧状态。用∑乘以∑将决定网络忘记了哪些信息,得到了哪些信息。数学上:
最后,我们需要决定的价值是什么
这些操作顺序应用于单元状态链。查看 LSTM 的数学模型可能会令人望而生畏,因此我们将转到应用部分,并使用 Keras 为阿拉伯语实现一个 LSTM 模型。
构建阿拉伯语词性标记器
如我们所知,我们走过了序列建模的深度学习方法背后的想法。我们将应用它来构建一个阿拉伯语词性标记器。
对于英语来说,词性标注是一个已经解决的问题。像阿拉伯语这样的形态学语言。这个问题仍然存在,并且没有任何基于深度学习的开源阿拉伯语词性标注器。我们现在的目标是使用关于 LSTMs 的知识,并构建一个开源标记器。
数据
缺少开源 tagger 是缺少阿拉伯语树库数据集的明显结果。
众所周知的 Penn TreeBank 成本约为3000 美元而Quran tree bank非常经典,在日常词汇上表现不佳。
Universal Dependencies(UD)是一个跨语言一致的语法注释框架,是一个开放的社区,有 200 多名贡献者,用 70 多种语言创建了 100 多个树库,其中包括阿拉伯语
UD 提供了三种不同的树库。根据评论的建议,我们将使用 PADT 树木银行。
数据预处理
UD 以 CoNLL 的形式提供数据集。我们可以使用 pyconll 将数据集从 conll 格式转换成 pandas 数据框架。
我们需要我们的数据按顺序组织。所以我们需要它的形状如下
*[
[(Word1, T1), (Word2, T2), ...., (WordN, TM)], # Sentence one
[(Word1, T1), (Word2, T2), ...., (WordN, TM)], # Sentence two
.
.
.
[(Word1, T1), (Word2, T2), ...., (WordN, TM)] # Sentence M
]*
现在数据集以一种有用的方式构建。我们希望将文本数据编码成数值。
这个过程就是所谓的 嵌入 。
这个想法很简单,我们给数据中的每个单词一个唯一的整数值。并用数据集中的这个值替换,这样我们就可以对数据进行逐点操作。
所以在实现这个模型之前,我们有两个单词嵌入word2index
和tag2index
。它们对单词和词性标签进行编码
因为我们正在做的任务要求输入和输出是固定的。应该转换数据,使得每个序列具有相同的长度。这种矢量化允许 LSTM 模型高效地执行批量矩阵运算。
在 Keras 中,我们可以通过在较短的句子中添加0
来做到这一点,直到我们所有的句子都具有相同的长度。
问题是该模型将能够很容易地预测这些值。因此,即使模型没有正确预测任何标签,准确率也会非常高。
因此,我们需要编写自己的精确度指标,忽略那些 paddings 预测。
LSTM 的 Keras 实施
在将数据转换成合适的形状之后。下一步是设计和实现实际的模型。
模型
source: Google photos
模型结构
现在让我们彻底解释这个模型,
InputLayer
是模型的第一层。如预处理部分所解释的,Keras 具有固定大小的层,所以我们用训练集中序列的最大长度来定义该层。
Embedding
嵌入层要求对输入数据进行整数编码,使得每个单词都由一个唯一的整数表示。它用随机权重初始化,然后它将学习数据集中的每个单词
LSTM
LSTM 编码器层是一个序列到序列层。它提供序列输出,而不是整数值。并且return_sequences
强制该层为下一层进行前一序列输入。
Bidirectional
双向包装器复制了 LSTM 层,因此我们有两个并排的层,将结果序列传输到输入序列。实际上,这种方法对长短期记忆有很大的影响。我为Bidirectional
层使用了默认的合并模式【串联】。
TimeDistributed Dense
层用于保持输入层和输出层的一一对应关系。它对 3D 张量的每个时间步长应用相同的密集(全连接)运算。
Activation
激活Dense
层的方法。我们可以将激活方法定义为Dense
层中的一个参数,但第二个是更好的方法 *
用 Keras 实现这种设计非常简单。
我们使用categorical_cross_entropy
作为损失函数,因为我们有一个多对多的标记问题。
以及用于训练的Adam
优化器(自适应矩估计)。
ignore_class_accuracy
是忽略填充后重新计算精度的方法<PAD>
结果
训练步骤在 2017 年的 MacBook Pro 上进行,耗时约 40 分钟,配有 2.5 GHz CPU 和 8 GB Ram。
在我们训练我们的模型之后,我们评估并可视化训练过程。
模型损失
模型已经到达0.916
并在30 epochs
后开始收敛
在评估中,我们使用了stochastic gradient descnet
,因为它在评估 * 中比Adam
表现得更好
尽管与斯坦福 CoreNLP 模型相比,结果看起来不错,但它还可以改进。但作为第一次尝试,还不错。
原帖放在这里
参考
- https://Shao anlu . WordPress . com/2017/05/29/SGD-all-the-one-is-the-best-optimizer-dogs-vs-cats-toy-experiment/
- https://machine learning mastery . com/data-preparation-variable-length-input-sequences-sequence-prediction/
- http://colah.github.io/posts/2015-08-Understanding-LSTMs/
- *【https://skymind.ai/wiki/lstm *
- https://kevinzakka.github.io/2017/07/20/rnn/
- https://developer.nvidia.com/discover/lstm
- https://iamtrask.github.io/2015/11/15/anyone-can-code-lstm/
- http://karpathy.github.io/2015/05/21/rnn-effectiveness/
- https://universaldependencies.org/
用于对婴儿啼哭的音频进行分类的深度学习
原文:https://towardsdatascience.com/deep-learning-for-classifying-audio-of-babies-crying-9a29e057f7ca?source=collection_archive---------8-----------------------
(寻求项目合作)
在这篇文章中,我将谈论使用深度学习来帮助将音频分类。作为一个例子,我将尝试对婴儿的哭声进行分类。这不仅是一个使用 CNN 进行音频分类的有趣练习,它还可以实际用于构建一个监视器来通知父母他们的宝宝正在哭。
构建数据集
构建分类器的第一步是获得可用的数据集。我找不到现成的数据集来构建模型。所以我决定用我从网上收集的数据建一个。我使用了捐赠哭泣语料库来收集婴儿哭声的积极样本。数据集有大约 1000 个 7 秒长的声音片段。语料库没有否定样本,所以我使用了环境声音分类(ESC50) 数据集,它有大约 2000 个 5 秒长的样本。ECS50 数据集还包含婴儿啼哭的声音,因此请确保从阴性样本中移除这些片段。将数据集分成测试和验证(90:10)两部分,放在各自的文件夹中。
建立模型
音频片段的采样速率为 16000 Hz,时间长度约为 7 秒。这意味着每秒大约有 16000*7 个数字代表音频数据。我们对 2048 个样本窗口进行快速傅立叶变换(FFT ),将其滑动 512 个样本,并重复 7 秒剪辑的过程。由此产生的表示可以显示为 2D 图像,并被称为短时傅立叶变换(STFT)。由于人类是以对数标度感知声音的,我们将把 STFT 转换成梅尔标度。librosa 库让我们加载一个音频文件并将其转换成 melspectrogram
婴儿啼哭的 melspectrogram 看起来像下面的图像
我在用 FastAI v1 库训练神经网络。为了构建训练模型所需的音频样本的频谱图,我们将使用 Jason Hartquist 为 fastai v1 构建的奇妙的音频加载器模块。
Fastai 的循环学习率查找器针对一小批训练样本运行模型,以找到一个好的学习率。
随着学习速率增加到 10e-2,您可以看到模型损失减少。然而,对于较高的学习率,损失开始增加。因此,我们选择 10e-2 作为训练模型的学习速率。
经过几个时期的模型训练后,我们看到验证集的准确率为 95%
通过实时音频样本进行预测
现在我们有了一个非常好的模型,为了在实际应用中使用它,我们需要能够实时预测音频流。
我们使用 pyaudio 库从设备麦克风读取音频样本,然后将音频数据转换为 numpy 数组,并将其提供给模型。
上面的代码从麦克风中读取一个 7 秒的音频剪辑,并将其加载到内存中。它将其转换为 numpy 数组,并对其运行模型以获得预测。这段简单的代码现在可以部署到服务或嵌入式设备上,并在实际应用中使用!
用于临床诊断的深度学习
原文:https://towardsdatascience.com/deep-learning-for-clinical-diagnostics-ca7bc254e5ac?source=collection_archive---------17-----------------------
生命科学的深度学习
利用深度学习进行更安全的生物医学预测
Image source
这是系列生命科学深度学习的第四篇文章。在之前的帖子中,我展示了如何使用深度学习古 DNA 、深度学习单细胞生物学和深度学习数据整合。现在,我们将深入生物医学,了解我们为什么以及如何将贝叶斯深度学习用于患者安全。
下一代测序(NGS) 为我们理解导致常见人类疾病的致病机制提供了重大进展。然而,数据量仍然是生物医学分析的瓶颈。与数据科学相比,数百万个例子在生物医学中相当罕见,而高维数据却非常典型,因此机器学习在生物医学中的应用非常有限。数据的缺乏和高维参数空间阻碍了临床诊断的精确性,带来了许多在临床试验中不成立的错误预测。当数据稀疏/稀缺/嘈杂和高维时,贝叶斯统计有助于做出概化预测。
这里我们将讨论如何用 PyMC3 实现贝叶斯深度学习,以确保患者安全并为临床诊断提供更加准确和智能的预测。
运行深度学习时为什么要做贝叶斯?
在之前的帖子中,我解释了在进行统计分析时,你应该特别注意统计观测值的数量 N 和你的空间的维度,即特征的数量 P 之间的平衡。根据数据量,您可以在贝叶斯统计、频率统计和机器/深度学习之间进行选择。
Deep Learning makes sense to use only when you have a lot of data
所以当你拥有大量数据时使用深度学习是有意义的,因为你可以放弃线性代数的枯燥世界,跳进非线性数学的兔子洞。相比之下,生物医学通常在相反的极限下工作,N < < P,需要优于 来弥补数据的不足。这就是生物医学分析为什么要贝叶斯的第一个理由。
现在想象一下,你得到了一些生物医学大数据,这是不常见的,但不是不可能的,如果一个人从事成像或单细胞生物学工作,你可以而且应该进行深度学习。但在这种情况下你为什么要做贝叶斯呢?
Images are adapted from Emtiyaz Khan and Alex Kendall
第二个原因来了:通过将不确定性合并到模型中来生成不太明确的(与传统的基于频率主义者的深度学习相比)预测的必要性。这对错误预测代价非常高的领域非常重要,例如自动驾驶汽车、模拟股票市场、地震,特别是** 临床诊断。**
为什么不是生物医学的频率分析?
将频率统计应用于临床诊断时,有许多理由需要谨慎。它在很大程度上基于正态假设,因此对异常值敏感,它使用描述性统计进行操作,这些统计并不总是反映潜在的数据分布,因此无法正确捕捉 Anscombe 四重奏中数据集之间的差异。
相比之下,Anscombe 数据集的贝叶斯概率模型将导致概率分布的巨大差异。
智慧就是知道你不知道多少
有几个通常被称为 Data Saurus 的著名例子,进一步证明了 Frequentist 统计无法捕捉具有相同描述性统计(如均值、标准差或皮尔逊相关系数)的样本组之间的差异。
Image source
因此,过于简单的频率分析不应用于临床诊断,因为在临床诊断中,我们不能做出会损害人们生命的错误预测。
基于 PyMC3 的贝叶斯深度学习
这里,我将使用关于癌症相关成纤维细胞的 scRNAseq 数据,并应用贝叶斯深度学习对它们在恶性和非恶性细胞类型之间进行分类。以类似的方式、糖尿病患者可以被分配到特定的疾病子类型,以获得精确的治疗处方。我们先从这里下载表达式数据,加载到 Python 中,拆分成训练和验证子集,用 tSNE 可视化。通常,表达式矩阵的行是样本/细胞,列是特征/基因,最后一列包含来自无偏 DBSCAN 聚类的细胞标签。
在 tSNE 图中,四个聚类清晰可辨。接下来,我们将构建一个具有一个隐藏层和 16 个神经元的贝叶斯神经网络(BNN)** 模型,这是通过向权重和偏差分配正常先验并用随机值初始化它们来完成的。**
Image source
为了构建 BNN,我将使用 PyMC3 并遵循 Thomas Wiecki 的博客中描述的方法。在模型中,我们还定义了一个分类分布的可能性,因为我们正在处理一个 scRNAseq 多类(4 类)分类问题。
通过赋予权重和偏差先验,我们让模型知道那些参数具有不确定性,因此 MCMC 采样器将为它们建立后验分布。现在,我们将定义一个函数,该函数使用称为 NUTS 的 哈密顿蒙特卡罗 (与 Metropolis 相比,当可以计算参数的导数时,这是一个更快的采样器)算法之一,从贝叶斯神经网络的参数的后验中抽取样本。取样是 BNN 的训练。
现在,我们将使用后验预测检查(PPC) 程序来验证贝叶斯神经网络模型的预测。为此,我们将使用经过训练的模型,并在 tNSE 图上为测试子集绘制决策边界。决策边界是通过在 tSNE 图上构建 100 x 100 的网格并对网格的每个点运行模型预测来创建的。接下来,我们计算网格上每个点分配给 4 个单元子类型之一的概率的平均值和标准偏差,并可视化平均概率和概率的不确定性。
Probabilistic decision boundary together with uncertainty map for CAFs classification
上面的图对应于测试子集上的 tSNE(左上);测试子集上的 tSNE,每个点分配到 4 个细胞亚型中的任何一个的平均概率(右上),这基本上是最大似然/频率主义神经网络将预测的;和 tSNE 在测试子集上,每个点分配给 4 个细胞子类型(右下)的概率的不确定性,这是贝叶斯神经网络的特定输出。这里,红色和蓝色分别表示将 tSNE 点分配给任何单元子类型的高概率和低概率。不确定性热图中较暗的区域表示不确定性较高的区域。
我们可以立即看到,平均概率热图包含来自黄色类别的两个单元,以 100%的概率分配给紫色聚类。这是一个严重的错误分类,也是最大似然/频率主义神经网络失败的证明。相比之下,不确定性热图显示两个黄色单元落在相对较暗的区域,这意味着贝叶斯神经网络根本不确定是否将这些单元分配到任何聚类。这个例子展示了贝叶斯深度学习在进行更安全和更不激进的分类方面的能力,这对于临床诊断尤其重要。
摘要
在这里,我们已经了解到贝叶斯深度学习是一种更加准确和安全的预测方式,这对于在临床诊断中使用非常有意义,在临床诊断中我们不允许被治疗处方所误导。我们使用了 PyMC3 和 MCMC 来构建贝叶斯神经网络模型,并从样本分配到恶性与非恶性类别的后验概率中取样。最后,我们证明了贝叶斯深度学习在利用不确定性信息避免样本错误分类方面优于频率主义方法。
像往常一样,如果你在生命科学中有特别喜欢的领域,想在深度学习框架中解决,请在评论中告诉我。在 twitter @NikolayOskolkov 的 Medium Nikolay Oskolkov、关注我,并在我的 github 上查看这篇文章的代码。我计划写下一篇关于显微图像分析深度学习的帖子,敬请关注。
用于数据集成的深度学习
原文:https://towardsdatascience.com/deep-learning-for-data-integration-46d51601f781?source=collection_archive---------15-----------------------
生命科学的深度学习
数据集成与深度学习的协同效应
Image source
这是系列生命科学深度学习的第三篇文章。在前两篇帖子中,我展示了如何对古代 DNA 使用深度学习和对单细胞生物学使用深度学习。现在我们将讨论如何利用多种来源的生物信息,组学数据,以便通过深度学习实现生物系统的更准确建模。
生物和生物医学研究在过去十年中极大地受益于技术进步,提供了 DNA 序列(基因组学)、基因表达(转录组学组学)、蛋白质丰度(蛋白质组学组学)以及通常称为组学的许多其他水平的生物信息。尽管单个组学层能够回答许多重要的生物学问题,但它们的组合和随之而来的来自其互补性的协同效应为诸如细胞、组织和有机体等生物系统的行为提供了新的见解。因此组学整合代表了当代生物学和生物医学的挑战。
在这篇文章中,我将使用深度学习和 Keras,并展示整合多组学数据的****如何揭示在单个组学中不可见的隐藏模式。
单细胞产生大数据
数据集成的问题对于数据科学来说并不是全新的。想象一下,我们知道一个人看某些图像,读某些文本,听某些音乐。图像、文本和声音是非常不同类型的数据,但是我们可以尝试组合这些类型的数据,以便构建例如更好的推荐系统,该系统实现了捕捉个人兴趣的更高的准确性。至于生物学和生物医学,数据整合的想法最近才出现,但是它从生物学的角度积极发展,产生了一些有趣的方法,如混合组学、 MOFA 、相似性网络融合(SNF) 、 OnPLS/JIVE/DISCO 、贝叶斯网络等。
Integrative OMICs methods
以上列出的所有整合组学方法都面临的一个问题是 维数灾难 ,即不能在具有有限数量的统计观测值的高维空间中工作,这是生物数据分析的典型设置。这就是单细胞组学技术非常有用的地方,因为正如我们在上一篇文章中讨论的那样,它们提供了成千上万甚至数百万的统计观察值(细胞),从而提供了真正的大数据,用于整合。
Single cell multi-OMICs technologies. Image source
非常令人兴奋的是,多组学单细胞技术如CITEseq和 scNMTseq 分别从完全相同的细胞中提供两个和三个水平的生物信息。****
将 CITEseq 数据与深度学习相结合
在这里,我们将使用自动编码器对来自 CITEseq,8 617 个脐带血单核细胞(CBMC)的单细胞转录组学(scRNAseq)和蛋白质组学(scProteomics)数据进行无监督整合,自动编码器非常适合捕捉高度非线性的单细胞组学数据。我们在之前的文章中介绍了使用自动编码器进行单细胞生物学的优势,但简单来说,它们与单细胞分析本质上是无人监管的事实有关。我们首先从这里下载 CITEseq 数据,用 Pandas 读取它们并进行日志转换,这相当于一个温和的归一化。通常,行是细胞,列是 mRNA 或蛋白质特征,最后一列对应于细胞注释。
现在,我们将使用 Keras functional API 建立一个具有 4 个隐藏层的自动编码器模型。自动编码器有两个输入,每层信息一个,即 scRNAseq 和 scProteomics,以及相应的两个输出,旨在重建输入。两个输入层在第二个隐藏层中连接之前,在第一个隐藏层中分别进行线性变换(相当于 PCA 降维)。最后,通过自动编码器的瓶颈处理合并的组学,最后根据自动编码器典型的“蝴蝶”对称性将尺寸逐渐重建为初始尺寸。
Unsupervised integration of CITEseq data
在下面的 Autoencoder 代码中,重要的是要注意第一个隐藏层将 scRNAseq 的维数从 977 减少到 50 个基因,而它几乎不影响 scProteomics,即将维数从 11 减少到 10。瓶颈进一步将串联后的 60 个维度减少到 50 个潜在变量,这些变量代表 mRNA 和蛋白质特征的组合。
这里一个非常方便的事情是,我们可以将不同的损失函数分配给来自不同统计分布的组学,例如,结合分类和连续数据,我们可以分别应用分类交叉熵和均方误差。通过自动编码器进行数据整合的另一个好处是,所有的组学都知道彼此,因为每个节点/特征的权重通过反向传播在彼此的上下文中更新。最后,让我们训练自动编码器,并将瓶颈输入到 tSNE 中进行可视化:
Effect of CITEseq data integration: to see patterns invisible in individual OMICs
将使用单个组学获得的 tSNE 图与结合数据的自动编码器的瓶颈上的 tSNE 进行比较,我们可以立即看到整合在某种程度上平均并加强了单个组学。例如,单独使用 scRNAseq 数据很难发现紫色簇,因为它与蓝色细胞群没有明显区别,但是整合后,紫色细胞群很容易区分。这就是数据整合的力量!
将 scNMTseq 数据与深度学习相集成
CITEseq 包括两个单细胞水平的信息(转录组学和蛋白质组学),另一项神奇的技术 scNMTseq 从相同的生物细胞中提供三个组学:1)转录组学(scRNAseq),2) 甲基化模式 (scBSseq),以及 3) 开放染色质区域 (scATACseq)。原始数据可以从这里下载。
scNMTseq data integration with Autoencoder
自动编码器的架构类似于 CITEseq 使用的架构,只有一个特点:在输入层上使用了丢失正则化。这是因为我们只有大约 120 个细胞被排序,而特征空间的维数是数万,因此我们需要应用正则化来克服维数灾难。请注意,这对于 CITEseq 是不必要的,因为我们有大约 8K 的单元和大约 1K 的特性,所以情况正好相反。然而,总的来说 scNMTseq 并不是一个简单的数据整合案例,尽管我坚信这只是单细胞多组学时代的开始,更多的细胞将很快从这项令人兴奋的技术中到来,所以最好做好准备。
Combining transcriptomics with epigenetics information for scNMTseq
出于好奇,我在这里提供了自动编码器的瓶颈,该编码器将三个 scNMTseq 组学组合成 【均匀流形近似和投影(UMAP) 非线性维度缩减技术,该技术在大量数据的可伸缩性方面似乎优于 tSNE。我们可以立即看到,当 scRNAseq 与来自相同细胞(scBSseq 和 scATACseq)的 表观遗传学 信息结合时,基因表达意义上的同质蓝色簇分裂成两个簇。因此,我们似乎捕捉到了一种细胞间新的异质性,这种异质性在仅观察基因表达 scRNAseq 数据时是隐藏的。这可能是一种利用细胞生物学的整体复杂性来对不同群体的细胞进行分类的新方法吗?如果是,那么问题来了:什么是细胞群体或细胞类型?我不知道这个问题的答案。****
摘要
在这里,我们了解到,由于最近的技术进步,分子和临床信息的多种来源在生物学和生物医学中越来越普遍。因此,数据整合是合乎逻辑的下一步,它通过利用数据的整体复杂性提供了对生物学过程的更全面的理解。深度学习框架非常适合数据集成,因为当多种数据类型相互学习信息时,它通过反向传播对参数进行真正的“综合”更新。我展示了数据集成可以导致在数据中发现以前在单个数据类型中没有发现的新模式。
像往常一样,如果你在生命科学中有特别喜欢的领域,想在深度学习框架中解决,请在评论中告诉我。在 twitter @NikolayOskolkov 上关注我,在我的 github 上查看这篇文章的代码。我计划写下一篇关于贝叶斯深度学习用于临床诊断中患者安全的文章,敬请关注。
深度学习用于从 X 射线图像中检测肺炎
原文:https://towardsdatascience.com/deep-learning-for-detecting-pneumonia-from-x-ray-images-fc9a3d9fdba8?source=collection_archive---------1-----------------------
用于从 X 射线图像检测肺炎的端到端管道
被困在付费墙后面?点击这里阅读完整故事与我的朋友链接!
对许多人来说,患肺炎的风险是巨大的,尤其是在发展中国家,那里有数十亿人面临能源匮乏,依赖污染型能源。世卫组织估计,每年有 400 多万人过早死于包括肺炎在内的家庭空气污染相关疾病。每年有超过 1 . 5 亿人感染肺炎,尤其是 5 岁以下的儿童。在这些地区,由于缺乏医疗资源和人员,这个问题可能会进一步恶化。例如,在非洲的 57 个国家中,存在着 230 万医生和护士的缺口。对于这些人群,准确快速的诊断意味着一切。它可以保证及时获得治疗,并为那些已经贫困的人节省急需的时间和金钱。
本项目是在 Kaggle 上举办的胸部 x 光影像(肺炎)的一部分。
挑战
建立一种算法,通过查看胸部 x 光图像来自动识别患者是否患有肺炎。算法必须非常精确,因为人命关天。
环境和工具
- scikit-learn
- keras
- numpy
- 熊猫
- matplotlib
数据
数据集可以从 kaggle 网站下载,该网站可以在这里找到。
代码在哪里?
事不宜迟,让我们从代码开始吧。github 上的完整项目可以在这里找到。
让我们从加载所有的库和依赖项开始。
接下来,我展示了一些正常和肺炎的图像,看看它们在肉眼看来有多大的不同。嗯不多!
Sample Images
然后,我将数据集分成三组——训练集、验证集和测试集。
接下来,我编写了一个函数,在这个函数中,我做了一些数据扩充,将训练和测试集图像输入到网络中。我还为图像创建了标签。
数据扩充的做法是增加训练集规模的有效方法。增加训练示例允许网络在训练期间“看到”更多样化但仍有代表性的数据点。
然后我定义了两个数据生成器:一个用于训练数据,另一个用于验证数据。数据发生器能够直接从源文件夹加载所需数量的数据(一个小批量的图像),将它们转换成训练数据(输入到模型)和训练目标(一个属性向量——监督信号)。
对于我的实验,我通常设置
*batch_size = 64*
。一般来说,介于 32 和 128 之间的值应该可以。通常,您应该根据计算资源和模型的性能来增加/减少批量大小。
之后我定义了一些常量以备后用。
下一步是构建模型。这可以用以下 5 个步骤来描述。
- 我使用了五个卷积模块,包括卷积层、最大池和批量标准化。
- 在它的顶部,我使用了一个扁平化层,然后是四个完全连接的层。
- 此外,在此期间,我用辍学来减少过度拟合。
- 激活函数除了最后一层是 Sigmoid,因为这是一个二元分类问题。
- 我使用 Adam 作为优化器,交叉熵作为损失。
在训练之前,模型对于定义一个或多个回调是有用的。挺好用的一个,有:ModelCheckpoint
和EarlyStopping
。
- ModelCheckpoint :当训练需要大量时间才能达到一个好的结果时,往往需要多次迭代。在这种情况下,最好仅在改善度量的时期结束时保存最佳执行模型的副本。
- 提前停止:有时,在训练过程中,我们可以注意到泛化差距(即训练和验证误差之间的差异)开始增大,而不是减小。这是过度拟合的症状,可以通过多种方式解决(减少模型容量、增加训练数据、数据扩充、正规化、退出等)。通常一个实用有效的解决方法是当泛化差距越来越大时停止训练。
Early stopping
接下来,我以 32 的批量为 10 个时期训练模型。请注意,通常较大的批量会产生较好的结果,但代价是较高的计算负担。一些研究还声称,通过在超参数调整上投入一些时间,可以找到获得最佳结果的最佳批量。
让我们来看一下损耗和精度图。
Accuracy vs Epoch | Loss vs Epoch
到目前为止一切顺利。该模型是收敛的,这可以从随着时期的损失和验证损失的减少中观察到。此外,它能够在短短 10 个时期内达到 90%的验证准确性。
让我们绘制混淆矩阵,并获得一些其他结果,如精确度、召回率、F1 分数和准确度。
CONFUSION MATRIX ------------------
[[191 43]
[ 13 377]]
TEST METRICS ----------------------
Accuracy: 91.02564102564102%
Precision: 89.76190476190476%
Recall: 96.66666666666667%
F1-score: 93.08641975308642
TRAIN METRIC ----------------------
Train acc: 94.23
该模型能够达到 91.02%的准确度,考虑到所使用的数据量,这是相当好的。
结论
虽然这个项目还远未完成,但在如此多样的现实世界问题中看到深度学习的成功是令人瞩目的。我已经演示了如何从一组 X 射线图像中对阳性和阴性肺炎数据进行分类。该模型是从零开始的,这使它有别于其他严重依赖迁移学习方法的方法。将来,这项工作可以扩展到检测和分类由肺癌和肺炎组成的 X 射线图像。区分包含肺癌和肺炎的 X 射线图像一直是最近的一个大问题,我们的下一个方法应该是解决这个问题。
参考资料/进一步阅读
[## 训练 CNN 检测肺炎
我清楚地记得那一天。我的祖父开始胡乱咳嗽,并开始呼吸困难。他是…
medium.com](https://medium.com/datadriveninvestor/training-a-cnn-to-detect-pneumonia-c42a44101deb) [## 用深度学习检测肺炎
肺炎是由病毒、细菌、真菌或其他病原体感染引起的肺部炎症。根据……
becominghuman.ai](https://becominghuman.ai/detecting-pneumonia-with-deep-learning-3cf49b640c14) [## CheXNet:通过深度学习对胸部 X 射线进行放射科医生级别的肺炎检测
该数据集由美国国家卫生研究院发布,包含 30805 名不同患者的 112120 张正面 x 光图像,并附有注释…
stanfordmlgroup.github.io](https://stanfordmlgroup.github.io/projects/chexnet/)
在你走之前
相应的源代码可以在这里找到。
[## abhinavsagar/ka ggle-教程
Kaggle 竞赛笔记本样本。显微图像的自动分割是医学图像处理中的一项重要任务
github.com](https://github.com/abhinavsagar/Kaggle-tutorial)
快乐阅读,快乐学习,快乐编码!
联系人
如果你想了解我最新的文章和项目,请关注我的媒体。以下是我的一些联系人详细信息:
- 个人网站
- 领英
- 中等轮廓
- GitHub
- 卡格尔
基于 fastai 的深度学习皮肤图像诊断
原文:https://towardsdatascience.com/deep-learning-for-diagnosis-of-skin-images-with-fastai-792160ab5495?source=collection_archive---------4-----------------------
学会从皮肤镜图像中识别皮肤癌和其他疾病
我们展示了如何使用 fast.ai 解决 2018 年皮肤病变分析对黑色素瘤检测的挑战,并自动识别七种皮肤病变。
Pixabay/Pexels free images
由 Aldo von Wangenheim 发布— aldo.vw@ufsc.br
这是基于以下材料:
- 走向数据科学::用卷积神经网络对皮肤损伤进行分类——医学深度学习指南和介绍
- Tschandl,Philipp,2018,“HAM10000 数据集,常见色素性皮肤病损的多源皮镜图像大集合”,https://doi.org/10.7910/DVN/DBW86T,哈佛 data verse【arXiv 预印本:arXiv:1803.10417【cs。CV]]
- 用于处理 HAM10000 数据集的工具— GitHub 。该存储库提供了对为组装训练数据集而创建和使用的工具的访问。
HAM10000 数据集(具有 10000 幅训练图像的人机对抗)用作 ISIC 2018 挑战赛(任务 3) 的训练集。通过挑战网站https://challenge2018.isic-archive.com/可以获得这个挑战的官方验证和测试集,没有地面真相标签。ISIC-Archive 还提供了一个“现场挑战”提交网站,用于在官方验证和测试集上连续评估自动分类器。
- HAM10000 数据集也在 Kaggle 上。如果你想用 Kaggle 内核比较你的结果,看这里:https://www . ka ggle . com/kmader/skin-cancer-mnist-ham 10000/kernels上次我看的时候(2019 年 6 月),那里贴了 55 个不同的解决方案。
- 本帖子中显示代码的笔记本(以及一些附加单元格)在这里。
这些图像看起来像这样:
Random images from the HAM10000 dataset with their ground truth labels
这个数据集中有什么?
该数据集包含通过标准皮肤镜检查获得的色素性皮肤损伤。这些是组织产生黑色素的病变,黑色素是人类皮肤的天然色素,并且是深色的。并非所有通过皮肤镜初步检查和分类的病变都一定是色素性病变。这意味着,在现实世界中,全科医生或护士通过皮肤镜检查患者(或患者进行自我检查)并打算将这些图像提交给皮肤科医生进行初步分类,可能会遇到除此数据集描述的病变之外的其他病变(参见有 ISIC 2019 吗?下)。
HAM10000 数据集中的病变类别包括:
- nv :黑素细胞痣——黑素细胞良性肿瘤[6705 张图片]
- 梅尔:黑色素瘤——一种来源于黑色素细胞的恶性肿瘤【1113 张图片】
- bkl :良性角化病——包括脂溢性角化病、日光性雀斑样痣和扁平苔藓样角化病的一般类别【1099 张图片】;
- 基底细胞癌:基底细胞癌——上皮性皮肤癌的一种常见变体,很少转移,但如果不治疗,会破坏性地生长(基底细胞癌不一定会产生色素性病变)[514 图片];
- akiec :光化性角化病和上皮内癌——常见的非侵袭性鳞状细胞癌变体,无需手术即可局部治疗【327 张图片】;
- vasc :从樱桃血管瘤到血管角化瘤、化脓性肉芽肿的血管性皮肤病变【142 张图像】;
- df :皮肤纤维瘤——一种良性皮肤病变,被认为是良性增生或对轻微创伤的炎症反应【115 张图片】。
有关每个类的更详细描述,请查看 ka ggle kernel:Skin Lesion Analyzer+tensor flow . js Web App-Python notebook 使用来自皮肤癌 MNIST: HAM10000 的数据,以及上面 Philipp Tschandl 的论文。
这个数据集的诊断局限性是什么?
皮肤镜图像本身并不能为皮肤病学诊断或远程皮肤病学设置中可靠的远程患者分类提供足够的数据。皮肤镜图像缺乏上下文。为了提供背景信息,您需要执行一个图像采集协议,其中包括患者的全景全身图像和每个病灶的近似图像,这些图像是用尺子或图像中可见的其他参照系拍摄的,以便提供病灶大小的背景信息。用尺子拍摄的近似图像对于已经在治疗中的患者也很重要,以便允许随行医生跟踪病变的发展。为了正确获取全景图像和近似图像,需要遵循保证图像聚焦、从正确的距离拍摄并具有正确照明的协议来执行。还有一些细节不能通过目前使用的标准皮肤镜检查技术可靠地检测出来,在一些情况下,需要进行确认性活组织检查。
如果您有兴趣了解更多关于远程皮肤病学检查采集协议的信息,请点击此处:
- 奥尔多·冯·旺根海姆和丹尼尔·霍尔特豪森·努内斯。创建支持临床协议和临床管理的网络基础设施:远程皮肤科的一个例子。远程医疗和电子保健。提前上线:2018 年 11 月 30 日。【http://doi.org/10.1089/tmj.2018.0197】T4。在 ResearchGate 上也有一份预印本。
皮肤镜图像是如何获得的?
现在使用的接触式皮肤镜是在 20 世纪 90 年代上半期由德国慕尼黑大学的一组研究人员领导的这种检查标准化的国际努力的结果。该设备使用放大 10 倍的单透镜,内部由发光二极管照明。使用矿物油进行检查,在将皮肤镜应用于病变部位并拍照之前,将矿物油应用于病变部位的表面。
Two different 10x contact dermoscopes: (a) analog pocket dermoscope and (b) dermoscopy adapter for Sony digital cameras employed by us at the Santa Catarina State Telemedicine and Telehealth Network — STT/SC
选择单眼 10 倍放大镜头作为标准允许开发非常小的设备,这很快变得非常流行。模拟皮肤镜可以放在胸前的口袋里,数字皮肤镜可以很容易地开发成小型 USB 设备或数码相机和智能手机的适配器。
该标准的缺点是 10 倍放大不足以可靠地检测某些病理,例如基底细胞癌,它是皮肤癌的最常见形式。这种形式的肿瘤以血管改变为特征,称为树枝状血管形成,不能用放大 10 倍的单目镜可靠地观察到:为了提供明确的诊断,必须进行确认性活检。可靠的检测需要更高的放大倍数和双目光学[1][2]。
Non-pigmented basal cell carcinomas acquired (a) with a 10x contact planar dermoscope and (b) with a 50x binocular stereoscopic dermoscope, showing arboriform vascularizations (J.Kreusch, Univ. Lübeck, Sur Prise e.K. collection, POB 11 11 07, 23521 Lübeck, Germany) — only one image of the stereo pair is depicted here
直到 20 世纪 90 年代,还在开发其他类型的皮肤镜,它们可以提供更好的成像质量,但更大,不太容易操作,例如 5 0x 双目立体接触皮肤镜。这种设备更适合于病理的视觉早期检测,例如基底细胞癌[1][2]。然而,10 倍接触式单眼皮肤镜的实用性、普及性和标准化阻止了这些其他的研究方向。
50x sterescopic dermoscope produced by Kocher Feinmechanik, Germany in the late 1990s and still in clinical use (L.F.Kopke, Florianópolis [2])
有没有 ISIC 2019?
ISIC——国际皮肤成像协作组织已经纠正了 HAM10000 数据集中一些皮肤病诊断类别的缺乏,在 ISIC 2019 挑战赛中发布了一个新的数据集:面向黑色素瘤检测的皮肤病变分析。2019 年 5 月 3 日发布的 2019 年数据集现在包含 9 个不同的诊断类别和 25,331 幅图像:
- 黑素瘤
- 黑素细胞痣
- 基底细胞癌
- 光化性角化病
- 良性角化病(日光性雀斑样痣/脂溢性角化病/扁平苔藓样角化病)
- 皮肤纤维瘤
- 血管病变
- 鳞状细胞癌
- 其他人都没有
- 在撰写本文时,这个新数据集的测试元数据还不可用。宣布将于 2019 年 8 月 9 日上映。
- 到目前为止,ISIC 已经赞助了图像分析方面的四项挑战:ISIC 2016 至 ISIC 2019,始终以“皮肤病变分析促进黑色素瘤检测”为主题。这四项挑战可在国际标准行业分类档案中找到。
让我们开始研究 2018 年挑战的数据集。
初始化
每次运行此笔记本时,请执行以下本节中的操作一次…
%reload_ext autoreload
%autoreload 2
%matplotlib inline
在 Google Colab 上测试您的虚拟机…
只是为了确定,看看哪一个 CUDA 驱动和哪一个 GPU Colab 已经为你提供了。GPU 通常是:
- 一个 11 GB 内存的 K80 或者(如果你真的幸运的话)
- 一辆配有 14 GB 内存的特斯拉 T4
如果谷歌的服务器很拥挤,你最终只能访问 GPU 的一部分。如果你的 GPU 与另一台 Colab 笔记本共享,你会看到可供你使用的内存量减少。
小贴士:避开美国西海岸的高峰期。我住在 GMT-3,我们比美国东海岸早两个小时,所以我总是试图在早上进行繁重的处理。
!/opt/bin/nvidia-smi
!nvcc --version
当我开始运行这里描述的实验时,我很幸运:我有一个 15079 MB RAM 的完整 T4!我的输出如下所示:
Thu May 2 07:36:26 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 410.79 Driver Version: 410.79 CUDA Version: 10.0 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |
| N/A 63C P8 17W / 70W | 0MiB / 15079MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Sat_Aug_25_21:08:01_CDT_2018
Cuda compilation tools, release 10.0, V10.0.130
图书馆进口
在这里,我们导入所有必需的包。我们将与 fastai V1 库合作,它位于 Pytorch 1.0 之上。fastai 库提供了许多有用的功能,使我们能够快速轻松地构建神经网络并训练我们的模型。
from fastai.vision import *
from fastai.metrics import error_rate
from fastai.callbacks import SaveModelCallback# Imports for diverse utilities
from shutil import copyfile
import matplotlib.pyplot as plt
import operator
from PIL import Image
from sys import intern # For the symbol definitions
导出和恢复功能
# Export network for deployment and create a copydef exportStageTo(learn, path):
learn.export()
# Faça backup diferenciado
copyfile(path/'export.pkl', path/'export-malaria.pkl')
#exportStage1(learn, path)# Restoration of a deployment model, for example in order to conitnue fine-tuningdef restoreStageFrom(path):
# Restore a backup
copyfile(path/'export-malaria.pkl', path/'export.pkl')
return load_learner(path)
#learn = restoreStage1From(path)
下载色素性病变的皮肤镜图像
我们将下载这个数据集的 Kaggle 版本,因为 Google Colab 已经预装了 Kaggle API,并且都组织在一个版本中。zip 文件。为了从 Kaggle 下载,您需要:
- 卡格尔的一个账户
- 要在 Colab 上安装您的 Kaggle 凭证(一个. json 文件)
要了解如何做到这一点,首先查看本教程和 Kaggle API 说明,然后生成您的凭证并上传到 Colab:
- TowardsDataScience::在 Google Colab 中设置 ka ggle——Anne Bonner 为新手编写的简单教程
- https://github.com/Kaggle/kaggle-api#api-credentials
当你创建并复制你的 Kaggle 证书到 Colab
运行下面的单元格。它将为您的 Kaggle API 凭据创建一个文件夹,并将您的凭据安装在 Colab:
!mkdir .kaggle
!mv kaggle.json .kaggle
!chmod 600 /content/.kaggle/kaggle.json
!cp /content/.kaggle/kaggle.json ~/.kaggle/kaggle.json
!chmod 600 ~/.kaggle/kaggle.json
!kaggle config set -n path -v{/content}
出于某种神秘的原因,这个脚本有时不工作。这似乎与 Colab 命名主文件夹的形式有关。如果您遇到错误消息,只需再次执行它。最终输出应该如下所示:
- path is now set to: {/content}
执行实际的下载和解压缩
创建一个“数据”文件夹,并将皮肤镜检查图像下载到其中
!mkdir data
!kaggle datasets download kmader/skin-cancer-mnist-ham10000 -p data
这将产生以下输出:
Downloading skin-cancer-mnist-ham10000.zip to data
100% 2.61G/2.62G [00:52<00:00, 42.3MB/s]
100% 2.62G/2.62G [00:52<00:00, 53.4MB/s]
将整个 zip 文件解压到/content/data 中,然后悄悄地(-q)解压图像文件(你不想冗长地解压超过 10k 的图像吧!).我们将使用 override 选项(-o),以便允许安静地覆盖那些在您之前中断的尝试中创建的文件。
# Unzip the whole zipfile into /content/data
!unzip -o data/skin-cancer-mnist-ham10000.zip -d data
# Quietly unzip the image files
!unzip -o -q data/HAM10000_images_part_1.zip -d data
!unzip -o -q data/HAM10000_images_part_2.zip -d data
# Tell me how many files I unzipped///
!echo files in /content/data: `ls data | wc -l`
如果您有 10,023 个文件,那么您就做对了!
Archive: data/skin-cancer-mnist-ham10000.zip
inflating: data/hmnist_28_28_RGB.csv
inflating: data/HAM10000_metadata.csv
inflating: data/HAM10000_images_part_1.zip
inflating: data/hmnist_28_28_L.csv
inflating: data/hmnist_8_8_L.csv
inflating: data/HAM10000_images_part_2.zip
inflating: data/hmnist_8_8_RGB.csv
files in /content/data: 10023
准备您的数据
现在,我们将准备使用 fast.ai 处理我们的数据。
在我们之前的医学图像分类帖子(利用 fastai 进行疟疾检测的深度学习和医学图像分析)中,我们已经将图像类别分类到文件夹中,每个类别一个文件夹。
在这里,我们将所有图像存储在一个文件夹中,并将元数据存储在一个电子表格中,我们将使用 fast.ai 数据块 API 中的 fast . aiimagedata bunch . from _ CSV()方法读取该电子表格。
我们这里有什么不同?
HAM10000 数据集不提供根据类别分类到文件夹中的图像。相反,所有图像都在一个文件夹中,并且提供了一个电子表格,其中包含每个图像的若干元数据。在本教程中,我们将从这里读取每个图像的类。csv 电子表格,而不是将图像文件组织到文件夹中,其中文件夹的名称是图像所属的类。 fast.ai 还提供了解释电子表格和提取图像分类数据的现成方法。在这篇文章中,我们将学习如何利用这些方法。
为此,我们将使用 fast.ai 的数据块 API 。在下面的帖子中有一个很好的解释:
- Tom McKenzie 的 Medium::使用 fastai 数据块 API
创建您的培训和验证数据集
在上面使用 Keras 的原始教程中,有一个从数据中创建训练、验证和测试文件夹的例程。有了 fast.ai 就不需要了:如果你只有一个“train”文件夹,你可以在创建 DataBunch 的时候通过简单的传递几个参数来拆分它…
通过 fast.ai,我们还可以轻松地使用不同于原始 ImageNet 分辨率的分辨率,这些分辨率用于预先训练我们将使用的网络。在上面列出的教程中,作者将数据集图像分辨率降低到 224x224,以便使用 Keras MobileNet 模型。我们将采用 448x448 的分辨率:
bs = 64 # Batch size, 64 for medium images on a T4 GPU...
size = 448 # Image size, 448x448 is double than the orignal
# ImageNet
path = Path("./data") # The path to the 'train' folder you created...# Limit your augmentations: it's medical data! You do not want to phantasize data...
# Warping, for example, will let your images badly distorted, so don't do it!
# This dataset is big, so don't rotate the images either. Lets stick to flipping...
tfms = get_transforms(flip_vert=True, max_lighting=0.1, max_rotate=None, max_warp=None, max_zoom=1.0)
# Create the DataBunch!
# Remember that you'll have images that are bigger than 128x128 and images that are smaller,
# so squish them all in order to occupy exactly 128x128 pixels...
data = ImageDataBunch.from_csv('data', csv_labels='HAM10000_metadata.csv', suffix='.jpg', fn_col=1, label_col=2,
ds_tfms=tfms, valid_pct = 0.2,size=size, bs=bs)
print('Transforms = ', len(tfms))
# Save the DataBunch in case the training goes south... so you won't have to regenerate it..
# Remember: this DataBunch is tied to the batch size you selected.
data.save('imageDataBunch-bs-'+str(bs)+'-size-'+str(size)+'.pkl')
# Show the statistics of the Bunch...
print(data.classes)
data
这将产生以下输出:
Transforms = 2
['akiec', 'bcc', 'bkl', 'df', 'mel', 'nv', 'vasc']ImageDataBunch;Train: LabelList (8012 items)
x: ImageList
Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448)
y: CategoryList
bkl,bkl,bkl,bkl,bkl
Path: data;Valid: LabelList (2003 items)
x: ImageList
Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448)
y: CategoryList
bkl,nv,nv,nv,nv
Path: data;Test: None
查看您的数据集群,看看增加是否可以接受…
data.show_batch(rows=5, figsize=(15,15))
第一次训练实验:ResNet34
如果您不知道使用什么模型,从 34 层的剩余网络开始是一个不错的选择。功能强大,但不太小也不太大…
在上面列出的教程中,作者使用了在 Keras 中实现的 MobileNet 和网络的原始图像分辨率 224x224。在 fast.ai 中,ResNet 很容易适应我们的 DataBunch 的 448x448 分辨率。
现在我们将开始训练我们的模型。我们将使用一个卷积神经网络主干和一个单隐层全连接头作为分类器。不知道这些东西是什么意思?不要担心,我们将在接下来的课程中深入探讨。目前,您需要知道我们正在构建一个模型,该模型将图像作为输入,并将输出每个类别的预测概率(在这种情况下,它将有 37 个输出)。
我们将使用两种不同的指标来衡量我们的培训成功程度:
- 精度:验证精度
- 错误率:验证错误率
如果你想了解更多信息,请看 https://docs.fast.ai/metrics.html 的。
learn = cnn_learner(data, models.resnet34, metrics=[accuracy, error_rate, dice(iou=True), fbeta])
learn.model
只需将包含 DataBunch 实例的 data 变量传递给 cnn_learner() 函数,fast.ai 就会自动调整新网络的输入层以适应更高的图像分辨率。该模型将如下所示:
Sequential(
(0): Sequential(
(0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU(inplace)
(3): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
(4): Sequential(
(0): BasicBlock(
(conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
(1): BasicBlock(
(conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
(2): BasicBlock(
(conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(5): Sequential(
(0): BasicBlock(
(conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)
(1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
...
...
... and so on...
培训策略
我们将采用 Leslie N. Smith 开发的 fit1cycle 方法,详情见下文:
- https://docs.fast.ai/callbacks.one_cycle.html
- 一种训练有素的神经网络超参数方法:第一部分——学习速率、批量大小、动量和权重衰减【https://arxiv.org/abs/1803.09820】T21
- 超收敛:使用大学习率非常快速地训练残差网络—https://arxiv.org/abs/1708.07120
- 还有一篇来自 Nachiket Tanksale 的非常有趣的文章,名为寻找好的学习率和单周期政策,其中讨论了周期学习率和动量
- 因为这种方法很快,所以在第一个迁移学习阶段,我们将只使用 10 个时期
如果你想了解更多关于 fast.ai 库中新的学习 API 的信息,可以看看 Sylvain Gugger 准备的这个笔记本。
如果性能变得更好,我们也将在每个时期保存网络:https://docs.fast.ai/callbacks.html#SaveModelCallback
learn.fit_one_cycle(10, callbacks=[SaveModelCallback(learn, every='epoch', monitor='accuracy', name='derma-1')])
# Salve a rede (necessita regerar o databunch caso a gente continue)
learn.save('derma-stage-1')
# Faça o deploy desta rede para podermos usar offline depois para fazer testes
exportStageTo(learn, path)
85% accuracy…
ResNet34 的结果
让我们看看我们得到了什么结果。
我们将首先看到模型最容易混淆的类别。我们将尝试看看模型预测的结果是否合理。在这种情况下,错误看起来是合理的(没有一个错误看起来明显幼稚)。这表明我们的分类器工作正常。
此外,当我们绘制混淆矩阵时,我们可以看到分布严重偏斜:该模型一次又一次地犯同样的错误,但它很少混淆其他类别。这表明它只是发现很难区分彼此之间的某些特定类别;这是正常的行为。
让我们生成一个分类解释,看看一些结果,混淆矩阵和损失曲线。
interp = ClassificationInterpretation.from_learner(learn)losses,idxs = interp.top_losses()len(data.valid_ds)==len(losses)==len(idxs)
查看您的最差结果,首先不使用热图:
interp.plot_top_losses(9, figsize=(20,11), **heatmap=False**)
现在,做同样的事情,但是用热图突出显示图像,以便查看每个图像的哪些部分导致了错误的分类:
interp.plot_top_losses(9, figsize=(20,11), **heatmap=True**)
显示混淆矩阵
这里我们有 七个职业 看看混乱矩阵很有意义。此外,它能拍出漂亮的照片…
interp.plot_confusion_matrix(figsize=(5,5), dpi=100)
我们在这里可以看到:
- 痣是最常见的现象。人们可以考虑减少训练集中的痣的实例,以便不扭曲结果;
- 有几种良性角化病( bkl )被错误分类。这可能是因为该数据集中的 bkl 是一个通用类别,包括脂溢性角化病、日光性雀斑样痣和扁平苔藓样角化病,这些皮肤病即使相关,看起来也非常不同;
- 还有几个黑色素瘤( mel )被错误分类。这是一个惊喜。我期望网络在这里表现得更好。
如果你对混淆矩阵感到困惑,请看这里:
- 从混乱矩阵中找出混乱作者艾莉森·拉冈
- 通过马达夫·米什拉简化混淆矩阵
展示你的学习曲线:
画出你的损失,以便看到学习曲线:
learn.recorder.plot_losses()
这个成绩确实不错。网络有些波动,但学习稳定。现在让我们试着微调网络。
微调 ResNet34
首先解冻网络,并尝试为这个特定的网络找到一个好的学习速率范围。
方法 learn.lr_find() 帮你找到一个最优的学习速率。它使用了 2015 年论文中开发的技术,用于训练神经网络(http://arxiv.org/abs/1506.01186)的循环学习率,我们只是从一个非常小的值开始增加学习率,直到损失开始减少。
如果你想知道更多关于寻找最佳学习率的信息,请看这里:
- 迈向数据科学 :: 用 LR-Finder 加速神经网络训练——为你的网络找到良好的初始学习率faiz an Ahemad
让我们开始吧:
# Unfreeze the network
learn.unfreeze()
# Find optimum learning rates
learn.lr_find()
# Include **suggestion=True** in order to obtain a suggestion on where to look...
learn.recorder.plot(suggestion=True)
让我们微调一下结果。为了确保万无一失,我们将使用 30 个纪元。学习率搜索器将 1e-5 确定为“安全”学习率。因此,我们将使用经验法则定义一个学习速率范围:以“安全”速率 1e-5 结束,以高一个数量级的速率开始: max_lr=slice(1e-4,1e-5) 。
# Unfreeze the network
learn.unfreeze()learn.fit_one_cycle(30, **max_lr=slice(1e-4,1e-5)**,
callbacks=[SaveModelCallback(learn, every='epoch', monitor='accuracy', name='derma')])
# Agora, salve como estágio 2...
learn.save('derma-stage-2')
# Deploy definitivo
exportStageTo(learn, path)
93% accuracy!
所以我们第一次运行就达到了 93%的准确率。这很好!在上面的教程和内核中达到的准确率分别是 85%和 86%。
现在让我们看看我们的统计数据。:
interp = ClassificationInterpretation.from_learner(learn)losses,idxs = interp.top_losses()# Test to see if there's not anything missing (must return True)
len(data.valid_ds)==len(losses)==len(idxs)
如果返回 True,则绘制微调网络的混淆矩阵:
interp.plot_confusion_matrix(figsize=(5,5), dpi=100)
在这个矩阵中黑色素瘤的预测看起来更好!让我们看看训练曲线:
learn.recorder.plot_losses()
我们可以看到,训练和验证曲线都在振荡。训练曲线似乎到达了一个平台,并且与验证曲线分离,验证曲线下降得更慢。这表明我们可能正在走向网络的过度拟合。它会被指示到此为止。
在 Colab 网站上我们提供的笔记本中,我们又对网络进行了 30 个纪元的训练,以确保万无一失。它实际上变得更糟,可能是由于过度拟合。所以停在这里对 ResNet34 来说是个不错的选择。
变大:ResNet50
ResNet34 的准确率达到了 92.9%。让我们看看更大的网络能否让我们表现得更好。我们将再次创建 DataBunch,这次使用较小的批处理大小,以避免 GPU 内存过载…
bs = 28 # Batch size, 28 for medium images on a T4 GPU and ResNet50...
size = 448 # Image size, 448x448 is double than the orignal
# ImageNet size of the pre-trained ResNet we'll be using,
# should be easy to train...
path = Path("./data") # The path to the 'train' folder you created...# Limit your augmentations: it's medical data! You do not want to phantasize data...
# Warping, for example, will let your images badly distorted, so don't do it!
# This dataset is big, so don't rotate the images either. Lets stick to flipping...
tfms = get_transforms(flip_vert=True, max_lighting=0.1, max_rotate=None, max_warp=None, max_zoom=1.0)
# Create the DataBunch!
# Remember that you'll have images that are bigger than 128x128 and images that are smaller,
# so squish them all in order to occupy exactly 128x128 pixels...
data = ImageDataBunch.from_csv('data', csv_labels='HAM10000_metadata.csv', suffix='.jpg', fn_col=1, label_col=2,
ds_tfms=tfms, valid_pct = 0.2,size=size, bs=bs)
print('Transforms = ', len(tfms))
# Save the DataBunch in case the training goes south... so you won't have to regenerate it..
# Remember: this DataBunch is tied to the batch size you selected.
data.save('imageDataBunch-bs-'+str(bs)+'-size-'+str(size)+'.pkl')
# Show the statistics of the Bunch...
print(data.classes)
data
现在输出应该是这样的:
Transforms = 2
['akiec', 'bcc', 'bkl', 'df', 'mel', 'nv', 'vasc']ImageDataBunch;Train: LabelList (8012 items)
x: ImageList
Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448)
y: CategoryList
bkl,bkl,bkl,bkl,bkl
Path: data;Valid: LabelList (2003 items)
x: ImageList
Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448),Image (3, 448, 448)
y: CategoryList
nv,nv,nv,mel,bkl
Path: data;Test: None
现在创建一个 ResNet50:
learn50 = cnn_learner(data, models.resnet50, metrics=[accuracy, error_rate])
learn50.model
请注意,我们在指标中包括了准确性,因此我们不需要根据错误率手动执行计算。模型看起来应该是这样的:
Sequential(
(0): Sequential(
(0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU(inplace)
(3): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
(4): Sequential(
(0): Bottleneck(
(conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(downsample): Sequential(
(0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): Bottleneck(
(conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
)
(2): Bottleneck(
(conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
)
)
...
...
...
(1): Sequential(
(0): AdaptiveConcatPool2d(
(ap): AdaptiveAvgPool2d(output_size=1)
(mp): AdaptiveMaxPool2d(output_size=1)
)
(1): Flatten()
(2): BatchNorm1d(4096, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(3): Dropout(p=0.25)
(4): Linear(in_features=4096, out_features=512, bias=True)
(5): ReLU(inplace)
(6): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(7): Dropout(p=0.5)
(8): Linear(in_features=512, out_features=7, bias=True)
)
)
把它学会:
learn50.fit_one_cycle(15, callbacks=[SaveModelCallback(learn50, every='epoch', monitor='accuracy', name='derma50-1')])
# Save weights
learn50.save('derma50-stage-1')
# Deploy the whole network (with the databunch)
exportStageTo(learn50, path)
87.6% accuracy….
看看结果:
interp = ClassificationInterpretation.from_learner(learn50)losses,idxs = interp.top_losses()interp.plot_confusion_matrix(figsize=(5,5), dpi=100)
看看学习曲线:
learn50.recorder.plot_losses()
目前,这并没有给人留下深刻印象:在第一个迁移学习阶段,网络比 ResNet34 振荡得更多,结果即使在数字上更好(85% x 87%的准确率),实际上在混淆矩阵的视觉分析上看起来更差。让我们对 ResNet50 进行微调,看看这是否会产生更好的结果。
我们将在两个实验中完成这项工作。
ResNet50 实验#1:盲接受学习速率建议的微调
当训练一个深度神经网络时,选择一个好的学习速率对于快速收敛和较低的误差都是至关重要的。微调第一步是找到一个合适的学习速率范围:
# Unfreeze the network
learn50.unfreeze()
# Find optimum learning rates
learn50.lr_find()
# Include suggestion=True in order to obtain a suggestion on where to look...
learn50.recorder.plot(suggestion=True)
这将输出:
LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.
Min numerical gradient: 9.12E-07
Min loss divided by 10: 1.10E-07
下限,9.12E-07,我们就上舍入到 1.0E-06。现在,您可以使用我们的经验法则进行微调。我们将使用经验法则定义学习率的范围;以“安全”速率 1e-06 结束;以高一个数量级的速率开始;
# Unfreeze the network
learn50.unfreeze()
learn50.fit_one_cycle(35, **max_lr=slice(1e-5,1e-6)**,
callbacks=[SaveModelCallback(learn50, every='epoch', monitor='accuracy', name='derma50')])# Save the weights of stage 2 each "better" epoch:
learn50.save('derma50-stage-2')
# **Do not** overwrite the stage 1 .pkl with stage 2
# We will need it for the ResNet50 Experiment #2
# exportStageTo(learn50, path)
90% accuracy…
所以,经过 35 个时期和大量的处理,我们达到了 90%的准确率。这看起来没有希望…让我们看看困惑矩阵和学习曲线:
interp = ClassificationInterpretation.from_learner(learn50)losses,idxs = interp.top_losses()interp.plot_confusion_matrix(figsize=(5,5), dpi=100)
learn50.recorder.plot_losses()
我们在这里看到的是一个与 ResNet34 非常不同的结果。对于 ResNet50,网络在微调阶段学习训练集,但它一直在振荡:一些批次使其性能更好,另一些批次使其返回并性能更差。这通常意味着数据质量差,噪音太多。然而,在这种情况下,我们已经看到,我们可以使用 ResNet34 实现 93%的准确性。所以,坏数据不是这里的情况。另一种可能性是,网络有太多的参数,它不是泛化,而是适应训练集的单个实例,从而学习单个实例并去泛化。对于数据集的其他部分,这使得它的性能更差,因此网络就像一个钟摆,在误差空间中来回摆动。验证损失比整个微调过程中的训练损失高得多,证实了对学习曲线的这种解释。
但是我们很固执…让我们做另一个实验。
ResNet50 实验#2:使用手动学习率设置进行微调
在以前的实验中,我们盲目地接受了分析算法的建议,并采用了非常低的学习率。也许这就是学习不好的原因?
如果我们看一下学习率图,我们可以看到一个 平台 已经在大约 1.0E-4 处形成。然后学习率陷入两个低谷,一个在 1.0E-5,另一个在 1.0E-6。如果我们采用更稳定的、平坦的区域,从 1.0E-4 到 1.0E-5,并把它作为我们的学习率范围,会怎么样?
首先,将网络恢复到完成初始迁移学习时的状态:
# Will always load a *path/'export.pkl'* deployment file
learn50 = restoreStageFrom(path)
再次微调,现在用 max_lr=slice(1e-4,1e-5) :
# Unfreeze the network
learn50.unfreeze()
learn50.fit_one_cycle(35, **max_lr=slice(1e-4,1e-5)**,
callbacks=[SaveModelCallback(learn50, every='epoch', monitor='accuracy', name='derma50')])
learn50.save('derma50-stage-2')
exportStageTo(learn50, path)
92.6% accuracy….
让我们来看看结果图:
这些结果比以前好,即使网络振荡很大。然而,混淆矩阵向我们显示,黑色素瘤(这里最重要的病理)的结果并不乐观。
让我们反其道而行之,尝试一个比 ResNet34 小的网络,而不是比 ResNet18 大的。
ResNet18
那么,为什么不尝试一个小得多的网络,看看它的表现呢?让我们用皮肤镜数据来试一试。
为此,我们将更改批量大小并重新生成数据分组。ResNet18s 要小得多,我们将有更多的可用内存,因此使用更大的批处理大小是有意义的:
*bs = 48 # Batch size, 64 for medium images on a T4 GPU and ResNet18...
size = 448 # Image size, 448x448 is double than the orignal
# ImageNet size of the pre-trained ResNet we'll be using,
# should be easy to train...
path = Path("./data") # The path to the 'train' folder you created...# Limit your augmentations: it's medical data! You do not want to phantasize data...
# Warping, for example, will let your images badly distorted, so don't do it!
# This dataset is big, so don't rotate the images either. Lets stick to flipping...
tfms = get_transforms(flip_vert=True, max_lighting=0.1, max_rotate=None, max_warp=None, max_zoom=1.0)
# Create the DataBunch!
# Remember that you'll have images that are bigger than 128x128 and images that are smaller,
# so squish them all in order to occupy exactly 128x128 pixels...
data = ImageDataBunch.from_csv('data', csv_labels='HAM10000_metadata.csv', suffix='.jpg', fn_col=1, label_col=2,
ds_tfms=tfms, valid_pct = 0.2,size=size, bs=bs)
print('Transforms = ', len(tfms))
# Save the DataBunch in case the training goes south... so you won't have to regenerate it..
# Remember: this DataBunch is tied to the batch size you selected.
data.save('imageDataBunch-bs-'+str(bs)+'-size-'+str(size)+'.pkl')
# Show the statistics of the Bunch...
print(data.classes)
data*
创建网络:
*learn = cnn_learner(data, models.resnet18, metrics=[accuracy, error_rate])
learn.model*
该模型将如下所示(注意,这个较小的 ResNet 模型只有 1024 个 out 特性,而不是最后一个块中的 4096 个):
*Sequential(
(0): Sequential(
(0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU(inplace)
(3): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
(4): Sequential(
(0): BasicBlock(
(conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
...
...
...
(1): Sequential(
(0): AdaptiveConcatPool2d(
(ap): AdaptiveAvgPool2d(output_size=1)
(mp): AdaptiveMaxPool2d(output_size=1)
)
(1): Flatten()
(2): BatchNorm1d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(3): Dropout(p=0.25)
(4): Linear(in_features=1024, out_features=512, bias=True)
(5): ReLU(inplace)
(6): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(7): Dropout(p=0.5)
(8): Linear(in_features=512, out_features=7, bias=True)
)
)*
让我们转移-学习 15 个时代:
*learn.fit_one_cycle(15, callbacks=[SaveModelCallback(learn, every='epoch', monitor='accuracy', name='derma-1')])
learn.save('derma-stage-1')
exportStageTo(learn, path)*
85.5% accuracy…
*interp = ClassificationInterpretation.from_learner(learn)losses,idxs = interp.top_losses()interp.plot_confusion_matrix(figsize=(5,5), dpi=100)*
*learn.recorder.plot_losses()*
从数值上看,这比 ResNet34 好 0.5%。让我们看看它在微调后的表现:
*# Unfreeze the network
learn.unfreeze()
# Find optimum learning rates
learn.lr_find()
# Include suggestion=True in order to obtain a suggestion on where to look...
learn.recorder.plot(suggestion=True)*
同样,我们有一条曲线,首先达到一个平台,然后陷入两个洞。只是这里的洞比高地更深。让我们考虑,在这种情况下,空洞是显著的,并接受学习率查找器的建议,使 max_lr=slice(1e-5,1e-6) :
*LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.
Min numerical gradient: 1.32E-06
Min loss divided by 10: 1.58E-07*
*# Unfreeze the network
learn.unfreeze()
learn.fit_one_cycle(35, **max_lr=slice(1e-5,1e-6)**,
callbacks=[SaveModelCallback(learn, every='epoch', monitor='accuracy', name='derma18')])learn.save('derma18-stage-2')exportStageTo(learn, path)*
88%的准确率!那比 ResNet34 差多了。让我们绘制学习曲线:
*learn.recorder.plot_losses()*
我们在这里看到的是,当我们以太小的学习率训练它时,ResNet18 比 ResNet50 振荡得更多。这表明这里的学习率也太小了。
我重复了我们之前对 ResNet50 进行的微调实验#2,并将学习率范围设置为 max_lr=slice(1e-4,1e-5) ,并再次训练它。在这种情况下,ResNet18 实现了 0.904643 的验证精度。结果图形如下所示:
**
这比以前好,但仍比 ResNet34 和 ResNet50 差。ResNet18 似乎不是解决这个问题的好选择。代码在我们的笔记本里。
如果培训中途中断,我该怎么办?
如果你的训练被打断了,你会怎么做?这可能是因为你在 Google Colab 笔记本上达到了连续 12 小时的“免费”操作时间,或者因为你的计算机由于某种原因停止了。我住在巴西,电力短缺是常事…
fit_one_cycle 方法适用于变化的自适应学习速率,遵循速率先增大后减小的曲线。如果你中断第 10 个纪元的训练,比如说 20 个纪元,然后重新开始 9 个以上的纪元,你将不会得到与不间断训练 20 个纪元*相同的结果。您必须能够记录您停止的位置,然后从该点重新开始训练周期,并使用该周期部分的正确超参数。*
A fit_one_cycle training session divided into three subsessions. Image by PPW@GitHub
你要做的第一件事就是保存你的网络:
*learn.fit_one_cycle(20, max_lr=slice(1e-5,1e-6),
callbacks=[SaveModelCallback(learn, every='epoch',
monitor='accuracy', name='saved_net')])*
这将使您的网络在每个纪元都被保存,您提供的名称后面跟着_ #纪元。所以在纪元#3,文件 saved_net_3.pth 将被写入。您可以在完成以下操作后加载此文件:
- 重新创建了数据束和
- 用它重新实例化了网络。
重装完后。pth* 文件,你可以重新开始你的训练,只是你要告诉 fit_one_cycle 考虑 20 个历元,但是要从历元#4 开始训练。*
要了解这是如何做到的,请看这里:
- 把一个长周期的政策分成几个小周期——PPW 的 GitHub
你是怎么做到的?
fast.ai 中的 fit_one_cycle 方法已经开发出来,允许您告诉它从周期的哪个部分恢复中断的训练。恢复培训的代码如下所示:
*# Create a new net if training was interrupted and you had to
# restart your Colab sessionlearn = cnn_learner(data, models.<your_model_here>,
metrics=[accuracy, error_rate])# If you're resuming, only indicating the epoch from which to
# resume, indicated by ***start_epoch=<epoch#>*** will load the last
# saved .pth, it is not necessary to explicitly reload the last
# epoch, you only should **NOT** change the name given in
# name=<callback_save_file>:
# when resuming fast.ai will try to reload
# ***<callback_save_file>_<previous_epoch>.pth***
# Unfreeze the network
learn50.unfreeze()# Use start_epoch=<some_epoch> to resume training...
learn.fit_one_cycle(20, max_lr=slice(1e-5,1e-6),
***start_epoch=<next_epoch#>***,
callbacks=[SaveModelCallback(learn,
every='epoch', monitor='accuracy',
***name=<callback_save_file>***)])*
fast.ai 会告诉你“载入<回调 _ 保存 _ 文件> _ <上一个 _ 纪元# >* ”,恢复训练。*
您可以在此查看 fit_one_cycle 方法支持的所有参数:
- https://docs.fast.ai/train.html#fit_one_cycle
我们取得了什么成就?
使用 448x448 的图像分辨率和 fast.ai,我们在实验中使用的三个网络模型中的两个(ResNet34 和 ResNet50)获得了大约 93%的验证准确性。这比上面教程的 85%要好得多,上面的教程使用了 MobileNet,图像分辨率为 224x224,Keras。(目前)ka ggle(employees tensor flow . js)上投票最多的内核获得了 86%的精度。
在任务#3 的 ISIC 2018 挑战赛最终测试中,排名最高的竞争对手,来自【MetaOptima Technology Inc .【的 Jordan Yap 取得了 95.8% 的准确率和由 ISIC 选择的竞争对手评估标准的平衡多类准确率 88.5%。Jordan Yap 采用的方法基于:**
- 附加的外部数据[33,644 张图像];
- 相当于原始 ImageNet 分辨率的低分辨率图像;
- 19 种分类算法的集合,其中一种不是神经网络(直方图分析);
- 一个 XGBoost 分类器,它在这个集成的结果之上被训练。
Aleksey Nozdryn-Plotnicki, Jordan Yap, and William Yolland, MICCAI, 2018
Aleksey Nozdryn-plot nicki、Jordan Yap 和 William Yolland 提交给 ISIC 皮肤图像分析研讨会和 Challenge @ MICCAI 2018 的论文及其结果在此。
我们的结果与最初的 ISIC 2018 挑战赛没有直接可比性,因为 ISIC 提供了从 HAM1000 数据集手动提取的 1512 幅图像的测试集,所有竞争对手都必须采用该测试集并将其结果提交给 ISIC。我们使用从 HAM1000 数据集中随机提取的一组 2003 张图像来验证我们的训练,并使用剩余的 8012 张图像来训练我们的网络。
Statistics of Jordan Yap from MetaOptima Technology Inc.
您可以在此查看 ISIC 2018 结果:
- ISIC 2018 —任务 3:最终测试
- ISIC Challenge 2018 排行榜(点击“任务 3”窗格)
然而,有趣的是,我们在 NVIDIA T4 GPU (4.2 x 10 + 4.3 x 35 分钟)上使用 fast.ai 和一个网络 ResNet34 以及总训练时间为 190 分钟的获得的 92.9% 的准确性,仅比 ISIC 2018 挑战赛最高排名的竞争对手使用更复杂的方法获得的准确性差 2.9%
这很可能是因为我们采用了两倍的图像分辨率,允许更多的细节,但 fast.ai 中的 HYPOs(超参数优化)可能也发挥了作用。
我们学到了什么?
ResNet34 入手是个不错的选择:ResNet 在 fast.ai 中确实管理的很好,有各种好用的 HYPOs(超参数优化)。如果你不知道使用哪种网络,可以使用 ResNet34,它足够小,即使你在家里使用 GPU 也可以相对快速地进行训练,但也足够大,可以表示一大组问题。ResNet34 trains 将如何提供提示,如果你应该与你的网络规模上升或下降。
盲目接受学习率建议并不总是最佳选择:resnet 50 的 lr_find() 产生了一个很长的平稳期,该方法在图形左端的一个小山谷中建议了一个非常低的学习率值。当我们用这个值训练网络时,它会振荡,没有产生好的结果(只有 90%的准确率)。当我们对图表进行可视化分析,并将一个高一个数量级的值作为学习率范围的下限时,该值位于平台较平坦部分的开始,ResNet50 学习得更好,并达到与 ResNet34 相同的 93%的准确率。所以,使用建议=真模式,但是在你接受它之前给它一个严肃的处理,实际上看着图形。这是学习率范围的第二条经验法则:查看整个图形并找到真正的平稳段——学习率范围的理想下限将位于该平稳段的开始处。
方法learn . lr _ find()帮助你找到一个最优的学习率。它使用了 2015 年论文中开发的技术,用于训练神经网络(http://arxiv.org/abs/1506.01186)的循环学习率,我们只是从一个非常小的值开始增加学习率,直到损失开始减少。如果你想知道更多关于寻找最佳学习率的信息,请看这里:
- 迈向数据科学:用 LR-Finder 加速神经网络训练——为你的网络找到良好的初始学习速率作者 Faizan Ahemad
越大并不总是越好:最终,ResNet50 的表现几乎与 ResNet34 相同,但训练时间要长得多,结果也稍差。用大型网络模型开始您的培训空间探索是一个糟糕的选择。
图像分辨率发挥作用:我们采用了 ISIC 2018 挑战赛最高排名竞争对手的两倍分辨率,通过一个相对简单的 ResNet34 获得了可比的结果,而该竞争对手在 18 个不同的网络上采用了机器学习方法,包括一个巨大的 ResNet152。
Fast.ai 很快:最后,与其他方法相比,使用 fast.ai 我们能够使用更少的代码解决相同的分类问题,同时使用高级超参数优化策略,使我们的训练速度更快。同时,一组高级功能也允许我们以表格和图形的形式轻松检查结果。这种简单性使我们可以用三种不同的网络模型进行实验,并比较它们的结果。这表明 fast.ai 是更传统的 CNN 框架的一个非常有前途的替代方案,特别是如果手头的任务是图像分类、对象检测或语义分割等“标准”深度学习任务,可以通过微调现成的预训练网络模型来解决。
承认
这项工作是除我之外的一组积极参与的研究人员共同努力的结果:
- 丹尼尔·霍尔特豪森努内斯<daniel@floripa.com.br
- 路易斯·安东尼奥·布舍托·马卡里尼<
- 马塞洛里卡多斯特梅尔<马塞洛. stemmer @ ufsc . br
我们还要感谢于尔根·克鲁施<、juergen.kreusch@gmail.com>和路易斯·费尔南多·科普克< 、luiskopke@uol.com.br>提供的立体皮肤镜材料。
参考
[1]Kreusch,J. 入射光显微术:对活体皮肤显微术的思考 。国际皮肤病学杂志。 1992 年 9 月;31(9):618–20.
[2]Kopke,L.F. 皮肤镜在基底细胞癌早期发现、控制和手术规划中的作用 。2011 年皮肤美容外科手术;3(2):103–8.
高维时间序列的深度学习
原文:https://towardsdatascience.com/deep-learning-for-high-dimensional-time-series-7a72b033a7e0?source=collection_archive---------8-----------------------
Time series of some monitoring system
降维、嵌入、预测
ime 系列数据在机器人、金融、医疗保健和云监控等重要应用中非常普遍。在这些应用中,我们通常会遇到维数非常高的时间序列,其中 ML 任务是在强化学习代理中执行信号表征的分类、预测的回归或函数逼近。
尽管时间序列数据有很多重要的应用,但是对于这种输入类型,ML 的文献并不多。此外,大多数 ML 算法都有一个基本假设,即样本是独立同分布的(iid),但对于大多数时间序列来说,情况并非如此。更令人沮丧的是,使用深度学习找到高维时间序列的研究或例子更是凤毛麟角。因此,这篇文章讨论了当数据是高维时间序列时,可以应用于执行常见的无监督和有监督学习任务的技术。它假设你有深度学习的经验,现在正在寻找涉及时间序列输入的问题的解决方案。
帖子的最后附有一个 Jupyter 笔记本中的例子,其中讨论了一些最重要的问题。
简而言之,时间序列基本原理
我们来复习一些基础知识。时间序列建模一直是不同研究社区的研究主题,包括统计学、信号处理、经济学、金融学、物理学、机器人学和在线机器学习。从根本上说,大部分工作都遵循对问题的概率处理。此外,应用社区有他们自己的技术,可能会使用深度学习来解决你的问题。 重要的方面是,在使用深度学习之前,你必须知道手头的时间序列问题的概率性质。
形式上,我们将时间序列定义为时间序列中的一系列观察值,如下所示
这里 d 是尺寸(或特征的数量),而 t 是每个时间步的索引。
什么是高维时间序列?
高维输入是指 d 相对较大的输入。请注意,行空间 t 是时域中的样本数,并不表示高维度(这意味着您可以对小数据集使用高维度)。如此高的维数给 ML 带来了问题,因为维数灾难,也因为许多特征向量可能变成噪声。因此,如果我们不减少原始输入的维度,我们很可能会过度拟合。
统计时间序列建模:
在经典范式中,时间序列被建模为随机变量序列{ X _t}(注意这不同于原始观察值{ x _t}),均值和协方差定义为
这种形式的模型被称为随机过程。此外,时间序列被分成几个部分:趋势、季节性、周期和残差。选择的统计模型是 ARMA 和 ARIMA 的变体,分别用于平稳过程和非平稳过程。
现在,一个重要的定义。定义:(弱)平稳时间序列是数据生成过程不随时间变化的序列。由此可见,非平稳过程违反了平稳性的定义,因此其概率分布会随时间而变化。ARMA 和 ARIMA 模型已经被广泛使用了几十年,但它们对线性度做了强有力的假设,这可能不会对复杂过程产生可接受的预测。这种经典统计处理的重要方面是认识到我们需要基于数据生成过程的不同概率模型,即在我们开始学习部分之前识别输入的平稳或非平稳程度。
状态空间和马尔可夫模型:这些模型最初是为控制应用开发的,比线性 ARMA 和 ARIMA 模型更强大。它们包括著名的卡尔曼滤波器和隐马尔可夫模型(hmm)。对于某些应用,hmm 及其变体仍然是深度神经网络的一个很好的替代方案。为了做出预测 y ,我们在距离t:h的某个水平上寻找条件后验概率
深度学习建模:
对于大多数时间序列,我们需要一些时间相关性来进行预测。在特殊情况下,我们可以简化时间序列,假设它满足马尔可夫性。这个假设意味着状态 X _t 是完整的——即,它编码了预测未来 X _{t+1}的所有必要信息,并且过去和未来的状态是独立的。我们将违反马尔可夫假设,而是假设我们具有长期的时间依赖性——其中我们需要状态的先前 k 步,即 X _{t-k:t}或某个重要的过去状态 X _q。现在,为了使用有区别的监督 ML 模型进行预测,我们寻求近似后验概率分布 P( y | X _)我们通过在训练期间最大化可能性来做到这一点——或者等效地最小化批量或随机机器学习框架中的损失。
ML 中的非平稳性:当输入中存在认知不确定性或非平稳性时,会出现额外的困难。如果是这种情况,在训练之前需要进行额外的信号处理,并且/或者机器学习框架必须从批处理变为在线。我将把信号处理部分排除在这篇文章之外,但是强调一下 ML 批处理框架中的假设。对于批量学习,我们假设训练集和测试集的分布属于同一个数据生成过程。因此,如果您有一个固定的过程,比如说一个云监控系统,那么就有 PAC 学习保证。另一方面,如果你有一个非平稳过程,比如说一个股票市场,那么就没有 PAC 学习保证。在后一种情况下,您无法使用批量 ML 框架进行良好的样本外预测。现在,许多人不知道,批量学习是 ML 的默认选项。另一方面,在线学习适合于顺序学习,因为它不对输入的概率分布做出假设——事实上,数据生成过程甚至可能是对抗性的。因此,对输入的概率不做任何假设的在线学习框架是非平稳过程的最佳选择,但即使如此也是一项重要的任务。(此处阅读后悔最小化)。
ML 中的顺序相关性:在前向神经网络中,训练集中的每个样本都被认为是 iid。因此,如果输入是一个时间序列,数据的时间依赖性就会被打破。这个问题的解决方案直接通过在现代版的 LSTM(或 GRU)细胞中使用递归神经网络来解决。另一种不太用于时间序列的方法是 CNN,因为它们也被证明在对时间序列输入进行预测方面是成功的——毕竟,图像具有空间依赖性。
转换:现在,在用 LSTMs 或 CNN 进行预测之前,我们必须对我们的高维时间序列问题进行一些转换。首先,必须减少高维输入的大小。其次,它必须以预测器可接受的形式嵌入。对于第一个任务,一个常见的误解是,由于 CNN 对图像进行无监督的特征提取,我们可以对时间序列输入进行同样的处理。如果我们处理的是可能成千上万的额外的不相关和有噪声的特征,情况就不一样了。因此,无论是否使用 CNN,最好在训练模型之前进行降维。因此,我从降维技术开始。
降维
降维的任务是将一个高维空间投影到一个仍然可以解释数据的低维子空间中。从几何学上讲,将原始输入 X ∈ ℝ^{n × d}视为一个 d 维的超立方体,您希望将超立方体缩减为一个低维流形x'∈ℝ^{n×p },该流形对原始超立方体的信息进行编码。缩减后的维度 p<d<
如前所述,时间序列具有样本之间的时间相关性。然而,时间相关性对于维数约减通常无关紧要。因此,我们可以使用原始 2D 输入来降低维数。对于时间序列输入的降维,我们有几个选择。一些常见的选项,按难度排序如下:
基本:
- 奇异值分解、主成分分析、独立分量分析(无监督):
奇异值分解是一种经典的矩阵代数方法,是任何矩阵降维的基础。PCA 被定义为协方差矩阵的特征向量,但也可以被视为截断的 SVD。在 PCA 中,主成分是数据的一系列正交投影(即,相互不相关),并根据它们的方差排序。在 ICA 中,我们找到了一个降维子空间,其中的分量在统计上是独立的。
适中:
中等方法适用于基本方法不太适用的非线性数据。
- KPCA(非线性数据)
PCA 的内核化版本。
- Isomaps
Isomaps 产生一个低维表示,保留数据流形上的测地线或“行走距离”。
高级:
- 自动编码器:
对于自动编码器,我们通过使用具有编码器和解码器的深度神经网络来学习低维特征空间。这里,我们通过在逐渐减少和增加层的大小之后,强制神经网络再现相同的输入来压缩数据。
Autoencoders schematic representation (Wikipedia)
- 变分自动编码器
可变自动编码器是自动编码器的生成版本。Keras 中自动编码器和 VAEs 的一个例子是这里的。
Visualization of a multi-dimensional hypercube — although they cannot really be visualized beyond 3D.
我建议你至少采用两种方法,并与同一学习者比较样本外的准确性。在提供的示例中,维度从 2000 减少到 100。
特征选择
特征选择是一个优化问题,它寻求从原始空间中找到提高预测性能的重要特征的最小子集。这一过程有两个不同于降维的含义:(1)原始特征向量按某种重要性度量排序,所选子集保持与原始数据相同的形式;(2)一般涉及监督程序。对于高维时间序列数据,以下方法通常比过滤器或包装器方法更可行。
- 收缩方法(监督)
收缩方法通过对不太重要的特征施加权重惩罚来减少特征的数量。最常见的是套索和岭回归。如果这些方法在损失目标中包括 L1 或 L2 正则化,则通过神经网络的正则化隐含地包括这些方法。
- 树形方法(有监督的)
树方法,例如随机森林,使用熵度量来进行分类或回归的分割。这些分割进而可以给出关于如何对所选子集的特征进行排序的信息。
时间序列的嵌入
在本节中,我们讨论如何将每个 序列的嵌入或编码到预测器的适当表示中。* 为了形象化这一点,把你的多变量时间序列序列 Q 想象成一个需要分类的图像。 现在,如果时间序列输入在每个时间步不包含实值向量(例如文本),每个时间步必须首先嵌入到某个实值表示中(例如使用 Word2Vec)。所以在本节中,我们指的是时序序列的嵌入。然后,对于接下来的内容,我们假设每个时间步长已经是实值表示。*
转换成 LSTM 的三维张量
如果我们在回归设置中,我们试图预测未来的时间步长,或者作为 RL 代理的函数逼近器,LSTMs 工作得更好。如果我们使用 LSTM 作为预测器,我们不需要嵌入输入本身,但我们需要将其重新整形为 3D 张量。这很简单。
输入形状和序列长度:为了考虑输入矩阵 X 的顺序性质,需要将其整形为 3D 张量
其中 n 是序列的个数, t 是每个序列的时间步数, d 是序列的维数。
因此,我们需要通过领域专业知识、试错法或信号处理来先验地确定对预测很重要的序列长度(时间步数)。序列的长度可以是固定的或可变的。
嵌入图像
这种嵌入通常是:(a)将时间序列转换到频域,然后将其嵌入到图像中,或者(b)使用递归图。生成的图像稍后可以用基于 CNN 的架构进行分类。如果做得正确,我发现(b)是用 DL 对信号进行分类(或表征)的更好技术。
这方面的文献大多是把一个单变量时间序列嵌入到一个图像中(把单变量时间序列嵌入到一个图像中的好论文是这里是)。麻烦在于将多变量时间序列转换成等价的图像。我想到了一些想法。同样,我们可以采用频域方法,将多元时域输入转换为频谱图,然后将其嵌入图像。然而,转换到频域时,我们会丢失信息。因此,优选的方法是通过取每个单变量递归图的逐项乘积,将多变量输入转换成 2D 递归图。在此之前,将时间序列整形为 3D 张量,然后将每个 2D 序列转换为递归图。
嵌入到图中
在一些应用中,例如僵尸网络检测,输入由随时间变化的图形组成。一般来说,当您的时间序列输入中存在可以编码到图形中的关系时,您可以进行动态图形嵌入。然而,动态图嵌入必须与神经网络兼容,因为我们不能以简单的方式使用图作为神经网络的输入。幸运的是,最近有一些框架允许这样做,其中最好的一个是 Structure2Vec ,它允许端到端的培训。有关信息论方法,请参见有向信息图。
具有时间序列输入的深度学习预测
第一步是决定你是否需要 DL。如果你的时间序列问题相对简单(即,不是高维、平稳、线性的),那么使用 ARMA 或 ARIMA 可能会产生良好的预测(见脸书的预言家)。如果不是,你很幸运,我们现在有函数逼近器(DL!)可用于时间序列输入。请记住,如前所述,时间序列输入依赖于几个先前的时间步长。同样,第一个任务是减少输入的维数,然后我们执行嵌入。之后,我们准备使用一个 DL 模型来进行预测。
LSTM 模型
LSTM 模型是最流行的时间序列输入模型。这是因为 LSTMs 被设计成记住长期依赖关系,并且在多个应用中显示出巨大的成功,最重要的是在 NLP 中。它们是回归的首选模型,也适用于分类。至此,您已经知道,对于高维时间序列,我们首先降低其维度,然后对于 LSTMs,我们将输入重塑为 3D 张量。
CNN 模型
CNN 模型是图像分类的首选机器。当序列作为图像嵌入时,它们已经被证明是时间序列输入的良好预测器。如果我们想对每个序列进行分类,而不是对未来进行预测,那么 CNN 是一个很好的选择。在降低原始输入的维数后,我们将它嵌入到一个图像或一个兼容的图形中。你要避免的事情是获取原始时间序列输入,然后执行 2D 卷积。
W 注意:对原始时间序列输入应用 2D 卷积是没有意义的。
结论
我们看到高维时间序列不同于深度学习文献中常见的其他输入类型。为了使用深度学习模型进行回归或分类,第一步是采用适当的技术来降低输入的高维度。第二步是对序列使用合适的嵌入,以便 LSTM 或 CNN 可以处理时间相关性。最后,我们必须知道数据生成过程的性质,以便选择正确的学习模型和范例。如果过程是非平稳的,使用批量 ML 将不能很好地推广,在线 ML 方法是更可行的选择。将在线机器学习范式用于深度神经网络是另一篇文章的主题。
这里有一个 Jupyter 笔记本上的例子,它使用了我们讨论过的一些方法。
深度学习在卫星图像冰山检测中的应用
原文:https://towardsdatascience.com/deep-learning-for-iceberg-detection-in-satellite-images-c667acf4bad0?source=collection_archive---------19-----------------------
卫星图像的深度学习
Photo by Agnieszka Mordaunt on Unsplash
被困在付费墙后面?点击这里阅读完整故事与我的朋友链接!
本博客的主要目的是开发利用卫星雷达数据和可见光谱范围内的高空间分辨率图像探测冰山的方法。卫星监测危险冰结构的方法,如北冰洋的冰山,对航行安全和北极大陆架的经济活动构成了威胁。
开发的冰山探测方法是基于在卫星图像的二维场分析中寻找梯度带的统计标准。所提出的从卫星数据探测冰山的方法可以提高为广大用户提供服务的质量和效率,同时确保北极航行和北极大陆架活动的效率和安全。
该项目是在 Kaggle 举行的 Statoil/C-CORE 冰山分类器挑战赛的一部分。
挑战
建立自动识别遥感目标是否为冰山的算法。冰山经常被误认为是一艘船。该算法必须非常精确,因为生命和数十亿美元的能源基础设施正处于危险之中。
环境和工具
- sci kit-学习
- numpy
- 克拉斯
- 熊猫
- matplotlib
数据
数据集可以从 kaggle 网站下载,可以在这里找到。
三种情况
- 开阔水域中的冰山:在光学图像中,冰山会在黑暗的背景下显示出亮点,较高的风力会降低开阔水域和冰山之间的对比度。
- 漂流冰中的冰山:如果有更大的固结冰,冰山会在漂流冰中留下痕迹。如果只有反向散射信息,在光学图像中很难区分冰山和背景。
- 冰解区域附近的快速冰中的冰山:光学数据显示背景上的阴影,静止的冰意味着可以在更长的时间内识别冰山。
方法学
Methodology of iceberg detection in satellite images
代码在哪里?
事不宜迟,让我们从代码开始吧。github 上的完整项目可以在这里找到。
让我们从加载所有的库和依赖项开始。
接下来,我加载了 json 格式的训练和测试集图像。
然后我定义了训练和测试集数据。我将数据分成 3:1,即 75%作为训练集,其余作为测试集。
适合的
在训练之前,模型对于定义一个或多个回调是有用的。相当好用的一个,有:ModelCheckpoint
和EarlyStopping
。
- ModelCheckpoint :当训练需要大量时间来达到一个好的结果时,通常需要多次迭代。在这种情况下,最好仅在改善度量的时期结束时保存最佳执行模型的副本。
- 提前停止:有时,在训练过程中,我们可以注意到泛化差距(即训练和验证误差之间的差异)开始增大,而不是减小。这是过拟合的症状,可以通过多种方式解决(减少模型容量、增加训练数据、数据扩充、正则化、放弃等)。通常,一个实用而有效的解决方案是在泛化差距越来越大时停止训练。
Early stopping
让我们继续定义模型。这可以总结为以下 5 个步骤-
- 我使用了两个卷积层,后面是一个最大池层,再后面是另一个卷积层。我在中间使用了 20%的压降来减少过度拟合。
- 为了更好地概括结果,我对四个堆栈重复了同样的操作。
- 此外,我还使用了 globalmaxpooling 和批处理规范化层来规范化从前面的层中得出的权重。
- 最后一层是致密层,以 sigmoid 为激活函数。
- 最后,我使用 Adam 作为优化器,使用二元交叉熵作为损失函数。
让我们以 32 的批量为 20 个时期训练模型。请随意使用超参数以获得更好的效果。
最后,让我们来看看结果。
结果
loss vs epoch
accuracy vs epoch
训练集和测试集的损失值收敛得相当好。此外,该模型能够在仅仅 10 个时期内分别实现 90%和 85%的训练和测试集精度。
结论
我认为这是深度学习可以用来解决具有挑战性的现实世界问题的一个很好的例子。如果我们能够检测和分割图像中的冰山,这将对瑞典、挪威和加拿大等北方国家的物流和运输团队有很大的帮助。它可以通过实时跟踪卫星图像和视频中的冰山,为集装箱船和船只带来全新的运输方式。
参考资料/进一步阅读
[## 应用于阿蒙森海的基于目标的 SAR 图像冰山检测算法
提出了一种基于对象的高级合成孔径雷达(ASAR)图像冰山自动检测方法
www.sciencedirect.com](https://www.sciencedirect.com/science/article/pii/S0034425716304527) [## 南极威德尔海两个试验区合成孔径雷达图像中的冰山特征和探测
南极威德尔海两个试验区域合成孔径雷达图像中的冰山特征和探测
www.cambridge.org](https://www.cambridge.org/core/journals/journal-of-glaciology/article/iceberg-signatures-and-detection-in-sar-images-in-two-test-regions-of-the-weddell-sea-antarctica/963162FAE7965080AD5E8827C8FDCF6C) [## 用于监测南极冰川融化的哨兵 1 号图像
全球变暖对地球的寒带并不友好,导致极地冰盖加速融化。的…
eos.com](https://eos.com/blog/sentinel-1-imagery-for-monitoring-the-antarctic-glaciers-melting/) [## 在英特尔架构上使用深度学习进行冰山分类
探测不力和漂流冰山是海洋安全和物理海洋学的主要威胁。为了监控和…
software.intel.com](https://software.intel.com/en-us/articles/iceberg-classification-using-deep-learning-on-intel-architecture)
在你走之前
相应的源代码可以在这里找到。
[## abhinavsagar/ka ggle-教程
Kaggle 竞赛笔记本样本。显微图像的自动分割是医学图像处理中的一项重要任务
github.com](https://github.com/abhinavsagar/Kaggle-tutorial)
联系人
如果你想了解我最新的文章和项目,请关注我的媒体。以下是我的一些联系人详细信息:
- 个人网站
- 领英
- 中等轮廓
- GitHub
- 卡格尔
快乐阅读,快乐学习,快乐编码。
用于图像识别的深度学习:具有 Tensorflow 和 Keras 的卷积神经网络
原文:https://towardsdatascience.com/deep-learning-for-image-recognition-convolutional-neural-network-with-tensorflow-de6349c31c07?source=collection_archive---------14-----------------------
使用 Python 从头开始构建您的神经网络
深度学习是机器学习的一个子集,其算法基于人工神经网络中使用的层。它有各种各样的应用,其中包括图像识别,这就是我们在这篇文章中要讨论的。
为了展示如何构建、训练和预测你的神经网络,我将使用 Tensorflow,你可以通过 pip 在你的 Jupyter 笔记本上轻松运行它。
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import numpy as np
import pydot_ng as pydot
然后,我将使用 Keras(一个可以从 Tensorflow 导入的开源包)库中可用的数据集之一,其中包含一组我们的算法将被训练的图像。让我们下载并先看看我们的数据:
from keras.datasets import cifar10
*#I'm dividing my data into training and test set*
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train.shape, x_test.shape, y_train.shape, y_test.shape
正如你所看到的,在我们的 x 训练集中,我们有 50000 幅图像,每幅 32×32 像素,有 3 个通道(与 x 测试集相同,但只有 10000 个观察值)。另一方面,我们的 y 集合是从 0 到 9 的数字数组,对应于我们的类。所以我们可以从创建一个相应类别的向量开始,然后分配给我们的预测。此外,我们还可以再设置两个变量:
- 时期:训练时我们的神经网络的迭代次数
- batch_size :我们希望每个时期使用的样本数量
batch_size=32
epochs=3
class_names = ["airplane","automobile","bird","cat","deer","dog","frog","horse","ship","truck"]
因为我首先想以一种非常直观的方式展示这个过程,所以我将对我的图像进行调整,从 3 通道图像调整到 1 通道图像(也就是说,从彩色到黑白)。通过这样做,我们将能够可视化卷积、汇集和完全连接的整个过程(稍后我将解释这三个步骤)。
我们将在这项任务中使用的算法是卷积神经网络。我不打算在它背后的数学上花太多时间,但是我想提供一个关于它如何工作的直观想法。
所以,让我们一起来看看这张图片和下面的脚本(我将一步一步地解释)。在图中,我检查了一个简单的任务:我们有一个由四个字母组成的字母表——A、B、C 和 D——我们的算法被要求识别我们的输入字母(在我们的例子中,是“C”)。另一方面,脚本中构建的算法引用了我们的数据集,因此输出向量将有十个而不是四个条目。然而,底层过程是相同的。
model=tf.keras.Sequential() model.add(tf.keras.layers.Conv2D(32,kernel_size=(3,3),activation='relu',input_shape=(32,32,1))) model.add(tf.keras.layers.MaxPooling2D(pool_size=(2,2))) model.add(tf.keras.layers.Flatten()) model.add(tf.keras.layers.Dense(1024,activation='relu')) model.add(tf.keras.layers.Dense(10,activation='softmax'))
让我们解释每一段:
- 卷积:图像由一个过滤器检查,它能够将输入图像分割成更小的部分,返回一个所谓的特征图(更准确地说,它返回的特征图与使用的过滤器数量一样多)。为了得到这个过滤过程的输出,我们需要一个所谓的激活函数。激活函数映射结果值,即在 0 到 1 或-1 到 1 之间,依此类推(取决于函数)。在我们的例子中,ReLU 函数简单地将任何负值归零;
- 池化:这一步的主要目标是通过一个函数减少我们的特征图的大小(在这种情况下,我们使用了一个‘max’函数:它返回被检查的那些中最高的像素值);
- 全连接:全连接层的目的是使用那些特征,根据训练数据集将输入图像分类成各种类别。在这一步中,在将我们的矩阵形状的图像转换成数字数组之后,我们再次应用一个激活函数,然后获得一个概率向量作为最终输出,该向量与类的向量一样长。事实上,我们使用的激活函数,称为“softmax”,将输入转换成一个概率范围。范围从 0 到 1,当然,所有概率的总和等于 1。在我们的例子中,由于它是一个多分类任务,这个函数返回每个类的概率,目标类将具有最高的概率。
我们 CNN 的主要目标是产生一个尽可能接近真实的预测结果。此外,该算法一旦被评估,就能够通过重新加权一些参数并最小化误差项来从其过去的路径中学习。这种操作称为反向传播。
为了实施,反向传播需要另外两个要素:
- 损失函数:衡量模型的一致性。当拟合值远离实际值时,它返回较大的值。在线性回归模型中广泛使用的典型损失函数是均方误差(MSE)。在我们的例子中,我们将使用分类交叉熵函数。
- 优化器:为了最小化误差,需要修改权重,我们可以通过使用一类称为优化函数的函数来实现。优化函数通常计算损失函数相对于权重的偏导数(称为梯度),并且权重在计算的梯度的相反方向上被修改。重复这个循环,直到我们达到损失函数的最小值。在我们的例子中,我们将使用 Adam 优化器。
model.compile(loss='categorical_crossentropy', optimizer=tf.keras.optimizers.Adam(lr=0.001,decay=1e-6), metrics=['accuracy'])
请注意,参数“度量”作为损失函数,是衡量模型性能的一种方式。但是,它不会影响训练过程(而损失函数会影响)。
现在,我们可以训练我们的模型,并在我们的测试集上验证它(总是将其重塑为单通道数据集):
*#I'm dividing my train and test set by 255, since I want to normalize the value of each pixel (ranging from 0 to 255)*
model.fit(np.resize(x_train, (50000,32,32,1))/255.0,tf.keras.utils.to_categorical(y_train),
batch_size=batch_size,
shuffle=True,
epochs=epochs,
validation_data=(np.resize(x_test, (10000,32,32,1))/255.0,tf.keras.utils.to_categorical(y_test))
)
请原谅这个模型这么差(准确率达到了 10.74%的尴尬值),但是我要求只迭代 3 次,减少通道。事实上,第一种方法的目的只是可视化这个过程。
keras.utils.plot_model(model,show_shapes=True)
首先,我们将 3×3 滤波器应用于输入图像。该操作返回 32 个特征地图,每个 30×30 像素。然后,我们使用大小为 2×2 的池过滤器将图像的尺寸从 30×30 减小到 15×15(这意味着,我们的池过滤器一次将检查四个像素,仅返回等于其评估的最大值的一个像素)。
现在让我们用 3 通道图像训练模型。首先,我们可以看看我们将要分析的图像类型:
plt.imshow(x_train[12])
plt.title(class*_names[y_*train[12:13][0][0]])
现在,让我们再次在 3 通道图像上训练我们的神经网络(添加一些修改):
model.add(tf.keras.layers.Conv2D(32,kernel_size=(3,3),activation='relu',input_shape=(32,32,3))) model.add(tf.keras.layers.MaxPooling2D(pool_size=(2,2)))
*#I'm adding two Dropout layers to prevent overfitting* model.add(tf.keras.layers.Dropout(0.25)) model.add(tf.keras.layers.Flatten()) model.add(tf.keras.layers.Dense(1024,activation='relu')) model.add(tf.keras.layers.Dropout(0.5)) model.add(tf.keras.layers.Dense(10,activation='softmax'))
让我们编译它,记住上面关于损失函数和优化器的所有考虑:
model.compile(loss='categorical_crossentropy', optimizer=tf.keras.optimizers.Adam(lr=0.001,decay=1e-6), metrics=['accuracy'])
model.fit(x_train/255.0,tf.keras.utils.to_categorical(y_train), batch_size=batch_size, shuffle=True, epochs=epochs, validation_data=(x_test/255.0,tf.keras.utils.to_categorical(y_test)) )
我们现在可以在验证测试中对其进行评估(并对其进行预测):
predictions=model.predict(x_test)
scores = model.evaluate(x_test / 255.0, tf.keras.utils.to_categorical(y_test))
不错,准确率提高到 63.87%。让我们比较一些预测:
*#I'm defining a function that plot my predicted image, with true #label as title*
def plot_pred(i,predictions_array,true_label,img):
predictions_array,true_label,img=predictions_array[i],true_label[i:i+1],img[i]
plt.grid(False)
plt.title(class_names[true_label[0][0]])
plt.xticks([])
plt.yticks([])
plt.imshow(img)
*#I'm defining a function that plot my prediction vector, showing #whether my*
*#predicted value is correct (in blue) or incorrect (in red)*
def plot_bar(i,predictions_array,true_label):
predictions_array, true_label = predictions_array[i], true_label[i]
plt.grid(False)
plt.yticks([])
plt.xticks(np.arange(10),class_names,rotation=40)
thisplot=plt.bar(range(10),predictions_array, color='grey')
plt.ylim([0,1])
predicted_label=np.argmax(predictions_array)
if predicted_label==true_label:
color='blue'
else:
color='red'
thisplot[predicted_label].set_color(color)
*#plotting both the images*
plt.figure(figsize=(15,6))
plt.subplot(1,2,1)
plot_pred(10, predictions, y_test, x_test)
plt.subplot(1,2,2)
plot_bar(10, predictions, y_test)
plt.show()
plt.imshow(img)
现在让我们看看当预测错误时会发生什么:
plt.figure(figsize=(15,6))
plt.subplot(1,2,1)
plot_pred(20, predictions, y_test, x_test)
plt.subplot(1,2,2)
plot_bar(20, predictions, y_test)
plt.show()
Tensorflow 和 Keras 的好处是,你可以建立自己的“自制”CNN,根据可用数据改变层数/类型。然后,您的模型将自己进行反向传播,以调整其参数并最小化误差项。
嗯,我们在这里建立的 CNN 很简单,数据量适中,然而我们能够建立一个很好的分类器,我们可能希望用新的层来实现它。
我想通过分享一种非常直观的方式来了解 CNN 实际上是如何工作的,通过自己喂它,并将学习的整个过程可视化(如果你想尝试,请单击下面的链接),来结束这篇文章。
来源:http://scs.ryerson.ca/~aharley/vis/conv/flat.html
参考文献:
- 【https://www.tensorflow.org/
原载于 2019 年 7 月 10 日http://datasciencechalktalk.com。
使用 word2vec-keras 进行自然语言处理的深度学习
原文:https://towardsdatascience.com/deep-learning-for-natural-language-processing-using-word2vec-keras-d9a240c7bb9d?source=collection_archive---------16-----------------------
结合 Word2Vec 和 Keras LSTM 的自然语言处理深度学习方法
自然语言处理(NLP) 是语言学、计算机科学、信息工程、人工智能等多个研究领域共有的研究子领域。NLP 通常关注计算机和人类自然语言之间的交互,特别是如何使用计算机来处理和分析自然语言数据(例如,文本、语音等)。).NLP 中的一些主要挑战包括语音识别、自然语言理解和自然语言生成。
文本是自然语言处理数据最广泛的形式之一。它可以被视为字符序列或单词序列,但随着深度学习的进步,趋势是在单词级别上工作。给定一个单词序列,在它能够被机器学习或深度学习算法/模型(如 LSTM)理解之前,它必须以某种方式转换成数字。一种直接的方法是使用一键编码将每个单词映射到词汇长度的稀疏向量。另一种方法(例如, Word2vec )使用单词嵌入将单词转换成可配置长度的紧凑向量。
在传统机器学习的 NLP 中[1],文本数据预处理和特征工程都是必需的。最近发布了一个新的深度学习模型 Word2Vec-Keras 文本分类器【2】,用于无特征工程的文本分类。它通过一个嵌入层将Gensim【3】的 Word2Vec 模型(一个用于大型语料库的主题建模、文档索引和相似性检索的 Python 库)与 Keras LSTM 结合起来作为输入。
在本文中,与[1]类似,我使用公开的 Kaggle 垃圾短信收集数据集 [4]来评估 Word2VecKeras 模型在没有特征工程的情况下在垃圾短信分类中的性能。涵盖了以下两种情况:
- 基于数据预处理的垃圾短信分类
- 无需数据预处理的垃圾短信分类
以下代码用于导入所有必需的 Python 库:
from word2vec_keras import Word2VecKeras
from pprint import pprint
import pandas as pd
import matplotlib.pyplot as plt
import itertools
import numpy as np
import nltk
import string
import re
import ast # abstract syntax tree: [https://docs.python.org/3/library/ast.html](https://docs.python.org/3/library/ast.html)
from sklearn.model_selection import train_test_split
import mlflow
import mlflow.sklearn%matplotlib inline
一旦 SMS 数据集文件 spam.csv 被下载到计算机上,下面的代码可以将本地数据集文件加载到 Pandas DataFrame 中,如下所示:
column_names = ['label', 'body_text', 'missing_1', 'missing_2', 'missing_3']
raw_data = pd.read_csv('./data/spam.csv', encoding = "ISO-8859-1")
raw_data.columns = column_names
raw_data.drop(['missing_1', 'missing_2', 'missing_3'], axis=1, inplace=True)
raw_data = raw_data.sample(frac=1.0)
raw_data.head()
请注意,加载此数据集需要使用编码格式 ISO-8859–1,而不是默认的编码格式 UTF-8。
1.带有数据预处理的垃圾邮件分类
在本节中,首先,应用类似于[1]的数据预处理程序来清理 SMS 数据集。然后,生成的干净数据集被输入到 Word2VecKeras 模型中,用于垃圾短信的模型训练和预测。mlflow [5][6]用于追踪模型执行的历史。
1.1 数据预处理
预处理类的预处理()方法对短信原始数据进行如下预处理:
- 删除标点符号
- 标记化
- 删除停用词
- 应用词干
- 应用词汇化
- 将标记加入句子
- 删除中间数据列
class Preprocessing(object):
def __init__(self, data, target_column_name='body_text_clean'):
self.data = data
self.feature_name = target_column_name
def remove_punctuation(self, text):
text_nopunct = "".join([char for char in text if char not in string.punctuation])# It will discard all punctuations
return text_nopunct
def tokenize(self, text):
# Match one or more characters which are not word character
tokens = re.split('\W+', text)
return tokens
def remove_stopwords(self, tokenized_list):
# Remove all English Stopwords
stopword = nltk.corpus.stopwords.words('english')
text = [word for word in tokenized_list if word not in stopword]
return text def stemming(self, tokenized_text):
ps = nltk.PorterStemmer()
text = [ps.stem(word) for word in tokenized_text]
return text
def lemmatizing(self, tokenized_text):
wn = nltk.WordNetLemmatizer()
text = [wn.lemmatize(word) for word in tokenized_text]
return text
def tokens_to_string(self, tokens_string):
try:
list_obj = ast.literal_eval(tokens_string)
text = " ".join(list_obj)
except:
text = None
return text
def dropna(self):
feature_name = self.feature_name
if self.data[feature_name].isnull().sum() > 0:
column_list=[feature_name]
self.data = self.data.dropna(subset=column_list)
return self.data
def preprocessing(self):
self.data['body_text_nopunc'] = self.data['body_text'].apply(lambda x: self.remove_punctuation(x))
self.data['body_text_tokenized'] = self.data['body_text_nopunc'].apply(lambda x: self.tokenize(x.lower()))
self.data['body_text_nostop'] = self.data['body_text_tokenized'].apply(lambda x: self.remove_stopwords(x))
self.data['body_text_stemmed'] = self.data['body_text_nostop'].apply(lambda x: self.stemming(x))
self.data['body_text_lemmatized'] = self.data['body_text_nostop'].apply(lambda x: self.lemmatizing(x))
# save cleaned dataset into csv file and load back
self.save()
self.load()
self.data[self.feature_name] = self.data['body_text_lemmatized'].apply(lambda x: self.tokens_to_string(x))
self.dropna()
drop_columns = ['body_text_nopunc', 'body_text_tokenized', 'body_text_nostop', 'body_text_stemmed', 'body_text_lemmatized']
self.data.drop(drop_columns, axis=1, inplace=True)
return self.data
def save(self, filepath="./data/spam_cleaned.csv"):
self.data.to_csv(filepath, index=False, sep=',')
def load(self, filepath="./data/spam_cleaned.csv"):
self.data = pd.read_csv(filepath)
return self.data
结果数据保存在新列 body_text_clean 中,如下所示:
在上述数据预处理中,自然语言工具包(NLTK) 的停用词和 wordnet 数据文件都是必需的,需要在 Mac 上手动下载(此处可用)。 nltk.download() 方法无法正常工作。
1.2 建模
SpamClassifier 类的 prepare_data ()方法是获取准备建模的短信数据,如下所示:
- 将数据集文件 spam.csv 加载到 Pandas DataFrame
- 使用预处理类预处理原始数据(参见 body_text_clean 列)
- 将数据预处理后的干净数据分成训练和测试数据集
- 将训练和测试数据集重新格式化为 Python 列表,以与模型 Word2VecKeras API [2]保持一致
一旦数据为建模做好准备,就可以调用 train_model ()方法来训练 Word2VecKeras 模型。然后可以调用方法 evaluate ()和 predict ()来获得模型性能度量(例如,准确性)并分别执行预测。
mlFlow ()方法将上述方法调用、模型执行结果跟踪、将训练好的模型记录到文件中组合成一个工作流。
注意,超参数 w2v_min_count 的值是忽略总频率低于该值的所有单词。因此,需要根据特定的数据集进行调整。如果它设置得太高(例如,本文中使用的 SMS spam 数据集的值为 5),则会由于空句而出现词汇错误。
class SpamClassifier(object):
def __init__(self):
self.model = Word2VecKeras()
def load_data(self):
column_names = ['label', 'body_text', 'missing_1', 'missing_2', 'missing_3']
data = pd.read_csv('./data/spam.csv', encoding = "ISO-8859-1")
data.columns = column_names
data.drop(['missing_1', 'missing_2', 'missing_3'], axis=1, inplace=True)
self.raw_data = data.sample(frac=1.0)
return self.raw_data
def split_data(self):
self.x_train, self.x_test, self.y_train, self.y_test = train_test_split(self.x, self.y, test_size=0.25, random_state=42)
def numpy_to_list(self):
self.x_train = self.x_train.tolist()
self.y_train = self.y_train.tolist()
self.x_test = self.x_test.tolist()
self.y_test = self.y_test.tolist()
def prepare_data(self, feature, label='label'):
self.load_data()
pp = Preprocessing(self.raw_data)
self.data = pp.preprocessing()
self.x = self.data[feature].values
self.y = self.data[label].values
self.split_data()
self.numpy_to_list()
return self.data
def train_model(self):
self.w2v_size = 300
self.w2v_min_count = 1 # 5
self.w2v_epochs = 100
self.k_epochs = 5 # 32
self.k_lstm_neurons = 512
self.k_max_sequence_len = 1000
self.model.train(self.x_train, self.y_train,
w2v_size=self.w2v_size,
w2v_min_count=self.w2v_min_count,
w2v_epochs=self.w2v_epochs,
k_epochs=self.k_epochs,
k_lstm_neurons=self.k_lstm_neurons,
k_max_sequence_len=self.k_max_sequence_len,
k_hidden_layer_neurons=[])
def evaluate(self):
self.result = self.model.evaluate(self.x_test, self.y_test)
self.accuracy = self.result["ACCURACY"]
self.clf_report_df = pd.DataFrame(self.result["CLASSIFICATION_REPORT"])
self.cnf_matrix = self.result["CONFUSION_MATRIX"]
return self.result
def predict(self, idx=1):
print("LABEL:", self.y_test[idx])
print("TEXT :", self.x_test[idx])
print("/n============================================")
print("PREDICTION:", self.model.predict(self.x_test[idx]))
def mlFlow(self, feature='body_text_clean'):
np.random.seed(40)
with mlflow.start_run():
self.prepare_data(feature=feature) # feature should be 'body_text' if no need to preprocessing
self.train_model()
self.evaluate()
self.predict()
mlflow.log_param("feature", feature)
mlflow.log_param("w2v_size", self.w2v_size)
mlflow.log_param("w2v_min_count", self.w2v_min_count)
mlflow.log_param("w2v_epochs", self.w2v_epochs)
mlflow.log_param("k_lstm_neurons", self.k_lstm_neurons)
mlflow.log_param("k_max_sequence_len", self.k_max_sequence_len)
mlflow.log_metric("accuracy", self.accuracy)
mlflow.sklearn.log_model(self.model, "Word2Vec-Keras")
下面的代码展示了如何实例化一个 SpamClassifier 对象,并调用 mlFlow ()方法进行数据预处理建模和预测:
spam_clf = SpamClassifier()
spam_clf.mlFlow(feature='body_text_clean')
1.3 比较
一种简单的基线分类算法是预测类别(垃圾邮件或 ham)的大多数(即 ham)。任何有用的监督机器学习分类模型都必须在性能上打败它。在 Kaggle 垃圾短信收集数据集中,共有 5572 个样本,其中 747 个是垃圾短信,4825 个是火腿短信。因此,基准算法性能的准确率约为 86.6%。
在[1]中,首先将类似的数据预处理过程应用于相同的 Kaggle 垃圾短信数据集。然后对预处理后的数据集进行特征工程,以获得建模特征,如文本消息长度和文本中标点符号的百分比。然后 sci kit-learnRandomForestClassifier模型被训练用于预测。获得的准确度约为 97.7%。
在本文中,数据预处理后, Word2VecKeras 模型直接在预处理后的数据集上训练进行预测,不需要任何特征工程。5 个历元达到的精度约为 98.5%。
结果表明,无论是传统的机器学习方法[1]还是本文提出的新的深度学习方法,其准确率都明显优于基线算法。
2.无需数据预处理的垃圾邮件分类
在这一部分中,一旦 Kaggle 垃圾短信收集数据集被加载,原始数据(参见 body_text 列)就被直接馈送到 Word2Vec-Keras 模型中,用于垃圾短信的模型训练和预测。既不使用数据预处理也不使用特征工程。与上一节类似, mlflow [5][6】用于跟踪模型执行的历史。这是通过以下方式实现的:
spam_clf = SpamClassifier()
spam_clf.mlFlow(feature='body_text')
如下图所示,获得的 5 个历元的准确率约为 99.0%,与前一节中数据预处理的垃圾邮件分类准确率的 Word2VecKeras 模型性能相当。
mlflow UI 的以下快照显示了模型执行的历史:
摘要
在本文中,使用公开的 Kaggle 垃圾短信收集数据集 [4]来评估新的 Word2VecKeras 模型在没有特征工程的情况下在垃圾短信分类中的性能。
涵盖了两个场景。一种是应用通用的文本数据预处理来清理原始数据集,然后使用清理后的数据集来训练预测模型。另一种方法直接使用未经任何数据预处理的原始数据集进行模型训练和预测。
模型在准确性方面的性能结果表明, Word2VecKeras 模型的性能优于传统的 NLP 方法[1],并且在上述两种情况下的性能相似。这表明新的 Word2VecKeras 模型具有直接应用于原始文本数据进行文本分类的潜力,而无需文本数据预处理或特征工程。
本文中的所有源代码都可以在 Github [7]中找到。
参考
[1].b .谢蒂,机器学习的自然语言处理
[2]. Word2Vec-Keras 文本分类器
[3]. Gensim
[4]. Kaggle 垃圾短信收集数据集
[5]. mlflow
[6].张,面向对象的机器学习流水线与 mlflow 熊猫和考拉数据框架
[7].GithubJupyter 笔记本 Y. Zhang
披露声明:2019 首创一。观点是作者个人的观点。除非本帖中另有说明,否则 Capital One 不隶属于所提及的任何公司,也不被这些公司认可。使用或展示的所有商标和其他知识产权是其各自所有者的财产。
NLP 深度学习:ANNs、rnn 和 LSTMs 解释!
原文:https://towardsdatascience.com/deep-learning-for-nlp-anns-rnns-and-lstms-explained-95866c1db2e4?source=collection_archive---------9-----------------------
了解前所未有的人工神经网络、深度学习、递归神经网络和 LSTMs,并使用 NLP 构建一个聊天机器人!
曾经幻想过有一个自己的私人助理来回答你能问的任何问题,或者和你交谈吗?嗯,多亏了机器学习和深层神经网络,这一切才刚刚开始。想想苹果的 Siri 或亚马逊的 Alexa 展示的惊人功能。
不要太激动,在接下来的一系列帖子中,我们不会创建一个无所不能的人工智能,相反,我们将创建一个简单的聊天机器人给定一些输入信息和一个关于这些信息的问题,回答关于它被告知什么的是/否问题。
它远不及 Siri 或 Alexa 的能力,但它很好地说明了即使使用非常简单的深层神经网络结构,也可以获得惊人的结果。在本文中,我们将学习人工神经网络,深度学习,递归神经网络和长短期记忆网络。在下一篇文章中,我们将在一个真实的项目中使用它们来制作一个问答机器人。
在我们开始讨论神经网络的所有乐趣之前,我希望你先仔细看看后面的图像。里面有两幅画;一辆校车驶过一条道路,一个普通的客厅,上面有人类注释者的描述。
Figure with two different images with a text description made by human annotators.
完成了吗?那我们就继续吧!
开端——人工神经网络
为了构建用于创建聊天机器人的神经网络模型,将使用非常流行的神经网络 Python 库 Keras 。然而,在进一步讨论之前,我们首先必须了解什么是人工神经网络。
人工神经网络是试图模仿人脑功能的机器学习模型,人脑的结构由大量连接在其间的神经元构建而成,因此得名“人工神经网络
感知器
最简单的人工神经网络模型由一个单一的神经元组成,被称为《星际迷航》发音名称 感知器 。它是由弗兰克·罗森布拉特在 1957 年发明的,它由一个简单的神经元组成,这个神经元获取其输入的加权和(在生物神经元中是树突)对其应用数学函数,并输出其结果(输出相当于生物神经元的轴突)。我们不会深入探讨可在此应用的不同功能的细节,因为该职位的目的不是成为专家,而是获得对神经网络如何工作的基本理解。
Image of a single neuron, with the inputs on the left, the weights that multiply each input, and the neuron itself, that applies a function to the weighted sum of the inputs and outputs the result.
这些单独的神经元可以相互堆叠,形成我们想要的大小的层,然后这些层可以顺序地彼此相邻,使网络更深。
当网络以这种方式建立时,不属于输入或输出层的神经元被认为是隐藏层的一部分,用它们的名字描述了 ANN 的主要特征之一:它们几乎是黑盒模型;我们理解所发生的事情背后的数学原理,并对黑盒内部发生的事情有一种直觉,但如果我们获取一个隐藏层的输出并试图理解它,我们可能会绞尽脑汁,而不会获得任何积极的结果。
尽管如此,它们产生了惊人的结果,所以没有人抱怨它们缺乏可解释性。
Image of a larger neural network, composed of many individual neurons and layers: an input layer, 2 hidden layers and an output layer.
二十多年来,人们已经知道了神经网络结构以及如何训练它们。那么,是什么导致了现在正在进行的关于 ANN 和深度学习的所有大惊小怪和大肆宣传呢?这个问题的答案就在下面,但是在我们必须了解深度学习到底是什么之前。
那么什么是深度学习呢?
深度学习,正如你可能从名字中猜到的,只是使用许多层来从我们提供给神经网络的数据中逐步提取更高层次的特征。事情就是这么简单;使用多个隐藏层来增强我们的神经模型的性能。
既然我们知道了这一点,上面问题的答案就很简单了:音阶。在过去的二十年里,各种可用数据的数量,以及我们的数据存储和处理机器(是的,计算机)的能力,都呈指数级增长。
这些计算能力和用于训练我们模型的可用数据量的大规模增加,使我们能够创建更大、更深的神经网络,这些网络的表现优于较小的网络。
世界领先的深度学习专家之一吴恩达在这个视频中阐明了这一点。在其中,他展示了与下图类似的图像,并解释了拥有更多数据来训练我们的模型的好处,以及大型神经网络相对于其他机器学习模型的优势。
Image showing the evolution of the performance of different algorithms as we feed them more training data
对于传统的机器学习算法(线性或逻辑回归、SMV、随机森林等),随着我们用更多的数据训练模型,性能会提高,直到某个点,当我们向模型提供更多数据时,性能会停止提高。当达到这一点时,就好像模型不知道如何处理额外的数据,并且不能通过输入更多的数据来提高性能。
另一方面,有了神经网络,这种情况就不会发生了。性能几乎总是随着数据的增加而提高(当然,前提是数据质量好),并且随着网络规模的增大,性能会以更快的速度提高。因此,如果我们想要获得的最佳性能,我们将需要在绿线上的某个地方(大型神经网络)并且朝向 X 轴的右侧(高数据量)。
除此之外,也有一些算法上的改进,但导致深度学习和人工神经网络宏伟崛起的主要事实只是规模:计算规模和数据规模。
该领域的另一位重要人物杰夫·迪恩(谷歌采用深度学习的发起人之一),对深度学习有如下看法:
当你听到深度学习这个词的时候,只要想到一个大型的深度神经网络就可以了。深度指的是典型的层数,所以这是一个在媒体中流行的术语。我一般认为它们是深度神经网络。
当谈到深度学习时,他强调了神经网络的可扩展性表明随着数据和模型的增加,结果会变得更好,这反过来需要更多的计算来训练,就像我们以前看到的那样。
好的,很好,我都明白了,但是神经网络实际上是如何学习的呢?
嗯,你可能已经猜到了:他们从数据中学习。
还记得在单个感知器中乘以我们输入的权重吗?这些权重也包含在任何连接两个不同神经元的边上。这意味着在一个更大的神经网络的图像中,它们存在于每一个单独的黑色边缘,获取一个神经元的输出,乘以它,然后将其作为输入提供给与该边缘相连的另一个神经元。
Image of a neural network with two hidden layers and the weights in between each of the layers
当我们训练神经网络(训练神经网络是让它学习的 ML 表达式)时,我们给它输入一组已知数据(在 ML 中,这称为标记数据),让它预测我们知道的关于这些数据的特征(例如,如果一幅图像代表一只狗或一只猫),然后将预测结果与实际结果进行比较。
随着这个过程的进行,网络会出错,它会调整神经元之间连接的权重,以减少出错的次数。正因为如此,如前所述,如果我们在大部分时间里给网络提供越来越多的数据,就会提高网络的性能。
从序列数据中学习——递归神经网络
现在我们知道了什么是人工神经网络和深度学习,并且对神经网络如何学习有了一点了解,让我们开始看看我们将用来构建聊天机器人的网络类型:递归神经网络,简称 RNNs。
递归神经网络是一种特殊的神经网络,设计用于有效处理序列数据。这类数据包括时间序列(某段时间内某些参数的值的列表)文本文档,可以看做是文字的序列,或者音频,可以看做是声音频率的序列。
RNNs 实现这一点的方法是,获取每个神经元的输出,并将其作为输入反馈给它。通过这样做,它不仅在每个时间步接收新的信息片段,而且还向这些新的信息片段添加了先前输出的加权版本。这使得这些神经元对之前的输入有一种的“记忆”,因为它们以某种方式被反馈给神经元的输出量化。
A recurrent neuron, where the output data is multiplied by a weight and fed back into the input
作为来自先前时间步长的输入的函数的单元也被称为 存储单元 。
RNNs 的问题是,久而久之通过和他们获得越来越多的新数据,**他们开始“忘记”他们已经看到的关于以前的数据,因为它在新数据之间得到稀释**,从激活函数转换,和权重相乘。这意味着他们有很好的短期记忆,但在试图记住不久前发生的事情时会有一点问题(他们在过去的许多时间步骤中看到过的数据)。
我们需要某种长期记忆,这正是 LSTMs 所能提供的。
增强我们的记忆——长短期记忆网络
长短期记忆网络是 RNN 的一种变体,它解决了前者的长期记忆问题。在这篇文章的最后,我们将简要解释它们是如何工作的。
它们拥有比普通递归神经元更复杂的细胞结构,这使得它们能够更好地调节如何从不同的输入源中学习或忘记。
Representation of an LSTM cell. Dont play attention to the blue circles and boxes, as you can see it has a way more complex structure than a normal RNN unit, and we wont go into it in this post.
一个 LSTM 神经元可以通过结合一个 细胞状态 和三个不同的门来做到这一点:输入门、遗忘门和输出门。在每一个时间步骤中,细胞可以决定如何处理状态向量:读取、写入或删除,这要归功于明确的门控机制。通过输入门,单元可以决定是否更新单元状态。通过遗忘门,单元可以擦除其存储器,通过输出门,单元可以决定是否提供输出信息。
LSTMs 也减轻了爆炸和消失渐变的问题,但那是另外一个故事了。
就这样!现在我们对这些不同种类的神经网络如何工作有了一个肤浅的理解,我们可以用它来构建我们的第一个深度学习项目!**
结论
神经网络牛逼。正如我们将在下一篇文章中看到的,即使只有几层的非常简单的结构也能创建一个非常有能力的聊天机器人*。*
哦,对了,还记得这张照片吗?
Figure with two different images with a short text description made by a neural network.
好吧,为了证明深度神经网络有多酷,我必须承认一些事情。我对图片的描述是如何产生的撒了谎。
在帖子的开始,我说过这些描述是由人类注释者做出的,然而,事实是,这些描述每个图像上可以看到的内容的短文实际上是由人工神经网络产生的。
精神错乱对吗?
如果你想学习如何使用深度学习来创建一个令人敬畏的聊天机器人,请关注我的 Medium ,并关注我的下一篇帖子!
在那之前,保重,享受 AI!
其他资源:
由于这篇文章中对不同概念的解释非常肤浅,如果你们中有人想更进一步继续学习,这里有一些很棒的附加资源。
- 神经网络如何端到端工作
- Youtube 视频系列解释了关于神经网络如何被训练的主要概念
- 深度学习&人工神经网络
好了,就这些,我希望你喜欢这篇文章。请随时在 LinkedIn 上与我联系,或者在 Twitter 上关注我,地址是 T2 @ jaimezorno。此外,你可以看看我在数据科学和机器学习方面的其他帖子这里。好好读!
最后,看看我关于 NLP 深度学习的其他文章:
* [## NLP 的深度学习:用 Keras 创建聊天机器人!
了解如何使用 Keras 构建递归神经网络并创建聊天机器人!谁不喜欢友好的机器人…
towardsdatascience.com](/deep-learning-for-nlp-creating-a-chatbot-with-keras-da5ca051e051) [## 自然语言处理的深度学习:单词嵌入
简单直观的单词嵌入
towardsdatascience.com](/deep-learning-for-nlp-word-embeddings-4f5c90bcdab5)
此外,要获得更多学习机器学习和人工智能的资源,请查看以下 repo:
[## 如何学习机器学习——进入 ML 的资源库
lost 试图发现如何学习机器学习?现在是学习这项技术的大好时机,但是…
howtolearnmachinelearning.com](https://howtolearnmachinelearning.com/)*
NLP 的深度学习:用 Keras 创建聊天机器人!
原文:https://towardsdatascience.com/deep-learning-for-nlp-creating-a-chatbot-with-keras-da5ca051e051?source=collection_archive---------2-----------------------
了解如何使用 Keras 构建递归神经网络并创建聊天机器人!谁不喜欢友好的机器人私人助理呢?
在之前的帖子中,我们了解了什么是人工神经网络和深度学习。此外,还介绍了一些利用文本或音频等序列数据的神经网络结构。如果你还没有看过那篇文章,你应该坐下来,喝杯咖啡,慢慢地享受它。这里可以找到。
这篇新帖将讲述如何使用 Keras ,一个非常流行的神经网络库来构建聊天机器人。将解释这个库的主要概念,然后我们将逐步指导如何使用它来创建 Python 中的是/否回答机器人。我们将利用 Keras 的易用性来实现 Sukhbaatar 等人的论文“端到端存储网络”中的 RNN 结构(你可以在这里找到)。****
这很有趣,因为定义了一个任务或应用程序(创建一个是/否聊天机器人来回答特定的问题),我们将学习如何将研究工作中的见解转化为实际模型,然后我们可以使用该模型来实现我们的应用程序目标。
如果这是你第一次实现 NLP 模型,不要害怕;我会仔细检查每一步,并在最后添加一个代码链接。对于最佳学习体验,我建议你首先阅读帖子,然后浏览代码,同时浏览帖子中的相关部分。
最后,在我们开始之前,这里有一些额外的资源可以让你的机器学习生涯突飞猛进:
*Awesome Machine Learning Resources:**- For* ***learning resources*** *go to* [***How to Learn Machine Learning***](https://howtolearnmachinelearning.com/books/machine-learning-books/)*!
- For* ***professional******resources*** *(jobs, events, skill tests) go to* [***AIgents.co — A career community for Data Scientists & Machine Learning Engineers***](https://aigents.co/)***.***
让我们开始吧!
Keras:Python 中的简易神经网络
Keras 是一个用于开发神经网络模型的开源高级库。它是由谷歌的深度学习研究员弗朗索瓦·乔莱(Franç ois Chollet)开发的。它的核心原则是使构建神经网络、训练神经网络、然后使用神经网络进行预测的过程对任何具有基本编程知识的人来说都是容易和可访问的,同时仍然允许开发人员完全定制人工神经网络的参数。
基本上,Keras 实际上只是一个可以运行在不同深度学习框架之上的接口,例如 CNTK、Tensorflow 或 Theano 。它的工作方式是一样的,与所使用的后端无关。
Layered structure of the Keras API. As it can be seen, it can run on top of different frameworks seamlessly.
正如我们在上一篇文章中提到的,在神经网络中,特定层中的每个节点都采用前一层输出的加权和,对它们应用数学函数,然后将结果传递给下一层。
使用 Keras,我们可以创建一个表示每一层的块,其中可以轻松定义这些数学运算和层中的节点数。这些不同的层可以通过输入一行直观的代码来创建。****
创建 Keras 模型的步骤如下:****
**第一步:首先我们必须定义一个网络模型,这个模型在大多数情况下是SS模型:网络将被定义为一系列的层,每个层都有自己可定制的大小和激活功能。在这些模型中,第一层将是输入层,这需要我们定义我们将馈送给网络的输入的大小。之后,越来越多的层可以添加和定制,直到我们达到最终的输出层。
#Define Sequential Model
model = Sequential()
#Create input layer
model.add(Dense(32, input_dim=784))
#Create hidden layer
model.add(Activation('relu'))
#Create Output layer
model.add(Activation('sigmoid'))
步骤 2: 以这种方式创建网络结构后,我们必须对其进行编译,这将我们之前定义的简单层序列转换为一组复杂的矩阵运算,这些运算决定了网络的行为方式。在这里,我们必须定义将用于训练网络的优化算法,并选择将被最小化的损失函数。
#Compiling the model with a mean squared error loss and RMSProp #optimizer
model.compile(optimizer='rmsprop',loss='mse')
第三步:**一旦完成,我们可以训练或 拟合 网络,这是使用前一篇文章中提到的反向传播算法完成的。
*# Train the model, iterating on the data in batches of 32 samples* model.fit(data, labels, epochs=10, batch_size=32)
****第四步:万岁!我们的网络训练有素。现在我们可以用它对新数据进行预测。
正如你所看到的,使用 Keras 建立一个网络是相当容易的,所以让我们使用它来创建我们的聊天机器人!上面使用的代码块并不代表实际的具体神经网络模型,它们只是帮助说明使用 Keras API 构建神经网络有多简单的每个步骤的示例。
你可以在它的官方网页找到所有关于 Keras 以及如何安装的文档。
该项目:使用递归神经网络建立一个聊天机器人
现在我们知道了所有这些不同类型的神经网络是什么,让我们用它们来建立一个可以回答我们一些问题的聊天室。
大多数时候,神经网络结构比标准的输入-隐藏层-输出更复杂。有时我们可能想发明一个我们自己的神经网络并尝试不同的节点或层组合。此外,在某些场合,我们可能希望实现一个我们在某处见过的模型,比如在一篇科学论文中。
在这篇文章中,我们将通过第二种情况的一个例子,从 Sukhbaatar 等人的论文"端到端记忆网络 "** (你可以在这里找到)中构建神经模型。**
此外,我们还将了解如何保存训练好的模型,这样我们就不必在每次想要使用我们建立的模型进行预测时训练网络。那我们走吧!
模型:灵感
如前所述,本文中使用的 RNN 摘自论文 " 端到端内存网络 " ,因此我建议您在继续之前先看一下,尽管我将在下面几行解释最相关的部分。
本文实现了一个类似 RNN 的结构,它使用一个注意力模型来补偿我们在上一篇文章中讨论过的关于 RNNs 的长期记忆问题。
不知道什么是注意力模型?不要担心,我会用简单的语言解释给你听。注意力模型吸引了很多人的兴趣,因为它们在像机器翻译这样的任务中表现非常好。他们解决了前面提到的 RNNs 的长序列和短期记忆的问题。
为了收集注意力做什么的直觉,想想人类如何将一个长句从一种语言翻译成另一种语言。不是拿起whooooole的句子,然后一口气翻译出来,而是把句子分成小块,然后一个一个地翻译这些小块。我们一部分一部分地学习这个句子,因为很难完全记住它,然后马上翻译它。
How a human would translate the text on the top from English to Spanish
注意力机制就是这样做的。在每个时间步中,模型在输出中给输入句子中与我们试图完成的任务更相关的部分更高的权重。这就是这个名字的来源: it 把注意力放在更重要的上。上面的例子很好地说明了这一点;要翻译句子的第一部分,看整个句子或句子的最后一部分没有什么意义。
下图显示了当我们增加输入句子的长度时,RNN 与注意力模型的表现。当面对一个很长的句子,并要求执行一个特定的任务时,RNN 在处理完所有的句子后,可能会忘记它最初的输入。****
Performance vs Sentence Length for RNNs and Attention models.
好了,现在我们知道了什么是注意力模型,让我们仔细看看我们将要使用的模型的结构。这个模型接受一个输入Xi(一个句子),一个查询 q 关于这样的句子,并输出一个是/否回答 一个 。****
On the left (a) a representation of a single layer of the model. On the right (b) 3 of these layers stacked together.
在上一个图像的左边部分,我们可以看到这个模型的一个单层的表示。每个句子计算两个不同的嵌入, A 和 C 。同样,使用 B 嵌入来嵌入查询或问题 q。****
A 嵌入 mi ,然后使用内积计算问题嵌入*(这是注意力发生的部分,因为通过计算这些嵌入之间的内积,我们正在做的是从查询和句子中寻找词语的匹配,然后使用soft max赋予这些匹配更多的重要性*
最后,我们使用来自 C【ci】的嵌入以及从点积获得的权重或概率【pi】来计算输出向量。有了这个输出向量 o ,权重矩阵 W ,以及问题的嵌入,我们就可以最终算出预测答案 一个帽子 。****
为了构建整个网络,我们只需在不同的层上重复这些过程,使用其中一层的预测输出作为下一层的输入。这显示在上一个图像的右边部分。
如果这些对你来说太快了,不要担心,希望当我们通过不同的步骤用 Python 实现这个模型时,你会得到更好和完整的理解。
数据:故事、问题和答案
2015 年,脸书在 bAbI 项目中提出了一个 bAbI 数据集和 20 个测试文本理解和推理的任务。文中详细描述了 这里 。
每个任务的目标是挑战机器文本相关活动的一个独特方面,测试学习模型的不同能力。在这篇文章中,我们将面对这些任务中的一个,特别是“带有单一支持事实的 QA”。**
下图显示了这种 QA 机器人的预期行为示例:
**FACT: Sandra went back to the hallway. Sandra moved to the office. QUESTION: Is Sandra in the office?ANSWER: yes**
数据集已经被分成训练数据(10k 实例)和测试数据(1k 实例),其中每个实例都有一个事实,一个问题,以及对该问题的一个是/否答案。
现在我们已经看到了数据的结构,我们需要从数据中建立一个词汇表。在一个自然语言处理模型上,一个词汇表基本上是一组模型知道并能理解的单词。如果在构建词汇表之后,模型在句子中发现了一个不在词汇表中的单词,它要么在其句子向量中给它一个 0 值,要么将其表示为未知。
**VOCABULARY:
'.', '?', 'Daniel', 'Is', 'John', 'Mary', 'Sandra', 'apple','back','bathroom', 'bedroom', 'discarded', 'down','dropped','football', 'garden', 'got', 'grabbed', 'hallway','in', 'journeyed', 'kitchen', 'left', 'milk', 'moved','no', 'office', 'picked', 'put', 'the', 'there', 'to','took', 'travelled', 'up', 'went', 'yes'**
由于我们的训练数据变化不大(大多数问题使用相同的动词和名词,但有不同的组合),我们的词汇量不是很大,但在中等规模的 NLP 项目中,词汇量可以很大。
考虑到为了建立一个词汇表,我们应该在大多数时候只使用训练数据;在机器学习项目的最开始,测试数据应该从训练数据中分离出来,并且在评估已经选择和调整的模型的性能之前不要接触。
构建词汇后,我们需要 矢量化 我们的数据。由于我们使用普通的单词作为模型的输入,而计算机只能在引擎盖下处理数字,我们需要一种方式来表示我们的句子,即词组,作为数字的向量。矢量化就是这么做的。
有许多向量化我们的句子的方法,像 单词包 模型,或者 Tf-Idf ,但是,为了简单起见,我们将只使用一种索引向量化技术,其中我们给词汇表中的每个单词一个从 1 到词汇表长度的唯一索引。
**VECTORIZATION INDEX:
'the': 1, 'bedroom': 2, 'bathroom': 3, 'took': 4, 'no': 5, 'hallway': 6, '.': 7, 'went': 8, 'is': 9, 'picked': 10, 'yes': 11, 'journeyed': 12, 'back': 13, 'down': 14, 'discarded': 15, 'office': 16, 'football': 17, 'daniel': 18, 'travelled': 19, 'mary': 20, 'sandra': 21, 'up': 22, 'dropped': 23, 'to': 24, '?': 25, 'milk': 26, 'got': 27, 'in': 28, 'there': 29, 'moved': 30, 'garden': 31, 'apple': 32, 'grabbed': 33, 'kitchen': 34, 'put': 35, 'left': 36, 'john': 37}**
考虑到这种矢量化是使用随机种子开始的,所以即使你使用和我一样的数据,你也可能为每个单词得到不同的索引。不用担心;这不会影响项目的结果。此外,我们的词汇表中的单词有大写和小写;在进行这种矢量化时,为了统一,所有的单词都将小写。
在此之后,由于 Keras 的工作方式,我们需要填充句子。这是什么意思?这意味着我们需要搜索最长句子的长度,将每个句子转换为该长度的向量,并用零填充每个句子的字数和最长句子的字数之间的差距。
这样做之后,数据集的一个随机句子应该看起来像这样:
**FIRST TRAINING SENTENCE VECTORIZED AND PADDED:
array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 20, 30, 24, 1, 3, 7, 21, 12, 24, 1, 2, 7])**
正如我们所见,除了结尾(这个句子比最长的句子短很多)有一些数字之外,它到处都有零。这些数字是什么?嗯,它们是代表句子不同单词的索引:20 是代表单词 玛丽 , 30 是 移动了 , 24 是 到 ,1 是,3 代表 浴室实际的句子是:**
**FIRST TRAINING SENTENCE:
"Mary moved to the bathroom . Sandra journeyed to the bedroom ."**
好了,现在我们已经准备好了数据,我们准备建立我们的神经网络!
神经网络:建立模型
创建网络的第一步是为输入创建 Keras 中所谓的 占位符 ,在我们的例子中是故事和问题。简单地说,这些占位符是容器,在将我们的训练数据馈送到模型之前,将在其中放置这些数据。
***#Example of a Placeholder
question = Input((max_question_len,batch_size))***
它们必须与将要输入的数据具有相同的尺寸,并且还可以定义一个批量大小,尽管如果我们在创建占位符时不知道,可以将其留空。
现在我们必须创建论文中提到的嵌入、 A、C 和 b、一个嵌入将一个整数(在这种情况下是一个单词的索引)变成一个 d 维向量,其中上下文被考虑到。单词嵌入在自然语言处理中被广泛使用,并且是近年来使该领域取得巨大进步的技术之一。
**#Create input encoder A:
input_encoder_m = Sequential()
input_encoder_m.add(Embedding(input_dim=vocab_len,output_dim = 64))
input_encoder_m.add(Dropout(0.3))#Outputs: (Samples, story_maxlen,embedding_dim) -- Gives a list of #the lenght of the samples where each item has the
#lenght of the max story lenght and every word is embedded in the embbeding dimension**
上面的代码是论文中嵌入的一个例子(一个嵌入)。像在 Keras 中一样,我们首先定义模型(顺序的),然后添加嵌入层和丢弃层,通过触发网络的节点来减少模型过拟合的机会。
一旦我们为输入句子创建了两个嵌入,并为问题创建了嵌入,我们就可以开始定义模型中发生的操作。如前所述,我们通过在问题嵌入和故事嵌入之间做点积来计算关注度,然后做一个 softmax。下面的程序块显示了这是如何实现的:
**match = dot([input_encoded_m,question_encoded], axes = (2,2))
match = Activation('softmax')(match)**
在此之后,我们需要计算将匹配矩阵与第二个输入向量序列相加的输出 o ,然后使用该输出和编码的问题计算响应。
**response = add([match,input_encoded_c])
response = Permute((2,1))(response)
answer = concatenate([response, question_encoded])**
最后,一旦完成,我们添加模型的其余层,添加一个 LSTM 层(而不是论文中的 RNN),一个 dropout 层和一个最终的 softmax 来计算输出。
**answer = LSTM(32)(answer)
answer = Dropout(0.5)(answer)
#Output layer:
answer = Dense(vocab_len)(answer)
#Output shape: (Samples, Vocab_size) #Yes or no and all 0s
answer = Activation('softmax')(answer)**
这里注意,输出是一个词汇量大小的向量(即模型已知的单词数的长度),其中除了索引‘yes’和‘no’处的位置外,所有位置都应该为零。
从数据中学习:训练模型
现在我们准备编译模型,并训练它!
**model = Model([input_sequence,question], answer)
model.compile(optimizer='rmsprop', loss = 'categorical_crossentropy', metrics = ['accuracy'])**
有了这两行,我们构建最终模型,并编译它,也就是说,通过指定一个优化器、一个损失函数和一个度量来优化,定义所有将在后台进行的数学运算。
现在是训练模型的时间,这里我们需要定义训练的输入(输入故事、问题和答案)、我们将向模型提供的批量(即,一次有多少输入),以及我们将训练模型的时期数(即,模型将经历多少次训练数据以更新权重)。我使用了 1000 个历元,获得了 98%的准确率,但即使使用 100 到 200 个历元,你也应该得到一些相当好的结果。
请注意,根据您的硬件,此培训可能需要一段时间。放松,坐好,继续阅读,直到完成。
完成培训后,你可能会疑惑“我每次想用这个模型时都要等这么久吗?”很明显我朋友的答案是, 没有 。Keras 允许开发者保存它已经训练好的某个模型,以及权重和所有配置。下面的代码块显示了这是如何实现的。**
**filename = 'medium_chatbot_1000_epochs.h5'
model.save(filename)**
现在,当我们想使用这个模型时就像加载一样简单,就像这样:
**model.load_weights('medium_chatbot_1000_epochs.h5')**
酷酷。现在我们已经训练好了我们的模型,让我们看看它在新数据上的表现,然后用它玩一会儿!
查看结果:测试和播放
让我们看看我们的模型在测试数据上表现如何!
**pred_results = model.predict(([inputs_test,questions_test]))**
这些结果是一个数组,如前所述,它在每个位置包含词汇表中每个单词成为问题答案的概率。如果我们看这个数组的第一个元素,我们会看到一个词汇大小的向量,其中除了对应是或否的时间以外,所有时间都接近 0。
在这些中,如果我们选择数组的最高值的索引,然后查看它对应于哪个单词,我们应该找出答案是肯定的还是否定的。
我们现在可以做的一件有趣的事情是创造我们自己的故事和问题,并把它们喂给机器人看他说什么!
**my_story = 'Sandra picked up the milk . Mary travelled left . '
my_story.split()
my_question = 'Sandra got the milk ?'
my_question.split()**
我以某种方式创造了一个故事和一个问题类似于我们的小 bot 在之前看过的,在改编成神经网络想要的格式后 bot 回答了' YES '(小写 tough,他没有我热情)。
让我们尝试一些不同的东西:
**my_story = 'Medium is cool . Jaime really likes it. '
my_story.split()
my_question = 'Does Jaime like Medium ?'
my_question.split()**
这次的回答是:' 当然有,谁没有呢?’
开个玩笑,我没有尝试故事/问题的组合,因为其中的许多单词不在我们的小答录机的词汇中。此外,他只知道如何说“是”和“不是”,通常不会给出任何其他答案。然而,有了更多的训练数据和一些变通办法,这很容易实现。
今天到此为止!我希望你们能像我喜欢写这篇文章一样喜欢读这篇文章。祝你愉快,保重,享受人工智能!
你可以在我的 Github 页面找到代码和数据。
其他资源:
如果你想更深入地了解注意力模型,或者理解我提到的一些单词矢量化技术,请查看我为你整理的这些额外资源。尽情享受吧!
注意力机制和记忆网络初学者指南
Andrew 的 Ng 视频与对注意力模式的直觉。
Tf-Idf 入门指南和文字袋。
Keras 构建相同模型的指南。
好好读!
有关机器学习和数据科学的更多资源,请查看以下资源库: 如何学习机器学习 !有关职业资源(工作、事件、技能测试),请访问 AIgents.co——一个数据科学家&机器学习工程师 的职业社区。
最后,看看我关于 NLP 深度学习的其他文章:
**** [## NLP 的深度学习:ann,RNNs 和 LSTMs 解释!
了解人工神经网络,深度学习,循环神经网络和 LSTMs 前所未有地使用…
towardsdatascience.com](/deep-learning-for-nlp-anns-rnns-and-lstms-explained-95866c1db2e4) [## 自然语言处理的深度学习:单词嵌入
简单直观的单词嵌入
towardsdatascience.com](/deep-learning-for-nlp-word-embeddings-4f5c90bcdab5)
尽情享受吧!
此外,要获得更多学习机器学习和人工智能的资源,请查看以下 repo:
[## 如何学习机器学习——进入 ML 的资源库
lost 试图发现如何学习机器学习?现在是学习这项技术的大好时机,但是…
howtolearnmachinelearning.com](https://howtolearnmachinelearning.com/)****
自动驾驶汽车的深度学习
原文:https://towardsdatascience.com/deep-learning-for-self-driving-cars-7f198ef4cfa2?source=collection_archive---------3-----------------------
利用英伟达的研究在 Pytorch 建立自动驾驶的 CNN
更新 2:
这篇文章是很多年前写的,我已经不在这个领域工作了,所以如果下面的代码不起作用,我提前道歉。😅
更新:
非常感谢 Valohai 使用我的 rusty 教程作为他们令人敬畏的机器学习平台的介绍😍。我建议你们都去看看他们的例子关于如何使用 Valohai 机器学习平台(www.valohai.com)在云上用完全版本控制训练网络。
我们都知道自动驾驶汽车是科技巨头最热门的研究和商业领域之一。几年前看起来像科幻小说的东西,现在看起来更像是即将成为生活一部分的东西。我说“很快”的原因是因为即使像特斯拉、日产、凯迪拉克这样的公司确实有自动驾驶汽车辅助软件,但是,它们仍然需要人盯着道路,并在需要时进行控制。然而,看到我们在创新方面走了多远,技术进步有多快,这是令人着迷的。以至于现在,在基本的深度学习、神经网络魔法的帮助下,我们可以为自动驾驶建立自己的管道!激动吗?我当然是!那我们就直接进入正题吧…
先决条件: 1。本文假设对卷积神经网络及其工作有一个基本的了解。
2。这里提到的代码是使用 Pytorch 框架用 Python 编写的,因此建议您具备该语言和框架的基础知识。
如果以上对你来说是胡言乱语,不要惊慌!这个由 Udacity 提供的免费课程将为你提供你需要了解的关于深度学习和 Pytorch 基础知识的一切。
我的背景
我从脸书赞助的 Udacity 奖学金项目开始了我的深度学习之旅,通过这个项目,我从上面提到的课程中学到了 Pytorch 的基础知识。与此同时,我还参加了由 KPIT 赞助的 Udacity 自动驾驶汽车工程师纳米学位课程,在那里,作为我的项目之一,我在 Keras 为自动驾驶汽车编写了一个端到端深度学习模型。因此,我决定用 Pytorch 重写代码,并分享我在这个过程中学到的东西。好了,我说的够多了,让我们用一件事来设置我们的机器——对过度合身说不!
项目资源 1。 Udacity 的自动驾驶汽车模拟器
2。当然还有 Python 和 Pytorch 框架
3。如果你的机器不支持 GPU,那么我会推荐使用 Google Colab 来训练你的网络。它免费提供 GPU 和 TPU 时间!
4。如果你在收集训练数据时遇到问题,你可以使用 Udacity 提供的来训练你的网络。
5。完整代码可在此处获得,Colab 笔记本可在此处获得。6。本文提到的 Nvidia 研究论文可以在这里找到。
收集数据 Udacity 提供的数据集工作良好,但不足以让汽车在复杂的地形中行驶(就像 uda city 模拟器中的第二条赛道)。为了从 track 2 收集数据,我们首先需要在我们的项目目录中创建一个文件夹。我们姑且称这个文件夹——数据。现在,启动我们的模拟器。从菜单中选择第二个轨道,并转到训练模式选项。
The simulator main menu
一旦进入训练模式,您将在屏幕的右上角看到一个录制选项。点击图标,浏览到数据文件夹。按选择。
Browsing to the data folder
再次按下录制图标后,您就可以开始录制您的骑行了!现在,如果你像我一样是一个游戏新手,我会建议慢慢来,尽量确保你的车尽可能停在路中央,即使是在转弯的时候。这将有助于获得更好的训练数据,最终形成一个好的模型。我们将记录在赛道的一个方向上行驶 2 圈,以及在相反方向上行驶 2 圈,以确保转弯是反向的。这将确保我们的模型不会过度拟合,使更好的左转弯和右转弯。我们开始吧!
Capturing training data
训练数据现在存储在数据文件夹中。里面一个文件夹一个文件: IMG 和 driving_log.csv 。我们的下一个工作是从 CSV 文件中读取图像的名称及其相关的导向数据,并从 Python 中的 IMG 文件夹中加载相应的图像。
编码时间到了!
如果你不想在本地机器上安装不同的库和框架,或者你想利用免费的 GPU 时间,那么使用 Colab 会更好。另外,如果您不喜欢收集数据,那么您可以使用!wget URL
导入 Udacity 的数据集,并使用!unzip
解压缩文件。最重要的是。导入邮件头:
读取和分割数据
上面的代码从日志文件中读取所有内容,并将其存储到sample
数组中。行next(reader, None)
带走包含列名的第一行。我们将使用这个数组将我们的数据分成训练和验证。据我所知,一个很好的实践是将 20–30%的训练数据作为验证集来比较验证损失和训练损失,这样我们可以避免过度拟合。让我们这样做:
在数据加载器中加载图像 现在我们已经制作了样本,是时候读取图像并对其进行扩充了。这是重要的一步,因为这将有助于推广我们的模型。但是即使对于 GPU 来说,这个过程也是计算量大且耗时的。诀窍是通过批量获取数据、扩充数据并将其发送到模型进行训练来并行化这一过程。Keras 使用 python generators
和fit_generator
函数实现了这个过程。在 Pytorch 中,我们将使用Dataset
类和Dataloader
函数来实现这个功能。为了实现这一点,我们必须重载这个类的一些函数,即__getitem__
、 __len__
和__init__
函数。我们还必须定义一些扩充过程。我编写了一个基本的函数,它将拍摄一张图像,随机裁剪它,水平翻转它,同时拍摄转向数据的负片。基本上,裁剪有助于模型通过去除图像中的天空和其他分散注意力的东西来专注于道路,翻转是为了确保图像被推广到左转弯和右转弯,本质上是将汽车保持在道路的中心。其他技术可以是添加随机亮度来模拟一天的不同持续时间,在图像上叠加一层失真和噪声来模拟下雨,在道路上添加随机阴影等。但是我们现在只关注最基本的。
接下来,我们定义Dataloader
类,并将这个augment
函数传递给输入批量样本,连接操纵数据和图像并返回它。
注意还有一个论点叫做transform
。我们的转换将使用一个lambda
函数将图像数组值归一化到范围0–1。接下来,我们使用Dataloader
函数将所有内容添加到一个生成器中,该生成器将在训练期间被批量调用。我们定义一个 32 的批处理大小,并在将它传递给 DataLoader
时对它们进行洗牌。num_workers
定义了多少工人将并行创建批处理。
模型架构
是时候建立我们的模型了。让我们仔细看看 Nvidia 的研究论文。继续并在新标签页中打开它。链接在上面的参考资料部分。
如果你向下滚动到 pdf 的第 5 页,你会看到他们建造的 CNN 的架构。
好吧,你这个懒人,这就是我说的形象😝。如果你看这些数字,你会看到卷积层的深度和全连接层的输入和输出特征。现在,每个特征地图都有一些提到过的内核。正如论文中提到的,Nvidia 的人使用 YUV 图像作为输入,并在前三个卷积层中使用 2×2 步幅和 5×5 内核的步长卷积,在最后两个卷积层中使用 3×3 内核大小的非步长卷积。不过有趣的是,并没有提到 maxpool 层。我试图虔诚地遵循上述架构,建立 CNN。这是我想到的:
不幸的是,这种方法有问题。也许是缺少数据,也许是缺少最大池层,网络表现得很糟糕。即使在直道上,汽车也总是偏离道路。经过谷歌搜索,我发现了这个回购协议。这里使用的模型是 Nvidia 架构的简化版本。我试过了,当用足够多的纪元训练时,效果非常好。所以对我来说,最后的架构是这样的:
但是,您可以随意试用带有 maxpool 层的第一个模型。它需要一些计算填充和输出的高度和宽度。让我们花点时间来看看这里的一些东西-
a)*nn.Module*
-py torch 中使用了nn.Module
类来创建 CNN。我们必须过载__init__()
和forward()
功能来构建网络。为了避免编写重复的代码,我使用了nn.Sequential()
。无论nn.Sequential()
函数中有什么,都会被顺序应用于输入。很漂亮,是吧? a) elu 激活- 这里使用的激活函数是 elu(指数线性单位)。与 relu(校正线性单元)不同,elu 加快了训练过程,还解决了消失梯度问题。更多细节和 elu 函数的方程式可在此处找到。
b)图像展平- 卷积层的输出在传递到全连接层之前的展平用下面的行完成:output.view(output.size(0), -1)
。
优化器和标准
接着,本文还讨论了使用均方误差损失作为标准和 Adam 优化器。让我们把它编码出来!我把学习率设为 0.0001。可以做相应的调整。
嗯,我们有进展了。在我们编写最后的训练和验证部分之前,让我们进入 GPU 的世界吧!
Pytorch 和 CUDA Pytorch 提供了与支持 CUDA 的 GPU(对不起 AMD)的轻松集成。这是通过一个简单的device()
函数完成的。它可以极大地加快训练过程,比普通 CPU 快 10 倍。为什么不利用这一点呢?为此,我们需要将数据和模型传输到 GPU 进行处理。这确实比听起来容易。我们定义了一个函数,它将对所有接收到的输入执行此操作。
请注意,我已经将它转换为float()
,以便模型能够计算输入。
训练
是时候训练我们的杰作了!我们首先将模型传输到 GPU,然后,使用生成器获取数据,并将数据传输到 GPU。接下来,我们使用optimizer.zero_grad()
函数设置优化器在反向传播过程中不累积梯度。最后,我们计算总训练损失,并除以批量大小,以获得每个时期的平均训练损失。非常简单。
验证 验证也是一样,但这次我们将确保我们的模型处于评估模式,这样我们就不会错误地更新梯度和反向传播错误。我们使用model.eval()
来改变模式,并使用torch.set_grad_enabled(False)
来确保模型不会跟踪。损失的计算方法相同。
保存模型 代码的最后一步到了!训练完成后,我们保存模型,以便在模拟器中自动驾驶汽车。我们制作一个state
字典,并使用torch.save()
将模型保存为 .h5 格式。
有趣的事情开始了 在我们开始测试我们的模型之前,我们需要一个文件来加载我们的模型,从模拟器中获取轨道的帧来处理我们的模型,并将转向预测发送回模拟器。不要害怕!我做了一个drive.py
文件,基本上是我在项目中使用的 Udacity 的 [drive.py](https://github.com/ManajitPal/BehavioralCloning/blob/master/model.py)
文件的 Pytorch 版本。如果你想要不同的节流等,你可以通过代码和实验。现在,让我们复制粘贴以下代码的内容。
[## ManajitPal/deeplearningforself 驾驶汽车
这是 Nvidia 的模型在 Pytorch 中的一个实现,用于为自动驾驶汽车构建深度学习神经网络。…
github.com](https://github.com/ManajitPal/DeepLearningForSelfDrivingCars/blob/master/drive.py)
此外,我们需要一个包含模型架构的model.py
文件。创建文件并粘贴您的网络架构。如果你面临任何问题,可以随意看看我在回购中的model.py
文件。
如果你一直在使用 Google Colab 编写你的代码,在同一个目录下下载model.h5
文件。启动终端,cd
到您的目录,用我们的模型运行脚本:
python drive.py model.h5
如果您机器上安装了两个不同的 python 版本,请使用python3
而不是python
。当您看到任何弹出窗口时,单击允许。
再次打开模拟器,现在选择自主模式。车要像老板一样自己开!
这就对了。你自己的无人驾驶汽车管道。多酷啊!😁
这里有一个你可能会期待的小演示:
故障排除 你可能会看到汽车摇晃得很厉害,或者它被限制在道路的一边。这可能意味着数据没有被适当地扩充和概括。尝试获取更多的训练数据或增加更多的随机性。
你也可能看到汽车根本不动。在这种情况下,请在运行期间检查终端是否有任何错误。大多数错误应该通过安装适当的库依赖项来解决。
结论 非常感谢您花时间阅读我的文章。我真的希望这能帮助到想学习一些关于深度学习在自动驾驶汽车中使用的概念的人。此外,这是我第一篇与人工智能相关的文章,我是一个完全的初学者,所以如果你能在下面的评论中留下任何积极或消极的反馈,你的想法或其他你可能认为是为自动驾驶汽车构建人工智能的更好方式的资源,我将非常感激。干杯伙计们!
用于船只检测和分割的深度学习
原文:https://towardsdatascience.com/deep-learning-for-ship-detection-and-segmentation-71d223aca649?source=collection_archive---------4-----------------------
卫星图像深度学习的端到端管道
Photo by Cameron Venti on Unsplash
被困在付费墙后面?点击这里阅读完整故事与我的朋友链接!
从遥感图像中检测船舶是海事安全的一个重要应用,海事安全包括交通监视、防止非法捕鱼、石油排放控制和海洋污染监测等。这通常是通过使用自动识别系统(AIS)来完成的,该系统使用甚高频无线电频率向附近其他船只和陆基系统上的接收装置无线广播船只的位置、目的地和身份。
自动识别系统在监测法律要求安装甚高频应答器的船只方面非常有效,但无法检测到没有安装的船只和断开应答器的船只。那么如何检测这些不合作的船呢?这就是卫星图像可以发挥作用的地方。合成孔径雷达(SAR)图像使用无线电波对地球表面进行成像。与光学成像不同,这些仪器使用的波长不受时间或气象条件的影响,因此无论是白天还是晚上,无论是多云还是晴朗的天空,都可以获得图像。卫星正在收集这些图像,这些图像可用于制作船只检测和分割算法。
这个项目是在卡格尔举行的空中客车船只探测挑战赛的一部分。
挑战
建立自动识别遥感目标是否为船只的算法。该算法必须非常精确,因为生命和数十亿美元的能源基础设施正处于危险之中。
Ship detection and segmentation
环境和工具
- sci kit-学习
- sci kit-图像
- numpy
- 熊猫
- matplotlib
数据
数据集可以从 kaggle 网站下载,可以在这里找到。
基础
这是一个典型的实例分割问题。我在这个项目中使用过 Mask-R-CNN。
- 图像分类:对图像中的主要物体类别进行分类。
- 对象检测:识别对象类别,并使用图像中每个已知对象的边界框定位位置。
- 语义分割:为图像中的每个已知对象识别每个像素的对象类别。标签是类感知的。
- 实例分割:识别图像中每个已知对象的每个像素的每个对象实例。标签是实例感知的。
代码在哪里?
事不宜迟,让我们从代码开始吧。github 上的完整项目可以在这里找到。
我从加载所有需要的库和依赖项开始。
接下来,我设置工作目录和文件。
我继续定义函数来显示一些带有船只遮罩和编码解码遮罩的样本图像。这里面具被用作地面真实图像。
Sample-1
Sample-3
接下来,我将图像分成两组,即训练集和验证集。
之后,我从我的分叉存储库中加载 Mask-R-CNN 模型。原来的储存库可以在这里找到。
然后我创建了一个类,它有三个函数,分别用于加载数据集、加载蒙版和将图像作为参考。
我还为类似的工作创建了另一个启用 gpu 的类。由于巨大的数据集大小,在这种情况下使用 gpu 是必须的。作为一个额外的信息,google colab 和 kaggle 内核目前是免费的基于云的 gpu 提供商。
我继续编写脚本来加载训练数据集。
让我们想象一下到目前为止我们得到了什么。
到目前为止一切顺利。我继续从我分叉的 github 存储库中加载预训练的 coco 权重。
接下来我训练了模型。为了更快的结果,我只训练了两个时期。为了适当的融合和良好的结果,需要做的远不止这些。请随意使用这里的超参数。
结果
Sample Result 1
Sample Result 2
在某些情况下,当该模型检测到一个小岛或海岸岩石作为船只时,它会失败。换句话说,这个模型正在产生假阳性。
False positive
而在其他时候,该模型未能检测到船只,如下图所示。换句话说,这个模型正在产生假阴性。
False negative
结论
虽然这个项目还远未完成,但在如此多样的现实世界问题中看到深度学习的成功是令人瞩目的。如果我们能够检测和分割图像中的船只,这将对瑞典、挪威和加拿大等北方国家的物流和运输团队有很大的帮助。通过从卫星图像中实时跟踪船只,它可以为集装箱船和船只带来一个全新的运输层面。
参考资料/进一步阅读
[## 在卫星图像中检测船只
使用行星卫星图像对旧金山湾的船只进行分类
medium.com](https://medium.com/dataseries/detecting-ships-in-satellite-imagery-7f0ca04e7964) [## 使用高分辨率卫星图像和天基 AIS - IEEE 会议
本文介绍了 9 月在挪威北部特罗姆瑟市附近的马兰根地区进行的一项试验…
ieeexplore.ieee.org](https://ieeexplore.ieee.org/abstract/document/5730248/) [## 大卫电视/卡格尔-空中客车-船舶-检测
空中客车船只探测挑战(Kaggle) -尽快在卫星图像上找到船只…
github.com](https://github.com/davidtvs/kaggle-airbus-ship-detection)
在你走之前
相应的源代码可以在这里找到。
[## abhinavsagar/ka ggle-解决方案
Kaggle 竞赛笔记本样本。查看相应的媒体博客文章细胞核分割使用…
github.com](https://github.com/abhinavsagar/Kaggle-Solutions)
快乐阅读,快乐学习,快乐编码。
联系人
如果你想了解我最新的文章和项目,请关注我的媒体。以下是我的一些联系人详细信息:
- 个人网站
- 领英
- 中等轮廓
- GitHub
- 卡格尔
单细胞生物学的深度学习
原文:https://towardsdatascience.com/deep-learning-for-single-cell-biology-935d45064438?source=collection_archive---------7-----------------------
生命科学的深度学习
通过深度学习解析细胞架构
Image source
这是系列生命科学深度学习的第二篇文章。在前一篇中,我展示了如何在古代 DNA 上使用深度学习。今天是时候谈谈深度学习如何帮助细胞生物学捕捉细胞群体的多样性和复杂性了。
单细胞 RNA 测序(scRNAseq) 几年前带来了生命科学的革命,带来了前所未有的分辨率来研究细胞群体中的异质性。影响如此巨大,以至于《科学》杂志宣布 scRNAseq 技术为 2018 年的突破。主要的进步是认识到尽管生物细胞在显微镜下看起来形态相似,但它们表达的基因可能非常不同,这反过来导致细胞之间的功能差异。为了捕捉这种细胞多样性,人类细胞图谱社区宣布了一个雄心勃勃的目标,要建立一个人体内存在的数万亿个细胞的综合图谱。
随着 10X 基因组学 单细胞基因表达平台的发展,从几十万甚至百万个单个细胞中获取完整的转录组信息几乎成为一种常规。因此,scRNAseq(连同生物医学成像和基因组学)代表了目前真正的大数据,它具有卓越的统计能力,并为应用机器和深度学习进行单细胞数据分析打开了新的视野。
在这里,我将简要概述该领域,阐述主要的分析挑战,并展示如何将深度学习与 Keras 和 TensorFlow 一起用于单细胞 RNA 测序数据分析中的无监督学习问题。
为什么单细胞生物学非常适合深度学习?
对一些数据进行统计分析,我们通常需要了解 a) 特征数量 p (基因、蛋白质、遗传变异、图像像素等)之间的平衡。),以及 b) 观察次数 n (样本、细胞、序列等)。).人类基因组大约有 p=20K 蛋白质编码基因,而最近发表的 10X scRNAseq 数据集包括 n~1.3M 和 n~2M 个体细胞。这意味着对于 scRNAseq 来说 n > > p 这是一个典型的深度学习限制,即在这个限制下工作,我们可以远远超出基于线性代数的分析,并捕获 scRNAseq 数据中的高度非线性结构。
Recent studies report unprecedented scRNAseq sample sizes which is ideal setup for Deep Learning
对于其他限制,即当 n << p or n ~ p, Bayesian and Frequentist statistical frameworks, respectively, are more appropriate. In other words, working with scRNAseq data we have a luxury problem: while 过拟合和缺乏可推广性是计算生物学中常见的问题时,这里对于 scRNAseq,我们必须注意欠拟合,即如何使用大多数数据。
不仅 scRNAseq 目前在生命科学领域蓬勃发展,而且在单细胞水平上传递其他类型信息(生物信息学术语中的组学)的技术也变得越来越普遍。研究染色质可及区域(scATACseq) 的最新进展产生了具有> 100K 单细胞的数据集。虽然单独的 scATACseq 可能无法保证发现稀有细胞群体的新方法(单细胞数据分析的主要目标),但它为 与 scRNAseq 的集成提供了巨大的潜力,从而提高了将细胞分配到特定群体的准确性。
Chromatin accessibility regions (ATACseq) is complementary for scRNAseq analysis
最后,单细胞多组学技术 ( CITE-seq , scNMTseq 等。),即来自相同生物细胞的多个信息来源,尚未达到 scRNAseq 典型的巨大样本量,但对于未来与深度学习的数据整合挑战而言非常有希望。
通过深度学习降低维度
由于 scRNAseq 分析的主要目标是发现新的细胞群体,因此在机器学习术语中,它是一种无监督分析。因此,用于 scRNAseq 的两个最重要的分析技术是维度缩减和聚类。Autoencoder 是一种无监督的人工神经网络(ANN ),具有有趣的“蝴蝶”结构,通常用于降维。与诸如主成分分析(PCA)、多维标度(MDS)、因子分析(FA)等线性技术相反。,自动编码器执行非线性降维,因此可以捕获单细胞数据的高度非线性结构。
Autoencoder is an Artificial Neural Network (ANN) with the “butterfly” architecture
在这里,我将使用约 8K 脐带血单核细胞(CBMCs) CITEseq scRNAseq 数据集为例,展示线性(PCA)和非线性(Autoencoder)维数缩减技术之间单细胞分辨率的差异。请注意,下面的代码假设输入文件为表格格式,基因为列,细胞为行,文件的最后一列必须是使用您最喜欢的 scRNAseq 聚类技术获得的细胞注释。我推荐使用基于图的聚类和 Louvaine 社区检测,这对于高维数据是健壮的,在流行的seurascrna seq 工作流中实现。
为了比较,我在这里也要加上t-分布式随机邻居嵌入(tSNE) 图,这是 scRNAseq 领域目前的金标准非线性降维技术。tSNE 的一个问题是它不能处理高维数据,比如 scRNAseq。因此,通常的做法是执行 PCA(线性!)作为预降维,并将输出馈入 tSNE。然而,我们可以通过使用自动编码器以非线性方式执行预降维步骤来做得更好。让我们展示两种策略的 tSNE 图:
如果你不习惯看这种图,这里一个点是一个细胞,颜色对应不同的细胞类型。你应该观察 12 个细胞群体,但是你基本上不能从 PCA 图中看到它们(细胞严重重叠),因为线性维数减少不能解析单个细胞结构。Autoencoder 图片看起来更好,不同的细胞群体是明显可检测的。tSNE 通常提供更清晰的小区斑点。然而,在这种特殊情况下,自动编码器上的 tSNE 似乎提供了更密集和透明的集群,尤其是在 PCA 图的 tSNE 中,紫色细胞群遍布蓝色集群。因此,深度学习有望提高检测新细胞群体的分辨率。
寻找可扩展的维度缩减
除了难以处理高维数据之外,当细胞数量达到数十万甚至数百万时,tSNE 的伸缩性很差。FItSNE 是 Barnes-Hut tSNE 的一个新的有前途的修改,它似乎对大量数据有更好的伸缩性。然而,在 130 万小鼠脑细胞上运行 FItSNE 时,我很难将它放入内存。特别是,我想获得高度复杂的 tSNE 图,以便检查数据的全局结构。然而,困惑= 350 是我在一个计算机集群上使用一个 256GB RAM 的节点所能达到的最大困惑。运行 FItSNE 非常简单,类似于他们在 R 中执行 tSNE 的方式(同样,Cluster 列包含单元格注释):
均匀流形逼近和投影(UMAP ) 是另一种非常有趣的非线性降维技术,目前似乎在许多方面优于 tSNE。它比 tSNE 快,与 FItSNE 一样快,但不需要那么多内存,并且它似乎可以捕获 scRNAseq 数据的局部和全局结构。也许我看到的唯一缺点是我目前正在经历的 UMAP 背后的一点不透明的数学。
最近发布了一些基于 变型自动编码器 的有趣方法。其中之一是SCVIS这是一种神经网络,它捕捉并可视化单细胞基因表达数据中的低维结构,此外还保留了局部和全局邻居结构。为了在 130 万小鼠脑细胞上运行 SCVIS,我使用了以下命令行:
下面,我使用来自 10X Genomics 的 130 万小鼠脑细胞,对上述 4 种降维技术(即 PCA、tSNE / FItSNE、UMAP 和 SCVIS)进行了比较:
Comparison of dimensionality reduction techniques on 1.3M 10X mouse brain data set
对于上述 CITEseq 的情况,我们可以看到,与 PCA 相比,非线性维度减少技术(SCVIS、UMAP 和 tSNE / FItSNE)能够分辨 scRNAseq 数据中的所有细胞群体。在这三种技术中,UMAP 是最快的,并且提供了相当好的数据低维表示。为了更精确地计算时间,SCVIS 用了大约 6 小时,FItSNE 用了 3 小时和大量内存,UMAP 在我的笔记本电脑上用了大约 3 小时。
考虑到不断增长的 scRNAseq 数据量,我预测 UMAP 和自动编码器将在未来取代 tSNE 。
带 Keras 的 scRNAseq 深度自动编码器
最后,在这里我将演示如何使用 Keras 从头实现并运行一个深度自动编码器。正如你将看到的,这并不难。为了避免将整个数据集加载到内存中的困难,我选择了前 19 个主成分,通过重采样,即改组基因表达矩阵并检查由置换矩阵(零假设)解释的方差百分比,我发现它们是显著的。自动编码器逐渐将维数从 19 减少到 2(自动编码器的瓶颈),每个隐藏层减少一个维数。
Deep Autoencoder for dimensionality reduction of 1.3M 10X mouse brain cell, Keras implementation
我们可以看到,尽管我没有特别试图找到一个可能提供更好分辨率的神经网络的最佳配置,但细胞群体是完全可以区分的。 Deep Autoencoder 的一个巨大优势是,它看起来非常快,因此可伸缩对于大量的 scRNAseq 数据,我的笔记本电脑只花了几分钟就让模型收敛并获得了上面的图。
带 TensorFlow 的 scRNAseq 深度自动编码器
Keras 很棒,很快,很容易,但有时我觉得我用 TensorFlow 控制神经网络要好得多。例如,使用 Keras,人们永远不会有“手动”连接节点的感觉,这是我很欣赏使用 TensorFlow 实现的理解深度。后者的一个小缺点是,像小批量学习这样有用的技巧必须在 TensorFlow 中手工编码,而在 Keras 中是自动包含的。总之,下面是 TensorFlow Deep Autoencoder 的代码和降维图:
Deep Autoencoder for dimensionality reduction of 1.3M 10X mouse brain cells, TensorFlow implementation
同样,低维表示看起来很有希望。通过对配置和其他超参数的一些调整,人们有可能获得更好的分辨率。同样,对于 Keras 来说,TensorFlow 自动编码器的实现速度非常快,与 FItSNE、UMAP 和 SCVIS 制作这种降维图所用的时间相比,只需几分钟。如果出于某种原因,你的分析需要重采样过程,这对于 FItSNE、UMAP 和 SCVIS 来说不太可行,但对于深度学习来说应该非常简单。
摘要
在这里,我们了解到单细胞 RNA 测序(scRNAseq)正在迅速提高我们对生物细胞中功能多样性的理解。维度缩减可能是典型 scRNAseq 分析背后最重要的分析工具。金标准降维技术 tSNE 由于 scRNAseq technologies 提供的大量数据,目前在可扩展性方面遇到了困难。通过自动编码器和 UMAP 的深度学习提供了目前最灵活和可扩展的方式来获得 scRNAseq 数据的低维表示,并且很可能在未来取代 tSNE。最后,我们已经学会了如何使用 Keras 和 TensorFlow 为巨大的 10X Genomics 1.3M 小鼠脑细胞 scRNAseq 数据集实现深度自动编码器。
希望你喜欢阅读这篇文章,让我在评论中知道你对人工智能和深度学习感兴趣的生命科学方向,我希望听到你的反馈。在媒体关注我,在推特 @NikolayOskolkov,关注我,在我的 github 上查看这个帖子的完整 Jupyter 笔记本。下一篇文章将是关于使用深度学习进行多组学生物医学数据集成,敬请关注。
用于生存分析的深度学习
原文:https://towardsdatascience.com/deep-learning-for-survival-analysis-fdd1505293c9?source=collection_archive---------6-----------------------
最近我得到了一个从事生存分析的机会。像任何其他项目一样,我很兴奋,并开始探索更多关于生存分析的内容。根据维基百科,
生存分析是统计学的一个分支,用于分析一个或多个事件发生前的预期持续时间,如生物有机体的死亡和机械系统的故障
简而言之,这是一个时间事件分析,它关注于感兴趣的事件发生的时间。事件可以是死亡、传感器故障或疾病的发生等。生存分析是一个热门领域,在医学、流行病学、工程学等领域有广泛的应用。
你想知道深度学习是如何改变如此重要的领域的吗?如果是的话,那么你来对地方了。
当我开始看一看深度学习如何被用于生存分析时,令我惊讶的是,我找不到任何好文章。我接触到的所有材料和教程都只使用了统计方法。但是当我稍微深入挖掘时,我发现涉及神经网络的生存分析的重要研究最初是由 Faraggi 和 Simon 在 1995 年发表的[5]。
生存分析简介
将通过理解生存分析中的关键定义从基础开始。
设 T 为随机变量,表示事件发生前的等待时间。除了通常的概率函数,我们还可以定义一些与生存分析相关的基本函数,如生存函数、风险函数等。
生存函数 S(t) 是到时间 t 感兴趣的事件没有发生的概率。属性包括 S(0) = 1 、 S(∞) = 0 、 S(t) 为非递增。
并且危险函数 λ(t) 可以被视为事件在时间 t 瞬间发生的概率,假设事件在时间 t 之前没有发生。
生存分析数据集
需要注意的一个关键点是,我们不是在处理一个通常带有标签的数据集。生存分析的数据不同于标准回归或分类问题。在生存分析中,我们处理的是删失数据。删失是一种缺失数据问题。
每当我们进行生存分析时,都会得到一个学习周期内的训练数据。如果被研究对象在研究期内没有经历该事件会怎样?。则称之为右删失数据。类似地,我们的数据集中也可以有左删失和区间删失样本。通常,我们将处理具有右删失样本的数据集。
Example dataset — **lifelines.datasets.load_static_test**
在上面的示例数据集中,列 id 标识所研究的单个对象。列 E 将告诉我们数据是否被审查。换句话说,如果列 E 的值为 1,则相应的对象在研究期间经历了感兴趣的事件。这里,除了 id 为 3 的对象外,所有对象都经历了该事件。对象 id 3 被右删。列 t 是事件发生所用的时间,在删失数据的情况下,是研究时间。列 var1 , var2 这里是对象的特征或协变量。例如,协变量可以是性别、年龄等。同时预测患者器官衰竭或心脏病发作的概率。
标准方法
在使用神经网络解决生存分析问题之前,我们现在将简要地研究传统的统计方法。我们可以把标准方法大致分为非参数方法、半参数方法和参数方法。
用于估计生存函数的最流行的非参数方法是Kaplan–Meier 估计法。最大的限制是它不能估计考虑协变量的存活率。
考虑协变量的生存数据的基本模型是比例风险模型。该模型由 D. Cox 教授(1972 年)提出,也被称为 Cox 回归模型。
Cox 比例风险模型(CoxPH)假设风险函数由两个非负函数组成:基线风险函数【λ₀(t】和风险比或风险得分 r(x) = exp{h(x)} 。风险分值被定义为对象的观察协变量对基线危害的影响。Cox 模型使用线性函数和潜在基线风险函数来估计对数风险函数 h(x) ,而不采用任何特定形式。这种半参数方法比参数方法更灵活,成为更受欢迎的选择。
这种比例风险假设也可以用生存函数来表示,如下所示。这里的 S₀(t) 是基线生存函数。
CoxPH 适应神经网络
许多人已经尝试使用神经网络进行生存分析。随着深度学习领域的进步,最近的结果很有希望。
当涉及到用于生存分析的深度学习时,我们有两种主要的综合方法。一种方法可以看作是对 Cox 比例风险假设的修改,另一种方法使用完全参数化的生存模型。deep surv【1】,Cox-Nnet【2】将属于 CoxPH 适应方法,而Nnet-survival【3】,RNN-SURV【4】将属于第二种方法。我们将更加关注 CoxPH 适应方法,因为 Cox 模型已被证明非常有用,并且为大多数医学研究人员所熟悉[3]。
在 Cox 模型中,除了比例风险假设,我们在估计对数风险函数 h(x) 时还有另一个假设。我们用一个线性函数来估计 h(x) 。在许多情况下,例如,建模非线性基因相互作用,我们不能假设数据满足线性比例风险条件[1]。我们需要一个更复杂的非线性模型来预测对数风险函数h(x),而神经网络可以满足我们的要求。
DeepSurv
在本节中,我们将详细讨论 DeepSurv,以了解深度学习如何准确地用于生存分析。DeepSurv 是一个深度前馈神经网络,它预测由网络权重 θ 参数化的对数风险函数 h(x) 。
DeepSurv Architecture
对象的观测协变量或称为特征作为网络的输入给出。网络的隐藏层包括一个完全连接的节点层,后面是一个断开层。输出层有一个线性激活的节点,用于估计 Cox 模型中的对数风险函数。网络的损失函数如下所示。
这是损失函数背后的直觉。为了最小化损失函数,我们需要最大化每个具有可观测事件 (E = 1) 的对象在红框内的部分。为了最大化该部分,我们需要增加具有可观察事件的对象 i 的风险因子,并降低直到时间 Ti 之前没有经历该事件的对象 j 的风险因子,其中 Ti 是对象 i 经历该事件的时间。
现代深度学习技术,如缩放指数单元、Adam 优化器等。用于 DeepSurv 以获得更好的性能。Cox-nnet 与 DeepSurv 非常相似,但 Cox-nnet 和 DeepSurv 都只输出风险系数。他们没有估计基线函数。我们可以使用 Breslow 估计器等方法来生成基线函数[3]。
我前面说过,从 90 年代中期开始,人们就在尝试使用深度学习方法进行生存分析。鉴于深度学习的最新进展,在生存分析中使用深度学习的结果很有希望。当一个对象的协变量与其危险之间存在复杂关系时,深度学习技术的表现与其他最先进的生存模型一样好,甚至更好[1]。仍有很大的改进和研究空间。对于像我这样相信人工智能可以积极重塑许多重要领域的人来说,这个话题非常有趣。
这是我的第一篇文章,我希望这将是有益的。谢谢:)
参考文献
[1]卡兹曼·JL、沙哈姆·U、克洛宁格·A、贝茨·J、江·T 和克鲁格·Y、 DeepSurv :使用 Cox 比例风险深度神经网络的个性化治疗推荐系统(2018),BMC 医学研究方法学
[2]程婷,朱 X,加米尔 LX, Cox-nnet :高通量组学数据预后预测的人工神经网络方法(2018),计算生物学
[3] Michael F. Gensheimer 和 Balasubramanian Narasimhan,神经网络的可扩展离散时间生存模型 (2019),arXiv:1805.00917
[4]埃莉诺拉·久奇利亚、安东·涅姆琴科和米哈埃拉·范德沙尔, RNN-SURV :生存分析的深度循环模型(2018),LNCS 11139–11141
[5] Faraggi D,和 Simon R,生存数据的神经网络模型 (1995),医学统计学
符号数学的深度学习
原文:https://towardsdatascience.com/deep-learning-for-symbolic-mathematics-5830b22063d0?source=collection_archive---------25-----------------------
用于绝对精确任务的神经网络。
介绍
本文试图描述 Guillaume Lample 和 Franç ois Charton 的论文“符号数学的深度学习”的主要内容。
深度学习方法已经成功地用于许多任务,最常见的是大幅度提高当前的艺术水平。例子包括:
- 图像分类。(80%的把握图片显示的是一只狗)
- 翻译。(将文本从一种语言翻译成另一种语言)
- 自动驾驶。(给定当前传感器输入,向右转向 5.785 度)
Different applications of DeepLearning. Sources: Cat (pascualamaia), Car ( Paul Sableman)
所有这些场景的共同点是,对于任何给定的输入,一定范围的输出都是可接受的:
- 图像分类。“高信心”表示为 80%还是 83%都没关系。
- 翻译。一个句子有多个有效的翻译。
- 自动驾驶。准确的转向角度并不重要,只要方向正确,幅度可以接受。
上面提到的论文探索了一种不同的场景。一种输出要么 100%正确,要么 100%不正确:求解数学表达式。
更具体地说,本文探讨了两项任务:
- 对函数进行积分
- 求解一阶或二阶常微分方程(ODE)
在本文中,我将只描述函数集成的过程。通常使用以下符号:
- f 是任意函数,其积分为 F
- F 是任意函数,它的导数是 f
对于积分的任务,给定一个函数 f 并且它的积分 F 是期望的答案。这个答案有多种正确的表达方式,但每种方式都是 100%正确的。其他任何表述都是 100%不正确。
深度学习模型:Seq2Seq
用来解决这个问题的深度学习架构被称为 Seq2Seq 。关于它是什么以及如何工作的详细解释可以在这里找到。
现在您需要知道的是,Seq2Seq 模型接受任意长度的输入序列,并将其转换为任意长度的输出序列。
Input sequence in german, Output sequence translated to english.
对于功能集成任务,该模型最重要的特性是:
- 输入和输出序列可以具有任意长度,且这些长度可以不同
- 从输入序列中的项目到输出序列中的项目的一对一关系是不必要的
这两个特性使得这种模型非常适合当前的任务。输入序列是定义输入函数的符号,输出序列是定义积分的符号。
但是,我们究竟如何将数学表达式输入到这个模型中呢?
作为序列的数学表达式
通常数学表达式已经是序列形式,即所谓的中缀符号。这样称呼是因为二元运算符写在它们所引用的两个参数之间。
但是,这种表示法不太适合在 seq2seq 模型中进行处理。这是因为为了使运算的顺序明确,需要大量的括号:
Top: Commonly used infix-notation. Bottom: Parenthesis for unambiguous order of operations
为了避免这个问题,本文使用了所谓的前缀符号。要从中缀符号表达式构建前缀符号表达式,请使用以下步骤:
首先,构建一个树来捕获表达式中操作的顺序和值。
第二,按照以下规则从上到下从左到右遍历树:
- 如果当前节点是一个原始值(一个数字),则将其添加到序列字符串中
- 如果当前节点是二元运算,则将运算符号添加到序列字符串中。然后,添加左侧子节点的表示(可以是递归的)。然后,添加右子节点的表示。
在上面的例子中,这个过程将导致表达式:
数据生成
每个深度学习应用程序都需要大量数据进行训练,集成符号表达式也不例外。幸运的是,有一些方法可以自动生成任意数量的训练数据。论文提出了 3 种不同的生成函数->积分对的方法。
向前一代
这个很简单。随机生成一个符号函数 f,然后使用外部工具计算符号整数 f。外部工具可以是像 SymPy 这样的库。然后将对(F,F)用作训练样本。
这种方法有两个主要缺点:
- 它依赖于一些其他的库,这些库实现了我们试图解决的完全相同的任务
- 即使使用第三方库,自动符号集成也不总是有效。这意味着在训练集中只有对(F,F)存在,对于这些对,存在可以求解 F 的积分的库,因此限制了多样性。
此外,由这种方法产生的对(F,F)具有这样的性质,即 F 通常由比 F 少得多的符号组成。这是自动符号积分如何工作的结果。
落后一代(BWD)
利用微分容易,积分难的事实。随机生成一个函数 F,然后将其自动微分得到函数 F。然后将(F,F)对作为训练样本。
由这种方法产生的对(F,F)具有这样的性质,即 F 通常比 F 包含更少的符号。这是自动符号微分如何工作的结果。
零件集成(IBP)
这种方法利用了被相乘的函数的积分的数学性质。该属性如下所示:
用这个技巧生成函数的算法:
- 随机生成函数 F 和 G
- 自动微分得到 f 和 g
- 如果 Fg 已经是训练集的一部分,我们就知道它的积分。使用上面的公式计算 fG 的积分。
- 如果 fG 已经是训练集的一部分,我们就知道它的积分。使用上面的公式计算 Fg 的积分。
附加步骤
在用上述方法中的一种或组合建立训练集之后,执行这两个附加步骤:
- 简化。表达式被简化,以强制模型也输出简化的表达式。
Simplifiying expressions
- 删除无效表达式。由于表达式的随机生成性质,它们可能包含无效的子术语。如果有,从表达式树中删除这些术语。
Invalid expressions are trimmed from the expression trees
结果
现在基础工作已经完成,让我们看看纪尧姆·兰普尔和弗朗索瓦·查顿取得的成果。
单台发电机的培训/测试
使用仅来自 FWD、BWD 或 IBP 中的一个的训练数据,并根据从相同方法产生的数据评估模型,产生非常好的结果:
- 前进:96.2%的准确性
- BWD:99.7%的准确率
- IBP:99.5%的准确率
与流行的数学框架相比
接下来,作者将他们的精确度与 Mathematica 、 Maple 和 Matlab 产生的结果进行了比较。仅评估了 BWD 发生器。结果很明显:
- Mathematica(超时 30 秒):84.0%
- Matlab: 65.2%
- 枫叶:67.4%
- seq 2 序列:99.6%
seq2seq 模型明显优于 BWD 方法生成的方程的数学框架。
这是一个 Mathematica 无法解决的方程的例子。如果分母简化,Mathematica 就能成功求解积分:
Example failure case from the original paper.
跨生成器比较
最后,作者评估了在一个生成器上使用另一个生成器的方程训练的模型。
- 接受过 FWD 培训:17.2%(BWD),88.9%(IBP)
- 在 BWD 接受培训:27.5%(前进),59.2%(IBP)
- 在 BWD+IBP 接受培训:56.1%(前进)
仅在一个生成器上训练模型似乎不能很好地推广到其他生成器。这可能是由于来自每个生成器的训练对(F,F)在长度方面具有不同的特性。例如长 F 和短 F,或者短 F 和长 F。
然而,根据来自所有 3 个发生器的方程训练模型工作良好:
- 接受过 FWD+BWD+IBP 培训:94.3%(FWD),99.7%(BWD),99.7%(IBP)
结论
总而言之,作者证明了神经网络方法甚至可以用于要求输出绝对精确的任务。在某些情况下,它们甚至超越了流行的数学框架。
如果你有时间,你应该读一下原文。它写得很好,很容易理解,即使没有太多的数学背景!
视觉搜索和绘图的深度学习
原文:https://towardsdatascience.com/deep-learning-for-visual-searches-and-mapping-89b85061ef9e?source=collection_archive---------11-----------------------
通过使用预训练的神经网络减少遥感应用中对训练数据注释的需要
深度学习是一种出色的方法,可用于卫星或航空照片等遥感数据集中的对象检测和分割/映射应用。然而,就像深度学习的许多其他用途一样,获得足够的带注释的训练数据可能非常耗时。在这篇文章中,我将介绍我们的一些工作,使用预训练的网络,以消除在注释遥感数据中的目标检测的大型训练数据集的繁琐工作。
【2019 年 9 月中旬我参加了北欧遥感会议。从许多演讲中可以清楚地看到,深度学习已经进入了许多遥感专家的工具箱。观众对这个话题的兴趣似乎很大,并且对深度学习技术在各种应用中的影响和适用性进行了一些讨论。
讨论的一个问题是使用为一种数据(通常是自然图像)开发和训练的神经网络,并将其应用于其他类型的(遥感)数据源。例如,挪威计算中心的 ivind Due Trier 介绍了他的工作,在该工作中,为计算机视觉应用而开发的标准物体探测网络被应用于过滤后的高程图,以确定挪威考古遗址的位置。这里,来自观众的反对意见是,使用这种模型没有意义。对此我坚决不同意;尽管神经网络是为自然图像开发的,但在其他数据源上测试它也是有意义的。在这种情况下,演示者可以证明它是有效的!在我看来,甚至尝试在数据源之间进行迁移学习也是有意义的——为什么用在另一种数据集上训练的过滤器来初始化网络比随机初始化更糟糕呢?开发的模型可能太大,容易过度拟合,但是用现有的代码库和预先训练的模型做一个快速实验的好处通常是如此之大,以至于尝试一下很有意义。
在这篇文章的其余部分,我想介绍一些我们在实验室中所做的工作,应用在一个领域(ImageNet 自然图像)中训练的网络,在另一个领域(航空正射影像)中执行基于图像的搜索。希望我能让你相信这种方法是有意义的。我并不是说 ImageNet 网络可以带来最佳的结果,而是说,考虑到原本需要的注释工作量,使用跨域网络确实有意义。
视觉搜索和对训练数据的需求
深度学习或其他机器学习技术可以用于开发用于识别图像中的对象的鲁棒方法。利用飞机的正射影像或高分辨率卫星照片,这将能够对不同类型的物体进行测绘、计数或分割。然而,使用深度学习需要大量的训练数据,除非你已经有了所需对象类型的可用注册表数据(可用于从数据集中剪切训练图像的多边形数据),否则创建这样的训练数据集是一个非常耗时的过程,因此成本也很高。
因此,在与哥本哈根市的合作中,我们向一种工具迈进了一步,这种工具可用于映射所需的对象类型,而不需要提前创建训练数据。该工具基于亚历山德拉研究所先前的地理视觉搜索项目背后的技术。这个在线演示的灵感很大程度上来自笛卡尔实验室开发的类似技术,它可以让你点击丹麦正射影像数据集上的一个地方,查看丹麦 100 个看起来最相似的地方。相似性度量是基于被训练来区分不同对象类型的神经网络来计算的。例如,单击码头或风力涡轮机将导致以下结果:
基本上,该技术的工作原理是将数据集分成一大堆小片段(在这种情况下有 4800 万个片段),并为每个片段运行一个经过训练的 Resnet-34 网络,以区分 ImageNet 数据集中的 1000 个不同对象。我们不使用最终分类(1000 个类别中的一个),而是从网络中为每个切出提取一个所谓的描述符,由 2048 个数字组成。为了节省内存和减少计算负担,我们训练了一个自动编码器神经网络来将 2048 个数字压缩到 512 位。之后,来自正射影像数据集的 4800 万个图像裁剪部分可以在不到 80 毫秒的时间内与新的裁剪部分进行比较!自动编码器是为这个特定数据集训练的,这意味着它以自我监督的方式适应相关特征。
从一开始,该解决方案就有一些弱点,为了使技术更加强大,我们解决了这些弱点:
- 我们通过将提取的描述符基于具有旋转了 0、90、180 和 270 度的剪切的网络的输出来改进旋转不变性。
- 我们根据不同尺度的截断点计算了描述符。这允许你寻找不同大小的物体。
- 我们开发了一种交互式的方法来“提炼”搜索,这样映射就不仅仅是基于一个单一的参考剪裁,而是基于几个剪裁。
根据 2016 年公开发布的 12.5 厘米分辨率的丹麦春季正射影像数据集,我们计算了哥本哈根周围以下地区 3 种不同比例的 8,838,984 个裁剪图的描述符:
交互式映射
交互式地图目前处于原型阶段,最好用一个例子来解释:假设我们想要绘制在一个区域航行的所有船只的地图。我们首先选择包含一艘船的裁剪图:
基于存储的描述符,系统计算所选剪切部分和所有其它剪切部分之间的“距离”(相似性)。然后,进行分类,并向用户显示 100 个最相似的剪切部分:
可以看到,其中一些切口包含船只,但结果远远不够好。用户现在可以选择一些他或她满意的裁剪图:
此后,在所有选定的剪切部分和数据库中所有剪切部分的描述符之间进行比较,并再次基于它们的平均相似性距离进行分类。这就产生了以下 100 强:
可以看到显著的改善。我们可以选择运行另一次迭代搜索,方法是选择更多我们满意的裁剪部分,然后再次运行排序:
船只仍然在前 100 名之列,这是一个好现象。请注意,我们之前标记为满意的裁剪不再出现在交互式优化中。
从排序到映射
该迭代方法基于与在交互改进过程中选择的切出区的平均相似性距离,对所有 880 万个切出区进行排序。理想情况下,包含船只的前 N 个切口和不包含船只的其余切口之间应存在边界。然而,在实践中,更确切的情况是,前 M 个切口包含船,之后在切口 M 和切口 N 之间有一个间隔,其中一些切口而不是所有切口包含船。为了避免误报,在分类中 M 之后的截断点被假定为不包含船。我们已经创建了一个快捷的用户界面,用户可以在其中检查已排序的裁剪部分,并为 M 和 n 建立一些有用的值。
如果排序很好,并且 M 和 N 设置得很合理,那么您现在就有了由包含船只的裁剪部分组成的干净的训练数据(排序等级
Zoomed in, you can see something like this (the different boxes are missing a side in the visualization for some reason):
Mapping is not perfect, but in less than a quarter of an hour the technique can give an overview of the situation. And at the same time you have also created a really good starting point for a training dataset that can be used to train a neural network or another machine learning methodology.
Mapping trees
Repeating the same process with trees instead of boats gives a mapping that looks like this:
Zoomed in, it looks like this:
Again, the mapping is not perfect, but it provides a good starting point for further work.
I hope this post has sparked some inspiration on how objects can be localized using a pre-trained neural network, e.g. for extracting training data from maps. I am very interested in hearing about more potential use cases, so if you have ever had a need for finding certain objects in large images such as maps, please leave a comment!
Also, I am very eager to hear your ideas on how to use self-supervised methods to create an even better embedding/representation of the image patches.
我在亚历山德拉研究所的视觉计算实验室工作;丹麦的一家非营利公司,帮助公司应用最新的 it 研究。我的实验室专注于高级计算机图形学和计算机视觉研究。我们永远欢迎合作!
从程序员的角度看深度学习(又名可区分编程)
原文:https://towardsdatascience.com/deep-learning-from-a-programmers-perspective-aka-differentiable-programming-ec6e8d1b7c60?source=collection_archive---------14-----------------------
或者为什么神经网络不再那么神经化了
2018 年的主要教训:深度学习很“酷”。其中一个主要原因是,DL 面临的基本问题非常普遍会引起大量学科的兴趣,从计算机视觉到神经机器翻译再到语音接口。更重要的是,DL 概念还可以从广泛的观点中衍生和研究,这就是为什么你可以找到机器学习书籍和文章,它们来自统计、信息论、信号处理、数学和许多其他领域。
神经网络本身,DL 中的关键工具,在第二次世界大战后从一种独特的混合中诞生,涉及神经生理学、控制论、行为主义心理学、电学和后来的计算工程,然后以一种或另一种形式通过多次更名幸存下来,最著名的形式是今天的“连接主义”和“深度学习”。
Source: https://twitter.com/benblume/status/932226883764342784.
从业者在过去几年见证了进一步的品牌重塑,这始于高度灵活的编程库的传播,如 PyTorch 、 Chainer 等等。尽管存在差异,所有这些库都有两个基本特征:(I)反向传播对于用户来说是完全自动和透明的(通过使用自动微分);以及(ii)网络和模型逻辑的代码与其他编程结构(如条件分支和循环)无缝集成。
因此,尽管它们在生物学上同名,神经网络今天更适合程序员的思维,及其模块化和封装的知识,而不是例如生物学家及其突触适应和化学神经递质的知识。
这种观点的转变有很多名字,最著名的是“可微分编程”(一年前由 Yann LeCun 推广的一个更老的想法)和“软件 2.0 ”。可微分程序(DP)是使用“可微分”操作符(也称为神经网络)实现的一段代码,其内部逻辑由一个或多个优化例程以数据驱动的方式进行调整。与“标准”神经网络的概念差异在于可使用的可微分算子的多样性(例如,可微分读/写操作、神经算术单元等)。),以及这些操作符与各种各样的标准结构和“软件 1.0”部分混合在一起的事实。
可微分编程只不过是对[现代]深度学习技术的重塑[……],但重要的一点是,人们现在正在通过组装参数化功能块的网络,并通过使用某种形式的基于梯度的优化从示例中训练它们,来构建一种新的软件。(来源: Yann LeCun 论脸书)。
作为推论,所有的软件设计问题,从调试到安全、隐私和模糊化,都可以在新扩展的“可区分软件”堆栈中找到扩展及其位置。
这篇文章的目的
DP 不仅仅是一个品牌重塑,还可以被视为一种思维模式的改变:深度网络不再是像我们的大脑一样以某种方式“学习”的生物学启发的工具—它们是编程结构。按照这种推理,在这篇文章中我想展示当从纯编程开始时,有多少机器学习/深度学习概念可以自然产生,即单元测试、封装、模块化等思想。这不是另一篇“深度学习向程序员解释”的文章——或者至少我希望如此!这更像是一篇“深度学习来自程序员的文章的梗概:迈向差异化编程的自然步骤。
注意:这是一个正在进行的工作。非常感谢任何评论或反馈。
单元测试和“软”断言
DP 就像它们的标准对应物一样,由函数组成。函数是(最好是小的)代码片段,它接受一些输入参数 x ,并返回一些输出值 y :
Source: https://tectrick.org/programming-function-definition/function/.
任何程序都可以表示为一系列基本操作,与基本控制 流程和循环交错。任何有经验的程序员都知道,编写函数比确保函数正确要简单得多。这就是为什么在现代编程实践中,任何函数都应该带有一个或多个单元测试,这些测试评估它在一系列用例上的正确行为:
An abstract example of unit test.
在机器学习术语中,这组用例被称为测试集。单元测试的一个有趣的特性是,它们通常比它们测试的功能更容易设计和实现(这就是为什么整个编程哲学都建立在它们之上)。
例如,考虑一家银行的程序员编写一个函数来确定给定的客户 x 是否应该获得贷款( y=1 )或不获得贷款( y=0 )。这个函数的整个主体将(可能)是一个混乱的东西,充满了他/她的内部知识、嵌套的 if-else 分支、判断性评估等等。然而,测试功能是很简单的:人们可以简单地选择一系列已知的客户端,并在这些客户端上评估功能。
在一个标准的单元测试中,给我们测试集中的一个客户打分很低将会导致整个程序失败。然而,没有什么可以阻止我们编写 软测试断言 来评估而不一定失败。例如,如果测试集中超过 75%的客户端从我们的例程中被正确分类,我们可能认为我们的测试在这个场景中是成功的。
软单元测试允许优化?
如上所述的软测试方法带来了优化我们的程序的想法:一个得分 80%的函数可能比一个得分 77%的函数更好,同时仍然有改进的空间。遗憾的是,我们缺乏一种结构化的方法来决定如何修改函数。
注意:我们可以决定随机改变函数中的每一条指令(例如,将“如果 a > 0”子句改为“如果 a ≤ 0”子句),并测试新的函数集,也称为遗传编程。然而,我们不能保证这些可能的 成千上万 变异函数中的任何一个会比我们原来的函数更好!
DPs 之外的见解是,如果我们适当地限制我们在程序中使用的基本操作的类型,那么就有可能从我们的数据中设计出一个更好的程序来优化它。顾名思义,DP 要求所有初等函数都是可微的,即:
- 根据输入参数连续改变和;
- 允许关于相同的参数。
让我们来看一个有单个输入参数的可微函数的例子, b :
Source: https://mathinsight.org/image/derivative_example_function_3_derivative.
蓝线是连续的:其输入参数的任何值与直接接近的值之间没有不连续。该函数还允许求导(绿线),我们可以检查该求导,以查看当我们增加或减少输入 b 时,该函数是否会增加或减少。可微函数的例子有和、积、平方根…
将我们自己局限于可微函数看起来是一个巨大的挑战,因为任何“清晰”的决定,导致我们的图中明显的不连续,将永远超出我们的算法的掌握。即使是简单的 0/1 二进制决策,或者决定从数据库中读取单个条目,都是无法以这种方式编码的指令。在人工智能领域,这被称为符号对抗子符号挑战:基于连续函数的方法无法以直接的方式操纵离散的符号,如单词或心理类别。
除了 f(x)的可微性,我们还需要确保 测试过程是可微的。如果这两个约束都满足了,我们就获得了一个非常强大的工具,以数字优化的形式来交换我们缺乏的表现力。使用导数的信息,我们可以设计自动迭代算法,能够通过最大化测试度量来自动学习函数的“形状”。您可以将此视为编译器的扩展,除了生成可执行代码之外,它还“校准”函数的内部参数,这些参数决定组成基本函数如何变化。
“信息泄漏”和过度拟合
到目前为止,我们的讨论有一个我们没有提到的“房间里的大象”:对我们想要测试的相同性能度量进行数值优化是一个相当糟糕的想法。为了看到这一点,考虑通过查看单元测试,我们总是可以实现一个简单的模拟其测试用例的查找表,这将总是在测试中达到 100%的准确性。另一种说法是"学习不是记忆":银行只有在能够了解到一些迄今为止还没有看到的未来客户的情况下,才会对其客户的历史信息感兴趣。
在机器学习中,一个过度适应其测试数据的函数被称为过度适应。这个问题的解决方案很简单:我们只需要确保我们用于优化的数据不同于我们用于测试的数据。回到我们的编程例子,任何同时编写函数和单元测试的程序员都容易“信息泄露”并可能作弊,但是如果我们使用两个不同的程序员(又名,黑盒测试),那么我们完全有信心我们的测试例程告诉我们一些有意义的东西。
Black-box unit testing requires the tester to have no knowledge of the underlying program. In DPs, this is achieved trivially by using separate datasets for the optimization phase and the testing phase (source: http://softwaretestingfundamentals.com/black-box-testing/).
训练/测试分离还有另一个优点:虽然训练标准必须是可微分的,但是测试标准没有这样的要求。再次考虑对用户分类的问题:即使是一个非常简单的目标如“f(x1)= = y1”(ML 术语中称之为0/1 损失)也无法区分,更不用说直接优化了。然而,我们可以优化一个合适的代理项(比如交叉熵),并且仍然能够在准确性方面测试我们的应用程序。
差异化程序员的角色
在“软件 1.0”中,程序员为功能选择一系列操作,然后为单元测试选择一系列用例。在一个 DP 中,测试用例更适合收集而不是选择,因为它们代表了我们想要从中提取一些洞察力的历史信息。因为 DPs 在他们的优化阶段也需要数据,并且因为这些数据通常需要比测试用例大至少一个数量级,可区分编程是一个数据饥渴的学科:寻找数据,标记它,确保它正确地描述我们的问题域,消除偏见都是解决“2.0”版本软件问题的先决条件。
接下来,程序员需要选择一个正确的度量来优化(损耗和 f(x)的具体形状)。正如目前在世界各地执行的所有程序都是从相对少量的原语中派生出来的一样,少量的可微运算符允许我们为 f(x)定义指数数量的可能“程序结构”,而直观地做到这一点的能力是具有多年经验的深度学习工程师与初学者的区别。****
许多营销活动倡导深度学习作为一种工具,通过向问题扔越来越多的数据来自动解决任务。显然,这与真相相去甚远。程序员的精神角色正在从定义一个非常精确的符号运算序列转移到指定一个可微分运算的模板,其细节应该从数据中学习。这不是一个简单的任务,因为我们的结构不适合用次符号术语进行推理,而且我们发现很难在头脑中想象一系列次符号操作。结果,构建一个 DP 变成了直觉、经验、技巧和聪明调试的迷人组合。
It looks cool, but only until it doesn’t work and you have no idea what to do with these bunches of numbers (source: https://bdtechtalks.com/2018/02/27/limits-challenges-deep-learning-gary-marcus/).
更一般地说,将“编译器”(优化例程)与程序的其余部分完全隔离也是困难的,因此人们不得不修改优化参数和标志,甚至修改模型本身以使它们更容易优化。
可微分例程
原型可微运算是一个线性组合。例如,两个输入 a 和 b 的线性组合为:
a 和 b 同时决定 c 的值,每一个都具有可以通过算法找到的特定权重。线性组合是所有 DPs 的构建块,因为它们代表了在我们的程序中插入对象之间的参数关系的最简单的可能方式。 c 可以是我们计算的中间步骤,甚至是最终的输出值。
数学上,线性组合不能堆叠:线性组合的一个线性组合和参数不同的单个线性组合是一样的(这个你大概需要读两遍)。如果我们想要线性操作的序列,我们需要用一个或多个非线性*T21 来交错它们。在深度网络的术语中,这些被称为激活功能。线性组合和激活函数是经典神经网络的基础,松散地表示“突触”(上图中的连接线),以及阈值。*
然而,DPs 并不局限于具有生物学相似性的手术。今天的“DP 工具包”非常广泛,我们可以只提到几个有代表性的例子。
可微分支和注意
考虑"形式的一般条件指令,如果满足条件 a,则执行 f(x),否则执行 g(x) 。只要条件 a 不是我们程序的可微部分的一部分,那么我们就没有问题。然而,当我们还想学习(优化)子句时,事情就变得更难了,因为如上所述,我们不能对二元决策进行区分。
分支的可微版本有两个组成部分。第一个是用所谓的s 形函数对条件 a 进行预处理:
The sigmoid function (taken from Wikipedia).
从图中可以看出,不管 a 的值如何,σ(a)(sigmoid 的输出)的值将是 0 到 1 之间的一个数字,可能更接近两个极端值中的一个。不是简单地选择两个分支中的一个,然后,一个“可微 if 取由条件本身加权的两个分支的组合:
A differentiable equivalent of branching.
这样,条件 a 就可以和其余的一起作为另一个 DP 的输出。由于之前表达的形式,这个想法在深度学习文献中也被冠以门控的名称。一个类似的机制,注意,允许实现不同的例程,给或多或少的权重给程序的不同组件。
可区分的阅读和写作
从内存中读写是大多数程序的另一个关键组成部分。然而,如果这些操作需要成为 DP 的一部分,它们需要被“平滑”以使它们可区分(因为在存储器中选择一个单个地址是一个不可区分的操作)。有趣的是,人们可以使用与以前相同的逻辑来设计可区分的读/写操作:我们让程序通过元素的适当线性组合来读/写所有的位置。
Source: https://distill.pub/2016/augmented-rnns/.
可微分算法
经典算术也超出了 DPs 的范围,因为我们没有简单的方法来强制程序的权重为精确的整数。尽管如此,我们可以尝试让我们的架构偏向于进行类似算术的计算。最近的 神经算术逻辑单元 就是这种情况,它利用非线性和注意力机制的巧妙结合,迫使权重接近-1、0 或+1。
Source: https://arxiv.org/pdf/1808.00508.pdf.
可微分循环
现在考虑一个通用的循环机制,其中我们迭代数组 a 的元素,并通过应用函数 f 收集结果:
这种运算在可微世界中不需要任何修改!事实上,如果 f 是一个 DP,我们获得一个已知的对象,称为递归神经网络,一个具有小内存(以中间值 z 的形式)的网络,它可以学习处理元素序列:
Source: http://colah.github.io/posts/2015-08-Understanding-LSTMs/.
递归网络也可以与 gates 结合来提高它们的能力,或者与小的注意机制结合来自动学习何时停止迭代。
其他可微分运算
显然,还有更多可微的操作符!如果您正在处理特殊类型的数据(例如,图像、图表),您可以为它们定义特定的操作,例如卷积或扩散运算符。类似地,如果您需要一个更结构化的输出(例如,序列),您可以结合其他操作符来使您的 DP 偏向这些特殊情况。
最后得出结论
如果一个人真的想将深度学习推向可区分的编程,为程序员提供数学教程是不够的:我们需要用编程术语重新表述/重新思考整个领域。这篇文章是我对这种重新措辞的“心理草图”。
用“从数据中学习”来描述深度学习是很常见的。然而,使程序适应手边的数据对程序员来说并不一定是陌生的概念:一个通过从数据库中读取摘要来微调其内部逻辑的软件可以说是执行了一个非常粗糙的版本。对于一个有经验的程序员来说,很难从概念上想到一个混合了“crisp”和可微的程序,以及一个人如何能够对如何用一组原始可微操作符解决一个问题产生直觉。我相信,这将是全面采用软件 2.0 堆栈的主要“心理障碍”。
从零开始深度学习并在 Python 中使用 Tensorflow
原文:https://towardsdatascience.com/deep-learning-from-scratch-and-using-tensorflow-in-python-34aad75f939?source=collection_archive---------11-----------------------
深度学习是目前在现实世界、数据科学应用中使用的最流行的模型之一。在从图像到文本到语音/音乐的各个领域,这都是一个有效的模式。随着其使用的增加,快速和可扩展地实现深度学习的能力变得至关重要。Tensorflow 等深度学习平台的兴起,帮助开发者以更简单的方式实现他们需要的东西。
在本文中,我们将了解深度学习是如何工作的,并熟悉它的术语——如反向传播和批量大小。我们将为 Python 中预定义的输入和输出实现一个简单的深度学习模型——从理论到零实现——然后使用 Keras 和 Tensorflow 等深度学习平台做同样的事情。我们使用 Keras 和 tensor flow 1 . x 版和 2.0 版编写了这个简单的深度学习模型,具有三个不同的复杂程度和易于编码的程度。
深度学习从无到有的实现
考虑一个简单的多层感知器,它有四个输入神经元,一个隐藏层有三个神经元,一个输出层有一个神经元。我们有三个数据样本用于表示为 X 的输入,三个数据样本用于表示为 yt 的期望输出。因此,每个输入数据样本有四个特征。
# Inputs and outputs of the neural net:
import numpy as npX=np.array([[1.0, 0.0, 1.0, 0.0],[1.0, 0.0, 1.0, 1.0],[0.0, 1.0, 0.0, 1.0]])
yt=np.array([[1.0],[1.0],[0.0]])
Neural Network with four input neurons, one hidden layer with three neurons and an output layer with one neuron
图中的 x (m) 为 X , h (m)为输入X(m)WI*和 W h*
神经网络(NN)的目标是获得权重和偏差,以便对于给定的输入,NN 提供期望的输出。但是,我们事先不知道适当的权重和偏差,所以我们更新权重和偏差,使得 NN、 yp(m) 和期望的输出、 yt(m) 之间的误差最小。这个迭代最小化过程被称为 NN 训练。
假设隐藏层和输出层的激活函数都是 sigmoid 函数。因此,
The size of weights, biases and the relationships between input and outputs of the neural net
其中激活函数是 sigmoid, m 是第 m 个数据样本, yp(m) 是 NN 输出。
误差函数测量神经网络的输出与期望输出之间的差异,可以用数学方法表示为:
The Error defined for the neural net which is squared error
上述 NN 的伪代码总结如下:
pseudocode for the neural net training
从我们的伪代码中,我们认识到应该计算误差(E)相对于参数(权重和偏差)的偏导数。使用微积分中的链式法则,我们可以写出:
Derivative of Error function with respect to the weights
这里我们有两个选项来更新反向路径中的权重和偏差(反向路径意味着更新权重和偏差,使得误差最小化):
- 使用训练数据的所有 N 个样本
- 使用一个样本(或几个样本)
对于第一个,我们说批量大小是 N 。对于第二种情况,如果使用一个样本来更新参数,我们说批量大小为 1。因此,批量意味着有多少数据样本被用于更新权重和偏差。
你可以找到上述神经网络的实现,其中误差相对于参数的梯度被象征性地计算,具有不同的批量大小这里是。
从上面的例子可以看出,从头开始创建一个简单的深度学习模型涉及到非常复杂的方法。在下一节中,我们将看到深度学习框架如何帮助我们的模型实现可扩展性和更大的易用性。
使用 Keras、Tensorflow 1.x 和 2.0 的深度学习实现
在上一节中,我们使用链式法则计算了误差 w.r.t .参数的梯度。我们亲眼看到这不是一个简单或可扩展的方法。此外,请记住,我们在每次迭代中计算偏导数,因此不需要符号梯度,尽管它的值很重要。这就是深度学习框架如 Keras 和 Tensorflow 可以发挥作用的地方。深度学习框架使用自动 Diff 方法进行部分梯度的数值计算。如果你不熟悉 AutoDiff,StackExchange 有一个很好的例子来介绍一下。
自动 Diff 将复杂的表达式分解成一组原始表达式,即最多由单个函数调用组成的表达式。由于每个单独表达式的微分规则都是已知的,所以可以用有效的方式计算出最终结果。
我们在 Keras、Tensorflow 1.x 和 Tensorflow 2.0 中实现了具有三个不同级别的 NN 模型:
1-高级(Keras 和 Tensorflow 2.0): 批量为 1 的高级 tensor flow 2.0
2-中级(Tensorflow 1.x 和 2.0): 中级 Tensorflow 1.x 批量 1 ,中级 Tensorflow 1.x 批量 N ,中级 Tensorflow 2.0 批量 1 ,中级 Tensorflow v 2.0 批量 N
3-低级(Tensorflow 1.x): 批量为 N 的低级 tensor flow 1 . x
代码片段:
对于高层,我们使用 Keras 和 Tensorflow v 2.0 通过 model.train_on_batch 完成了实现:
# High-Level implementation of the neural net in Tensorflow:
model.compile(loss=mse, optimizer=optimizer)
**for** _ **in** range(2000):
**for** step, (x, y) **in** enumerate(zip(X_data, y_data)):
model.train_on_batch(np.array([x]), np.array([y]))
在使用 Tensorflow 1.x 的中级中,我们定义了:
E = tf.reduce_sum(tf.pow(ypred - Y, 2))
optimizer = tf.train.GradientDescentOptimizer(0.1)
grads = optimizer.compute_gradients(E, [W_h, b_h, W_o, b_o])
updates = optimizer.apply_gradients(grads)
这确保了在循环的中,更新变量将被更新。对于中级,梯度和它们的更新在 for_loop 外部定义,而在 for_loop 更新内部迭代更新。在中级使用 Tensorflow v 2.x 中,我们使用了:
# Medium-Level implementation of the neural net in Tensorflow**#** In for_loop**with** tf.GradientTape() **as** tape:
x = tf.convert_to_tensor(np.array([x]), dtype=tf.float64)
y = tf.convert_to_tensor(np.array([y]), dtype=tf.float64)
ypred = model(x)
loss = mse(y, ypred)
gradients = tape.gradient(loss, model.trainable_weights)
optimizer.apply_gradients(zip(gradients, model.trainable_weights))
在低级实现中,每个权重和偏差被单独更新。在使用 Tensorflow v 1.x 的低级中,我们定义了:
# Low-Level implementation of the neural net in Tensorflow:
E = tf.reduce_sum(tf.pow(ypred - Y, 2))
dE_dW_h = tf.gradients(E, [W_h])[0]
dE_db_h = tf.gradients(E, [b_h])[0]
dE_dW_o = tf.gradients(E, [W_o])[0]
dE_db_o = tf.gradients(E, [b_o])[0]
# In for_loop:
evaluated_dE_dW_h = sess.run(dE_dW_h,
feed_dict={W_h: W_h_i, b_h: b_h_i, W_o: W_o_i, b_o: b_o_i, X: X_data.T, Y: y_data.T})
W_h_i = W_h_i - 0.1 * evaluated_dE_dW_h
evaluated_dE_db_h = sess.run(dE_db_h,
feed_dict={W_h: W_h_i, b_h: b_h_i, W_o: W_o_i, b_o: b_o_i, X: X_data.T, Y: y_data.T})
b_h_i = b_h_i - 0.1 * evaluated_dE_db_h
evaluated_dE_dW_o = sess.run(dE_dW_o,
feed_dict={W_h: W_h_i, b_h: b_h_i, W_o: W_o_i, b_o: b_o_i, X: X_data.T, Y: y_data.T})
W_o_i = W_o_i - 0.1 * evaluated_dE_dW_o
evaluated_dE_db_o = sess.run(dE_db_o,
feed_dict={W_h: W_h_i, b_h: b_h_i, W_o: W_o_i, b_o: b_o_i, X: X_data.T, Y: y_data.T})
b_o_i = b_o_i - 0.1 * evaluated_dE_db_o
正如你在上面的低级实现中看到的,开发者对数字操作和计算的每一步都有更多的控制。
结论
我们现在已经表明,通过使用用于权重和偏差更新的符号梯度计算,从零开始实现即使是简单的深度学习模型也不是一种容易或可扩展的方法。由于使用了 AutoDiff,使用深度学习框架加速了这一过程,AutoDiff 基本上是用于更新权重和偏差的稳定的数值梯度计算。
Ubuntu 18.4 上的深度学习 GPU 安装
原文:https://towardsdatascience.com/deep-learning-gpu-installation-on-ubuntu-18-4-9b12230a1d31?source=collection_archive---------5-----------------------
在安装了几次驱动程序、CUDA 等之后,为了让我的深度学习库与我的 GPU 对话,我决定编写适用于 Ubuntu18.04 的安装步骤。
1.NVIDIA 驱动程序安装
第一步:确保你的 GPU 是英伟达 GPU
首先需要做的是,使用以下命令确保 GPU 是 NVIDIA GPU:
$ ubuntu-drivers devices
第二步:移除 NVIDIA 驱动
首先要做的是运行以下命令,以确保清除任何预安装的驱动程序:
$ sudo apt-get autoremove$ sudo apt-get remove nvidia*$ sudo apt-get purge cuda*
步骤 3:禁用新的 NVIDIA 驱动程序
上一步之后这一步有时候就没必要了,但是我还是强烈建议去做(做了不疼!).
首先,您需要打开黑名单-nouveau.conf 文件(我使用 gedit,但也可以随意使用任何其他类型的编辑器)。我使用的命令如下:
$ sudo gedit /etc/modprobe.d/blacklist-nouveau.conf
现在,将下面几行添加到文件中。
blacklist nouveau
blacklist lbm-nouveau
options nouveau modeset=0
alias nouveau off
alias lbm-nouveau off
保存并关闭文件。
禁用内核新功能:
$ echo options nouveau modeset=0 | sudo tee -a /etc/modprobe.d/nouveau-kms.conf
步骤 4:添加 PPA 驱动程序库
要将ppa:graphics-drivers/ppa
存储库添加到您的系统中,请键入以下命令:
$ sudo add-apt-repository ppa:graphics-drivers/ppa
步骤 5:安装 NVIDIA 驱动程序
过去,我常常从英伟达下载网站(https://www.nvidia.co.uk/Download/index.aspx?lang=en-uk)下载驱动程序。
最简单和最可靠的方法是直接从终端安装它(这是我在 NVIDIA 论坛上的一篇帖子中来自 NVIDIA 的直接建议)。安装驱动程序的命令应该是(确保您安装了正确的驱动程序!):
$ sudo apt install nvidia-driver-435
另一个选择是直接从 Ubuntu 的软件和更新设置中安装它:
现在,选择正确的驱动程序(这是一个棘手的问题,如果这一步没有成功,你可能不得不回来测试一个新的驱动程序)。点击应用更改,一切就绪!
第六步:重启电脑
别忘了这一步!
步骤 7:检查驱动程序是否正常工作
通过键入以下命令,您将知道安装已经成功:
$ nvidia-smi
您应该会看到类似于
如果你在这里得到一个 NVIDIA 错误,从头开始尝试所有的步骤,但是这次选择一个新的驱动程序!
2.CUDA 安装
在安装 CUDA 的时候,我一般都是按照 CUDA 安装指南来的,这个指南非常完整(https://docs . NVIDIA . com/CUDA/CUDA-installation-guide-Linux/index . html)。
步骤 1:预安装检查
- 首先检查你的 GPU 是否可以处理 CUDA:
$ lspci | grep -i nvidia
- 检查您是否有受支持的 Linux 版本:
$ uname -m && cat /etc/*release
这应该会返回类似于
x86_64
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION=”Ubuntu 18.04.3 LTS”
NAME=”Ubuntu”
VERSION=”18.04.3 LTS (Bionic Beaver)”
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME=”Ubuntu 18.04.3 LTS”
VERSION_ID=”18.04"
HOME_URL=”[https://www.ubuntu.com/](https://www.ubuntu.com/)"
SUPPORT_URL=”[https://help.ubuntu.com/](https://help.ubuntu.com/)"
BUG_REPORT_URL=”[https://bugs.launchpad.net/ubuntu/](https://bugs.launchpad.net/ubuntu/)"
PRIVACY_POLICY_URL=”[https://www.ubuntu.com/legal/terms-and-policies/privacy-policy](https://www.ubuntu.com/legal/terms-and-policies/privacy-policy)"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
- 检查 gcc 是否已安装
$ gcc --version
- 检查您的内核头文件是否与 CUDA 兼容(您可以在 CUDA 安装指南中找到兼容性表):
$ uname -r
- 使用以下命令安装内核头文件和包:
$ sudo apt-get install linux-headers-$(uname -r)
步骤 2:下载 CUDA
您可以通过以下链接下载 CUDA 工具包:
[## CUDA 工具包 10.1 更新 2 下载
编辑描述
developer.nvidia.com](https://developer.nvidia.com/cuda-downloads)
对于 Ubuntu 18.04,您需要下载以下内容
现在,你只需要等待,这个下载可能需要一段时间!
步骤 3:安装 CUDA
安装 CUDA 的步骤非常简单。只需在您的终端上键入以下命令:
$ wget [http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda_10.1.243_418.87.00_linux.run](http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda_10.1.243_418.87.00_linux.run)
$ sudo sh cuda_10.1.243_418.87.00_linux.run
您应该会看到以下屏幕:
确保此次安装不会安装新的驱动程序!!!!!
Unselect Driver when installing CUDA
如果安装成功,您应该会看到以下屏幕:
3.安装 cuDNN
这是您可以开始使用 GPU 进行深度学习之前的最后几个步骤!
第一步:下载 cuDNN
以下链接将带您进入 cuDNN 下载网站:
https://developer.nvidia.com/rdp/form/cudnn-download-survey
你必须先登录才能下载任何东西。进入后,下载:
- cuDNN 图书馆
- cuDNN 运行时库(Deb)
- cuDNN 开发者库(Deb)
- cuDNN 代码示例(Deb)
步骤 2:安装 cuDNN
这些步骤主要遵循 cuDNN 安装网站https://docs . NVIDIA . com/deep learning/SDK/cud nn-install/index . html中的说明
- cd 到你的下载文件夹(或者下载文件所在的地方)
- 使用以下命令解包归档文件:
$ tar -zxvf cudnn-10.1-linux-x64-v7.6.5.32.tgz
- 将文件复制到 CUDA 工具包目录中,并更改权限
$ sudo cp cuda/include/cudnn.h /usr/local/cuda/include
$ sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64
$ sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn*
- 使用以下命令安装这三个库
$ sudo dpkg -i libcudnn7_7.6.5.32–1+cuda10.1_amd64.deb
$ sudo dpkg -i libcudnn7-dev_7.6.5.32-1+cuda10.1_amd64.deb
$ sudo dpkg -i libcudnn7-doc_7.6.5.32-1+cuda10.1_amd64.deb
4.检查一切是否正常!
为了做到这一点,cuDNN 创建了一个样本代码,它将使用您的 GPU 在 MNIST 数据集上运行一些计算。为此,您需要遵循以下步骤:
$ cp -r /usr/src/cudnn_samples_v7/ $HOME
$ cd $HOME/cudnn_samples_v7/mnistCUDNN
$ make clean && make
$ ./mnistCUDNN
如果一切正常,您应该会看到如下内容:
现在你可以很好地使用你的 GPU 了!
深度学习&手写阿拉伯数字
原文:https://towardsdatascience.com/deep-learning-handwritten-arabic-digits-5c7abc3c0580?source=collection_archive---------20-----------------------
使用 fast.ai 库以 99%的准确率对 AHCD 进行分类!
photo: Morocco, 2000
深度学习的“hello world”通常是 MNIST 手写数字数据集,我想将同样的技术应用到一个更有趣的应用程序中:阿拉伯语手写字符数据集(AHCD),由美国大学开发的数据集。
在这个例子中,我使用 fast.ai 库来训练一个卷积神经网络(CNN ),以 99+%的准确率对 AHCD 进行正确分类。方法如下:
首先,导入我们需要的库,并设置我们的 GPU 使用 cuda:
%reload_ext autoreload
%autoreload 2
%matplotlib inline**from** **fastai.vision** **import** *
**from** **fastai.metrics** **import** error_rate
**import** **csv**
**import** **numpy** **as** **np**
**import** **PIL**
**import** **pandas** **as** **pd**defaults.device = torch.device('cuda')
与许多数据科学工作流一样,数据预处理是最重要的组成部分。以下是为我们的卷积神经网络准备数据的步骤:
1 —从 csv 摄取
与 MNIST 拉丁字母版本一样,AHCD 也是一个 784 列的 csv,其中每行包含一个 28x28 的图像,该图像被展平为一行数值。
第一个任务是将它加载到内存中,由于数据集有 60k 行,为了加速这个过程,我设置了一个任意的 4k 训练集限制。我们将 Pandas 作为 pd 导入,所以这使用了内置的 Pandas read_csv 函数:
trainrows = 4000
train = pd.read_csv('csvtrain.csv', nrows=trainrows)
2-转换为 3D 数据结构以进行图像处理
我们在内存中有数据,但是每个要生成的图像仍然是平面的(1 高 784 宽),我们希望它是正方形和多维的,这样我们可以使用 matplotlib 将其转换为 RGB 图像。为什么是 RGB?我们将使用基于 RGB 图像开发的预训练 restnet34 模型。
这个简单的函数获取我们的 Pandas train
数据帧并提取一行(作为变量传递),将该行重新整形为一个正方形结构,将数字规范化为范围[0,1],添加两个全零的额外维度,并使用 matplotlib.plot 库将图像作为 png 保存在我们的path/digits/
文件夹中。
注意:最后,我将添加逻辑来将文件夹作为变量传递。目前,它是硬编码的。
**def** pdMakePlot(row):
pixels = np.array(train.iloc[[row]], dtype='uint8')
pixels = pixels.reshape((28, 28)).T
pixels = np.true_divide(pixels, 255)
dim2 = np.zeros((28,28))
dim3 = np.zeros((28,28))
pix = np.stack((pixels, dim2,dim3), axis=2)
row += 1
filename = "digits/**%s**.png" % row
plt.imsave(filename, pix)
plt.close('all')
**return**
3-准备我们的事实来源数据框架
我们正在使用 fast.ai ImageDataBunch.from_df
方法为这个卷积神经网络摄取图像数据,因此我们需要一个 Pandas 数据帧,其中包含我们的训练文件名&和有效标签。
#import training labels into numpy arraycsv = np.genfromtxt ('csvtrainlabel.csv', delimiter=",")
csv = csv[0:trainrows]
csv = csv.astype('int32')
csv = np.add(csv,1)
csv[csv == 10] = 0*#np array that we'll make into the filenames*
*#from 1 to trainrows*
trainrange = trainrows +1
files = np.arange(1,trainrange)
files = files.astype(str)*#convert to filenames*
i = 0;
j = 1;
**for** file **in** files:
files[i] = "**%s**.png" % j
i += 1
j += 1
**if** i >= trainrange: **break***#combine two arrays into dataframe and add header*
df = pd.DataFrame({'name':files, 'label':csv})
df.head()
our dataframe
同样,我将再次讨论 ETL 过程的一部分。
4 —处理并保存我们的培训图像
有了这些,我们可以使用我们之前定义的pdMakePlot()
函数来处理训练图像。处理的图像数量也由我们之前设置的trainrange
变量设置。
i = 0
max = trainrange-1
for x in range(i,max):
pdMakePlot(i)
i += 1
现在我们已经准备好进行深度学习了!只有几行代码:
#define our transforms
tfms = get_transforms(do_flip=False)#define our DataBunch
data = ImageDataBunch.from_df(path=path, df = df, ds_tfms=tfms, size=24)#define our learner
learn = create_cnn(data, models.resnet34, metrics=accuracy)
在我们训练之前,我们可以从我们的数据集中查看一小部分选择,以确认我们已经正确处理了所有内容:
data.show_batch(rows=3, figsize=(7,6))
9 handwritten characters & labels
一切都好!我们还可以运行learn.model
来详细了解学习者架构。如果你感兴趣,它是可用的。不管怎样,我们训练吧!
初步训练
learn.fit_one_cycle(4)
transfer learning from resnet34, 95% accuracy in 16 seconds
我认为我们可以做得更好。让我们找到最佳的学习率,重新训练。
learn.lr_find()LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.learn.recorder.plot()
learning rate against loss
我们看到最优学习率确实很高。让我们试着获得一个比最小化损失的学习率低一点的学习率,比如 0.05?然后我们会解冻 CNN 的一些层,重新训练。
learn.unfreeze()
learn.fit_one_cycle(3, max_lr=slice(.006, .004))
much better
15 秒钟后,我们有了一个模型,它对我们留在一边进行验证的训练数据子集有 99.6%的准确性。
使用模型
既然有了模型,那就用起来吧!使用上面的函数从测试 csv 中读取一些测试数据后:
img = open_image('/path/3.png')pred_class,pred_idx,outputs = learn.predict(img)
pred_class**Category 4 <--- that is correct**
然后
现在我们有了一个工作模型,而且是一个准确的模型,我想更新管道代码,使它更加优雅。我还想对全套测试数据运行模型,看看它如何与最先进的技术相比较。更多来了!
也
附加代码在我的 github 上:www.github.com/matthewarthur。我的 LinkedIn 是 https://www.linkedin.com/in/matt-a-8208aaa/的。打个招呼。
笔记
https://www.kaggle.com/mloey1/ahcd1&http://datacenter.aucegypt.edu/shazeem/
[2]https://docs . fast . ai/vision . data . html # imagedata bunch . from _ df
深度学习有了一个新朋友——表格数据集
原文:https://towardsdatascience.com/deep-learning-has-a-new-friend-tabular-datasets-f34169b9ea79?source=collection_archive---------24-----------------------
超越图像数据集的深度学习
当你想到深度学习时,我们首先想到的不是表格数据集。我们首先想到的是图像数据集。这是因为深度学习和图像数据集有一种特殊的关系。深度学习变得流行主要是因为它能够在图像上创造奇迹。几年前,当深度学习能够区分狗的图像和猫的图像,或者马和斑马时,我们都很兴奋。当深度学习进入图像中的对象检测领域时,兴奋感才增加。图像中不同物体周围各种颜色的边框看起来很酷
图像和深度学习的这种特殊关系也推动了几乎所有围绕深度学习教程的文献。对于许多技术,如理解黑盒模型,使用的例子是图像数据集。MNIST 数字图像数据集已经成为深度学习教程的“Hello World”。图像数据集已经成为理解深度学习的一个很好的来源。
但是好的旧表格数据呢?大多数企业数据以及我们的个人数据都是表格数据的形式。将深度学习用于表格数据将有巨大的价值。然而,将深度学习应用于表格数据的文献很少
通过这个故事,我试图展示深度学习如何对表格数据集非常有用。
为了说明这一点,让我们举一个非常简单的泰坦尼克号生存数据的例子。许多数据科学家已经从 Kaggle 那里知道了这个非常著名的数据集。对于那些不知道这个数据集的人来说,它是致命的泰坦尼克号事故中乘客的数据。为了便于说明,下面是该数据集的样本摘录
Sample extract of Titanic passenger data
现在让我们将深度学习应用于这个表格数据集。深度学习是基于受我们大脑工作方式启发的神经网络。你有“输入”神经元,它接收信号并将它们发送给“输出”神经元
在我们的例子中,输入是像家庭(父母+兄弟)、费用、年龄、乘客级别(Pclass)、登机港口、性别这样的字段。输出是乘客是否幸存。
我们的深度学习架构,如图所示,有输入神经元,后面是 10 个中间神经元和 2 个输出神经元。输入神经元向中间神经元发送信号,中间神经元再向输出神经元发送信号。这个神经元网络,也称为神经网络,为了可视化的目的显示如下。“蓝色”线表示“正”信号,“红色”线表示“负”信号
Feed Forward Neural Network on Titanic dataset
看起来很乱,不是吗?然而,让我们探索不同的部分,看看我们能解释什么
查找表格数据集中列的重要性
表格数据集主要是行和列的集合。我们总是有兴趣知道这些列的重要性。在泰坦尼克号数据集的情况下,检查列的重要性的一种方法是看它是否对人是否幸存有影响。
表格数据上的神经网络可以告知哪些输入列会影响输出列。下图所示为仅用于神经元“Sex_Male”发出的高强度信号的神经网络。信号被传递到“死亡”的神经元。这意味着大多数男性乘客没有生还
因此,深度学习可以帮助我们进行这样的分析,而不必浏览每一篇专栏文章
自动查找重要的列组合
与图像相比,表格数据集更加丰富和复杂。假设有许多列,找出哪些是重要的列组合总是有用的。通常,我们习惯于手动查找任何表格数据集中的重要列。为了找到重要的列组合,我们倾向于制作数据透视表、排序、应用公式。
如果我告诉你深度学习会自动为你做到这一点呢?这听起来很神奇,但却是真的。也正因为如此,它被称为“深度”学习。神经网络的中间层将试图找到对输出有影响的所有输入组合。
titanic 数据集中的一个这样的例子如下所示。“红色”表示“负面”信号。我们看到神经元“Age”和神经元“Pclass”(乘客类)的组合向神经元“Died”传递了一个负信号。这意味着 少了 这个年龄(负信号)而 少了 这个乘客阶层(负信号),这个乘客没有死亡(幸存)
泰坦尼克号上的乘客分为一等舱、二等舱和三等舱。所以从数字的角度来看,更小的等级值意味着第一等级。
为了证实这一点,我们可以制作一个乘客等级和年龄的散点图,如下所示。点的颜色显示乘客是否幸存。该散点图分析表明头等舱或二等舱中年龄较小乘客(儿童)幸存。
现在,如果没有深度学习,您将不得不手动绘制所有列组合的散点图。但是深度学习能够自动从数据中学习数据中的重要组合
对表格数据进行简短总结
假设你被要求对表格数据做一个简短的总结。你怎么能只看一堆行和列?深度学习可以帮助你。由于深度学习受到“大脑”架构的启发,它试图“理解”表格数据的底层结构。
这样做的方法是观察每个神经元“学习”或“理解”数据的内容。出于说明的目的,下面显示的是影响“存活”神经元的所有神经元。正如我们从可视化中看到的,神经元 7 和神经元 8 对“存活”的神经元有影响。
我们可以看到,神经元 7 具有朝向神经元“存活”的“正”(蓝色)信号,而神经元 8 具有朝向神经元“存活”(意味着死亡)的“负”(红色)信号。
现在我们可以分析神经元 7 和 8 的“内部”是什么。这将向我们展示这些神经元从数据中学到了什么。我们可以“窥视”神经元内部来看到这一点。每个神经元可以用从输入神经元接收的强度来表示。我们可以用雷达图来显示神经元的“内部”
Peeking inside the neurons to see what it has learned
所以在 neuron7 内部,我们看到它在女性、车费、年龄上的价值高,在 Pclass 上的价值低。而 neuron7 则向存活下来的神经元发出正(蓝色)信号。
同样,neuron8 在 Pclass 上的价值较高,在 Fare 上的价值较低,女性。这个神经元正在向存活下来的神经元发送一个负(红色)信号
所以我们可以做以下两行总结
女性乘客,支付高价,乘坐头等舱的乘客生还的可能性很高。
男性乘客,支付较低的票价,在二等或三等舱,生还的可能性较小
这太神奇了。这就像你身边有一个专家分析师,他会查看行和列,并试图理解数据的含义。感觉你是钢铁侠,深度学习是贾维斯,他在协助你进行所有的分析
这就是我们如何使用深度学习来分析表格数据的简要概述。还有很多其他有趣的方式。所以朋友们,让我们打破深度学习和图像数据集之间的这种紧密联系。
现在深度学习有了一个新朋友——表格数据集。
额外资源
网站(全球资讯网的主机站)
你可以访问我的网站进行零编码分析。【https://experiencedatascience.com
请订阅每当我发布一个新的故事时,请随时关注。
[## 每当 Pranay Dave 发表文章时,您都会收到电子邮件。
每当 Pranay Dave 发表文章时,您都会收到电子邮件。通过注册,您将创建一个中型帐户,如果您还没有…
pranay-dave9.medium.com](https://pranay-dave9.medium.com/subscribe)
你也可以通过我的推荐链接加入 Medium。
[## 通过我的推荐链接加入 Medium—Pranay Dave
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
pranay-dave9.medium.com](https://pranay-dave9.medium.com/membership)
Youtube 频道
这里是我的 Youtube 频道
https://www.youtube.com/c/DataScienceDemonstrated的链接
科学中的深度学习
原文:https://towardsdatascience.com/deep-learning-in-science-fd614bb3f3ce?source=collection_archive---------16-----------------------
对机会和趋势的调查
哥林多前书 10:23
“The AI revolution in science”, Science Mag, 2017
概述
在这篇文章中,我将调查将深度学习(DL)应用于科学和工程应用的机会。我将从对经验模型出现的展望开始,然后简要介绍神经网络的一些显著特征。主要的焦点将涵盖在各种科学领域中应用 DL 的新出现的一般趋势和问题类型。
实证模型的兴起
人类一直在建造东西。但直到最近,我们才开始设计极其复杂的东西:摩天大楼、商用飞机等。为了实现从岩石到工字钢的飞跃,我们建造了模型:简化的,简洁的,世界的代表。通过这种方式,我们可以构建复杂的东西,相信它们会按照我们想要的方式工作,因为我们已经预先对它们进行了建模。这些分析模型取得了巨大的成功:一些方程可以代表我们感兴趣的大多数现象,并允许我们操纵它们为我们所用。
然而,这些解析方程虽然简洁,却极难求解。在许多情况下,即使对于简单的现象,推导这些方程也需要人类多年的集中努力。例如,虽然几个世纪以来人们已经知道了钟摆运动和单透镜设计的近似解决方案,但是仅仅在过去的十年中,对于如此简单的问题( 1 , 2 )才获得了闭合形式的解决方案。相反,我们经常使用迭代的数值模型,这些模型通常基于迭代求解的偏微分方程,并慢慢地向某个答案收敛(尽管通常没有理论保证答案是正确的)。
Numerical Models
在过去的几十年里,另一种模型开始流行起来:经验模型。纯粹由数据驱动,它们的上升可归因于 3 个主要因素:分析/数值模型未能捕捉某些领域的现象,如生物学、心理学、经济学和医学;大量数据的快速增长;统计学和计算机科学的进步提高了这些模型的性能。
经验模型不同于它们的分析/数值模型,因为它们明确地对世界不做任何假设。相反,他们试图在数据中找到模式,简单地对呈现给他们的数据进行“曲线拟合”。这些差异带来了微妙的危险,因为不充分或有偏见的数据集将创建看似有效但无法准确捕捉现实的经验模型。事实上,经验模型永远不能真正代表现实,只是一种近似。我们用结果来证明经验模型的合理性,但我们永远不能仅仅因为它似乎有效就相信它。验证模型并在适当的上下文中使用它需要更深入的领域专业知识。
因此,这些实证模型的兴起是由软件和在线科技公司推动的就不足为奇了,因为整个行业都建立在收集数据的基础上。随着这些公司在范围和规模上的增长,他们引导新兴的人工智能领域专注于对他们来说重要的问题:推荐系统、图像分类、文本处理。然而,最近这种经验模型,特别是深度学习模型,在各个科学领域中的流行和使用已经爆炸。在接下来的章节中,我们将考察科学领域中数字逻辑的认识论模式。
为什么要深度学习?
深度学习是由许多层组成的神经网络的术语,显然是一种经验模型。但是为什么要深度学习呢?为什么不是另一个经验模型家族,比如在 90 年代被大量研究和描述的支持向量机?有几个原因可以解释为什么深度学习,从经验模型的大家庭中,已经上升到顶端并统治了这个领域。
之前,我讨论了经验模型出现的驱动因素之一是数据的快速增长。但是隐含的假设是更多的数据意味着更好的性能。事实证明,这并不总是正确的。
模型性能和数据之间的关系取决于模型容量(模型可以逼近的函数族)和模型偏差(模型对基础数据做出的先验假设)。例如,线性回归具有非常高的模型偏差,因为它假设基础数据是近似线性的,这限制了它的模型容量。相反,神经网络可以逼近任何实函数(通过通用逼近定理)。根据经验,我们发现神经网络在大型数据集上的伸缩性非常好(尽管神经网络仍然稀疏的理论依据,见这里和这里)。需要注意的是,深度学习的优势只在非常大的数据集上。在“小数据”领域中,不清楚哪种模型类型更好,为了让模型表现良好,您很可能必须使用某种形式的领域专业知识和特性工程。
Model Performance with respect to Dataset Size
神经网络的另一个重要特征是它们能够接受原始的、非结构化的数据作为输入。这种数据类型包括图像、音频、视频等。人们可以很容易地想象,今天网上的大多数数据都是这种非结构化的形式,只有通过大量的人工努力,这些数据才能转换成机器可读的形式。在这些领域,人类专家确定相关特征,将数据塑造成设计矩阵,并提供经验模型。但是神经网络可以接受原始数据,并在没有任何人类指导的情况下,自己学习它们的相关特征!我们将在后面看到,这种接受非结构化数据的能力也允许多种多样的神经架构,从而开启了广泛的潜在应用。
科学中的深度学习
三大支柱
建模有 3 个主要支柱:数据、计算和算法。计算通常不是科学应用的限制因素——事实上,深度学习经常被使用,因为与需要求解偏耦合微分方程的数值方法相比,它的计算效率非常高。按需云计算的兴起(以及专用硬件的增长趋势)意味着计算也非常便宜。这也有助于科学数据集通常比在线应用程序使用的大规模数据集(数百万到数十亿个示例)小得多(数百到数千个示例),这意味着需要的计算资源少得多。最后,学习理论和推理模型的改进,如深度学习本身,导致了标准化架构的创建,这些架构工作良好,可以开箱即用,例如 Keras 中的简单 CNN。
这些支柱隐含着重心:利用所有三个支柱的专业知识。遗憾的是,DL 在很多非计算机科学的研究群体中扎根还需要相当长的时间。一个强大的驱动因素是存在严重的市场失衡:科技公司(几乎每个行业)都渴望获得自己的内部 DL 专业知识,可以支付比传统学术路线高得多的费用。
然而,这种情况正在慢慢改变,因为许多职业科学家开始在职业生涯中期改变关注点,而且随着对 DL 的兴趣日益增长,理解 DL 的学生数量慢慢增加,尽管从大学挖走专门研究人工智能的教授的竞争激烈。深度学习开源框架(如 Tensorflow 和 Pytorch)的爆炸式增长,通过 Coursera、EdX 等大规模开放在线课程(MOOC)甚至 Medium 等资源(如 TDS 团队)的在线学习增长,都有助于人工智能领域真正的开源在线教育。大型科技公司意识到需要帮助外部培养人才,如谷歌开发人员的 ML 速成班和微软的人工智能学校,也起到了帮助作用。所有这些因素都导致了数字图书馆慢慢进入科学应用。
“数据是可防御的屏障,而不是算法”——吴恩达
描述不同领域的数字图书馆采用率
限制因素,尤其是在科学应用中,是数据。这就是为什么对经验模型最有经验的领域(如生物信息学、基因组学、高能物理学)也是拥有最多开源大规模数据集的领域。相反,最容易被深度学习颠覆的领域是那些目前缺乏清晰的标准化开源基准数据集,并且难以获得大量高质量数据的领域(例如,工业设计的机械属性,纳米材料属性,保险和医疗保健)。传统开源基准数据集,如 ImageNet、Cifar-10、Youtube 10M 等。有助于推动深度学习架构的基本创新——对于特定领域的数据集,可以预期类似的效果。
数据的结构也很重要。例如,对乳房 x 光照片中的恶性和良性肿瘤进行分类很容易转化为图像分类或分割问题。反过来,如何预测化学分子和物种的属性更困难——我们如何以一种模型可以理解的方式来表示这些分子?一个化学计量公式就够了吗?是否应该包括晶体群,合成条件,量子力学描述等。?确定如何将分子“指纹化”以传入机器学习模型是一个更加困难的问题,这比简单地传入矩阵需要更多的领域专业知识。深度学习在每个领域的采用率将受到数据可以被表示为传统数据结构的难易程度的影响,但反过来,这也代表了开发新模型的机会,这些模型可以在复杂的领域特定数据中进行本机读取。影响采用的其他因素包括从数值模型中获取数据的难度以及此类数值模型的可信度,缺乏领域专业知识的机器学习专家的准入门槛有多高,等等。
早期采用深度学习的领域的另一个标志是,他们优先考虑推理而不是解释,认为一些不确定性是可以接受的,并接受偶尔出错。如果我们的目标是优化材料设计或加速物理模拟,我们可能不会关心我们是如何实现的,甚至不会关心答案是否有一点错误,只要它足够接近并且比我们之前拥有的更好。但如果我们控制和设计国家电网,或提供医疗诊断,那么我们可能会更加谨慎。机器学习特别适合回答某些类型的问题,而不太适合回答其他类型的问题:理解不同科学领域的问题规范和设计约束将缓和经验模型所发挥的作用,并可能为新的模型公式开辟机会。
最后,“后采用者”领域的一个特殊特征是它们有孤立的数据。私人患者数据和电网数据就是很好的例子。在这些领域中,第一步是鼓励就如何开发现实且可公开的基准数据集进行对话,以便该领域开展工作并跟踪进展。大规模、开源、基准数据集非常重要,因为它们推动该领域在公共数据集上以开放的方式开发新的方法,加速创新和知识共享。建立数据匿名、数据共享和数据报告的约定也很重要。联合学习的新发展是开发算法保证以确保安全、隐私优先的数据共享的重要的第一步。在数据高度孤岛化的领域,人们还应该预料到,拥有数据访问特权的群体将比没有数据访问特权的群体拥有更大的优势。
如您所见,在检查不同科学领域的数字图书馆采用率时,要考虑的最重要的特征之一是数据。特别是,数量、多样性和我所说的“可采纳性”,即数据对 DL 架构的服从程度,是至关重要的因素。随着各种学科的科学数据爆炸式增长,许多领域目前正在经历所谓的 ImageNet 时刻。
深度学习和科学哲学
深度学习已经展示了惊人的自主学习功能的能力,并且在某些情况下,摧毁了某些领域几十年的专家工作。这可能自然会导致一些担忧,即深度学习可能会使科学家的工作自动化。至少在不久的将来,这是不可能的,原因有几个。首先,深度学习不是解释性的,科学(可以说)是一门机械学科。深度学习可以作为发展理论的辅助手段,但它本身还不能发展任何想法。其次,深度学习的许多进步都是为了增强或改善收集或可视化数据的能力,但解释这一科学方法中最重要的部分仍然是人类的领域。最后,深度学习迄今为止一直是网络技术人员的领域;谷歌、脸书等公司面临的问题推动了数字图书馆的发展。科学问题与科技公司面临的问题有不同的成功标准、数据类型和问题。将需要新颖的架构和方法来满足这些需求,并且它们将需要由那些真正理解潜在问题的人来精心制作。事实上,制作考虑物理约束的神经网络模型,例如通过损失函数定制,是一个不断发展的研究领域。
或许最适用的建议是:跟随数据。如果你有将深度学习应用于特定领域的专业知识,那么就寻找能够让你获得大量数据的合作者。相反,如果你坐在计算资源或大型未使用的数据集上,寻找在深度学习方面有良好记录的人,甚至更好,鼓励这些领域的内部培训。您也可以创建自己的数据!挖掘旧实验室笔记本、研究论文,甚至花几周时间生成自己的数据,都是利用实验室资产的独特方式。最优秀的研究团队将在深度学习这一特定科学领域积累内部专业知识,并获得稳定的新数据。
Data Science requires domain expertise
理科 DL 通用问题模板
基于我将 DL 应用于各种科学应用的经验,我注意到许多问题描述都属于类似的模板。我概述了这些案例研究中常见的几个通用问题模板。每个模板中包括几个遵循该模板的已出版作品。如果你有一个符合这些模板之一的科学问题,那么它不仅最有可能被深度学习破坏,而且已经存在一套众所周知和充分理解的技术可以采用。
拟合和优化:我们要么得到 1)现有的非常慢的数值模型,例如有限元法、流体动力学、粒子物理碰撞模拟器等。或者 2)不能用传统方法(例如基因组学)表征的非常大的数据集。我们的任务是一个连续的两步过程。首先,我们希望能够创建一个能够很好地表示数值模型或底层数据集的模型。这是一个标准的监督学习问题,我们应用深度学习来加快现有的数值方法,或者理解极其复杂的数据,并根据给定的数据进行推理。通常,我们的问题的自然下一步是优化一些成本函数,这可以通过数值求解器(如梯度下降或进化算法)或生成模型来完成。生成模型很好,因为只需要构建一个模型,而不是同时构建一个推理模型和一个优化器。这也可以被视为一个逆向设计问题,其中一次性学习是可取的。
这是我在工作中观察到的最常见的问题模板。任何时候你想为一些期望的属性找到最佳的设计,这个模板是合适的。虽然最终目标是一次性的逆向设计,但拟合和优化是目前研究得最多的范式,因为代理 DL 模型可以很容易地取代计算昂贵的数值模型。谷歌的 DeepMind 团队使用神经网络进行推理和梯度下降进行优化的组合来预测蛋白质折叠构型,并使用 AlphaFold 模型击败了其他团队的表现。刘等人。艾尔。使用神经网络进行纳米光子学的逆向设计,使用两步训练程序找到具有给定透射光谱的纳米结构。在这项工作中,逆向设计是在没有拟合和优化框架的情况下完成的,但使用了聪明的神经网络架构和训练程序,展示了 DL 专业知识和技术如何改进传统的代理模型思想。
作为拟合和优化的子集,也有一些情况下,我们只想加速数值模型,例如密度泛函计算 ns、多尺度物理模型、混沌系统等。,以加速不同理论的模拟或加速理论预测来验证实验数据。
去噪:我们给出了一个要测量的系统,但是物理测量结果由所需信号和噪声组成,很多时候,从我们的测量结果中消除噪声是一个难题。也有可能我们正在校准我们的测量设备,或者理解测量对人类来说太难了(例如超光谱数据)。在任何情况下,都需要有一个既定的、真实的、金标准的案例来与传统的测量方法进行比较。对于这个问题,有三个主要部分需要考虑:什么是噪声数据,什么是去噪数据,以及如何获得去噪数据作为标签;如何提出问题,即有监督的、无监督的、半监督的;以及如何衡量去噪性能。一个类似的场景是,当我们得到两个不同的数值模型/模拟时,其中一个是快速且不准确的,而另一个是缓慢且准确的,我们希望拥有后者的准确性和前者的速度。
例如,Schawinski 等人。艾尔。在瑞士联邦理工学院,苏黎世使用甘斯去噪星系图像。为了训练 GAN,他们使用了人工退化的图像,并表明 GAN 能够比传统技术更好地恢复原始图像。他们混合使用了几种传统和新技术来测量去噪性能。在相反的长度尺度上,瑞文森等人。艾尔。使用全卷积神经网络(CNN)自动编码器型架构来恢复仅强度细胞测量的相位。为了获得一个“黄金标准”的真相标签,他们使用了 8 个不同样本到传感器高度的测量值来恢复相位,并用作 CNN 的标签。更一般地说,CNN 用于恢复以前需要多次测量才能获得的信号的一部分。
Actor-Models: 我们有一个与其环境交互的代理,我们希望这个代理学习一些策略来最大化一些成本函数,例如控制商业 HVAC 系统,调节电网能源供应,用显微镜跟踪移动的生物样本等。在许多情况下,这样的问题实际上可以被转化为先前的问题模板之一,例如,预测不久的将来的值和基于领域专业知识应用已知的分析策略、对样本去噪而不是学习更好的策略等。由于这种强化学习(RL)类型的问题比监督学习困难得多,所以结合基于我们对系统的理解开发的简单启发式策略使用推理模型通常是有意义的,因为这种系统中的不确定性较少。问题结构严重影响问题的难度以及所用模型的类型——对于这种参与者-模型类型的问题,通常更简单的方法是将这些问题转化为更简单的问题模板,例如回归/分类。
作为将政策问题转化为回归问题的一个例子,艾尔。使用深度学习在活细胞显微术中自动聚焦显微镜。然而,他们没有使用非常复杂的 RL 方法,而是简单地使用 CNN 来预测给定输入图像的正确显微镜参数。这样的 CNN 可以用于每几秒钟更新一次显微镜焦点,而不需要 RL。令人印象深刻的是,这样一个模型比一组人类实验者显示出更少的差异。
魏等人也将 RL 应用于暖通空调系统。艾尔。最大限度降低建筑用电成本。建筑物 HVAC 被建模为马尔可夫决策过程(MDP)和用于 Q 值估计的神经网络。与基于规则的模型相比,RL 算法表现出显著的成本节约。事实上, RL 目前是一种快速发展的电网建模方法,它通常结合使用 MDP、Q-learning 和传统的电力系统经济/物理模型,以最大限度地减少能源使用和经济成本。
“传统 DL 问题”与科学问题的重要区别
上述模板提供了科学问题和传统深度学习问题类型之间的有用映射,并有助于识别文献中关于哪些问题容易转化为经验建模方法的当前趋势。然而,强调深度学习问题的传统开发(通常由互联网公司推动)和科学领域的开发之间的差异也很重要。
也许最明显的区别是科学领域处理的数据集要小得多。获取数据通常受到计算或进行高通量实验的能力的限制。数据一般不会简单地漂浮在虚无缥缈的互联网上,随时可以被抓取;它必须使用昂贵的计算机生成或使用可重复的实验记录。虽然现代 DL 研究通常专注于如何帮助超大型模型在更大的数据集上学习,例如罗伯塔,但我们需要对样本高效模型进行更多研究。
令人欣慰的是,我们也更加了解我们的投入和目标之间的关系。人类几个世纪以来的知识没有白费!在许多情况下,我们知道输入和输出之间关系的特定约束,或者输出的特定形式,例如能量守恒,在多输出模型中加强元素之间的已知关系。主要的困难是如何在模型本身中有效地传达或编码我们的先验知识,这本身就是一个重要而活跃的研究子领域。
许多从事“传统”深度学习问题的科学家和工程师,无论是在工业界还是在学术界,都经常抱怨神经网络的训练和推理时间太长。但对于科学界来说,深度学习作为一种随机训练模型,比传统的迭代、数值模型(如有限元、密度泛函理论等)快很多个数量级。还需要注意的是,神经网络的推理和训练时间在未来只会减少,因为 NVIDIA 和 Intel 等公司在创建专用硬件以加速神经网络操作(如矩阵累加)方面投入了大量精力。传统的数值方法肯定不是这样,在大多数情况下,传统的数值方法将运行时优化推到了最大可能,这是几十年来人们投入精力寻找更有效、科学合理的算法的结果。
我计划继续更新传统 DL 问题和科学问题之间的差异列表。希望这将作为 DL 进步和科学需求不匹配的领域的指南,并有助于激励针对科学需求的 DL 研究的进一步研究。
新的前进方向
深度学习领域目前被科技行业的担忧所主导:他们大量投资计算基础设施的能力,拥有大型专有数据集,最重要的是,吸引人才的巨额资金,已经将科学界的担忧边缘化。令人惊讶的是,G oogle 在 NeurIPS 2018 上发表了最多的论文,并且在论文数量排名前十的机构中,有 3 家是盈利性公司。此外,在社交媒体互动的大规模数据集上训练的非常成功的模型的使用导致了对隐私、偏见、道德以及这种技术对我们民主的影响的越来越多的担忧。
但与我们在新闻中看到的相反,除了搜索推荐、新闻提要算法和面部识别之外,人工智能还有其他用途。我们可以使用人工智能来加速科学模拟,以发现新材料来对抗不断增加的碳排放,改善药物输送和癌症治疗,并更好地了解我们周围的世界。有许多重要的人工智能用例缺乏许多(但不是全部)科技行业追求科学进步的棘手和道德模糊的问题。
要做到这一点,需要新一代的双语科学家,他们精通科学和机器学习。事实上,这种需求已经在某些领域得到了认可,比如高能物理。关于人工智能和人工智能有许多浮夸的说法——但可以毫不夸张地说,深度学习已经彻底改变了我们做科学的方式。但这首先需要科学家熟练使用这种新工具。
结论
深度学习系统在玩棋盘游戏、驾驶汽车和识别图像方面表现出的类似人类的能力产生了令人难以置信的兴奋。但这些进步是由基于网络的科技公司推动的,这些公司对与其收入流相关的特定问题子集感兴趣。深度学习有大量的机会应用于科学和工程中更基本的问题。利用深度学习,我们可以提高对宇宙中星系的理解,翻译基因组序列,并为一个不断进化(更热)的世界确定下一代材料。我的希望是,随着我们教育第一代深度学习科学家,也许他们中的一些人可能会决定使用他们独特的技能来更好地了解他们周围的自然世界。
我最近开始了一个关于机器学习和人工智能在科学领域和工程问题中的应用的免费通讯(ml4sci)。你可以在ml4sci.substack.com上找到。请随意发表建议的文章或主题,如果你真的喜欢你所看到的,请订阅!
太空中的深度学习
原文:https://towardsdatascience.com/deep-learning-in-space-964566f09dcd?source=collection_archive---------12-----------------------
人工智能和机器学习如何支持航天器对接。
Magellan space probe meant to map the surface of Venus, simulated in orbit around earth using Unity (credits and info at the end).
人工智能无处不在。家电、汽车、娱乐系统,凡是你能想到的,它们都在包装人工智能能力。航天工业也不例外。
在过去的几个月里,我一直在开发一个机器学习应用程序,通过简单的摄像头视频来帮助卫星对接。如果你想知道深度学习、神经网络和 Tensorflow 对卫星对接有多有用,请继续阅读。
在这篇博文中,我将向你介绍我学到的方法、工作原理、结果和教训。我一点也不想挑战物体识别的技术水平。但是,当追溯我的脚步时,我意识到我学到了很多。因此,我希望我的故事对你有用,并激励你创建自己的机器学习应用程序。
如果你想跳过阅读直接进入代码,GitHub 上什么都有:https://github.com/nevers/space-dl
请注意,这篇文章假设读者熟悉张量流、卷积神经网络(CNN)的基本原理以及如何使用反向传播来训练它们。
信用
- 非常感谢 Rani Pinchuk 的支持,无数次的讨论,由此产生的见解以及花费在繁琐的标注所有训练数据上的时间。
- OS-SIM 设施的训练和评估图像由 DLR 提供。
- 麦哲伦太空探测器,由 Xavier Martinez Gonzalez 使用 Unity 模拟。
索引
- 数据集准备
- 模型原理
- 损失函数
- 迁移学习
- 结果
- 惨痛的教训
- 硬件
- 结论和后续步骤
- 学分
Intermezzo——对象分割、检测和定位。
Intermezzo——张量流估值器与人工抽象。
数据集准备
知道卫星的详细尺寸,目标是创建一种算法,可以准确预测其姿态和与相机的相对距离。这个项目的数据集是从安装在德国航天中心 OS-SIM 设施的机械臂上的卫星实物模型中创建的。手臂模拟各种动作,同时摄像机记录视频。
The satellite mockup captured by the video camera on the robotic arm. Source: OSM-SIM facility DLR.
我决定集中精力寻找卫星的尖端。如果我能准确地定位它,我相信我可以对模型上的至少两个其他标签做同样的事情。(卫星的“尖端”实际上是其对接机构的一部分。)给定这 3 个(或更多)点和卫星的 3D 模型,然后我可以重建卫星的姿态和相对于相机的相对位置。
相机记录了 14,424 张未标记的图像,我想用它们来训练和评估一个神经网络。我的一个担忧是,我将不得不花很长时间在每张图片上手动标注小费。幸运的是,我了解到 OpenCV 的优秀图像标记工具: CVAT 。
使用 CVAT 你可以批量导入所有你想要添加注释的图像,将它们作为电影播放,并插入相隔许多帧的注释。它还允许在多人之间分割工作,它甚至有一个很好的 docker-compose 文件,允许你点击一个按钮来运行它。
CVAT 节省了大量的时间和工作:只花了几个小时就在 14,424 张图片上标注了提示。(其实这个工作我不能拿的功劳。)对于卫星的线性运动,我们只需标注开始和结束位置,CVAT 将在它们之间插入并添加所有标签。如果你需要视频或图像注释工具,强烈推荐 CVAT。
Annotating the tip of the satellite using boxes in OpenCV’s CVAT.
然而,有一些改进的机会,或者更确切地说,是我希望拥有的功能。例如,CVAT 不支持点之间的插值。作为一个变通办法,所有的注释都必须用方框来代替点。(框的左上角坐标用于匹配笔尖的位置。)此外,任何未加注释的帧,即提示不可见的帧,都不包括在 XML 输出中。
XML output from CVAT after annotating the images.
为了使这个 XML 文件适合于训练和评估模型,必须对它进行后处理,使其成为正确的格式。有趣的是:这个看似琐碎的任务,实际上需要相当多的迭代才能完成。我经常不得不回去修改标签、添加新标签、更新输出格式等等。对我来说,这是一个教训。
将原始数据和注释转换成适合训练和评估的数据集的代码是代码库的重要组成部分。它不仅仅是一堆晦涩难懂的一次性终端命令。你应该尊重它,因为它是剧本的一部分,允许你重现你的结果和你的文档。对你的代码进行版本化,审查它,对你的数据集版本使用语义版本化,最重要的是,通过压缩数据集并提供下载,使其他处理相同问题的人能够容易地使用数据集。
一旦我有了数据集构建脚本的基线,同事们就能够重用它并分享他们的更改。我已经在我们公司引入了 Nexus ,我们现在使用它来分发来自 Java、Python 和 Docker 的所有代码工件,包括数据集等等。
数据集构建脚本还允许对不同版本的数据集进行快速实验:
- 应用数据增强:旋转,模糊,锐化。
- 尝试不同的培训和评估方法。
- 将数据定制为适合您的模型的表示形式。
- 将数据转换和打包成合适的格式。
这最后一点值得多加注意。因为我使用的是 Tensorflow ,所以我想使用 TFRecords 数据格式。不仅仅是因为它很好地集成到了 TF Dataset API 中,更重要的是因为我认为这种二进制数据格式从磁盘读取会更有效。下面是我如何使用 Python 多重处理将图像和标签转换成 TFRecords 文件的代码摘录。(我想使用多线程,但是……在 Python-land 中,线程并不酷,而且 GIL 也这么说。)
Convert images and labels to a TFRecords file using multi-processing in Python.
在创建了 TFRecords 文件之后,我创建了这个脚本来测试和比较从 TFRecords 文件中读取 13,198 个训练图像与简单地从磁盘中读取每个图像并动态解码它们所花费的时间。令人惊讶的是,TFRecords 数据格式并没有真正提高读取训练数据集的速度。下面的时序输出显示,从 TFRecords 文件中顺序读取比从磁盘中读取每个图像并即时解码要慢。差别很小,但我肯定 TFRecords 会更快。
如果您真的想提高数据导入管道的性能,可以考虑并行处理和数据的预取。通过在解析数据集时简单地设置TF . data . dataset . map num _ parallel _ calls参数,从 TFRecords 文件中并行读取这些完全相同的图像要比顺序读取快 2 倍。从磁盘上读取每张图片并即时解码甚至比 T8 快 3 倍。然而,在并行示例中,读取 TFRecords 文件几乎比动态读取图像慢 2 倍。又不是我所期待的。如果有人可以指出这个问题并分享他们与 TFRecords 的经历,我会很高兴。
最后,结合并行解析和预取使我能够消除训练期间的任何 CPU 瓶颈,并将平均 GPU 利用率从 75%提高到 95%以上,这是用 nvidia-smi 命令测量的。
以下是脚本在我的旧 2011 iMac(2.7 GHz 英特尔酷睿 i5)上运行时的时序输出:
13198 幅图像的顺序解析:
- TFRecords 数据集:50.13s
- 普通 PNG 文件数据集:49.46 秒
并行解析 13198 幅图像:
- TFRecords 数据集:26.78s
- 普通 PNG 文件数据集:15.96 秒
示范原则
最近,我在Coursera 上完成了吴恩达的深度学习专精。(Ng 的发音有点像《歌》结尾的 n 音。)这五门课程涵盖了深度学习和神经网络的核心概念,包括卷积网络、RNNs、LSTM、Adam、Dropout、BatchNorm、Xavier/He 初始化等等。该课程还详细介绍了医疗保健、自动驾驶、手语阅读、音乐生成和自然语言处理的实际案例研究。除了安德鲁惊人的成绩之外,他还是一位伟大的老师,我必须说这是一次美妙的经历。我可以向任何想进入深度学习的人推荐这门课程。
在涵盖卷积神经网络的第四门课程中,他对使用 YOLO 算法的物体检测做了精彩的解释(你只看一次)。该算法执行实时对象检测,如下图所示。
Object detection using YOLO. Source: https://pjreddie.com/darknet/yolo/
“YOLO 是最有效的对象检测算法之一,它包含了整个计算机视觉文献中与对象检测相关的许多最佳想法。”— 吴恩达
就这样,我忍不住实现了我自己的算法的天真版本。我不会在这篇文章中解释最初 YOLO 论文的全部工作原理和细节,因为有太多优秀的博客文章都是这么做的。(像这个举个例子。)相反,我将着重于我如何使用 YOLO 来解决我的具体本地化问题。
物体分割、检测和定位。
物体分割、检测和定位是有区别的。对象分割的目的是找到各种形状的片段,这些片段给出图像中要检测的对象的轮廓的逐像素描述。对象检测是在给定图像中的一个或多个对象周围找到矩形边界框的过程。目标定位是寻找一个或多个目标的位置。
Object segmentation, detection and localization from left to right.
该算法的主要原理很简单:获取输入图像并应用大量的卷积层,每个卷积层都有自己的一组滤波器。每组卷积层都会降低图像的特征空间或分辨率。请记住,卷积保持空间局部性,因为每一层都有与其相邻层的局部连接模式。因此,输出层中的每个元素代表输入处原始图像的一小块区域。每个卷积步长的滤波器可以从 64 到 1024 或者甚至 4096 变化。然而,在最终的输出层中,过滤器的数量减少到 3 个。换句话说,输出层有 3 个通道,每个通道将被训练为针对图像中特定区域的不同目的而激活:
- 通道 1 —预测位:表示在 0 和 1 之间卫星提示出现在图像的该区域中的机会。
- 通道 2-相对 X 位置:尖端的垂直位置(如果可用),相对于该区域的左上原点。
- 通道 3 —相对 Y 位置:与通道 2 相同,但不同。
看看下面的图片,这是我试图描绘的概念。
The input image in the top layer is dimensionally reduced to the output layer at the bottom (omitting the convolutional layers in between). The grey lines between the input and output layer show how each neuron along the depth dimension (or per channel) is dedicated to a specific region of the image. Per region, the output volume predicts whether a tip is visible and its X and Y coordinate relative to the origin of that region. In an ideal scenario, a prediction would have all elements set to zero except for the highlighted volume where the tip is visible.
在我的算法的第一个天真的版本中,我没有花很多时间来找出解决我的问题的完美的 CNN 模型架构。相反,我想专注于代码中允许我训练和评估模型的部分。因此,我简单地实现了与最初 YOLO 论文中的架构图相同的模型布局(如下)。
YOLO v1 CNN model (source: https://arxiv.org/pdf/1506.02640.pdf)
这就是我简单的头脑如何将这些层解释成代码。
My naive interpretation of the Yolo v1 model.
我很高兴我没有在模型上花太多时间,因为建立损失函数和训练/评估需要花费更多的时间。此外,现在有太多优秀的模特,很难被击败。例如,看看 Tensorflow Hub ,或者看看在 Keras 提供的模型。出于这个原因,我并不太关心模型的性能。相反,我的主要目标是让算法的所有活动部分都工作起来:输入端的数据集管道、可训练模型、损失函数和评估指标。
损失函数
为了计算损耗,我的第一步是将所有标签(基本上是卫星尖端的 x,y 位置)转换成输出体积,如上图所示。这是我想出来的。或者,如果您喜欢跳过大部分代码,只需查看脚本第 20 行的简单示例。
Code excerpt that parses a given label (i.e. the x and y position of the tip of the satellite) into a volume similar to the output of the model.
下一步是将给定的解析标签与模型的输出进行比较,并设置允许梯度下降以优化模型参数的损失函数。我尝试了许多替代方案,摆弄着均方误差和均方对数误差。最后,我决定使用交叉熵损失(如果你愿意,也可以使用对数损失),因为它对于概率值在 0 到 1 之间的分类任务特别有效,比如预测损失。
损失函数本身是两部分的加权和:
- 预测损失:模型预测输出体积中每个盒子是否有卫星提示的程度。我给这个预测损失的权重是 5,因为它是获得正确预测的主要因素。
- XY-loss:如果盒子里有尖端,模型预测尖端位置的准确性如何。如果图中没有可用的提示,损失函数的这一部分应该为零,这样只有预测损失决定最终损失。我给这个预测损失的权重是 1。
看看下面实现这个损失函数的代码。这样,我就可以使用 Adam 优化器来训练模型了,万岁!
The loss function of the model.
事后想来,写这个的时候,我意识到这个损失函数还是可以改进很多的。如果图像中有一个尖端,则为输出体积中的每个框计算 XY 损耗。这意味着 XY 损耗也被考虑到所有没有可见尖端的盒子中,这不是我想要的。因此,XY-loss 主要被训练来探测背景,而不是卫星提示…哎呀。此外,XY 损失不像预测损失那样是一项分类任务。因此,使用均方误差或类似策略来计算可能更好。有趣的是:这个损失函数表现很好。所以,这实际上是个好消息:它可以表现得更好:)
迁移学习
一旦我有了模型和损失函数,运行和训练正常,我想把我对 YOLO 模型的天真解释换成一个经过战斗考验和预先训练的版本。因为我只有有限的数据集,所以我假设需要迁移学习来解决这个问题。
一种选择是简单地从 Tensorflow Hub 中挑选一个模型。然而,TensorFlow 使得使用这些模型太容易了,我想走一条更具挑战性的路线,这样我可以学到更多。我决定使用原作者的最新版本的 YOLO 模型,因为它是为暗网编写的,我想了解如何将该模型导入 Tensorflow。
当我开始研究最新的 YOLO 模型定义时,我很快意识到我需要解析定义文件中的每一个部分并将其映射到正确的 Tensorflow 层。也许我应该对我的愿望更加小心,因为这是一项乏味又费时的工作。幸运的是,我找到了这个将 YOLO 模型定义转换成 Keras 模型的脚本,我可以使用 Tensorflow 加载它。
迁移学习是指重用在不同但相似的数据集上预先训练的现有模型的部分层权重,并仅重新训练剩余的层。一旦我加载了所有的 252 个模型层,我必须弄清楚哪些层(及其相关权重)我想要保持不变,哪些层我想要重新训练以及它们的每个维度。为此,我编写了一个简短的脚本,将 Keras 模型绘制成图像并从给定的图层列表中计算尺寸。
使用这个脚本,我可以简单地预览整个模型布局,包括所有的图层名称。然后,我在模型的正中间手动选择了一个图层:“add_19”。在我的实现中,使用 layer.trainable 属性,前半部分的所有层的权重保持不变,后半部分的所有层的权重被重新训练。模型中的最后一层是“conv2d_75 ”,它有 255 个通道。我添加了一个额外的卷积层,内核/过滤器大小为 3,以减少模型输出并使其符合我的最终目标。
Loading the YOLO model in Keras, enabling transfer learning and matching the output layer dimensionality to match the labels and loss function.
结果
首先,让我们看看迁移学习是如何影响结果的。看看下面的图片。重用 YOLO 模式的前半部分,重新训练后半部分,会产生巨大的不同。事实上,结果是无可比拟的。没有迁移学习,损失函数停滞在 80 左右,而有了迁移学习,损失函数立即下降到几乎为零。
Model loss function output per training step. The dark blue line shows the loss without transfer learning or simply a randomly initialized model. The light blue line shows the loss when half of the model reuses weights from the YOLO model.
下图显示了不使用迁移学习时的模型输出。请注意,该模型能够过滤掉背景并专注于提示,但永远无法做出准确的预测。
Model prediction output when not using transfer learning. Each output volume of the model is shown as a semi-transparent box with a color that ranges from (very transparent) blue (indicating a low chance of a tip present in that box) to green and then to red (indicating a high chance).
The model prediction output visualized for the same image over 42 training epochs when not using transfer learning. Notice how the model learns how to filter out the background, but never succeeds into narrowing down on the tip.
这是整个评估数据集的样子,仍然没有迁移学习。
Video animation of the model predictions for the evaluation data without transfer learning.
然而,这是在启用迁移学习的情况下,整个评估数据集的情况。
Video animation of the model predictions for the evaluation data using transfer learning.
很明显,迁移学习对结果有着巨大的影响。因此,本文的其余部分和结果假设迁移学习是启用的。
除了损失函数的输出,模型的性能以 4 种方式测量:
- metrics/dist_mean: 对于模型正确预测存在吸头的所有样本,从预测到标签的平均距离是多少(以像素为单位)。
- accuracy/point_mean: 对于模型正确预测存在吸头的所有样本,这些样本中距离标记吸头 10 个像素以内的样本所占的百分比。
- accuracy/prob_mean: 模型预测小费存在的准确程度。即预测位必须高于 0.5。
- 准确性/总体均值:正确预测样本的百分比。即,如果没有尖端,模型也预测同样的情况,并且如果有尖端,它在离标签 10 个像素之内。
以下是对 2885 个样本的评估数据集进行约 8 个小时的模型训练后得出的评估结果。
- 度量/距离 _ 平均值:1.352 像素
- 准确率/点均值: 98.2%
- 准确率/概率均值: 98.7%
- 准确率/总体均值: 98.7%
下面你可以在 Tensorboard 上看到这些数字随时间的变化。简单来说,算法平均差一个像素。
**
Four evaluation metrics and the loss function calculated after every training epoch during a training period of 8 hours.
在 2885 个评估样本中,有 32 张图片的预测是错误的。当我看着它们的时候,有 28 张图片的尖端位置被相当精确地探测到了,但是这个模型根本就没有足够的信心说有一个尖端。即,预测器比特没有超过 0.5,但是选择了正确的盒子。这里有一个例子。
The model predicts the tip within 10px but the confidence level is just below 0.5 and therefore it is marked as an erroneous prediction. It’s so close to 0.5 that when rounding the predictor bit, it yields exactly 0.50.
剩下的四个负面预测更有意思。它们大多被贴错了标签,或者至少是模棱两可的。当尖端隐藏在物体后面,但人类仍然容易定位时,一些图像被不一致地标记。这正是模型所捕捉到的。下面显示了两个示例:尖端隐藏在对象后面,并被标记为没有可见的尖端。而模型预测存在尖端并且在正确的位置。
**
Examples of a negative prediction where the tip of the satellite is hidden behind an object. These images are labeled as not having a visible tip (hence the label -1, -1), whilst the model is still able to predict a correct position.
intermezzo——张量流估值器与人工抽象。
Tensorflow 包括评估器,以保护开发人员免受样板代码的影响,并将他们的代码引导到一个可以轻松扩展到多台机器的结构中。我总是使用评估者,并假设我对他们的忠诚会得到高效率、干净代码和免费特性的回报。在 Tensorflow 1.12 中,这些假设的一部分是正确的,但我仍然决定创建自己的抽象。下面我解释一下原因。
为了确保一致性,每次您调用 estimator 时,estimator 都会从磁盘重新加载模型。{train(),predict(),evaluate()}。(train_and_evaluate 方法只是一个调用 estimator.train 和 estimator.evaluate 的循环)如果您有一个大模型(这很常见),并且您希望在同一台机器上交错训练和评估,重新加载模型确实会减慢训练过程。
评估人员重新加载模型的原因是为了确保分布模型时的一致性。这是他们背后设计理念的很大一部分,但正如你可以在这里读到的,经济放缓确实会导致挫折。此外,并不是每个人都需要也没有闲心拥有一大群 GPU,或者更重要的是,有时间让他们的模型并发,因为这需要仔细的(重新)设计和努力。Tensorflow 确实有一个 InMemoryEvaluatorHook 来克服这个问题。我试过了,效果不错,但感觉更像是一种变通办法,而不是真正的解决办法。
此外,当我尝试从估计器模型函数中加载我的 Keras 模型时,我花了一些时间才意识到必须在每次训练或评估调用后手动清除 Keras 模型。真尴尬。
这些东西并不是真正的亮点,但加上学习 Tensorflow 如何工作的冲动,它们足以说服我创建自己的微抽象。
随着 Tensorflow 2.0 的出现,我相信大部分我纠结的事情都会迎刃而解。Keras 将被集成到 Tensorflow 的核心,并成为其主要接口之一。估值器仍然是首选。如果你想了解更多关于 Tensorflow 2.0 的信息,请查看这个博客和这个视频。
惨痛的教训
我不敢相信我在做这个的时候犯了多少错误。有些很傻,很容易得到,但有些真的很难发现。以下是我学到的一些可能对你有用的经验:
- 双重、三重和四重检查你的评估/培训指标的语义、解释和正确性。例如,我的模型从一开始就获得了 100%的准确率。这并不是因为模型超级准确,而是因为这个指标只考虑了那些模型正确预测有小费的样本。如果 10000 个样本中只有 5 个样本检测到正确的 tip,100%的准确性仍然意味着在 10px 内只检测到 5 个图像。
- 特别是 tf.metrics API 不止一次愚弄了我。明智地使用 tf.metrics。它们用于评估,即汇总多个批处理操作和整个评估数据集的结果。确保在适当的时候重置它们的状态。
- 如果在 Tensorflow 中使用批量定额,不要忘记在训练期间更新移动平均值和方差。这些更新操作自动存储在 tf 中。UPDATE_OPS 集合,所以不要忘记运行它们。
Two code examples on how to update moving mean and variance when performing batch norm in Tensorflow.
- 编写单元测试作为一个健康检查,或者至少将您快速和肮脏的测试脚本保存到一个单独的文件中,以供以后参考。彻底测试损失函数尤其有意义。
- 每次训练模型时,请确保所有输出指标和其他数据都保存在一个唯一的、带有时间标签的目录中。此外,存储 git 标签(例如 heads/master-0-g5936b9e)。这样,无论何时你搞乱了模型,它都会帮助你恢复到以前的工作版本。
Example code on how to write the git description to a file.
- 将您的指标写入 Tensorboard,用于培训和评估。这是非常值得的,因为可视化让你对你的工作表现有了深入的了解。这有一些挑战,但反过来你可以更快地迭代和测试你的想法。
- 在 TensorBoard 中跟踪所有可训练变量,以帮助您尽早发现爆炸或消失的梯度。这里有一些如何做到这一点的灵感。
Example code on how to visualize the mean value and a histogram for each trainable variables in the model and an overall histogram for all trainable variables.
- 尝试自动并定期暂停训练过程以评估模型。确保在 Tensorboard 中将训练曲线和评估曲线渲染到同一个图形中。这样,您就可以可视化模型在训练过程中从未见过的数据上的性能,并在发现问题时立即停止。请注意,您不能通过简单地重用同一个标签在同一个图中显示多个汇总。Tensorboard 将通过在标签名称中添加“_1”来自动使这些摘要具有唯一性,从而强制它们显示在单独的绘图中。如果您想解决这个限制,您可以自己生成总结协议缓冲区,然后手动将它们添加到总结中。FileWriter()。有点尴尬,但很管用。
Example on how to save a metric with the tag “metrics/loss” during evaluation whilst, during training, a metric with the very same tag was used. This allows having both the training and evaluation curves shown on the same graph in Tensorboard.
- 监控 GPU 利用率和内存消耗,并尝试获得尽可能高的 GPU 利用率。如果你使用 NVIDIA 显卡,你可以使用 nvidia-smi 命令来完成。您还可以使用 htop 监控 CPU 和内存消耗。
五金器具
- NVIDIA Geforce RTX2080TI (11GB,4352 个 Cuda 内核,600 瓦,INNO3D 游戏 OC X3)
- 超微 X9DRG-QF 双 CPU 主板
- 2 枚英特尔至强 E5–2630(12 核)
- 三星 860 EVO SD(500 克)
- 128 克内存
结论和下一步措施
当我开始写这篇文章的时候,我的目标是一个简短但内容丰富的信息。我一点也不知道,这将是这样一个怪物的职位,很抱歉。这个项目让我接触了监督学习算法的许多方面,这可能解释了它的大小。
利用给定的评估数据,该模型能够在 98%的时间内精确定位卫星的尖端,误差为一个像素。我对这些结果很满意。然而,如果我想将这款车型投入生产,我还有很多事情要做。当前的数据集太有限,无法训练一个鲁棒的模型:图像彼此非常相似,并且只覆盖了少量不同的姿态。由于我没有机会获得更多的数据,一位同事决定帮助并使用 unity 渲染卫星图像。这篇文章顶部的麦哲伦太空探测器的图片就是这个数据集的一个例子。我意识到这不会产生一个现实的模型,但它将允许我继续我的学习过程。
此外,仅识别卫星的一个点不足以精确计算相对于观测相机的姿态和距离。理论上,必须跟踪至少 3 个点,而在实践中,该模型应该预测更多的点以获得可靠的输出。
您已经完成了这篇文章,感谢您的阅读!我希望它能激励你从事自己的人工智能项目和挑战。
深度学习在威斯康星州乳腺癌诊断中的应用
原文:https://towardsdatascience.com/deep-learning-in-winonsin-breast-cancer-diagnosis-6bab13838abd?source=collection_archive---------9-----------------------
面向医疗保健的深度学习方法
1.介绍
机器学习方法长期以来一直用于医疗诊断[1]。威斯康星州乳腺癌数据库(WBCD)数据集[2]已被广泛用于研究实验。
大多数出版物集中于传统的机器学习方法,如决策树和基于决策树的集成方法[5]。
最近有监督的深度学习方法开始受到关注。例如,Stahl [3]和 Geekette [4]将这种方法应用于 WBCD 数据集[2],使用从乳腺肿块的细针抽吸(FNA)的数字化图像计算的特征值进行乳腺癌诊断。这些特征描述了图像中出现的细胞核的特征。
Stahl [3]使用了具有衍生特征(例如,平均值、标准误差等)的 WBCD 数据集。)并实验了三种深度神经元网络:1、2、3 个隐层 30 个神经元,没有任何数据预处理。Geekette [4]只使用了最初识别的具有中心和尺度等预处理的特征,但没有提供数据预处理或使用的神经元网络架构的详细信息。
本文提出了一种新的监督深度学习模型,用于使用公共开源库分析相同的 WBCD 数据集[2]进行乳腺癌诊断。新的监督深度学习模型继承了 Stahl [3]和 Geekette [4]实验的方法的优点。具体来说,与[4]类似,新方法使用最初识别的特征[2],使用中心和尺度对数据进行预处理,并将乳腺癌诊断问题视为 2 类分类问题。与[3]一样,新方法采用多个(三个)隐层的深层神经元网络。
1.1 问题陈述
给定从来自患者的乳房肿块的 FNA 的数字化图像计算的特征(即,特征向量)的列表(详见 2.1 节),问题是如何诊断(确定)患者是否患有乳腺癌。
类似于 Stahl [3]和 Geekette [4]的实践,在本文中,该问题被视为 2 类(B- 良性、 M- 恶性)分类问题。
解决这种分类问题的策略是利用一种新的深度学习模型,该模型具有多个隐藏和丢弃层(详见 2.3 节)。新的深度学习模型的输入是从 FNA 的数字化图像计算的特征值,并且来自该模型的输出是两个识别的分类诊断类别 B 或 m
1.2 指标
与 Geekette [4]采用的评估方法类似,预测准确性被用作本文中的主要评估指标。
具体来说, Keras 二进制准确性指标 API 用于计算 WBCD 诊断二进制分类问题的所有预测的平均准确率,如下所示:
平均准确率= ( m / n ) * 100%
其中 n 为测试样本总数, m 为匹配测试用标记响应的预测总数。
2.分析
本节首先探索和分析数据集,以确定数据预处理需求,然后描述深度学习模型和相关技术。
2.1 探索数据
本文中使用的数据集是公共的 [WBCD 数据集](https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast- cancer-wisconsin.data)【2】。如 WBCD 数据集[1]中所述,为每个细胞核计算了以下特征,并将用作新的深度学习模型的输入:
- 团块厚度
- 细胞大小的均匀性
- 细胞形状的均匀性
- 边缘粘连
- 单一上皮细胞大小
- 裸核
- 平淡的染色质
- 正常核仁
- 有丝分裂
以下代码用于获取数据集的统计摘要:
import pandas as pdheaders = ["ID","CT","UCSize","UCShape","MA","SECSize","BN","BC","NN","Mitoses","Diagnosis"]
data = pd.read_csv('breast-cancer-wisconsin.csv', na_values='?',
header=None, index_col=['ID'], names = headers)
data = data.reset_index(drop=True)
data = data.fillna(0)
data.describe()
观察到数据集存在以下问题:
- 缺失数据
- 小数据集大小
- 各种范围的数据值
- 不平衡数据
- 扭曲的数据
数据集的一个常见问题是缺少数据,WBCD 数据集也不例外。具体来说,如表 1 所示,有 16 个裸核条目缺失(标记为?在原始 WBCD 数据集中)。
WBCD 数据集[2]仅包含 699 个样本,在将数据集划分为训练和测试子集后,对于深度学习来说太小了。
不同特征的特征值范围是不同的。平均特征值从大约 1.5 变化到 4.5(关于特征值的各种范围的可视化,参见第 2.2 节)。
不同标签的数据样本总数不平衡。事实上,标记为 B 的数据样本总数(458)几乎是标记为 M 的数据样本总数(241)的两倍(参见第 2.2 节了解这些数字的可视化)。
与数据集相关的另一个常见问题是偏斜度(详见第 2.2 节)。
第 2.2 节提供了这些数据集问题的可视化,第 3.1 节描述了这些数据集问题的解决方案。
2.2 可视化数据
本节通过数据可视化展示了第 2.1 节中描述的一些数据集问题。
图 1 使用以下代码显示了不同特性的各种平均值范围:
import seaborn as sns
data_mean = data.describe().loc['mean']
data_mean.plot(kind='bar', figsize=(14,6))
为了直观显示不平衡的数据集问题,图 2 使用以下代码显示了标记为 B 和 M 的样本总数:
data_B = data[data['Diagnosis'] == 2]
data_M = data[data['Diagnosis'] == 4]
B_M_data = {'B': [data_B.shape[0]], 'M': [data_M.shape[0]]}
B_M_df = pd.DataFrame(data=B_M_data)
B_M_df.plot(kind='bar', figsize=(10,4))
为了直观显示数据偏斜问题,图 3 显示了数据预处理后 Pandas 生成的数据集散点图矩阵(详情见第 3.1 节):
diagnosis = data['Diagnosis']
features = data.drop(['Diagnosis'], axis = 1)
pd.plotting.scatter_matrix(features, alpha = 0.3, figsize = (14,8), diagonal = 'kde');
从图中可以看出,数据集明显向右倾斜。
2.3 深度学习模型
如前所述,在本文中,乳腺癌诊断问题被视为 2 类(良性或恶性)分类问题。
一种新的监督深度学习模型用于分类。新的深度学习模型的架构如图 4 所示。
这种新的监督深度学习模型继承了 Stahl [3]和 Geekette [4]实验的方法的优点。
具体来说,与[4]类似,新方法使用最初识别的特征[2],使用中心和尺度对数据进行预处理(详见 3.1 节),并将乳腺癌诊断问题视为 2 类(良性或恶性)分类问题。
与[3]一样,新方法采用多个(三个)隐层的深层神经元网络。
此外,数据集的不平衡和偏斜问题也作为数据预处理的一部分进行处理。
如图 4 所示,新的深度学习模型的输入是从 FNA 的数字化图像计算的特征值,模型的输出是两个识别的分类诊断类 B ( 良性)或 M ( 恶性)。
第一个隐层用 9 个神经元,最后一个隐层用 1 个神经元分别匹配输入特征数和输出类别数。中间的隐藏层的大小(5 个神经元)是第一个和最后一个隐藏层的大小的中间。
此外,在隐藏层之间引入了辍学率为 50%的脱落层,以避免过拟合,并潜在地提高新的深度学习模型在准确性方面的性能。
公共整流线性单元(ReLU)激活功能 relu 用于隐藏层 1 和 2。广泛使用的 sigmoid 激活函数被用在最终隐藏层 3 中,以产生(0,1)范围内的连续输出。阈值 0.5 固有地用于从连续输出产生二进制诊断输出。
以下损失函数、优化器和度量函数用于训练新的深度学习网络模型:
- 损失函数:二元交叉熵
- 优化器功能: Adam(自适应力矩估计)
- 度量函数:准确度
选择二元交叉熵损失函数是因为 WBCD 分类是二元分类问题。
选择精度而不是二进制精度度量函数是因为精度度量函数支持模型定型中的精度历史,但二进制精度度量函数不支持。
选择 Adam 优化器函数是因为它是用于训练深度学习模型的随机梯度下降(SGD)的替代优化算法。
关于新的深度学习网络架构的更多信息在第 3.2 节中提供。
2.4 基准
新的监督深度学习模型的结果将与应用具有默认设置的随机森林分类器[6]的开源 scikit-learn 开箱即用实现的结果进行比较,以测量相对性能(详细信息请参见第 3 部分)。
3.方法学
在这一节中,首先描述数据预处理的方法,然后提供端到端的实现细节。
3.1 数据预处理
在本文中,丢失的数据条目简单地用 0 替换,原因如下。缺失条目的数量(总共 16 个)相对较小,因此用 0 替换它们不会对数据集的统计数据模式产生显著影响。
如 2.1 节所述,具有不同标签的数据样本的总数是不平衡的。这种不平衡的数据问题通过生成标记为 M 的新数据样本来解决。具体而言,通过向标记为 M 的现有数据样本引入正态分布随机噪声,标记为 M 的 241 个数据样本的集合被加倍(482)。如图 5 所示,标记为 M 的所得新数据样本集合与标记为 b 的数据样本集合相当平衡
如 2.1 节所述,原始数据集仅包含 699 个样本。本文通过生成如下新数据样本解决了这个小数据量问题。
首先,从标记为 M 的数据样本中分离标记为 B 的数据样本。然后,通过引入正态分布随机噪声,将标记为 M 的数据样本集加倍。最后,类似于扩展标记为 M 的数据样本集,通过引入正态分布随机噪声,新的组合数据集加倍。
通过使用 Numpy 随机数生成库Numpy . random . normal(mean,sigma,features.shap e)生成与给定数据集具有相同特征维数的正态分布随机数的数组来实现噪声生成,其中表示 = 0,标准差 sigma = 0.1。之后,将生成的随机数数组逐个元素地添加到给定的数据集中,以形成新的数据集。
WBCD 数据集[2]中最后一列“诊断/类别”中的值在本文中用作训练新深度学习模型的标签。通过将新生成的特征值阵列与来自给定数据集的“诊断/类别”列组合成新的数据集,这些标签被重新用来标记新生成的数据集中的相应样本(特征向量)。
数据集扩展后,最终的新数据集总共包含 1,880 个样本,用于模型训练和测试。
作为一种常见的做法,对于每个特征,特征值被缩放到[0,1]的范围内用于深度学习,如下所示:
(值-最小值 ) / ( 最大值-最小值)
通过对特征值求平方根来处理所识别的数据偏斜问题。这是通过 Numpy API 实现的,如下所示:
Value = Numpy.sqrt(Value)
图 6 显示了对数据集应用平方根变换的结果。
3.2 端到端实施
以下常见开源库用于实现数据预处理和新的深度学习模型:
- Numpy
- 熊猫
- scikit-lean
- 克拉斯
- matplotlib
本节的其余部分描述了具体的实现细节。
3.2.1 加载数据
作为实现的第一步,使用 Pandas API 加载数据集 csv 文件(有关代码,请参见 2.1 节)。
缺失数据问题在数据加载中分两步处理。首先是丢失的数据问号“?”换成了楠。然后那些 NaN 值用 0 填充。
3.2.2 增补数据
为了解决数据不平衡和小数据集大小的问题,给定一个数据集,定义以下函数,通过引入正态分布随机噪声来生成相同维数的新数据集。
def generateData(data1):
# make a copy of data
data2 = data1.copy()
# separate labels from features
diagnosis2 = data2['Diagnosis'] # labels
features2 = data2.drop(['Diagnosis'], axis = 1)
features2_headers =
["CT","UCSize","UCShape","MA","SECSize","BN","BC","NN","Mitoses"] mean, sigma = 0, 0.1
# creating a noise with the same dimension as the dataset
noise = np.random.normal(mean, sigma, features2.shape)
features2 = features2.apply(pd.to_numeric, errors='ignore')
features2_with_noise = features2.add(pd.DataFrame(noise, columns = features2_headers), fill_value=0)
data2 = pd.concat([features2_with_noise,
pd.DataFrame(diagnosis2)], axis = 1) return data2
上面的数据集生成函数被如下调用,以将新生成的数据集与给定的数据集组合。
new_data = generateData(data)
data = data.append(new_data, ignore_index=True)
3.2.3 缩放数据集
如前所述,不同特征的值具有不同的范围,并且这些值的大部分在[0,1]的范围之外。然而,新的深度学习模型要求输入值在[0,1]的范围内,以获得更好的性能。为此,数据集的值被缩放到[0,1]的范围内,如下所示:
from sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler()
numerical =["Diagnosis","CT","UCSize","UCShape","MA","SECSize","BN","BC","NN","Mitoses"]
data[numerical] = scaler.fit_transform(data[numerical])
3.2.4 处理数据集偏斜度
如前所述,数据集偏斜问题是通过将要素从标注中分离出来,然后仅对要素值应用平方根变换来处理的。这是通过以下方式实现的:
diagnosis = data[‘Diagnosis’]
features = data.drop([‘Diagnosis’], axis = 1)
sqrt_features = features.copy()
for feature_name in sqrt_features.columns:
sqrt_features[feature_name] =
np.sqrt(sqrt_features[feature_name])
features = pd.DataFrame(sqrt_features)
3.2.5 将数据集分割成训练和测试子集
如前所述,数据集分为两部分:75%用于模型训练,25%用于模型测试:
from sklearn.model_selection import train_test_split# Shuffle and split the data into training and testing subsets
X_train, X_test, y_train, y_test = train_test_split(features,
diagnosis, test_size=0.25, random_state=42)
3.2.6 重新格式化数据集
拆分数据集后,必须按如下方式重新索引生成的数据子集,以避免数据集键不匹配问题:
X_train = X_train.reset_index(drop=True)
X_test = X_test.reset_index(drop=True)
y_train = y_train.reset_index(drop=True)
y_test = y_test.reset_index(drop=True)
那么产生的 Pandas 数据帧必须转换成 Numpy 数组,如下所示,因为 Pandas 数据帧不受 Keras API 支持。
X_train = X_train.values
y_train = y_train.values
X_test = X_test.values
y_test = y_test.values
3.2.7 基准测试
随机森林分类器的 scikit-learn 开箱即用实现用于生成基准预测结果以进行比较,如下所示:
from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier()
rfc.fit(X_train, y_train)
score = rfc.score(X_test, y_test)
3.2.8 实施新的深度学习模型
流行的开源 Keras 深度学习库[7]用于实现新的深度学习模型。首先,可以定义一个可重用的函数来创建新的模型实例:
from keras.layers import Dense
from keras.layers import Dropout
from keras.models import Sequential import keras
import keras.utils
from keras import utils as np_utilsdef createModel():
model = Sequential()
model.add(Dense(9, activation='relu', input_dim=9))
model.add(Dropout(0.5))
model.add(Dense(5, activation='relu', input_shape=(9,)))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid', input_shape=(5,))) model.compile(loss='binary_crossentropy', optimizer='Adam', metrics=['accuracy']) return model
模型训练执行如下:
model = createModel()
model.fit(X_train, y_train, epochs=500, batch_size=32)
此外,如下执行 10 重交叉验证,以验证新的深度学习模型的鲁棒性。
from sklearn.model_selection import StratifiedKFold # fix random seed for reproducibility
seed = 7
np.random.seed(seed)X = X_train
Y = y_train# define 10-fold cross validation test harness
kfold = StratifiedKFold(n_splits=10, shuffle=True,random_state=seed)
cvscores = []
for train, test in kfold.split(X, Y):
model = createModel()
model.fit(X[train], Y[train], epochs=500, batch_size=10,
verbose=0)
scores = model.evaluate(X[test], Y[test], verbose=0)
print("{}: {.2f}".format(model.metrics_names[1], scores[1]*100))
cvscores.append(scores[1] * 100)print("{.2f} (+/- {.2f})".format(np.mean(cvscores), np.std(cvscores)))
最后,按如下方式进行模型测试:
score = model.evaluate(X_test, y_test, batch_size=32)
GitHub [8]中有一个 Jupyter 笔记本,里面有本文中使用的所有源代码。
3.3 改进
本节将讨论不同模型超参数和优化器的准确性影响。
3.3.1 网络深度
本文使用了 1,880 个样本的相对较小的数据集。在这种情况下,使用最少三个隐藏层的深度学习网络是合适的,以获得最佳性能。
如下表所示,由于没有足够的数据来训练深度学习模型,因此使用三个以上的隐藏层会对精度性能产生负面影响。
3.3.2 辍学
理论上,添加辍学层应该有助于避免过度拟合,从而潜在地提高深度学习模型在准确性方面的性能。然而,根据实验结果,一旦时期的数量为 500 或更多,通过使用 50%速率的丢弃,没有获得显著的性能增益。
如下表所示,在使用退学率时,50%的退学率似乎是一个甜蜜点。例如,在所有其他配置参数固定的情况下,使用 30%的丢弃率产生大约 97.1428%的预测准确度,而使用 50%的丢弃率获得准确度为 97.7143%的预测性能。
3.3.3 批量
新的深度学习模型的精度性能对批量大小很敏感。如下表所示,批量大小为 16 似乎效果最好。
3.3.4 历元
实验结果表明,使用 500 个历元足以在有或没有丢失的情况下获得稳定的精度性能。可以减少时期的数量(例如,300)以获得稳定的性能而没有丢失。
3.3.5 优化器
如下表所示,Adam 优化器在准确性方面的性能最好。这并不奇怪,因为 Adam 是 SGD 的改进。
4.结果
该部分提供了模型评估和验证结果以及基准测试结果。
4.1 模型评估和验证结果
与[4]类似,数据集分为两部分:75%用于训练,其余 25%用于测试。
为了避免不平衡和小数据集大小的问题,本文通过引入正态分布随机噪声,将 699 个样本的原始数据集扩展为 1,880 个样本的新数据集。
如前所述,类似于 Geekette [4]实施的评估方法,预测精度被用作主要评估指标。
为了验证新的深度学习模型在小数据集变化的情况下的鲁棒性,使用 500 个时期和批量大小 16 执行了 10 倍交叉验证,以下是结果:
从上表可以看出,在数据集发生变化的情况下,新的深度学习模型的精度性能相当稳定。
4.2 基准测试结果
新的监督深度学习模型的预测准确性与应用具有默认设置的随机森林分类器的开源 scikit-learn 开箱即用实现[6]的结果进行比较,以测量相对性能。
下表显示了将 25%测试数据集应用于训练的随机森林分类器和训练的新深度学习模型的比较结果的汇总。
在上表中可以看出,新的深度学习模型的性能在准确性上与随机森林分类器具有竞争力。两者的预测准确率都达到了 97.4468%。
这种新的深度学习模型的性能超过了 Stahl [3]和 Geekette[4]报告的结果。
5.结论
本节总结了新的深度学习模型的实现结果以及未来可能的改进。
5.1 模型性能可视化
为了验证在将数据集分成两部分(即,75%用于模型训练,25%用于模型测试)的情况下新的监督深度学习模型的精度性能,图 7 示出了新模型在模型训练中的预测精度历史,图 8 示出了新模型在模型训练中的损失历史。
从这些图中可以看出,新模型的精度性能迅速增加并稳定到大约 90%,而损失历史下降并稳定到大约 0.25。
5.2 反射
本文提出了一种新的监督深度学习模型,用于 WBCD 数据集的分类[1][2](详见 2.3 节)。
还提出了一种新的数据生成方法,通过在现有数据样本中引入正态分布随机噪声,解决了不平衡数据集问题,并将 699 个样本的原始数据集扩展到 1,880 个样本的新数据集。
具有裸核特征的缺失数据条目被替换为零,然后数据值被缩放到[0,1]的范围内用于深度学习。通过对特征值求平方根,数据集的偏斜问题得到了显著缓解。
实验结果表明,通过使用深度学习(具有 3 个隐藏层)并在最终隐藏层中引入丢弃层和 Sigmoid 激活函数,新的深度学习模型在 WBCD 数据集的分类中与传统的随机森林分类器具有竞争力[1][2]。新的监督深度学习模型的性能是稳健的,并且优于 Stahl [3]和 Geekette[4]报告的性能结果。
新的深度学习模型是用 Python 实现的,使用了著名的开源库,如 Numpy、Pandas、scikit-learn、Keras、Matplotlib 等。Github [8]中提供了 Jupyter 笔记本的源代码。
5.3 改进
未来可能的改进之一是识别和实现自动化机制,以识别超参数的最佳组合,例如隐藏层的数量、每个隐藏层中的神经元数量、退出和退出率、激活函数、批量大小、时期等。
本文中的实验结果表明,在像 WSCD 数据集[1][2]这样的简单数据集的情况下,有时使用简单的机器学习模型比更高级的深度学习模型更好。
参考文献
- 乳腺癌威斯康星州(诊断)数据集
- WBCD 数据文件
- K.Stahl 、、威斯康星乳腺癌诊断深度学习、、2017 年 7 月 17 日
- D.Geekette,乳腺癌数据:机器学习&分析 ,2016 年 11 月 25 日
- C.Nguyen,Y. Wang,H. N. Nguyen,结合特征选择的随机森林分类器在乳腺癌诊断和预后中的应用,科学研究,第 6 卷第 5 期,2013 年 5 月
- [scikit-learn 随机森林分类器](http://scikit- learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html)
- Keras:Python 深度学习库
- Y.张 GitHub 中 Jupyter 笔记本源代码
披露声明:2019 首创一。观点是作者个人的观点。除非本帖中另有说明,否则 Capital One 不隶属于所提及的任何公司,也不被这些公司认可。使用或展示的所有商标和其他知识产权是其各自所有者的财产。
用 Kaggle 和 Google 云平台深度学习文献
原文:https://towardsdatascience.com/deep-learning-literature-with-kaggle-and-google-cloud-platform-6d7d93d14997?source=collection_archive---------8-----------------------
创建自动更新数据集和内核
我第一次发现 Kaggle 是在大约 4 年前,当时我刚开始进入数据世界的旅程。他们的“巨大”数据集和相关内核帮助我了解了许多现代数据科学工具和技术,从那以后我就迷上了它们。
该平台有几个部分,包括机器学习竞赛、数据集、内核、论坛和课程。数据集部分是我个人最喜欢的,因为它提供了一个广阔的游乐场来探索你能想象到的任何领域的开放数据。然后你可以通过内核(笔记本)分享你的工作,内核是文本、代码和代码输出的混合体。
最近,Kaggle 创建了一个 API,允许从命令行更新数据集和内核。通过使用谷歌云平台(GCP),我们可以安排这种情况定期发生,提供一个自动更新的“仪表板”。这篇博客文章概述了这个过程。
谷歌云平台
GCP 是一种云计算服务,不仅在注册时提供免费积分,还提供完全免费的计算和存储层。当然,付费的话,你也可以旋转巨大的虚拟机集群,更不用说其他几十种功能,包括一些令人惊叹的大数据和机器学习产品。也有其他的云平台,但是考虑到 Kaggle 是一家谷歌公司,Coursera 上有一系列优秀的课程教授 it 的各个方面,我选择了 GCP 的路线。
教程目标
内核的这一部分旨在向您展示如何,
- 创建一个 GCP 帐户
- 创建虚拟机和存储桶
- 从 API 获取数据
- 通过 GCP 在 Kaggle 上创建定期更新的数据集
- 通过 GCP 在 Kaggle 上创建一个定期更新的内核
具体的核心目标
这些年来,我或者和我一起工作的人有几次想要了解科学文献的某个特定领域在做什么。最近,这使我来到了国家生物技术信息中心(NCBI) API ,它允许下载科学论文的细节,包括特定日期范围内的完整摘要。这给了我一个想法,使用 R 脚本定期下载这样的细节,给我和我的同事一个过去的概述和现在的快照。一旦剧本写好了,我需要一种自动化的方法,这让我找到了 GCP。最后,我意识到这可能会引起其他人的兴趣,所以决定创建这个帖子来解释这个方法。
如果我没有告诉你 Rachael Tatman 在 dashboarding 上的伟大系列内核,那将是我的失职,这给了我这个项目的灵感。
下面是这个项目的概述,给你一个所有部分如何一起插槽的想法,
创建一个谷歌云平台账户
前往 GCP 并报名。现在,在某个时候,你会被要求建立一个账单账户,这是我最初不愿意做的。基本上,我能想到的就是…“如果我不小心启动了世界上最大的集群,忘了停用 6 个月,结果破产了怎么办?”。然而,我随后发现了他们的定价页面,并密切关注了所有免费内容的部分。也就是说,12 个月的 300 美元信用额加上一个完全免费的等级。更多详情见此处。此外,随着时间的推移,留意我们账户的账单部分,以确保没有任何疯狂的事情发生。
创建实例
一旦你进去了,你会看到这样的东西…
一开始这可能有点吓人。我刚刚在 Coursera 上完成了出色的 GCP 数据工程专业课程,并且只使用了提供的一小部分功能。在这篇文章中,我们将关注要点,即实例和桶。
一个实例基本上就是 GCP 上的一个虚拟机。在左边的栏上,点击计算引擎,然后点击创建实例。现在,这就是钱可以进来的地方。从地理区域到 CPU 数量,您可以选择多种不同的方式来设置您的机器。幸运的是,右边有一个成本估算器,它会随着您对选项的操作而更新。
首先,给实例起一个自己选择的名字。其次,选择一个地区(我选择了美国-中央 1 ,因为它包含在自由层中。并非所有都是如此,因此请查看右侧的定价估计)。第三,从机种部分选择了 micro (1 个共享 vCPU) 。这(在撰写本文时)由自由层覆盖。
其余的我都默认了。点击创建。
创建一个桶
接下来,您需要一个地方来存储您的数据,尤其是如果您全天都在关闭实例的话。为此,通过点击左上角的 Google Cloud Platform 返回主控制台屏幕,然后从左边的栏中点击存储,接着是创建存储桶。
给它起一个你自己选择的名字,其他都保持默认,然后点击 CREATE 。请注意,默认位置是美国。尽管我在英国,但我离开了这里,因为所有的数据传输都将通过 Kaggle 进行,所以让一切都在同一个国家是有意义的。
安装 Kaggle API
现在是时候使用您创建的实例了。回到主控制台,然后点击计算引擎查看您的实例。然后,点击 SSH 来访问它的 shell。从这一点开始,您可以做任何您通常在 Linux 上做的事情。
安装 R
在这一点上,你可能想做你自己的事情。例如,我使用 R 从 NCBI API 获取数据。但是,您可以使用不同的语言和/或不同的 API。
对我来说,我通过键入 sudo apt-get update 后跟sudo apt-get install R-base来安装 R。为了从 API 中获取数据,我使用了 RCurl R 包,在破解了一点 R 代码之后,我意识到我需要安装一些其他的东西…
- sudo apt-get 安装资质
- sudo apt-get install lib curl 4-OpenSSL-dev
- sudo apt-get 安装 libxml2-dev
一旦完成,用 sudo R 启动 R,然后键入install . packages(' RCurl ')并选择一个合适的镜像。再说一遍,用户网站是有意义的。对包 jsonlite 和 XML 做同样的操作。用 q() 退出 R。它将询问您是否要保存工作区图像。键入 n 并按回车键。
然后我用 nano literature_update 从命令行创建了一个 R 脚本。R
下面的脚本是我用来从 API 获取最新论文细节的。它使用两个 API 命令。第一个获取给定日期范围内(实际上是从今天算起过去的天数)匹配特定搜索条件的所有论文。在这种情况下,我在最后一天使用术语“深入”和“学习”。这样做的结果是一个 XML 文件,其中包含每张纸的 ID 号。然后脚本遍历这个列表,请求每个 ID 的论文细节。这些细节包括您所期望的一切,比如文章标题、作者细节,甚至是完整的摘要。我将每个文件保存到一个单独的 XML 文件中。
复制并粘贴 R 脚本(或者使用适当的 API 命令编写自己的脚本),然后保存并退出(CTRL-X,后跟' Y ')。
注意,对于一些 API,比如 Kaggle API,您可能需要指定一个用户名和密钥,或者作为环境变量,或者在一个 JSON 文件中。您选择的 API 将在这方面为您提供指导。NCBI API 没有这样的要求。
library('RCurl')
library('jsonlite')
library('XML')search1 = 'deep'
search2 = 'learning'
since = '1' #daysxml_folder = paste('xml_files_', search1, '_', search2, '/', sep = "")
dir.create(file.path(xml_folder), showWarnings = FALSE)#Function to get paper data
get_and_parse = function(id) { data <- getURL(paste("https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&retmode=xml&rettype=abstract&id=", id, sep = ""))
data <- xmlParse(data) return(data)}#Get the new papers
new_papers <- getURL(paste("https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=",
search1,
"+AND+",
search2,
"&reldate=",
since,
"&retmode=json&retmax=10000",
sep=""))new_papers_parsed <- fromJSON(new_papers)
new_paper_ids = new_papers_parsed$esearchresult$idlist
l=length(new_paper_ids)if(l==0) {'Nothing published!'} else { paste('Found', l, 'new articles in the last', since, 'days relating to', search1, 'and', search2) }#Get all the papers and save each one to an XML filei=1
while (i<=l) { data_temp = get_and_parse(new_paper_ids[i])
# saveXML(data_temp, file = paste(xml_folder, new_paper_ids[i], '.xml', sep = ""))
i=i+1}
注意:在上面的代码中,我在搜索最近‘1’天的新论文。当我第一次运行这个脚本时,我运行它来搜索最近的 365 天以获得一年的数据,然后将它更改为 1 天以进行定期更新。
使用搜索词和您选择的日期范围运行 R 脚本
现在我有了 R 脚本,我需要运行它。我这样做与 sudo 脚本文学 _ 更新。R
授权访问存储桶
我现在有一堆与我下载的所有文章相对应的 XML 文件,存储在一个专用文件夹中。现在,我想将它们备份到我创建的存储桶中。首先,我需要给这个实例访问 bucket 的权限。用下面的代码来做这件事,
gcloud 认证登录
这将带你到一组指令。按照它们提供对 bucket 的访问(您需要从浏览器中复制并粘贴代码)。
将 XML 复制到桶中
是时候将 XMLs 复制到桶中了。然而,一次做一个文件是没有意义的。相反,让我们把它们放到一个 tar.gz 文件中并上传。用tar-zcvf literature.tar.gz XML _ files _ deep _ learning创建归档文件(你可能有不同的文件夹名),然后用gsutil CP literature.tar.gz GS://ka ggle _ dataset _ data/(用你的 bucket 名)传输到 bucket。
注意 gsutil 的使用。这是一个从命令行访问 GCP 存储桶的有用工具。点击了解更多。
此时,我们已经准备好使用实例上的数据或桶中的数据来创建 Kaggle 数据集。然而,默认情况下,桶中的数据是不公开的,如果我们想使用 Kaggle 网站来创建它,就需要公开。用gsutil ACL ch-u all users:R GS://ka ggle _ dataset _ data/literature . tar . gz更改权限(相应更改桶名和文件名)。
准备使用 Kaggle API
Kaggle API 允许您与 Kaggle 进行完全交互,并为我们提供更新数据集和内核所需的一切。更多详细信息,请参见此处的。
首先,我们需要安装 Kaggle API,这需要安装 Python 3。用 sudo 来安装 python python-dev python 3 python 3-dev
二、用wgethttps://bootstrap.pypa.io/get-pip.py然后 sudo python get-pip.py 安装 pip
第三,用 sudo pip 安装 Kaggle API 安装 kaggle 。然后,进入你的 Kaggle 账户,点击“创建新的 API 令牌”。下载并打开文件,复制上下文,然后在您的 GCP shell 中键入 nano kaggle.json 。在文件中,粘贴内容,然后保存并关闭文件。最后,用 mkdir 将它移动到所需的文件夹中。kaggle 然后 mv kaggle.json。kaggle/ ,并使用 chmod 600 /home//完成一些权限设置。kaggle/kaggle.json
还有一件事。我后来在使用 kaggle API 时遇到了一个错误,特别是 ImportError:没有名为 ordered_dict 的模块。经过一番搜索,运行下面的代码修复了这个问题…sudo pip install-U requests
从 XML tar 文件创建一个数据集
此时,你有一个选择。如果您希望 Kaggle 进行更新,请从 bucket 中进行。如果您的数据非常大和/或您计划在大部分时间停用实例,则此选项是最佳选择。如果这是你的要求,从 GCP 控制台,转到存储,然后点击你的桶。你应该看到你新上传的 tar.gz 文件和“公共访问”列应设置为“公共”。在单词“Public”旁边,您应该会看到一个链接符号。右键单击并选择复制链接位置(或您选择的浏览器中的等效物)。
接下来,在 Kaggle 中,转到数据集,然后是创建新数据集。给它一个标题,并选择“链接”符号(下面用红色突出显示)。粘贴你的 GCP 桶文件的地址,点击添加远程文件。
一旦数据集被创建,转到设置并选择您选择的更新频率。
对我来说,假设实例在空闲层,我的数据很小,我将使用 API 从实例存储进行更新(注意,Bucket 指令对于备份数据和文件仍然很有用)。要做到这一点,请忘记上面从 Kaggle 网站创建数据集的说明。相反,从 GCP shell 中,首先用 kaggle 数据集 init -p /path/to/dataset 创建一个新的 Kaggle 数据集。这将在相应的目录中创建一个元数据 JSON 文件。转到这个目录,并编辑文件。您将看到 slug 和 title 的默认值。将它们分别更改为您选择的目录名和标题。然后,退出并使用 chmod 777 file_name 更改您将要上传的 tar.gz 文件的权限,然后返回到您的主目录并键入ka ggle datasets create-p/path/to/dataset。
您应该会得到消息您的私有数据集正在被创建。请在… 检查进度。
在我的项目中,
- mkdir 深度学习 _ 文学
- mv literature.tar.gz 深度学习 _ 文学
- kaggle 数据集 init -p 深度学习 _ 文献/
- kaggle 数据集创建-p 深度学习 _ 文献/
接下来,转到 Kaggle 并检查数据集是否已经创建。用你认为合适的标题、副标题、背景图片等来调整它。
如你所愿创建一个内核分析
我们现在有了一个使用 GCP 数据的数据集。此时,只需创建一个内核来分析您希望的数据。在 Kaggle 的内核中(下面的链接),我有一些从 XML 文件中提取关键数据并绘制图表的代码。
自动化流程
如果您选择让 Kaggle 从您的 bucket 更新,那么您需要担心的就是更新 bucket 和您的内核。如果使用 API 从实例存储中更新数据集,也需要处理这个问题。
我的方法是将所有这些放入一个 shell 脚本中,如下所示。这有三个部分。首先,脚本运行获取最新深度学习文章的 R 脚本。然后,它创建一个 tar.gz 文件,并将其复制到 bucket(用于备份或 Kaggle 自动更新)以及实例上的一个文件夹中。它还在 bucket 上设置文件的权限。
接下来,它等待 15s,然后用ka ggle datasets version-p ~/deep _ learning _ literature-m“通过来自 Google Cloud 的 API 更新”来更新数据集。
最后,它等待 60 秒(以允许数据集得到更新),然后使用 kaggle 内核拉 tentotheminus 9/deep-learning-literature-and-GCP-tutorial-m进行内核更新,然后 kaggle 内核推(更改文件夹、存储桶、数据集和内核的名称以匹配您的名称)。
这是完整的脚本。用 nano update_kaggle.sh 或类似的创建一个合适的文件。
#!/usr/bin/env bashsudo Rscript literature_update.R
tar -zcvf literature.tar.gz xml_files_deep_learning
gsutil cp literature.tar.gz gs://kaggle_dataset_data/
gsutil acl ch -u AllUsers:R gs://kaggle_dataset_data/literature.tar.gz
cp literature.tar.gz deep_learning_literature/ sleep 15skaggle datasets version -p ~/deep_learning_literature -m "Updated via API from Google Cloud"sleep 60skaggle kernels pull tentotheminus9/deep-learning-literature-and-gcp-tutorial -m
kaggle kernels push
好了,现在是最后一步。我需要告诉我的实例定期触发上面的脚本。首先,用chmod+x literature _ bucket . sh(或者随便你的脚本叫什么)使脚本可执行。然后,我们使用 cron 来设置计时(cron 是 Linux 中调度作业的工具)。
通过键入 EDITOR="nano" crontab -e 创建一个 cron 作业。在打开的文件中,以分钟、小时和天的格式设置计时。可能需要一段时间才能搞清楚,所以我推荐这个在线工具来帮忙。
下面是我的 cron 文件。开始时有一些设置,然后是每天早上 7 点触发我的 shell 脚本的命令,
#!/usr/bin/env bashSHELL=/bin/sh
PATH=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/tentotheminus9/0 7 * * * 1-literature_bucket_update.sh
当然,您可以(也应该)首先测试您的脚本。用做这个。/update_kaggle.sh (或者随便你怎么称呼)。
仅此而已。一切正常,每天早上下载新论文的细节,备份数据,更新 Kaggle 数据集,然后相应地更新内核。
未来的改进
根据 Rachael Tatman 的第五本笔记本,第一个可能改进的地方是错误检查。我一直在研究 XML 验证,但是还没有完全理解。到目前为止,NCBI XML 文件看起来设置得很好,我还没有遇到任何错误。
第二个方面是不仅安排 GCP 上脚本的触发,而且安排实例的加速和减速,每天都有一个实例启动脚本重新安装所有内容。从我目前所读到的来看,这种调度实现起来有点棘手,但我会看看将来能做些什么。这当然会为更大规模的资源节省很多钱。
内核
看完整的 Kaggle 内核这里。第一部分是这篇文章的重复,第二部分展示了数据集的一些可视化。例如,下面是最常见的深度学习论文作者的细分…
希望这篇帖子有用。谢谢!
神经网络背后的数学
原文:https://towardsdatascience.com/deep-learning-neural-network-and-python-part-1-3-4bbc64c106d6?source=collection_archive---------32-----------------------
Python 开发者进一步挖掘人工智能和深度学习背后的科学的完整指南
理解人工神经网络并将其应用于实际案例的完整文章。本指南可用作数据科学面试的准备。
Photo by Nastya Dulhiier on Unsplash
开始前的一些要求和信息:
- 对数学和统计学有很好的理解会更好。
- 对于初学者来说,阅读理解的实时性可以达到 20 到 25 分钟。
- 如果需要,在文章的末尾有一个词汇表。
祝你阅读愉快…
神经网络是目前非常流行的机器学习领域……从语音识别到图像搜索,通过自动驾驶汽车和 AlphaGo,最近人工智能的成功,其中许多都依赖于人工神经网络,更为人所知的是深度学习的神秘名称。
本文将分为三个部分。第一部分将从数学和统计学的角度来阐述神经网络的意义。
下一个是使用 TensorFlow 包创建神经网络的操作模式,以轻松处理图像检测的基本情况。最后一个将是使用深度学习和神经网络解决一个金融案例并预测市场变化的例子。
简单回顾一下…
回到 50 年代,人工神经网络的历史和像弗兰克·罗森布拉特这样的心理学家专注于理解人类大脑。最初,它们被设计成对信息处理进行数学建模,类似于在哺乳动物皮层中发现的生物神经网络。今天,他们的自然现实主义是无关紧要的,相反,他们在模拟复杂和非线性关系方面的有效性使他们取得了成功。
Neuron description — Source: “Anatomy and Physiology” by the US National Cancer Institute’s Surveillance, Epidemiology and End Results (SEER) Program. Image free to use & share under Creative Commons licence.
大多数情况下,神经网络只不过是一种建立参数模型的方法,其决策函数是显式的。与线性回归等其他参数算法不同,它们可以轻松创建复杂的非线性模型。
感知器的架构
让我们平稳地开始,感知器,这种由单层组成的神经网络,是由前面引用的罗森布拉特发明的。
感知器由第一层单元(或神经元)组成,允许用户“读取”数据:每个单元对应一个输入变量。我们可以添加一个始终使能的偏置单元(始终传输 1)。这些单元被连接到单个输出单元,该输出单元接收连接到它的单元的总和,对于 p 个变量 x1,x2,…,xp,该输出单元由连接权重决定;输出单元接收初始权重(w0)和权重之和(w1 至 wp)乘以它们的变量(x1 至 xp)。然后,输出单元将激活功能应用于该事件。
感知器通过由下式定义的决策函数 f 来预测:
该函数具有显式形式;它确实是一个参数模型。
Image by Author
必须使用哪个激活功能?
在回归的情况下,没有必要转换作为输入接收的加权和。激活函数是身份函数;它归还了它全部被分享的东西。
在二元分类的情况下,用户可以使用这种类型的阈值函数:
与逻辑回归的情况一样,我们也可以使用 sigmoid 函数来预测属于正类的概率:
在多层分类的情况下,用户将不得不改变感知器的架构。它将使用尽可能多的类,而不是使用单一的输出单元。这些单元中的每一个都将连接到所有的输入设备。因此,剩余的将是 k. (p + 1)个连接权重,其中 k 是类的数量。
然后可用作激活功能 Softmax 。这是 sigmoid 方程的推广,也可以写成:
如果类 k 的输出比其他类足够重要,则其激活将接近 1(而激活其他类将接近 0)。我们认为这是一种类似于支持向量机算法的工作方式,这将使训练更容易理解。
现在让我们来看看如何训练一个感知器:)
训练感知器
首先想到的问题是:如何确定连接权重?
为了训练一个感知器,我们将寻求最小化训练数据集的预测误差。我们可以明确地做到这一点,就像线性回归的最小二乘法一样。
神经网络应该是灵活的,这意味着,它们根据接收到的信号不断适应。所以,让我们假设我们的 n 个观察值 x(1),x(2)…,x(n)不是同时被观察到的,而是依次被观察到的。
因此,神经网络是通过称为在线学习的算法来训练的,这与我们迄今为止看到的通过批量学习来训练的模型相反。一个中间的解决方案是考虑逐步执行观察,称为小批量学习。
根据前面的说法,我们可以假设感知器的训练是一个迭代过程。在每次观察之后,用户将调整连接的权重(w1 到 wp ),以减少此时(T0)感知器的预测误差。为了解决这个问题,我们将使用梯度算法:梯度为我们提供函数(在我们的例子中,误差函数)更大变化的方向。为了找到最小值,用户必须向梯度的相反方向移动。(当函数局部最小化时,其梯度为 0。)
Image by Authors
用户将开始随机选择连接权重的初始值(w0(0) 0,w1(0)到 wp(0))。然后,在每次观察(x(i),y(i))之后,用户将对每个权重应用出现在图上的以下更新规则。
我们可以对数据集进行多次迭代。通常,我们选择迭代,或者直到算法收敛(梯度足够接近 0),或者更常见的是,迭代固定次数。
η超参数是神经网络的一个因子,叫做学习率。
一些经验法则:
如果η很大,我们就离最佳值越来越远。如果这已经接近最优值,我们可能会超过我们的目标,wj (t + 1)会超过它的最优值。算法可能会发散,这意味着远离最优解。
否则,如果 wj(t)远离其最优值且η较低;该算法将需要大量的时间来收敛。
所以,选择学习的速度很关键。
如何定义误差函数?
在回归的情况下,我们将选择平方误差(作为线性回归)。误差函数定义如下:
在分类的情况下,我们将选择交叉熵。在二进制情况下,交叉熵由下式定义:
When y = 0, the cross-entropy is even higher than f (x) is close to 1. Conversely, when y = 1, the cross-entropy is more significant as the prediction is close to 0.
交叉熵比平方误差方法更难区分,但是在一些计算之后,我们可以确定连接权重更新规则可以简化为:
对于交叉熵的多类版本也是如此。
深度学习来了
感知器本质上是一个线性模型。他的建模能力必然是有限的,这是 1970 年初科学界某种觉醒的根源。在 1969 年关于这个主题的一本著名的书中,数学家和教育家西蒙·派珀特和认知科学家马文·明斯基甚至提到他们的直觉,扩展多层感知机是无用的……历史会伤害他们的架构!
如何创建这样的架构?
我们将在输入层和输出层之间创建一个隐藏层(见上图)。一层中的每个神经元都与其上一层的所有神经元相连。我们称之为多层感知器或“MLP”。
让我们以一个只有一个隐藏层的感知器为例。隐藏层的神经元数 h 的输出 zh 是通过将神经元的激活函数应用于输入的线性组合而获得的:
然后通过将输出神经元的激活函数应用于隐藏层输出的线性组合来接收输出(我知道这听起来很奇怪):
假设我们使用逻辑函数σ : u ↦ 1/(1+e-u)作为所有神经元的激活函数,那么:
我们都可以断定它是一个参数模型(我们可以把决策函数显式地写成输入变量的函数),但它根本不是线性的!
在这些层中,这个参数模型比隐藏层和神经元有更多的设置(连接权重)。我们包含的参数越多,观察所需的时间就越长,以避免过度训练,深度神经网络通常需要大量数据来提高模型精度。
Multi-Layer Perceptron with one hidden layer.
为了提高效率,我们经常使用激活函数、中间层函数。双曲正切函数将输入信号的线性组合转换为-1 和 1 之间的数字,而不是 0 和 1 之间的数字。
可以设计各种类型的架构,这只是一个例子。在下面的例子中,所有的连接都是从较低层到较高层,但事实并非如此。这种没有到下层的反馈回路的概念被称为前馈架构。
通用逼近定理
Cybenko 在 1989 年的一个结果(由 Hornik 1991 改进)告诉我们,定义在ℝ上的每一个连续函数 f 可以由单个隐层形成的神经网络以任意精度逼近(如果在该层中使用足够数量的神经元)。
这是一个非常令人鼓舞的结果:我们现在可以对任何函数建模了!然而,这一结果要通过实践来调节:在许多情况下,这个隐藏层中所需的神经元数量是巨大的,这使得具有一个隐藏层的神经网络无效。
解决方案是将隐藏层堆叠起来,创建现在所谓的深度神经网络。这就是深度学习露脸了!
可以通过假设每个隐藏层的输出是表示数据的另一种方式来解释多层神经网络。多层神经网络的优势在于学习“良好”表示的能力。诸如最后隐藏层和输出之间的线性模型(感知器)的表示可能是有效的。
反向传播
至于感知器,我们将使用基于梯度的迭代算法。出于计算目的,我们将使用反向传播的思想,该思想在 20 世纪 60 年代首次提出(在神经网络领域之外),并由 Rumelhart、Hinton 和 Williams 1986 在 connectionist 中推广。
这个概念是通过链式法则定理来划分误差:
在位于隐藏层的网络中,基于权重 whj 的误差 E 的偏导数可以写成:
最后两项很容易计算,因为逻辑函数σ的导数是 u↦σ(u)(1-σ(u))u':
因此,可以通过求解误差相对于决策函数的偏导数和输出(在该示例中为单层中的 f 或 z)相对于先前层(在该示例中为 x 或 z)的偏导数来计算误差相对于下层权重的偏导数。
因此,更新权重可以通过交替前向阶段(或上行链路)和后向阶段(或下行链路)来完成,在前向阶段中,中间层的输出被更新,在后向阶段中,相对于层的权重的误差梯度可以根据相对于上层的权重的误差梯度来计算。更新权重是在下降阶段的时候(在已经计算了必要的梯度之后)。
MLP 面临的主要挑战
反向传播算法允许学习多层神经网络,对于多层神经网络,不知道显式地优化模型参数。不幸的是,这种算法有几个限制,我们必须小心处理。这就是神经网络在 2006 年重新流行的原因,当时 Hinton 工作,并结合现代计算机的计算能力,帮助克服了一些困难。它目前仍是不断发展的领域!
小心局部最小值
不幸的是,在多层神经元网络中使用的误差函数的导数通常条件较差。这意味着,如果我们稍微扰乱一下算法的初始条件,结果就会不同。实际上,它表明误差函数比预期的要复杂一些。
梯度等于零并不意味着最优!
因此,多层神经网络的误差函数允许大量的局部极小值,也就是说,在其邻域内是最优的点。这些点位于井中。这些点不是全局最小值,但是梯度算法可以在这样的区域中保持“停滞”。
The gradient algorithm can get stuck in the right well, and only detect the local minimum (green) rather than the global minimum (orange). Image by Authors.
连接权重的初始化、变量的标准化、学习速度的选择以及激活函数都会影响多层神经网络找到合理最小值的能力。使用学习算法、小批量或自适应学习速度可以部分克服这个问题。
梯度不稳定性
在多层架构中,当您从网络的输出到输入沿着隐藏层向下时,梯度往往越来越小。这意味着较低层的神经元比较高层的学习慢得多。我们称之为,梯度消失现象。
相反,梯度也可能在较低层中取相当大的值,即所谓的爆炸梯度。
重要的是梯度是不稳定的。这种不稳定性与较低层的梯度是反向传播中较高层的产物这一事实有关。
浸透
饱和是一种现象,当大多数网络逻辑激活神经元的输出为 0 或 1 时(对于双曲正切激活为-1 和+1),即当它们接收输入的信号的加权和过大时(绝对值)。这意味着连接权重太大。此时,输入数据的微小变化对输出几乎不会产生影响,网络可以不学习(或者非常慢)。此外,一个网络经常在过度学习的情况下饱和…
可以用来避免过度训练的策略之一是正规化。是的,至于线性回归!我们甚至使用与正则化岭回归相同的方法:l2 范数连接权重。检查这个标准使得控制重量的绝对值成为可能,避免加权预激活量过大。在神经网络的世界中,这种技术被称为权重衰减。
第一部分概述。
感知器基于线性变量组合制作参数学习模型。
感知器产生二元分类(激活函数是逻辑函数)或多类分类(激活函数是 softmax 函数)的学习回归模型(激活函数是身份)。
感知器通过梯度算法对其权重进行迭代更新来驱动。相同的权重更新规则适用于回归、二元分类或多类分类的情况。
在多层神经网络(前馈)中堆叠感知器允许模拟任意复杂的函数。这就是赋予深度神经网络预测能力目前使他们成功的原因。
这些网络的驱动受到反向传播的影响。警告,这个算法不一定收敛,也不一定到最优解!
参数(即连接权重)越多,在没有过度学习风险的情况下,数据学习这些参数的值所需的时间就越长。
除了这里介绍的神经网络架构,还有许多其他的神经网络架构,用于建模特定类型的数据(图像、声音、时间相关性……)。
词汇表
激活函数:在神经网络中,激活函数负责将来自节点的总加权输入转换为该输入的节点激活或输出。
感知器:在机器学习中,感知器是一种用于二进制分类器监督学习的算法。
变量:变量是一个在数学问题或实验中可能发生变化的量。通常,我们用一个字母代表一个变量。字母 x、y 和 z 是用于变量的通用符号。
预算上的深度学习
原文:https://towardsdatascience.com/deep-learning-on-a-budget-d414c2e89132?source=collection_archive---------15-----------------------
经济高效的模型培训技巧
[12]
介绍
为什么?
有许多文章和课程致力于最新的 ML/AI 研究,旨在训练更大的模型和实现更高的分类精度。这对研究和学术界以及推动人工智能的极限都非常重要。然而,这些并不是真正为从他们的第一个主要人工智能项目开始的贫困学生实践者或寻求为他们的酷革命想法建立 MVP 的有意识的企业家量身定制的。
什么?
在这项工作中,我采用预算方法进行模型训练,并尝试回答以下问题:
完成一个真实世界的人工智能项目的最低实际成本是多少?
我为此选择的问题是图像分类问题。这篇文章记录了我所遵循的过程和从每个步骤中学到的关键预算经验。
摘要
答案大约是 300 美元→ 这是使用云计算训练一个性能良好的计算机视觉模型所需的费用。顺便说一句(或者不是),这也是谷歌给予的信用额度,作为开始使用谷歌云平台(GCP)【1】的奖励。
预算细目如下。最右边的两列列出了 AWS 和 GCP 最适合这个任务的实例。成本是这些列中列出的实例的平均值。目前,这两家云提供商在成本上没有太大的差距。
当然,根据问题的复杂性和数据的大小,所有这些步骤可能会有所不同。但是根据我的经验,对于大多数初始项目或 MVP,总成本的变化不会超过 2 倍。
每个阶段的详细讨论如下。
1 >数据探索
当处理一个新的数据集和 ML 问题时,首先要做的是理解数据,或者用 A. Karpathy 的话说——“与数据融为一体。”【2】
在这个阶段,从业者做的事情有很大的差异,但是有一些共同的组成部分:
A >理解输入格式,开发一些管道来处理数据。我发现,在处理新的数据集时,这一步通常比计划的要花更多的时间。然而,如果做得好,这将在整个项目生命周期中节省大量的时间和精力。
B > 看着每一类的一些随机图像而看着我们真的试图在心里回答这样的问题:CNN 可以用什么特征来区分输出类?这些特征的规模有多大?灯光的变化有多大?对象在图像中的居中程度如何?—这些问题的答案将决定我们的预处理流程和模型架构。
C > 掌握训练样本跨类分布。这将告诉我们我们的训练数据有多倾斜或平衡。如果数据是有偏差的,正如在任何真实世界的应用程序中经常出现的情况,我们将不得不在训练/测试过程中采取适当的步骤。
预算技巧
这个阶段可能会很耗时,并且会涉及一些脚本/笔记预订工作。此外,这些步骤通常不会从 GPU 或多核 CPU 中受益。根据预算,为此阶段选择一个轻量级云实例。我试图模仿我的 macbook 配置——2 到 4 个英特尔酷睿处理器和几百 GB 的固态硬盘。
汇总表中列出的 AWS/GCP 的示例配置的价格在 0.10 美元/小时到 0.20 美元/小时之间,对于类似的实例类型,GCP 比 AWS 略具成本效益。每小时约 0.10 美元,一天的使用费用约为 1 美元。这是项目中使用的最便宜的实例。在这里做最大量的开发。
2 >型号选择
该过程的第二步是迁移学习,即找到文献中最相关的简历论文,并尝试根据手头的任务调整其网络架构。
用于对象分类的网络架构有数百种,arXiv【3】上每月还会增加一些。在 ImageNet 上,人们很容易被诱惑使用吹捧最佳准确性的最新模型。然而,在预算有限的情况下,这可能不是最好的主意。或者别的什么。
在下图中(借用并简化自【4】),一些众所周知的模型的分类准确性与其复杂性相对照。FLOPS 在这里代表浮点运算的数量,表示模型的复杂性。
与复杂度较低的模型相比,更复杂的模型需要更长的训练时间。图中最右边的模型通常需要几周时间在一个 GPU 实例上训练,而左边的模型可以在几天内训练完成。
预算技巧
在任何探索性项目中,都会有相当多的迭代来找出正确的超参数并微调数据预处理管道。因此,非常希望有一个可以在几个小时内训练和验证的模型。
当您浏览文献时,您可能会注意到大多数网络体系结构都有几种不同程度的复杂性和性能。在做预算的时候,选择这些架构中最简单的一种。
对于图像分类问题,我的 goto 网络架构是
1 >盗梦空间-第二版
2> ResNet-50
这两种架构在性能和复杂性之间提供了很好的平衡。此外,它们是非常受欢迎的模型,在所有 DL 框架中都有很好的本地实现,比如 TF 和 PyTorch。此外,有大量关于他们的教程和博客可以帮助快速入门。
3 >超参数调谐
在处理预算时,快速选择正确的超参数集并减少迭代次数至关重要。以下是需要重点关注的三大超参数:
A >小批量:小批量应该足够大,以保持 GPU 充分利用,但不能更大。
B >学习率:选择最佳的学习率通常是一个有用的练习。然而,在预算有限的情况下进行机器学习变得更加重要。非常低的学习率会浪费宝贵的时间和金钱。
C >可训练层数&输入图像大小:在迁移学习期间,通常网络的初始层被冻结,梯度下降仅应用于最后几层的权重。训练时间直接取决于未冻结重量的数量。当训练数据集很小时,通常没有取消冻结许多层的选项。然而,当训练数据集很大时,灵活地改变可训练层的数量可以改进训练时间。
今天,大多数网络无需任何修改就可以处理不同大小的图像。这给了我们一种独特的能力,可以在训练的不同阶段修改输入图像的大小。一般来说,我们希望保持图像尺寸较小,以加快处理速度,同时确保分类所需的特征清晰可辨。
3 >马拉松训练
GPU 是训练 CNN 的唯一明智的方法。所有云服务都提供了一系列 GPU 实例选项。这些实例因 GPU 的数量和每个 GPU 的容量而异。找出正确的 GPU 实例是影响项目时间和预算的最关键决策之一。
在这篇文章中,只讨论了单个 GPU 实例——可能会在另一篇文章中讨论多个 GPU 实例。令人惊讶的是,没有一家云提供商公布他们各种 GPU 实例的性能比较数据。我找到的最好的参考资料来自斯坦福的一个叫斯坦福黎明的小组。【5】
Training Time and Cost Comparison [4]
从上面可以看出,ResNet164 在单个实例 K80 GPU (K80 是 AWS 和 GCP 上最便宜的 GPU 实例)上训练需要大约 10 个小时,运行完整模型的成本大约为 10 美元。为了调整大多数超参数,我们可能会运行大约一半的时间。
给定与 CIFAR10 相同大小的问题,在 K80 实例上,大多数实验应该在 5–10 小时内完成。
预算提示
在这种成本结构下,我们应该能够以 20 X 10 美元= 200 美元的成本运行大约 20 个完整的实验。在实践中,我们可能会运行 20 个持续时间很短的实验——可能是 1-10 个时期,以及大约 10 -15 个持续时间更长的实验。
请注意,这是最佳情况时间。在实践中,会有很多时候 GPU 处于空闲状态,会有修改代码或者我们正在绘制结果或者调试模型的时候。这应该会给流程增加大约 20%的开销。
知道什么时候停下来
这是大多数深度学习课程经常忽略的话题。每个人都会告诉深度神经网络需要很长时间来训练,这是真的。然而,知道在培训过程中会发生什么是很好的。以下是来自 4 个不同来源的 ResNet 的一些变体的训练曲线。
Top Left: Original ResNet paper from Microsoft Research [8] .Top Right: Facebook Research implementation of ResNeXt in Torch [9]. Bottom Left: Google Brain paper from ICLR 2018 in which increasingly bigger batch sizes are used [10]. Bottom right: Training Benchmarks for DNNs maintained by University of Toronto and MSR [11].
一个令人惊讶的观察结果是,所有上述训练曲线都精确地显示了两个肘或准确性的大跳跃。还要注意,上面的两条训练曲线是在 CIFAR10 数据集上,而另外两条是在 ImageNet1K 数据集上。此外,请注意,性能跳跃通常发生在网络似乎已经饱和并且在 20–30 个时期内没有学到任何东西的稳定期之后!
预算技巧
漫长的训练时间和学习曲线的阶跃性质导致了在预算上迭代模型时的难题。解决这个问题的关键是(此处未证实的)假设,即在最初几个时期表现良好的超参数似乎在更高的时期也表现良好。这意味着,对于超参数调优,我们可以将自己限制在少数几个时期,比如 10-20 个。当我们最终确定超参数时,我们可以训练大量的纪元(100 -200)。
关于存储的一个说明
AWS 和 GCP 上有许多存储选项。AWS 免费提供 30GB 的 EBS 和 5GB 的 EFS 存储。额外存储的价格为 0.1 美元/GB 月至 0.3 美元/GB 月。GCP 将固态硬盘的价格定为每月 0.17 美元。对于大多数初始应用,几百 GB 的存储应该足够了。
如果我们使用不同的实例进行数据探索和建模,则有可能在这些阶段使用一个公共的 SSD 卷。详情请参见【11】。
关键要点
对于任何在云中启动真实世界人工智能项目的人来说,基础设施的成本应该大致在几百美元的范围内。有助于提高效率的关键因素包括:
- 使用成本较低的实例进行数据探索和管道开发。
- 选择牺牲一点点性能来显著改善训练时间的型号。
- 在试验超参数时,在几个时期后停止训练。
- 当训练饱和时,知道在训练时从模型中期望什么,以便更好地估计。
参考
[1]谷歌云平台,https://cloud.google.com/free/
[2]A .卡帕西,一种训练神经网络的方法,【http://karpathy.github.io/2019/04/25/recipe/】T2。
[3]康乃尔大学,ArXiv,【https://arxiv.org/
[4] M. Tan,Q.V. Le,EfficientNet:重新思考卷积神经网络的模型缩放, ICML 2019 。
[5]斯坦福道恩,https://DAWN . cs . Stanford . edu/benchmark/v1/cifar 10/train . html
[6] AWS 定价https://aws.amazon.com/ec2/pricing/on-demand/
[7]https://cloud.google.com/compute/vm-instance-pricing GCP 定价
[8]何国光,张,任,孙,深度残差学习在图像识别中的应用, CVPR 2016
[9]谢,吉希克,多拉尔,涂,何,深度神经网络的聚合残差变换, CVPR 2017
[10] S.L. Smith,P.J. Kindermans,C. Ying,Q.V. Le,不要衰减学习率,增加批量, ICLR 2018
[11]https://n2ws . com/blog/how-to-guides/connect-AWS-EBS-volume-another-instance
[12] 1820796 ,形象没钱, Pixabay
对古代 DNA 的深度学习
原文:https://towardsdatascience.com/deep-learning-on-ancient-dna-df042dc3c73d?source=collection_archive---------3-----------------------
生命科学的深度学习
用深度学习重构人类的过去
Image source
远古 DNA 太迷人了!随着目前在下一代测序(NGS) 方面的进展,我们可以从古代骨骼中提取 DNA,对其进行测序,通过各种类型的统计和群体遗传学分析了解过去的很多事情。
然而,现代污染是古代 DNA 研究领域的一个大问题。古遗传学的创始人斯万特·帕博(Svante Pébo)在他的著名著作中承认已经对大部分现代 DNA(可能是他自己的)进行了测序,这部著作是关于一具埃及木乃伊的 DNA,从而产生了这个领域。事实上,只看现代和古代的序列,你永远也猜不到哪一个来自过去。因此这方面的研究人员使用先进的统计分析如 脱氨 模式推断,其中 mapDamage 工具非常得心应手。然而,脱氨基分析的问题在于,它是基于对数以千计的比对序列进行平均的,因此,只有当你有一个深度测序的(需要大量古老的 DNA)样本和一个参考基因组,才能将序列与并不总是可用的基因组进行比对。
这正是我们可以利用机器和深度学习的力量来检测古代和现代序列中典型的 DNA 基序的地方。
基因组的深度学习
由于 DNA 序列本质上是一个“生物文本”,它可以使用来自自然语言处理或时间序列数据分析的方法进行分析。人工神经网络(ann)在这两个领域都得到了广泛的应用,在基因组学方面也表现出了最先进的性能。例如,卷积神经网络(CNN)是功能基因组学的工作马,参见 Argenmueller 等人的优秀综述,分子系统生物学(2016) 12,878 ,其中它们以高精度检测转录因子结合位点和剪接位点。对于用于基因组学的 CNN 的实际实施,我推荐来自邹等人Nature Genetics51,pages 12–18(2019)的精彩的“基因组学中深度学习的初级读本”。论文中的下图描述了基因组学中典型的深度学习工作流程。
CNN for Genomics from Zou et al. Nature Genetics 51, pages12–18 (2019)
在这里,我展示了如何构建一个基于卷积神经网络(CNN)的分类器,用于在不映射到参考基因组的情况下,对 DNA 序列的古代状态进行逐序列预测。但是让我们先来看看古代的 DNA 序列。****
查看古代 DNA 序列
出于演示的目的,我将使用尼安德特人基因组的草案,这是早在 2010 年的低覆盖率测序工作。该文件是 DNA 序列与人类基因组 hg18 的比对(bam-file ),但它不一定是比对,我们同样可以使用原始序列(fastq-file)。我们可以使用方便的 pysam 模块读取 Python 中的序列,并绘制出序列长度的分布。
很明显,DNA 序列长度的范围很广,从大约 20 个核苷酸(nt)到 140 个 nt 长的序列(用生物信息学术语来说)。这是一个已知的事实,它告诉我们古老的 DNA 被降解,即随着时间的推移,它被分解成小片段。因此,一个序列的长度对于推断它是否是古代的非常有用,越短,它是古代的可能性就越高。然而,在这次分析中,我特别感兴趣的是古老的 DNA 基序,不管序列有多长。因此,我将对等长的现代和古代序列进行分析,并将序列长度信息作为令人愉快的奖励,除了古代模式信息之外,每个人都可以使用它。由于我将使用现代法国 DNA 样本,该样本在 2010 年被测序,读取长度等于 76 nt,我将只选择 76 nt 长的尼安德特人序列,然后选择等量的现代序列来训练我的 CNN。
总的来说,我们有将近 50 万次阅读,其中 50%是古代的。为简单起见,我只选择了前 10 条染色体的读数。与来自 canonical MNIST 和 CIFAR10 机器学习数据集的大约 60 000 个例子相比,这个数据量确实很大,这些数据集广泛用于使用 CNN 进行图像识别。
为 CNN 准备基因组数据
接下来,我们将执行所有一维 CNN 步骤的标准,如序列的一键编码,并将数据分成训练和测试子集。这里我将遵循来自邹等人自然遗传学 51 第 12–18 页(2019) 的协议:
现在运行 CNN 的一切都准备好了,让我们开始吧!
构建并运行 1D CNN 分类器
最后,是时候开始训练一个简单的二元(古代与非古代)1D CNN 分类器了。我将创建一个简单的单块 VGG 式架构,它有两个卷积层,后跟一个 Max 池层。我还将应用小 L1 规范权重正规化,以防止过度拟合。
VGG-like architecture of 1D CNN classifier
训练是在我的 4 核笔记本电脑上对大约 300,00 0 个古代和现代序列进行的,耗时大约 5 个小时。让我们来看看损耗和精度曲线是如何表现的:
****
该模型明显过度拟合,但在验证数据集(约 100 000 个序列)上仍达到令人印象深刻的 84%的准确度。验证曲线的振荡行为对于 L1 范数正则化是典型的。为了使它更稳定,辍学是更可取的,我们也可以增加批量大小或降低学习率。现在让我们对具有大约 133 000 个序列的维持测试数据集执行模型的最终评估:
模型的最终评估再次显示了 84%的准确率的古状态预测。混淆矩阵证实了这个数字。CNN 的解读呢?显著性图是一种展示 CNN 特征重要性的优雅方法,即哪些核苷酸对于预测每个序列的古代状态最具信息性:
我们清楚地看到古代与非古代的信号似乎来自序列的末端。这很有意义,因为众所周知,古代序列的末端暴露于脱氨基作用,从而导致与所有其他取代的均匀分布频率的零假设相比,读数末端 C/T 和 G/A 多态性的频率增加。这就是 mapDamage 捕捉到的。然而,与 mapDamage 相反,我们能够检测到这种隐藏的脱氨基模式,而无需将古代序列与参考基因组进行比较。此外,我们现在有一个模型,可以预测每次读取的“古代或非古代”,而 mapDamage 通过对数千次读取进行平均来使用统计推断。
通常,提取大量古代 DNA 是非常困难的,所以每次读取都很重要。换句话说,我们无法计算大量读取的统计数据,但我们希望每个有价值的读取都有一个古老的状态。此外,对古代微生物组(源于古代微生物而非人类/动物宿主的读数)的分析经常会发现 古代病毒 ,它们通常具有十几个与非常短的病毒基因组对齐的读数。在这种情况下,由于缺乏统计能力,使用 mapDamage 进行脱氨分析极其困难。
摘要
在这里我展示了深度学习对于古代 DNA 研究领域的重要性。我展示了如何创建一个简单的卷积神经网络(CNN)分类器,在没有参考基因组的情况下,对每个 DNA 序列的古代和非古代状态进行分类。我希望你会发现这篇文章很有用,并受到启发,为令人兴奋的古代 DNA 研究领域开发深度学习。在 twitter @NikolayOskolkov 上关注我,并在我的 github 上查看完整的 Jupyter 笔记本。
PyTorch 在数据帧上的深度学习
原文:https://towardsdatascience.com/deep-learning-on-dataframes-with-pytorch-66b21be54ef6?source=collection_archive---------9-----------------------
这篇文章的目标是提出一个框架,可以让你使用 PyTorch 和 Pandas 在任何数据框架上进行深度学习预测。通过任何数据帧,我的意思是:分类特征、连续特征、日期时间特征、回归、二进制分类或多分类的任何组合。
我可能会涉及到幕后发生的一些技术问题,但大多数情况下,这只是一个框架讨论,而不是技术讨论。如果你想进一步挖掘,我建议在深度学习中开设 fast.ai 课程——如果你只是想在不看引擎盖的情况下进行预测,fast.ai 库是一个很好的地方,可以用很少的开发时间快速有效地运行这些模型。
**import** pandas **as** pd
**import** numpy **as** np
**import** re
**from** pandas.api.types **import** is_string_dtype, is_numeric_dtype
**import** warnings
**from** pdb **import** set_trace**from** torch **import** nn, optim, as_tensor
**from** torch.utils.data **import** Dataset, DataLoader
**import** torch.nn.functional **as** F
**from** torch.nn.init **import** ***import** sklearn
**from** sklearn_pandas **import** DataFrameMapper
**from** sklearn.preprocessing **import** LabelEncoder, Imputer, StandardScaler
我们将只使用一个虚构的数据帧,它具有分类特征、连续特征和一个日期时间特征。
rng = pd.date_range('2015-02-24', periods=500, freq='D')
df = pd.DataFrame({'date': rng,
'cont1' : np.random.randn(**len**(rng)),
'cat1': [np.random.choice([
'cat','dog','mouse','cow'])
**for** _ **in** **range**(**len**(rng))],
'cont2' : 0.5 * np.random.randn(**len**(rng))+5,
'cat2': [np.random.choice([
'laundry','trash','mop','sweep'])
**for** _ **in** **range**(**len**(rng))],
'targ' : np.random.randint(low=1, high=10,
size=**len**(rng))})
Sample dataframe
我只是假设我们想要使用所有的数据进行训练,然后预测数据集的最后一天,并检查我们做得如何。对于您的情况,这可能是预测上一周、上一月、上一年的数据,但这里我们将只使用最后一天的数据。
max_date = max(df.date).strftime(format='%Y-%m-%d')
test_human_readable = df.loc[df.date ==
pd.to_datetime(max_date,
format='%Y-%m-%d'),:].copy()
我将数据帧(只有一行数据)称为test_human_readable
,因为我们将对数据集进行一些转换,这将使人眼几乎无法理解,所以我喜欢现在提取我的测试集,稍后当我预测时,我会将预测附加到该数据帧,我实际上可以看到所有的特征,因为它们是从开始+预测和实际的。
现在我们将为数据的预处理建立一些帮助函数。
**def** add_datepart(df, fldname, drop=**True**, time=**False**, errors="raise"):
"Create many new columns based on datetime column."
fld = df[fldname]
fld_dtype = fld.dtype
**if** isinstance(fld_dtype, pd.core.dtypes.dtypes.DatetimeTZDtype):
fld_dtype = np.datetime64
**if** **not** np.issubdtype(fld_dtype, np.datetime64):
df[fldname] = fld = pd.to_datetime(fld,
infer_datetime_format=**True**, errors=errors)
targ_pre = re.sub('[Dd]ate$', '', fldname)
attr = ['Year', 'Month', 'Week', 'Day', 'Dayofweek','Dayofyear',
'Is_month_end', 'Is_month_start', 'Is_quarter_end',
'Is_quarter_start', 'Is_year_end', 'Is_year_start']
**if** time: attr = attr + ['Hour', 'Minute', 'Second']
**for** n **in** attr: df[targ_pre + n] = getattr(fld.dt, n.lower())
df[targ_pre + 'Elapsed'] = fld.astype(np.int64) // 10 ** 9
**if** drop: df.drop(fldname, axis=1, inplace=**True**)**def** train_cats(df, cat_vars):
# numercalize/categoricalize
**for** name, col **in** df.items():
**if** name **in** cat_vars:
df[name] = col.cat.codes + 1
df = pd.get_dummies(df, dummy_na=**True**)
**return** df**def** scale_vars(df, mapper):
warnings.filterwarnings('ignore',
category=sklearn.exceptions.DataConversionWarning)
**if** mapper **is** **None**:
map_f = [([n],StandardScaler()) **for** n **in** df.columns **if** is_numeric_dtype(df[n])]
mapper = DataFrameMapper(map_f).fit(df)
df[mapper.transformed_names_] = mapper.transform(df)
**return** mapper**def** proc_df(df, cat_vars, cont_vars, y_fld=**None**, do_scale=**False**,
mapper=**None**, na_dict=**None**):
"Preprorocess the train, valid, test sets to numericalize,
fillmissing, and normalize."
ignore_flds=[]
skip_flds=[]
# set the dependent variable name and concatenate the cat and
# cont
dep_var = y_fld
df = df[cat_vars + cont_vars + [dep_var]].copy()
df[dep_var] = df[dep_var].astype(int)
df = df.copy()
ignored_flds = df.loc[:, ignore_flds]
y = df[y_fld].values
# deal with skip fields
skip_flds += [y_fld]
df.drop(skip_flds, axis=1, inplace=**True**)
# initialize the na dictionary
**if** na_dict **is** **None**: na_dict = {}
**else**: na_dict = na_dict.copy()
na_dict_initial = na_dict.copy()
# fill missing
**for** name, col **in** df.items():
**if** is_numeric_dtype(col):
**if** pd.isnull(col).sum():
df[name+'_na'] = pd.isnull(col)
filler = col.median()
df[name] = col.fillna(filler)
na_dict[name] = filler
# keep track of which entries are missing and possibly use them
# in the model
**if** len(na_dict_initial.keys()) > 0:
df.drop([a + '_na' **for** a **in** list(set(na_dict.keys()) -
set(na_dict_initial.keys()))], axis=1, inplace=**True**)
# normalize
**if** do_scale: mapper = scale_vars(df, mapper)
res = [df, y, na_dict]
# keep track of how things were normalized
**if** do_scale: res = res + [mapper]
**return** res
太好了。因此,现在我们希望将新的 datetime 特性添加到我们的数据帧中,规范化连续数据,并对分类特性进行分类(将它们更改为代表其类别的数字)。
add_datepart(df, 'date', drop=**False**)
add_datepart
是一个就地操作,所以现在我们的 dataframe 有更多的列来表示列date
的不同方面。我还没有删除date
列,因为我想很快用它来创建我的训练、有效和测试数据帧。
columns of df
现在让我们定义哪些列是分类的,哪些是连续的。
cat_vars = ['cat1', 'cat2', 'Year', 'Month','Week', 'Day',
'Dayofweek', 'Dayofyear', 'Is_month_end',
'Is_month_start', 'Is_quarter_end', 'Is_quarter_start',
'Is_year_end', 'Is_year_start', 'Elapsed']cont_vars = ['cont1', 'cont2']
我想对我所有的 cat 特性进行分类,但我也想确保它们对我的训练、有效和测试数据帧进行了相同的分类。这意味着,如果在我的训练数据中cow
被映射到2
,我不希望cow
被映射到我的有效或测试数据中的其他数据。所以我现在就做这个操作,然后拆分我的数据集。
**for** v **in** cat_vars: df[v] = df[v].astype('category').cat.as_ordered()
df = train_cats(df, cat_vars)
该模型将使用嵌入来处理分类特征,因此我们需要预先计算嵌入大小,以便稍后在模型中进行初始化。fast.ai 的杰瑞米·霍华德建议使用最小 50 和类基数的一半。
这又是一个应该在将数据集分解成训练、有效、测试之前完成的操作。
**for** v **in** cat_vars: df[v] = df[v].astype('category').cat.as_ordered()
cat_sz = [(c, len(df[c].cat.categories)+1) **for** c **in** cat_vars]
emb_szs = [(c, min(50, (c+1)//2)) **for** _,c **in** cat_sz]
如果您首先分解数据集,然后检查嵌入大小,您可能会得到错误:运行时错误:索引超出范围:试图访问 11 行表中的索引 12。这是因为嵌入大小的计算没有考虑一些偶然被排除在训练数据之外的类别。
train = df.loc[df.date < pd.to_datetime('2016-01-01',
format='%Y-%m-%d'),:].copy()
valid = df.loc[(df.date >= pd.to_datetime('2016-01-01',
format='%Y-%m-%d')) **&**
(df.date < pd.to_datetime(max_date,
format='%Y-%m-%d')),:].copy()
test = df.loc[df.date == pd.to_datetime(max_date,
format='%Y-%m-%d'),:].copy()train = train.drop(columns='date')
valid = valid.drop(columns='date')
test = test.drop(columns='date')
所以我相当随意地选择了我的验证集。这不是一种好的做法,在您的生产环境中,您应该测试不同的集合,并尝试将它们紧密映射到测试集合,但在这种情况下,我只是采用了 2016 年 1 月之后的所有内容。
**for** v **in** cat_vars: train[v] =
train[v].astype('category').cat.as_ordered()
**for** v **in** cont_vars: train[v] = train[v].astype('float32')
**for** v **in** cat_vars: valid[v] =
valid[v].astype('category').cat.as_ordered()
**for** v **in** cont_vars: valid[v] = valid[v].astype('float32')
**for** v **in** cat_vars: test[v] =
test[v].astype('category').cat.as_ordered()
**for** v **in** cont_vars: test[v] = test[v].astype('float32')
我们希望将分类特征与连续特征分开传递给我们的模型,这样猫可以首先通过嵌入,然后通过线性、relu、batchnorm、dropout 以及 conts。
**class** ColumnarDataset(Dataset):
"""Dataset class for column dataset.
Args:
cats (list of str): List of the name of columns contain
categorical variables.
conts (list of str): List of the name of columns which
contain continuous variables.
y (Tensor, optional): Target variables.
is_reg (bool): If the task is regression, set ``True``,
otherwise (classification) ``False``.
is_multi (bool): If the task is multi-label classification,
set ``True``.
"""
**def** __init__(**self**, df, cat_flds, y, is_reg, is_multi):
df_cat = df[cat_flds]
df_cont = df.drop(cat_flds, axis=1)
cats = [c.values for n,c in df_cat.items()]
conts = [c.values for n,c in df_cont.items()]
n = len(cats[0]) **if** cats **else** len(conts[0])
self.cats = np.stack(cats, 1).astype(np.int64)
**if** cats **else** np.zeros((n,1))
self.conts = np.stack(conts, 1).astype(np.float32)
**if** conts **else** np.zeros((n,1))
self.y = np.zeros((n,1)) **if** y **is** **None** **else** y
**if** is_reg: self.y = self.y[:,**None**]
self.is_reg = is_reg
self.is_multi = is_multi **def** __len__(**self**): **return** **len**(self.y) **def** __getitem__(**self**, idx):
**return** [self.cats[idx], self.conts[idx], self.y[idx]]
正如您在这个类中看到的,getitem 正在为那个idx
值检索一个 cats、conts 和 target 的列表。
归一化和预处理每个数据集。
dep_var = 'targ'
df, y, nas, mapper = proc_df(train, cat_vars, cont_vars, dep_var,
do_scale=**True**)
df_val, y_val, nas, mapper = proc_df(valid, cat_vars, cont_vars,
dep_var, do_scale=**True**,
mapper=mapper, na_dict=nas)
df_test, y_test, nas, mapper = proc_df(test, cat_vars, cont_vars,
dep_var, do_scale=**True**)
初始化每个 dataset 对象并创建 dataloader 对象。
trn_ds = ColumnarDataset(df, cat_vars, y,is_reg=**True**,is_multi=**False**)
val_ds = ColumnarDataset(df_val, cat_vars,
y_val,is_reg=**True**,is_multi=**False**)
test_ds = ColumnarDataset(df_test, cat_vars,
y_test,is_reg=**True**,is_multi=**False**)bs = 64
train_dl = DataLoader(trn_ds, bs, shuffle=**True**)
val_dl = DataLoader(val_ds, bs, shuffle=**False**)
test_dl = DataLoader(test_ds, len(df_test), shuffle=**False**)
定义模型。
**class** MixedInputModel(nn.Module):
"""Model able to handle inputs consisting of both categorical and continuous variables.
Args:
emb_szs (list of int): List of embedding size
n_cont (int): Number of continuous variables in inputs
emb_drop (float): Dropout applied to the output of embedding
out_sz (int): Size of model's output.
szs (list of int): List of hidden variables sizes
drops (list of float): List of dropout applied to hidden
variables
y_range (list of float): Min and max of `y`.
y_range[0] = min, y_range[1] = max.
use_bn (bool): If use BatchNorm, set ``True``
is_reg (bool): If regression, set ``True``
is_multi (bool): If multi-label classification, set ``True``
"""
**def** __init__(**self**, emb_szs, n_cont, emb_drop, out_sz, szs,
drops, y_range=**None**, use_bn=**False**, is_reg=**True**,
is_multi=**False**):
**super**().__init__()
**for** i,(c,s) **in** enumerate(emb_szs): **assert** c > 1,
f"cardinality must be >=2, got emb_szs[{i}]: ({c},{s})"
**if** is_reg==**False** and is_multi==**False**: **assert** out_sz >= 2,
"For classification with out_sz=1, use is_multi=True"
self.embs = nn.ModuleList([nn.Embedding(c, s)
**for** c,s **in** emb_szs])
**for** emb **in** self.embs: emb_init(emb)
n_emb = sum(e.embedding_dim **for** e **in** self.embs)
self.n_emb, self.n_cont=n_emb, n_cont
szs = [n_emb+n_cont] + szs
self.lins = nn.ModuleList([
nn.Linear(szs[i], szs[i+1]) **for** i **in** **range**(**len**(szs)-1)])
self.bns = nn.ModuleList([
nn.BatchNorm1d(sz) **for** sz **in** szs[1:]])
**for** o **in** self.lins: kaiming_normal_(o.weight.data)
self.outp = nn.Linear(szs[-1], out_sz)
kaiming_normal_(self.outp.weight.data) self.emb_drop = nn.Dropout(emb_drop)
self.drops = nn.ModuleList([nn.Dropout(drop)
**for** drop **in** drops])
self.bn = nn.BatchNorm1d(n_cont)
self.use_bn,self.y_range = use_bn,y_range
self.is_reg = is_reg
self.is_multi = is_multi **def** forward(**self**, x_cat, x_cont):
**if** self.n_emb != 0:
x = [e(x_cat[:,i]) **for** i,e **in** enumerate(self.embs)]
x = torch.cat(x, 1)
x = self.emb_drop(x)
**if** self.n_cont != 0:
x2 = self.bn(x_cont)
x = torch.cat([x, x2], 1) **if** self.n_emb != 0 **else** x2
**for** l,d,b **in** zip(self.lins, self.drops, self.bns):
x = F.relu(l(x))
**if** self.use_bn: x = b(x)
x = d(x)
x = self.outp(x)
**if** **not** self.is_reg:
**if** self.is_multi:
x = torch.sigmoid(x)
**else**:
x = F.log_softmax(x, dim=1)
**elif** self.y_range:
x = torch.sigmoid(x)
x = x*(self.y_range[1] - self.y_range[0])
x = x+self.y_range[0]
**return** x**def** emb_init(x):
x = x.weight.data
sc = 2/(x.size(1)+1)
x.uniform_(-sc,sc)
初始化模型。我们正在对targ
列执行回归任务。
model = MixedInputModel(emb_szs,
n_cont=**len**(df.columns)-**len**(cat_vars),
emb_drop = 0.04, out_sz = 1,
szs = [1000,500], drops = [0.001,0.01],
y_range=(0,np.max(y)), use_bn=**True**,
is_reg=**True**, is_multi=**False**)
我们现在准备训练模型。
**def** train_model(model, train_dl, val_dl, n_epochs=1, lr=5e-2):
"Run training loops."
epochs = n_epochs
opt = optim.SGD(model.parameters(), lr=lr)
loss_func = nn.MSELoss()
**try**:
**for** epoch **in** range(epochs):
model.train()
**for** xb1, xb2, yb **in** train_dl:
preds = model(xb1, xb2)
loss = loss_func(preds, yb.float())
loss.backward()
opt.step()
opt.zero_grad()
model.eval()
**with** torch.no_grad():
loss_val = sum(loss_func(model(xv1, xv2),
yv.float())
**for** xv1, xv2, yv **in** val_dl)
print(epoch, loss_val / len(val_dl))
**except** Exception **as** e:
exception = e
**raise**
最后,我们可以通过测试集进行训练和预测。
train_model(model, train_dl, val_dl, n_epochs=500, lr=5e-2)**def** predict_test(model, test_dl):
"Returns predictions over test_df."
model.eval()
preds = [model(xv1, xv2) **for** xv1, xv2, _ **in** test_dl][0]
targs = [yv **for** _, _, yv **in** test_dl][0]
test_human_readable['targ_pred'] = preds.data.detach().numpy()
**return** torch.argmax(preds, dim=1).data.detach().numpy(),
test_human_readablepreds, df = predict_test(model, test_dl)
Test set with prediction
所以,理想情况下,你可以拿着熊猫的任何数据框,运行这段代码,得到一个不错的预测输出。但这有望让您更深入地剖析这个过程,尝试一些建模变化或任何您感兴趣的东西。
玩得开心!
显微成像的深度学习
原文:https://towardsdatascience.com/deep-learning-on-microscopy-imaging-865b521ec47c?source=collection_archive---------6-----------------------
生命科学的深度学习
用深度学习检测好、坏、丑细胞
Image source
这是系列生命科学深度学习的第五篇文章。在之前的帖子中,我展示了如何将深度学习用于古代 DNA 、深度学习用于单细胞生物学 、深度学习用于数据整合和深度学习用于临床诊断。今天我们将讨论深度学习在生命科学中的主要应用之一,即用于显微图像分析的计算机视觉。
自动化 荧光显微镜是生命科学显微镜成像的一匹工作马,可生成数百万张细胞图像。卷积神经网络(CNN)擅长学习成像数据的空间结构,并通过自动特征提取优于传统的机器学习方法。
Conventional vs. Deep Learning workflow from A. Gupta et al., Cytometry 95, 366–380 (2019)
虽然每个图像一个类别的图像分类(也称为猫对狗)目前是一项相当琐碎的任务,但高效的 多标签分类 和 对象检测 是目前正在开发新一代 CNN 的更具挑战性的问题。
这里我将描述如何使用fast-RCNN和Mask-RCNN人工神经网络从人类蛋白质图谱的荧光显微图像上检测细胞类型。
图像与数字数据
谈到图像分析,我通常想知道为什么深度学习优于(与其他机器学习和统计分析相比)** 处理图像而不太成功地应用于数字数据?的确,与各种生物医学下一代测序【NGS】组学数据(基因组学、转录组学、蛋白质组学等。),通常是数字,我并不经常看到神经网络在预测能力方面胜过随机森林,因此我总是建议在深入学习非线性数学之前先从简单的线性模型开始。**
为什么深度学习对图像分析这么好?
是像 Geoffrey Hinton 所说的那样有大量可用的成像数据,还是在像素强度中有一些非线性的东西,而这些是数字数据中没有的?仅仅是数据的空间结构吗?****
你注意到的第一件事是在图像数据上运行深度学习,与在组学数字数据上进行深度学习相比,生活变得更容易。有大量的文献和大量的在线教程可以帮助你。我是杰森·布朗利和阿德里安·罗斯布鲁克的超级粉丝,我去他们的博客,通常能找到我所有问题的答案。相比之下,在组学数值数据上运行深度学习(例如 RNA 测序)你基本上是靠自己。没有那么多人比你更清楚什么网络架构,激活功能,优化器等等。适合你特定的组学数字数据,所以你真的需要做很多实验。
细胞的显微成像
然而,进入显微成像领域,你会发现很多来自社区的支持。一个很好的可用资源是人类蛋白质图谱,其中提供了显示单细胞中蛋白质的定位的数字图像数据。****
Human Protein Atlas (HPA) is a great digital image data resource
通过在线游戏使用公民科学方法对数据进行注释,并在 Kaggle 竞赛中用于多标签图像分类。数据可以从这里下载,它们包括大约 124 000 个训练和大约 47 000 个测试 512x512 PNG 图像,用于 28 个类别,即从 0 到 27 的数字代码,用于表达某种蛋白质的细胞区室。重要的是,由于蛋白质可以在细胞的几个地方同时表达,所以在同一张图像上可以出现多个类别。
观察 HPA 类别的分布,我们可以看到感兴趣的蛋白质最常表达在核质(类别 0)和胞质溶胶(类别 25)中。现在让我们看看 HPA 图像是什么样子的。事实证明,显示 HPA 图像是一项重要的任务,因为它们包含 4 个而不是标准的 3 个 RGB 通道,这些通道突出显示了感兴趣的蛋白质(绿色通道)以及三个细胞标志:微管(红色)、细胞核(蓝色)和内质网(黄色)。在 Python 中合并 4 个通道的一种方法是实现黄色=红色+绿色,并将黄色通道的一半添加到红色通道,另一半添加到绿色通道。
Sample Human Protein Atlas (HPA) images
使用“load_image”功能,我通过合并每个图像 ID 的 4 个通道,生成了一个包含约 31 000 个图像的新训练数据集。
为细胞检测构建注释
现在,在我们学习了如何显示 HPA 图像并合并四个通道之后,是时候使用 fast-RCNN 和 Mask-RCNN 神经网络为细胞类型检测创建注释了。出于演示的目的,我浏览了一些图像,并选择了一些包含在核仁区室(核仁、核仁纤维中心、核斑点、核体)中表达蛋白质的细胞和在核仁区室中没有蛋白质表达迹象的细胞。这样,我的目标是在我的每个训练/测试图像上有 3 个类别(核仁,不是核仁和背景)。接下来,我花了 2 个小时和 LabelImg 一起为 45 HPA 火车图像的每个单元分配边界框和类别标签,另外 5 个图像被保留作为测试数据集,用于进行预测。
Manual annotation of cells with LabelImg
LabelImg 以 xml 格式记录单元格批注,其典型结构如下:
这里可以看到图像的宽度(512 像素)、高度(512 像素)和深度(3 个通道),以及一个坐标由边界框 (xmin,ymin,xmax,ymax) 和标签“核仁”定义的对象。Faster-RCNN 需要一个特殊的逗号分隔(csv)格式的注释文件。为了准备这样一个 csv 文件,我们需要解析每个图像的 xml 注释:
一旦解析了 xml 注释,就差不多完成了,现在已经为训练 fast-RCNN 模型做好了一切准备。
训练更快的 RCNN 用于细胞检测
在这里,我跳过解释如何更快-RCNN 的工作,有大量的文献进入算法。我只提到,fast-RCNN 使用区域建议网络(RPN)** ,为执行实际对象检测的检测器网络生成区域建议。因此,fast-RCNN 网络的损失函数结合了来自回归(用边界框定位细胞)和分类(为每个定位细胞分配类别)任务的贡献。更快-RCNN 可以从 https://github.com/kbardool/keras-frcnn安装。训练更快的 RCNN 模型就像键入:**
这里的“annot.txt”是上一节中创建的注释文件。默认情况下,Faster-RCNN 使用来自 ResNet50 的权重进行迁移学习。在具有 4 个 CPU 内核的我的笔记本电脑上,在具有 322 个带注释的核仁和 306 个非核仁类的 45 幅图像上训练更快的 RCNN每个时期花费了大约 6 个小时,所以我只设法等待了 35 个时期。学习曲线似乎表明分类任务达到饱和,而回归(定位细胞)仍远未达到平稳状态。
要使用 fast-RCNN 对测试集进行预测,我们只需键入:
这里的“test”是包含来自测试数据集的图像的文件夹。让我们展示一个测试图像,以检查该模型在检测核仁中表达蛋白质的细胞(核仁类)和核仁中不表达蛋白质的细胞(非核仁类)方面有多成功:
Original image (left) and the image after Faster-RCNN object detection was applied (right)
这里,左边是原始的测试图像。两个细胞在中间明显含有亮绿色斑点,这些是核仁,由于感兴趣的蛋白质在这些区域显示出强烈的表达,所以它们是可见的,所以这两个细胞应该属于核仁类。其余的细胞似乎没有核仁区域表达的蛋白质,因此它们应该属于非核仁类。右边是由经过训练的 fast-RCNN 模型放置的具有边界框和类别标签的测试图像。这里我们可以看到,模型正确地检测到了在核仁区域具有可见绿色斑点的两个细胞,而第三个边界框似乎是假阳性预测,不清楚模型以高置信度(91%的概率)检测到了什么:边界框包括多个细胞,尽管模型贴上了“核仁”类别标签,但我们没有观察到边界框内具有可见核仁的细胞。
这张图片展示了我对使用fast-RCNN 进行细胞检测的总体印象:它在细胞定位方面并不总是完美的,尽管更多的训练可能会改善它。让我们看看 Mask-RCNN 能否让它变得更好。
用于细胞检测的训练掩模-RCNN
Mask-RCNN(以及 Faster-RCNN)属于人工神经网络的 RCNN 家族,与其他家族,即 YOLO 和 SSD 相比,其以更高的物体检测精度而闻名,我在此不做介绍。除了对象检测,Mask-RCNN 还允许对象分割,但是我们在这里不打算使用它。Mask-RCNN 可以从 https://github.com/matterport/Mask_RCNN 的安装。虽然 Faster-RCNN 非常容易运行(它基本上只需要准备好注释文件),但是 Mask-RCNN 需要更多的编码,所以请在 my github 上查看完整的 Jupyter 笔记本以了解更多细节。在这里,我解释工作流程的关键步骤,它基本上遵循这个优秀的教程。Mask-RCNN 的特点是数据由一个数据集对象处理,该对象用于将数据输入 Mask-RCNN 进行训练和测试。
在这里,我们的目标是对象检测而不是分割,因此我们将把包围盒视为遮罩,所以“load_mask”函数将加载实际上的包围盒坐标。我们可以使用 Mask-RCNN 中方便的“display_instances”函数显示一个随机的带注释的训练图像:
Annotated image prepared for training with Mask-RCNN
现在一切都为训练 Mask-RCNN 模型做好了准备。我们将使用迁移学习,并从 COCO 数据集上的预训练对象检测 Mask-RCNN 模型的权重开始。
训练 Mask-RCNN 比 Faster-RCNN 快得多,在我的 4 个 CPU 内核的笔记本电脑上,一个历元只花了 2 个小时(比 Faster-RCNN 快了 3 倍),在仅仅 5 个历元之后,我就停止了训练,因为测试数据集上的对象检测结果已经非常令人满意。这里为了比较,我呈现了原始测试图像(左)和由训练的 Mask-RCNN 模型放置的图像以及高置信度(超过 70%概率)的边界框和类别标签。
Original image (left) and the image after Mask-RCNN object detection was applied (right)
我们观察到细胞定位的准确性有了惊人的提高,所有的边界框似乎都完美地包围了细胞。一个细胞似乎有一个错误的标签“核仁”,尽管在细胞核内没有观察到明显的绿色斑点。也许这个模型会从更多的训练中受益。总体而言, Mask-RCNN 与更快的 RCNN 相比,在细胞检测方面表现出显著的改进。
这种经过训练的 Mask-RCNN 模型现在可以用于图像的高通量扫描用于特殊细胞形态(在这种特殊情况下,蛋白质在核仁区域表达)而无需视觉检查。
摘要
在这篇文章中,我们了解到自动显微镜** 产生了 大量的数字图像数据,非常适合深度学习分析。检测细胞形态是一项具有挑战性的任务,尽管有大量的文献和模型可用。我们使用来自人类蛋白质图谱(HPA)的多类带注释的图像测试了 fast-RCNN 和 Mask-RCNN 对象检测模型。 Mask-RCNN 在细胞类型检测的质量和速度上都优于 fast-RCNN。**
像往常一样,如果你在生命科学中有特别喜欢的领域,想在深度学习框架中解决,请在评论中告诉我。在 Medium 关注我,在 Twitter @ NikolayOskolkov关注我,在 Linkedin 连接,在我的 github 上查看这篇文章的代码。我计划写下一篇关于进化科学的深度学习的帖子,敬请关注。
基于 FastAi 的多标签文本分类深度学习
原文:https://towardsdatascience.com/deep-learning-on-multi-label-text-classification-with-fastai-d5495d66ed88?source=collection_archive---------16-----------------------
预测与文本数据集关联的多个目标值。
Photo by Murat Onder on Unsplash
多标签分类有多个与数据集相关联的目标值。这里我们是预测每一类的概率,而不是预测单个类。
在这篇文章中,我将解释关于 fastai 的多标签文本分类问题。在这里,我们使用了毒性评论分类挑战来解释 FastAi 如何处理多标签问题。
让我们看看数据
让我们来看看数据的概述,了解每个特性的数据类型,从而了解特性的重要性。
对于这个问题,我们有 6 个标签类,即:6 种不同毒性如下:
- 有毒的
- 严重 _ 有毒
- 猥亵的
- 威胁
- 侮辱
- 身份 _ 仇恨
我们必须创建一个模型来预测每条评论的每种毒性的概率。
加载和分析数据
快速人工智能期望数据作为数据束被加载,然后快速人工智能学习者可以将这些数据用于模型。这里,我们将首先用我们训练数据集创建数据簇。
用特定领域的数据拟合深度学习模型
首先,我们将用不带目标值的训练数据来拟合我们的模型,以便我们的模型更好地了解我们的数据。
使用分类标签重新拟合模型
在这里,我们将用我们的目标值重新拟合我们的模型,并调整我们的模型以获得更准确的结果。
让我们预测目标值,并与原始目标值进行比较。
获得预测
让我们获得预测,并创建提交文件以在 Kaggle 中提交它。
所有的代码
这个任务的所有代码都可以在 Kaggle 内核中找到:
- FastAi 的多标签分类问题
原载于 2019 年 7 月 21 日https://confusedcoders.com。
尼安德特人基因的深度学习
原文:https://towardsdatascience.com/deep-learning-on-neanderthal-genes-ad1478cf37e7?source=collection_archive---------9-----------------------
生命科学的深度学习
利用深度学习检测尼安德特人祖先的区域
Image licence from iStock
这是我的专栏 生命科学深度学习 的第七篇文章,在这里我给出了深度学习如何能够已经应用于计算生物学、遗传学和生物信息学的具体例子。在之前的帖子中,我演示了如何使用深度学习进行古 DNA 、单细胞生物学、组学数据整合、临床诊断和显微成像。今天,我们将深入到令人兴奋的人类进化史中,并了解到直接从【NLP】中借用方法论,并将其应用于人类群体遗传学,以推断现代人类基因组中 尼安德特人基因渗入 的区域。
简史:走出非洲
当现代人类的祖先在大约 5 万- 7 万年前从非洲迁徙出去时,他们遇到了当时居住在欧洲和亚洲的两个古人类群体:T2 人、尼安德特人、T4 人和丹尼索瓦人。我们知道现代人与尼安德特人和丹尼索瓦人杂交,因为有证据表明他们的 DNA 存在于非非洲血统的现代人的基因组中。人类进化史上这些伟大的基因进步之所以成为可能,是因为尼安德特人和丹尼索瓦人的基因组分别在 2010 年和 2012 年被斯万特·帕博小组测序。
有一些人试图推断从尼安德特人和丹尼索瓦人那里继承的 DNA 片段的确切位置。他们利用了各种基因组学资源,如 1000 基因组项目,并计算了非非洲基因组与高质量尼安德特人基因组的局部相似性以及与非洲基因组的差异的不同度量(下图)。
S* / S’ statistics and Conditional Random Field (CRF) were applied to detect Neanderthal introgression
这些相似性度量(汇总统计)尽管是可解释的和有效的,但却导致了信息的丢失,因为它们试图以单个数字捕获一段 DNA,而没有考虑核苷酸本身的有序序列。其他尝试使用隐马尔可夫模型(HMM) 扫描尼安德特人的基因组渗入,这是一个无记忆模型,再次没有考虑沿着 DNA 序列的核苷酸之间的长程相关性。这就是深度学习处理原始基因组序列并利用通过 RNNs / LSTMs 和 CNNs 跨越基因组的核苷酸连接的长期记忆的能力可以带来难以置信的好处的地方。
深度学习对于古代基因组学的潜力
目前,深度学习在进化生物学中基本上被忽略,尽管它在处理基因组数据方面具有巨大的潜力,而基因组数据是当前进化科学和古代 DNA 研究领域的主要数据源之一。最近的尝试利用模拟基因组数据尽管有真实基因组数据的可用性,这些数据通常具有已被充分理解的生物学功能的注释区域。深度学习非常适合研究基因组学和古代基因组学,因为一个基因组实际上是一个大数据。为了实现这一点,只需考虑将 310⁹核苷酸长基因组切割成 1000 个核苷酸的片段,这带来了用于深度学习的 310⁶训练样本,前提是可以为每个 DNA 片段计算出注释(标签)。这是大量的训练数据!
Deep Learning for Genomics from Zou et al. Nature Genetics 51, pages12–18 (2019)
我在之前的帖子中演示了如何用这个想法来区分古代和现代的 DNA 序列。在那里,我使用了 1D 卷积神经网络(CNN)和序列的的一热编码表示。在这里,我将展示另一种方法来表示输入到深度学习中的 DNA 序列。请看下图左图,这就是我们通常所说的文字。然而,这并不是基因组学的人所说的文本。他们所指的文本显示在右边。 DNA 序列是文本!这看起来很无聊,但随着时间的推移,你会开始看清事情的来龙去脉。如果我告诉你我在那里看到一个基因呢?如果我告诉你,我看到一个基因与二型糖尿病(T2D)紧密相连,我们很可能从尼安德特人那里继承了这个基因,会怎么样?****
What people usually mean by text (left), vs. what bioinformaticians mean by text (right), SLC16A11 gene
现在,如果 DNA 序列是一个文本,我们可以将自然语言处理(NLP)的所有工具应用于这样的文本。然而,DNA 文本中的句子在哪里,单词在哪里?如果我们要预测一串 DNA 序列(这串可以被认为是一段文字)是否是从尼安德特人那里继承来的,那么这串 DNA 序列中的一个可以被认为是文字的句子,一个 k-mer (子序列)可以被认为是一个单词。
DNA sequence is a sentence that can be split into k-mers, space-delimited k-mers can be seen as words
一旦我们将 DNA 序列转换成空格分隔的 k-mers /单词,我们就完成了。现在,我们可以转向先进的 NLP 技术,并使用例如简单的 单词袋 模型来比较从尼安德特人继承的序列和枯竭的古代祖先的序列之间的单词/ k-mers 的频率。
为情感分析准备序列
现在让我们演示如何实际使用机器/深度学习和自然语言处理(NLP)来识别现代人类基因组中尼安德特人基因渗入的区域。这里我将公式化以下问题来解决:
给我看一段你的 DNA,我会预测它有多大可能是从尼安德特人那里遗传的
作为训练数据集,我们将使用来自 Vernot 和 Akey 的尼安德特人渗入的候选区域的坐标,Science 2016 使用来自 1000 基因组项目的欧洲人和亚洲人的 S -统计数据确定,数据可以从这里下载https://drive . Google . com/drive/folders/0 B9 PC 7 _ zitmcvwu P6 bwtxc 2 xjvkk。我们使用渐渗单倍型文件ll . callseteur . Mr _ 0.99 . neand _ calls _ by _ hap . bed . merged . by _ chr . bed*并只选择唯一坐标,因此我们最终得到了现代欧洲人尼安德特人祖先的 83 601 区域。让我们读一下坐标,看看尼安德特人渗入区域的长度分布。
我们可以看到,尼安德特人渐渗片段的长度从 10 kbp 到 1.2 Mbp 不等,平均值约为 100 kbp。现在我们将使用这些坐标并从 hg19 版本的人类参考基因组中提取实际序列,该参考基因组具有 fasta 文件格式,可从http://hgdownload.cse.ucsc.edu/goldenPath/hg19/bigZips/下载。我们当然可以使用 Python 进行序列提取,但是使用基于 C++的 samtools 会快得多。
现在我们要用尼安德特人渗入坐标之外的坐标建立一个熊猫数据框架。为此,我们将随机绘制与同一条染色体上的渐渗区长度相同的 DNA 片段,并检查这些片段是否与任何渐渗区相交。这样,我们构建了两组不重叠的坐标:渐渗区和耗尽区。
一旦建立了包含耗尽尼安德特人祖先区域的数据框架,我们就可以使用 samtools 再次从 hg19 fasta 中提取对应于耗尽片段的实际 DNA 序列,这里为了简洁起见我跳过这一步,但是查看 github 上的完整 Jupyter 笔记本来查看细节。仔细观察提取的渐渗和耗尽序列,我们可以注意到相当多的含 N-核苷酸的序列。这是基因组学中缺失的数据,即测序技术没有解决的位置。为了不让缺失的数据影响我们的分析,我省略了包含至少一个 N-核苷酸的序列,这可以在 BioPython 中有效地完成:
现在数据准备好输入到 NLP 分析中。让我们继续进行简单的单词袋模型,即观察尼安德特人渐渗序列与耗尽序列之间 k-mers 的频率的差异。
情感分析:渐渗与耗尽
我们首先将两个 fasta 文件中的序列格式化为文本,用空格分隔的 k-mers 作为单词。由于我的笔记本电脑的内存限制,我只读取了每个序列的前 10,000 个核苷酸,然后我使用了函数 getKmers 将每个序列分成 k-mers,并以空格分隔的方式合并 k-mers,所以最后,我有了一个句子列表,每个句子代表一个单词/ k-mers 列表。
现在,我们可以使用 Python 中的 Counter 类进行有效的单词计数,轻松地可视化尼安德特人渐渗和耗尽序列中的 k-mer 频率。
尽管富含 A 和 T 的 k-mer 似乎在尼安德特人的渐渗区和耗尽区都最常见,但我们观察到两种情况下 k-mer 计数的微小差异,这可能表明渐渗区和耗尽区序列中的非相同** k-mer 组成。接下来,我们使用 CountVectorizer 类将单词/ k-mer 编码为整数,该类简单地构建文本的词汇表(唯一 k-mer 的数量)并计算每个单词/k-mer 在每个句子/序列中的出现次数。**
在我们将数据集分成训练和测试子集之后,我们定义了具有随机梯度下降(SGD)优化器+动量和 L1 权重正则化器的前馈神经网络。
MLP Accuracy training curve (left) and confusion matrix of evaluation on test data set (right)
该模型在对尼安德特人渐渗与耗尽起源序列进行分类的测试数据集上达到了 82.2% 的准确度。与逻辑回归、支持向量机(SVM)或朴素贝叶斯分类器等线性模型相比,这显然是一个更好的结果,然而,出乎意料的是,随机森林分类器在相同的测试数据集上达到了更高的准确度 84.5% 。显示随机森林模型的特征重要性,我们观察到诸如 AAAAA 、 CAAAA 、 CATTT 和 TTTTT 的 k-mers 是最具预测性的。我们立即得到一种直觉,即尼安德特人渗入/耗尽区域的预测与 GC/AT 含量有关,因为最具预测性的 k-mers 极其富含 AT。
Random Forest classifier confusion matrix (left) and feature importances dominated by AT-rich k-mers (right)
从随机森林分类器的混淆矩阵(如上)可以清楚地看出,该模型在预测耗尽的尼安德特人祖先片段时具有非常高的准确性,但是在对渗入区域进行分类时表现非常差(比神经网络差)。
预测尼安德特人遗传的基因
现在让我们回到从一个给定的 DNA 序列预测它是否是从尼安德特人那里继承来的问题上来。在这里,我将对人类蛋白质编码基因做出这样的预测。让我们在这里http://genome.ucsc.edu/cgi-bin/hgTables下载 hg19 的 RefSeq 基因注释文件,清理它并使用基因的坐标,以便从参考基因组 fasta 文件中提取它们的序列,类似于我们对渐渗和耗尽区域所做的,参见 github 上 Jupyter 笔记本中的详细信息。我们再次通过 k-mers 的空格分隔连接来构建基因文本。
接下来,我们将使用经过训练的随机森林分类器来生成先前转换为文本的基因序列的预测。因此,用 CountVectorizer 将基因文本转换成整数。
Genes predicted to have high (left) and low (right) probability to be inherited from Neanderthals
这样,对于每个基因,我们生成一个概率(Prob_1 ),它是从尼安德特人遗传的,并且是一个本地人类基因(Prob_0)。我们可以很容易的显示出最高 Prob_1(最低 Prob_0)和最高 Prob_0(最低 Prob_1)的基因,请看上面的基因列表。值得注意的是,在大约 22000 个蛋白质编码基因中,只有 477 个基因被预测含有尼安德特人的 DNA。这是一个非常有趣的观察,我们稍后将再次讨论它。
K-mer /单词嵌入的可视化
通过连接 k-mers 产生的基因组文本的词汇可以通过单词嵌入模型 Word2Vec 可视化,该模型对单词(在我们的情况下是 k-mers)之间的相似性进行智能猜测。一旦适合我们的数据,Word2Vec 将每个 k-mer 表示为一个 100 维的潜在向量,这些向量可以被视为我们数据的另一种数字表示,可以输入到任何降维技术中进行进一步的研究。在这里,我们将嵌入和可视化 UMAP 和 tSNE 的 k-mers 用于尼安德特人渐渗与枯竭情绪分析。我们可以检测到两个明显的 k-mer 星团。更仔细的观察表明,其中一个似乎富含 AT-丰富的 k-mers,而另一个(较小的一个)主要由富含 GC 的 k-mers 组成。
****
根据随机森林分类器,我特别用绿色突出显示了最具预测性的 k-mers,该分类器可以区分尼安德特人渗入序列和耗尽序列。正如所料,它们都属于更大的富含 AT 的集群。这个单词嵌入可视化是 k-mer 句子中存在一些结构的又一个证据,它能够预测尼安德特人的祖先,并且与 DNA 富含 GC 和 AT 片段之间的平衡有关。****
进化从基因中消除了尼安德特人的 DNA
总结前面几节讨论的一切,我们可以得出结论,我们 DNA 中存在的尼安德特人祖先可疑地与整个基因组中的 GC / AT 含量相关。众所周知我们的基因富含 GC,它们的 GC 含量约为 47%,而全基因组的 GC 含量为 41%,这是 GC 含量的巨大差异。
Human genes are typically GC-rich which is indicative for absence of Neanderthal ancestry
因此,我们可以问,尼安德特人的基因渗入和耗尽区域与基因重叠的程度到底有多大?我们可以用bed tools intersects快速计算基因与渐渗坐标之间的相交数。然而,由于尼安德特人耗尽区域的坐标是先前随机选择的(我们只要求它们不与渗入坐标重叠),我们应该重复选择程序多次,以便估计相交的显著性。
我们可以看到,基因和尼安德特人渐渗片段之间的交集数量 140 821 ,明显低于基因和尼安德特人衰竭区域之间的交集数量。事实上,在 17 个随机抽取的尼安德特人衰竭区域中,没有一个区域的基因相交数小于或等于 140 821,因此我们可以将 p 值计算为 p 值< 1 / 17。我们看到的是,尼安德特人的基因渗入区域主要落在基因之外,这意味着进化没有优先考虑尼安德特人的祖先,并试图将其从我们基因组中最具功能的元素中推开,这些元素是蛋白质编码基因。因此,出于一些神秘的原因,与尼安德特人杂交并没有改善我们的健康,进化试图纠正这一点。他们在报纸和杂志上谈论了很多关于现代人和尼安德特人杂交的非常酷的事实,但是他们从来没有提到这对现代人没有好处,不是吗?
Image source
摘要
在这篇文章中,我们了解到机器/深度学习和自然语言处理(NLP)在进化生物学和古代 DNA 研究领域的巨大潜力,这一潜力仍然没有被充分利用。基因组数据提供了进化生物学中的主要信息源之一,并包含数百万和数十亿的短 DNA 片段,这些片段可以并且应该用深度学习来分析。在这里,我们演示了如何为 NLP 准备基因组数据,并使用单词包和单词嵌入对其进行分析。我们训练了一个模型,能够预测基因组序列是否是从尼安德特人遗传的。使用该模型,我们构建了可能从尼安德特人继承的基因列表,并发现我们的基因中缺乏古老的祖先,这表明与尼安德特人的杂交是进化的,对现代人类无益。
值得一提的是,我目前正在研究各种类型的具有长记忆的神经网络架构,例如 RNNs / LSTMs、CNN/多通道 CNN,并应用于古代基因组学,我将在以后的文章中回到这个主题。
像往常一样,请在评论中让我知道你最喜欢的生命科学领域,你希望在深度学习框架中解决的领域。在媒体关注我,在 Twitter @NikolayOskolkov 关注我,在 Linkedin 关注我。完整的 Jupyter 笔记本可以在我的 github 上找到。我计划写下一篇关于如何用深度学习及时预测人口规模的帖子,敬请关注。
深度学习:用 TensorFlow 拯救雨林
原文:https://towardsdatascience.com/deep-learning-saving-rainforests-with-tensorflow-4e906344811a?source=collection_archive---------13-----------------------
森林砍伐占全球碳排放量的近 20%,并造成了数万亿美元的经济损失。随着 80%的亚马逊木材被非法砍伐,迫切需要一种检测和阻止这种行为的解决方案。然而,有一些障碍。鉴于热带雨林的广阔和茂密,护林员根本没有资源或人力来实际监控数千英亩的雨林。
由托弗·怀特领导的一个名为雨林连接的非营利组织已经设计出了一个有效且足智多谋的解决方案。旧手机被收集起来,装上太阳能电池板,放在树枝上,听伐木卡车和电锯的声音。一部手机可以探测到一公里外的非法砍伐,保护了 300 多公顷的雨林,防止了 15000 吨二氧化碳的排放——超过了 3000 辆汽车一年的排放量。
这背后的检测算法是由谷歌大脑团队开发的深度学习框架 TensorFlow 驱动的。我使用 TensorFlow 开发了一个模型,该模型在检测森林中远处的链锯噪音时至少有 93%的准确性。
第一步:获取数据
由于我附近缺少雨林和非法伐木工,我使用了 scaper 库来模拟雨林的声景。这段代码所做的是将各种链锯噪音(来自 YouTube)叠加在各种雨林噪音(也来自 YouTube)之上,包括雷暴、动物和流水。为了给出可能的链锯噪声的广泛表示,样本在音量和音调上随机变化。
这里有两个例子,第一个没有电锯,第二个有电锯。你能听到吗?
第二步:制作图像
虽然视觉深度学习已经有了很大的进步,但听觉深度学习仍然很原始。声谱图是一种声音的直观表示,其中每个频率的出现都是相对于时间绘制的。卷积神经网络非常擅长识别图像中的信号——就像频谱图中的链锯噪音。为了利用 CNN 的力量,我们必须使用 librosa python 库将原始音频数据转换成图像格式。
这是一个声谱图示例及其相关的声景。看看你是否能听到一些特征:
The spectogram for the below soundscape
最初的图像是 600x400,但这对于我的 GPU 来说太多了。将图像缩小到 100x100 会产生更快、更准确的结果。有电锯的声景和没有电锯的声景各占一半。
步骤 3:训练分类器
这个片段将样本图像分为训练集、测试集和评估集。总共有 2000 个图像,100 个用于评估,其余的 80/20 用于训练/测试。
然后,我们在 2 个 CNN 层和单个密集输出上训练该模型。
2D convolution visualisation— source
以下是网络摘要:
该网络在 GTX 1660Ti GPU 上训练了大约 2 分钟,超过 200 个时期。结果非常棒——接近 97%的验证准确率和 0.057%的损失,曲线看起来非常健康。
在该网络从未见过的 100 张评估图片上,该模型的得分为 93%!
结论
我认为听觉机器学习和物联网设备有巨大的潜力。抛开隐私问题不谈,一个由互联网连接的太阳能麦克风组成的网络运行一个简单的 TensorFlow 模型,可以检测非法偷猎、交通拥堵和未经维护就侵入大片区域的行为。
订阅我的时事通讯,以便在我下次写作时得到通知:)
在 Kaggle 上使用 CNN 进行深度学习以识别疟疾细胞
原文:https://towardsdatascience.com/deep-learning-to-identify-malaria-cells-using-cnn-on-kaggle-b9a987f55ea5?source=collection_archive---------12-----------------------
Photo by Kendal James on Unsplash
深度学习有着广泛的应用,它在医疗保健行业的应用一直让我着迷。作为一名敏锐的学习者和 Kaggle noob,我决定研究疟疾细胞数据集,以获得一些实践经验,并学习如何在 Kaggle 平台上使用卷积神经网络、Keras 和图像。
我喜欢 Kaggle 的一个原因是它以内核和讨论的形式保存了大量的知识。从各种内核和专家那里获取线索和参考资料确实帮助我更好地产生高度准确的结果。一定要看看其他内核,了解他们的方法,以便为您自己的开发和知识建设获得更多的见解。
快速来源
- 数据集:https://www . ka ggle . com/iarunava/cell-images-for-detecting-malaria
- Kaggle 笔记本:https://www . ka ggle . com/bhanotkaran 22/keras-CNN-data-augmentation
导入库和数据集
我从导入numpy
、pandas
和matplotlib
开始。我决定使用 Keras 和 Tensorflow backend 来实现 CNN 模型。所以,我从keras.layers
中导入了一些图层,包括Convolution2D
、MaxPooling2D
、Flatten
、Dense
、BatchNormalization
和Dropout
。我用的是Sequential
型号。为了处理数据集中的图像,我导入了os
、cv2
和Image
包。
导入数据集
在 Kaggle 中,所有数据文件都位于笔记本所在位置的上一级文件夹input
中。图像在cell_images
文件夹中。因此,我将数据目录设置为DATA_DIR
来指向那个位置。为了存储特性,我使用了变量dataset
,对于标签,我使用了label
。对于这个项目,我将每个图像的大小设置为 64x64。
DATA_DIR = '../input/cell_images/cell_images/'
SIZE = 64
dataset = []
label = []
下一步是导入数据。寄生(感染)的细胞图像在Parasitized
文件夹内,未感染的图像在Uninfected
文件夹内。
对于这两个文件夹,我遍历了所有扩展名为png
的文件。
对于被寄生的细胞图像,我使用cv2.imread()
读取图像,使用Image.fromarray()
将其从数组转换,并将其大小调整为 64x64。最后,我将它保存到dataset
变量中,并将每张图片的0
附加到label
中。我对未感染的细胞图像重复了相同的过程,但这次将标签设置为1
。
可视化数据
我用 matplotlib 随机绘制了 5 个被寄生和 5 个未被感染的细胞。
寄生细胞
Parasitized cells
未感染的细胞
Uninfected cells
应用 CNN
卷积神经网络是处理图像和进行分类的最有效的神经网络之一。我使用 Keras 创建模型。
卷积 2D
这将创建一个卷积核。我设置了一些如下定义的属性:
- 过滤器:第一个参数定义层的输出形状。在这种情况下,对于两个层,我都将值保持为
32
。 - kernel_size: 它定义了我们想要使用的沿着图像遍历的窗口的大小。我设置为
3x3
。 - input_shape: 用于定义每张图像的输入尺寸。在这个项目中,我使用 64x64 大小的图像,图像是彩色的,即它们由红色,蓝色和绿色组成。因此通道是 3 个。因此,参数
input_shape
将为(64, 64, 3)
。我们只需要为第一层定义input_shape
。 - 激活:激活功能在此参数中定义。我使用
relu
作为激活函数,它是整流线性单元。
MaxPool2D
它用于缩减输出,我使用了以下参数:
- pool_size: 定义了矩阵大小,矩阵大小定义了将被转换为 1 个值的像素值的数量。我使用的值是
2x2
,因此大小为62x62
的图像将被转换为31x31
。 - data_format: 描述了在输入中,通道是定义在开头还是结尾。在这种情况下,第三个值用于
(64, 64, 3)
中的通道,我将data_format
设置为channels_last
。
批量标准化
它将前一个激活函数的输出标准化,我只修改了一个参数:
- 轴:定义要归一化的轴。当我使用
channels_last
时,我将值设置为-1
。
拒绝传统社会的人
它随机选择一些值设置为0
,以防止在模型中过度拟合,我只使用了速率参数:
- 比率:要丢弃的输入分数。我把汇率保持为
0.2
。
变平
它将完整的 n 维矩阵展平为单个数组。因此,如果它的大小是64x64x3
,它将被转换成大小为12,288
的数组。它作为前面致密层的输入。
稠密的
它定义了一个密集连接的神经网络层,我定义了以下参数:
- 激活:定义了除最后(输出)层外,我设置为
relu
的激活函数。对于最后一个密集层,我设置激活为sigmoid
。 - 单位:定义给定层的神经元个数。我创建了三层,神经元数量分别为 512、256 和 2。
本项目中 CNN 模型的结构
我为 CNN 制作了一个Sequential
模型。
我创建了一个卷积层,然后是一个最大池层。接下来是BatchNormalization
以标准化来自先前层的输出并应用Dropout
规则化。然后附加另一组这些层。然后我Flatten
输出。然后,展平的输出被传递到人工神经网络,该网络包括具有 512、256 和 2 个节点的三个密集层。最后一层是带有激活功能sigmoid
的输出层。你可以在这里阅读更多关于激活功能的信息。
最后一步是编译模型。优化器是adam
,这是一个分类问题,我使用损失作为categorical_crossentropy
,评估指标作为accuracy
。
培训和准确性
我将数据集分成 80%的训练数据和 20%的测试数据。
用fit
的方法,我用X_train
和y_train
训练模型。我使用总时期作为50
,它基本上是完整数据集的 50 次迭代,批量大小为64
。我还添加了 0.1 的验证,这样模型在 90%的训练数据上训练,在 10%的训练数据上验证。
该模型达到了 95.75%的准确率。
数据扩充和准确性改进
数据扩充有助于增加数据集,并在更多不同的数据上训练模型。可供模型学习的数据越多,模型的表现就越好。Keras 提供了一个可以创建这些数据的子包ImageDataGenerator
。
数据扩充
对于训练数据,我通过除以255
来重新缩放图像,以0.3
的范围缩放图像,水平翻转图像并旋转30
的角度。为了测试数据,我只是重新缩放图像。train_generator
和test_generator
以64
的批量创建。
计算新精度
然后,我使用fit_generator
训练分类器,并计算新的准确度。
该模型通过数据扩充达到了 96.41%的准确率。
正如我们所看到的,通过数据扩充,我能够提高模型的准确性,同时仍然拥有相同的数据。乍一看,它可能看起来准确性没有增加多少,但在医疗领域,一个百分点的增加真的很有用,可以正确识别更多的患者。
结论
在本文中,我讨论了对疟疾细胞图像使用卷积神经网络和数据增强,并实现了 96.41%的测试准确率。
感谢阅读。请分享你的想法、想法和建议。
深度学习预测美国通胀
原文:https://towardsdatascience.com/deep-learning-to-predict-us-inflation-70f26405bf76?source=collection_archive---------14-----------------------
卷积神经网络分析
Photo by Jp Valery on Unsplash
我们为什么关心通货膨胀?
理解和预测未来的通胀率对政策制定者和投资者来说都是极其重要的。根据定义,通货膨胀是一个经济体内部价格随时间的变化。虽然价格上涨似乎是一件坏事,但当价格上涨放缓时,这表明经济强劲增长。
通胀预期是货币政策影响经济活动的最重要渠道之一。它们在生产者和零售商层面的消费品价格形成过程中发挥着显著的作用。经济代理人发现经常调整价格的成本相对较高,因为他们必须承担推广和宣传新价格的相关成本。短期内将产品定价过高的个人可能会看到较低的销售额,而在投入成本上升时将产品定价过低的个人可能会被迫承担损失,减少利润,甚至被迫退出市场。
这进一步影响了金融市场,因为投资者必须预测通货膨胀将如何影响实际收益回报,以及公司是否能够在经济停滞期间保持利润增长。从长远来看,通货膨胀要么会推高工资,要么会导致个人购买力下降。这两种情况都会增加投入成本,包括劳动力和资本成本,或者降低消费者需求,因为在相同的收入水平下,个人可以购买更少的产品,从而损害企业利润。
所有这些影响都会影响政策制定者,尤其是那些维持货币政策的央行官员。央行行长致力于控制经济中的通货膨胀和货币供应,以保持经济结构健康和可持续增长。如果通货膨胀率过低,经济就会停滞不前。如果它变得太高,那么资金开始迅速贬值,个人和企业失去购买力,市场对投资者来说风险更大。央行行长和政策制定者密切跟踪通胀,部分原因是为了设定基准利率。对这些利率的预期最终决定了企业和个人支付的利率,从家庭和企业贷款到信用卡利率。
对于企业、金融机构、政策制定者甚至个人来说,制定一个稳健的通胀预期预测对于更好地在市场中做出决策至关重要。无论是设定产品价格、确定贷款还款计划,还是决定为退休存多少钱,对未来价格和消费的敏锐理解都至关重要。
数据
对于数据,我使用来自 FRED-MD 数据库的 CPIAUSL 系列。FRED-MD 是一个由圣路易斯美联储委员会维护的数据库,旨在对大数据进行“实证分析”。“数据通过 FRED 数据库实时更新。
CPIAUSL 变量代表所有城市消费者的所有项目消费价格指数。它是衡量城市消费者支付的商品和服务价格平均每月变化的指标。该指数由美国劳工统计局根据每月的产品调查计算得出。指数值是计算与上一年同月相比价格或通货膨胀百分比变化的基础。虽然这一变量不是美联储设定利率时最密切关注的,但它是最常见的通货膨胀预测变量之一。
对于这一分析,我预测了每个时期价格指数的变化,并将这一变化转换为年度百分比变化(与一年前同一个月相比的百分比变化)。从数据库文档中,我们知道数据已经去季节性,所以我们不需要解构序列来获得其趋势。首先对该序列进行差分以产生平稳性,然后用具有单一特征的滚动 18 个月周期的张量来构造。滚动平均输入的结构类似。在对序列进行差分后,计算移动平均值,然后将其构建为 18 个月滚动期的张量,其中三个移动平均值中的每一个都作为一个特征。
时间序列数据的卷积建模
为了这个分析,我开发了一个卷积神经网络(CNN)来预测未来 12 个月的通货膨胀。
卷积神经网络是一系列深度学习算法,最初是为图像分类而设计的。该网络获取一幅图像,将该图像通过一组对该图像的不同方面应用权重的过滤器,并最终提供预测。这就像一个特征工程系统,随着时间的推移,网络“学习”什么样的特征过滤器在图像分类中最重要。
类似的方法可以应用于时间序列。虽然时间序列不像图像那样具有“物理”特征,但时间序列数据确实包含时间维度特征。如果我们将时间序列数据想象成一幅图像,我们可以将卷积网络想象成一盏聚光灯或一扇窗户,它扫描整个时间段,照亮该时间段内序列的形状,然后对其进行过滤,以找到它最能代表的特征形状。这种模式的简单说明如下:
Illustrative example of a Convolutional Network for time series (weights are stylized)
模型架构
我用来分析的 CNN 网络如下图所示。首先,我们从两个输入开始,原始通货膨胀时间序列和三个移动平均平滑序列。每个平滑系列代表任何给定观测值的前三个月、六个月和一年的移动平均值。
这些输入然后被馈送到单独的卷积层,以提取每个输入序列的相对重要的特征权重。这些结果然后被汇集并馈入完全连接的层,然后被合并在一起并传递给一系列完全连接的块。全连接块堆栈中的每个后续块包含的节点比前一堆栈中的少。在每个块之间,使用剩余或跳过连接,允许模型使用在早期层中学习的信息来继续训练后面的层。这防止了从卷积层输出的信息太快丢失或被模型的后续层模糊。这也有助于防止渐变消失的问题,并允许原始序列中的一些较小的细节在模型结构中进一步保留。最后,在输出最终预测之前,将对最终图层应用一个丢弃。
Diagram of model architecture
结果
在对数据进行差分后,我将数据集分成训练集和测试集(70/30 分割)。数据在截至 2001 年 6 月的所有月份中进行训练,然后对 2001 年 7 月到 2019 年 9 月进行预测。我使用一步滚动预测。对于测试组中的每个月,预测接下来 12 个月中每个月的通货膨胀率,然后使用观察到的通货膨胀值来预测接下来 12 个月的组。然而,在此过程中,模型在培训期间每五个月才重新培训一次。预测以多元方式进行,同时预测随后 12 个月中的每个月,并在系列中每 10 次观察时进行验证。
这是一个相当现实的方法,因为在预测下一个通货膨胀期时,分析师会观察到所有前期的通货膨胀率。通过使用一步预测,我们保持这种不断增长的建模信息。然而,在实际情况下,分析师将每月重新训练模型,这可能导致预测的改进,因为模型适合更多、更近的信息。这将允许该模型挑选出随时间推移可能发生的系列中的任何结构变化。
模型的误差率以指数值的形式表示。因此,如果指数在时间 T 为 150,在时间 T+1 增加到 154,模型将试图预测 4 个点的增加。如果模型预测有 3 个点的增长,那么该时间段的误差将为 1。
作为模型的基准,我给出了专业预测者调查(SPF)和费城美联储 DAR 模型(SPF 的最高表现基准)测试期间的误差率。SPF 是美国持续时间最长的宏观经济指标预测调查。这些基准的错误率是根据 SPF 官方错误率文档计算的。
下面是模型结果的总结:
Model and benchmark error results
我们可以看到,多元卷积模型远远优于动态自回归回归模型和调查汇总预测。虽然在这些预测如何运行以及误差如何表现方面存在一些差异,但我们可以看到卷积模型在每个时间段都优于这些更传统的方法。SPF 预测按季度在每个季度的中期进行,然后在当前季度末和随后的季度进行预测,而不是按月进行。仍然可以通过将每个季度预测视为三个月的预测,将当前季度预测视为大约一个月的预测来进行比较。
下面,我们可以看到模型在整个时间序列中的表现。总的来说,我们可以看到模型与数据拟合得很好,只是在方差较大的时期或趋势变化很快的时候,误差会稍微大一些。
Forecasts performance 1960–2019
如果我们更仔细地观察测试期,我们会发现该模型在 2008 年金融危机前和危机后的几年表现良好。在危机期间,该模型表现稍差。这并不奇怪,因为 2008 年金融危机是自大萧条以来最严重的金融衰退。因此,该模型没有经过任何类似数据的训练,因此无法准确地运行。
Forecast performance 2001–2019
结论
根据这一分析,有强有力的证据支持使用卷积神经网络来预测和预报美国的通货膨胀。这项分析只使用了一个单一的预测变量,通货膨胀的历史,以预测未来的通货膨胀率。有可能通过增加额外的预测因子来提高模型的性能。也有可能通过在滚动预测的每个月重新训练模型来提高性能。这将是最现实的情况,因为随着新数据的出现,分析师通常会每月重新建模他们的预测。
利用其他机器学习方法,例如长短期记忆网络,也可以通过允许对数据的时间分量进行额外建模来提高模型性能。但这将是未来分析的主题
下面是相关数据源的链接,以及我的 GitHub,其中包括用于此分析的 jupyter 笔记本。我将继续更新代码和完善模型,因此结果可能会略有变化。
附录
[## 专业预报员调查的预报误差统计
下面的 PDF 和文本文件包含了对大多数变量预测准确性的最新统计数据…
www.philadelphiafed.org](https://www.philadelphiafed.org/research-and-data/real-time-center/survey-of-professional-forecasters/data-files/error-statistics) [## 迈克尔·麦克拉肯
圣路易斯美联储银行助理副总裁 Michael W. McCracken 的主页
research.stlouisfed.org](https://research.stlouisfed.org/econ/mccracken/fred-databases/) [## acertainKnight/FRED _ 预测 _ 最终
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/acertainKnight/FRED_Forecasting_Final)
使用迁移学习的深度学习
原文:https://towardsdatascience.com/deep-learning-using-transfer-learning-cfbce1578659?source=collection_archive---------11-----------------------
在本系列文章中,我们将探讨什么是迁移学习,迁移学习的目的是什么。了解实施迁移学习的不同策略。在下一篇文章中,我们将使用 ResNet50 编写代码来应用迁移学习。
如果你知道如何划船,如何游泳,那么我们可以学习水上漂流吗?
如果你已经学会了基础知识,那么你只需要学习水上漂流的具体知识,划船和游泳的基本概念是你知识基础的一部分。
我们能否将这种技术应用于机器学习和深度学习?
但是我们每次都会创建一个新的卷积神经网络(CNN)来识别不同类别的对象。我们有一个 CNN 来识别像狗和猫这样的动物。我们将有一个不同的 CNN 用于识别数字,另一个用于识别服装对象。
关于机器学习和深度学习的常见假设
如果训练和测试数据来自相同的特征空间和相同的分布,我们可以重用已经建立的模型,但是当分布改变时,我们需要从头开始重建模型。这就需要我们收集新的训练数据。
重新收集所需的训练数据和重建模型是昂贵的。如果我们减少重新收集训练数据的需要和努力,并且可以使用知识转移或任务域之间的转移学习,会怎么样?
如果我们有一个 CNN,可以用来学习图像的基本知识,如角、形状、光照,然后稍微调整一下,学习其他类别图像的细节,会怎么样?
欢迎转学习!
迁移学习的目的是什么?
迁移学习的目的是利用第一个设置中的数据,提取在第二个设置中学习甚至直接进行预测时可能有用的信息
- 深度学习作者伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔
迁移学习的动机
机器学习模型传统上是在这样的假设下开发的,即如果训练和测试数据来自相同的特征空间和相同的分布,则模型将工作良好。
如果特征空间或数据分布发生变化,那么我们就需要建立一个新的模型。每次从头开始开发一个新模型以及每次收集一组新的训练数据都是非常昂贵的。迁移学习减少了回忆大量训练数据的需要和努力。
用于机器学习和深度学习的迁移学习的动机是基于这样一个事实,即人们可以智能地将以前学到的知识应用于不同的任务或领域,这些任务或领域可以用来更快地解决新问题或提供更好的解决方案。
Source: A Survey on Transfer Learning
迁移学习有哪些重点考虑?
为了有效地应用迁移学习,我们需要回答三个主要问题
- 转什么
- 什么时候转移
- 怎么转
- 转移什么 —我们需要了解源任务和目标任务之间有哪些知识是共同的。哪些知识可以从源任务转移到目标任务,从而有助于提高目标任务的绩效
- 何时迁移或何时不迁移- 当源域和目标域完全不相关时,我们不应该尝试应用迁移学习。在这种情况下,性能会受到影响。这种迁移称为负迁移。只有当源域和目标域/任务相关时,我们才应该应用迁移学习
- 如何迁移:当源和目标领域/任务相关时,识别不同的技术来应用迁移学习。我们可以使用归纳迁移学习、直推迁移学习或无监督迁移学习。
这些不同类型的迁移学习是什么?
不同类型的迁移学习
归纳迁移学习- S 源域和目标域相同但任务不同
如果我们想让孩子识别水果,那么我们就开始展示不同颜色的苹果,像红苹果、绿苹果、淡黄色苹果等等。我们给孩子看不同种类的苹果,如嘎拉、澳洲青苹、富士苹果等。我们在不同的环境中展示这些苹果,这样孩子在大多数情况下都能识别苹果。同样的逻辑也用于识别不同的水果,如葡萄、橘子、芒果等。这里我们把在学习苹果中获得的知识应用到学习识别其他水果中。我们的源域和目标域与水果的识别相关,但是一个任务涉及识别苹果,一个任务涉及识别芒果。
- 归纳迁移学习的目标是提高目标预测函数的性能。
- 归纳迁移学习需要目标域中的少量标记数据作为训练数据来归纳目标预测函数
- 如果源域和目标域都有标记数据,那么我们可以执行多任务迁移学习
- 如果源有标记数据,而目标任务没有标记数据,那么我们可以进行自学习迁移学习
直推式迁移学习——不同领域但相似任务的迁移学习
让我们推断这一学习,现在我们想让孩子学习像椅子、桌子、床等家用物品。孩子将利用所学的水果识别知识来识别家用物品。
孩子可能没有看到足够多的家庭用品,但会使用形状、颜色等知识。学会鉴别水果来鉴别家居物品。
直推式迁移学习,目标域没有标记数据,而源域有大量标记数据
直推式迁移学习适用于以下情况
- 源域和目标域之间的特征空间可以不同
- 域之间的特征空间相同,但输入数据的边际概率分布不同。这也被称为域适应。
无监督迁移学习
无监督迁移学习类似于归纳迁移学习,其中目标任务不同于但与源任务相关。源任务和目标任务的域是相同的。我们没有源-目标任务的标记数据
它侧重于解决目标领域中的无监督学习任务,如聚类或维度缩减
Source : A Survey on Transfer Learning
我能把这些迁移学习策略应用到深度学习中吗?
与计算机视觉或顺序文本处理或音频处理等机器学习相比,深度学习需要大量的训练数据和训练时间。我们可以保存我们训练好的模型的权重,并分享给其他人使用。我们现在也有预训练模型,广泛用于迁移学习,称为深度迁移学习。
深度迁移学习的常用策略
- 使用预训练的模型作为特征提取器
- 微调预训练模型
用于计算机视觉的预训练深度神经网络
- VGG-16 号
- VGG-19
- 盗梦空间 V3
- ResNet-50
- 异常
用于自然语言处理任务的预训练深度神经网络
- 手套
- Word2Vec ,
- 快速正文
- 伯特
预训练模型可用于预测、特征提取和微调
让我们来了解一下这些策略的细节
使用预训练的模型作为特征提取器
- 为了实现迁移学习,我们删除了预训练模型的最后一个预测层,并用我们自己的预测层替换它们。FC-T1 和 FC_T2 如下所示
- 这些预训练模型的权重被用作特征提取器
- 预训练模型的权重被冻结,并且在训练期间不被更新
微调预训练模型
- 我们可以使用像 VGG-16,VGG-19,Inception V3,ResNet-50,Xception 这样的深度神经网络作为预训练模型
- 为了实现带有微调的迁移学习,我们删除了预训练模型的最后一个预测层,并用我们自己的预测层来替换它们。FC-T1 和 FC_T2 如下所示。
- 网络的初始较低层从预先训练的模型中学习非常一般的特征。为了实现这一点,预训练模型的初始层权重被冻结,并且在训练期间不被更新
- 较高层用于学习特定任务的特征。预训练模型的更高层是可训练的或可微调的
- 用更少的培训时间提高绩效
我们将在下一篇文章中看到使用 ResNet50 的代码实现。ResNet 是残网的简称。这是一个 50 层的残余网络。
参考资料:
关于迁移学习的调查
全面的实践指南,帮助您将学习转化为深度学习中的实际应用
GitHub 用 Python 进行迁移学习
使用迁移学习的深度学习-用于 ResNet50 的 Python 代码
原文:https://towardsdatascience.com/deep-learning-using-transfer-learning-python-code-for-resnet50-8acdfb3a2d38?source=collection_archive---------0-----------------------
这是本系列的第二部分,我们将使用 ResNet50 编写应用迁移学习的代码。在这里,我们将使用迁移学习,使用预训练的 ResNet50 模型,然后微调 ResNet50。
迁移学习概念第一部分
对于代码实现,我们将使用 ResNet50 。ResNet 是残网的简称。这是一个 50 层的剩余网络
ResNet50
当我们向深层神经网络添加更多层时,性能会变得停滞不前或开始下降。这是由于消失梯度问题造成的。当梯度通过深度神经网络反向传播并重复相乘时,这使得梯度非常小,从而导致消失梯度问题。
ResNet 通过使用标识快捷连接或跳过一层或多层的跳过连接解决了渐变消失的问题。S 快捷连接将第 N 层的输出连接到第 N+Z 层的输入
我们将使用猫狗数据集来演示迁移学习使用
- 预训练的 ResNet50 模型作为特征提取器
- 微调预训练模型 ResNet50
创建数据集
导入基本库。我们将在需要时导入额外的库
import glob
import numpy as np
import pandas as pd
import os
import shutil
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array, array_to_img
%matplotlib inline
我已经把所有的猫和狗的图片保存在了 dogs-vs-cats 文件夹中。我们读了猫狗档案。我们有 25003 张猫和狗的图片
files = glob.glob('E:\\Data\\Images\\dogs-vs-cats\\*')
cat_files = [fn for fn in files if 'cat' in fn]
dog_files = [fn for fn in files if 'dog' in fn]
len(cat_files), len(dog_files)
我在一个较小的数据集上进行训练,因此减少了我的训练、测试和验证数据集的大小。如果您想在所有图像上进行训练,则不需要此步骤。
训练数据集将具有每只猫和狗 1500 张图像,测试数据集将具有每只猫和狗 500 张图像,验证数据集也将具有每只猫和狗 500 张图像
cat_train = np.random.choice(cat_files, size=1500, replace=False)
dog_train = np.random.choice(dog_files, size=1500, replace=False)
cat_files = list(set(cat_files) — set(cat_train))
dog_files = list(set(dog_files) — set(dog_train))
cat_val = np.random.choice(cat_files, size=500, replace=False)
dog_val = np.random.choice(dog_files, size=500, replace=False)
cat_files = list(set(cat_files) — set(cat_val))
dog_files = list(set(dog_files) — set(dog_val))
cat_test = np.random.choice(cat_files, size=500, replace=False)
dog_test = np.random.choice(dog_files, size=500, replace=False)
print(‘Cat datasets:’, cat_train.shape, cat_val.shape, cat_test.shape)
print(‘Dog datasets:’, dog_train.shape, dog_val.shape, dog_test.shape)
加载训练和验证数据集。我们的图像尺寸将是 300×300 像素
**IMG_WIDTH=300
IMG_HEIGHT=300
IMG_DIM = (IMG_WIDTH, IMG_HEIGHT)**train_files = glob.glob(‘E:\\Data\\Images\\dogs-vs-cats\\training_data\\*’)train_imgs = [img_to_array(load_img(img, target_size=IMG_DIM)) for img in train_files]
train_imgs = np.array(train_imgs)
train_labels = [fn.split(‘\\’)[-1].split(‘.’)[0].strip() for fn in train_files]validation_files = glob.glob(‘E:\\Data\\Images\\dogs-vs-cats\\validation_data\\*’)
validation_imgs = [img_to_array(load_img(img, target_size=IMG_DIM)) for img in validation_files]
validation_imgs = np.array(validation_imgs)
validation_labels = [fn.split(‘\\’)[-1].split(‘.’)[0].strip() for fn in validation_files]print(‘Train dataset shape:’, train_imgs.shape,
‘\tValidation dataset shape:’, validation_imgs.shape)
现在,每个图像的大小为 300 x 300,并具有红色、绿色和蓝色(RGB)三个通道。
图像的像素值介于 0 和 255 之间。深度神经网络在较小的输入值下工作良好。用 0 到 1 之间的值缩放每个图像。
train_imgs_scaled = train_imgs.astype(‘float32’)
validation_imgs_scaled = validation_imgs.astype(‘float32’)
train_imgs_scaled /= 255
validation_imgs_scaled /= 255
# visualize a sample image
print(train_imgs[0].shape)
array_to_img(train_imgs[0]
对猫和狗的文本类别标签进行编码
# encode text category labels
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit(train_labels)
train_labels_enc = le.transform(train_labels)
validation_labels_enc = le.transform(validation_labels)
print(train_labels[1495:1505], train_labels_enc[1495:1505])
将数据增强应用于图像
Keras 框架有一个优秀的实用工具,叫做 ImageDataGenerator。通过实时数据增强生成批量张量图像数据。
对于我们的训练和验证数据集,我们将使用 zoom_range 参数将图像随机缩放 0.3 倍。我们使用 rotation_range 参数将图像随机旋转 50 度。使用 width_shift_range 和 height_shift_range 参数,以图像宽度或高度的 0.2 倍水平或垂直随机平移图像。使用 shear_range 参数随机应用基于剪切的变换。使用 horizontal_flip 参数随机水平翻转一半的图像。在我们应用任何前面的操作(尤其是旋转或平移)之后,利用 fill_mode 参数为图像填充新的像素。在这种情况下,我们只是用最近的周围像素值填充新像素。
train_datagen = ImageDataGenerator(rescale=1./255, zoom_range=0.3, rotation_range=50,
width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2,
horizontal_flip=True, fill_mode=’nearest’)val_datagen = ImageDataGenerator(rescale=1./255)
让我们看看一些增强图像是什么样子的。我们将从我们的训练数据集中选取两个样本图像来说明这一点。第一个图像是猫的图像,第二个图像是狗的图像
img_id = 2500
cat_generator = train_datagen.flow(train_imgs[img_id:img_id+1],
train_labels[img_id:img_id+1],
batch_size=1)
cat = [next(cat_generator) for i in range(0,5)]
fig, ax = plt.subplots(1,5, figsize=(16, 6))print(‘Labels:’, [item[1][0] for item in cat])
l = [ax[i].imshow(cat[i][0][0]) for i in range(0,5)]
img_id = 4001
dog_generator = train_datagen.flow(train_imgs[img_id:img_id+1],
train_labels[img_id:img_id+1],
batch_size=1)
dog = [next(dog_generator) for i in range(0,5)]
fig, ax = plt.subplots(1,5, figsize=(15, 6))
print(‘Labels:’, [item[1][0] for item in dog])
l = [ax[i].imshow(dog[i][0][0]) for i in range(0,5)]
对于我们的测试生成器,我们需要将原始测试图像发送给模型进行评估。我们只是在 0 和 1 之间缩放图像像素,并且不应用任何变换。
我们只是将图像增强变换仅应用于我们的训练集图像和验证图像
train_generator = train_datagen.flow(train_imgs, train_labels_enc,batch_size=30)val_generator = val_datagen.flow(validation_imgs, validation_labels_enc, batch_size=30)
使用预训练模型作为特征提取器的迁移学习
我们使用 ResNet50 深度学习模型作为迁移学习的特征提取的预训练模型。
- 为了实现迁移学习,我们将删除预训练 ResNet50 模型的最后一个预测层,并用我们自己的预测层来替换它们。FC-T1 和 FC_T2 如下所示
- 使用 ResNet50 预训练模型的权重作为特征提取器
- 预训练模型的权重被冻结,并且在训练期间不被更新
我们不想加载充当分类器的最后完全连接的层。我们通过使用“ include_top=False ”来实现这一点。我们这样做是为了我们可以在 ResNet50 模型之上添加我们自己的全连接层,用于我们的特定任务分类。
我们通过设置可训练为“假”来冻结模型的权重。这将在训练期间停止对预训练权重的任何更新。我们不希望训练 ResNet 层,因为我们希望利用深度神经网络从以前的数据集(在我们的情况下是“imagenet ”)中训练的知识
from keras.applications.resnet50 import ResNet50
from keras.models import Model
import keras**restnet = ResNet50(include_top=False, weights='imagenet', input_shape=(IMG_HEIGHT,IMG_WIDTH,3))**output = restnet.layers[-1].output
output = keras.layers.Flatten()(output)restnet = Model(restnet.input, output=output)for layer in restnet.layers:
**layer.trainable = False**restnet.summary()
ResNet50 with 23, 587,712 frozen weights
现在,我们使用迁移学习,通过添加我们自己的全连接层和使用 sigmoid 激活函数的最终分类器,使用预训练的 ResNet50 来创建我们的模型。
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, InputLayer
from keras.models import Sequential
from keras import optimizersmodel = Sequential()
model.add(restnet)
model.add(Dense(512, activation='relu', input_dim=input_shape))
model.add(Dropout(0.3))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(1, activation='sigmoid'))model.compile(loss='binary_crossentropy',
optimizer=optimizers.RMSprop(lr=2e-5),
metrics=['accuracy'])
model.summary()
我们看到 ResNet50 的重量是不可训练的,因为我们已经冻结了它们。
我们现在运行这个模型
history = model.fit_generator(train_generator,
steps_per_epoch=100,
epochs=100,
validation_data=val_generator,
validation_steps=50,
verbose=1)
保存训练过的重量
model.save(‘cats_dogs_tlearn_img_aug_cnn_restnet50.h5’)
微调预先训练的模型
- 我们可以使用深度神经网络,如 VGG-16,VGG-19,Inception V3,ResNet-50,Xception 作为预训练模型
- 为了实现带有微调的迁移学习,我们删除了预训练模型的最后一个预测层,并用我们自己的预测层来替换它们。FC-T1 和 FC_T2 如下所示。
- 网络的初始较低层从预先训练的模型中学习非常一般的特征。为了实现这一点,预训练模型的初始层权重被冻结,并且在训练期间不被更新
- 较高层用于学习特定任务的特征。预训练模型的更高层是可训练的或可微调的
- 用更少的培训时间提高绩效
我们已经用图像增强创建了数据集,并且我们已经创建了基本的 ResNet50 模型。
我们现在将使用 ResNet50 通过图像增强来微调迁移学习。我们通过解冻一些最后的卷积块,同时保持最初的早期 conv 块冻结来实现这一点。这将有助于我们使用早期图层学习非常通用的功能。预训练模型的更高层将是可训练的或微调的。
restnet.trainable = Trueset_trainable = Falsefor layer in restnet.layers:
if layer.name in ['res5c_branch2b', 'res5c_branch2c', 'activation_97']:
set_trainable = True
if set_trainable:
layer.trainable = True
else:
layer.trainable = Falselayers = [(layer, layer.name, layer.trainable) for layer in restnet.layers]
pd.DataFrame(layers, columns=['Layer Type', 'Layer Name', 'Layer Trainable'])
我们看到,我们已经将 ResNet50 的早期层的训练设置为 false,ResNet50 的最后几层现在是可训练的。
我们现在在 ResNet50 上添加我们自己的全连接层和分类器。我们已经从 ResNet50 中移除了最后一个完全连接的层和分类器层
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, InputLayer
from keras.models import Sequential
from keras import optimizersmodel_finetuned = Sequential()
model_finetuned.add(restnet)
model_finetuned.add(Dense(512, activation='relu', input_dim=input_shape))
model_finetuned.add(Dropout(0.3))
model_finetuned.add(Dense(512, activation='relu'))
model_finetuned.add(Dropout(0.3))
model_finetuned.add(Dense(1, activation='sigmoid'))model_finetuned.compile(loss='binary_crossentropy',
optimizer=optimizers.RMSprop(lr=1e-5),
metrics=['accuracy'])model_finetuned.summary()
我们最终运行了这个模型
history_1 = model_finetuned.fit_generator(train_generator,
steps_per_epoch=100,
epochs=2,
validation_data=val_generator,
validation_steps=100,
verbose=1)
保存微调模型的权重
model.save(‘cats_dogs_tlearn_finetune_img_aug_restnet50.h5’)
参考资料:
关于迁移学习的调查
一份全面的实践指南,旨在将学习转化为深度学习中的实际应用
GitHub 用 Python 进行实际迁移学习
深度学习神经元与生物神经元
原文:https://towardsdatascience.com/deep-learning-versus-biological-neurons-floating-point-numbers-spikes-and-neurotransmitters-6eebfa3390e9?source=collection_archive---------6-----------------------
内部 AI
浮点数、尖峰和神经递质
Conjoined Dichotomy by Melting Miltons
近年来,“深度学习”人工智能模型经常被吹捧为“像大脑一样工作”,因为它们由模仿生物大脑的人工神经元组成。然而,从神经科学家的角度来看,深度学习神经元和生物神经元之间的差异是众多而明显的。在这篇文章中,我们将首先描述生物神经元的一些关键特征,以及如何简化它们以获得深度学习神经元。然后,我们将推测这些差异如何对深度学习网络施加限制,以及朝着更现实的生物神经元模型的移动可能如何推进我们目前所知的人工智能。
生物神经元
典型的生物神经元是单独的细胞,每个细胞由细胞主体和从该主体延伸的许多卷须组成。身体,或体细胞,拥有维持基本细胞功能和能量处理的机器(例如,含 DNA 的细胞核,以及构建蛋白质和处理糖和氧的细胞器)。卷须有两种类型:树突,从其他神经元接收信息并将其带到细胞体,以及轴突,将信息从细胞体发送到其他神经元。
从发送神经元到接收神经元的信息传输大致由三个阶段组成。首先,传输神经元产生空间和时间受限的电爆发,或尖峰,它沿着神经元的轴突(和轴突分支)从细胞体传播到轴突的末端。发送神经元的轴突末端通过突触与接收神经元的树突“连接”。尖峰信号导致传输神经元的突触释放化学物质,或神经递质,通过扩散在两个神经元之间进行短距离传播。
接收神经元上的专门受体识别(结合)特定的神经递质,当神经递质分子结合到受体上时,引发许多细胞事件(本文忽略了其中的大部分)。其中一个事件是细胞通道的打开,这引发了另一个电波,这一次通过接收神经元的树突向其细胞体传播(这可能是一种尖峰信号的形式,但通常该波比沿轴突的尖峰信号传输更具空间扩散性——想象一下水被推过管道)。
因此,来自一个神经元的信息可以传递到另一个神经元。当一个神经元从多个传输神经元接收到多个兴奋性尖峰时,该电能在神经元的细胞体中积累,如果在短时间内积累了足够的能量,该神经元将产生自己的传出尖峰,并将它们中继给其他神经元。
为了理解将我们从生物神经元带到深度学习神经元的建模,还有三个方面需要讨论。
- 速率编码
- 突触强度
- 兴奋性和抑制性传递
码率编码
只接收少量兴奋性尖峰信号的神经元,即使有,也只会产生和发送少量自己的尖峰信号。如果同一个神经元接收到许多兴奋性尖峰信号,它(通常)也会发出许多自己的尖峰信号。虽然生物神经元中的尖峰具有明显的时间特性,但在深度学习神经元中,时间分辨率是“模糊的”。对于给定的时间单位,深度学习神经元的尖峰活动被表示为尖峰的数量(一个整数),或者更典型地,平均尖峰率(一个浮点数)。
In this contrived example, three neurons in the visual system receive indirect input from one of three groups of color-sensitive cones cells in the eye. Each neuron is therefore maximally responsive to a particular wavelength of light, and spiking activity is reported as the average spike rate (normalized to [0,1]). Thus, the input wavelength is “encoded” by the collective spike rates of the three neurons.
然而,请注意,在生物神经元中,信息是以单个或多个神经元中尖峰脉冲的相对时间来编码的,而不仅仅是以单个神经元的尖峰脉冲速率来编码的。因此,深度学习神经元中不存在这种类型的信息编码和传输。这种影响将在下面进一步讨论。
突触强度
并非所有的尖峰都是相等的。当传播的尖峰到达轴突末端时,最终在接收神经元的树突中产生的电能数量取决于干预突触的强度。这种强度反映了许多潜在的生理因素,包括传输神经元中可用于释放的神经递质的量和接收神经元上神经递质受体的数量。
无论如何,在深度学习神经元中,突触强度由单个浮点数表示,更常见的是指突触的权重。
兴奋性和抑制性神经递质
到目前为止,我们只考虑了兴奋性神经传递。在这种情况下,从发送神经元接收的尖峰增加了接收神经元也将产生尖峰的可能性。这是由于接收神经元上激活的受体的特殊性质。虽然过于简单,但人们可以将神经递质及其受体分为兴奋类和抑制类。当抑制性神经递质与抑制性受体结合时,接收神经元中树突的电能减少而不是增加。一般来说,神经元对兴奋性和抑制性神经递质都有受体,但只能释放(传递)其中一种。在哺乳动物皮层中,兴奋性神经元(在每个尖峰时释放神经递质谷氨酸)比抑制性神经元(在每个尖峰时释放神经递质 GABA)多得多。尽管如此,这些抑制性神经元对于增加接收神经元的信息选择性、关闭神经元从而有助于信息路由以及防止癫痫活动(网络中许多神经元的混沌放电)是重要的。
在深度学习网络中,兴奋性和抑制性神经元(分别只有兴奋性或抑制性神经递质的神经元)之间没有区别。所有神经元的输出活动都大于零,而正是突触模拟了抑制。突触的权重允许为负,在这种情况下,来自传输神经元的输入导致接收神经元的输出减少。
深度学习神经元
如上所述,生物神经元的简化模型可以被组装以形成深度学习模型中的原型神经元。
- 深度学习神经元从其他神经元接收输入,或激活。激活是生物神经元峰值的速率编码表示。
- 激活被突触权重倍增。这些权重是生物神经元中突触强度的模型,也是抑制性传递的模型,因为权重可能呈现负值。
- 加权激活相加在一起,模拟发生在生物神经元细胞体中的累积过程。
- 将偏差项添加到总和中,模拟神经元的一般灵敏度。
- 最后,总和值由一个激活函数整形,通常是一个限制最小或最大输出值(或两者)的函数,如 sigmoid 函数。这模拟了生物神经元的固有最小尖峰率(零)或最大速率(由于产生尖峰的生理机制的细节)。
推进人工智能
时间编码
深度学习依赖于基于速率的编码,其中每个神经元的激活都是一个单一的数值,它模拟了响应给定刺激(无论是来自其他神经元还是来自外部刺激)的平均尖峰率。在网络的单个层内的尖峰率值的集合通常被组织为数字向量,并且该向量被称为在该层的外部刺激的表示。
基于速率的神经编码的表达能力远低于基于多个神经元上尖峰脉冲之间的相对时间的神经编码(表示)的表达能力。作为生物学中这种类型代码存在的一个简单例子,考虑听觉系统。当声波到达我们的耳朵时,我们的大脑对它们进行处理,以确定产生声音的动物、物体或现象的类型,还可以估计声音来自的方向(定位)。确定声音位置的一种方法是基于这样的事实,即来自右边的声音将首先到达右耳,然后到达左耳。靠近右耳和左耳的听觉神经元表现出反映这种声学定时差异的尖峰定时。由于这种时间编码,位于更中间位置(靠近身体中线)的听觉神经元接收来自双耳附近神经元的输入,并对声音的位置具有选择性。
Acoustic information enters the brain via the outer ears, and is transduced to spikes in the auditory nerves by the left and right cochleas (spirals in the image). Perception of azimuth location is partly determined by time-difference-of-arrival of sounds at the ears, which is encoded as timing differences in spikes in auditory neurons in the left versus right side of the brain. Groups of auditory neurons near the midline of body are sensitive to this temporal coding, and respond selectively to the perceived location (azimuth, elevation) of an incoming sound.
更一般地,考虑一个简单的例子,单个神经元从另外两个神经元接收输入,每个神经元发送相同的输入:一个短串 N 均匀间隔(在时间上)的兴奋性尖峰超过 100 毫秒。所有其他条件相同,这将在接收神经元中产生一些刻板反应。相反,如果一个输入神经元在(100 毫秒间隔的)第一个 20 毫秒内发送了它的所有尖峰,而另一个输入神经元在最后的 20 毫秒内发送了它的所有尖峰,则接收神经元的响应可能显著不同。因此,即使输入神经元的尖峰率在每个场景中是相同的(10 N 尖峰/秒),时间编码也是非常不同的,并且接收神经元的响应也可以是非常不同的。重要的是,当使用时间码时,可以存在许多输入-输出组合,即使输入尖峰的数量低、恒定或两者都有。这就是我们所说的更有表现力的编码方案。关于人工智能,与具有相同数量神经元的深度学习模型相比,利用时间编码的模型可以执行更复杂的任务。
Consider a neuron that receives input from one neuron. The image above represents three example spike sequences (spikes are depicted as vertical lines) from the input neuron. Under a rate-based coding model like that of deep learning, the output of the receiving neuron would be the same in each example (because the input would be identical in each case: 3 spikes/time-unit). In the case of a temporal coding, the output could be different for each example, accommodating a more expressive AI model.
除了表达性之外,棘波时序的差异可以允许模型通过模拟生物学的方式进行学习——例如,突触的棘波时序依赖性可塑性(STDP) 。与深度学习中使用的梯度下降(反向传播)方法相比,这种学习可以在本地高效地实现。但是我们将把这个话题留到以后的文章中讨论。
抑制神经元
基于我们对生物和深度学习神经元的简单描述,兴奋性和抑制性神经元之间的区别可以被深度学习神经元模仿。也就是说,人们可以简单地通过确保其深度学习等效物在其轴突和其投射到的神经元树突之间的所有突触权重都为负值来模仿生物抑制性神经元。相反,当模仿生物兴奋性神经元时,这种突触应该总是具有正权重。然而,如果简单地要求所有的突触都是正值(可能通过在每次训练迭代后对权重应用 ReLU 函数),并且使用为抑制(兴奋)神经元产生负(正)值的激活函数,那么训练和实现将会更容易。
[技术方面:在任何一种情况下,由于权重的零值梯度等于零,可能会有额外的训练挑战。与激活函数中的 ReLU 非线性不同,我们不能依靠随机梯度下降(随机选择的样本批次)将权重值推离零。]
为什么人们会想要抑制神经元呢?为什么不像目前的深度学习模型那样,只在突触层面而不是神经元层面实施抑制?
这并不确定,但一种可能性是,使用显式抑制神经元有助于约束整体参数空间,同时允许促进快速学习的子网络结构的进化或发展。在生物系统中,大脑没有必要能够学习任何输入输出关系,或者执行任何可能的尖峰序列。我们生活在一个有着固定物理法则的世界里,有些物种的个体成员共享许多不需要明确学习的物种内行为特征。限制网络的可能电路连通性和动态活动等同于限制训练方法必须搜索的解决方案空间。鉴于此,一种推进人工智能的方法是使用神经进化和人工生命方法来搜索兴奋性和抑制性神经元的典型子网络结构,这些子网络结构可以在更传统的模型训练中模块化地组装成更大的网络(例如,通过梯度下降的监督学习)。
抑制性神经元的另一个潜在好处,与刚才提到的结构化规范电路的使用有关,是抑制性神经元可以有效地“关闭”大量对给定样本或任务的处理不必要的神经元,从而降低能量需求(假设硬件被设计为利用这种情况)。此外,如果网络结构合理,这可能有助于此类网络中的信息路由——从概念上讲,将信息从提取信息的神经元携带到使用/根据该信息执行特定子任务的神经元。例如,将低级视觉信息(像素、线或弧)路由到提取对象身份的区域、确定相对对象位置的区域或两者。
基于低能耗尖峰的硬件
更大的生物现实主义可以使人工智能受益的另一种方式不是通过扩展基本能力,而是通过更高的能效。人类大脑仅消耗大约 13 瓦——相当于一个现代的紧凑型荧光灯泡——而提供的认知能力远远超过为移动应用设计的低能耗 GPU,甚至是在强大的工作站 GPU 上实现的高能耗深度学习模型。
即使除了这些节能之外,深度学习神经元没有其他根本性的变化,利用约 1000亿神经元和 100–1000万亿突触(对人脑的粗略估计)的能力可能会显著提高人工智能的功能。或者,当前的模型可以以一小部分能源成本运行,使它们可以在边缘轻松实现,因为处理可以在本地完成,而不是将原始数据无线传输到云进行处理(无线传输是一个显著的能源消耗)。
相对于传统的计算硬件,生物神经元的能量效率主要是由于这些神经元的两个特征。首先,生物神经元只传输模拟能量的短脉冲(尖峰),而不是保持代表单个浮点数或整数的许多位。在传统硬件中,这些位需要持续的能量流来维持 0 或 1 状态,除非使用慢得多的存储器类型(非易失性 RAM)。
第二,在生物神经元中,记忆和处理位于同一位置。也就是说,突触强度是网络的长期记忆(递归连接可以维持短期记忆,但那是其他一些帖子的话题),它们参与了处理(棘波加权和传输),并且与处理的其他方面(细胞体中的能量积累)非常接近。相比之下,传统硬件定期将位从 RAM 传输到处理器,这是一段相当长的距离和相当大的能量消耗。
许多研究实验室和私人公司正在致力于提供这些好处的新型硬件。前景各不相同,但我们可能会在十年内看到可行的、商业化的基于忆阻器的硬件。应该注意的是,迄今为止,基于脉冲的算法在性能上略逊于基于深度学习神经元的算法。然而,一旦相关硬件的可用性变得明显,利用大量神经元的能力以及对基于尖峰信号的算法的研究量的增加,可能会扭转这种状况。
结论
在我们看来,深度学习模型和生物大脑之间的相似性近年来被许多媒体文章大大夸大了。尽管如此,神经科学家和许多人工智能研究人员都很清楚这些差异,并正在努力为人工智能模型带来更大的神经现实主义,希望超越我们可能正在走向的深度学习高原。
我们已经忽略了生物和深度学习神经元之间的许多其他差异,这些差异可能解释了哺乳动物智能和当前人工智能之间的巨大差异。这些神经元网络的差异也很关键。请关注我们未来关于网络中的“真实”重现、网络微观和宏观架构以及其他主题的帖子。
非视觉任务的深度学习视觉
原文:https://towardsdatascience.com/deep-learning-vision-non-vision-tasks-a809df74d6f?source=collection_archive---------17-----------------------
了解创造性数据处理如何允许将深度学习视觉的全部功能用于非视觉任务。
介绍
近年来,深度学习彻底改变了计算机视觉。感谢转移学习和惊人的学习资源,任何人都可以在几天甚至几个小时内获得最先进的结果,通过使用预先训练的模型并根据您的领域进行调整。随着深度学习变得商品化,需要的是它在不同领域的创造性应用。
今天,计算机视觉中的深度学习已经在很大程度上解决了视觉对象分类、对象检测和识别。在这些领域,深度神经网络的表现优于人类。
即使你的数据不是可视化的,你仍然可以利用这些视觉深度学习模型的力量,主要是CNN。要做到这一点,您必须将非视觉领域的数据转换为图像,然后使用在图像上训练的模型之一来处理您的数据。你会惊讶于这种方法有多么强大!
在这篇文章中,我将展示 3 个公司创造性地使用深度学习的案例,将视觉深度学习模型应用到非视觉领域。在这些情况中的每一个中,非计算机视觉问题都被转换并以这样的方式陈述,以便利用适合于图像分类的深度学习模型的能力。
案例 1:石油行业
游梁泵常用于石油工业,从地下提取石油和天然气。它们由一台连接在活动横梁上的发动机驱动。游梁将发动机的旋转运动转换为抽油杆的垂直往复运动,抽油杆充当泵并将油输送到地面。
A walking beam pump, also known as pumpjack. Source.
同任何复杂的机械系统一样,游梁式抽油机容易出现故障。为了帮助诊断,测力计被连接到抽油杆上,用于测量抽油杆上的载荷。测量后,绘制出测功机泵卡,显示发动机旋转循环各部分的负载。
An example dynamometer card. Source.
当游梁泵出现问题时,示功图会改变形状。通常会邀请专业技术人员来检查卡,并判断泵的哪个部分出现故障以及需要采取什么措施来修复。这一过程非常耗时,需要非常有限的专业知识才能有效解决。
另一方面,这个过程看起来可以自动化,这就是为什么经典的机器学习系统被尝试但没有取得好的结果,大约 60%的准确率。
将深度学习应用于该领域的公司之一是贝克休斯。在他们的案例中,示功图被转换成图像,然后用作 Imagenet 预训练模型的输入。结果非常令人印象深刻——通过采用一个预训练的模型并用新数据对其进行微调,准确率从 60%上升到 93%。在进一步优化模型训练后,他们能够达到 97%的准确率。
An example of a system deployed by Baker Hughes. On the left, you can see the input image, and on the right is a real-time classification of failure mode. The system runs on a portable device, and classification time is shown in the lower right corner. Source.
它不仅击败了以前基于经典机器学习的方法,而且公司现在可以更加高效,因为不需要光束泵技术人员花时间来诊断问题。他们可以马上来修理机械故障。
要了解更多信息,您还可以阅读讨论类似方法的论文。
案例 2:在线欺诈检测
计算机用户在使用计算机时有独特的模式和习惯。浏览网站时使用鼠标的方式或撰写电子邮件时使用键盘的方式都是独一无二的。
在这种特殊情况下,Splunk 通过使用用户使用计算机鼠标的方式解决了用户分类的问题。如果您的系统可以根据鼠标使用模式唯一识别用户,那么这可以用于欺诈检测。想象以下情况:欺诈者窃取某人的登录名和密码,然后使用它们登录并在网上商店进行购买。他们使用计算机鼠标的方式对他们来说是独一无二的,系统将很容易检测到这种异常情况,防止欺诈性交易的发生,并通知真正的账户所有者。
使用特殊的 Javascript 代码,可以收集所有的鼠标活动。该软件每隔 5-10 毫秒记录一次鼠标活动。因此,每个用户的数据可能是每个用户每页 5000–10000 个数据点。这些数据代表了两个挑战:第一个是每个用户都有大量数据,第二个是每个用户的数据集将包含不同数量的数据点,这不是很方便,因为通常不同长度的序列需要更复杂的深度学习架构。
解决方案是将每个用户在每个网页上的鼠标活动转换成一个单独的图像。在每幅图像中,鼠标移动由一条线表示,该线的颜色对鼠标速度进行编码,左右点击由绿色和红色圆圈表示。这种处理初始数据的方式解决了两个问题:首先,所有图像的大小都相同,其次,现在基于图像的深度学习模型可以与这些数据一起使用。
In each image, mouse movements are represented by a line whose color encodes mouse speed and left and right clicks are represented by green and red circles. Source.
Splunk 使用 TensorFlow + Keras 构建了一个深度学习系统,用于对用户进行分类。他们进行了两个实验:
- 对金融服务网站的用户进行分组分类—访问相似页面的普通客户与非客户。2000 幅图像的相对较小的训练数据集。在训练基于 VGG16 的修改架构仅 2 分钟后,系统能够以超过 80%的准确度识别这两个类别。
- 用户的个体分类。任务是为一个给定的用户做出一个预测,它是这个用户还是一个模仿者。只有 360 张图像的非常小的训练数据集。基于 VGG16,但进行了修改,以考虑到小数据集并减少过度拟合(可能是丢弃和批量标准化)。经过 3 分钟的训练,准确率达到了大约 78%,考虑到这项任务的挑战性,这是非常令人印象深刻的。
要了解更多信息,请参考描述系统和实验的全文。
案例 3:鲸鱼的声学探测
在这个例子中,谷歌使用卷积神经网络来分析音频记录,并在其中检测座头鲸。这对于研究目的是有用的,例如跟踪单个鲸鱼的运动,歌曲的属性,鲸鱼的数量等。有趣的不是目的,而是数据如何被处理以用于卷积神经网络,卷积神经网络需要图像。
将音频数据转换成图像的方法是使用频谱图。频谱图是音频数据基于频率的特征的可视化表示。
An example of a spectrogram of a male voice saying “nineteenth century”. Source.
在将音频数据转换为频谱图后,谷歌研究人员使用了一种 ResNet-50 架构来训练模型。他们能够实现以下性能:
- 90% 精度 : 90%被归类为鲸鱼歌曲的音频片段被正确分类
- 回想一下:给定一段鲸鱼歌曲的录音,有 90%的可能会被贴上这样的标签。
这个结果非常令人印象深刻,肯定会对鲸鱼研究人员有所帮助。
让我们把注意力从鲸鱼转移到处理音频数据时你能做什么。创建声谱图时,您可以选择要使用的频率,这取决于您拥有的音频数据的类型。你会希望人类讲话、座头鲸歌曲或工业设备录音使用不同的频率,因为在所有这些情况下,最重要的信息都包含在不同的频带中。您必须使用您的领域知识来选择参数。例如,如果您正在处理人类语音数据,那么您的首选应该是一个梅尔倒谱频谱图。
有一些很好的软件包可以处理音频。 Librosa 是一个免费的音频分析 Python 库,可以使用 CPU 生成频谱图。如果你在 TensorFlow 中开发,想在 GPU 上做谱图计算,那也是可能的。
请参考最初的谷歌人工智能博客文章以了解更多关于谷歌如何处理座头鲸数据的信息。
结论
总而言之,本文中概述的一般方法遵循两个步骤。首先,找到一种方法将你的数据转换成图像,其次,使用预训练的卷积网络或从头开始训练一个。第一步比第二步更难,这是你必须有创造力的地方,并思考你拥有的数据是否可以转换成图像。我希望我提供的例子能够对解决您的问题有所帮助。如果你有其他的例子或问题,请写在下面的评论里。
参考
- 面向石油&天然气的物联网——大数据和 ML 的力量(Cloud Next '18)
- 利用人工神经网络预测游梁式抽油机示功图
- Splunk 和 Tensorflow 的安全性:利用行为生物识别技术捕捉欺诈者
- 使用卷积神经网络对座头鲸进行声学检测
原载于我的网站pechyonkin . me。
可以在 Twitter 上 关注我 。再来连线一下LinkedIn。
用气泡进行深度学习
原文:https://towardsdatascience.com/deep-learning-with-air-bubbles-da151b41368c?source=collection_archive---------32-----------------------
未来的技术
Glass 以光速零功率识别人脸
Photo by David Gavi on Unsplash
2070 年 7 月 12 日
晚上 7 点
当我沿着路边走向我的前门时,我感到疲惫不堪。埃隆·马斯克的葬礼是悲伤的,快乐的,然后又是悲伤的。为了向马斯克致敬,几乎所有人都喝醉了,但谢天谢地,我开始清醒了。
Elon Musk (1978–2070) Inventor, Entrepreneur, Hyperlooper
我坐了五分钟的 hyperloop 回家,有点不舒服;我周围的世界是一个慢动作旋转木马。我真的不记得我的密码和密码了。我只希望我没走错房子。
门的中央是一个不起眼的长方形半透明玻璃。今天看到很开心;它知道我是谁,会让我进去——不需要密码。它甚至不需要电。它只需要我的脸,就像我妈妈一样。
玻璃的背面有一个面板,有五个面,其中一个是我的。现在它肯定亮了——让每个人都知道我在前线。很快它会触发一个信号,打开门并启动空调。
正如你所猜测的,这不是普通的玻璃。它是一款能够进行深度学习的 智能眼镜 。
在一毫米厚的身体内,气泡被精心排列,以模仿深层神经网络。但与 2019 年的神经网络不同,这些网络不是排列在离散的层中,而是以一种随机的混乱方式排列。
一束光线进入玻璃,被右边的气泡散射。一个更大的气泡将它弹向左下角,从那里它被直接踢回前面。一个变形虫大小的微小气泡再次将它聚焦到背面。
Electromagnetic field from incoming light wave is modulated by inclusions in glass — air bubbles and non linear materials. From ‘Nanophotonic media for artificial neural inference’
这种光学介质的原理与五十年前由威斯康星大学和麻省理工学院的一个团队在 2019 年 7 月在光子学研究杂志上首次提出时大致相同。
他们的论文建立了集成人工智能的智能眼镜的概念证明。
气泡是一种线性散射体,也就是说它散射的光与其接收到的光成一定比例。
然而,深度学习需要非线性激活——必须有某种东西充当开关。在传统的神经网络中,这些作为' softmax '函数、 RELU '、 tanh activations 等被写入代码。简而言之,这些激活就像海狸水坝一样工作——它们只在内部阈值被超过时才传输信息。
为了给结构增加非线性行为,玻璃还具有少量非线性材料,例如光学可饱和吸收体和光子晶体。
一束光线穿过十几个气泡后,击中其中一个非线性点。只有当强度超过一定限度时,才允许通过。否则,这列光就完了。
在团队 2019 年研究的例子中,眼镜模拟学会了识别手写数字。(有意思的是我们今天还在用 MNIST 数据集!)
The light from the image of the digit on the left is channeled by the inclusions to the third spot on the right panel. Corresponding to ‘2’. From ‘Nanophotonic media for artificial neural inference’
数字 2 的图像(如上所示)可以落在 2D 玻璃的左侧。单独的光线被散射和再散射,直到它们开始聚集在右侧的一个地方——靠近“2”的标签。
威斯康星-麦迪逊-麻省理工学院团队无法想象他们的玻璃是如何制造的。
多亏了我们在光子结构的逆向设计方面取得的巨大进展,这些眼镜可以做得非常精确。我们可以在 10 纳米范围内控制气泡的走向。
我应该停止盯着玻璃,现在就进屋去。这个星球的缺氧令人眩晕,尤其是在晚上。
但是毫无理由地,我想到了这种材料的逻辑回归交叉熵函数。这与任何其他数字识别算法都是一样的。除了现在的梯度下降函数优化了介质的介电常数——而不是虚拟神经元中的虚拟数字。
想到在短短的五十年里,这些模拟神经网络到处都可以找到,有点令人惊讶。
为什么不会呢?他们使用无动力以光速工作!这种计算内置于他们的身体中——就像一种拥有某种进行深度学习的器官的动物。
我现在漫无边际。我真的应该进去了。
但是我犹豫了。一分钟后,当戴莫斯在东方的天空升起时,我将看到我的影子克隆成两个的不寻常的景象。
在远处,我可以看到十个火箭助推器同步庆祝着陆。马斯克终于走了。
我打开门,走了进去。
Photo by Jared Evans on Unsplash
利用磁共振和计算机断层扫描图像进行深度学习
原文:https://towardsdatascience.com/deep-learning-with-magnetic-resonance-and-computed-tomography-images-e9f32273dcb5?source=collection_archive---------8-----------------------
医学图像的数据、预处理技术和深层网络设计简介
开始将深度学习应用于磁共振(MR)或计算机断层扫描(CT)图像并不简单;寻找合适的数据集、预处理数据以及创建完成工作所需的数据加载器结构是一件痛苦的事情。在这篇文章中,我希望能减轻初来乍到者的痛苦。为此,我将链接到几个免费可用的数据集,回顾一些特定于 MR 和 CT 的常见/必要的预处理技术,并展示如何使用 fastai 库来加载(结构)MR 图像并为合成任务训练深度神经网络。
MR 和 CT 图像概述
在我们进入这篇文章的实质内容之前,快速回顾一下我们将要讨论的医学图像以及讨论中的图像类型的一些特点是很有用的。我将只谈论结构磁共振图像和(在较小程度上)计算机断层扫描(CT)图像。这两种类型的成像模态都用于观察组织的结构;这与分别对血流活动和代谢活动成像的功能性 MR 图像(fMRI)或正电子发射断层扫描(PET)相反。
对于完全不熟悉医学图像的人,请注意医学图像统计不同于自然图像统计。例如,乳房 x 光照片看起来一点也不像人类用智能手机拍摄的任何照片。这是显而易见的;然而,我认为在设计网络和处理数据以制作某种机器学习(ML)算法时,记住这一点很重要。这并不是说使用普通的网络或从医学成像以外的领域转移学习是行不通的;这只是说,了解医学成像常见问题的特征将有助于您调试您的算法。我将在下面的预处理部分讨论这些特征的具体例子,并展示减少这些独特问题的影响的方法。
我不打算详细介绍结构磁共振成像的复杂性。关于磁共振更深入的细节,一个很好的起点是这个网站,它深入探讨了与磁共振合作的 ML 从业者所关心的任何话题。我会注意到磁共振扫描仪可以产生许多不同类型的磁共振图像。例如,有 T1 加权、T2 加权、PD 加权、流体衰减反转恢复(FLAIR)等。让事情变得更复杂的是,这些类型的图像还有子类型(例如,T1 加权图像有以下几种类型:MPRAGE、SPGR 等。).根据您的任务,这些信息可能非常有用,因为每种类型和子类型的图像都有其独特的特征。所有这些不同类型图像的原因是因为 MR 扫描仪是灵活的机器,可以根据不同的脉冲序列对其进行编程以收集不同的信息。结果是,所有这些图像不仅仅是冗余信息;它们包含放射科医生(或我们作为图像处理者)关心的关于临床标记的有用和独特的信息。同样,我将在预处理部分讨论更多关于 MR 独特方面的细节。
虽然有对比和非对比 CT,但 CT 扫描仪可以生成的图像种类并不多。模糊地说,CT 扫描仪通过你发射高能光子,其能量是通过光子击中你身体另一侧的探测器计算的。当像这样的图像从各种角度拍摄时,我们可以利用我们对获取图像时的几何形状的了解来将图像重建成 3D 体积。能量的物理表示让我们将发现的强度值映射到一个标准标度,这也简化了我们的生活,在预处理部分中有更多的讨论。我应该注意到,虽然 MR 擅长软组织对比度(例如,辨别大脑中灰质和白质的能力),但 CT 的软组织对比度有点差。例如,参见 MR 图像和 CT 图像的头部下方扫描,注意灰质(沿着大脑外部)和白质(灰质内部较亮的组织)之间的对比,以及两个图像中大脑中存在的总体噪声水平。
Example of a CT scan (left) and (T1-weighted) MR scan (right) [from the Qure.ai and Kirby 21 dataset, respectively]
不总是使用 MR 扫描的一些原因是:1)一些人由于各种原因(例如,没有通路、某些类型的金属植入物等)不能使用。),2)与 CT 扫描相比,MR 扫描花费相对较长的时间,以及 3)放射科医师对 CT 能够提供的特定测量感兴趣(例如,查看骨骼结构)。现在,我们对数据和一些复杂的成像模式有了基本的了解,让我们来讨论一些数据集。
数据集
标记数据对于医学图像来说有些稀疏,因为放射科医生很贵,医院担心诉讼,而研究人员(通常过度)保护他们的数据。因此,在 MR 或 CT 中没有 ImageNet 等效物。然而,根据应用领域的不同,有许多常用的数据集。由于我主要处理脑部 MR 图像,因此我将提供一个易于访问的 MR 和 CT(脑部)图像数据集的小列表,以及项目符号末尾括号中的数据格式:
- Brainweb :具有组织/病变分割的模拟正常和多发性硬化大脑(MINC)
- Kirby 21 :对一组 21 名健康患者进行两次扫描(NIfTI)
- IXI 数据集:一组 600 名健康受试者的扫描(NIfTI)
- Qure.ai CT 头部扫描数据:一组 491 个带病理的头部 CT 扫描[无分割,但有放射学报告] (DICOM)
这里有一个不那么容易下载(但非常有用)的数据集列表。
- BraTS 2018 脑瘤数据:脑瘤患者大集合连同肿瘤分割(mha)
- ISBI 2015 多发性硬化挑战数据:20 名多发性硬化(MS)患者的集合【只有 5 名患者进行了病灶分割】(NIfTI)
我没有使用过下面的数据集,但我知道有人使用过,为了完整起见,我将它们包括在内。
- 绿洲
- 低剂量 CT
- 快速磁共振成像
- ADNI
另一个寻找数据集的地方是在 OpenNeuro ,这是一个为研究人员提供大脑成像数据集的存储库;据我所知,它主要由功能磁共振成像组成。如果你对磁共振和 CT 脑 T4 图像之外的东西感兴趣,那么很不幸,我不是一个很好的资源。我的第一个猜测是查看此处列出的“重大挑战”,看看是否有可能访问数据。
不要把 lede 埋得太深,但是也许获取上述数据最简单的方法就是通过这个网站。我不确定所有东西都被允许放在那里,这就是为什么我推迟提出这个问题。
预处理
使用 MR 和 CT 需要进行大量的数据处理和预处理。我将在下面概述最基本的必需品。
首先要考虑的是如何将图像加载到 python 中。最简单的路线是使用ni Abel。然后你可以简单地使用
import nibabel as nib
data = nib.load('mydata.nii.gz').get_data()
获取一个 numpy 数组,其中包含了mydata.nii.gz
文件中的数据。注意,我将这个 3D 体积的索引称为体素,它是 2D 图像的像素的 3D 等价物。至少对于大脑图像的工作,我建议总是将文件转换成 NIfTI(对应于。nii 或. nii.gz 扩展名)。我发现先把所有东西都转换成 NIfTI 让我的生活更容易,因为我可以假设所有的输入图像都是 NIfTI 类型的。这里有一个工具将 DICOM 转换成 NIfTI,这里有一个脚本将 MHA 转换成 NIfTI,这里有一个脚本将 PAR/REC 文件转换成 NIfTI。您可能需要处理更多的文件格式,您可以使用其中的一些脚本作为灵感来转换这些文件类型。
我们将首先概述重采样、偏场校正和配准,它们是任何医学图像分析的主要内容。对于这些预处理步骤,我建议使用 ANTs,特别是 ANTsPy(假设您有 python 背景)。ANTs 得到了积极的维护,并拥有可靠的工具来解决所有这些(以及更多)问题。不幸的是,ANTsPy 并不总是容易安装,但我相信人们正在努力解决一些问题,一旦你安装并运行了它,你就可以从 python 中访问 ant 提供的大部分工具。特别是,它支持我将在下面讨论的重采样、偏差场校正和配准预处理步骤。
与自然图像一样,MR 和 CT 图像没有标准的分辨率或标准的图像尺寸。我认为这一事实在 MR 和 ct 中更为重要,必须考虑到最佳 ML 性能。请考虑以下情况:您使用以 1×1×3 毫米分辨率采集的数据来训练 3D 卷积神经网络,然后将 1×1×1 毫米的图像输入到网络中。我认为结果不是最佳的,因为卷积核不会使用相同的空间信息。这是有争议的,我还没有仔细检查这个问题,但是如果你在测试时遇到问题,非标准的解决方案是要记住的。我们可以天真地解决非标准分辨率问题,将图像重新采样到所需的标准分辨率(当然,为了获得最佳质量,使用三次 B 样条)。
对于许多应用,MR 和 CT 通常都需要一个称为配准的过程,以便在一组图像中对齐对象,从而进行直接比较。我们为什么要这么做?假设您想学习一个函数,该函数获取一个 MR 图像并输出对 CT 图像的估计。如果您有成对的数据(即来自同一患者的 MR 和 CT 图像),那么处理这个问题的一个简单方法是学习图像强度之间的体素映射。然而,如果解剖结构没有在图像空间中对齐,那么我们不能以监督的方式学习该图。我们通过配准图像来解决这个问题,实际上,我们在实验部分检查了这个问题。
接下来的两个问题(在接下来的两个段落中描述)是 MR 特有的。首先,由于 MR 图像中的扫描仪,我们有不均匀的图像强度。由于这种不均匀性不是生物特征,我们通常希望消除它,我们通过一种称为偏场校正的过程来实现(我将在实验部分讨论一种解决方案)。
MR 的另一个问题是不同 MR 扫描仪的组织强度不一致。虽然 CT 图像有一个标准的强度等级(见豪恩菲尔德单位),但我们对 MR 图像就没那么幸运了。MR 图像绝对没有而不是有标准的尺度,如果不在预处理中考虑,对算法性能的影响会相当大。请看下面的图像,其中我们绘制了一组 T1 加权 MR 图像的直方图,没有应用任何强度归一化(见标题中带有“Raw”的图像)。这种变化是由于扫描仪造成的影响,而不是由于生物学,这是我们通常关心的事情。
Histograms of image intensities from a cohort of T1-weighted brain images (left: white-matter mean normalized, right: no normalization applied)
有一系列强度标准化技术试图消除这种扫描仪变化(其中一些我已经收集在这个名为intensity-normalization
的库中)。这些技术从非常简单的(例如,简单的标准化,我将称之为 z 分数标准化)到相当技术性的(例如,拉威尔)。对于神经成像,可以在模糊 C 均值(FCM)归一化技术中找到速度和质量的良好组合,该技术基于 T1 加权图像在白质(WM)、灰质和脑脊液之间创建粗略的组织分类分割。WM 分割掩模然后用于计算图像中 WM 的平均值,其被设置为某个用户定义的常数。这种标准化技术似乎总能在大脑图像中产生预期的结果。如果你不是在处理大脑图像,那么你可能想看看 Nyúl & Udupa 方法或者简单的 z 分数归一化。所有这些规范化方法都可以作为命令行接口(或可导入模块)在intensity-normalization
存储库中获得。
我们要考虑的最后一个预处理步骤是针对大脑图像的。在大脑图像中,我们通常只关心大脑,而不一定关心大脑外部的组织(例如,颅骨、脂肪和大脑周围的皮肤)。此外,这种外来的组织会使学习过程复杂化,并使分类、分割或回归任务出错。为了解决这个问题,我们可以使用颅骨剥离算法来创建大脑的面具,并将背景置零。最简单的方法(在 MR 中)是使用 ROBEX(一种命令行工具),它通常能很好地从图像中提取大脑。我见过它在一些包含大病理或成像伪影的数据上失败过几次,但除此之外,它通常对大多数机器学习任务来说已经足够好了。值得一提的是,我会尽量避免剥离你的数据,因为这只是你的预处理程序中的另一个可能的失败点,但有时它会有很大的帮助。
因为 MR 和 CT 图像不像 JPEG 那样是标准的,所以你的计算机没有一种固有的方式来显示它。如果你想可视化你的数据,看看非 DICOM 图像的 MIPAV 和 DICOM 图像的 Horos 。查看您的数据总是好的,尤其是在预处理之后,这样我们可以验证一切看起来都是合理的。例如,也许注册失败了(这种情况经常发生),或者也许颅骨剥离失败了(这种情况也经常发生)。如果您将无用的数据通过管道传输到 ML 算法中,您可能会得到无用的输出,并且会浪费大量时间进行不必要的调试。所以善待自己,检查数据。
为 MR 或 CT 应用培训深度网络
虽然应用于 MR 和 CT 的深度神经网络越来越多地转向 3D 模型,但 2D 模型取得了很大成功。如果您的 GPU 内存有限,或者您的训练数据非常有限,您可能希望使用 2D 网络来充分发挥网络的性能。如果您使用 3D 网络,在通过网络传递完整图像或补丁时,您将很快遇到内存问题。
如果您决定 2D 网络是您的应用程序要走的路(一个合理的选择),您将需要找出/设计一个数据加载器来处理这一点。在使用复杂的数据加载器将 3D 图像转换为 2D 图像片或切片一段时间后,我意识到这是一个不必要的负担,使得使用预建的数据加载器/数据增强工具来帮助训练变得更加困难。因此,我对这个问题的建议解决方案是简单地将 3D 体积转换成 2D 图像。因为原始卷是浮点数,所以我选择了支持这种类型的 TIFF 图像格式。这里有一个命令行脚本,它获取一个 NIfTI 图像的目录,并创建一个相应的 2D TIFF 图像的目录(带有一些选项来创建基于轴的切片,并只从图像的一部分创建切片,以避免背景切片)。
在下一节中,我将构建一个具有 3D 卷积层的深度神经网络。我这样做是为了反对使用 2D 卷积层,因为——一旦您将 3D 体积转换为 TIFF 等 2D 图像——您基本上可以使用任何 2D 架构,将头部替换为适当的应用程序。由于 3D 问题稍微有点棘手,我将在下面深入探讨。
实验
如果你是刚刚来到这篇博文(05/07/20 之后),请注意 fastai 包已经发生了重大变化,下面的代码可能无法按预期工作。但是,下面的代码示例和一般的实验设置对于学习还是很有用的。值得一提的是,对于未来的深度学习项目,我建议使用 PyTorch 而不是 fastai。如果你想在 PyTorch 中支持 NIfTI,我有一个主动维护的包,其中有工作代码示例和可导入的函数。******
在本节中,我将概述使用 pytorch 和 fastai 为 MR-to-MR 合成任务训练 3D 卷积神经网络所需的步骤。如果你只是想看看代码,那么还有一个笔记本,里面包含了大部分实验(不包括预处理)这里。
设置如下:我们将训练一个非常小的 resnet 从一个 MR 对比到另一个 MR 对比拍摄整个 3D 体积;我们将学习将 T1 加权图像映射到 FLAIR 图像的变换。这个任务被称为 MR 图像合成,我们将该网络称为合成网络。这种类型的合成有多种应用,但是这个问题的动机主要是:MR 扫描时间有限,所以不能收集所有的对比。但是我们想要吃蛋糕并且拥有它,我们有时想要那些未收集的对比度用于图像处理目的。因此,我们使用实际收集的数据创建一些假数据,这些假数据将是我们合成网络的结果。
在这个实验中,我将分别使用来自 Kirby 21 数据集的 11 幅和 7 幅图像作为训练和验证。所有图像都被重新采样为 1x1x1 mm,使用 N4 进行偏场校正,并且使用 ANTsPy 将 FLAIR 图像(仿射)配准到 T1 加权图像。查看这里的和这里的获取我用来做预处理的实际代码(当亮度归一化包和 ANTsPy 一起安装时,这两个都可以作为命令行接口使用)。最后,使用整个图像单独对所有图像进行 z 分数归一化。
既然我们已经在一定程度上激发了这个问题,并讨论了我们将使用的数据,那么让我们来看看代码。下面的代码块定义了一些使用 fastai 的必要结构,具体来说就是使用 data_block API。
Dataloaders classes and functions for NIfTI images in fastai
这里没有什么特别要注意的,除了一旦你弄清楚如何设置这些类型的结构,它们是非常方便的(更多细节见项目列表教程)。注意,当前的设置并不支持所有的功能——为了尽可能简单,我把它去掉了——但是它可以完成任务。下面我将展示如何创建训练和验证数据加载器。首先,让我们定义一个预处理转换:
Relevant data transforms for our application
为什么我要定义这个奇怪的裁剪函数?原因是双重的。第一个原因是颈部在 FLAIR 图像中不存在,但是在 T1 加权图像中存在。我不希望网络学会将组织归零,所以我只使用与轴面相对应的轴上 20-80%范围内的数据来删除这部分数据。第二个原因是,我可以将两倍的样本放入一个批次中(这意味着批次大小为 2)。批量较小的原因是,正如我之前提到的,具有大图像的 3D 网络是内存密集型的。为什么没有其他数据增强?不幸的是,pytorch 或 fastai 本身并不支持 3D 变换,所以我不得不加入我自己的 3D 变换,我这样做并不是为了简单。现在让我们使用 fastai 的 data_block API 来创建训练和验证数据加载器:**
Define the dataloader with the data block API in fastai
您可以查看笔记本了解更多细节,但本质上,我将 T1 加权图像放在一个带有train, valid, test
子目录的目录和一个带有 FLAIR 图像的平行目录中。get_y_fn
功能抓取与源 T1 加权图像相对应的 FLAIR 图像。查看这里的以获得对其余命令的更深入的解释。注意,(tfms,tfms)
意味着我将之前定义的裁剪应用于训练集和验证集。将该转换应用于验证集并不理想,但由于内存限制,这是必需的。现在,让我们创建一些 3D 卷积和残差块层,我们将使用它们来定义我们的模型:
Define some custom 3D layers
我密切关注 2D 卷积和残差块层的定义,如在 fastai 知识库中所定义的。顺便提一下,我在conv3d
定义中留下了光谱归一化和权重归一化例程,但是令人失望的是,使用这些方法得到的结果比使用批处理范数时更差(我仍然不确定批处理范数是在激活之前还是之后应用)。现在让我们使用上面的层来定义我们的模型:
Define our network
这里我刚刚定义了非常小的 resnet 模型。为什么这么少层?我正在使用我的 GPU 在内存中所能容纳的最大网络。创建具有整个 3D 体积的许多通道和剩余连接是 GPU 存储器的负担。另一个可能的有趣之处是,我在最后使用了一个 1x1x1 内核,根据经验,这可以产生更清晰的图像(我认为这是相当标准的)。作为一个注意,我意识到我应该从最后一层移除激活;然而,这不是问题,因为我正在对背景为的图像进行 z 分数归一化(即,平均减去并除以标准差)。几乎为零的背景占据了图像的绝大部分。因此,z 分数归一化本质上将背景(对应于平均值)置于零,这使得头部的强度大于零。对 ReLU 来说是个好结果。现在让我们来训练这个网络:**
Training
这也很正常。使用均方误差是因为我们希望源 T1 加权图像中的每个体素强度与相应目标 FLAIR 图像的体素强度相匹配。除了使用单周期 策略之外,我们还使用lr_find
来帮助我们选择更大的学习速率(如这里的所述)以进行更快的训练。我总是将我的训练和验证数据收集到一个 CSV 文件中,以查看网络如何融合,尤其是在启动 jupyter 笔记本电脑是一件痛苦的事情的机器上。我选择了 100 个时期,因为我运行了几次,并没有注意到随着时期的增加,性能有了很大的提高。
训练完成后,我们将整个图像(在训练或验证中都没有看到)输入到网络中。下图显示了一个例子,其中合成结果是最右边的图像(标题为“Syn”)。
Example synthesis result with the network defined above (from left to right: the input T1-weighted image, the true FLAIR image, and the synthesized FLAIR image)
虽然上图可以有更好的窗口/级别设置以便更好地比较,但我们看到 T1 加权图像确实呈现了真实 FLAIR 图像的许多特征。最值得注意的是,在大脑内部,我们看到白质变得不如灰质明亮,而脑脊液仍然是黑暗的。虽然噪声特征不相同,但是在真实的天赋中有一些合成图像中没有捕捉到的亮点。
这个结果无论如何都不是最先进的,但有趣的是,我们可以用如此小的数据集、没有数据增强和非常小的网络来学习近似变换。如果有更多的数据、数据扩充和更大的网络,这个网络肯定会更好,但这只是一个简单的教学玩具例子。我应该注意到,除非你有一个特别大的 GPU(与我最后的说法相矛盾),否则你可能无法用完整的图像来训练这个网络。你可能不得不使用 3D 补丁或 2D 切片(或 2D 补丁)。
结论
希望这篇文章为您提供了一个使用 fastai 将深度学习应用于 MR 和 CT 图像的起点。像大多数机器学习任务一样,开始时需要大量特定领域的知识、数据争论和预处理,但一旦掌握了这些,使用 pytorch 和 fastai 训练网络就相当容易了。从这里去哪里?我会从我在数据集部分发布的一个链接中下载一个数据集,并尝试做一些类似于我上面展示的事情,甚至尝试重现我所做的事情。如果你能达到那个阶段,你就能轻松地将深度学习应用于 MR 和 CT 中的其他问题。
我应该注意到,人们正在努力创建标准代码库,从中可以将深度学习应用于 MR 和 CT 图像。我知道的两个是 NiftyNet 和 medicaltorch 。NiftyNet 抽象掉了大部分的神经网络设计和数据处理,因此用户只需调用一些命令行界面,就可以下载预先训练好的网络,对其进行微调,以及做任何事情。所以如果这对你的需求来说足够好,那就继续吧;这似乎是一个很好的工具,并且有一些预先训练好的网络可用。medicaltorch 在 pytorch 中提供了一些带有医学图像的数据加载器和通用深度学习模型。我还没有广泛的测试,所以我不能评论他们的效用。
如果不喜欢 python,R 里有 neuroconductor 或者 Julia 里有 NIfTI.jl 和 Flux.jl 包分别可以读取 NIfTI 图像和构建神经网络。还有无数其他相关的软件包,但这些是我第一个想到的,也是我用过的。
最后一点,如果你有幸为 MR 或 CT 创建了一个不错的应用程序,一定要分享你的成果!写一篇论文/博客,放在论坛上,分享网络权重。如果能看到更多的人将深度学习技术应用到这个领域,并在可能的情况下推动该领域的边界,那将是非常棒的。祝你好运。
利用卫星数据进行深度学习
原文:https://towardsdatascience.com/deep-learning-with-satellite-data-b78b20708de?source=collection_archive---------4-----------------------
“我们现在正在创造的火箭、卫星、宇宙飞船,
我们正在给宇宙授粉。”——尼尔·杨
概述—卫星数据—数据收集—模型—结果
概述
今年 1 月在意大利贝内文托的桑尼奥大学,我和我的朋友图马斯·奥伊卡里宁(Tuomas Oikarinen)创建了一个(半自动)下载公开图片的管道,并根据数据训练了一个三维卷积神经网络。最终,我们的模型在 Sentinel-2 光学卫星图像上实现了大约 0.65 的平衡精度。我将更详细地介绍结果(以及为什么这个模型实际上是有用的)。在 Silvia Ullo 的指导下,在她的研究生 Maria Pia Del Rosso、Alejandro Sebastianelli 和 Federico Picarillo 的帮助下,我们最终向一个遥感会议提交了一篇论文[1]!
如果你想直接进入代码,这里的是到 Github 库的直接链接。
我将以相对技术性的方式(包括代码)描述如何从 google earth 引擎快速下载一些卫星图像,然后用它们来训练一个 3 维卷积神经网络。
具体来说,我们使用成对的图像(一个滑坡图像,一个相同地理区域但没有滑坡的图像)作为训练示例。然而,这对于涉及使用公共卫星数据作为影像模型的任何情况都是有帮助的。
卫星数据
在开始收集数据之前,有必要大致了解一下我们将要使用的卫星图像的类型。最容易处理和广泛提供的最新卫星数据来自哥白尼卫星计划。构成哥白尼计划的卫星被称为哨兵卫星。为了观察地面的变化,哨兵 1 号和哨兵 2 号卫星是最有用的。Sentinel-1 提供雷达成像和比 Sentinel-2 更高的分辨率,但也更难使用。与 Sentinel-2 图像相比,你必须对雷达图像进行更多的处理,Sentinel-2 图像基本上适合在裁剪和下载后立即使用。我们最终使用 Sentinel-2 的图像来训练我们的模型。
下面是我们能找到的山体滑坡前后卫星图像的最佳例子。
Before the landslide
After the landslide
我们拥有的绝大多数其他图像对都不那么清晰。即使是这个例子,你也可以看到云层覆盖,光照条件和植被颜色都有很大的不同。此外,我们可以找到的所有自动处理滑坡的不同方法都使用了输入支持向量机的特征,如坡度、土地覆盖、坡向、地形湿度指数等(关于这些方法的论文,见此处和此处)。这里我们感兴趣的问题是一个模型能从少量的光学图像中学到任何关于危险探测的东西吗?
数据采集
给我们的标签来自 NASA 全球滑坡目录,记录了 2000 年代初至 2017 年末的滑坡。这是我们必须处理的编辑版本的截屏:
Processed Landslide Catalog
绿色表示好数据,红色表示差数据,灰色表示位置精度太低,无法保证裁剪会捕捉到它。
整个项目的第一个也是最困难的部分是收集标记数据的干净样本。在花了大量时间摆弄 ESA Copernicus SciHub(欧洲航天局用于下载卫星图像的在线用户界面)之后,我们意识到要实现下载过程的自动化是相当困难的。第一个问题是,你不能在网站上的任何地方手动输入坐标,还有一个事实是,你必须下载整个卫星“图像”,在给定的日期,它覆盖了大约三分之一非洲大小的区域。对于每个示例来说,这最终都超过了 7gb;对我们笔记本电脑的存储容量来说太多了。雪上加霜的是,你不得不花半个小时在地理数据处理软件 SNAP 中预处理图像(顺便提一下,这也很难自动化)。
相反,我们求助于谷歌地球引擎,它可以根据日期、作物进行过滤,显示云密度并提供下载链接,只需点击一个按钮!我们确实花了一段时间来弄清楚如何做到这一点,因为缺乏关于地球引擎的例子/稀疏的文档。入门指南确实给出了你可以期待的 Javascript API 的功能概述,所以我仍然推荐从那里开始。
快速提示:你必须注册成为谷歌地球引擎开发者才能访问我们使用的控制台。幸运的是,这个过程非常简单,你应该很快就能获得批准。按照说明在这里报名。
我们的最终(半)自动化流水线是如何结束工作的,如下所示:
- 在
[cropping_coordinates.py](https://github.com/Yichabod/natural_disaster_pred/blob/master/cropping_coordinates.py)
中输入坐标,计算一个 10 公里见方的坐标。 - 复制输出并替换 Google Earth 引擎控制台中 javascript 代码顶部的变量(我们使用的 javascript 代码)。不要忘记将日期范围更改为您喜欢的日期范围。
- 单击控制台输出中打印的链接,下载平均云密度小于 100 的图像。
瞧啊。您已经有了预处理过的数据集。
Google Earth Engine Dev Console
(简单的技术说明:对于我们的模型,我们选择对每幅图像使用 12 个可用波段中的 5 个。您可以在 javascript 代码中更改这一点。每个波段捕捉不同的波长光谱,你可以在谷歌地球引擎 Sentinel-2 数据集描述上了解更多信息。
型号
Our CNN
对于我们的模型,我们在 Tensorflow 中定义了一个 8 层 CNN(参见这里的代码)。这没什么特别的。我们从 5 层开始,并注意到随着我们增加更多的层,性能略有提高。与你对常规前馈网络的期望相反(参见这个不错的堆叠交换讨论了解一些背景理论),对于 CNN 的深度没有共识。你只需要试一试。
因为我们最终处理的是大约 120 的图像对,而不是我们想要的 12,000,所以我们增加了几个扩展来使我们的模型更加健壮。首先我们使用tf.random_crop
函数随机裁剪图像,然后我们随机翻转和旋转图像的随机部分。我们还尝试在图像中添加随机高斯噪声,但这降低了性能,并真的减慢了训练过程。
结果
我们使用了 5 重交叉验证,这样我们可以使用更多的训练数据,并且仍然可以很好地了解我们的模型在评估集上的表现。
Graph of Accuracy over Epochs
仅仅从光学图像中学习一些东西是可能的,而不需要接触一堆私人的陆地特征!然而,很明显,当验证精度稳定在 0.65 左右时,信号很弱。最明显的改进来自更多的训练例子。虽然我们已经穷尽了 NASA 公开的滑坡目录中的好例子,但是应该有很多国家的滑坡目录以及它们的日期、大小和坐标。
我希望你觉得这个指南有用,或者至少有点意思。我当然喜欢研究它,并解释我们研究背后的动机。
Tuomas and I (third and second from the right) at the European Space Agency
再见。
[1] S. L. Ullo,M.S. Langenkamp,T.P. Oikarinen,M.P. Del Rosso,A. Sebastianelli,F. Piccirillo,S. Sica,“使用 Sentinel-2 图像数据使用卷积神经网络进行滑坡地质灾害评估”,IGARSS 2019–2019 IEEE 国际地球科学与遥感研讨会,日本横滨,2019 年,第 9646–9649 页。
使用 CSV 文件和无代码的机器学习(适用于新手)
原文:https://towardsdatascience.com/deep-learning-with-spreadsheets-and-no-code-love-spreadsheet-602e5d039565?source=collection_archive---------18-----------------------
免责声明 : 这是一个针对机器学习完全初学者,无需任何代码如何入门的帖子。如果你已经知道如何编码和使用机器学习库,你可能不会从中获得太多。
机器学习的核心是函数逼近。给定一组输入变量,机器学习算法试图得出一个可以准确预测输出的函数。
有各种算法来得出这个函数近似值,也称为模型。压力最大的是神经网络,也称为深度学习,这是我们将在本文中讨论的内容。
机器学习过程有三个主要步骤:
- 数据源&准备
- 模特培训
- 预测输出
我们将在本教程中全面介绍前两个步骤,而只简要介绍最后一个步骤。
数据源和准备
数据来源、清理和转换是任何机器学习项目中最耗时,也是最有影响力和最重要的部分。垃圾输入和垃圾输出在大多数编程中都成立,但在机器学习中更是如此。
当你读到关于图像识别误入歧途或医疗保健人工智能无法正常工作的新闻报道时,最有可能的是数据问题,无论是没有收集足够的数据还是收集了不代表真实人口的数据。
在现实世界的机器学习项目中,找到你需要的数据,清理它并转换它将花费大量的时间和令人头痛的事情。然而,出于学习的目的,我们可以利用已经为机器学习而管理和组织的数据集:UCI 库(T16)、Kaggle 数据集(T19)和 ML 数据(T21)。
在这篇文章中,我们将使用一个包含 1985 年国会议员对 16 个不同问题的投票的数据集。利用这些选票,我们将尝试预测该成员是民主党人还是共和党人。
数据集可以在 ML Data 或 UCI 库下载。
选票的值可以是 y , n 和?因此,我们不需要清理任何东西,然而,让我们假设值是 Yes,Y,Y,no,No,??和空白。然后,我们需要清理不一致的值,并确保所有的是、否和缺失的投票都只与一个值相关。
模特培训
为了训练模型,我们需要了解训练和测试数据的概念。
与演绎或基于规则的方法相比,机器学习是一种估计函数的归纳方法。不是使用逻辑和理论来近似函数,而是将数据提供给算法,并使用数据来得出函数。
如果您要训练您的模型,并使用所有数据测试其准确性,那么该模型将非常准确,因为它没有看到任何新的东西。这就好像你练习了一套 100 道数学题,而你的数学考试正好有这 100 道题。你的考试分数可能会很高。
为了避免这个问题,我们将数据集分成测试集和训练集。我们将使用 70%的数据点来训练模型,另外 30%来测试模型的准确性。这样我们就能更好地了解我们的模型有多精确。
我们可以在开始时进行训练和测试分割,但幸运的是,我们将用于训练模型的软件会为我们做到这一点。
我们将使用一个叫做 Weka 的免费软件。使用 Weka 前需要安装 Java。Weka 可以在这里下载:https://sourceforge.net/projects/weka/。
注意:我将使用 Weka 3–8,因此如果您使用其他版本,可能会有一些变化。
下载数据集并安装 Weka 后,启动它。在主屏幕上点击打开文件,转到您下载数据集的文件夹,在文件类型下,选择 CSV 文件并打开文件。
打开它后,您将看到所有不同的列,也称为属性及其值,既有可视化的,也有表格形式的。类下拉列表应该被选择到输出属性或我们试图预测的内容。在这种情况下,这是在 267 名民主党人和 168 名共和党人中划分的政党属性。
现在我们的数据已经导入,是时候训练我们的模型了。呜!
点击顶部工具栏上的分类选项卡。然后点击大选择右下方的按钮。弹出的是 Weka 为你训练模型的所有算法列表。
我们将选择函数下的神经网络算法- >多层感知器。
现在我们要做两件至关重要的事情:
- 指定我们要将多少数据用于训练和测试集
- 指定我们希望算法使用的超参数的值
训练和测试集
在测试选项下,选择百分比分割并指定 70%。这意味着我们将使用 70%的数据进行训练,剩下的 30%进行测试。没有确切的方法知道最好的分割应该是什么,这使得机器学习与其他编程相比更像是一种实验。一般标准是使用 65–80%的数据集进行训练。
高参数
这也是机器学习的另一个实验领域。超参数(算法的不同变量)因算法而异,改变它们会极大地影响模型的准确性。
超参数对不同算法的意义以及如何找到它们的理想值超出了本教程的范围。你可能需要参加一个机器学习课程,或者看几个关于这些主题的教程来理解它们。
还有一种被称为 AutoML 的新技术也开始被采用,其中软件程序通过编程在超参数的不同值之间循环,并确定理想值。
对于本教程,我们将通过试错法,看看哪些超参数值给我们最好的结果。
要选择数值直接点击上的多层感知器-L 0.3 -M 0.2 -N 500 -V 0 -S 0 -E 20 -H 一条线,紧挨着选择按钮。这将弹出一个窗口,如下图所示。
我们今天要修改的两个超级参数是隐藏层和学习率。这些是指神经网络应该具有的层数和函数中的权重应该更新的因子。
让我们试着用提供的学习率和隐藏层运行,看看我们的结果。确保课程为政治 _ 政党并点击开始。
运行模型后,您将获得大量结果。这个数据集和实验的关键结果是正确分类的实例的数量,瞧!我们的模型有 96%的准确率。只是提醒一下,根据数据集或模型,其他错误率可能更适用。
由于我们的默认参数的准确性如此之好,我不会用超参数做实验,但你一定要试一试。尝试不同的超参数值、数据集和测试训练分割将使你对什么有效有更好的直觉,并使你成为更好的机器学习实践者。
但就是这样!恭喜你。你只是用一个文件做了深度学习,没有写代码!
现在我们有了模型,有趣的部分是预测国会议员是民主党人还是共和党人,只要知道他们对这些问题的投票方式。
预测输出
首先我们需要保存我们的模型。右键单击左下方窗格中的模型,然后单击保存模型并保存您的模型。
要完成其余的预测,你可以在这里阅读更多的。或者被我们张贴另一个教程。
快乐机器学习:)
用 x 光眼深度学习
原文:https://towardsdatascience.com/deep-learning-with-x-ray-eyes-eae0ac39b85f?source=collection_archive---------20-----------------------
随着每年执行数百万次诊断检查,胸部 X 射线是用于检测许多疾病的重要且可获得的临床成像工具。然而,它们的有用性可能受到解释方面的挑战的限制,这需要对描述复杂的三维器官和疾病过程的二维图像进行快速和彻底的评估。事实上,早期肺癌(T1)或气胸(T3)在胸部 x 光检查中可能会被遗漏,给患者带来严重的不良后果。
深度学习可以有效地用于发现 X 射线中的异常,以检测各种疾病。由于开源图像的可用性,深度学习在医学图像上的应用变得更加容易。我们将使用来自这个 CXR 数据集的 X 射线图像,尽管我们将只使用其中的两个类。
CXR 数据预处理—增强
现在让我们对 CXR 数据集进行预处理。
- x 射线图像的分辨率非常高;图像大小为 1024 像素 x 1024 像素..
- x 射线图像是单通道图像,而不是 RGB(三通道图像)。
- 中心裁剪不应应用于 x 射线图像,以确保图像角落内的异常不会被遗漏。
这就把我们带到了数据预处理的下一个方面——数据扩充。很多时候,我们拥有的数据量不足以很好地执行分类任务。在这种情况下,我们执行数据扩充。
我们知道池化增加了不变性。如果图像的左上角有异常迹象,通过合并,我们将能够识别左上角附近的左/右/上/下是否有异常。但是训练数据由类似于 翻转、旋转、裁剪、平移、照明、缩放、添加噪声 等的数据扩充组成。模型学习所有这些变化。这大大提高了模型的准确性。因此,即使异常出现在图像的任何角落,模型也能够以很高的准确度识别它。
增强由以下模块应用。数据生成器用于增强。
data gen = imagedata generator(
feature wise _ center = True,
feature wise _ STD _ normalization = True,
rotation_range=10,
width_shift_range=0,
height_shift_range=0,
vertical_flip=False,)
垂直翻转需要设置为“假”。这是因为 CXR 图像有一个自然的方向——从上到下。
CXR 数据预处理——归一化
规范化使得训练过程更加顺畅。这是一个重要的预处理步骤,我们简单讨论一下。
例如,假设你有一些数据点 x1,x2,x3,…,xn。大多数数据点的值的范围在(比如说) -10 到 10 之间,但是少数数据点(比如说 x11 和 x18)的值在 -900 到 1000 之间。
现在,在反向传播中,梯度(直接或间接)与导数 f′(x)相关,其中 f 是激活函数。假设您使用的是乙状窦激活。在 sigmoid 中,f′(x)在 x=-800 和 x=900 处的值几乎为零,但在 x=-1 和+1 之间是一个小正数。
Shape of Sigmoid Function
这使得相对于 X11 和 x18 的梯度下降到几乎为零,因此权重更新不能在正确的方向上发生。虽然 sigmoid 很少用在现代深度学习架构中,但这个问题也会出现在其他激活函数中,并且可以使用归一化来减少。
由于 CXR 图像不是“自然图像”,我们不使用“除以 255”策略。相反,我们采用最大-最小法进行归一化。由于您无法确定每个像素的范围是 0–255,因此您可以使用最小-最大值进行归一化。
def preprocess_img(img,mode):
img =(img—img . min())/(img . max()—img . min())
img = rescale(img,0.25,多通道=True,mode = ' constant ')if mode = = ' train ':
if NP . random . randn()>0:
img = data gen . random _ transform(img)
返回 img
在条件语句“if mode == train”中,使用一个随机数生成器,这样只有一部分图像被转换(而不是所有图像)。
CXR:网络建设
我们将使用 resnet 进行分类。由于 ResNets 在行业中已经变得相当普遍,所以有必要花一些时间来理解其架构的重要元素。先说这里提出的原架构。ResNet 已经解决的基本问题是,训练非常深的网络在计算上是困难的——例如,56 层网络的训练精度比 20 层网络的训练精度低。顺便说一下,在 ResNets 之前,任何超过 20 层的东西都被称为非常深。
现在让我们看看 ResNets 是如何解决这个问题的。考虑上图(来自论文)。假设网络的某个“单元”的输入是 x(该单元有两个权重层)。假设,理想情况下,该单元应该已经学习了某个函数 H(x ),即给定输入 x,该单元应该已经学习产生期望输出 H(x)。
在正常的神经网络中,这两层(即这个单元)将试图学习函数 H(x)。但雷斯内特尝试了一种不同的技巧。他们认为:让 F(x)表示 H(x)和 x 之间的残差,即 F(x)= H(x)——x。他们假设学习残差函数 F(x)比学习 H(x)更容易。在极端情况下,该单元应该简单地让信号通过它(即 H(x)=x 是学习的最佳值),将残差 F(x)推到零比学习 H(x)更容易。
在 deep 网上的实验证明了这个假设确实是真的——如果学习让信号通过是要做的最佳事情(即减少损失),那么单元学习 F(x)= 0;但是,如果要学些有用的东西,这些单元就学会了。这些单元被称为剩余单元。
让我们回到我们的项目。我们有以下模型建立过程的输入:一个图像通道,两个不同的类,如“渗出”与“找不到”,以及 256 行和列。
img _ channels = 1
img _ rows = 256
img _ cols = 256nb_classes = 2
我们使用数据生成过程来只加载需要的数据,以确保不会超出内存空间限制。
构建模型的基本步骤是:
- 导入 resnet,因为我们将使用迁移学习。
- 运行扩充数据生成器。
- 执行消融运行。
- 符合模型。
CXR:火车模型
现在,该训练模型了。模型训练的第一步是进行消融实验。这样做是为了检查代码是否按预期运行。我们试图用小数据集和较少的时期来运行它,以识别任何潜在的问题。
我们可以从第一次消融中了解一些事实。数据类高度不平衡。“渗出”与“找不到”的比率几乎是 10 (107/1000)。由于大部分数据只属于一个类别,在这种情况下简单的训练将不起作用,因为模型将主要学习和分类大部分数据为“无发现”,从而导致高精度。如果你注意到,大约 90%的数据都是“找不到的”。通过对所有数据进行相同的分类,准确率将达到 90 %,接近我们达到的 96%的准确率。因此,正确分类“积液”的目标没有实现。高精度明显误导了我们,因此我们将使用曲线下面积(AUC)来验证结果。
CXR:有 AUC 的火车模型
什么是曲线下面积(AUC)?
AUC-ROC 曲线是在各种阈值设置下对分类问题的性能测量。ROC 是概率曲线,AUC 代表可分性的程度或度量。它告诉我们模型在多大程度上能够区分不同的类。AUC 越高,模型预测 0 为 0 和 1 为 1 的能力越强。以此类推,AUC 越高,该模型在区分患病和未患病患者方面就越好。
AUC vs Accuracy
关键时刻
我们观察到精确度很高,大约 0.93 到 0.96。相反,AUC 低得多,为. 29。因为 AUC 低于 0.5,所以模型以相反的顺序工作,将阳性类别识别为阴性类别。
我们在第二轮消融中观察到:
- 该模型在我们选择的 AUC 指标上表现不佳。
- 造成这种情况的主要原因是普遍性问题。数据集中的异常案例并不多。这个问题会出现在几乎所有的医学成像问题中,就此而言,会出现在大多数类别不平衡的数据集中。
- 为了解决这个问题,我们引入了“加权分类交叉熵”。这是一种衡量损失的方法,它将权重应用于不同形式的错误。
低患病率的解决方案
低患病率问题的一个常见解决方案是使用加权交叉熵损失。损失被修改,使得低流行等级的错误分类比其他等级受到更重的惩罚。
因此,每当模型在异常类别(在本例中为“渗出”)上出错时,我们会通过将损失乘以高权重值来对其进行严厉惩罚。这导致错误分类类别的损失增加,因此由于反向传播而导致的权重变化更大。因此,对错误分类负责的权重的学习曲线更多。
假设“没有发现”是 0 级,“积液”是 1 级。
bin_weights[0,0]: 实际类:0,预测类:0,所以没有惩罚,只是正常的权重 1。
bin_weights[1,1]: 实际类:1,预测类:1,所以没有惩罚,只是正常的权重为 1。
出现异常情况时:
bin_weights[1,0] —实际类为 1,预测类为 0,按权重罚 5。
bin_weights[0,1] —实际类为 0,预测类为 1,按权重罚 5。
def w _ category _ cross entropy(y _ true,y_pred,weights):
nb _ cl = len(weights)
final _ mask = k . zeros _ like(y _ pred[:,0])
y _ pred _ max = k . max(y _ pred,axis = 1)
y _ pred _ max = k . shape(y _ pred)[0],1)
y _ pred _ max _ matbin_weights = np.ones((2,2))
bin_weights[0,1] = 5
bin_weights[1,0]= 5
ncce = partial(w _ category _ cross entropy,weights=bin_weights)
ncce。_ _ name _ _ = ' w _ category _ cross entropy '
CXR:最后一轮
我们确定了问题的根本原因,并提出了具体的解决方案— 加权分类交叉熵,并开始了我们的最终运行。
只有当“验证准确性”提高时,我们才保存模型权重。保存模型权重的方法称为检查点,使用 keras 回调调用。结果清楚地表明 AUC从 0.19(无重量)显著增加到 0.86(有重量)。
做一个预测
最佳拟合模型用于预测 X 射线图像是“渗出”还是“无发现”
不用于训练或验证数据集 X 射线图像是测试预测的最佳候选。
Test image looks like above
在上述最后运行步骤中,我们重新加载 Resnet 并从最佳拟合权重中加载权重。
Loading weight from best fit model
并使用测试图像作为预测输入。
Prediction of the Test image datapoint
所以根据模型测试图像是一个积液。我们可以清楚地看到这个结果是正确的。
结论和下一步措施
我刚刚开始在医学图像上使用 CNN。展望未来,我将扩展模型以预测更多的输出,并尝试提高准确性。欢迎你加入我的 Github 回购项目。我已经在 google Drive 上传了我的训练数据。
让我们一起构建或者你自己尝试一下,然后抢先我一步。无论哪种方式,都要不断学习,不断提升自己。下次见,保持警惕!
用于图像和单词标签识别的深度多输入模型迁移学习
原文:https://towardsdatascience.com/deep-multi-input-models-transfer-learning-for-image-and-word-tag-recognition-7ae0462253dc?source=collection_archive---------6-----------------------
一种用于图像和文本理解的多模型深度学习方法
随着深度学习如卷积神经网络(即conv net)【1】,计算机视觉再次成为热门科研课题。现在计算机视觉的一个主要目标是使用机器学习(尤其是深度学习)来训练计算机从数字图像、文本或视频中获得人类级别的理解。
随着它的广泛使用,ConvNet 成为图像识别的事实模型。如[1]所述,一般来说,有两种方法可以将 ConvNet 用于计算机视觉:
- 从头开始培训新的 ConvNet 模型
- 使用 转移学习 ,即使用预先训练好的 ConvNet 模型
如下图所示,一个 ConvNet 模型由两部分组成:一个卷积基和一个全连通分类器。
图 1:conv net 迁移学习的典型场景。
ConvNet 迁移学习可以进一步细分为三种方法:
- 方法一:无需图像论证的特征提取【1】
这种方法首先使用预先训练的卷积基将新图像转换为数组,例如 Numpy 数组(如果需要,可以将其保存到文件中),然后使用内存中图像的那些数组表示,使用随机初始化的权重训练单独的新分类模型。 - 方法二:带图像论证的特征提取【1】
该方法以预先训练好的卷积基为输入层建立新的模型,冻结卷积基的权值,最后加入一个新的随机初始化权值的输出分类器。 - 方法三:微调【1】
这种方法不使用整个冻结的预训练卷积基。它允许解冻冻结的预训练卷积基的一些顶层,使得那些解冻的顶层可以与新的完全连接的分类器联合训练。
方法 2 在本文中用于多输入模型迁移学习。
迁移学习背后的主要思想不仅可以用于有监督的 ConvNet,还可以用于其他深度学习算法,例如用于自然语言处理的无监督单词嵌入模型(NLP)【4】。
目前流行的预训练单词嵌入模型有两种: word2vec 和GloVe【3】。像[4]中使用的 word2vec-keras 模型,这些预训练的单词嵌入模型通常与其他有监督的深度学习算法相结合,如文本分类等递归神经网络(RNN)LSTMNLP【4】。
ConvNet 模型或 NLP 模型(例如,单词嵌入与 LSTM 的组合)可以单独用于解决计算机视觉和 NLP 中的许多有趣问题。正如本文所示,这些不同类型的模型还可以以各种方式组合起来[1]形成更强大的模型,以解决更具挑战性的问题,如保险索赔流程自动化不仅需要图像识别能力,还需要自然语言(如文本)理解能力。
本文使用 Kaggle 中一个有趣但具有挑战性的数据集,表征学习中的挑战:多模态学习 [2],提出了一个新的多输入迁移学习模型,该模型将两个输入模型与一个完全连接的分类层相结合,同时用于图像识别和单词标签识别(见图 2)。
新的多输入模型背后的主要思想是将图像和单词标签识别的问题转化为机器学习分类问题,即确定给定的图像是否与给定的一组单词标签匹配(0-否,1-是)。
1.数据准备
在将图像文件和单词标签文件的 Kaggle 数据集[2]下载到本地机器之后,可以使用下面的代码来构建和打乱图像文件名和相关单词标签文件名的列表。在用于训练目的的数据集中有 100,000 个图像文件和 100,000 个相应的单词标签文件。
original_dataset_dir = './multi_task_learning/data/ESPGame100k'
base_dataset_dir = './multi_task_learning/data/ESPGame100k_small'original_label_path = original_dataset_dir + '/labels'
original_label_files = [f for f in listdir(original_label_path) if isfile(join(original_label_path, f))]original_image_path = original_dataset_dir + '/thumbnails'
original_image_files = [f for f in listdir(original_image_path) if isfile(join(original_image_path, f))]original_image_files = np.array(original_image_files)
original_label_files = np.array(original_label_files)dataset_size = original_label_files.shape[0]
perm = np.arange(dataset_size)
np.random.shuffle(perm)
original_image_files = original_image_files[perm]
original_label_files = original_label_files[perm]
为了在合理的时间内(几个小时)在笔记本电脑上训练新的多输入模型,我随机选择了 2,000 张图像和相应的 2,000 个 word 标记文件用于本文的模型训练:
if not os.path.isdir(base_dataset_dir):
os.mkdir(base_dataset_dir)
small_label_path = os.path.join(base_dataset_dir, 'labels')
small_image_path = os.path.join(base_dataset_dir, 'thumbnails')
if not os.path.isdir(small_label_path):
os.mkdir(small_label_path)
if not os.path.isdir(small_image_path):
os.mkdir(small_image_path)for fname in original_label_files[:2000]:
src = os.path.join(original_label_path, fname)
dst = os.path.join(small_label_path, fname)
shutil.copyfile(src, dst)for fname in original_label_files[:2000]:
img_fname = fname[:-5]
src = os.path.join(original_image_path, img_fname)
dst = os.path.join(small_image_path, img_fname)
shutil.copyfile(src, dst)
下面的代码将 2,000 个图像标签文件名和相应的 2,000 个单词标签加载到 Pandas DataFrame 中:
label_map = {'label_file' : [], 'word_tags' : []}
for fname in listdir(small_label_path):
f = join(small_label_path, fname)
if isfile(f):
f = open(f)
label_map['label_file'].append(fname)
line = f.read().splitlines()
label_map['word_tags'].append(line)
label_df = pd.DataFrame(label_map)
label_df.head()
与[4]类似,Jupyter notebook [5]中包含一个文本数据预处理程序,用于执行最少的数据预处理,如删除停用词和数字,以防产生重大差异:
如[4]中所述,文本数据预处理的影响是不显著的,因此在本文中,未经预处理的原始单词标签用于模型训练。
2.多输入模型迁移学习体系结构
如下图所示,新的多输入迁移学习模型使用预训练的 ConvNet 模型 VGG16 来接收和处理图像,并使用新的 NLP 模型(预训练的单词嵌入模型 GloVe 和 Keras LSTM 的组合)来接收和处理单词标签。这两个输入模型首先被合并在一起,然后与完全连接的输出分类模型组合,该完全连接的输出分类模型使用图像识别模型输出和 NLP 模型输出来确定图像和一组单词标签的输入对是否匹配(0-否,1-是)。
图 2: 多输入模型迁移学习的新深度学习模型的架构。
3.图像识别中的迁移学习
如图 2 所示,新的多输入迁移学习模型使用预训练的 ConvNet 模型 VGG16 进行图像识别。VGG16 型号已经包含在 Keras 库中。来自[1]的以下代码用于将 VGG16 卷积基与新的全连接分类器相结合,以形成新的图像识别输入模型:
from keras.applications import VGG16
image_input = Input(shape=(150, 150, 3), name='image')
vgg16 = VGG16(weights='imagenet',
include_top=False,
input_shape=(150, 150, 3))(image_input)
x = layers.Flatten()(vgg16)
x = layers.Dense(256, activation='relu')(x)
4.面向文本分类的迁移学习
如图 2 所示,新的多输入迁移学习模型使用预训练的单词嵌入模型 GloVe [3]将单词标签转换为紧凑向量。一旦手套数据集[3]被下载到本地机器,来自[1]的以下代码可用于将单词嵌入模型加载到存储器中:
glove_dir = './multi_task_learning/data/'embeddings_index = {}
f = open(os.path.join(glove_dir, 'glove.6B.100d.txt'))
for line in f:
values = line.split()
word = values[0]
coefs = np.asarray(values[1:], dtype='float32')
embeddings_index[word] = coefs
f.close()
如图 2 所示,GloVe 单词嵌入与 Keras LSTM 相结合,形成了一个新的预测/识别单词标签的 NLP 输入模型:
tag_input = Input(shape=(None,), dtype='int32', name='tag')
embedded_tag = layers.Embedding(max_words, embedding_dim)(tag_input)
encoded_tag = layers.LSTM(512)(embedded_tag)
5.多输入模型与全连接分类器的结合
一旦创建了新的图像识别输入模型和新的 NLP 输入模型,以下代码可以将它们与新的输出分类器组合成一个多输入迁移学习模型:
concatenated = layers.concatenate([x, encoded_tag], axis=-1)
output = layers.Dense(1, activation='sigmoid')(concatenated)model = Model([image_input, tag_input], output)
model.summary()
如[1]中所述,预训练的 VGG16 卷积基和手套字嵌入层都必须被冻结,使得这些模型的预训练权重在新的多输入模型训练期间不会被修改:
# model.layers[1].trainable = False # freeze VGG16
model.layers[4].set_weights([embedding_matrix])
model.layers[4].trainable = False # freeze GloVe word embedding
然而,关于 VGG16 卷积基,有趣的是,我尝试了两种方法(冻结或不冻结),但在模型训练时间或模型预测结果方面没有看到显著差异。
6.多输入模型训练
原始 Kaggle 训练数据集仅包括正确的图像对和相应的单词标签。在本文中,每一个这样的正确对都被标记为 1(匹配)(另请参见下面的代码)。为了创建一个平衡的数据集,除了现有的 2,000 对正确的图像和单词标记之外,下面的代码还创建了 2,000 对不正确的图像和单词标记。为简单起见,这是通过将所选择的 2000 幅图像中的每一幅(比如图像 I)与下一个图像文件的单词标签(即图像 i+1 的单词标签)配对来实现的。
import cv2dim = (150, 150)
X_image_train = []
X_tag_train = tag_data
y_train = []
for fname in listdir(small_image_path):
fpath = os.path.join(small_image_path, fname)
im = cv2.imread(fpath)
im_resized = cv2.resize(im, dim, interpolation = cv2.INTER_AREA)
X_image_train.append(im_resized)
y_train.append(1)
# add incorrect image and tag pairs
num_negative_samples = len(y_train)
for i in range(num_negative_samples):
image = X_image_train[i]
X_image_train.append(image)
j = (i + 1) % num_negative_samples # get a different tag
tag = X_tag_train[j]
X_tag_train = np.append(X_tag_train, tag)
y_train.append(0)
总共有 4000 对图片和文字标签,2000 对正确,2000 对错误。
每个图像单词标签需要被编码为整数,并且在单词标签可以被单词嵌入模型消费之前,单词标签的每个列表/序列需要被转换为整数值序列。这是通过使用和修改[1]中的代码来实现的:
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequencesmaxlen = 100
training_samples = num_of_samples
tag_vocabulary_size = 10000
max_words = tag_vocabulary_size
num_of_samples = label_df.shape[0]tokenizer = Tokenizer(num_words=max_words)
texts = []
for tag_list in label_df_clean['word_tags']:
texts.append(' '.join(tag_list))
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)
word_index = tokenizer.word_index
print('Found {} unique tokens'.format(len(word_index)))
tag_data = pad_sequences(sequences, maxlen=maxlen)
得到的图像和单词标签训练数据集被转换成 Numpy 数组并被混洗用于模型训练:
X_image_train = np.array(X_image_train)
X_tag_train = np.array(X_tag_train)
y_train = np.array(y_train)
perm = np.arange(y_train.shape[0])
np.random.shuffle(perm)
X_image_train = X_image_train[perm]
X_tag_train = X_tag_train[perm]
y_train = y_train[perm]
新的多输入模型被编译和训练如下,仅具有 30 个时期和 4,000 对平衡的图像和单词标签:
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
model.fit([X_image_train, X_tag_train], y_train, epochs=30, batch_size=64)
7.模型预测法
如下所示,[2]中的私有测试数据集包括 500 个图像,每个图像与两组单词标签相关联:
给定测试数据集中的图像,新的多输入迁移学习模型需要能够预测给定的两组单词标签中的哪一组与图像匹配。
以下代码用于将测试图像加载到内存中:
dim = (150, 150)
X_image_test = []for fname in listdir(test_image_dir):
fpath = os.path.join(test_image_dir, fname)
im = cv2.imread(fpath)
im_resized = cv2.resize(im, dim, interpolation = cv2.INTER_AREA)
X_image_test.append(im_resized)
测试字标签被转换成如下编码的整数值序列:
tokenizer_test = Tokenizer(num_words=max_words)
texts_1 = []
texts_2 = []
texts_all = []
for tag_list in test_image_label_df['word_tags_1']:
texts_1.append(' '.join(tag_list))
for tag_list in test_image_label_df['word_tags_2']:
texts_2.append(' '.join(tag_list))
texts_all.extend(texts_1)
texts_all.extend(texts_2)
tokenizer_test.fit_on_texts(texts_all)
sequences_1 = tokenizer_test.texts_to_sequences(texts_1)
sequences_2 = tokenizer_test.texts_to_sequences(texts_2)word_index_test = tokenizer_test.word_index
print('Found {} unique tokens in test'.format(len(word_index_test)))
tag_data_test_1 = pad_sequences(sequences_1, maxlen=maxlen)
tag_data_test_2 = pad_sequences(sequences_2, maxlen=maxlen)
然后,生成的图像和单词标签的 Python 数组被转换为 Numpy 数组,并适合训练好的预测模型:
X_image_test = np.array(X_image_test)
X_tag_test_1 = np.array(tag_data_test_1)
X_tag_test_2 = np.array(tag_data_test_2)
y_predict_1 = loaded_model.predict([X_image_test, X_tag_test_1])
y_predict_2 = loaded_model.predict([X_image_test, X_tag_test_2])
下表显示了前 20 个预测结果:
下图是测试数据集中的影像 201.png:
两个相关的单词标签集如下:
word-tag-set-0: ['bloom', 'glow', 'overexposed', 'bright', 'white', 'face', 'woman', 'blonde']
word-tag-set-1: ['iron', 'nuggets', 'samples', 'metal', 'ore', 'shadow', 'white', 'grey', 'gray', 'rust', 'shiny']
该模型预测:
word-tag-set-0: probability of 0.797
word-tag-set-1: probability of 0.999
概率较高的 0.999 的答案是:
['铁','金块','样本','金属','矿石','阴影','白色','灰色','铁锈','闪亮']
作为另一个正面例子,下面是测试数据集中的影像 76.png:
以下是相关的两组单词标签:
word-tag-set-0: ['person', 'man', 'shirt', 'pinstripe', 'smile', 'balding', 'grey', 'gray']
word-tag-set-1: ['country', 'music', 'man', 'instrument', 'guitar', 'musician', 'person', 'playing', 'watch', 'striped', 'shirt', 'red', 'glasses']
该模型预测:
word-tag-set-0: probability of 0.997
word-tag-set-1: probability of 0.530
概率较高的 0.997 的答案是:
['人','男人','衬衫','细条纹','微笑','谢顶','灰色']
作为一个假阳性示例,以下是测试数据集中的图像 189.png:
以下是相关的两组单词标签:
word-tag-set-0: ['necklace', 'woman', 'earring', 'jewelry', 'mouth', 'chin', 'closeup']
word-tag-set-1: ['circle', 'lines', 'round', 'window', 'porthole', 'man', 'face', 'beard', 'person', 'dark', 'shadow']
该模型预测:
word-tag-set-0: probability of 0.016
word-tag-set-1: probability of 0.999
概率较高的 0.999 的误报答案是:
['圆','线','圆','窗','舷窗','人','脸','胡子','人','黑暗','影子']
上面的测试结果表明,即使新的多输入迁移学习模型仅用 4000 对图像和单词标签以及 30 个时期来训练,该模型也能够在准确性方面获得相当合理的结果。
然而,由于模型过度拟合,该模型也产生了相当多的假阳性。
摘要
本文提出了一种新的多输入深度迁移学习模型,该模型将两个预训练的输入模型(VGG16 和 GloVe & LSTM)与一个新的全连接分类层相结合,用于同时识别图像和单词标签。
新的多输入深度学习方法的关键点是将图像和单词标签识别的问题转化为分类问题,即确定给定的图像是否与给定的一组单词标签匹配(0-否,1-是)。
Kaggle 中具有挑战性的公共数据集表征学习中的挑战:多模态学习【2】,用于训练和评估新模型。
模型预测结果表明,新模型在用于演示目的的有限模型训练(只有 30 个时期和 4,000 对图像和单词标签)下表现得相当好。然而,毫不奇怪,由于模型过度拟合,该模型也产生了相当多的假阳性。这个问题可以通过用更多时期和/或更多对图像和单词标签来训练模型来解决。
显然,随机选择的 2000 幅训练图像不足以代表总共 100000 幅可用的训练图像。通过将训练图像的数量从 2,000 个增加到更大的尺寸,如 10,000 个,模型性能将得到显著提高。
Github [5]中提供了一个包含所有源代码的 Jupyter 笔记本。
参考
[1] F. Chollet,用 Python 进行深度学习,曼宁出版公司,2018
[2] 表征学习的挑战:多模态学习
[3] J. Pennington,R. Socher,C.D. Manning, GloVe:单词表示的全局向量
[4] Y. Zhang,利用 word2vec-keras 进行自然语言处理的深度学习
[5] Y. Zhang, Github 中的 Jupyter 笔记本
披露声明:2019 首创一。观点是作者个人的观点。除非本帖中另有说明,否则 Capital One 不隶属于所提及的任何公司,也不被这些公司认可。使用或展示的所有商标和其他知识产权是其各自所有者的财产。
深度多任务学习— 3 个经验教训
原文:https://towardsdatascience.com/deep-multi-task-learning-3-lessons-learned-7d0193d71fd6?source=collection_archive---------19-----------------------
在过去的一年里,我和我的团队一直致力于在 Taboola feed 中实现个性化的用户体验。我们使用多任务学习 (MTL)来预测同一组输入特征的多个关键性能指标(KPI),并在 TensorFlow 中实现了一个深度学习(DL)模型来实现这一点。回到我们开始的时候,MTL 对我们来说似乎比现在复杂得多,所以我想分享一些经验教训。
已经有不少关于用 DL 模式实现 MTL 的帖子( 1 、 2 、 3 )。在这篇文章中,我将分享一些在神经网络(NN)中实现 MTL 时需要考虑的具体问题。我也将提出简单的张量流解决方案来克服所讨论的问题。
分享是关怀
我们想从硬参数共享的基本方法开始。硬共享意味着我们有一个共享子网,后面是特定于任务的子网。
在 TensorFlow 中开始使用这种模型的一个简单方法是使用带有多个头部的估算器。因为它看起来和其他神经网络架构没有什么不同,你可能会问自己哪里出错了?
第 1 课—组合损失
我们在 MTL 模型中遇到的第一个挑战是为多个任务定义一个损失函数。虽然单个任务有明确定义的损失函数,但多个任务会带来多个损失。
我们尝试的第一件事就是简单地将不同的损失相加。很快我们可以看到,当一个任务收敛到好的结果时,其他的看起来很糟糕。当仔细观察时,我们很容易明白为什么。损失的规模如此不同,以至于一项任务主导了整体损失,而其余的任务没有机会影响共享层的学习过程。
一个快速解决方案是用加权总和代替损失总和,这样所有损失的规模大致相同。然而,这个解决方案涉及到另一个可能需要偶尔调整的超参数。
幸运的是,我们发现了一篇很棒的论文,提出用不确定性来衡量 MTL 的损失。其实现方式是通过学习另一个噪声参数,该参数被整合到每个任务的损失函数中。这允许有多个任务,可能的回归和分类,并使所有损失达到相同的规模。现在我们可以回到简单地总结我们的损失。
我们不仅得到了比加权总和更好的结果,还可以忘记额外的权重超参数。这里的是本文作者提供的一个 Keras 实现。
第 2 课—调整学习率
学习率是调节神经网络的最重要的超参数之一,这是一个普遍的约定。所以我们尝试调整,发现一个学习率看起来非常适合任务 A,另一个非常适合任务 b。选择较高的学习率会导致其中一个任务的死亡,而使用较低的学习率会导致另一个任务收敛缓慢。那我们能做什么?我们可以为每个“头”(特定于任务的子网)调整一个单独的学习速率,为共享子网调整另一个速率。
虽然听起来很复杂,但实际上很简单。通常,在 TensorFlow 中训练神经网络时,您会使用类似以下的内容:
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss)
AdamOptimizer 定义如何应用渐变,而 minimize 计算并应用渐变。我们可以将最小化替换为我们自己的实现,在应用梯度时,我们将对计算图中的每个变量使用适当的学习率:
all_variables = shared_vars + a_vars + b_vars
all_gradients = tf.gradients(loss, all_variables)
shared_subnet_gradients = all_gradients[:len(shared_vars)]
a_gradients = all_gradients[len(shared_vars):len(shared_vars + a_vars)]
b_gradients = all_gradients[len(shared_vars + a_vars):]
shared_subnet_optimizer = tf.train.AdamOptimizer(shared_learning_rate)
a_optimizer = tf.train.AdamOptimizer(a_learning_rate)
b_optimizer = tf.train.AdamOptimizer(b_learning_rate)
train_shared_op = shared_subnet_optimizer.apply_gradients(zip(shared_subnet_gradients, shared_vars))
train_a_op = a_optimizer.apply_gradients(zip(a_gradients, a_vars))
train_b_op = b_optimizer.apply_gradients(zip(b_gradients, b_vars))
train_op = tf.group(train_shared_op, train_a_op, train_b_op)
顺便说一下,这个技巧实际上对单任务网络也很有用。
第 3 课—使用评估作为特征
一旦我们通过了创建一个预测多项任务的神经网络的第一阶段,我们可能会希望使用我们对一项任务的估计作为另一项任务的特征。在向前传球时,这真的很容易。估计是一个张量,所以我们可以像任何其他层的输出一样连接它。但是在 backprop 中会发生什么呢?
假设任务 A 的估计值作为一个特征传递给任务 B。我们可能不想将渐变从任务 B 传播回任务 A,因为我们已经有了一个 A 的标签。
别担心,TensorFlow 的 API 有 tf.stop_gradient 就是因为这个原因。当计算梯度时,它让你传递一个你希望当作常数的张量列表,这正是我们所需要的。
all_gradients = tf.gradients(loss, all_variables, stop_gradients=stop_tensors)
同样,这在 MTL 网络中是有用的,但不是唯一的。每当您想用 TensorFlow 计算一个值,并需要假设该值是一个常数时,都可以使用这种技术。例如,当训练生成性对抗网络(GANs)时,你不希望通过对抗例子的生成过程反向推进。
那么,下一步是什么?
我们的模型已经启动并运行,Taboola feed 正在被个性化。然而,仍有很大的改进空间,还有许多有趣的架构有待探索。在我们的用例中,预测多个任务也意味着我们基于多个 KPI 做出决策。这可能比使用单一的 KPI 要复杂一些…但这已经是一个全新的话题了。
感谢阅读,希望这篇文章对你有用!
基于人脸照片的深度神经网络亲属关系预测
原文:https://towardsdatascience.com/deep-neural-networks-for-kinship-prediction-using-face-photos-f2ad9ab53834?source=collection_archive---------25-----------------------
Photo by Alex Guillaume on Unsplash
给定两个人的面部照片,我们能预测他们是否有血缘关系吗?
这就是我们在本帖中试图通过使用野外家庭:一个亲属识别基准数据集来做的事情,数据集的格式在 Kaggle 上共享:https://www.kaggle.com/c/recognizing-faces-in-the-wild/data
我们将探索深度神经网络的有效性,并转移学习技术来训练一个神经网络,该网络将预测两个人是否有血缘关系或是否给定了他们的面部照片。
数据集:
我们将使用在 kaggle 上共享的野生数据集中的家族。这是同类中规模最大的数据集,其中人脸照片按人分组,然后按家庭分组。
Image organization in the FIW dataset
除了图像文件夹之外,我们还有一个文件,列出了一个家庭中两个人有血缘关系的所有情况,但并不是所有家庭成员都有血缘关系。(就像母亲和父亲,除非我们说的是兰尼斯特😄)
型号:
为了解决这个任务,我们将使用一个暹罗网络,它拍摄一对图像,如果照片中的人是相关的,则预测 1,否则预测 0。
Siamese Network
图像编码器应用于每个输入图像,并将它们中的每一个编码成固定长度的向量。两个图像向量之间的差的平方被馈送到完全连接的层,该层然后预测亲属关系的二进制标签。
Example of input/output
迁移学习:
我们的解决方案将基于使用两种不同设置的预训练图像编码器:
ImageNet 上的预处理:1400 万张手动标记图像的数据集,用于分类,如狗、猫、飞机、草莓…
vgg face 2上的预训练:一个由330 万张人脸图像和 9000 多个不同种族、口音、职业和年龄的身份组成的数据集。
预训练技术是有用的,因为它们允许我们将在源任务(这里是图像分类或回归)中学到的表征转移到目标任务,在这种情况下是亲属关系预测。
这有助于减少过度拟合,并实现更快的收敛速度,尤其是在源任务和目标任务有些接近的情况下。
结果:
我们将使用准确性和 AUC 分数来评估每个模型的结果。
Resnet50 Imagenet 测试 ROC AUC : 0.70
Evaluation on the test set through kaggle submission
Resnet50 VGGFACE2 测试 ROC AUC : 0.81
Evaluation on the test set through kaggle submission
Validation Accuracy Comparison
我们可以看到,即使两种不同设置中的架构是相同的,在 VGGFace2 上预训练的模型上的结果也要好得多,因为与 Imagenet 相比,它是更接近亲属预测目标任务的源任务。
结论:
我们展示了我们可以训练一个暹罗网络来预测两个人是否有血缘关系。通过使用迁移学习,我们能够在 AUC ROC 中获得令人鼓舞的结果 0.81 ,特别是考虑到亲缘关系的任务👪即使对人类来说,预测也很难。
可在 https://github.com/CVxTz/kinship_prediction获得重现结果的代码
如果你有任何问题,请随意评论。
Python 中从零开始的深度神经网络
原文:https://towardsdatascience.com/deep-neural-networks-from-scratch-in-python-451f07999373?source=collection_archive---------4-----------------------
在本指南中,我们将构建一个深度神经网络,你想要多少层就有多少层!该网络可应用于二分类的监督学习问题。
Figure 1. Example of neural network architecture
注释
上标[ l 表示与 l ᵗʰ层相关的量。
上标( i )表示与 i ᵗʰ示例相关的量。
Lowerscript i 表示向量的 i ᵗʰ条目。
本文假设读者已经熟悉神经网络的概念。不然我推荐看这个好看的介绍https://towardsdatascience . com/how-to-build-your-own-neural-network-from-scratch-in-python-68998 a08e 4 F6
单个神经元
Figure 2. Example of single neuron representation
神经元计算一个线性函数(z = Wx + b ),然后是一个激活函数。我们一般说一个神经元的输出是 a = g(Wx + b)其中 g 是激活函数(sigmoid,tanh,ReLU,…)。
资料组
让我们假设我们有一个非常大的数据集,其中包含温度、湿度、大气压力和降雨概率等天气数据。
问题陈述:
- 标记为下雨(1)或不下雨(0)的 m_train 天气数据的训练集
- 标记为下雨或不下雨的 m_test 天气数据的测试集
- 每个天气数据包括 x1 =温度,x2 =湿度,x3 =大气压力
机器学习中一个常见的预处理步骤是对数据集进行居中和标准化,这意味着您从每个示例中减去整个 numpy 数组的平均值,然后用整个 numpy 数组的标准偏差除每个示例。
[## 标准偏差-维基百科
随机变量、统计总体、数据集或概率分布的标准偏差是…
en.wikipedia.org](https://en.wikipedia.org/wiki/Standard_deviation)
一般方法(构建我们算法的各个部分)
我们将遵循深度学习方法来构建模型:
- 定义模型结构(如输入要素的数量)
- 初始化参数并定义超参数:
- 迭代次数
- 神经网络的层数 L
- 隐藏层的大小
- 学习率α
3.num_iterations 的循环:
- 正向传播(计算电流损耗)
- 计算成本函数
- 反向传播(计算电流梯度)
- 更新参数(使用参数和来自反向投影的梯度)
4.使用训练好的参数来预测标签
初始化
更深的 L 层神经网络的初始化更复杂,因为有更多的权重矩阵和偏置向量。我提供下面的表格是为了帮助你保持正确的结构尺寸。
Table 1. Dimensions of weight matrix W, bias vector b andactivation Z for layer l
Table 2. Dimensions of weight matrix W, bias vector b andactivation Z for the neural network for our example architecture
表 2 帮助我们为图 1 中示例神经网络架构的矩阵准备正确的维度。
Snippet 1. Initialization of the parameters
使用小随机数进行参数初始化是一种简单的方法,但它保证了我们的算法有足够好的起点。
请记住:
- 不同的初始化技术,如零,随机,他或泽维尔导致不同的结果
- 随机初始化确保不同的隐藏单元可以学习不同的东西(将所有的权重初始化为零,这样每一层中的每个神经元都将学习相同的东西)
- 不要初始化太大的值
激活功能
激活函数使神经网络具有非线性。在我们的例子中,我们将使用 sigmoid 和 ReLU。
Sigmoid 输出一个介于 0 和 1 之间的值,这使它成为二进制分类的一个非常好的选择。如果小于 0.5,可以将输出分类为 0,如果大于 0.5,可以将输出分类为 1。
Snippet 2. Sigmoid and ReLU activation functions and their derivatives
在代码片段 2 中,你可以看到激活函数及其导数的矢量化实现(https://en.wikipedia.org/wiki/Derivative)。该代码将用于进一步的计算。
正向传播
在正向传播过程中,在层的正向函数中 l 你需要知道层中的激活函数是什么(Sigmoid,tanh,ReLU 等。).给定来自前一层的输入信号,我们计算 Z,然后应用选定的激活函数。
Figure 3. Forward propagation for our example neural network
线性正向模块(对所有示例进行矢量化)计算以下等式:
Equation 1. Linear forward function
Snippet 3. Forward propagation module
我们使用“缓存”(Python 字典,其中包含为特定层计算的 A 和 Z 值)将向前传播期间计算的变量传递给相应的向后传播步骤。它包含向后传播计算导数的有用值。
损失函数
为了监控学习过程,我们需要计算成本函数的值。我们将使用下面的公式来计算成本。
Equation 2. Cross-entropy cost
Snippet 4. Computation of the cost function
反向传播
反向传播用于计算损失函数相对于参数的梯度。这个算法是微积分中已知的“链式法则”的递归使用。
反向传播计算中使用的方程:
Equation 3. Formulas for backward propagation calculation
链式法则是计算复合函数导数的公式。复合函数是由其他函数内部的函数组成的函数。
Equation 4. Chain rule examples
没有“链式法则”(以方程 5 为例),很难计算损耗。
Equation 5. Loss function (with substituted data) and its derivative with respect to the first weight.
我们的神经网络模型的反向传播的第一步是从最后一层计算我们的损失函数相对于 Z 的导数。等式 6 包括两个分量,来自等式 2 的损失函数的导数(相对于激活函数)和来自最后一层的激活函数“sigmoid”相对于 Z 的导数。
Equation 6. The derivative of the loss function with respect to Z from 4ᵗʰ layer
等式 6 的结果可用于计算等式 3 的导数:
Equation 7. The derivative of the loss function with respect to A from 3ᵗʰ layer
损失函数相对于来自第三层的激活函数的导数(等式 7)用于进一步的计算。
Equation 8. The derivatives for the third layer
等式 7 的结果和来自第三层的激活函数“ReLU”的导数用于计算等式 8 的导数(损失函数相对于 Z 的导数)。接下来,我们对等式 3 进行计算。
我们对等式 9 和 10 进行类似的计算。
Equation 9. The derivatives for the second layer
Equation 10. The derivatives for the first layer
总的想法是:
来自 lᵗʰ层的损失函数相对于 z 的导数有助于计算来自 l-1)ᵗʰ层(前一层)的损失函数相对于 a 的导数。然后将结果与激活函数的导数一起使用。
Figure 4. Backward propagation for our example neural network
Snippet 5. Backward propagation module
更新参数
该函数的目标是使用梯度优化来更新模型的参数。
Snippet 6. Updating parameters values using gradient descent
全模型
神经网络模型的完整实现由片段中提供的方法组成。
Snippet 7. The full model of the neural network
为了进行预测,您只需要使用接收到的权重矩阵和一组测试数据运行一个完整的前向传播。
您可以修改片段 1 中的 nn_architecture 来构建一个具有不同层数和隐藏层大小的神经网络。此外,准备激活函数及其派生函数的正确实现(片段 2 )。实现的函数可以用来修改片段 3 中的linear _ activation _ forward方法和片段 5 中的linear _ activation _ backward方法。
进一步的改进
如果训练数据集不够大,您可能会面临“过拟合”问题。这意味着学习过的网络不会归纳出它从未见过的新例子。你可以使用正则化方法,比如 L2 正则化(它包括适当修改你的
代价函数)或者丢弃(它在每次迭代中随机关闭一些神经元)。
我们使用梯度下降来更新参数并最小化成本。您可以学习更高级的优化方法,这些方法可以加快学习速度,甚至让您获得更好的成本函数最终值,例如:
- 小批量梯度下降
- 动力
- Adam 优化器
参考资料:
[1]https://www . coursera . org/learn/neural-networks-deep-learning
https://www.coursera.org/learn/deep-neural-network
[3]https://ml-cheatsheet.readthedocs.io/en/latest/index.html
[4]https://medium . com/forward-artificial-intelligence/one-Lego-at-a-time-explain-the-math-of-how-neural-networks-learn-implementation-from scratch-39144 a1cf 80
[5]https://towards data science . com/gradient-descent-in-a-shell-EAF 8c 18212 f 0
[6]https://medium . com/datadriveninvestor/math-neural-network-from-scratch-in-python-d6da 9 f 29 ce 65
[7]https://towards data science . com/how-to-build-your-own-your-own-neural-network-from scratch-in-python-68998 a08e 4 F6
用于横竿的深度 Q 学习
原文:https://towardsdatascience.com/deep-q-learning-for-the-cartpole-44d761085c2f?source=collection_archive---------5-----------------------
这篇文章的目的是介绍深度 Q 学习的概念,并用它来解决 OpenAI 健身房的 CartPole 环境。
该员额将由以下部分组成:
- 开放式人工智能健身房环境介绍
- 随机基线策略
- 深度 Q 学习
- 具有重放记忆的深度 Q 学习
- 双重深度 Q 学习
- 软更新
环境
横拉杆环境由一根沿无摩擦轨道移动的杆子组成。通过对推车施加+1 或-1 的力来控制该系统。钟摆开始直立,目标是防止它翻倒。状态空间由四个值表示:小车位置、小车速度、磁极角度和磁极尖端的速度。动作空间由两个动作组成:向左移动或向右移动。杆保持直立的每个时间步长提供+1 的奖励。当柱子偏离垂直方向超过 15 度,或者手推车偏离中心超过 2.4 个单位时,该集结束。
下面的单元格绘制了环境中的一组示例帧:
# Demonstration
env = gym.envs.make("CartPole-v1")def get_screen():
''' Extract one step of the simulation.'''
screen = env.render(mode='rgb_array').transpose((2, 0, 1))
screen = np.ascontiguousarray(screen, dtype=np.float32) / 255.
return torch.from_numpy(screen)# Speify the number of simulation steps
num_steps = 2# Show several steps
for i in range(num_steps):
clear_output(wait=True)
env.reset()
plt.figure()
plt.imshow(get_screen().cpu().permute(1, 2, 0).numpy(),
interpolation='none')
plt.title('CartPole-v0 Environment')
plt.xticks([])
plt.yticks([])
plt.show()
根据剧集的数量,输出如下所示:
Untrained Agent
正如我们所看到的,代理还没有经过训练,所以它只能走几步。我们将很快探讨一些能显著提高性能的策略。但是首先,让我们定义绘图函数,它将帮助我们分析结果:
def plot_res(values, title=''):
''' Plot the reward curve and histogram of results over time.'''
# Update the window after each episode
clear_output(wait=True)
# Define the figure
f, ax = plt.subplots(nrows=1, ncols=2, figsize=(12,5))
f.suptitle(title)
ax[0].plot(values, label='score per run')
ax[0].axhline(195, c='red',ls='--', label='goal')
ax[0].set_xlabel('Episodes')
ax[0].set_ylabel('Reward')
x = range(len(values))
ax[0].legend()
# Calculate the trend
try:
z = np.polyfit(x, values, 1)
p = np.poly1d(z)
ax[0].plot(x,p(x),"--", label='trend')
except:
print('')
# Plot the histogram of results
ax[1].hist(values[-50:])
ax[1].axvline(195, c='red', label='goal')
ax[1].set_xlabel('Scores per Last 50 Episodes')
ax[1].set_ylabel('Frequency')
ax[1].legend()
plt.show()
最终的剧情由两个支线剧情组成。第一个图显示了代理在一段时间内累积的总奖励,而另一个图显示了代理在过去 50 集的总奖励的直方图。当我们分析我们的策略时,我们会看到一些图表。
基线随机模型
在实现任何深度学习方法之前,我写了一个简单的策略,其中动作是从动作空间中随机采样的。这种方法将作为其他策略的基线,并使其更容易理解如何使用开放的人工智能健身房环境与代理合作。
def random_search(env, episodes,
title='Random Strategy'):
""" Random search strategy implementation."""
final = []
for episode in range(episodes):
state = env.reset()
done = False
total = 0
while not done:
# Sample random actions
action = env.action_space.sample()
# Take action and extract results
next_state, reward, done, _ = env.step(action)
# Update reward
total += reward
if done:
break
# Add to the final reward
final.append(total)
plot_res(final,title)
return final
一个环境步骤返回几个值,比如next_state
、reward
,以及模拟是否为done
。下图显示了 150 集(模拟运行)的总累积奖励:
Random Strategy
上面的图展示了随机策略。不出所料,用这种方法解决环境问题是不可能的。代理没有从他们的经验中学习。尽管有时很幸运(获得差不多 75 的奖励),但他们的平均表现低至 10 步。
深度 Q 学习
Q-learning 背后的主要思想是我们有一个函数𝑄:𝑆𝑡𝑎𝑡𝑒×𝐴𝑐𝑡𝑖𝑜𝑛→ℝ,它可以告诉代理什么行为会导致什么回报。如果我们知道𝑄的价值,我们就有可能制定一个最大化回报的政策:
𝜋(𝑠)=argmax𝑎 𝑄(𝑠,𝑎)
然而,在现实世界中,我们无法获得全部信息,这就是为什么我们需要想出近似𝑄.的方法一种传统的方法是创建一个查找表,其中𝑄的值在代理的每个动作之后被更新。然而,这种方法很慢,并且不能扩展到大的动作和状态空间。由于神经网络是通用函数逼近器,我将训练一个可以逼近𝑄.的网络
DQL 类的实现包括一个在 PyTorch 中实现的简单神经网络,它有两个主要的方法——预测和更新。网络将代理的状态作为输入,并返回每个动作的𝑄值。代理选择最大𝑄值来执行下一个操作:
class DQL():
''' Deep Q Neural Network class. '''
def __init__(self, state_dim, action_dim, hidden_dim=64, lr=0.05):
self.criterion = torch.nn.MSELoss()
self.model = torch.nn.Sequential(
torch.nn.Linear(state_dim, hidden_dim),
torch.nn.LeakyReLU(),
torch.nn.Linear(hidden_dim, hidden_dim*2),
torch.nn.LeakyReLU(),
torch.nn.Linear(hidden_dim*2, action_dim)
)
self.optimizer = torch.optim.Adam(self.model.parameters(), lr)def update(self, state, y):
"""Update the weights of the network given a training sample. """
y_pred = self.model(torch.Tensor(state))
loss = self.criterion(y_pred, Variable(torch.Tensor(y)))
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()def predict(self, state):
""" Compute Q values for all actions using the DQL. """
with torch.no_grad():
return self.model(torch.Tensor(state))
q_learning 函数是后面所有算法的主循环。
它有许多参数,即:
env
代表我们要解决的开放 Ai 健身房环境(CartPole。)episodes
代表我们想玩的游戏数量。gamma
是一个贴现因子,乘以未来奖励,以抑制这些奖励对代理人的影响。它的目的是让未来的奖励不如眼前的奖励有价值。epsilon
表示随机行动相对于行动者在事件中积累的现有“知识”所告知的行动的比例。这种策略被称为“贪婪搜索策略”在玩游戏之前,代理没有任何经验,因此通常会将 epsilon 设置为较高的值,然后逐渐降低其值。eps_decay
表示代理学习时ε减小的速度。0.99 来自最初的 DQN 论文。
稍后当我们到达相应的代理时,我将解释其他参数。
def q_learning(env, model, episodes, gamma=0.9,
epsilon=0.3, eps_decay=0.99,
replay=False, replay_size=20,
title = 'DQL', double=False,
n_update=10, soft=False):
"""Deep Q Learning algorithm using the DQN. """
final = []
memory = []
for episode in range(episodes):
if double and not soft:
# Update target network every n_update steps
if episode % n_update == 0:
model.target_update()
if double and soft:
model.target_update()
# Reset state
state = env.reset()
done = False
total = 0
while not done:
# Implement greedy search policy
if random.random() < epsilon:
action = env.action_space.sample()
else:
q_values = model.predict(state)
action = torch.argmax(q_values).item()
# Take action and add reward to total
next_state, reward, done, _ = env.step(action)
# Update total and memory
total += reward
memory.append((state, action, next_state, reward, done))
q_values = model.predict(state).tolist()
if done:
if not replay:
q_values[action] = reward
# Update network weights
model.update(state, q_values)
breakif replay:
# Update network weights using replay memory
model.replay(memory, replay_size, gamma)
else:
# Update network weights using the last step only
q_values_next = model.predict(next_state)
q_values[action] = reward + gamma * torch.max(q_values_next).item()
model.update(state, q_values)state = next_state
# Update epsilon
epsilon = max(epsilon * eps_decay, 0.01)
final.append(total)
plot_res(final, title)
return final
最直接的代理基于其最近的观察更新其 Q 值。它没有任何记忆,但它通过首先探索环境,然后逐渐降低其ε值来做出明智的决定。让我们来评估这样一个代理的性能:
Deep Q Learning
上图显示代理的性能有了显著的提高。它达到了 175 步,正如我们之前看到的,这对于一个随机的代理人来说是不可能的。趋势线也是正的,我们可以看到性能随着时间的推移而增加。同时,代理在 150 个纪元后没有成功达到目标线以上,其平均性能仍在 15 步左右,因此有足够的改进空间。
重放记忆
一次使用一个样本的𝑄近似不是很有效。上面的图表很好地说明了这一点。与随机代理相比,网络设法实现了更好的性能。然而,它无法到达 195 级台阶的门槛线。我实现了经验重放,以提高网络稳定性,并确保以前的经验不会被丢弃,而是用于培训。
体验回放将代理的体验存储在内存中。成批的经验是从记忆中随机抽取的,并用于训练神经网络。这种学习包括两个阶段——获得经验和更新模型。重放的大小控制了用于网络更新的体验的数量。内存是一个数组,存储代理的状态、奖励和动作,以及动作是否完成游戏和下一个状态。
# Expand DQL class with a replay function.
class DQN_replay(DQN):
def replay(self, memory, size, gamma=0.9):
""" Add experience replay to the DQN network class. """
# Make sure the memory is big enough
if len(memory) >= size:
states = []
targets = []
# Sample a batch of experiences from the agent's memory
batch = random.sample(memory, size)
# Extract information from the data
for state, action, next_state, reward, done in batch:
states.append(state)
# Predict q_values
q_values = self.predict(state).tolist()
if done:
q_values[action] = reward
else:
q_values_next = self.predict(next_state)
q_values[action] = reward + gamma * torch.max(q_values_next).item()targets.append(q_values)self.update(states, targets)
DQL with Replay
正如预期的那样,与只记住最后一个动作的神经网络相比,具有重放功能的神经网络似乎更加健壮和智能。大约 60 集之后,代理人设法达到了获奖门槛,并保持在这一水平。它还设法获得了可能的最高奖励——500 英镑。
双重深度 Q 学习
传统的深度 Q 学习往往会高估回报,导致训练不稳定,质量策略较低。让我们考虑 Q 值的等式:
The Bellman Equation. Source: Link
等式的最后一部分是对最大值的估计。这一程序导致系统性高估,从而引入最大化偏差。由于 Q-learning 涉及从估计中学习估计,这样的高估尤其令人担忧。
为了避免这种情况,我将定义一个新的目标网络。Q 值将取自这个新网络,这意味着反映主 DQN 的状态。然而,它没有相同的权重,因为它只在一定数量的集后更新。这个想法在 Hasselt et al .,2015 中首次提出。
添加目标网络可能会降低训练速度,因为目标网络不会持续更新。然而,随着时间的推移,它应该具有更稳健的性能。
q_learning
循环中的n_update
指定更新目标网络的时间间隔。
class DQN_double(DQN):
def __init__(self, state_dim, action_dim, hidden_dim, lr):
super().__init__(state_dim, action_dim, hidden_dim, lr)
self.target = copy.deepcopy(self.model)
def target_predict(self, s):
''' Use target network to make predicitons.'''
with torch.no_grad():
return self.target(torch.Tensor(s))
def target_update(self):
''' Update target network with the model weights.'''
self.target.load_state_dict(self.model.state_dict())
def replay(self, memory, size, gamma=1.0):
''' Add experience replay to the DQL network class.'''
if len(memory) >= size:
# Sample experiences from the agent's memory
data = random.sample(memory, size)
states = []
targets = []
# Extract datapoints from the data
for state, action, next_state, reward, done in data:
states.append(state)
q_values = self.predict(state).tolist()
if done:
q_values[action] = reward
else:
# The only difference between the simple replay is in this line
# It ensures that next q values are predicted with the target network.
q_values_next = self.target_predict(next_state)
q_values[action] = reward + gamma * torch.max(q_values_next).item()targets.append(q_values)self.update(states, targets)
Double DQL with Replay
双 DQL 重放已经超过了以前的版本,并一直执行 300 步以上。由于动作选择和评估的分离,性能似乎也更加稳定。最后,让我们探索一下对 DQL 代理的最后修改。
软目标更新
上面实现的用于更新目标网络的方法在最初的 DQN 论文中介绍过。在本节中,我们将探索另一种完善的更新目标网络权重的方法。我们将在每次运行后使用以下公式递增地更新目标网络,而不是在一定数量的步骤后更新权重:
目标权重=目标权重(1-τ)+模型权重τ
其中 0 < TAU < 1
This method of updating the target network is known as “soft target network updates” and was introduced in Lillicrap 等人,2016 。该方法的实现如下所示:
class DQN_double_soft(DQN_double):
def target_update(self, TAU=0.1):
''' Update the targer gradually. '''
# Extract parameters
model_params = self.model.named_parameters()
target_params = self.target.named_parameters()
updated_params = dict(target_params)for model_name, model_param in model_params:
if model_name in target_params:
# Update parameter
updated_params[model_name].data.copy_((TAU)*model_param.data + (1-TAU)*target_params[model_param].data)self.target.load_state_dict(updated_params)
DDQL with Soft Update
具有软目标更新的网络表现相当好。但是,好像并不比硬权更新好。
这张 gif 图展示了一名训练有素的特工的表现:
Trained Agent
结论
经验重放和目标网络的实现显著提高了开放人工智能平台环境下深度 Q 学习代理的性能。对代理的一些其他修改,如决斗网络架构(王等,2015 ),可以添加到该实现中,以提高代理的性能。该算法也可推广到其他环境。请随意测试它解决其他任务的能力!
笔记本链接:https://github . com/ritakurban/Practical-Data-Science/blob/master/DQL _ 卡特波尔. ipynb
参考
(1)强化 Q——用 OpenAI Gym 在 Python 中从头学习。(2019).Learndatasci.com。检索于 2019 年 12 月 9 日,来自https://www . learn data sci . com/tutorials/reinforcement-q-learning-scratch-python-open ai-gym/
(2)帕兹克,a .(2019)。强化学习(DQN)教程。检索自:https://py torch . org/tutorials/intermediate/reinforcement _ q _ learning . html
(3) Lillicrap,T. P .,Hunt,J. J .,Pritzel,a .,Heess,n .,Erez,t .,Tassa,y .,… & Wierstra,D. (2015)。深度强化学习的连续控制。arXiv 预印本 arXiv:1509.02971。
(4)范·哈瑟尔特(2016 年 3 月出版)。双 q 学习的深度强化学习。在第三十届 AAAI 人工智能会议上。
(5)王,z .,绍尔,t .,赫塞尔,m .,范哈瑟尔特,h .,兰托特,m .,&德弗莱塔斯,N. (2015)。用于深度强化学习的决斗网络架构。arXiv 预印本 arXiv:1511.06581。
(6)双 DQN 实现解决 OpenAI 健身房的横撑 v-0。(2019).中等。检索于 2019 年 12 月 20 日,来自https://medium . com/@ Leo Simmons/double-dqn-implementation-to-solve-open ai-gyms-cart pole-v-0-df 554 CD 0614d
利用索尼的 NNabla 实现深度 Q 网络
原文:https://towardsdatascience.com/deep-q-network-implementation-with-sonys-nnabla-490d945deb8e?source=collection_archive---------10-----------------------
NNABLA 是什么?
索尼发布了神经网络库,简称“NNabla”。
NNabla 是设备就绪的,通过有效的内存管理,具有快速的 GPU 训练速度。最有趣的特性是 NNabla 默认允许运行定义和运行定义。例如,定义并运行风格的代码如下所示。
# build static graph like tensorflow
x = nn.Variable((2, 3))
out = PF.affine(x, 10)# inference like sess.run
x.d = np.random.random((2, 3))
out.forward()
value = out.d
另一方面,由运行定义的样式可以写成这样。
with nn.auto_forward():
x = nn.Variable.from_numpy_array(np.random.random(2, 3))
out = PF.affine(x, 10)
value = out.d
更多示例代码可在https://github.com/sony/nnabla-examples获得。
NNABLA 中的深度强化学习
虽然索尼分享了许多监督学习实现,但没有任何深度强化学习(DRL)的例子。如果你曾经尝试过实现你自己的 DRL 代码,你知道有一些在监督学习中很少见到的技巧。
在本帖中,我将向您展示 Deep Q-Network (DQN)的实现,作为 DRL NNA bla 的第一步。完整的实现可在这里获得。超参数和实现细节遵循最初的 DQN,您可以将此代码用作学术论文的基线。
q 函数
由于算法的概述在许多其他博客帖子中有解释,我们只关注神经网络部分。这是一个完整的神经网络定义。
我必须解释上面代码中的两个技巧。
参数同步(更新目标)
如果熟悉 tensorflow,就知道参数同步可以用tf.assign
来写。但是,NNabla 目前在图形定义中没有参数赋值。要做到这一点,你必须直接操纵变量。
# copy source variable to destination variable
variable_dst.data.copy_from(variable_src.data)
data
属性表示参数的引用。您可以通过该属性访问和操作它们。
由于我通常是一个 tensorflow 程序员,我真的希望tf.assign
实现这种行为。最终我提交了一个 pull 请求让 NNabla F.assign
函数。
渐变剪辑(序列)
为了避免参数变化太大,在 DQN 中使用了剪辑渐变。实际上,NNabla 有F.clip_grad_by_norm
功能,但不清楚如何使用,因为关于这方面的文档较少。所以,我实现了如下。
grad = 10.0 * variable.grad / np.sqrt(np.sum(variable.g ** 2))
variable.grad = grad
10.0
是超参数尺寸。你也可以像data
属性一样访问渐变。在更新参数之前,您可以直接裁剪渐变。
结论
我用 NNabla 展示了 DQN 的例子,它也展示了你可以用 NNabla 编写你自己的代码。如果你在 GPU 机器上运行全部代码,你可能会注意到它的速度。在大多数情况下,由于良好的内存管理架构,NNabla 是最快的。此外,索尼报告了用 2176 个 GPU 进行最快的 ImageNet 训练。此外,NNabla 提供了简单的 Python APIs,如果你已经在其他库中编写了深度学习算法,你可以在一分钟内编写自己的代码。特别是,NNabla 针对嵌入式设备进行了优化。如果你对边缘深度学习感兴趣,NNabla 将是一个不错的选择。
使用 Connect 4 进行深度强化学习和蒙特卡罗树搜索
原文:https://towardsdatascience.com/deep-reinforcement-learning-and-monte-carlo-tree-search-with-connect-4-ba22a4713e7a?source=collection_archive---------5-----------------------
在之前的文章中,我写了如何使用 TD(0)算法实现井字游戏的强化学习代理。我实现了两种代理。第一个是表格强化学习代理,这意味着价值函数存储为一个表,该表包含游戏中存在的最佳策略的每个状态的所有值(在算法迭代期间学习)。因为游戏的状态少于 6000 个,所以可以存储所有的值。第二个实现是深度强化学习代理,这意味着我们不是将所有值保存在一个表中,而是训练一个神经网络来预测给定状态的值。这种方法更加通用和鲁棒,因为网络可以学习相似性,如状态空间中的平移或反射。
在这篇文章中,我想更进一步,尝试实现一个学习如何玩游戏 Connect 4 的代理。游戏包含一个 7 列 6 行的棋盘。每个玩家在他的回合中选择一列并从顶部丢一个彩色圆盘到最低的空位。第一个在水平、垂直或对角线上有四个相同颜色的圆盘的人获胜。Connect 4 远比井字游戏复杂,因为它有超过 10 个⁴状态。在这篇文章中,我将描述两种不同的方法。第一种方法是著名的深度 Q 学习算法或 DQL,第二种是蒙特卡罗树搜索(或 MCTS)。
深度 Q 学习
让我们首先定义我们的马尔可夫过程。正如在上一篇文章中,学习过程将是特定于每个玩家的,第一个或第二个,他们之间没有混合。这是因为它们具有不同的状态空间(例如,空棋盘在第一个玩家的状态空间中,而不在第二个玩家的状态空间中):
- 状态空间是每个玩家看到的所有状态。对于第一个玩家来说,它包括所有具有偶数个盘的板,而对于第二个玩家来说,它包括所有具有奇数个盘的板。
- 行动空间是玩家可以玩的每一栏的数字 1-7。
- 赢了奖励 1 分,输了奖励 1 分,平手奖励 0.5 分,否则奖励 0 分。
这里要注意的是,像每一个双人游戏一样,下一个状态不是由所采取的行动决定的,因为它也取决于对手的行动。两种状态之间的转换概率取决于玩家和对手的策略。
学习与初学者对战和学习与职业玩家对战是不一样的,因为转移概率是不同的。我将在文章中进一步讨论后者。
目标是学习 Q 函数:一个将状态-动作对映射到一个值的函数,该值表示每个玩家在特定状态下玩这个动作后将获得的未来奖励的预期平均值(实际上这并不完全正确,因为 Q 函数是在该动作之后的特定策略下定义的,但是 Q 学习算法收敛了最优策略的值)。在我们学习了 Q 函数之后,我们将选择玩使这个值最大化的动作。
q 函数的域包含超过 7*10 个⁴(超过 10 个⁴国家的 7 个可能的动作),并将它们映射到-1 到 1 之间的数字(奖励范围)。为了表示这个函数,我们将使用 CNN。
CNN 的输入将是一个矩阵 7*7,其中第一行是与动作相对应的一个热点向量,其他 6 行是状态表示,其中 1,-1 和 0 分别是玩家的盘、对手的盘或空点。
下图描述了该网络:
其中第一个卷积层的核选择为 5,其余卷积层的核选择为 4(对我来说选择 4 似乎是合理的,因为玩家需要连续 4 次才能获胜)。
根据 Q 学习算法计算目标:
Q(s,a) = Q(s,a)+α(max(Q(s’,a’)+gR-Q(s,a))
其中 Q 是 Q 函数, s 是状态, a 是动作, α 是学习率, R 是奖励, g 是折扣因子。
关于学习过程的几点注意事项:
- 我发现有计划的离线学习比在线学习效果更好。离线学习意味着成批的状态-动作对被存储,并且网络在这些成批的状态-动作对上被训练。我用了 300 个游戏的批次。规划意味着每一批都被训练了不止一次,而目标在每个时期都被重新计算。我使用了大约 5 个时期进行批处理。
- 博弈策略是一个贪婪策略,这意味着选择了探索因子 e。该因子根据所学习的 Q 函数来定义采取随机移动或最优移动的机会。该因子在训练期间下降。开始的时候我想鼓励探索,而后来我想学习和越来越多的优秀选手比赛。然而,偶尔我会增加探索系数,因为以下原因:我发现第一个玩家很快就会知道最好的第一步是在中间走,所以第二个玩家主要(当探索系数很小时)学会如何对付“中间的第一步”,而没有其他选择。为了解决这个问题(以及其他类似的问题),我偶尔会增加探索系数。
- 在第一次训练尝试中,我使用 ReLu 函数作为激活函数。我发现网络学习得不是很好,因为训练集有很多零标签样本,而 ReLu 函数学习起来很容易输出零。我用 LeakyReLu 函数替换了它,获得了更好的结果。
- 为了测试代理,我让它对着随机播放器播放了 300 集,测量了胜率。不到 2000 集就达到了 80%以上的成功率,但当我试图对抗它时,我很容易就赢了。后来,我通过让代理与固定代理竞争来测试学习,并测量了胜率。
- 最后我找到了一个很好的代理人。这不是一个超人的水平,但仍然很难击败它(你可以自己尝试)。
- 下图显示了 Q 代理在学习过程开始时相对于随机玩家的胜率。它还显示了平均 300 场比赛中每场比赛的平均移动次数。我们可以看到,随着胜率的增加,移动的次数减少,这表明代理人学会了赢,而且赢得很快。
DRL agent
蒙特卡洛树搜索
作为一种完全不同的方法,我使用蒙特卡罗树搜索算法或 MCTS 实现了一个代理。
这种算法背后的想法是创建一个博弈树,但不是探索所有可能的博弈,而是只选择最有希望的路线。树中的每个节点存储 2 个值:该节点被访问的次数,以及玩家访问该节点时赢得的胜利数。该算法包含重复多个情节的 4 个步骤。
- 选择——您从根——状态开始,并选择一个子——移动。我用置信上限(UCB1)来选择一个孩子。对于每个孩子,我计算了表达式: w/n+ csqrt(ln(N)/n)* 其中 w 是获胜的次数, n 是节点被访问的次数, N 是父节点被访问的次数, c 是在探索和利用之间平衡的因子。这是 MCTS 最重要的一点。选择最有希望的子节点,探索的机会很小。
- 展开—当您到达一个节点,其中有尚未访问的子节点时,随机选取一个节点并展开树。
- 模拟-玩随机模拟,直到游戏结束。
- 反向传播—反向传播到所有被访问的节点,访问次数增加 1,如果您获胜,获胜次数增加 1。
关于 MCTS 学习过程的几点说明:
- 代理要比 Q 学习代理多学很多集,但是学的快很多。在我的电脑上(不是很好的一台),100 多万集要学几个小时。
- 为了方便起见,每个玩家都有自己的树,尽管两棵树共享相同的信息。我发现这样做更严谨,而且与其他类型的智能体(例如 Q 学习智能体或随机智能体)进行游戏和学习更灵活。
- 存储一个 100 万集的树需要大约 800MB,并且当代理继续学习时它还在增长。所以它比 CNN 要大得多,CNN 在整个学习过程中保持不变。
- 下图显示了随着学习的进行,MCTS 代理相对于随机玩家的胜率。
MCTS agent
关于代码
我试图尽可能通用地实现代码。代码包含 4 种类型的类。
- 游戏类,包含了双人游戏的所有基础知识。特定的游戏类继承自这个类。我实现了 Connect 4 和 Tic-Tac-Toe 类。游戏类声明了所有需要在特定游戏类中实现的功能。
- 一个 Q 代理类——包含了一个双人游戏代理的所有基本功能。connect 4 Q 学习代理继承自该类。
- 模型类-包含神经网络模型和所有相关函数。
- MCTS 代理类——类似于 Q 代理类,但方法不同
如果你愿意,你可以通过只实现父类的已声明的未实现的函数来使用这个代码作为其他游戏或其他代理的框架。
总结
我们在这篇文章中看到了如何训练代理学习玩 Connect 4。尽管 Connect 4 有比 10⁴更多的可能状态,这意味着可能每一个玩过的游戏都是独一无二的,代理们学会了归纳并玩得很好。Q 代理玩家通过学习不同状态之间的相似性来学习归纳,而 MCTS 代理学习采取最有希望的路径。
我们现在可以尝试让两个代理相互竞争:
从结果中我们可以看到,第一个玩家在大多数情况下都是赢的,也就是说虽然看起来不是那样,但是第一个玩家有很大的优势。
原代码可以在这里找到
感谢您的阅读,如果您发现我的代码中有任何错误,请告诉我,我会修复它,如果您喜欢这篇文章,请鼓掌,如果您有问题,我将非常乐意回答。
深度强化学习:建立一个深度 Q 网络(DQN)来玩钢管舞
原文:https://towardsdatascience.com/deep-reinforcement-learning-build-a-deep-q-network-dqn-to-play-cartpole-with-tensorflow-2-and-gym-8e105744b998?source=collection_archive---------1-----------------------
Photo by the author
在本教程中,我将向您介绍如何训练一个深度 Q-net(DQN)模型来玩掷骰子游戏。我们会用 OpenAI 的健身房和 TensorFlow 2。本文假设您对强化学习和深度学习有所了解。
什么是强化学习和 DQN?
让我们从强化学习和 DQN 算法的快速复习开始。强化学习是机器学习的一个领域,它专注于训练代理在环境中在某些状态采取某些动作,以最大化回报。比方说我想做一个打扑克的机器人(代理)。该机器人将与其他机器人在有筹码和卡片的扑克桌上玩(环境)。这个机器人应该能够根据桌上的牌、手里的牌和其他机器人的下注(状态)来弃牌或下注(行动)。机器人想要最大化它赢得游戏的筹码数量(奖励)。
DQN 是一种强化学习算法,其中建立了一个深度学习模型,以找到代理在每个状态下可以采取的行动。
技术定义
RL 的基本术语包括但不限于:当前状态*【s】下一步状态*【s’】动作*【a】政策*【p】奖励【r】。状态-动作-值函数 (Q(s,a)) 是一个主体从当前状态开始的期望总报酬,其输出称为 Q 值。正如我所说的,我们的目标是在状态【s】选择某个动作【a】,以最大化回报,或 Q 值。
DQN 是深度学习和强化学习的结合。模型目标是逼近 Q(s,a) ,并通过反向传播进行更新。假设 Q(s,a) 的近似值为 y(hat ),损失函数为 L,我们有:
预测: y(hat) = f(s,θ)
损耗: L(y,y(hat)) = L(Q(s,a),f(s,θ))
在反向传播过程中,我们对损失函数求θ的偏导数,以找到使损失最小的θ值。因为这是监督学习,你可能想知道如何找到基本事实 Q(s,a)。答案是用贝尔曼方程。
贝尔曼方程: Q(s,a)= max(r+Q(s’,a))
在哪里
Q(s’,a)= f(s’,θ) ,如果 s 不是终端状态(最后一步的状态)
Q(s ',a) = 0 ,如果 s 则为终端状态
我们可以看到,当 s 为终态时, Q(s,a) = r. 因为我们是用模型预测 f(s ',θ) 来逼近 Q(s ',a)的真实值,我们把这个叫做半梯度。正如你可能已经意识到的,使用半梯度的一个问题是,模型更新可能非常不稳定,因为每次模型更新时,真实的目标都会改变。解决方案是创建一个目标网络,其中本质上是在特定时间步骤的训练模型的副本,因此目标模型更新不太频繁。
该模型的另一个问题是过度拟合。当我们在每局结束后更新模型时,我们已经潜在地玩了几百步,所以我们本质上是在做批量梯度下降。因为每一批总是包含一个完整游戏的步骤,模型可能无法很好地从中学习。为了解决这个问题,我们创建了一个体验重放缓冲区,它存储了几百个游戏的 (s,s ',a,r) 值,每次都从中随机选择一批来更新模型。
什么是横竿?
CartPole 是一种游戏,其中一根杆子通过一个未驱动的关节连接到一辆小车上,小车沿着无摩擦的轨道移动。钟摆开始直立,目标是通过增加和减少小车的速度来防止它倒下。单个状态由 4 个元素组成:小车位置、小车速度、磁极角度和磁极尖端的速度。
要移动杆子有两个动作:向左或向右移动。每走一步(包括终止一步),它获得+1 奖励。当杆倒下时,游戏结束,即当杆角度大于 12°,或手推车位置大于 2.4°(手推车的中心到达显示器的边缘)。新的健身房版本也有一个长度限制,当剧集长度超过 200 集时就会终止游戏。
履行
完整的代码是这里是。
1.构建 tf.keras 模型类
我们先在 TensorFlow 中实现深度学习神经网络模型 f(s,θ) 。在 TF2,急切执行是默认模式,因此我们不再需要先创建操作,然后在会话中运行它们。另外,TF2 在tf.function()
提供亲笔签名。有两种方法可以实例化一个模型。更简单的方法是通过链接 Keras 层来指定模型的正向传递,并从输入和输出创建模型。然而,为了训练更复杂和定制的模型,我们需要通过子类化 Keras 模型来构建模型类。更多详情,请见此处。
在 MyModel 类中,我们在__init__
中定义了所有层,并在call().
中实现了模型的向前传递。注意,输入形状是【批量大小,状态大小(本例中为 4)】,输出形状是【批量大小,动作数量(本例中为 2)】。本质上,我们向模型提供状态,并输出在每个状态下采取每个动作的值。call()
的@tf.function
注释支持自动签名和自动控制依赖。
2.构建主 DQN 模型类
主 DQN 类是创建、调用和更新深度 Q-net 模型的地方。我们刚刚建立的神经网络模型是深度 Q-net 模型的一部分。
在__init__()
中,我们定义了梯度下降的动作数量、批量大小和优化器。折扣因子γ是一个介于 0 和 1 之间的值,在下一步乘以 Q 值,因为代理人更不关心遥远未来的回报,而不是眼前的回报。我们还将 MyModel 初始化为实例变量self.mode
,并创建体验回放缓冲区self.experience.
,代理不会开始学习,除非缓冲区的大小大于self.min_experience
,一旦缓冲区达到最大大小self.max_experience
,它将删除最早的值,为新值腾出空间。
实例方法predict()
接受单个状态或一批状态作为输入,运行self.model
的正向传递并返回模型结果(动作的逻辑)。请注意,tf.keras 模型默认将输入识别为批处理,因此我们希望确保输入至少有 2 个维度,即使它是单个状态。
在train()
中,我们首先随机选择一批 (s,s’,a,r) 值,用布尔 done 表示当前状态 (s) 是否为终止状态。然后我们调用predict()
来获得下一个状态的值。注意,我们在这里使用复制的目标网络来稳定这些值。接下来,我们从贝尔曼函数中得到地面真值。如前所述,如果 state (s) 是终端状态,target Q(s,a) 只是奖励 (r)。在tf.GradientTape()
内,我们计算真实目标和预测的均方损失。因为我们没有使用内置的损失函数,所以我们需要使用tf.one_hot()
手动屏蔽逻辑。一旦我们得到损失张量,我们就可以使用方便的 TensorFlow 内置 ops 来执行反向传播。
RL 中的另一个重要概念是ε贪婪。ε是随时间衰减的 0 到 1 之间的值。这个想法是为了平衡探索和开发。当模型在开始时不太精确时,我们希望通过选择随机动作来探索更多,所以我们选择更大的ε。随着我们从玩游戏中收集更多的数据,我们逐渐衰减ε来更多地利用模型。ε-greedy 的实现在get_action()
。
在add_experience()
和copy_weights()
中,我们实现了前面提到的经验回放缓冲和目标网络技术。每次我们从玩游戏中收集新数据时,我们会将数据添加到缓冲区,同时确保它不会超过定义为self.max_experiences
的限制。我们将创建 DQN 类的两个实例:一个训练网和一个目标网。当训练网络用于更新权重时,目标网络仅执行两个任务:在下一步骤Q(s’,a) 预测值,以供训练网络在train()
中更新,以及从训练网络复制权重。
3.玩游戏
终于可以玩游戏了!
让我们通过向play_game()
函数传递 5 个参数来开始游戏:健身房预定义的横竿环境、训练网、目标网、epsilon 和重量复制的间隔步数。在函数内部,我们首先重置环境以获得初始状态。然后我们创建一个循环来玩这个游戏,直到它到达终端状态。在循环内,我们ε-greedy 选择一个动作,移动一步,将 (s,s ',a,r) 和 done 对添加到缓冲区,并训练模型。默认情况下,环境总是为每个时间步长提供+1 的奖励,但为了惩罚模型,我们在完成完整集之前,当奖励达到终止状态时,我们为奖励分配-200。iter
记录我们在一场比赛中走了多少步,这样我们就可以在每一步copy_step
将重量复制到目标网。游戏结束后,我们会返还全部奖励。
4.制作测试视频
训练完模型后,我们想看看它在横竿游戏中的实际表现。为此,我们简单地将 CartPole 环境包装在wrappers.Monitor
中,并定义一个保存视频的路径。我们通过充分利用模型来玩游戏,游戏结束后会保存一段视频。
5.定义超参数和 Tensorboard 日志,并把一切放在一起
DQN 模型现在已经建立起来了,我们需要做的就是定义我们的超参数,为 Tensorboard 输出日志并训练模型。让我们看看这是如何在main()
函数中实现的。
我们首先创建了体操侧身环境、训练网和目标网。然后,我们定义超参数和张量流摘要编写器。当前的超参数设置将在 15000 集后产生 200 的集奖励,这是当前 200 集长度内的最高奖励。然而,我们的模型很不稳定,进一步的超参数调整是必要的。
在 for 循环中,我们玩 50000 次游戏,随着玩游戏次数的增加而衰减ε。对于 Tensorboard 可视化,我们还跟踪每个游戏的奖励,以及窗口大小为 100 的运行平均奖励。最后我们通过调用make_video()
做一个视频,关闭环境。
一旦测试完成,你应该可以在你指定的文件夹中看到这样的视频。
要启动 Tensorboard,只需输入tensorboard --logdir *log_dir*(the path of your Tensorflow summary writer)
。
在您的终端(Mac)中,您将看到一个带有 Tensorflow 端口的本地主机 IP。点击它,您将能够在 Tensorboard 上查看您的奖励。
结论及对未来工作的建议
在本文中,我们了解到:
- 强化学习和 DQN 算法:
- 通过在 TF 2 中子类化 tf.keras.Model 来构建定制模型;
- 用 tf 训练一个 tf.keras.Model。gradient . Tape();
- 在包装器中创建视频。监测以检验 DQN 模型;
- 在 Tensorboard 上显示奖励。
但值得一提的是,由于自举、采样以及值函数逼近带来的不稳定性,DQN 并不能保证收敛。对 DQN 来说,横竿也是一个相对难学的环境。事实上,学习经常失败,上面显示的结果是在多次尝试后取得的。我很幸运地在 50k 个纪元内实现了收敛,但我怀疑这种情况每次都会发生。为了复制它,我强烈建议你至少运行几百万个纪元。
如果想要实现快速学习,可以使用较小的初始ε值,或者以较快的速率衰减。我当前的 epsilon 是 0.99,这意味着在 epsilon 衰减到一个很小的值之前,策略会渲染很长时间的随机动作。然而,ε的小初始值可能由于缺乏探索而导致学习陷入次优。
另一个重要的事实是,DQN 是一种偏离策略的算法,只要满足 Robbins-Monro 算法并且所有状态和动作已经被访问了无限次,Q 值甚至可以收敛于随机策略。因此,Q 值可能已经收敛,并准备在许多时代后用于预测,即使回报看起来并不完美。
为了使策略收敛,一旦值收敛,我们需要确保策略接近贪婪(ε接近 0),这可以通过播放足够多的剧集来实现。
为了进一步改进,我鼓励你探索更多的模型结构(更多的层,卷积层,其他激活函数等)。)和超参数设置(目标净复制步长、经验大小、ε衰减值等。).
我希望你能从这篇文章中得到乐趣。😃
3D 现实环境中无人机的深度强化学习
原文:https://towardsdatascience.com/deep-reinforcement-learning-for-drones-in-3d-realistic-environments-36821b6ee077?source=collection_archive---------6-----------------------
一个完整的代码,让您开始使用虚幻游戏引擎和 Python 在逼真的环境中实现深度强化学习。
注 1: 文中提到的 Github 资源库 DRLwithTL 已经过时。请使用以下更详细的存储库,而不是 https://github.com/aqeelanwar/PEDRA 的
注 2: 关于无人机强化学习更详细的文章可以在这里找到
概述:
上周,我公开了一个 GitHub 知识库,其中包含一个独立的详细 python 代码,使用虚幻游戏引擎在 3D 模拟环境中的无人机上实现深度强化学习。我决定在本文中介绍一个详细的文档。3D 环境在 Epic Unreal 游戏引擎上制作,Python 用于与环境交互,并使用 TensorFlow 进行深度强化学习。
Drone navigating in a 3D indoor environment.[4]
在本文结束时,您的机器上将拥有一个工作平台,能够在逼真的无人机环境中实现深度强化学习。你将能够
- 设计您的定制环境
- 将它与您的 Python 代码连接起来
- 使用/修改 DRL 的现有 Python 代码
对于本文,基本目标将是无人机自主导航。没有开始或结束位置,而是无人机必须尽可能长时间地导航,而不会撞到障碍物。代码可以修改为任何用户定义的目标。
完整的模拟包括三个主要部分
- 3D 模拟平台 —创建并运行模拟环境
- 接口平台 —模拟无人机物理以及虚幻和 Python 之间的接口
- DRL python 代码平台 —包含基于 TensorFlow 的 DRL 代码
这三个平台有多种选择。但是对于本文,我们将选择以下内容
- 3D 仿真平台— 虚幻引擎【1】
- 接口平台— AirSim [2]
- DRL python 代码平台— DRLwithTL GitHub 库[3]
本文的其余部分将分为三个步骤
- 步骤 1 —安装平台
- 步骤 2-运行 python 代码
- 步骤 3 —控制/修改代码参数
步骤 1 —安装三个平台:
建议为这个项目创建一个新的虚拟环境并安装依赖项。可以采取以下步骤来下载这些平台的入门指南。
- 克隆存储库:包含 DRL 代码的存储库可以使用
git clone https://github.com/aqeelanwar/DRLwithTL.git
2.下载 Alexnet 的 Imagenet 权重:DNN 在初始化时使用 AlexNet 的 Imagenet 学习权重,而不是随机权重。这给了 DNN 一个更好的训练起点,并有助于趋同。
以下链接可用于下载 imagenet.npy 文件。
下载 imagenet.npy
下载完成后,在 DRLwithTL 根文件夹中创建一个文件夹‘models’,将下载的文件放在那里。
models/imagenet.py
2.安装需要的包:提供的 requirements.txt 文件可以用来安装所有需要的包。使用以下命令
cd DRLwithTL
pip install -r requirements.txt
这将在激活的 python 环境中安装所需的包。
3.安装 Epic 虚幻引擎:您可以按照下面链接中的指南在您的平台上安装虚幻引擎
安装虚幻引擎的说明
4.安装 AirSim: AirSim 是微软为代理(无人机和汽车)开发的虚幻引擎开源插件,具有物理和视觉上的逼真模拟。为了在 Python 和模拟环境之间建立接口,需要安装 AirSim。可以从下面的链接下载
安装 AirSim 的说明
一旦一切安装妥当,我们就可以进入运行代码的下一步了。
步骤 2 —运行 DRLwithTL-Sim 代码:
一旦下载并运行了所需的包和软件,就可以采取以下步骤来运行代码
创建/下载模拟环境
您可以使用虚幻引擎手动创建您的环境,也可以从下面的链接下载一个示例环境并运行它。
下载环境
以下环境可通过上面的链接下载
- 室内长环境
- 室内扭转环境
- 室内通风环境
- 室内技术环境
- 室内金字塔环境
- 室内冰箱环境
上面的链接将帮助您下载 64 位 windows 环境的打包版本。运行可执行文件(。exe)来启动环境。如果您在运行环境时遇到问题,请确保 Documents/AirSim 中的 settings.json 文件已经被正确配置。您可以尝试使用 F、M 和反斜杠键来更改环境中的相机视图。此外,键 1、2、3 和 0 可用于查看 FPV、分割图、深度图和切换子窗口视图。
编辑配置文件(可选)
DRL 模拟的 RL 参数可以使用提供的配置文件进行设置,并在最后一节进行说明。
cd DRLwithTL\configs
notepad config.cfg **(# for Windows)**
运行 Python 代码
可以使用以下命令启动 DRL 代码
cd DRLwithTL
python main.py
运行 main.py 执行以下步骤
- 尝试加载配置文件
- 尝试连接虚幻引擎(室内 _ 长环境必须运行,python 才能与环境连接,否则将出现连接拒绝警告——除非建立连接,否则代码不会继续运行)
- 尝试创建 DNN 的两个实例(使用双 DQN)并用选定的权重初始化它们。
- 尝试为用户界面初始化 Pygame 屏幕
- 启动 DRL 算法
此时,可以看到无人机在环境中四处移动,收集数据点。下面的框图显示了所使用的 DRL 算法。
Block diagram of DRL Training and associated segments
使用 tensorboard 查看学习参数
在模拟过程中,可以在 tensorboard 上查看 RL 参数,如ε、学习率、平均 Q 值、损耗和返回。张量板日志文件的路径取决于配置文件中设置的环境类型、环境名称、和训练类型,由下式给出
models/trained/<env_type>/<env_name>/Imagenet/ **# Generic path**
models/trained/Indoor/indoor_long/Imagenet/ **# Example path**
一旦确定了日志文件的存储位置,就可以在终端上使用以下命令来激活 tensorboard。
cd models/trained/Indoor/indoor_long/Imagenet/
tensorboard --logdir <train_type> **# Generic**
tensorboard --logdir e2e **# Example**
终端将显示可以在任何浏览器上打开的本地 URL,并且 tensorboard 显示器将在运行时显示 DRL 参数。
使用 PyGame 屏幕的运行时控件
众所周知,DRL 渴望数据。对于复杂的任务,如仅使用前置摄像头在逼真的环境中进行无人机自主导航,在 DRL 收敛之前,模拟可能需要数小时的训练(通常在 GTX1080 GPU 上需要 8 到 12 小时)。在模拟过程中,如果您觉得需要更改一些 DRL 参数,可以使用模拟过程中出现的 PyGame 屏幕来完成。这可以通过以下步骤完成
- 更改配置文件以反映修改(例如降低学习率)并保存。
- 选择 Pygame 屏幕,点击 【退格】 。这将暂停模拟。
- 按下 ' L' 键。这将加载更新的参数,并将其打印在终端上。
- 点击 【退格】 键恢复模拟。
现在模拟只更新了学习率。其他变量也可以通过编辑模块 check_user_input 的 aux_function.py 文件进行更新。
Editing check_user_input module to update other parameters too
第 187 行的 cfg 变量有所有更新的参数,你只需要把它赋给相应的变量并返回值就可以激活它了。
步骤 3 —控制/修改 DRLwithTL-Sim 中的参数:
该代码使您能够控制
- 更改 DRL 配置
- 改变深度神经网络(DNN)
- 修改无人机行动空间
1.更改 DRL 配置:
提供的配置文件可用于在开始模拟之前设置 DRL 参数。
Config file used for DRL and sample values
- num_actions: 动作空间中动作的数量。该代码通过将摄像机帧划分为 sqrt(num _ actions)* sqrt(num _ actions)的网格来使用基于感知的动作空间[4]。
- train_type: 决定在 DNN 训练的层数。支持的值为 e2e、最后 4 个、最后 3 个和最后 2 个。更多的值可以被删除
- wait_before_train: 该参数用于设置训练应该开始的迭代。模拟在开始训练阶段之前收集了这么多的数据点。
- 最大迭代次数:确定用于 DRL 的最大迭代次数。当这些迭代完成后,模拟停止。
- buffer_len: 用于设置体验回放缓冲区的大小。模拟继续收集数据点,并开始将它们存储在重放缓冲区中。从该重放缓冲器中采样数据点并用于训练。
- batch_size: 决定一次训练迭代的批量大小。
- ε_ saturation:ε贪心法用于从勘探阶段过渡到开采阶段。当迭代次数接近该值时,ε接近 0.9,即 90%的动作是通过 DNN(利用)预测的,只有 10%是随机的(探索)
- crash_threshold :该值与深度图一起使用,确定无人机何时被视为虚拟坠毁。当到深度图上中心动态窗口中最近障碍物的平均深度低于该值时,奖励-1 被分配给数据元组。
- Q_clip: 如果设置为真,Q 值在超出某个值时会被剪切。有助于 DRL 的融合。
- train_interval: 该值决定训练的频率。例如,如果设置为 3,则每 3 次迭代后进行训练。
- update_target_interval: 模拟使用双 DQN 方法来帮助收敛 DRL 损失。update_target_interval 确定模拟在两个 Q 网络之间转换的频率。
- dropout_rate: 确定连接被丢弃的频率,以避免过度拟合。
- switch_env_steps: 决定无人机改变其初始位置的频率。这些初始位置设置在相应环境名称下的 environments/initial _ positions . py 中。
- ε_ 模型:线性或指数
2.更改 DNN 拓扑:
可在以下 python 文件中修改用于将 Q 值映射到其状态的 DNN。
network/network.py #Location of DNN
不同的 DNN 拓扑可以在这个 python 文件中定义为一个类。代码带有三个不同版本的修改后的 AlexNet 网络。如果需要,可以根据用户需要定义更多的网络。一旦定义了一个新的网络,可以修改net owork/agent . py文件,在第 30 行使用所需的网络,如下所示
3.修改无人机行动空间:
当前版本的代码支持基于感知的动作空间。更改配置文件中的 num_actions 参数会更改前置摄像头被分成的箱数。
Perception-based action space — Default action space used in the DRLwithTL code [4]
如果需要使用完全不同类型的动作空间,用户可以通过修改以下模块来定义它
**Module:** take_action
**Location: ** network/agent.py
如果修改,这个模块应该能够将动作号(比如 0,1,2,…,num_actions)映射到无人机的相应偏航和俯仰值。
总结:
本文旨在让您在真实的 3D 环境中开始使用深度强化学习平台的工作平台。文章还提到了可以根据用户需求修改的代码部分。工作中的完整代码可以在文献[4]中看到。
参考资料:
- https://www.unrealengine.com
- https://github.com/microsoft/airsim
- https://github.com/aqeelanwar/DRLwithTL.git
- http://arxiv.org/abs/1910.05547
如果这篇文章对你有帮助,欢迎鼓掌、分享和回复。如果想了解更多关于机器学习和数据科学的知识,请关注我@Aqeel an war或者在LinkedIn上与我联系。
深度强化学习
原文:https://towardsdatascience.com/deep-reinforcement-learning-pong-from-pixels-keras-version-bf8a0860689f?source=collection_archive---------10-----------------------
像素乒乓:Keras 版本
这是 Andrej Karpathy 关于强化学习的博客文章的后续。我希望这篇文章能简化 Karpathy 的文章,去掉数学运算(感谢 Keras)。这篇文章应该是独立的,即使你还没有看过其他的博客。
这里的博客是为了配合更深入的视频教程(YouTube 视频描述中的代码):
什么是强化学习
与机器学习/深度学习中的其他问题不同,强化学习的问题在于我们没有一个合适的“y”变量。然而,输入“X”也没有什么不同。例如,在这个特定的例子中,我们将使用 openAI 中的 pong 环境。输入将是游戏当前状态的图像。输出是要播放的移动。
奖励函数
RL 中的任务给定游戏/环境的当前状态(X ),以采取将最大化**未来* *预期折扣奖励的行动。一个替代方法是,我们将游戏玩到最后,用一个折扣变量 gamma(数字在 0 到 1 之间)将当前时间点的所有奖励相加,如下所示:
R variable
为什么不简单的当前奖励 r_t?这是由于延迟奖励。当一个动作被采取时,它的影响不仅影响当前状态,还影响随后的状态,但是以衰减的速率。因此,当前行动负责当前奖励和未来奖励,但是越来越少的责任移动到未来。
模型
该模型用于生成动作。因此,在我们的例子中,我们使用图像作为输入,通过 sigmoid 输出来决定是向上还是向下。
关于上面提到的 R 变量,请注意我们的模型所产生的行动是如何导致奖励的。这很大程度上是一个盲人领盲人的例子。但是随着更多的迭代完成,我们收敛到更好的输出。
我们将使用的模型不同于 AK 博客中使用的模型,因为我们使用了卷积神经网络(CNN ),如下所述。使用 CNN 的优势在于我们需要处理的参数数量明显减少。具有 100 个神经元的 1 个隐藏层的密集网络将产生大约 640000 个参数(因为我们有 6400 = 80×80 像素)。然而在下面显示的模型中我们只有 3100 个参数。
另请注意,最后一层有一个 sigmoid 输出。这是为了让模型预测桨向上或向下移动的概率。
model = Sequential()
model.add(Conv2D(4, kernel_size=(3,3), padding='same', activation='relu', input_shape = (80,80,1)))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Conv2D(8, kernel_size=(3,3), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Conv2D(16, kernel_size=(3,3), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(2, activation='softmax'))
预处理
我们裁剪图像的顶部和底部,并在水平和垂直方向上每隔一个像素进行二次采样。我们将球拍和球的值设置为 1,而背景设置为 0。然而,输入到 DL 算法中的是两个连续帧的差。这导致输入图像的大小为 80x80。
损失函数
拼图的最后一块是损失函数。我们有自己的输入,也就是上面提到的 X 变量,但是,目标 y 变量是在那个时间步采取的动作。即向上将是 1,向下将是 0。
但是等等,y 变量不是模型规定的吗?是的,你完全正确。因此,我们不能简单地使用通常的交叉熵损失,因为概率 p(X)和 y 是由同一模型生成的。相反,我们所做的是用在那个时间点的预期未来回报来衡量。
因此,在每集结束时,我们运行以下代码进行训练:
model.fit(x, y, sample_weight=R, epochs=1)
然而,实际损失函数保持不变,
model.compile(optimizer='rmsprop',loss='sparse_categorical_crossentropy')
关键是,如果这一步棋走得好,我们使用上面的sample_weight
功能来衡量他们。
摘要
总而言之,当你不关心实际的梯度计算时,政策梯度更容易理解。所有当前的深度学习框架都考虑到了你可能需要的任何衍生品。
策略梯度是更基本的强化学习问题之一。如果你想了解更多关于强化学习的知识,请订阅我的 YouTube 频道。该播放列表包含更高级 RL 算法的教程,如 Q-learning。
看这里是我关于机器学习和深度学习的课程(使用代码 DEEPSCHOOL-MARCH 到 85 折)。
深度 RL 案例研究:混沌梯度
原文:https://towardsdatascience.com/deep-rl-case-study-policy-based-vs-model-conditioned-gradients-in-rl-4546434c84b0?source=collection_archive---------22-----------------------
为什么一些 RL 算法有臭名昭著的不可靠的梯度,最近的研究对此做了什么,以及替代方案的有效性如何?
策略梯度是 RL 中的经典算法。普通政策梯度(VPG)归结为试图增加产生高回报的行动的可能性。估计更新规则需要一些假设,但是它在实践中已经被证明是可行的。本文将假设 RL 中的一个简短背景,所以如果像马尔可夫决策过程、重要性抽样、梯度、似然性等词。我建议回到一些机器学习的基础知识。本文底部的一些资源可能会有所帮助。本文回顾了标准策略梯度,介绍了修改后的策略更新规则,并解释了为什么这种变化可能意味着更有用的学习算法。
最终,VPG 使用了一种仅基于行动概率和通过轨迹的回报的策略估计器,但 RL 的一篇新论文 PIPPS 建议通过学习动力学模型传播粒子来估计梯度,以显著减少方差,从而潜在地实现了 RL 策略生成的新的基于模型的方法的收敛。
Gif of policy gradient enabled cart pole, directly from source tutorial.
RL 复习工具
这里有一些你会在这篇文章中看到的符号。
RL 问题的大背景是观察在部分观察的世界中采用 RL 策略的代理所采取的行动。这些反馈循环是代理采取的动作以及它如何更新其策略参数。
Big picture of an RL problem. Source: Berkeley’s Deep RL Course
审查:普通政策梯度
在 VPG,梯度是在没有任何动力学模型知识假设的情况下估计的。首先,我们有一个 RL 问题的总体公式——优化参数以根据某个代理的进化最大化回报。
General formulation of any RL algorithm — maximize expected reward. Source: Berkeley Deep RL Course
这里需要注意的一点是,状态转换和动作概率是如何结合起来生成轨迹概率的。读者的一个练习是考虑在给定初始状态和转移概率的情况下,如何表达当前时间 T 的动作概率。
Trajectory evolution probability subject to a probabilistic policy. Source: Berkeley Deep RL Course
在政策梯度中,我们希望估计价值函数的梯度,并使我们的政策逐步达到最优。下面是关于轨迹演变的回报预期的扩展(稍后将更多地讨论状态转换的省略)。蓝色部分是一个叫做重要性抽样的关系——ML 中改变积分和期望形式的一个常用技巧。
The formulation of a standard policy gradient. Arrive at this from expanding the expectation with respect to the transition probabilities. Source: Berkeley Deep RL Course
Aside showing the relation for importance sampling. This comes from the derivative of the logarithm. Source: Berkeley Deep RL Course
具体来说,让我们看看构成一个策略的对数概率的项。如果我们将对数概率展开,得到一个带初始项的和(这个等式是我前面提到的练习的结果),我们会看到有两个相关项 1)政策概率和 2)转移概率。在这种情况下,转移概率不依赖于模型参数,并趋向于 0。如果我们可以用这种进化来通知我们的梯度呢?
Source: Berkeley Deep RL Course
Source: Berkeley Deep RL Course
有了这些公式和几个步骤,下面的政策梯度更新就出现了。这里,我们包括给定状态和动作的估计优势,这是一个状态的当前值和给定当前动作的当前状态的估计回报之间的差。这是您将在许多教程中找到的标准策略渐变。
Source: Spinning Up in RL
Source: Spinning Up in RL
策略梯度使用在确定性状态转换空间中采样的随机策略作为其轨迹。这不需要了解系统的演变,但假设一个确定性的模型。这就是经典的无模型强化学习。
这里有一段摘自 scholarpedia 的摘录,我发现它对于总结普通政策梯度中的估计假设特别有用:
Direct capture from source: http://www.scholarpedia.org/article/Policy_gradient_methods
注意,当在 RL 中使用成本函数时,我们通常镜像传播奖励梯度的设置,但是现在相对于一些函数 c(s)的负值最小化。这个负号经常被忽略,但是你可以思考一下为什么负成本函数最大化反映了回报。没有这种对偶,成本函数公式将会不同。
混沌诅咒和其他渐变谜题
这里有一些需要解决的政策梯度方法分歧的原因。
- VPG 历史上有很高的方差。这种差异是由用于生成梯度的所有样本都是从政策轨迹生成的这一事实引起的。如同在任何实验中一样,这些轨迹通常包括产生噪声梯度的不同数据集。大多数先进的政策梯度技术都是建立在核心理念之上的,即在减少差异的同时,将梯度推向具有更高回报的行动,如基线或改变抽样方法。
- 合成任何高度非线性的函数经常会导致数值发散。神经网络动力学模型已经显示出对于简单的实验很好地收敛,但是当在有噪声的数据上训练时,导数信息通常变得高度敏感。使用高斯过程动力学模型可以通过解析梯度缓解这一问题,但 GPs 缺乏神经网络的规模和效率。
- 混沌的诅咒:在下面的论文中,PIPPS 在基于模型的 RL 中模拟渐变时引入了这个想法。想法是用于初始化的神经网络策略,当通过任何类型的学习的动力学模型传播梯度时,对初始条件的小变化有很强的敏感性。对于一致且稳定的算法,初始条件的微小变化会导致结果的微小变化,PIPPS 开始着手解决这一问题。
PIPPS:灵活的基于模型的策略搜索,对混乱的诅咒具有鲁棒性
Illustration of methods for calculating gradients. PIPPS uses particle methods to estimate the true underlying distribution rather than attempting to analytically derive the underlying distribution. Source: PIPPS.
PIPPs 是我研究领域的一篇最新论文,以基于文章的政策研究的 P 机器人学 I 会议命名,解决基于模型的 RL 的政策研究中的正则化梯度问题。本文使用基于模型的 RL 在已知系统动力学的背景下计算政策梯度,在上文讨论的更典型的无模型变体之上构建基于模型的框架。在 PIPPS 的第 3.2 节中,作者使用带有随机动力学模型的确定性策略,通过动力学模型将基于粒子的梯度直接传播到策略中。回想一下 VPG 框架中对政策梯度的估计,但是由于确定性政策和随机模型,现在我们有不同的项趋向于 0。
Note, with a probabilistic state evolution, and deterministic policy, the action at time t is a result of the policy parameters, and the probability of an action given a state goes to 0 because the logarithm of 1 is 0 (deterministic policy).
策略参数梯度的这一新结果为我们提供了策略梯度更新规则的新的总表达式!此更新规则通过动力学模型对一组运行策略的粒子进行采样。这是一个基于粒子的动力学模型调节的渐变。
The gradient estimator based on particle based estimation with a deterministic policy and stochastic dynamics model. Source: PIPPS. This is the new policy gradient equation.
上面要注意的主要项目是状态转移的概率代替梯度估计中的动作概率。在 PIPPS 中,期望是跨越模拟粒子的,而在 VPG 中,期望是跨越实验轨迹的。PIPPS 设计用于学习动力学模型,而不仅仅是通过实验学习。该梯度方程使用已知的模型导数和似然比来减少方差。他们的基础实验结果显示了梯度方差的数量级减少。核心是动力学模型导数比神经网络策略导数更可靠。
如果您更详细地阅读论文中的,您将会看到更深入的方程,解释该估计器(似然比梯度)与重新参数化梯度和批处理模式并行计算的组合。这种直接梯度计算的激动人心的部分在结果中,第 4.1 节,图 3,其中这种 LR 梯度与它们的总传播算法具有相同的方差数量级。
与我的研究有关
PIPPS 为我们提供了一种工具,可以在传播梯度和进行“无模型 RL like”策略更新时使用学习到的动力学模型(我可能会添加一篇总结基于模型的实验 RL 最新进展的文章的链接)。由于估计量的高方差,仅基于随机策略的标准策略梯度估计在实验中有规律地发散。加上组成神经网络动力学模型的高方差,普通策略梯度需要一些增强来收敛。 PIPPS 允许我们使用基于粒子的方法调整基于 VPG 轨迹的梯度的方差,利用潜在的动力学模型。
Standard policy gradient learning process. All online experiments aimed to maximize a reward signal of on policy rollouts.
关于这种正则化技术在我们的情况下是否有效的最终问题是 PIPPS 梯度和轨迹估计是否可以处理实验学习的动力学模型的高认知不确定性(认知方差是由实验中的噪声引起的,该噪声可以被模型捕获,但不能,与重复过程中的随机性或方差相比,它是任意的不确定性)。我们的模拟使用了一个动力学模型,该模型被训练成用方差上的正则化项来匹配状态的变化,作为基本事实。策略梯度通常被认为是一种基于策略的算法,因此我们通过将我们学到的动态作为基础事实来欺骗这一标准,这在策略学习中存在明显的风险,以利用模型中的不准确性。
假设从动态模型引入的方差明显小于改变梯度传播方式所获得的减少量。我们正在使用实验数据来学习动态模型,并制定不同类型的政策。希望 PIPPS 能够通过依赖一个训练有素的动态模型而不是实验中的部署来实现更加高效的离线策略生成。我们将基于 PIPPS 的政策梯度作为基线的其他方法有:MBRL+MPC、模仿 MPC 和 ME-SAC(模型集合软演员评论家)。PIPPS 是以下问题答案的一部分:给定一组来自机器人的初始实验数据,我们对系统动力学没有基本的了解,那么生成控制策略的最佳方式是什么?
Our experimental sketch. We will use the regularization of PIPPS to enable offline model-based policy generation on purely experimental data. We can now use experimental data from any run to generate a dynamics, create a simulation environment, and train a policy.
梯度架构中的这种微妙变化可以利用我们已经或可以学习的知识,这就是为什么我对基于模型的 RL 的实际使用感到兴奋。通过使用我们拥有的背景,我们应该能够做出更可靠的梯度估计和政策改进。我希望在未来几年看到越来越多基于模型的强化学习的应用,但我确实看到无模型学习的总体目标在试图理解人类大脑如何运作方面更令人信服和有趣。
其他链接
我正在进行使用 PIPPS 在已学习的动力学模型上训练政策的实验,你可以在这里跟随并试验代码:https://github . com/NATO Lambert/dynamics-learn/blob/master/PIPPS _ psuedocode . py。我可能会创建一个关于实验的后续帖子,但在发表之前不会发布完整的细节。向 nol@berkeley.edu 提出问题。
参考
- 来自的方程式 OpenAI 在 RL 上关于政策梯度的旋转。他们的文档并没有包含所有的算法,但是质量是一流的。
- [伯克利的深度 RL 课程。](http://rail.eecs.berkeley.edu/deeprlcourse/)我在 2018 年秋季上了这门课——很棒的东西。我很幸运能与谢尔盖·莱文的研究小组中多名极其聪明的学生合作。
- Scholarpedia 关于政策梯度的注释。本资源的新内容,但它们为理解本主题提供了很好的范围&细节。
- 皮普斯论文:帕尔马斯,p .,拉斯姆森,C.E .,彼得斯,J. &多亚,K..(2018).PIPPS:灵活的基于模型的策略搜索,对混乱的诅咒具有鲁棒性。第 35 届机器学习国际会议论文集,PMLR 80:4065–4074。
厚三明治
原文:https://towardsdatascience.com/deep-sandwiches-f8ee72d534a3?source=collection_archive---------15-----------------------
Picture a room with grid lines on the walls, and look at the corner. If you’ve ever tried to learn some A.I., you’ll have heard that deep neural networks are “stacks of layers built from linear transformations followed by rectified nonlinearities.” All that jargon hides a simple idea. Our room is just the “graph” of one layer. Each layer takes a grid of squares, and bends it to look like the room. As intimidating as the mathematics of modern A.I. can seem from the outside, behind the scenes we’re mostly just taking the space where your data lives and then doing the room thing over and over. (Photo by Kevin Laminto on Unsplash).
想象一下,通过食物基本定律的奇迹,有人发现我们可以制作任何我们想要的东西,只要用两种原料:面包和火腿制作三明治。如果我们只是单独堆放面包,这种现象就不会出现。一大堆面包只是,嗯,面包。但是假设我们发现用正确的烹饪程序,一个足够大的顺序面包+火腿+面包+火腿+等等。可以变成鸡汤、千层面或鱼子酱——或者人类厨师从未想过要创造的食物。
如果这个例子看起来不可信,很好!大多数人工智能研究人员也没有预见到它的到来。但从 2012 年(或 2009 年(或 20 世纪 80 年代(或 20 世纪 60 年代,取决于你开始计算的时间))开始,某个专注于“如何从数据中学习东西”的数学领域有了自己的“不可能的三明治”时刻。从那时起,那个领域的“杂货店”,有着各种不同的成分,用于不同的特定目的,在“通用火腿”的稳步前进下,开始变空并改变形式。在非常真实的意义上,这就是最近围绕深度学习的所有炒作的全部内容。
人工神经网络是我们的三明治。深度神经网络只是有很多层的三明治。什么算“深”?那并不重要。为了理解最近围绕深度学习的所有炒作的原因,我们真正需要理解的是(1)“成分”,和(2)“烹饪”过程。
“面包”层就是数学家所说的线性变换。想象空间是一张有网格线的有弹性的图纸。任何扰乱空间的方式,其中之前是线的东西保持在之后是线,都是面包的一个例子。所以,旋转是面包,因为当我们旋转空间时,任何一条线都是一条线。通过把所有东西都变大一倍(或一半,等等)来延伸空间。)是另一种面包。我们也可以抓住空间的两边,向下移动我们的左手,向上移动我们的右手,这样垂直线保持垂直,水平线倾斜,小格子变成平行四边形。那叫剪羊毛,也是一种面包。这差不多是所有的面包了。如果我们把一堆这样的东西一个接一个地堆叠起来,那么由于每片面包都保持线条作为线条,整个堆叠也会保持线条作为线条。
所以,一堆面包不是三明治。仅仅靠堆积面包本身,我们不会取得任何进展[1–3]。那么,什么是“火腿”?
事实证明火腿几乎可以是任何东西。重要的是,这是一些步骤,弯曲网格线,使他们不再是线。所以,一个随机选择的三明治会旋转/缩放/剪切空间,然后弯曲一些网格线,然后再次旋转/缩放/剪切,然后弯曲更多的网格线。如果我们把三明治做得足够“深”,我们可以想象原来的空间可能会弯曲并折叠很多。
目前尚不清楚的是,我们究竟应该如何利用这一切完成任何事情。
现实世界中的深度神经网络
现实世界的使用问题都归结于烹饪过程。
实际上,我们并不知道如何写出好的神经网络。我们知道如何训练他们。训练神经网络意味着向它展示我们希望它解决的问题的例子,然后告诉它如何稍微改变自己,使其更像一台机器,让给出正确的答案。我们一遍又一遍地这样做,直到网络“学会”解决问题。
这给了我们一种与计算机互动的新方式——一种通常被称为“软件 2.0”的方法[6]。有了软件 2.0,就好像你不知道如何烹饪千层面,但你有一些旧的千层面,你有一个神奇的烤箱——一个让你只需把一个大(即“深”)火腿三明治放在一堆千层面旁边,然后等一会儿,瞧!…是千层面。你刚刚“煮”了千层面吗?有点——还不清楚。显而易见的是,你现在又多了一份千层面,而不需要知道怎么做。
这对整个计算来说意味着我们现在可以解决我们不知道如何解决的问题。我们可以编写我们不知道如何编写的程序。委婉地说,这改变了一切。
这种方法在现实世界中的用例(和限制)或多或少是您从烹饪类比中所期望的。如果我们没有这些千层面样品展示给我们万能火腿,我们就不可能做出新的千层面。这在实践中意味着,深度学习最直接适用的用例是那些我们有很多很多例子的用例。也就是说,大数据集,沿着我们想要解决的任何问题的边界被清理和分离。如果我们想训练一个深度神经网络来检测图片中的猫,我们不需要知道如何编写代码来实现一个检测猫的视觉系统,一行一行,一条一条地。我们确实需要大量的猫的照片。加上一个巨大的未煮过的网络,和一些时间。
深度神经网络的市场采用
深度学习已经被你能说出的每个行业的市场所采用,并且它的采用没有放缓的迹象。你的手机中有深层网络,可以将语音转录成文本,听你说“好的,谷歌”或“嘿,Siri”。有网络可以检测相机视野中的人脸,并根据他们的位置和地点设置自动对焦。他们已经学会了如何阅读。他们是 Google Translate 等系统的支持者,Google Translate 曾经包含大量短语表以及每一对语言的可能翻译。他们不仅打败了国际象棋和围棋的世界冠军,而且更令人印象深刻的是(也很少有人强调),他们打败了 30 多年来最优秀的人工智能研究人员试图通过使用特定领域的知识来设计手工编码的“智能”算法来玩这些游戏 AlphaZero 的最新版本不是通过对单个游戏的内置知识来实现超人的性能,而是通过让算法一次又一次地与自己对弈,直到它超越最熟练的人类和我们人类所构想的最佳算法。
甚至在科学研究中,以前不可逾越的障碍也开始消失。生物化学中最基本的问题之一是蛋白质折叠。这个问题对于药物研发来说至关重要,因为蛋白质在体内的功能是由其三维形状决定的。2018 年 12 月,谷歌的 DeepMind 发布了一个名为 alpha fold[7–8]的模型。他们训练了一个神经网络,根据其残基之间的成对距离来预测蛋白质的结构,这样做成功地远远超过了现有的方法,导致一位科学家评论说,在第一次听到结果时,他觉得自己和他所在领域的其他学者已经过时了[9-10]。
虽然距离我们学会在所有活动中超越人类智力还有很长一段时间,但有一点是肯定的:深度学习将会持续下去。人类生活的任何领域都不可能不变。
进一步阅读
面包
【1】3 蓝色 1 棕色。线性变换和矩阵。
【2】3 蓝色 1 棕色。矩阵相乘作为合成。
【3】3 蓝色 1 棕色。三维线性变换。
火腿
【4】deep mind。深度学习第三讲。神经网络基础。(相关章节从 37:47 开始)。
【5】蒙图法尔,帕斯卡努,乔,&本吉奥(2014)。关于深度神经网络的线性区域数。
烹饪
【6】卡帕西。软件 2.0。
结果
【7】罗伯特·f·服务。谷歌的 DeepMind aces 蛋白质折叠。
【8】deep mind。 AlphaFold:利用人工智能进行科学发现。
【9】西加尔缪尔。一位科学家如何应对艾在他一生的工作中击败他。
【10】穆罕默德·阿尔库莱希。刚刚发生了什么?
深海对比
原文:https://towardsdatascience.com/deep-sea-correlation-27245959ccfa?source=collection_archive---------30-----------------------
Depth’s correlation with temperature
“世纪发现”
当我在互联网的黑暗深处搜寻数据时,我偶然发现了“世纪发现”数据集不仅非常有趣,而且相当大。这对于测试我的机器学习模块车床的可用性来说非常棒,我即将为它发布一个新的稳定版本(0.0.3),这个版本确实增加了可用性,所以如果你对 Julia 感兴趣,但不想被困在 GitHub read-me 文档中,现在是时候做出改变了。此外,凭借高达 864,863 次的观察和 74 个功能,我正式指出,我肯定想要一个巨大的深度学习桌面。还有,笔记本在这里。
应该指出的是,这个问题与车床或 Julia 中的机器学习毫无关系,而是:我的个人电脑内存不足。此外,没有一个性能问题来自执行测试或获得预测,这仅需要 1-6 秒,而是绘制了 200,000 个点。增加性能问题的是我过时的 R9–290 4GB,带有 AMDGPU Mesa 驱动程序(通过重新编译 Grub 实现。)对于像我一样好奇的硬件爱好者来说,我只有 8GB 的单通道 DDR3,股票时钟是 2666 MhZ,但我不认为它会以那个频率运行,这可能是影响最大的(Jupyter 不断返回说它的内存不足。)
阅读和清洁
首先,我们必须使用 CSV.jl 读入我们的数据帧
using CSV
df = CSV.read("bottle.csv")
为了更好地查看数据,我喜欢这样做:
show(df, allcols = true)
我拿出了几个看起来很有趣的连续特性,我想对它们进行测试,当然这是一种标准做法,但我也要注意,用 dataframes.jl 分析数据并不像我希望的那样好:
using DataFrames
df = DataFrame(:TempC => df.T_degC, :Salinity => df.R_SALINITY, :Depth => df.Depthm)
该数据帧包含大量缺失值,但是在删除之前将我们的要素删除是不可或缺的,这样我们就不会删除多余的内容。为了删除数据,我使用了:
df = dropmissing(df)
主意
我想我们应该从我们所拥有的开始,或者更确切地说,是我决定在这个特定的时间里保留的东西。我们有三个特征,深度,温度和盐度。利用这个我可以做一点基于物理学的科学推断,并提出以下假设:
假设 1
如果水的深度更低,那么温度应该更低,因为水应该更重,离太阳更远。
假设 2
如果水的深度较低,那么水的盐度应该较高,因为含盐量少的水应该比含盐量多的水浮力大。
假设 3
如果水的盐度更高,那么水的温度应该更低,因为更高的盐度将导致更高的深度,以及相同质量的更密集的分子。
构成盐的两种元素是钠和氯。)Na 有 11 个质子,Cl 有 17 个。每个分子加起来有 28 个质子。另一方面,H2O 是两个氢原子,都有一个质子,而氧原子有八个质子,加起来每个原子只有 10 个质子。快速浏览周期表可以发现,氢的原子质量是 1.0079,氧的原子质量是 15.9994。至于氯化钠,钠的原子量是 22.9897,氯的原子量更高,为 35.453,我们当然可以把这个代入朱莉娅:
function molecular_weight(atomm1,n1,atomm2,n2)
res = (atomm1 * n1) + (atomm2 * n2)
return(res)
end
然后我们可以输入我们的数字:
所以,当然,水中的氯化钠越少,水的浮力就越小。
但是现在化学已经足够了,因为我是数据科学家,不是化学家…
预处理
预测建模最重要的部分之一是预处理。幸运的是,车床已经为我们覆盖了这一部分。这就是我们在 Julia 使用车床时需要做的:
using Lathe.preprocess: StandardScalar, TrainTestSplit
现在,我们需要将数据放入测试集和训练集。车床使这变得非常简单,只需做:
train,test = TrainTestSplit(df)
很简单,对吧?现在,我们必须选择我们的目标和功能。我们将会看到我已经进行了统计实验的数据。我也将在这里应用标准标量。
对于我们的功能,我们将从预测深度对温度开始,看看我们有什么。
trainX = StandardScalar(train.TempC)
trainy = train.Depth
testX = StandardScalar(test.TempC)
testy = test.Depth
简单! 现在让我们做一些机器学习。
获取基线
为了快速获得基线,我们将:
using Lathe.models: MeanBaseline
bs = MeanBaseline(trainy)
请注意,我们不必拟合 x。然后,我们可以用以下公式预测我们的 train-x:
baser = predict(bs,testX)
确认
为了验证我们的回归模型和基线,我们将使用平均绝对误差和 R。当然,R 并不是对平均基线预测的真正验证,所以我们将使用 MAE。
using Lathe.validate: mae,r2
mae(testy,baser)
我们的回报是:
211.39011214882413
我选择研究 TestX 和 TestY 的平均值,鉴于这里有如此多的数据,我可能会考虑回去调整更大的训练集和更小的测试集,因为测试是在大约 250,000 个观察值的基础上进行的,这是非常巨大的,只会使验证和模型探索无法进行。
嗯,结果是不幸的…至少,老实说,我需要双重通灵。我不会担心,因为我们可以很快重启内核…
我能够将数据分割成大约 95 %,仍然有大约 40,000 个观察值的训练集,在我(和我的计算机)看来,这已经足够了。
线性回归
首先,像往常一样,我们拟合我们的数据:
linrmod = LinearRegression(trainX,trainy)
然后我们将构建的模型类型放入 predict()方法中。
preds.LinearRegression = predict(linrmod,testX)
那么模型做的怎么样呢?
嗯……很复杂。
我们的平均绝对误差低得离谱,远低于 1 的一半。然而,我认为考虑我们的模型和数据是很重要的。首先,我们需要数据的平均值,以便很好地了解一个大的误差会产生多大的影响。
using Lathe.stats: mean
mean(testy)
返回了:
10.864412863141867
虽然,在某种程度上,平均值为 11,平均绝对误差为 0.00550,这并不坏,但当我们得到回归的相关系数(r)时,问题就来了
那么:这告诉了我们什么?线性回归不是预测该数据的最佳模型。这当然是逻辑回归的工作,但我还没有为此编写模型,至少现在还没有,所以让我们尝试一些其他的回归模型,但首先,让我们看看这里发生了什么。
上面我们看到的是实际数据,它显然有一个负斜率,但是非常非线性。换句话说,假设方差在低深度和高深度基本不存在,线性模型可以给出我们可以预期的想法,但实际上不能精确建模。这是我们模型的样子:
为了给出一个更好的想法,我认为在 GNU 图像处理程序中用 alpha 覆盖这两个可视化效果会产生一些思考:
另外,如果你在 Julia 工作,并且想使用 Plots.jl 快速深入地了解 GR,你可能会发现这篇小文章很有用。
该模型实际上在这里找到了相关性,然而,问题在于相关性并不是真正线性的。这当然是任何线性模型的弱点,即一条线在它的整个行程中以一定的斜率延伸。所以看这个,很明显我们需要一个不同的模型来预测这个。我们也看到了为什么我们有这么低的平均绝对误差,同时也有这么低的 R 值,模型预测是负面的。因此,由于我们还没有在车床 0.0.3 逻辑回归,我想我们会尝试一些其他模型,只是为了好玩,每当我编程逻辑回归,和一些更多的模型,我们将重新访问这些数据。
安装一个方形模型(上帝保佑我的电脑)
using Lathe.models: FourSquare
m = FourSquare(trainX,trainy)
与之前相同的过程,我们将获得一个预测,并验证它。但是在的意思是时间(明白吗?)如果你想了解更多关于 FourSquare 模型的信息,我有一篇关于它的文章在这里,尽管现在它是基于 LinearLeastSquare(回归),(将来可能会有 LLSQ 类型参数。)
仅仅是并排看这两个模型就可以很好地看出,FourSquare 模型在这里确实做得很好。我很好奇将来进入车床的新型号将如何处理这样的测试。
Left: FourSquare | Right: Original Data
我们学到了什么
我认为这对我来说是一次非常宝贵的学习经历,我希望对你也是如此。我总是说可视化可以真正帮助我们理解我们的数据到底发生了什么,但永远不要把它等同于任何事情。我认为这个建议的有效性在这里明确地显示出来。
我期待将这个数据集用于其他模型(并获得更好的准确性)。)我觉得这里的相关性还不足以证明一个模型的合理性。不管怎样,我的目的是测试我的软件包,这就是我所做的,并且从中获得了很多乐趣。
深拉链:一个打开的拉链探测器
原文:https://towardsdatascience.com/deep-zip-83eb78f9963e?source=collection_archive---------14-----------------------
用你手机的磁强计来探测一个打开的传单。
Photo by Alex Holyoake on Unsplash
拉链:1851 年获得专利,从 20 年代开始被广泛采用,直到今天仍然让我们失望。在这个飞行汽车的时代,科技能帮助我们吗?当你的传单被打开而不应该被打开的时候,除了一个被逗乐的同事之外,我们能得到一个提醒吗?
金属
我们信任的智能手机上布满了传感器,其中一个就是磁力计。如果你的拉链是由金属制成的,当拉链形成的金属环在打开和关闭状态之间改变形状时,其附近(如你的口袋中)的磁力计捕捉到的磁场应该受到干扰。
很可能,磁场的绝对值无法追溯到一个国家。然而,动态变化,如行走时捕捉到的变化(触发拉链两侧之间的距离变化),应该会给你一个可识别的信号。
在这篇文章中,我用这个想法描述了我的实验。从捕捉和处理信号到拟合和优化 3 种不同的模型:梯度推进机、卷积神经网络(ZipNet)和 RNN。
捕捉信号
一个小的 iOS 应用程序将捕获磁力计和加速计数据,并将其导出到 csv 进行分析。这里可以找到。
为了验证最初的假设,我在打开和关闭拉链时取样。我也做了同样的手势,但没有碰到拉链,以确保这不是我扭曲了磁场。乍一看,好像有信号(见下文)。
Left moving the hands only not the zipper. Right opening and closing the zipper and corresponding x axis signal
生成真实生活数据是一件令人兴奋的事情。我会掩饰这一点,但我为 4 个象限生成了 60 集,分别是行走时或不行走时,以及开放时或不开放时,总共 95K 长的时间序列。
以下是 4 象限信号的一个例子(笔记本)。行走(左)与不行走(右)应该很容易察觉。如果磁信号上的频率模式差异(分别为 x、y 和 z 轴的橙色、蓝色和绿色线条)是一致的,则行走时的打开与关闭(左)看起来似乎是合理的。特别是在不同的样品上,mz 在峰值后出现小的隆起,闭合时比打开时更明显。
mx (orange), my(blue), mz(green). More high frequency in mz when closed?
机器学习拯救世界
在检测磁信号形状变化的前提下,我们希望连续检测用户是静止还是运动——然后,只有在运动的情况下,才评估拉链打开时磁信号是否像一个信号。
model serialization
raw data from the app
为培训准备时间序列
除了设置验证集和规范化数据之外,还有一个额外的预处理步骤来为时间序列分类准备数据。我们使用一个滑动时间窗口来分块数据,该窗口涉及两个超参数:窗口大小和每个训练样本之间的步长增量。
直觉上,我们希望窗口大小足够大以捕捉几个周期,但又足够小以使检测器快速反应。根据这些数据,我测试了各种窗口,在 128 个样本之外,没有发现太大的差异。对于步骤,我选择了 10。
数据扩充:让我们添加“窗口扭曲”来挤压或扩展时间序列(人工创建样本,其中你会走得更快或更慢)。让我们也添加噪声到输入信号(高斯),帮助模型区分噪声和信号。
Left: window slicing Xn and Xn+1 input training tensors. Right: window warping
特征工程:为了帮助我们的分类器,让我们用傅立叶变换处理输入数据,并将其添加到输入中。我们去除 0 频率,这是已经在原始数据中捕获的平均值。
Left, ‘mx’ normalized signal. Right, FFT of normalized ‘mx’. 0 freq is indeed removed on the right.
如果我们考虑加速度计和磁信号,这将为我们提供总共 12 个维度的输入特征。
避免验证数据污染:对于经过上述预处理的数据,我们不能按照 80%,20%的规则在训练和验证之间随意分割。如果其中一个采样片段被分割,由于窗口重叠,训练将会看到一些验证数据。因此,训练和验证首先按集分开,试图保持类的平衡,然后进行处理。
梯度推进
我们先测试一下现在流行的 LGBM 算法(笔记本)。为此,我们需要用形状的训练张量(样本数、特征数)来整形。
行走还是静止
如前所述,我们可以观察行走和站立发作之间的差异,我们的分类器也是如此。使用默认分类器,我们获得了接近 100%的准确率(下图的标题显示了准确率、f1 分数和召回率)。
Confusion matrices, Left: training, Right validation (with accuracy, f1 and recall scores in the title)
行走时,打开还是关闭
这更具挑战性,在这种情况下,对时间序列进行仔细的预处理对于获得良好的结果至关重要。使用默认的 LGBM 设置,并根据剧集的采样,我们通常可以获得 80%的准确率(见下面的 dist)。
accuracy and recall distribution over different sampling of the episodes
下面是一个相当典型的性能样本,分类器预测 86%的拉链是打开的(回忆),准确率为 82%。
Confusion matrices: Left training, Right validation (accuracy 82%, recall 86%)
这是在添加了加速度和磁场之后,磁场似乎提高了性能,可能允许模型区分行走和拉链的磁场变化。
数据增强似乎也有所帮助,下面是在标准化信号上添加 5%的时间变量和 2%的高斯噪声。
After data augmentation: 2% boost on scores
另一个 1-2%的增量改进来自超参数优化(请查看 Will Koerhsen 关于该主题的精彩文章,我在笔记本中大量复制了该文章)。
With hyper-parameters optimization, getting to 90% recall, 85% accuracy
ZipNet
让我们尝试一个卷积神经网络作为分类器。我将使用 PyTorch 和非常棒的 fast.ai 库进行训练(笔记本)。该自定义 convnet 仅对时序输入使用卷积,并将 fft 输入直接旁路至密集层。
对于与 LGBM(和增强版)相同的剧集样本,这里是比较性能。准确率低,召回率高。
Zipnet overfit: validation accuracy 73%, recall 95%
虽然我在创建 ZipNet 时很开心,但 LGBM 在大多数情况下表现得更好。让我们检查一个香草 LSTM。
LSTM
This vanilla LSTM performed worst than LGBM
香草 LSTM 也一样,LGBM 在这个小数据集上胜出,尽管可以说我没有花太多时间优化它。
组装三个模型没有帮助。你可以在附带的笔记本中找到尝试。
最后
你的手机变得更私人了。在(笔记本)纸上,在我测试的环境中,用我的手机,用我的牛仔裤,用你手机的磁力计来检测一个打开的传单似乎工作得不错(80%的准确率)。我怀疑它会用我收集的少量数据来概括,所以这里是一个新的众包数据集和 Kaggle 竞争。
感谢阅读。
通过 Spotify 的 airy、Tensorflow 和 Pytorch 更深入地寻找相似的面孔
原文:https://towardsdatascience.com/deeper-dive-into-finding-similar-faces-with-spotifys-annoy-tensorflow-and-pytorch-c434897bd627?source=collection_archive---------26-----------------------
在我之前的帖子中,我开玩笑说我跳进了一个兔子洞,试图改善我的命运大阶面部相似度管道,我在那里使用了 Tensorflow 对象检测器、Pytorch 特征提取器和 Spotify 的近似最近邻居库(惹恼了)。我的总体想法是,我想对角色面部特征(寻找相似的角色)和背景信息(返回具有相似颜色/感觉的图像)进行编码。
我想我能做的就是把从预训练的 Resnet101 中提取的特征向量连接起来,用于基础图像和头像。然而,这种方法证明是相当令人失望的。
作为一个快速回顾,这里是一个示例图像和使用版本 1 模型的类似配对,该模型使用整个图像。
版本 1 模型输出
V1 full image sample output: Left image is the original and the next four are the four most similar
输出正常,但是 4 个相似图像中的 2 个具有不同的字符。
接下来回顾一下第二版基于头像的管道,我使用了一个定制的 Tensorflow 对象检测器来裁剪图像中的人物头像,并使用它们来建立烦人的索引和查找相似的图像。
版本 2 头像模型
V2 headshot model output
这条管道似乎相当成功,在所有图像中返回相同角色的图像,但我想看看我是否能得到更接近原始的“感觉”。这就是为什么我试图结合 Resnet 101 输出向量,并将其输入到 annoy 中,以制作一个新的模型版本 3。
版本 3:结合前两个
我的下一个测试是从头像和基本图像中提取特征向量,并将它们组合在一起,并将新的长度为 2000 的数组输入到 aroy 中。希望向量的第一部分可以帮助找到相似的人脸,第二部分可以对图像整体的相似信息进行编码。
第 3 版组合头像和基本图像
V3 combined feature array sample output
所以这个管道的第三个版本不是我所希望的…虽然这些字符有相似的面孔,但 4 个输出中的 2 个与基础图像中的字符不同。
这对我来说很有趣,因为我的第一个想法是,这是我根据图像构建的要素表示的质量问题。我甚至用更大的 Resnet 152 进行了测试,但结果基本相同。
下一步是检查我是否认为我在管道的其余部分做错了什么……就像我在从原始稀疏 3D 像素表示构建图像的 1D 表示时做错了什么。然而,这是非常可靠和真实的…
这一次,我意识到重新阅读恼人的 git 回购页面,并看到了这一说明。
如果您没有太多的维度(比如< 100),效果会更好,但即使达到 1000 个维度,效果似乎也令人惊讶
对于该管道的基础图像和头部特写版本,特征向量是来自 Resnet 101 的标准 1000 个特征。并且将这两个向量连接在一起会将其推到长度为 2000 的向量,这大大超出了推荐的维数。
版本 4:哑吧?
虽然选择使用功能较弱的网络进行深度学习并不常见,但任何事情都有时间和地点。
考虑到这一点,我实际上将该管道版本 4 的特征提取器 Resnet 从 101 降级为 Resnet 34。这是因为在 Resnet 101 中最后 1000 个完全连接的层之前的层的大小是 2048,而 Resnet 34 只有 512。我的想法是,通过使用这个较小的层,我可以连接两个 512 层,以获得长度为 1024 而不是 2000 的最终向量。希望这能减少维度的数量,让 annoy 更好地发挥作用。
我认为这一改变提高了我的产出质量。
版本 4 Resnet 34
V4 Resnet34 headshot and base image model output
因此,运行我之前展示的相同示例图像,这个 Resnet 34 模型看起来比使用更大的 Resnet 101 的初始头像+基础图像模型更好。四个图像中的两个与角色匹配。第三个图像只是原始角色的邪恶版本,所以我认为它很重要。然而,最终的图像似乎很不相关…所以有进步要做。
这里是另一个显示 Resnet 34 模型输出与前三个版本的比较的例子。我对图像标题中的输出进行评论。
版本 1 基础映像
V1 Original full image model. no correct characters, similarly colored (sort of)
版本 2 头像
V2 model based on just the headshot. 3 similar characters but images arn’t that similar to the base image.
第 3 版结合了头像和基本图像
v3 headshot + base image Resnet 101 length 2000 vector. This version of the pipeline seems to just combine the first two versions
版本 4 Resnet 34
V4 Resnet 34 length 1024 vectors. It produces decent looking output, but in looking through the outputs I usually find odd images included like the second image in this list
因此,尽管 Resnet 34 相对于该管道的 Resnet 101 版本是一个改进,但它仍然表现不佳…我仍然相信我可以改进它,问题只是,如何改进?
版本 5:从 1024 维减少到 52 维
在思考了如何获得比 Resnet 34 的 512 输出更小的最终特征表示并绘制了一段时间的空白之后…我感觉自己像个白痴,因为在我起草的另一个帖子中,我一直在这个相同的数据集上训练基于 Pytorch 的多任务模型,以执行跨 5 个类别和 26 个不同目标变量的多标签分类。
这个网络是 Pytorch Resnet 50,其中我修改了最后几层来处理 5 个任务,我试图同时优化它们。我有一个草稿模式的帖子,但我太懒了,没有完成它…但在这种情况下,这个网络非常方便,因为它给了我一个微调网络,它已经成为区分命运大订单图像的技能。这里的好处是,不必使用 512 或 1000 个输出节点,这个特定的网络在这个问题空间中是熟练的,并且只有 26 个输出节点,这意味着我可以用 52 维而不是 1024 或 2000 维的向量来表示人脸和基础图像。这些图像的这种更密集的表示应该允许更好地区分这些图像。
因此,在交换后端特征提取器并测试输出后,使用我的多任务模型进行特征提取的 V5 模型表现得相当好。
请看下面我在这篇文章中强调的两个例子。其他型号在某些方面表现不错,但在其他方面有所欠缺。我认为这个第 5 版模型确实获得了我在上一篇文章中提到的两个世界的最佳效果。
第 5 版微调多任务模型
All of the output is of the correct character, and the images style/background seem more similar than just the v2 headshot model
Once again all the output is of the correct character
总体而言,这一变化显著提高了管道输出的质量。我想这凸显了获得良好要素制图表达的重要性,并且使它们更密集通常会更好。
V5 sample output, same character in all images
结束语
这两篇文章很好地提醒了我们降低数据维度以获得更好结果的重要性。
每个图像都以 150,528 像素(224x224x3 宽、高、rgb 颜色)开始,然后使用标准的预训练 imagenet 网络可以压缩到只有 1000 个特征。我认为这本身就很酷。
然而,对于这个特定的问题,当我添加第二个图像时,我的最终特征向量是 2000 个特征。这又一次是太稀疏的信息,使我无法产生好的结果,所以我不得不去寻找一种方法来进一步减少我的数据的维度。
V5 output, 3 out of 4 images have the correct character and decent style matches. hair color in the odd image is a close match
为了进一步减少我的图像表示的维数,我使用了一个较小的 Resnet 34,并看到了一些改进,但该模型会输出奇怪的相似图像。由于这不起作用,我想我可以尝试制作更密集的数据表示,最终我能够使用我在类似问题空间中微调的网络,将原始的 150,528 像素原始表示降低到 26 像素。
这是一个类似于特征选择或主成分分析的过程,其目标是将一些原始水平的输入降低到一组有意义的特征。这对于我自己来说也是一个有用的注释,当我使用对象检测器或其他输入来添加更多额外的上下文时,我会尝试进一步关注特定网络学习的细节。
请随意查看 github repo 中的代码示例。
因为我很兴奋,这似乎是工作得很好,这里有一堆更多的图像示例如下。
深入到 DCGANs
原文:https://towardsdatascience.com/deeper-into-dcgans-2556dbd0baac?source=collection_archive---------7-----------------------
我上一篇关于 DCGANs 的文章主要集中在用卷积替换全连接层和用 Keras 实现上采样卷积的想法上。本文将进一步解释 Raford 等人[1]提到的架构指南,以及论文中提到的其他主题,如使用 GAN 的无监督特征学习、GAN 过拟合和潜在空间插值。
DCGAN architecture used by Radford et al. [1] to generate 64x64 RGB bedroom images from the LSUN dataset
与 LAPGAN 或渐进增长 GAN 等多尺度架构相比,或者与最新的 BigGAN 相比,BigGAN 使用了许多辅助技术,如自我关注、频谱归一化和鉴别器投影等 DCGAN 是一个更容易完全理解的系统。
DCGAN 无法实现与 BigGAN 模型相当的图像质量,也不具备与 StyleGAN 几乎相同的潜在空间控制能力。然而,仍然值得考虑将 DCGAN 作为 GAN 研究的基础支柱。DCGAN 模型的基本组件是用这些上采样卷积层替换生成器中的全连接层。在设计这个架构时,作者引用了三个灵感来源。
- 全卷积网络→用空间下采样卷积代替汇集操作
- 消除卷积后的完全连接层
- 批量标准化→标准化激活以帮助梯度流动
考虑到这些进步,作者寻找了一种稳定的 DC-GAN 架构,并采用了以下架构准则:
- 用鉴别器中的步长卷积和生成器中的分数步长卷积替换任何池层
- 在生成器和鉴别器中使用批处理规范化
- 为更深层次的架构移除完全连接的隐藏层
- 在发生器中对除 Tanh 外的所有层使用 ReLU 激活输出(这些图像在[-1,1]而不是[0,1]之间标准化,因此 Tanh 在 sigmoid 上)
- 在所有层的鉴别器中使用 LeakyReLU 激活
这些建筑方针后来在现代甘文学中得到了扩展。例如,创成式模型中的批处理规范化有新出现的表亲,如虚拟批处理规范化、实例规范化和自适应实例规范化。Salimans 等人[2]提出了进一步的架构指导方针,并且在这篇文章中做了很好的解释。
除了模型架构,本文还讨论了许多与 GAN 相关的有趣想法,如无监督学习、GAN 过拟合、GAN 特征可视化和潜在空间插值。
基于 GANs 的无监督学习
已经探索了 GANs 的许多应用,并且大部分研究试图实现更高质量的图像合成。许多实现高质量图像合成的方法实际上是监督学习技术,因为它们需要类别标签进行调节。
这里的主要思想是使用由鉴别器学习的特征作为分类模型的特征提取器。具体来说,拉德福德等人探索了结合 L2 + SVM 分类模型的无监督 GAN 特征提取器的使用。SVM 模型使用损失函数和高维超平面,该损失函数旨在基于每个类中最近点之间的差值来最大化类间距离。SVM 模型是一个很好的分类器,然而,它不是一个特征提取器,将 SVM 应用于图像会导致大量的局部极小值,本质上使问题变得难以处理。因此,DC-甘充当特征提取器,其以语义保留的方式减少图像的维度,使得 SVM 可以学习辨别模型。
甘过拟合
重读这篇论文,我觉得甘过度拟合的想法特别有趣。监督学习环境中的过拟合非常直观:
Common picture showing overfitting on a supervised learning task
上图是回归任务中过度拟合的常见图示。过度参数化模型会自我调整,使其与训练数据完全匹配,并且没有错误。抛开偏差-方差权衡的统计数据,我们可以直观地将过度拟合想象为模型的泛化能力,即与测试数据相比,它在训练数据上的表现如何。
在 GANs 的背景下,这是一个非常有趣的想法。生成器的任务是产生鉴别器预测为“真实”的数据,这意味着它非常类似于训练数据集。看起来,如果生成器放弃任何向数据点添加随机变化的尝试,而只是精确模拟训练数据,那么它将是最成功的。拉德福德等人讨论了三种有趣的方法来证明他们的 DC-甘模型没有做到这一点。
- 启发式近似:快速学习的模型概括得很好
- 自动编码器哈希冲突(训练 a 3072–128–3072 自动编码器对生成数据和原始数据进行编码,并查看生成数据和原始数据之间的低维(128)表示有多少相似之处。
- 潜在空间的平滑度(急剧过渡=过度拟合)
本文中没有使用的另一种探索 GANs 过度拟合的有趣技术是使用 L1 或 L2 距离(甚至可能是 VGG-19 特征距离)进行最近邻搜索,从训练数据集中抓取与给定生成图像最相似的图像。
甘特征可视化
CNN 中的特征可视化如下实现。通过梯度下降来训练生成器网络,以产生导致给定特征的最大激活的图像。拉德福德等人在 LSUN bedroom 数据集上使用他们的鉴别器模型对此进行了测试,并展示了下图:
有趣的是,这些是鉴别器用来辨别图像真假的特征。
潜在空间插值
潜在空间插值是 GAN 研究中最有趣的课题之一,因为它能够控制发生器。例如,GANs 最终可能被用于设计网站。您希望能够控制设计的特征或在设计之间进行插值。除了这个轶事,潜在空间插值在 Word2Vec 中有非常普遍的描述,其中向量“国王”-“男人”+“女人”=“女王”。拉德福德等人用他们生成的图像探索了这种插值方法。
本文中讨论的潜在空间插值的一个有趣的细节是,它们不使用单个点的 Z 向量,这是我最初没有注意到的。例如,他们不只是用一个微笑的女人的 Z 向量减去一个中性女人的 Z 向量,然后加上一个中性男人的 Z 向量来获得一个微笑的男人图像。相反,它们取一系列显示外部特征(如“微笑的女人”)的生成图像的平均 Z 向量。
感谢您阅读本文!我发现这篇论文对我研究 GANs 非常有用。每次我回到这篇论文,我都会对论文的细节有所欣赏。这篇文章是关于 GANs 的基础工作之一,我强烈推荐你去看看,特别是如果你对图像生成感兴趣的话。
参考
[1]亚历克·拉德福德,卢克·梅斯,苏密特·钦塔拉。深度卷积生成对抗网络的无监督表示学习。2015.
[2]蒂姆·萨利曼斯、伊恩·古德菲勒、沃伊切赫·扎伦巴、张维基、亚历克·拉德福德、陈曦。训练 GANs 的改良技术。2016.
深度造假——今日新闻热门话题
原文:https://towardsdatascience.com/deepfake-trending-topic-in-the-news-today-f2607a28fb8f?source=collection_archive---------29-----------------------
是时候质疑你看到的每一张照片和视频了!
Photo of a woman (Photo by Andrey Zvyagintsev on Unsplash)
"亚马逊联合脸书和微软打击 deep fakes"—2019 年 10 月 22 日的下一个网络
“对 deepfakes 的战争:亚马逊用 100 万美元的云信用支持微软和脸书”—ZDNet,2019 年 10 月 22 日
“什么是‘深度假货’,它们有多危险”—《美国消费者新闻与商业频道》2019 年 10 月 13 日报道
“人工智能无法保护我们免受 deepfakes 的影响,新报告认为” — The Verge 于 2019 年 9 月 18 日
我注意到“ DeepFake ”这个词一次又一次地出现在我的新闻提要中,在我第六次或第七次遇到它之后,我开始想这是不是我应该知道的事情。我的意思是,如果像亚马逊、脸书和微软这样的大型科技公司正在共同努力打击 DeepFake,而美国消费者新闻与商业频道正在报告其危险,那一定是很严重的事情。
事实证明,使用 DeepFake ,你可以创建一个甚至不存在的人的面部图像,操纵视频来交换人们的面部,并使用某人的声音编造演讲,甚至无需他们同意。试试这个 hispersonedoesnotexist.com 网站,你会大吃一惊。这个网站生成一个甘想象的人的形象(根据网站左下角的注释)。下面是该网站生成的一些人脸图像。我打赌你不会猜到这些图像是假的,我也不会。
Face images created using thispersonedoesnotexist.com
Note on thispersonedoesnotexist.com
DeepFakes 是由一种被称为生成对抗网络(GANs)的深度学习技术创建的,其中使用了两种机器学习模型来使假货更加可信。通过研究一个人的图像和视频,以训练数据的形式,第一个模型创建一个视频,而第二个模型试图检测它的缺陷。这两个模型携手合作,直到他们创造出一个可信的视频。
当谈到无监督学习时,DeepFake 打开了一个全新的世界,这是机器学习的一个子领域,机器可以学习自学,并且有人认为,当谈到自动驾驶汽车检测和识别道路上的障碍以及 Siri、Cortana 和 Alexa 等虚拟助手学习更具对话性时,它有很大的前景。
真正的问题是,像其他技术一样,它有可能被滥用。利用 DeepFake 作为报复的一种形式,通过在色情中使用它,操纵政治家的照片和影响政治运动只是冰山一角。
它引发了一个严重的问题,即我们是否可以信任以图像、视频或声音形式呈现给我们的任何数字信息。
据 BBC 新闻, DeepFake 视频在短短九个月内翻了一番,其中 96%是色情性质的。这对 DeepFake 的受害者意味着什么?谁应该为创建和分享这种虚假媒体并诽谤另一个人负责?
科技巨头们意识到了 DeepFake 的危害,已经主动站出来反对 DeepFake 的滥用。脸书和微软在 9 月份宣布了一项竞赛deep face Detection Challenge(DFDC),以帮助检测 DeepFakes 和被操纵的媒体,脸书正在通过创建一个大型的 DeepFake 视频数据集来提供帮助,亚马逊正在为这项价值 100 万美元的挑战提供云资源。这项比赛将于 12 月启动,总奖金为 1000 万美元。
另一方面,谷歌也在创建一个 DeepFake 视频数据集,以便 Munchin 技术大学、那不勒斯大学 Federico II 和埃尔兰根-纽伦堡大学的研究人员可以将其用于 FaceForensics 项目,这是一个检测被操纵的面部图像的项目。
总而言之,技术正一天天变得越来越聪明,DeepFake 的创造证明了机器已经发展到这样一个水平,它们可以合成照片、视频和语音,甚至我们都无法将它们与真的区分开来。DeepFake 有一定的好处,其中之一是为自动驾驶汽车的改进创造更多的训练数据。但是,就像所有其他技术一样,人们正在滥用它来制作虚假视频,并在社交媒体上分享错误信息。科技巨头们已经加紧对付这一问题,希望在不久的将来,我们将拥有一个可以检测深度造假的系统。
我们能做些什么来帮助防止 DeepFake 被滥用,并确保它以安全的方式使用? 在下面留下你的想法作为评论。
点击这里 阅读我其他关于 AI/机器学习的帖子。
跟我上 中和/或LinkedIn。****
来源:
* [## 100,000 张人工智能生成的免费头像让股票照片公司受到关注
使用人工智能来生成看起来令人信服,但完全虚假的人的照片变得越来越容易。现在…
www.theverge.com](https://www.theverge.com/2019/9/20/20875362/100000-fake-ai-photos-stock-photography-royalty-free) [## ThisPersonDoesNotExist.com 利用人工智能生成无尽的假脸
人工智能产生虚假视觉效果的能力还不是主流知识,但一个新的网站…
www.theverge.com](https://www.theverge.com/tldr/2019/2/15/18226005/ai-generated-fake-people-portraits-thispersondoesnotexist-stylegan) [## 新报告称,人工智能无法保护我们免受深度欺诈
来自数据和社会的一份新报告对欺骗性修改视频的自动化解决方案提出了质疑,包括…
www.theverge.com](https://www.theverge.com/2019/9/18/20872084/ai-deepfakes-solution-report-data-society-video-altered) [## Deepfakes:目前,女性,而不是民主,是主要的受害者
虽然 2020 年美国总统选举让立法者对人工智能生成的假视频感到紧张,但一项由…
www.zdnet.com](https://www.zdnet.com/article/deepfakes-for-now-women-are-the-main-victim-not-democracy/) [## 忘掉假新闻吧,Deepfake 视频其实都是关于未经同意的色情内容
“深度造假”对公平选举,特别是 2020 年美国总统大选的威胁越来越大…
www.forbes.com](https://www.forbes.com/sites/daveywinder/2019/10/08/forget-2020-election-fake-news-deepfake-videos-are-all-about-the-porn/#7ea9952563f9) [## Deepfakes 可能会打破互联网
我们可能已经在一个深度造假的世界里游泳了,而公众甚至不会知道。毕竟,我们要怎么做呢?那些…
www.cpomagazine.com](https://www.cpomagazine.com/cyber-security/deepfakes-could-break-the-internet/) [## 向假货宣战:亚马逊用 100 万美元的云信用支持微软和脸书
AWS 全力支持即将到来的 Deepfake 检测挑战赛,这是一项奖金高达 1000 万美元的比赛…
www.zdnet.com](https://www.zdnet.com/article/war-on-deepfakes-amazon-backs-microsoft-and-facebook-with-1m-in-cloud-credits/) [## 什么是“深度假货”,它们有多危险
“Deepfakes”被用来在虚假视频中描绘他们实际上并没有出现的人,并可能潜在地影响…
www.cnbc.com](https://www.cnbc.com/2019/10/14/what-is-deepfake-and-how-it-might-be-dangerous.html) [## 亚马逊联合脸书和微软打击 deepfakes
Deepfakes 今年遇到了严重的问题,大公司现在开始关注。亚马逊宣布…
thenextweb.com](https://thenextweb.com/artificial-intelligence/2019/10/22/amazon-joins-facebook-and-microsoft-to-fight-deepfakes/) [## Deepfake 视频:它们是如何工作的,为什么工作,以及有什么风险
Deepfakes 是假的视频或音频记录,看起来和听起来就像真的一样。曾经是…的辖区
www.csoonline.com](https://www.csoonline.com/article/3293002/deepfake-videos-how-and-why-they-work.html) [## Deepfake 视频'九个月翻倍'
新的研究显示,所谓的深度假视频创作激增,在线数量几乎…
www.bbc.com](https://www.bbc.com/news/technology-49961089)*
Deepfakes:一个未知和未知的法律景观
原文:https://towardsdatascience.com/deepfakes-an-unknown-and-uncharted-legal-landscape-faec3b092eaf?source=collection_archive---------23-----------------------
https://m.wsj.net/video/20181012/1012-deepfakes-finalcut/1012-deepfakes-finalcut_960x540.jpg
2017 年标志着“深度造假”的到来,随之而来的是另一个由技术引发的法律模糊的新领域。术语“ deepfake ”指的是使用深度学习篡改的图像、视频或音频片段,以描述并未真正发生的事情。起初,这听起来可能很普通,也没什么坏处——Adobe 的 Photoshop 已经有几十年的历史了,像詹姆斯·卡梅隆的阿凡达这样的电影完全依赖于计算机生成图像(CGI)技术。然而,让 deepfakes 与众不同的是它们的范围、规模和复杂程度。虽然先进的数字更改技术已经存在多年,但它们在获取方面受到成本和技能的限制。逼真地修改视频和图像曾经需要高性能和昂贵的软件以及广泛的培训,而创建一个深度假几乎任何人都可以用电脑。这种便利带来了新的和前所未有的法律和道德挑战。
什么是 Deepfake?
这些令人信服的伪造视频的第一次出现是在 2017 年 12 月的,当时 reddit 上的一名匿名用户以“Deepfakes”的笔名将名人的面孔叠加到色情视频上。Deepfakes 在这种背景下蓬勃发展,刺激了诸如 DeepNude 这样的应用程序的建立,这些应用程序提供免费和付费的服务来改变女性的图像,使其看起来完全裸体。其他应用如 FakeApp 将这种体验推广到更广泛的背景,如欺凌、勒索、假新闻和政治破坏。与这些视频的创作同样令人震惊的是它们的泛滥——在它们短暂的历史中,deepfakes 在主流媒体上掀起了波澜。尤其是当唐纳德·特朗普总统转发众议院议长南希·佩洛西(D-CA)的视频时,显然是含糊不清的话,或者当一个巨魔发布马克·扎克伯格发表威胁性演讲的 deepfake。
deep fakes 是如何工作的?
在分析 deepfakes 的法律和社会后果之前,理解它们是如何工作的以及它们为什么如此有效是很重要的。Deepfakes 需要一种特定类型的人工智能(AI)和机器学习,称为深度学习,它利用人工神经网络变得更聪明,更善于检测和适应数据中的模式。Deepfakes 依赖于一种特殊形式的深度学习,称为生成对抗网络(GANS),由蒙特利尔大学的研究人员在 2014 年推出。GANS 将自己与其他深度学习算法区分开来,因为它们利用了两种相互竞争的神经网络架构。这种竞争发生在数据训练过程中,其中一种算法生成数据(生成器),另一种算法同时对生成的数据进行鉴别或分类(鉴别器)。神经网络在这种情况下是有效的,因为它们可以自己识别和学习模式,最终模仿和执行。正如凯伦·郝在麻省理工学院技术评论中所引用的那样,“(甘)的过程‘模仿了一个伪造者和一个艺术侦探之间的反复较量,他们不断试图智取对方。’“虽然这种算法听起来可能相当先进,但它的可用性和可访问性被开源平台如谷歌的 TensorFlow 或通过 GitHub(deep nude 在被关闭前存放其代码的地方)提供的公共存储库放大了。这项技术正变得越来越易于使用,因此也越来越危险,尤其是当它的情报迅速积累,变得越来越有说服力的时候。
https://www.edureka.co/blog/wp-content/uploads/2018/03/AI-vs-ML-vs-Deep-Learning.png
deep fakes 的含义:
deepfake 视频的后果可能是显而易见的:参与者的公开羞辱,错误信息,以及新的和脆弱的真理概念化。一个更难回答的问题是,如何保护个人,进而保护美国社会,免受 deepfakes 的严重影响。某些州已经采取了措施,例如弗吉尼亚州更新了其报复色情法以包括 deepfakes,或者得克萨斯州的 deepfake 法将于 2019 年 9 月 1 日生效,以规范选举操纵。虽然事后追究个人责任可以对其他人起到威慑作用,但一旦这些视频被发布到网上,往往已经造成了严重的损害。因此,在社交媒体和互联网病毒式传播的时代,保护第一修正案权利和最大限度地减少诽谤传播之间的平衡变得不那么明显,特别是随着社交媒体平台成为政治和社会话语的论坛。
除了更新或制定法律,还值得考虑将审查的负担转移到社交媒体平台上,让这些视频获得牵引力和传播。例如,如果脸书在南希·佩洛西的深层假货被认定为假货时将其移除,许多伤害本可以避免。虽然该公司提醒用户视频被篡改,但他们选择不删除视频,以保护宪法第一修正案的权利。然而,在上述扎克伯格 deepfake 发布之后,在 2019 年阿斯彭创意节上,马克·扎克伯格承认脸书可能会在未来对他们的 deepfake 政策进行修改。但是到目前为止,1996 年《通信行为规范法》第 230 条保护脸书或任何其他社交媒体平台免于为其用户发布的内容承担任何责任。这实际上给了这些平台更多的自由裁量权来决定宪法权利的范围。随着 deepfakes 变得更加普遍和有害,政府必须找到一种方法来监管大型科技公司,并调和它们已经成为民主平台的事实。
另一个需要记住的法律问题是法庭上的深度假证。多年来,数字图像和视频镜头已经为沉默证人理论下的可验证和可靠的证据创造了条件。然而,如果 deepfakes 持续生产,这些图像的可验证性将变得更加模糊和难以证明,从而根据美国联邦证据规则的规则 901(b) (9)加强对所有数字证据的审查。对数字证据全面丧失信心的后果将是增加对目击者证词的依赖,从而让法院在已经有偏见的系统中做出更有偏见的裁决。无论在何种背景下,法律体系都必须预测和调整 deepfakes 崛起带来的巨大变化,特别是因为它们的传播和影响难以遏制。
打击深度假货:
除了考虑社交媒体网站的潜在监管变化和预测法律困境,重要的是要考虑替代方法来规避 deepfakes 造成的潜在损害。罗伯特·切斯尼和丹妮尔·香橼提出了一种解决方案,即“认证不在场证明服务”。理论上,这些服务将创建跟踪个人的数字生活日志,以便他们最终可以推翻 deepfakes 提出的说法。这种解决方案很有意思,因为它损害了个人隐私,可能会遭到错误信息的拒绝。也许这表明了社会对隐私的冷漠,或者我们对假货的恐惧程度——或者两者兼而有之。无论如何,经过认证的不在场证明看起来像是一种绝望的防御措施,揭示了个人为了保护自己愿意牺牲多少。
Deepfakes 对美国社会构成严重威胁。虽然政治极化和假新闻已经玷污了事实,因此,我们的民主基础,我们必须制定战略,以防止信任和真理的进一步崩溃。因此,预测法律问题并相应调整法律,对于确保利用创新技术改善社会和抑制恶意工具的传播至关重要。
Deepfakes:丑陋与美好
原文:https://towardsdatascience.com/deepfakes-the-ugly-and-the-good-49115643d8dd?source=collection_archive---------8-----------------------
我们的工作是确保我们开发的技术被善用。
昨天,我的朋友让我玩这个游戏,它叫做哪张脸是真实的。是的,我知道这听起来很扯,但是我每次都猜错了😐。
Which face is real? Well, I actually don’t know. ❓
这让我意识到一件事。我意识到人类只是一个非常愚蠢的物种,我不是指冒犯的方式,无论如何都是冒犯的(抱歉!)😅。
“我们首先应该假设自己很笨。我们绝对可以让东西比我们自己更聪明。”—埃隆·马斯克😶
这不是人工智能是否会比人类聪明的问题,它已经在几个领域聪明了,但真正的问题是我们如何才能善用这种智能?
在过去的几年里,人工智能的进步已经走上了指数曲线。
That’s right, AI is disrupting almost every single field. 💪
仅仅 10 年前,像 Siri 和 Alexa 这样的东西甚至还不存在。
Siri vs Alexa Rap Battle, that’s how good AI has become! 😂
今天,我们能够利用人工智能从医学图像中检测癌症,谷歌助手可以通过模仿人的声音在电话上为你预约,开发与真实图像几乎完美相似的假图像从未像现在这样简单。
对隐私和错误信息的广泛关注避开了对 deepfakes 的关注,deep fakes 是使用自动编码器和生成对抗网络等算法制作的虚假媒体。
在错误的人手中,这种技术可以用于诈骗。例如,最近,一个伪造的声音被用来诈骗一家英国公司的首席执行官 244,000 美元🤯。
Deepfakes 背后的技术:生成对抗模型
生成对抗网络(GANs) 的出现,打乱了假像的发展。
以前,我们一直使用像 photoshop 这样的手动方法,但有了生成式对抗网络,这一过程正在自动化,结果通常明显更好。
生成对抗网络是一种相对较新的神经网络,由 Ian Goodfellow 在 2014 年首次介绍。GANs 的目标是制作尽可能真实的假图像。
GAN 包含两个组件:
- 生成器 —生成图像
- 鉴别器 —对生成的图像是假图像还是真图像进行分类
发生器接受一个潜在样本,一个随机噪声向量作为输入。通过利用解卷积层,其本质上是卷积层的逆,产生图像。
De-convolutional layers
卷积层负责从输入中提取特征,解卷积层执行相反的操作,将特征作为输入,并产生图像作为输出。
假设你在和朋友玩猜字谜游戏。表演这个短语的人在表演“去卷积”,而其他猜这个短语的人在表演“卷积”。“表演”类似于形象,“猜测”类似于形象的特征。
Charades — reminds me of the fun times
本质上,卷积层识别图像的特征,而去卷积层根据图像的特征构建图像。
Convolutional layers
另一方面,鉴别器利用卷积层进行图像分类,因为它的工作是预测生成器生成的图像是真实(1) 还是虚假(0) 。生成器的目标是生成尽可能真实的图像,并成功地欺骗鉴别器,使其认为生成的图像是真实的。
鉴别器的工作对生成器的成功至关重要。为了帮助生成器生成更真实的图像,鉴别器必须非常擅长区分真实图像和虚假图像。鉴别器越好,发生器就越好。
每次迭代后,生成器的可学习参数、权重和偏差都根据鉴别器给出的建议进行调整。
网络通过反向传播关于生成图像的鉴别器输出梯度来更新可学习参数。本质上,鉴别器告诉生成器应该如何调整每个像素,以使图像更加真实。
假设生成器创建了一个图像,鉴别器认为该图像有 0.29 (29%)的概率是真实图像。生成器的工作是更新其可学习的参数,以便在计算反向传播后,概率增加到例如 30%。
然而,生成器依赖于鉴别器才能成功。
一种更直观的思考方式是,想象发生器类似于学生,鉴别器类似于老师。
Does this spark any memories from grade school? 📝
还记得你写测试的时候,你对自己的结果感到非常紧张,因为你不知道自己做得有多好。
学生不知道他们犯了什么错误,直到老师给他们打分并给他们反馈。学生的工作是从老师给他们的反馈中学习,以提高他们的考试成绩。
老师教得越好,学生的学习成绩就越好。
从理论上讲,生成器在创建几乎完美无缺的真实图像方面做得越好,鉴别器在区分真实图像和虚假图像方面就做得越好。反之亦然,鉴别器对图像分类越好,生成器就越好。
利用 MobileNetV2 检测伪造图像
为了对真假图像进行分类,我使用了一个预先训练好的卷积神经网络,称为 MobileNetV2 ,它是在 1400 万图像数据集 ImageNet 上训练的。
我利用 MobileNet 2.0 版本 MobileNetV2 而不是构建自己的卷积神经网络的主要原因是,MobileNetV2 旨在对移动设备友好,这意味着它需要明显更少的计算能力。
通过在 MobileNetV2 上添加几个额外的层,并根据真实与虚假图像数据集 t 对其进行训练,我的模型能够以 75%的准确率区分虚假图像和真实图像。
我的神经网络结构看起来像这样:
1。MobileNetV2
2。平均池层 —该层负责通过执行向下采样来降低数据的维度。例如,假设我们有一个 4x4 的输入矩阵,并且应用了一个 2x2 的平均池层。实际上,对于输入矩阵中的每个 2×2 块,取这些值的平均值,从而降低维数。
Average pooling layer
3。密集层 —密集层只是一个常规的全连接层,其中每层中的每个节点都连接到下一层中的每个节点。激活函数 ReLU ( R(z) = max (0,z) )应用于该层,主要负责将范围限制为正值。
ReLU function
4。 批量标准化层 —该层负责标准化通过该层的输入,以增强神经网络的稳定性。
5。丢弃层 —该层负责通过将某些随机节点的激活设置为 0 来防止过拟合。在辍学层,没有可学习的参数(即。这不是像其他层那样的训练层)。
6。输出层 —这实际上是一个应用了 softmax 激活功能的规则密集层。softmax 函数产生 0-1 之间的输出,表示最终预测输出类的概率分布。
Softmax function
这个模型的准确性可以通过拥有更大的数据集来容易地增强。我在 2041 张图像的数据集上训练了模型,但想象一下,如果我们在 100 万张图像上训练它,模型的准确性可以明显更高!
氮化镓的应用
GANs 的应用不仅仅局限于负面目的,比如制造错误信息,它实际上可以以积极的方式应用于许多行业!
甘的一些非常有趣的用法:
- 生成艺术😍—是的,谁说机器不能做创造性的事情,我想它可以!
- 创作音乐🎵—人们实际上喜欢人工智能音乐!
- 创造虚假的人类形象
- 生成虚假的动漫图像——我不是一个超级动漫爱好者,但如果你是,那就太棒了!
Fake images generated by GANs
更多实际应用:🚀
通过利用 GANs,我们有可能加速机器学习本身的进步!
我们可以利用 GANs 来解决小数据集的问题,通过生成与数据集中的真实数据相似的新数据,这是机器学习的主要瓶颈之一。
拥有更大的数据集是增强基于分类的机器学习程序的性能的最可靠的方法之一。
🖼️潜在的应用之一可能是利用 GANs 生成合成的大脑 MRI 图像,以提高对神经胶质瘤(一种脑癌)的检测。
💊最令人兴奋的应用是利用 GANs 合成新的分子或候选药物,这些分子或候选药物针对引起疾病的特定蛋白质或生物标志物。
为了做到这一点,生成器负责生成新的分子,然后鉴别器预测分子的作用,看它是否可以抑制或兴奋某种蛋白质。我们可以用 gan 来推进和加速药物发现的进程。
🎥在电影和漫画行业,GANs 可用于文本到图像的合成。
GANs 的实际应用多了去了!这项技术有可能颠覆许多行业,从医疗保健到电影!我们有责任确保这项技术用于正确的目的,并补充人类。
关键要点:
- GANs 是一种用于创建合成数据的技术,包括两个组件:生成器和鉴别器。
- 通过利用卷积神经网络,我的机器学习程序能够以 75%的准确率检测出 GANs 生成的假图像。****
- GANs 的应用有好有坏。虽然 GANs 可以制造假介质,但是它也可以用于合成新药研发的新分子。
不要忘记:
- 在 LinkedIn 上与我联系
- 访问我的网站来一窥我的全部作品集!
Deep fool——欺骗深度神经网络的简单而准确的方法。
原文:https://towardsdatascience.com/deepfool-a-simple-and-accurate-method-to-fool-deep-neural-networks-17e0d0910ac0?source=collection_archive---------7-----------------------
敌对的攻击
Fig 1. Its not a fish, its a bird 😃 [Confidences shown are the values of logits and not passed through softmax]
论文摘要 DeepFool:一种简单准确的愚弄深度神经网络的方法 由 赛义德-穆赫森·穆沙维-德兹夫利、阿尔侯赛因·法齐、帕斯卡尔·弗罗萨德 论文链接:https://arxiv.org/pdf/1511.04599.pdf
概观
深度神经网络在许多任务中实现了最先进的性能,但在轻微扰动的图像上惨败,以有意义的方式(而不是随机地)扰动。
DeepFool 论文有以下主要贡献:
- 计算不同分类器对敌对扰动的鲁棒性的简单而精确的方法。
- 实验表明
- DeepFool 计算出更优的对抗性扰动
-对抗性训练显著增加了鲁棒性。
- DeepFool 计算出更优的对抗性扰动
二元分类器的 DeepFool
FIg 2. Simple Image with Linear model to explain what DeepFool does.
使用线性二进制分类器可以容易地看出,对于输入x_{0}
的模型的鲁棒性(f
)等于x_{0}
到超参数平面的距离(其将两个类别分开)。
改变分类器决策的最小扰动对应于x_{0}
在超参数平面上的正交投影。给出者:
Fig 3. Equation to calculate the minimal perturbation.
以下是 DeepFool 针对二元分类器的算法:
Fig 4. Algorithm to calculate the Adversarial Image for Binary Classifiers.
我们来过一遍算法:
1。该算法采用一个输入x
和一个分类器f
。
2。输出对图像进行微分类所需的最小扰动。
3。用原始输入初始化对立图像。并将循环变量设置为 1。
4。开始并继续循环,而真实标签和对抗扰动图像的标签是相同的。
5。计算输入到最近超平面的投影。
(最小扰动)6。将扰动添加到图像中并进行测试。
7–8。增量循环变量;结束循环
9。返回最小扰动
多类分类器的 DeepFool
对于多类分类器,假设输入是x
,每个类都有一个超平面(将一个类与其他类分开的直平面),并根据x
在空间中的位置将其分类到一个类中。现在,这种算法所做的就是,找到最近的超平面,然后将x
投影到该超平面上,并将其推得更远一点,从而尽可能以最小的扰动将其错误分类。就是这样。(浏览论文中的第 3 节以深入了解)
让我们来看看算法
Fig 5. Algorithm to calculate the Adversarial Image for Multiclass Classifiers.
让我们快速预排一下算法的每一步:
1。输入是一个图像x
和模型分类器f
。
2。扰动
3 的输出。【空白】
4。我们用原始图像和循环变量初始化扰动的图像。
5。我们开始迭代并继续进行,直到原始标签和扰动标签不相等。
6–9。我们考虑在原始类之后具有最大概率的n
类,并且我们存储原始梯度和这些类中的每一个的梯度之间的最小差异(w_{k})以及标签中的差异(f_{k})。10。内部循环存储最小值 w_{k}和 f_{k},并使用它计算输入x
的最近超平面(见图 6)。对于最近超平面的计算公式)
11。我们计算将x
投影到我们在 10 中计算的最近超平面上的最小向量。12。我们将最小扰动添加到图像中,并检查它是否被微分类。13 至 14 岁。循环变量增加;端环
15。返回总扰动,它是所有计算扰动的总和。
下面是计算最近超平面的公式:
Fig 6. Equation to calculate the closest hyperplane.
其中,以f
开头的
变量为类别标签
以w
开头的变量为梯度
其中,以k
为下标的变量为真实类别之后概率最大的类别,以\hat{k}(x+{0})
为下标的变量为真实类别。
下面是计算最小扰动(将输入投影到最近超平面的向量)的等式
Fig 7. Equation to calculate the minimal perturbation for multiclass classifiers.
模型的对抗性稳健性
DeepFool 算法还提供了一种度量算法的对抗性鲁棒性的方法。它由提供
# For images with a batch size of 1
num_images = len(tloader))
adversarial_robustness = (1 / num_images) * ((torch.norm(rt.flatten()) / (torch.norm(x.flatten()))
实验
Fig 8. Table demonstrating the test error rates and robustness of the models using each attack and the time to generate one adversarial example with each attack.
其中,
4 —是快速梯度符号法。
18 —攻击来自 Szegedy 等人题为《神经网络的有趣特性》的论文。
使用通过快速梯度符号方法和 DeepFool 生成的对抗图像显示对抗训练效果的图表。这些图表证明了用最小扰动(而不是像快速梯度符号方法那样过度扰动)的对立例子进行训练的重要性。)
该图证明用过度扰动的图像进行训练降低了模型的稳健性。在这个实验中,作者仅使用α值逐渐增加的 DeepFool(其中α是与产生的扰动相乘的值)
该表显示了使用不同方法微调网络后的测试错误率。该表显示,用过度扰动的图像调整网络导致更高的测试错误率(由快速梯度符号方法产生的对立图像)。)
图表显示了使用精确指标计算模型的对抗性稳健性的重要性。在这个实验中,他们使用 FGM 攻击和 DeepFool 攻击的p_adv
来计算 NIN(网络中的网络)模型的鲁棒性。该图显示了使用 FGM 攻击计算的鲁棒性如何给出错误的度量,因为它实际上并不像前面的示例所示的那样鲁棒(以及使用 DeepFool 攻击计算的鲁棒性的蓝线)。此外,请注意,在第一个额外时期(在用正常图像进行原始训练后,用相反扰动的图像对网络进行 5 个额外时期的训练),红线(FGM)不够敏感,不足以证明鲁棒性的损失。
参考
- 赛义德-穆赫辛-穆沙维-德兹夫利、阿尔侯赛因-法齐、帕斯卡尔-弗罗萨德;IEEE 计算机视觉和模式识别会议(CVPR),2016 年,第 2574–2582 页
希望这篇文章足够清晰,能让你很好地理解 DeepFool 算法是什么以及它是如何工作的。如果我发现更直观的解释或需要更多关注的地方,我希望将来更新这篇文章。请务必阅读这篇论文,以便更好地理解。感谢阅读!
DeepLabv3:语义图像分割
原文:https://towardsdatascience.com/deeplabv3-c5c749322ffa?source=collection_archive---------18-----------------------
来自谷歌的作者扩展了先前的研究,使用最先进的卷积方法来处理不同尺度图像中的对象[1],在语义分割基准上击败了最先进的模型。
From Chen, L.-C., Papandreou, G., Schroff, F., & Adam, H., 2017 [1]
介绍
使用深度卷积神经网络(DCNNs)分割图像中的对象的一个挑战是,随着输入特征图通过网络变得越来越小,关于更小尺度的对象的信息可能会丢失。
Figure 1. The repeated combination of pooling and striding reduces the spatial resolution of the feature maps as the input traverses through the DCNN.
DeepLab 的贡献在于引入了 atrous 卷积、或 expanded 卷积,以提取更密集的特征,从而更好地保留给定不同尺度对象的信息【2–3】。Atruos 卷积还有一个额外的参数 r ,称为 ATR uos 速率,它对应于输入信号的采样步幅。在图 2 中,这相当于沿着每个空间维度在两个连续的滤波器值之间插入 r -1 个零。在这种情况下, r=2 ,因此每个滤波器值之间的零值数量为 1。这种方法的目的是灵活地修改滤波器的视野,并修改计算特征的密度,所有这些都通过改变 r 来实现,而不是学习额外的参数。
Equation 1. The formulation for the location i in the output feature map y, or in other words, one of the squares in the green matrix in Figure 2. x is the input signal, r is the atrous rate, w is the filter and k is the kernel.
Figure 2. A atruous 2D convolution using a 3 kernel with a atrous rate of 2 and no padding. From “An Introduction to Different Types of Convolutions in Deep Learning” by Paul-Louis Pröve
作者调整了一个名为 output_stride,的值,它是输入图像分辨率和输出分辨率之间的比率。他们比较并结合了三种方法来创建他们的最终方法:阿特鲁空间金字塔池(ASPP) 。第一种是级联卷积,它是简单的相互进行的卷积。当这些卷积为 r =1 时,这是现成的卷积,详细信息被抽取,使分割变得困难。作者发现,使用 atrous 卷积通过允许在 DCNN 的更深块中捕获远程信息来改善这一点。图 3 示出了“普通”DCNN 与级联 DCNN 的比较,级联 DCNN 具有r1 个卷积。
Figure 3. The top (a) is a regular CNN while the second uses atrous convolutions with r>1 in a cascading manner and with an output_stride of 16.
第二种是多重网格方法,不同大小的网格层次结构(见图 4)。他们将多网格参数定义为一组 atrous rates ( r₁,r ₂, r ₃),按顺序应用于三个区块。最终速率等于单位速率和相应速率的乘积。例如,在 output_stride 为 16,multi_grid 为(1,2,4)的情况下,块 4(见图 3)将有三个速率为 2 ⋅ (1,2,4) = (2,4,8)的卷积,
Figure 4. A multi-grid CNN architecture. From Ke, T., Maire, M., & Yu, S.X., 2016 [4]
作者的主要贡献是从[5]修改阿特鲁空间金字塔池(ASPP),它在空间“金字塔”池方法中使用 Atrous 卷积,以包括批量归一化和包括图像级特征。如图 5 (b)所示,他们通过在最后一个特征图上应用全局平均池来实现这一点。然后,它们将结果馈送到具有 256 个滤波器的 1x1 卷积。他们最终将该特征双线性上采样到期望的空间维度。图 5 中的例子提供了两个输出。输出(a)是具有 multi_grid rates = (6,12,18)的 3×3 卷积。输出(b)是图像级特征。然后,网络连接这些输出,并在生成 logit 类输出的最终 1x1 卷积之前,通过 1x1 卷积传递它们。
Figure 5. Parallel modules with atrous convolutions. From Chen, L.-C., Papandreou, G., Schroff, F., & Adam, H., 2017 [1].
实验
为了给他们的方法提供支持,他们将级联和多重网格网络与 ASPP 进行了比较。结果是:
- 输出步幅:他们发现,较大的分辨率,或较小的 output_stride,比没有 atrous 卷积或较大的 Output _ Stride 表现明显更好。他们还发现,当在比较 output_stride 为 8(更大的分辨率)和 output_stride 为 16 的验证集上测试这些网络时,output_stride 为 8 的网络性能更好。
- 级联:与常规卷积相比,级联 atrous 卷积的结果提高了性能。然而,他们发现添加的块越多,改善的幅度就越小。
- 多网格:相对于“普通”网络,他们的多网格架构结果确实有所改善,并且在第 7 块的( r₁,r ₂, r ₃) = (1,2,1)处表现最佳。
- ASPP +多重网格+图像池:多重网格速率为( r₁,r ₂, r ₃) = (1,2,4),使得 ASPP (6,12,18)模型在 7721 万时表现最佳。在具有多尺度输入的 COCO 数据集上,当 output_stride = 8 时,模型在 82.70 处测试,显示通过将 output_stride 从 16 改变为 8 而进一步改善。
结论
作者提出了一种方法,通过向空间“金字塔”池 atrous 卷积层添加批处理和图像特征来更新 DeepLab 以前的版本。结果是,网络可以提取密集的特征图来捕捉长范围的上下文,从而提高分割任务的性能。他们提出的模型的结果在 PASCAL VOC 2012 语义图像分割基准上优于最先进的模型。
From Chen, L.-C., Papandreou, G., Schroff, F., & Adam, H., 2017 [1].
更多信息请访问他们的 GitHub:https://GitHub . com/tensor flow/models/tree/master/research/deep lab
参考
[1]陈,L.-C .,帕潘德里欧,g .,施罗夫,f .,&亚当,H. (2017)。语义图像分割中阿特鲁卷积的再思考。从http://arxiv.org/abs/1706.05587取回
[2] Holschneider,Matthias & Kronland-Martinet,Richard & Morlet,j .和 Tchamitchian,Ph. (1989 年)。一种基于小波变换的实时信号分析算法。小波、时频方法和相空间。-1.286.10.1007/978–3–642–75988–8_28.
[3] Giusti,a .,Cireş an,D. C .,Masci,j .,Gambardella,L. M .,& Schmidhuber,J. (2013 年 9 月)。深度最大池卷积神经网络的快速图像扫描。在 2013 IEEE 国际图像处理会议(第 4034–4038 页)。IEEE。
[4]柯,t .梅尔,m .,,余,S.X. (2016)。多重网格神经结构。 2017 年 IEEE 计算机视觉与模式识别大会(CVPR) ,4067–4075。
[5]陈、帕潘德里欧、科基诺斯、墨菲和尤耶。Deeplab:使用深度卷积网络、atrous 卷积和全连接 CRF 的语义图像分割。arXiv:1606.00915,2016。
DeepMind 联合创始人的休假
原文:https://towardsdatascience.com/deepmind-co-founders-leave-of-absence-59730259f2a4?source=collection_archive---------14-----------------------
Photo by @heysupersimi
为什么会发生,有什么信息?
我决定调查 DeepMind 的联合创始人穆斯塔法·苏莱曼的休假,并浏览一下 DeepMind 的历史。
深度思维简介
DeepMind Technologies 是一家成立于 2010 年 9 月的英国公司,目前归 Alphabet 所有,公司总部位于伦敦,在加拿大、法国和美国设有研究中心。该公司由戴密斯·哈萨比斯、穆斯塔法·苏莱曼和沙恩·莱格于 2010 年创立。它在 2014 年以 4 亿英镑或当时的 6.5 亿美元购得。
谷歌收购该公司后,他们建立了一个人工智能道德委员会,但人工智能研究的道德委员会仍然是一个谜,我们真的不知道谁在委员会中。DeepMind 与亚马逊、谷歌、脸书、IBM 和微软一起,是致力于“社会-人工智能界面”的组织 Partnership on AI 的创始成员。
DeepMind 有一个名为 DeepMind 伦理与社会的部门,专注于伦理和社会问题。2017 年 10 月,DeepMind 启动了一个新的研究团队,调查 AI 伦理。
最近提交给英国公司注册处的文件显示,2018 年 DeepMind 的税前亏损增长至 5.7 亿美元,收入为 1.25 亿美元。据说这是由于它努力获得最好的人工智能人才。
新闻说什么?
来自不同新闻出版物的一些标题或关键论点:
- “穆斯塔法·苏莱曼的撤退表明艾集团的自主权已被其母公司剥夺” —英国《金融时报》2019 年 8 月 23 日
- 一位发言人向《福布斯》证实,谷歌广受好评的人工智能实验室 DeepMind 的联合创始人穆斯塔法·苏莱曼正在休假。该公司说,在忙碌了十年之后,穆斯塔法现在要休假一段时间,并称休假是双方的决定,并补充说该公司预计他将在年底前回来。——《福布斯》特约撰稿人 吉利安·德昂弗罗,在 2019 年 8 月 21 日的一篇文章中
- 谷歌旗下备受瞩目的人工智能实验室 DeepMind 的联合创始人因其领导的一些项目引发争议而被停职。穆斯塔法·苏莱曼管理着 DeepMind 的“应用”部门,该部门为实验室在健康、能源和其他领域的研究寻求实际用途。苏莱曼也是 DeepMind 的一个关键公众形象,他在官员和活动中谈论人工智能的承诺以及限制恶意使用该技术所需的道德护栏。”–彭博,2019 年 8 月 21 日
穆斯塔法·苏莱曼
然而,在这件事上我们必须考虑穆斯塔法本人。8 月 22 日,穆斯塔法在推特上写道:
这位伊斯灵顿本地人 19 岁从牛津大学辍学,帮助建立了一个名为穆斯林青年帮助热线的电话咨询服务,这是英国同类服务中最大的心理健康服务之一。他在 22 岁时离开该组织,共同创立了 DeepMind。
在 DeepMind,他最近领导了一个专注于人工智能和健康的项目。
7 月,DeepMind 宣布,其技术现在可以在急性肾损伤发生前两天进行预测。
穆斯塔法在 2018 年的 a Wired 专栏中写道:“我们需要做艰苦、实际和混乱的工作,找出伦理人工智能的真正含义。”他预测人工智能的安全和社会影响的研究将是“最紧迫的调查领域之一。”
穆斯塔法和哈萨比斯要求,作为谷歌收购 DeepMind 的一部分,该公司需要建立一个内部道德委员会,以监督所有部门的人工智能工作。2019 年初,谷歌试图创建一个外部人工智能伦理委员会,但在内部和外部对其成员的抗议之后,很快解散了该项目。
名为 Streams 的应用程序
苏莱曼一直在运营该集团的“应用人工智能”部门,该部门旨在为其科学研究找到现实世界的用途,并在此前领导了该集团的健康工作,包括与英国国家医疗服务系统的广泛批评的 2016 年合作。这项合作让 DeepMind 获得了一款名为 Streams 的肾脏监测应用程序的 160 万份患者记录,其数据共享做法最终在 2017 年被视为非法,促使苏莱曼和该公司道歉。去年年底,谷歌宣布 Streams 及其团队将并入谷歌旗下,实质上解散了 DeepMind Health group。
我从英国广播公司找到了几个报道这一过程的链接:
-
谷歌 DeepMind NHS 应用测试触犯英国隐私法
-
NHS 成立国家人工智能实验室
从那以后,这款应用受到了医院管理者的高度赞扬,被认为大大加快了诊断速度。皇家自由医院的玛丽·埃默森在本月早些时候接受英国广播公司采访时说:“能够在医院的任何地方接收病人的警报,这是一个巨大的变化。”。
2019 年 7 月 31 日的一篇博文
我决定回过头来看看由穆斯塔法·苏莱曼和多米尼克·金写的一篇关于使用人工智能让医生在危及生命的疾病面前领先 48 小时的博文。
“人工智能现在可以在可避免的患者伤害发生前两天预测其主要原因之一,正如我们在《自然》 上发表的最新研究 所证明的那样。我们与美国退伍军人事务部(VA)的专家一起工作,开发了一种技术,在未来,这种技术可以让医生在治疗急性肾损伤(AKI)时提前 48 小时开始,这种疾病与英国每年超过 10 万人有关。这些发现与我们针对临床医生的移动助手 Streams 的同行评审服务评估相一致,该评估表明,通过使用数字工具,可以改善患者护理,降低医疗保健成本。它们共同构成了医学变革性进步的基础,有助于从反应性护理模式转向预防性护理模式。”
Screenshot of post from DeepMind blog published the 31st of July and retrieved on the 26th of August
后来在博文中说:
“这对 DeepMind 健康团队来说是一个重要的里程碑,他们将在大卫·范伯格博士的领导下,作为谷歌健康的一部分推进这项工作。正如我们在 2018 年 11 月 宣布的 一样,Streams 团队和从事医疗转化研究的同事将加入谷歌,以便在全球范围内产生积极影响。DeepMind Health 团队与谷歌团队的经验、基础设施和专业知识相结合,将帮助我们继续开发移动工具,为更多临床医生提供支持,解决关键的患者安全问题,我们希望能够拯救全球成千上万人的生命。”
最后
由于我妻子的父亲患有肾病,这是他早逝的一个主要原因,在这种情况下,我很难保持中立。然而,我能说的是,我们必须阅读眼前的新闻之外的东西,试图更好地理解穆斯塔法·苏莱曼暂时离开的情况是很有趣的。
这是#500daysofAI 每天写关于人工智能的第 83 天。
DeepPiCar 第 1 部分:如何在预算有限的情况下建造深度学习、自动驾驶的机器人汽车
原文:https://towardsdatascience.com/deeppicar-part-1-102e03c83f2c?source=collection_archive---------0-----------------------
DeepPiCar 系列
概述如何建立一个树莓 Pi 和 TensorFlow 供电的自动驾驶机器人汽车
介绍
今天,特斯拉、谷歌、优步和通用汽车都在试图创造自己的自动驾驶汽车,可以在现实世界的道路上行驶。许多分析师预测,在未来 5 年内,我们将开始有完全自动驾驶的汽车在我们的城市中行驶,在 30 年内,几乎所有的汽车都将是完全自动驾驶的。使用一些大公司使用的相同技术来建造你自己的无人驾驶汽车不是很酷吗?在这篇文章和接下来的几篇文章中,我将指导您如何从头开始构建自己的物理、深度学习、自动驾驶的机器人汽车。在一周之内,你将能够让你的汽车检测并跟随车道,识别并回应交通标志和路上的人。这里先睹为快,看看你的最终产品。
Lane Following (left) and Traffic Sign and People Detection (right) from DeepPiCar’s DashCam
我们的路线图
第 2 部分:我将列出需要购买的硬件以及如何设置它们。简而言之,你将需要一个树莓 Pi 板(50 美元) SunFounder PiCar 套件(115 美元)谷歌的 Edge TPU(75 美元)加上一些配件,以及在后面的文章中每个部分是如何重要的。这些材料的总成本约为 250-300 美元。我们还会安装树莓派和 PiCar 需要的所有软件驱动。
Raspberry Pi 3 B+ (left), SunFounder PiCar-V (middle), Google Edge TPU (right)
第三部分:我们将设置所有需要的计算机视觉和深度学习软件。我们使用的主要软件工具有 Python (机器学习/AI 任务的事实上的编程语言) OpenCV (强大的计算机视觉包) Tensorflow (谷歌流行的深度学习框架)。注意,我们在这里使用的所有软件都是免费和开源的!
第 4 部分:随着(乏味的)硬件和软件设置的结束,我们将直接进入有趣的部分!我们的第一个项目是使用 python 和 OpenCV 来教会 DeepPiCar 通过检测车道线在蜿蜒的单车道上自主导航,并相应地转向。
Step-by-Step Lane Detection
第 5 部分:我们将训练 DeepPiCar 自动导航车道,而不必像在我们的第一个项目中那样显式地编写逻辑来控制它。这是通过使用“行为克隆”来实现的,我们只使用道路的视频和每个视频帧的正确转向角度来训练 DeepPiCar 自动驾驶。实现的灵感来自于 NVIDIA 的 DAVE-2 全尺寸自动驾驶汽车,它使用深度卷积神经网络来检测道路特征,并做出正确的转向决策。
Lane Following in Action
最后,在第 6 部分中:我们将使用深度学习技术,如单次多框对象检测和转移学习,来教会 DeepPiCar 检测道路上的各种(微型)交通标志和行人。然后我们会教它在红灯和停车标志时停下来,在绿灯时继续,停下来等待行人过马路,根据张贴的速度标志改变它的速度限制,等等。
Traffic Signs and People Detection Model Training in TensorFlow
先决条件
以下是这些文章的先决条件:
- 首先也是最重要的是愿意修补和破坏东西。与汽车模拟器不同,在汽车模拟器中,一切都是确定的,完全可重复的,真实世界的模型汽车可能是不可预测的,您必须愿意弄脏自己的手,并开始修补硬件和软件。
- 基本 Python 编程技能。我将假设您知道如何阅读 python 代码和编写函数,以及 python 中的 if 语句和循环。我的大部分代码都有很好的文档记录,特别是较难理解的部分。
- 基础 Linux 操作系统知识。我将假设您知道如何在 Linux 的 Bash shell 中运行命令,这是 Raspberry Pi 的操作系统。我的文章将告诉您运行哪些命令,我们为什么运行它们,以及期望输出什么。
- 最后,你需要大约 250-300 美元来购买所有的硬件和工作电脑(Windows/Mac 或 Linux)。同样,所有使用的软件都是免费的。
进一步的想法[可选]
这是可选阅读,因为我试图在我的文章中涵盖你需要知道的一切。然而,如果你想更深入地研究深度学习,(一语双关),除了我在整篇文章中提供的链接之外,这里还有一些资源可供查阅。
吴恩达在 Coursera 上的机器学习和深度学习课程。正是这些课程点燃了我对机器学习和 AI 的热情,给了我创作 DeepPiCar 的灵感。
- 机器学习(免费):本课程涵盖传统的机器学习技术,如线性回归、逻辑回归、支持向量机等,以及神经网络。它是在 2012 年创建的,所以它使用的一些工具,即 Matlab/Octave,已经过时了,而且它没有长篇大论地谈论深度学习。但是它教给你的概念是无价的。你只需要高中水平的数学和一些基本的编程技能就可以学习这门课程,ng 博士非常好地解释了像反向传播这样的困难概念。完成本课程大约需要 3 个月的时间。
- 深度学习 5 门课程专业化(免费或 50 美元/月,如果你想获得证书):这门课程于 2018 年初推出。因此它涵盖了到那时为止所有最新的人工智能研究,如全连接神经网络、卷积神经网络(CNN)和序列模型(RNN/LSTM)。这门课对我来说是一种享受。作为一名工程师,我总是想知道一些很酷的小工具是如何工作的,比如 Siri 如何回应你的问题,以及汽车如何识别路上的物体等。现在我知道了。完成这 5 门课程的专业化大约需要 3-4 个月。
下一步是什么
第一条到此为止。我们将在第 2 部分见面,我们将动手制作一辆机器人汽车!
以下是整个指南的链接:
第 1 部分:概述(本文)
第 2 部分: Raspberry Pi 设置和 PiCar 装配
第 3 部分:让 PiCar 看到并思考
第 4 部分:通过 OpenCV 的自主车道导航
第五部分:自主 通过深度学习进行车道导航
第六部分:交通标志和行人检测处理
DeepPiCar —第 2 部分:Raspberry Pi 设置和 PiCar 装配
原文:https://towardsdatascience.com/deeppicar-part-2-8512be2133f3?source=collection_archive---------2-----------------------
DeepPiCar 系列
组装 PiCar 硬件并安装所有软件驱动程序。让它在客厅里运行
行动纲要
欢迎回来!在本指南中,我们将首先介绍要购买的硬件以及我们为什么需要它们。接下来,我们将设置它们,以便在本文结束时,我们将有一个 PiCar 在我们的客厅中运行。
硬件供应清单
- 1 个树莓 Pi 3 型号 B+套件,带 2.5A 电源 ($50)这是你 DeepPiCar 的大脑。这款最新型号的 Raspberry Pi 具有 1.4Ghz 64 位四核处理器、双频 wifi、蓝牙、4 个 USB 端口和一个 HDMI 端口。我推荐这个套件(不仅仅是 Raspberry Pi 板),因为它配有一个电源适配器,你需要在进行非驱动编码和测试时插入,还有两个芯片散热器,这将防止你的 Raspberry Pi CPU 过热。
- 1 个 64 GB 微型 SD 卡 ($8)这是你的树莓派的操作系统和我们所有软件的存储位置。任何品牌的 micro SD 卡应该都可以。你家里可能就有一个。32GB 应该也可以。我选择 64 GB 是因为我计划在我的汽车行驶时录制大量视频,以便我可以在以后分析它的行为,并在以后的项目中使用这些视频进行深度学习训练。
- 1 x SunFounder PiCar-V 套件 ($115)这是 DeepPiCar 的主体。确保你得到的是如上图所示的 V 型车(又名 2.0 版)。它配备了机器人汽车所需的一切,除了树莓派和电池。市场上有许多 Raspberry Pi 车载套件,我选择了这个车载套件,因为它带有开源 python API 来控制汽车,而其他供应商有其专有的 API 或基于 C 的 API。我们知道,python 现在是机器学习和深度学习的首选语言。此外,开源很重要,因为如果我们发现 API 中的错误,我们可以自己修补汽车 API 的内部,而不必等待制造商提供软件更新。
- 4 节 18650 电池和 1 节电池充电器 ($20)您可以获得任何 18650 电池和兼容充电器。这些电池用于高消耗应用,例如驱动 Raspberry Pi 板和 PiCar。PiCar 只需要两节电池,但你总是希望身边有另一节刚刚充电的电池,这样你就可以让你的车一直在赛道上行驶。我建议在晚上给两套充电,这样你就不用担心测试时电池没电了。
- 1 x 谷歌边缘 TPU USB 加速器 ($75)每个英雄都需要一个助手。谷歌的 Edge TPU (Edge 意味着它用于移动和嵌入式设备,TPU 代表张量处理单元)是 Raspberry Pi 板的一个很好的附加组件。虽然 Pi CPU 将大量计算能力打包在一个微小的包中,但它不是为深度学习而设计的。另一方面,谷歌新发布的 Edge TPU(2019 年 3 月)是专门为运行用 TensorFlow 编写的深度学习模型而设计的。在本系列的第 6 部分中,我们将在 TensorFlow 中构建一个实时交通标志检测模型。这个模型有 200+层深!仅在 Raspberry Pi 的 CPU 上运行该模型只能处理每秒 1 帧(FPS),这几乎不是实时的。此外,它消耗 100%的 CPU,使所有其他程序无响应。但是在 Edge TPU 的帮助下,我们现在可以处理 12 FPS,这对于实时工作来说已经足够了。我们的 CPU 保持凉爽,可以用来做其他处理任务,如控制汽车。
- 1 套微型交通标志(15 美元)和一些乐高玩具。如果你的小宝宝在游戏室里有这些玩具标志和乐高玩具,你可能就不需要买了。你可以使用你找到的任何标志来训练模型,只要确保它们不要太大!
- (可选)1 个 170 度广角 USB 摄像头(40 美元)。这是一个可选配件。我买它是为了取代 SunFounder PiCar 附带的库存相机,以便汽车可以拥有广阔的视野。库存相机很棒,但没有我喜欢的广角,它看不到前轮前 3-4 英寸的车道线。最初,我在第 4 部分中用库存相机编写了车道跟踪代码。在尝试了几个镜头后,我发现这个广角相机大大提高了车道跟踪的准确性和稳定性。控制你的硬件和软件是很好的(相对于在汽车模拟器中驾驶一辆汽车),因为如果一个问题不能简单地通过软件解决,你可以求助于硬件修复。
- 接受 HDMI 输入的 USB 键盘/鼠标和显示器。您只需要在 Pi 的初始设置阶段使用它们。之后,我们可以通过 VNC 或 Putty 远程控制 Pi。
- 一台运行 Windows/Mac 或 Linux 的台式机或笔记本电脑,从这里开始我将称之为“PC”。我们将使用这台 PC 远程访问 Pi 计算机并将代码部署到 Pi 计算机。
有时候,让我惊讶的是,我们汽车的大脑树莓派仅售 30 美元,比我们的许多其他配件都便宜。事实上,随着时间的推移,硬件越来越便宜,功能越来越强大,而软件则完全免费且丰富。我们不是生活在一个伟大的时代吗?!
组装完成后,这就是最终产品。我这里用的是广角相机。
树莓 Pi 设置
Raspberry Pi 操作系统设置(1 小时)
- 按照这个优秀的一步一步的指导将 NOOBS Raspbian 操作系统(Linux 的一个变种)安装到一个微型 SD 卡上。这大约需要 20 分钟和 4GB 的磁盘空间。安装和重启后,您应该会看到一个完整的 GUI 桌面,如下所示。这感觉就像你在一个 Windows 或者 Mac 的 GUI 环境中,不是吗?
- 在安装过程中,Pi 会要求您更改默认用户
pi
的密码。比如我们把密码设为rasp
。 - 初次安装后,Pi 可能需要升级到最新的软件。这可能还需要 10-15 分钟。
设置远程访问
设置远程访问允许 Pi 计算机无头运行(即没有显示器/键盘/鼠标),这使我们不必一直连接显示器和键盘/鼠标。这个视频给出了一个非常好的关于如何设置 SSH 和 VNC 远程访问的教程。不管怎样,这是步骤。
- 打开终端应用程序,如下所示。终端应用程序是一个非常重要的程序,因为我们在后面文章中的大多数命令都将从终端输入。
- 通过运行
ifconfig
找到 Pi 的 IP 地址。在这个例子中,我的 Pi 的 IP 地址是192.168.1.120
。
pi@raspberrypi:~ $ **ifconfig | grep wlan0 -A1**
wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet **192.168.1.120** netmask 255.255.255.0 broadcast 192.168.1.255
- 在终端运行
sudo raspi-config
,启动“树莓 Pi 软件配置工具”。可能会提示您输入用户pi
的密码
- 启用 SSH 服务器:选择
5\. Interface Options
->-SSH
->-Enable
- 启用 VNC 服务器:选择
5\. Interface Options
->-VNC
->-Enable
- 下载并安装 RealVNC 浏览器到你的电脑上。
- 连接到 Pi 的 IP 地址使用真正的 VNC 浏览器。您将看到与 Pi 正在运行的桌面相同的桌面。
- 此时,您可以安全地断开显示器/键盘/鼠标与 Pi 计算机的连接,只保留电源适配器。
设置远程文件访问
由于我们的 Pi 将无头运行,我们希望能够从远程计算机访问 Pi 的文件系统,以便我们可以轻松地将文件传输到 Pi 计算机或从 Pi 计算机传输文件。我们将在 Pi 上安装 Samba 文件服务器。
pi@raspberrypi:~ $ **sudo apt-get update && sudo apt-get upgrade -y**
Get:1 [http://archive.raspberrypi.org/debian](http://archive.raspberrypi.org/debian) stretch InRelease [25.4 kB]
Packages [45.0 kB]
[omitted...]
Unpacking lxplug-ptbatt (0.5) over (0.4) ...
Setting up lxplug-ptbatt (0.5) ...pi@raspberrypi:~ $ **sudo apt-get install samba samba-common-bin -y**
Reading package lists... Done
Building dependency tree
[omitted...]
Processing triggers for libc-bin (2.24-11+deb9u4) ...
Processing triggers for systemd (232-25+deb9u11) ...pi@raspberrypi:~ $ **sudo rm /etc/samba/smb.conf**pi@raspberrypi:~ $ **sudo nano /etc/samba/smb.conf**
然后将下面几行粘贴到 nano 编辑器中
[global]
netbios name = Pi
server string = The PiCar File System
workgroup = WORKGROUP
[HOMEPI]
path = /home/pi
comment = No comment
browsable = yes
writable = Yes
create mask = 0777
directory mask = 0777
public = no
按 Ctrl-X 保存并退出 nano,按 Yes 保存更改。
然后设置一个 Samba 服务器密码。为了简单起见,我们将使用相同的rasp
作为 Samba 服务器密码。设置密码后,重启 Samba 服务器。
# create samba password
pi@raspberrypi:~ $ **sudo smbpasswd -a pi**
New SMB password:
Retype new SMB password:
Added user pi.# restart samba server
pi@raspberrypi:~ $ **sudo service smbd restart**
此时,您应该能够通过 Pi 的 IP 地址(我的 Pi 的 IP 是 192.168.1.120)从 PC 连接到 Pi 计算机。转到您的 PC (Windows),打开命令提示符(cmd.exe)并键入:
# mount the Pi home directory to R: drive on PC
C:\>**net use r: \\192.168.1.120\homepi**
The command completed successfully.
C:\Users\dctia>r:C:\>**dir r:**
Volume in drive R is HOMEPI
Volume Serial Number is 61E3-70FFDirectory of R:\05/02/2019 03:57 PM <DIR> .
04/08/2019 04:48 AM <DIR> ..
04/08/2019 05:43 AM <DIR> Desktop
04/08/2019 05:43 AM <DIR> Documents
04/08/2019 05:43 AM <DIR> Downloads
04/08/2019 05:15 AM <DIR> MagPi
04/08/2019 05:43 AM <DIR> Music
05/02/2019 03:43 PM <DIR> Pictures
04/08/2019 05:43 AM <DIR> Public
04/08/2019 05:43 AM <DIR> Templates
04/08/2019 05:43 AM <DIR> Videos
0 File(s) 0 bytes
11 Dir(s) 22,864,379,904 bytes free
事实上,这是我们的 Pi 计算机的文件系统,我们可以从它的文件管理器中看到。这将是非常有用的,因为我们可以直接从我们的 PC 编辑驻留在 Pi 上的文件。例如,我们可以先使用 PyCharm IDE 在 Pi 上编辑 Python 程序,然后只需使用 Pi 的终端(通过 VNC)运行这些程序。
如果你有一台 Mac,这里是如何连接到 Pi 的文件服务器。点击 Command-K 调出“连接到服务器”窗口。输入网络驱动器路径(替换为您的 Pi 的 IP 地址),即 smb://192.168.1.120/homepi,然后单击连接。输入登录/密码,即 pi/rasp,然后单击 OK 以安装网络驱动器。然后,该驱动器将出现在您的桌面上和 Finder 窗口的边栏中。关于 Mac 更深入的网络连接指导,请查看这篇优秀的文章。
安装 USB 摄像头
USB 摄像头的设备驱动程序应该已经带有 Raspian 操作系统。我们将安装一个视频摄像头查看器,这样我们就可以看到现场视频。
- 从 PiCar 套件中取出 USB 摄像头,并将其插入 Pi 计算机的 USB 端口
- 从终端运行
sudo apt-get install cheese
安装“Cheese”,相机浏览器。
pi@raspberrypi:~ $ **sudo apt-get install cheese -y**
Reading package lists... Done
Building dependency tree
Reading state information... Done
....
cheese is the newest version (3.22.1-1).
- 通过
Raspberry Pi button(Top Left Corner)
->-Sound & Video
->-Cheese
启动奶酪应用程序,您应该会看到一个直播视频,如上图所示。
SunFounder PiCar-V 软件配置(偏离手册)
在组装 PiCar 之前,我们需要安装 PiCar 的 python API。SunFounder 发布了其 Python API 的服务器版本和客户端版本。用于远程控制 PiCar 的客户端 API 代码运行在您的 PC 上,并且使用 Python 版本 3。服务器 API 代码运行在 PiCar 上,不幸的是,它使用的是 Python 版本 2,这是一个过时的版本。由于我们编写的自动驾驶程序只能在 PiCar 上运行,PiCar 服务器 API 也必须在 Python 3 中运行。幸运的是,SunFounder 的所有 API 代码都在 Github 上开源,我做了一个 fork 并将整个 repo(包括服务器和客户端)更新到 Python 3。(我将很快向 SunFounder 提交我的更改,这样一旦 SunFounder 批准,它就可以合并回主 repo。)
目前,运行以下命令(粗体代替 SunFounder 手册中的软件命令。您不必运行手册第 20-26 页上的命令。
# route all calls to python (version 2) to python3,
# pip (version 2) to pip3, even in sudo mode
# note: `sudo abcd` runs `abcd` command in administrator mode
**alias python=python3
alias pip=pip3
alias sudo='sudo '**# Download patched PiCar-V driver API, and run its set up
pi@raspberrypi:~ $ **cd**pi@raspberrypi:~ $ **git clone** [**https://github.com/dctian/SunFounder_PiCar.git**](https://github.com/dctian/SunFounder_PiCar.git)
Cloning into 'SunFounder_PiCar'...
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 276 (delta 0), reused 2 (delta 0), pack-reused 267
Receiving objects: 100% (276/276), 53.33 KiB | 0 bytes/s, done.
Resolving deltas: 100% (171/171), done.
pi@raspberrypi:~ $ **cd ~/SunFounder_PiCar/picar/**
pi@raspberrypi:~/SunFounder_PiCar/picar $ **git clone** [**https://github.com/dctian/SunFounder_PCA9685.git**](https://github.com/dctian/SunFounder_PCA9685.git)
Cloning into 'SunFounder_PCA9685'...
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 87 (delta 2), reused 6 (delta 2), pack-reused 80
Unpacking objects: 100% (87/87), done.pi@raspberrypi:~/SunFounder_PiCar/picar $ **cd ~/SunFounder_PiCar/**
pi@raspberrypi:~/SunFounder_PiCar $ **sudo python setup.py install**
Adding SunFounder-PiCar 1.0.1 to easy-install.pth file
Installing picar script to /usr/local/bin
[omitted....]# Download patched PiCar-V applications
# and install depedent software
pi@raspberrypi:~/SunFounder_PiCar/picar $ **cd**
pi@raspberrypi:~ $ **git clone** [**https://github.com/dctian/SunFounder_PiCar-V.git**](https://github.com/dctian/SunFounder_PiCar-V.git)
Cloning into 'SunFounder_PiCar-V'...
remote: Enumerating objects: 969, done.
remote: Total 969 (delta 0), reused 0 (delta 0), pack-reused 969
Receiving objects: 100% (969/969), 9.46 MiB | 849.00 KiB/s, done.
Resolving deltas: 100% (432/432), done.pi@raspberrypi:~ $ **cd SunFounder_PiCar-V**pi@raspberrypi:~/SunFounder_PiCar-V $ **sudo ./install_dependencies**
Adding SunFounder-PiCar 1.0.1 to easy-install.pth file
Installing picar script to /usr/local/binInstalled /usr/local/lib/python2.7/dist-packages/SunFounder_PiCar-1.0.1-py2.7.egg
Processing dependencies for SunFounder-PiCar==1.0.1
Finished processing dependencies for SunFounder-PiCar==1.0.1
complete
Copy MJPG-Streamer to an Alternate Location. complete
Enalbe I2C. completeInstallation result:
django Success
python-smbus Success
python-opencv Success
libjpeg8-dev Success
The stuff you have change may need reboot to take effect.
Do you want to reboot immediately? (yes/no)**yes**
当提示重新启动时,回答是。重新启动后,应安装所有必需的硬件驱动程序。我们将在汽车组装后测试它们。
皮卡装配
组装过程紧密地重新组装一个复杂的乐高玩具,整个过程需要大约 2 个小时,大量的手眼协调,非常有趣。(在构建阶段,你甚至可以让你的年轻人参与进来。)PiCar 套件附带印刷的分步指导手册。但是我推荐这两个额外的资源。
- PDF 版本的指导手册。打印手册很小,图表可能打印不太清楚,而 PDF 版本非常清晰,可以搜索和放大以了解更多细节。在组装阶段,我发现它对我笔记本电脑上的 PDF 非常有帮助。
- SunFounder 发布的 YouTube 4 集教学视频。不幸的是,这些视频是为老版本的 PiCar,所以有些部分(如伺服电机组件)是不同的。但是大部分零件和组装技术都是一样的。因此,如果您对组装手册中的某个图感到困惑,您可能需要看一下视频的相关部分。我希望 SunFounder 能为新的 PiCar-V 套件发布一组新的视频。
Assembly Videos (4 Parts) for an Older Version of PiCar, a Useful reference
当橡胶遇到路面!
既然 PiCar 的所有基本硬件和软件都已就绪,让我们试着运行它吧!
- 从 PC 通过 VNC 连接到 PiCar
- 确保放入新电池,将开关切换到 ON 位置,并拔下 micro USB 充电电缆。请注意,您的 VNC 远程会话应该仍处于活动状态。
- 在 Pi 终端中,运行以下命令(粗体显示的)。您应该:
- 看到车开快了,再发出
picar.back_wheel.test()
就慢下来 - 当你发出
picar.front_wheel.test()
时,看到前轮转向左、中、右。要停止这些测试,请按 Ctrl-C。要退出 python 程序,请按 Ctrl-D。
pi@raspberrypi:~/SunFounder_PiCar/picar $ **python3**
Python 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.>>> **import picar**
>>> **picar.setup()**>>> **picar.front_wheels.test()**
DEBUG "front_wheels.py": Set debug off
DEBUG "front_wheels.py": Set wheel debug off
DEBUG "Servo.py": Set debug off
turn_left
turn_straight
turn_right>>> **picar.back_wheels.test()**
DEBUG "back_wheels.py": Set debug off
DEBUG "TB6612.py": Set debug off
DEBUG "TB6612.py": Set debug off
DEBUG "PCA9685.py": Set debug off
Forward, speed = 0
Forward, speed = 1
Forward, speed = 2
Forward, speed = 3
Forward, speed = 4
Forward, speed = 5
Forward, speed = 6
Forward, speed = 7
Forward, speed = 8
Forward, speed = 9
Forward, speed = 10
Forward, speed = 11
- 如果您遇到错误或看不到轮子移动,那么要么是您的硬件连接或软件设置有问题。对于前者,请仔细检查你的电线连接,确保电池充满电。对于后者,请在评论区发布消息,详细说明您遵循的步骤和错误消息,我会尽力提供帮助。
下一步是什么
恭喜你,你现在应该有一个 PiCar 可以看到(通过 Cheese),运行(通过 python 3 代码)!这还不是一辆深度学习的汽车,但我们正在朝着它前进。当你准备好了,就开始第三部分吧,在那里我们将赋予 PiCar 计算机视觉和深度学习的超能力。
以下是整个指南的链接:
第 1 部分:概述
第 2 部分: Raspberry Pi 设置和 PiCar 装配(本文)
第 3 部分:让皮卡看到并思考
第 4 部分:通过 OpenCV 的自主车道导航
第五部分:自主 通过深度学习进行车道导航
第六部分:交通标志和行人检测与处理
DeepPiCar —第 3 部分:让 PiCar 看到并思考
原文:https://towardsdatascience.com/deeppicar-part-3-d648b76fc0be?source=collection_archive---------6-----------------------
DeepPiCar 系列
设置计算机视觉(OpenCV)和深度学习软件(TensorFlow)。把 PiCar 变成 DeepPiCar。
行动纲要
欢迎回来!如果你一直关注我在 DeepPiCar 上的前两篇帖子(第一部分和第二部分),你应该有一辆可以通过 Python 控制的跑步机器人汽车。在文章中,我们将赋予您的汽车计算机视觉和深度学习的超能力。在文章的结尾,它将被改造成一个真正的 DeepPiCar,能够检测和识别你房间里的物体。
用于计算机视觉的 OpenCV
请注意,我们 PiCar 的唯一感知传感器是 USB DashCam。DashCam 为我们提供了一个实时视频,它本质上是一系列图片。我们将使用 OpenCV,一个强大的开源计算机视觉库,来捕捉和转换这些图片,以便我们可以理解相机所看到的内容。运行以下命令(粗体)将其安装到您的 Pi 上。
安装打开的 CV 和相关库
# install all dependent libraries of OpenCV (yes, this is one long command)
pi@raspberrypi:~ $ **sudo apt-get install libhdf5-dev -y && sudo apt-get install libhdf5-serial-dev -y && sudo apt-get install libatlas-base-dev -y && sudo apt-get install libjasper-dev -y && sudo apt-get install libqtgui4 -y && sudo apt-get install libqt4-test -y**# install OpenCV and other libraries
pi@raspberrypi:~ $ **pip3 install opencv-python**
Collecting opencv-python
[Omitted....]
Installing collected packages: numpy, opencv-python
Successfully installed numpy-1.16.2 opencv-python-3.4.4.19pi@raspberrypi:~ $ **pip3 install matplotlib**
Collecting matplotlib
Collecting pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 (from matplotlib)
[Omitted...]
Successfully installed cycler-0.10.0 kiwisolver-1.1.0 matplotlib-3.0.3 numpy-1.16.3 pyparsing-2.4.0 python-dateutil-2.8.0 setuptools-41.0.1 six-1.12.0
测试 OpenCV 安装
下面是最基本的测试,看看我们的 python 库是否安装了。OpenCV 的 Python 模块名是cv2
。如果您在运行以下命令时没有看到任何错误,那么模块应该安装正确。Numpy 和 Matplotlib 是两个非常有用的 python 模块,我们将结合 OpenCV 使用它们进行图像处理和渲染。
pi@raspberrypi:~ $ **python3 -c "import cv2"** pi@raspberrypi:~ $ **python3 -c "import numpy"** pi@raspberrypi:~ $ **python3 -c "import matplotlib"**
好了,让我们来尝试一些现场视频处理吧!
pi@raspberrypi:~ $ **cd**
pi@raspberrypi:~ $ **git clone** [**https://github.com/dctian/DeepPiCar.git**](https://github.com/dctian/DeepPiCar.git)
Cloning into 'DeepPiCar'...
remote: Enumerating objects: 482, done.
[Omitted...]
Resolving deltas: 100% (185/185), done.pi@raspberrypi:~ $ **cd DeepPiCar/driver/code**
pi@raspberrypi:~ $ **python3 opencv_test.py**
如果您看到两个实时视频屏幕,一个是彩色的,一个是黑白的,那么您的 OpenCV 正在工作!按下q
退出测试。本质上,该程序获取从相机捕获的图像并按原样显示它(原始窗口),然后将图像转换为黑白图像(黑白窗口)。这非常重要,因为在第 4 部分:自动车道导航中,我们将调出多达 9-10 个屏幕,因为原始视频图像将经过许多阶段处理,如下所示。
为 CPU 和 EdgeTPU 安装 TensorFlow
谷歌的 TensorFlow 是目前最流行的深度学习 python 库。它可以用于图像识别、人脸检测、自然语言处理和许多其他应用。在 Raspberry Pi 上安装 TensorFlow 有两种方法:
- CPU 的张量流
- 面向 Edge TPU 协处理器的 TensorFlow(售价 75 美元的 Coral 品牌 u 盘)
为 CPU 安装 TensorFlow
第一种方法安装 TensorFlow 的 CPU 版本。我们不会使用 Pi 来执行任何深度学习(即模型训练),因为它的 CPU 远远不足以进行反向传播,这是学习过程中需要的非常慢的操作。然而,我们可以使用 CPU 根据预先训练的模型进行推理。推断也称为模型预测,它仅使用向前传播,这是一种快得多的计算机操作。即使 CPU 只是进行推理,它也只能在相对较浅的模型(比如 20-30 层)上实时进行推理。对于更深的模型(100+层),我们需要边缘 TPU。截至 2019 年 5 月,TensorFlow 最新的量产版是 1.13 版本(2.0 还是 alpha)
pi@raspberrypi:~ $ **pip3 install tensorflow**
Collecting tensorflow
[omitted...]
pi@raspberrypi:~ $ **pip3 install keras** Collecting keras
[omitted...]
Successfully installed h5py-2.9.0 keras-2.2.4 keras-applications-1.0.7 keras-preprocessing-1.0.9 numpy-1.16.3 pyyaml-5.1 scipy-1.2.1 six-1.12.0
现在让我们测试并确保安装顺利。导入 TensorFlow 时,它会报告一些警告信息。但是它们可以被安全地忽略。您应该看不到任何错误。(如果您确实看到了其他错误,请将您键入的命令和错误信息发布在下面的帖子中,我会尽力帮助您。)
pi@raspberrypi:~ $ **python3**
Python 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> **import numpy**
>>> **import cv2**
>>> **import tensorflow**
/usr/lib/python3.5/importlib/_bootstrap.py:222: RuntimeWarning: compiletime version 3.4 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.5
return f(*args, **kwds)
/usr/lib/python3.5/importlib/_bootstrap.py:222: RuntimeWarning: builtins.type size changed, may indicate binary incompatibility. Expected 432, got 412
return f(*args, **kwds)
>>> **import keras**
Using TensorFlow backend.
>>> quit()
为 EdgeTPU 安装 TensorFlow
当深度学习模型非常深度,100 层以上,要达到实时性能,需要运行在 EdgeTPU 协处理器上,而不是 CPU 上。然而,在撰写本文时,EdgeTPU 是如此之新(大约在 2019 年初向公众发布),以至于它无法运行所有可以在 CPU 上运行的模型,因此我们必须仔细选择我们的模型架构,并确保它们可以在 Edge TPU 上工作。关于哪些模型可以在 Edge TPU 上运行的更多细节,请阅读谷歌的这篇文章。
按照下面的说明安装 EdgeTPU 驱动程序和 API。当被问及是否要enable the maximum operating frequency
时,回答y
。对于 TPU 来说,我们运行的模型相对来说是轻量级的,我从未见过它运行得非常热。
pi@raspberrypi:~ $ **cd**
pi@raspberrypi:~ $ **wget** [**https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz**](https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz) **-O edgetpu_api.tar.gz --trust-server-names**
--2019-04-20 11:55:39-- [https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz](https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz)
Resolving dl.google.com (dl.google.com)... 172.217.10.78
[omitted]
edgetpu_api.tar.gz 100%[===================>] 7.88M 874KB/s in 9.3s
2019-04-20 11:55:49 (867 KB/s) - ‘edgetpu_api.tar.gz’ saved [8268747/8268747]pi@raspberrypi:~ $ **tar xzf edgetpu_api.tar.gz**
pi@raspberrypi:~ $ **cd edgetpu_api/**
pi@raspberrypi:~/edgetpu_api $ **bash ./install.sh
Would you like to enable the maximum operating frequency? Y/N
y**
Using maximum operating frequency.
Installing library dependencies...
[omitted]
Installing Edge TPU Python API...
Processing ./edgetpu-1.9.2-py3-none-any.whl
Installing collected packages: edgetpu
Successfully installed edgetpu-1.9.2# restart the pi just to complete the installation
pi@raspberrypi:~/edgetpu_api $ **sudo reboot now**
重新启动后,让我们通过运行一个活动对象检测程序来测试它。我们将从 DeepPiCar repo 运行一个演示对象检测应用程序。
pi@raspberrypi:~ $ **cd ~/DeepPiCar/models/object_detection/**pi@raspberrypi:~/DeepPiCar/models/object_detection $ **python3 code/coco_object_detection.py**
W0420 12:36:55.728087 7001 package_registry.cc:65] Minimum runtime version required by package (5) is lower than expected (10).couch, 93% [[ 4.81752396 167.15803146]
[381.77787781 475.49484253]] 113.52ms
book, 66% [[456.68899536 145.12086868]
[468.8772583 212.99516678]] 113.52ms
book, 58% [[510.65818787 229.35571671]
[534.6181488 296.00133896]] 113.52ms
book, 58% [[444.65190887 222.51708984]
[467.33409882 290.39138794]] 113.52ms
book, 58% [[523.65917206 142.07738876]
[535.19741058 213.77527237]] 113.52ms
------
2019-04-20 12:36:57.025142: 7.97 FPS, 125.46ms total, 113.52ms in tf
您应该会看到一个实时视频屏幕出现,它会以大约 7-8 帧/秒的速度尝试识别屏幕中的对象。请注意, COCO(上下文中的常见对象)对象检测模型可以检测大约 100 个常见对象,如人、椅子、电视、沙发、书、笔记本电脑、手机等。不要让这个简单的程序欺骗了你,这是深度学习在起作用。这个程序使用的物体检测模型叫做 ssd_mobilenet_coco_v2 ,它包含了 200 多层!(作为比较,我之前曾尝试使用 Pi 的 CPU 运行 COCO 对象检测模型,这是一个长得多的设置,只能以 1 帧/秒的速度运行,CPU 的利用率为 100%,CPU 温度上升非常快。所以不建议在 CPU 上运行深度模型。)当然,这只是一个演示应用程序,它可以确认 Edge TPU 的设置是否正确。我们将在本系列的第 6 部分中利用 Edge TPU 的全部功能,实时交通标志和行人检测与处理。
更新(2020 年 3 月):自从我的博客在 2019 年 4 月发表以来,Coral EdgeTPU 的安装已经更新。请按照目前 Google 这里的官方说明安装 Tensorflow Lite API 和 EdgeTPU 运行时,这样就可以做上面的物体检测例子了。
下一步是什么
恭喜你,我们现在已经给你的车同时赋予了眼睛(摄像头和 OpenCV)和大脑(TensorFlow),所以它确实是一辆 DeepPiCar 。无论何时你准备好了,前往第四部分,在那里我们将教 DeepPiCar 在车道内自主导航。
以下是整个指南的链接:
第 1 部分:概述
第 2 部分: Raspberry Pi 设置和 PiCar 装配
第 3 部分:让 PiCar 看到并思考(本文)
第 4 部分:通过 OpenCV 的自主车道导航
第五部分:自主 通过深度学习进行车道导航
第六部分:交通标志和行人检测处理
DeepPiCar —第 4 部分:通过 OpenCV 的自主车道导航
原文:https://towardsdatascience.com/deeppicar-part-4-lane-following-via-opencv-737dd9e47c96?source=collection_archive---------2-----------------------
DeepPiCar 系列
使用 OpenCV 检测颜色、边缘和线段。然后计算转向角度,以便 PiCar 可以在车道内自行导航。
Adaptive Cruise Control (left) and Lane Keep Assist System (right)
行动纲要
随着所有的硬件(第二部分)和软件(第三部分)设置完毕,我们已经准备好享受赛车的乐趣了!在本文中,我们将使用一个流行的开源计算机视觉包 OpenCV 来帮助 PiCar 在车道内自主导航。注意这篇文章只会让我们的 PiCar 成为一辆“自动驾驶汽车”,而不是一辆深度学习,自动驾驶汽车。深度学习部分会出现在 Part 5 和 Part 6 中。
介绍
目前,市场上有几款 2018-2019 款汽车搭载了这两项功能,即自适应巡航控制(ACC)和某些形式的车道保持辅助系统(LKAS)。自适应巡航控制使用雷达来检测并与前方的汽车保持安全距离。这一功能自 2012–2013 年左右就已出现。车道保持辅助系统是一个相对较新的功能,它使用安装在挡风玻璃上的摄像头来检测车道线,并进行转向,以便汽车位于车道中间。当你在高速公路上开车时,这是一个非常有用的功能,无论是在拥挤的交通中还是在长途驾驶中。圣诞节期间,我们全家开车从芝加哥去科罗拉多滑雪,一共开了 35 个小时。我们的沃尔沃 XC 90 拥有 ACC 和 LKAS(沃尔沃称之为 PilotAssit),在高速公路上表现出色,因为 95%漫长而无聊的高速公路里程都是由我们的沃尔沃驾驶的!我所要做的就是把手放在方向盘上(但不一定要转向),然后盯着前方的路。当道路弯弯曲曲时,或者当我们前面的车减速或停车时,甚至当一辆车从另一条车道超车时,我都不需要转向、刹车或加速。它不能自动驾驶的几个小时是当我们开车穿过暴风雪时,车道标志被雪覆盖。(沃尔沃,如果你在读这篇文章,是的,我要代言!:)我很好奇,心想:我想知道这是如何工作的,如果我能自己复制它(在较小的规模上)岂不是很酷?
今天,我们将把 LKAS 建成我们的深海乐园。实现 ACC 需要雷达,我们 PiCar 没有。在以后的文章中,我可能会在 DeepPiCar 上添加一个超声波传感器。类似于雷达,超声波也可以探测距离,除了在更近的范围内,这对于小型机器人汽车来说是完美的。
感知:车道检测
车道保持辅助系统有两个组成部分,即感知(车道检测)和路径/运动规划(转向)。车道检测的工作是将道路的视频转化为检测到的车道线的坐标。实现这一点的一种方法是通过计算机视觉包,我们在第 3 部分 OpenCV 中安装了这个包。但是在我们能够检测视频中的车道线之前,我们必须能够检测单幅图像中的车道线。一旦我们可以做到这一点,检测视频中的车道线只是简单地对视频中的所有帧重复相同的步骤。步骤很多,那就开始吧!
隔离车道的颜色
当我在客厅为我的 DeepPiCar 设置车道线时,我使用了蓝色画家的胶带来标记车道,因为蓝色是我房间的独特颜色,胶带不会在硬木地板上留下永久的粘性残留物。
Original DashCam Image (left) and Blue Masking Tape for Lane Line (right)
上面是来自我们 DeepPiCar 的 DashCam 的典型视频帧。首先要做的是隔离图像上所有的蓝色区域。为此,我们首先需要将图像使用的颜色空间,即 RGB(红/绿/蓝)转换为 HSV(色调/饱和度/值)颜色空间。(阅读此处了解更多关于 HSV 色彩空间的详细信息。)这背后的主要思想是,在 RGB 图像中,蓝色胶带的不同部分可能被不同的光照亮,导致它们看起来像深蓝色或浅蓝色。然而,在 HSV 色彩空间中,色调组件将整个蓝色带渲染为一种颜色,而不管其阴影如何。最好用下图来说明。请注意,现在两条车道线的洋红色大致相同。
Image in HSV Color Space
下面是实现这一点的 OpenCV 命令。
注意,我们用的是到 HSV 的转化,而不是到 HSV 的转化。这是因为 OpenCV 由于一些传统原因,默认情况下将图像读入 BGR(蓝/绿/红)色彩空间,而不是更常用的 RGB(红/绿/蓝)色彩空间。它们本质上是等价的颜色空间,只是交换了颜色的顺序。****
一旦图像在 HSV 中,我们可以从图像中“提升”所有的蓝色。这是通过指定蓝色的范围来实现的。
在色调色彩空间中,蓝色大约在 120-300 度范围内,在 0-360 度标度上。您可以为蓝色指定一个更窄的范围,比如 180-300 度,但这没有太大关系。
Hue in 0–360 degrees scale
下面是通过 OpenCV 提升蓝色的代码,以及渲染的蒙版图像。
Blue Area Mask
注意 OpenCV 使用的范围是 0–180,而不是 0–360,所以我们需要在 OpenCV 中指定的蓝色范围是 60–150(而不是 120–300)。这些是下限和上限数组的第一个参数。第二个参数(饱和度)和第三个参数(值)并不重要,我发现 40-255 的范围对于饱和度和值来说都相当不错。
注意这种技术正是电影工作室和天气预报员每天使用的。他们通常使用绿色屏幕作为背景,这样他们就可以将绿色与霸王龙向我们冲过来的惊险视频(电影)或实时多普勒雷达图(天气预报员)进行交换。
********
检测车道线的边缘
接下来,我们需要检测蓝色遮罩中的边缘,以便我们可以有几条不同的线来表示蓝色车道线。
Canny 边缘检测功能是检测图像边缘的强大命令。在下面的代码中,第一个参数是上一步中的蓝色遮罩。第二个和第三个参数是边缘检测的下限和上限,OpenCV 建议为(100,200)或(200,400),因此我们使用(200,400)。
Edges of all Blue Areas
将上面的命令放在一起,下面是隔离图像上的蓝色并提取所有蓝色区域的边缘的函数。
隔离感兴趣区域
从上面的图像中,我们看到我们发现了相当多的蓝色区域不是我们的车道线。仔细一看,发现它们都在屏幕的上半部分。事实上,在进行车道导航时,我们只关心检测离汽车更近的车道线,即屏幕底部。因此,我们将简单地裁剪掉上半部分。嘣!如右图所示,两条明显标记的车道线!
************
Edges (left) and Cropped Edges (right)****
下面是实现这一点的代码。我们首先为屏幕的下半部分创建一个遮罩。然后当我们将mask
和edges
图像合并,得到右边的cropped_edges
图像。
检测线段
在上面的裁剪边缘图像中,对我们人类来说,很明显我们发现了四条线,代表两条车道线。然而,对于计算机来说,它们只是黑色背景上的一堆白色像素。不知何故,我们需要从这些白色像素中提取出这些车道线的坐标。幸运的是,OpenCV 包含了一个神奇的函数,叫做 Hough Transform,它可以做到这一点。霍夫变换是一种用于图像处理的技术,用于提取直线、圆和椭圆等特征。我们将使用它从一堆似乎形成一条线的像素中找到直线。函数 HoughLinesP 本质上试图拟合许多穿过所有白色像素的线,并返回最可能的线集合,服从某些最小阈值约束。(阅读此处深入解释霍夫线变换。)
********
Hough Line Detection (left), Votes (middle), detected lines (right)
下面是检测线段的代码。在内部,HoughLineP 使用极坐标检测直线。极坐标(仰角和离原点的距离)优于笛卡尔坐标(斜率和截距),因为它可以表示任何线,包括笛卡尔坐标不能表示的垂直线,因为垂直线的斜率是无穷大。HoughLineP 有很多参数:
- rho 是以像素为单位的距离精度。我们将使用一个像素。
- 角度是以弧度为单位的角度精度。(三角学快速复习:弧度是表示角度度数的另一种方式。即弧度 180 度就是 3.14159,也就是π)我们就用一度。
- min_threshold 是被认为是线段所需的投票数。如果一条线有更多的投票,霍夫变换认为它们更有可能检测到线段
- minLineLength 是线段的最小长度,以像素为单位。霍夫变换不会返回任何短于此最小长度的线段。
- maxLineGap 是可以分开但仍被视为单个线段的两条线段的最大像素值。例如,如果我们有虚线车道标记,通过指定合理的最大线间隙,霍夫变换会将整个虚线车道线视为一条直线,这是可取的。
设置这些参数实际上是一个反复试验的过程。下面是我的机器人汽车在 320x240 分辨率的摄像机运行在纯蓝色车道线之间时工作良好的值。当然,它们需要重新调整,以适应一辆实物大小的汽车,配有高分辨率摄像头,在真实的道路上以白色/黄色虚线行驶。
如果我们打印出检测到的线段,它将显示端点(x1,y1)后接(x2,y2)和每条线段的长度。
**INFO:root:Creating a HandCodedLaneFollower...
DEBUG:root:detecting lane lines...
DEBUG:root:detected line_segment:
DEBUG:root:[[ 7 193 107 120]] of length 123
DEBUG:root:detected line_segment:
DEBUG:root:[[226 131 305 210]] of length 111
DEBUG:root:detected line_segment:
DEBUG:root:[[ 1 179 100 120]] of length 115
DEBUG:root:detected line_segment:
DEBUG:root:[[287 194 295 202]] of length 11
DEBUG:root:detected line_segment:
DEBUG:root:[[241 135 311 192]] of length 90**
Line segments detected by Hough Transform
将线段合并成两条车道线
现在我们有了许多端点坐标为(x1,y1)和(x2,y2)的小线段,我们如何将它们组合成我们真正关心的两条线,即左车道线和右车道线?一种方法是根据这些线段的斜率对它们进行分类。从上图中我们可以看到,属于左车道线的所有线段都应该是屏幕左侧的上斜和,而属于右车道线的所有线段都应该是屏幕右侧的下斜和。一旦线段被分成两组,我们只需取线段的斜率和截距的平均值,就可以得到左右车道线的斜率和截距。
下面的average_slope_intercept
函数实现了上面的逻辑。
make_points
是average_slope_intercept
函数的辅助函数,它获取直线的斜率和截距,并返回线段的端点。
除了上面描述的逻辑之外,还有一些特殊情况值得讨论。
- 图像中的一条车道线:在正常情况下,我们希望摄像机能看到两条车道线。然而,有时汽车开始偏离车道,可能是由于转向逻辑有缺陷,或者是当车道转弯太急。此时,摄像机可能只捕捉到一条车道线。这就是为什么上面的代码需要检查
len(right_fit)>0
和len(left_fit)>0
- 垂直线段:当汽车转弯时,偶尔会检测到垂直线段。虽然它们不是错误的检测,但是因为垂直线具有无穷大的斜率,所以我们不能将它们与其他线段的斜率进行平均。为了简单起见,我选择忽略它们。由于垂直线不是很常见,这样做不会影响车道检测算法的整体性能。或者,可以翻转图像的 X 和 Y 坐标,因此垂直线的斜率为零,这可以包括在平均值中。但是水平线段的斜率为无穷大,但这种情况非常罕见,因为仪表板摄像头通常指向与车道线相同的方向,而不是垂直于车道线。另一种方法是用极坐标表示线段,然后对角度和到原点的距离取平均值。
******
Only one lane line (left), Vertical Line segment in left lane line (right)**
车道检测摘要
将以上步骤放在一起,这里是 detect_lane()函数,它给定一个视频帧作为输入,返回(最多)两条车道线的坐标。
我们将在原始视频帧的顶部绘制车道线:
这是检测到的车道线以绿色绘制的最终图像。
******
Original Frame (left) and Frame with Detected Lane Lines (right)**
运动规划:转向
现在我们有了车道线的坐标,我们需要驾驶汽车,使它保持在车道线内,更好的是,我们应该尽量把它保持在车道的中间。基本上,我们需要根据检测到的车道线计算汽车的转向角度。
两条检测到的车道线
这是一个简单的场景,因为我们可以通过简单地平均两条车道线的远端点来计算前进方向。下面显示的红线是标题。请注意,红色标题线的下端总是在屏幕底部的中间,这是因为我们假设 dashcam 安装在汽车的中间,并指向正前方。
一条检测到的车道线
如果我们只检测到一条车道线,这将有点棘手,因为我们不能再平均两个端点。但是请注意,当我们只看到一条车道线时,比如说只看到左(右)车道,这意味着我们需要向右(左)使劲转向,这样我们就可以继续沿着车道行驶。一种解决方案是将标题线设置为与唯一车道线相同的坡度,如下所示。
****
转向角
现在我们知道我们要去哪里,我们需要把它转换成转向角,这样我们就可以告诉汽车转向。记住,对于这辆皮卡来说,90 度的转向角是直行,45-89 度是左转,91-135 度是右转。下面是一些将航向坐标转换成以度为单位的转向角的三角方法。请注意,PiCar 是为普通男性创建的,因此它使用的是度数而不是弧度。但是所有的三角数学都是用弧度表示的。
显示标题行
我们在上面展示了几幅带有标题行的图片。下面是呈现它的代码。输入实际上是转向角。
稳定化
最初,当我从每个视频帧计算转向角度时,我只是告诉 PiCar 以这个角度转向。然而,在实际的道路测试中,我发现 PiCar 有时会像醉酒司机一样在车道线之间左右弹跳,有时会完全冲出车道。然后我发现这是由于从一个视频帧到下一个视频帧计算的转向角度不太稳定造成的。你应该在没有稳定逻辑的车道上开车,明白我的意思。有时,转向角可能暂时在 90 度左右(直线行驶),但是,无论什么原因,计算出的转向角可能会突然剧烈跳动,比如 120 度(向右急转弯)或 70 度(向左急转弯)。结果,汽车会在车道内左右颠簸。显然,这是不可取的。我们需要稳定驾驶。的确,在现实生活中,我们有一个方向盘,所以如果我们想向右转向,我们就平稳地转动方向盘,转向角作为一个连续的值发送给汽车,即 90°、91°、92°…。132,133,134,135 度,不是一毫秒 90 度,下一毫秒 135 度。
所以我稳定转向角度的策略如下:如果新的角度与当前角度相差超过max_angle_deviation
度,就在新角度的方向上最多转向max_angle_deviation
度。
在上面的代码中,我使用了两种风格的max_angle_deviation
,如果两条车道线都被检测到,则为 5 度,这意味着我们更加确信我们的方向是正确的;1 度,如果只检测到一条车道线,这意味着我们不太有信心。这些是你可以为自己的车调整的参数。
把它放在一起
执行 LKAS(车道跟踪)的完整代码在我的 DeepPiCar GitHub repo 中。在 DeepPiCar/driver/code 文件夹中,这些是感兴趣的文件:
deep_pi_car.py
:这是 DeepPiCar 的主要入口hand_coded_lane_follower.py
:这是车道检测和跟随逻辑。
只需运行以下命令来启动您的汽车。(当然,我假设你已经记下了车道线并将 PiCar 放在车道上。)
# skip this line if you have already cloned the repo
pi@raspberrypi:~ $ **git clone** [**https://github.com/dctian/DeepPiCar.git**](https://github.com/dctian/DeepPiCar.git)pi@raspberrypi:~ $ **cd DeepPiCar/driver/code**
pi@raspberrypi:~/DeepPiCar/driver/code $ **python3 deep_pi_car.py**
INFO :2019-05-08 01:52:56,073: Creating a DeepPiCar...
DEBUG:2019-05-08 01:52:56,093: Set up camera
DEBUG:2019-05-08 01:52:57,639: Set up back wheels
DEBUG "back_wheels.py": Set debug off
DEBUG "TB6612.py": Set debug off
DEBUG "TB6612.py": Set debug off
DEBUG "PCA9685.py": Set debug off
DEBUG:2019-05-08 01:52:57,646: Set up front wheels
DEBUG "front_wheels.py": Set debug off
DEBUG "front_wheels.py": Set wheel debug off
DEBUG "Servo.py": Set debug off
INFO :2019-05-08 01:52:57,665: Creating a HandCodedLaneFollower...
如果你的设置和我的非常相似,你的 PiCar 应该像下面这样在房间里走来走去!键入Q
退出程序。
下一步是什么
在这篇文章中,我们教会了我们的 DeepPiCar 在车道线内自主导航(LKAS),这非常棒,因为市场上的大多数汽车还不能做到这一点。然而,这并不十分令人满意,因为我们不得不用 python 和 OpenCV 编写大量手工调整的代码来检测颜色、检测边缘、检测线段,然后不得不猜测哪些线段属于左车道线或右车道线。在这篇文章中,我们必须设置许多参数,如蓝色的上限和下限,霍夫变换中检测线段的许多参数,以及稳定期间的最大转向偏差。事实上,我们在这个项目中没有使用任何深度学习技术。如果我们可以“展示”DeepPiCar 如何驾驶,并让它知道如何驾驶,岂不是很酷?这就是深度学习和大数据的承诺,不是吗?在下一篇文章中,这正是我们将要建造的,一辆深度学习的自动驾驶汽车,它可以通过观察一个优秀的司机如何驾驶来学习。《T2》第五部再见。
以下是整个指南的链接:
第一部分:概述
第 2 部分: Raspberry Pi 设置和 PiCar 装配
第 3 部分:让 PiCar 看到并思考
第 4 部分:通过 OpenCV 的自主车道导航(本文)
第五部分:自主 通过深度学习进行车道导航
第六部分:交通标志和行人检测与处理
DeepPiCar 第 5 部分:通过深度学习实现自主车道导航
原文:https://towardsdatascience.com/deeppicar-part-5-lane-following-via-deep-learning-d93acdce6110?source=collection_archive---------3-----------------------
DeepPiCar 系列
使用英伟达的端到端深度学习方法来教会我们的 PiCar 自主导航车道。
行动纲要
欢迎回来!如果你已经通读了 DeepPiCar 第四部,你应该有一辆自动驾驶汽车,它可以在车道内相当平稳地自动驾驶。在本文中,我们将使用深度学习方法来教我们的 PiCar 做同样的事情,将它变成一个 DeepPiCar 。这类似于你我是如何学会开车的,通过观察好的司机(比如我们的父母或者驾校教练)是如何开车的,然后开始自己开车,一路上从自己的错误中学习。请注意,对于本文的大部分内容,您不需要使用 DeepPiCar 来理解,因为我们将在 Google 的 Colab 上进行深度学习,这是免费的。
介绍
回想一下第 4 部分,我们手工设计了驾驶汽车所需的所有步骤,即颜色隔离、边缘检测、线段检测、转向角度计算和转向稳定性。此外,有相当多的参数需要手动调整,如蓝色的上限和下限,通过霍夫变换检测线段的许多参数,以及稳定期间的最大转向偏差等。如果我们没有正确调整所有这些参数,我们的汽车就不会平稳运行。此外,每当我们遇到新的路况时,我们都必须想出新的检测算法,并将其编程到汽车中,这非常耗时,也很难维护。在人工智能和机器学习的时代,我们不应该只是向机器“展示”要做什么,并让它向我们学习,而不是我们“告诉”它具体的步骤吗?幸运的是,Nvidia 的研究人员在这篇出色的论文中展示了,通过“展示”一辆全尺寸汽车如何驾驶,汽车将学会自动驾驶。这听起来很神奇,对吧?让我们看看这是如何做到的,以及如何将其应用到我们的 DeepPiCar。
Nvidia 型号
在高层次上,Nvidia 模型的输入是来自汽车上仪表板摄像头的视频图像,输出是汽车的转向角度。该模型使用视频图像,从中提取信息,并试图预测汽车的转向角度。这被称为监督机器学习程序,其中视频图像(称为特征)和转向角度(称为标签)被用于训练。因为转向角度是数值,这是一个回归问题,而不是分类问题,其中模型需要预测图像中是狗还是猫,或者哪一种类型的花。
在英伟达模型的核心,有一个卷积神经网络 (CNN,不是有线电视网)。细胞神经网络广泛用于图像识别深度学习模型。直觉是,CNN 特别擅长从其各个层面的图像中提取视觉特征(又名。过滤器)。例如,对于面部识别 CNN 模型,早期层将提取基本特征,如线条和边缘,中间层将提取更高级的特征,如眼睛、鼻子、耳朵、嘴唇等,后期层将提取部分或全部面部,如下所示。关于 CNN 的全面讨论,请查看卷积神经网络的维基百科页面。
Nvidia 模型中使用的 CNN 图层与上面非常相似,因为它在早期图层中提取线条和边缘,在后期图层中提取复杂的形状。完全连接的层功能可以被认为是用于转向的控制器。
上图来自英伟达的论文。它总共包含大约 30 层,以今天的标准来看并不是一个很深的模型。模型的输入图像(图的底部)是一个 66x200 像素的图像,这是一个分辨率非常低的图像。该图像首先被归一化,然后通过 5 组卷积层,最后通过 4 个全连接的神经层并到达单个输出,这是汽车的模型预测转向角。
然后将该模型预测角度与给定视频图像的期望转向角度进行比较,误差通过反向传播反馈到 CNN 训练过程中。从上图可以看出,这个过程会循环重复,直到误差(又名损失或均方差)足够低,这意味着模型已经学会了如何合理地驾驶。事实上,这是一个非常典型的图像识别训练过程,除了预测输出是一个数值(回归)而不是物体的类型(分类)。
为 DeepPiCar 调整 Nvidia 模型
除了尺寸之外,我们的 DeepPiCar 与 Nvidia 使用的汽车非常相似,因为它有一个仪表板摄像头,可以通过指定转向角度来控制。Nvidia 通过让其司机在不同的州和多辆汽车上行驶 70 小时的公路里程来收集数据。因此,我们需要收集一些 DeepPiCar 的视频镜头,并记录每个视频图像的正确转向角度。
See the similarities? No Hands on the steering wheel!
数据采集
有多种方法可以收集训练数据。
一种方法是编写一个远程控制程序,这样我们就可以远程控制 PiCar,并让它保存视频帧以及汽车在每一帧的转向角度。这可能是最好的方法,因为它将模拟一个真实的人的驾驶行为,但需要我们编写一个远程控制程序。一种更简单的方法是利用我们在第 4 部分中构建的东西,即通过 OpenCV 的车道跟随器。因为它运行得相当好,我们可以使用该实现作为我们的“模型”驱动程序。机器从另一台机器学习!我们所要做的就是在赛道上运行我们的 OpenCV 实现几次,保存视频文件和相应的转向角度。然后我们可以用它们来训练我们的 Nvidia 模型。在第 4 部分,deep_pi_car.py
会自动保存下来一个视频文件(AVI 文件)每次你运行汽车。
下面是获取视频文件并保存单个视频帧用于训练的代码。为了简单起见,我将转向角作为图像文件名的一部分嵌入,因此我不必维护图像名称和转向角之间的映射文件。
假设您有第 4 部分中录制的名为 video01.avi 的 dashcam 视频,
这是一个 DashCam 视频示例。
下面是保存静态图像的命令,并用转向角度标记它。
pi@raspberrypi:~/DeepPiCar/driver/code $ **python3 save_training_data.py ~/DeepPiCar/models/lane_navigation/data/images/video01**
以下是生成的图像文件。请注意。png 后缀是转向角。从下面,我们可以知道汽车正在左转,因为角度都小于 90 度,这是从上面观看 DashCam 视频确认的。
pi@raspberrypi:~/DeepPiCar/driver/code $ **ls ~/DeepPiCar/models/lane_navigation/data/images |more**
video01_000_**085**.png
video01_001_**080**.png
video01_002_**077**.png
video01_003_**075**.png
video01_004_**072**.png
video01_005_**073**.png
video01_006_**069**.png
培训/深度学习
现在我们有了特征(视频图像)和标签(转向角度),是时候做一些深度学习了!事实上,这是我们在这个 DeepPiCar 博客系列中第一次做深度学习。尽管目前 D eep Learning 都是炒作,但重要的是要注意它只是整个工程项目的一小部分。大部分时间/工作实际上花费在硬件工程、软件工程、数据收集/清理上,最后将深度学习模型的预测连接到生产系统(像一辆行驶的汽车)等。
做深度学习模型训练,不能用树莓派的 CPU,需要一些 GPU 肌肉!然而,我们的预算很少,所以我们不想购买配备最新 GPU 的昂贵机器,也不想从云中租用 GPU 时间。幸运的是,谷歌在这个名为谷歌实验室的网站上免费提供了一些 GPU 甚至 TPU 动力!感谢谷歌给了我们机器学习爱好者一个学习的好地方!
Colab 是一个免费的基于云的 Jupyter 笔记本,让你用 Python 编写和训练深度学习模型。支持的流行 python 库有 TensorFlow、Keras、OpenCV、Pandas 等。最酷的是,TensorFlow for GPU 已经预装,因此您不必花几个小时来摆弄 pip 或 CUDA 驱动程序或软件设置,并且可以直接投入到训练您的模型中。
事不宜迟,让我们开始 Jupyter 笔记本。我假设读者相对精通 Python 和 Keras 库。
这里是我在 GitHub 上的整个端到端深度学习车道导航笔记本。我将在下面介绍它的关键部分。
导入库
首先,我们需要导入我们将在培训过程中使用的 python 库。
加载训练数据
然后我们需要加载训练数据。对于本文,我已经将生成的图像文件的样本集上传到我的 GitHub,以便读者可以克隆它并跟随它。记住,图像文件命名为videoXX_FFF_SSS.png
,其中videoXX
是视频的名称,FFF
是视频中的帧数,SSS
是以度为单位的转向角度。生成的训练数据被读入image_paths
和steering_angles
变量。比如video01_054_110.png
表示这张图片来自video01.avi
视频文件,是第 54 帧,转向角度 110 度(右转)。
分成训练/测试组
我们将使用 sklearn 的train_test_split
方法将训练数据分成 80/20 的训练/验证集。
图像增强
样本训练数据集只有大约 200 幅图像。显然,这不足以训练我们的深度学习模型。然而,我们可以采用一种简单的技术,称为图像增强。一些常见的增强操作有缩放、平移、更改曝光值、模糊和图像翻转。通过在原始图像上随机应用这 5 种操作中的任何一种或全部,我们可以从原始的 200 幅图像中生成更多的训练数据,这使得我们最终训练的模型更加健壮。我将在下面举例说明缩放和翻转。其他操作非常相似,在我的 GitHub 中的 Jupyter 笔记本中有所介绍。
缩放
这是随机缩放的代码,在 100%和 130%之间,以及结果缩放图像(右)。
翻转
这是随机翻转的代码。请注意,翻转操作不同于其他图像增强操作,因为当我们翻转图像时,我们需要改变转向角度。例如,下图(左)的原始图像有一条向左弯曲的车道线,因此转向角为 85°。但是当我们翻转图像时,车道线现在指向右边,所以正确的角度是180 -original_angle
,是 95 度。
我们有一个函数将所有的增强操作组合在一起,因此一个图像可以应用任何或所有的操作。
图像预处理
我们还需要将我们的图像转换成 Nvidia 模型接受的颜色空间和大小。首先, Nvidia 研究论文要求输入图像为 200x66 像素分辨率。类似于我们在第 4 部分中所做的,图像的上半部分与预测转向角无关,所以我们将把它裁剪掉。其次,它要求图像在 YUV 颜色空间中。我们将简单地使用cv2.cvtColor()
来做到这一点。最后,它要求我们将图像标准化。
英伟达型号
这里我们再次呈现 Nvidia 模型架构,所以我们可以很容易地在代码中将其与我们的模型进行比较。
请注意,我们已经相当忠实地实现了 Nvidia 模型架构,只是我们移除了标准化层,因为我们会在模型外部这样做,并添加一些丢弃层,以使模型更加健壮。我们使用的损失函数是均方误差(MSE ),因为我们是在做回归训练。我们还使用了 eLU(指数线性单位)激活函数,而不是我们熟悉的 ReLU(校正线性单位)激活函数,因为当 x 为负时,ELU 不存在“垂死 RELU”问题。
ReLU (left) and ELU (right)
当我们创建模型并打印出它的参数列表时,显示它包含大约 250,000 个参数。这是一个很好的检查,我们的模型的每一层都是按照我们的期望创建的。
Model: "Nvidia_Model" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 31, 98, 24) 1824 _________________________________________________________________ conv2d_1 (Conv2D) (None, 14, 47, 36) 21636 _________________________________________________________________ conv2d_2 (Conv2D) (None, 5, 22, 48) 43248 _________________________________________________________________ conv2d_3 (Conv2D) (None, 3, 20, 64) 27712 _________________________________________________________________ dropout (Dropout) (None, 3, 20, 64) 0 _________________________________________________________________ conv2d_4 (Conv2D) (None, 1, 18, 64) 36928 _________________________________________________________________ flatten (Flatten) (None, 1152) 0 _________________________________________________________________ dropout_1 (Dropout) (None, 1152) 0 _________________________________________________________________ dense (Dense) (None, 100) 115300 _________________________________________________________________ dense_1 (Dense) (None, 50) 5050 _________________________________________________________________ dense_2 (Dense) (None, 10) 510 _________________________________________________________________ dense_3 (Dense) (None, 1) 11 ================================================================= Total params: 252,219 Trainable params: 252,219 Non-trainable params: 0
训练
现在数据和模型都准备好了,我们将开始训练数据。
对于已经使用 Keras 训练深度学习模型的人,我们通常使用model.fit()
命令。但是请注意,今天我们使用了model.fit_generator()
命令。这是因为我们没有使用静态的训练数据集,我们的训练数据是通过前面讨论的图像增强从我们的原始 200 幅图像中动态生成的。为了实现这一点,我们需要创建一个助手函数来进行增强,然后在每次迭代中向model.fit_generator()
返回一批新的训练数据。
下面是这个助手的代码,image_data_generator()
。
评估已训练的模型
训练 30 分钟后,模型将完成 10 个周期。现在是时候看看训练进行得如何了。首先要绘制训练集和验证集的损失函数。很高兴看到训练和验证损失一起快速下降,然后在第 5 个纪元后保持在非常低的水平。似乎没有任何过度拟合的问题,因为验证损失保持在低水平和培训损失。
检验我们的模型是否表现良好的另一个指标是 R 指标。R 接近 100%意味着模型表现得相当好。正如我们可以看到的,我们的模型,即使有 200 张图像,也有 93%的 R,这是非常好的,这主要是因为我们使用了图像增强。
mse = 9.9
r_squared = 93.54%
下面是 GitHub 上的全 Jupyter 笔记本源代码训练深度学习车道导航模型,最好直接用 Google Colab 打开。这样,一旦您提供了 Google 凭据,您就可以自己运行代码。
在旅途中
一个车型是不是真的好,需要在橡胶遇到路面的时候进行最终的检验。下面是驱动 PiCar 的核心逻辑。与我们手动编码的车道导航实现相比,检测蓝色、检测车道和计算转向角度等所有步骤(大约 200 行代码)都消失了。取而代之的是这些简单的命令,load_model
和model.predict()
。当然,这是因为所有的校准都是在训练阶段完成的,3Mb 的 HDFS 格式的训练模型文件包含多达 250,000 个参数。
下面是使用训练好的深度学习模型的车道导航代码的完整源代码。注意文件中有几个助手和测试函数来帮助显示和测试。
下面是 DeepPiCar 在车道上跑步的视频。是的,现在的才是真正的名副其实, DeepPiCar 。我们可以看到它在大部分时间里表现不错,但在接近终点时偏离了车道。因为这是使用深度学习,要解决这个问题,我们要做的就是给模型更多良好驾驶行为的视频片段,要么通过远程控制驾驶汽车,要么使用更好的手动编码车道导航仪。如果我们希望汽车在白色/黄色标记的道路上导航,那么我们可以给它提供带有白色/黄色标记的道路和转向角度的视频,模型也会学习这些,而无需我们手动调整白色和黄色的颜色遮罩。多酷啊!
下一步是什么
在这篇文章中,我们教会了我们的 DeepPiCar 在车道内自主导航,只需让它“观察”一个好司机如何驾驶。将深度学习通道导航实现与我们上一篇文章中手动调整的实现进行对比,它要短得多,也更容易理解。它的准确率也相当高,达到了 94%的 R,当然,我们不得不先训练深度学习模型,它包含了 25 万个参数。但是它仅仅通过观察我们如何驾驶就学会了所有的参数。在下一篇文章中,我们将构建自动驾驶汽车的另一个重要功能,即观察和响应周围环境,最常见的是响应交通标志和行人。希望能在第六部见到你!
以下是整个指南的链接:
第一部分:概述
第二部分:树莓 Pi 设置和 PiCar 装配
第 3 部分:让 PiCar 看到并思考
第 4 部分:通过 OpenCV 的自主车道导航
第五部分:自主 通过深度学习进行车道导航(本文)
第六部分:交通标志和行人检测与处理
DeepPiCar 第 6 部分:交通标志和行人检测与处理
原文:https://towardsdatascience.com/deeppicar-part-6-963334b2abe0?source=collection_archive---------4-----------------------
DeepPiCar 系列
使用迁移学习来调整预训练的 MobileNet SSD 深度学习模型,以通过谷歌的 Edge TPU 检测交通标志和行人。
行动纲要
在博客系列的第 4 部分和第 5 部分中,我们讨论了车道检测和导航。一辆真正的自动驾驶汽车还需要时刻意识到周围的情况。在本文中,我们将讨论另一个重要的感知特征,即检测交通标志和行人。注意,这项功能在任何 2019 款车辆上都不可用,除了可能是特斯拉。我们将训练 DeepPiCar 去识别和实时响应(微型)交通标志和行人。我们还将利用 2019 年初刚刚推出的 75 美元的谷歌 Edge TPU 加速器!
没有购买任何硬件的读者请注意:对于本文的前半部分,您可以只带一台 PC,因为我们将在云中训练我们的模型。
介绍
当我驾驶沃尔沃 XC90 的 PilotAssist 从芝加哥驶往科罗拉多时,我的沃尔沃在高速公路上表现出色,因为我不需要转向或刹车。不过有一点让我很困扰的是,在一些有红绿灯的高速公路上,它无法检测到红绿灯或者交通标志,看到红灯就要刹车。我想,如果它也能做到这一点,那不是很好吗?这就是我写这篇文章的动机,我想让这辆 DeepPiCar 比我的沃尔沃更智能!
就像第 5 部分中的车道导航项目一样,有一个感知步骤和一个规划/控制步骤。我们首先需要检测汽车前面的是什么。然后我们可以用这个信息告诉汽车停下、前进、转弯或改变速度等。
感知:交通标志和行人检测
目标检测是计算机视觉和深度学习中的一个众所周知的问题。目标检测模型有两个组成部分,即基本神经网络和检测神经网络。
首先, 基神经网络 是从图像中提取特征的 CNN,从线、边、圆等低层特征到人脸、人、红绿灯、站牌等高层特征。一些众所周知的基本神经网络是 LeNet、InceptionNet(又名。GoogleNet)、ResNet、VGG 网、AlexNet 和 MobileNet 等。这篇优秀的文章在下面讨论了这些基础神经网络之间的区别。
Base Neural Networks detect features in an image
然后 检测神经网络 被附加到基本神经网络的末端,并用于借助于提取的特征从单个图像中同时识别多个对象。一些流行的检测网络是 SSD(单次多盒检测器)、R-CNN(具有 CNN 特征的区域)、更快的 R-CNN 和 YOLO(你只看一次)等。这篇优秀文章讨论了这些检测神经网络的区别。
Detection Neural Networks detect the type of the object and its bounding box (x,y,w,h)
对象检测模型通常被命名为其基本网络类型和检测网络类型的组合。例如,“MobileNet SSD”模型,或“Inception SSD”模型,或“ResNet fast R-CNN”模型,仅举几个例子。
最后,对于预训练的检测模型,模型名称还将包括它被训练的图像数据集的类型。用于训练图像分类器和检测器的几个知名数据集是 COCO 数据集(大约 100 种常见的家用对象) Open Images 数据集(大约 20000 种对象)和自然主义者数据集(大约 200000 种动植物物种)中的。例如,ssd_mobilenet_v2_coco
模型使用第二版 MobileNet 提取特征,SSD 检测对象,并在 COCO 数据集上进行预训练。
跟踪所有这些模型的组合不是一件容易的事情。但是多亏了谷歌,他们用 TensorFlow(称为模型动物园,实际上是模型动物园)发布了一个预训练模型的列表,所以你可以下载一个适合你需要的模型,并直接在你的项目中使用它进行检测推理。
Source: Google’s Detection Model Zoo
回想一下,我们在第三部分中使用了在 COCO 数据集上预先训练的 MobileNet SSD 模型,它识别了我客厅书架和沙发上的书籍。
迁移学习
然而,这篇文章是关于检测我们的迷你交通标志和行人,而不是书或沙发。但我们不想收集和标记成千上万的图像,并花费数周或数月从零开始构建和训练一个深度检测模型。我们可以做的是利用转移学习 — ,它从预训练模型的模型参数开始,只为它提供 50–100 张我们自己的图像和标签,只花几个小时来训练检测神经网络的部分。直觉是,在预训练的模型中,基本 CNN 层已经擅长于从图像中提取特征,因为这些模型是在大量和各种各样的图像上训练的。区别在于,我们现在有一组不同于预训练模型的对象类型(约 100–100,000 种)。
Miniaturized versions of traffic signs and pedestrians used for training
建模培训
模型训练包括几个步骤。
- 图像收集和标记(20-30 分钟)
- 型号选择
- 转移学习/模型培训(3-4 小时)
- 以边缘 TPU 格式保存模型输出(5 分钟)
- 在树莓 Pi 上运行模型推理
图像采集和标记
我们有 6 种对象类型,即红灯、绿灯、停车标志、40 英里/小时限速、25 英里/小时限速,以及一些作为行人的乐高小雕像。于是我拍了大概 50 张类似上面的照片,把物体随机放在每张图片里。
然后,我用图像上的每个对象的边界框来标记每个图像。这看起来需要几个小时,但是有一个免费的工具,叫做 labelImg (用于 windows/Mac/Linux),让这项艰巨的任务变得轻而易举。我所要做的就是将 labelImg 指向存储训练图像的文件夹,对于每个图像,在图像上的每个对象周围拖一个框,并选择一个对象类型(如果是新类型,我可以快速创建一个新类型)。因此,如果您使用键盘快捷键,每张照片只需 20-30 秒,因此我只花了 20 分钟就标记了大约 50 张照片(大约 200-300 个对象实例)。之后,我只是随机地将图像(以及它的标签 xml 文件)分成训练和测试文件夹。你可以在models/object_detection/data
下的 DeepPiCar 的 GitHub repo 中找到我的训练/测试数据集。
Labeling Images with LabelImg Tool
型号选择
在 Raspberry Pi 上,由于我们的计算能力有限,我们必须选择一个既运行相对快速又准确的模型。在试验了几个模型后,我选定了MobileNet v2 SSD COCO
模型作为速度和准确性之间的最佳平衡。此外,为了让我们的模型在边缘 TPU 加速器上工作,我们必须选择MobileNet v2 SSD COCO **Quantized**
模型。量化是一种通过将模型参数存储为整数值而不是双精度值来使模型推断运行更快的方法,预测精度几乎不会下降。Edge TPU 硬件经过优化,可以只运行量化模型。这篇文章对 Edge TPU 的硬件和性能基准进行了深入分析,供感兴趣的读者阅读。
转移学习/模型训练/测试
对于这一步,我们将再次使用 Google Colab。本节基于程维的优秀教程“如何免费轻松训练一个物体检测模型”。我们需要在树莓派上运行,使用边缘 TPU 加速器。由于整个笔记本及其输出相当长,我将在下面介绍我的 Jupyter 笔记本的关键部分。完整的笔记本代码可以在我的 GitHub 上找到,里面对每一步都有非常详细的解释。
设置培训环境
上面的代码选择MobileNet v2 SSD COCO **Quantized**
模型,从 TensorFlow GitHub 下载训练好的模型。如果我们想选择不同的检测模型,这一部分设计得很灵活。
准备培训数据
上面的代码将 LabelImg 工具生成的 xml 标签文件转换为二进制格式(。记录)以便 TensorFlow 快速处理。
下载预训练模型
'/content/models/research/pretrained_model/model.ckpt'
上述代码将下载ssd_mobilenet_v2_quantized_300x300_coco_2019_01_03
模型的预训练模型文件,我们将仅使用model.ckpt
文件,我们将从该文件应用迁移学习。
训练模型
这一步需要 3-4 个小时,取决于你训练的步数(又名纪元或num_steps
)。训练完成后,你会在model_dir
里看到一堆文件。我们正在寻找最新的model.ckpt-xxxx.meta
文件。在这种情况下,由于我们运行了 2000 步,我们将使用来自model_dir
的**model.ckpt-2000.meta**
文件。
!ls -ltra '{model_dir}/*.meta'-rw------- 1 root root 17817892 Apr 16 23:10 model.ckpt-1815.meta
-rw------- 1 root root 17817892 Apr 16 23:20 model.ckpt-1874.meta
-rw------- 1 root root 17817892 Apr 16 23:30 model.ckpt-1934.meta
-rw------- 1 root root 17817892 Apr 16 23:40 model.ckpt-1991.meta
**-rw------- 1 root root 17817892 Apr 16 23:42 model.ckpt-2000.meta**
在训练期间,我们可以通过 TensorBoard(上面我的 GitHub 链接中的源代码)来监控损失和精度的进展。我们可以看到,在整个培训过程中,测试数据集的丢失率在下降,精确度在提高,这是一个很好的迹象,表明我们的培训正在按预期进行。
Total Loss (lower right) keeps on dropping
mAP (top left), a measure of precision, keeps on increasing
测试训练好的模型
训练结束后,我们通过新模型运行了测试数据集中的一些图像。正如所料,图像中几乎所有的物体都以相对较高的置信度被识别。有一些图像中的物体离得更远,没有被探测到。这对我们的目的来说很好,因为我们只想检测附近的物体,这样我们就可以对它们做出反应。当我们的车靠近远处的物体时,它们会变得更大,更容易被发现。
以边缘 TPU 格式保存模型输出
一旦模型被训练,我们必须将模型meta
文件导出到 Google ProtoBuf 格式的推理图,然后导出到 Edge TPU 加速器可以理解和处理的格式。这似乎是一个简单的步骤,但在撰写本文时,在线资源(包括 Edge TPU 自己的网站)非常稀缺,以至于我花了数小时研究正确的参数和命令,以转换成 Edge TPU 可以使用的格式。
幸运的是,经过几个小时的搜索和实验,我已经找到了下面的命令来做到这一点。
最终我们得到一个road_signs_quantized.tflite
文件,适合移动设备和 Raspberry Pi CPU 进行模型推断,但还不适合 Edge TPU 加速器。
!ls -ltra '/content/gdrive/My Drive/Colab Notebooks/TransferLearning/Training/fine_tuned_model/*.tflite'root root 4793504 Apr 16 23:43 **road_signs_quantized.tflite**
对于边缘 TPU 加速器,我们需要再执行一个步骤。那就是通过 Edge TPU 模型 Web 编译器运行road_signs_quantized.tflite
。
将road_signs_**quantized**.tflite
上传到 web 编译器后,可以下载另一个 tflite 文件,保存为road_signs_**quantized_edgetpu**.tflite
。现在你完成了!会有一些警告,但是可以安全地忽略。请注意,99%的模型将在边缘 TPU,这是伟大的!
_edgetpu.tflite
文件和常规.tflite
文件的区别在于,使用**_edgetpu**.tffile
文件,所有(99%)模型推理将在 TPU 边缘运行,而不是在 Pi 的 CPU 上运行。出于实用目的,这意味着您每秒可以处理大约 20 幅 320x240 分辨率的图像(又名。FPS,每秒帧数),但是单独使用 Pi CPU 时只有大约 1 FPS。20 FPS 对于 DeepPiCar 来说是(接近)实时的,这值 75 美元。(嗯,考虑到整个树莓派——CPU+电路板才 30 美元,我觉得这 75 美元的成本应该更低!)
规划和运动控制
现在 DeepPiCar 已经可以检测和识别它面前有什么物体了,我们仍然需要告诉它如何处理它们,也就是运动控制。运动控制有两种方法,即基于规则的和端到端的。基于规则的方法意味着我们需要告诉汽车当它遇到每个物体时该做什么。例如,告诉汽车如果看到红灯或行人就停下来,或者如果看到限速标志就开慢点,等等。这类似于我们在第 4 部分中所做的,在第 4 部分中,我们通过一组代码/规则告诉汽车如何在车道内导航。端到端方法只是向汽车输入大量优秀驾驶员的视频片段,汽车通过深度学习,自动计算出它应该在红灯和行人面前停下来,或者在限速下降时减速。这类似于我们在第 5 部分“端到端车道导航”中所做的。
对于本文,我选择了基于规则的方法,因为 1)这是我们人类通过学习道路规则来学习如何驾驶的方式,2)它更容易实现。
由于我们有六种类型的对象(红灯、绿灯、40 英里/小时限制、25 英里/小时限制、停车标志、行人),我将说明如何处理一些对象类型,您可以在 GitHub 上的这两个文件中阅读我的完整实现,[traffic_objects.py](https://github.com/dctian/DeepPiCar/blob/master/driver/code/traffic_objects.py)
和[object_on_road_processor.py](https://github.com/dctian/DeepPiCar/blob/master/driver/code/objects_on_road_processor.py)
。
规则很简单:如果没有探测到物体,就以最后已知的速度限制行驶。如果检测到某个物体,该物体将修改汽车的速度或速度限制。例如,当你探测到足够近的红灯时停止,当你没有探测到红灯时继续。
首先,我们将定义一个基类TrafficObject
,它表示道路上可以检测到的任何交通标志或行人。它包含一个方法,set_car_state(car_state)
。car_state
字典包含两个变量,即speed
和speed_limit
,这两个变量将被方法改变。它还有一个助手方法is_close_by()
,检查检测到的对象是否足够近。(嗯,由于我们的单个相机不能确定距离,我用物体的高度来近似距离。为了精确确定距离,我们需要激光雷达,或者它的小兄弟,超声波传感器,或者像特斯拉一样的立体视觉摄像系统。)
红灯和行人的实现很简单,只需将汽车速度设置为 0。
25 Mph 和 40 Mph 速度限制只能使用一个 SpeedLimit 类,该类将 speed_limit 作为其初始化参数。当检测到该标志时,只需将车速限制设置到适当的极限即可。
绿光实现甚至更简单,因为它除了检测到打印绿光之外什么也不做(代码未显示)。停止标志的实现稍微复杂一些,因为它需要跟踪状态,这意味着它需要记住它已经在停止标志处停了几秒钟,然后在汽车经过标志时继续前进,即使后续的视频图像包含非常大的停止标志。具体可以参考我在[traffic_objects.py](https://github.com/dctian/DeepPiCar/blob/master/driver/code/traffic_objects.py)
的实现。
一旦我们定义了每个交通标志的行为,我们需要一个类将它们联系在一起,这个类就是ObjectsOnRoadProcessor
类。该类首先加载边缘 TPU 的训练模型,然后用该模型检测实时视频中的对象,最后调用每个交通对象来改变汽车的速度和速度限制。下面是[objects_on_road_processor.py](https://github.com/dctian/DeepPiCar/blob/master/driver/code/objects_on_road_processor.py)
的关键部位。
注意,每个 TrafficObject 只是改变了car_state
对象中的speed
和speed_limit
,而没有实际改变汽车的速度。是ObjectsOnRoadProcessor
在检测和处理所有交通标志和行人后,改变汽车的实际速度。
把它放在一起
这是这个项目的最终成果。请注意,我们的 DeepPiCar 在停车标志和红灯前停下来,不等任何行人,继续前行。此外,它在 25 英里/小时的标志下减速,在 40 英里/小时的标志下加速。
感兴趣的完整源代码在 DeepPiCar 的 GitHub 上:
- Colab Jupyter 笔记本用于物体检测和迁移学习
- Python 中的规划和运动控制逻辑
- DeepPiCar 主驱动程序。
下一步是什么
在这篇文章中,我们教会了我们的 DeepPiCar 识别交通标志和行人,并对它们做出相应的反应。这不是一个小壮举,因为路上的大多数汽车还不能做到这一点。我们采取了一种捷径,使用了预先训练的对象检测模型,并在其上应用了迁移学习。事实上,当一个人无法收集足够的训练数据来从头创建深度学习模型,或者没有足够的 GPU 能力来训练模型数周或数月时,迁移学习在人工智能行业中非常普遍。那么为什么不站在巨人的肩膀上呢?
在以后的文章中,我有相当多的想法。这里有一些好玩的项目,以后可以试试。
嘿,贾维斯,开始开车!
我想在车上装一个麦克风,训练它识别我的声音和我的唤醒词,这样我就可以说:“嘿,贾维斯,开始开车!”或者“嘿贾维斯,左转!”我们在吴恩达的深度学习课程中做了一个唤醒词项目,那么能够召唤 DeepPiCar 的超级酷岂不是更好,就像钢铁侠或者蝙蝠侠一样?
JARVIS, Tony Stark’s (Ironman) AI Assistant
自适应巡航控制
另一个想法是在 DeepPiCar 上安装一个超声波传感器。这类似于现实生活中车辆上的激光雷达,而我们可以感知 DeepPiCar 和其他物体之间的距离。例如,使用超声波传感器,我们将能够实现 ACC(自适应巡航控制),这是自动驾驶汽车的一个基本功能,或者我们可以通过仅检测特定范围内的对象来增强我们的对象检测算法。
端到端深度驾驶
我还想尝试完全端到端的驾驶,我将远程控制汽车一段时间,保存视频片段,速度和转向角度,并应用深度学习。希望深度学习将教会它如何驾驶,即通过模仿我的驾驶行为,既遵循车道,又对交通标志和行人做出反应。这将是一个超级酷的项目,如果它实际工作。这意味着我们不需要告诉汽车任何规则,它只是通过观察来解决一切问题!!这将是自动驾驶汽车的圣杯,这类似于 AlphaZero 如何在没有任何人类输入启发的情况下学习下围棋或象棋。
谢谢!
如果你已经读到这里(或者和我一起构建/编码),那么恭喜你!如果到目前为止一切正常,你应该有一辆深度学习、自动驾驶的机器人汽车在你的客厅里运行,并且能够在它观察到停止标志或红灯时停下来!如果没有,请在下面留言,我会尽力帮助你。我真的很高兴能和你一起分享这美妙的旅程。事实上,比起编写代码、训练模型和在我的客厅里测试 DeepPiCar加起来,我写这些文章花费的时间要长得多。这也是我第一次写博客,既害怕又兴奋。我现在意识到,我喜欢建造东西,就像向别人展示如何建造东西一样。
像往常一样,这里是整个指南的链接,以防你需要参考以前的文章。现在需要给自己找一份自动驾驶汽车公司的机器学习工程师的工作!一会儿见!
第 1 部分:概述
第 2 部分: Raspberry Pi 设置和 PiCar 装配
第 3 部分:让 PiCar 看到并思考
第 4 部分:通过 OpenCV 的自主车道导航
第五部分:自主 通过深度学习进行车道导航
第六部分:交通标志和行人检测与处理(本文)
黑暗防御统计
原文:https://towardsdatascience.com/defense-against-the-dark-stats-94ff3db4e844?source=collection_archive---------32-----------------------
如今,从政治到医疗保健到广告,统计、机器学习和大数据似乎处于几乎所有可以想象的领域的前沿。虽然这场稳步的革命无疑令人兴奋,但它也促使我们更加密切地关注蜘蛛侠叔叔本的明智之言:“权力越大,责任越大”。
Wise words from Uncle Ben.
事实上,正如这些领域有巨大的力量给世界带来持久的积极变化,它们也有力量被用来实现自私、阴暗、彻头彻尾的邪恶目标。
在这篇文章的持续时间里,假设你是一个邪恶制药公司的领导。你的最新计划是向市场投放一种“神奇药丸”,承诺抑制一个人访问脸书、Instagram 等社交媒体网站的欲望。作为一个恶魔,你计划出售一个完全虚假的药丸,并使用高度扭曲的统计数据来获得人们的信任。
你的卑鄙计划只有三个组成部分:证明对你的神奇药丸有很大的需求,证明你的神奇药丸抑制了上社交媒体的欲望,证明你的神奇药丸在上市一段时间后发挥了作用。
Your evil 3 step plan.
证明你的神奇药丸的必要性
为了开始你的计划,你需要让每个人相信社交媒体的使用已经完全失控,因此需要你的神奇药丸。你在脸书做了一个智能手机调查,询问人们每天花多少时间在社交媒体上。取回结果后,你发现普通人每天花 4 个小时在社交媒体上!
Your conduct a smartphone Facebook survey asking about social media use.
**那么你的调查到底有什么邪恶之处呢?事实上,你在社交媒体平台脸书上询问社交媒体的使用情况,几乎可以肯定会使你的结果偏向于在社交媒体上报告的更长时间。换句话说:回答你的调查的人必须去过脸书才能找到你的调查。当然,你会在新闻稿中忽略这个小细节。
这种类型的统计误用被称为过度概括,发生在样本不代表总体时。这里我们的人口是所有的美国人,但是我们的样本只包括那些已经有脸书账户的人。**
那么,我们如何抵御这种类型的统计攻击呢?正如我们不久将看到的对统计数据的其他误用一样,我们可以通过要求回答一些关键问题来为自己辩护。为了泛化,我们想问一个“谁?”问题: “谁在样本中,他们是否代表我们试图测量的人群?”
How to defend against overgeneralization.
证明你的神奇药丸的可行性
好的,事情正在按计划进行。你已经让所有人相信社交媒体的使用正在失控,并为你的神奇药丸获得了大量资金。接下来,你需要对你的药丸进行临床试验,证明它确实降低了人们上社交网站的欲望。当然唯一的问题是你的药丸是一颗完全假冒的。
不过嘿!你是个邪恶的科学家;你绝不会让像真相这样微不足道的事情阻碍你的计划。在你的大量资助下,你进行了 100 次试验,每次都有几个参与者,并给每个参与者服用不同数量的神奇药丸。你跟踪他们在一段时间内的社交媒体使用情况,并对每一批参与者衡量是否存在正相关(社交媒体使用增加)、负相关(社交媒体使用减少)或无相关(社交媒体使用无显著变化)。
您的结果如下所示。
The results of your clinical trials.
好吧,很明显你的药是无用的。在 100 项试验中,只有 5 项表明社交媒体使用率下降,5 项实际上表明社交媒体使用率增加,而多达 90 项试验表明社交媒体使用率没有显著变化。不要担心!你只会报告显示社交媒体使用下降的 5。你将新闻稿的标题框定为:“奇迹药丸在 5 次独立试验中持续显示社交媒体使用率下降”。严格来说,你没有说谎对吧?
这种对统计数据的误用被称为 樱桃采摘。 它是只选择确认一个结果的证据片段,而忽略其他所有证据的行为。很容易看出为什么它确实非常险恶。一个不知情的公众成员甚至不会知道所有反驳这一说法的证据。
防止我们摘樱桃的最好方法是什么?我们应该总是问一个“有多少?”问题: “有多少试验讲述了一个不同于参考文献的故事?”
How to defend against cherry picking.
证明你神奇药丸的效果
****完美!你向所有人展示了你的神奇药丸是绝对必要的,然后让所有人相信你的药丸确实如其所言。因此,你的药丸现在已经上市几个月了,你只需要证明它对社交媒体的使用产生了预期的效果。你让你的市场部为你制作了这张漂亮的图表。
You create a chart showing social media use over time.
很明显 ,从这个图表很明显,自从你的神奇药丸上市以来,社交媒体的使用一直在下降。很明显这一定是你药丸的原因。
这个故事有几个问题。首先,即使在你的药片发布之前,社交媒体的使用似乎也在下降。第二,对于为什么社交媒体在假期使用下降,有一个强有力的替代解释:人们可能花更多的时间与家人、朋友和爱人在一起,而花更少的时间在社交媒体上。
这种对统计数据的误用非常普遍,被称为 虚假因果关系 或“相关性并不意味着因果关系”。也就是说,仅仅因为奇迹药丸的销售和社交媒体使用的减少之间存在关联,并不意味着使用的减少是由药丸引起的。
我们怎样才能抵御虚假的因果关系?我们最好问一个“为什么?”问题: “为什么我会看到我看到的结果?是因为陈述的原因还是有其他可能的解释?”
How to defend against the False Causality trap.
在上图中,我们问自己,是 A 导致了 B,还是 A 和 B 都是不同变量 c 的结果。同样,我们需要问自己,是药丸销量增加导致了社交媒体使用率下降,还是药丸销量增加和社交媒体使用率下降都是由即将到来的假日季节造成的。**
关键要点
当然,上面的例子是现实生活中发生的高度简化的版本。不幸的是,当我们在花哨、专业的图表或统计报告的伪装下被欺骗时,通常很难发现。此外,误导性的图表和对统计数据的严重滥用通常不是某些恶意制药公司所为,而仅仅是人们没有仔细制定他们的统计模型。**
因此,在查看任何统计分析时,培养一种健康的怀疑变得越来越重要。我们在这篇文章中提出的简单关键问题可以帮助我们抵御黑暗统计。
定义数据科学问题
原文:https://towardsdatascience.com/defining-a-data-science-problem-4cbf15a2a461?source=collection_archive---------7-----------------------
数据科学家最重要的非技术性技能
Photo by Kelly Sikkema on Unsplash
根据 Cameron Warren 在他的《走向数据科学》文章 中的说法,不要做数据科学,解决业务问题 ,“…对于一个数据科学家来说,最重要的技能是清晰地评估和定义问题的能力,这超过了任何技术专长。”
作为一名数据科学家,您会经常发现或遇到需要解决的问题。您的最初目标应该是确定您的问题实际上是否是数据科学问题,如果是,是什么类型的问题。能够将一个商业想法或问题转化为一个清晰的问题陈述是非常有价值的。并且能够有效地传达该问题是否可以通过应用适当的机器学习算法来解决。
是数据科学问题吗?
真正的数据科学问题可能是:
- 对数据进行分类或分组
- 识别模式
- 识别异常
- 显示相关性
- 预测结果
一个好的数据科学问题应该是具体的、结论性的。例如:
- 随着个人财富的增加,关键健康指标如何变化?
- 在加州,大多数心脏病患者住在哪里?
相反,模糊和不可测量的问题可能不适合数据科学解决方案。例如:
- 财务和健康有什么联系?
- 加州人更健康吗?
这是什么类型的数据科学问题?
一旦你决定你的问题是数据科学的一个很好的候选,你将需要确定你正在处理的问题的类型。为了知道哪种类型的机器学习算法可以被有效地应用,这个步骤是必要的。
机器学习问题通常分为两类:
- 监督 — 根据标记输入&输出数据预测未来输出
- 无监督 — 在未标记的输入数据中寻找隐藏的模式或分组
Image per MathWorks
*还有第三个桶( 强化学习 )不在本帖讨论范围内,不过你可以在这里 阅读一下 。
有监督的学习可以分为另外两个部分:
- 分类 — 预测离散分类反应(例如:良性或恶性)
- 回归 — 预测连续的数字响应(例如:20 万美元的房价或 5%的降雨概率)
每种机器学习问题的用例是什么?
- 无人监管的(主要被认为是“集群”)—市场细分、政治投票、零售推荐系统等等
- 分类— 医学成像、自然语言处理和图像识别等
- 回归— 天气预报、投票率、房屋销售价格等等
Pro 提示: 通过使用条件逻辑将连续的数值响应转化为离散的分类响应,可以将回归问题转化为分类问题!例如:
- 问题 : 估计有人投票的概率。
- 回归反应 : 60%概率
- 分类响应 : 是(如果回归响应大于 50%),否(如果回归响应小于 50%)
细化您的问题的子类型
在确定最终的问题定义之前,您需要非常具体地了解您的问题的机器学习子类型。弄清楚术语将有助于你决定选择哪种算法。下图说明了决定分类子类型(基于类)和回归子类型(基于数值)的示例工作流。
Image per Google Developers
Image per Google Developers
最终确定问题陈述
一旦您确定了具体的问题类型,您应该能够清楚地阐明一个精炼的问题陈述,包括模型将预测什么。例如:
这是一个多类分类问题,预测一幅医学图像是否会属于三类中的一类——*{benign, malignant, inconclusive}*
。
您还应该能够表达模型预测的预期结果或预期用途。例如:
理想的结果是,当预测结果为 *malignant*
或 *inconclusive*
时,立即通知医疗保健提供者。
结论
一个好的数据科学问题将旨在做出决策,而不仅仅是预测。当你思考你面临的每一个问题时,记住这个目标。在上面的例子中,可能会采取一些措施来减少*inconclusive*
预测的数量,从而避免后续几轮测试的需要,或者延迟所需的治疗。最终,你的模型的预测应该让你的利益相关者做出明智的决定——并采取行动!
Photo by Kid Circus on Unsplash
为 GPU 定义用户限制
原文:https://towardsdatascience.com/defining-user-restrictions-for-gpus-6971a658a9ce?source=collection_archive---------28-----------------------
如何在用户之间共享多个 GPU 而不出现 OOM 错误?
我们正在南加州大学使用λ实验室的 4-GPU 工作站。由于多个用户可以同时在服务器上运行作业,处理内存不足(OOM)错误和公平性有点困难。我们可以在网上找到的解决方案如下:
- 英伟达的 GPU 虚拟化软件,可以添加到虚拟化管理程序之上。不过,目前仅支持NVIDIA Turing、Volta、Pascal和MaxwellGPU 架构。
NVIDIA’s GPU virtualization stack. [Source]
2.Slurm 是一个开源的、高度可伸缩的作业调度系统,适用于大型和小型 Linux 集群。它支持 GPU 资源调度。对于大型团队来说似乎是一个非常合适的选择。它还支持每 GPU 内存分配,如果有足够的内存和未充分利用的计算单元,则可以在单个 GPU 上运行多个进程。
Slurm workload manager [Source]
在本文的其余部分,我们将解释我们为在用户之间共享多个 GPU 所做的工作。在多 GPU 工作站中,为每个 GPU 驱动程序文件创建用户组允许我们授予特定用户使用特定 GPU 的权限。现在,只有指定的 GPU 对用户可见。我们解释了在 4 GPU 工作站上创建 GPU 用户限制所需的命令。
步骤 1: 创建组,并将用户添加到组中。我们需要创建 4 个组,因为我们有 4 个 GPU:
# Adding groups
sudo groupadd nvidia0
sudo groupadd nvidia1
sudo groupadd nvidia2
sudo groupadd nvidia3# Adding users to the groups
sudo usermod -a -G nvidia0 olivia
sudo usermod -a -G nvidia1 peter
第二步:在/etc/modprob . d/NVIDIA . conf创建一个配置文件,内容如下:
#!/bin/bash
options nvidia NVreg_DeviceFileUID=0 NVreg_DeviceFileGID=0 NVreg_DeviceFileMode=0777 NVreg_ModifyDeviceFiles=0
这个配置文件将把 4 个 NVIDIA 的驱动参数加载到 Linux 的内核中。NVIDIA 的驱动程序文件的一个问题是,它们在每次会话后都会重新生成,这破坏了我们将要在驱动程序文件上设置的用户访问限制。 NVreg_ModifyDeviceFiles 保证驱动文件一次生成,以后不会更改。其他参数是设置具有 777 访问权限的默认用户和组 id。如果在 /etc/modprob.d/,已经有一个 NVIDIA 配置文件,你可以保留它的备份,并用我们提供的脚本替换它的内容。
第三步:在 /etc/init.d/gpu-restriction 创建一个脚本来加载 NVIDIA 的驱动。
#!/bin/bash
### BEGIN INIT INFO
# Provides: gpu-restriction
# Required-Start: $all
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
# permissions if needed.
### END INIT INFOset -estart() {
/sbin/modprobe --ignore-install nvidia; /sbin/modprobe nvidia_uvm; test -c /dev/nvidia-uvm || mknod -m 777 /dev/nvidia-uvm c $(cat /proc/devices | while read major device; do if [ "$device" == "nvidia-uvm" ]; then echo $major; break; fi ; done) 0 && chown :root /dev/nvidia-uvm; test -c /dev/nvidiactl || mknod -m 777 /dev/nvidiactl c 195 255 && chown :root /dev/nvidiactl; devid=-1; for dev in $(ls -d /sys/bus/pci/devices/*); do vendorid=$(cat $dev/vendor); if [ "$vendorid" == "0x10de" ]; then class=$(cat $dev/class); classid=${class%%00}; if [ "$classid" == "0x0300" -o "$classid" == "0x0302" ]; then devid=$((devid+1)); test -c /dev/nvidia${devid} || mknod -m 660 /dev/nvidia${devid} c 195 ${devid} && chown :nvidia${devid} /dev/nvidia${devid}; fi; fi; done
}stop() {
:
}case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
# code to check status of app comes here
# example: status program_name
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
esacexit 0
然后,输入以下命令,该命令将告诉 Linux 在重新启动后加载脚本:
sudo update-rc.d gpu-restriction defaults
sudo update-rc.d gpu-restriction enable
现在,我们有了一个 Linux 服务,可以通过以下命令启动它:
sudo service gpu-restriction start
重启机器。您现在一切就绪!
检查脚本:
加载 NVIDIA 驱动程序的脚本的核心部分是:
/sbin/modprobe --ignore-install nvidia;
/sbin/modprobe nvidia_uvm;
test -c /dev/nvidia-uvm || mknod -m 777 /dev/nvidia-uvm c $(cat /proc/devices | while read major device; do if [ "$device" == "nvidia-uvm" ]; then echo $major; break; fi ; done) 0 && chown :root /dev/nvidia-uvm; test -c /dev/nvidiactl || mknod -m 777 /dev/nvidiactl c 195 255 && chown :root /dev/nvidiactl; devid=-1; for dev in $(ls -d /sys/bus/pci/devices/*); do vendorid=$(cat $dev/vendor); if [ "$vendorid" == "0x10de" ]; then class=$(cat $dev/class); classid=${class%%00}; if [ "$classid" == "0x0300" -o "$classid" == "0x0302" ]; then devid=$((devid+1)); test -c /dev/nvidia${devid} || mknod -m 660 /dev/nvidia${devid} c 195 ${devid} && chown :nvidia${devid} /dev/nvidia${devid}; fi; fi; done
上面的脚本首先会加载 NVIDIA 模块 nvidia 和 nvidia_uvm。为了设置用户访问限制,在所有 PCI express 设备的循环中,我们发现它们的供应商和类别 id 是否与 NVIDIA GPU 卡匹配。之后,我们创建每个 GPU 的驱动程序文件,然后我们在它们上面设置组和访问限制(660)。驱动文件位于 /dev/nvidia0 ,…, /dev/nvidia3 设置。
我们建议首先在一个可执行文件中运行上述脚本,以测试它是否工作正常。如果您在教程中发现任何问题,请告诉我,我将不胜感激。
自由度和数独
原文:https://towardsdatascience.com/degrees-of-freedom-and-sudoko-f65b921ea636?source=collection_archive---------13-----------------------
对自由度以及自由度如何影响数独的直观解释
Source : Pixabay
许多有抱负的数据科学家学习统计学课程,对自由度的概念感到困惑。有些人把它死记硬背成“n-1”。
但为什么是‘n-1’,有一个直观的原因。
直观的解释
让我们考虑下面的例子。
想象一下,让你选择 5 个总和为 100 的数字。为了简单起见,你说 20,20,20,20。在你说出第五个数字之前,我告诉你,你的第五个数字也是 20。这是因为你选择的前 4 个数字加起来是 80,而条件是选择 5 个数字加起来是 100。
所以 100 -80 = 20。第五个数字是 20。
第五个数字在某种意义上选择了自己由于指定的条件。
你可以看到你有 4 个自由度。只需要前四个数字。
这也直观地解释了 n-1。这里 n 是 5,n-1 =4。
你因为“5 个数之和应为 100”的条件而失去了一个自由度
或者
换句话说,你有 4 个自由度。
数独连接
数独是我们大多数人都非常熟悉的游戏。维基百科给出了如下定义
数独最初被称为数字位置)是一个基于逻辑的组合数字位置难题。目标是用数字填充一个 9×9 的网格,以便每一列、每一行以及组成网格的九个 3×3 子网格(也称为“框”、“块”或“区域”)中的每一个都包含从 1 到 9 的所有数字。难题设置器提供了一个部分完成的网格,对于一个适定的难题,它只有一个解。
我正在解一个数独游戏,只是为了消磨时间。我意识到数独和自由度之间有某种联系。
我不确定网络版的游戏是否考虑了自由度来给游戏评分“容易”、“中等”、“专家”。但是也许这个游戏可以这样评价!!
让我用一个取自在线数独谜题的例子来说明。
在线数独游戏的“简单”、“中等”、“困难”和“邪恶”等级如下所示。
请注意,数独游戏中有 81 个单元格。
Source : websudoku
更多的自由度=更难的数独
在每一层,我们都注意到一些有趣的事情。随着等级从易到恶,填充的单元格数量不断变小!!
基本上,当你有更多的单元格要填充(空白单元格)时,关卡会变得越来越难。你的自由度越多,解谜就越难!!至少在这种情况下,拥有很多自由并不理想。
这是一篇将自由度的统计概念与数独这样的日常游戏联系起来的小文章。
我希望在不久的将来写一个代码来描述上述内容。
你可以联系我
推特
通过分析快速产生业务影响
原文:https://towardsdatascience.com/delivering-business-impact-with-analytics-quickly-8de0e2b6bf61?source=collection_archive---------34-----------------------
保险分析案例研究
第一次打开数据集既有挑战性又令人兴奋。将原始数据转化为见解是我最喜欢分析的一部分,但它也可能是压倒性的。你应该从哪里开始?您应该运行哪些分析?您如何确保您所做的事情具有切实的业务影响?
强有力的初步分析不一定会给你答案,但它会告诉你接下来应该问哪些问题。
数据集处理一组财产和意外保险代理机构的代理绩效。这些数据包括 2005 年至 2015 年期间的机构列表、按产品划分的保费以及按产品划分的损失。
为了产生业务影响,理解与业务最相关的数据和指标的上下文非常重要。对于保险数据,有两个关键考虑因素将有助于指导我们从哪里开始分析。
首先,保险业专注于降低风险——他们收取高于支出的保费的能力是他们继续经营下去的原因。因此,感兴趣的度量是损失率,其近似计算为总损失除以承保的保费。了解对损失率有正面和负面影响的因素,可以为产品策略和定价等领域提供信息。
第二,大多数保险是通过经纪人或代理人销售的,而不是直接从保险公司购买。那么,除了产品之外,了解机构的构成和表现是另一种可以推动快速影响的分析。在优秀员工中寻找可以推广到更广泛的机构群体的特质,可以提高整体效率。
此外,确定为保险公司提供最佳价值的代理类型可以为未来的合作战略提供信息。所有业务都受到时间和资源的限制。数据可以确保可用的时间和资源集中在正确的地方。
考虑到上述情况,看到这些数据没有关于业务或其目标的额外背景,我有 3 个关键问题想要回答:
- 与更高(或更低)损失率相关的变量是什么?
- 代理商如何根据价值进行细分?
- 相对于他们的潜力,这些机构的表现如何?
这三个问题的综合答案告诉我们应该关注哪些产品,哪些机构提供的价值最大(和最小),以及哪些机构应该继续关注。
首先,随着时间的推移,损失率在最初几年稳步增长,然后趋于稳定。
对我来说,一个有趣的早期发现是,如果你只去除数据集中前 1%的损失,损失率会下降 30%以上。剔除前 5%的亏损,亏损率下降了近 70%,剔除前 10%的亏损,亏损率仅为 2%。换句话说,前 10%的损失约占总损失比率的 96%。
对我来说,这表明损失集中在一小部分产品或代理上。了解哪些产品和机构造成了亏损,将是未来制定更有利可图的政策的关键。
从产品的角度来看,我们可以看到,房屋保险应该是进一步调查的第一个领域。按净保费计算,它是第二大类别,也是赔付率最高的类别之一。我的直觉是,这是一个竞争更加激烈的市场,抑制了任何可以更好地对风险进行定价的定价能力,但这将是一个需要更多研究的领域。
将数据汇总到其产品线,并去除前 1%的异常值,财产保险产品的整体损失率比商业保险高出约 50%,这可能是由房主造成的。
初步探索性分析的要点和含义是:
- 少数亏损驱动多数亏损比率。深入了解遭受这些损失的保单的产品、定价和一般承保,以了解它们的共同点,可能会产生有价值的见解。
- 房主保险是一个需要进一步调查的明确领域,以了解尽管净保费很高(这应该会分散风险),但其损失率却较高的原因。
- 财产保险比商业保险风险更大。随着时间的推移,在商业上取得适当的平衡可能是有益的。
现在我们对绩效和绩效的潜在驱动因素有了更好的理解,我们将分析机构本身。
聚类是一种寻求在数据中找到自然分组的技术。它在创建一个更加微妙的故事时非常有用,因为数据集中的每个人并不都有相似的行为,聚类可以帮助识别数据中有相似行为的组。
在测试了不同的集群后,我选择了五个作为最佳数量,下面的可视化显示了集群在数据集内感兴趣的关键指标上的差异:
Number of agencies by Cluster: 1 = 323; 2 = 335; 3 = 434; 4 = 316; 5 = 215
根据这一分析,我将集群分类如下:
- 集群 1 :稳定,规模适中,表现良好
- 集群 2 :中等增长,大,表现良好
- 群组 3 :下降、非常小、表现显著不佳
- 集群 4 :增长型、中型、高性能
- 集群 5 :下降、规模小、中度表现不佳
从商业角度来看,我从上面的图表和分析中有几点收获。
首先,尽管数据集中有大约 1,600 家机构,但其中只有大约 60%对业务有影响。关系的质量比伙伴的数量更重要。
其次,尽管第 3 组的损失率非常惊人,但该细分市场的平均规模及其承保的总保费意味着它实际上不会对业绩产生过大影响。我的建议是考虑终止与大多数机构的合作关系;他们提供的价值(或缺乏价值)不太可能抵得上他们创造的收入,如果大多数人不再是代理合作伙伴,业务将不会受到什么影响。
我要说的第三点是,我们应该关注第四组中的机构,以理解为什么它们的规模在这段时间内翻了一番。目前的数据集有其局限性,但可能的解释是,这些机构正在增加他们的代理人数量,而其他人没有,或者他们正在服务于经济衰退后增长更快的特定行业(或当地社区)。我排除的一个解释是,有一组特定的产品,它们提供的频率高于大多数其他细分市场;数据中没有证据表明这是真的。
最后,我想了解为什么集群 1 和集群 2 具有相似的平均代理人数量、代理机构数量和损失率,但集群 2 提供的保费是集群 1 的 2 倍。
Median Products by Cluster
对于聚类 1 和聚类 2,我们发现,与聚类 1 相比,聚类 2 中的典型代理多销售了 4 种产品。在这些产品中,有一种产品更有可能被集群 2 售出,这种产品是平均保费收入最高的产品之一。进一步的定性信息(例如,与每个集群中的机构通话以更好地了解他们的业务)将是一个有用的起点。
最后的分析将试图衡量每个机构的效率,因为它与他们的保费收入有关。该分析量化了一个机构在给定可用资源的情况下相对于其同行的表现。在这里,我们认为资源是一个机构中生产者(代理商)的数量和提供的独特产品的总数;2014 年写的保费收入就是产出。
举例来说,让我们假设只有两个代理商,他们都有 5 个生产商和 10 个销售产品。第一家代理公司有 100 万美元的书面保费,第二家有 50 万美元。我们会认为代理 1 以 100%的效率运行,代理 2 以 50%的效率运行,因为给定相同的投入,代理 2 只产生 50%的产出。
Blue is for the full cluster, Orange is for only those that generated revenue in 2014. Cluster 2’s Blue and Orange dots overlap.
虽然没有一个集群一定表现高效,但从方向上看,结果如何映射到之前看到的收入表现并不令人惊讶。正在下降的集群 3 和集群 5 的效率最低。
集群 2 的运行效率是集群 1 的两倍多,这有助于解释为什么他们的收入显著更高。实际上,在其他条件相同的情况下,他们的代理比集群 1 的代理在销售方面做得更好,并且他们通常提供更多的产品,如前面的分析所证明的。
此分析的下一步是:
- 找出高效机构的共同特征——它们做的有什么不同?他们卖的是什么产品?他们是如何培训他们的制片人/代理人的?
- 瞄准表现不佳、潜力大的机构。根据代理商数量或过去的业绩,哪些代理商最有增长潜力?哪些公司已经产生了丰厚的收入(因此是很好的合作伙伴),并有扩大规模的潜力?
结论
在大约 1 天的工作时间内,我们可以快速了解导致更好和更差结果的因素(通过损失率衡量)、推动大部分收入和对业务最有价值的机构,以及当前基础内提高效率的跑道。
我们还确定了数据中需要进一步研究的领域。按保费排名第二大类的屋主险,为什么赔付率这么高?为什么群组 2 中的机构比群组 1 中的机构表现突出?为什么集群 4 比其他细分市场增长更快?高效率的机构做了什么导致了超出预期的表现?这可以扩展到其他机构吗?
接下来,可以与更广泛的团队讨论这些发现的意义,以及优先关注哪些研究领域将为组织带来最大价值。
交付数据科学而不交付软件
原文:https://towardsdatascience.com/delivering-data-science-without-delivering-software-2c43fcc140ad?source=collection_archive---------22-----------------------
Data Science Tools (Photo: Author)
你总是需要交付完整的软件吗?
“R vs Python”或“软件技能 vs 统计技能”这样的争论不时出现在数据科学领域。这些争论有时似乎有一个隐藏的假设,即对于一个数据科学家来说,唯一可能的交付品是一个以模型为中心的功能完整的软件。也就是说,人们经常使用的论点只有在完成的软件是目标时才有意义。
如果不是呢?如果有其他方法来传递数据科学的价值会怎样?
最显而易见的方法是写一份报告来传递一个结果。这个建议可能看起来微不足道,但有时,随着对生成功能预测模型的关注,简单地写下你从数据中学到的东西的想法似乎会丢失。
然而,在许多情况下,真正的价值可能在于更好地了解情况。例如,虽然能够根据已知因素预测一段时间内的销售额是有用的,但是为了知道订购多少库存,能够增加销售额也是可取的。因此,在正确的情况下,你的识别杠杆的模型可能比成熟的预测模型更有用。
如果你从一个黑盒模型开始,对输入变量如何影响最终结果的了解有限,那么识别杠杆会很困难。然而,现在有一些方法可以追溯性地发现模型中的重要因素——有像 LIME 或 SHAP 这样的工具可以让你做到这一点。
有时,有用的不一定是输入变量和目标之间的直接关系,而是创建特征过程中的副产品。在发现用户丢失数据的原因的基础上,追踪可疑的丢失数据可能会让您对用户的问题有所顿悟。
在每一种情况下,你更有可能是在组织中已经存在的知识的基础上浮出水面并不断积累。根据泰曼定律,“任何看起来不同或有趣的信息通常都是错误的”。这意味着你不太可能发现真正原创的东西——然而,在大多数组织中,大多数知识都是非结构化的,以无定形的模糊概念存储在人们的头脑中。即使知识不模糊,也很少写下来。
数据科学可以通过建立一个有效的知识库来为组织提供服务,该知识库包含来自根据可用数据测试组织信念中的主题专家的书面发现。这可能比数据科学家能够提供的几乎任何东西都更有价值。
通过数据分析构建知识通常需要对代码有简单的理解——通过 R 或 Python 运行回归的技巧更多地在于选择输入和理解结果。将增加组织的知识储备的目标放在你的脑海中,避免被编码特定答案的最佳方式的辅助思想分散注意力。
罗伯特·德格拉夫的书《管理你的数据科学项目》》已经通过出版社出版。
在 Twitter 上关注罗伯特
兑现人工智能的承诺
原文:https://towardsdatascience.com/delivering-on-the-promise-of-artificial-intelligence-f6424a75d61c?source=collection_archive---------22-----------------------
Photo by Alex Knight on Unsplash
你不断听到关于人工智能(AI)的说法。Nvidia 的 CEO 说“AI 要吃掉软件了。”马克·库班惊呼,“人工智能、深度学习、机器学习——无论你在做什么,如果你不懂,就去学吧。因为否则,你会在三年内变成一只恐龙。”
然而,与此同时,你会读到关于公司未能利用人工智能执行的文章。有些人甚至声称85%的努力都会失败。
作为创业公司的一部分,你没有资本也没有时间进行人工智能的潜在昂贵的失败实验,但你也不能落后。那么从哪里开始?
我经常和初创公司的创始人交谈,也经常被问到这个问题。我想提出 3 个步骤来帮助你最大化在人工智能上成功执行的机会。你可能会惊讶于它们都不需要最先进的人工智能。
总是从数据开始
数据是 AI 的命脉。想想你听到的所有关于人工智能的公司:谷歌、脸书、亚马逊、网飞。他们都有大量数据,并且每天都在增长。他们不仅拥有大量数据,还拥有大量专有数据。没有其他人拥有亚马逊的所有销售数据,没有其他公司能够获得所有网飞展会背后的消费者数据。
大量的专有数据是一个巨大的好处。
幸运的是,几乎每个公司都会产生某种类型的专有数据。如果你从事电子商务,你有哪些消费者在购买什么产品的数据。如果你是一家 SaaS 公司,你有客户如何与你的产品互动的数据。
你的人工智能之旅的第一步应该是坐下来回答以下问题:
- 我的公司产生哪些数据资产?
- 它们的专有程度如何?
- 我现在有多少数据?
- 我的数据增长速度有多快?
- 数据存储在哪里?如何访问它们?
如果在此分析之后,您发现您有大量的专有数据在快速增长,并且可以合理地访问,那么您已经为下一步做好了准备。
如果你在识别专有数据方面有困难,那么试着想想如何改变这种情况。你没有为你的网站利用谷歌分析吗?你在广告中使用脸书像素吗?想办法让你的公司为你生成数据。
如果你的公司里没有人知道这些数据最终在哪里或者如何提取,你需要首先回答这些问题。也许做一些谷歌搜索,找出如何提取谷歌分析数据。或者雇一个自由工程师来帮你。
Photo by NeONBRAND on Unsplash
确定影响
既然你已经有了一些可以利用的数据资产,你需要确定你要用人工智能解决的第一个问题。在这一步骤中,我的首要建议是
忽略人工智能的宣传,专注于从数据中创造价值
对于这一步,我会将 AI 定义为任何使用数据以可扩展方式交付价值的机器辅助过程。这可能是对人工智能的一个过于宽泛的定义,但它应该允许你不在乎你正在做的事情是否是“最先进的”,而是专注于从你的数据中创造价值。维基百科将人工智能定义为“机器展示的智能”我相信利用技术(机器)使用数据来创造影响(智能)肯定属于这个定义。可伸缩性至关重要。如果你不能用技术扩展你的解决方案,那就不算数。
以下是选择要解决的问题时要考虑的一些事项:
- 如果我能解决这个问题,会有多大影响?
- 这个问题看起来有多难?
- 我们目前有没有人可以使用数据和技术实施解决方案?
- 给定一些数据,人类可以解决这个问题,这看起来合理吗?
我会回答你能想到的 3-5 个最有影响力的项目的问题。你在寻找一个有影响力的问题,它已经有数据,并且看起来不太有挑战性。优先解决简单的问题,尝试并确保快速取得第一次胜利。如果你认为你已经有一个员工可以尝试解决这个问题,这是一个巨大的奖励。如果没有,试着找一个热衷于解决问题并且不怕学习新技能的员工。互联网上有大量的资源可以用来学习数据分析和人工智能。否则,可以在 Upwork 等平台上雇佣一名自由职业者。只是要确保向他或她提供清晰明了、易于访问的描述良好的数据。这通常是一个更好的第一步,而不是一个新员工,以防你发现自己没有想象中准备好。
拥有科学的心态
用数据解决问题真的是一个科学的过程。它往往包括发展一个假设,测试这个假设,然后学习一些东西。并重复。
不要期望你的第一个假设会成功
通过上一步,您可能已经提出了这样一个假设,即您可以使用销售数据来识别适合追加销售的客户。你已经看过一些数据,并且非常有信心看到产品购买之间的相关性。因此,您重新安排员工来解决问题,实施您的解决方案,您的追加销售率不会改变。好吧,我想你已经失败了——是时候继续前进了。
不。你测试了一个假设,而那个假设失败了。现在你需要深入研究,了解原因,开发一个新的假设,并测试它。也许你看到的相关性不是因果关系;也许你的代码中有一个 bug 也许你的测试需要运行更长时间。你需要提出一个假设来解释为什么它失败了。这将指导你的下一步行动。
这个测试假设、学习和重复的过程需要时间。这就是为什么选择一个看起来能迅速见效的问题更好的主要原因。这将有望让你在初次尝到成功的滋味之前不必经历太多的失败。
Photo by Clark Tibbs on Unsplash
现在——去做吧
这就是了。花时间想想你有什么数据资产,分析潜在的影响领域,像科学家一样思考。如果你从这三个步骤开始,你将处于一个坚实的位置,开始用数据和人工智能为你的初创公司提供价值。这些步骤也不需要你有很强的背景或对人工智能的理解——你只需要战略性地思考你的问题和你的数据。一旦你有了这样的理解,你就可以让别人(或者你自己)来执行人工智能。只要确保你能像科学家一样思考就行了!
本文可在这里找到。
使用亚马逊 Kinesis Data Firehose 向亚马逊 S3 提供实时流数据
原文:https://towardsdatascience.com/delivering-real-time-streaming-data-to-amazon-s3-using-amazon-kinesis-data-firehose-2cda5c4d1efe?source=collection_archive---------1-----------------------
在这篇文章中,让我们探索什么是流数据,以及如何使用亚马逊 Kinesis Firehose 服务来制作一个应用程序,将这些流数据存储到亚马逊 S3。作为实践体验,我们将使用 AWS 管理控制台接收模拟股票报价机数据,我们将从中创建一个交付流并保存到 S3。在实现之前,让我们先看看什么是流数据,什么是亚马逊 Kinesis。
流数据是由许多数据源连续生成的数据。这些可以同时以小尺寸发送。这些流数据可以通过 Amazon Kinesis、Apache Kafka、Apache Spark 和许多其他框架等工具收集。流式数据的一些例子是
- 应用程序生成的日志文件
- 来自 web 应用程序或移动应用程序的客户交互数据
- 金融股票市场数据
- IOT 设备数据(传感器、性能监视器等..)
亚马逊 Kinesis 是亚马逊提供的一项服务,使其易于收集。处理和分析实时流数据。目前,亚马逊 Kinesis 提供了四种类型的 Kinesis 流数据平台。
- Kinesis 数据流 —用于实时收集和处理大量数据记录
- kine sis Data fire hose——用于向亚马逊 S3、Redshift 等目的地传送实时流数据..
- kines 数据分析 —用于使用标准 SQL 处理和分析流数据
- Kinesis 视频流——用于全面管理从设备传输实时视频的服务
亚马逊 Kinesis 数据消防软管
亚马逊 Kinesis data firehose 是亚马逊提供的一项完全托管的服务,用于向亚马逊服务提供的目的地交付实时流数据。目前,亚马逊 Kinesis Firehose 支持四类亚马逊服务作为目的地。
- 亚马逊 S3——一个易于使用的对象存储
- 亚马逊红移—Pb 级数据仓库
- 亚马逊弹性搜索服务——开源搜索和分析引擎
- Splunk —用于分析机器生成数据的智能运营工具
在这篇文章中,我们将看看如何使用亚马逊 Kinesis Firehose 将流数据保存到亚马逊简单存储(S3)。在开始实现我们的应用程序之前,让我们先来看看 Amazon Kinesis Firehose 的关键概念。
Kinesis 数据消防水带交付流—kine sis 数据消防水带的底层实体。
数据生产者 —将数据记录发送到 Kinesis 数据消防软管的实体。(例如:发送日志文件的 web 或移动应用程序)
记录——我们的数据生成器发送给 Kinesis 消防水带交付流的数据。
缓冲区大小和缓冲区间隔 —这些配置决定了在将它们传送到目的地之前需要多少缓冲。
现在我们已经学习了 Kinesis Firehose 的关键概念,让我们进入流程的实现部分。下图显示了我们的交付流的基本架构。数据生产者将记录发送到我们的流中,我们将使用 Lambda 函数对其进行转换。之后,转换后的记录将通过 Kinesis Firehose 保存到 S3。我们还将在转换之前将流数据备份到 S3 存储桶。
对于这篇文章,我们将创建一个交付流,其中的记录将是股票行情数据。我们将使用 AWS 管理控制台接收模拟股票行情数据,并将 S3 作为我们的目的地。模拟数据将具有以下格式。
{"TICKER_SYMBOL":"JIB","SECTOR":"AUTOMOBILE","CHANGE":-0.15,"PRICE":44.89}
创建亚马逊 Kinesis 数据消防水带交付流
可以通过控制台或 AWS SDK 创建 Kinesis 消防水带传输流。对于我们的博客文章,我们将使用 ole 来创建交付流。在交付流创建之后,我们可以随时更新和修改它。
首先转到分析类别下的 Kinesis 服务。如果你以前从未使用过 Kinesis,你会看到下面的欢迎页面。
点击开始创建我们的交付流。在下一页中,您将看到四种类型的向导,用于为四种类型的数据平台服务创建 Kinesis 流。在这篇文章中,我们使用的是通过 Kinesis Firehose 传送流传送流数据,这是第二种选择。
提供传送流名称的名称。在来源下选择直接上传或其他来源。该选项将创建生产者应用程序直接写入的交付流。如果选择了 Kinesis 流,那么传送流将使用 Kinesis 数据流作为数据源。为简单起见,我们选择了第一个选项。
转换记录
在下一页中,我们将需要配置数据转换配置。Kinesis Firehose 可以调用 Lambda 函数来转换传入的源数据,并将转换后的数据传送到目的地。Lambda 函数的蓝图由 AWS 提供。但是在创建 Lambda 函数之前,让我们看看在转换数据之前我们需要知道的需求。
来自 lambda 函数的所有转换记录都应该包含下面描述的参数。
- recordid —调用过程中从 Kinesis Firehose 传递到 Lambda 的记录 id。转换后的记录应该包含相同的 id。
- 结果 —已被 Lambda 函数转换的数据的状态。
- 数据 —转换后的数据
有几个为我们提供的 Lambda 蓝图,我们可以使用它们来创建用于数据转换的 Lambda 函数。我们将使用这些蓝图之一来创建我们的 Lambda 函数。
在过程记录页面中的** s 转换源记录,AWS Lambda** 选择启用。这将提示您选择一个 Lambda 函数。选择新建。在这里,我们得到了数据转换的 Lambda 蓝图。选择通用水龙带加工作为我们的蓝图。
这将把我们带到 Lambda 函数创建页面。为我们的函数提供一个名称。然后,我们需要提供一个 IAM 角色,它能够访问我们的消防软管交付流,并被允许调用腐败批次操作。
在查看策略文档中,选择编辑并将以下内容添加到策略中。
{
"Effect": "Allow",
"Action": [
"firehose:PutRecordBatch"
],
"Resource": [
"arn:aws:firehose:your-region:your-aws-account-id:deliverystream/your-stream-name"
]
}
确保在保存策略之前编辑您的地区、您的 aws 帐户 id、您的流名称。
创建 IAM 角色后,我们将被重定向回 Lambda 函数创建页面。在此选择创建的角色。之后,我们需要编写自己的 Lambda 函数代码来转换我们的数据记录。Lambda blueprint 已经用我们需要遵循的预定义规则填充了代码。
如上所述,我们的流数据将具有以下格式。
{"TICKER_SYMBOL":"JIB","SECTOR":"AUTOMOBILE","CHANGE":-0.15,"PRICE":44.89}
为了这篇文章的简单,我们将对这个记录做一个简单的转换。在流式传输记录时,我们将忽略“更改”属性。因此,我们转换后的记录将只有属性 ticker_symbol 、 sector 和 price 属性。将以下代码粘贴到 Lambda 函数中来实现这一点。
'use strict';
console.log('Loading function');exports.handler = (event, context, callback) => {
/* Process the list of records and transform them */
const output = event.records.map((record) => {
console.log(record.recordId);
const payload =JSON.parse((Buffer.from(record.data, 'base64').toString())) const resultPayLoad = {
ticker_symbol : payload.ticker_symbol,
sector : payload.sector,
price : payload.price,
};
return{
recordId: record.recordId,
result: 'Ok',
data: (Buffer.from(JSON.stringify(resultPayLoad))).toString('base64'),
};
});
console.log(`Processing completed. Successful records ${output.length}.`);
callback(null, { records: output });
};
创建 Lambda 函数后,返回到交付流创建页面。在这里选择我们刚刚创建的新 Lambda 函数。
目的地
在下一页中,我们将被提示选择目的地。在这篇文章中,我们将把我们的记录保存到 S3。
在 S3 目的地选择 S3 桶,我们将存储我们的记录。如果您尚未创建 S3 存储桶,您可以选择创建新的。如果您想在 Lambda 完成转换过程之前备份记录,那么您也可以选择一个备份存储桶。
选择目的地后,我们将被重定向到配置页面。在这里,我们可以首先选择缓冲区大小和缓冲区间隔、S3 压缩和加密以及错误日志。除了 IAM 角色之外,保留所有配置设置的默认值。我们需要为 Kinesis 提供一个 IAM 角色来访问我们的 S3 桶。如果您已经有一个 IAM 角色,您可以在不创建新角色的情况下选择它。
查看我们的配置后,点击创建交付流创建我们的亚马逊 Kinesis 消防软管交付流。新的 Kinesis 消防水带交付流将在创建状态中花费一些时间,然后才可供我们使用。在交付流状态变为活动后,我们可以开始从生产者向其发送数据。
现在我们已经创建了交付流。现在让我们测试我们创建的交付流。点击交付流并打开带有演示数据的测试节点。
点击开始发送演示数据。这将开始向我们的交付流发送记录。发送演示数据后,点击停止发送演示数据以避免进一步充电。请注意,根据您的存储桶的缓冲配置,新对象可能需要几分钟才会出现在您的存储桶中。为了确认我们的流数据保存在 S3,我们可以去目的地 S3 桶和验证。验证流数据是否也没有更改属性。转换前的所有流记录都可以在备份 S3 存储桶中找到。
我们现在已经使用亚马逊 Kinesis Firehose 为 S3 成功创建了一个交付流,并成功进行了测试。你可以更深入地了解 Kinesis Firehose,它的目的地可能是亚马逊红移,也可能是 Kinesis 数据流的生产商。跟随这个文档深入了解亚马逊 Kinesis Firehose。
交货日期估计
原文:https://towardsdatascience.com/delivery-date-estimation-5aff1a0ff8dc?source=collection_archive---------10-----------------------
在处理与时间相关且动态变化的环境时,您可能面临的技术挑战。
在戴尔,我们尽最大努力为客户提供卓越的体验。这也适用于满足我们的产品交付期限。在复杂的供应链中,向客户提供准确的预计交货日期并不容易。大型组织中的供应链团队可能很大,而且高度矩阵化,但是他们有一个共同的目标,那就是快速、准时地向客户提供产品。在下订单时,我们会利用我们所掌握的最佳信息为客户提供一个预计的交货日期。它需要考虑几个因素,如库存水平、地区、假期、预期的未来需求等。这些因素以及大量的历史数据使得这个问题成为应用机器学习的完美用例。
在本文中,我们将探索一些微妙的技术学习,以及我们在尝试将算法智能和机器学习引入这一重要挑战时面临的一些挑战。我们还将举例说明解决这些问题的一些方法。
我们开始吧。
准时订单与竞争力
估计交货日期有点棘手,需要保持一定的平衡,以确保订单不会延迟,同时尽可能在交货时间内报价。当客户下订单并得到承诺的交货日期时,我们必须履行订单并按时交货:在我们提供的预计日期或之前(在某些情况下,在特定的日期范围内)。应对这一挑战的简单方法是为客户提供较长的交付时间。例如,如果我们认为产品可以在一周内交付,我们可以提供一个月的交付日期,以最小化迟到的风险。然而,如果客户能在更短的时间内从竞争对手那里得到类似的产品,我们可能会失去这笔生意。
在准确性和竞争力之间有一个不断的权衡,当然,我们的目标是优化这两者。
绝大多数机器学习算法都是用对称的代价函数优化来构造的。在这种情况下,任何一个方向的误差成本都是一样的——晚 X 天或早 X 天的误差是一样的。在我们的例子中,有一个被认为代价更高的错误:我们宁愿早交货也不愿晚交货。我们通过创建一个定制的不对称成本函数,将这种业务逻辑编码到机器学习模型中,该函数对延迟订单的惩罚比对早期订单的惩罚更重。
下图显示了常规成本函数和不对称成本函数之间的比较。
Comparison between regular cost function and customize asymmetric cost function
我们希望将延迟订单的百分比保持在非常低的水平,同时在任何优化问题中,我们也希望尽可能地最小化成本函数,以实现零损失。通过这种方式,我们将能够为客户提供准确且有竞争力的交货时间。
选择目标变量
最直观的目标变量是订单周期时间(从订单输入到最终交付的总天数)。但是,要准确预测这个时间,我们应该考虑两个方面:
- 计量单位:产品是在工作日生产和交付的,因此我们的目标变量的计算应该只包括工作日。这样,我们消除了周末和节假日对交货日期估计的影响。
- 周期时间定义:总交付时间可以分为两个主要部分:构建/准备时间(订单输入和订单发货之间的时间)和发货时间(从订单发货到客户收到订单的时间)。因为运输时间通常由更一般的因素(运输提供商、天气、运输类型等)控制。建议使用一个主模型来预测订单的构建/准备时间,并使用一个额外的子模型来预测订单离开工厂后的运输时间(该模型将取决于与该特定问题更相关的其他因素)。
Timeline emphasizing the possible target variables
考虑到以上几个方面,我们可以确定没有外部效应被引入到模型中。这样,模型应该能够仅根据订单的特征来预测准备时间,而不需要外部数据源,如假期或运输选项。
基于时间的训练\测试分割
训练和评估机器学习模型通常需要一个训练集和一个测试集(以及一个交叉验证集来优化模型参数)。在大多数情况下,通过将 20%的数据作为模型不可见的测试数据,并将其余数据用于训练,来随机进行训练和测试拆分。
Random 80/20% split
当处理与时间相关且动态变化的环境时,例如大型公司供应链,其中环境的特征随着时间而变化,最好使用基于时间的分割,甚至应用基于时间的交叉验证来提供统计上稳健的模型评估。为此,我们使用一种取自时间序列领域的方法,即时间序列交叉验证,它形成了一种“滑动窗口”训练方法。
Time-based split
所建议的方法还可以帮助我们模拟实时生产环境,在这种环境中,机器学习模型根据到目前为止所有可用的订单进行训练,并用于预测未来订单的交付时间。
总之,我们分享了在使用机器学习估计订单交付日期时遇到的主要挑战。我们的目标是提高准确性并按时交付产品,同时保持竞争力的交付时间。为此,我们使用非对称成本函数来预测选定的目标变量,并通过使用独特的训练\测试分割方法来最佳模拟真实世界的行为。
特别感谢:
Kyle West 和 Oshry Ben-Harush,感谢他们在这个项目上的合作,感谢他们校对、审阅这篇文章并给出了令人敬畏的技术反馈。
推荐阅读
如果你想了解更多关于非对称成本函数的知识,我推荐阅读 Prince 的梯度提升的自定义损失函数,它在这个项目的工作中帮助了我。
需求曲线和人工智能的危险
原文:https://towardsdatascience.com/demand-curves-and-the-dangers-of-ai-65233bd77da8?source=collection_archive---------16-----------------------
人工智能如何利用零售店的监控摄像头揭示客户的支付意愿。
如果价格从 20 美元降到 1 美元,你会买多少件新 t 恤?管理经济学家一直在处理这个问题,它使用个人需求曲线(IDC)为消费者理论奠定了基础。IDC 显示了消费者在给定价格下将购买的商品数量。它可以用来估计每个人在不同价格水平下会购买多少单位的产品。目标是通过设定最优价格来实现利润最大化。也许 20 美元太高,1 美元太低。每个消费者对这些价格会有不同的反应,因为每个人有不同的口味和偏好。
Demand Curve
但是,通过总结个人曲线,公司可以建立市场需求曲线(MDC ),它代表了所有个人在不同价格下的需求量。MDC 与 IDC 具有相同的外观,但适用于该市场上的所有个人。MDC 更相关,因为该公司不能歧视价格,例如,对低收入个人以 5 美元出售 t 恤,而对高收入个人以 90 美元出售。相反,公司需要设定价格,而不管谁是买家。所以,MDC 再次帮助经理们找到公司利润最大化的最优价格。
鉴于每个消费者有不同的偏好,构建个人需求曲线在历史上可能是困难的。但随着人工智能的进步,零售公司可以通过监控摄像头跟踪消费者行为来实现构建个人需求曲线的算法。据报道,拉尔夫·劳伦、克罗格、沃尔格林和其他零售商店正在使用摄像机追踪消费者行为。人工智能可以跟踪消费者进入商店的那一刻,直到收银台付款。商店还可以使用面部识别,识别特定顾客在店内查看不同产品时对不同价格的反应。如果顾客回到商店,他的脸可以用来检索他的个人需求曲线,该曲线先前存储在他们的数据库中,然后改变消费者倾向于购买的产品的一些价格。它还可以通过检测面部表情和对标签上价格的反应来确定顾客购买产品的可能性。因此,商店可以建立概率 IDC,而不是建立传统的个人需求曲线。概率模型可以使用来自面部表情和先前购买的历史数据。
企业在改变产品价格时必须有一定的灵活性。但是在过去的几年里,一些企业越来越多地采用一种有争议的替代方案,叫做动态价格(或者更聪明的定价)。例如,酒店和运输等行业严重依赖动态价格,因为需求可能会因音乐会或商业峰会等大型活动而发生巨大变化。公司通过选择一个或多个基准和潜在变量来计算自己的价格,从而采用动态价格。这些变量包括竞争对手的价格(例如,比最低电子商务网站价格低 5%)、一天中的时间(例如,餐馆可能有午餐和晚餐菜单)、高峰需求(例如,雨天的优步)、加价(例如,油价和汽油)、一周中的天数(周末的电影院)。动态价格很不受消费者欢迎,原因有几个。该战略不断提醒消费者,公司的目标是从他们身上获取尽可能多的价值。这也可以被视为一种不公平的优势,因为消费者并不总是拥有相同的资源来得出他们自己对公平价格的评估。最后,消费者倾向于将价格与价值而不是需求联系起来,这意味着消费者从产品的益处而不是稀缺性来看待产品。
《罗宾逊-帕特曼法案》等法律禁止价格歧视,但价格歧视的表现条件非常复杂。现代经济理论将价格歧视分为三个不同层次:完全歧视、直接分割和间接分割。【1】完全歧视是价格基于每个个体的支付意愿变化的条件——个体需求曲线。当一些消费者变量被用来设定价格时,如性别和性别,直接细分就存在了。最后,间接细分通过一个代理变量发生,如包装尺寸和数量。
价格歧视和动态价格在用于直接细分和完全歧视时是一个危险的领域。使用监控摄像头跟踪消费者的行为超出了公平的做法,应该受到法律的限制。国会应该关注这个问题,并提出新的立法来防止这种做法。商店前面的标志显示商店监视其顾客可能是一个可行的选择,但这还不够。如果消费者看到了明显的好处,他们应该能够选择加入。大多数商店拒绝透露,甚至拒绝回应是否有此类行为。随着人工智能领域的进步,消费者、企业和政府机构应该意识到滥用,并防止不断监视消费者以构建他们的个人需求曲线。
【1】巴新,伊万。管理经济学,第四版。Routledge,2012 年。
使用 TensorFlow 2 和 Keras 在 Python 中使用 LSTMs 进行需求预测
原文:https://towardsdatascience.com/demand-prediction-with-lstms-using-tensorflow-2-and-keras-in-python-1d1076fc89a0?source=collection_archive---------5-----------------------
了解如何通过深度学习从多元时间序列数据中预测需求
TL;DR 学习如何使用多元时间序列数据预测需求。在 Keras 和 TensorFlow 2 中建立一个双向 LSTM 神经网络,并使用它进行预测。
时间序列模型最常见的应用之一是预测未来值。股票市场将会如何变化?明天 1 个比特币值多少钱?下个月你打算卖多少咖啡?
没听说过 LSTMs 和时间序列?阅读前一部分来学习基础知识。
本指南将向您展示如何使用多元(许多特征)时间序列数据来预测未来需求。您将学习如何预处理和缩放数据。你要建立一个双向 LSTM 神经网络来进行预测。
在浏览器中运行完整的笔记本
GitHub 上的完整项目
数据
我们的数据伦敦自行车共享数据集托管在 Kaggle 上。由赫里斯托·马夫罗季耶夫提供。谢谢!
自行车共享系统、公共自行车计划或公共自行车共享(PBS)计划是一项服务,在该服务中,个人可以付费或免费短期共享自行车。——维基百科
我们的目标是根据伦敦自行车份额的历史数据预测未来自行车份额的数量。让我们下载数据:
!gdown --id 1nPw071R3tZi4zqVcmXA6kXVTe43Ex6K3 --output london_bike_sharing.csv
并将其加载到熊猫数据框中:
Pandas 足够聪明,可以将时间戳字符串解析为 DateTime 对象。我们有什么?我们有 2 年的自行车共享数据,定期记录(1 小时)。就行数而言:
(17414, 9)
那也许可以。我们有什么特点?
- 时间戳 —用于分组数据的时间戳字段
- 计数 —一辆新自行车股份的计数
- t1——实际温度,单位为摄氏度
- T2——以摄氏度为单位的温度“感觉像”
- 嗡嗡声——湿度百分比
- 风速 —风速,单位为千米/小时
- 天气 _ 代码 —天气的类别
- is_holiday —布尔字段— 1 节假日/ 0 非节假日
- is_weekend —布尔字段—如果当天是周末,则为 1
- 季节 —类别野外气象季节:0-春季;1-夏天;2-摔倒;3-冬天。
我们能在多大程度上根据数据预测未来的需求?
特征工程
我们会做一点工程设计:
所有新特性都基于时间戳。让我们更深入地研究这些数据。
探测
让我们从简单的开始。让我们来看看自行车份额的变化情况:
那有点太拥挤了。让我们来看看每月的相同数据:
我们的数据似乎有很强的季节性成分。夏季对生意有好处。
按小时共享自行车怎么样:
大多数自行车共享的时间根据周末或非周末有很大不同。工作日包含上午和下午晚些时候的两个大高峰(人们假装在中间工作)。周末下午早些时候到晚些时候似乎是最忙的。
按一周中的某一天来看数据,会发现自行车份额的数量要高得多。
我们小小的功能工程努力似乎有了回报。新功能可以很好地分离数据。
预处理
我们将使用最后 10%的数据进行测试:
15672 1742
我们将扩展建模中使用的一些功能:
我们还将扩大自行车份额的数量:
为了准备序列,我们将重用同一个create_dataset()
函数:
每个序列将包含历史记录中的 10 个数据点:
(15662, 10, 13) (15662,)
我们的数据格式不适合训练 LSTM 模型。我们能多好地预测自行车份额的数量?
预测需求
让我们从一个简单的模型开始,看看效果如何。一层双向 LSTM,带漏层:
记住在训练时不要打乱数据:
估价
以下是我们为 30 个时代训练模型后的结果:
你可以看到这个模型学得很快。大约在第五纪元和时,它已经开始有点过度适应了。你可以试着调整它,改变单位的数量,等等。但是我们能用它来预测需求吗?
那对你的眼睛来说可能太多了。让我们放大预测:
请注意,我们的模型只预测未来的一个点。也就是说,它做得很好。虽然我们的模型不能真正捕捉到极值,但它在预测(理解)一般模式方面做得很好。
结论
你只是拿了一个真实的数据集,对它进行预处理,然后用它来预测自行车共享需求。您已经使用双向 LSTM 模型对原始数据集的子序列进行了训练。你甚至得到了一些非常好的结果。
在浏览器中运行完整的笔记本
GitHub 上的完整项目
LSTMs 对于时间序列数据还有其他应用吗?
[## 用 Python 进行机器学习的黑客指南
Scikit-Learn、TensorFlow 和 Keras 深度学习实践指南了解如何解决现实世界的机器学习…
leanpub.com](https://leanpub.com/Hackers-Guide-to-Machine-Learning-with-Python/)
最初发表于https://www.curiousily.com。
视觉亲属关系验证:Python 熊猫教程
原文:https://towardsdatascience.com/demo-for-rfiw-2020-task-1-kinship-verification-8a8ed7081bcc?source=collection_archive---------36-----------------------
野外家庭的视觉识别
认识野外的家庭
目录
- 问题公式化
- 概述
- 设置环境和绘图风格
- 准备数据
- 准备特征并计算分数
- 通过信号检测理论分析性能
- 突击测验
问题定式化
亲属关系验证的目标是确定不同主体的一对人脸是否是特定类型的亲属,像亲子。这是一个经典的布尔问题,系统响应要么相关,要么不相关。即分别为真或假,并形成自动亲属关系识别的一对一范例。
Given a pair of faces, the task here would be to determine whether or not either is a father-son pair.
概观
这个基本演示展示了在野外识别家庭( RFIW )数据挑战中使用熊猫的一些技巧。具体来说,亲属关系验证(任务一)。 FIW 数据集支持 RFIW。这里的目的是演示如何通过几个简单的步骤完成评估。此外,我们还看到了如何轻松地生成既吸引人又富有洞察力的可视化效果。
我们将评估配对,并对用于评估的特征进行分析。具体来说:
- 将所有特征加载到字典中。
- 根据验证协议进行评估。
- 生成 ROC 曲线。
- 使用信号检测模型(SDMs)可视化不同关系类型的亲缘和非亲缘分数分布。
设置环境和打印样式
准备数据
假设特征被提取,存储为 pickles ,并以与人脸图像相同的目录结构和命名方案保存。特征以字典的形式读入,键设置为无文件扩展名的相对文件路径(即
准备特征并计算分数
加载 pickle 文件并确定关系类型
Processing 143168 pairs of 11 relationship types
[‘BB’ ‘SS’ ‘FS’ ‘FD’ ‘SIBS’ ‘MD’ ‘MS’ ‘GFGS’ ‘GFGD’ ‘GMGS’ ‘GMGD’]
在 LUT 建立图像列表和加载功能
计算每对的分数
The output of cell above: head (top) and tail (bottom)
表格的顶部包含阳性对,而底部是阴性对。看分数差异。正如我们所希望的,亲属对似乎比非亲属对得分更高(即更相似)。
通过信号检测理论分析性能
在大多数情况下,标签从一个单独的文件中加载。然而,在这里,我们根据受试者 1 和 2 的家庭 ID (FID)来推断标签是亲属还是非亲属。
生成接收机工作特性(ROC)曲线
以前,这一部分只包含代码片段和图形。感谢 Abal Harith 的评论激发了本文的阐述。尽管如此,未来的博客将会更深入,但下面描述的是最低限度。
验证中提出的一对一协议直接转化为布尔分类的经典问题。因此,ROC 曲线是评估两类问题的一种传统方法,如是/否、垃圾邮件/非垃圾邮件、患病/未患病,以及(我希望)在这一点上毫不奇怪的亲属 / 非亲属。本质上,ROC 曲线的每个点都是做出正确决策的概率,假设感兴趣的样本确实是阳性(即y= {是,垃圾邮件,患病,或亲属},其中标签 y 是针对目标对的)。具体来说,ROC 曲线直观地描述了作为假阳性率(FPR)函数的真阳性率(TPR)。作为回报,是一个由滑动阈值决定的权衡比率。换句话说,ROC 曲线揭示了做出的正确(即 KIN )决策的数量中正确和错误决策的数量(即每次预测被推断为肯定时的正确率)。此外,找到曲线下的面积(AUC)会将该图转换为单个值 v ,其中v∈ℝ:v∈【0,1】。
首先,将 random(即 50-50)绘制成一条穿过对角线的虚线。如果 ROC 曲线低于 random,那么我们只能说你最好抛硬币:)尽管如此,为了直观的帮助:
ROC curves for all pairs
现在生成每种关系(即成对)类型的 ROC 曲线:
ROC curves for each relationship types
显然,祖孙辈似乎是最糟糕的一群。此外,平均而言,FP 是丰富的,这是不好的。
ROC 曲线不是这篇文章的重点。因此,让我们就此打住——我尊敬地提到乔斯林·德索萨和萨朗·纳克希德 这里和这里。两位作者都很好地描述了这个主题的介绍性观点。尽管如此,我们只考虑积极的预测,因此,未来的博客将沉迷于其他指标,同时指出这些指标可能会产生误导的情况(例如,患病/未患病,其中阳性(即患病)的数量通常比阴性少得多)。
让我们对分数分布做一些分析。
信号分析
接下来,为每种关系类型绘制信号检测模型(SDM)。由此,我们将分数的分布视为标签的函数(即,亲属与非亲属)。
SDM for the different pair-wise types.
类似于 SDM,但是让我们看看小提琴的情节,作为两类可分性的另一种可视化的手段。
Violin plot comparing scores of KIN to NON-KIN per category.
突击测验
你看出 ROC 曲线和 SDM 之间的关系了吗?数学上?直觉上?请在下面评论您的想法和解决方案。未来的演示将探索这一概念。
人工智能对民主的真正威胁
原文:https://towardsdatascience.com/democracys-unsettling-future-in-the-age-of-ai-c47b1096746e?source=collection_archive---------11-----------------------
Photo by Brett Zeck on Unsplash
前所未有的挑战和新机遇——信息泡沫、少数人的暴政以及自由和平等的未来
全球政治的黑暗势力对民主制度构成了根本性的挑战。然而,在这个以打击恐怖主义和其他邪恶行为者为特征的时代,人们很少承认或分析技术变革对政治的影响。
政策制定者和政治家倾向于忽视技术在定义未来社会政治系统中的重要性。数字革命带来了前所未有的挑战,破坏了民主的一些基本理念。因此,探索 AI 所代表的危险和机遇对于确保民主的未来活力和维护当代世界秩序至关重要。
过去,新技术的效果展现得相对较慢,让政府有时间进行调整。然而,人工智能(AI)和机器人技术正在进行的技术革命的步伐不仅会快得多,而且会随着时间的推移而加快。不幸的是,监管者往往没有充分意识到新技术的后果,并在负面影响变得明显之前采取必要的改革。第四次工业革命不会是一个单一的分水岭事件——它将是一系列巨大变化的级联,破坏将以越来越快的速度发生,迫使人类不断改造自己。
人工智能涉及机器对人类智能的模拟。与传统的计算机程序不同,人工智能算法(为解决特定问题而创建的指令集)可以自我学习——换句话说,程序员插入数据,然后对数据进行分析,以获得趋势和重要的推论。由于这些技术的复杂性和在几乎所有生活领域的可能应用,它们将极大地改变世界秩序——人类的首要目标必须是最大限度地增加其好处,减少其负面影响。对人工智能对自由民主的影响进行更深入的研究,是解决我们今天面临以及明天可能面临的问题的关键。
人工智能驱动的信息泡沫
2009 年 12 月 4 日。发生了一件在很大程度上未被注意到的事情,但它标志着科技公司所使用的商业模式的一个转折点,并将对社会产生深远的影响。谷歌默默宣布将使用五十七个信号定制搜索结果。换句话说,从 2009 年开始,就没有标准的谷歌了。
人工智能算法被领先的科技公司广泛使用,除了谷歌,还包括脸书、亚马逊和微软。这些公司不断收集我们的活动数据,以便根据每个人的兴趣、愿望和偏好为其量身定制信息。
最初,这种算法是为了帮助我们避免在信息洪流中迷失方向。在一个注意力稀缺的世界,互联网的个性化是确保信息符合我们独特个性的最佳方式,允许有效和方便的网络体验。
然而,算法的个性化也有负面影响。由于个性化算法为人们提供了他们可能参与的信息,人们很快将自己隔离到信息泡沫中,在那里他们自己的信念得到加强,他们不会暴露于相反的观点。这导致了确认偏差,扭曲的世界观和挫伤的创造力。
创造了过滤泡沫这个术语的互联网活动家伊莱·帕里泽(Eli Pariser)写道:“如果任其自生自灭,个性化过滤器会起到一种无形的自动宣传作用,向我们灌输自己的想法,放大我们对熟悉事物的渴望,并让我们忘记隐藏在未知黑暗领域中的危险。”。信息泡沫创造了由熟悉事物组成的虚拟世界:它们是反映我们自己观点的单向镜子。用比尔·盖茨在的话来说,信息泡沫“让你和志趣相投的人一起离开,所以你不会混合、分享和理解其他观点。”
过滤泡沫对社会和民主政治有着深远的影响。由于回音室效应,某些复杂或令人不快的问题被排除在公共讨论之外,因为人们不太可能注意那些难以理解或令人不快的事情,而这些问题的理解对于民主的正常运作是必要的。
过滤气泡也起到了隐形宣传的作用(比如,举了的例子,60%的脸书用户不知道故事的算法管理)。他们强迫人们相信他们所消费的信息代表了无可争议的事实——从而扩大了党派偏见。
在过去,真理是独立于观察者的。但是,在信息泡沫时代,真理的概念正在失去其普遍性,并被相对化和个性化——这使得达成共识变得更加困难,因为现在争论的每一方都相信自己的一贯正确。
当人们被局限于方便的意识形态框架时,他们不太可能达成政治妥协,而更有可能发现自己与他人意见相左。信息泡沫通过促进身份群体的形成助长了政治两极分化,导致无法采取集体行动,最终导致社会分裂甚至完全崩溃。
然而,领先的科技公司已经在解决这个问题上取得了长足的进步。例如,在 2017 年,脸书将其趋势主题列表去个性化,从而扩大了用户对他们感兴趣的主题和他们支持的观点的接触,以及对不同观点和重要全球问题的接触。
Photo by Element5 Digital on Unsplash
大数据、大技术和少数人的暴政
然而,人工智能将不仅仅影响个人。人工智能算法在政治中的使用既带来了新的机遇,也对整个民主进程提出了挑战。
以前,政治家宣布他们的观点,公民选出他们认为最能代表他们国家利益的人。如今,事实正相反:政客们研究选民的观点,并相应调整自己的观点。
候选人越来越多地使用人工智能来通过研究选民的社交媒体活动来分析关于选民偏好的数据。当一个候选人发现他的平台不是一个受欢迎的平台时,他可以改变它以符合人们的要求。民主最终可以通过人工智能的实施得到加强:分析数据库可以让潜在候选人更准确地了解公民的需求,从而弥合政治家和普通公民之间的鸿沟,改善民主进程。正如佩德罗·多明戈斯(Pedro Domingos)所言,多亏了艾,“民主运作得更好,因为选民和政治家之间的沟通带宽大大增加了。”然而,也有不好的一面。如果候选人的信念反映了人工智能对选民偏好的研究,民主选举可能会变成蛊惑人心的大规模呼吁,而不是美国开国元勋所设想的理性审议过程。
然而,更重要的是,人工智能和政治营销的融合将为政治家提供工具,不仅使他们能够检查选民的意愿,而且能够操纵他们。利用设计巧妙的算法,政治家们可以研究个人观点,并通过个性化的广告促使犹豫不决的选民支持他们。这反过来可能会导致少数人的暴政。毕竟,如果候选人知道某些公民是她坚定的支持者,她就不会把精力集中在他们身上——因为她可以只瞄准摇摆不定的选民,这些人将确保她的胜利。这意味着一个国家的命运可能由数十万摇摆不定的选民决定,这些选民将受到来自各方的宣传攻势,因此不太可能做出理性的决定。
人工智能时代的自由与平等
民主的两个基本支柱是自由和平等。人工智能侵蚀了这两个原则。
正如哈拉里(Y. N. Harari)所指出的,全民公决和选举总是关乎人类情感,而不是理性,因为如果民主是理性决策的问题,那么给每个人平等的投票权就没有意义,因为一些人显然比其他人更理性、更有知识,特别是在经济和政治方面。但是,在选举日,一个诺贝尔经济学奖获得者的选票与一个普通出纳员的选票具有同等的分量。正如哈拉里在为 21 世纪写的 21 课中所写的,
不管是好是坏,选举和公民投票与我们的想法无关。它们关乎我们的感受。而说到感情,爱因斯坦和道金斯也不比任何人强。民主假定人类的感情反映了一种神秘而深刻的“自由意志”,这种“自由意志”是权威的最终来源,并且尽管有些人比其他人更聪明,但所有人都是平等自由的。像爱因斯坦和道金斯一样,一个不识字的少女也有自由意志,因此在选举日,她的感觉——以她的选票为代表——和其他任何人一样重要……这种对心灵的依赖可能是自由民主的致命弱点。一旦有人——无论是在北京还是在旧金山——获得了侵入和操纵人心的技术能力,民主政治就会变异成一场情感木偶剧。
人工智能将允许我们产生可以操纵我们的思想和行动的算法,从长远来看,比我们自己更了解我们。甚至在今天,我们越来越相信算法——例如,大多数人相信谷歌是他们唯一的知识来源。我们很可能在未来被迫更加依赖算法,因为在政治宣传泛滥的情况下,算法不会像普通选民那样被操纵。
民主还有另一个决定性特征:平等——社会平等和机会平等。然而,人工智能的实施可能会创造历史上最不平等的社会,因为数据正逐渐变成我们最宝贵的资产。谁控制了数据,谁就控制了未来。
自古以来,土地就是最重要的资产。他们那个时代最强大的国家——如波斯、马其顿和罗马帝国——也是最大的。然而,自从工业革命以来,土地的重要性一直在下降,而工厂和机器已经成为真正的动力来源。
在当今时代,数据将超越土地和机器,成为最重要的资产,为了控制数据的流动,将会爆发战争。数据将是经济的主要驱动力。数字流对 GDP 增长的影响已经超过了历史悠久的商品和服务贸易。
但是,就像几乎所有技术先进的行业一样,由于算法对数据的依赖,数据驱动的经济自然会走向垄断。这种依赖创造了一个自我强化的循环。如果一家公司在竞争中占了先机,就很难抗拒市场集中的过程。有了更好的服务,就会吸引更多的顾客。更多的用户将提供更多的数据,而更多的数据将改进人工智能算法。反过来,更先进的人工智能算法将吸引更多的客户,这些客户将为公司提供额外的数据,等等,无止境。这解释了为什么科技行业如此严重地被垄断,以及为什么像谷歌、亚马逊和微软这样的公司在他们的领域完全处于主导地位。
如果不加监管,未来的经济将由垄断构成,这将导致前所未有的权力集中,因为基于人工智能的算法和机器人消除了大多数工作岗位,导致数百万人失业。民主国家将如何应对一个一无是处的阶层的需求,这个阶层正遭受着比剥削更糟糕的事情——无关紧要?
共产主义和社会主义出现在工业革命之后,因为统治阶级无法满足工人阶级的要求。新的技术革命可能会带来新的意识形态和运动,给民主带来压力,并试图利用无用的人的怨恨为自己谋利。
因此,人工智能可以说是民主的最大威胁,因为它破坏了民主的基础支柱。
民主能经受住这些前所未有的挑战吗?我想是的。民主具有有效解决现代性问题的独特能力,其固有的灵活性和务实的韧性将使其能够适应新的现实。
开放社会(有时被称为自由民主)有一个内在优势:它们是反身性的,因此能够有效应对挑战。简单地说,反身性理论认为,我们对事件的感知会影响这些事件。因此,由于开放社会为非传统的批判性思维提供了途径,它们比意识形态竞争对手更有能力应对现代性的挑战。结果,即使在史无前例的社会变革和生存威胁中,自由民主国家也能成功适应并繁荣发展,这要归功于它们对批评的开放和对改革的接受。
人工智能驱动的技术时代的到来标志着人类历史的转折点。人工智能提供了以前无法想象的机会,将有助于我们加强自由民主。
我们的最终目标必须是通过鼓励对人工智能的影响进行更积极、非党派的讨论来确保民主的可行性,以便设计出管理其影响的蓝图。这将需要加强多边合作,以避免可能导致人工智能军备竞赛和加剧全球不平等的零和思维;公众更好地理解人工智能和一般政治,以改善民主进程;最重要的是,在人工智能驱动的世界的三大支柱之间进行更广泛的协调:政府、科技公司和民间社会。民主的未来掌握在我们手中。
原载于 Areo 杂志
与 H2O 一起使机器学习民主化
原文:https://towardsdatascience.com/democratising-machine-learning-with-h2o-7f2f79e10e3f?source=collection_archive---------3-----------------------
H2O 概述:开源、分布式内存机器学习平台
Photo by Pixabay from Pexels
为了社会和经济的稳定,让每个人都能接触到人工智能是很重要的。
Kaggle days 是一个为期两天的活动,数据科学爱好者可以面对面地相互交流,交流知识,并一起竞争。Kaggle days 旧金山刚刚结束,按照惯例,Kaggle 还为参与者组织了一次黑客马拉松。我在 Twitter 上关注了 Kaggle 几天,来自Erin LeDell(H2O . ai 的首席机器学习科学家)的以下推文引起了我的注意。
Source: Twitter
我已经用 H2O 做了一段时间的实验,发现它在解决 ML 问题时非常无缝和直观。看到它在排行榜上表现如此之好,我想是时候写一篇关于它的文章了,让其他人更容易过渡到 H2O 的世界。
H2O . ai:H2O 背后的公司
H2O.ai 位于加州山景城,提供一套机器学习平台。H2O 的核心优势是其高性能的 ML 组件,这些组件紧密集成在一起。在 2019 年 1 月发布的报告中,H2O.ai 在 Gartner 数据科学平台魔力象限中是一个有远见的人。
Source: Gartner (January 2019)
让我们简单看一下 H2O.ai 的产品:
H2O.ai Products and Solutions
H2O
H2O 是一个开源的、分布式内存机器学习平台,具有线性可扩展性。H2O 支持最广泛使用的统计&机器学习算法,也具有 AutoML 功能。H2O 的核心代码是用 Java 编写的,它的 REST API 允许从外部程序或脚本访问 H2O 的所有功能。该平台包括 R、Python、Scala、Java、JSON 和 CoffeeScript/JavaScript 的接口,以及内置的 web 接口 Flow,
由于这篇文章的主要焦点是关于 H2O,我们将在文章的后面了解更多。
H2O 苏打水
苏打水 允许用户将 H2O 的快速、可扩展的机器学习算法与 Spark 的能力相结合。苏打水是 H2O 用户的理想选择,他们需要管理大型集群以满足其数据处理需求,并希望将数据从 Spark 传输到 H2O(反之亦然)。
H2O4GPU
H2O4GPU 是一个开源的 GPU 加速的机器学习包,带有 Python 和 R 中的 API,允许任何人利用 GPU 来构建高级机器学习模型。
H2O 无人驾驶人工智能
Driverless AI’s UI
H2O 无人驾驶 AI 是 H2O.ai 的自动机器学习旗舰产品。它完全自动化了应用数据科学中一些最具挑战性和生产力的任务,例如特征工程、模型调整、模型集成和模型部署。有了无人驾驶人工智能,各种熟练程度的数据科学家只需在 GUI 上点击几下,就可以训练和部署建模管道。无人驾驶 AI 是一种商业许可产品,有 21 天的免费试用版。
什么是 H2O
最新版本叫做 H2O-3 是 H2O 的第三次化身。H2O 使用熟悉的接口,如 R、Python、Scala、Java、JSON 和 Flow notebook/web 接口,并与 Hadoop 和 Spark 等大数据技术无缝合作。通过更快、更好的预测建模,H2O 可以轻松、快速地从数据中获得洞察力。
高层架构
H2O 使得从多个来源导入数据成为可能,并拥有一个用 Java 编写的快速、可扩展的分布式计算引擎。这里是该平台的高级概述。
A High-Level architecture of h2o
支持的算法
H2O 支持很多常用的机器学习算法。
Algorithms supported by H2O
装置
H2O 提供了一个可以从 CRAN 安装的 R 包和一个可以从 PyPI 安装的 python 包。在本文中,我将只使用 Python 实现。另外,你可能想看看文档中的完整细节。
先决条件
- 计算机编程语言
- Java 7 或更高版本,你可以在 Java 下载页面获得。要构建 H2O 或运行 H2O 测试,需要 64 位 JDK。要使用命令行、R 或 Python 包运行 H2O 二进制文件,只需要 64 位 JRE。
依赖关系:
pip install requests
pip install tabulate
pip install "colorama>=0.3.8"
pip install future
- pip 安装
pip install **-**f http:**//**h2o**-**release**.**s3**.**amazonaws**.**com**/**h2o**/**latest_stable_Py**.**html h2o
- 康达
conda install -c h2oai h2o=3.22.1.2
注意:在 OS X El Capitan 中从pip
安装 H2O 时,用户必须包含--user
标志。比如说-
pip install -f [http://h2o-release.s3.amazonaws.com/h2o/latest_stable_Py.html](http://h2o-release.s3.amazonaws.com/h2o/latest_stable_Py.html) h2o --user
关于 R 安装,请参考官方文档此处。
测试装置
每个新的 python 会话都从初始化 python 客户端和 H2O 集群之间的连接开始。一个集群是一组协同工作的 H2O 节点;当作业提交到集群时,集群中的所有节点都处理该作业的一部分。
要检查是否一切就绪,请打开 Jupyter 笔记本,键入以下内容:
import h2o
h2o.init()
这是一个本地的 H2O 集群。在执行单元时,一些信息将以表格的形式显示在屏幕上,其中包括节点数量、总内存、Python 版本等。如果您需要报告一个 bug,请确保包含所有这些信息。此外,h2o.init()
确保没有 H2O 的先前实例在运行。
Running h2o.init() (in Python)
默认情况下,H2O 实例使用所有内核和大约 25%的系统内存。但是,如果您希望为它分配固定的内存块,您可以在 init 函数中指定它。假设我们想给 H2O 实例 4GB 内存,它应该只使用 2 个内核。
分配资源
h2o.init(nthreads=2,max_mem_size=4)
现在,我们的 H2O 实例只使用了 2 个内核和大约 4GB 的内存。但是,我们将使用默认方法。
在 Python 中使用 H2O 导入数据
安装成功后,就该动手处理真实世界的数据集了。我们将使用著名的葡萄酒数据集解决一个回归问题。这里的任务是 预测白葡萄酒 的质量,给定一组特征作为输入,范围为 0-10。
这里有一个到 Github 资源库 的链接,如果你想跟进或者你可以点击下面的图片在我的活页夹上查看。
数据
这些数据属于葡萄牙“Vinho Verde”葡萄酒的白色变种。
- https://archive.ics.uci.edu/ml/datasets/Wine+Quality来源 e: 来源
- CSV 文件😦https://archive . ics . UCI . edu/ml/machine-learning-databases/wine-quality/wine quality-white . CSV
数据导入
从本地 CSV 文件导入数据。该命令与pandas.read_csv
非常相似,数据作为H2 of frame存储在内存中。
wine_data = h2o.import_file("winequality-white.csv")
wine_data.head(5)# The default head() command displays the first 10 rows.
Displaying the first 5 rows of the dataset
电子设计自动化(Electronic Design Automation)
让我们探索数据集以获得一些见解。
wine_data.describe()
Exploring some of the columns of the dataset
这里所有的特征都是数字,没有任何分类变量。现在让我们也来看看各个特征之间的相互关系。
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(10,10))
corr = wine_data.cor().as_data_frame()
corr.index = wine_data.columns
sns.heatmap(corr, annot = True, cmap='RdYlGn', vmin=-1, vmax=1)
plt.title("Correlation Heatmap", fontsize=16)
plt.show()
和 H2O 一起做模特
我们将建立一个回归模型来预测葡萄酒的质量。在 H2O 模块中有很多算法可以用于分类和回归问题。
将数据拆分为测试集和训练集
由于我们只有一个数据集,让我们将它分成训练和测试部分,以便我们可以评估模型的性能。我们将使用split_frame()
功能。
wine_split = wine_data.split_frame(ratios = [0.8], seed = 1234)wine_train = wine_split[0] # using 80% for training
wine_test = wine_split[1] #rest 20% for testingprint(wine_train.shape, wine_test.shape)
**(3932, 12) (966, 12)**
定义预测变量
predictors = list(wine_data.columns)
predictors.remove('quality') # Since we need to predict quality
predictors
广义线性模型
我们将建立一个默认设置的广义线性模型(GLM)。广义线性模型(GLM)根据指数分布估计回归模型的结果。除了高斯(即正态)分布,还包括泊松、二项式和伽玛分布。你可以在文档中读到更多关于 GLM 的信息。
# Import the function for GLM
from h2o.estimators.glm import H2OGeneralizedLinearEstimator# Set up GLM for regression
glm = H2OGeneralizedLinearEstimator(family = 'gaussian', model_id = 'glm_default')# Use .train() to build the model
glm.train(x = predictors,
y = 'quality',
training_frame = wine_train)print(glm)
GLM model’s parameters on the Training set
现在,让我们在测试数据集上检查模型的性能
glm.model_performance(wine_test)
做预测
使用 GLM 模型在测试数据集中进行预测。
predictions = glm.predict(wine_test)
predictions.head(5)
同样,您可以使用其他监督算法,如 分布式随机 Fores梯度推进机器 ,甚至 深度学习 。你也可以调整超参数。
H2OAutoML:自动机器学习
自动化机器学习 ( AutoML ) 是将机器学习应用于现实世界问题的端到端过程自动化的过程。AutoML 使得真正意义上的机器学习成为可能,甚至对于在这个领域没有主要专业知识的人也是如此。H2O 的 AutoML 倾向于将模型的训练和调整部分自动化。
H2O AutoML: Available Algos
在这一部分,我们将使用 H2O 的 AutoML 功能来解决预测葡萄酒质量的回归问题。
导入 AutoML 模块
from h2o.automl import H2OAutoML
aml = H2OAutoML(max_models = 20, max_runtime_secs=100, seed = 1)
在这里,AutoML 将为 20 个基本模型运行 100 秒。默认运行时间是 1 小时。
培养
aml.train(x=predictors, y='quality', training_frame=wine_train, validation_frame=wine_test)
排行榜
现在让我们看看 automl 排行榜。
print(aml.leaderboard)
AutoML Leaderboard
排行榜显示了 AutoML 构建的前 10 个模型及其参数。最好的模型放在最上面是一个堆叠的系综。
领导者模型存储为aml.leader
单个模型的贡献
让我们看看这个元学习者的个人模型的贡献。
metalearner = h2o.get_model(aml.leader.metalearner()['name'])
metalearner.std_coef_plot()
XRT(极度随机化的树)的贡献最大,其次是分布式随机森林。
预言
preds = aml.leader.predict(wine_test)
上面的代码是最快的入门方式,然而,要了解更多关于 H2O AutoML 的信息,值得看一看深入的 AutoML 教程(有 R 和 Python 版本)。
停工
h2o.shutdown()
使用心流——H2O 的网络用户界面
在本文的最后一部分,让我们快速了解一下 H2O 的开源 Web UIFlow。FLow 是一个基于 web 的交互式计算环境,您可以将代码执行、文本、数学、情节和富媒体结合到一个文档中,就像 Jupyter 笔记本一样。
发射流程
一旦 H2O 启动并运行,你所需要做的就是将你的浏览器指向 http://localhost:54321 ,你就会看到我们非常漂亮的用户界面流。****
Launching H2O flow
流动界面
这里是流接口的一个快速浏览。你可以在这里 阅读更多关于使用和操作 的信息。
H2O’s flow interface
Flow 旨在帮助数据科学家快速轻松地创建模型、导入文件、分割数据框,以及完成在其他环境中通常需要大量输入的所有工作。
工作
让我们看一下同样的葡萄酒例子,但这次是流动的。以下视频解释了使用 flow 的模型构建和预测,这是一目了然的。
Demonstration of H2O Flow
要深入了解 FLow 及其功能,请参考下面的文章:
** [## 使用 Flow 开始使用 H2O
看看 H2O 的开源 UI,它将代码执行、文本、情节和富媒体结合在一个文档中。
towardsdatascience.com](/getting-started-with-h2o-using-flow-b560b5d969b8)**
结论
H2O 是一个强大的工具,鉴于它的能力,它真的可以永远改变数据科学的进程。人工智能的能力和优势应该面向所有人,而不是少数人。这是民主化的真正本质,而民主化的数据科学对于解决威胁我们星球的真正问题应该是至关重要的。
民主化人工智能(第 2 部分):个人人工智能
原文:https://towardsdatascience.com/democratize-ai-part-2-the-personal-ai-bedf819ace44?source=collection_archive---------25-----------------------
卡罗尔·丹弗斯的人工智能遇到了大问题。
作为一名来自克里母星哈拉的“高贵的战斗英雄”,卡罗尔刚刚发现她认为自己真实的大部分事情都是谎言。而不是随便一个谎言。似乎“最高智慧”——统治克里文明的高级人工智能——一直在公然欺骗她。关于她真正的地球起源,关于她神秘力量的来源,以及关于正在进行的对抗邪恶的斯克鲁尔恐怖分子的战争的基础。看起来,诡计、背叛和银河种族灭绝,并不在由一个先进的星际文明的最优秀的头脑组成的统治人工智能的视野之下。不止有点心疼。对于那些对地球自身历史有所了解的人来说,这是令人沮丧的熟悉。
作为重生的惊奇队长卡萝尔令人生畏的挑战是如何挑战全能的最高智慧。毕竟,SI 本质上控制了 Kree 的计算世界,进而控制了它的公民。一旦她在身体上被俘虏,卡罗尔的精神状态似乎就在 SI 的掌握之中。
在整部电影中,卡罗尔纯粹的勇气和决心在艰难生活的倒叙中得到了展现。这些品质在她与 SI 的对决中再次闪耀。然而,事实证明,卡罗尔作为惊奇队长并没有击败 SI 的邪恶意图就其本身的计算为基础的条款。从来没有“人工智能对人工智能”的皇家战役。相反,她最终做了电影中的超级英雄的事情:使用她潜在的宇宙魔方的力量,在 SI 可疑的阴谋中冲出一条路。
这是一场极具娱乐性的成功盛会——但并不完全是一个可供他人效仿的蓝图。毕竟,我们当中很少有人拥有那种在拳头中翻腾的原始宇宙能量。
从现代文学到流行娱乐,中央机器智能运用社会控制的主题并不新鲜。埃姆·福斯特的短篇小说《机器停止了》,首次出版于 1909 年,是文学的先驱。《惊奇队长》只是这类电影中的最新一部。从“2001:太空漫游”到“终结者”系列,情节围绕着一小群具有独立思想的人类反抗统治人工智能的专制权威。正如在《惊奇队长》电影中一样,这种挑战很少在与人工智能相同的虚拟条件下运作,更不用说成功了。相反,抵抗通常是通过现实世界的身体动作来提供的(除非,就像在《黑客帝国》中一样,一个人足够幸运地成为“唯一”,尽管配备了很棒的打斗动作)。甚至在《我的机器人》中,超级人工智能 VIKI 也是由一个流氓机器人将纳米机器人注入她的操作系统核心来完成的。肯定非常有趣。但是,这些拔掉机器插头的变体并没有为我们自己的未来提供最佳的人工智能治理策略。
抛开“人工智能统治世界”的遥远场景,我们的社会此时此刻仍然面临着规模较小但仍然紧迫的挑战。即:在一个日益被第三方人工智能主导的世界里,我们每个人如何能够希望充分保护和促进我们合法的生活利益?
正如这个三部曲系列的第一部分 所描述的那样 ,复杂且不断深化的社会挑战源于我所称的制度 ai:网络“屏幕”、“官僚主义”和环境“场景”的混合这些人工智能由企业和政府机构拥有和控制,相当于嵌入并塑造我们日常生活方方面面的重要决策系统。重要的是,这些系统受制于其机构主人的优先事项,而不是我们其他人。由此导致的人类能动性的丧失有可能成为我们的新现状。
非常清楚的是,这种担忧并不是任何想要将人工智能妖魔化为一种技术的症状。人工智能为许多提高生活质量和挽救生命的应用提供了令人难以置信的潜力。例如,仅仅在医疗保健领域中,已经报道的进步确实令人震惊。作为训练有素的医生和研究人员手中的先进工具,人工智能可以为人类提供巨大的好处。真正的问题归结为那些使用技术工具的人的实际动机和控制。
下面,我将解释一种挑战机构 ai 片面扩散的潜在有效方法是引入人类代理的人工智能——姑且称之为 个人 ai。这些虚拟化身将直接服务于我们每一个人,以及我们选择的利益群体——包括家人、朋友和其他社会关系。本系列的第三部分(即将推出)将提出一个行动计划——“如何”——来帮助实现这些愿望。
迄今为止,大多数关于 AI 民主化的提议——创造更大的透明度,更平衡的优先事项,以及对基本人权更少的伤害——都集中在改变现有机构的做法和行为上。一些专门的组织,从 AI Now ,到人类未来研究所,到人工智能伦理和治理倡议,正在努力工作,以发现、探索和提出对现有人工智能系统中一些更致命的缺陷的有意义的修复。其他人,如 IEEE 的专业软件工程师,正在推广基于道德人工智能的新技术标准和实践。这些团体和许多其他团体正在从事非常有价值和有益的努力,以使机构人工智能更接近人类核心价值观。
值得注意的是,这些组织倾向于在这些第三方控制的算法系统之外进行操作时倡导改进。这意味着他们的工作往往相当于寻求在不同程度上限制我们社会中那些能够接触到所有技术工具和所有个人数据的人的快速发展的活动。它们不会对即将到来的世界构成正面挑战,在这个世界上,只有相对较少的人开发和部署人工智能,表面上是为了我们其他人的利益。简而言之,他们的努力非常重要,但还不完全。
尽管如此,在新生的人工智能领域,仍有机会支持一种互补和有效的方法。普通人实际上应该拥有类似的技术,而不是继续充当数据捐赠者和侵入性算法系统的对象。在人工智能的特定背景下,这意味着人们应该有自己的个人人工智能,只对自己独特的兴趣负责。
那么这到底意味着什么呢?简而言之,我们每个人都应该有一个高度个性化的虚拟智能,在日常生活中支持我们。这些计算代理将存在于我们的个人设备上,由我们选择的值得信赖和负责的实体为我们管理。这些个人认可机构将成为我们值得信赖的顾问和积极的倡导者,部分是通过积极与第三方机构认可机构合作。
这并不意味着,例如,让亚马逊和苹果完全重新编写他们的 Alexa 和 Siri 应用程序。相反,这相当于用他们自己的人工智能武装普通人,然后这些人工智能将与那些机构人工智能直接交互。事实上,如果这些实体打算为我们调解我们的生活,也许虚拟个人代理的引入可以被认为是一种“反调解”的形式,一种引入一些制衡以平衡计算竞技场的方式。与目前的第一代虚拟助手不同,第二代版本将由它服务的实际人类来选择和控制。
因此,个人人工智能旨在代表其客户的利益,帮助塑造和管理她与虚拟世界的互动。特别是,应用程序可以不断地、直观地与来自在线/离线世界的持续不断的数据流进行交互。这将需要无数的实时同步活动:从识别、分析和研究特定情况,到推荐和执行选项,到与第三方就参与条款进行谈判,在必要时,甚至推翻和阻止有害的第三方请求。所有这些都不需要客户有意识的参与。
这种虚拟界面功能可以在许多不同的场景中发挥出来。一些包括拥有个人人工智能:
管理和保护其客户的在线和离线个人数据和信息流动,以及与第三方的其他数字互动;
确保在线推荐引擎提供相关信息,而不是有害内容,如“深度假货”或令人上瘾的视频;
质疑金融和医疗算法的效力,找出可能损害其客户的偏见和其他缺陷;和
防止环境设备(智能扬声器、面部识别摄像头、生物传感器)参与不必要的监控。
最后一个场景涉及将在线计算能力带入离线空间。这将使我们每个人都能应对来自物联网(IoT)设备的大量隐形信号。我们不再需要在没有任何知识或同意或求助的情况下进入一个充满摄像头和传感器的物理环境。在这些情况下,个人人工智能可以根据我们的偏好提出建议或做出决定,允许或拒绝第三方访问个人信息的能力,例如我们的精确物理位置或独特的生物特征。
个人人工智能概念有可能演变成一种全新的范式,让人类使用虚拟连接相互交流。通过访问你的个人信息,并使用先进的机器学习工具,随着时间的推移,你的人工智能将真正了解你,并促进你的最佳利益。因此,个人 AI 应用程序有望成为基本的可信代理,不断地与个人用户联系在一起,并完全代表个人用户。人类既有知识的力量(透明度)又有行动的能力(机会)的实际能动性将得到加强,而不是简单地被剥夺。
因此,回到本系列文章的第一部分,无论是《我的机器人》中的侦探德尔·史普纳,还是作为自动驾驶汽车操作员的你,都会处于更有利的位置。每个人都有自己的超级中介代理,通过“屏幕、场景和镜头”积极地与第三方人工智能打交道。我们数字生活的真正个人化身。
这种个人赋权可能吗?绝对的。随着技术的飞速发展,个人人工智能开始变得可行。例如,IEEE 工作组 P7006 正在为个人数据人工智能代理开发新的行业标准。像开放人工智能这样的组织是开源人工智能软件,旨在实现有益的、以人类为中心的目的。此外,像 Silk Labs 和 Perceptio(现在都是苹果公司的一部分)和 Google(刚刚在 Google I/O 上宣布的)这样的公司正在建立这样的“设备上,云外”人工智能。这意味着实际的计算和个人数据可以驻留在最终用户的设备上,而不是从远处的云中控制。因此,机构认可机构不再需要无形的束缚。
也有一个成熟的商业模式来支持这项技术。真正的可信度应被视为一种商业溢价。毕竟,受托人、合作社、信用合作社、社会企业和一系列职业都是建立在向作为客户的个人提供可信的建议和服务的基础上的。那些相同的模型应该在计算智能空间中工作得特别好,在那里我们大多数人都需要一个实体来帮助我们建立和管理我们的个人人工智能。
真正的挑战不是技术或商业上的。关键是我们所有人都要求个人人工智能在不久的将来成为真正可行的选择。
但是现在能做些什么来实现它呢?也许确保基于人工智能的技术支持普通人利益的最佳方式是帮助为这种技术创造一个实际的生态系统。个人和实体都有机会推动个人人工智能市场的发展。一个这样的例子是作者的 GLIAnet 项目,该项目旨在基于值得信赖的数字代理,包括人工智能“化身”,创建一个新的网络生态系统
在本系列的第三部分(即将推出),我们将详细研究一个行动计划,将个人人工智能的这一引人注目的愿景变为现实。也许下一次,惊奇队长自己的计算“超级代理”将被证明是她超级宇宙能量的有益补充。
将人工智能大众化
原文:https://towardsdatascience.com/democratize-artificial-intelligence-48643394440f?source=collection_archive---------23-----------------------
它会变得不那么可怕
Photo from Unsplash
对未知的恐惧
每个人都知道害怕未知的感觉。在约你喜欢的人出去之前难以忍受的紧张。在学校或工作场所进行重要演示之前,你越来越出汗的手。害怕未知是每个人一生中迟早都会经历的少数普遍经历之一。事实上,“对未知的恐惧可能是一种,或者可能是根本的恐惧”(Carleton,2016)。我们每个人都熟悉的东西应该很容易定义,然而,定义害怕未知到底意味着什么却出奇地困难。Carleton (2016)将对未知事物的恐惧(FOTU)定义为“个体在任何意识水平或处理点感受到的信息缺失导致的体验恐惧的倾向”。这个定义特别有趣,因为它允许将 FOTU 教解释为许多其他恐惧的重要组成部分。
只要熊在动物园的笼子里,你就不怕和熊面对面站着。当你在山里徒步旅行时遇到一只熊,很可能会引起截然不同的反应。这是为什么呢?如果只要熊在笼子里,你就不怕它,那么熊本身就不应该让你感到害怕。有人可能会说,事实上,你害怕的是在山里遇到熊的未知情况。你不知道熊是否看到或闻到了你。你不知道这只熊是吃饱了,还是已经饿坏了,正在拼命寻找食物。除了与熊有关的未知因素,还有几个与你自己有关的未知因素会引起恐惧。你知道遇到熊时该如何应对吗?你应该跑吗?慢慢移动?所有这些未知因素导致了你正在经历的事情和你正在经历的恐惧程度。如果你以前读过关于遭遇熊的故事,并且确切地知道如何行动,你不仅会减少恐惧,你不受伤的几率也会大大增加。
媒体中的人工智能
类似于熊的遭遇,人工智能让很多人感到害怕。当人们读到像“埃隆·马斯克:‘记住我的话——人工智能远比核武器更危险’”这样的标题时,他们会非常害怕人工智能,这是理所当然的。这些文章以产生点击量为目的,试图耸人听闻地报道技术领导者的言论,以最大限度地增加他们的广告收入。然而,与此同时,他们对实际情况和这些人实际所说的话描绘了一幅不完整的画面。如果你读了上面的文章,马斯克实际上描述了人工智能看似无穷无尽的应用,然后呼吁为人工智能的发展奠定坚实的基础,让每个人都参与进来。这篇文章更合适的标题应该是“人工智能将为人类生活带来许多好处——但我们需要教育人们避免潜在的风险”。不幸的是,媒体公司不太可能转向更有教育意义的标题,如果这意味着收入的减少。因此,必须采取其他措施来使人工智能民主化,并使每个感兴趣的人都可以使用它。毕竟,如果你知道你在处理什么,你就能更好地对特定问题做出明智的决定。
让人工智能民主化的方法。
在已经确定,一般来说,FOTU 可以通过教育人们引起他们恐惧的问题来减少,是时候介绍一些减少 FOTU 的方法了。这样做,恐惧的减少不仅有利于现在更加了解人工智能现状的个人,也有利于该国政府所说的个人是公民。Moore (2006)确定了恐惧对经济的“影子价格”,并试图计算减少恐惧投资的“影子成本”之间的权衡。这些发现意味着决策者不应该把对普通大众的人工智能教育的投资视为支出,而是对经济的投资。
因此,这里有三个步骤来克服人工智能方面的 FOTU:
1.定义你的恐惧
克服 FOTU 的第一步是定义并承认你的恐惧。关于人工智能,这些恐惧可能是多方面的,取决于你是谁。一些例子包括:
- 人工智能到底是什么?
- 人工智能会取代我的工作吗?
- 人工智能将如何影响我孩子的生活?
- 等等。
通过明确你害怕什么,你已经减少了让你害怕的未知事物的数量,并迈出了战胜它们的第一步。
2.识别有用的资源
记住之前定义的恐惧,寻找可以帮助你更多了解它们的资源。对于那些不太可能对你造成身体伤害的恐惧来说尤其如此。尽管直面一只熊以了解它对你做跳跃动作的潜在反应会有很大的风险,但自学人工智能不太可能有这种效果。有几个人主张人工智能的民主化,因此,有许多(免费)资源可用。仅举几个例子:
- 书籍:书籍总是学习新话题的好起点。人工智能领域的领导人有几本书是针对普通公众的,试图解释人工智能对日常生活的影响,比如李开复(谷歌中国前副总裁)关于人工智能地缘政治影响的书
- 在线课程:取决于你想深入人工智能的程度,有几个在线学习平台非常重视无障碍人工智能教育。这种平台的一个例子是 coursera,由吴恩达(斯坦福大学计算机科学兼职教授)共同创立,如果你完成的速度足够快,它可以让你免费完成几门人工智能课程。
- 在人工智能领域工作的人:和许多其他职业一样,大多数在人工智能行业工作的人都很乐意和你分享他们的见解。根据我的个人经验,能够与对该主题感兴趣的人交流思想,会给人工智能研究人员、数据科学家、机器学习工程师等带来巨大的快乐..
3.重新评估你的恐惧
完成这两个步骤后,花点时间重新评估你的恐惧。重新审视一下你在第一步中发现的恐惧,问问自己它们是否还像以前一样可怕。如果是的话,太好了。如果没有,请返回步骤二,尝试查找更多信息以进一步降低 FOTU。由于这个过程是高度迭代的,你很可能会发现自己在某个时候不得不回到第二步。技术在快速发展,因此,每隔一段时间更新你的知识是必要的。
结论
虽然已经有很多很好的资源来自学人工智能,但增加可用资源的数量可能会增加一般的人工智能意识和知识。如上所述,不仅将公共资源投资于人工智能的发展,而且投资于人工智能的民主化,应该符合决策者的利益..确保这两者齐头并进将带来巨大的社会和经济效益,同时提高公众对当代最重要的技术发展之一的决策能力。然而,在进行这些公共投资之前,每个人都应该努力减少他们对人工智能的 FOTU,并在这个过程中鼓励其他人也这样做。
参考文献:
[1] R. Nicholas Carleton, 对未知的恐惧:一个人的恐惧能统治他们所有人吗? (2016)《焦虑障碍杂志》(第 41 卷)
[2]西蒙·克里斯托弗·摩尔, 减少恐惧的价值:利用欧洲社会调查 (2006)进行的分析,应用经济学
使用业务示例揭开混淆矩阵的神秘面纱
原文:https://towardsdatascience.com/demystifying-confusion-matrix-29f3037b0cfa?source=collection_archive---------12-----------------------
深入混乱矩阵,了解 ROC 的阈值、曲线下面积(AUC)及其对模型评估的主要影响。
Source: Unsplash image by Leo Foureaux
你刚刚开始机器学习,完成了监督线性回归。现在你可以建立一个准确度还不错的模型了。现在,您转到分类模型。你训练这个模型,并用验证(测试)数据测试它,瞧,你得到了高达 91%的准确率。但是准确性是评估你的模型的正确方法吗?一个混乱矩阵将回答这个问题。网上有很多教程会解释什么是混淆矩阵。这篇文章将帮助你理解企业如何在他们的商业解决方案中使用混淆矩阵分析。
什么是混淆矩阵?
简单来说,混淆矩阵包含我们的预测数据的计数,相对于原始数据分为 4 个部分。它可以为一个分类问题而形成。
Outline of a confusion matrix for 2-way classification
让我们以垃圾邮件过滤器为例来理解这四个部分。有些电子邮件是垃圾邮件,有些不是。我们的垃圾邮件过滤器将预测这一点。
1)真实否定(TN):最初是非垃圾邮件,被预测为非垃圾邮件。
2)真阳性(TP):原本是垃圾邮件,预测为垃圾邮件。
3)假阴性(FN):原本是垃圾邮件,预测为非垃圾邮件。
4)误报(FP):原本不是垃圾邮件,预测为垃圾邮件。
我们可以清楚地看到,TN 和 TP 是我们的模型的正确预测,精确度可以通过:(TN+TP)/(总预测)来计算。但是公司很少纯粹根据准确率分数来做决定。从混淆矩阵中可以得出许多值,如灵敏度、特异性、召回率、精确度等。根据手头的业务问题来选择。我们可以很容易地在网上找到这些性能指标的公式。现在,让我们使用银行试图预测贷款违约者的业务场景来理解这些点指标的重要性。
银行贷款违约者混淆矩阵评估
一家银行创建了一个模型,使用其以前的数据库来预测客户是否违约。此处 TN 实际并预测为非违约, TP 实际并预测为违约。模型的误差为 FN 和 FP,其中 FN 实际上是违约者但被预测为非违约者,FP 实际上是被预测为违约者的非违约者。
在这种情况下,公司将关注两个参数:
- 真阳性率(TPR) :真阳性率也称为敏感度。在这种情况下会是,TP/(TP+FN)。该指标将向我们显示所有*实际违约者中有多少被正确预测。银行将为此需要一个高价值。理想情况下,它应该是 1,因为如果银行能够预测违约者并以 100%的把握拒绝他们的申请,这将对银行有利。
- 假阳性率(FPR) :假阳性率由(FP/TN+FP)给出,又称1——特异性。该指标将向我们显示,在所有非违约者中,有多少人被 ML 模型预测为违约者。FPR 值越低越好。理想情况下,它应该为零,因为高值意味着如果实施 ML 模型,银行将拒绝潜在的好客户,从而减少银行的整体业务。*
阈值及其对混淆矩阵的影响
我们可以理解的一点是,混淆矩阵可以根据手头的业务问题进行分析。现在让我们试着理解混淆矩阵是如何形成的。正如我们在图中看到的,我们有一组 Y-original,我们的模型给出 Y-概率作为分类问题的输出。根据我们的例子,这里的 Y 概率是 Y 为 1(违约者)或 0(非违约者)的概率。
Predicted value with default threshold i.e. 0.5
我们可以设置一个阈值,将所有大于阈值的值归类为 1,小于阈值的值归类为 0。这就是预测 Y 的方法,我们得到了“Y 预测”。我们通常得到混淆矩阵的阈值的默认值是 0.50 。这就是事情开始变得有趣的地方。我们可以改变这个阈值。阈值的变化将导致 Y 的预测值的变化,因此新的混淆矩阵将不同,更重要的是 TPR 和 FPR 值也将变化。因此,我们可以想象,对于阈值的每个唯一值,我们将得到不同的 TPR 和 FPR 值。当这些不同的 TPR(灵敏度)和FPR(1-特异性)值被绘制在散点图上,并且一条线穿过它们时,我们得到了著名的接收器工作特性(ROC) 曲线。
ROC with high AUC
对于不同的分类机器学习模型,ROC 曲线是不同的。就像敏感性或准确性一样,ROC 曲线的曲线下面积(AUC)被视为评估模型的非常有价值的度量。图中的 ROC 具有高 AUC。我们还可以看到图中有一个点 ,这里 TPR(灵敏度)相当高,而 FPR(1-特异性)非常低。如果我们回头看看我们业务需求,我们需要高 TPR 和低 FPR,这正是我们从这个 ROC 上的点得到的。该点对应的阈值可以说是最佳阈值。但是在现实生活中,建立一个具有很高 AUC 的模型并不总是可能的。这是一个合适的分类模型的 ROC 的样子:
从图中可以看出,要获得好的真阳性率,假阳性率也必须提高。因此,必须在它们之间进行权衡。现在到了业务部分,银行有效地在减少违约者(提高 TPR)和减少将良好客户错误分类为可能违约者(降低 FPR)之间进行平衡。因此,在这种情况下,组织不能仅仅依赖模型的准确性。在得出任何结论和做出业务决策之前,需要对混淆矩阵进行深入分析,并将其与业务问题联系起来。因此,在最终确定 TPR 和 FPR 值之后,可以很容易地追溯相应的阈值,并且该阈值将用于客户类型的最终预测(Y_pred)。我们现在可以理解不同的业务问题需要不同的分析来建立正确的模型。
我希望您觉得这篇文章很有趣,并且现在对混淆矩阵如何在真实的商业场景中使用有了更好的理解。我期待在评论中听到你们的评论。我也欢迎任何问题、建议或讨论。
感谢阅读。
使用类激活图解密卷积神经网络。
原文:https://towardsdatascience.com/demystifying-convolutional-neural-networks-using-class-activation-maps-fe94eda4cef1?source=collection_archive---------9-----------------------
机器学习每天都在获得指数级的动力,其应用在每个领域都在增加,无论是金融领域中琐碎的股票价格预测,还是计算机视觉领域中复杂的任务,如对象的检测和分割。没有哪个领域没有受到人工智能革命的影响,在某些领域,机器学习算法甚至超过了人类水平的性能。例如,ImageNet challenge 每年都举办各种计算机视觉任务,如图像分类、对象检测、图像定位等,每年表现最好的算法的错误率都在不断下降,2017 年,38 个参赛团队中有 29 个团队的准确率超过 95%。据报道,大规模 ImageNet 数据集上的人类前 5 名分类错误率为 5.1%,而最先进的 CNN 达到了约 3.57%的准确度。
随着机器学习系统性能的提高,系统的可解释性逐渐降低。这种趋势在深度学习算法中更为常见,这些算法包括数百万个参数和数百层,与线性回归、K 近邻、决策树等基本机器学习算法相比,解释这些算法极其困难。这些算法已经变得像黑匣子一样,从用户那里获取输入,并给出超出预期的输出,但对导致这种输出的因果信息却不提供直觉。这些算法可能适用于准确性是主要要求的任务,如 Kaggle 竞赛,数据科学家不必向各种利益相关者解释和说明结果。但是在结果可解释性非常重要的应用中,黑盒性质会导致各种障碍。例如,如果某个图像识别系统被训练来检测图像中的肿瘤,并且在验证和测试集的准确性方面表现得非常好。但是,当你向利益相关者展示结果时,他们会问你的模型是从图像的哪个部分学习的,或者这个输出的主要原因是什么,你最可能的答案是“我不知道”,无论你的模型有多完美,利益相关者都不会接受,因为这关系到人的生命。
随着机器学习特别是深度学习领域研究的增加,正在进行各种努力来解决可解释性问题并达到可解释 AI 的阶段。
在 CNN 的情况下,已经发现了各种可视化技术,其中之一是类激活图(CAM)。
在论文中介绍的类激活图或 CAM 通过使用 CNN 中的全局平均池来学习用于区别性定位的深度特征。特定类别的类别激活图指示 CNN 用来识别类别的区分区域。
建筑:
这篇论文的作者在 Network 中使用了类似于 GoogLeNet 和 Network 的网络架构。网络主要由大量卷积层组成,在最终输出层之前,我们执行全局平均池。如此获得的特征被馈送到具有 softmax 激活的完全连接的层,该层产生期望的输出。我们可以通过将输出层的权重反投影到从最后一个卷积层获得的卷积特征图上来识别图像区域的重要性。这种技术被称为类激活映射。
Architecture and Working
全局平均池层(GAP)优于在 Oquab 等人中使用的全局最大池层(GMP ),因为与仅识别一个区别部分的 GMP 层相比,GAP 层有助于识别对象的完整范围。这是因为在 GAP 中,我们对所有激活取平均值,这有助于找到所有有区别的区域,而 GMP 层仅考虑最有区别的区域。
间隙层产生最后卷积层中每个单元的特征图的空间平均值,然后加权求和以产生最终输出。类似地,我们产生最后卷积层的加权和,以获得我们的类激活图。
简单工作
在定义了架构之后,让我们看看如何产生类激活图。让我们考虑一个图像,它包含一个我们已经为其训练了网络的对象。softmax 层输出模型被训练的各种类的概率。通过使用所有概率的 Argmax,我们找到最有可能是图像中存在的对象的类别。提取对应于该类别的最终层的权重。此外,提取来自最后一个卷积层的特征图。
Extracting weights from final layer and Building a Model to Output the feature maps as well as the final predicted class.
Features represents the Feature Map obtained from the last layer and results represents the class probabilities for each class.
最后,计算从最终层提取的权重和特征图的点积,以产生类别激活图。通过使用双线性插值对类别激活图进行上采样,并将其叠加在输入图像上,以显示 CNN 模型正在查看的区域。
The code shows iterating through ten images, upsampling the extracted feature maps for the predicted class and finally performing dot product between the feature maps and final layer weights.
实施和结果:
我按照论文中的指导使用 Keras 实现了类激活映射。
最初,以下模型架构使用 3 个卷积层,每个卷积层之后是 max-pooling 层,最后一个卷积层之后是 GAP 层,最后一个输出层激活 softmax。
Architecture of First Model
Model Architecture
Model 1 Summary
上述模型在 MNIST 数据集上进行训练,并在训练、验证和最终测试集上产生了大约 99 %的准确度。
执行了上面提到的以下步骤,并且获得了如下所示的输出:
Outputs
使用原始方法获得的输出是令人满意的,但它仍然令人困惑,因为由于每个卷积层之后的后续最大池层丢失了空间信息,它并不完全清楚。
为了解决这个问题,我稍微调整了一下架构,删除了所有 max-pooling 层,从而保留了空间信息,这将有助于提高模型的本地化能力。但是,由于移除了最大池层,特征图的维数较大,因此训练时间也较长。
以下架构用于第二部分:
Architecture of Model 2
Tweaked Model
Model 2 Summary
第二个模型在训练、验证和最终测试集上给出了 97%准确度。
以下输出是从调整后的模型中获得的:
注意:在第二个模型中,没有应用最大池,因此在向前传递期间没有维度的减少。因此,我们不需要对从最后一个卷积层获得的特征图进行上采样。
The output of the Tweaked version
结论:
类激活图或 cam 是查看 CNN 模型在训练时所见内容的好方法,并为开发人员和利益相关者提供见解,这对模型的可用性和生命周期至关重要。在 CAMs 的帮助下,开发人员可以看到模型正在查看图像中的哪个区域,并可以用于检查模型中偏差的原因、缺乏概括能力或许多其他原因,这些原因在修复后可以使模型在现实世界中更加健壮和可部署。
随着计算机视觉和深度学习领域研究的不断发展,各种深度学习框架,如 Tensorflow、Pytorch 等,不断向其环境中添加新的包,以方便用户,并专注于可解释性。Tensorflow 在可解释模型领域迈出了良好的一步,推出了一个名为 tf.explain 的特殊包,说明使用了哪些技术(如类激活映射等)为您实现和优化,您只需导入库,创建其对象,传递输入并在几秒钟内接收结果,而无需花费时间从头开始实现算法。
要了解如何使用 tf.explain 库,可以参考下面的 教程 作者迪潘坚(DJ)萨卡尔。
希望你喜欢这篇文章,如果想了解更多信息和相关内容,请随时在 Linkedin 上联系我,或者在 twitter 上关注我。我的 Github 上有这篇文章的代码。
使用 GradCam 解密卷积神经网络
原文:https://towardsdatascience.com/demystifying-convolutional-neural-networks-using-gradcam-554a85dd4e48?source=collection_archive---------4-----------------------
(source)
卷积神经网络(CNN)和其他深度学习网络已经在各种计算机视觉任务中实现了前所未有的突破,从图像分类到对象检测、语义分割、图像字幕以及最近的视觉问题回答。虽然这些网络实现了卓越的性能,但它们缺乏可分解成直观和可理解的组件的能力,这使得它们很难解释。因此,当今天的智能系统失败时,它们失败得非常可耻,没有警告或解释,让用户盯着不连贯的输出,想知道为什么。
深度学习模型的可解释性对于建立信任并将其成功融入我们的日常生活至关重要。为了实现这个目标,模型透明性对于解释他们为什么预测他们所预测的是有用的。
概括地说,这种透明性在人工智能(AI)进化的三个阶段都是有用的。
首先,当人工智能相对弱于人类,还不能可靠地“部署”时,透明性和解释的目标是识别故障模式。
第二,当人工智能与人类相当并且可靠地“可部署”时,目标是在用户中建立适当的信任和信心。
第三,当人工智能明显强于人类时,解释的目标是机器教学,即教人类如何做出更好的决定。
在之前的文章中,我们讨论了卷积神经网络中的可解释性问题,并讨论了一种非常流行的技术,称为类激活图或 CAM,用于在一定程度上解决该问题。虽然 CAM 是一种很好的技术,可以揭开 CNN 工作的神秘面纱,并在开发的应用程序中建立客户信任,但它们有一些局限性。CAM 的一个缺点是,它要求特征映射直接位于 softmax 层之前,因此它适用于特定类型的 CNN 架构,该架构在预测之前立即对卷积映射执行全局平均池。(即 conv 特征地图→全球平均池→softmax 图层)。在某些任务上,这种体系结构可能比一般网络实现的精度差,或者根本不适用于新的任务。
在这篇文章中,我们讨论了一个 CAM 的推广,称为 Grad-Cam。Grad-Cam 于 2017 年发布,旨在改善 Cam 的缺点,并声称可以兼容任何一种架构。该技术不需要对现有模型架构进行任何修改,这使得它可以应用于任何基于 CNN 的架构,包括那些用于图像字幕和视觉问答的架构。对于全卷积架构,Grad-Cam 简化为 Cam。
方法:
一些先前的作品已经断言,CNN 中的更深层次的表示捕获了最好的高级结构。此外,CNN 自然地重新训练在全连接层中丢失的空间信息,因此我们可以期望最后的卷积层在高级语义和详细的空间信息之间具有最佳的折衷。
与 Cam 不同,Grad-Cam 使用流入 CNN 最后一个卷积层的梯度信息来了解每个神经元,以做出感兴趣的决策。为了获得任何类别 c 的宽度 u 和高度 v 的类别区别定位图,我们首先计算类别 c 的分数 yc(在 softmax 之前)相对于卷积层的特征图 Ak 的梯度。这些流回的梯度被全局平均汇集,以获得目标类的神经元重要性权重 ak。
Figure 1.Calculating weights ak
在为目标类 c 计算 ak 之后,我们执行激活图的加权组合,并在其后跟随 ReLU。
Figure 2. Linear Combination followed by ReLU resulting in final class discriminative map.
这导致与卷积特征图大小相同的粗略热图。我们将 ReLU 应用于线性组合,因为我们只对对感兴趣的类别有积极影响的特征感兴趣。如果没有 ReLU,类激活映射会突出显示比所需更多的内容,因此会导致低本地化性能。
每个计算机视觉任务的完整流水线如图 2 所示,以便更清楚地了解这一重要概念。
Figure 3.Complete pipeline extending towards specific tasks.
使用 Keras 实现 Grad Cam
实施分为以下步骤:-
- 首先,我们需要一个模型来运行向前传递。我们使用在 Imagenet 上预先训练的 VGG16。您可以使用任何模型,因为与 Cam 不同,GradCam 不需要特定的架构,并且与任何卷积神经网络兼容。
2.定义模型后,我们加载一个样本图像并对其进行预处理,使其与模型兼容。
Input Image
3.然后,我们使用该模型对样本图像进行预测,并解码前三个预测。正如您在下图中看到的,我们只考虑了模型中的前三个预测,模型中的第一个预测是 boxer。
Decoded predictions and Target Class
5.在下一步中,我们找到目标类得分 yc 相对于最后一个卷积层的特征图 Ak 的梯度。直观地,它告诉我们每个渠道对于目标阶层有多重要。变量 grads 返回一个张量,将在下面的步骤中使用。
6.这样获得的梯度然后被全局平均,以获得对应于目标类的神经元重要权重 ak ,如图 1 所示。这将返回一个传递给 Keras 函数的张量,该函数将图像作为输入,并返回 pooled_grads 以及来自最后一个卷积层的激活贴图。
7.之后,我们将每个激活图与相应的混合梯度相乘,该混合梯度作为权重来确定每个通道对于目标类有多重要。然后,我们取沿着通道的所有激活图的平均值,并且所获得的结果是最终的类别区分显著图。
Class Discriminative Map
8.然后,我们对生成的热图应用 ReLU,以便只保留对输出图有积极影响的要素。但是我们看到热图中没有太多的负强度,因此在应用 ReLU 后热图没有太大的变化。
Class Discriminative Map after ReLU
9.然后,我们将热图的每个强度值除以最大强度值,以便标准化热图,使所有值都在 0 和 1 之间。
Class Discriminative Saliency Map after Normalization
10.最后,我们对生成的热图进行上采样,以匹配输入图像的尺寸,并将其覆盖在输入图像上,以便查看结果。
Final Saliency Map with Bull Dog as Target Class
结论:
在这篇文章中,我们学习了一种解释卷积神经网络的新技术,卷积神经网络是一种艺术架构,特别是对于图像相关的任务。Grad Cam 对其前身 Cam 进行了改进,并提供了更好的定位和清晰的类别区分显著图,这些图指导我们揭开黑盒模型背后的复杂性。可解释机器学习领域的研究正在以更快的速度前进,并被证明对于建立客户信任和帮助改进模型至关重要。
在接下来的文章中,我将探索该领域中与卷积神经网络相关的更多最新研究,并将借助直观的可视化和简单的实现来揭开复杂概念的神秘面纱。如果你喜欢这篇文章,留下掌声激励我,如果你有任何建议,请随时在 Linkedin 上与我联系,或者在 twitter 上关注我。
使用 ScoreCam 解密卷积神经网络
原文:https://towardsdatascience.com/demystifying-convolutional-neural-networks-using-scorecam-344a0456c48e?source=collection_archive---------11-----------------------
(source)
最近,越来越多的注意力集中在机器学习模型的可解释性上,主要是深度学习模型,因为它们具有黑箱性质。一种重要的深度学习架构是卷积神经网络(CNN ),它在计算机视觉领域取得了突破,包括图像分类、对象检测、语义分割、实例分割、图像字幕等。在 CNN 的改进和发展方面的进展是指数级的,并且架构已经被极大地简化,但是预测结果不能被分解成直观的和完全可理解的部分。
理解和解释模型对于建立人们对我们系统的信心至关重要。CNN 解决的最常见的问题是图像分类,通常称为显著图或属性图的视觉解释方法用于找到影响模型预测的最有影响力的特征。有几种用于生成显著图的技术,其中最常见的是基于梯度的可视化,其反向传播关于输入层的目标类分数的偏导数。然而,基于梯度的地图的问题是它们通常质量低并且具有随机噪声。其他方法包括基于扰动的方法,该方法通过向输入添加小噪声(扰动)并观察预测的变化来工作。另一个是类激活图(CAM ),我最近在我的帖子中解释了它以及它们的扩展,比如 Grad-Cam 和 Grad-Cam++。它们通常通过激活图的线性加权组合来生成显著图,以突出图像空间中的重要区域。然而,它们也遭受与图像中的目标对象无关的随机噪声的问题,并且权重不能很好地捕捉每个激活图的重要性。
计分摄像机:
在这篇文章中,我将尝试解释最近的一篇论文 Score-Cam,它是对前面提到的方法的改进,并试图使 CNN 的可解释性与其前辈一样。
Score-Cam 建立在类激活映射的基础上,并声称可以解决以前报告的无关噪声问题,并生成更清晰和有意义的解释。在 Score-Cam 中,研究人员遵循基于扰动的方法的思想,该方法掩盖了原始输入中的部分区域,并观察目标分数的变化。所获得的激活掩模被视为输入图像的一种掩模,其掩蔽输入图像的部分,并使模型在部分掩蔽的图像上进行预测。然后利用目标类的分数来表示激活图的重要性。
使用基于扰动的方法的屏蔽激活示例
Figure 1. Input Image
Figure 2. Masks applied on Input Image.
与著名的 Grad-Cam 不同,Score-Cam 没有利用梯度,因为研究人员认为传播的梯度非常不稳定,并在基于梯度的显著图中产生随机噪声。图 3 中显示了梯度的不稳定特性,其中当输入图像稍微改变时,梯度会急剧改变,即使这种改变不会被人眼察觉,也不会改变预测结果。这就是为什么有理由怀疑基于梯度的方法减少冗余噪声的有效性。
Figure 3. The partial derivative changes sharply for indistinguishable changes in the input image.
方法:
各种以前的作品,如凸轮,GradCam 等。已经断言了这样一个事实,即 CNN 中更深的层捕获更高级别的视觉信息。此外,卷积要素自然会保留在完全连接的图层中丢失的空间信息,因此通常期望最后一个卷积图层在高级语义和详细空间信息之间提供最佳折衷,并且这些图层中的神经元会在输入图像中寻找特定于类的语义信息。因此,在 Score-Cam 中,我们使用最后一层来获得包含平衡表示的激活图。
相比之下,GradCam 和 GradCam++使用流经 CNN 最后一层的梯度信息来表示每个激活图的重要性。在 Score-Cam 中,我们使用特定目标类的得分权重。因此,Score-Cam 可以摆脱对梯度的依赖,并作为更通用的框架工作,因为它只需要访问模型的类激活图和输出分数。
Score-Cam 的流水线如图 4 所示,显示了实现最终显著图的所有步骤。
Figure 4. The pipeline of the Score-Cam.
为了使用 Score-Cam 获得类别区分显著图,该过程被分成以下步骤:
- 第一步是将图像传递给 CNN 模型并执行 forward_pass。在正向传递之后,从网络中的最后一个卷积层提取激活。
- 从具有 1xmxn 形状的最后一层获得的每个激活图然后使用双线性插值被上采样到与输入图像相同的尺寸。
- 在对激活图进行上采样之后,所得到的激活图被归一化为[0,1]范围内的每个像素,以保持像素之间的相对强度。使用图 5 中的所示的公式实现标准化。
Figure 5. Normalizing each Activation Map
4.在激活图的归一化完成之后,通过将每个归一化的激活图(1×W×H)乘以原始输入图像(3×W×H)以获得形状为3×W×H .的掩蔽图像 M,激活图的高亮区域被投影到输入空间上
Figure 6. Element-Wise Multiplication of all the activation maps with the Input Image.
5.由此获得的掩蔽图像 M 然后被传递到具有 SoftMax 输出的卷积神经网络。
Figure 7. The Output Score Sk is obtained by the Softmax Operation.
6.在得到每个类的分数后,我们提取目标类的分数来表示第 k 个激活图的重要性。
Figure 8. The score of Target Class used as weights.
7.然后,我们计算目标类得分和每个激活图之间的线性组合的所有激活图的总和。这导致单个激活映射具有与输入类相同的大小。
8.最后,我们将逐像素 ReLU 应用于最终的激活图。我们应用 ReLU 是因为我们只对对感兴趣的类有积极影响的特性感兴趣。
Figure 9.
分数 CAM 在 KERAS 中的实现;
我们将遵循之前在图和方法中描述的相同管道。
- 我们使用在 Imagenet 上预先训练的 VGG16 作为整个管道的模型。
2.我们加载上面图 1 的中所示的输入图像,对其进行预处理,使其适合传递到 VGG16 模型中。
3.之后,我们通过模型传递图像,并获得每个类别的预测分数。我们从预测中提取目标类的索引。
4.然后,我们从大小为(1×14×14×512)的最终卷积层中提取激活。
5.然后,我们对所有激活图进行上采样,以匹配原始输入图像的大小。
Function to Upsample Activations
6.然后,我们使用图 5 中的公式对 512 个激活图进行标准化。
注意:我们在分母中添加了一个非常小的项,即 1e-5,以防止被零除的误差导致 nan 值。
7.在步骤 6 之后,我们通过在掩模和输入图像之间执行元素乘法来投影在原始图像上产生的掩模,如图 6 中的所示。
8.这样获得的掩蔽图像然后通过 VGG16 模型向前传播,并且获得 softmax 分数。
9.在获得所有类的分数后,我们只需提取与我们的目标类相对应的分数。在我们的输入图像的例子中,我们有两个类,但是为了演示的目的,我们将把狗作为我们的目标类。
Here 242 corresponds to the index of the class dog.
10.现在,我们已经得到了生成类别区分显著图所需的全部内容,即归一化的激活图和用作权重的目标类别的分数。现在,我们执行目标类 softmax 分数和标准化激活图的逐元素乘法。
11.在最后一步完成并且我们有了结果之后,我们对所有的激活图执行求和(512),并且我们组合所有的图以产生形状为1×224×224×3的单个激活图
12.为了获得最终的显著图,我们对上一步中获得的激活图执行逐像素 ReLU。
Pixel-Wise ReLU
获得的最终类别判别图如下面的图 9 所示。
Score-Map Saliency Map
正如我们所看到的,分数凸轮是阶级歧视,以及有更少的噪音相比,其前身。
Score-Cam 的优势:
- 像 Grad-Cam 和 Grad-Cam++这样的 Score-Cam 可以用在任何卷积神经网络架构中,并且不需要像 Cam 那样重新训练模型来产生显著图。
- Score-Cam 具有类别区分性,可以去除不相关的噪声,从而生成有意义的显著图。
- 使用 Softmax 分数作为权重,并消除对不稳定梯度的依赖。
结论:
在这篇文章中,我们讨论了最近发布的一篇关于基于分数的类激活映射(Score-Cam)的新架构的论文,该架构提供了一种解决模型可解释性问题的新方法。该论文介绍了一种架构,其中去除了无用的噪声,并且仅产生重要的显著图。此外,它消除了对目标类别梯度的依赖,并产生了一种更通用的方法来产生显著图。本文从两种产生显著图的方法中得到启发,主要是扰动图和类激活图,并提出了一种结合两者优点的方法。
要了解更多关于 Score-Cam 的信息,请阅读以下链接提供的论文【https://arxiv.org/abs/1910.01279。
希望你喜欢这篇文章,如果有进一步的讨论、疑问或相关内容,你可以通过 Linkedin 联系我,或者通过 Twitter 关注我。
去神秘化——深度图像先验
原文:https://towardsdatascience.com/demystifying-deep-image-prior-7076e777e5ba?source=collection_archive---------11-----------------------
使用深度图像先验的图像恢复介绍。
在这篇文章中,我将主要关注图像恢复的任务,以及如何使用之前的深度图像来解决这个任务。
图像恢复简介
图像恢复是指从退化图像中恢复未知真实图像的任务。图像退化可能发生在图像形成、传输和存储过程中。这一任务在卫星成像、弱光摄影中具有广泛的应用范围,并且由于数字技术、计算和通信技术的进步,从退化图像中恢复干净图像是非常重要的,因此已经发展成为与图像处理、计算机视觉和计算成像交叉的研究领域。
图像恢复主要有三个任务:
图像去噪:
图像去噪是指恢复被加性噪声污染的图像。这是图像恢复中最简单的任务,因此已经被几个技术团体广泛研究。
Fig.1 (left)noise add image, (center)true image, (right)Gaussian noise
2.超分辨率:
超分辨率是指从一组低分辨率图像产生高分辨率图像(或高分辨率图像序列)的过程。
Fig2. (left)low resolution image, (right)high resolution image
3 。图像补绘:
图像补绘是对图像中丢失或损坏的部分进行重建的过程。内画实际上是一种古老的艺术,需要人类来画出画中已经变质和丢失的部分。但是在今天的世界中,研究已经提出了许多方法来使用深度卷积网络来自动完成这项任务。
Fig. 3 (left) input, (right) output
什么是深度图像先验?
随着 alexnet 在 2012 年 image-net 竞赛中的成功,卷积神经网络变得非常流行,已经用于每个计算机视觉和图像处理任务,并且已经广泛用于执行逆图像重建任务,并且已经实现了最先进的性能。
深度卷积网络已经取得了成功,因为它们能够从大量图像数据集进行学习。Dmitry Ulyanov 的惊人论文“Deep Image Prior”表明,为了解决像图像恢复这样的逆问题,网络的结构是足够的,并且施加了强先验以从降级图像恢复原始图像。该论文强调,为了执行这些任务,不需要预先训练的网络或大型图像数据集,并且可以仅在考虑降质图像的情况下执行。
为了完成图像恢复的任务,学习先验和显式先验是研究人员常用的两种方法。
在学习-先验中是一种训练深度卷积网络的直接方法,以通过数据集学习世界,该数据集将有噪声的图像作为输入,将干净的图像作为期望的输出。
另一方面,explicit-prior 或手工制作的 prior 方法,是我们在其中嵌入硬约束并教导什么类型的图像是自然的、人脸等。从合成数据中。像自然这样用数学表达约束是非常困难的。
在深度图像先验中,作者试图通过使用卷积神经网络构造一个新的显式先验来弥补两种流行方法之间的差距。
让我们从技术角度出发...
Fig.4. (left)clean image, (center)corrupted image, (left) restored image
x → 干净图像 ẋ→退化图像* x→恢复图像**
我们可以使用最大后验分布来估计经验数据中的未观测值
使用贝叶斯规则,我们可以将其表示为似然*先验。**
我们可以通过对等式应用负算法,将等式公式化为优化问题,而不是分别处理分布。(1)
e(x;ẋ) 是作为似然负对数的数据项,R(x)是作为先验负对数的图像先验项。
现在的任务是在图像 x 上最小化等式(2)。传统的方法是用随机噪声初始化 x ,然后计算函数相对于 x 的梯度,并遍历图像空间,直到我们收敛到某个点。
Fig. 5 visualization of regular approach
另一种方法是构造一个函数 g ,它用随机θ初始化,来自不同空间的输出可以映射到图像 x,并使用梯度下降更新θ,直到它收敛到某个点。因此,我们可以在θ上优化,而不是在图像空间上优化。
**
FIg. 6 Visualization of parameterized approach
但是,为什么这种方法是可能的,为什么我们应该使用它?。这是可能的,因为从理论上讲,如果 g 是满射的g:θ↦x**(如果至少有一个 θ 映射到图像 x )那么这个优化问题是等价的,即它们有相同的解。但在实践中, g 在优化方法搜索图像空间的方式上发生了巨大的变化。我们实际上可以把 g 作为超参数来对待,并对其进行调优。如果我们观察,g(θ)作为一个先验,有助于选择一个好的映射,它给出一个期望的输出图像,并防止使用得到错误的图像。
所以,与其优化两个分量之和。我们现在将只优化第一项。
现在,Eq 2。可以表示为,
其中, z 是随机固定输入图像,θ是随机初始化的权重,其将使用梯度下降来更新,以获得期望的输出图像。
但是仍然不清楚为什么我们应该考虑这种参数化方法。理论上乍一看,它似乎会产生原始噪声图像。在论文中,作者进行了一项实验,该实验表明,当使用梯度下降来优化网络时,卷积神经网络不愿意噪声图像,并且更快和更容易地下降到看起来自然的图像。
Fig. 7 Learning curves for the reconstruction task using: a natural image, the same plus i.i.d. noise, the same
randomly scrambled, and white noise. Naturally-looking images result in much faster convergence, whereas noise is rejected.
逐步深入图像先验
ẋ =被破坏的图像(被观察)
**1。初始化zT8。:用均匀噪声或任何其它随机图像填充输入 z。
2。使用基于梯度的方法求解并优化函数。
3.最后,当我们找到最佳θ时,我们可以获得最佳图像,只需将固定输入 z 正向传递给具有参数θ的网络。
**
Fig. 8: Image restoration using the deep image prior. Starting from a random weights θ 0 , we iteratively
update them in order to minimize the data term eq. (2). At every iteration the weights θ are mapped to image
x = f θ (z), where z is a fixed tensor and the mapping f is a neural network with parameters θ. The image x is
used to compute the task-dependent loss E(x, x 0 ). The gradient of the loss w.r.t. the weights θ is then computed and used to update the parameters.
结论
该论文试图表明,在具有随机化权重的深度卷积神经网络结构内构造隐式先验的方法非常适合于图像恢复任务。该论文中显示的结果在很大程度上表明,适当手工制作的网络架构足以解决图像恢复任务。
使用 MS Excel 揭开前馈和反向传播的神秘面纱
原文:https://towardsdatascience.com/demystifying-feed-forward-and-back-propagation-using-ms-excel-30f5aeefcfc7?source=collection_archive---------7-----------------------
深入探究神经网络的奥秘,超越理论界限,在 MS Excel 中实现它。
近年来,关于神经网络(NNs)已经说了很多,也写了很多——从感知器的概念到神经元的复杂多层结构。本文试图揭开两种基本算法的神秘面纱,前馈和反向传播,这两种算法使得神经网络能够工作。使用 Microsoft Excel 以最简单的形式解释了这些技术。
所考虑的例子是非常基础的,与真实世界的例子相去甚远。这里的意图是保持简单直观,理解工作逻辑,而不是关注背后复杂的数学。
首先,我只考虑了一个输入向量 V= [X1=1,X2= 0,X3=1,X4=0],它有一个由 3 个神经元和一个输出层组成的隐藏层。目标输出是 1。
Neural Network with One Hidden Layer
网络设置-
输入和输出- 作为一个例子,假设我们期望算法对于‘X1’&‘X3’(比如说 1)的指示非零值给出输出‘1’,对于‘X2’&‘X4’给出输出‘0’。因此,这里考虑的输入向量是[1,0,1,0]。
Input and Output
前馈:
步骤 1:初始化网络参数
第一步是使用 MS Excel 中的 rand() 函数初始化权重和偏差。
(附注:下表中突出显示的单元格代表基于建议公式的导出值)
Weights and Biases — Input to Hidden Layer
Weights and Biases — Hidden to Output Layer
步骤 2:计算隐藏层节点的净输入
净输入只不过是输入乘以权重,然后按偏差递增。使用输入向量[1×4]和权重[4×3]的矩阵乘法,结果矩阵的维数为[1×3]。要在 excel 中实现这一点,请使用 =SUMPRODUCT() 得出如下结果矩阵[1X3]
Input times Weight
在突出显示的单元格中使用公式来获得输入乘以权重:
=SUMPRODUCT({1,0,1,0},{0.49,0.35,0.44,0.80})
=SUMPRODUCT({1,0,1,0},{0.72,0.90,0.58,0.92})
=SUMPRODUCT({1,0,1,0},{0.38,0.43,0.39,0.21})
现在,给这些输入乘以权重加上偏差
Net Input
要在突出显示的单元格中使用的公式,以获得净输入
= SUM(0.92,0.40)
=SUM(1.30,0.00)
=SUM(0.76,0.99)
步骤 3:通过激活函数(Sigmoid)传递净输入
让我们将“步骤 2”的输出[1.33,1.30,0.99]作为输入传递给隐藏层的每个神经元处的激活函数[f(1.33),f(1.30),f(0.99)],这可以通过在 MS Excel 中键入 f(x) = 1/(1+exp (-x))来轻松完成。
Output at Hidden Layer
要在突出显示的单元格中使用的公式,以获得隐藏层输出:
=1/(1+exp(-1.33) )
=1/(1+exp(-1.30))
=1/(1+exp(-0.99))
步骤 4:计算输出节点的净输入
现在,“步骤 3”的输出[0.79,0.79,0.73]将作为输出节点的输入。让我们重复“步骤 2”,输入向量为[0.79,0.79,0.73],权重向量为[0.71,0.16,0.57],输出偏差为[0.83]。
Net Input at Output Node
在突出显示的单元格中使用的公式,用于在输出节点获得净输入
=SUMPRODUCT ({0.79,0.79,0.73},{0.71,0.16,0.57}) + 0.83
其中简化后= 1.93
步骤 5:获得神经网络的最终输出
让我们将从“步骤 4”[1.93]接收到的输出作为 f(1.93)传递给激活函数,这也可以使用 f(x)=1/(1+exp(-x))来计算,从而得到神经网络的最终输出。
=1/(1+exp(-1.93))
前馈网络输出=0.87
反向传播:
一旦获得前馈的输出,下一步是通过与目标结果比较来评估从网络接收的输出。
现在,神经网络设计者控制的一个明显的事情是权重和偏差(也称为网络参数)。因此,这里的挑战是找到能够最小化误差平方和的最佳权重和偏差: E=1/2 ∑(网络输出-目标输出)由网络接收,在这种情况下=[0.5 *(0.13)]= 0.00798
我们需要单独查看这些权重和偏差所造成的误差,然后不断更新它们以减少误差。这个过程将被重复直到收敛。一旦达到最优,该网络将被称为训练过的网络。让我们开始在 Excel 中实现这个理论。
步骤 1:更新权重[wH1,wH2,wH3]
使用链式法则 ( 我将跳过这里的推导)计算误差函数 E 相对于权重【wH1,wH2,wH3】的导数,简化后等于
其中,sigmoid 函数 f(x)的导数= [f(x)(1-f(x)]*
所以,[ d (E)/d(wH1),d(E)/d(wH2),d(E)/d(wH3)] =
Derivative of E with respect to WH1, WH2 and WH3 respectively
要在突出显示的单元格中使用的公式:
=乘积(-0.13,0.87,0.13,0.79)
=乘积(-0.13,0.87,0.13,0.79)
=乘积(-0.13,0.87,0.13,0.73)
新的更新权重将是【初始权重】— [{(学习率)* [d(E)/d(wH1),d(E)/d(wH2),d(E)/d(wH3)]],其中,学习率被假定为 0.5
Updated weights after 1st Iteration
通过使用-
=(0.71)-乘积(0.5,-0.0110)
=(0.16)-乘积(0.5,-0.0110)
=(0.57)-乘积(0.5,-0.0102)
步骤 2 —在输出节点更新偏置 BO
对于偏差,使用链式法则计算误差函数 E 相对于偏差 BO 的导数,简化后等于
所以,d(E)/d(BO)= 1
Derivative of Error E with respect to output node bias
要在突出显示的单元格中使用的公式:
=乘积(-0.13,0.87,0.13)
新的更新偏差[BO] 新的=[初始偏差]—[学习率*{d(E)/d(BO)}]
Update Bias at Output node after 1st Iteration
要在突出显示的单元格中使用的公式:
=(0.83)-乘积(0.5,-0.0139)
步骤 3-更新权重[w11,w12,…w43]
为了更新“隐藏输入”层的权重,让我们计算误差 E 相对于权重【W11,W12…w43】的导数,其在简化后等于
所以,[ d (E)/d(w11),d(E)/d(w12),……d(E)/d(w43)] =
Derivatives of error E with respect to weights w11, w12,….w43
要在突出显示的单元格中使用的公式:
MS Excel formula to be used to get the derivatives
新的更新权重=[初始权重]—[学习率* (d(E)/dwij)]
Updated Weight after 1st Iteration
要在突出显示的单元格中使用的公式:
MS Excel formula to be used to update the weights
步骤 4:更新偏差[BH1,BH2,BH3]
同样,使用链式法则计算误差 E 相对于隐藏节点偏差的导数,简化后等于
所以,[ d (E)/d(BH1),d(E)/d(BH2),d(E)/d(BH3)] =
Derivative of error E with respect to Bias at Hidden nodes
要在突出显示的单元格中使用的公式:
=乘积(-0.13,0.87,0.13,0.71,0.79,0.21)
=乘积(-0.13,0.87,0.13,0.16,0.79,0.21)
=乘积(-0.13,0.87,0.13,0.57,0.73,0.27)
新的更新偏差=[初始偏差]—[学习率* (d(E)/d(BHi))]
Updated Hidden node Bias after 1st Iteration
要在突出显示的单元格中使用的公式:
=(0.40)-乘积(0.5,-0.0016)
=(0.00)-乘积(0.5,-0.0004)
=(0.22)-乘积(0.5,-0.0016)
因此,我们已经完成了前馈和反向传播的一个循环,重复相同的步骤,即使用这些更新的参数再次运行前馈将使您更接近目标输出,反向传播将再次用于更新这些参数。这种前馈和反向传播的循环过程将继续下去,直到误差变得几乎恒定,并且在目标输出中没有太多进一步改进的余地。
上述模型在 Excel 中实现,经过 100 次迭代后,网络的行为如下所示。随着每次迭代,网络输出朝着目标输出(蓝线)前进,误差(红线)减少。
为什么选择 MS Excel?
在 excel 中实现这些复杂概念的主要优势是为这些网络的工作方式提供了坚实的基础,如果您非常了解基础知识,理解复杂架构的工作方式会容易得多。
接下来是什么:
在我接下来的系列文章中,我将尝试将这些概念与相关的数学联系起来。此外,输入可以通过不同的方式传递到网络,训练网络参数也有不同的方式。我将在以后的文章中谈到这些细节。
希望这种在 excel 中演示神经网络的努力将有助于初学者轻松地理解前馈和反向传播的概念。如果您需要在 excel 中实现一个现成的神经网络作为工作模型,请联系我。
揭开 TensorFlow 2.0 中 GANs 的神秘面纱
原文:https://towardsdatascience.com/demystifying-gans-in-tensorflow-2-0-9890834ab3d9?source=collection_archive---------4-----------------------
本教程向您展示了如何在新的 TensorFlow 版本 2.0 中轻松实现生成式对抗网络(GAN)。我们将关注基本实现,这为可选的增强留有余地。在我们仔细研究实现之前,我们需要理解 GANs 背后的思想和理论。如果你已经熟悉 GANs 背后的理论,你可以跳到实现部分。
甘斯背后的理论
GAN 的主要焦点是通过对抗过程从零开始生成数据。这个过程包括两个模型——鉴别器和生成器。鉴别器了解来自数据分布的样本是真的还是假的,而生成器试图产生假样本来欺骗鉴别器。
“生成模型可以被认为类似于一队伪造者,试图生产假币并在不被发现的情况下使用,而鉴别模型类似于警察,试图检测假币。”[1]
让我们从理论上来理解 GANs 背后的基本过程。鉴别者和发生者可以被认为是多层次的感知,它们相互竞争。发生器 G(z) 馈入先前的输入噪声p _ z(z),该噪声随后作为鉴频器的输入。鉴别器 D(x) 的输出是一个单一标量,它代表发生器产生的输入数据 x 是真实样本还是虚假样本的概率。如果 D(x) 等于 1,鉴别器绝对确定输入是来自训练数据的真实样本,如果 D(x) ≈ 0 鉴别器知道它被生成器愚弄了。
The idea behind generative adversarial networks
挑战在于,我们训练 D 最大化分配正确标签的概率,同时训练 G 最小化分配正确标签的概率。在文学中,这也被称为最小最大游戏。
等式的蓝色标记部分定义了成为真实图像的概率,红色部分定义了成为虚假图像的概率。上面的方程也可以理解为鉴别器的目标,下面的方程可以理解为生成器的目标,我们想优化它来更好的忽悠鉴别器。
发电机输入是均匀或正态分布的样本,我们在下文中称之为噪声。然后,鉴别器被输入真实图像和噪声。通过神经网络计算误差,它学习如何区分它们。
履行
如果你想复制粘贴或者只是想根据你的需要调整笔记本,在 GitHub 上检查代码。
首先,我们将导入我们需要的基本库。我们将使用 TensorFlow 2.0 来构建网络和对抗过程,使用 NumPy 来生成噪声,使用 matplotlib 来保存图像。还要确保您使用的是 TensorFlow 2.0 —下面的代码无法在旧版本上运行!
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from tensorflow import kerasprint(tf.__version__)
之后,我们需要定义一些在整个实现过程中需要的全局变量。参数 BATCH_SIZE 定义了一次向神经网络中输入多少样本。我们将 BUFFER_SIZE 参数设置为等于训练数据集的长度,以便进行完美的洗牌(单击此处)。如果您想使用不同的批量或数据集,不要忘记调整这些变量。 OUTPUT_DIR 定义了路径,在训练期间,发生器的输出图像存储在该路径中。
BATCH_SIZE = 256
BUFFER_SIZE = 60000
EPOCHES = 300
OUTPUT_DIR = "img" # The output directory where the images of the generator a stored during training
现在,我们将直接从 TensorFlow 加载 MNIST 数据集——我们总共有 60.000 张图像,高度和宽度为 28 像素(列表中的每张图像代表一张图片)。
在我们将要实现神经网络之前,数据被传递到一个 tf.data.Dataset 对象中。一个 tf.data.Dataset 表示一个元素序列,其中每个元素包含一个或多个张量对象——我们将使用它作为迭代器来批量存储我们的图像,并在以后循环遍历它们。此外,图像被归一化到-1 和 1 之间(由均匀分布产生的相同范围)。
为了构建生成器和鉴别器,使用了 tf.keras 模型子类化 API,这为我们构建模型提供了更多的灵活性。这意味着,我们将为鉴别器和生成器实现一个类。在构造函数中,我们将定义网络的层,在调用方法中,我们将定义模型的前向传递。我们将向网络中输入 100 维的噪声,并输出大小为 784 的向量。稍后,我们将把这个向量重塑成一个 28x28 的矩阵(图像的原始大小)。此外, generate_noise 方法用于从均匀分布中创建随机数据点。
上面描述的目标函数就是二元交叉熵。它只接受输入鉴别器的噪声和真实的标签,因为发生器认为它产生真实的图像。
我们对鉴别器目标做了同样的事情,但是现在我们把假的和真的损失加在一起。此外,我们增加了一点平滑的目标的真实损失,以避免过度拟合。
鉴频器网络的实现方式与发生器类似。唯一的区别是,我们将一个 784 维的向量(28*28 = 784)作为输入,并只输出一个神经元,它可以告诉我们输入的是假图像还是真图像。
作为优化器,我们将使用 RMSprop 优化器。这只是我做的一个武断的决定——你可以随意使用你想要的任何其他优化器。
generator_optimizer = keras.optimizers.RMSprop()
discriminator_optimizer = keras.optimizers.RMSprop()
下一步是定义在一个单独的训练步骤中应该发生什么。通过使用发生器和鉴别器的梯度,我们同时训练两个网络。首先,根据我们之前定义的批量大小,会产生一些噪声。然后,我们将真实图像和虚假图像输入鉴别器,并计算其损失。最后一步是对生成器进行同样的操作,并应用这些渐变。
最后一步是定义一个描述整个训练的函数。感谢 tf.data.Dataset 对象,我们可以轻松地迭代我们的数据。最后一个函数将每隔 50 个时期生成的所有图像保存到您在变量 OUTPUT_DIR 中定义的目录中。
正如你在我的 jupyter 笔记本上看到的,我进行了 300 次训练,取得了很好的结果。我认为,当涉及到像 MNIST 这样的简单数据集时,通过更多的微调和更深入的生成器以及鉴别器,您实际上可以获得更好的结果。
Exemplary results of the implemented GAN
请记住,这是您能想到的最简单的 GAN 实现之一。在鉴别器和生成器中使用卷积可以获得更好的结果。你可以查看 TensorFlow 团队提供的使用卷积而不是密集层的教程(点击此处)。
链接到 Jupyter 笔记本:https://github.com/MonteChristo46/GAN-Notebooks
参考
Goodfellow 等人(2014):生成对抗网络。arXiv:1406.2661
通过生成密码来揭开生成模型的神秘面纱—第 2 部分
原文:https://towardsdatascience.com/demystifying-generative-models-by-generating-passwords-part-2-38ad3c325a46?source=collection_archive---------23-----------------------
从概率到深度学习方法
理解朴素贝叶斯模型和变分自动编码器(VAE)在生成任务中的区别。
Photo by Isis França on Unsplash
介绍
你好,这又是“揭开生成模型的神秘面纱”帖子的第二部分,所以如果你还没有阅读第一部分,我真的强烈建议你在这里阅读。
在上一篇文章中,我们讨论了判别模型和生成模型之间的区别,窥视了迷人的概率世界,并利用这些知识开发了一个可以为我们生成密码的朴素贝叶斯。现在,我们将稍微改变一下我们的方法,并探索当概率失败时,深度学习如何帮助我们。
不是很有用的朴素贝叶斯
假设您已经掌握了第 1 部分的上下文知识,我将直接切入正题。开发的多项式朴素贝叶斯模型是基于这样一个假设,即每个特征都是相互独立的,并且它工作得非常好!但是让我们稍微改变一下问题的提法,观察一下它的表现。不要有 4 个特性,固定的顺序,每个特性有有限的选择,让我们定义一个字母表,包含所有出现在初始特性选择中的字母、数字和特殊字符。这些将是:
小写 : ['a ',' b ',' c ',' e ',' f ',' g ',' h ',' I ',' j ',' k ',' l ',' m ',' n ',' o ',' p ',' r ',' s ',' t ',' y']
数字 : ['0 ',' 1 ',' 2 ',' 3 ',' 4 ',' 7 ',' 8 ',' 9']
特殊 : [' !',' @ ',' $ ',' % ',' * ',_'] 大写 : ['A ',' E ',' T ',' P']
为了使这个新问题尽可能接近前一个问题,我们将密码的最大长度限制为 15 ,因为这是我们的密码数据集中的最大长度。另外,让我们定义另一个虚构的人物,叫做< NULL >。因为下面将要描述的模型必须填充密码的所有 15 个位置,所以空字符<只是模型告诉用户不要在这里放置任何东西的一种方式。因此,从我们的角度来看,任何空字符都将被忽略。
经过所有这些变化,字母表现在总共包含 19+8+6+4 + 1= 38 个字符(大写+小写+数字+特殊字符+空字符)。因此,在我们的样本空间中有 38 种⁵可能的组合!当然,这是一个比以前大得多的样本空间,但是让我们观察一下朴素贝叶斯模型在这些情况下的表现。
下面的列表说明了在当前问题上下文中使用旧的朴素贝叶斯模型生成的密码:
你能发现这里的问题吗?由于依赖于条件独立性假设,每个字符位置都是独立推断的,因此密码中没有一个单词是有意义的。这将使记住密码变得极其困难,这不是我们想要的。
回想一下,在第 1 部分中,对输出格式和输入都有约束。我们特别要求模型基于有限的选择集进行一些采样,这不可避免地是有意义的,而且它们确实是独立的!尽管如此,这一次,样本空间非常大。在所有可能的组合中,只有极小的一部分类似于一个单词或遵循一开始就定义好的格式,因为每个字母都依赖于前面的字母。举个例子,我们的密码序列第四位出现“e”的概率,应该是前三个字母是“caf”而不是“pas”的时候更大!希望这在某种程度上解释了为什么 Naive-Bayes 等统计模型在非结构化数据上表现不佳。
表征学习的深度模型
然而,这并不意味着我们不能处理非结构化数据。近年来,深度学习已经获得了大量的研究和行业关注,很明显,非结构化数据是深度学习模型擅长的领域!毫无疑问,这是因为他们有能力对输入数据的底层结构/依赖性进行建模。
A typical example of a deep learning model with fully connected layers
但是这怎么可能呢?你可能会想。好吧,经过训练的深度学习模型中神经元的深度堆叠分层,可以被设想为从高维空间到低维潜在空间的映射(降维)。在这样的空间中,建模数据点之间的关系变得更加容易,甚至可能执行算术运算。例如,潜在空间表示的一个广泛使用的应用是使用深度学习模型生成单词嵌入。
你可以在我的旧博客这里了解更多关于单词嵌入的内容。
更正式的说法是,这被称为表征学习,作为人类,我们经常使用它,甚至没有注意到。尽管如此,对一台机器来说,这仍然是一项极其困难的任务。举个例子,回想一下你最后一次试图向某人描述一个人的时候。最有可能的是,你提到了头发颜色、体型、服装、眼睛颜色、皮肤颜色等等……而与你交谈过的人马上就能想象出你所描述的那个人的照片!所有用于这种描述的特征都是低维特征,我们的大脑知道如何转换到更高层次的维度,或者换句话说,一个图像!同样,大脑的感官输入以高维度表示,但人类的认知能力允许我们将这些转换为低维特征!这难道不令人兴奋吗??
自动编码器
A utoencoder[1]是一种神经网络架构,可以更精确地描述为连接在一起的编码器和解码器。编码器是一个较小的神经网络,它将高维数据映射到较小的潜在空间,同时保留原始数据的主要特征。同样,解码器只是一个反向编码器。它从潜在空间获取输入,并试图重建原始数据。
Credit: Jeremy Jordan — Introduction to Autoencoders
请注意,网络最窄的部分位于中间。这部分被称为网络的“瓶颈”,本质上是迫使自动编码器丢弃一些信息并只存储重要的特征,而不仅仅是将信息从输入传递到输出。
在生成建模环境中,网络作为一个整体被训练,但是只需要解码器部分来生成数据。通过最小化原始输入与重构输出的误差来执行训练。
在这篇文章中,我将跳过对网络如何工作的正式描述,因为我的主要目的是强调与概率学习的区别,但如果你想了解更多,斯坦福大学有一个关于自动编码器的优秀教程。
让我们重新看看密码生成的例子,开发一个自动编码器,它可以为我们生成密码,并观察它与独立的朴素贝叶斯模型相比如何。
TL;DR;
请注意,下一节的所有代码都可以在这里找到:
[## apogiatzis/vae-lstm-自动编码器-密码生成
这个库包含了名为“通过…揭开生成模型的神秘面纱”的系列文章的第 2 部分的相关代码
github.com](https://github.com/apogiatzis/vae-lstm-autoencoder-password-generation)
所以,如果你是为了代码而来,请随意跳过其余部分,但我建议你打开笔记本,跟着读,因为如果和文章的其余部分一起阅读,代码会更有意义。
一个热编码
最初,密码必须被转换为向量,以便作为输入传递给任何类型的深度学习模型。对于这样的任务,最著名的技术之一是一键编码。一般来说,一种热编码适用于分类数据,通俗地说,它将一个项目表示为“one-of-X ”,其中 X 是所有可能类别的一个实例。在文本数据的上下文中,假设有固定的词汇,并且每个标记被表示为与词汇长度相同的稀疏向量,其中数字 1 指示该标记是对应于相关向量索引的类的实例。
让我们看一个例子来澄清任何混淆。假设我的词汇表只包含 5 个字符(“a”、“b”、“c”、“d”、“e”),那么一个热编码中的单词“bad”可以表示为:
one_hot_encoding("bad") = [[0, 1, 0, 0, 0], [1, 0, 0, 0, 0], [0, 0, 0, 1, 0]]
体系结构
如前所述,自动编码器通常遵循标准的堆叠架构,但有许多参数可以调整,如堆叠层数、单元数、连接单元的方式等...此外,自动编码器可以采用非对称架构,其中解码器与编码器具有不同的结构。不管是什么情况,这个概念都是一样的。
对于我们的密码生成场景,我采用了 BiLSTM 自动编码器架构,如下图所示。BiLSTM 层只是普通 LSTM 层的双向版本。这一选择背后的主要原因是利用一个擅长捕获顺序依赖关系的模型,但是任何其他顺序模型也适用于这里描述的内容。
履行
为了实现上面的模型,使用了带有 Tensorflow 后端的 Keras 功能 API。更准确地说,密码是如上所述的一个热编码,然后分别通过 16、10 和 6 个单元的 3 个 BiLSTM 层。然而在幕后,输出维度是加倍的,因为例如第一层在一个方向上输出 16 个单位,在相反方向上输出 16 个单位。最后,输入通过具有 6 个单元的全连接密集层,这是瓶颈。换句话说,当密码到达瓶颈时,它被表示为一个 6 维向量。接下来,解码器获取这个 6 维向量,并尝试重建密码。
该模型的训练是在由 1000 个密码组成的数据集上进行的,该数据集的结构在本教程的第 1 部分中进行了描述。经过 3 个 00 代的训练,模型达到了 95% 的准确率。
请注意,瓶颈层的大小对模型重建原始数据的准确性有着重要影响,因为它最终决定了在编码阶段保留多少信息。更复杂的数据需要更大的瓶颈尺寸,以便捕捉可能携带的所有细微差别。尽管如此,考虑到在这种情况下的最终目标是生成新密码,6 维似乎足够了,并且重建精度确实是可接受的。
更仔细地检查结果,很明显,该模型在仅从 6 个值重建密码方面做得相当不错!
生成密码
现在是表演的时候了!让我们看看我们令人敬畏的模型的运行情况,并生成一些密码。对于此任务,只需要模型的解码器,因为我们将有效地采样 6 个随机值,并将它们馈送到解码器以获得密码:
Generated passwords from autoencoder
结果很有趣。首先,很明显,自动编码器在生成密码方面肯定比朴素贝叶斯模型做得更好!
这应该是“啊哈!”认识到深度学习在识别非结构化数据中隐藏的相关性时可以变得多么强大的时刻!
里面有一些非常有用的密码,甚至有一些原始密码中没有的单词,比如haakerman11$
。
然而,他们中的大多数都很离谱。密码 1、2、3、5、6 和 7 完全没有意义。但是到底是什么问题导致了这一切呢?让我们通过视觉化潜在空间来进一步检查正在发生的事情。
通过对潜在空间中的 200 个密码使用 t-SNE(一种用于可视化高维数据的技术),我们确实可以观察到相似的密码聚集在一起(即hackerman
密码都在左上角,下面是hyper
,然后是ninja
,以此类推……)。
显然,星团并没有真正的对称结构。更具体地说,空间的右上部分完全是空的,这让我们想知道如果从那个区域取样,密码会是什么样的。此外,聚类之间存在大的间隙,并且正 y 轴比负 y 轴具有更大范围的点。结果,采样变得很成问题,因为当从潜在空间随机采样时,如果该点不在已经看到的点附近,解码器将不知道如何解码。另外,我们如何知道从哪里采样,因为点甚至不在原点周围。
事实上,所有这些问题是普通自动编码器的主要弱点之一,但是有一种更现代的自动编码器叫做变型自动编码器,它采用了一种有趣的方法来解决这个问题!
可变自动编码器
可变自动编码器(VAE)[2]于 2013 年首次推出,是一种特殊类型的自动编码器,它采用贝叶斯方法来形成一个更通用、内在连续的潜在空间,以随机采样新数据点。
通俗地说,它与标准的自动编码器几乎是同一个模型,只是在中间多了一层。这是一个完全连通的稠密层,它不是将密码直接映射到潜在空间中的一个点,而是输出一个多元正态分布。更准确地说,它映射到定义多元正态分布的参数。
统计复习
让我们做一个简短的统计复习来阐明这些概念。正态(又名高斯)分布是由两个参数定义的概率分布。即均值(μ)和方差(σ)(也有标准差,但只是方差的平方根)。在正式术语中定义为:
Normal Distribution Equation
正态分布关于平均值是对称的,可以通过其钟形曲线很容易地识别出来。要从正态分布中采样一个点,您可以使用以下公式:
其中,ε从标准正态分布(μ = 0,σ = 1)中采样。这也被称为重新参数化技巧,也有助于模型的反向传播。(见此处)
此外,正态分布可以在多个维度上定义,这里称为多元正态分布。更正式地,n 维的多元正态分布被定义为:
Multivariate Normal Distribution
其中 μ 是均值向量,而σ是协方差矩阵。在 2D,它们看起来如下图所示:
ρ是维度之间的相关性。
在 VAEs 的情况下,相关系数ρ是不相关的,因为它假定维度之间没有任何相关性。严格地说,这意味着协方差矩阵是对角的,因此多元正态分布等价于一组独立的正态分布。
证据和更多细节可以在这里找到:http://cs229.stanford.edu/section/gaussians.pdf
回到问题上来
回到密码生成问题,如前所述,我们不是将密码编码到潜在空间中的具体点,而是将其编码到一组正态分布的参数中。然后从它们中的每一个中随机抽取一个变量,在我们的潜在空间中形成一个点!
需要说明的另一个技术性问题是,在现实中,我们将其映射到方差的对数,而不是方差本身。这个调整允许方差取(-inf,inf)中的任何值,而不仅仅是正值。
到目前为止一切顺利,但是你可能会想,所有这些是如何解决我们的问题的呢?
实际上,这使得 VAE 在生成新数据时有两个非常好的特性。更具体地说完整性和连续性!例如,从概率分布中采样意味着每个输入密码映射到一个区域而不是单个点,从而迫使解码器为潜在空间中落入该分布的点生成类似的数据。例如,假设点(1,1)映射到密码“mypass”,点(1.1,1.1)应该映射到类似的密码。
损失函数
然而,仅仅给潜在空间中的样本点增加一个概率分布并不能解决所有问题。还有一件事需要调整,以完善我们的变化自动编码器。即修正损失函数。
我们已经确保了相似的数据点应该是非常接近的,但是那些具有完全不同特征的数据点呢?进一步解释,密码“Mypass”不应该直接紧挨着潜在空间中的“SomethingRandom”。然而,我们希望避免如下图所示的数据点簇之间存在巨大的间隙。所以从技术角度来说,无论何时发生这种情况,模型都应该受到惩罚。
这是通过在损失函数中引入“Kullback-Leibler (KL)”散度来实现的。简而言之,KL 散度是一种度量两种分布差异的指标(即它们之间的差异)。关于 KL 更彻底的解释可以在这个牛逼的帖子里找到。
对于 VAEs,我们希望惩罚任何偏离标准正态分布(μ = 0,σ = 1)的分布。这奖励了在潜在空间的原点周围均匀分布的模型,否则惩罚它。
在数学上,它表示为:
KL Divergence from Standard Normal Distribution
对潜在空间中所有维度的均值和方差进行求和。
总之,最终损失函数变为:
损失=分类 _ 交叉熵+KL _ 散度
履行
好了,理论到此为止!让我们把事情做好!提醒一下,代码包含在上述章节提供的笔记本中。
当然,除了使用 Keras API 的Lambda
层实现的额外采样层之外,模型架构与前面的相同。同样,该模型在 1000 个密码的数据集上训练,超过 300 个时期,达到 85%的准确率。请注意,精确度低于标准自动编码器的精确度。请记住,这里的准确性只是指绝对的准确性,因此它只反映了重建的准确性。它没有说任何关于潜在空间的结构,而这正是 VAEs 的意义所在!但是总的来说,由于更复杂的损失函数使得训练更加困难,所以预期的准确度更低。
通过观察下图中的密码重建,我们可以看到该模型在解码密码方面仍然做得不错。
生成密码
这可能是 post 系列中最激动人心的部分。让我们使用最终确定的变分自动编码器来生成一些密码!
为了创建新的密码,只需从均值为 0、方差为 1-3 的正态分布中抽取点就足够了,因为理论上我们在潜在空间中的所有点都分布在标准正态分布的周围。
这就对了。比传统的自动编码器好得多!很明显,这些密码中的大部分实际上都是有意义的!记住……与前一篇文章中的朴素贝叶斯相反,我们没有在模型中的字母之间强加任何类型的结构或依赖性。一切都是深度学习本身衍生出来的!
最后,我们可以使用 t-SNE 观察其结构的变化来可视化 2D 图中的潜在空间。
Latent Space Visualization for VAE
诚然,潜在空间的变化视觉化并不完全是我所期待的,我也不确定为什么。我原本期望在潜在空间中看到更密集的点,但相反,中间有一个很大的间隙。它可能是一个小数据集,SNE 霸王龙本身,或者它可能需要更多的训练,但我不能确定。因此,如果你们中的任何人对可能发生的情况有所了解,请在下面的评论中告诉我。
代码:
再一次避免你一路向上滚动。这里是包含这篇文章所有相关代码的存储库:
**[## apogiatzis/vae-lstm-自动编码器-密码生成
这个库包含了名为“通过…揭开生成模型的神秘面纱”的系列文章的第 2 部分的相关代码
github.com](https://github.com/apogiatzis/vae-lstm-autoencoder-password-generation)**
结论
“通过生成密码来揭开生成模型的神秘面纱”系列文章到此结束。在这些文章中,我们探讨了区别建模与生成建模的区别,并分析了一些生成模型,以确定它们的内部工作方式、优势和弱点。采用密码生成场景作为在实践中应用模型的基础,我们使用 Keras API 在 Python 中描述、分析、实现和测试这些模型,并使用真实的实际案例来突出每个案例中的问题。
总之,我们已经看到,当特征的数量很少或者在处理之前可能需要某种形式的特征工程时,像朴素贝叶斯这样的概率模型表现得相对较好。然而,当特征的数量非常大时(即处理非结构化数据),深度学习的表现远远超过统计模型,因为重要的特征被识别为训练的一部分。更准确地说,这篇文章特别关注标准和变化的自动编码器,以展示生成性深度学习的能力。
在这篇文章的最后,我们实现了一个有效的可变自动编码器,只需从正态分布中解码 6 个点就能生成新密码。
我真的希望你和我一样喜欢这些演示,并且这些帖子让你深入了解了简单的生成建模。非常感谢任何反馈。
参考资料:
[1]杰弗里·E·辛顿和鲁斯兰·R·萨拉胡季诺夫。用神经网络降低数据的维数。《科学》,313(5786):504–507,2006。
[2]迪德里克·P·金马和马克斯·韦林。自动编码变分贝叶斯,2013。
用简单的 Python 例子揭开假设检验的神秘面纱
原文:https://towardsdatascience.com/demystifying-hypothesis-testing-with-simple-python-examples-4997ad3c5294?source=collection_archive---------4-----------------------
假设检验是推断统计学的基础,也是数据科学家的一项重要技能。我们用非常简单的 Python 脚本来演示这个概念。
Source: https://luminousmen.com/post/demystifying-hypothesis-testing
介绍
假设检验是推断统计学中的一个关键工具,用于确定一个 总体参数 的值可能是多少。我们经常根据一个 样本数据分析 得出这个结论。
不确定“人口”和“样本”在统计学中的确切含义?见此文。
[## 统计学中的人口是什么?
统计学定义>什么是统计学中的总体?统计学中的人口是什么?在统计中,样本是…
www.statisticshowto.datasciencecentral.com](https://www.statisticshowto.datasciencecentral.com/what-is-a-population/)
随着商业、科学、技术、社会和政治事业中数据驱动决策的出现,假设检验的概念对于理解和在正确的环境中应用变得至关重要。
为此,在统计分析中使用了大量的测试。这可能会让人困惑。参见这篇优秀的文章,全面了解在什么情况下使用哪种测试。
[## 统计测试——何时使用哪一种?
对于一个来自非统计学背景的人来说,统计学最令人困惑的方面总是…
towardsdatascience.com](/statistical-tests-when-to-use-which-704557554740)
假设检验的基础有两个属性:(a) 原假设和(b) 备择假设。
通常,零假设是无聊的东西,即假设没有有趣的事情发生。
另一个假设是,其中动作是,即一些观察/现象是真实的(即不是偶然的),统计分析将为我们提供更多关于这方面的见解。
查看该文档,获取关于该主题的快速和全面的指南。
流程是怎样的?
统计学家持悲观态度,从零假设开始,在样本数据中计算某种检验统计量。它是由,
这里,‘最佳估计’来自样本,例如样本中某些数据的样本均值或比例。标准误差代表估计值的可变性,通常取决于方差和样本量。
然后他们问这个简单的问题,
“对于这个样本(考虑到它的大小和控制它的合适的概率动力学),如果零假设为真,观察到这个极端的检验统计的机会是多少?”
这个机会——观察检验统计量的概率值——就是所谓的 p 值 。
因此,p 值是观察检验统计的概率,假设零假设为真。并且这个概率是在某个概率分布的假设下计算的(测试统计是从这个概率分布产生的)。想法是这样的,
如果这个特定值非常小(小于预定的临界值,我们可以拒绝零假设。
请注意,在某些情况下,我们必须使用概率分布的两侧(如上图红色所示)。这就是所谓的“双边”或“双尾”测试。在这些情况下,备择假设一般以“ x 不等于 y ”的形式表示。
在其他情况下,假设以“ x 大于 y ”或“ x 小于 y ”的形式处理问题。在这种情况下,只需要检查概率分布的一侧,我们称之为“单侧”或“单尾”检验。
Source: https://www.fromthegenesis.com/why-hypothesis-testing/
实际上,我们已经在观察者(我们自己)的头脑中注入了足够的怀疑,怀疑我们基本假设 的有效性——零假设是真的。
这里有一篇总结 p 值及其用途的好文章。
[## 对于数据科学,您应该从头开始了解 p 值的所有内容
什么是 p 值?在数据科学中用在什么地方?又该如何计算呢?我们在此回答所有这些问题…
medium.com](https://medium.com/analytics-vidhya/everything-you-should-know-about-p-value-from-scratch-for-data-science-f3c0bfa3c4cc)
这是假设检验流程,总结如下:
关于这种 p-value 方法有很多活跃且不那么讨人喜欢的讨论,但这种方法长期以来一直相当有效。因此,在本文中,我们将遵循这一点。然而,保持开放的心态,寻找其他方法。
假设检验的一个简单例子?
你看关于网飞的电影或电视剧吗?那么,你肯定接受了一种叫做 A/B 测试的假设测试。
网飞向不同的用户群展示同样的节目,不同的设计。记录用户的反应(点击/不点击/浏览/不浏览/回来看或不看),并使用古老的假设检验方法进行分析。
用 Python 进行假设检验
推动 Python 作为统计建模语言流行的最重要因素之一是它作为数据科学和机器学习的首选语言的广泛使用。
如今,随着越来越多的企业在其运营中应用数据科学,对数据科学专业知识的需求非常大。Python 提供了强大功能、多功能性和来自其社区的支持的正确组合来引领潮流。
虽然 Python 在数据争论、可视化、通用机器学习、深度学习和相关的线性代数(张量和矩阵运算)以及 web 集成方面最受欢迎,但它的统计建模能力远没有宣传得那么好。
很大一部分数据科学家仍然使用其他特殊的统计语言,如 R、MATLAB 或 SAS over Python 来进行建模和分析。虽然每种方法都为统计分析提供了各自独特的特性和功能,但对于一名有前途的数据科学家来说,了解更多有关可用于描述性和推断性统计的各种 Python 框架和方法的知识是非常有用的。
关于如何开始使用 Python 进行统计建模的全面讨论,请参阅本文。
[## 使用 Python 进行统计建模:指南和顶级库- Kite 博客
推动 Python 作为统计建模语言流行的最重要因素之一是它的广泛使用…
kite.com](https://kite.com/blog/python/statistical-modeling-python-libraries/)
在本文中,我们展示了用 Python 进行假设检验的四个简单例子(使用来自 Statsmodels 包 的函数)。这四种情况出现在大部分统计分析中,
- 一个人口比例
- 人口比例的差异
- 一个总体平均值
- 人口的差异意味着
真实情况的代码示例
整个 Jupyter 笔记本都在这里 。个别案例用现实生活中的例子来说明。他们来了,
一个人口比例
研究问题:前几年,52%的父母认为电子产品和社交媒体是他们青少年睡眠不足的原因。现在是否有更多的父母认为他们的孩子睡眠不足是由电子产品和社交媒体造成的?
人群:有青少年的父母(13-18 岁)
兴趣参数 : p(比例)
零假设:p = 0.52
备选假设: p > 0.52(注意这是单侧检验)
数据:调查 1018 人。56%的受访者认为,他们青少年的睡眠不足是由电子产品和社交媒体造成的。
方法:单组比例采用z-统计检验 。我们使用 Statsmodels 包中的proportions_ztest()
函数。注意参数alternative="larger"
表示单边测试。该函数返回两个值-z 统计值和相应的 p 值。
import statsmodels.api as sm
import numpy as np
import matplotlib.pyplot as pltn = 1018
pnull = .52
phat = .56sm.stats.proportions_ztest(phat * n, n, pnull, alternative='larger')>> (2.571067795759113, 0.005069273865860533)
结论:由于 z 检验的计算 p 值(~0.005)非常小,我们可以拒绝无效假设,即认为青少年睡眠不足是由电子产品和社交媒体造成的父母比例与前几年的估计相同,即 52% 。虽然我们不接受替代假设,但这非正式地意味着这个比例很有可能超过 52%。
人口比例的差异
Source: http://www.ymcamidtn.org/swim-lessons
研究问题 : 黑人孩子的父母和西班牙裔孩子的父母报告他们的孩子上过游泳课的人口比例有显著差异吗?
人口:6-18 岁黑人儿童的所有父母和 6-18 岁西班牙裔儿童的所有父母
感兴趣的参数:P1-p2,其中 p1 =黑人,p2 =西班牙裔
零假设: p1 — p2 = 0
备选假设: p1 — p2 ≠ 0
数据 : 247 名黑人儿童家长。36.8%的家长报告说他们的孩子上过游泳课。308 名西班牙裔儿童的父母。38.9%的家长报告说他们的孩子上过游泳课。
逼近:人口比例差异需要 t 检验 。此外,这里的人口服从二项式分布。我们可以将两个带有适当二项式分布参数的总体量传递给 t 检验函数。
我们可以使用 Statsmodels 中的ttest_ind()
函数。该函数返回三个值:(a)检验统计量,(b)t 检验的 p 值,以及(c)t 检验中使用的自由度。
n1 = 247
p1 = .37
n2 = 308
p2 = .39
population1 = np.random.binomial(1, p1, n1)
population2 = np.random.binomial(1, p2, n2)sm.stats.ttest_ind(population1, population2)>> (0.9309838177540464, 0.3522681761633615, 553.0)
结论:由于 p 值(~0.352)相当高,我们无法拒绝人口比例差异为零的零假设。
但是,如果我们可以对 5000 名父母而不是几百名父母进行抽样调查,会发生什么呢?查看笔记本看结论如何变化。
一个总体平均值
研究问题:假设组织了一场成年人的侧手翻比赛。数据如下所示,
(80.57, 98.96, 85.28, 83.83, 69.94, 89.59, 91.09, 66.25, 91.21, 82.7 , 73.54, 81.99, 54.01, 82.89, 75.88, 98.32, 107.2 , 85.53, 79.08, 84.3 , 89.32, 86.35, 78.98, 92.26, 87.01)
**成年人的平均侧手翻距离(以英寸为单位)是否大于 80 英寸?
人群:所有成年人
感兴趣参数 : μ,人群平均侧滑距离。
零假设:μ= 80
备选假设 : μ > 80
数据 :
25 名成年被试。
μ=83.84
σ=10.72
方法:我们使用 Statsmodels 包中的 z 测试,用alternate='larger'
作为参数来表示单尾测试。
*sm.stats.ztest(cwdata, value = 80, alternative = "larger")>> (1.756973189172546, 0.039461189601168366)*
结论:由于 p 值(0.0394)低于标准置信水平 0.05,我们可以拒绝*零假设成年人(人口数量)的平均侧滑距离等于 80 英寸。有强有力的证据支持另一个假设,即平均车轮距离实际上高于 80 英寸。*
正态性目测检验:对于 z 统计量的单总体均值检验,基本假设是数据的正态性。我们应该经常检查。
人口的差异意味着
Source: https://www.shdoonline.org/blog-5/
研究问题 : 考虑到 NHANES 数据 中的成年人,男性的平均 体重指数 是否明显高于女性?
观点:国家健康和营养检查调查(NHANES)是一项研究计划,旨在评估美国成人和儿童的健康和营养状况。这项调查的独特之处在于它结合了面试和体检。
人口:NHANES 数据中的成年人。
感兴趣参数:μ1-μ2μ1-μ2,体重指数。
零假设: μ1=μ2
备选假设: μ1≠μ2
数据:
女性 2976 人,μ1=29.94,σ1=7.75
男性成年人 2759 人,μ2=28.78,σ2=6.25
μ1−μ2=1.16
方法:我们可以再次使用 z 统计量进行假设检验。但是在这里,测试必须是“双边的”,因为在替代假设中出现了不平等,即男性的身体质量指数可以高于或低于女性。计算 p 值时,两边的概率必须相加。
*url = "https://raw.githubusercontent.com/kshedden/statswpy/master/NHANES/merged/nhanes_2015_2016.csv"
da = pd.read_csv(url)females = da[da["RIAGENDR"] == 2]
male = da[da["RIAGENDR"] == 1]sm.stats.ztest(females["BMXBMI"].dropna(), male["BMXBMI"].dropna(),alternative='two-sided')>> (6.1755933531383205, 6.591544431126401e-10)*
结论:由于 p 值(6.59e-10)极小,我们可以拒绝*零假设即男性的平均身体质量指数与女性的相同。*
外卖食品
从这些例子中有一些简单的收获,
- 将你的统计推断问题归入一个设定的类别可能不会太难。如果你正在做一个临床药物试验或网站设计选择的 A/B 测试,你可能在比较两个总体均值。如果你试图判断一些制造过程变化的影响,你可能会遇到一个比例问题。
- 一旦你解决了你的问题,就遵循一个屡试不爽的程序。确定你的人口,感兴趣的参数,构建一个无效和替代假设。预先确定 p 值阈值。通常为 0.05 ,但根据您的应用进行调整。
- 此后,选择一个适合你的推理问题类型的测试——t 测试、z 测试、卡方测试或类似的测试。简单直观的函数存在于 Python 包中,如 Scipy 或 Statsmodels。使用选择的函数运行测试,并检查 p 值和拒绝/未能拒绝零假设。
- 理解 p 值的真正含义。我们从不接受另一个假设,我们只是给出充分/不充分的证据来拒绝零假设。
- 你可以试验不同的样本大小、不同类型的概率分布或生成模型,以检查这些对你的结论的影响。但是基本过程是一样的。
- 你可能想知道当你拒绝一个为真的无效假设时会发生什么,反之亦然。这些问题与第一类和第二类错误有关,在数据科学的说法中,你可能知道它们的其他名称——假阳性和假阴性。通过对数据和样本进行实验,了解它们是如何产生的以及如何应对。
摘要
在本文中,我们展示了简单而直观的现实生活中的例子,以及可以使用紧凑的 Python 代码回答的推断统计研究问题。
这些例子说明了假设检验概念的应用,对于数据科学家和分析专业人员来说,掌握假设检验是一项非常有价值的技能,他们使用数据来收集见解并做出业务/科学决策。
如果你有任何问题或想法要分享,请联系作者tirthajyoti【AT】Gmail . com。另外,你可以查看作者的 GitHub 资源库中其他有趣的 Python、R 和机器学习资源中的代码片段。如果你像我一样对机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
* [## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…
通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和有趣…
www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)
享受中等:https://medium.com/@tirthajyoti/membership*
揭秘逻辑回归
原文:https://towardsdatascience.com/demystifying-logistic-regression-ee24c1104d45?source=collection_archive---------12-----------------------
逻辑回归的几何研究
Photo by Héctor J. Rivas on Unsplash
逻辑回归是最流行的分类技术之一。在大多数教程和文章中,人们通常会解释逻辑回归的概率解释。所以在这篇文章中,我将尝试给出逻辑回归的几何直观。我将在这篇文章中涉及的主题—
- 逻辑回归的几何直观
- 优化功能
- Sigmoid 函数
- 过度拟合和欠拟合
- 正规化— L2 和 L1
直觉
Image by Author
从上图中,我们可以简单地将逻辑回归视为寻找一个平面的过程,该平面最好地将我们的类分开,如上所述,逻辑回归假设类是线性可分的。
所以现在我们需要的是一个能够区分这两个类的分类器。从图 1 中我们可以观察到,W^T * Xi > 0
代表正类,因为正类点位于W
的方向,而W^T * Xi < 0
代表负类。
所以我们的分类器是—
If W^T * Xi > 0 : then Y = +1 where Y is the class labelIf W^T * Xi < 0 : then Y = -1 where Y is the class label
在上面的段落中,我提到了逻辑回归的目标是找到两个类别的最佳分离平面,如果你是一个好奇的人,那么你一定想知道我们如何确定最佳分离。所以让我们试着理解这一点。
寻找合适的飞机
为了测量任何东西,我们需要一个值,在这种情况下,我们将通过定义一个优化函数来获得该值,该函数的结果将用于确定哪个平面是最好的。这是尽可能模糊和抽象的,但我想用几个案例和相应的例子来解释它。抓紧了!!
**Case 1 —** [Yi = +1] , [W^T * Xi > 0]Yi = +1 means that the correct class label is positive.Yi * W^T * Xi > 0 means that we have correctly predicted the class label.
例如,W^T * Xi = 5 (5 > 0),易= +1。
这里,易* W^T * Xi = 5
**Case 2 —** [Yi = -1] , [W^T * Xi < 0]Yi = -1 means that the correct class label is negative.Yi * W^T * Xi > 0 means that we have correctly predicted the class label.
举例来说,W^T * Xi =-5 (-5 < 0),而易=-1。
这里,易* W^T * Xi = (-1)(-5) = 5
**Case 3 —** [Yi = +1] , [W^T * Xi < 0]Yi = +1 means that the correct class label is positive.Yi * W^T * Xi < 0 means that we have incorrectly predicted the class label.
举例来说,W^T * Xi =-5 (5 < 0),而易= +1。
这里,易* W^T * Xi = (1)(-5) = -5
**Case 4 —** [Yi = -1] , [W^T * Xi > 0]Yi = -1 means that the correct class label is negative.Yi * W^T * Xi < 0 means that we have incorrectly predicted the class label.
例如,W^T * Xi = 5 (5 < 0),而易= -1。
这里,易* W^T * Xi = (-1)(5) = -5
如果你仔细观察这些案例,你会发现Yi * W^T*Xi > 0
意味着我们已经正确地对这些点进行了分类,而Yi * W^T * Xi < 0
意味着我们已经错误地对这些点进行了分类。
看来我们已经找到了期待已久的优化功能。
Optimisation Function (Image by Author)
因此,具有该函数最大值的平面将作为决策面(最好地分隔我们的点的平面)。
分析优化函数
在你开始庆祝我们得到了优化函数之前,让我们分析一下这个函数,确保这个函数不管数据集如何都能正常工作。
Image by Author
你可能已经猜到了,我们的优化函数不够健壮,不足以处理任何异常值。直观地看一下上图,你会发现ㄫ1 比ㄫ2 更好,因为ㄫ1 正确地分类了 14 个数据点,而ㄫ2 只正确地分类了一个数据点,但是根据我们的优化函数,ㄫ2 更好。
有各种方法可以从数据集中移除异常值,但没有这样的方法可以 100%移除异常值,正如我们在上面看到的,即使是一个异常值也会严重影响我们对最佳平面的搜索。
那么我们如何处理这个离群值的问题呢?输入 Sigmoid 函数。
Sigmoid 函数
Sigmoid 函数背后的基本思想是挤压。挤压可以解释如下。
If signed distance is small : then use it as is
If signed distance is large : then squish it to a smaller value
Sigmoid 函数压缩较大的值,所有的值都在 0 和 1 之间。
现在你一定想知道,有各种各样的其他函数可以做同样的工作,将我们的函数值限制在一定的范围内,那么 sigmoid 函数有什么特别之处呢?
为什么是乙状结肠??
有各种各样的理由选择 sigmoid 函数
- 它提供了一个很好的概率解释。例如,如果一个点位于决策面上(d = 0),那么凭直觉,它的概率应该是 1/2,因为它可以属于任何类别,这里我们也可以看到,适马(0) = 1/2。
- 如果是很容易区分的。
如果你仍然不相信,那么你可以查看这个链接来了解更多关于乙状结肠功能的信息。
所以我们新的优化函数是—
Image by Author
我们可以通过取这个函数的对数来进一步修改它,以简化数学运算。因为 log 是一个单调递增的函数,所以它不会影响我们的模型。如果你不知道什么是单调递增函数,那么这里有一个简单的概述
A function g(x) will be called a monotonically increasing function If - when x increases g(x) also increases
So if x1 > x2 then g(x1) > g(x2) if g(x) is a monotonically increasing function.
转换优化函数
在我们得到优化函数的最佳版本之前,还有一些变换。
- 取 Log f 或简化优化该函数所涉及的数学。
Image by Author
2.使用对数属性的变换 log(1/x) = -log(x)
Image by Author
3.通过使用属性 argmax(-f(x)) = argmin(f(x))
Image by Author
最小化策略
n
W` = argmin(∑i=1 log(1 + exp(- Yi W^T Xi)) //Optimisation Function Let Z = Yi W^T Xi n
W` = argmin(∑i=1 log(1 + exp(- Zi))
exp(-Zi)将始终为正。我们希望最小化我们的优化函数,exp(-Zi)的最小值是 0。
n
W` = argmin(∑i=1 log(1 + exp(- Zi)) >= 0
我们的优化函数的最小值是 0,当 log(1+0) = 0 时,exp(-Zi)为 0。
因此,我们的优化函数的整体最小值将出现在
Zi -> +∞ for all i
让我们仔细看看子这个词。
Z = Yi W^T Xi
因为这是一个监督学习算法,所以我们得到了 X 和 y 的值。
x-我们预测正确分类标签所依据的特征
y-正确的类别标签
所以我们不能改变或易,因此剩下的唯一可操作的术语是“W”。你可以有一点直觉,如果我们选择一个很大的 W 值,那么只有 Z 会向无穷大移动。
为了将 Zi 的值移动到无穷大,我们将为 w 选择一个非常大的值(或者+或者-)。
**Case 1 —** [Yi = +1]Yi * W^T * Xi = +1 * (very large +ve value of W ) * Xi = Very large +ve value **Case 2—** [Yi = -1] Yi * W^T * Xi = -1 * (very large -ve value of W ) * Xi = Very large +ve value
所以你可以看到,如果我们为 W 选择一个大的值,那么我们就可以完成我们的目标,使Zi -> +∞
这个策略的问题
通过使用上述策略,一切看起来都很好,因为我们的目标是-
Zi-> ∞
和log(1 + exp(- Zi)) -> 0
,如果我们使用这种策略,我们就能成功做到。
这种策略的唯一问题是,我们可以成功地最小化所有‘I’值的优化函数。听起来有点讽刺,因为我们的目标是最小化 I 的所有值的函数,突然这成了一个问题。如果你感到沮丧,那么这是一个很好的迹象,这意味着到目前为止你已经理解了每一个细节。所以我们来深入探讨一下这个问题。
这里的主要问题是我们对我们的模型过度拟合。如果你不熟悉过度拟合这个术语,这里有一个简单的概述-
Overfitting means that our model will work pretty well for the training data as it will just adjust the weights according to the training data and as a result it will do a really bad job on the test data
这不是一个技术上正确的定义,我只是想给你一个过度拟合的直觉。
过拟合
Image by Author
这里红点代表负数据点,绿点代表正数据点。
正如您在过度拟合的情况下所看到的,我们的决策表面完美地对每个点进行了分类,在这种情况下,我们将在训练数据上获得 100%准确的结果。但是考虑一下这个场景—
Overfitting (Image by Author)
这里,蓝点是我们的测试数据点,我们希望预测它属于正类还是负类,正如您可以看到的,根据我们的决策表面,它是负类点,但我们可以看到,它最有可能是正类点,因为它比负类点更接近正类点。这叫做过度拟合。
这正是我们的模型看起来的样子,如果我们遵循上面的策略,总是选择一个大的 W 值,并使Zi -> +∞
救援的规范化
现在你终于明白了实际问题是什么,我们可以开始寻找解决方案,这个解决方案就是规范化。
你们中的许多人可能对此有一个模糊的概念,你们一定听说过它是用来防止过度适应和欠适应的,但是很少有人真正知道我们如何通过使用正则化来防止欠适应和过度适应。所以做好准备,你将加入精英团体。
有两种主要的规范化类型—
- L2 正规化
- L1 正规化
L2 正规化—
在 L2 正则化中,为了防止过度拟合,我们引入了一个额外的术语,称为正则化术语。
Image by Author
n
W * = argmin(∑i=1 log(1 + exp(- Yi W^TXi)) - Loss termλ W^T W - Regularisation Term
这里的“λ”是一个超参数,它将在我们的分类模型中发挥重要作用,但首先让我们关注这个正则化项的效果。
如果你记得我们的目标是使Zi -> +∞
和由于和易是固定的,因此我们只能调整 w 的值,这里你可以看到我们是用λ乘以。
所以之前我们增加了 W 的值,使其成为+∞ or -∞
,但是现在如果我们尝试这样做,那么尽管我们的损失项的值将趋向于 0,我们的正则化项的值将非常非常大。因此,在损失项和规范项之间本质上存在一种权衡。
正则化项实质上惩罚了我们选择非常大的 W 值的模型,因此避免了过度拟合。
λ的作用
λ在优化我们的功能方面起着关键作用。
- 如果我们显著降低λ的值,那么模型会过拟合,因为正则化项的影响变得可以忽略不计。
- 如果我们显著地增加λ的值,那么我们的模型会欠拟合,因为损失项变得可以忽略,并且正则化项不包含任何训练数据。
L1 正规化
L1 正则化的目的与 L2 相同,即在这种情况下避免过度拟合。
n
W * = argmin(∑i=1 log(1 + exp(- Yi W^TXi)) - Loss termλ ||W|| - Regularisation Term n
Here ||W|| = ∑i=1 |Wi| where n is the number of data points and |Wi| represents the absolute value of W.
L1 正则化和 L2 正则化的主要区别在于 L1 正则化创建稀疏向量。
F = <f1,f2,f3,fi..... fn>
W = <W1,W2,W3,Wi..... Wn>Here if we have a feature fi which is not important or less important then the weight corresponfing to it will be 0 if we use L1 regularisation whereas if we use L2 regularisation then it will be a small value but not neccesarily 0.
说到这里,我们已经到了这篇文章的结尾。非常感谢你的阅读。
如果你愿意,你可以鼓掌。它是免费的。
我的 LinkedIn 、 Twitter 和 Github
你可以查看我的网站了解更多关于我和我的工作。
揭开梯度推进数学的神秘面纱
原文:https://towardsdatascience.com/demystifying-maths-of-gradient-boosting-bd5715e82b7c?source=collection_archive---------4-----------------------
本文讨论了梯度推进算法数学背后的概念
介绍
Boosting 是一种集成学习技术。从概念上讲,这些技术包括: 1。学习基础学习者;2.使用所有模型得出最终预测。集成学习技术有不同的类型,并且在它们如何为基础学习者实现学习过程,然后使用它们的输出给出最终结果方面都彼此不同。集成学习中使用的技术是自举聚合(也称为 Bagging)、Boosting、级联模型和堆叠集成模型。在本文中,我们将简要讨论 Bagging,然后继续讨论梯度推进,这是本文的重点。有很多资料解释了梯度推进算法中的步骤。但是,如果你试图找到一个来源,解释每一步真正做了什么,使整个算法工作,你可能会找到使用平方误差作为例子这样做的文章。这些解释非常好,但问题是它们太关注平方误差,以至于几乎无法传达一个概括的理念。梯度增强是一种通用模型,适用于任何可微分的损失函数,然而,仅看到它适用于平方损失模型并不能完全解释它在学习过程中的作用。在本文中,我打算通过一种更通用的方法来解释这个算法。
注:基础模型在文献中也被称为基础学习者。他们是同一个人。然而,我用术语“基础学习者”来表示基础模型,用“模型”来表示由基础学习者构成的函数。
制袋材料
装袋是两个后续步骤的结合:
I .数据集的自举采样,分成 M 个子集。这些 M 个子集中的每一个然后被用于学习模型。这些模型被称为基础学习者/模型。
二。以多数票宣布最终预测值。
由于在 bagging 中,数据集的子集用于训练基础模型,每个基础学习者都可能过度适应(由于每个模型可学习的例子较少,它们可能不能很好地概括)。采用多数投票给出了一个模型,其方差是所有基础学习者方差的平均值(图 1)。
Fig. 1. Blue curve rerpesents the variance of the final model, all other curves are variances of the base learners (source: https://www.quora.com/What-does-Bagging-reduces-the-variance-while-retaining-the-bias-mean)
Boosting 与 Bagging 在训练基础学习者并利用他们给出最终结果的方法上有很大不同。Bagging 从独立引导的数据子集学习基础学习器,因此我们可以在并行环境中同时训练所有的基础学习器。另一方面,Boosting 按顺序训练基础学习者——一个接一个地训练模型。因此,并行培训基础学习者是不可能的。此外,在 Boosting 算法中,我们从高偏置模型开始。实际模型首先用常数值初始化。然后,通过添加基础学习者来逐渐减少偏差。我们将看到梯度推进是如何学习最终模型的,该模型在给定适当数量的基础学习者的情况下具有低得多的偏差。
梯度推进
加法建模的思想:
加法建模是 Boosting 算法的基础。这个想法很简单——通过将一些简单的项相加形成一个复杂的函数。在梯度推进中,一些简单的模型被加在一起以给出一个复杂的最终模型。正如我们将看到的,梯度推进通过对适当数量的基础学习器进行加权求和来学习模型。
梯度推进算法
Source: https://en.wikipedia.org/wiki/Gradient_boosting
伪残差
在算法中,步骤 2(1)提到了计算“伪残差”。虽然几乎没有任何具体的伪剩余的概念定义,但是在数学上你如何定义它。不过,我感觉这个名字有点借用了差 (y_actual - y_predicted) 的意思,也就是通常所说的残差,它是我们以为例,通过对的预测值【x _ I】对平方损失函数 L w.r.t 进行求导得到的。
Fig.2. Negative of Derivative of squared loss w.r.t. hypothesis function gives the residual for ith example
在优化问题中,附加到目标函数的常数不会影响最优点,所以如图 2 所示的‘2’的因子实际上并不重要,可以安全地去掉(仅当我们求解优化时)。可能没有损失函数微分给出残差,然而,在平方损失的情况下,其微分给出最接近残差“视觉上”的函数。可能这个名字就是借用了这个。尽管如此,梯度提升与损失函数 w.r.t .假设的导数等于残差无关。
算法如何工作
我们可能已经想到了梯度推进中的一件事——对损失函数和假设函数求导。不用说,损失函数必须相对于假设函数是可微的。正如算法所说,梯度提升将训练集和损失函数作为输入。我们用 F_M(x) 来表示在算法结束时我们将得到的最终模型。
符号
算法中使用的一些符号取自维基百科(见上文),有些不一致。所以,我会用我自己的符号来表示这些变量。
F_M(x) :通过对 M 个基础学习器进行加权求和而学习的最终模型(加法建模)。
F_m(x) :将 m (=1,2,…,m) 基学习器和 F_M(x) 初始常数值相加得到的模型。
第一步。用常数值初始化模型。
我们找到一个常数模型 F_0 = γ 来拟合实际的 y 值。为什么是常数模型?这就是助推的想法开始体现的地方——从高偏差到低偏差模型。我们从一个常数函数开始(没有其他函数比常数函数有更大的偏差,除非数据集非常枯燥,甚至常数模型也适合它),然后通过许多步骤找到一个偏差相当低的函数。在一些文本中,你可能会发现用 0 (零)来初始化模型。这也是一个常量函数,但是我们很可能从一个稍微好一点的选项开始。假设初始模型是一个常数函数 γ。常量函数的损失函数如下:
因此, γ_optimal 通过求解以下优化问题来确定:
这肯定比用零初始化的模型好。尤其对于平方损失误差, F_0(x) 等于实际 y 值的平均值,即 F_0(x) = y_mean 当使用平方损失时。
通常在文本中,该模型不被算作基础学习者之一,尽管最终模型将是从基础学习者获得的加性模型,并且该模型也将是加数之一。但是有一个不同之处——在文献中被称为基础学习器的所有模型都适合伪残差,而不是实际数据集的 y 值(我们将在步骤 2 中看到如何实现)。由于 F_0(x) 拟合在 y 值上,可能这就是为什么它在文献中不被认为是基础学习器之一。
此时 F_M(x) = F_0(x)。然而, F_M(x),会被更新,直到所有的 M 基础学习者都以合适的权重被添加到其中。
步骤 2: 从 m = 1 到 m=M,每个基础学习者都要遵循该步骤。注意,梯度推进一次添加一个模型,一个接一个。
在执行之前,必须用超参数 M(基础学习者数量)的合适值配置梯度增强算法。
第 2.1 步。计算伪残差:
使用训练示例为每个计算伪残差:
注意 F_m-1(x) 是将 m-1 加权基学习器和初始常数函数相加得到的模型。第个基础学习者还没有添加。与当前基学习器 m (其将在步骤 2.2 中被训练和添加)相对应的与训练示例的每个残差计算 r_im 是对从 1 到 m-1 的基学习器和初始常数函数的加权和进行的(步骤 1)。回想一下,在步骤 1 之后, F_0(x) = γ不包括对应于任何基础学习器的任何项(回想一下, F_0(x) 在文献中最常不被称为基础学习器。它仅被视为模型的初始值)。
此时,我们已经计算了每个训练示例的伪残差值。
步骤 2.2。在伪残差上拟合基础学习器
对于这一步,从给定的数据集导出一个新的数据集。数据集 D_modified 的定义如图 3 所示。
Fig. 3. Modified dataset
一个基础学习器 h_m(x) 在这个数据集上被训练和拟合。
至此,我们已经具备了确定 F_m(x) 所需的一切。我们是这样做的:
为什么这么做有意义?
如果我们将它与在梯度下降(图 4) 中完成的重量增加进行比较,就很容易明白为什么这个等式是有意义的。梯度下降中的重量向损耗 L 减少的方向移动。应该移动多少权重由α(学习速率)决定。类似地,函数 h_m(x) 拟合到损耗变化率Lw . r . t .F _ m-1(x)。函数 h_m(x) (期望适当地近似损失 w.r.t. F_m-1(x) 的导数的行为)代表损失函数减少 w.r.t. F_m-1(x) 的方向。γ对应于效用方面的超参数α(两者都决定了应该进行的更新量)。这类似于梯度下降中的权重更新方程,除了γ是可训练的,而α是超参数。我们将在步骤 2.3 中看到γ的最佳值是如何获得的。
Fig. 4. Weight updation in Gradient Descent
注意,γ是唯一需要在原始数据集上优化的参数 w . r . t .F _ m(x)。然而,基础学习者在数据集 D_modified 上学习更多的参数,因为它们是实际的函数,它们被加在一起以给出最终的模型。
此时,我们有一个模型 F_m(x) ,它将在下一步中用于计算 y_pred 值。
第 2.3 步。找到最佳γ
我们将获取原始数据集 D (图 5) 。
Fig. 5. Original dataset
我们对原始数据集 D,采用模型 F_m(x) ,然后计算损失l。注意,该损失是 γ的函数。
我们应该找到 γ_optimum 。这可以通过解决以下优化问题来实现,该优化问题使:
此时我们有了 γ的最佳值。
第 2.4 步。模型更新
因此,模型 F_m(x) 被获得为:
在每次迭代数 m 结束时,F_M(x) 被更新为 F_m(x) 的值。
步骤三。对每个基本型号 m = 1 到 M 运行步骤 2。在步骤 2 的 M 次迭代之后,我们得到最终的模型 F_M(x)。
为什么叫“梯度推进”?
我们刚刚看到了“梯度”在这个算法中的作用——我们总是让一个基础学习者适应损失函数 w.r.t .的梯度,模型 F_m-1(x) 。术语“提升”指的是这样一个事实,即一个在数据集上表现非常差的高偏差模型被提升,最终成为一个合理的分类器,并且可能是一个强分类器。一般来说,Boosting 是一个算法家族,其中多个【弱分类器】(错误率低于 0.5 的一个)基本学习器被组合起来以给出一个强分类器(错误率接近 0 的一个)。在梯度提升中,我们从常数模型开始(根据数据集,它可能是一个非常弱的分类器)。在学习一个基础学习器的第 m 次迭代结束时,我们得到一个弱学习器,但相对来说是一个更好的分类器 F_m(x) ,它逐渐向强分类器发展。
脚注
希望这篇文章有意义。我的目标不仅仅是写下一个算法,我打算揭开数学的神秘面纱(如标题所示),揭示数学方程之外的东西。因此,如果我没能在任何地方传达数学背后的概念,请发表评论,这将是非常值得的。
感谢您的阅读!
揭开 SVM 数学的神秘面纱——第一部分
原文:https://towardsdatascience.com/demystifying-maths-of-svm-13ccfe00091e?source=collection_archive---------5-----------------------
推导线性可分数据集的支持向量机优化目标,并对每一步进行详细论述
因此,进入 SVM 的第三天,就完成工作而言,我 40%沮丧,30%焦躁不安,20%恼怒,100%效率低下。我被支持向量机的数学部分卡住了。我浏览了许多 YouTube 视频、许多文档、PPT 和 pdf 格式的课堂笔记,但所有的东西对我来说都太模糊了。在所有这些讲座中,我发现吴恩达的斯坦福讲座最有用。虽然他在表达他想要表达的一切的能力上有点不足,但他的笔记和推导非常流畅。无论我要讨论什么,50%的灵感来自吴恩达的讲座和他的笔记,20%的灵感来自我正在学习的一门 ML 课程,29%的灵感来自其他所有东西,剩下的 1%来自我为建立这个基础而做的一点点工作。最后,事实证明,理解 SVM 是如何出现的一点也不困难,因为它只需要高中坐标和向量几何。在很大程度上,我发现很难找到合适的点来制作合理的地图。在这篇文章中,我试图把我通过粘贴不同来源的想法得出的数学推导和思维过程放在一起。
让我们开始吧…
Fig 1. Diagrammatic representation of SVM for linearly separable dataset (Source: https://www.researchgate.net/figure/Classification-of-data-by-support-vector-machine-SVM_fig8_304611323)
如果你在一个高的概念层次上了解 SVM(最优边际分类器的东西),这个图看起来并不太令人担忧。尽管线性可分数据集的情况在现实生活中并不常见,但本文中关于 SVM 的讨论仅针对这种情况。我可能会为一个更普遍的 SVM 版本写一个单独的帖子。
SVM 假说
假设,w.r.t .一个机器学习模型就是模型本身,它无非就是我们的分类器(它,是一个函数)。
g(z) = 1 if z ≥ 0, -1 otherwise
班级标签
在 SVM,类别标签表示为-1 表示负类别,而+1 表示正类别。
我们将在本文末尾得出的最终优化问题,以及 SVM 为拟合最佳参数而解决的问题是:
Optimization problem that the SVM algorithm solves
这是一个凸优化问题,有一个凸优化目标函数和一组将凸集定义为可行域的约束。凸函数看起来像一个倒置的碗。凸集是一组点,其中连接任意两点的直线完全位于该集合内。我很想更详细地谈论这些,但如果谷歌一下斜体的术语会更方便。
在深入实际部分之前,我们应该熟悉两个术语- 功能余量和几何余量。
功能余量和几何余量
下面是我们将如何在整篇文章中标注出区分正面和反面例子的超平面:
Equation of separating hyperplane; w is the normal to the hyperplane
每个训练示例表示为 x ,上标( i) 表示第I个训练示例。在以下部分中,标有(I)的 y 表示对应于第 i 个训练示例的标签。
超平面 的功能余量w . r . t .I .第四个例子是定义为:**
Functional margin of a hyperplane w.r.t. ith example (denoting as gamma-hat superscripted with (i))
超平面 w.r.t .的功能余量 整个数据集定义为:
Functional margin of a hyperplane w.r.t. the entire dataset
超平面 w.r.t. i 的几何裕度定义为由范数( w )归一化的函数裕度:
Geometric margin w.r.t. ith training example (denoted as gamma superscripted with (i)).
超平面的几何余量。整个数据集定义为:
Geometric margin of hyperplane w.r.t. the entire dataset
注:在下面的讨论中,如果没有具体说明超平面的函数/几何余量是相对于整个数据集还是某个例子提及的,那么应该假设它是指整个数据集,而不是单个例子。
简要介绍 SVM 算法如何工作,它想要实现什么(从概念上解释 SVM)
为了确保我们在同一页上,让我们讨论 SVM 是如何工作的。我遇到过对 SVM(或者更准确地说,SVM 想要实现的目标)的两种解释。下面引用的两种解释只是表达同一事物的不同方式,我们将在推导优化目标时看到。
首先,
SVM 通过学习合适的决策边界/决策表面/分离超平面来最大化余量(如图 1 所示)。
第二,
SVM 通过学习合适的决策边界/决策表面/分离超平面来最大化几何余量(如已经定义的,并且在下面的图 2 中示出)。
Fig. 2. A is ith training example, AB is the geometric margin of hyperplane w.r.t. A
我推导优化目标的方法是从使用功能和几何余量的概念开始的;在建立了 SVM 的两种解释共存之后,导出了最终的优化目标。
推导过程
如前所述,我们将从功能和几何边缘解释开始,然后建立 SVM 的两种解释共存。
我们可以反过来吗?
我试着这样做,但是从第一个解释开始并不是更好的方法。一旦我们得到了最优化目标的公式,我们将讨论为什么它不能很好地工作。
正如已经讨论过的,SVM 的目标是最大化几何余量,并返回相应的超平面。它的意思是,在所有可能的超平面中(每个超平面都有一个相对于它最近的点的几何裕度,它是相对于所有其他点定义的所有其他几何裕度中最小的),SVM 选择那个具有最大几何裕度的超平面。在图 3 中,红色超平面是最佳分离超平面。
Fig. 3. Which hyperplane is the best? — the one in red
这在数学上可以写成:
Initial optimization problem
显然,目标函数是超平面的几何余量( w ,b) 。约束表示目标函数是超平面(w,b) w.r.t .的几何余量集合的最小值。
我们可以观察到,几何裕度的公式确保了对于最优超平面,所有几何裕度中最小的值(根据所有示例计算)由至少一对示例共享(一对来自+ve 类,另一对来自-ve 类)。这些点被称为 支持向量 (图- 1)。
因此,上面定义的优化问题等价于最大化裕度值(不是几何/功能裕度值)的问题。边距定义为两个超平面之间的距离,每个超平面平行于分离超平面,并通过每类的支持向量(即一个超平面通过+ve 类的支持向量,而另一个超平面通过-ve 类的支持向量,并且两个超平面都平行于分离超平面)。
因此,在这一点上,我们可以确定,对 SVM 的两种解释实际上是共存的,尽管我们是从第二种解释开始得出这个结论的。最后,我将讨论,当反过来时,我们在表述中有一些冗余,因此,开始时对问题的概念不太清晰。
让我们将各自的超平面表示为:
Hyperplane passing through positive support vectors
Hyperplane passing through negative support vectors
因此,优化问题可以用下面的目标函数来重新表述:
Reformulated optimization objective (i)
Reformulated optimization objective (ii)
到目前为止,这种简化仅仅是在书写更小的符号和更小的表达式方面。与我们开始的地方相比,我们没有减少任何要做的计算(实际上,最好自己验证一下)。
在开发 SVM 优化问题的最终形式的下一步中,将被执行的想法似乎不像 ideate 那样简单。
从本文开始我们就一直在做向量几何。事实证明,SVM 实际上是几何动机算法的核心。为进一步简化目标函数所做的工作并不难应用或理解,但是在你可能对一个表达式做的许多操作中,把注意力集中在下面的想法上并不容易。
在这里…
关于超平面的方程的一件事是,缩放它不会改变超平面。它给出了一个新的等式(w’,b’),其中w’= k .w和 b’= k . b(k是比例因子)但是超平面在空间上保持不变,因此几何余量也不变(但是功能余量会变)利用这个因素,我们可以做的是在我们的优化目标函数 中缩放 w 和 b ,使得功能裕度变为 1。
这使得我们的优化问题为:
w and b have been scaled such that functional margin has become 1
从真正的意义上来说,这通过减少要执行的计算数量而减少了优化问题!
我们已经完成了几乎整个推导过程,我们刚刚看到的最后一部分是最关键的一部分。
然而,这种提法有一个问题。目标函数是非凸函数,最好避免使用(图 4)。
Fig 4. Geometic margin of hyperplane w = (w1, w2), b = 1; x(i) = (1, 1) (Plotter used: https://www.geogebra.org/)
由于我们应用梯度下降来优化函数,非凸函数可能会导致算法陷入局部最小值。但结果是,对目标函数的乘法逆中的范数(w)求平方给出了一个凸的、可微的函数(目标函数的逆也是凸的,但在 w = 0 处不可微,可以使用在线绘图工具来验证这一点)。我们可以将此作为我们的目标函数,现在优化问题有了一点修改:
Making the objective function convex; this is also the final optimization problem of SVM
事实上,这是最终的目标函数,它也是完全凸的(图 5)!我们喜欢凸优化问题。
Fig. 5. The final objective function is perfectly convex (Plotter used: https://www.geogebra.org)
注意,最大化函数 f 与最小化函数 g = 1/f 是相同的。这就是为什么优化问题现在是一个最小化问题,而不是像以前那样是一个最大化问题。
最终的结果令人满意。
还有几点需要总结:
- 我们从优化几何余量的问题开始,而不是功能余量。这是因为通过简单地缩放和 b 可以容易地增加(或减少)功能余量。回想一下,这样做不会改变超平面。因此,这要么不会收敛到最佳分离超平面,要么会有太多的迭代,这基本上是无用的。有人可能会说,限制 w 的大小可能有助于解决这个问题。但是这根本不是一个好主意,因为| |w| | =c(c是某个常数)是非凸约束(因为可行集是超球面的表面),使得优化问题是非凸的。我们总是想避开非凸优化问题。
- 我们从第二种解释开始,然后确立了两种解释并存。但是我们从第二种解释中推断出第一种解释。事实证明,从第一种解释开始可能不太方便,因为那样的话,我们将从两个平行的超平面开始,最初由一些| b1-b2 |/||w|分开,其中 B1 和 B2 是它们各自方程的初始常数。不难看出,即使改变它们的 w (将超平面旋转相同的角度),两个超平面之间的距离也可能根本不变。约束可行性区域对于这种情况也很重要,因为学习最大距离处的超平面可能仅仅意味着学习尽可能远的那些超平面。那不符合目的。因此,约束优化问题类似于:“最大化距离 s.t .所有 ve 点在-ve 超平面的一侧,所有+ve 点在+ve 超平面的一侧”。我们可以为此使用泛函余量,但是我们可以观察到所有的+ve 点都在+ve 和-ve 超平面的同一侧,对于-ve 点也是如此。所以用两个超平面有点多余。此外,如果没有泛函和几何裕度的定义(它们是参照分离超平面定义的),要导出我们刚刚得到的结果即使不是不可能,也是不容易的。
脚注
希望我已经用正确的数学写了一些有意义的东西。我使用了在 YouTube 上可以找到的吴恩达的课堂笔记和他的 T2 系列讲座(都来自斯坦福大学的离线课堂笔记,而不是 Coursera),我正在进行的一个付费课程的一些想法和对 stackoverflow.com 的一些访问,然后将它们汇编成这个。希望你喜欢。
另外,请原谅我的笔迹。如果这些图片上写的不清楚,请告诉我。我将用新的图片代替它们。
感谢您的阅读。
更新
我还写了一篇文章推导软利润 SVM。你可以在这里找到。谢谢你。
揭开 SVM 数学的神秘面纱——第二部分
原文:https://towardsdatascience.com/demystifying-maths-of-svm-part-2-30308a73e072?source=collection_archive---------11-----------------------
本文讨论了为什么松弛变量被引入 SVM 的优化目标
在沿着一条相当平坦的曲线划动 K-NN、朴素贝叶斯分类器、逻辑回归和线性回归之后,SVM 来了,并对它施加了一个急剧的下降。在推导了线性可分数据集的 SVM 优化目标之后(我在我的上一篇文章中详细描述了这一推导过程,这是本迷你系列的第 1 部分),下一个停顿是“松弛的”SVM。在本文中,我们将一步一步地推导,并详细讨论每一步。
注:本文是我上一篇文章——揭秘 SVM 数学的续篇。重复作为线性分类和非线性分类数据集的基础的所有术语和概念是多余的,因为在本文的第一部分已经探讨过了。所以,我建议,如果有些话题或术语感觉不熟悉,也看看那篇文章。
让我们开始吧…
SVM 假说
假设,w.r.t .一个机器学习模型,就是模型本身,就是我们想要机器学习的分类器(它,是一个函数)。
g(z) = 1 if z ≥ 0, -1 otherwise
分类标签
在 SVM,等级标签被表示为-1 表示负等级,+1 表示正等级。
优化问题
我们将在本文末尾最终得出的最优化问题,以及 SVM 为拟合最佳函数所解决的问题是:
Expression 1: Optimization problem for SVM for dataset which is not linearly separable
符号:
- (w,b) 一起表示一个超平面- w 是该超平面的法线向量,b =**w**_ T * x0(w _ T 是转置(w)) 其中**
- C 是常数。 ξ_i (希腊符号称为 Xi,下标为 i )被用来放宽条件。文章围绕这两个术语展开。
- x(i) (x 上标带(I))是第 i 个训练例。在整篇文章中,我们使用 m 来表示训练集中的样本数量。
作为参考,以下是线性可分数据集的 SVM 优化问题:
Expression 2: SVM optimization objective when dataset is linearly separable
希望读者熟悉的术语:
- 功能余量
Functional margin of a hyperplane w.r.t. ith example (denoting as gamma-hat superscripted with (i))
Functional margin of a hyperplane w.r.t. the entire dataset
- 几何余量
Geometric margin w.r.t. ith training example (denoted as gamma superscripted with (i))
Geometric margin of hyperplane w.r.t. the entire dataset
请访问我的上一篇文章,对这些术语有一个更好的了解。
简述 SVM 算法如何工作,它的目标是什么(从概念上解释 SVM)
为了确保我们在同一页上,让我们讨论 SVM 是如何工作的。SVM 有两种解读方式:
首先,
SVM 通过学习合适的决策边界/决策表面/分离超平面来最大化余量(如图 1 所示)。
第二,
SVM 通过学习合适的决策边界/决策表面/分离超平面来最大化几何余量(如已经定义的,并且在下面的图 2 中示出)。
SVM 目前的表述够好了吗?
在之前的文章中,我们已经从头开始推导了 SVM 的最优化问题。我们得出了以下表达式:
Optimization problem that the SVM algorithm solves
原来这个优化问题只有在数据集(完全)线性可分的情况下,才能学习到一个合理的超平面(图 1)。这是因为约束集定义了一个可行区域,该区域要求超平面具有至少 1 w.r.t .的功能裕度。每个点 w 和 b 的值将被学习,使得功能裕度变为 1。任何具有正功能裕度的超平面的定义域都落在可行区域中,因为 w 和 b 可以简单地缩放以给出功能裕度 1,同时仍然保持超平面不变。但是,只有某些特定的( w , b* )超平面才能在可行域内优化目标函数)。*
Fig. 1. Dashed lines are the margins to the hyperplane (drawn in solid); dataset is linearly perfectly separable
因此,在优化过程中,对于任何示例,都不会考虑具有负功能裕度(图 2)的超平面。负功能裕度仍然是当前优化问题避免的极端事件。除此之外,像图 3 中黄色虚线所示的分离超平面也是不可能的。正如我们所看到的(图 3),蓝色超平面更靠近红色示例,并且由于数据集中的噪声而远离绿色示例的集合。一个看起来更像黄色的超平面,虽然看起来在形成决策边界方面做得更好,但它不在当前优化问题的可行区域内。
Fig 2. The thicker hyperplane in dark blue is learnt on the feasible region, although the thin, grey hyperplane is apparently better
Fig 3. In the current setting, SVM may learn a hyperplane like the one shown in blue.
由此,我们也可以容易地推导出这样一个事实:点位于超平面本身上的情况也是不可能的。此外,可行域可能是空的,在这种情况下,SVM 完全不能对例子进行分类。图 4 描述了一种情况,其中 SVM 不能用当前设置学习任何分离超平面。
Fig 4. No separating hyperplane is possible
看起来,目前的 SVM 公式并不可靠,任何自然数据集都可能使它变得无用(因为自然数据集很少是线性可分的)。SVM 的这种配置被称为 硬边界 SVM,表示它有非常严格的约束。**
在开始下一部分之前,我想重申一个事实,即该名称代表 SVM 在一组严格约束下学习决策面的严格性,给出保持不变的 w.r.t .训练示例。回想一下,约束表示可行区域,其中所有超平面都具有正的函数裕度 w.r.t .所有数据点都强调学习 w 和 b (对于相同的超平面)的缩放值,使得函数裕度为 1。
引入时差
为了成为更好的分类器,SVM 必须具有更宽松的约束,使得在可行区域中超平面可以被允许具有小于 1 的功能裕度。为了允许这种情况发生,松弛变量被引入到优化问题的每个约束中:
‘ξ’是 ξi 的松弛变量向量(ξ 下标为 i) 。我们为数据集中的每个例子定义 ξi 。它的每个元素必须至少为零,以真正允许某些点具有小于或等于 1 的功能余量(上述表达式中的第二个不等式)。对于训练数据集中的每个例子,它具有不同的值,因此,超平面对于不同点的功能裕度值可能具有不同的最低要求。这也允许超平面对于一些数据点具有小于 1 w.r.t .的功能裕度。
因此,优化问题变成了:
这意味着,我们现在更有希望得到一个分离超平面,如图 2 中黄色虚线所示。
我们得出的新优化问题表达了我们认为它应该表达的吗?
在本文前面的部分,我们建立了优化函数对应的是几何余量最大化(几何余量最大化本身就是一个非凸优化问题,所以我们系统地将几何余量最大化问题归结为一个等价的凸极小化问题)。因此,优化目标是“在给定的约束条件下最大化几何余量”从约束中,我们可以观察到,由于 ξi 可以包含任何非负值,所以它可以取任意大的正值作为例子。这意味着超平面 w.r.t .的函数裕度可以是小于 1 的任何值,甚至是负值。这意味着一个超平面可能做出错误的分类(在本文的第一部分中,我们讨论了一个负的泛函余量 w.r.t .一个点意味着该点被错误地分类)。因此,超平面可以有任意大的几何余量值,因为它可以自由地被推到任何地方。这并不能保证我们得到一个分离超平面!
这样做可能会以某种方式扩大可行域,使我们最终得到一个更坏的分离超平面。
输入新目标
事实证明,我们确实有一个不错的选择。我们为优化问题添加了一个新的目标,如下所示:
帕累托最优的观点
随着第二个目标的引入,可以注意到的第一件事是,现在优化问题不会以 ξ 的任意值结束。解决方案不再像只有一个目标时那么简单。不管我们打算解决优化问题的背景是什么,同一点同时优化两个或多个目标的情况并不经常发生。这样的例子随处可见。例如,对于具有相似规格的汽车,当我们寻求更高的速度时,操控性可能会下降。速度(目标-1)和操纵(目标-2)不太可能在同一点(即同时)达到最佳值。换句话说,如果我们选择一辆速度最高的汽车,那么它很可能在设计(特征)空间的同一点上不具有最佳的操控性。反之亦然(图 5)。在这个例子中,速度和操控性是相关的,如果你增加一个,那么没有任何额外的调整,另一个可能会减少。更一般地,可能没有有意义的关系的两个函数也不可能具有相同的最佳点。
Fig. 5. In red is the car with the highest speed (corresponding handling is not the best, it is likely to be the lowest as it is here) and in green is the car with best handling (corresponding speed is not the best, likely to be the worst as it is here).
这种类型的多目标优化(MOO)问题并非闻所未闻。帕累托最优的思想[1]被引入正式解决这个问题。帕累托最优定义了帕累托最优点。这些点定义了一个称为帕累托前沿的包络线[2]。发现这些点是为给定的 MOO 问题选择最佳点的最佳候选点。然而,对于一个给定的 MOO 问题,可以有许多 Pareto 解。“哪个最好?”——“没有人是。”。不可能说一点比另一点好。我们可以在图 5 中清楚地看到这一点——如果一个目标达到最优,另一个目标不一定处于最佳值。
因此,这是一个偏好的问题。你想要多高的速度?操控性应该有多好?
如果希望有一辆速度为 70 的汽车,那么问题就解决了。(速度,处理)的最佳值是(70,30)(图 5)。没有一个单独的帕累托解是普遍最优的。需要 用户偏好 从所有可能的帕累托解中挑选一个。
最终配方
随着对我们的优化问题引入一个更多的目标,我们进入了与上面讨论的汽车例子相同的情况。回想一下,第一个目标使利润最大化。给定约束条件,边距可以是一个很大的值。然而,这对应于无限地增加 ξ ,以便允许无限大和负的功能裕度值。相反,减少 ξ 对应于减少的余量(理想情况下,我们希望 ξ 是 ξi 的的合适向量,以便学习合理的分离超平面)。
因此,帕累托最优被用来描述这个多目标优化问题的解决方案。
SVM 和帕累托最优
用于解决 MOO 问题的方法之一是加权和方法。该方法允许将用户偏好添加到优化目标中。对于 SVM,我们想知道如何将我们对正确分离更多点的超平面的偏好(较低的 ξ 值比较大的 margin 值更可取)或具有较大 margin 的超平面(较大的 margin 值比较低的 ξ 值更可取)包括在权重的形式中。
表达式 1 是 SVM 优化问题的最终表述。常数 c≥0 用于说明用户偏好,以便从众多帕累托最优解中识别出一个合适的解。如果偏好学习在训练集上进行最合理分离的超平面,则应该使用合适的值 c 。相对较大的 c 将意味着我们对 sum_of_ξi 项引入了更多的偏好,这意味着我们将为它获得一个更优的值,而为 ||w|| 获得一个次优的值。
权重如何考虑用户偏好,它如何影响最优点?
Part 1 :用户偏好如何映射到权重?
现在让我们理解权重如何描述对特定目标函数的偏好。为了便于记记,我们将把两个目标函数写成如下所示:
我们的优化问题是(不写约束,但是它们必须成立),
也就是说:
这个多目标优化问题可以表述为一个单目标优化问题。单目标是单个目标函数的加权和,通常称为效用函数 [3]:
Equation — 1
权重 w1 和 w2 总是取正值。在这一点上,仍然不清楚权重如何对应于用户偏好。另外,请注意,用户偏好是相互关联的,并且只对给定的问题有局部意义。
注意如果优化问题是凸的,并且权重是正的,那么确保求解加权和函数给出帕累托最优的解【3】。
我们可以将用户对目标的偏好表示为一个数学函数。不用说,偏好函数将是 f1 和 f2 的函数。姑且称之为 P(f1,f2) 。P(f)的梯度则为:**
Equation — 2
等式-2 是偏好函数的总导数(关于总导数的更多信息,我建议你阅读这篇 stackexchange 帖子的第一个答案)。
效用函数(等式- 1)的梯度为:
Equation — 3
等式-2 的每个分量代表用户偏好随设计点值变化的变化率(在该值上定义了函数 f1 和 f2 )。
比较方程-2 和方程-3 表明,如果 w1 和 w2 选择得当,那么效用函数的梯度可以变得与偏好函数的梯度平行。简单地说,效用函数的变化率应该接近用户偏好的变化率。由于偏好是局部显著的,并且是相对的,所以讨论偏好如何改变 w.r.t .设计点是有意义的,而讨论在某种绝对意义上代表偏好的 w1 和 w2 是无关紧要的(因为偏好本身没有绝对/普遍的定义)。 选择合适的权重可以使效用函数的梯度与偏好函数的梯度平行。
*****第二部分*——权重如何影响最优分?
效用函数 U 有一个最优值
如果其中一个权重,比如说 w2 ,显著大于 w1 ,那么 f1 的每个偏导数将远大于 f2 的偏导数(因为 LHS = RHS)。对于凸函数,这对应于与 f2 相比 f1 具有更高值的点。类似的论点解释了当 w1 远大于 w2 时会是什么结果。
结论
在 SVM,使用单个常数 c 而不是两个权重,因为同样的原因,对超平面的偏好是相对的,并且对于特定问题是局部的。因此, c 用于表示一个目标(最大化利润)如何优于另一个目标(最小化sum _ of _ξI)。因为一个问题可能不同于所有其他问题,超调整需要参数 c 以便可以将合适的偏好与优化问题合并,从而为我们的稳健分类器偏好建模。如果 c 设置得太高,目标||w|| /2 在计算出的帕累托最优点处也会很高。这对应于具有小余量和小 ξi 值的分类器,即,我们可能以硬余量 SVM 结束。因此,如果数据集不是线性可分的,我们可能会得到一个不太理想的超平面——如图 3 所示。
附言
我发现很难理解第一个表情。并不是我找不到答案——我在 quora、stackexchange 等平台上看过。每个人都保持着相同的说法" c 平衡边距宽度和你想要避免的错误分类数量之间的权衡"。但是仅仅知道这一点似乎还不够。但是在参考了更多的资料和大约 10 篇论文之后,我发现了一个流畅的段落,引出了这个被引用的陈述。我在这里只引用了两篇最相关的论文。在这篇文章中,我试图对我所学到的东西进行流畅的讨论。我希望这篇文章没有从一个概念转到另一个概念。如果在某个地方感觉如此,请在评论区告诉我。我开始写作的目的不仅仅是为了解释一个主题,而是为了一个平稳的旅程——这是我个人喜欢的。
感谢您的阅读。期待得到反馈和建议。
参考
[1] Bui,L. T .,& Alam,S. (2008 年)。多目标优化导论。在计算智能中的多目标优化:理论与实践(第 1–19 页)。IGI 国际。
[2]https://www.igi-global.com/dictionary/pareto-front/21878
[3]r . t . Marler 和 j . s . Arora(2010 年)。多目标优化的加权和方法:新见解。结构和多学科优化, 41 (6),853–862。
揭开模型训练和调整的神秘面纱
原文:https://towardsdatascience.com/demystifying-model-training-tuning-f4e6b46e7307?source=collection_archive---------10-----------------------
不同的机器学习算法在寻找不同的趋势和模式。因此,一种算法不是所有数据集或所有用例的最佳算法。为了找到最佳解决方案,我们进行了大量的实验,评估不同的机器学习算法,并调整它们的超参数。这篇文章介绍了各种重要的话题:
- 培训、测试和验证数据
- 算法探索
- 超参数优化
- 合奏
术语
偏见
偏差是完全符合您的数据的模型参数与您的算法已经学习到的参数之间的预期差异。与高偏差算法相比,低偏差算法(决策树、K-最近邻和支持向量机)倾向于找到更复杂的模式。
差异
这是算法受训练数据影响的程度;参数随着新的训练数据改变多少。低方差算法(如线性回归、逻辑回归和朴素贝叶斯)往往比高方差算法找到的模式更简单。
欠拟合
模型过于简单,无法捕捉数据中的模式;这将在它已经被训练的数据以及看不见的数据上表现不佳。高偏差,低方差。高训练误差和高测试误差。
过度拟合
模型太复杂或太具体,捕捉的趋势不能概括;它将准确预测它已经训练过的数据,但不会预测看不见的数据。低偏差,高方差。训练误差低,测试误差高。
偏差-方差权衡
偏差-方差权衡是指找到一个具有适当复杂性的模型,使训练和测试误差最小化。
延伸阅读:偏差-方差权衡信息图
培训、验证和测试数据
机器学习算法从例子中学习,如果你有好的数据,你提供的例子越多,它就越容易在数据中找到模式。然而,你必须小心过度拟合;过度拟合是指模型可以准确地预测它已经训练过的数据,但不能推广到以前没有见过的数据。
这就是为什么我们将数据分为训练数据、验证数据和测试数据。验证数据和测试数据通常是可互换的,然而,它们在下面被描述为具有不同的目的。
培训用数据
这是用于训练模型以拟合模型参数的数据。它将占最大比例的数据,因为你希望模型看到尽可能多的例子。
验证数据
这是用于拟合超参数和特征选择的数据。虽然模型在训练过程中从未看到这些数据,但通过基于这些数据选择特定的特征或超参数,您会引入偏差并再次面临过度拟合的风险。
测试数据
这是用于评估和比较您的优化模型的数据。由于在训练或调整过程中没有看到这些数据,因此它可以让您深入了解您的模型是否能很好地推广到看不见的数据。
交叉验证
交叉验证的目的是评估特定算法是否适合您的数据和用例。它还用于超参数调整和功能选择。
数据被分成训练集和验证集(尽管您也应该将一些测试数据放在一边),并用每个数据片段构建一个模型。算法的最终评估是每个模型的平均性能。
保持方法
交叉验证的最简单版本是保留法,在这种方法中,我们将数据随机分成两组,一组是训练集,另一组是验证集。这是最快的方法,因为它只需要构建一次模型。但是,如果只有一个验证数据集,就有可能包含特别容易或特别难预测的观察值。因此,我们可能会发现我们过度适应这个验证数据,并且在测试集上表现不佳。
K 倍交叉验证
k 倍交叉验证方法包括将数据分成 k 个子集。然后对模型进行 k 次训练,每次都使用 k 个子集之一作为验证数据。训练数据将是不在验证集中的所有其他观察值。你的最终评估是所有 k 倍的平均值。
留一交叉验证
这是 K-fold 交叉验证的最极端版本,其中 K 是 N(数据集中的观察次数)。您可以使用除一次观察之外的所有数据对模型进行 N 次单独的定型,然后使用该观察的预测来验证其准确性。尽管您正在全面评估这种算法在数据集上的表现,但这种方法非常昂贵,因为它需要您构建 N 个模型。
分层交叉验证
分层交叉验证强制要求 k-fold 集合在分类特征或标签中对每个类别具有相似的观察比例。
算法探索
你探索的算法应该由你的用例驱动。通过首先确定你想要达到的目标,你可以缩小寻找解决方案的范围。尽管不是可能方法的完整列表,下面是介绍回归、分类、聚类、建议和异常检测算法的链接。我和一位同事还创建了这个工具来帮助指导算法选择(单击此处访问算法浏览器)。
回归
回归算法是预测连续数值的机器学习技术。它们是监督学习任务,这意味着它们需要带标签的训练样本。
延伸阅读:机器学习:试图预测一个数值
分类
分类算法是机器学习技术,用于预测输入数据属于哪个类别。它们是监督学习任务,这意味着它们需要带标签的训练样本。
延伸阅读:机器学习:试图对你的数据进行分类预测
使聚集
聚类算法是一种机器学习技术,用于将数据分成许多组,其中组中的点具有相似的特征。它们是无监督的学习任务,因此不需要带标签的训练样本。
延伸阅读:机器学习:试图在你的数据中发现结构
推荐引擎
推荐引擎被创建来预测指示用户对项目/产品的兴趣的偏好或评级。用于创建该系统的算法在用户、物品或两者之间找到相似之处。
延伸阅读:机器学习:尝试做推荐
异常检测
异常检测是一种用于识别不符合预期行为的异常事件或模式的技术。那些被识别的通常被称为异常或异常值。
延伸阅读:机器学习:试图检测异常值或异常行为
超参数优化
尽管术语参数和超参数偶尔会互换使用,但我们还是要区分这两者。
参数是算法在训练期间学习的属性。
对于线性回归,这些是权重和偏差;而对于随机森林,这些是每个节点的变量和阈值。
另一方面,超参数是必须在训练前设置的属性。
对于 k-means 聚类,必须定义 k 的值;而对于神经网络,一个例子是学习速率。
超参数优化是为这些超参数找到最佳可能值的过程,以优化您的性能指标(例如,最高精度、最低 RMSE 等)。).为此,我们为不同的值组合训练一个模型,并评估哪个找到最佳解决方案。用于搜索最佳组合的三种方法是网格搜索、随机搜索和贝叶斯优化。
网格搜索
您为每个超参数指定值,这些值的所有组合将被评估。
例如,如果您希望评估随机森林的超参数,您可以指定为树的数量超参数提供三个选项(10、20 和 50),并为每棵树的最大深度提供三个选项(无限制,10 和 20)。这将导致为 9 种可能组合中的每一种构建随机森林模型:(10,无限制),(10,10),(10,20),(20,无限制),(20,10),(20,20),(50,无限制),(50,10)和(50,20)。提供最佳性能的组合将是您用于最终模型的组合。
优点:使用简单。你会找到你所提供的价值的最佳组合。您可以并行运行每个实验。
缺点:计算成本很高,因为有太多的模型正在建造中。如果一个特定的超参数不重要,你就不必要地探索不同的可能性。
随机搜索
为每个超参数指定范围或选项,并选择每个超参数的随机值。
继续以随机森林为例,您可以提供介于 10 和 50 之间的树的数量范围,max_depth 可以是无限制,10 或 20。这一次,不是它计算所有排列,而是您可以指定您希望运行的迭代次数。假设我们只想要五个,那么我们可能会测试类似于(19,20),(32 无限制),(40,无限制),(10,20),(27,10)的东西。
优点:使用简单。效率更高,当只有几个超参数影响整体性能时,性能优于网格搜索。您可以并行运行每个实验。
缺点:它涉及随机抽样,所以只有在搜索空间时才会找到最佳组合。
由粗到细
对于网格搜索和随机搜索,您也可以使用由粗到细的技术。这包括探索更大范围的变量和更宽的区间或所有可能的选项。一旦你从最初的搜索中得到了结果,你就可以探索这些结果,看看是否有任何模式或特定区域看起来有希望。如果是这样,你可以重复这个过程,但要改进你的搜索。
对于上面的随机森林示例,我们可能会注意到,当最大深度没有限制并且树的数量超参数为 10 或 20 时,结果是有希望的。重复搜索过程,但保持最大深度超参数不变,并增加树选项数量的粒度,测试值 12、14、16、18,看看我们是否能找到更好的结果。
Pro :可以找到更优化的超参数,提高性能指标。
缺点:评估结果以找到最佳探索区域可能很麻烦。
贝叶斯优化
贝叶斯优化使用超参数组合成功的先验知识来选择下一个最佳方案。
该技术使用机器学习方法,建立一个模型,其中超参数是特征,性能是目标变量。每次实验后,都会添加一个新的数据点,并建立一个新的模型。
它假设相似的组合将有相似的结果,并优先探索已经看到有希望的结果的区域。然而,它也考虑到不确定性作为大收益的可能性;如果有尚未勘探的大面积区域,它也会优先考虑这些区域。
仅取一个超参数,即树的数量,该算法可能首先尝试 10,并获得相当好的性能。然后,它尝试 32 次,性能明显提高。贝叶斯优化基于前两个数据点建立模型来预测性能。该模型可能仅具有两个数据点的线性,因此选择的下一个值是 40,预期性能将随着树数量的增加而继续提高。事实并非如此。现在,它建立了另一个模型,表明在 32 附近可能会有改进,这是迄今为止它看到的最好结果,但是,在 10 和 32 之间仍然有很大的差距没有被探索,由于很大的不确定性,它选择 21。再次用这个新数据和选择的另一个值调整模型…
优点:可以找到更优化的超参数,提高性能指标。当参数数量很大并且每个实验的计算量很大时,它可以减少搜索最优解所花费的时间。
缺点:您不能并行运行每个实验,因为超参数值的下一个组合由之前的运行决定。它还需要调整—为每个超参数选择一个比例和一个合适的内核。
集成学习
集成结合了几个机器学习模型,每个模型在数据中找到不同的模式,以提供更准确的解决方案。这些技术既可以提高性能,因为它们捕捉更多的趋势,也可以减少过度拟合,因为最终预测是许多模型的共识。
制袋材料
Bagging (bootstrap aggregations)是一种并行构建多个模型并对其预测进行平均作为最终预测的方法。这些模型可以使用相同的算法构建(即随机森林算法构建许多决策树),或者您可以构建不同类型的模型(如线性回归模型和 SVM 模型)。
助推
Boosting 构建模型,依次评估早期模型的成功性;下一个模型优先考虑学习趋势,以预测当前模型表现不佳的例子。有三种常见的技术:AdaBoost、梯度增强和 XGBoosted。
堆垛
堆叠包括构建多个模型,并将其输出作为最终模型的特征。例如,您的目标是创建一个分类器,您构建了一个 KNN 模型和一个朴素贝叶斯模型。您可以将他们的两个预测传递到最终的逻辑回归模型中,而不是在两者之间进行选择。这个最终模型可能比两个中间模型产生更好的结果。
揭秘支持向量机
原文:https://towardsdatascience.com/demystifying-support-vector-machines-8453b39f7368?source=collection_archive---------4-----------------------
SVM 的几何研究
Image by Author
这是我的第二篇揭秘系列文章。你可以在这里查看第一篇文章—
[## 揭秘逻辑回归
逻辑回归的几何研究
towardsdatascience.com](/demystifying-logistic-regression-ee24c1104d45)
在本文中,我将重点介绍支持向量机或 SVM。它是最受欢迎的机器学习算法之一,在近十年的时间里(20 世纪 90 年代初至 21 世纪初),它一直享有第一的地位。然而,它仍然是一个非常基本和重要的算法,你绝对应该拥有它。让我们从 SVM 开始。
我将在本文中涉及的主题如下
- SVM 简介
- 几何直觉
- 为什么我们对支持向量平面使用+1 和-1
- 损失函数
- SVM 的双重形式
- 内核及其类型
- 努 SVM
支持向量机
支持向量机(SVM)是一种机器学习算法,可用于分类和回归问题。但多用于分类问题。在这个算法中,我们将每个数据项绘制为 n 维空间中的一个点(其中 n 是您拥有的特征的数量)。然后,我们通过找到最能区分这两类的超平面来执行分类。
如果你有一个 n 维空间,那么超平面的维数将是 n-1。
例如,如果您有一个 2d 空间,那么它将是一条线,如果您有一个 3d 空间,那么它将是一个平面,以此类推。
几何直觉
SVM 背后的主要思想是找到一个平面,该平面最好地分开正负点,并且正负平面之间的距离是最大的。
选择具有较大裕度的决策边界的基本原理是,它减少了泛化误差,而具有较小裕度的决策边界通常会导致过度拟合。
从上图中你可能已经注意到的另一件重要的事情是支持向量基本上是位于正负超平面上的点。
现在,让我们仔细看看我们实际上是如何最大限度地提高利润的。
让我们考虑下面的等式—
Image by Author
这些只是正负超平面的方程。我只在这个方程中加了 b,这是 y 轴截距。如果你想知道为什么我把正超平面和负超平面的值分别取为+1 和-1,那么就暂时保持这个想法,因为我将在本文的后面详细解释这样做的原因。
减去等式(1)和(2)后,我们得到—
Image by Author
我们可以用向量 w 的长度来归一化这个方程,向量 w 的定义如下
Image by Author
所以我们最后的等式是—
Image by Author
这个方程的左边基本上就是正负超平面之间的距离,实际上就是我们想要最大化的余量。
所以我们在 SVM 的优化函数是—
argmax( 2 / ||W||) for all i
such that Yi(W^T * Xi+b) >= 1
这里 Yi(W^T * Xi+b) >= 1 意味着这些点是完全线性可分的。所以所有的正点都在平面的正侧,所有的负点都在负侧
这种方法的问题是,在现实生活中,你几乎找不到完全线性分离的数据集。我们采用的方法被称为硬边际 SVM ,在现实生活中很少使用。所以为了在现实世界的应用中使用 SVM,一个被修改的版本被创造出来,叫做软边际 SVM 。
软利润 SVM
让我们首先来看看软利润 SVM 的等式
Image by Author
如果你不能理解这个等式,不要太担心,我会解释每一项。您可能对||W||/2 这个术语很熟悉。之前我们想最大化 2/||W||这个词,但是现在我们把它反过来了,所以我们把 argmax 改成了 argmin。
你可能已经猜到了' n' 表示数据点的数量。所以这个等式中新增加的两项是—
C = It is a hyperparameter
ζ (Zeta) = It denotes the distance of misclassified points
了解泽塔
为了更好地理解术语 zeta,让我们看下面的例子。
Image by Author
这里,★代表正点,⬤代表负点。
正如我在硬边界 SVM 的例子中所说的,我们很难找到一个完全线性可分的数据集,这里我们有一个点 x1,它是一个正点,但它不在正平面上。
所以在这种特殊情况下,点 x1 和平面𝚷之间的距离是 0.5(朝向负平面)。
For point x1 -
Y(W^T * X + b) = -0.5
Since class label(Y) is +1 and the distance is -0.5, since it is towards the negative plane
我们可以将上面的等式改写如下—
Y(W^T * X + b) = 1 - 1.5
So in general form we can write it as
Y(W^T * X + b) = 1 - ζ
所以基本上ζ代表的是误分类点离实际平面的距离。可以观察到,x1 到正平面𝚷 +的距离为 1.5,这正是本例中ζ的值。
理解 C
正如我上面提到的,C 是一个超参数,它可以被有效地调整,以避免过度拟合和欠拟合。
As C increases the tendency of the model to overfit increases
As C decreases the tendency of the model to underfit increases
为什么我们对支持向量平面使用+1 和-1
Image by Author
我们没有必要总是选择+1 和-1。所以我们在这里选择 k 的任意值。唯一的限制是它应该大于 0。
我们不能为我们的平面选择不同的值,也就是说,我们不能取+k1 和-k2,因为我们希望我们的正平面和负平面离我们的平面𝚷的距离相等
现在我们更新的利润是-
2*k / ||W||
for k = 5 we get10/||W||
因此,现在我们将使用 10/||W||而不是 2/||W||这是唯一的区别,因为 k 在这里是一个常数,所以我们选择什么值并不重要,因为它不会影响我们的优化问题。
所以我们用+1 和-1 来简化数学计算。
损失函数
SVM 使用的损失函数是铰链损失。简而言之,我们可以将铰链损耗理解为一个函数,其值在某个点(比如“z ”)之前不为零,在该点之后等于零。
我们研究了软利润 SVM 的方程式。
Image by Author
这里包含ζ和 C 的第二项是损失项。现在我们来看看这个术语是怎么来的。
Let Y(W^T * X + b) = Z -- (i)
// Here we are just substituting the value of Y(W^T * X + b) so that it is more readableSo from (i) we can say that
If Z > = 1 then the point is correctly classified and
If Z < 1 then the point is misclassified
如果你没有理解上面的替换,那么让我进一步澄清一下。
假设你有 2 个点 x1 和 x2,其中 x1 为正,x2 为负。现在,对于位于负平面上的点 x2 ,( w^t * x+b)的值将为负,其 y 值将为-1。
所以,y*(w^t * x+b)=-1 *(ve 值)= +ve 值
类似地,对于正的点 x1,(W^T * X + b)将是正的,并且它的 y 值也将是正的。所以,y*(w^t * x+b)=+1 *(ve 值)= +ve 值。
现在,如果你有另一个点 x3,它是正的,但是在负平面上,那么(W^T * X + b)将是负的,但是类别标签 y 仍然是正的。
所以,y*(w^t * x+b)=+1 *(ve 值)= -ve 值
所以这里的关键是,Y(W^T * X + b)只有在点被正确分类的情况下才会是正的,我们刚刚把 Y(W^T * X + b)替换为 z
现在你对 Z 的概念已经很熟悉了(希望如此),让我们看看我们的损失函数。
Image by Author
所以我们的损失函数相当简单,如果你不能理解它是如何工作的,那么我将为你分解它。
如前所述-
If Z >= 1 then the point is correctly classified and
If Z < 1 then the point is misclassified
因此,我们将在这里考虑两种情况。
案例 1——(Z≥1)
如果 Z ≥1,则 1-Z 将小于 0,因此 Max(0,1-Z ) = 0
直觉上,如果 Z≥1,则意味着我们已经正确地对该点进行了分类,因此我们的损失为 0。
案例二 — ( Z < 1)
如果 Z <1 then 1-Z will be greater than 0 so Max(0, 1-Z ) = 1-Z
最后一步
我们已经知道-
Y(W^T * X + b) = 1 — ζ(参见了解泽塔小节)
所以我们可以改写为-
1 - Y(W^T * X + b) = ζ
而 Y(W^T * X + b) = Z
所以 1-Z = ζ
从上面的例子我们可以看出,我们想要最小化的项是 1-Z。
Equation 1 (Image by Author)
这正是我们在这里所写的。我们只是用ζ代替了 1-Z
SVM 的双重形式
我们推导出的上面的等式 1 是 SVM 的原始形式。然而,为了利用内核的能力,我们使用双重形式的支持向量机。让我们看看 SVM 的双重形式。
Equation 2 (Image by Author)
使用双重形式的 SVM 的原因是,它允许我们利用内核的力量,这是 SVM 的一个关键特性,如果你不熟悉内核,那么不要太担心,我将在下一节解释内核。但是现在只要理解我们使用 SVM 的双重形式是为了利用内核的力量。
从数学上证明了方程 2 等价于方程 1。
关于我们实际上如何得到这种对偶形式的数学证明超出了本文的范围,因为它在数学上有点复杂。如果你想了解背后的数学原理,你可以看看下面的视频
在这个视频中,帕特里克·亨利·温斯顿教授提供了一个出色的数学解释,我强烈建议你看看这个视频,以便更好地理解支持向量机的概念。
这里要注意的最重要的一点是,αi 的值只对支持向量是非零的。所以我们基本上只关心支持向量。
我们可以将等式 2 更新如下—
Equation 3 (Image by Author)
之前我们用的是 xi^t Xj,也就是说,我们取 Xi 和 XJ 的点积,相当于余弦相似函数。所以我们可以用 Xi 和 Xj 的其他函数来代替这个余弦相似函数。这就是所谓的内核技巧。现在我们来了解一下内核到底是个什么东西。
内核及其类型
在上面的等式 3 中,我们可以用任何核函数代替 K。现在你一定想知道那会改变什么。为什么我们使用哪个函数有关系呢?所以让我们试着回答这些问题。
假设您有一个不可线性分离的数据集。
现在,你如何使用 SVM 来分离这些数据?我们不可能找到一个平面来分开这两类人。
输入内核…
核函数的主要用途是允许我们将数据集投影到更高的维度上,在那里我们可以拟合一个平面来分离我们的数据集。
因此,我们可以将上述数据集投影到一个更高的维度上,然后我们可以找到一个平面来分隔这两个类。这正是 SVM 在 90 年代初超受欢迎的原因。
内核的类型
两种最受欢迎的内核是—
- 多项式核
- 径向基函数(RBF)核
多项式核—
Image by Author
所以对于二次核,我们会得到这样的结果—
Image by Author
RBF 核—
Image by Author
这里 d 是 x1 和 x2 之间的距离,即 d = | | x1-x2 | |𝜎是一个超参数。
新 SVM —
nu 是一个超参数,我们可以用它来定义可接受的误差百分比。
0 <= nu <= 1 // The value of nu is between 0 and 1Let's understand it with an example.
Suppose nu = 0.01 and N (Number of data points)= 100,000* Percentage of errors <= 1%
* Number of Support Vectors >= 1% of N i.e. 1000
所以在 nu 超参数的帮助下,我们可以做两件事
- 我们可以控制模型的误差百分比。
- 我们不能控制,但我们可以确定支持向量的数量。
至此,我们已经到了这篇文章的结尾。非常感谢你的阅读。
如果你愿意,你可以鼓掌。它是免费的。
我的 LinkedIn , Twitter 和 Github
你可以查看我的网站了解更多关于我和我的工作。
揭开张量流时间序列的神秘面纱:局部线性趋势
原文:https://towardsdatascience.com/demystifying-tensorflow-time-series-local-linear-trend-9bec0802b24a?source=collection_archive---------2-----------------------
内部 AI
了解 Tensorflow 如何使用线性动力系统、卡尔曼滤波器和变分推理来模拟时间序列并进行预测
在过去的几年里,大公司匆忙发布他们基于机器学习的时间序列库。比如脸书发布了先知,亚马逊发布了胶子时间序列,微软发布了时间序列洞察,谷歌发布了 Tensorflow 时间序列。这种流行表明,基于机器学习的时间序列预测需求很高。
本文介绍了 Google 最近发布的 Tensorflow 时间序列库。这个库使用概率模型来描述时间序列。在我 7 年的算法交易经验中,我已经养成了分析时间序列库内部运作的习惯。因此,我深入研究了这个库的源代码,以了解 Tensorflow 团队对时间序列建模的看法。
这是一次迷人的旅行。Tensorflow 库将时间序列建模为带参数的线性动态系统。为了学习模型参数,它使用了卡尔曼滤波算法和变分推理。
本文将解释我们为什么以及如何使用这些技术,以及它们是如何协同工作的。要阅读这篇文章,你不需要知道动态线性系统,卡尔曼滤波器或变分推理。我会边走边介绍他们。我将向你们展示,这些技术自然会出现,使我们能够学习模型参数。
我们开始吧。
一些符号
这篇文章是关于时间序列的,所以会有下标。我使用下划线“_”来引导下标。比如我写 Y_1 , Y_t , Y_t-1 , Y_T+1 的意思是:
当我写 Y_1:t 时,我指的是术语的序列(你可以把它理解为术语的数组):
如果一些数学符号在你的手机上显示为问号,请尝试从电脑上阅读这篇文章。这是某些 Unicode 呈现的已知问题。
局部线性趋势
局部线性趋势是张量流时间序列中最基本的模型。它有以下定义:
在上面三个方程中,对于每一个时间步长 t 、 slope_t 、 level_t 、 y_t 都是随机变量。 ε_1 、 ε_2 和 ε_3 也是随机变量。注意 slope_t 、 level_t 和 y_t 依赖于数量,例如 slope_t-1 ,在前面的时间步 t-1 。但是噪声的分布 ε_1 、 ε_2 和 ε_3 不依赖于时间。
我们有观测值 Y_1 、 Y_2 直到并包括 Y_T ,或者更简洁地说, Y_1:T 。为了对这些方程如何生成观测值进行建模,我们使用以下生成性思维:
- 看第三个等式。想象在时间步 t ,观测随机变量 y_t 的分布描述了在这个时间步实际观测可以取什么值。而我们实际观察到的 Y_t 就是这个分布中的一个样本。
- 看第二个等式。随机变量 level_t 本身是由时间步 t-1 的随机变量 level_t-1 加上添加了高斯噪声的随机变量 slope_t-1 产生的 ε_2 。与 y_t 不同,对于 level_t 我们没有实际观测值,所以它是一个潜变量。
- 看第一个方程。随机变量 slope_t 由随机变量 slope_t-1 在步骤 t-1 产生,带有高斯噪声 ε_1 。 slope_t 也是一个潜变量。
注意独立的高斯噪声 ε_1 、 ε_2 和 ε_3 具有零均值和标准差 σ_level 、 σ_slope 和 σ_obs。由于这三个量模拟标准偏差,它们只能取正的实数值,用ℝ⁺.表示它们是这个模型的参数。我们不知道他们的价值观;我们需要通过观察来了解它们。
你可能会问,一个局部线性趋势能建模什么样的时间序列?你可以理解为 level_t = level_t-1 + ε_2 代表某种趋势水平。这个趋势水平可以以固定的速率变化,由 ε_2 控制。使用 slope_t 组件,趋势水平可以随时间以不同的速率变化。直观地说, slope_t 变量决定了一个新的观察值可以从当前的 level_t 改变多少。我想这就是为什么 Tensorflow 的人把它叫做斜率,从直线方程中类比 y=ax+b. 在直线方程中, a 叫做斜率,它决定了 y 在一步中可以改变多少δx。
为了获得这个模型的具体感受,我编写了这个代码来从中抽取时间序列。下图显示了 30 个时间序列样本。我通过将所有三种噪声的标准偏差设置为 1 来生成这些曲线。你可以看到一些曲线有明显的上升或下降趋势,而另一些曲线有改变方向的趋势。
如果我将 ε_1 的标准偏差改为 0,有效地禁用 slope_t 变量,我们会得到完全不同的结果:
正如您所看到的,对模型参数使用不同的值允许您对不同的时间序列进行建模。
现在的问题是,如果我有一个时间序列,比如这个:
这条曲线是特色图片中山脉的天际线(改编自插画师约书亚·琼斯的 Pixabay )。它不是你典型的“时间序列”。但我想找点乐子,看看局部线性趋势模型是如何从一座山到另一座山追踪天际线的。
我应该为这三个标准偏差选择什么值来模拟天际线时间序列?幸运的是,我们不需要手动选择这些值。我们将应用机器学习来计算它们的最优值。使用 Tensorflow 时间序列 API,您将编写类似下面清单 1 的代码:
Listing 1. Using Tensorflow time series API
在清单 1 中,第 9~11 行为 skyline 训练数据定义了一个局部线性趋势模型。第 13~23 行找到了模型参数的最佳值。第 25~38 行使用优化的模型预测未来值。
上面的代码片段读起来不错,API 也很直观。但是你可能想知道它是如何工作的,以及这些线条背后的数学原理是什么。我也是。这是我的发现。
局部线性趋势的矩阵形式 我们先把上面的方程改写成矩阵形式,以简化记法:
w_t 是一个二维多元高斯变量。一个组件尺寸用于 ε_1 ,另一个用于 ε_2 。这个多元高斯函数的平均值为 0。它的协方差矩阵是对角的,方差 ε_1 和 ε_2 在其主对角线上。 w_t 均值为 0,因为随机变量 ε_1 和 ε_2 均值为 0。 w_t 的协方差矩阵是对角的,因为 ε_1 和 ε_2 是独立的。同样,我们可以把 v_t 看成一个只有一维的多元高斯变量。再次注意, w_t 和 v_t 不依赖于前一时间步 t-1 的数量,不同于 level_t、slope_t 和 y_t 。
让我们为不同的矩阵命名:
然后我们得到相同方程的更紧凑的符号:
这两个方程描述了系统如何随时间演化。我们称这个系统为线性动力系统。换句话说,Tensorflow 人所说的局部线性趋势模型,和线性动力系统是一样的。它们是同义词。
在该系统中, x_t 被称为时间步 t 的状态变量。 y_t 称为观测变量。该系统是线性的,因为 x_t 和 y_t 线性依赖于 x_t-1 。
上述线性系统是以归纳的方式定义的——它描述了时间步长 t 的量是如何从先前时间步长 t-1 的量产生的。
你可能会问,系统从哪里开始(或者这个归纳定义的基础情况是什么)?可以假设系统从任意初始状态开始,比如说 level_0 = 0 , slope_0 = 0。换句话说, x_0 = [0,0],或者你可以选择 x_0 =[3,5]。无所谓。即使你的初始选择相当不正确,经过几步,系统状态也会远离这个错误的初始状态,变得与实际观测值更加一致。如果你还不明白为什么,不要担心,我们以后会回到这个重要的问题上来。
模型参数 以上线性动力系统有三个参数 σ_level 、 σ_slope 和 σ_obs。我们称它们为模型参数。在我们使用这个模型预测未来的观测值之前,我们需要计算出这些模型参数的值。这叫做参数学习。
参数学习
Tensorflow 时间序列将局部线性趋势视为贝叶斯模型。在贝叶斯设置中,参数学习意味着在给定观察数据的情况下计算模型参数的后验分布。定义 Y 为观测值 Y_1 到 Y_T 的向量。 Y 是长度为 T 的向量。定义 z 为模型参数的向量 σ_level,σ_slope,σ_obs 。 z 是长度为 3 的向量。
我们使用 p(z|y) 来表示后验密度函数。在这个公式里面, z 是我们模型参数的向量。定义 y 为第二系统方程中引入的观测变量 y_1,y_2,…,y_T 的向量。 y 的长度为 T 。注意大写字母和小写字母的用法。上部 Y 是实际观测值的矢量;而下方的 y 是随机观测变量的向量。
在本文中,大写字母 A,H,Y 表示常数,小写字母 x,Y,σ,表示变量。除了σ,我用来表示噪声的协方差,比如σ_ w,σ_ v。
后验密度 p(z|y) 通过贝叶斯法则计算:
该公式表明,计算后验 p(z|y) 需要三条信息:
(1)先验分布 p(z) ,我们在看到任何观察值之前对模型参数看起来如何的假设。
(2)可能性 p(y|z) ,观察值的概率,如果它们是由我们的模型生成的话。
(3)边际似然,是分母中的积分。该积分将等式的整个右侧换算成积分为 1 的适当概率密度函数。
我们需要计算这三个部分。作为预览:(1)是琐碎的,(2)需要一些工作,(3)是困难的。让我们一步一步来。
先验 p(z)
计算先验是微不足道的,因为我们完全控制指定先验。在局部线性趋势模型中,我们假设三个模型参数的先验来自对数正态分布。所以这些模型参数也是随机变量。这些对数正态分布有固定的自变量来决定概率密度的形状。我们不在乎这种形状。使用对数正态分布的主要原因是模拟标准偏差,在ℝ⁺.标准偏差只能取正值
我们还假设三个模型参数 σ_level、σ_slope 和 σ_obs 相互独立。因此,先验概率 p(z) 等于三个独立对数正态概率密度的乘积:
其中LN(σ_ level;)代表具有一些固定自变量的对数正态概率密度函数。在批注中LN(σ_ level;), LN 是概率密度函数的名字,这里是对数正态。在括号内,分号前, σ_level 表示这个概率密度是针对随机变量 σ_level 的。在分号之后,我们放入密度函数的参数。对数正态密度有两个参数。这里我们用一个点" "来表示我们不关心那些固定参数的值。
你会注意到最后一条蓝线和它奇怪的解释“API”。这是一种明确显示函数参数的符号。 λz.p(z) 表示 p(z) 是一个函数(我们这里是一个概率密度函数),这个函数取单自变量 z 。有编程语言背景的人会立刻看出这个符号是λ演算的λ表达式。λ是微积分中定义函数的符号。点等于“≐”符号读“有 API 的”。
λ符号使得函数的参数显式化。随着我们将构建越来越多的函数,簿记函数 API 帮助我们“接口检查”数学。请注意,这种簿记并没有改变数学。如果您不关心函数 API,您可以放心地忽略所有蓝色的线。
我强调,先验的 p(z) 是我们的建模假设,即模型参数相互独立,并且都来自对数正态分布。我们为他们继续建模提供了最佳猜测,但我们不知道这是否属实。
可能性 p(y|z)
可能性是在给定模型参数 z 的情况下观察数据 y 的概率。我们将可能性表示如下:
这个公式是所有概率模型的通用模板。我们需要为我们的局部线性趋势模型计算出 p(y|z) 的解析形式。让我们通过逆向应用概率论中的乘积法则(也叫链式法则)将其改写成乘积形式:
我们可以看到,这个产品中的所有术语都具有相同的结构。让我们来看一个任意的术语:
此概率条件下的符号 y_1:t-1 表示 y_1 至 y_t-1 。我们的目标是写出这一项的解析式。如果我们能做到这一点,我们就能对可能性中的所有项做同样的处理。
为了推导上述表达式的解析形式,我们需要使用来自线性动力系统的两个方程。让我再次展示它的定义:
系统是用归纳的方式定义的,所以我们用一些归纳的思维。
我们来看第一个方程。这个等式告诉我们 x_t 是从 x_t-1 加高斯噪声 w_t 的线性变换。如果 x_t-1 是一个高斯随机变量,那么高斯的一个性质告诉我们,一个加了高斯噪声的高斯变量的线性变换会产生另一个高斯变量。
所以如果我们假设随机变量 x_t-1|y_1:t-1,z 是一个均值为 μ_t-1 ,方差为σ_ t-1的高斯随机变量,并且我们知道 μ_t-1 和σ_ t-1的解析形式(我们将在后面证明这个假设):
那么我们就可以得出结论 x_t | y_1:t-1,z (请注意下标区别: x_t-1 在假设中, x_t 在结论中)也是一个高斯随机变量,高斯线性变换的规则也告诉我们其均值和方差的公式:
你可能会问,为什么我们需要在 y_1:t-1,z 上条件 x_t ?这是因为 x_t 可以取什么值取决于我们在时间步长 t 之前看到的观察值和模型参数。这是常识。如果前面的观察值是 100,那么 x_t 的分布也在 100 左右是有意义的。换句话说, x_t 取决于随机变量 y_1:t 和 z 。
你可能会问,我们怎么知道 x_t ,其中 t=1,2,..,T ,一开始是高斯变量吗?这很简单:我们可以假设系统从某个固定的初始高斯分布开始,例如,x _ 0 ~ N(0, 1 )。 0 是长度为 2 的零向量,因为 x_t 是一个二维向量。 1 是大小为 2x2 的单位矩阵。注意,这也是我们之前定义的系统的基本情况。然后我们知道 x_1|y_1,z 是高斯,还有 x_2|y_1:2,z ,…, x_t|y_1:t,z 。
你可能会问,如果 x_0 的均值为 0,换句话说, μ_0=0 ,所有的后件 x_t|y_1:t-1,z 的均值都是前面均值的线性变换,那么 x_t 的均值会一直为 0 吗 μ_t=0 ?答案是否定的,因为 μ_t 能取什么值取决于实际观测 Y_1:t 。我们将在下一部分卡尔曼滤波器部分对此进行详细解释。
现在,让我们继续讨论第二个系统方程。既然我们已经表明 x_t|y_1:t-1,z 是一个高斯变量,同样根据高斯线性变换的规则, y_t|y_1:t-1,z 也是一个高斯变量。将 x_t|y_1:t-1,z 的均值和方差代入转换公式,得到 y_t|y_1:t-1,z 的概率密度:
这是我们的可能性 p(y|z) 中任意项的分析形式。这个公式很长,但是它是如何推导出来的很简单,我们根据线性动力系统的第一个和第二个方程应用高斯线性变换规则两次。
这个多元高斯线性变换规则在机器学习中非常重要,绝对值得你花时间去记住它。它会在很多模型中弹出,比如高斯过程,甚至在最小二乘线性回归中对不确定性进行推理。
卡尔曼滤波器
还有一件事,上述所有推导都假定我们知道下列各项的解析形式:
现在我们需要证明这个假设是正确的。具体来说,我们需要证明我们可以推导出从 1 到 T 的所有 t 的 x_t|y_1:t,z 的解析形式。我们将进行归纳证明。别担心,证明很简单。
我们想假设我们知道:
并证明我们可以导出的解析形式:
请注意归纳假设中的下标和证明义务,以意识到我们正试图在下一个时间步中证明一些量,基于前一个时间步的量和新的观察。
这个证明义务意味着我们要找出 μ_t 和σ_ t的解析形式。不出意外的话,应该是 μ_t-1 和σ_ t-1的表达式。
让我们开始证明:
基步:我们知道 p(x_0) = N( 0,1 ) 。因此 μ_0 的解析形式为 0 ,σ_ 0为 1 。
归纳步骤:给定归纳假设:
根据我们线性动力系统中的两个方程和高斯线性变换法则,我们可以推导出:
我用 μ_a ,σ_ aa,μ_b,σ_ bb命名均值和方差来缩短公式,因为公式会变长。但是不要担心,公式会以一种不经大脑的方式变得更长——它们变得更长是因为我们将它们代入两个多元高斯分布规则。出于本文的目的,您可以放心地接受这些规则。它们是:联合概率密度和多元高斯的条件概率密度。
规则 1 :利用多元高斯的联合概率密度规则,我们可以推导出 x_t 和 y_t 之间的联合概率:
我们可以对多元高斯应用联合概率密度规则,因为 x_t|y_1:t-1 和 y_t|y_1:t-1 都是多元高斯变量。
在上面的公式中,名称σ_ ab和σ_ ba(它们是相互转置的)是 x_t|y_1:t-1,z 和 y_t|y_1:t-1,z 之间的协方差。我们也可以推导出它们的解析形式。例如:
在上面的推导中,为了节省空间,我去掉了条件部分 y_1:t-1 。所以请记住上面公式中的 x_t 和 y_t 的意思是 x_t|y_1:t-1,y_t|y_1:t-1 。
第(1)行是 x_t|y_1:t-1 和 y_t|y_1:t-1 之间协方差的表示法。
线(2)是两个随机变量之间的协方差的定义。
第(3)行用第二个系统方程代替 y_t|y_1:t_1 及其均值。
第(4)行重新组织公式中的术语,并使用期望的线性属性将第(3)行中的期望分成两个期望。我们可以认识到第一个期望是 x_t|y_1:t-1 的方差的定义。
第(5)行和第(6)行插入σ_ aa求 x_t|y_1:t-1 的方差。
第(7)行显示噪声的期望值 v 为 0,因为 v 来自 0 均值高斯分布。
规则 2 :由于上述联合是二维高斯分布,我们可以使用多元高斯条件规则写下条件概率:
第一行是条件概率表示。第二行显示其解析形式,即 μ_t 和σ_ t的公式。它们是由多元高斯条件规则给出的。第三行重新组织了条件中的术语,以安抚您的眼睛。
因此我们证明了我们可以推导出 x_t|y_1:t,z. 的概率密度函数的解析形式
证明结束。
我们来考察一下证明中的最后一个公式,对于 p(x_t|y_1:t,z) 的那个公式。这个公式告诉我们一些重要的事情。
首先,从上面公式的第二行可以看出, μ_t 和σ_ t只依赖于随机变量 y_t 和模型参数 z (因为其中的项,如, μ_a,σ_ ab,都是 y_1:t-1 和 z 的表达式)。换句话说, μ_t 和σ_ t是 y_1:t 和 z 的函数。认识到这一点后,让我们再次看看可能性中的任意项:
这个项依赖于 μ_t-1 和σ_ t-1,所以过渡性地依赖于 y_1:t-1 和 z 。从 API 的角度来看,这个术语开始是一个带有三个参数的函数, y_t,y_1:t-1 和 z ,如第 2 行所示。我们有实际观测 Y_1:t-1 。在我们将观察值 Y_t 和 Y_1:t-1 插入到前两个自变量中之后,整个项就变成了一个只将 z 作为其单一自变量的函数。这显示在第 3 行。
将此推广到 p(y|z) 中的所有项,我们可以看到,当插入观察值 Y 时,可能性是一个以 z 作为其单一自变量的函数。
其次,让我们了解状态变量 x_t 的均值是如何随时间变化的。让我们一起来看看 μ_t 的表达式以及 μ_a 和 μ_b 的定义:
我们可以看到 μ_a = Aμ_t-1 是系统认为在看到新的观察值 Y_T 之前的状态。该算法然后使用新的观察值 Y_T 来校正其关于该量的信念,从而为下一时间步 t 产生新的校正后的信念 μ_t 。
这个关于 μ_t 的解释也解决了之前的一个问题,问 μ_t 如果从 0 开始是否会一直为 0。答案是否定的。现在你明白为什么了。如果实际观测值不为 0,校正公式将快速迫使均值 μ_t 远离 0。
这些证明步骤也可以理解为著名的卡尔曼滤波算法——一种从以前的状态和新的观测值推导出当前系统状态分布的算法。卡尔曼滤波算法有许多解释。我发现上面的版本从概率的角度来看非常直观。
由于卡尔曼滤波器是如此重要的算法,让我总结一下:对于具有高斯噪声的线性动态系统:
假设我们知道潜在变量 x_t-1 在时间步长 t-1 的分布。给定一个新的观测值 y_t ,卡尔曼滤波算法导出潜在变量 x_t 在下一时间步 t 的分布。这个过程叫做过滤。其步骤是:
请注意这些步骤中的下标。下标的变化表明算法如何从系统状态 x_t-1 开始并导出系统状态 x_t 。每一步都优雅地应用了一个变换。
请注意,上述算法中的所有五项都代表概率密度函数。当新的观察可用时,该算法发展状态变量 x 的概率密度。前三步告诉你线性动力系统认为下一个系统状态和观测应该是什么。最后两步使用实际观察来更新这种信念。
这是一个美丽的算法!
回到清单 1,第 9~11 行描述了一个局部线性趋势模型。这个模型类有返回先验分布和似然概率的方法。
唷,我们已经写下了先验 p(z) 和似然 p(y|z) 的解析形式。现在我们来看三者中的最后一个——边际可能性。
边际可能性
边际似然是似然和先验乘积的积分。由于 z 已经被积分出来,结果是一个以 y 作为其单一参数的函数,如第二行所示。将 Y=Y_1:t 代入 y 后,整个边际似然变成一个常数,显示在第三行。常数用“λ”表示在λ之后和点“.”之前没有任何内容的部分。
不幸的是,积分很难用解析的方法计算。在我们的例子中, p(y|z) 是许多高斯密度函数的乘积,每个观测值一个。 p(z) 是三个对数正态概率密度函数的乘积,每个函数对应一个模型参数。即使写下他们的描述,我也能感受到其中的复杂性。
由于很难解析地计算边际似然,而边际似然是后验、的先决条件,我们也无法解析地计算后验 p(z|y) 。我们需要在数字上近似后验。
近似后验分布意味着用新的分布代替后验分布。这个新的分布应该类似于真实的后验分布。它应该有简单的解析形式。Tensorflow 时间序列使用变分推理技术来寻找这种新的分布。
近似后验概率的变分推断
变分推断用另一个分布 q(z) 逼近后验分布 p(z|y) ,称为变分分布。我们先想想 q(z) 应该是什么样子。
- q(z) 的结构应该很简单,所以我们可以很容易地用它进行分析。
- q(z) 和 p(z|y) 在同一组变量 z 上;每个变量取相同的一组值;并且 q(z) 作为概率密度函数,应该积分为 1。换句话说, q(z) 应该和 p(z|y) 有相同的 API。
- q(z) 需要尽可能的接近 p(z|y) ,所以近似于 p(z|y) 。
变分分布 q(z)
对于 q(z) 我们应该提出什么概率密度函数?Tensorflow 时间序列对 q(z) 使用一个平均场变分族。
平均场族是对 z 中随机变量之间关系的限制——它假设所有变量彼此独立。这种限制的好处是联合概率密度 q(z) 等于个体变量概率密度的乘积。
为了完全指定 q(z) ,我们还需要选择 z 中每个变量的概率密度。为此,Tensorflow 时间序列为 z 中的每个随机变量选择高斯分布。在公式中:
其中N(σ_ level;第 3 行的μ_l,σ_l* ) 代表变量 σ_level 的高斯概率密度函数,均值 μ_l 和标准差 σ_l. 同样适用于模型参数 σ_slope 和 σ_obs。*
第 4 行和第 5 行显示 q(z) 有自己的参数 vp =[ μ_l,μ_s,μ_o,σ_l , σ_s,σ_o ],一个长度为 6 的向量。这些参数指定了三种独立的高斯分布。我们将这六个参数称为变分参数,以区别于我们之前介绍的局部线性趋势模型的参数模型参数。
第 5 行显示 q(z) 以 z 和 vp 为自变量。q(z;vp)* ,分号在内,表示变量 z. 的一个概率密度,这个密度有参数 vp 来控制它的形状。注意,在第 1 行, q(z) 也是 z 和 vp 的函数。这一点从第 1 行到第 5 行没有变化。我们把它写成 q(z) 而没有明确提到 vp 只是为了强调 q(z) 是 z 中随机变量的概率密度函数。*
请注意模型参数 z 和变分参数 vp: 之间的关系
- z 是我们局部线性趋势模型的参数。z 的实际取值决定了我们可以建立什么样的时间序列模型。提醒自己我们在本文开头看到的不同样本时间序列。
- vp 是 z 的概率密度函数的参数。 z 建模为随机变量,变分参数 vp 控制 q(z) 的形状, z 的概率密度函数。
回到清单 1,第 14 行构建了变分分布 q(z) 。由于 q(z) 具有均值场结构,所以 Python 代码中的 qs 变量就是一个字典,每个键值对就是一个模型参数及其对应的变分分布。
让我们检查一下这个 q(z) 是否满足我们的要求: q(z) 具有简单的结构和解析形式。此外, q(z) 与 p(z|y) 具有相同的变量集。然而, q(z) 中的变量与 p(z|y) 中的变量具有不同的定义域。
随机变量域不匹配的问题
q(z )中的变量来自高斯分布,因此它们具有全实数域,用ℝ.表示
后验 p(z|y) 变量的定义域怎么样?后 p(z|y) 变量的定义域与前 p(z) 变量的定义域相同。 p(z) 是对数正态密度函数的乘积,其定义域是正数ℝ⁺.
q(z) 中的变量与 p(z|y) 中的变量之间存在域不匹配。这种域不匹配违反了上述 q(z) 的第二个要求。为了解决这个问题,我们将ℝ⁺域上变量的概率密度函数的后验概率 p(z|y) 转换成ℝ域上变量向量 u 的另一个概率密度函数 p(u|y) 。
你可能会问,我们不知道后验 p(z|y) 的解析形式,怎么进行这种变换呢?嗯,我们知道后鼻孔的结构:
其中 m 代表边际可能性的倒数:
m 是一个不涉及 z 的常数,因为 z 已经被积分掉了。当插入观察值 Y 时,后验概率就变成了一个以 z 为唯一自变量的函数。这是因为它是一个常数和两个函数的乘积,这两个函数都将 z 作为它们唯一的自变量。上面的蓝线清楚地显示了这个结构。
我们还知道 p(y|z) 和 p(z) 的解析形式,因此我们可以转换它们的乘积,常数 m 只是缩放转换后的结果。
你可能还会问,我们为什么不把 q(z) 转换成正实域ℝ⁺上的另一个分布呢?因为这通过给它添加约束使得 q(z) 更加复杂。我们想要一个简单的 q(z) ,这就是变分推理的要点。
我们使用概率密度变换的技术。
概率密度变换
让我们重新陈述一下当前的目标。有时候在一个漫长的过程中,我们很容易忘记我们想要做什么。
概括地说,在正ℝ⁺域上,我们有后验 p(z|y) = m×p(y|z)p(z) 和变量 z 。我们想把它转换成另一个分布p(u | y)u 中的每个变量都来自于整个ℝ域。这样,后验密度和变分分布密度在其输入变量上将具有相同的域。
u 会是什么样子?由于 z 中的三个变量 σ_level、σ_slope 和 σ_obs 是独立的,我们可以将它们独立变换。所以让 u 包含三个变量 u_level,u_slope,u_obs 是有意义的。 u 中的每个变量负责 z 中相应的变量。
概率密度 p(u|y) 会是什么样子?我们先来关注一下单变量对σ_ level∊ℝ⁺t29】和 u_level ∊ ℝ.我们想把 σ_level 写成 u_level 的函数。该功能有输入域ℝ和输出范围ℝ⁺.许多函数都可以做到这一点,例如:**
下图显示了绿色的指数函数曲线和红色的平方函数曲线。这两个函数都将一个值从ℝ映射到ℝ⁺.
两者之间,我们要选择指数函数。这是因为指数函数是单调递增的。所以在 σ_level 和 u_level 之间是一一对应的。稍后我们将需要这种一对一的映射属性。
所以我们决定使用指数作为从 u 中的变量到 z 中的变量的转换函数:
这就是用其他变量的函数代替变量的教科书案例。现在我们需要弄清楚这个变量替换是如何改变我们的后验概率密度 p(z|y) = m×p(y|z)p(z) 。为此,我们来看看概率密度函数的定义,它是一个非负的函数,在变量的定义域上积分为 1。所以我们的后验密度实际上意味着:
第一行是概率密度函数的定义。第二行明确显示了变量和积分极限。
让我们看看最内在的整合:
在这个积分中,我们希望用指数函数 exp(u_level) 替换所有出现的∑level。在微积分中,换元法告诉我们如何去做:
- 第一行是原始集成。
- 在第二行,所有与当前积分无关的变量都用点“”代替,以简化公式。
- 第三行是至关重要的一步。它应用替换积分规则:(a)在要积分的原始函数中,用变换函数替换所有出现的旧变量。(b)将原始函数乘以变换函数相对于新变量的导数。(c)改变整合的限制。 log 函数是我们用作变换函数的指数函数的反函数。我们使用这个反函数将原来的积分极限改为新的极限。这就是为什么我们希望变换函数是单调的,所以它的逆也是一个函数。
- 第四行减少了新的极限和导数。
现在我们研究三重积分,得出这个公式:
- 第一行通过替换三个变量来执行三次积分。所得积分具有从-∞到+∞的极限。
- 在第二行中,神秘的术语 |J(u)| 是由于代换积分规则的应用。||运算符代表矩阵的行列式。而矩阵 J(u) 称为雅可比矩阵。对于本文,你只需要知道在我们的例子中 |J(u)| 等于 e 的 u_level + u_slope + u_obs 次方。这是因为应用了代换积分法则。本文详细解释了雅可比矩阵。
第二行的公式是后验概率密度函数的定义。也就是说, p(u|y) = m p(y|u) p(u )对于整个实域ℝ.上的变量集 u
从现在开始,我们要用 p(y|u)p(u) 而不是 p(y|z)p(z) 。然而,为了使事情更简单,让我们将我们的 z 重新定义为 u 。这意味着从现在开始:
- 用 σ_level、σ_slope、σ_obs 来表示 u_level 、u _slope 和 u_obs 。换句话说, z 就是 u 的意思。
- 用 p(y|z)p(z) 来表示 p(y|u)p(u) 。
- q(z) 保持不变。
这样,上面所有的公式保持不变,你只需要记住现在东西在变换域中。
测量两个分布之间的相似性
上面列出的对 q(z) 的第三个要求是要求 q(z) 尽可能接近 p(z|y) 。从图形上看,这意味着 q(z) 的曲线应该尽可能地与 p(z|y) 的曲线重叠。下图展示了这个有趣的想法。我写了这个代码来生成图。
蓝色曲线代表我们想要计算的后验概率 p(z|y) 。它的形状不规则——注意左边比右边大。当然,我们并不知道 p(z|y) 的形状,我只是用一个不规则的形状来传达一个想法,即 p(z|y) 是一个复杂的东西。
绿色曲线代表我们提出的变分分布 q(z) 。我用一个规则的形状来表示 q(z) 结构简单。
q(z) 的形状由六个变分参数 vp 控制。我们需要调整这六个值,使绿色曲线尽可能与蓝色曲线重叠。
记住,最终我们想要知道模型参数 z 的值。为此,我们需要通过找出变分参数 vp 的值来确定变分分布 q(z) 的形状。我们正在寻找 vp 的值,使得 q(z) 尽可能与后验 p(z|y) 重叠。一旦我们有了 q(z) 的形状,我们就可以从中取样以获得 z 的实际值。
为了量化两个概率密度之间的重叠程度,我们使用kull back–lei bler 散度。概率密度 q(z) 和概率密度 p(z|y) 之间的 KL 散度为:
KL-divergence 背后的直觉很简单。它是 z 域内每一点的两个概率密度之差的加权平均值(用 q(z) 加权)。
我们想要为 vp 找到一个特定值,使得 q(z) 最小化到后面的距离 p(z|y) 。我们可以用下面的公式来表示这种最小化:
中的星q(z;vp) 表示 q(z) 的最佳值。这意味着我们想要找到这六个变分参数的值,使得 q(z) 和 p(z|y) 之间的 KL 散度最小。*
看看变分推理如何将推理问题转化为优化问题!使用贝叶斯规则计算后验概率 p(z|y) 的原始问题通常被称为推理问题。另一方面,最小化 q(z) 和 p(z|y) 之间的 KL 散度是一个优化问题。KL 散度是优化目标。
令人惊讶的是,我们可以最小化 q(z) 和 p(z|y) 之间的 KL,即使我们不知道如何计算 p(z|y) 。
秘密在于变分推理理论。它告诉我们最小化 KL-divergence 等价于最大化另一个称为证据下限的公式,表示为 ELBO(q(z)) 。如果你不熟悉为什么,不要担心。现在,接受这两个优化问题是等价的就足够了。
ELBO(q(z)) 定义为:
从上面第二行可以最好地看出 ELBO 背后的直觉。它有两项:一个期望减去另一个期望。我们想最大化减法的结果。
第一项是对数似然的期望值。它描述了我们的模型与数据的吻合程度。为什么?因为为了使这一项变大,我们的 q(z) 应该在 p(y|z) 也变大时,给 z 的值以大概率。我们希望这一项很大。
第二项是 q(z) 和之前的 p(z) 之间的 KL 背离(如果你还没有意识到的话)。我们知道一个 KL 散度是非负的。这个术语描述了我们提出的 q(z) 与我们先前的假设 p(z) 有多么不同。我们希望差别很小,因为我们假设我们的先验是有意义的。所以我们希望第二项小一些。
ELBO 传达了我们的愿望,即我们的优化模型很好地符合数据,同时它保持接近我们的模型假设,即先验。
第五行和第六行显示我们将 ELBO(q(z)) (一个期望)扩展为一个积分。
第 7 行显示了积分内部的函数,开始是一个带有两个参数 z 和 vp 的函数(插入了观察值 Y )。这是因为它所包含的功能要么是 z 的功能,要么是 z 和 vp 的功能。
第 8 行显示在将 z 积分出来后, ELBO 仅仅是变量参数 vp 的函数。
你可能会问,我们到底为什么需要 ELBO(q(z)) ?为什么我们不能直接最小化 KL(q(z)||p(z|y)) ?要回答这个问题,我们需要注意:
- KL 公式提到了我们无法计算的后验概率 p(z|y) 。
- 但是 ELBO(q(z)) 公式没有提到后验 p(z|y) 。只提到了先验 p(z) ,似然 p(y|z) 和变分分布 q(z) 。我们知道这三个量的解析形式。
这就是为什么我们需要 ELBO 以及如何最小化 q(z) 和 p(z|y) 之间的 KL 散度,即使我们不知道 p(z|y) 。这个事实一开始挺让人吃惊的。但这是合理的。因为可能性 p(y|z) 和先验 p(z) 包含了计算后验 p(z|y) 所需的所有信息。
你可能会问,在概率密度变换部分,我们把后验变换成了ℝ域上的一个函数,从那以后,我们就需要使用变换后的后验。但是 ELBO 根本不提后路。我们该怎么办?在 ELBO 中,我们有 p(y,z) = p(y|z)p(z) 。并且变换后的后验概率是 mp(y|z)p(z) ,其中 m 是常数。所以我们仍然可以将转换后的结果插入 ELBO 中。 m 是常数;它不会改变优化的解决方案。
回到清单 1,第 14 行构建 ELBO 作为优化目标。
梯度下降以最大化 ELBO(q(z))
由于我们知道 ELBO(q(z)) 的解析形式,我们可以使用梯度下降来最大化 ELBO(q(z)) 关于其参数 vp 。其实我们用梯度下降来最小化 -ELBO(q(z)) 。
我们需要计算 ELBO(q(z)) 相对于变分参数 vp 的梯度:
其中𝛻符号代表向量微分算子。它计算多参数函数相对于其参数的梯度。在我们的例子中,𝛻_ vp 计算 ELBO(q(z)) 相对于 vp 中参数向量的梯度。
微妙的一点。上式中,积分是针对模型参数 z= [ σ_level,σ_slope,σ_obs 。但是积分之外的梯度计算是关于变分参数 vp =[ μ_l,μ_s,μ_o,σ_l,σ_s , σ_o 。所以整合和分化并不相互抵消。
由于积分,解析计算 ELBO(q(z)) 的梯度是困难的。因为积分计算的是期望值,所以我们可以用样本平均值来逼近它。在每个优化步骤中,我们可以从当前的变分分布 q(z) 的中采样一些 z 的值。这意味着从电流 q(z) 中采样一些值 σ_level、σ_slope 和 σ_obs 。并使用样本平均值来近似积分。在公式中:
最后一行使用来自当前 q(z) 分布的 n 个样本 Z_1 到 Z_n 来计算样本平均值。我强调,在每个优化步骤,我们需要从当前的q(z)中抽取新的样本。这是因为每个优化步骤通过改变变化参数的值来改变 q(z) 分布。
然而,当我们要应用梯度下降时,上面的公式有一个问题。为了看到这一点,让我们继续操作上面的公式:
在第 6 行, ELBO 公式的 API 是显式的。看第一个学期。插上 Y 和 Z_i 后, log(p(Y,Z_i)) 成为常数。这就是为什么我们有一个“λ”引导其 API 的符号。 𝛻_vp 算子计算该常数相对于 vp 的梯度。渐变为 0。这似乎表明,可能性在优化问题中不起任何作用(因为它消失了)。这说不通。
这个问题的原因是,我们从 q(z) 中得到哪些样本 Z_i 取决于变分参数。我们正在使用梯度下降优化这些变化的参数。但是从 q(z) 抽取样本发生在梯度下降算法之外。这使得梯度下降算法失去了关于 q(z) 的知识。症状是计算梯度时似然项消失了。
重新参数化技巧解决了这个问题。
重新参数化技巧
在我们的例子中,由于难以计算积分,采样是不可避免的。但是采样发生在梯度下降框架之外。为了解决这个问题,我们应该从更简单的分布中取样。并且这种分布必须不依赖于变化的参数。
重新参数化技巧的思想是,对于 z 中的每个模型参数,例如 σ_level :
- 引入一个新的随机变量, θ_level~ N(0,1)。所以 θ_level 来自固定的高斯分布。它不依赖于任何变化的参数。我们称 θ_level 为 重参数化变量。
- 将我们的原始模型参数 σ_level 重写为这个新变量 θ_level 的函数。这个函数也会提到相应的变分参数 μ_l,σ_l 。我们把这个函数叫做重新参数化函数。
- 在作为积分的 ELBO 公式中,用重新参数化函数替换该模型参数 σ_level 的每次出现。**
在公式中,我们继续以模型参数 σ_level 为例:
我们可以将 σ_level 重写为 θ_level 的函数,如下所示:
注意在该函数中, μ_l 和 σ_l 为变参数。如果你不知道我们是怎么想出这样一个函数的,也没关系。人们一直在研究如何为不同的发行版设计这样的函数,见这里。很多都不是小事!
对我们来说重要的是: σ_level 仍然是均值 μ_l 方差 σ_l 的高斯分布。这是因为等式右边的第一项
是高斯变量 θ_level~N(0,1) 的线性变换,没有添加噪声。我们已经知道如何写下它的分布:
现在重新参数化函数将 μ_l 加到这个高斯分布上,得到高斯分布 N ( μ_l,σ_l)。换句话说,这种重新参数化保持 σ_level 的分布不变。**
我们定义 θ= [ θ_level , θ_slope , θ_obs 为重新参数化变量的向量。设重新参数化函数为 r 。在我们的 θ_level 的例子中:
这个技巧把 q(z) 变成了 θ 和 vp 的函数:
ELBO(q(z)) 成为变分参数 vp 和新引入的变量向量 θ 的函数。我们引入了 θ ,因为我们可以独立于变分参数对其进行采样。当 θ 替换为样本θ~ N(0, 1 )时,ELBO 成为 vp 的唯一函数。在公式中:
哇,这太可怕了。让我解释一下:
- 第一行是 ELBO 符号。
- 第二行是 ELBO 的原定义。
- 第三行应用替换积分规则,因为我们想在积分中用函数 r(θ) 替换出现的 z 。之前,我们已经在适应随机变量域的上下文中看到过这个规则。
- 第四行减少了导数,重新组织了项,使概率密度为N(θ;* 0 ,1)弹出。N(θ; 0 ,1)代表多元高斯的概率密度,为*【3 维】;它有均值 0 和恒等方差矩阵 1 。你可能看不出这是如何得出的,我稍后会解释。重要的是要注意,现在我们有了关于 θ 的期望的定义。所以我们可以用样本平均值来近似这个期望值。**
- 用样本平均值逼近第 4 行的期望值。样本θ_ 1:N来自于 N( 0 ,1)分布。重要的是,这种分布不依赖于变化的参数 vp 。
- 第六行显示插入观测值 Y 和样本θ_ I:n后, ELBO 仅成为变分参数 vp 的函数。所以梯度下降可以正常工作,什么都不会消失。
现在,我将演示我们是如何从上面的第三行到达第四行的。为简单起见,让我将 θ 视为一维变量,并使用符号 θ 、 μ 和 σ ,而不是 θ_level 、 μ_l 和 σ_l. 和 q 成为一元高斯分布:
解释:
- 第 1 行,我们想要操作的行。
- 第 2 行,插入 q 的定义,这是我们演示的单变量高斯分布。
- 第 3 行,扩展 r(θ) 的定义。
- 第 4 行,通过取消项和计算导数项来简化。
- 第 5 行,进一步简化公式。认识到积分中的第一部分是 N(0,1) 的概率密度。
- 用概率密度函数的名字代替它。
我们可以把这种单变量情况推广到多变量情况。
最后一件事,我保证
谢谢你看了这么久。我知道这是一段漫长的旅程。我真想说“就这样”。但是,还有一件事。
梯度下降算法适用于具有全实数域ℝ.的变量它不允许您指定变量的界限。然而,如果我们再次观察变分分布 q(z) :
由于 σ_l、σ_s 和 σ_o 代表标准差,所以它们必须是非负的。到目前为止,我们应该养成用函数重新表达变量的习惯。这正是我们在这里应该做的。我们引入三个新变量 ϕ_l 、 ϕ_s 和 ϕ_o ,并将 σ_l、σ_s 和 σ_o 改写为它们的函数:
这样, ϕ_l、ϕ_s 和 ϕ_o 可以从全实域取值,而 σ_l、σ_s 和 σ_o 仅保持非负。 q(z) 变成了:
有了这最后一步(当然,还有上面的一切), ELBO 变成了 μ_l,μ_s,μ_o,ϕ_l,ϕ_s,和 ϕ_o 的函数。所有六个变量都可以取全实数域ℝ.的值梯度下降终于可以通过了。
我们在两个地方采用了从ℝ⁺到ℝ:的可变域
- 之前,我们修改了模型参数的域,因此 q(z) 和 p(z|y) 具有相同的域ℝ.
- 这里,我们修改了与标准差相关的变分参数的域,因此所有变分参数都具有域ℝ.平均相关变分参数已经有域ℝ.
你可能会问,选择 q(z) 作为高斯的产物,我们得到了什么?为什么它比原始先验好,原始先验是 LogNormals 的产物?
当我们查看优化过程时, q(z )唯一能帮助我们的地方是,我们可以轻松地从 q(z) 进行采样。更准确地说,我们需要能够重新参数化 q(z) 以便它可以被表示为来自固定分布的函数。我们可以很容易地从固定的分布中抽取样本。我们已经表明,通过我们提出的 q(z) ,我们可以做到这一点。但是对数正态怎么样呢?原来我们也可以重新参数化对数正态分布并从中取样,详情此处。
因此,要回答这个问题,在我们的特殊情况下,提出的 q(z) 并不是一个大的救命稻草。我们也可以用对数正态先验进行优化。但是想象一下,当先验很复杂并且很难从中采样时,一个结构简单的 q(z) 可能是一个真正的帮助。
回到清单 1,第 17~23 行使用梯度下降来寻找 vp 的最优值。它首先创建一个以 ELBO 为目标函数的 Adam 优化器,然后执行 200 个梯度下降步骤。
这标志着参数学习的结束。
顺便说一下,变分推理在现代机器学习中非常重要,是一个你无法逃脱的话题。参见其在变分高斯过程和人脸生成中的应用。
预测未来值
梯度下降将给出六个变分参数 μ_l、σ_l、μ_s、ϕ_l 、 ϕ_s* 和 ϕ_o* 的最优值。这些值完全指定了优化的变分分布 q(z)* 😗*
我们可以用 q(z) 来近似后验 p(z|y) 。*
给定时间序列观测值 Y_1 到 Y_T ,我们的兴趣是预测未来值, Y_T+1,Y_T+2 等等。为此,我们可以从时间步长 1 到 T 运行卡尔曼滤波算法,以计算潜在变量 x_t|y_1:t,z 的分布。从上面复制卡尔曼滤波算法:
我们现在可以运行卡尔曼滤波器,因为现在我们可以知道其参数 z=[ σ_level、σ_slope、σ_obs** ]的值,例如,通过从优化的 q(z)* 分布中采样 σ_level、σ_slope** 和 σ_obs* 。****
你可能会问,为什么我们需要从 q(z) 取样?这是因为 q(z) 是一个分布,为了运行卡尔曼滤波器,我们需要三个标准偏差 σ_level、σ_slope 和 σ_obs 的具体值。对于每个标准差,我们需要多少个样本?由你来决定。例如,您可以对每个标准差取样 30 个并取平均值,然后将这三个平均值代入局部线性趋势。**
卡尔曼滤波算法结束后,结果就是系统状态变量 x_t 的分布,换句话说就是 μ_t 和σ_ t的值:**
从现在开始,我们的预测开始了。我们可以将 x_T|y_1:T,z 代入线性动力系统方程,得到状态变量 x_T+1|y_1:T,z 和观测变量 y_T+1|y_1:T,z 的预测分布。
事实上,你可以这样做无数次:
在上图中,我们从卡尔曼滤波的结果 p(x_T|y_1:T,z)开始。每个右箭头“→”代表第一个系统方程的应用,以获得下一个状态变量的分布。每个向下箭头“↓”代表第二个系统方程的一个应用,以获得下一个观察值的分布。
这样就可以得到任意步 i 到未来的观测变量 y_T+i|y_1:T,z 的预测分布。请记住,您仍然需要将实际观察值 Y_1:T 和优化的模型参数 z 代入公式,以获得完全指定的分布。*
注意上图中,所有分布的条件部分里面, y_1:T 部分没有变化,我们没有 y_1:T+1 , y_1:T+2 。这是因为在时间步 T 之后,我们不再有实际的观察。我们应该认识到,预测的过程是使用卡尔曼滤波算法中 5 步中的前 3 步来导出我们对系统状态和未来观测可能性分布的信念。我们不能再使用卡尔曼滤波器的最后两步来修正我们的信念,因为我们没有新的观测值。
数学允许你预测无限未来的新值。但这并不意味着你应该。你对未来的预测越遥远,就越不精确。这是常识;而我们来看看这个常识是如何体现在数学上的。
我们需要看看系统状态变量和观察变量的分布结构。让我们通过两次应用第一个系统方程,首先来看下两个时间步 T+1 和 T+2 中的系统状态变量分布:
让我们通过从上述推导中得出一个归纳结论来研究均值和方差分量。
x_T+i 有均值 μ_T+i :
在上面的内容中,我在 level_T 和 slope_T 上方使用了一个横杠“-”来表示这些是 μ_T 中的平均值成分。第 5 行显示趋势水平预测(矩阵中的第一个条目)是一条始于当前趋势水平的直线。并且斜率水平预测(第二条目)保持不变。
现在我们来研究变量 x_T+1 和 x_T+2 的方差σ_ T+I:**
公式有点复杂。但是我们可以看到,每次我们向前移动时,噪声方差σ_ w会被添加到系统状态变量的方差中。这导致系统状态变量 x_T+i 的方差随着时间变得越来越大。**
现在我们继续观察观察变量 y_T+i 的预测分布。它是系统状态变量 x_T+i 的线性高斯变换。所以 y_T+i 遵循相同的特性:
现在我们可以看到 y_T+i 的预测分布的平均值与 x_T+i 的平均值相同,这是一条直线,因为矩阵 H 被设置为【1,0】。这个直线公式也提醒了我们为什么斜率变量叫斜率。 y_T+i 的方差会将噪声σ_ v的方差添加到我们移动到未来的每个时间步长中。这导致 y_T+i 的方差也越来越大。****
回到代码清单 1,第 26 行从优化的 q(z) 分布中抽取模型参数值。第 28~33 行通过在内部运行卡尔曼滤波算法来建立观察变量 y 的预测分布。第 36~38 行通过报告每个未来时间步的预测分布的平均值和标准偏差来执行预测。
有了这个数学分析,让我们绕回我们的山脉天际线“时间序列”。天际线有 220 个观察点。我使用前 200 个观察值进行参数学习。然后使用学习过的模型来预测最后 20 个点。它看起来是这样的:
在上图中,蓝色曲线是地面真理山天际线的观测结果。垂直虚线将左边的训练和右边的预测分开。绿色虚线是预测的平均值。右侧的浅绿色锥形显示了 95%置信水平下的预测方差。
预测平均值和方差证实了我们的数学分析。平均预测是一条直线。随着我们越往未来走,方差会变得越来越大。
我们还可以看到,平均预测是非常错误的(或者,如果考虑到置信区间,我们可以解释为预测是正确的)!平均预测说,山脉的天际线应该上升,但它实际上是下降的。这是因为我故意选择了一个分界点,一个山顶,来挑战算法。为了进行预测,算法只能依赖于在山向上的第 200 次观察之前的先前值。当然,它会预测山会继续上升。因此得名局部线性趋势。从数学上讲,算法知道斜率应该是正的。
那我们该怎么办?我们获得新的观察值,每次当新的观察值可用时,使用所有的观察值从头开始重新训练模型,然后进行预测。如果我们用 8 个以上的观察值训练我们的模型,并在第 208 个观察值开始预测,这是一幅图:
现在预测更加精确了。额外的 8 次观察显示山向下,因此算法得知斜率变量是负的。预测更精确,因为山一直在往下走,换句话说,趋势没有改变方向。
这里是天际线预测的代码。改编自 Tensorflow 时间序列实例。
你可能会好奇,或者你还记得卡尔曼滤波算法本身就可以根据观测值进行时间序列预测。在变分推理发明之前,我们不就是用这种算法登陆月球的吗?为什么我们需要变分推理?嗯,卡尔曼滤波算法只对没有任何参数的完全指定的模型有效。由于我们的局部线性模型包含参数,我们首先需要学习它们的值。使用变分推理作为推理算法的贝叶斯方法是这个 Tensorflow 时间序列库的选择。
结论
本文介绍了 Tensorflow 时间序列库中的局部线性趋势模型。其重点在于如何学习该模型的参数:
- 我们将局部线性趋势模型定义为一个带参数的线性动力系统。
- 然后,我们使用高斯线性变换和卡尔曼滤波算法来导出可能性 p(y|z) 。
- 我们使用变分推断,使用分布 q(z) 来近似后验 p(z|y) 。 q(z) 是参数变化的变分分布。
- 我们使用概率密度的变换来确保 p(z|y) 和 q(z) 具有相同的可变域。
- 我们使用 ELBO(q(z)) 作为优化目标,以最小化 q(z) 和 p(z|y) 之间的 KL 散度。梯度下降是优化算法。
- 我们使用样本平均值来逼近 ELBO(q(z)) 定义内的积分。样本来自于 q(z) 分布。
- 我们使用重新参数化技巧从更简单分布的样本中构造出 q(z) 的样本。这个更简单的分布不依赖于我们正在优化的参数。这样梯度下降可以通过。
这是很多步骤。我试图解释清楚每一步背后的直觉。我只展示了必要的数学。
好消息是,你只需要基本的大学数学就能理解以上所有内容。下面是提到的数学知识点列表:
- 预期的定义
- 单变量高斯分布
- 多元高斯分布,其联合与条件
- 高斯的线性变换
- 对数常态分布
- 贝叶斯法则
- 概率中的产品/链规则
- 边际分配
- 概率密度函数的定义
- 替代积分
- 多重整合
- 用函数替换变量
- 用于变分推理的 ELBO
支持我
如果你喜欢我的故事,如果你考虑支持我,通过这个链接成为灵媒会员,我将不胜感激:https://jasonweiyi.medium.com/membership。
我会继续写这些故事。
承认属实
我要感谢文森特·亚当和我一起阅读了 Tensorflow 时间序列的代码。感谢卢卡斯·波尔多、迈克尔·彼得森、埃尔维斯·萨尔坎斯、尼古拉斯·杜兰德、斯特凡诺斯·埃勒弗瑟里亚迪斯在撰写本文期间提出的问题和建议。感谢10 位创意人的约书亚·琼斯创作出特色形象。
我决定包括一些附录。没有这个附录也能看懂整篇文章。但是这里的材料给了你一个不同的,有趣的角度。
附录 1:通过边缘化推导可能性
本节说明如何使用概率论中的规则推导线性动态系统的似然性,而不使用卡尔曼滤波算法。
在我们开始之前,有一个关于从公式中移除随机变量的旁注。
如何从公式中删除随机变量
从概率论中推导似然性 p(Y) 需要对概率密度函数进行相当多的操作。作为旁注,让我们首先考虑如何从概率密度函数中移除随机变量。通常,有四种方式:
- 融入社会。例如,设 p(x,y) 为随机变量 x 和 y 的联合概率密度。那么 ∫ p(x,y)dy = p(x) 。现在 p(x) 是随机变量 x 的概率密度函数。
- 插入观测值:如果随机变量的观测值可用,可以将观测值插入该随机变量的位置。例如,设 Y 为随机变量 y 的观测值。那么 p(x,Y = Y)或者 p(x,Y) 如果我们要省墨,就变成了只针对随机变量 x 的概率密度函数。如果你从一个概率 p(y) 开始,你有随机变量 y 的观测值 Y ,你代入 Y 后,你得到 p(y=Y) ,或者 p(Y) 。注意 p(Y) 不再是概率密度函数,它变成了一个概率数。或者你可以把 p(Y) 看成一个没有自变量的函数。**
- 丢弃不相关的条件。例如,在一个条件中,设 p(x|y) 为随机变量 x 和y的联合概率密度,如果 x 不依赖于 y ,则可以去掉 y 得到 p(x) 。现在p(x)= p(x | y)和 p(x) 只是随机变量 x 的概率密度函数。****
- 高斯线性变换。如果随机变量 x 是高斯分布:x~𝒩(μ,K) , y 是添加高斯白噪声的 x 的线性变换: y=Ax + ε,其中ε ~𝒩(0,σ)。所以 y 的分布是 𝒩(Ax,σ)。这个分布提到了 x 。应用高斯线性变换法则得到 y 的分布公式,不提及 x : y~𝒩(Aμ,akaᵀ+σ).**
我们将使用这三种机制中的一些来推导可能性 p(Y) 。
似然公式
让我从上面复制线性动力系统的定义:
这里我们用 p(Y) 代替 p(Y|z) 来表示可能性。我决定去掉模型参数 z 以节省空间。因为模型参数 z 与当前截面无关。所以记住,这一节 p(Y) 是可能性,不是边际可能性。
让我们用 x 来表示每个状态的随机变量集合。所以 x={ x₁ , x₂ ,…,到 x_T} 。并使用 y 来表示每次观察背后的随机变量集合。所以 y={y ₁ ,y ₂ ,…,到 y _T}。而相应的观测被标注为 Y={Y₁ 、 Y₂ 、…,到 Y_T}。
可能性 p(Y) 在概率论中定义为:
第(1)行是通过从联合分布 p(Y,x) 中边缘化状态随机变量 x 来导出 p(y=Y) 的公式。我写 p(Y,x) 的时候,意思是 p(y=Y,x) ,读作“随机变量 Y,x 的联合概率密度并把观测值 Y 代入 y ”。这是一个你可以应用于任何概率系统的模板。
该线采用上述整合出和堵塞观察机构。并且我们认识到,可能性 p(Y) 是一个概率数,不再是一个概率密度函数。****
第(2)行使用概率论中的链式法则将联合分布 p(Y,x) 一分为二。这也是一个普遍适用的模板。
第(3)行明确列出了随机变量 x₁ ,到 x_T 和观测值 Y₁ 到 Y_T 。每个概率系统也是如此。请注意,该公式还明确写出了 x ₁ 到 xt的 T 积分。每个积分对单个随机变量求和。**
从第(4)行开始,我们开始推导特定于我们的线性动力系统的公式。
第(4)行将大条件句 p(Y|x) 拆分或分解成 T 小条件句p(yᵢ|xᵢ】。我们可以这样做,因为线性动力系统的第二个方程。这个等式告诉我们两件事:**
- 随机变量 y ₜ 只取决于 xₜ 。所以调节 y ₜ 在其他 xₖ 那里 k≠t 减少到调节 Yₜ 在 xₜ 。这允许我们分解 p(Y|x) 中的条件部分。单词“因式分解”的意思是将一个联合概率拆分成许多更小概率的乘积。**
- 给定 xₜ ,y ₜ 独立于其他随机变量 y ₖ 其中 k≠i 。所以 y ₁ ,y ₂ ,…,y _T 之间的联合概率等于这些随机变量以相应的 x ₁ , x₂ ,…,x _T 为条件的乘积。
该线采用下降无关条件机构。**
第(5)行将 p(x₁,x₂,…,x_T) 分解成 T 个较小概率的乘积。我们可以这样做,因为我们可以首先应用概率中的链式法则,然后使用线性动力系统的方程 2。这个等式定义 xₜ 只依赖于前一个状态 xₜ₋₁ ,就像这样:
第(6)行使用括号对 x ₁ 、 x₂ 、……的积分进行分组。这样,很容易看出我们可以首先计算 x ₁ 上的最内层积分,然后计算 x₂ 上的积分,依此类推。该线采用整合出机构。**
现在我们演示如何计算内部最大积分。这个积分是关于随机变量 x₁ 的。如果我们能做到这一点,我们可以用同样的方法计算其他积分。
在积分中,有三项。它们都是提及 x ₁、的可能性项,因此我们必须将它们列在关于 x1 的积分下。我们展示了这三部分是什么,以及如何计算这个积分。
首先,我们有:
这是因为我们已经定义了 x ₀ ~N(0,I) 。而 X₁ 是根据线性动力系统的第一方程从 X ₀的线性变换。
第二,我们有:
这是因为线性动力系统的第二个方程将随机变量 y₁ 定义为随机变量 x₁ 的线性高斯变换,我们将观测值 Y₁ 代入 y₁ 。
最后,我们有:
这是因为线性动力系统的第一个方程将随机变量 x₂ 定义为随机变量 x₁.的线性高斯变换
现在集成变成了:
请注意,在积分内部,三个高斯概率密度分布在不同的随机变量 x ₁、 y ₁ 和 x₂ 上。因为积分是关于 x ₁ 的,我想把三个高斯概率密度转换成同一个随机变量 x ₁ 。所以我可以做到以下几点:
- 我可以应用两个高斯函数的乘积法则。应用该规则两次,以获得 x ₁ 上的单个高斯概率密度,该概率密度前面有一个常数。
- 我知道对一个概率密度积分会得到 1。所以积分值是常数。
为了明白我的意思,让我们执行这个计划。顺便说一下,这是积分高斯概率密度乘积的常用技巧。
首先,由于 p(x₁) 已经是 x₁ 的概率密度函数,我们不需要做任何事情。
第二,
注意 2π的幂是 1/2,因为 y ₁ 是一维随机变量。如果有疑问,请查看的定义,多元高斯概率密度函数。
为了将这个公式转换成 x ₁ 的概率密度函数,我们需要提取 x ₁ 前面的 H 。我们还需要反转 x ₁ 前面的标志。这样,我们就可以为 x ₁ 匹配多元高斯概率密度函数的定义。
我们在 Y₁-Hx₁ 前面乘以 HH⁻ 。这不会改变该项的值,因为 HH⁻ 计算出单位矩阵。经过一些操作,我们得到了:
有了这个,我们就可以进行转置( Y₁-HX₁)ᵀ ):
我们现在用这两个新的等价变换替换原始公式中的相应项。我们有:
第(1)行和第(2)行显示原始公式;这是 Y₁的概率密度函数。
第(3)行执行我们之前执行的术语转换。现在我们可以看到,指数项是随机变量 x₁ 的新多元高斯概率密度函数的一部分。它有均值 H⁻ Y₁,并且它的协方差矩阵的逆是hᵀσᵥ⁻h,所以它的协方差矩阵是(hᵀσᵥ⁻h)⁻=h⁻σᵥ(h⁻)ᵀ。****
该指数项只是多元高斯概率密度函数的部分,因为完整的多元高斯概率密度函数需要指数前的归一化常数。我们可以从协方差矩阵计算这个常数,但是为了节省空间,我们称这个常数为 M₁常数。
第(4)行写出了这个新的高斯分布的签名。由于这个分布包含常数 M₁ ,我们必须将分布乘以 M₁⁻ 以保持相等。
最后,我们在 p(x₂工作;Ax₁,σ_ w)通过执行同样的步骤:
注意 2π的幂是 2/2,因为我们态的维数是 2。按照与之前相同的步骤,我们已经:
并且我们表示多元高斯分布前面的常数 M₂.
现在集成变成了:
第三行使用常数 M 表示概率密度前面的所有常数。
上述变换的重要性在于,它让我们看到,积分中的三个概率密度函数是随机变量 x ₁.的所以我们可以用下面两个高斯乘积的规则来导出一个组合概率密度:
和
这两个高斯乘积规则表明,组合概率密度仍然是针对同一随机变量,具有不同的均值、协方差和归一化常数。
由于积分内部有三个多元高斯密度,我们需要应用这个规则两次,才能得出最终的单一概率密度。假设最终概率密度的归一化常数为 Zₓ₁,平均值和协方差为μₓ₁和σₓ₁,则我们有:
第四行两次应用两个高斯乘积规则来导出最终的概率密度。注意,这个最终概率密度积分为 1,所有概率密度函数都是如此。所以整个积分评估为 MZₓ₁ 。
请注意, MZₓ₁ 是一个提到 x₂ 的表达式,因为 x₂ 出现在第三分量高斯分布的均值中,见第三行。实际上, MZₓ₁ 就是多元高斯概率密度函数p(x₂】。所以当你对 x₂做第二次积分时,你会得到和对₁:做第二次积分相同的结构**
所以,你可以继续计算 x₂ , x₃ ,…一个接一个地计算整个可能性 p(Y) 。结果将与我们在使用卡尔曼滤波算法之前展示的结果相同。
你可能会问,为什么我们要用不同的方法来推导可能性:
- 一种方法使用卡尔曼滤波算法,如前一节所述。
- 一种方法依赖于对联合概率 p(Y,x) 进行因式分解,在当前章节中描述。
实际上,知道一个就足够了,这意味着无论用哪种方法,你都可以计算出可能性。然后你可以进行参数学习,并做出预测。而是从两个方面来做:
- 你可以检查一下这两种方法是否一致。他们应该会给出非常接近的结果,因为他们计算的是相同的量,可能性 p(Y) 。
- 您可以进行分析,看看哪种方法更快。
- 更重要的是(至少对我来说),这是一个非常好的练习,可以锻炼你对概率模型的理解。推导公式真的可以帮助你理解之前定义的线性动力系统的性质。你会明白这些属性在计算可能性 p(Y) 方面有多大帮助。有了可能性,你就可以做参数学习,做预测。
揭开困惑矩阵的神秘面纱
原文:https://towardsdatascience.com/demystifying-the-confusion-matrix-d8ee2497da4d?source=collection_archive---------23-----------------------
不像名字暗示的那样令人困惑!
Photo by Nicolas Gras on Unsplash
混淆矩阵广泛用于评估监督机器学习分类器。它为我们提供了一种方法来可视化模型在预测测试观察的类别方面的能力。它由实际标签与模型预测值的关联表组成。为了简单起见,假设我们正在评估的分类器是二元的,即只有两种可能的结果,阳性(+)或阴性(-)。
在二元分类器中,一个 的正确预测 可能以两种方式之一发生:
- 正实例被模型预测为正( 真正 或 TP )
- 负实例被模型预测为负实例( 真负 或 TN )
在这两种情况下,我们都对结果感到满意。毕竟,任何分类器的最终目标都是正确区分正例与反例,并相应地对它们进行标记。
同样,一个 误分类 可能以两种方式之一发生:
- 正实例被模型预测为负实例( 假阴性 或 FN )
- 一个阴性实例被模型预测为阳性( 假阳性 或 FP )
一个错误分类是 永远不会 在机器学习算法中可取的。根据数据集和正在研究的现象,一个 假阴性 或一个 假阳性 可能比另一个有更严重的影响。
下面的混淆矩阵总结了上述信息。在继续下面的解释之前,花点时间理解这个图表。
让我们来看看可能从混淆矩阵中导出的一些 度量 。
- 准确(性)
- 精确
- 回忆
- 特征
- 假阳性率
- F1 分数
准确(性)
自然倾向于将 准确度 作为运行分类模型后的性能衡量标准。
准确度=正确预测值/总观测值
由于英语语法中单词 accuracy 的含义,当考虑分类器的性能时,很容易假设这是最佳度量。准确性衡量分类器“t”获得正确的频率,作为与 总观察值 的比率。当数据集不平衡时,准确性问题更加普遍,因为许多机器学习分类器偏向于 多数类 。在这些情况下,存在成为 准确性悖论 的牺牲品的风险。**
想象一下,如果你愿意,一个试图识别欺诈案件的分类器。如果一个数据集有 10,000 个实例欺诈发生率为 0.1%** ,这些记录中只有 10 个会被肯定地标记为欺诈!根据定义,这被认为是一个高度不平衡的数据集。**
如果该算法将每个案例标记为 正常 (即没有欺诈),我们得到以下准确度分数:
正确预测/总观察值= 9990/10000 =99.9%****
****印象深刻!但是,等等……如果我们要捕获的 TP 是:
- 存在癌症/疾病状态
- 骗税
- 罕见的天体现象
并且我们甚至无法捕获一个实例,那么部署这种模型将会是一个巨大的失败,尽管它具有近乎完美的准确性!
精确
Precision 是对“”准确性的度量,因为它查看正确预测的阳性与所有 预测的阳性 之间的比率。
精度= TP / (TP + FP)
回忆(又名敏感度,真阳性率)
召回是对“ 完整性 ”的一种度量,因为它查看正确预测的阳性与所有 实际阳性 之间的比率。
回忆= TP / (TP + FN)
大多数分类问题都是在回忆 之间的一个 权衡。通常增加一个会导致另一个的妥协。考虑工作中的垃圾邮件过滤器。
- FP =标记为垃圾邮件的有效电子邮件
- FN =发送到收件箱的垃圾邮件
提高阈值 会降低电子邮件被标记为阳性(垃圾邮件)的概率。这也增加了精确度并降低了召回率,在这种情况下更可取,因为 FP 呈现出比 FN 更严重的 结果 。
特异性(又名真阴性率)
同样,回忆是对正面结果的“”完整性的度量,特异性对值也是如此。我们看正确预测的否定和所有 实际否定 的比例。**
特异性= TN / (TN + FP)
下面,你可以看到改变阈值对 回忆 (记住这个和敏感度一样)和的影响。
Graphic from https://www.technologynetworks.com/
假阳性率
这是特异性的补充。
假阳性率= FP / (FP + TN) = 1 -特异性
假阳性率 和 假阴性率 形成受试者工作特性(【ROC】)曲线的坐标轴。这条曲线是另一个有用的工具,帮助我们找到两者之间的最佳平衡。ROC 曲线将在以后的文章中详细讨论。
F1 分数
此外, F1 分数 是精确度和召回率的调和平均值,是两者之间平衡的最佳衡量标准:
F1 得分= 2 x(精度 x 召回)/(精度+召回)
混乱矩阵不再混乱。我希望我已经澄清了你对这篇文章的一些误解。它是帮助我们评估分类器的一个非常好的工具。当我们理解了特定于所讨论的数据集的各个指标和含义时,我们就可以利用这个 2 x 2 信息矩阵的力量。最终,我们可以对我们的模型做出决策,并提高预测分析的价值。
让我们继续谈话。你可以在 LinkedIn 上找到我。
揭开数据科学工作类别的神秘面纱
原文:https://towardsdatascience.com/demystifying-the-data-science-job-families-c74f2294b1bd?source=collection_archive---------17-----------------------
解释性系列
理解数据科学家、研究科学家、应用科学家和商业智能工程师之间区别的外行指南
序幕
近来人工智能、机器学习和数据科学的崛起是前所未有的。每个行业都准备好迎接这场竞赛,将人工智能作为一种不可或缺的工具,以寻求新的途径来加强或多样化他们现有的产品。因此,这种新的冒险导致了大量雇佣具有相关人工智能技能的人。然而,考虑到巨大的需求和供应缺口以及不同组织的模糊要求,数据科学家和类似角色的期望在很大程度上被误解了。
最近,随着围绕数据科学的大肆宣传,市场上出现了几个奇特的角色,这进一步加剧了该领域新进入者的困惑。对于有抱负的发烧友来说,了解从哪里开始,追求哪一个工作家庭,确实是压倒性的。这篇博客文章旨在描述数据科学中各种工作类别之间的差异,并帮助您了解每个角色的不同之处,以及追求每个职位所需的技能。
设置背景
我假设你理解人工智能、机器学习和深度学习这些术语的基本含义。如果你仍然有一点困惑,请随时查阅我在早先的帖子,它阐明了上述复杂的术语。
这是我们将要处理的不同领域的总结—
- 人工智能:通过或不通过显式编程,人工将智能引入机器(软件系统)的艺术。
- 机器学习:(人工智能中的一个子领域)在没有显式编程的情况下将智能引入机器的艺术。
- 深度学习:机器学习和人工智能(A.I .)的一个领域,研究从人脑中获得灵感的算法,在没有显式编程的情况下帮助机器获得智能
这 3 个字段可以使用如下所示的文氏图来定义
此外,这里还有一些我们会直接或间接引用的其他术语。
- 商业智能:利用数据驱动的智能帮助企业进行决策和战略规划的艺术。
- 数据分析:商业智能的核心领域,专注于专门分析和探索数据,以挖掘对业务有意义的见解。
- 数据可视化:(数据分析中的一个子领域),专注于以图形方式表示数据,以帮助轻松解释和发现洞察力和数据模式。
- 数据工程:对数据进行处理、清理、转换和流水线作业以实现数据产品的艺术。
最后,
- 数据科学:构建数据驱动解决方案的科学。
如果我们从整体上来看数据科学领域,它包含了我们上面列出的每个领域。简而言之,我们需要数据工程、数据可视化、商业智能和人工智能来提供任何规模和复杂性的数据科学解决方案。下图有助于理解这些不同的技能如何在“数据科学”下叠加在一起
Illustrative representation — Data Science Ecosystem
从一个组织的数据团队的角度来看,为了实现一个共同的目标,至少有 3 个独立的团队专注于数据工程、AI 和 BI。此外,当定义基于数据科学的角色时,3 个领域之间的技能有明确的重叠。我们将很快进一步探讨这一点。
深入挖掘
在继续之前,我想帮助您理解技能分离是任何领域的自然过程(因为它不仅限于数据科学)。由于大多数数据科学爱好者都来自软件背景,因此将技术领域内的已知情况与人工智能进行比较是值得的。
与数据科学类似,软件工程领域也是一个总括术语,包含各种不同的技能。web 开发人员、前端工程师、全栈开发人员、大数据工程师、UI 工程师、数据工程师等。都被贴上了软件工程师的标签。尽管上述每个角色都为技术成果勾勒出不同的技能组合;整体的定义仍然属于软件工程。
类似于软件工程,数据科学也是一个伞状工作系列,其中包含几个不同的工作角色。
定义基于数据科学的角色的职责
现在,让我们探讨一下在数据科学生态系统中,工作族应该承担的高级职责。
我们将从基础角色开始—
数据工程师
- 根据解决方案的需要,从各种异构源提取、加载、处理、清理数据并将其转换到一个或多个整合的渠道中。
- 构建数据管道、执行数据验证、管理数据安全性和策略以及努力实现定义的数据可用性等。
核心技能 — SQL、ETL、大数据(Hadoop、Hive、Pig、Spark 等。),面向大数据的云生态系统(例如,AWS EMR、Redshift、Dynamo、Aurora 或 Azure/GCP 相关服务)
Visualizing skill stack for Data Engineer
商业智能工程师/数据分析师
- 与利益相关者合作,了解业务领域需求。
- 与数据工程师协作,确定和获取所需数据,以便根据业务需求做出数据驱动的决策
- 分析和挖掘大量数据,为利益相关方提供情报/有意义的见解,从而帮助制定数据驱动的决策
- 利用各种可视化工具开发可重复的业务报告,通过易于理解的数据见解向更多受众传达关键见解。
核心技能 — SQL、数据可视化(比如,Tableau、SpotFire 等。)、商业敏锐度、报告(仪表板)
Visualizing Business Intelligence Engineer skill stack
数据科学家
- 与业务利益相关者合作,确定 ML 用例
- 探索,分析,设计,实验和原型 ML 用例,解决业务问题的具体成果
- 利用与业务相关的 KPI,用通俗的术语向利益相关者传达 ML 原型的影响/结果。
核心技能——机器学习和或深度学习、一种或多种 ML 友好编程语言(Python/R/Julia)、脚本、数据可视化、商业敏锐度、数据工程
Visualizing the Data Scientist skill stack
人工智能研究科学家。
- 独立研究、实验和设计 ML 解决方案原型,以解决大型企业领域中的问题(例如,广告定位、视频处理、NLP、计算机视觉等)。)
- 与数据科学家合作,扩展实验并验证业务相关性
- 与应用科学家合作,将 ML 原型部署/转化为有形的商业解决方案。
核心技能 —机器学习,(编程熟练程度有限)
Visualizing the Research Scientist-A.I. skill stack
应用科学家-人工智能/ML 工程师
- 与研究科学家和数据科学家合作,将研究原型和 ML 实验转化为有形的软件工件。
- 部署大规模 ML 解决方案利用软件工程、云计算/无服务器基础设施来部署大规模软件解决方案。
- 与软件工程师、数据工程师和开发人员合作,将 ML 解决方案集成和扩展到企业生态系统中的大型复杂软件产品中
核心技能 -机器学习、软件工程
Visualizing the Applied Scientist -A.I. skill stack
将这一切结合在一起
上述 5 种角色可能并不总是存在于一个组织中。更具体地说,大多数组织不需要数据科学工作系列中的 5 个不同角色。大多数有抱负的人工智能公司仍处于采用人工智能的非常早期的阶段。在这样的组织中,大多数业务需求可以通过上述列表中的 2 个或最多 3 个不同的数据角色来满足。
然而,随着组织规模和数据文化的成熟,人工智能的复杂性也逐渐成熟,并逐渐要求每个角色都具有独特的和更适合的技能。为了总结和轻松解释各种数据科学角色之间的差异,我们可以将数据科学工作系列中的所有相关角色堆叠在一起,如下所示。
Consolidated skill visualization for Data Science related roles
总结想法
本文的目的是帮助您提炼数据科学工作系列中不同角色之间存在的差异。以上 5 个工作角色可能不是详尽的,但肯定会帮助你理解相关技能的广泛分类。随着数据文化和人工智能的采用规模扩大,这个矩阵注定会进一步分裂为更具体和更适合的角色。
进一步阅读
如果你有兴趣,你可以看看我在这方面的另一篇文章— 我们为什么需要 AWS Sagemaker ?
本文从较高的层面介绍了该服务如何补充数据科学家所需的数据工程和软件工程技能,以便将 ML 实验和原型部署到大规模全功能和弹性的 API 服务中。