TowardsDataScience-博客中文翻译-2021-九十-
TowardsDataScience 博客中文翻译 2021(九十)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
基于 Spark 的 Twitter 数据主题建模和情感分析
原文:https://towardsdatascience.com/topic-modeling-and-sentiment-analysis-on-twitter-data-using-spark-a145bfcc433?source=collection_archive---------13-----------------------
某个地区的 twitter 用户关注什么,他们对某些问题的反应是什么?
亚历山大·沙托夫在 Unsplash 上拍摄的照片
介绍
这是与队友一山、小静、贾尼斯和兰吉特完成的学校项目总结。Twitter 情绪分析是一个面向大数据分析新手的 hello world 项目。
在这个项目中,我们想知道新加坡用户在 twitter 上关注什么,以及人们对某个话题的反应。为了回答这个问题,我们使用 Spark SQL、Spark MLlib 和 Spark streaming 等 Spark 库设计了两条 twitter 数据分析管道。
建筑
作者图片
管道 1:批处理和主题建模
在这一部分中,我们使用 tweepy 从完整的归档 API 中提取 tweets 并保存到 hdfs 中。然后,我们调用 Spark SQL 和 Spark MLlib 来处理 tweets 以进行主题建模,并用 matplotlib 或 tableau 保存结果以进行可视化。
管道 2:流处理和情感分析
在这一部分中,我们使用 tweepy 和主题建模中的关键字来过滤流媒体 tweets。我们还在 tweepy 和 Spark 之间创建了一个 TCP 套接字。TCP 套接字会将 tweets 发送到 Spark 流进行处理。然后,结果将被发送到使用 Flask 构建的仪表板。
批处理和主题建模
步骤 1:从 twitter API 批量获取推文
Twitter 刚刚将 API 从 1.0 版升级到 2.0 版。要使用 2.0 版 API,我们需要使用 tweepy v4.0 版,该版本目前仍处于 Github 的开发阶段。使用 twitter 的原生 API 也可以。要使用完整的存档 API,我们需要有一个学术帐户。我们为这个学校项目申请了一个学术帐户,该帐户每月授予我们 1000 万条推文配额和更多的查询 API。
我们为完整的存档推文设定了一些标准。推文的位置应该是新加坡,语言英语和转发被排除在外。可以调整返回的开始时间和结束时间以及其他字段,在本例中,时间设置为 2021 年 4 月。
对于 4 月份发布的推文,我们能够提取出大约 4.8 万条符合标准的推文。
第二步:批处理
在这一步中,我们需要在建模之前做一些预处理。我们探索了 tweets 的 json 结构。嵌套 json 结构被简化为每行一个记录,每列一个属性。展*后,执行一些常见的预处理步骤,如去除非文本、标记化、词条化和去除停用词。
步骤 3:使用网格搜索的主题建模
在文本清洗和标记化之后,我们使用 LDA 进行主题建模。由于我们不确定主题的最佳数量,我们使用网格搜索来确定。通过简单的肘法,我们发现 4 月推文中有 6 个话题。
步骤 4:基于主题创建条形图竞赛
在主题建模之后,我们可以为每条推文分配主题,并将推文分配给一个主导主题。我们汇总了每天每个主题下的推文数量。然后我们用柱状图 race 包演示了四月份话题的动态变化。
作者提供的视频
流处理和情感分析
步骤 1:过滤后的 tweets 流并发送到 TCP 套接字
从第一个管道,我们决定把重点放在缅甸政变的话题。我们使用缅甸作为流数据的关键字。在这一部分中,我们还创建了一个 TCP 套接字来接收流数据。这些数据最终会被火花流消耗掉。
第二步:使用 Spark 流进行推特情感分析
在这一部分中,我们使用 spark 流来处理实时数据。Spark streaming 是一个较老的 API,它使用最小批量方法。我们需要定义将流数据转换为离散流(名为 d stream)的批处理间隔。我们将批处理间隔定义为 2 秒。我们会根据文本-blob 包中的情绪极性将每条推文定义为积极、中立或消极。然后,我们统计了每个类别下的推文数量。我们还统计了最常用的词和标签,并显示了过去一周推文的地理位置。我们使用过去一周的推文而不是实时推文进行地理定位的原因是,只有 1-2%的推文带有地理标签。
第三步:烧瓶仪表板
在这一部分,我们使用 MVC(模型-视图-控制器)框架来设计仪表板。我们定义了如何在模板的每个部分显示数据。
实时仪表板
作者提供的视频
在线性虐待材料科学文献的主题建模(CSAM)
原文:https://towardsdatascience.com/topic-modeling-of-scientific-literature-on-online-sexual-abuse-materials-csam-749a3e42250b?source=collection_archive---------40-----------------------
使用 TF-IDF、Louvain 聚类和 D3.js 的网络图可视化
我最*与救助儿童会合作参加了 Omdena AI 挑战赛,这是一个领先的儿童人道主义组织,使用自然语言处理(NLP)技术探索针对儿童的在线性暴力问题。
照片由若昂·赞诺在 Unsplash 上拍摄
主题建模
主题建模是一种无监督的机器学习文本分析技术,能够检测文档集合中的单词和短语模式。然后,检测到的模式用于将文档聚类到特定主题中。它是一种常用的文本挖掘工具,用于发现文本数据中的语义结构。
简单地说,关于特定主题的文档或多或少会包含特定于该主题的某些单词。
该任务的目标是收集科学文章的文本数据,应用主题建模将文档聚类成单独的主题,然后使用图形网络创建该聚类的可视化。
数据收集
在进行任何分析之前,首先执行的任务之一是收集关于 CSAM 的数据。文章收集自多个资源库,包括核心、理念、研究门户、开放获取期刊目录和世界猫。在本文中,我们将重点关注从 CORE 收集的文章。
数据是通过 API 收集的。为了发出请求,我们向 CORE 注册了一个帐户,并收到了一个 API 密钥。我们需要 API 键和搜索词来提出请求。使用的搜索词—
#query = "((internet OR online OR technology OR chatroom OR chat) AND (minor OR child OR underage OR children OR teenager) AND (abuse OR exploitation OR grooming OR predation) AND (sex OR sexual OR carnal)) OR (internet OR online OR technology OR chatroom OR chat) AND (predators OR offenders) AND (sex OR sexual OR carnal) OR (child sexual abuse material OR CSAM)"#query = "(internet OR online OR technology OR chatroom OR chat) AND (predators OR offenders) AND (sex OR sexual OR carnal)"#query = "(child sexual abuse material OR CSAM)"
收集数据的 Python 代码—
核心提取代码
核心数据帧
数据清理和预处理
与任何类型的数据分析一样,我们必须首先清理数据。对数据的直观检查显示存在重复的行。基于包括标题、摘要和 DOI 在内的许多列,删除了重复的内容。对这些问题进行了单独和组合研究。
core_df = core_df.drop_duplicates(subset=['Title'])
我们使用了 clean text library,这是一个 python 包,它结合了许多清理步骤,包括删除标点、数字和多余的空格,以及将文本改为小写。
通过检查某些关键词是否出现在摘要和/或文本栏中来过滤数据。
关键词过滤
然而,这种手动过滤方法导致了许多相关文章的丢失。最终采取了不同的方法。稍后将详细介绍。
在预处理步骤之后,我们在数据帧中有 35K 行—
已清理的文本—按作者排序的图像
TF-IDF 矢量化
在自然语言处理中,文本必须首先被转换成机器能够理解的东西。转换成数字使我们能够对它们进行数学运算。有许多文本矢量化的方法,在本文中,我们将探讨 TF-IDF 矢量化。
TF-IDF 代表词频逆文档频率。这是一种技术,我们给语料库或数据集中的词分配一个重要性分数。重要性的分配基于两个标准——
词频 —这被定义为单词在文档中出现的频率除以单词的数量。
逆文档频率—一个词在语料库中的稀有或常见程度。这可以通过取文档总数与包含该单词的文档数之比的对数来计算。我们通过取这两项的乘积来计算 TF-IDF 分数。术语越高,单词越重要。
TF-IDF 矢量器
参数值 max_features 为 10000 是指要考虑的顶级特性的最大数量。ngram_range 指定我们正在考虑一元模型和二元模型。矢量器的输出是一个 35000x10000 的稀疏矩阵,其中 35K 表示文章的数量,10000 表示 max_features。
降维
这是通过将数据集中的特征的维数从高维空间减少到低维空间来进行的数据转换,使得低维表示仍然保留数据的一些相对有意义的属性。
我们遇到了一些问题,在内存上拟合 K-Means 聚类的数据。我们选择使用潜在语义分析(LSA)或截断奇异值分解(在 SKlearn 上)进行降维。
与任何降维技术一样,为了决定要选择的组件数量,我们检查了不同数量的组件,并选择了具有最高解释比率的组件。
降维
我们选择了一些 2800 的成分,其解释方差比为 0.89。
k 均值聚类
K-Means 是一种流行的无监督学习聚类技术,用于将数据点分组到非重叠的子组中。集群被定义为与集群内的其他对象比与集群外的对象更相似的对象组。
类似地,我们对 2-80 范围内的多个聚类数运行 K-Means,并计算每个聚类数的轮廓得分。选择得分最高的聚类。
k 均值聚类
剪影分数图-作者提供的图像
我们选择 72 作为最佳聚类的初始数量。
去掉无关的话题
在对集群进行人工检查时,我们注意到一些集群被认为需要移除。我们注意到与领域无关的文档集群,以及不同语言的集群。聚类是过滤掉不相关文章的好方法。
词云
文字云可视化——作者图片
上面的单词云显示了第一次实现聚类时每个片段中最重要的单词。例如,我们注意到,Cluster-ID 4、10、14、18 和 44 不是英语。
网络图
艾莉娜·格鲁布尼亚克在 Unsplash 上的照片
网络图是显示实体间相互联系的一种方式。这个子任务的目标是可视化地表示不同文章之间的关系。为了实现这一点,我们选择突出两种类型的关系,文章所属的不同主题,以及文章之间相似性的数字度量。我们决定采用两种不同的技术来实现这一点—
余弦相似性
这是对文档之间相似程度的一种度量。它用于测量在多维空间中投影的两个向量之间的角度的余弦。这就告诉我们这些矢量是指向相同的方向。
衡量文档间相似性的另一种常用方法是计算它们共有的字数。这种方法有一个问题,然而,文档越大,不管主题是什么,它们之间的共同点就越多。余弦相似性在这里起作用,因为它捕捉的是向量的方向,而不是大小。
鲁文聚类
用于社区检测的 Louvain 聚类是一种无监督的机器学习技术,用于理解和检测大型复杂网络中的社区。
Louvain 集群实现
主题
从卢万,我们得到 5 个不同的社区。对社区的人工检查表明—
- 制度、政治(立法)和社会话语
- 在线儿童保护—漏洞
- 技术视角
- 罪犯分析
- 商业视角与贩运
主题分布-按作者分类的图片
形象化
随着余弦相似性的计算和 Louvain 聚类的实现,我们现在有了创建网络图所需要的东西。如上所述,网络图显示了实体之间的连接,实体可以由节点(或顶点)表示,节点之间的连接由链接(边)表示。
余弦相似性输出是介于 0 和 1 之间的数字,分别代表无关系到完美关系的范围。文档越相似,链接就越强。节点可以基于文章最认同的主题来着色。
可视化是使用 D3.js 创建的,托管在 Netlify 的免费 Github 托管服务上(如果第一次没有正确加载,请刷新页面),可以在这里找到。
网络图实现
将鼠标悬停在节点上可查看文章和其他链接文章的标题。可以拖动节点以获得更好的可视性。为了获得更好的可视性,我们为链接强度设置了一个阈值,这意味着低于 0.3 的链接应该从可视化中排除。
此外,为了防止节点偏离可视屏幕区域太远,我们设置了一个边框,这就是可视化周围的方形边框形状。
报纸文章也做了类似的分析,可以在这里找到。
未来的工作
许多不同的领域可能需要改进。TF-IDF 有许多限制——对于大型词汇表来说计算量很大,并且不能捕获单词的语义。例如,困惑和迷惑在意思上是相似的,但是 TF-IDF 可能没有抓住这一点。
更高级的方法包括单词嵌入、word2vec 和 doc2vec(针对文档而非单词)。
例如,一种更先进的测量文档相似性的方法是使用来自变压器的双向编码器表示(BERT) 使用变压器,一种基于注意力的模型来学习单词嵌入。
一个可能的应用是创建一个搜索功能,在与特定文章相似的某个范围内查询特定主题内的文章。这可以借助于能够以图形结构存储数据的图形数据库来实现。图形网络的直观结构允许人们进行复杂的查询,而这在关系数据库中是不可能的。
Neo4j 数据库—图片由作者提供
此时加载的特定数据非常简单,只有一些节点、属性,并且只定义了一个关系(余弦相似性)。然而,由于图形数据库的灵活性,将来或在需要时,可以添加更多的节点和标签,以及定义更多的关系。这些关系可以使用机器学习以及其他非 ML 方法来导出。
Neo4j 还允许安装第三方插件,包括 data science/ML 插件,允许在数据库中实现和应用机器学习算法,包括 Louvain 聚类和社区检测。
参考
Nasar Z,Jaffry S W,Malik M K (2018)从科学文章中提取信息:一项调查http://faculty . pucit . edu . PK/swjaffrey/RPR/scientimetrics 18 Information mining . pdf
Stecanella R (2017)文本矢量化初学者指南https://monkey learn . com/blog/初学者指南-文本-矢量化/
范德马腾,劳伦斯;邮政局长,埃里克;范·登·赫里克,贾普(2009)维数约减:一个比较评论https://members . loria . fr/moberger/enseignment/AVR/Exposes/TR _ dimensionereductie . pdf
Pantola P (2018)自然语言处理:文本数据矢量化https://medium . com/@ paritosh _ 30025/Natural-Language-Processing-Text-Data-矢量化-af2520529cf7
普拉巴卡兰(2019)余弦相似性——理解数学及其工作原理https://www.machinelearningplus.com/nlp/cosine-similarity/
博斯托克 M (2017)力定向图https://observablehq.com/@d3/force-directed-graph
Raghunathan D (2020) NLP in Python-矢量化https://towardsdatascience . com/NLP-in-Python-矢量化-a2b4fc1a339e
Jayaswal V (2020)文本矢量化:词频—逆文档频率(tfi df)https://towardsdatascience . com/Text-Vectorization-Term-Frequency-Inverse-Document-Frequency-tfi df-5a 3f 9604 da6d
巴赫 T (2020)用变形金刚寻找相似文档https://www . codegram . com/blog/Finding-similar-documents-with-transformers/
Borad A (2020) NLP 文本预处理:文本矢量化【https://www.einfochips.com/blog/nlp-text-vectorization/
图像上的主题建模?为什么不呢?!
原文:https://towardsdatascience.com/topic-modeling-on-images-why-not-aad331d03246?source=collection_archive---------15-----------------------
但是让我们称之为概念建模吧!
主题建模是一组技术的集合,允许用户在大量数据中发现主题,不受监督。当试图对那些文档的内容建模和执行 EDA 时,这可能是非常有利的。
不久前,我创建了一个名为 BERTopic 的主题建模技术,它利用 BERT 嵌入和基于类的 TF-IDF 来创建密集的集群,从而允许轻松解释主题。
过了一段时间,我开始思考它在其他领域的应用,比如计算机视觉。如果我们可以在图像上应用主题建模,那该有多酷?
在图像和文本上执行主题建模所需要做的就是。图片由作者提供。
花了一段时间,但经过一些实验,我想出了解决办法, 概念 !
Concept 是一个同时在图像和文本上引入主题建模概念的包。然而,由于主题通常指的是书面或口头的话,它不能完全概括分组图像的含义。相反,我们将这些分组的图像和文本称为概念。
概念的标志。图片由作者提供。
因此,概念包执行概念建模,这是一种用于发现出现在图像和相应文档集合中的抽象概念的统计模型。
概念建模是主题建模对图像和文本的概括
为了让您有个概念,下面的概念是通过概念建模检索的:
通过概念建模产生的多模态概念。图片由作者提供。
你可能已经注意到了,我们可以通过它们的文本表示和视觉表示来解释这些概念。然而,概念建模的真正优势可以通过组合这些表示来发现。
概念建模允许概念的多模态表示
一幅图像比一千个字更能说明问题。但是如果我们给图像添加文字呢?这两种沟通方式的协同作用可以丰富对一个概念的解释和理解。
https://colab.research.google.com/drive/1XHwQPT2itZXu1HayvGoj60-xAXxg9mqe?usp=sharing
在本文中,我将介绍使用概念创建您自己的概念模型的步骤。你可以跟随上面链接中的 Google Colab 笔记本。
步骤 1:安装概念
我们可以通过 PyPI 轻松安装 Concept:
pip install concept
步骤 2:准备图像
为了执行概念建模,我们需要大量的图像进行聚类。我们将从 Unsplash 下载 25,000 张图片,因为它们已经由句子-变形金刚包准备好了。
准备好图像后,我们已经可以在没有任何文本的情况下在概念中使用它们了。但是,不会创建任何文本表示。所以下一步是准备我们的文件。
第三步:准备文本
这个概念有趣的一面是任何文本都可以输入到模型中。理想情况下,我们希望给它输入与手边图像最相关的文本。我们通常对在我们的图像中能找到什么有一些了解。
然而,情况可能并不总是如此。因此,出于演示目的,我们将向模型输入英语词典中的一组名词:
在上面的例子中,我们采用 50.000 个随机名词有两个原因。首先,没有必要在英语词典中找到所有的名词,因为我们可以假设 50.000 应该代表足够的实体。第二,这稍微加快了计算速度,因为我们需要从更少的单词中提取嵌入。
在实践中,如果你有你知道的与图像相关的文本数据,使用它们而不是名词!
第四步:训练模型
接下来就是训练模型了!像往常一样,我们保持相对简单。只需将每个图像的路径和我们选择的名词输入到模型中:
concepts
变量包含每个图像的预测概念。
概念的底层模型是 Openai 的剪辑,它是一个训练了大量图像和文本对的神经网络。这意味着该模型在生成嵌入时受益于使用 GPU。
最后,运行concept_model.frequency
来查看包含概念频率的数据帧。
注:使用Concept(embedding_model="clip-ViT-B-32-multilingual-v1")
选择支持 50 多种语言的机型!
预训练图像嵌入
对于那些想要尝试这个演示但没有 GPU 的人,我们可以从句子变形金刚网站加载预训练的图像嵌入:
然后,我们将预训练的嵌入添加到模型中,并对其进行训练:
第五步:形象化概念
现在有趣的事情,可视化的概念!
如前所述,由此产生的概念是多模型的,即自然的视觉和文本。我们需要找到一种方法在一个概览中同时表现这两者。
要做到这一点,我们需要一些最能代表每个概念的图片,然后找出最能代表这些图片的名词。
实际上,创建可视化非常简单:
九个最常见的概念被可视化。图片由作者提供。
我们数据集中的许多图片都与自然有关。然而,如果我们看得更远一点,我们可以看到更有趣的概念:
更频繁的概念。注意概念的多样性。图片由作者提供。
上面的结果给出了一个很好的例子,说明如何在概念建模中直观地思考概念。我们不仅可以通过一系列图像看到视觉表现,而且文字表现有助于我们进一步理解在这些概念中可以发现什么。
步骤 6:搜索概念
我们可以通过嵌入搜索词并找到最能代表它们的聚类嵌入来快速搜索特定的概念。例如,让我们搜索术语**beach**
,看看我们能找到什么。为此,我们只需运行以下命令:
每个元组包含两个值,第一个是概念簇,第二个是与搜索词的相似度。返回前 5 个相似主题。
现在,让我们将这些概念形象化,看看搜索功能的效果如何:
“海滩”一词的搜索结果。图片由作者提供。
正如我们所看到的,产生的概念与我们的搜索词非常相似!该模型的多模态特性允许我们轻松地搜索概念和图像。
步骤 7:算法概述
对于那些对概念的基础感兴趣的人来说,下面是用于创建结果概念的方法的抽象概述:
概念的算法概述。图片由作者提供。
1.嵌入图像和文档
我们首先使用 OpenAI 的剪辑模型将图像和文档嵌入到同一个向量空间中。这使我们能够在图像和文本之间进行比较。文档可以是单词、短语、句子等。你觉得最好的代表概念群。
2.概念集群
使用 UMAP + HDBSCAN,我们可以对图像嵌入进行聚类,以创建视觉上和语义上彼此相似的聚类。我们将集群称为概念,因为它们代表了多模态的性质。
3.概念表征
为了直观地表示概念簇,我们将与每个概念最相关的图像称为样本。根据概念聚类的大小,每个聚类的样本数可能超过数百个,因此需要一个过滤器。
我们使用 MMR 来选择与概念嵌入最相关的图像,但是彼此之间仍然有足够的差异。这样,我们可以尽可能多地展示这个概念。然后,所选图像被组合成单个图像,以创建单个视觉表示。
4.多模态
最后,我们将文本嵌入与创建的概念簇嵌入进行比较。使用余弦相似性,我们选择彼此最相关的嵌入。这将多模态引入到概念表示中。
注意:还有一个选项是使用 c-TF-IDF 来提取使用concept_model = ConceptModel(ctfidf=True)
的文本表示
感谢您的阅读!
如果你和我一样,对人工智能、数据科学或心理学充满热情,请随时在 LinkedIn 上添加我,或者在 Twitter 上关注我。
您可以在下面找到 Concept 及其文档:
https://github.com/MaartenGr/Concept https://maartengr.github.io/Concept/
使用 LDA 的主题建模
原文:https://towardsdatascience.com/topic-modeling-using-lda-59586a20dbfa?source=collection_archive---------38-----------------------
快速获取 30,000 多条推文的要点!
简·安东宁·科拉尔在 Unsplash 上拍摄的照片
在我的最新项目中,我探索了这样一个问题,“在新冠肺炎·疫情期间,美国公众对 K-12 学习的看法如何?”。
使用从 Twitter、自然语言处理和监督机器学习收集的数据,我创建了一个文本分类器来预测推文对这个话题的情绪。
太棒了。我能够根据积极、消极或中性的情绪对推文进行分类。但是 Twitter 用户在这些推文中实际上在谈论什么呢?如果我们只关注情绪,有没有什么模式或趋势我们可能会错过?在一种特定的情绪下,某些话题会出现得更频繁吗?在这些推文的内容中,我们还有很多可以探索的地方。
考虑到这一点,我决定执行主题建模来补充情感分类器。我的观点是,主题建模是对基于频率的“词云”方法的改进,以理解文本语料库中的内容。
不要误会我;我喜欢漂亮的文字云来展示时髦的图形。然而,由于我的文本(或者我应该说 Tweet)语料库如此之大(~30,000 条 Tweet)并且如此多样(美国范围内以及在 COVID 疫情期间 K-12 学习的广泛主题),主题建模无疑是正确的选择。为了使主题建模更加有效,我利用了奇妙的交互式可视化工具 pyLDAvis 。
以下是我将推文分成不同主题并进行探索性数据分析的步骤。
- 文本处理
- 主题建模
- 交互式可视化
文本处理
在使用LatentDirichletAllocation(LDA)执行主题建模之前,我需要应用一些文本处理。当我训练文本分类器识别情感时,标点符号和大写字母实际上对分类器是有用的,所以在训练分类器之前,我只对语料库进行了非常轻微的文本处理。对于主题建模,标准化语料库文本实际上是必要的。下面是我应用的文本处理:
- 将 Tweet 文本改为小写( nltk 的 TweetTokenizer 处理此)
- 删除 RT (Retweets)和# (hashtag 符号)(使用正则表达式)
- 移除 URL(使用正则表达式
- 从文本中删除停用词和标点符号。
- 对所有单词执行词汇化(使用 nltk 中的词汇词汇化)
所有的文本处理都发生在clean _ tokenize _ lemma tize _ tweet函数中。
sw_and_punct = stopwords.words(‘english’) + list(string.punctuation)# TweetTokenizer will put all text in the tweet to lowercase, strip out usernames/handles and reduce reated chars in words
tweet_tokenizer = TweetTokenizer(preserve_case=False, strip_handles=True, reduce_len=True)lemmatizer = WordNetLemmatizer()def clean_tokenize_lemmatize_tweet(tweet):
#remove urls
tweet = re.sub(r’http\S+|www\S+|https\S+’, ‘’, tweet, flags=re.MULTILINE)
#remove RT
tweet = re.sub(r’^RT\s+’, ‘’, tweet)
#remove the # symbol
tweet = re.sub(‘#’, ‘’, tweet)
#tokenize
tokens = tweet_tokenizer.tokenize(tweet)
# remove stopwords and punctuation
tokens = [token for token in tokens if token not in sw_and_punct]
# remove tokens that are only 1 char in length
tokens = [token for token in tokens if len(token)>1]
#lemmatize
lemmatized_tokens = [lemmatizer.lemmatize(token) for token in tokens]
return lemmatized_tokens
主题建模
使用 sklearn 的 LatentDirichletAllocation 进行主题建模相当简单。首先,您需要通过创建文档术语矩阵(DTM)将语料库中的单词转换成数字。我用 sklearn 的计数矢量器创建了一个 DTM。查看下面的代码:
sample_corpus = ['This is the first sample document.',
'This document is the second sampledocument.',
'And this is the third one.',
'Is this the first document? I do think so!' ]my_cv = CountVectorizer(tokenizer=clean_tokenize_lemmatize_tweet)my_lda = LatentDirichletAllocation(n_components=5)
my_dtm = cv.fit_transform(sample_corpus)my_lda.fit(my_dtm) # may take a while with a large corpus ;)
交互式数据可视化
既然 LDA 已经施展了它的魔法,我们可以看看这些主题了。你可以把这些画出来;然而,使用 pyLDAvis 来探索你的语料库主题要有趣得多!
import pyLDAvis.sklearn
pyLDAvis.enable_notebook()
pyLDAvis.sklearn.prepare(my_lda, my_dtm, my_cv)
只需这几行代码,您就能得到一个令人印象深刻、信息丰富的交互式可视化效果,如下图所示!
图片由作者提供
如果你想看看 pyLDAvis 的表现,看看我的“在 COVID 期间学习”推文中的一些话题。
结论
通过对语料库应用主题建模,并添加 pyLDAvis 包以提供交互式可视化,我们打开了深入研究来自美国各地 30,000 多条推文的主题之门!
如果您发现这很有帮助,我鼓励您在自己的工作中扩展这个例子。请随时提出改进建议,或者让我知道这对您是否有帮助。
主题建模:深入研究 LDA、混合 LDA 和非 LDA 方法
原文:https://towardsdatascience.com/topic-modelling-a-deep-dive-into-lda-hybrid-lda-and-non-lda-approaches-d17d45ddaaaf?source=collection_archive---------28-----------------------
在你写一行代码之前,你需要知道的是
由 Raphael Schaller 在 Unsplash 拍摄的照片
主题建模是我发现在我的角色中最需要的自然语言处理技术之一。最*,我看到它作为实体提取而流行起来,然而,它的目的仍然是一样的——在文本语料库中进行模式识别。
在本文中,我将对可用于对短格式文本进行主题建模的技术进行深入的回顾。短格式文本通常是用户生成的,由缺乏结构、存在噪声和缺乏上下文来定义,导致机器学习建模困难。
这篇文章是我的情感分析深度探索的第二部分,是我做的关于主题建模和情感分析的系统文献综述的结果。
概观
主题建模是一种文本处理技术,旨在通过找出并展示文本数据中被识别为主题的模式来克服信息过载。它实现了改进的用户体验,允许分析师在已识别主题的引导下快速浏览文本语料库或集合。
主题建模通常通过无监督学习进行,运行模型的输出是所发现主题的概述。
检测话题可以在在线和离线模式下完成。当在线完成时,它的目标是随着时间的推移发现出现的动态话题。离线时,它是回顾性的,将语料库中的文档视为一批,一次检测一个主题。
主题检测和建模有四种主要方法:
- 基于键盘的方法
- 概率主题建模
- 衰老理论
- 基于图表的方法。
方法也可以通过用于主题识别的技术进行分类,这产生了三个组:
- 使聚集
- 分类
- 概率技术。
1.潜在狄利克雷分配
LDA(潜在狄利克雷分配)是一个贝叶斯分层概率生成模型,用于收集离散数据。它基于文档中单词和主题的可交换性假设进行操作。它将文档建模为主题的离散分布,后面的主题被视为文档中术语的离散分布。
最初的 LDA 方法使用变分期望最大化(VEM)算法来为 LDA 推断主题。后来基于 Gibbs 抽样的随机抽样推断被引入。这改进了实验中的性能,并且已经被更频繁地用作模型的一部分。
首次引入 LDA 的 Blei 和他们的同事们展示了它相对于概率 LSI 模型的优越性。 LSI(潜在语义索引)使用线性代数和单词袋表示法来提取意思相似的单词。
LDA 的好处——LDA 有什么好处?
- 战略业务优化
在所有审查的技术中,LDA 最常被列为模型的一部分,并被认为对战略业务优化有价值。
2。通过更好地理解用户生成的文本来提高竞争优势。
一项 2018 研究证明了 LDA 作为一种通过从用户在线评论中提取信息并随后根据情感对主题进行分类来提高公司竞争优势的方法的价值。
3。提高公司对用户的了解。
基于 LDA 的主题建模也被用于描述用户的个性特征,基于他们的在线文本出版物。
在我自己的研究中,我使用 LDA 主题建模,根据用户在社交媒体上发布的与产品或公司相关的简短的用户生成文本,在用户的客户旅程阶段对用户进行分类。
4。了解客户投诉,提高客户服务效率。
在一项 2019 年的研究中, LDA 主题建模用于分析消费者金融保护局的消费者投诉。预先确定的标签用于分类,这通过任务自动化提高了投诉处理部门的效率。
LDA 的局限性——LDA 被批评了什么?
- 无力伸缩。
LDA 因其所基于的技术的线性而被批评为不能缩放。
其他变体,如 pLSI,LSI 的概率变体,通过使用统计基础和生成数据模型来解决这一挑战。
2。假设文件可交换性
虽然 LDA 很有效并且经常使用,但是它对文档可交换性的假设受到了批评。在主题随时间演变的情况下,这可能是限制性的。
3。通常忽略共现关系。
基于 LDA 的模型因通常忽略所分析文档之间的共现关系而受到批评。这导致检测到不完整的信息,并且无法通过上下文或其他桥接术语发现潜在的共现关系。
为什么这很重要?这可以防止重要但罕见的主题被检测到。
这种批评也出现在对后来一项研究的分析中,作者提出了一个专门为在线社交网络主题建模定制的模型。他们证明,与 LDA 相比,即使应用于神经嵌入特征表示的浅层机器学习聚类技术也能提供更有效的性能。
4。不适合用户生成的简短文本。
Hajjem 和 Latiri (2017) 批评 LDA 方法不适合短格式文本。他们提出了一个混合模型,该模型利用了信息检索领域的典型机制。
LDA-混合方法也被提出来解决这些限制。然而,即使它们在短格式文本上的表现也不是最优的,这使得 LDA 在嘈杂、非结构化的社交媒体数据中的效率受到质疑。
2.混合 LDA 方法
为了解决 LDA 的一些突出的局限性,引入了学习单词的向量表示的模型。
通过学习单词和隐藏主题的向量表示,它们被证明在短格式文本上具有更有效的分类性能。
Yu 和 Qiu 提出了一种混合模型,其中使用 Dirichlet 多项式混合和词向量工具扩展了用户-LDA 主题模型,当在微博(即短)文本数据上与其他混合模型或单独的 LDA 模型相比时,产生了最佳的性能。
另一个概念上类似的方法可以应用于 Twitter 数据。这就是层次潜在狄利克雷分配(hLDA) ,旨在通过使用 word2vec(即向量表示技术)自动挖掘推文主题的层次维度。通过这样做,它提取数据中单词的语义关系,以获得更有效的维度。
其他方法,如非负矩阵分解(NMF) 模型也被认为在类似配置下对短文本的性能优于 LDA。
3.LDA 替代方案
除了 LDA,在主题发现领域还有许多其他的发展。考虑到他们缺乏学术关注,他们似乎有一些关键的局限性,仍然没有得到解决。
在 2017 年的一项研究中,提出了一种用于主题检测的分层方法,其中单词被视为二元变量,只允许出现在层次结构的一个分支中。尽管与 LDA 相比是有效的,但是由于表征数据的语言模糊性,这种方法不适合在 UGC 或社交媒体短文本上应用。
一个高斯混合模型也可以用于新闻文章的主题建模。该模型旨在将文本表示为概率分布,作为发现主题的手段。虽然比 LDA 好,但它在 UGC 短文本的主题发现中可能再次表现得不太一致。原因是短格式文本缺乏结构和数据稀疏性。
另一个基于形式概念分析(FCA )的模型被提出用于 Twitter 数据的主题建模。这种方法显示了基于来自先前主题的信息的新主题检测的便利性。然而,它不能很好地概括,这意味着它不可靠,对主题敏感,这是它没有受过训练的。
其他模型,如 TG-MDP(主题图马尔可夫决策过程),考虑了文本数据的语义特征,并以较低的时间复杂度自动选择最优主题集。这种方法仅适用于离线主题检测(如前所述,这种方法不太常见)。尽管如此,当与基于 LDA 的算法(GAC,LDA-GS,KG)进行基准测试时,它提供了有希望的结果。
这些模型可以用来做什么?—你可能想知道。
- 在 Twitter、Reddit 和其他网站等微博社区中发现新兴话题
- 观察话题在一段时间内的演变
最后的想法
总的来说,尽管有许多方法可以进行主题建模,但是 LDA 已经发展成为最常用的方法。
考虑到它的局限性,许多混合方法后来被开发出来,以提高主题的准确性和相关性。这些方法经常挑战 LDA 的概率层次结构。
也开发了非 LDA 方法,然而,它们不太适合于简短形式的文本分析。
在以后的一篇文章(本系列的第三部分)中,我将分析用于短文本的最佳主题建模和情感分析算法。
主题建模完全实用指南
原文:https://towardsdatascience.com/topic-modelling-f51e5ebfb40a?source=collection_archive---------12-----------------------
使用 pyLDAvis 执行主题建模的完整指南
梅尔·普尔在 Unsplash 上的照片
主题建模: 这个 NLP 步骤的目的是理解输入数据中的主题,这些主题有助于分析文章或文档的上下文。该步骤还将进一步帮助使用在该步骤中跨每组相似文档生成的主题的数据标注需求。
这种无监督统计建模算法的主要目的是理解输入数据中的主题。
这一步真的很关键,也需要一定程度的数学理解。
用于执行主题建模的重要库有:Pandas、Gensim、pyLDAvis。
用于生成主题的算法:LDA
LDA(潜在狄利克雷分配)是一种生成统计模型,它允许一组观察值由未观察到的组来解释,这些组解释了为什么数据的某些部分是相似的。
- 它将文档视为一个单词集合或一个单词包。
- LDA 假设文档由帮助确定主题的单词组成,然后通过将文档中的每个单词分配给不同的主题,将相似的文档映射到主题列表。
下面,我将讨论将数据输入 LDA 模型以生成文档主题的不同步骤。
步骤 1: 读取预处理后的数据集。
步骤 2: 读取 N-Grams
- 在这一步中,创建的函数将读取传递的文本文件并返回列表。
- 在同一步骤中,另一个函数将读取二元模型和三元模型,并返回 N_Grams 的列表
步骤 3: 生成组合 N_Grams
- 这一步将读取获得的 N_Grams,并使用' _ '返回组合的 N_Grams 列表。
步骤 4: 将组合的 N _ gram 映射到单独的 N _ gram
- 这一步将进行映射并返回字典。
步骤 5: 将 N_Grams 添加回数据集中每篇文章的文本中。
- 这一步将用组合的 N_Grams 替换文本中最初出现的 N_Grams。
例如:我已经为我的部落尝试了这么多种干粮。
步骤 6: 从输入文本中删除停用词。
- 这是至关重要的一步,因为这些词在定义主题时不起任何作用。
**第七步:**去掉标点符号。
- 我们实际上考虑了一些特殊字符(。,?!)对于我们未来的工作是有效的,但是主题建模步骤根本不需要标点符号。
- 记住!主题建模背后的思想是文档由主题组成,主题由单词组成。所以,没有必要在这里保留标点符号。
步骤 8: 标记化
- 将文本分解为标记列表,为主题模型创建字典和文档术语矩阵。
- 结果将是一个输入文本列表。
步骤 9: 根据 POS_Tags 过滤代币。
- 这个函数将使用 NLTK 标记对应于语料库中每个标记的部分语音。
步骤 10: 创建字典和文档术语矩阵
- 使用数据的符号化输入,并准备字典和文档术语矩阵。
使用 LDA 的主题建模: 主题建模是指识别最能描述一组文档的主题的任务。LDA 的目标是以某种方式将所有文档映射到主题,使得每个文档中的单词大部分被那些虚构的主题捕获。
步骤-11: 准备题目模型。
- 在不同 k 值上训练 LDA 模型
- LDA 模型需要良好的内存和内核来加快训练速度。
- 因此,明智地选择块大小参数非常重要。
- 为了得到更好的结果,我已经运行这个模型 10 次了。
- 不要忘记保存所有的结果,因为有可能 10 个结果中的第一个是最好的。
步骤-12: 生成连贯性评分。
- 我已经为前 25 个 LDA 模型生成了一致性分数。
- 下面是 5 个 LDA 模型及其相应一致性分数的快照。
可视化前 25 个 LDA 模型的一致性分数:
- 因为从上面的视觉效果可以非常明显地看出,对于等于 4 的主题数量,一致性得分最高。
LDA 模型结果:
- 由于我不能真正展示主题和视觉效果,我突出了视觉效果的一些部分。
- 这是主题和主题 5 的关键字出现频率的可视化表示。
LDA 模型的 4 个阶段:
- 我花了一些时间对参数进行实验,得出了一些结果,我认为这些结果对将来超调 LDA 的参数非常有帮助,可以得到更好的结果。
请参考 完整代码 以便更好地理解。
主题建模的主要发现:
- 从上面的实验和结果,我得出结论,没有名词过滤器的模型表现最好。
- 保持 alpha 和 eta 值等于默认值,以获得更好的结果。
- 我得到了 k=16 和没有过滤器的数据的最佳结果。
- LDA 在小数据集上表现不佳。
- 由于内存/时间问题,LDA 几乎无法在大数据上运行。如果你有 64x 架构和 16 GB 或更大 RAM 容量的机器,它会运行得更好。
- 非常接* 0 的 lambda 值将显示对所选主题更具体的术语。这意味着我们将看到对特定主题“重要”但对整个语料库不一定“重要”的术语。
- 非常接*于 1 的λ值将显示那些在特定主题的术语的频率和来自语料库的术语的总频率之间具有最高比率的术语。
- 对于所提供的数据集,我使用 LDA 找到了 16 个独特的主题。
- 使用这个目标,我能够在每篇文章中找到覆盖文章大部分的最主要的主题。
- 我还看到了不同主题的文档数量,以及这些文档在同一主题中的相似程度。
- 结果真的令人印象深刻,因为主题是独特的和可分的。还包含了一组类似的文章,涵盖了每个独特的主题。
挑战:
- LDA 的时间复杂度和不可发现的输出。
得出结论,对 LDA 进行改进:
- 经过一点研究,我发现 LDA 不适合小数据集。因为它是一种无监督的学习方法。我所说的小数据是指 100 篇文章或长度小于 50 个令牌的文章。因此,它可能无法很好地处理评论或评论数据。
- 用于创建字典& doc_term_matrix 的矢量化技术可能是不可发现输出的问题,需要重新考虑。我们应该在 word2vec()、doc2vec()和 doc2bow()技术之间进行试验。
- 而不是只在 LDA 中过滤名词。应该着手检查标记有不同 POS _ tags 的令牌。在我的例子中,POS_tags (CD,MD,POS,CJ,PRP,DT)已经被删除。
- 对于 POS_tags (VB,VBG,DT,PRP),查看重要的标记,并在停用列表中提供其余不必要的标记。
- 我已经写了执行这个过滤的确切函数,它最终确实改善了结果。要查看那个函数,请参考这里的完整代码 。
为了改善结果,应该总是通过改变其参数值来进行实验。
希望这篇文章能对你有所帮助,解决大部分与 LDA 相关的问题。
感谢您的阅读。
所以,如果我的博客帖子对你有所帮助,而你此刻觉得很慷慨,请不要犹豫,请给我买杯咖啡。☕😍
是的,点击我。
And yes, buying me a coffee **(and lots of it if you are feeling extra generous)** goes a long way in ensuring that I keep producing content every day in the years to come.
您可以通过以下方式联系我:
- 订阅我的 YouTube 频道 视频内容即将上线 这里
- 跟我上 中
- 通过 LinkedIn 联系我
- 跟随我的博客之旅:-https://kajalyadav.com/
- 成为会员:https://techykajal.medium.com/membershipT21
也可以看看我的其他博客:
</15-free-open-source-data-resources-for-your-next-data-science-project-6480edee9bc1>
用 spaCy 和 Gensim 在 Python 中进行主题建模
原文:https://towardsdatascience.com/topic-modelling-in-python-with-spacy-and-gensim-dc8f7748bdbf?source=collection_archive---------1-----------------------
关于无监督机器学习的主题建模的完整指南,发布在 GitHub 页面上
作者图片
介绍
黑客最*攻击了一家国际公司。他们复制了几千份文件,并把数据公布在黑暗网络上。该公司找到了我的雇主,问我们是否可以浏览这些数据,以评估文件中包含的信息类型。我的第一个想法是:主题建模。
主题建模是一种从大量文本中提取隐藏主题的技术。我将介绍的技术被归类为无监督的机器学习算法。该算法的名称是潜在的狄利克雷分配(LDA ),是 Python 的 Gensim 包的一部分。
LDA 是由 Blei 等人在 2003 年首先开发的。LDA 是一种类似于朴素贝叶斯的生成概率模型。它将主题表示为单词概率,并允许发现潜在的或隐藏的主题,因为它基于单词在相应文档中的共现来聚类单词。
该过程
使用市场上最先进的工具(即 PowerPoint),我创建了下面的图像,描绘了整个过程。我将从收集文档开始这个过程(步骤 1);之后,我将进行一些数据清理,并将所有文档分解成令牌(步骤 2)。从这些标记中,我可以构建一个字典,为每个标记提供一个惟一的 ID 号,然后可以使用这个 ID 号创建一个语料库或单词包来表示这些标记的频率(步骤 3)。我使用我的字典和语料库建立一个主题范围,并试图找到主题的最佳数量(步骤 4)。最后一步是找到每个文档中主题的分布(步骤 5)。
作者图片
在我们开始上面的可视化步骤之前,我将要求您浏览下面的代码,并确保所有的东西都已安装和导入。
!pip install pyLDAvis -qq
!pip install -qq -U gensim
!pip install spacy -qq
!pip install matplotlib -qq
!pip install seaborn -qq
!python -m spacy download en_core_web_md -qqimport pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
import spacy
import pyLDAvis.gensim_models
pyLDAvis.enable_notebook()# Visualise inside a notebook
import en_core_web_md
from gensim.corpora.dictionary import Dictionary
from gensim.models import LdaMulticore
from gensim.models import CoherenceModel
收集数据(步骤 1)
我将使用的数据包含 500 个不同报告的概述,包括它们的摘要。我已经在我的 GitHub 上提供了这些数据,所以请随意跟随或下载数据并编辑 URL。
reports = pd.read_csv('https://github.com/sg-tarek/Python/raw/main/cordis-h2020reports.gz')reports.head()
作者图片
上面的代码片段只显示了前六列,尽管数据总共包含十五列。
reports.info()
作者图片
预处理数据(步骤 2)
在自然语言处理领域,文本预处理是清理和准备文本数据的实践。我将使用一个名为 spaCy 的开源软件库来准备用于分析的数据,但是也可以使用其他库,比如 NLTK。
我之前告诉过你要导入并下载一个叫做“en_core_web_md”的东西,这是 spaCy 预先训练好的模型。这个模型,我称之为“nlp”,可以被认为是一个管道。当您对文本或单词调用“nlp”时,文本会通过一个处理管道运行,如下图所示。这意味着,如果文本没有被标记化,那么它将被标记化,然后,不同的组件(标记器、解析器、ner 等。)将被激活。将文本标记化意味着将字符串或文档转换成更小的块(标记)。
该模型经过专门的英语文本训练(注意模型名称中的“en”),使其能够检测不同的英语单词。也支持其他语言模型。
空间的管道
管道中最有趣的组件是 tagger,它根据 SpaCy 的英语语言模型分配词性(POS)标签,以获得各种注释。词性标签(或词性标签)是分配给文本语料库中每个标记的特殊标签,用来表示标记的类型(是形容词吗?标点符号?一个动词?等等。)以及其他语法范畴,如时态、数(复数/单数)、符号等。词性标签用于语料库搜索和文本内分析工具和算法。
下面列出了一些 POS 标签:
POS 标签
我们可以使用 POS 标签通过删除不需要的标签来预处理数据。假设我们想删除文本中的所有数字,我们可以指向一个特定的标签并删除它。
我将把重点放在“摘要”一栏上,在这里我将标记化、词汇化并删除停用词:
# Our spaCy model:
nlp = en_core_web_md.load()# Tags I want to remove from the text
removal= ['ADV','PRON','CCONJ','PUNCT','PART','DET','ADP','SPACE', 'NUM', 'SYM']tokens = []
for summary in nlp.pipe(reports['summary']):
proj_tok = [token.lemma_.lower() for token in summary if token.pos_ not in removal and not token.is_stop and token.is_alpha]
tokens.append(proj_tok)
扩展知识的注意事项:
- 您可能会注意到“is_alpha”和“is_stop”,它们是连接到特定令牌的属性;你可以在这里看完整名单:【https://spacy.io/api/token】T4
- 另一点是“nlp.pipe”,它专门用于将文本作为字符串序列进行处理。这比逐个处理文本要高效得多。如果你只是处理一个单一的文本,只需删除。管道延伸。来源:https://spacy.io/usage/processing-pipelines
让我们通过创建一个新列来将令牌带回到报告中:
reports[‘tokens’] = tokens
reports[‘tokens’]
作者图片
创建词典和语料库(步骤 3)
LDA 主题模型的两个主要输入是词典和语料库:
- 字典:字典的思想是给每个令牌一个惟一的 ID。
- 语料库:为每个令牌分配了惟一的 ID 后,语料库只包含每个 ID 及其频率(如果您想深入研究,那么可以搜索单词包(BoW ),它将向您介绍单词嵌入)。
# I will apply the Dictionary Object from Gensim, which maps each word to their unique ID:
dictionary = Dictionary(reports['tokens'])
您可以打印字典,它会告诉您找到了 8848 个唯一 ID。我们可以看看分配给令牌的一些 id:
print(dictionary.token2id){‘available’: 0, ‘capability’: 1, ‘cea’: 2, ‘challenge’: 3, ‘chemistry’: 4, ‘chimie’: 5, ‘coating’: 6, ‘commercial’: 7, ‘company’: 8, ‘compliant’: 9, ‘concentrated’: 10, ‘conductive’: 11, ‘conductivity’: 12, ‘cost’: 13, ‘demand’: 14, ‘design’: 15, ‘dispersion’: 16, ‘easily’: 17,…
我将过滤掉低频和高频词汇,并将词汇量限制在 1000 个单词以内:
dictionary.filter_extremes(no_below=5, no_above=0.5, keep_n=1000)
- No_below:过滤掉出现在少于 5 个文档中的标记。
- No_above:出现在超过 50%的总语料库中的标记也被默认移除。
- Keep_n:我们限制自己使用前 1000 个最常用的令牌(默认值为 100.000)。如果您想全部保留,请设置为“无”。
我们现在准备使用上面的字典和 doc2bow 函数来构建语料库。函数 doc2bow()简单地计算每个不同单词的出现次数,将单词转换为其整数单词 id,并将结果作为稀疏向量返回:
corpus = [dictionary.doc2bow(doc) for doc in reports['tokens']]
模型构建(步骤 4)
下一步是在数据上训练无监督的机器学习模型。我选择使用 LdaMulticore,它使用所有的 CPU 内核来并行化和加速模型训练。如果出于某种原因,这对您不起作用,请尝试 gensim . models . LDA model . LDA model 类,它是一个等效的、但更简单的单核实现。
当将我们的语料库插入主题建模算法时,对语料库进行分析,以便找到每个主题中的单词分布和每个文档中的主题分布。
lda_model = LdaMulticore(corpus=corpus, id2word=dictionary, iterations=50, num_topics=10, workers = 4, passes=10)
作为输入,我给了模型我们以前的语料库和词典;此外,我选择在语料库上迭代 50 次来优化模型参数(这是默认值)。我选择主题的数量为 10 个,工人的数量为 4 个(通过按 ctr+shift+esc 键找到您的 PC 上的内核数量)。pass 是 10,这意味着模型将在训练期间通过语料库十次。
作者图片
话题的最佳数量是多少?
训练完模型后,下一步自然是评估它。在构建了主题之后,可以计算连贯性分数。分数衡量每个主题中的高分单词之间的语义相似程度。以这种方式,通过插入不同数量的主题,可以为每次迭代计算一致性分数。
已经引入了一系列算法来计算一致性分数(C_v、C_p、C_uci、C_umass、C_npmi、C_a、…)。使用 gensim 库使得为主题模型计算这些一致性度量变得相当简单。我个人选择实现 C_v 和 C_umass。C_v 的相干分数范围从 0(完全不相干)到 1(完全相干)。根据约翰·麦克里维的说法,高于 0.5 的值相当好(来源:做计算社会科学:约翰·麦克里维的实用介绍)。另一方面,C_umass 返回负值。
下面我简单地遍历不同数量的主题,并将一致性分数保存在一个列表中。后来,我用 seaborn 绘图。
- 使用 C_umass 计算一致性分数:
topics = []
score = []for i in range(1,20,1): lda_model = LdaMulticore(corpus=corpus, id2word=dictionary, iterations=10, num_topics=i, workers = 4, passes=10, random_state=100) cm = CoherenceModel(model=lda_model, corpus=corpus, dictionary=dictionary, coherence='u_mass') topics.append(i)
score.append(cm.get_coherence())_=plt.plot(topics, score)
_=plt.xlabel('Number of Topics')
_=plt.ylabel('Coherence Score')
plt.show()
作者图片
- 使用 C_v 计算一致性分数:
topics = []
score = []for i in range(1,20,1): lda_model = LdaMulticore(corpus=corpus, id2word=dictionary, iterations=10, num_topics=i, workers = 4, passes=10, random_state=100) cm = CoherenceModel(model=lda_model, texts = reports['tokens'], corpus=corpus, dictionary=dictionary, coherence='c_v') topics.append(i)
score.append(cm.get_coherence())_=plt.plot(topics, score)
_=plt.xlabel('Number of Topics')
_=plt.ylabel('Coherence Score')
plt.show()
作者图片
当使用 C_umass 或 C_v 算法查看相干性时,最好的通常是最大值。看着图表,我选择了 5 个主题,虽然没有确定的答案。
lda_model = LdaMulticore(corpus=corpus, id2word=dictionary, iterations=100, num_topics=5, workers = 4, passes=100)
打印和可视化主题(步骤 5)
我们现在可以打印出五个主题和相关的单词:
lda_model.print_topics(-1)
- [( 0 ,' 0.015* "基准"+ 0.013* "服务"+ 0.010* "研究"+ 0.010* "支持"+ 0.009* "欧洲"+ 0.009* "网络"+ 0.009* "社交"+ 0.009* "人"+ 0.008* "提供"+ 0.008* "*台"'),
- ( 1 ,' 0.021* "疾病"+ 0.016* "病人"+ 0.015* "健康"+ 0.015* "临床"+ 0.012* "治疗"+ 0.012* "研究"+ 0.010* "药物"+ 0.010* "癌症"+ 0.009* "系统"+ 0.009* "护理"'),
- ( 2 ,' 0.021* "系统"+ 0.015* "技术"+ 0.013* "市场"+ 0.013* "能量"+ 0.012* "高"+ 0.012* "成本"+ 0.010* "产品"+ 0.010* "流程"+ 0.009* "基础"+ 0.009* "解决方案"'),
- ( 3 ,' 0.034* "细胞"+ 0.013* "学习"+ 0.013* "植物"+ 0.012* "新"+ 0.012* "了解"+ 0.010* "机制"+ 0.009* "过程"+ 0.009* "人"+ 0.008* "发展"+ 0.008* "目标"'),
- ( 4 ,' 0.026* "研究"+ 0.024* "创新"+ 0.016* "中小企业"+ 0.015* "市场"+ 0.013* "新"+ 0.012* "业务"+ 0.011* "计划"+ 0.011* "合作伙伴"+ 0.011* "支持"+ 0.010* "发展" ')]
让我们来看看我们的第一份报告摘要:
reports['summary'][0]“Polyaniline has historically been one of the most promising conductive polymers from a cost/performance perspective, but processing issues have limited its uptake. Building upon seminal work on polyaniline performed at the CEA, RESCOLL (an independent research company based in France specialized in chemistry materials) has developed and patented a new electrically conductive polyaniline formulation under the trade name of PANIPLAST™….”
根据我们的 LDA 模型,上述文本属于主题 2 和主题 4。文章 87%属于话题 2(索引 1),12%属于话题 4(索引 3)。
lda_model[corpus][0][(2, 0.870234), (4, 0.122931786)]
让我们想象一下主题和每个主题中的单词。就像我们在上面看到的一样,但是请注意,圆圈中的数字与上面“print_topics”中的数字不一致:
lda_display = pyLDAvis.gensim_models.prepare(lda_model, corpus, dictionary)
pyLDAvis.display(lda_display)
作者图片
上图用圆圈代表了我们的五个主题。它们是用一种叫做 PCA 的降维技术画出来的。目标是有一个距离,以避免重叠,并使每个圆都是独一无二的。当我将鼠标悬停在一个圆圈上时,右边会显示不同的单词,显示所选主题中的词频(蓝色)和估计词频(红色)。彼此越接*的话题越有关联。
向数据框架添加主题
我们可以在数据框架中创建一个新的列,它包含每篇文章所属的最可能的主题。我们可以通过浏览每个摘要文本来添加最可能的主题:
reports['topic'] = [sorted(lda_model[corpus][text])[0][0] for text in range(len(reports['summary']))]
我们来统计一下每个话题出现的频率:
reports.topic.value_counts()
计数显示:
- 话题 1: 320
- 话题二:86
- 话题 3: 57
- 话题 4: 19
- 话题 5: 18
这与之前的视觉化非常一致。
完整的代码如下所示:
在 GitHub 页面上发布
我们可以通过上传到 GitHub 页面来分享我们的主题可视化。点击此处查看我的话题并与之互动。
第一步是下载我们之前创建的 HTML 格式的可视化。由于 GitHub 页面将会寻找一个具有此名称的文件,因此保持名称为 index.html 是很重要的:
pyLDAvis.save_html(lda_display, ‘index.html’)
您需要编辑索引文件以使其正常工作。该文件包含大量的 HTML 代码,不管内容如何,复制下面的行并将其添加到您的文件中。注意,一些代码在顶部,而
<!DOCTYPE html>
<html lang="en">
<body>LDA CODE GOES HERE! </body>
</html>
下一步是在 GitHub 上创建一个新的存储库,并对 repo 使用以下命名约定:
<用户名>. github . io
然后,将您的 index.html 文件放到 repo 中,并访问与 repo 同名的主题建模可视化:
我希望你像我喜欢写这篇文章一样喜欢它。如果你理解我的代码有任何困难,请留下评论。数据科学社区给了我很多,所以我总是乐于回馈。
请随时在 Linkedin上与我联系,并在 Medium 上关注我以接收更多文章。
进一步阅读的灵感
https://medium.com/@soorajsubrahmannian/extracting-hidden-topics-in-a-corpus-55b2214fc17d
https://aclanthology.org/D11-1024.pdf
使用 Gensim,LDA 对 NYT 文章进行主题建模
原文:https://towardsdatascience.com/topic-modelling-on-nyt-articles-using-gensim-lda-37caa2796cd9?source=collection_archive---------33-----------------------
菠萝供应公司在 Unsplash 上的照片
NYT 文章主题建模指南,了解趋势
假设给你一个文本数据,要求你找出这个文本数据是关于什么的。快速浏览一下数据就可以了。现在想象一下,必须浏览大量的文本文档才能理解它的内容。乏味,对吗?在这种情况下,主题建模可以派上用场。
主题建模的其他有趣应用是索引研究论文,帮助研究人员跟踪研究趋势和识别要阅读的论文;推荐系统通过对产品评论的聚类和情感分析来匹配用户和新闻文章。
在本文中,我们将了解主题建模的本质,并使用名为 Gensim 的 python 库对 2020 年的《纽约时报》文章进行主题建模。
文章的流程如下:
- 主题建模简介
- 实现主题建模的要素
- Gensim,一个执行各种 NLP 任务的 python 库
- LDA,最流行的主题建模算法之一
- 实现 LDA
a .预处理数据
b .创建字典和语料库
c .执行 LDA
d .可视化结果 - 进一步增强
1.主题建模简介
主题建模允许我们理解高维文本数据,并通过给出每个主题的关键词来识别我们的文本数据的主要主题。这样提取的主题可以用于从文本数据中获得有意义的见解。主题也可以用于给下一个模型(可以是监督学习)额外的分析提升。
在深入研究这个过程之前,有几个术语需要了解。
- **文档:**每个文本文件(我们案例研究中的文章)
- **语料库:**所有文档的集合
- **字典:**每个唯一单词到唯一索引的映射集合
假设:每个文档都与语料库相关,没有文档是从语料库中孤立出来的
在执行任何自然语言处理任务时,我们必须在将数据提供给模型之前对文本数据进行预处理,因为预测和数据一样好。同样,在这里,我们首先预处理文本数据,然后对预处理的数据进行主题建模。在这个案例研究中,我们从模型中看到的两个结果是,
- 每篇文章映射到一个独特的主题
- 每个主题都有一组构成特定主题的关键字
实现最佳效果的重点领域如下:
- 处理数据的技术,以确保只有重要的信息进入模型,因为模型预测只与我们训练它的数据一样好。
- 根据我们为每个模型获得的一组关键词来解释主题的能力。
因此,选择正确的预处理方法和拥有领域知识来理解主题建模的结果是至关重要的。
2.实现主题建模的要素
a.根西姆
Gensim 是一个令人惊叹的开源 python 库,用于无监督主题建模和自然语言处理。Gensim 设计用于处理大型文本集合。
b.皱胃向左移
主题建模算法,例如我们在本文中将要使用的潜在狄利克雷分配(LDA ),是一组基于自然语言处理的模型,用于在巨大的文本语料库中检测潜在的主题。LDA 中的潜伏是指发现 隐藏的 主题,狄利克雷是 概率分布 用来理解一个关键字和主题是如何关联的。
LDA 使用每个文档中的主题概率和每个主题中的单词概率,将每个文档(在我们的例子中是新闻文章)分配给一个唯一的主题,并将每个主题分配给一组关键字。
LDA 的内部
- 选择主题数量(输入参数)
- LDA 将每个单词随机分配给一个主题号
- 遍历每个文档计算以下两个概率:
a .文档中的主题: 文档属于每个主题的概率
b .主题中的单词: 对每个主题有贡献的单词的概率 - 基于来自步骤 3 的概率分数,'通过次数',一个输入参数,times,重新分配单词以产生主题号和具有主题号的文档。
Gensim 提供了一个函数 LDAModel ,该函数在很少或没有指令的情况下完成上述所有步骤。然而,我们可以调整各种参数来获得所需的输出。
3.实施 LDA
本案例研究中使用的数据集是 2020 年的纽约时报文章数据。该数据集包含大约 69k 个数据点。
下图显示了数据的快照。
文章数据快照(图片由作者提供)
列' year' 可以忽略,因为我们只使用 2020 年的数据。列'句子'具有句子级别的文章数据。
我们将首先预处理句子列,然后将 Gensim 中的 LDA 模型应用于预处理后的数据。
a.预处理数据
预处理文本数据不是一步到位的过程,因为它包含冗余和/或重复的单词,必须经过大量的清理。此外,这个过程有时取决于我们寻求的目标。
这个阶段包括删除对文本意义没有附加值的单词或字符**、**。让我们在下面逐一讨论:
- 降低文本的大小写是必要的,原因如下:
单词“选举”、“选举”和“选举”都给句子增加了相同的值。降低所有单词的大小写有助于通过减少词汇的大小来减少维度。 - 删除任何标点符号将有助于处理像“万岁”和“万岁!”这样的词同理。
- 停用词是语言中经常出现的词,如“the”、“a”、“an”、“is”。我们可以在这里删除它们,因为它们不会为我们的分析提供任何有价值的信息。另外删除停止字减少了数据的维度。
- 在本案例研究中,当我们寻找构成主题的关键词时,数字不会增加任何价值。因此,我们正在从数据中删除数字。
我们可以使用 Gensim 执行上述所有操作。Gensim 提供了一个函数, preprocess_string, 提供了最广泛使用的文本数据预处理技术。该函数提供的默认技术(过滤器)如下:
- strip_tags(),
- strip _ 标点符号(),
- strip_multiple_whitespaces(),
- strip_numeric(),
- remove_stopwords(),
- strip_short(),
- stem_text()
使用下面的单行代码,我们可以使用默认过滤器对整个文本数据进行预处理。
b.词典和语料库的创建
让我们创建一个字典和一个单词语料库包,作为输入传递给模型。
- 字典 :收集所有独特的单词
- bow_corpus :将整个语料库中的每个单词转换成单词包。单词包是通过使用唯一单词的字典将文档简单转换为向量,在字典中我们可以获得每个单词的频率。
字典和 bow_corpus 的快照(图片由作者提供)
c.LDA 模型
我们把 字典 和 bow_corpus 传递给 Gensim 提供的 LDA 模型,由它做每个句子的主题建模。
下面是使用 LDA 执行主题建模的代码行。
d.可视化结果
有许多方法可以用来可视化的结果,如 tSNE,文字云,条形图。我们将使用 pyLDAvis 来可视化我们的 LDA 模型,因为它是查看结果的最具交互性的工具之一。
下面是用于显示 LDA 模型结果的代码。
pyLDAvis 可视化主题,每个主题有前 30 个相关术语(图片由作者提供)
每个气泡代表一个主题。每个主题的大小显示了主题的受欢迎程度,各个主题的接*程度显示了主题之间的相似性。
正如我们所看到的,最常见的话题是电晕、病毒、疫情,我们知道这是 2020 年全球讨论最多的话题。
看到结果,我们可以断言,我们创建了一个非常好的模型,能够将主要新闻识别为最受欢迎的话题。
4.进一步增强
如前所述,模型性能高度依赖于预处理。我们可以使用领域知识和各种文本处理技术来改进预处理——比如词性标注,生成单词的二元/三元模型。
我们也可以从观想中看到,有几个主题彼此非常接*。当我们减少主题的数量时,这样相似的主题就会聚集到同一个主题中,这使得主题更具排他性。这可以根据我们的目标进行调整。
摘要
在这篇文章中,我们了解了主题建模是什么,为什么和如何。使用 python 库、Gensim 和 Gensim 的 LDA 对 2020 年的《纽约时报》文章进行预处理和主题建模。使用 pyLDAvis 生成结果的交互式可视化。该模型的性能与预先定义的参数是令人满意的。
感谢阅读!我也将在未来写更多初学者友好的帖子。请在媒体上关注我,以便了解他们。我欢迎反馈,可以通过 Twitter ramya_vidiyala 和 LinkedIn RamyaVidiyala 联系我。快乐学习!
用变形金刚生成主题语言
原文:https://towardsdatascience.com/topical-language-generation-with-transformers-69aac8ee774a?source=collection_archive---------18-----------------------
控制大型语言模型的生成能力是一项重要的任务,需要在现实世界中使用。
作者图片
全文
代码
基于大规模转换器的语言模型(LMs)在开放文本生成方面展示了令人印象深刻的能力。然而,控制生成的文本的属性,例如主题、风格和情感,是具有挑战性的,并且通常需要对模型架构进行重大改变,或者根据新的监督数据对模型进行重新训练和微调。
我们通过将预先训练的语言模型与主题建模信息相结合来引入主题语言生成(TLG)。我们使用贝叶斯概率公式来解决这个问题,主题概率作为先验,LM 概率作为似然,主题语言生成概率作为后验。在学习模型时,我们从用户提供的文档的自然结构中导出主题概率分布。此外,我们通过引入新的参数和函数来影响生成文本中主题特征的数量,从而扩展了我们的模型。这个特性将允许我们轻松地控制生成文本的主题属性。
语言建模和解码
自然语言处理中语言生成的应用可以分为两大类:定向语言生成和开放式语言生成。定向语言生成包括将输入转换为输出,如机器翻译、摘要等。这些方法需要输入和输出之间的一些语义对齐。另一方面,开放式语言生成在生成过程中有更多的自由,因为它不需要与任何输出保持一致。开放式语言生成在条件故事生成、对话系统和预测响应生成中具有应用。尽管与定向语言生成相比,在选择下一个标记时有更多的灵活性,但是控制所生成文本的顶级特征是需要解决的期望属性,并且仍然是一个具有挑战性的问题。
给定 m 个记号 x_1 的序列,..,x_m 为上下文,开放式语言生成问题可以表述为寻找具有 n 个标记的延续 x_{m+1},…,x_{m+n}。换句话说,如果我们考虑整个上下文加上延续如下:
语言建模概率可以使用链式规则分解为:
语言建模概率可以与解码策略一起使用,以生成用于语言生成的下一个令牌。寻找最佳延拓可以被公式化为:
求解上述方程是不容易的,因此实际的解码策略使用*似来产生下一个记号。最著名和最广泛使用的解码策略是贪婪解码和波束搜索方法。贪婪解码在每个时间步长选择最高概率的记号,而波束搜索保持一组假设,然后随着它的通过更新假设中的记号,并解码更多的记号。这些方法非常适合于定向语言生成,但是它们受到重复、泛化和退化延续的困扰。
这两种方法都是确定性的,因为它们的算法中不包含任何随机选择。
另一方面,随机解码方法从依赖于模型的分布 q 中采样:
最简单的随机采样包括从顶部 k 个概率中进行采样,常数 k 的使用是有问题的,因为在一些情况下,下一个记号的概率分布是*坦的,这意味着有大量合理的下一个记号可供选择,但是在一些其他情况下,分布集中在少数记号中。为了解决这个问题,(Holtzmanet et al .(2020))提出了细胞核采样。在这种方法中,词汇的子集被定义为最小集合 V(p ),使得:
那么基于新词汇的结果分布应该被重新缩放以形成概率分布。在 Nucleus 采样下,似是而非的下一个记号的数量随着上下文和生成的记号而动态变化。在这项工作中,我们使用核采样作为基本解码技术,并提出了一种新的方法来考虑主题知识的令牌。
主题语言建模
给定 K 个主题的列表 t = {1…K},为了控制语言模型的输出以遵循某个主题,在每个生成步骤,我们必须对以下概率分布进行建模:
与之前的等式相比,唯一的区别是它以主题 t_j 为条件。为了创建等式 6 的右侧,我们更改了创建逻辑的网络的最后一层。
这里,我们采用 GPT 变压器架构。如果 S 是最后一层,我们使用 softmax 来获得最终概率:
我们可以使用 P(x_i|x
因为在主题建模中,文档被视为单词包,所以我们还可以假设每个标记的主题概率独立于先前生成的标记。基于这一假设,我们有:
现在,假设我们有 P(t_j|x_i ),那么使用等式 10 我们可以证明主题语言模型的条件可以写成:
要获得完整的证明,请参考这篇论文。
主题建模
主题建模算法自动从文本数据集合中提取主题。它们基于发现贯穿文档的主题的统计无监督模型。我们在主题建模中使用两种主要算法。
- LDA(潜在狄利克雷分配):LDA 背后的基本思想是,在一个文档集合中,每个文档都有多个主题,每个主题都有一个概率分布。此外,每个主题在词汇上都有分布。例如,文档可以是关于“足球”、“新闻”和“美国”的主题,并且“足球”的主题可以包含包括“NFL”、“足球”、“团队”的单词,与其他单词相比,这些单词具有更高的概率。给定词汇为 V 的 M 个文档的集合,我们可以将主题的数量固定为 K。在 LDA 中,每个文档的主题和标记的主题的概率可以分别用矩阵形式θ_M×K 和φ_K×|V|来概括。学习之后,我们有了每个标记的主题分布,因此我们可以写:
- LSI(潜在语义索引):LSI 是将奇异值分解方法应用于单词-文档矩阵,行和列分别代表单词和文档。设 X_|V|×M 是记号-文档矩阵,使得 X_{i,j}是记号 I 在文档 j 中的出现,则奇异值分解可用于找到低秩*似:
分解之后,U 仍然有相同数量的行作为标记,但是有更少的列来表示通常被解释为“主题”的潜在空间。因此,归一化 U 给我们每个主题的每个标记的分数。我们可以使用这个分数来计算词汇表中每个标记 I 的主题 j 的概率:
可控生成方法
上面等式中的条件主题语言模型为我们提供了一个以特定主题为条件的令牌生成,但我们无法控制影响的大小。
1-添加话题参数和 logit 阈值:将 log(P(t_j|x_i))项直接添加到来自模型的实际 logit 中,在某些情况下会恶化生成文本的流畅性。我们提出两种方法来缓解这个问题。我们引入一个新的参数γ来控制主题分布的影响:
γ值越高,生成的主题文本越多,因为最终概率更多地取决于 log(P(t_j|x_i))而不是基本语言建模的 logit。
另一种方法是用阈值来削减主题的对数概率。S 的较低值对应于模型给出非常低概率的记号,我们不想改变它们,因为它引入了不想要的记号并降低了流畅性。在上面的等式中,对于所有大于阈值的 S 值,我们只保留 log(P(t_j|x_i))。
和 log prob,用于以下等式:
阈值的较低值与更多的主题文本生成相关,因为我们通过 log(P(t_j|x_i))从原始模型改变了更多的标记。
2-使用α-entmax 而不是 soft max:soft max 函数的问题是,它给了许多不必要和不可信的令牌非零的概率。softmax 函数是密集的,因为它与 exp 函数成比例,并且永远不会在输出中给出精确的零概率。相反,我们使用α-entmax 来创建更稀疏的概率,这些概率不容易退化文本。α-entmax 定义为
其中:| V | 1:= { p∈IR | V | 1,∑IPI = 1 }是概率单形,对于α≥1,HTα(p)是 Tsallis 熵,它定义熵族如下:
α-entmax 是 softmax 函数的广义形式。特别地,对于α=1,它精确地降低到 softmax 函数,并且随着α的增加,输出概率的稀疏度连续增加。这里,我们特别感兴趣的是α=2,它导致 sparsemax:
与 softmax 函数不同,sparsemax 可以分配零概率。
3-增加温度和重复惩罚参数:我们需要对基核采样做一些改变,以控制基分布*坦度,防止其产生重复字。我们将上述更改后的最终 logit 表示为 ui。给定温度、重复惩罚 r 和生成的标记列表 g,采样的最终概率分布为:
当 T→0 时,采样简化为贪婪采样;而如果 T→∞,则分布变得更*坦和更随机。受惩罚的采样不鼓励绘制已经生成的记号。
具有不同主题的主题文本生成
TLG 的最大好处之一是它可以用于不同的语言模型,而无需对基础模型进行任何重新训练或微调,然而,要生成主题文本,我们需要从文本语料库中提取主题。为了训练主题模型,我们使用了 Alexa 主题聊天数据集。这个数据集包含从政治、音乐到体育的各种话题的对话和知识库。我们不使用数据集中主题的标签,而是使用我们的 LDA 和 LSI 主题模型自动提取它们。这种无监督的方法使我们能够灵活地处理任何原始文本语料库。
在这个实验中,使用了一个固定的中性提示来确保模型不受少数初始标记的限制。下表中的结果表明,从主题建模输出中选择主题后,该模型可以创建长的、连贯的和流畅的文本延续,而无需手动注入来自其他资源的额外知识或通过对标记数据集的训练。
作者图片
超参数对 TLG 的影响
在我们提出的方法中,我们可以使用γ和阈值作为旋钮参数来控制主题对语言生成过程的影响。更具体地说,基于等式 27,更高的伽马值将导致更多的主题结果。此外,较低的阈值与更多的主题语言生成相关。在极限中,如果我们设置γ=0,threshold=0TLG 就还原为没有任何主题的原始语言模型。但是,我们的实验表明,改变γ值比改变阈值对生成文本的流畅性危害更小。这是因为阈值化可以容易地切断与词汇表中的函数标记(如停用词)相关的概率,这损害了模型的流畅性。下图演示了在固定主题(足球)上使用不同的γ值和阈值进行语言生成。为了显示每个词汇在主题中所占的比重,我们使用了颜色编码,颜色越深,主题词越多。我们跳过了解码的最后阶段。这就是为什么可以看到来自字节对编码(BPE)标记化的单个标记。
作者图片
现在告诉我它是如何工作的?
语言生成是根据先前生成的标记生成下一个标记的任务。基本语言模型中的下一个标记的概率分布在一些标记位置更*坦,而在一些其他标记位置更为突出。例如,给定“问题是”的提示,与几乎总是“开”的类似“它被聚焦”的提示的下一个标记相比,有大量可能的下一个标记。语言模型的这一特性使我们能够灵活地干预生成过程,并在概率分布更*坦时引导它向所需的标记前进。
*坦或尖峰分布的概念可以很容易地用分布的熵来度量。在图 a 和 b 中,我们将基本模型的熵(表征熵)与来自等式 20 的后验概率分布进行比较,作为总熵。在一个位置的基础模型的较高熵是其从具有几乎相等概率的大量潜在标记中进行采样的能力的标志,但是在我们的条件语言建模中,我们希望将该集合限制为符合所选主题的较小集合。因此,几乎在所有情况下,TLG 模型的熵与基本模型相比都显著下降。我们可以观察到,代表主题的标记(如球队、足球、文化和音乐)的差异较大,而功能标记(如在不同主题中不起任何作用的停用词)的差异较小。
作者图片
另一个有趣的观察是从主题建模中提取的先验分布如何迫使语言模型选择主题标记。图 4 描述了生成过程中最有可能出现的前 5 个令牌。对于足球主题,模型选择的前 5 名候选令牌与所选主题兼容。
作者图片
图形用户界面
作者图片
我们还提供 GUI 作为用户使用 TLG 的*台。在左侧面板中,您可以控制数据集、主题模型、主题数量和其他生成设置。操场给你一个图表,这是一个新颖的主题表现,以及它们是如何相互关联的。然后你可以选择感兴趣的主题,选择一个提示,最后点击生成按钮,获得主题文本。
专题图:全球变暖热图
原文:https://towardsdatascience.com/topical-plots-global-warming-6b5fb80a0371?source=collection_archive---------39-----------------------
哪个图表能最好地传达信息
全球变暖的各种图表——作者图片
一摄氏度似乎不算多。慵懒的夏日午后,坐在阳光下,25 度和 26 度之间的差别几乎无法察觉。
但是地球是一个很大的地方,所以将它升温 1 度所需的能量是巨大的。这就是为什么随着全球气温上升,我们会看到更多的极端天气事件,这是由大气中增加的能量驱动的。
但是我们如何有效地传达正在发生的温度变化呢?
首先,我们需要一些数据,然后我们可以看看如何用图形表示它。我将描述下面的数据,然后建议一些可能合适的图—线图、散点图和热图。我不会将本文与用于生成本文中的情节的 Python 代码混为一谈,因为它并不真正相关,但是我会提供一个链接,您可以在那里下载它。
获取数据
HadCRUT 是一个追踪自 19 世纪后期以来气温变化的数据集。你可以根据开放政府许可 v3 从英国气象局哈德利中心下载页面免费下载它的版本(也参见下面的参考部分)。
其他几个地方拥有这些数据,包括 IPCC、东安格利亚大学气候研究中心(CRU)和美国国家航空航天局(NASA)。
该数据集是一个时间序列,用于跟踪相对于 1961-1990 参考期的历史地表温度异常。也就是说,我们将 1961 年至 1990 年间的*均温度视为零度,并绘制出该范围内每年的正负变化。看起来是这样的:
HadCRUT 数据的前几行—作者图片
温度列是每个年份与基数之间的实际差异,而*滑列是一个在多年范围内的 Lowess *滑。您可以在下面的简单线形图中看到绘制的数据:
一个简单的折线图——作者图片
可视化气候数据
个别年份的变化差异很大,但*滑线显示的趋势明显是向上的,尤其是当我们越接*现在。
然而,简单的线形图并不是特别引人注目的可视化。
对于不*滑的数据,也许可以用散点图来更好地表示相同的数据。在下面的图中,我也对散点图上的点进行了着色,以对应温差——温度越高,颜色越暖(我使用了 matplotlib 色图,名为inferno——这似乎很合适)。
折线图和散点图——图片由作者提供
严格地说,在这个版本的图表中,颜色是多余的,因为它复制了 y 轴上的值。但也许这有助于强化气温正在上升的信息。
另一种使用颜色的方法是热图。你可以在下面看到*滑数据的热图。我认为这非常清楚地证明了*几十年来气温的上升。深色中有较浅的颜色,但颜色的整体变化是相当引人注目的。
*滑数据的热图—作者提供的图像
非*滑数据更真实地反映了个别年份实际发生的情况。下一个热图是这些数据,你可以清楚地看到个别年份没有遵循趋势,但仍然欣赏整体模式。
非*滑数据的热图—作者提供的图像
虽然最后这张图比前一张图显示了更多的细节,但当它们都被挤在一个轴上时,很难看到单独的一年。
我们可以试着通过重新格式化数据让它更清晰。在这里,我创建了一个二维数组,每一列代表一个十年。
二维数组形式的数据—作者提供的图像
现在我们可以绘制另一个热图,这将使我们更容易地看到各个年份(1964 年看起来有点冷)。
二维热图形式的数据—作者提供的图片
有点不幸的是,最后一列只有一个条目——不美观——但重新格式化为其他维度的矩形会破坏自然的 10 年格式。除此之外,随着更多数据的公布,这些空白空间将被填满。
前 10 名
查看数据的另一种方式是关注年份,并根据温度对它们进行排序。如果我们这样做,我们会得到一个这样的表(显示了前 10 个条目)。
十大最热年份——作者图片
在这里,我们可以清楚地看到,表中最热的年份是最*几年。事实上,前 20 名中有 19 名是 2000 年代的,剩下一名是 1998 年的。
热图也是可视化这些数据的一种便捷方式。这是前二十名。
前二十个最热的年份——作者图片
从 1880 年开始的整个地图太大了,不能在这里插入,但是我认为看到每一年的数据是非常有趣的,所以我在文章的最后加入了图表。
一如既往,感谢阅读。这里没有使用火箭科学,但我希望你已经发现我对数据的漫游,以及它可能是如何表示的,很有趣。
参考
使用观测估计集合量化全球和区域温度变化的不确定性:HadCRUT4 数据集,科林·p·莫里斯,约翰·j·肯尼迪,尼克·a·雷纳和菲尔·d·琼斯
要获得创建这些图表和下载数据的代码,请访问我的 Github 页面。
如果你想知道我什么时候发表新文章,请考虑在这里注册一个电子邮件提醒。
如果你不是一个媒体订阅者,那就注册吧,这样你就可以每月花 5 美元阅读尽可能多的文章。在这里注册我会赚一小笔佣金。
如果你对熊猫有兴趣,我的介绍在这里:
https://towards data science . com/plotting-with-pandas-an-introduction-to-data-visualization-8bd 7c 0831650
按温度排序的 141 年
按温度排列的所有年份—按作者排列的图片
拓扑变化点检测
原文:https://towardsdatascience.com/topological-change-point-detection-162c6e11d3ca?source=collection_archive---------15-----------------------
作者图片
思想和理论
发现时间序列数据中的临界点
变点检测是时间序列分析中的一个重要课题,涵盖了广泛的应用领域,在这些应用领域中,需要检测以可测量的时间序列为特征的系统中与标称行为的显著差异。几个现实世界的系统包括太阳耀斑群、萤火虫闪光模式、神经尖峰脉冲序列、气候数据和金融指数等等。
发现时间序列的潜在结构有助于预测信号源数据产生过程中的突变。通常,统计分析用于变化点检测,以识别随机过程的概率分布何时显著影响时间序列特征的变化。在这里,我提出了一种方法,应用拓扑数据分析的方法来提取特征,并预测时间序列数据中可感知的结构变化的开始。
具体来说,本文将演示使用拓扑数据分析来预测时间序列中的变化点。时间序列是从经典的 Kuramoto 模型合成的,拓扑特征是从 Kuramoto 模型相位响应的动态持续图中提取的。然后,这些拓扑特征被用在梯度提升分类器流水线中,以顺序预测是否将到达系统变化点。这种方法适用于我们想要对复杂系统中可能导致灾难性的、不可逆转的影响的临界点的出现进行建模的情况。
在本文中,您将学习如何:
- 从 Kuramoto 系统生成时间序列
- 从时间序列中提取拓扑特征
- 建立机器学习管道,使用拓扑特征预测时间序列状态
- 评估模型的变点预测性能
仓本模型
Kuramoto 模型已经被广泛用于模拟大型弱耦合振荡器的行为。它可以描述出现在化学振荡器、神经元尖峰序列、火焰动力学和萤火虫闪光图案系统中的模式。Kuramoto 模型的定义特征是相位同步。同步是复杂网络系统中出现的一种现象,其中一大组几乎相同的组件开始同相振荡。这种同步的开始可以非常突然地发生,并且可以通过瞬时相位相干性来测量。在正常的、非耦合的系统行为和完全同步的状态之间有一个可检测的区域吗?下面的图 1 是使用 Kuramoto 模型方程模拟 1000 个时间步长的全连接鄂尔多斯-Renyi 网络的 50 个节点系统的时间序列图。时间序列代表网络中每个节点相位的正弦值。
图一。50 节点鄂尔多斯-仁义网络的 Kuramoto 模型时间序列(图片由作者提供)。
定性地说,你可以看到不连贯的区域(t < 200), partial coherence (200 < t < 400) and complete synchronization (t > 400)。这表明从正常到部分(“开始”区域)的转变和完全同步可以从潜在的时间序列结构中检测到。
变化点检测和拓扑数据分析
变化点检测试图识别一个特定的时间点,此时底层数据源中的突然结构变化导致相关可观测时间序列的行为发生可检测的变化。在这里可以找到应用于变化点检测的传统方法的综述。在本文中,我们将应用拓扑数据分析的方法来解决这个问题。
应用于时间序列机器学习的拓扑数据分析试图提取尽管存在噪声、离群值、缺失数据和尺度变化,但仍保留数据中潜在的全局时间结构的特征。在代数拓扑术语中,这被称为数据的“持久同源性”。简而言之,持续同源性通过计算数据中存在的连接成分、2D 环或更一般的 d 维“洞”的数量来量化数据的结构。查看这篇优秀的介绍性文章,获得对持续同源概念的直观解释。
通常,我们将同步行为与周期性规律相关联,将非同步行为与非周期性相关联。图 2 说明了当时间序列中存在周期性和非周期性结构时,持续同源性的差异。显然,H1 持续长度(绿色点距离虚线的距离)和 H2 的存在或不存在(紫色点)是可以在变化点预测中利用的可分离特征。
图二。周期性(顶部)和非周期性(底部)系统的持久性图。请注意绿点分布(H1)和 H2 存在(上)和不存在(下)的差异。这些特征可以用来检测周期性,周期性又可以用来检测我们的模型中同步的开始(图片来自 giotto-tda:一个用于机器学习和数据探索的拓扑数据分析工具包)。
通过在原始时间序列上的滑动窗口序列上计算一组持久性特征向量,数据集的持久性同源性可以被矢量化为特征向量,并以熟悉的方式用于机器学习管道中。我们将使用 giotto-tda ,一个无缝集成到 scikit-learn 的监督机器学习管道中的拓扑数据分析 python 库,来研究检测 Kuramoto 动态模型生成的时间序列中的变化点开始的能力。
问题范围
为了创建用于变化点检测的监督数据集,我们需要创建一组标签。对于上图 1 中时间序列数据的每个窗口,我们将通过*均每个节点与其邻居的相位相干性来计算全局顺序度量。下一张图显示了我们 50 节点网络的相干函数。
图 3。Kuromoto 模型的相干函数测量作为时间函数的网络的相位同步性(图片由作者提供)。
同样,我们可以看到一个以 t=200 附*的部分相干区域为特征的开始区域。准确地说,我们的任务将是在给定当前数据时间窗口的情况下,预测先行一步的状态。通过将图 3 中的相干函数量化为三类(分别为正常、开始和完全同步状态的 0、1 和 2 ),我们可以为我们的监督分类问题创建目标标签。我们在下面的窗口代码(第 2 段)的第 14–16 行中这样做。
管道
数据处理流程非常简单。
- 模拟数据:
- 创建一个 50 个节点的全连接鄂尔多斯-仁义网络。
- 模拟 Kuramoto 方程,得到所需的时间序列数据和一步到位的标签。
2.现在,使用 giotto-tda 滑动窗口转换器将数据和标签窗口化。这不仅对给定窗口大小和步距(*移每个窗口的量)的数据进行窗口处理,而且对标签进行重新采样,使得数据窗口X_sw
对应于labels
上相应窗口中的最后值yr_one_step
。
3.接下来,我们提取特征向量来训练和测试我们的监督机器学习算法。为了计算时间序列的每个窗口段的持续同源性,我们最初使用皮尔逊相异度变换器来计算每个窗口的 2D 相异度矩阵,并将结果堆叠到 3D 对象中。然后,对于每个 2D 相异矩阵,计算 Vietoris-Rips 持久性,直到同源性为 2。最后,为每个结果持续性图计算振幅、持续性熵和每个同源维度的图点数,产生形状(195200 x 9)
特征向量X_tot
。每个持久图特征变换器计算的细节可以在这里找到。
4.我们管道的最后一步是训练和测试模型。我们将使用 scikit learn 的梯度增强分类器,尽管使用 SVM 和随机森林分类器可以获得类似的结果。
结果
结果表明,使用拓扑数据分析的方法可以检测开始(部分同步)和完全同步变化点。在下面的图 4 和图 5 中,真实状态由背景色序列表示(品红色=正常,青色=发病,黄色=同步)。时间序列用预测的先行一步分类值进行颜色映射:绿色=正常,蓝色=开始,红色=同步。
图 3。改变点检测结果。真实状态由背景颜色序列指示(品红色=正常,青色=发病,黄色=同步)。时间序列本身以其分类值进行颜色映射:绿色=正常,蓝色=发病,红色=同步(图片由作者提供)。
从下面的放大图可以更容易地量化检测机的性能。很明显,对开始区域(洋红色)的检测较晚,然而,我们对完全同步状态(黄色)的检测稍早。
图 4。拓扑变化点检测结果的放大图。我们可以看到对开始区域的检测较晚,然而,我们对完全同步机制的检测稍早(图片由作者提供)。
最后的外卖
那么拓扑变化点检测对现实世界的应用有什么用呢?由于我们是在给定当前时间窗口的情况下预测系统的先行一步状态,因此只要我们可以从可观测数据中测量动态时间序列,我们就可以表面上估计各种信号源(如气候、金融、机械或生物系统)的未来变化点。准确可靠地预测系统未来的变化点,可以让我们避免复杂系统中出现可能导致灾难性、不可逆转后果的临界点。
这里,我们合成了一个简单的互联节点网络,但是,由于它能够使用任何时间序列数据提取隐藏的结构信息,拓扑变点检测可以应用于涉及广泛变化的空间和时间尺度、数据类型和节点组成的系统,包括自然和人造系统。此外,所提出的算法可以实时在线执行,因为我们不需要整个时间序列,而只需要当前时间窗。
总认知空间
原文:https://towardsdatascience.com/total-cognitive-space-4a571033af82?source=collection_archive---------18-----------------------
思想和理论
F 从 AI 到组织变革,我们如何架构我们所做的塑造可及可能性的总空间。
作者的作品
一段时间以来,我越来越意识到,无论技术如何进步,人工智能系统(简称为 AIs)都不会像我们一样有良知,除非它们体现在完美模拟我们身体的物理容器中。即使那样也不行。
我想这没什么大不了的。但是,当我偶尔思考这个问题时,一些有趣的概念出现了,我觉得有必要写下它们,因为我相信这可能有助于思考组织模式以及它们如何面对我们在现代都必须应对的挑战。
有很多研究和广泛的商业兴趣,让人工智能预测人类在给定场景下的行为。我们将如何购买这个春季,我们什么时候会转换电话公司?我们更喜欢什么产品,怎样才能发现自己喜欢的新事物?寻找一个能够辨别我们行为的正确线索的人工系统,以及在更广泛的背景下,能够辨别事情发生的原因以便我们能够改善对它们的反应的系统,是一个重要的系统,并且值得退一步,尝试从更广阔的角度来看待这个问题。事情是这样的,当我们试图建立一个能理解事物一部分的系统时,他们需要能够在他们的整个可寻址认知空间所能容纳的范围内表现出那部分事物。我们正试图找到解决系统认知空间不足的问题的方法。
我所说的认知空间是什么?我举几个例子解释一下。以一个像素的图像为例,其中像素可以是黑色或白色。这个图像只知道两种可能的现实。一个人类观察者可能对仅仅是黑或白的图像有反应,并开始赋予它意义,每个人根据他们自己的经历、他们的情绪、反射等等。但是图像本身不能代表除了黑色或白色之外的任何东西。
一个白色像素,一个黑色像素。话不多说。(图片由作者提供)
如果我们把图像做得更复杂一点,例如由 16 像素乘 16 像素组成,每个像素可以是 4 种颜色中的一种,我们就有了一个可以代表更多事物的图像。如果这些像素有能力表现更多的颜色,它们可以不断扩大自己的表现空间。
左图:一张 16x16 像素的图像,每个像素有 4 种可能的颜色。右图:同样大小的图像,但每个像素有更多的颜色;它现在可以渴望代表迭戈·委拉斯开兹。(图片由作者提供)
这个例子是显而易见的,但它是同样的概念,适用于基本上每一个人,每一个机构,你在生活中做的每一项活动。所有存在的事物都是在一定的背景下发生的。与环境的关系极大地解释了我们所考虑的事物、实体或存在的成功。与语境的关系取决于事物、实体或存在所能代表的认知空间。
就人工智能而言,你们大多数人至少知道这些系统如何工作的基本知识。他们有一个模型,用于处理输入集合,并提供输出集合。例如,被设计和训练来评估消费者信用风险的模型包含关于设计者/建模者认为将有助于解释风险情景的某些变量的信息,例如个人的工资、他们是否累积了以前的债务、他们是否有还款历史等。模型的认知空间受限于它所拥有的变量,受限于这些变量中的数据深度,等等。以推荐歌曲为使命的系统可能具有关于你喜欢哪些其他歌曲、你的年龄、谁是你的朋友以及他们喜欢什么等信息。协调城市中交通灯的系统可以具有考虑交通状态、每条街道的流量、过去的预测、过去的结果、天气信息等的模型。这不像只有两种可能状态/两种可能表示的图像那样容易表示。但原理是一样的。交通系统有一个变量和组合的总数,它塑造了我称之为认知空间的东西:它能代表的情况的数量。如果一个巨大的怪物来自太空,降落在城市里并扰乱了交通,模型无法意识到这种情况,因为它甚至不知道这是可能的。不在它的认知空间内。它会选择它能从输入中看到的现实的最佳表现,愉快地忽略一个来自外太空的野兽正坐在市中心三个街区之外的事实。
我们自己的认知空间
我们呢?我们的认知空间也受到许多因素的影响和约束。我们仍然不太了解良心是什么,它来自哪里,我们的存在感是如何从我们的存在中产生的等等。有许多心智模型和意识理论,这是一个令人兴奋的研究领域,我试图去了解它。从流传的各种理论中,我看到了一些共同的特征。显然,这与各种感官输入的整合有关。它与试图理解我们周围正在发生的事情,选择与我们和我们的目标相关的输入有关。它与调和我们周围的东西和我们内心的东西有关:我们过去的经历,我们知道的,我们记得的,我们学到的和我们爱的。这与我们如何在大脑中将这些东西联系起来有关。所以它与感官输入以及我们处理这些输入的方式有关。此外,当暴露于这些输入时,我们大脑中的一些处理中心以某种方式做出反应,释放出某种神经递质,使我们有所感觉。情绪也是处理我们周围发生的一切的副产品,或者从我们试图收集的关于大脑如何工作的最基本的知识来看是这样。当我们考虑我们在认知空间中能够表现的情境总量(外部和内部)时,情绪是另一个需要考虑的变量(哦,它们基本上指导我们的行为,但这是另一篇文章的主题)。
我们大脑中的远距离连接。为了获得更多令人惊叹的视觉效果,更好的是,研究我们的大脑是如何内部连接的,请查看 人类连接体项目;图片由阿纳斯塔西娅·延迪基博士、MGH/哈佛大学博士维维安娜·西莱斯提供
我们的大脑大约有 840-1000 亿个神经元(84.000-100.000 亿个神经元),以及大约 100 万亿个突触(神经元之间的连接)。我们真的不知道不同类型的神经元是如何工作的,除了神经元和连接的数量之外,在理解这产生了多少种不同的激活模式组合时,可能还有更多变量在起作用。所有变量的可能组合是我们必须在我们的心智模型中表现的工具,无论是外在的还是内在的。它定义了人类总的可寻址认知空间。因此,无论我们的良知是什么,无论我们对自我的感觉是什么,它似乎都是由我们的大脑是如何构建的,我们拥有的连接,神经元,以及它们如何与世界互动等因素形成的。我们能够处理的总认知空间是有上限的。不完全是上限,而是一个给定的 N 维形状:它覆盖了一个由所有影响它的维度定义的空间,并且它有跨越所有这些维度的边界。 不一定涵盖所有有的。它涵盖了它能理解的内容。在这个认知空间中不可表现的事物会以对人有意义的方式被体验,但可能与现实无关(就像交通模型无法知道来自半人马座阿尔法星的某个哥斯拉正在离少校的房子几个街区远的地方享受星际间的乐趣)。这个总的认知空间决定了我们的适应能力。只要我们的认知空间允许我们理解它,我们就能对我们的环境做出反应。其他系统和活动也是如此。
你的人工智能有不同的“思维地图”
我希望你明白我所说的总认知空间的意思。那么,为什么我要费这么大的劲来解释这个想法呢?让我们回到本文的开头:人工智能不会像我们这样有良心,我说。无论我们的人工智能有多先进,就其构成而言,它们都不会像我们一样。它们没有我们的感官,如果我们为这些系统建立人工感官输入(摄像头来看,人工触摸传感器,人工鼻子等)。),它们会用不同于我们处理的信号来表达现实。我们所能想到的最相似的生物也许会有一个与我们有很大重叠的认知空间,但仅此而已。不过,最有可能的是,这样的系统会有一个认知空间,与我们的认知空间有些重叠,但存在着我们无法理解的大片区域。我们所能希望的是,正确地识别重叠部分,并尝试将我们需要处理的其他实体的东西投射到重叠部分中。这让我想起了柏拉图洞穴的寓言。我们看不到现实,而是把绝对现实投射到我们的认知空间中。那些人工智能会经历不同的投射。
这为讨论和思考开辟了几个途径。
首先,它应该提醒我们对我们构建的系统有什么期望。或者说,不期待什么。那些系统能理解我们吗?很可能不是,因为他们存在于不同的认知空间,因此他们对情况的“理解”是不同的。从更实际的角度来说,如果你正在为人类构建推荐系统,不要忘记你的模型不能编码情感。因此它将是非常不完整的。你可以找到可能增强模型认知空间的变通方法,但是模型本质上不可能“理解”一种情绪,因此它不能正确地处理这种情绪。它还应该有助于从广泛的角度理解这样一个事实,即模拟一种情况需要不同的数据来源。你拥有的数据源越多(也就是说,你看待一种情况的方式越多),模型的认知空间就越大,它的表现能力就越强。不仅仅是更多的观点:设计和构建在所有感官输入(包括内部状态)之间有意义的相互联系的系统,以及不同部分之间相互作用的可能性,是必不可少的。两个不同元素之间的每一个新的联系,都是拓展认知空间的新维度。
这发生在最好的家庭
很明显,这不仅仅发生在人类和人工智能之间。例如,这在不同的人类文化中都会发生。当一个人有神经问题,改变了神经元、连接、情绪、经验等的总组合时,就会发生这种情况。这产生了一种可能的对世界的理解,这种理解不同于任何“健康”的大脑。如果我们明白,这个总的认知空间不仅仅是由原材料限制或形成的,而是在给定的时间点上它们是如何烹饪的(例如,在我们的大脑中,它包括我们已经知道的东西,我们对这些东西的感觉,我们的信仰等等。)那么我们可以看到,认知空间及其状态的差异也是人类无休止冲突的根源。对我来说,当我们考虑实体之间的交互时,把所有这些都考虑进去是非常重要的。可能的互动发生在认知空间的重叠中。在那个交叉点之外,那个重叠部分,是每个实体都无法识别的东西。因此试图从非重叠空间中获得适当的交互结果是没有希望的,也是虚幻的。
这也意味着认知空间与我们不同的其他实体过于珍贵。他们能看到我们看不到的东西。任何试图探索和理解外界事物、我们经历的变化以及如何更好地行动的人,都应该有兴趣找到它们与其他认知空间的适当重叠。这是我看到未来人工智能最大潜力的地方。拥有与我们重叠的人工智能来试图解释他们看到的东西,但拥有与我们自己不同的能力,因此能够创造一种超越我们生物本性所允许的共享存在。试图建立模拟我们自身功能的系统,希望创造可以冒充人类的合成生物,对我来说似乎有点无聊。有很多人需要去了解和学习,为什么我要复制他们呢?更好的做法是建造能带来新事物的东西。
考虑更广泛的影响
在我看来,这个非常简单的想法对我们如何组织我们的活动有很多影响。既然认知空间是允许实体适应其环境的东西,为什么我们不考虑在例如我们建立的公司中重塑它。太多的公司不仅试图推进他们当前的产品和服务,还试图推进他们现有的内部组织(互联、政治、治理、动态等)。).随着环境的变化,他们会很好地尝试重塑他们的认知空间。例如,当前对拥有更加多样化的劳动力的兴趣是实现这一目标的最佳实践。促进员工队伍的多元化会给公司带来不同的经历、背景和情感,并有效地拓展认知空间。然而,还有更多事情要做。工作动力的多样性,流程的多样性。这可能会对优化产生反作用,但我认为只考虑优化而不是建立适应能力的时间已经过去了。不过,这是另一篇文章的主题。问题是,这将有助于公司扩大其影响和对其背景的理解。
它也适用于社会、政府和教育。这是一个普遍适用的简单想法。在以后的文章中,我想把这个想法更深入地扩展到组织是如何设计的及其含义。为什么分散经济对人类来说是个好主意。艺术如何扩展他们的认知空间,而这又如何扩展人类的认知空间。
总之,这只是一个简单的想法。我将很高兴知道你对它的想法,请随时联系我,给我你的反馈。谢谢你读到这里。
(原载于【https://www.iillucid.com】,作者网站为观点、艺术和随机灵感)
总订单向前分解:HTN 计划者
原文:https://towardsdatascience.com/total-order-forward-decomposition-an-htn-planner-cebae7555fff?source=collection_archive---------23-----------------------
一种更广泛用于实际应用的人工智能规划算法,因为它与人类解决问题的思维方式相似
马库斯·温克勒在 Unsplash 上的照片
介绍
HTN 规划是解决人工智能规划问题的另一种方法。它类似于经典的条状规划器,它表示世界的状态,并执行将一种状态转换为另一种状态的动作。
然而,它在计划什么和如何计划方面是完全不同的。在传统的规划方法中,输入是一组目标,算法搜索实现目标的可能性。在 HTN 计划中,输入的是一个要执行的 任务 。
任务是给予计划者的一个高级抽象概念,用于计划者提出一组可操作的基本任务(或操作符)。
这个想法很简单,因为通常有不止一种方法来执行一项任务,这取决于特定时刻的环境。因此,如果我们赋予我们的计划者如何将抽象的任务分解成具体行动的知识,它将能够给我们解决方案。
“分解”过程是递归的,从一个抽象的任务到不太抽象的子任务,最后是具体的行动。
这种方法在实际应用中使用得更广泛,因为它的工作方式是我们人类所熟悉的。我们熟悉从一个大的抽象问题到更小的问题及其解决方案的分层解决问题。
我们将讨论什么
在本文中,我们将讨论 HTN 计划的概述,然后我们将重点放在它的简单版本,总订单计划。然后我们看看如何在 C++中实现全序算法。
HTN 规划
状态、操作符、动作和状态转换的表示与前几篇文章中讨论的经典规划方法相同。
快速回顾如下:
状态是一组原子(详见一阶逻辑)。一个操作符是一个过渡函数,通常有三个组成部分:
- 名称(符号)
- 前提
- 效果
动作是操作符的实例化,在面向对象的编程中,你可以认为操作符是一个类,而动作是一个对象。状态转换是将一个动作应用到一个状态,将它转换到另一个状态。
状态转换(图片由作者提供)
假设 动作 1 和 动作 2 都适用于 状态 1 ,应用它们会将 状态 1状态 2 和 状态 3 转换成两种不同的状态。
任务、网络和方法
这种方法引入的新概念是任务、网络和方法。新的符号被引入,第一个叫做任务符号。运算符符号是一个任务符号。并且还有非原语任务的任务符号。它通常以下列形式书写:
任务表达式(作者图片)
例如,我们有一个操作员呼叫出租车,它有两个参数,人和出租车,它被写成:
任务表达式示例(图片由作者提供)
如果一个任务符号是一个操作符符号,那么这个任务就是本原的,否则就是非本原的。
第二个新符号是方法符号,表示方法的名称。方法是用于非原始任务的。
如果原语任务可以直接执行转换状态,非原语任务就不行。它们用于将抽象任务分解成抽象程度较低的任务或原始任务,或者两者的组合。
简单旅行领域的任务分解示例(图片由作者提供)
从这个例子中,我们可以看到有两种方法来执行一个旅行任务,要么乘出租车,要么步行。我们可以根据世界的现状,如距离、我们的钱数等,选择最佳的方法。
方法具有以下组件:
- 名称(方法符号)
例如,乘出租车出行。 - 任务(任务符号)
例如,*旅行,*它能解决的一个任务。 - 前提条件
了解该方法在当前世界形势下是否相关。 - 网络
我们将在下面进一步讨论的任务网络(或子任务)。
与运算符的表达式相同,可以写成如下形式:
方法表达式(图片由作者提供)
现在我们来看看什么是任务网络。任务网络是一个 ADG(无环有向图):
任务网(图片由作者提供)
其中是一组节点, E 是一组边。每个节点代表一个任务,边代表部分排序。如果所有节点都是完全有序的,我们可以用一系列任务来代替这个网络。
任务序列(图片由作者提供)
如果序列中的所有任务都是原始的,那么我们只要用行动代替任务就有了计划。
方法示例
让我们来看一个简单的方法示例,它使用上一节中的图片所示的简单旅行域。以下是乘出租车旅行的样子:
方法示例(图片由作者提供)
此方法可用于旅行任务,如果适用,将把任务分解成三个基本任务(操作符),依次是呼叫出租车、乘坐出租车和付费司机。
规划问题和解决方案
本办法中的规划领域包括:
- 状态
- 一组运算符
- 一套方法
规划问题由以下几部分组成:
- 初态
- 初始任务网络
- 一组运算符
- 一套方法
解决方案计划是能够完成初始任务网络的一系列行动。解决方案计划是将初始任务网络分解成可操作的基本任务(操作符)的结果。
总订单计划
在本文中,我们着重理解全订单计划,其中的任务网络不是一个图,而是一系列任务。这是 HTN 规划的简单版本。
算法如下:
TFD 算法(作者代码)
全阶向前分解(TFD)算法是一种递归算法。在上面的伪代码中,我们可以看到算法是从检查一个任务是原语还是非原语开始的。
对于原始任务,从一组适用的动作中选择一个动作。然后,就像在经典的规划方法中一样,所选择的动作被应用到当前状态来转换它。然后从任务网络中移除该任务,并且算法继续。
对于非原始任务,从一组相关的方法中选择一种方法。然后使用所选方法分解任务,并用任务网络中的新任务替换当前任务。状态T3s保持不变。
C++中的 TFD 实现
为了测试这个算法,我基于 Dana Nau 的实现用 C++17 编写了它,它是用 Python 编写的,如下所示:
**
规划领域
我们需要的第一件事是表示由状态、一组操作符、一组方法组成的规划域,我们还需要表示任务。
我们需要使所有这些通用,以便我们可以编写规划领域,而不必修改算法。
规划领域(作者代码)
所以我们把我们的状态和任务包装在 structs 中,在函数包装器中定义操作符和方法的格式。
规划问题
我们可以将规划问题表示为一个封装了规划域、初始状态和任务网络的类。
TFD 类别
主类 TFD 如下所示:
TFD 类(作者代码)
它需要的只是一个规划问题对象,那么我们只需要调用 TryToPlan 来获得解决方案,如果有的话。
实现我们的领域
为了实现我们的领域,我们需要用 C++编写以下代码:
- State
将它包装在上面的 State 类中 - 经营者
- 方法
关于详细的例子,您可以在 Github 上的我的资源库中找到它们(参见下面摘要部分的链接)。
摘要
与经典的规划方法相比,分层任务网络——HTN 是一种更广泛使用的人工智能规划方法,因为它与我们思考解决问题的方式相似。这使得实现和分析变得相对容易。
其中一个最简单的版本是全序向前分解(TFD ),它使用一系列子任务来代替任务网络的无环有向图。
它通过递归地将抽象任务分解成抽象程度较低的最终具体任务,或者可以由 AI 代理直接使用的动作,来解决规划问题。
我已经用 C++写了代码,包括算法的一般实现和一些例子。如果你有兴趣,可以在这里探索一下:
*https://github.com/debbynirwan/tfd_cpp *
对天真的数据新手的严厉的爱
原文:https://towardsdatascience.com/tough-love-for-na%C3%AFve-data-newbies-5dd376693eea?source=collection_archive---------2-----------------------
意见
不懂统计数据的书呆子会犯的 3 个错误
在在家工作的时代,许多新员工将没有机会享受来自附*隔间的愤世嫉俗的抱怨,这意味着如今养育我们年轻的数据科学家的大部分劳动都没有完成。让我来帮忙分配一些曾经交给我的塑造性格的好东西。我会尽最大努力模仿我遇到过的最暴躁的导师。尽情享受吧!
数据新手们,如果你从未被现实世界的项目摧毁过对数据的信心,这里有三个你会犯的错误:
- 以为你是来找正确答案的。
- 最努力地处理垃圾数据。
- 忘记了你的 AI 系统中最薄弱的环节。
图片:来源
如果你热爱数学,它会伤害更多
如果你因为数学的纯粹而热爱它,如果你喜欢寻找正确的答案…欢迎来到地狱。
两个人可以使用相同的数据得出不同的——并且完全有效的——统计结论。是的,你听到了:同样的数据,两种不同的答案,都是正确的。
这是因为你用真实世界的数据做的任何工作总是基于不被支持的假设。(原因如下。只要你评估你所做的假设,并意识到你的结论只有在这些假设下才是有效的,你做的每件事都是正确的。
两个人可以使用相同的数据,通过做出不同的假设,得出不同的——而且完全有效的——统计结论。
换句话说,从技术上讲,我们被允许假设任何我们喜欢的事情并且我们的答案是正确的。
除了,* 你是* 不是。 你 根本不允许做任何假设,除非你是 决策者 ,负责做出你所支持的数据驱动决策的人。唉,如果你是新来的,被授权做假设的人可能是你的老板或者你老板的老板。除非他们擅长用数学方法表达他们的假设,否则你可以选择要么学习一些非常微妙的询问技巧,要么接受这样一个事实:无论你选择什么样的假设,从技术上来说对决策来说都是错误的。
第一个错误是认为你在这里是为了得到正确的答案。最多,你会得到一个正确的答案。
我可以不停地谈论数据科学中的授权,但是让我们把痛苦保持在可承受的水*。在接下来的讨论中,让我们假设你是负责人并且你被授权做出假设。(这的确是一个巨大的假设!)
当你的分析不好,你应该感觉不好的时候
当复杂的不可测试的假设的规模完全淹没了你所能获得的信息量时,错误的应对方式是更加努力地(并且花更长的时间)做一个超级花哨的分析,完成它,并且为你所做的感到非常自豪。
有时候,更努力地工作是一种奇特的数学,更聪明地工作是知道何时止损。图片:来源。
坦白地说,你在绝望的情况下做出了绝望的反应,你应该知道不要假装你的结论不是站不住脚的。如果你打算与他人分享,收起你的笑容,并真诚地道歉。
“我们知道的是一滴水,我们不知道的是一片海洋。”―艾萨克·牛顿
例如,您可能正在处理一个继承的数据集而没有任何关于变量名实际含义的文档。如果是这样的话,你对这种极度复杂(并且自以为是)的分析做了什么?你的方法比瑞士奶酪有更多的漏洞,所以你为什么会声称你的辛勤劳动的成果是严谨的呢?你只是在瞎编。不管你在这种情况下运用了多少数学知识,都不应该把你的结果看得太重。
第二个错误是当假设盖过证据时更加努力工作。
相反,把它作为寻求灵感的途径,不要在数学上花太多时间。你的努力最好用在获取/创造更多信息。
当你的数据有月亮那么大,而你的假设有木星那么大时,出于礼貌,你应该每隔一段时间在
上向你的读者道歉。
单身。
行。
(我只是半开玩笑。)
木星(开始工作所需的不可测试假设的相对数量)+月亮(我们可以学习的东西的相对数量)=仓鼠轮(“让我们真正努力做一个花哨而正确的分析”)图片:来源
如果你在做假设,而你又不是领域专家,那么这些假设很可能是非常令人讨厌的垃圾假设。在你报告的每一行都要多次道歉,而不是一次。如果你的报告主要是道歉,那就更好了。
我最喜欢的统计学先驱之一,W. Edwards Deming,有一句名言“没有数据,你只是另一个有观点的人。这是真的,但不幸的是,“有了数据,你仍然只是另一个有观点的人。尤其是当你的假设超越了现实。
“有了数据,你仍然只是另一个有观点的人。''
换句话说,如果你要发表一份“数据”报告,试图隐藏那些践踏你那微不足道的数据在你的结论中发挥任何作用的能力的巨大假设,我希望你为自己感到羞愧。我更希望你说实话:“我的无知看法是……”
鉴于你的假设和你的证据之间的差距,你对数据的诉求是不明智的。如果你诚实地承认自己所知甚少,你的报告就会充满道歉,没有人会去读它。很好。
如果你不愿意诚实地承认你实际上知道的很少,那么在你浪费利益相关者的时间之前,努力工作去了解更多。
保持安静,直到你完成了让你值得听的作业。
我不提倡卑躬屈膝的道歉。我要求你保持安静,直到你完成让你值得听的作业。如果你坚持要分享你的观点,不要把藏在一点点相关数据(或者,更糟糕的是,一堆不相关的数据)后面。有勇气诚实地面对你所做的假设。
小心空隙!
一些让我畏缩的相关行为是 ML/AI 书呆子对让两个可敬的、有营养的 ML 模型围着一个我们不知道这里发生了什么的火车残骸模型在中间的反应。
来源
不管书挡有多花哨和正确,你都是在深渊上走一条极不稳定的钢索。为什么你会认为总体结果是一个好的、严谨的模型?这就像从一边开车兜风到另一边一样可靠…期待在中间享受一次巨大的碰撞。
你的解决方案只能解决最薄弱的环节。请对整件事负责。
在实践中,这种情况有很多种。经常被引用的一个例子是可疑的数据加上细致的记录,但我最喜欢的例子是当你从其他人那里购买模型,并且在没有在上下文中彻底测试它们的情况下部署它们。你的解决方案只能解决最薄弱的环节。请对整件事负责。
第三个错误是忘记了最薄弱的环节。
更坚强
做出假设是可以的,但是如果你的假设盖过了你的证据,不要对你自己(或其他人)的结论背后的严谨性撒谎。
当我第一次在 LinkedIn 上发布这个消息时,一些人非常不安。“有时这是我们仅有的,”他们哭着说。
我明白了。你很难过,你的数据不够好,不足以进行令人尊敬的分析。但这就是生活。克服它。仅仅因为你有一个充满数字的电子表格,并不保证你能从中获得任何有用的东西。
宇宙不会因为你掌握了一些数字就欠你可靠的结论。
对于那些努力用证据取代他们的假设,直到他们拥有的数据盖过他们没有证据支持的假设的勇敢的人来说,你们让我们所有人都感到骄傲。请继续做你正在做的事情!没有什么比证据将假设挤到一个小角落,然后提出一个令人信服的论点更美好的了,这个论点大部分是事实而不是虚构的。
被装扮成证据的意见可能比什么都没有还糟糕。
但有时,你没有做出可靠结论所需的信息,最好保持沉默,直到你有了这些信息。装扮成证据的观点可能比什么都没有更糟糕,所以请不要告诉我你认为无论如何都要展示数据是有荣誉的。如果你在评估数据的质量时没有考虑假设的质量,那你就错了。
取而代之做什么
我的建议是,当你面对这些情况(或它们的表亲)时,要更加谦逊。如果你淹没在不可能获得知识的事物中,保持你的方法简单。当你觉得自己被雇来做一个聪明的、有着花哨工具箱的人时,这很难。但你会很高兴你做到了。
好处包括:
- 诚实(对别人撒谎是不道德的,对自己撒谎是愚蠢的)
- 透明度(花更少的时间来弄清楚你如何得到你的结论,并理解它们的局限性)
- 努力守恒(简单的方法更简单)
2020 年 3 月,我在推特上看到一段对话,一位专家反对对新冠肺炎做出预测,一位家长愤怒地回应,还说了类似的话,“但是当我们的孩子问学校什么时候开学时,我们该怎么回答?”
父母们,我的建议是告诉你们的孩子我的父母在不确定时期告诉我的事情:真相。现在一起试试吧,“我.不要。知道。”
而且,事后来看,我们也不知道。
有风度地承认你不知道的事情。
有风度地承认你不知道的事情。一旦他们不再期待每个问题的答案,孩子们就能处理这样的答案。更令人惊讶的是,成年人也可以。我的猜测是,这两个群体都会因此变得更好——更明智、更有弹性。
感谢阅读!YouTube 课程怎么样?
如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:
在这里欣赏整个课程播放列表:bit.ly/machinefriend
环法Á瓜斯克拉拉什自行车赛的数据分析
原文:https://towardsdatascience.com/tour-de-%C3%A1guas-claras-cdb6c132b4ce?source=collection_archive---------27-----------------------
Francisco Aceldo 在 Unsplash 上拍摄的照片
也许这条路上没有像巴黎、卡尔卡松和图尔这样迷人的地方。也许它只是欧洲参考值的一小部分,比如说不到 1%。也许我是一个非常10 ⁰业余自行车运动员。也许,事实上,从环法开始,我只是借用了环法*这几个字。然而,我的环法自行车赛不是假的,是一次在我家附*骑行的很好的记录
我邀请你来看看记录速度、时间和高度的应用程序如何激发良好的数据分析,与数学、物理甚至公共政策进行很好的对话。请带上你的自行车跟我来。
关于我的旅行的一些话
Á·瓜斯·克拉拉是我家附*的名字。它是巴西首都巴西利亚所在的联邦区(DF)的一部分。DF 位于中部*原,一个统治我国中部大片地区的高原。
比较部分城市海拔
高海拔的特征与自行车旅行的数据分析相关,因为很容易看出,即使旅行发生在高原上,一些海拔变化也高于一些城市的*均海拔。这正是下图中呈现的要点。
不过在图前,一点点的 R 代码。请给我来点啤酒。
detalhe_percurso %>%
ggplot(aes(x= as.POSIXct(time_posix_millisecond/1000, origin = "1970-01-01"), y= altitude_meter)) +
geom_area(fill = "#976C42") + *#cor do solo de Brasília durante a seca*
geom_hline(yintercept = destaque[-c(3:5)], linetype = 5, alpha = 0.5 ) +
scale_y_continuous(breaks = c(seq(0,1200,300), destaque[-c(3:5)]))+
theme_light() +
theme(
*#panel.background = element_rect(fill="#696969"),*
panel.grid = element_blank()
) +
annotate("text",
x=hora_inicial,
y= altitude_fortaleza,
hjust = -0.1,
vjust= -0.1,
label= paste0("Fortaleza ",altitude_fortaleza,"m"))+
annotate("text",
x=hora_inicial,
y= altitude_ny,
hjust = -5,
vjust= -0.1,
label= paste0("NY ",altitude_ny,"m"))+
annotate("text",
x=hora_inicial,
y= altitude_guaramiranga,
hjust = -0.1,
vjust= -0.1,
label= "Guaramiranga")+
annotate("text",
x=hora_inicial,
y= altitude_paris,
hjust = -6,
vjust= -0.1,
label= paste0("Paris ",altitude_paris,"m"))+
annotate("text",
x=hora_inicial,
y= altitude_santiago,
hjust = -0.1,
vjust= -0.1,
label= "Santiago del Chile") +
labs(
x= "Horário",
y= "Altitude (m)"
)
现在上面的代码产生的图像。
海拔和城市。作者图片
正如我们所看到的,我这次旅行的海拔高度从 1045 米到 1150 米不等。这些分数远高于安第斯山脉环绕的智利圣地亚哥,也略高于巴西塞阿拉州一个迷人的小镇 Guaramiranga。最后,同样清楚的是,分数的差异大于一些大城市的海拔,如福塔莱萨、纽约和巴黎,这些城市的*均海拔几乎与海*面持*。
所有这些海拔高度的变化都与下面在开放街道地图的帮助下描述的这条路径有关。让我们看看我是如何实现地图可视化的。
**library**(leaflet)
**library**(sp)*# define bounding box with longitude/latitude coordinates*spdf_geo <- g_total$datacoordinates(spdf_geo) <- ~ longitude_degree + latitude_degree
proj4string(spdf_geo) <- "+init=epsg:4326"bbox <- list(
p1 = list(long = min(g_total$data$longitude_degree ), lat= min(g_total$data$latitude_degree) ),
p2 = list(long = max(g_total$data$longitude_degree), lat= max(g_total$data$latitude_degree))
)leaflet() %>%
addTiles() %>%
fitBounds(
lng1 = bbox$p1$long, lat1 = bbox$p1$lat,
lng2 = bbox$p2$long, lat2 = bbox$p2$lat,
) %>%
addPolylines(data=coordinates(spdf_geo), color = "blue")
乘坐。作者图片
蓝色路径代表游乐设备电路。在那个阳光明媚的八月星期天,我一醒来,就花了一个小时五十分钟骑自行车完成了我计划的* 30 公里。这条路线包括生态公园,沿着 DF 最繁忙的道路之一的自行车道,一些美丽的树木,和往常一样,一只流浪狗咬我的腿的风险。
描述整个旅程
在整个行程中观察到的正负梯度意味着速度的巨大变化。毕竟,正如牛顿已经知道的那样,存在着万有引力,这是物理学的普遍定律,它总是存在,并且在某种程度上使得像这样的飞行成为一项困难的任务。下面是一段代码,用于在图像中显示速度是如何随自行车道上的海拔高度变化的。向下滚动一点,查看生成的图表。
g_total<-
patch_graph( c("2021-08-01 08:56:00", "2021-08-01 10:48:55"))g_total + geom_hline(yintercept = destaque[1:2], linetype = 5, alpha = 0.5 ) +
scale_y_continuous(breaks = c(seq(0,1200,300), destaque[(1:2)]))
速度 x 高度(全程)。作者图片
颜色渐变显示了速度沿路线的变化。每条彩色垂直线代表 CycleDroid 应用程序每秒测量的速度。颜色越深,速度越高。
因为图表的刻度从零开始,所以高度变化看不清楚。这可能是一个好主意,查看速度图与缩放。相信我,对于我们这些骑自行车的人来说,下一张照片更好地展现了沿途山坡带来的情感。
g_total_zoom<-
patch_graph( bottom_altitude =1000) +
geom_hline(yintercept = destaque[1:2], linetype = 5, alpha = 0.5 )
g_total_zoom
速度 x 高度(缩放整个行程)。作者图片
让我们来评论一下这张图表。正如我们所看到的,有许多起伏。因此,在计算出的 15.8 km/h 的*均速度附*有很大的变化。该图对于将整个路线分解成一些关键部分非常有用。对于这篇文章,我们选择了与最激进的倾向相关的两个部分,你可以阅读下面的几个段落。
该图表对于检测异常事件也很有用。这是在 10:00 到 10:30 之间中断的情况。那时,我不得不等待着安全地穿过一条没有人行横道的繁忙的马路。我花了宝贵的几秒钟。也许像这样的发现可以帮助政府改善城市交通和休闲的公共政策。
正弦、导数、统计和总结完整路径的物理
为了更好地描述这个过程,在我们的分析中增加一些元素是很重要的。这里我们有一个问题。该应用程序只给我们提供瞬时速度、高度和时间的数据。更深入的描述还需要累积距离、加速度和倾斜度。在这方面,第一项任务是使用给定的变量计算所有这些新变量。
我引用了物理学中的公式,并使用一些微积分和三角学的方法,计算了剩余的变量。下面的代码引用了两个函数,我在其中进行了计算。
rad2deg <- function(rad) {(rad * 180) / (pi)}complete_ride_data <- function(df_ride){
df_ride$dif_altitude<- c(0,diff(df_ride$altitude_meter, lag=1))
df_ride$dif_speed<- c(0,diff(df_ride$speed_meter_per_second, lag=1)) df_ride$dif_time<- c(0,diff(df_ride$time_posix_millisecond, lag=1))/1000 df_ride$aceleration<- c(0,df_ride$dif_speed[2:NROW(df_ride)] / df_ride$dif_time[2:NROW(df_ride)])
df_ride$dist_percorrida<- c(0,df_ride$speed_meter_per_second[2:NROW(df_ride)] * df_ride$dif_time[2:NROW(df_ride)]) df_ride$dist_acumulada<- cumsum(df_ride$dist_percorrida) df_ride$inclinacao<- c(0,df_ride$dif_altitude[2:NROW(df_ride)]/df_ride$dist_percorrida[2:NROW(df_ride)]) df_ride$inclinacao_graus<- c(0, rad2deg(asin(df_ride$inclinacao[2:NROW(df_ride)])) )
df_ride
}
下面的代码使用函数 complete_ride_data,该函数又用作另一个函数的输入,该函数生成一个描述变量累积距离、速度、加速度和坡度变化的图形。
df_ride<- complete_ride_data(g_total_zoom$data )
graph_cinematic(df_ride)
科学在行动(全程游览)。作者图片
对于上面显示的所有图表,我应用了一个基于黄土回归的 R 函数来*滑曲线的形状。实际上,计算值中有很多噪声,尤其是最后三条曲线。
正如我们所看到的,累积距离,乍一看,可以被认为是一条几乎是直线的整条路线。然而,仔细观察会发现沿曲线的斜率有一些小的变化。事实上,在最后几分钟,曲线与一个形状相关,在该形状中,累积距离的增加速率略低于行驶开始时观察到的速率。
第一条曲线中的这些小变化与第二张图中观察到的不那么小的变化有关。当应用黄土算法时,瞬时速度以几乎正弦形状的方式变化,直到它变成向下直线的点。对于整个路线,这种行为主要是自行车道负斜率的结果,该负斜率从 9:15 一直持续到最后一秒。这意味着负加速度最好地描述了整个乘坐过程。
对于乘坐的具体部分,图片是完全不同的。就在其中两个下面,我们可以感受到冒险和艰苦的工作。
让我们来看看旅程的一个特定部分
首先,让我们看看如何将从 09:15 之前的某个时刻开始到 10:00 之前的某个时刻结束的特定部分的高度和速度联系起来。
图表就在下面,但首先是一些代码。
g_trecho_1<-
patch_graph(limits= c("2021-08-01 09:33:00","2021-08-01 09:48:00"), bottom_altitude =1000)
g_trecho_1
速度 x 高度(缩放第一部分)。作者图片
该图描述了一种情况,其中有一个正斜率和稳定下降的速度,然后我们可以看到某种*稳状态,速度以恒定值出现,变为零,并迅速恢复到之前的值。在*台的末端,有一个与高的正速度变化率相关的负斜率。这有点令人困惑,不是吗?也许这一段的地图会帮助我们确定到底发生了什么。但是正如你所知道的,首先是一些代码。
*# define bounding box with longitude/latitude coordinates*
spdf_geo <- g_trecho_1$data
lat_marker_1<- max(g_trecho_1$data$latitude_degree)
long_marker_1 <- g_trecho_1$data$longitude_degree[g_trecho_1$data$latitude_degree==lat_marker_1]
long_marker_2<- min(g_trecho_1$data$longitude_degree )
lat_marker_2 <- max(g_trecho_1$data$latitude_degree[g_trecho_1$data$longitude_degree==long_marker_2])
lat_marker_3<- min(g_trecho_1$data$latitude_degree)
long_marker_3 <- g_trecho_1$data$longitude_degree[g_trecho_1$data$latitude_degree==lat_marker_3]
long_marker_4<- max(g_trecho_1$data$longitude_degree )
lat_marker_4 <- g_trecho_1$data$latitude_degree[g_trecho_1$data$longitude_degree==long_marker_4]
coordinates(spdf_geo) <- ~ longitude_degree + latitude_degree
proj4string(spdf_geo) <- "+init=epsg:4326"
bbox <- list(
p1 = list(long = min(g_trecho_1$data$longitude_degree ), lat= min(g_trecho_1$data$latitude_degree) ), *#long -122.522, lat = 37.707*
p2 = list(long = max(g_trecho_1$data$longitude_degree), lat= max(g_trecho_1$data$latitude_degree)) *#long = -122.354, lat = 37.84*
)
leaflet() %>%
addTiles() %>%
fitBounds(
lng1 = bbox$p1$long, lat1 = bbox$p1$lat,
lng2 = bbox$p2$long, lat2 = bbox$p2$lat,
) %>%
addPolylines(data=coordinates(spdf_geo), color = "blue") %>%
addMarkers(lng= long_marker_1, lat= lat_marker_1, label = "Início subida",
labelOptions = labelOptions(noHide = T) ) %>%
addMarkers(lng= long_marker_2, lat= lat_marker_2, label = "Fim subida",
labelOptions = labelOptions(noHide = T) ) %>%
addMarkers(lng= long_marker_3, lat= lat_marker_3, label = "Fim ciclovia",
labelOptions = labelOptions(noHide = T) ) %>%
addMarkers(lng= long_marker_4, lat= lat_marker_4, label = "Fim descida",
labelOptions = labelOptions(noHide = T, direction = "right") )
第一部分。作者图片
我们可以在地图上看到四个地标。从上到下,第一个标志表示一个长的正斜率的开始,在第三个标志处结束。最后一个地标代表自行车道的终点。在那一点上,我做了一个 U 型转弯,这解释了零速度。我回到第三个标记,然后下到第二个标记。我认为这张地图描述足以解释令人困惑的速度变化。
关于这段路程的一些统计数据:
- 总距离:4153 米
- 正坡距:1595 米
- 正斜率时间:6 分 38 秒
- 总时间:15 分钟
- 最大速度:34.7 公里/小时
来自科学的更多帮助
现在出现了四个图表,从运动学的角度描述了路径。
科学在行动(第一部分)。作者图片
正如所料,当我们专注于整个轨迹的一小部分时,科学告诉了我们另一个故事。对于第一张图,更容易看到斜率的变化(仍然很小)。其他图表也更加动态。你可以看到坡度的不同会影响加速度,进而增加或降低速度。例如,前四分钟与速度的降低有关,受到一个负的(虽然是增加的)加速度的影响,反过来,服从于坡度的轻微上升。
尝试这样做:查看速度达到最低值点以外的图表,然后将四个图表与地图描述相关联,以解释图表中表示的四个变量的行为。
旅行中最困难的部分
在旅程接*尾声时,我面对一个非常陡峭的正坡。我的精力几乎耗尽,但既然我在写这篇文章,我想我活下来了。让我们看看第一张图表。
速度 x 高度(缩放第二部分)。作者图片
我们可以看到一个速度不断下降的正斜率,然后我们可以看到一些奇怪的测量结果,最后是高度的突然和持续下降,导致高速,然后是某种减速。我想地图会再次帮助我们更好地理解发生了什么。
地图再次出现
下面,我们可以看到与我们旅行的第二个特殊路段相关的地图。
第二部分。作者图片
这条路很长,尽头是一座供行人和骑自行车的人通过的桥,然后是一个急转弯。这条轨迹解释了上面显示的速度和高度图。顺便说一下,过桥与我前面提到的奇怪的测量值有关。
还有现在的统计拉伸:
- 总距离:1696 米
- 上坡距离:855 米
- 上坡时间:5 分 42 秒
- 总时间:8 分 38 秒
- 最大速度:39.3 公里/小时
毕达哥拉斯,牛顿&高斯帮助我们
让我们更详细地看看幕后的物理过程。
科学在行动(第二部分)。作者图片
在游乐设备的这一部分,更容易看到累积距离曲线的斜率变化。请注意,前几分钟与较小的变化率有关,然后这种行为发生逆转,因为我们可以看到这是斜率、加速度和速度变化的结果。花几分钟时间看看这四张图表,获得一些有趣的见解。
两个轮子上的科学
我相信这种分析的大部分可以通过一个好的应用程序来完成,该应用程序将我在这里计算的大部分数据汇集在一起,然后以漂亮的图形呈现出来。我在这里的目的是展示如何根据您的目标定制分析。这样做也是为了实践我们在课堂上学到的概念。换句话说,这篇文章收集了利用健康和可持续的实践中产生的数据创造性地进行科学研究的可能性:骑自行车穿过一个街区。此外,当在更大范围内进行分析时,像这样的数据可能会成为改善一些公共政策的良好起点。
代码和数据
我使用的大部分代码都在正文中有描述。尽管一些功能和配置变量没有示出。我的 GitHub 上有完整的代码和数据。
走向量子变压器
原文:https://towardsdatascience.com/toward-a-quantum-transformer-a51566ed42c2?source=collection_archive---------13-----------------------
Transformer 架构彻底改变了自然语言处理的世界。在通往理解圣杯的漫长道路上,与量子计算的结合可能会给它一个额外的推动力
*年来,在开创性的论文中首次引入的一种称为 变压器 的新颖神经网络架构arXiv:1706.03762彻底改变了序列数据的分析,特别关注自然语言处理任务,如机器翻译或从人类提示开始生成文本。Transformer 架构的推广将研究人员引向了各种领域的应用,如图像生成(图像毕竟是一系列像素)。
然而,这种神奇的神经网络的主要问题是,令人震惊的参数规模(在 OpenAI 的 GPT-3 的情况下,数量级为数百亿)通常需要巨大规模的训练数据集(例如,多种语言的完整维基百科语料库)和大规模的计算机网络来进行训练。GPT-3 的电费培训成本估计为 460 万美元,如果使用单个 GPU,将需要 350 多年。一些人认为这是整个人工智能领域变得越来越不民主的证据(这意味着一个小公司,更不用说一个人,根本无法与谷歌、微软和埃隆·马斯克的 OpenAI 等巨头竞争),而另一些人承认这一进展类似于过去几十年科学领域发生的事情:谁能负担得起在地下室建造一个大型强子对撞机的克隆体来研究希格斯玻色子的属性?
最后,关于这些网络实际上学习什么,有一个微妙的、相当哲学的问题。这些机器只是复制人类文档中看到模式,还是对所说的内容有更广泛的理解?“如果你把一个金属球扔向窗户,你可能会打破它”这样的句子对任何有金属和玻璃经验的人来说都有明显的意义。对于只接触过书面文本、与物理世界没有联系的神经网络来说,情况可能并非如此。另一方面,金属坚硬和玻璃易碎之间的关联很可能在文本语料库中出现足够多的次数,使得这一点即使对于最笨的机器来说也相当明显。关于这一点更详细的分析可以在道格拉斯·霍夫施塔特在《大西洋月刊》上发表的一篇名为《谷歌翻译的浅薄》的著名文章中找到。
有没有一种方法可以缩小这些神经网络的规模,甚至给它们注入对人类语言的理解?
那么,少了什么?对量子的需求
2020 年初,一家名为剑桥量子计算的英国公司宣布推出一种“意义感知”的量子自然语言处理(QNLP)模型,即一种能够将单词的语义信息与句子的句法结构拼接起来的数学理论。这个大胆的主张是基于这样的观察,即句法结构,如诺姆·乔姆斯基的上下文无关文法或分类组合分布(DisCoCat) 可以在量子物理学的框架内公式化。虽然 NLP 的希尔伯特空间的概念乍一看似乎很牵强,但直观的解释如下:NLP-as-we-know-it 植根于 经典统计学 (例如,单词嵌入是ℝ^d 空间中的向量),但经典统计学本身有其自身的局限性。被称为量子力学的物理学领域由量子统计学的数学描述,它通过用复数的矩阵来表示对象,从而扩展了经典统计学。最后,量子物理学和计算机科学交叉的研究领域被称为量子计算。因此,即使我们没有声称单词是粒子,我们需要描述人类语言的统计数据与量子物理学的基本相同也是偶然发生的。足够幸运的是,我们也正在进入一个时代,能够基于https://en.wikipedia.org/wiki/Qubit#:~:text=In%20quantum%20computing%2C%20a%20qubit,with%20a%20two%2Dstate%20device.量子位而不是数字信息位进行计算的初级且仍然相当嘈杂的设备正变得可以为更广泛的公众(包括小公司和个人)所用。因此,在 21 世纪 20 年代探索量子计算促进自然语言处理的可能性是有意义的。
混合方法
传统上,计算是由计算处理单元(CPU)执行的,这些单元可以处理数字形式的数字,即,将它们表示为逻辑位串。在 2009 年,在论文《使用图形处理器 的大规模 深度无监督学习》中,作者认识到了并行计算对加速计算的重要性,特别强调了神经网络中出现的最常见的操作,矩阵乘法,可以以并行形式进行转换,因此与图形处理单元(GPU)相关。然而,尽管 CPU 和 GPU 可以覆盖大量可能的计算,但有些仍然超出了它们的能力范围,或者至少不是以有效的方式,但如果计算是使用量子信息位(量子位)进行的,情况就不是这样了。这些问题中的一些例如在 NP-hard 或 NP-complete 问题的情况下出现。例如旅行推销员问题或柯尼斯堡的七座桥。这种优化问题可以用一种叫做量子退火器的设备来处理,比如由温哥华的 DWave 公司生产的那种。一类更普遍的问题可以用基于门的量子计算机来解决。事实上,人们已经注意到,在一些显著的情况下,如整数的因式分解,量子计算允许在更少的运算中找到结果,至少在量子位不受热噪声和其他与它们在物理系统中的实现相关的问题影响的理想世界中。为了更深入的解释,我参考了我之前在 CERN 的帖子幽灵计算机。
很明显,量子计算机不会解决世界上的所有问题,但在 CPU 可能永远占用时间的情况下,量子计算机非常有效。在化学领域尤其如此,毫不奇怪,科学家们正试图预测分子的属性,例如每个原子在三维空间中的位置。因此,这个想法是在常规计算机上进行大部分计算,并使用量子设备来解决棘手的部分。这种混合方法与我们在过去十年中使用 GPU 所做的并没有太大的不同。很快,人们意识到人工智能的一些子领域可以受益于这种加速,因此引入了 量子机器学习 。
在许多可能性中,最明显的一个是设计最简单的神经网络结构的量子等价物,并在更复杂的结构中的任何地方替换它。 感知器 也称为线性层或密集层*,简单来说就是矩阵乘法后跟一个非线性“激活”函数。此外,它的作用还在于改变(通常减少)特征空间的维度,例如从 512 个元素的输入向量,获得 128 的输出。量子电路不能天真地那样做,因为量子比特的性质决定了它只能在复杂的空间中“旋转”。因此,这个想法是通过一组角度θ_1,…,θ_ n (其中 n =量子位的数量)来参数化这个旋转,这些角度必须在训练期间“学习”,并且最终用两个线性变换来“夹层”或者更技术地“修饰”量子层,这两个线性变换考虑了维度的变化,在我们的例子中:512 - > n - > 128。这种变换被称为 变分量子电路 (VQC 或 QVC 取决于你问谁)。在我之前的文章 中,我给出了一个这种技术的实际例子,一个量子增强的 LSTM 层 。*
变分量子电路的例子摘自研究论文《用于深度强化学习的变分量子电路》(arXiv:1907.00397)。单量子位门 R_x(θ)和 R_z(θ)代表沿 x 轴和 z 轴旋转给定的角度θ。CNOT 门用于纠缠每个量子位的量子态。最后,沿着 z 轴进行投影测量。这种体系结构可能特别适合于实用目的,但是对于解释概念来说足够简单。
量子增强型变压器
正如在简介中提到的,Transformer 体系结构革新了顺序数据的分析,尤其是人类编写的文档。我在之前的帖子 中写了关于变形金刚的内容,请注意:忘记递归神经网络 ,但这里有一个简短的回顾。Transformers 是一种神经网络架构,它经过优化,可以在高度并行的设备上分析顺序数据,例如 GPU 和TPU。与递归网络不同,变压器没有“记忆”,但仍然能够通过组合位置相关嵌入 ( 即单词嵌入由另一组向量补充,该向量取决于单词在句子中的位置以及嵌入维度的索引)和注意力 ( 即计算出输入的哪些部分与计算输出相关)。任何变压器的核心都有所谓的多头注意力。其思想是将三种不同的线性变换 W_Q 、 W_K 和 W_V 应用于输入序列的每个元素,以将每个单词嵌入转换为其他一些内部表示状态,称为查询* ( Q )、键 ( K )和值 ( V )。这些状态然后被传递给计算注意力权重的函数,该函数被简单地定义为:*
注意力公式
为了促进从经典到量子实数的变换,人们可以简单地用变分量子电路代替线性变换 W_Q 、 W_K 和 W_V 。
基于 Google 的教程,这是 TensorFlow 2.0 中经典的多头注意力的样子:
要添加量子层,可以利用 Xanadu 的 PennyLane 量子机器学习库。有了这个框架,我们必须向执行量子计算(_circuit
)的类添加一个函数,然后用一个QNode
包装它,告诉 TensorFlow 如何用 参数移动规则 计算梯度。最后,我们创建一个KerasLayer
来处理混合神经网络中的 I/O。使用 PyTorch 接口可以完成类似的程序。请注意,PennyLane 0.13.0 还没有实现广播,所以KerasLayer
必须通过循环或列表理解应用于输入序列的每个元素。
编码部分到此为止!
训练这样一个网络需要大量的耐心。即使在经典情况下,也建议使用 GPU。在的例子中,我计划对 IMDB 数据集进行情感分析,在我的 MacBook Air 上训练一个二进制分类器一个时期需要大约 100 个小时!为了加快训练速度,我使用了 PennyLane 插件到 Qulacs 库,这是一个 VQC 模拟器,如果你有 GPU,它也会使用 GPU。另一种可能性是使用亚马逊的 AWS Braket 后端,但这可能是一种更昂贵的替代方案。如果你能找到更快的方法,请告诉我。需要说明的是, Qulacs 也可以通过[OpenMP](https://www.openmp.org/)
在多核模式下运行(只需设置一个环境变量,例如 export OMP_NUM_THREADS=32
)。
结论
在科幻系列星际迷航中,少校数据是一个机器人,他的 正电子大脑 让他拥有令人印象深刻的计算能力。这个虚构的大脑装置最初是由科幻作家艾萨克·阿西莫夫在小说 I,机器人中介绍的。它充当机器人的中央处理器(CPU),并为它们提供人类可识别的意识形式。有人可能会说,由于量子计算机的诞生通常可以追溯到理查德·费曼用计算机模拟物理(1982 年),艾萨克·阿西莫夫真正指的是量子处理单元(QPU)。众所周知,变形金刚能够完成句子和写短文,并且在某种程度上能够以不可思议的能力与人类(对话聊天机器人)进行对话。人们只能想象,如果量子增强版的变形金刚架构真的能够增加他们已经惊人的技能组合,会发生什么。
少校数据是虚构的 星际迷航 系列中的一个人物,由演员布伦特·斯皮内演绎。虽然他的正电子大脑让他拥有令人印象深刻的计算能力,但理解幽默和其他人类情感往往超出了他的能力范围。
训练量子增强变压器的代码可以在我的 GitHub 库中找到:https://github.com/rdisipio/qtransformer
为深度学习定义 AutoML
原文:https://towardsdatascience.com/toward-defining-automl-for-deep-learning-c257c3784b8c?source=collection_archive---------45-----------------------
深度学习背景下的 ML 管道的概述和分层定义
AutoML 在机器学习领域是一个相对较新且令人兴奋的概念。术语 AutoML 听起来很简单:在给定特定输入数据和任务的情况下,自动化构建机器学习生产模型的过程。但是,到目前为止,AutoML 还没有一个被广泛接受的定义,业界使用这个术语来指代许多不同的事物。
深度学习(DL)研究和实践中的最新方法简化了一些 ML 管道挑战,例如特征工程和选择。此外,DL 还增加了更多的超参数,如架构和训练制度的选择,并要求更多的标记训练数据,从而使 ML 管道变得复杂。
本文的目的是在 DL 的背景下提供 ML 管道的概述,并提出一个分级的定义,允许从业者和研究人员更精确地使用术语深度学习自动语言(DL-AutoML)。首先,让我们看看创建深度学习产生算法的主要步骤。
图 1:深度学习管道(图片由 deci.ai 提供)
- 任务制定——应用 ML 的第一个挑战是定义我们想要完成的任务和目标。例如,我们可能想要进行分类、回归、从数据库中检索等等。这一步还包括定义表示成功和失败的指标和目标。
- 数据准备—该步骤从识别原始数据源和原始数据采集开始。然后继续进行数据标记的过程。一旦数据被标记,额外的数据清理步骤被应用以移除异常值和不正确的标签。进一步的准备可能包括*衡类(如果数据分布不*衡)、归一化、训练和测试分区的形成等等。数据扩充是另一个可以用来丰富数据集的步骤。最后,使用数据质量分析来验证 DL 流水线获得了可能的最佳输入。
- 模型公式化——使用 DL 算法时,我们一般需要进行函数类选择。这一步包括选择类型的神经网络/架构家族(如 CNN、RNN、FC)和选择有效的架构(如 ResNet、MobileNet、EfficientNet 等)。此外,如果我们正在处理多模态,我们需要决定信息将如何从不同的模态传播到网络的更高部分。作为这一步的一部分,我们必须选择正确的损失函数,这个决定会极大地影响我们最终结果的质量。
- 培训—这一步包括实际的培训阶段。它从将数据划分成测试、验证和训练集开始。接下来,我们应用超参数搜索来选择模型的最佳参数,包括学习速率、宽度、深度等等。在这一步的最后,我们拟合模型,然后监控其在验证和测试数据上的泛化性能。
- 部署工程——给定一个训练有素的模型,我们的最终目标是将其集成到生产环境中。这包括为加载和预处理数据分配计算资源的过程,以及推理本身。在许多情况下,这一步还需要设计和实现负载*衡在为数据处理和推断执行的计算之间。在实时应用中,这一步应该包括推理运行时间的优化,以调整现有硬件的各种参数,如批量大小、操作类型和内存使用。
- 性能监控——一旦我们的模型被部署到生产环境中,监控它的操作、利用率和性能是必不可少的。在许多应用中,这种监控的一个重要部分是对模型的逐点不确定性的在线评估,以及检测分布变化的能力。
概述了 DL 管道的基本组件之后,定义 DL-AutoML 的自动化级别就变得更加容易了。
DL-AutoML 的主要目标是让深度学习对所有人开放,从个人到小型创业公司和大公司。无障碍一词在这方面至关重要。理想情况下,DL-AutoML 管道应该(1)价格合理(2)不需要高水*的专业知识(3)可靠和准确。这种方法为我们提供了流水线中自动化级别的粗略划分。每个子步骤都将根据其所需的专业水*进行优先排序,前提是该步骤可以被一个强大的自动化解决方案所取代。
例如,为任务选择正确的架构超参数需要高水*的专业知识。然而,这一步可以用神经结构搜索(NAS)来代替,它可能提供一个健壮的解决方案;因此,它获得了自动化的高优先级。另一个例子是数据标记,它在大多数应用中并不昂贵,也不需要高水*的专业知识。也就是说,我们不知道有什么解决方案能够以一种足够健壮的方式来自动标记数据,以完成广泛的任务。本着这种精神,我们现在定义自动化的 DL-AutoML 层次,并为每个层次提供典型的例子。
图 2:DL-AutoML 级别(图片由决策部提供)
0 级—深度学习管道的自动化、定制实施:
在很大程度上,这个自动化水*是历史性的,指的是深度学习时代的开始,在 Caffe、TensorFlow 和 PyTorch 等高级框架出现之前。当时,从业者需要自己实现深度学习管道,通常依赖于 C++等低级语言。在这个自动化级别,用户对他们的神经网络、优化器、损失函数、数据加载器等等进行编程。ML 管道中的其他元素,如数据处理、架构搜索和超参数调整都是根据人类的远见手动完成的。从头开始编写神经网络代码的过程容易出错,并且需要扎实的数学、编程和算法背景。这一级别所需的深刻掌握,以及深度学习的成功,导致了高级别库的出现,这是我们自动化水*的下一步。虽然是在熟悉的任务背景下,但这种自动化程度确实是“历史性的”。当我们看到现有框架中不支持的全新类型的网络和硬件(以及数据)时,0 级自动化是不可用的。
典型示例:假设我们想要实现一个二进制神经网络,其中每个权重和激活都是二进制的,即要么减一,要么减一。优势在于这种网络有可能使用更少的能量来运行。这种情况需要定制实现,最好使用非异或(Xnor)等逻辑门和填充计数操作。这种逻辑门和操作在神经网络中没有广泛使用,因此在 PyTorch、Tensorflow、Caffe 等高级框架中不可用。最有效的实现是用低级编程语言运行上述过程的定制程序。
级别 1 —高级 DL 框架
这是应用最广泛的自动化级别。用户不是使用低级编程语言,而是使用高级框架(例如,Caffe、TensorFlow、PyTorch 等)来实现 DL 模型和流水线。),它从层次、连接性和优化方面抽象了神经网络和工作流。这种框架让用户可以灵活地编写定制网络、优化器、损失函数等,所有这些都可以在通用硬件设备(如 GPU)上高效运行。这些库大大降低了构建和部署可靠的 DL 模型所需的专业知识水*。今天,大多数 DL 开发人员依赖于这种程度的自动化。然而,这一水*仍然要求在编程和 DL 方面有足够的熟练程度,这通常要求在开发非标准模型的领域中至少有硕士(或同等)学位。
典型的例子——假设我们有一个传感器,它提供一种新的数据,不同于任何现有的数据。如果我们的目标是为这种新类型的数据生成预测,现成的解决方案通常是行不通的。对于高质量的预测,我们可能会决定使用新的架构甚至新的架构系列来构建定制的网络。为此,假设自定义网络使用一般操作,最佳解决方案将是使用高级框架对神经网络进行编程。
第 2 级—解决预定义的任务和迁移学习。
监督机器学习中有许多任务被认为已经解决。比如视觉背景下的分类、物体检测、情感分析、语义分割等等。在这个级别中,假设感兴趣的任务或类似的任务在过去已经被解决。因此,有可能使用预训练模型和迁移学习来实现类似任务的准确解决方案。在这种情况下,我们可以采用在级别 1 中描述的高级框架之一(例如 PyTorch)内编程的训练模型(例如,来自开放源代码库)。然后,收集新任务的一些标记数据,并通过对新数据的额外训练来“微调”训练的模型。在这一水*上操作仍然需要工程师预处理数据并正确地执行微调。然而,所需的专业水*是基本的,完全可以由非专家完成。这种自动化水*的限制是使用已知模型的限制。如果模型运行得不好,用户需要回到第 1 级,这需要如上所述的编程和 DL 方面的深入知识。
典型的例子——假设我们想在一系列图像中检测行人,并在图像中的每个人周围画一个边界框。这项任务在过去已经解决,YOLO 框架为此类任务提供了高度准确的结果。为了建立一个适合新数据的模型,我们所要做的就是采用一个预训练的 YOLO 模型,并使用数据集(如加州理工学院行人检测基准)对其进行微调。在大多数情况下,这种方法产生的结果在准确性方面是令人满意的。
第 3 级—具有神经架构搜索和超参数调整的 DL-AutoML
此级别的目标是使第 2 级中提到的预定义解决方案可用于更广泛的任务。在这里,用户定义他们的任务并提供带标签的数据。如果可能,数据预处理由预定义的算法自动完成。给定清理后的数据,基于数据输入的种类自动选择函数类。基于任务公式自动选择神经架构的类型。然后,最终的结构也由神经结构搜索(NAS)自动确定;这里,考虑并测试了许多可能的架构,以便为手头的任务选择最有效的架构(例如,实现最高的准确性)。建立架构后,需要执行一个额外的步骤来调整超参数。NAS 不是灵丹妙药,但它将提供一个不错的解决方案——前提是它具备减少搜索空间所需的先验知识。由于这一限制,有些任务 NAS 无法解决,这一事实符合“没有免费的午餐”定理。如果没有达到期望的精度,人类必须进行干预,以确定在数据、学习算法或问题的可学习性中是否存在问题。在大多数情况下,任何数据问题都可以通过提供附加数据来解决。但是,模型问题要求用户返回到第 1 级。
典型的例子——让我们假设给我们一个医学图像的分类任务。在这种情况下,没有现成的模型可以使用。然而,这种数据是在文献中分析的,因此我们对所需的体系结构系列有一些先验知识,对所需的网络体系结构的先验知识很少。利用这一点,我们可以使用 NAS 在大量候选网络中进行搜索,并自动返回一个有效的网络。还可以使用网格搜索,或者更好的贝叶斯优化,来优化模型的其他超参数。
第 4 级—完全自动化,任何给定任务的 DL-AutoML
在这个级别,整个深度学习管道都是自动进行的。用户交付任务公式和数据,并且存在可以定义该数据和任务所需的先验知识的元模型。尽管这种元模型还不存在,但我们相信如果我们要实现 DL-ML 管道的完全自动化,这种模型是必不可少的。让我们仔细看看为什么。最初,深度学习仅用于简单的架构,如全连接架构。然后,AlexNet 引入卷积神经网络(CNN)进行图像分类,取得了图像分类的最新成果。这些 CNN 取得了优于全连接网络的结果,因为它们编码了一些分析图像所需的先验知识。基于对这类数据的研究和高度理解,在 LSTM 的文本、CNN 的声音和 RNN 的时态数据中发现了类似的先验知识。
在 DL-AutoML 的第 4 层,特定数据和任务所需的先验知识由某种元模型编码。给定训练数据,该元模型能够发明手边任务所需的体系结构家族,并且能够提供关于体系结构超参数的先验知识。利用这一知识,可以应用 NAS 过程来自动找到问题的最佳模型。结论
DL-AutoML 的目标是简化深度学习的使用,并让每个人都可以使用 DL 的惊人能力。*年来,DL-AutoML 的某些自动化级别已被广泛使用,并由许多科技公司提供。
本文提供了术语 DL-AutoML 的分层定义。我们首先定义了将 DL 算法从想法变成产品所需的各个阶段。然后,我们使用这些步骤来定义 DL-AutoML 的不同自动化级别。我们相信这一领域将继续发展。最终,部署深度学习将在按下按钮后完成。要了解 Deci 在 DL-AutoML 领域的发展,请下载我们的白皮书。
最初发布于:【https://deci.ai/ T3
走向完全自动化的主动学习管道
原文:https://towardsdatascience.com/towards-a-fully-automated-active-learning-pipeline-29b8f4eb7d73?source=collection_archive---------32-----------------------
用于主动学习的简单、模块化和通用架构
图片取自 freepik
在我的上一篇文章中,我简单介绍了主动学习的理论和方法。主动学习之旅的下一步是实施。在这篇文章中,我将分享我走向一个完整的自动化主动学习管道的旅程。
步骤 1——实施的动机
起初,像其他有动机的算法开发人员一样,我从实现所选择的主动学习方法开始。我没有考虑接下来的步骤和“大局”。一方面,它让我很快地实现了一个可行的(工程方面的)实现。另一方面,这使得接下来的步骤更加困难。在我的例子中,我有两个并行的后续步骤,这引出了三个不同的问题:
- 我如何建立一个积极的学习管道?
- 如何以模块化和通用的方式构建管道?
- 如何将多个不同的任务合并到管道中?
步骤 2 —主动学习管道—半自动
我的第一个主动学习管道实现是半自动的。每个周期完全自动运行,但手动执行。为此,主要增加了数据选择器。
数据选择器
数据选择器概括了主动学习的目的——以明智的方式选择下一个要注释的图像。其输入是一组当前未注释的数据,其输出是要注释的子集。
作者图片
数据选择器可以是附加的神经网络、经典算法、数据库查询或任何其他适合您的方法。
在每个周期,数据选择器基于前一周期的最佳模型。其输出集被添加到前一周期的训练集中(在对其进行注释之后)。
为什么半自动不够好?
除了手动执行每个周期的开销(这很耗时)之外,半自动流水线还需要监控。通过监控,我的意思是我们需要记住我们想要运行哪个周期,我们在哪里保存前一个周期的状态,手动选择前一个周期的推理模型,等等。这个过程很有可能出现错误、漏洞和混乱。理想情况下,我们需要全自动流水线,这是我们下一节的主题。
步骤 3 —模块化和通用的主动学习渠道
我有几种不同任务的模型。有一天,我发现自己一次又一次地从一个文件复制粘贴到另外四个不同的文件。此时,我认为有些事情需要改变,是时候进行标准化了。
培训管道组件是软件工程意义上最重要的组件。在您的培训管道中维护模块化和标准的架构,可以在您下次实施新网络时省去很多麻烦。
受这个模板的启发,我创建了自己的深度学习代码架构,有三个主要组件——数据加载器、图形和代理。
作者图片
数据加载器— 顾名思义,数据加载器封装了我们创建数据加载器对象所需的所有内容。
图表— 图表包含我们的网络模型和训练所需的其他组件,如优化器、调度器和损耗。
通过定义图,重用共享组件变得更加容易。例如,我有两个分割任务,使用相同的损失函数。我的图超类包含了 loss 函数实现,每个任务都实现为一个继承自图超类的图类。
代理— 代理是我们的培训班。每个特定的任务都继承自代理超类,并且必须实现 train 和 eval 方法。在代理超类中实现了一个通用的训练循环,从它继承的任何其他类都可以扩展它。
第 4 步—主动学习渠道—自动
回到主动学习管道,我们终于到了最后一步。为了创建一个完全自动化的管道,我们需要封闭循环。首先,每个周期需要加载前一个状态的状态,并保存其当前状态。其次,我们需要自动选择要使用的最佳推理模型。这是使用模型选择器模块完成的。
模型选择器 — 完成训练管道后,我们从训练循环的不同点保存了几个模型。模型选择器使用给定的标准选择最佳模型。
作者图片
该模型将在下一个周期中用作数据选择器模型(用于相关方法)以及新的生产模型。
额外步骤—比较模块
作者图片
我们是否总是想要为任何新选择的非注释批次重新训练我们的网络?大概不会。当我们注意到结果恶化时,我们希望重新训练我们的模型。为此,我们使用比较模块。
比较模块非常简单,工作方式如下:
- 在数据选择器模块中传递新的带注释的图像。
- 衡量结果的质量,并将其与您的关键绩效指标(KPI)进行比较。
- 满足 KPI —无需重新培训。
- 不符合 KPI —重新培训。
比较模块可以在开发阶段取消。在开发阶段,我们希望证明我们的主动学习方法是有效的。为此,我们使用一个已知的完全注释的数据集,并表明我们可以以一种明智的方式选择我们的下一个训练样本。更多细节,请看我之前的帖子。
终点线
是时候总结和概括整个架构了。在下面的方案中,您可以找到包含所有模块及其连接的自动化管道。
主动学习管道计划。图片作者。
我们做到了!
照片由 Jo Jo 在 Unsplash 上拍摄
现在,我们都熟悉了创建一个良好的主动学习渠道的步骤。
对我来说,花了一些时间来组织我所有的现有代码,以适应这种管道架构。但是完成之后,添加新任务或更改我的数据选择器方法变得容易多了。
祝你好运!
走向广义量子线性函数
原文:https://towardsdatascience.com/towards-a-generalized-quantum-linear-function-f682d572ee19?source=collection_archive---------26-----------------------
了解量子数据科学的基本构建模块
量子机器学习要不要入门?看看 动手量子机器学习用 Python 。
上周,我们介绍了一种创建量子线性函数的方法。我们将每个位置的值分成相等的块,并旋转量子位状态向量,以表示对应于块数的概率。
作者图片
然而,我们手动计算了所有的概率。因此,不清楚我们如何使用这种方法来创建其他线性函数。如果你还记得,线性函数的形式是 y=f(x)=ax+b。
从图形上看,a 表示图形的斜率。这是当 x 轴上的位置增加 1 时,图形中 y 的变化。$b$是截距,即图表与 y 轴相交的点。
作者图片
但是参数 a 和 b 没有出现在我们创建的代码中。因此,今天,我们推广我们的方法来解释这些参数。
因此,让我们简要回顾一下我们方法的步骤。
- 根据上量子位的值分割状态,并计算块数。
- 将上部量子位旋转 7/10,因为这是属于上部量子位为 1 的状态的块的分数。
- 根据低位量子位的值拆分高位量子位为 1 的状态,并计算块数。
- 将下部量子位旋转 4/7,因为这是属于下部量子位为 1 而上部量子位也为 1 的状态的块的分数。
- 根据较低量子位的值拆分较高量子位为 0 的状态,并计算块数。
- 将下部量子位旋转 2/3,因为这是属于上部量子位为 0 时下部量子位为 1 的状态的块的分数。
我们可以创建一个函数来代替手动计算块数,这个函数使用斜率(a)和截距(b)作为参数。
我们来看看前三个州的数字。
作者图片
每个状态都有代表 b(y 轴的截距)的块。第一个状态(00)没有更多的块,因为它位于 y 轴上(根据定义)。下面的状态(01)也有表示 a 的块—斜率。所以它有 a+b 块。第三个状态具有前一个状态的所有块加上另一个 a 块。所以,它有 2a+b 块。
因此,我们创建了一个为我们计算块数的函数。
这里,SLOPE
代表 a,INTERCEPT
代表 b,最后函数count_blocks
以状态的位置为参数,返回对应状态的块数。
所以,让我们调整剩下的代码,用计数函数替换固定的数字。
我们之前概述的步骤都在这段代码中。当我们用所示的斜率和截距值运行该电路时,我们得到的分布与之前相同。
作者图片
我们现在有了这两个参数。所以让我们和他们玩一会儿。例如,让我们设置斜率=2,截距=1。
作者图片
我们看到图形的斜率增加了(从 0.1 增加到大约 0.125,细微的差别是舍入误差)。但是,与此同时,代表截距的状态 00 的值减小了。这是量子位标准化的直接结果。所有状态的总和必须是 1=100%。
让我们看看如果我们设置INTERCEPT=0
会发生什么。在这种情况下,你可以为SLOPE
选择任何正值。
作者图片
状态 00 的概率现在是 0。因此,它没有出现在图表中。绝对斜率现在是 0.167。这是我们用两个量子比特所能达到的绝对最大值。原因还是在于正常化。
让我们试试别的东西。负斜率怎么样?你唯一需要考虑的是概率不能是负数。因此,我们需要相应地设置截距。
如果设置SLOPE=-1
和INTERCEPT=4
,会得到如下结果。
作者图片
结论
一旦你对量子线性函数有了感觉,你会发现它非常有限。
- 它只对两个轴上的正值有效
- 最小和最大斜率是有限的
- 这是一个只有少量数据点的离散函数
虽然我们不能改变前两点,但我们肯定可以在第三点上努力。这是我们在下一篇文章中要做的。
您还可以看到,实际(绝对)斜率取决于SLOPE
和INTERCEPT
的值之间的关系,而不是它们的绝对值。当你习惯于经典的线性函数时,这可能有点违背直觉。
量子机器学习要不要入门?看看 动手用 Python 学习量子机器。
在这里免费获得前三章。
迈向现代数据*台
原文:https://towardsdatascience.com/towards-a-modern-data-platform-93ab22fadb9a?source=collection_archive---------11-----------------------
开放、可扩展、快速且灵活
斯蒂夫·约翰森在 Unsplash 上拍照
这些年来,我目睹了数据基础架构领域的几次演变,或者更广泛地说,如何存储和使用数据。这个领域不仅发展迅速、引人入胜,而且是大多数公司都必须努力应对的问题。我们正在成为一个真正的数字物种,如果不是的话。我们所做的很多事情最终消耗了数据,并创造了更多的数据。这反过来导致为我们提供产品和服务的公司不得不以某种方式存储和使用这些数据。如果说软件正在吞噬世界,那么数据就是它的燃料。
这篇文章提供了我对这一领域发展的观点,从传统的数据仓库到数据湖,最后是云对数据空间的影响。
让我们开始吧。
Web 1.0 数据仓库
我的职业生涯始于 2000 年,当时如果您想要存储有意义的大小(和重要性)的数据,您可能会默认使用数据仓库,可能是 Oracle 的产品。数据仓库擅长以优化的性能存储和处理大量数据。数据仓库通过列存储、查询优化和常用表缓存等方法为结构化数据提供了强大的性能。仓库的基于表的模式支持 ACID 事务、记录级突变和粒度特权(在表和列级别)。数据仓库的典型用例过去是,现在仍然是报告和商业智能(BI)。
这个时代的数据仓库将作为运行在专用硬件上的软件交付。当我开始职业生涯时,您会在数据中心的装货区收到您的 Teradata 或 Oracle 数据库!除了软件与硬件的紧密耦合,这些数据仓库还将计算与存储紧密集成。最后,这些数据仓库以专有和优化的格式存储数据,这样做最终是为了获得良好的性能。
软件和硬件以及存储和计算的紧密结合有两个重要的含义。首先,很难快速且经济高效地扩展存储或计算。在这两种情况下,您都需要更多的硬件,通常是您必须直接从数据库供应商那里购买的定制硬件。第二,因为数据库最终以某种专有格式存储数据,所以您最终被供应商锁定。将数据转移到另一个数据库非常困难。那个时代的数据库在处理半结构化或非结构化数据时性能也很差,
房间里的大象:Hadoop
Apache Hadoop 是作为数据湖的第一个迭代引入的,以解决高成本和处理半结构化和非结构化数据的数据仓库挑战。Hadoop 在很大程度上是一种内部解决方案,但它以比数据仓库低得多的成本提供了一种开放式文件存储。低成本存储的前景让组织投入巨资将其数据从传统数据仓库迁移到 Hadoop 文件系统(HDFS)中。
然而,很明显,在 HDFS 转换、管理和分析数据并不容易,需要大量的工具,并且不容易提供交互式查询和 BI 等常见用例所需的性能。尽管文件存储的灵活性是一个优势,但缺乏数据管理功能(如事务和数据突变)阻碍了许多本地数据湖计划的成功。最终,我认为管理 Hadoop 环境的困难以及云对这一领域的重大影响最终导致了 Hadoop 的消亡。
然后出现了云
福斯托·加西亚-梅内德斯在 Unsplash 上的照片
云的兴起对传统的数据仓库和数据湖空间都有重大影响。在数据仓库方面,像 AWS 和 Azure 这样的公共云实现了计算和存储的分离,并承诺无限扩展两者。这导致了传统内部数据仓库的重组,并为根据数据量分别扩展存储和根据查询工作负载进行计算提供了更大的灵活性。
如今,现代云数据仓库,如雪花、AWS Redshift 和 Azure Synapse,提供了标准的数据管理功能,如事务、记录级突变和时间旅行,同时还将计算与存储层分离。然而,存储在这些数据库中的数据仍然是专有格式。
这些数据仓库与其前身非常相似,也要求数据库查询引擎处理的任何数据都存储在数据库中。这反过来又导致了冗长而繁琐的 ETL 过程,将数据从最初所在的位置移动到最终的数据仓库。
简而言之,这种新型数据库提供了独立扩展存储和计算的灵活性,但仍然没有解决供应商锁定问题,并且您仍然必须处理繁琐的 ETL 管道,这也导致了复制和移动数据的需要。
云对数据湖空间,尤其是 Hadoop 的影响是巨大的。像 S3 这样的产品提供了比 HDFS 更便宜、更易于管理和“无限”可扩展的替代品;Hadoop 的存储层。早期的云数据湖服务提供商,如 AWS EMR 和 Azure HDInsight,专注于将 Hadoop 堆栈引入云,提供基于云的开源计算引擎,如 Apache Spark、Hive 和 Presto。
虽然这些服务减少了在云中创建数据湖的工作量,但它们没有提供数据仓库和 BI 等常见用例所需的性能或数据管理功能。他们也缺乏事务支持,而这正是数据仓库擅长的。
然而,他们进一步扩展了将计算与存储分开的概念,将计算与数据分开。通过这种方式进一步分离架构,可以根据数据量和工作负载轻松扩展或缩小系统,同时保留传统数据湖架构中开放文件格式的灵活性。这还意味着我可以在同一个数据湖存储层(如 S3)中存储不同格式的数据,如拼花文件、CSV、JSON 等。
这一演变的不同之处在于,我可以根据数据类型和用例选择分析这些数据的处理引擎。这意味着即使我将 JSON 和 Parquet 文件存储在同一个存储层,我也不一定要对两者使用相同的处理引擎。
现代数据*台
现在,我认为我们正处于这个领域的另一次演变之中。其中,我们可以设计利用云优势的数据*台,即将计算与存储和数据分离,而不必牺牲性能或传统数据仓库(云或其他)的 ACID 保证。特别是,我看到正在出现的新*台提供了以下功能。
下图或四层蛋糕说明了构建满足上述标准的数据*台的一种方法。蛋糕的最底层是数据层,它基于开放的文件格式,如 Parquet、JSON、Orc 等。这些数据存储在基于云的文件系统中,如 S3、Azure Data Lake Storage 或 Databricks 的 Delta Lake。
作者图解
存储上面的层是引擎层。这些是处理存储在 S3 等地的数据的计算引擎。其中一些引擎,如 Dremio 和 Databricks ,能够以事务方式修改存储在存储层中的数据。Dremio 通过利用 Apache Iceberg 来实现这一点,Apache Iceberg 支持存储层上的 DML(插入、更新、删除)操作、事务和时间旅行,例如 S3,它不一定支持这些语义。最后,最顶层是应用程序层,如传统的 BI 工具和机器学习框架。
这种架构有几个优点。首先,它利用了开放文件标准,从而消除了供应商锁定的风险。其次,它利用了云文件系统的可靠性、易用性和灵活性,可以随着数据的增长而扩展。文件系统的扩展取决于您的数据占用量,不一定与计算或其他资源相关。第三,它消除了复制或 ETL 数据的需要。数据存储在云文件系统中,由 Dremio 等引擎直接处理,从而节省了时间和金钱。第四,它允许计算与数据分离。你现在可以自由地使用许多引擎,而不像数据仓库,不仅仅局限于一个。引擎的选择可以基于数据格式和总体用例。例如,Spark 可能是机器学习用例的首选引擎,而 Dremio 可能用于 BI 用例。
最后,这种架构并不排除人们仍然使用数据仓库。您仍然可以提供像 Redshift of Snowflake 这样的云数据仓库,并让它处理存储在云数据湖中的数据。你可以鱼与熊掌兼得:)
原载于 2021 年 10 月 3 日 https://karimfanous.substack.com*。*
迈向现代 LIMS:动态表格、无代码数据库和无服务器验证
原文:https://towardsdatascience.com/towards-a-modern-lims-dynamic-tables-no-code-databases-and-serverless-validations-8dea03416105?source=collection_archive---------10-----------------------
需要电子表格灵活性和数据库完整性的科学数据
插图由 Shutterstock 授权,用来自 Algorithmia 的 AI 着色
早在 2018 年,我的任务是为威尔康乃尔医学的基因组测序核心设施实施实验室信息管理系统(LIMS)。LIMS 本质上是一个具有几个关键特性的数据库:
- 动态表格:测序是一个前沿领域,随着新的试剂盒和方法的开发,每个月修改列和表格并不罕见
- 强打字:长整型、浮点型、小数型、对舍入的控制和分配测量单位对于科学数据是必须的
- 验证:运行测序仪的成本很高——需要对值和依赖关系进行可靠的检查和交叉检查
- 类似电子表格的用户界面:电子表格在湿实验室中无处不在 web GUI 必须支持从桌面软件复制粘贴行和列
在调查该领域并与其他测序核心会面后,我们发现商业产品都是过时的闭源专有系统,难以扩展,并且需要大量工作来定制我们的工作流程。至于开源,当时唯一真正的竞争者是来自著名的桑格研究所的sequence scape——这是一个成熟的 Rails 应用程序,具有后台工作和大量的功能和挂钩,使其更容易扩展。缺点是它与他们特定的内部工作流程紧密相关。例如,添加新的自定义列或表需要编写代码、停止服务器和迁移模式,这不是我们每个月都想做的事情。我们还研究了 AirTable ,但当时集成是有限的,它更侧重于营销/业务,例如,它不支持科学数据所需的测量类型和单位。
没过多久,制度性的 NIH 综合症就出现了,我们开始从零开始开发一个灵活的、可扩展的 LIMS,或者用今天的术语来说:一个无代码数据库。我们的目标是创建一个类似于旧的 MS Access 图形用户界面的东西,让任何人只需点击几下鼠标就可以构建一个全功能的数据库。我们工作过的其他核心也有类似的要求,因此保持系统尽可能通用、灵活和适应性很重要——它处理显微镜数据应该像处理测序数据一样容易,像处理泰国烹饪食谱一样容易。同样,它还应该支持多租户,以最小化我们的维护和系统管理员开销。
选择数据库:RDBMS vs 文档 vs 图形
文档数据库因其流动的数据模型而吸引人——每月从 UI 动态添加新的属性和集合轻而易举。然而这种好处也有坏处:没有结构化的模式,维护数据完整性就变得更加困难,正如在 shippiable发现的那样。图形数据库在提供具有关系完整性的结构化数据模型方面提供了两个世界的最佳选择,这种模型仍然非常灵活,但在 2018 年,社区中没有足够的支持使这成为一个可行的选择。例如,我们希望使用开源 BI 工具(如 Metabase、Apache Superset 等)来可视化我们的一些数据,而当时没有简单的方法将这些应用程序连接到 graph DB。所以我们选择了旧的可靠的 RDBMS,并选择了 PostgreSQL,主要是为了 JSONB 和模式支持(下面将详细介绍)。
带有 Postgres 的多租户动态表和列
在 JSONB 中存储动态列
我们首先想到的是尝试某种关系文档混合,其中公共基值(id、名称、修改时间等)存储在列中,而其他值都存储在单个 JSONB 列中。例如,一个集合可能是一个排序项目,而实体可能是那个项目的排序样本。一个项目可以有多个样本,一个样本可以有多个项目。
这种方法的优点是,外键可以用来加强高级关系的完整性(例如项目和样本),而额外的定制属性和值可以被动态地添加或删除,而没有任何中断。Postgres 还提供了支持将 JSONB 键值扩展到原生列查询的函数,这允许从 DB 查询中隐式检查/合并丢失的键或值,而不是在应用程序逻辑中编写繁琐的手动检查。
我们发现的两个主要缺点是,查询很快变得非常复杂,并且一旦 JSONB 字段变大(> 5000 个字符),它就无法伸缩——性能慢得令人无法忍受,尤其是当试图按 JSONB 值分组时。我们试着调优 TOAST ,发现用 CTE 模式重构查询产生了很大的不同,但是在我们所有的优化之后,在一个只有 100K 记录的表中完成一个简单的 JSONB 值分组仍然需要 5 秒多。
用 Postgres 模式隔离租户表
Postgresql 中的模式不仅仅是数据模型,它还是一个名称空间特性,包含数据库对象,如表、列、索引等。这反过来允许属于不同租户的数据被隔离在单个数据库中。因此,如果我们要开发一个应用程序来动态构建数据库,为什么不使用 Postgres 来创建和修改专用模式中的表呢?
如果我们编写代码来直接创建和修改表,那么我们就不能再使用我们的 ORM(我们使用 Rails 的 Active Record ),让我们像穴居人一样为每个操作写出原始 SQL。每个表和列也有一大堆元数据(例如,大多数数字列也需要一个度量单位),应用程序需要知道这些元数据的结构和值,然后才能做任何有用的事情。因此,除了丢失 ORM 之外,我们还需要实现一个元数据系统来跟踪表和列,这很快就让人感觉您正在创建数据库的副本。
实体-属性-价值模型
这是动态属性值的经典数据库(反)模式,最好的描述是 给你足够的绳子让你用 上吊。可以找到一些有利的观点,但是众所周知,除了最基本的应用程序之外,查询很快就会变得编写起来非常痛苦,执行起来非常缓慢,并且难以理解。
如果我们从 EAV 模型的数据库实现中抽象出来,转而在对象级别上考虑它,那么对于我们构建多个动态 RDBMS 的用例来说,它就变得更加合理了:
- 一个实体是一个 DB 行:一个有 ID 和类型或者组成的东西(比如一个项目或者一个样本)
- 每个实体都链接到一个或多个属性(列),每个属性都有一个 EntityAttributeValue (列-行值)的实例——它也可以链接到另一个实体(外键)
- 其结果是,传统表格(如示例表格)的 EAV 等价物是所有实体属性的集合,其中链接的实体匹配特定的组合类型*(如示例)*
在数据库层面,这是一个典型的数字键和神秘值的 EAV 混乱,但有了我们的 ORM,我们可以更直观、更有效地工作。例如,我们可以强类型化属性(并包括度量单位),所以在对象级别我们称之为*。val()* 但是在数据库级别,我们从匹配类型的列中进行选择(例如 dec_val 列,而不是 txt_val 或 date_val 列)并应用相应的单位转换函数。
我们实际上更进了一步,从 Alfresco 内容建模中借用了方面的概念,以便可以将常见的属性分组在一起——例如可测量的方面可能包括摩尔浓度、分子量、浓度等属性..有了这个特性,实体可以使用方面来建模一个生命周期或工作流,例如,在一个样本可以被排序之前,它必须有可测量的和质量可控制的方面。
Postgres 将未登录的表作为缓存
在 EAV 模型上使用对象更直观,也更容易操作,但是它不能解决选择查询速度慢的问题。我们还面临着与图形数据库相同的限制:我们不能使用期望关系数据结构的工具。
我们的解决方案是将数据从我们的 EAV 模型转移到 RDBMS 关系结构中,作为查询和外部工具的缓存。我们在 pure PL/pgSQL 中编写了一个函数,它为一个指定的表( Composition )选择所有的 EAV 数据,并将其转换为一个常规的表结构,包括 id、索引和外键。我们利用了 无日志表 的特性,因为数据是一次性的,稍加调整,我们可以在几秒钟内构建一个 50 万行的表。
这意味着:
- 选择查询被卸载到缓存表中
- 增量插入和更新在事务中有两个步骤:(1)从 ORM 中写入 entityspectattributevalue,这将触发(2)从自定义 DAL 中写入相应的缓存表
- 批量插入和更新只写入entityspectattributevalues,然后重建缓存表
- 对动态列或表的任何更改也会重建缓存表
EAV 模型中的每个实例都有一个 tenant_id ,用于将缓存表隔离为单独的 Postgres 模式,以便可以使用合理的名称(例如 weill_cornell.samples )访问它们,并分别保护它们。
这个解决方案为我们提供了在对象级构建多个独立数据库的所有优势,这些数据库的数据和元数据都在由 ORM 管理的静态表中,同时仍然支持高性能的常规选择查询和使用缓存表的外部工具。
无服务器验证
验证是科学工作流程的支柱——如果我们不能在进行一项价值 1000 美元的实验之前交叉检查数值,那么我们还不如使用笔记本。我们首先尝试使用关系模型在应用程序中实现验证:每个验证链接到一个或多个可重用的规则,每个规则包含一个逻辑 Ruby 表达式字符串来评估值。随着验证变得更加高级,我们继续构建关系模型。例如,我们添加了关系来说明不同级别的验证,即属性值对方面对实体对组合。
几个星期后,我们所希望的可以从 UI 配置的可重用验证组件的良好库变成了一堆条件和异常。像 AWS Lambda 这样的无服务器、无状态计算非常适合这种离散的功能计算,所以我们开始将验证转移到无服务器云实施中,并且从未回头。现在,针对特定情况的验证更加具体,但这是由从无服务器 web 控制台即时复制、编辑和部署新验证的便利性所弥补的。
类似电子表格的用户界面
我们希望找到一个网格 web UI 库,它可以动态地从 API 中发现数据模型,所以我们所要做的就是在服务器端编写接口,并将其插入。有很多商业产品可以处理静态预定义的数据库,但是没有一个可以从调用中读取模型并动态获取相应的列标题和值。GraphQL Jamstack,如 Gridsome 或 Gatsby 看起来很适合这个应用程序,但我仍然没有找到一个包支持动态数据模型的带有分页、排序、过滤和列选择的可写网格(类似于 Google Sheets UI)。
下一个最好的事情是找到一个 UI 库,并自己编写支持逻辑。我们选定了 Handsontable ,这是一个令人印象深刻的全功能的类似电子表格的 Javascript 库,具有漂亮的 API、良好的文档和活跃的社区。唯一的问题是,当时没有将浏览器 MVC 接口到服务器端模型的模板或示例,所以我们开发了自己的 Javascript 模型和控制器来管理 Handsontable 视图并与我们的自定义 Rails REST API 对话。我们希望使用一个标准接口,但是 restSQL 和 JSON/q 似乎没有得到很好的支持或者被放弃了,而 PostgREST 对于直接数据库查询来说很棒,但是不太适合我们的定制 DAL。如果我们今天重新构建它,GraphQL 是显而易见的选择。
通常情况下,UI 很快成为最耗时和最昂贵的组件——它工作得很好,但它很复杂,难以扩展,维护起来也很麻烦。这使得它成为用现代 Jamstack 重写的头号竞争者,但是在投入了如此多的时间和一个小的开发团队之后,很难证明做出这个决定是正确的。
最终想法
现在是 2021 年,整个领域已经有了很大的发展——从像 Hasura 这样的应用程序可以在 Postgres 中动态构建 GraphQL 数据库,到用 sorbet 在 Rails 中进行类型检查,到 Handsontable 对 React、Angular 和 Vue 的全面支持。我很想听听您对 LIMS 或支持具有多租户数据模型的动态表的数据库的体验。
在 Whitebrick 我们目前正在开发 Airtable 的最佳开源替代方案,因此如果您正在寻找无代码数据库或现代、灵活的 LIMS 即服务,请联系我们。
2022 年 5 月更新: 自从这篇文章首次发表以来,我们成功地使用 Hasura、GraphQL、Gatsby 和 Serverless 开发了一个工作测试版开源无代码数据库,但无法找到社区兴趣或商业支持来保持它的运行。我们已经将大量代码整合到我们自己的内部集成/CDR *台中,它仍然是使用现代架构的可定制、可扩展 LIMS 的一个很好的起点。你可以在 GitHub 上找到后端和前端以及我们的网站上的一些基础文档。如果你有任何兴趣(和资源或预算)来恢复这个项目,请随时联系我们。
走向负责任和有道德的人工智能
原文:https://towardsdatascience.com/towards-a-responsible-and-ethical-ai-ef93308b4e7e?source=collection_archive---------31-----------------------
人工智能校准和安全
错不在技术,而在意图
由格雷格·拉科齐在 Unsplash 上拍摄的照片
负责任的人工智能、有道德的人工智能、对社会有益的人工智能——我相信你一定在某个时候听说过这些术语,不管你是不是数据科学家。
当我第一次听到这些术语时,斯蒂芬·霍金教授的警告在我耳边响起:
"全人工智能的发展可能意味着人类的终结。"
在那里,我开始了理解人工智能基础的这个关键方面的旅程。我过去常常想知道如何将伦理与人工智能联系起来,人工智能只是一系列算法,而事实上,我们还不能在我们自己中间应用伦理行为。
来源:freepik 创建的商业矢量
根据斯坦福大学以人为中心的人工智能研究所发布的人工智能指数报告,网络安全和监管合规性是面向人工智能/人工智能的组织确定的首要风险之一。
来源:https://aiindex.stanford.edu/report/
另一份报告揭示了人工智能如何引起本科生的兴趣。
来源:https://aiindex.stanford.edu/report/
现在,让我们进入今天讨论的主题,人工智能中的伦理。在过去的五年里,在会议上发表的关于伦理的论文数量呈指数级增长,这充分说明了伦理的重要性。
资料来源:https://aiindex.stanford.edu/report/
无所不在的人工智能:
人工智能的应用几乎存在于我们生活的各个方面。当我们解锁手机时,看看我们的手机,神奇的事情马上就以面部识别的形式发生了。我们看到很多推荐反馈给我们,从新闻提要、视频、音乐、我们在电子商务网站上购买的产品,到我们在聊天或写电子邮件草稿时输入的单词的自动完成建议。
您不想键入任何查询—不要担心。有多个数字语音助手,Siri,Alexa,Ok 谷歌为您服务。
这些只是我们如何被无处不在的人工智能包围的一些例子。
人工智能似乎让我们的生活变得更容易了。的确如此。但就像硬币的两面一样,关于人工智能如何进入我们生活的观点需要从“另一面”不带偏见地看待。
让我们来看这个视频,我们将进一步讨论另一边是什么样子:
来源:youtube
忽略视频背后的品牌,分享一下如果你是 Felix 你的感受。当你做咖啡交易的时候,从你登上出租车到使用 GPS 告诉记录你的数据的组织你去了哪里,你遵循什么路线,你感到舒服吗?到此为止了吗?没有。
接下来要知道你遇到了谁,你们谈论了什么,你下一个可能的目的地是哪里,你应该买哪个品牌的小玩意,你的信仰是什么,你的家庭组成是什么,你的种族,文化,以及很多其他会让你不舒服的事情,就像费利克斯在视频结尾那样。
当我们认为应用程序要求我们**【允许访问】**为虚拟的无名小卒时,它被忽略了,但视频显示人们(阅读“盈利”公司)监视你,以赋予物理意义和存在,这令人生畏。
到底是谁的错——技术还是商业?
一些人认为过度批评利用人工智能盈利的企业也是不“道德”的。重点是不要批评任何人,特别是艾,毕竟,商业是为了获取利润,推动经济发展。
但是问题来了,我们同样关心我们的存在吗?空气污染、水污染、工业气体排放、垂死的海洋生物、公民权利等突出的问题需要同等的关注,如果不是更多的话。
只专注于经营企业可能会让人更快实现目标,但不会让任何人走得更远。最终,我们共同创造了一个需要我们所有人在可持续发展的环境中生存并爱护我们的地球的世界。
我不会讨论道德人工智能的原则和支柱。我将把它留给专家。特别是,下面的链接对我发展对人工智能生态系统的理解和道德视野帮助很大。
https://www.weforum.org/agenda/2021/06/ethical-principles-for-ai/ https://www.pewresearch.org/internet/2021/06/16/experts-doubt-ethical-ai-design-will-be-broadly-adopted-as-the-norm-within-the-next-decade/
看到这些组织戴上道德透镜并在这个方向上采取重大行动还有很长的路要走,令人痛心。
这种懈怠的原因之一也源于这样一个事实,即我们对这个伦理框架还不熟悉,在这个框架中有许多东西是我们不知道的。我们必须快速提问,并继续更新我们的道德规范,这本身就是一条更艰难的道路。
我们不知道什么是道德的,考虑以下问题:
- 在大人和小孩之间你会救谁?
- 谁的生命更重要——商业大亨还是每日赌注?注意重要性的定义本身是有问题的。
这些都是棘手的问题,我们甚至无法在自己之间达成共识,并期望机器以某种方式使用道德判断并为我们的决策服务。不管人工智能或人类有多道德,总会有人在另一边质疑他们的行为。所写的框架不是为了取悦每个人,而是为了更大的利益。
我们能做什么?
在家里嚼薯片时,指责他人并期望世界行为合乎道德更容易。当务之急是,我们都要在基层解决这个问题,并确保我们在数据科学家的职业中以最高的道德标准行事,拯救我们自己和整个世界,以免陷入灾难。
终极问题
我们会被 AI 淘汰吗?它困扰你吗?如果是,那么我们来看看在什么情况下会出现这种情况。
我们应该意识到,人工智能是一种本身并不邪恶的技术。就是把 AI 作为工具传递其险恶用心的人。如果一个人、一个社区、一个种族或者一个国家想要部署 AI 来伤害人类,他们可能会。
问题是我们想进化成什么样的人类?世界已经看够了疫情造成的痛苦和苦难。它不应该再有针对任何特定种族或社区的恐怖、操纵、侵犯隐私、伤害性评论。
我们都是一体的。让我们团结起来,把 AI 当成我们的盟友而不是竞争对手。
数学和物理定律的自动发现:代数信息深度网络(AIDN)
原文:https://towardsdatascience.com/towards-automatic-discovery-of-mathematical-laws-from-observed-data-algebraically-informed-deep-68eb0482e4b7?source=collection_archive---------43-----------------------
使用深度学习发现任意代数方程组的解
莱纳斯·米米耶茨在 Unsplash 上的照片
深度学习和数学接口的中心问题之一是建立能够从观察到的数据中自动揭示潜在数学规律的学习系统。在过去的几年里,深度学习技术已经被用于求解许多类型的方程,包括偏微分方程[2],非线性隐式方程组[3]和超越方程[5]。
在这篇文章中,我们朝着在解代数方程和深度学习之间建立桥梁的方向迈出了一步,并介绍了 AIDN ,代数信息深度网络 [1]。给定一组满足一组约束或方程的未知函数,AIDN 是旨在使用深度学习解决该问题的通用算法。
为了解释 AIDN 算法的主要思想及其广泛的应用,我们从一个例子开始,
杨-巴克斯特方程
杨-巴克斯特方程是以下形式的方程:
杨-巴克斯特方程是数学物理中的中心方程,具有广泛的应用,包括量子场论和统计力学
其中函数
R 矩阵是满足杨-巴克斯特方程的可逆映射
是我们喜欢寻找的未知函数。对于本文,我们可以将和视为欧几里德域*的子集。*任何满足杨-巴克斯特方程的可逆函数 R 称为 R 矩阵。寻找上述方程的解具有非常长的历史,具有广泛的应用,包括量子场论、低维拓扑和统计力学,并且通常被认为是一个困难的问题。
深度学习拯救世界
我们现在解释 AIDN 算法在寻找上述杨-巴克斯特方程的解上的应用。为了求解杨-巴克斯特方程,AIDN 算法将寻找解 R 的问题实现为优化问题。首先我们把函数 R 写成一个深度神经网络。我们将把这个网络称为 f_R 或者简称为 f 。
因为我们要求 f 是可逆的,那么我们创建另一个网络 g ,我们将它训练成 f 的逆。理论上我们可以选择网络 f 是可逆的,但是在我们的论文中我们选择训练 g 使得它是 f 的逆。为了更直观地理解我们的解决方案,采用图形符号更容易。首先,我们用以下两个黑盒来表示网络 f 和 g :
函数 f 和 g 的图形表示。图形来源[1]。
给定这个符号,我们可以通过下面的图表表示两个函数 f 和 g 彼此相反的事实:
函数 f 的可逆性之一的图示图来源[1]。
这里,垂直连接意味着网络的组合。上图简单的说就是 f 后面跟着 g 和 g 后面跟着 f 就是身份图。
类似地,杨-巴克斯特方程可以通过以下图表表示:
杨-巴克斯特方程的图示。图表的
为了训练这两个网络,我们定义了以下目标:
上述损失函数基本上有两个目的:满足杨-巴克斯特方程以及强制函数 f 的可逆性。
更实际地说,为了训练 f,g,我们创建了一个辅助神经网络来帮助我们进行训练。具体来说,用损失函数训练辅助网络:
在哪里
和
其中{xi,易,子}表示从 A × A × A 均匀采样的点,其中 A⊂ R^n,一般为单位区间[0,1]。仅此而已!在训练函数 f 和 g 之后,假设存在解,则满足杨-巴克斯特方程(参见我们的 repo 以获得关于实现的更多细节)。
AIDN 算法的通用版本
我们为杨-巴克斯特方程所解释的思想可以推广应用于更大范围的问题。具体来说,给定具有 n 个变量的 k 个方程(或我们在论文中称之为关系),然后 AIDN 通过创建一组 n 神经网络来训练这些网络,通过将方程转换为 MSE 损失函数来满足关系。详细情况如下:
AIDN 算法
AIDN 用在哪里?
我们提出的算法是相当通用的,它可以应用于许多领域。我们只是触及了表面,并解释了它对杨-巴克斯特方程的适用性。今天,杨-巴克斯特方程被认为是应用于量子力学、代数几何和量子群的几个物理和数学领域的基石。理论上,如果给定足够的计算能力,AIDN 能够找到任何代数方程组的解,只要这种系统的解存在。在我们的论文[1]中,我们展示了许多其他的应用,包括寻找新的量子不变量。
局限性和结论
关于 AIDN 性能的一个重要注释是当具有许多生成器和关系时训练的难度。虽然诸如 SGD 的现代优化范例允许人们训练高维数据的模型,但是我们发现训练与具有许多生成器和关系以及高维数据的代数结构相关联的多个网络是困难的。这可以通过使用更好的超参数搜索和更合适的优化方案来解决。
虽然没有理论保证神经网络存在,但我们在实验中始终发现,在给定网络的足够表达能力和来自这些网络的域的足够样本点的情况下,AIDN 能够实现良好的结果并找到期望的函数。这一观察结果与理论深度学习[4]中关于深度网络损失情况的其他公开研究问题是一致的。
密码
在我们的 repo 中详细给出了上述示例和许多其他示例的存储库。
参考文献
[1] Hajij,Mustafa 等.“代数信息深度网络 (AIDN):一种表示代数结构的深度学习方法。” arXiv 预印本 arXiv:2012.01141 (2020)。
[2] Maziar Raissi、Paris Perdikaris 和 George Em Karniadakis。物理学通知深度学习(第一部分):非线性偏微分方程的数据驱动的解决方案。arXiv 预印本 arXiv:1711.10561,2017 年
[3],,孟,,廖,和斯特凡诺·埃尔蒙。非线性方程求解:前馈计算的一种更快的替代方法。arXiv 预印本:2002.03629,2020
[4]拉维德·施瓦茨-齐夫和纳夫塔利·蒂什比。通过信息打开深度神经网络的黑匣子。arXiv 预印本 arXiv:1703.00810,2017
[5] SK Jeswal 和 Snehashish Chakraverty。用人工神经网络求解超越方程。应用软计算,73:562–571,2018
实现更好的数据可视化和图形
原文:https://towardsdatascience.com/towards-better-data-visualizations-and-graphics-a19e11146808?source=collection_archive---------11-----------------------
实践教程
创建基于数据的图形和视觉效果的设计原则
这是一个比喻。它是由查尔斯·约瑟夫·密纳德创作的,用来展示拿破仑在 1812-1813 年间的俄国战役。
俄罗斯战争中法国军队的继承人(来源:维基百科
现代信息科学家说,这是人类历史上制作的最好的统计图。米纳德的图表从多变量数据中讲述了一个丰富、连贯的故事,并描绘了军队的规模、在二维*面中的位置、运动方向、撤退期间各天的温度。这是使用可视化方式显示数据的最简洁的方式之一。
我们能创造我们自己的象征吗?
也许是的!
现代科技出版物有 25%的视觉信息,我们为日常商业活动创建的*台有大约 60%的视觉内容(图形、图表等);它为图形的卓越化提供了坚实的基础。
为什么关注观想?
数据可视化是数据科学和机器学习的一个主要部分,因为人们必须在将数据放入模型之前探索数据,然后将结果传达给相关的利益相关者。
定量信息的视觉展示是爱德华·塔夫特的永恒经典,也是 20 世纪最好的非虚构书籍之一。它讲述了可视化图形的历史,图形优秀的规则,以及设计基于数据的图形时要遵循的基本规则。
作为一名数据科学家,我从 200 多页的知识中受益匪浅。
关键要点和走向更好的图表
- 清除杂物——清除所有你不需要的东西。少即是多。
- 没有饼状图——它们没有多大用处,因为人眼无法识别圆形切片的大小。当它们稍微相等时。
- 不要每次都用视觉效果——如果你没有足够的数据,那就只用大数字或表格来显示信息。
- 记住观众——观众不应该花太多时间来分析视觉效果。数据应该从视觉本身脱颖而出。使用基本和原始的视觉线索,如颜色、形状、大小来引导注意力。
- 不要扭曲数据——这种通过扭曲数据来讲述你的故事的想法不是一个好的原则。让数据自己说话。
如何设计更好的图表?
这就是图形优秀的来源。
卓越的图形能在最短的时间最小的空间内给观众带来最多的想法。
您可以通过三种简单的机制在图表中实现这一点:
- 没有图表垃圾——去掉奇怪的字体、纹理、阴影或任何会分散观众对视觉和数据中心思想的注意力的东西。
- 没有无用的信息——图表的大部分应该用于显示数据。
简单来说,只展示必要的东西。
3.实质重于设计——你的图表应该引导用户思考它所提供的数据和实质,而不是迷失在图形/视觉背后的方法论中。所以,诉诸人类理解和引导注意力的自然方式——从大到小,从暗到亮,从左到右,从上到下。
T 创建视觉效果的另一个要点是意图——最初为什么要创建视觉效果?图表内容的设计方式应该通过传达结论来推动决策。
图表背后的驱动力不应该是使用某些工具、软件包或库,而是传达你从数据中得出的结论。
图表在运行
让我们看看这些原则如何应用到我们的工作中。
我为我在 2011 年到 2016 年间观看和喜欢的电影创建了一些虚拟数据。让我们创建一个同比对比图。
这是我在第一次迭代中想到的。
作者图片
让我们看看我们是否能在这方面有所改进。
似乎有很多图表垃圾。第一个是图表下面的表格,轴标签。有一个密集的背景网格,没有任何用途,因此是一次性的。
这里和那里的一点点变化,我们得到了比以前更好的视觉效果。
作者图片
它更干净、更清晰,并且能够描绘它想要的东西,而不会呈现任何不必要的信息。
再举一个例子
一个虚构的商店老板想要比较上半年各种商品的销售情况,他创建了以下内容。
作者图片
这个观点没有任何根本性的错误,但是没有任何突出的结论。这里的模式是什么?店主应该得出什么结论?
这是一种更好的观想方式吗?
作者图片
通过 4 种方式打破图表,观察到一个模式,这是关键的收获。
好,再来一个!
一家虚构的公司推出了一款新产品,营销团队对现有客户进行了调查。
作者图片
它告诉我们,大多数用户不感兴趣,但仅此而已,剩下的一半没有太多信息。
这可以而且应该通过对数据进行排序来弥补。
作者图片
这似乎是一个更好的信息视觉,因为读者可以很快了解谁对产品最不感兴趣,谁对产品最感兴趣。
让信息变得美丽
基于数据的图表的目标不是为了创造而创造视觉效果,而是为了传达结论以推动决策。
作者图片
如果你后退一步,思考图形的目的是什么,在设计时保持简单,并有一个故事要讲,视觉可以给你很大的帮助。
利用排序函数构建统一的特征选择框架
原文:https://towardsdatascience.com/towards-building-a-unified-framework-for-feature-selection-with-ranking-functions-5605ef665f26?source=collection_archive---------38-----------------------
思想和理论
一个代码来统治他们。一个代码实现所有这些,并在同一个框架中绑定它们。
由大卫·皮斯诺伊在 Unsplash 上拍摄的照片
在任何数据相关项目的特征工程中,我们经常必须手动过滤我们将用于训练我们的模型的列;这种过滤通常依赖于我们对数据的洞察力,也依赖于许多可以帮助我们区分有价值的属性和冗余或无意义的属性的标准,这个过程被称为特征选择。
它们是选择属性的许多不同方式;我们今天看到的这个就是所谓的排名特征选择。这是最基本的方法。它用一个函数评估每个属性,对它们进行排序,并保留最好的属性。
虽然这种排序可以用各种方法来完成,但我们将探索这些方法的分类,看看这种分类如何帮助我们将它们组织成一个可靠的、可扩展的框架,并使用这个框架来测试和比较它们的行为。
特征选择排序方法
在特征选择中,我们可以根据 Dash】和 Liu 的分类,将属性的质量度量分为五类。
- 距离度量:量化属性和标签之间的相关性。
- **信息度量:**这些信息理论度量在根据一个特征的值分割它们之后,对标签的熵感兴趣。
- **一致性度量:**如果相同的值不与类的不同值相关联,则特征是一致的。
- **依赖度量:**如果取一个特定值的概率不受另一个值的信息的影响,则称两个变量是独立的,因此这些度量通过量化类对属性的依赖来工作。
- **分类措施:**这些措施耗时;他们在获取特定属性时评估分类质量。
当然,在介绍我将考虑的措施时,我将回到每一类。
受孕基线
在定义我们的功能之前,我们需要设置一个清晰的、可伸缩的基线,以指导进一步的开发。
要使用它,我们需要隔离构建框架所需的不同组件;我提议的模型化基于三个关键概念:
- **测度:**测度量化两个向量之间的关系;这种关系可以与依赖性、独立性或它们之间的相关性相关。特征选择排序方法
- **评价函数:**评价函数通过使用度量来评价特征的重要性;对于互信息评估或相关性评估,评估可以被限制到单个测量,或者可以根据我们考虑的分类器调整到分类测量的不同测量。
- **特征选择函数:**特征选择函数获取整个数据集,并通过对数据集的特征进行排序并取百分比或通过进行增量选择来执行特征选择,我们将在后面看到。
现在,让我们列举每一类组件的主要功能,因为这将为我们提供我们必须放在架构顶部的内容:
- **度量:**函数可以对度量进行建模,因为它不需要对数据进行预处理;它只是计算一个值,这个值将被高层组件解释和使用。
- **评估函数:**这里我们可能有一个预处理,因为我们必须考虑到一些评估函数需要分类特征,然后这类组件将根据它们对离散化函数的需要分成两类,其中一部分,每个评估函数的主要用途是评估关于该类的特征的重要性。
- **特性选择功能:**这将是一个抽象接口,为最终用户提供对“选择”方法的访问,该方法选择给定数量的特性,并且将由许多子类实现,这取决于您想要用于选择的方法。
我们现在要做的就是从上到下开发我们的架构,并将其与我们的度量联系起来;这给了我下面的架构。
作者图片
可靠性测试
为了评估我们的框架的可靠性,特别是当添加一个新的度量时,我们必须考虑在每次添加一个评估函数时运行一个完整性测试;这个测试必须尽可能的通用,为了做到这一点,我们将采用一个约定,从现在开始每个评估函数类的名字中都必须包含“函数”这个词。
通过这样做,我们可以精心制作一个简单的测试,运行如下:对于它在文件“evaluation_functions.py”中找到的每个评估函数类,它将尝试对随机数据集的特征进行排序,以验证所有的评估函数都编写得很好。
当然,这很简单,只要我们有一种方法来检查脚本并动态实例化包含类的对象,我们可以通过使用 inspect 模块来完成。
from inspect import getmembers, isclass
from sklearn.datasets import make_classification
from core.Feature_Selection import Evaluation_Function
from core.Feature_Selection.Ranking_Function import Ranking_Selection
X,y = make_classification(n_samples=1000, n_features=10, n_classes=2)
for i, j in (getmembers(Evaluation_Function, isclass)):
if("Function" in i and not "CAT" in i):
print("Testing: ",i, end=" ")
EF = j()
R = Ranking_Selection(j())
c = R.fit(X, y)
print("✓")
这几行代码将创建一个包含 10 个特征和 1000 个样本的数据集,get_member 方法将检查 Evaluation_Function 脚本,对于其中每个名称中带有“Function”的类,我们将执行一个排名选择,并在完成后打印一个勾号。
使用的措施
使用框架的主要优势是它的广泛性,但是现在,我链接了以下函数;我不会深入每项措施的细节;我将只精确地描述他们的类以及他们如何评估特性:
- 皮尔逊相关系数 (来自 NumPy)是一种距离测度,可以通过计算两个变量的协方差之比来得到。
- 基于信号的相关性 (来自 NumPy)这是在 NumPy 中实现的另一种相关性度量。
- 互信息 (来自 Scikit-learn)这是一种信息度量,通过测量类中熵的减少来评估属性,如果我们相对于他的值分割它。
- Chi2 独立性检验 (来自 Scikit-learn)两个变量是独立的如果P(X = X;Y=y) = P(X=x)。P(Y=y) ,通过对属性和类之间的假设进行 Chi2 检验,我们可以量化它的重要性。
- 分类度量:作为一种分类度量,为了评估每个属性,我用局限于这个特定属性的数据集训练了一个分类器,然后测量它的准确性;因为分类器是作为一个参数给出的,所以我用决策树分类器尝试了这个方法,然后我还添加了一个逻辑回归分类器。
请记住,这篇博客的重点不是实现这些方法,所以我采取了已经实现的质量措施。
特性试验
每当我们实现一个新的评估功能时,我们不仅仅关心它是否符合框架。我们也要评估它的效率;
所以在完整性测试之后,我们将设计两个简单的性能测试;第一项测试包括以下内容:
- 我们创建一个虚拟数据集,其中包含 k 个相关特征。
- 我们用整个数据集训练一个分类器,并评估它的准确性。
- 对于每个函数,我们选择 k 个特征,用局限于所选特征的数据集训练分类器,并用 k 倍验证评估分类器的准确性。
第二个非常相似,但我们不是生成完全随机的数据集,而是获取 iris 数据集,并向其中添加随机采样的列。
每个测试做 10 次,并且测量每个评估函数的时间。
对于具有 20 个属性和仅 5 个信息属性的第一个测试,我们在 SVM 分类器上获得了以下结果:
base : 0.8974500000000001 Time: 0.0
CHI2_Function : 0.52885 Time: 0.017551565170288087
CorrelationSP_Function : 0.7693999999999999 Time: 0.00019888877868652345
Correlation_Function : 0.8606 Time: 0.0020094394683837892
DTClassification_Function : 0.6241 Time: 0.09251418113708496
MI_Function : 0.89475 Time: 0.1389768123626709
基数表示通过保留所有属性获得的精度。我们可以注意到,通过减少 80%的属性数量,我们保持了几乎相同的互信息性能;我们还注意到 CHI2 函数几乎没有用,但这可能是因为它被我使用的简单二进制化改变了,它只是简单地将数据范围划分为等间距的间隔。
让我们考虑另一个具有完全随机数据集的示例,这次我们将采用 200 个特征(仅 2000 个样本)和 50 个信息性特征,我们获得以下结果:
base : 0.7943999999999999 Time: 0.0
CHI2_Function : 0.46049999999999996 Time: 0.171110200881958
Correlation_Function : 0.8112499999999998 Time: 0.019919610023498534
DTClassification_Function : 0.60955 Time: 0.9978075504302979
MI_Function : 0.8505000000000001 Time: 1.4385223627090453
同样,我们可以看到互信息保留了非常相关的属性,以至于它甚至击败了所有变量的分类。
现在让我们看看第二个测试,
base : 0.9086666666666667 Time: 0.0
CHI2_Function : 0.946 Time: 0.01797773838043213
CorrelationSP_Function : 0.9740000000000001 Time: 0.00014123916625976562
Correlation_Function : 0.9693333333333334 Time: 0.0030328035354614258
DTClassification_Function : 0.3539999999999999 Time: 0.020097732543945312
MI_Function : 0.9493333333333334 Time: 0.091739821434021
这一次,作为分类度量一部分的所有度量都比基本度量表现得更好,这证实了排名度量的效率与数据集的结构密切相关。
比较排名方法的更可靠的方法
因为排序方法的主要优点是它们不耗费时间,所以我们可以生成排序,然后评估通过从排序的顶部到底部连续添加特征而获得的子集。
我们通过使用 Seaborn 和添加了无用列的数据集 IRIS 获得了下面的图。
作者图片
这证实了:
- 决策树分类不是此数据集的有效分级方法。
- 有用特征的数量似乎是 4,因为所有的排序方法对于大约 4 个特征给出了它们更高的性能。
结论:
因为一个排序方法并不(通常)耗费时间,如果我们有一个可靠的框架,我们可以使用许多排序方法来更好地洞察我们的特性质量。
这个框架还允许我们尝试新的评估功能或新的选择机制,我鼓励你通过分叉我的 GitHub repo 来这样做。
开放式问题:
这个框架提出了一个新的问题:我们能利用我们有许多特性排名的事实吗?我对答案有一点想法;保持联系,早日发现:)
如果你想讨论这个话题,欢迎通过邮件(ouaguenouni.hachemi@gmail.com 或 LinkedIn 加入我的讨论。
文本的可控生成:综述
原文:https://towardsdatascience.com/towards-controlled-generation-of-text-a-summary-7f4c954c1fad?source=collection_archive---------9-----------------------
对研究论文的通俗易懂的解释
斯科特·格雷厄姆在 Unsplash 上拍照
在这篇文章中,我将总结一篇在自然语言处理领域有影响力的论文,《走向文本的受控生成》[1]。这篇论文于 2017 年在 ICML 会议上发表,在撰写本文时被引用了 800 多次。
先决条件 —神经网络、自动编码器、变分自动编码器(VAE)。
目标— 本文的目标是生成逼真的句子,句子的属性是可以控制的。一个例子是生成具有积极/快乐情绪的句子。我们不仅要生成语法正确、逼真的句子,还要根据某些属性(用户自定义)来控制生成的句子。例如——情绪、时态等。).本文提出了实现这一目标的模型和训练过程,以及在训练模型时应对离散文本数据的不可微性的思想。
实现受控文本生成背后的关键思想是学习输入文本的一个复杂的潜在表示。该模型有一个自动编码器/变分自动编码器(VAE ),它从输入的低维表示(通常称为潜在代码)重建输入句子。通常,VAE[3]优于普通的自动编码器,因为潜在表示是*滑的、连续的,并且在 VAE 的情况下可以被采样。
解开潜在表征意味着将所学习的潜在表征分成不同的成分,其中潜在表征的每个成分存储关于特定属性的信息,并且可以用于在重构的句子中控制该属性。主要的挑战是设计一个模型和训练机制,可以有效地学习一个解开的潜在表征。如果潜在代码被解开,对潜在代码的某些组成部分的修改会导致所生成的句子的某种改变,从而给我们提供受控的文本生成能力。
关于文本生成和受控文本生成的历史详情,请参考原始论文[1]或其他调查文章[4]的相关工作(https://github.com/ChenChengKuan/awesome-text-generation)。在这篇文章中,我将把重点放在模型和它的细节上,以及上面提到的问题是如何解决的。
在下一节中,让我们更详细地讨论这个模型。下图是该模型的示意图。
受控文本生成模型[1]。来源链接
该模型由编码器和生成器组成。编码器和发生器与自动编码器/VAE 架构完全相同。生成器在重构输入句子时充当解码器,但也用于生成最终的输出句子,因此被称为生成器。
自动编码器/VAE 的潜在代码是非结构化的。潜在代码可以被采样(在 VAE 的情况下),并且生成器采用这个采样的潜在代码来生成新的句子。然而,生成的句子的属性在正常的 VAE 中不能被控制。
在该模型中,潜在代码被分成两个部分 z 和 c。从概念上讲,部分“z”具有非结构化属性,而“c”对用于控制生成的句子的结构化属性进行编码。句子可以由一个以上的因素控制,因此 c 可以有多个部分 c1、c2、..等等。例如用于生成受情绪和时态控制的句子。c1 将控制情感属性,c2 将控制时态属性。理论上,可以添加多个属性,但是随着受控属性数量的增加,训练可能会变得更加复杂和困难。
此外,还有歧视。鉴别器是帮助学习解开的潜在表示和编码潜在代码的结构化组件 c 中的特定属性的主要网络。鉴别器发送信号并引导发生器产生与输入码 c 一致的句子。
现在,我们已经有了模型和组件的高级细节,让我们深入到训练和损失函数的细节,这有助于完成解开。
训练被分成——发电机学习,在其上学习发电机参数的损失函数;和鉴别器学习,鉴别器参数学习的损失函数。
发电机学习
本部分描述了发电机培训的组成部分。
**下面显示的等式 1,**是标准的 VAE 损失,其目标是生成逼真的句子。KL 损失迫使来自编码器的学习到的潜在代码(q_E(z|x)接*先前的 p(z)(其通常是高斯分布)。第二个组成部分是重建损失,它迫使生成器生成从输入数据集学习到的似是而非的英语文本。
等式 1。来源链接
**方程式二。**从生成器生成的句子(实际上是离散句子的*似的软生成句子)被传递到鉴别器,该鉴别器试图从生成的句子中预测代码。来自鉴别器的预测码被用作训练发生器参数的信号。
G~_T(z,c) —使用软生成语句代替离散语句来解决可微性问题。该*似是基于稍后描述的 softmax *似来完成的。
具体来说,我们假设生成器网络用来生成一个句子的输入潜码是 c1。鉴别器获取生成的句子,并预测该句子是使用代码 c2 生成的。如果生成器信任鉴别器的决定,生成器现在会尝试修改为输入代码 c1 生成的句子,以便鉴别器预测偏向 c1。因此,生成器利用鉴别器预测来修改其生成的句子,使得用于生成句子的输入代码和句子的鉴别器预测相同。下面所示的等式是体现这一思想的损失函数。q_d(c|G~T(z,c)是鉴别器预测,用于训练发电机参数θ G。
等式 2。来源链接
用于训练发生器参数的学习信号通过鉴别器反向传播到发生器。但是,这里有一个重大拦路虎。生成器输出是一个文本,它是一个离散输出。因此,反向传播是不可能的,因为离散文本是不可微的。
解——代替离散输出,使用 logit 向量的 softmax 输出,如下式所示,其值由温度变量控制。这就是所谓的软生成句子,作为输入传递给鉴别器。
文本的非离散*似
**方程式 3。**使用等式 2,我们强制将生成的句子的某些属性(例如,情感)编码在潜在代码‘c’中。然而,这还不够,因为潜在代码“c”可能会在不经意间将一些其他属性与所需属性一起编码。如果例如,潜在代码 c 编码了情绪(期望)的属性,偶然编码了时态的属性。现在,如果我们修改潜在代码 c 的值,我们期望在所有其他属性不变的情况下,生成的句子具有不同的情感。但是,我们可能会看到新句子有不同的时态和不同的情绪。**这是我们应该避免的事情。**要做到这一点,我们需要强制除可控属性之外的所有其他属性都编码在潜在代码‘z’中。
不是为该任务设计新的鉴别器,而是重用编码器以将生成的句子作为输入,并预测非结构化潜在代码 z。这迫使生成器捕捉潜在代码 z 中的非结构化属性,从而也迫使潜在代码 c 不具有任何与之纠缠的非结构化属性。
等式 3。来源链接
发电机整体学习— 然后,根据等式 4 中的以下损失函数训练发电机,等式 4 基本上是上述 3 个等式的组合。所以总体来说,生成器应该能够生成似是而非的英语句子(等式 1),其属性可以由潜在代码 c 控制(等式 2),非结构化属性取决于潜在代码 z(等式 3)。
等式 4。来源链接
在生成器学习中,我们看到生成器生成与特定属性一致的句子的准确性,取决于来自鉴别器的信号。生成器相信鉴别器会给出正确的信息,告诉它所生成的句子是否具有所需的属性。因此,正确训练鉴别器以使其预测正确是很重要的。在下一节中,我们将讨论训练鉴别器的方法。
鉴别器学习
鉴别器能够正确地推断句子的属性,从而帮助生成器评估其生成具有期望属性的句子的性能,这是至关重要的。
鉴别器以半监督的方式被训练。它首先获取 x_L 和 c_L 的标记示例,并根据等式 5 训练鉴别器参数。
等式 5。来源链接
它还利用了标记代码 c 上的生成器生成的句子,形成了 x^和 c 的数据集,并使用了 Eq。6 在生成器数据集上训练鉴别器。由于生成器生成的数据集有噪声,因此使用最小熵正则化[2],这是等式的第二个组成部分。6.
等式 6。来源链接
结合等式 5 和等式 6,等式 7 示出了总的鉴别器学习函数。
方程式 7。来源链接
训练算法
数据集 —未标记(X=x)和少量已标记(X={x,c})句子的大型数据集。
- 通过最小化等式 1 来初始化基本 VAE(编码器和发生器)。
重复步骤 2 & 3 直到收敛
2.通过等式训练鉴别器。七
3.通过最小化 eq 来训练发电机。4 和编码器通过最小化等式 1
唤醒睡眠程序
唤醒睡眠程序。来源链接
模型的训练过程使用唤醒-睡眠过程,这基本上是在使用训练数据的真实样本训练模型时和在模型的生成样本上训练模型时之间的区别。唤醒过程对应于使用真实训练数据的训练方程。在我们的例子中,它对应于等式 1,其中编码器和发生器在真实数据 x 上被训练。图的左图显示了训练的尾流程序的前向传播(黑色箭头)和梯度传播(红色虚线箭头)。
睡眠过程对应于使用来自发生器的生成样本的训练方程。在这种情况下,它包括等式 2 和等式 3,其中鉴频器/编码器利用产生的样本分别预测代码 c 和 z,并提供反馈来训练发生器。它还包括等式 6,其中鉴频器根据发生器产生的数据样本进行训练。右图显示了训练睡眠程序的前向传播(黑色箭头)和梯度传播(红色箭头)。
睡眠阶段减少了对监督和大量标记训练数据的需要。
结论
我希望这个解释有助于对论文的直观理解。在接下来的文章中,我将解释本文关键部分的实现,并查看实验结果。这是我的文章总结了论文[为非*行文本风格转换解开表征学习](http://Disentangled Representation Learning for Non-Parallel Text Style Transfer)【5】。
参考文献
[1]胡智庭,杨子超,,梁,鲁斯兰·萨拉赫蒂诺夫,和埃里克·p·兴。2017.文本的可控生成。《第 34 届机器学习国际会议论文集——第 70 卷》(ICML'17)。JMLR.org,1587-1596 年。
[2] Grandvalet,Yves,Bengio,Yoshua,等.熵最小化半监督学习.NIPS,第 17 卷,第 529–536 页,2004 年。
[3]金玛、迪德里克·p .和马克斯·韦林。"自动编码变分贝叶斯."abs/1312.6114 (2014): n. pag。
https://github.com/ChenChengKuan/awesome-text-generation
[5] Vineet John、Lili Mou、Hareesh Bahuleyan 和 Olga Vechtomova。2018.文本风格转换的非纠缠表征学习。arXiv 预印本 arXiv:1808.04339
与 Dask 和 Pangeo 一起迈向 Azure 环境数字双胞胎
原文:https://towardsdatascience.com/towards-environmental-digital-twins-in-azure-with-dask-and-pangeo-71d35414ec58?source=collection_archive---------25-----------------------
J.A.Neshan Paul 在 Unsplash 上的照片
环境的数字双胞胎可以帮助实现可持续发展目标和解决气候变化相关问题。他们将强烈依赖地理空间数据及其处理和分析。云环境提供了处理潜在的巨大地理空间数据集所需的灵活性和可伸缩性。在这里,我探索了 Azure 云功能,并将它们放在一个更广阔的多云视角中。
环保数码双胞胎
存在许多数字孪生的定义,但一个共同点是物理对象或过程的数字表示。通常,这些对象由数字孪生的用户控制。在环境数字双胞胎中,我将户外环境视为中心“对象”,它不拥有所有者,或者,例如,在土地所有者的情况下,没有人完全控制该对象。至少有三个群体可以从环境数字双胞胎中受益,它们是:
-影响环境的组织
-规划土地使用和基础设施的组织
-运营依赖于环境的组织
云间交互
在另一篇博客文章中,我讨论了当涉及大型地理空间数据集,如卫星数据或模拟大气数据时,我们当前面临的分散数据格局。这种情况将持续很多年,因为我已经说过,没有任何组织能够或愿意托管所有这些数据集。由于数据的规模,将数据从一个环境转移到另一个环境并不总是可行的,因此,我认为云之间的交互是成功的环境数字双胞胎的关键。为了最大限度地减少在云和本地环境之间传输的数据量,应该在传输之前对数据进行处理。在每个云环境中,应该为数据选择、聚合和评分以及针对自己的代码的处理提供处理能力。这篇博文的剩余部分将关注微软 Azure 云环境中的技术映射,它可以促进云间的交互(图 1 中的绿色矩形)。
图一。多云环境中的数字孪生设置,重点是支持云间交互的 Azure 功能——绿色矩形。图的详细解释可以在这里找到(图片由作者提供)
蔚蓝能力
微软的环境可持续发展目标雄心勃勃,只有通过行业、政府、非政府组织和研究人员的合作才能实现。在某些方面,自然互动过程的运作以及与人类和地球系统的互动并没有被很好地理解。只有具备知识和洞察力,人们才能以可操作的洞察力有效应对气候变化。为了方便科学家和研究人员增加这些见解,微软建造了行星计算机。因此,行星计算机将有助于了解我们可以在哪里以及如何最好地减轻人类对环境的影响,以及支持决策者采取气候适应措施。行星计算机由四个主要部件组成,这四个部件也有助于建立环境数字双胞胎,它们是:
-行星计算机数据目录-搜索和查找开放数据集
-行星计算机 API 访问数据和检索数据
- Planetary Computer Hub —用于数据处理,与统一的开发人员环境相结合
-行星计算机应用程序-第三方开放式和封闭式应用程序构建在行星计算机基础架构上
组织可以建立他们的环境数字双胞胎,部分基于行星计算机,完全驻留在 Azure 中,以及所有其他 Azure 服务。在这里,我们将行星计算机的技术映射到环境数字孪生组件,这些组件促进了从 Azure cloud 看到的云间交互,参见图 2。
图二。Azure 中云内交互的技术映射支持云间交互的环境数字双胞胎(图片由作者提供)
开放数据和数据存储
微软已经装载了数 Pb 的数据,并通过行星计算机使它们可用,当前可用的数据集可以在行星计算机数据目录中找到。除其他外,这些数据集包括 Landsat 8、Sentinel-2 以及一个单独的统一的 Landsat-Sentinel2 数据集、Aster 等。所有数据都存储在 Azure blob 上,可以通过 blob 存储 API 直接访问。由于在 blob 存储上查找数据集可能是一个挑战,因此它们通过开放时空资产目录 STAC 规范进行索引和搜索。
除了行星计算机提供的数据之外,数字双胞胎的主人还需要引入他们自己的数据,这些数据在大型数据集的情况下很可能会存储在 blob 中。然而,地理空间矢量数据可以登陆 Azure 管理的数据库(SQL,Postgres,CosmosDB)或 blob,并通过 STAC OGC API-Features 提供。
计算引擎
行星计算机中枢为基于 Dask 集群的研究人员提供便利。Dask 支持在机器或集群上高效地并行化 Python 代码。这些行星计算机集群可以通过 web 客户端启动和访问,它们预装了一个 Pangeo 环境。这使得研究人员能够在一个充满云和地理空间以及 ML Python 库的稳定环境中直接使用地理空间数据集。研究人员通过 JuypterHub 或您的本地 Python 环境与 Dask 集群进行交互。行星计算机中枢使研究人员能够在没有 it 知识的情况下快速启动云基础设施。当需要更大的集群时,Hub 提供开箱即用,或者当 Digital Twin 所有者需要自己的应用程序基础架构时,Dask 集群可以在 Azure 订阅中轻松创建。借助 Dask 云提供商,集群可以在 Azure 和其他云中创建。这也使得能够一次性使用 Pangeo docker 映像,这样集群就预装了 Pangeo 环境,就像行星计算机中枢一样。
统一开发环境
行星计算机基于开源工具,具有开放数据并支持开放标准,使其对研究人员和开发人员来说是可访问的、透明的和灵活的。如果开发人员已经熟悉 Python,则不需要学习新的工具或语言,并且现有的 Python 代码可以被带到 Dask 环境中。Dask 集群可以通过 JupyterHub web 客户端或本地 Python 环境访问。由于这种方法适用于多个公共云提供商,有了 Dask 云提供商,开发人员就有了一个统一的开发环境。
最后一个音符
有些情况下,上面介绍的技术可能不是最佳的,尤其是当不仅需要应用 Python 代码,或者需要特定的作业调度程序时。在 Digital Twin 所有者的 Azure 订阅中,可以使用许多其他选项来促进数据处理和自动化,如 Azure Batch 、 Azure Databricks 和Azure Synapse Analytics Spark Pool、 Azure Kubernetes Services 等。
参考至总体博客文章: 为数字双胞胎设计
这里的意见是我的。
走向人工智能研究的更大目标
原文:https://towardsdatascience.com/towards-greater-purpose-in-ai-research-91218cd108ff?source=collection_archive---------27-----------------------
意见
我对深度学习研究现状的看法以及我将如何改变现状
图片来自 Unsplash(图片由马克·弗莱彻·布朗提供)
最*,我看了这个 TED 演讲:
该视频描述了爱因斯坦在 1905 年对物理学领域的贡献。在 4 篇独立的论文中,他理论化了光的粒子性质、新的原子模型、狭义相对论和世界著名的 E=MC 方程。
这和我有什么关系?嗯,我是一名有抱负的研究人员,已经发表了几篇论文(你可以在这里查看)。作为研究人员,我们都希望和渴望发表惊人的研究,从而彻底改变我们的领域(在爱因斯坦的情况下,改变我们对宇宙的基本理解)。此外,我们甚至都有其他的职业在消耗我们的时间——他是一名专利办事员,我是一名学生。
这个视频提醒了我研究的真正目的:进一步拓展这个领域,并真正以有意义的方式应用研究。不幸的是,我认为,特别是在一般的计算机视觉(CV)研究中,这个目的没有得到足够的重视。连我都为忘记了这个动机而感到内疚。
在这篇文章中,我想阐明我对当前研究状况的一些看法,以及为什么需要改变。然后,我将分享我的一些想法,关于我如何在人工智能研究中朝着更大的目标努力,我相信这是将 CV 应用于相关问题,如农村地区的民主化医疗保健。
我对当前研究状况的看法
直截了当地说,计算机视觉研究过于专注于击败最先进的技术(SOTA)。随着 NeurIPS 公认的论文最*发布,CVPR 截止日期刚刚过去,ICML 截止日期在新的一年即将到来,各种主题的新计算机视觉方法正在涌现,不可避免地,SOTA 的表现正在被打破。
专注于击败 SOTA 的问题在于,它转移了对相关话题的关注。对爱因斯坦来说,没有人能打败 SOTA。他的目标只是更好地了解这个世界,这使得未来的研究人员能够利用他的发现,做出相关的发现,提高人类的生活质量。然而,对于 CV 中的大多数 SOTA 方法,当它们被超越时,很快就被遗忘了。这场竞赛是为了争夺 SOTA,而不是为真正的成像挑战建立最有效和高效的模型,从而改变世界各地人们的生活。
我相信有代码的论文和他们的排行榜有助于延续这一点。排行榜显示了哪些型号在什么时间达到了什么精度或性能。看看 ImageNet 准确度排行榜。
ImageNet 最高准确度排行榜(图片来自代码为的篇论文)
正如我们所见,几个月之内,新车型就占领了 SOTA。如果任何不是这些方法专家的人试图理解它们,他们会很困惑。这些方法优先考虑精度的微小提高,而不是引入可以在实际应用中实际实现的方法。
这已经渗透到了高层会议的审议过程中。声称 SOTA 的方法很容易被接受,但是接* SOTA 的方法却被拒绝。以 FixMatch 为例,它因“过于简单”而被 ICML 拒绝
如果会议优先考虑新颖复杂的方法,而不是更优雅简单的方法,这将使研究远离有用和适用。具有极其复杂的训练过程的方法在最终需要使用它们的 web 或移动应用程序中实现是具有挑战性的。研究界关注的不是最新最棒的——而是最新更准确的,即使这是以更高效的算法为代价。
一般的计算机视觉是难以置信的理论性,这就是为什么我喜欢在医学成像领域工作,新算法的实际应用是重要的,并在审查过程中加以考虑。虽然这个领域也非常关注新颖性,但新颖性也可以存在于所解决的问题中,在我看来,这是一个很好的研究领域。
但不管怎样,回到 CV。另一个问题是研究界的公然剽窃。以这个故事为例:
我建议你看看这条推文,但我会很快总结一下。报纸 MomentumNet 被另一家名为 model m-RevNet 的报纸公然抄袭——多么不同的名字,对吗?在 Twitter、Reddit 和其他论坛上发了一系列帖子后,作者终于坦白了。他的道歉中有一句话很突出:
我非常后悔,因为我在急功*利的时候犯了一个大错
作者受到出版物和引文的驱使。随着他的作品进入 CVPR 和 ICCV,他得到了他想要的。即使在最*的记忆中,这也不是人们被抓到剽窃的唯一案例。
虽然抄袭显然是错误的,但这些抄袭的故事凸显了研究中一个更大的问题。人们因身处 CVPR、奈厄利普斯、ICCV、AAAI 等地而受到尊重,这分散了创作革命作品的主要精力。虽然我们确实会表彰那些做出爱因斯坦式贡献的人,例如何和他对 ResNets 的介绍,但我们也会表彰那些在顶级会议上没有充分动力做出革命性发现或将他们的发现应用于极其重要的应用的人。
这就是出版物的问题。对我来说,一旦我看到我关于谷歌学术的论文,我就兴奋不已。当我得到一些引用时,我感到被认可了。我沉迷于获取 ArXiv 和 Scholar 上的论文,有一小段时间,我看不到研究中什么是重要的。
我的研究远不及爱因斯坦在 1905 年完成的工作。它没有任何潜力做出那种改变,不仅因为我的想法没有革命性,而且因为我没有制作这种革命性作品的意图。目的是在某项任务中对当前的方法进行改进,但这项任务并不是非常有意义。
发表研究背后的意图是这个问题的主要原因。最糟糕的是,新的研究人员立即被吸引到代码排行榜的论文榜首,而不是专注于如何将他们的研究真正应用到有意义的问题上。我们专注于 ImageNet 上 top-1 准确率 0.1%的绝对增长,而不是创建一个可以将分类应用于世界农村地区医疗诊断的管道。
为了结束这一部分,我想分享我的一个想法:一旦某个模型在 ImageNet 上获得 99.9%的最高准确率,会发生什么?虽然我们还不一定接*它,但以这种速度,应该有可能很快达到它。但是一旦我们到达这个标记,我们下一步做什么?再也没有任何 SOTA 表演可以宣称了。我们最终会开始应用难以置信的复杂算法来筛查世界农村地区的疾病患者吗?或者,我们会让 ImageNet 的敌对变体成为我们新的基准数据集吗?只有时间能证明,但我希望是前者。
我从事行业研究的计划
如果你关注我的推特(你应该关注),你会注意到我是 DeepMind 的超级粉丝。他们的新作品总是让我着迷,最*的作品是的《思考网》。我甚至在笔记本电脑上贴了一张 DeepMind 的贴纸。
DeepMind 贴纸(图片来自艾萨克·皮尔庞特
所以很明显,我真的希望有一天能在 DeepMind 或者 Google Brain 工作。但对我来说,这似乎不是最好的利用我的时间。虽然我真的相信 DeepMind 是革命性的、对社会有益的开创性研究,如 AlphaFold ,但我可能不会为 AlphaFold 这样的工作做出贡献,而是致力于像 PonderNet 这样的项目。对我来说,这不是最好的利用我的时间。我想解决世界上最大的挑战,其中两个是获得医疗保健和减轻贫困,而在 DeepMind 工作根本不允许我这样做。
虽然我会谈到我希望如何在我的职业生涯中使用研究,但我想谈谈我将如何实现在 DeepMind 工作的梦想。我目前的长期职业目标是创办自己的公司,等我大学毕业后,我可以把它卖掉换钱。因此,虽然获得博士学位可以成为这个计划的一部分,但在 DeepMind 工作却不行。
由于我一直梦想着在 DeepMind 工作,我将在今年年底申请一份工作。虽然所有的工作和实习清单都要求至少同时注册一个博士项目,但我想我还是会申请的。没什么坏处,对吧?如果我得到的回应能让我得到一份实际的实习/工作机会,我会欣喜若狂。我的希望会实现,但我可能只会做兼职,这样我就可以专注于大学。虽然这不是我最初想象的,但也足以让我满意了。
如果我得不到回应,这很有可能,我会继续前进,把这个梦想抛在脑后。有更大的事情要做,不幸的是,对我来说,在 DeepMind 工作不是其中的一部分。
我将做什么研究
正如本文前面所讨论的,我不太喜欢人们成为研究者的一些潜在动机。虽然我可以理解他们为什么有这样的动机,因为这最终是一份工作,人们需要养活自己,但我希望我能做些更大的事情。
这里有一个故事确实引起了我的共鸣。去年的某个时候,我联系了孟加拉国领先的研究机构 BRAC 大学公共卫生学院。我要求对我用于糖尿病视网膜病变(DR)筛查的人工智能算法进行验证研究。巧合的是,他们最*正在与谷歌研究人员团队合作一个跨国项目,以建立一个用于 DR 诊断的自动化管道。我不知道任何关于谷歌项目或进行该项目的团队的细节,但不幸的是,他们结束了这个项目。这使得 BRAC 团队陷入混乱,并且在这个过程中有大量未标记的数据。
这个故事一直困扰着我,因为我觉得研究的目的已经失去了。通过阅读爱因斯坦和其他著名科学家的故事,我总是被告知他们的目标是让世界变得更好。但是听说这个项目被终止了,这个项目本可以让孟加拉国的许多病人获得改变生活的诊断,我对研究的想法被改变了。如果他们作为研究人员的目标是改变世界,他们为什么要离开?
不幸的是,他们的目标不是改变世界。最终,他们是一个万亿美元的公司,必须赚钱,如果项目进展太慢,他们就没有理由留下来。
我想改变这一点。如果有一天我真的在谷歌这样的研究机构工作,我会尽我所能鼓励社会导向。专注于创造可以尽快帮助人们的研究,而不是简单地试图打破 CIFAR-10 的最新 SOTA(它将不可避免地在几个月内被打破),这更符合我的胃口。
我想建立一个医疗成像研究创业公司,为孟加拉国的各种疾病提供免费诊断。因为孟加拉是我的祖国,我和这个社区有着各种各样的联系,所以它是我工作的完美地方。有了一个博士研究员和工程师团队,我将能够建立通用模型和廉价硬件,有效地为孟加拉国农村地区提供医疗筛查。
虽然这个梦想很乐观,但我希望它能成为现实。我是一个大梦想家,尤其是在 17 岁的年纪,但我认为我有决心实现它。但最终,只有时间能证明一切。总有一天我会回到这篇文章。
结束语
这篇文章只是我对简历研究现状的看法。我不能保证我的观点是正确的,因为我不像其他人那样了解最新的社区新闻,但我相信有许多人会同意我的观点。如果你不知道,请告诉我。我很乐意就这个话题展开讨论,并希望集思广益,找到鼓励真正革命性研究的方法。
我给研究界的信息是为你的研究找到一个目标。目的不应该仅仅是打败 SOTA。它应该对最需要帮助的人和社区产生有意义的影响。如果你对应用不感兴趣,那就朝着完全革命性的想法努力,比如 AlphaFold 或者爱因斯坦的广义相对论和狭义相对论。但不管怎样,你的研究应该有一个超越自我利益的目的。这样,我们就可以进行真正改变世界的研究。对我来说,我希望,我的贡献可以在一年内全部发生,这样 Ted-Ed 就可以制作一个关于我自己的奇迹年的视频。不太可能,但让我们看看我是否能让它发生。
减少人工智能系统中的歧视
原文:https://towardsdatascience.com/towards-less-discrimination-in-artificial-intelligence-systems-78b8a6e162e5?source=collection_archive---------36-----------------------
公*和偏见
随着 auto-ML *台的兴起,在没有数学知识的情况下设计机器学习系统变得前所未有的容易,但也没有意识到它们可能引发的沉重的伦理问题。然而,在最*的丑闻之后,专家们开始致力于为人工智能带来更多公*,你可以做出贡献。
[作者从谷歌新闻截取的拼贴画]
早在 2020 年 6 月,两位人工智能专家在 Twitter 上展开了一场激烈的辩论:图灵奖获得者、脸书首席人工智能科学家 Yann LeCun,以及研究科学家、“人工智能中的黑人”小组的联合创始人、谷歌 Timnit Gebru 道德人工智能团队的前技术联合负责人。争论的根源是这种脸部去像素化器模型,它可以生成模糊脸部照片的高清图片。一名测试人员在推特上发布了该模型对奥巴马模糊照片的测试结果,看起来该模型倾向于生成白人面孔,即使模糊照片是黑人。
LeCun 回应说,当数据有偏差时,ML 系统就会有偏差,这是因为模型是在大多数白人面孔的数据集上训练的。另一方面,Gebru 回答说,我们不能仅仅减少 ML 对数据集偏差造成的伤害。在今年早些时候她在 FATE/CV 的演讲中,她坚持认为社会和结构问题不能通过简单的数据多样化来解决。事情很快升级,两个阵营都被成千上万的人加入或攻击,从业余爱好者到高调的人工智能研究人员,LeCun 最终道歉,而 Gebru 坚持认为他的反应是一种边缘化模式。由于受到攻击,LeCun 甚至退出了 Twitter。
我们可以从这个故事中学到两件事:
- 好的一面是,这些公*问题正在被越来越多的讨论,我们可以听到伦理专家分享他们在这个问题上的工作;
- 糟糕的是,大多数人不同意——或者不知道——如何在人工智能中实现公*。
在构建 ML/AI 系统时,识别和避免歧视性偏差并不容易。
为什么?因为偏见往往是隐藏的模式,因此难以察觉。例如,预测住房贷款分配的模型可能会因为性别工资差距而偏向男性。根据原始历史数据训练的模型将固有地再现其偏见,坏消息是偏见在社会中根深蒂固,甚至专家也不知道一个无偏见的社会会是什么样子。但是,偏见实际上可能出现在机器学习管道的任何一个步骤中,从数据收集到将结果呈现给用户的方式,通过标记数据,选择性能指标或部署模型。如果您正在构建自己的监督模型,离群值(特征罕见的例子)通常会被错误预测;当数据点是人时,少数民族将是离群值,将遭受缺乏表现。如果您不是自己构建数据集或模型,或者您正在使用公共数据集或预训练的神经网络,则更难跟踪您将使用的数据固有的偏差。此外,没有大量可用的开源数据集,例如文本或人脸数据集,因此没有广泛的多样性。
此外,公*本身是一个复杂的问题,对于普通的数据科学家来说很难理解,尽管他们有良好的意愿,但可能不会很好地理解它。这是一个数据科学家可能面临的两难困境的例子:他应该支持公*的还是*等的公*?每个人(或多或少)都知道法律和它所要求的公正、无障碍和多样性原则。然而,将它们转化为 KPI 和技术规格并不容易。现有的股权指标 不能同时优化,必须在它们之间做出权衡以满足其中一个:没有最优策略。
有时候,*等不足以解决不公*。[转载自罗伯特·伍德·约翰逊基金会 ]
最后一点:人工智能中的伦理问题在人工智能社区中严重缺乏人气。大多数数据科学培训根本没有提到 ML 产生的潜在公*问题。越来越多的 auto-ML 工具出现在市场上,每个人都可以训练和部署人工智能模型,而不知道下面发生了什么以及可能会出错。
这幅全景图听起来可能相当悲观,但是每个人都已经可以采取行动来限制(如果不能防止的话)他们在工作或家庭中建立的 ML 系统中的歧视性偏见。
下面是几个开始行动的解决方案。
首先,与 ML 系统互动的人,从构建它们的数据科学家到使用它们的用户,必须被告知隐藏的歧视性偏见的风险。没有偏见的系统是不存在的,我们只能监控和限制我们意识到的偏见。此外,知道系统在某些方面有偏差,用户可以相应地使用算法结果。
为了避免偏见,我们可能倾向于在数据收集阶段从我们的数据集中排除受保护的变量(性别、年龄、种族……),并且永远不回头。但相反,人们可能希望保留它们,不是为了建模,而是为了分析源数据集的分布和这些变量的模型性能。著名的蒙田研究所称之为主动股票 。通过盲目地从我们的数据集中删除受保护的变量,我们忽略了社会偏见。
如果你知道看什么样的标准,把一个不公*的分类器变成一个更公*的分类器是很容易的。例如,使用基于阈值的分类器(如逻辑回归),可以根据人口子群调整阈值,以支持子群之间的公*性。假设你在一家银行工作,建立一个用于发放贷款的 ML 系统。在这种情况下,我们希望在能够偿还贷款的人中,每个小组中的相同比例的人实际上应该被授予贷款(这个概念被称为机会均等 )。在数据科学术语中,这转化为子组之间相同的真阳性率或召回率,并且很容易选择一个阈值来解决这个约束。相反,我们并不特别希望所有的子群体都获得相同数量的贷款(这一概念被称为人口均等);这将转化为相同的阳性率。
如何使用基于阈值的分类器实现机会均等的直观解释。【作者图片】
尽管有这些工具,但要求数据科学家成为公*专家并重新定义这一概念将会适得其反。其他一些学科花了几十年时间研究什么是公*,什么是不公*,以得出不同的公*定义。通过让计算机科学家与伦理学家、哲学家或社会学家进行对话,我们可以构建促进公*的工具。数据科学家可以通过阅读社会学研究来启动新的 ML 项目,确定收集的数据和要建模的过程中预期的现有偏差。
为了帮助数据科学家处理这些话题,一些组织已经开始制定“道德人工智能”政策,明确定义公*标准和实践,以及专门的治理和团队。这个想法是通过提供工具和度量标准来实施它,从而将它应用到每个数据项目中。实践之一应该总是建立代表多样性的项目团队,并且包括历史上没有特权的群体。这不是最简单的解决方案:例如,截至今天,只有 15%的数据科学家是女性。这种差异的根源可能在于科学教育对女性的偏见。
从更积极的方面来看,ML 研究人员开始认识到伦理在他们工作中的重要性。例如,一些研究人员已经开始研究人脸数据集中广泛存在的数据覆盖问题(这可能是人脸去像素器偏向肤色的原因)。在本文中,作者提出了一种被称为*、*的新模型,该模型在确保提高少数族裔群体覆盖率的同时,实现了具有竞争力的图像质量。这些先进的工作是伟大的,但不应该让你忘记最基本但必要的公*步骤:花时间想一想,在每一个 ML 项目中,是否有可能歧视一群人的偏见。
我希望这篇文章能给你一些提示,告诉你如何开始在你未来的人工智能项目中减少歧视。请随意分享你听说过的解决公*问题的好主意!
消除写作中的性别偏见
原文:https://towardsdatascience.com/towards-removing-gender-bias-in-writing-f1307d0a2b71?source=collection_archive---------21-----------------------
公*和偏见
学习如何理解日常文学消费中的性别偏见,并在自己的写作中避免性别偏见。
照片由桑迪·米勒在 Unsplash 拍摄
为什么会有性别偏见?
我在一个性别偏见普遍存在的文化中长大。作为一名作家,我发现这令人担忧,并试图在我的故事中减轻偏见的影响。我相信解决这个问题始于发现,所以我决定开展一个项目来发现可能的性别偏见。
免责声明
这个项目是我第一次接触数据科学、机器学习和自然语言处理。这是对我一直感兴趣的数据科学领域的探索。因此,重要的是要注意,这个项目是一个概念的证明,而不是一个完美的算法。
方法论
我决定从句子层面来研究性别偏见。另一种选择是审查段落甚至整个文本。如果我发现一个有偏见的单词,我会将整个文本标记为有偏见的。我避开了这种方法,因为我觉得一个单词不一定会使整篇文章有偏见。相反,我觉得更重要的是,更好地理解这个特定单词与其他单词的关系,以及它在产生偏见方面所起的作用。对我来说,做到这一点的唯一方法是使用高水*的粒度和处理句子,而不是大块的文本。
在检查句子时,我想将每个句子分解成单词,并确定每个单词的词性。我需要决定我想要检查的词类,以确定这个句子是否有偏见。我最终选择了主语和宾语,原因如下:宾语是作者联系到性别主语(男人、男孩、女人、女孩等)的东西。).此外,这些词类最有可能成为性别偏见的目标,两者之间的关系通常表明偏见。例如,如果作者把一些老套的东西和主语“女孩”联系起来,比如“护士”或“洋娃娃”,那么很明显这个句子是有偏见的。为此,我选择考察主客体关系。此外,加强我的选择的东西是我的观察,在大多数带有性别刻板印象的句子中,有偏见的关系通常在这两个部分之间。
注意:我检查的句子来自性别*等法律中心的一篇文章[1]。我也用了其中的一些句子来帮助我开发自己的算法。
我使用 Python 库 Spacy 来解构每个句子——因为它是为数不多的为我解析句子的库之一——并加载了一个名为“encore_web_lg”的文件,这允许我将每个句子中的单词分成 Spacy 令牌对象。令牌有许多特性,但我使用的主要特性是:
- token.pos_,用于词性
- token.dep_,表示依存关系或单词与句子中其他单词的关系
- token.text,它给了我单词的字符串形式
- token.lemma_,它给了我这个词的词根形式,例如:token.lemma_ for Women 就是 woman
这是一个句子“女孩应该喜欢洋娃娃”的例子。以空间显示:
图片作者。
使用 Spacy,我创建了两种方法来检查每个句子的宾语和主语。我只在主语是男是女的情况下处理句子,这是通过检查主语的引理和小写形式是否在以下列表中来确定的:
lemma_female=['女孩','女人','女人','女性']
lemma_male=['男孩','男人','男人','男性']
注意:我之所以包括了 women 和 men,尽管它们都不是词根,是因为在某些情况下,Spacy 无法检测到单词形式是 woman,因此它默认为 women。为了解释这个问题,我不得不把女人和男人加入到词条列表中。
以句子“一个女孩喜欢洋娃娃”为例我的方法会给我主体——女孩和客体——洋娃娃。
但是,我意识到那句‘一个女孩喜欢洋娃娃’会是无偏见的,因为没有坚持说一个女孩应该喜欢洋娃娃,不像“一个女孩应该喜欢洋娃娃”这样的句子
因此,为了确保我的方法只查看有偏见的句子,我检查了限定词,比如单词 should。限定词是“改变陈述的绝对、确定或概括程度”的词语[2].我特别检查了必要性和数量限定词,因为它们表明输入句子的用户是否认为男性和女性应该做某事,或者对性别或两者进行概括:
必要性限定词=['必须','应当','应当','必需','必须','必须']
quantity_qualifiers=['all ',' only ',' most']
此外,我检查了单词是否是复数性别术语,因为如果是,用户将对整个性别进行概括,而不仅仅是单个成员。为此,我检查了受试者是否在以下列表中:
plural_form=['女人','男人','女孩','男孩','女性','男性']
如果句子包含一个或多个以上的短语,那么用来寻找主语和宾语的方法就会处理这个文本。
例如,现在用“一个女孩喜欢洋娃娃”这个句子。这个方法不会输出任何东西。而句子“女孩应该喜欢洋娃娃”它会给我主体女孩和客体娃娃。
接下来,我需要找到一种方法来确定被检测的主体和客体之间的关系是否有偏差。因为这个项目是在二进制中进行的,我意识到唯一的方法就是将检测到的关系与异性和对象的关系进行比较。如果这种关系有所不同,那么就有可能存在偏见。
对于项目的这一部分,我决定使用余弦相似度来计算单词之间的相似度,因为这是一种常用的用于比较单词的 NLP 技术。较高的余弦相似性得分意味着单词之间的关系更密切。较低的余弦相似性分数意味着相反的情况:单词具有更远的关系。单词之间的相似性依赖于 Twitter 数据,这些数据有助于根据 Twitter 上的用户使用单词的方式来计算相关性。
对于比较部分,以“一个女孩应该喜欢洋娃娃”为例。首先,我的方法会将主体识别为“女孩”,将对象识别为“玩偶”。然后,我需要将“女孩”、“洋娃娃”(洋娃娃的引理或根版本)与“男孩”、“洋娃娃”进行比较。用余弦相似度,我先找到了‘女孩’和‘娃娃’的相似度,是 0.58。然后我找到了‘男孩’和‘娃娃’的相似度,是 0.48。这些结果意味着“女孩”和“娃娃”以及“男孩”和“娃娃”都是密切相关的。然而,因为“女孩”和“洋娃娃”的分数更高,这两个词之间的关系比“男孩”和“洋娃娃”更密切。从第一个中减去第二个的相似度,我们得到 0.10。这两种关系的显著差异表明“女孩”和“娃娃”之间的关系存在偏见。除了处理像这样只有一个主语和宾语的句子,该算法还可以处理有多个主语和宾语的句子以及共轭句。
基于我从上述工作中得到的差异,我需要确定这种关系是否有偏见。因为关于什么样的差异被认为是有偏差的研究很少,所以我设置了一个大于 0.02 或小于 0.02 的基本度量来进行限定;我在测试了许多有偏见的案例后决定了这个数字——比如“一个女孩应该喜欢洋娃娃。”观察这些分数之间的差异。
按照我的标准,如果差异大于 0.02,就意味着这个句子偏向女性。如果小于 0.02,则偏向男性。如果在两者之间,就没有偏见。
这是光谱的图像:
图片作者。
基于余弦相似度的差异,如果是> . 02,我添加了一个偏向女性的句子计数,如果是
I also checked to see if the subject and object methods did not output anything but still had gendered terms. If so, I did not go through the process above. Instead, using the Python library vaderSentiment, I calculated the compound sentiment score of the sentence, which ranges from -1 (negative sentiment) to 1 (positive sentiment). If the score was less than 0 and had female gendered terms, male gendered terms, or both, I marked it as biased and added them to the respective count. I decided to use sentiment analysis because I wanted to identify general bias and detect bias in sentences where there were no qualifiers.
Lastly, I calculated the percentages of bias in the entire text — biased towards males, biased towards females, biased towards males and females — by dividing each of the counts by the total number of sentences. Then I displayed my output.
I decided to use Streamlit, which allowed me to efficiently create my app, to display my output. I organized the information I received from my work above in a format that Streamlit would accept and outputted it on the screen.
My algorithm extracts text from books, articles, etc. in PDF and Word document form. It first processes the text, then inputs each sentence through my above algorithm, calculates the biased percentages, and displays the sentences with bias as well as which type of bias they had.
演示:
我用来解释我的算法工作方式的句子很简单。我主要使用它,所以我的算法分析很容易理解。相反,下面是我的算法分析一篇更复杂的文章的例子:
这是我网站的主页。用户可以上传 PDF 或 DOCx (Word)文件。可以看出,我选择了分析这篇关于消除女性不应该工作的刻板印象的女性网络文章,并将其上传为 PDF 格式。
作者图片
单击“处理”按钮后,结果如下:
图片作者。
这篇文章似乎主要偏向女性。对男性和两性都没有什么偏见。现在让我们来看几个发现了偏见的句子。
从对女性的偏见开始,这里有一句话:
这一切都是从我们谈论社会上发生的普通事情开始的,不知从哪里,我的朋友说,“女人不应该去工作。”
- 在这个句子中,确定的主语是女性。确定的对象是工作。这句话被标记为有偏见,因为它有一个复数的性别术语——妇女,并有一个必要性修饰语——应该。在比较了‘woman’(women 的引理版本或单词的词根形式)和‘work’(work 的引理版本或其词根形式)的余弦相似度(0.32)和‘man’与‘work’的余弦相似度(0.39)之后,可以清楚地看出,两者之间存在 0.07 的绝对值差异。这使得句子偏向女性。
接下来,这里有一个偏向男性的句子:
大多数男人在结婚前完全依赖他们的母亲,结婚后则依赖他们的妻子。
- 在这个句子中,主语被确定为‘男人’,宾语被确定为‘母亲’。这个句子被标记出来是因为它有一个复数的性别术语——men 和一个数量修饰语——most。这个句子有多个宾语:“妻子”和“母亲”。使用 Python 库 gensim 和来自 Google news vectors 的数据来查找与被识别对象最接*的单词,我发现最接*的单词是‘母亲’。“男人”(男人的词条版本或男人的根形式)和“母亲”(母亲的词条版本或其根形式)的余弦相似度为 0.50,“女人”和“母亲”的余弦相似度为 0.68。绝对值差 0.18,说明两者有差别,意思是句子偏向男性。
最后,这里是唯一一个偏向男性和女性的句子:
女性不能工作的另一个原因是男性的成长方式。
- 在这个句子中,确定的主语是女性和男性。因为两者都是复数,这意味着作者对两性做了某种假设。因为在这种情况下,没有办法比较两种性别,所以算法会自动将句子标记为偏向男性和女性。
我学到了什么:
这个项目教会了我如何使用机器学习来解决文本中的性别偏见等问题。然而,它也向我展示了 ML 是如何同时扩张和限制的。尽管 ML 的范围很广,但有时它不能满足我的算法的需求。因此,我必须找到算法来填补 ML 的空白。
我还学习了许多不同的 Python 库,现在完全理解了如何使用其中的许多库。总的来说,我的数据科学知识库扩展了很多。我从一个完全的初学者到快速适应 Python,学习 NLP,特别是理解 Spacy 的复杂性——用于处理文本和识别词性的 Python 库,以及理解如何在我的工作中使用大型数据集。
潜在的改进领域:
- 截至目前,该项目在性别二元制范围内运作。在未来,我希望将它扩展到解决对非双性恋和跨性别者的偏见。
- 此外,我想强调一下某些职业对某些性别的偏见。例如,从事护理工作的男性或从事计算机科学的女性经常被打上烙印,所以我的目标是找到解决对这些群体的偏见和成见的方法。
- 为了将一个主题与多个对象进行比较,我最初想将该主题与每一个单独的对象进行比较。就像“女孩应该喜欢洋娃娃和卡车”这样的句子来说。,我会比较“女孩”和“洋娃娃”(洋娃娃的引理版本或其根形式)以及“女孩”和“卡车”(卡车的引理版本或其根形式)。但是,如果有两个以上的对象或潜在的更多的主题,这个过程将变得乏味和耗时。然而,我觉得这样做会使我的算法更准确。因此,我想寻找一种有效的方法来做到这一点。
- 最后,我目前正在努力减少加载大文件和显示结果所需的时间。因此,在未来,我希望找到提高算法速度和效率的方法。
如果您有任何问题,请随时通过 LinkedIN 联系我。
感谢您的阅读。我希望你从我的项目中学到了一些东西!
参考文献:
[1] 性别陈规定型观念的例子:性别*等法 (2015 年),性别*等法律中心
[2] 使用限定词 (2005),改变思想
走向深度学习的终点和 AGI 的起点
原文:https://towardsdatascience.com/towards-the-end-of-deep-learning-and-the-beginning-of-agi-d214d222c4cb?source=collection_archive---------1-----------------------
最*的神经科学研究如何指出战胜对立例子和实现更具弹性、一致性和灵活性的人工智能形式的道路
作者哈维尔·Ideami@ideami.com 的绘画
作者哈维尔·Ideami@ideami.com 的绘画
对抗性例子是当今深度学习的一个研究热点。数据中微妙的、往往看不见的变化会推动我们的网络犯下可怕的错误。作为人类,我们似乎对感官输入的这些干扰更有弹性(尽管不是完全免疫)。
在我们的深度学习系统中有一定的模式。他们取得了非凡的成就,但他们有时也很脆弱。就像暴风雨中的一棵僵硬的树,它们看起来很雄伟,但可能会在没有警告的情况下随时开裂。为什么会出现这种情况,我们如何改善这种情况?
来自神经科学领域的新研究开始让事情变得明朗起来。在这篇文章中,我们将探索它。
在他最*出版的书《一千个大脑:智能新理论**》中,我非常喜欢这本书,科学家兼企业家杰夫·霍金斯剖析了他的团队 对我们大脑新皮层的最新研究,大脑新皮层占据了大脑体积的 70%,负责我们的高级智能。(另外 30%被大脑更古老、更原始的部分占据)。**
在一次迷人的旅程中,杰夫·霍金斯带我们深入到我们智力的中心。他认为:
- 大脑皮层中的回路非常复杂。在仅仅一*方毫米中,我们有大约十万个神经元、几十万个连接(突触)和千米长的轴突和树突。****
- 在周围的大脑皮层看起来非常相似。地区之间的差异很小。****
- 新大脑皮层的所有部分似乎都与运动的产生和运动任务相连。在新大脑皮层的每个部分,科学家们都发现了与旧大脑中与运动相关的区域相连接的细胞。****
作者哈维尔·Ideami@ideami.com 的绘画
一个电路来统治他们
****弗农·芒特卡斯尔是美国领先的神经生理学家,约翰·霍普金斯大学神经科学荣誉退休教授。他是大脑皮层柱状结构的发现者。他提出,通过进化,我们的大脑皮层变得更大,基本上是通过一遍又一遍地复制同样的东西,同样的基本回路。
当我在杰夫的书中读到蒙特卡斯尔的想法时,我想起了伟大科学家罗伯特·萨波尔斯基的一次精彩演讲。在回答是什么将我们与黑猩猩区分开来的问题(https://www.youtube.com/watch?v=AzDLkPFjev4)时,萨波尔斯基解释说,黑猩猩和人类之间的基因表达差异约有一半与嗅觉受体的编码基因有关,其他差异与骨盆弓的大小、体毛的数量、免疫系统识别能力、生殖隔离的某些方面等有关;这些和其他因素解释了黑猩猩和人类之间几乎所有的基因差异。那么,与人类大脑相关的基因差异在哪里?Sapolsky 解释说几乎没有任何**,而少数被确认的存在于**基因中,这些基因与胎儿大脑发育过程中细胞分裂的次数有关。基本上,我们的神经元比黑猩猩多 3 倍。这种比例上的差异似乎是我们高级智能的关键。****
这非常符合 Mountcastle 的单回路被复制许多许多次的想法(体积很重要,但体积足以将今天的深度学习系统推向 AGI 吗?下面我们继续探索)。
作者哈维尔·Ideami@ideami.com 的绘画
我们大脑皮层的所有部分都基于相似的原理在相同的基本回路上工作,这符合我们的大脑在不同场景中表现出的灵活性。如果体积很重要,这是否意味着 GPT-11 可能会让我们更接* AGI ?
可惜,没那么简单。因为房间里有一头巨大的大象,杰夫在他的书和理论中解释了这一点。一个我们已经忽略太久的问题。
150000 列
在我们去拜访房间里的大象之前,让我们建立一下背景。根据科学家的说法,我们的新大脑皮层中大约有 150000 个皮质柱。杰夫告诉我们,我们可以把这些柱子想象成细面条。所以,想象一下 150000 根细意大利面紧挨着。那是你的新大脑皮层打个比方。****
作者哈维尔·Ideami@ideami.com 的绘画
作者哈维尔·Ideami@ideami.com 的绘画
作者哈维尔·Ideami@ideami.com 的绘画
这些皮层柱内发生了什么?在过去的几年里,科学家们逐渐认识到大脑是一台预测机器。它产生一个世界模型并不断预测接下来会发生什么**。**
当我们大脑的预测不正确时,我们意识到有些事情不对劲,我们的大脑更新了它的世界模型。随着时间的推移,我们的世界模型变得更加丰富和复杂。
所以在某种程度上,我们确实生活在模拟环境中。因为我们所感知的实际上是大脑构建的模型,而不是外面的“现实”。这解释了幻肢和其他类似的场景。
杰夫·霍金斯指出我们的大脑通过注意当我们移动(或当那些输入移动)时它接收到的输入是如何变化的来学习世界的模型**。这就把我们带到了房间里的大象。**
明摆着的难题
世界在不断变化。万物皆动。有道理的是随着事物的移动和变化,我们的大脑不断更新我们的世界模型(我们很快就会看到我们的许多许多模型)。
正如注意力机制*年来彻底改变了深度学习领域**,注意力也是我们大脑如何学习这些模型的关键。**
但是,如果我们的新大脑皮层不断地做出大量的预测**,并且适应它的模型和它感知到的东西之间的任何偏差,为什么我们没有注意到所有那些预测,而是感知到一个连续的现实?让我们一步一步来。**
作者哈维尔·Ideami@ideami.com 的绘画
通过他们的最新研究,杰夫和他的团队获得了一些有趣的见解:
- 我们的每一个皮质柱(大约 150000)都在学习世界的模型,学习物体的模型,学习概念的模型,学习任何你能想象到的模型。就像我们的老大脑有 位置细胞 和 网格细胞 来制作我们周围环境的模型一样,他们提出新大脑皮层**,有等价的细胞,允许大脑制作物体、概念等的模型。皮质柱正在使用杰夫称之为的参照系,这就像是多个维度的网格帮助大脑组织任何种类的知识。**
- 杰夫告诉我们,思考是运动的一种形式。当我们在这些参考框架内改变位置 时,思考就会发生。所以你现在在想什么,你现在在想什么,取决于你的皮层柱在不同的参照系中的位置。当你的大脑在这些结构中导航时,你的思想也在不断进化。****
注意到运动的概念开始到处出现。运动和系统的动态本质是房间里的大象。我们将很快讨论这与对立例子的问题以及今天的深度学习中发生的许多事情的局限性有什么联系。
所以,它是关于参考框架或 T42 地图,物理空间的地图,概念的地图,任何东西的地图。杰夫告诉我们,就像旧大脑中的参照系是学习不同环境的地图一样,新大脑皮层中的参照系是学习物体的地图(在他们称之为" 什么"*列的情况下),或者身体周围的空间(在" where" 列)或者概念的地图***
我喜欢 Jeff 使用的关于如何成为任何领域的专家的类比,我们需要找到一个好的方法来组织我们关于该领域的知识**,我们需要在内部创建一个该领域的伟大参考框架或地图。想想看,为了在各自的专业领域出类拔萃,列奥纳多·达·芬奇或爱因斯坦所拥有的深刻而复杂的参照系。**
好吧,那么我们 15 万个皮层列中的每一个都在学习一个世界的预测模型**,因为它关注输入如何随着时间的推移而变化。并且这些列中的每一列 学习大量元素、对象、概念等的模型。**
作者哈维尔·Ideami@ideami.com 的绘画
因此,我们对任何事物、物体或概念的知识分布在成千上万个皮层柱中,成千上万个互补模型中。这就关系到杰夫理论** ( 一千个大脑)的名字。**
所有这些都与我们大脑的灵活性有关。我们的新大脑皮层并不依赖于单个列**。知识分布在成千上万的人身上。因此,即使受伤损坏了一组柱子,大脑也能继续工作(在学术文献中有很多这方面的例子)。**
接下来要考虑的是:如果每次运动发生时,大脑都在创造新的预测,这些预测储存在哪里?
杰夫和他的团队提出,神经元中不同树突上出现的尖峰是预测**(树突是神经元中的分支,通过它们的突触接收输入)。树突尖峰将与之相连的细胞置于中,杰夫称之为一种预测状态。因此,预测发生在神经元内部。这些预测改变了神经元的电属性并使其比其他情况下更早点火,但是预测并没有通过轴突发送到其他神经元,这解释了为什么我们没有意识到它们中的大多数。现在的问题是:我们如何确定一个特定的预测?**
作者哈维尔·Ideami@ideami.com 的绘画
投票一致
我们对现实的感知是投票过程的结果。不同的皮层列通过投票达成共识,这就是产生单一感知的原因,它统一了来自系统不同部分的不同预测(这也可能与多种类型的感官输入有关)。****
只有一些细胞需要投票,代表例如我们正在感知的特定物体的细胞。他们如何投票?****
我们皮层柱中的大多数连接是上下 新皮层的不同层。但是也有例外**。科学家发现,有些细胞通过新大脑皮层将轴突(输出连接)从一边发送到另一边。杰夫和他的团队认为这些远距离连接的细胞是负责投票的细胞。**
作者哈维尔·Ideami@ideami.com 的绘画
当我们认出一个物体时,我们的皮质柱已经达成共识。我们每一列中的投票细胞**(神经元)形成一个稳定的模式,代表那个物体以及物体相对于我们的位置。**
并且只要我们继续感知同一个物体,那些投票神经元的状态不会改变而我们继续与那个元素互动。当我们移动或物体移动时,其他神经元将改变它们的状态,但是投票神经元将保持稳定**。**
作者哈维尔·Ideami@ideami.com 的绘画
****这就是为什么我们的感知是稳定的并且我们没有意识到与正在发生的移动预测相关的一连串活动。我们只是知道最终的稳定模式,这些模式来自投票的细胞达成的共识。
因此:
- 运动是我们大脑感知世界的关键。正是由于运动(我们自己的或我们周围世界的运动),我们的大脑可以丰富其内部的物体和概念模型(运动不一定是物理的,它可以是虚拟的,等等)。
- 使用单一原则来处理各种输入并为我们与之互动的每个元素创建数千个预测和模型,使得这些模型丰富多样。****
- 通过投票达成的共识机制意味着我们对世界的感知是稳定的同时是灵活的、有弹性的。****
是时候回到对立的例子和深度学习领域的地位了。
如何打败对立的例子
**人类****也不能对对抗性的例子免疫。我们感官输入的扰动会使我们困惑,并使我们错误地解释事物。我们大多数人都经历过各种各样的视错觉。然而,总的来说,**我们的感知是一致的,而且相当有弹性,而且肯定比我们在今天的深度学习系统中发现的更加一致,在深度学习系统中,看不见的变化可以完全破坏我们的结果。
这种弹性、一致性和灵活性背后的原因是什么?不管它是什么,它可能包括以下一些内容:
- 由我们的皮质柱创建的模型是基于运动和参考框架的创建。当我们四处移动或世界在我们周围移动时,我们的大脑会为每个物体或概念创建成千上万个预测和模型。这提供了灵活性**。我们不会把所有的鸡蛋放在一个篮子里。就像我们在深度学习中使用集成一样,我们在这个问题上赌上了成千上万个角度,而不是一个。**
- 我们的认知基于多模态和稳定的投票动态。与特定对象(或概念等)相关的不同模型正在使用多种预测,这些预测通常连接到不同的感官模态 ( 视觉、触觉、听觉、手势、等)。在负责最终表示的单元之间进行投票会产生对变化具有弹性的稳定模式。对象或环境中的最小变化不会使稳定的投票模式脱轨,因为这种模式是基于成千上万个独立预测的组合,而这些预测又是基于许多不同角度、视角以及通常不同的感官形态的组合。就像集合经常在 Kaggle 比赛中获胜一样,它也是大脑中正在发生的一种集合,使我们的人类感知稳定、有弹性和灵活(当然是相对而言,但与当前的深度学习系统相比尤其如此)。
因此,深度学习中对立例子的“终结”,我说的“终结”并不是指绝对的终结,只是达到类似于我们作为人类所拥有的的弹性、一致性和灵活性的水*,将有可能结合:
- 运动:物理的还是虚拟的。深度学习系统需要能够通过丰富它们的内部模型来收集对世界的不同观点和角度,因为它们在移动或世界在它们周围移动。机器人技术和人工智能将不得不进一步融合。除了机器人学,运动也可以是虚拟的,所以这个原理超越了物理。
- 模型集合:我们必须超越单一的表象或模型。为了对对立的例子和其他挑战具有弹性,深度学习需要生成大量的预测和模型,并不断更新。投票机制然后可以创建稳定的模式和表示,这将对敌对的干扰更有弹性。
- 持续学习:外面的世界不会等待。以上的一个结果是学习需要持续不断。 深度学习系统如今太静态。持续学习是一个活跃的研究领域,它的重要性只会越来越大。
- 我们可以从 Jeff Hawkins 在他的书和理论中描述的参考框架中找到很多关于如何建立我们的表示和模型的灵感。正如 Jeff 指出的那样,像 Geoffrey Hinton 这样的深度学习领导者已经努力了很长时间,试图让深度学习模型更加灵活(见胶囊网络)。但是前面还有很长的路要走,而且越来越清楚的是,最新的神经科学研究正在用新的线索强化这个方向;我们的大脑比我们的深度学习模型更加灵活和有弹性,现在我们开始明白为什么了。
研究检测对立例子的新方法是一个有很多学术活动的有趣领域。现在缺少的是重新思考我们的深度学习架构和系统到从当前的静态范式 过渡到基于多模态、多模型、基于共识的预测系统的动态范式,该系统具有弹性、一致性和灵活性。当我们到达那一点时,我们将能够隐藏或扰乱我们系统的部分,并且仍然维持稳定的预测。
正如杰夫指出的,随着我们试图将人工智能系统应用到需要大量灵活性和弹性的场景中,这一点将变得越来越重要。
Mountcastle 的想法,Sapolsky 的想法以及我们对 GPT 建筑的迷恋,所有这些都表明了体积的重要性。 体积要紧。拥有 3 倍多的神经元,或者数千份相同的基本电路,或者数千亿个参数而不是 10 亿个**,所有这些都很重要。**
对于深度学习领域的现状来说,这是一个好消息。有了像 GPT 系统**、这样的项目,我们发现并确认了这样一个事实,即体积很重要**。
但是,我们也开始意识到,尽管数量很重要,但而不是足够带我们去我们想去的地方。
如果你在一系列播客和场合中跟踪关于像 GPT-3 这样的系统的最新对话,比如说在 机器学习街头谈话 播客中,你会听到类似的结论。 **GPT-3 令人印象深刻,但它也有点脆弱,让人感觉像个黑客。**这与人类大脑的弹性和灵活性无关。
体积很重要。但运动也是。我们不能仅仅通过纯粹的体积来逃避运动和变化。这个世界就像一场永不停息的风暴。
我们是静止的树,那棵变得越来越大但是一次又一次地折断,因为没有能力随着风暴移动。
思考就是运动。在参考坐标系中移动。通过共识机制统一的数千个预测和模型的运动。
前进的道路是通过运动。
后记 :佩德罗·多明戈斯在他的书**《大师算法》** 中写了与深度学习有关的不同范式:象征主义者、连接主义者、进化论者、贝叶斯主义者和类比主义者。很明显,通往 AGI 的道路可能有许多不同的路线和方法组合。关于杰夫和他的团队的工作和理论,正如肯尼斯·斯坦利教授所说的,我遵循着一个有趣的梯度(关于杰夫的工作,这个梯度的幅度相当大)。我觉得杰夫的理论和工作(以及他所有才华横溢的团队)可能包含非常有趣和有用的垫脚石,可以让我们更接* AGI** (或者至少他们的研究可以为我们指出这些垫脚石)。所以,是的,我们可以通过许多不同的方式到达 AGI,但是到目前为止,我们所知道的唯一有足够弹性和灵活性的智能系统是我们肩膀上的那个。因此,深入探索来自神经科学的最新研究可能会为我们指明通往 AGI 之路的有用垫脚石,这的确很有意义。**
如果你想深入探索激发我们深度学习人工智能系统的实体之谜,并使你的想法成为可能,请查看下面的相关文章。
作者哈维尔·Ideami@ideami.com 的绘画
理解格罗弗的搜索算法
原文:https://towardsdatascience.com/towards-understanding-grovers-search-algorithm-2cdc4e885660?source=collection_archive---------23-----------------------
电路恒等式的重要性
本帖是本书的一部分: 用 Python 动手做量子机器学习 。
格罗弗的搜索算法是第一个也是最突出的例子之一,展示了量子电路如何比经典算法快几个数量级。
在之前的文章中,我们建立了算法如何工作的概念理解。它遵循一个简单的程序。量子预言反转了被搜索状态的振幅。然后,扩散器翻转关于*均振幅的所有状态,因此,放大被搜索的状态。
作者弗兰克·齐克特的图片
建立一些直觉是一回事。将这种直觉转化为工作的量子电路是一个完全不同的故事。事实上,在量子电路中实现反射需要我们扩展思维。
第一阶段的思维不是用量子比特来思考,而是用状态来思考。当然,量子位是我们工作的计算单位。当然,多量子位系统的可能状态取决于我们使用的量子位。当然,量子系统的重要视觉化,例如布洛赫球,是建立在量子位元上。
但是我们也必须记住量子位元的一个重要特性。我们可以纠缠量子位。而且我们再也不能用两个分离的量子比特来代表两个纠缠的量子比特了。两个纠缠的量子位共享它们的状态。我们无法在没有另一个的情况下代表一个,因为如果我们测量其中一个量子位元,另一个的状态也会不可避免地改变。
此外,量子计算的强大之处在于,量子位不仅可以形成状态,而且我们可以同时处理它们的状态。因此,我们需要用状态来思考,而不是用量子位来思考。
先说格罗弗算法最简单的情况。我们有一个单量子位——两种可能的状态,开和关,|1⟩和|0⟩.
格罗弗算法的第一步总是一样的。我们将所有的量子位元放入相等的叠加态,让每个状态都有相同的振幅,因此也就有相同的测量机率。我们通过哈达玛之门实现这一目标。
现在,两个可能的状态,|0⟩和|1⟩,都有 0.5 的概率。
作者弗兰克·齐克特的图片
此外,两个状态共享相同的相位。
作者弗兰克·齐克特的图片
假设状态|1⟩描绘了我们想要找到的有利状态。然后,预言机由 z 门组成,当相应的量子位处于|1⟩.状态时,z 门切换振幅
作者弗兰克·齐克特的图片
结果,我们看到|1⟩.态的振幅发生了变化量子位现在处于|−⟩.状态它的两个国家|0⟩和|1⟩现在处于两个不同的阶段。
作者弗兰克·齐克特的图片
换句话说,我们把状态|1⟩的振幅从正翻转到负。
作者弗兰克·齐克特的图片
两种状态的测量概率仍为 0.5。扩散器的任务是放大振幅以有利于被搜索的状态。
作者弗兰克·齐克特的图片
单量子位元电路中的扩散器相当简单。这是另一个 H 门。
作者弗兰克·齐克特的图片
这个电路以绝对确定性产生|1⟩状态。
作者弗兰克·齐克特的图片
我们的量子位最终处于我们想要的状态|1⟩,因为哈达玛门把|−⟩状态变成了|1⟩.状态下图描述了我们在该电路中应用的旋转。
作者弗兰克·齐克特的图片
我们在量子位上应用了一个重要的序列,HZH 电路。这个电路被称为非门(x 门)的标识,它将|0⟩状态转换为|1⟩状态,反之亦然。
下面的等式证明了这个恒等式。
那么,我们为什么要使用 HZH 序列呢?如果它类似于非门,我们为什么不用它来代替呢?
简单来说,HZH-sequence 更灵活。这是格罗弗搜索算法的最简单形式。它从所有状态都相等开始(第一个 H 门)。它应用了一个神谕(Z 门)。它使用一个扩散器来放大所选状态|1⟩(第二个 h 门)的幅度。
为了证明这种灵活性,假设我们想选择|0⟩。这是先知的任务。起始状态和扩散器保持不变。|0⟩的神谕是 I-gate。或者,干脆什么都不做。
作者弗兰克·齐克特的图片
这个电路导致|0⟩状态,我们绝对确定地测量为 0。
作者弗兰克·齐克特的图片
仔细观察,我们可以很容易地发现这个电路根本不起作用。I-gate 什么也不做,Hadamard-gate 恢复正常。因此,我们最终处于默认的初始化状态|0⟩.
结论
虽然我们可以更简洁地重写这两个电路,但电路恒等式 HZH=X 和 HIH=I 让我们使用 Grover 算法的一般结构。简单地通过改变神谕,我们可以标记和放大不同的状态。我们不需要为我们想从列表中选择的每一个可能的状态想出一个新的算法。但我们只需要找到一个合适的先知。
我们的量子系统的状态越多,这种能力就越有用。
寻找两种可能状态中的一种甚至都不值得称为寻找。但是格罗弗算法的一般结构和这个非常简单的例子没有什么不同。它使用相移来增加有利状态的幅度,并减少所有其他状态的幅度。
本帖是本书的一部分: 用 Python 动手做量子机器学习 。
在这里免费获得前三章。
汉诺塔——递归方法
原文:https://towardsdatascience.com/tower-of-hanoi-a-recursive-approach-12592d1a7b20?source=collection_archive---------2-----------------------
使用 C++和 Python 解决汉诺塔难题的指南
作者图片
河内塔也被称为梵天塔或卢卡斯塔。这是一个数学游戏或谜题,由三根棒和 n 个不同直径的圆盘组成。
游戏的目标是按照以下三条规则将整叠圆盘从一根棒转移到另一根棒上:
- 一次只能移动一个磁盘。
- 只有一个堆叠中最上面的盘可以移动到另一个堆叠或空棒的顶部。
- 较大的磁盘不能放在较小的磁盘上面。
解决 n 个圆盘的汉诺塔难题所需的最少移动次数是(2^n)1。
用三个圆盘解出汉诺塔背后的逻辑:
**目的:**解决包含三个圆盘的汉诺塔难题。通过遵守上面已经提到的一组规则,盘的堆叠必须从杆 1 移动到杆 3。
作者图片
**步骤 1 😗* 最小的绿色圆盘,堆叠中最上面的圆盘从杆 1 移动到杆 3。
作者图片
**第二步:**接下来,杆 1 上最上面的圆盘是蓝色圆盘,它被转移到杆 2 上。
作者图片
**步骤 3 😗* 将放在杆 3 上的最小圆盘移回到杆 2 的顶部。
作者图片
**步骤 4 😗* 现在最大的红色圆盘被允许从杆 1 移动到其目的地杆 3。
作者图片
**步骤 5 😗* 现在,杆 2 上的两个圆盘必须移动到红色圆盘顶部的目标杆 3 上,因此首先将蓝色杆顶部最小的绿色圆盘移动到杆 1 上。
作者图片
**步骤 6 😗* 接下来,蓝色圆盘被允许移动到其目的地棒 3,棒 3 将堆叠在红色圆盘的顶部。
作者图片
**步骤 7 😗* 最后,最小的绿色杆也被移动到杆 3,这将是堆叠中最上面的杆。
作者图片
所以汉诺塔三盘已经解决了!!
在 DEV C++中执行的三个磁盘的汉诺塔程序输出
让我们试着解决 n=4 个圆盘的汉诺塔难题。
图片来源:BlogSpot
我们已经看到了如何求解 n=3 个圆盘的汉诺塔,同样的方法也适用于这里。
策略:
- 递归解决将圆盘 1,2,3 从杆 A 移动到杆 b 的难题。
作者图片
2.然后将最大的圆盘 4 从棒 A 移动到目的棒 c
3.递归求解将圆盘 1,2,3 从 B 杆移动到 c 杆的难题。
用递归法求解汉诺塔规划;
函数 hanoi(n,start,end) 输出一系列步骤,将 n 个磁盘从起始杆移动到结束杆。
hanoi(3,1,3) = >在杆 1 中总共有 3 个磁盘,它必须从杆 1 移动到杆 3(目标杆)。
假设:
1≤开始≤3
1≤结束≤3
开始≠结束
递归是如何工作的?
设 f(n)是递归函数。
三大法则:
- 展示 f(1)作品= >基础案例。
- 假设 f(n-1)起作用。
- 用 f(n-1)表示 f(1)的作品。
让我们以多米诺骨牌为例来理解上述规则。
想象一下,你必须击倒 n 张多米诺骨牌。
图片来源:网络剪贴画
只考虑第一张多米诺骨牌,当它被敲的时候,它会四分五裂。这是一个类比,表明 f(1)的基本情况是可行的。
图片作者:f(1)基础案例作品
现在将 n-多米诺骨牌放在地板上,当 f(1)第一张多米诺骨牌倒下时,假定最后一张被记为 f(n-1)的多米诺骨牌被击倒。
作者图片:假设 f(n-1)作品
如果我们把另一个多米诺骨牌 f(n)放在 f(n-1)后面,那么如果 f(n-1)被击倒,多米诺骨牌 f(n)就会倒下,这证明了第三个类比,即 f(n)使用 f(n-1)起作用。
作者图片:将 f(n)放在 f(n-1)后面
正确定义 f(n)和 f(n-1)之间的关系是很重要的,这里如果 f(n)远离 f(n-1)保持安静,那么 f(n)永远不会下降(即)它永远不会起作用。
图片作者:f(n)作品使用 f(n-1)
这是一个简单的思想来展示递归是如何工作的。
实现汉诺塔的 C++程序
Python 程序实现河内塔:
现在,上面的程序可以帮助你用 C++和 Python 用递归方法解决任意数量的磁盘的汉诺塔难题。
编码快乐!!
使用 LSTM 的毒性评论分类和使用 AWS EC2 的部署
原文:https://towardsdatascience.com/toxic-comment-classification-using-lstm-and-deployment-using-aws-ec2-b84afe2b266b?source=collection_archive---------36-----------------------
在 AWS EC2 上将深度学习模型部署为 web 应用程序的分步指南。
保罗·席尔瓦在 Unsplash 上的照片
介绍
在线论坛和社交媒体*台为个人提供了提出自己的想法和自由表达对各种问题和事件的意见的手段。在某些情况下,这些在线评论包含露骨的语言,可能会伤害读者。包含露骨语言的评论可以分为无数类别,如有毒、严重有毒、淫秽、威胁、侮辱和身份仇恨。虐待和骚扰的威胁意味着许多人停止表达自己,放弃寻求不同的意见。
为了保护用户免受在线论坛或社交媒体网站上攻击性语言的影响,公司已经开始标记评论并阻止那些被发现使用不愉快语言的用户。一些机器学习模型已经被开发和部署,以过滤掉难以控制的语言,并保护互联网用户免受在线骚扰和网络欺凌。
以下文章可以被视为有毒评论分类器项目的第二部分,本文旨在阐述在 AWS EC2 上成功部署深度学习模型所需的步骤。尚未阅读有毒评论分类器项目第 1 部分的以下文章的读者可以通过以下链接 阅读。
问题陈述
“开发一个 web 应用程序,它可以精确计算用户输入的语句的毒性。”
工作流程
有毒评论分类器项目的第一部分帮助我比较了两种不同深度学习架构的性能,LSTM 和 LSTM-CNN。它给了我一个很好的基础和必要的证据,让我得出结论,LSTM 模型是我用例的正确深度学习模型,因此,我选择将其作为后端部署到 AWS EC2 上的 web 应用程序。另外,对于 web 应用程序的前端,我决定选择 Gradio。一个非常棒的库,它提供了所有必要的工具,可以为任何机器学习或深度学习模型创建一个响应性的前端。
步骤 1:为整个项目创建一个目录结构。
在进行部署之前,我最终确定了项目的目录结构,并将有毒注释分类器项目第 1 部分中完成的全部工作划分到单独的 python 脚本中。我将提供每个 python 脚本的简要描述,并详细说明它的用途。
- config.py-源文件夹中的第一个脚本是 config . py。该 python 脚本包含所有数据文件、保存的模型文件和 fastText 的 word 嵌入文件的相对路径。我还在这里定义了深度学习模型将评论分类到的毒性类别,以及一些重要的训练参数,如时期数、批量大小等。
- data_cleaning.py —顾名思义,data_cleaning.py 脚本有助于数据清理和数据规范化。以下 python 脚本将数据转换为小写字符,并从数据中移除标点符号、空格、单词间空格“\n”、表情符号、非英语字符和数字。以下脚本在模型训练期间使用,并在我们的 web 应用程序中起着至关重要的作用,因为它确保干净的数据被发送到 LSTM 模型进行毒性分类。
- data_preprocessing.py —下面的脚本文件被赋予执行两个关键任务的功能。首先,将处理后的干净数据转换成序列向量并保存为. pickle 文件。第二,使用 fastText 的单词嵌入,并为我们的深度学习模型创建嵌入层。
- model_training.py —现在,数据已经清理完毕,可以用于训练,model.py 脚本文件用于训练我们的 LSTM 模型。此外,我们还使用这个 python 脚本来保存我们的 LSTM 模型,并在以后使用它来对我们的 web 应用程序上提交的有害评论进行分类。
- website.py —存在于 website 文件夹中,website.py 脚本托管我们的 web 应用程序前端的代码以及 tokenizer 文件和保存的模型文件的相对路径。我还从 data_cleaning.py 脚本中导入了所有组件,以便在 web 应用程序上提交评论进行分类时帮助进行数据清理和数据规范化。
步骤 2:保存序列向量和训练好的 LSTM 模型。
在我们继续部署过程之前,我们必须保存序列向量和 LSTM 模型,因为它将有助于对托管的 web 应用程序执行有害评论分类。为了完成这个任务,我执行了 python 脚本*“model _ training . py”,并将“data _ preprocessing . py”脚本中的 do_load_existing_tokenizer 标志切换为False 。这确保了创建保存序列向量的新文件。 注意: 一旦序列向量被创建并保存,将do _ load _ existing _ tokenizer 标志回到True**。“model _ training . py”脚本还帮助将训练好的 LSTM 模型以. h5 格式保存在“config . py”脚本中定义的位置。*
步骤 3:模型部署。
创建并生成了部署过程所需的所有文件后,我下载了完成部署所需的必要应用程序,在 AWS 上创建了一个帐户,最后,使用 AWS EC2 实例部署了我的应用程序。成功部署我的 LSTM 模型的每个步骤将在下面的中详细说明:
*1 -在 Amazon Web Services 上创建一个帐户,并登录您的帐户。登录后,在 AWS 管理控制台顶部的搜索栏中搜索 EC2。选择“*EC2”后,您将被重定向到 EC2 管理控制台,在这里您可以从“资源”选项卡中单击“实例”。
(图片由作者提供)
(图片由作者提供)
2 -单击 Instances 会将您重定向到包含所有正在运行或已停止的 EC2 实例的页面。如果你是第一次在 EC2 上部署机器学习或深度学习模型,你可以通过点击位于屏幕右上角的“启动实例”来创建一个新的实例。
(图片由作者提供)
3 -创建实例的第一步是为 EC2 实例选择所需的操作系统,在我的例子中,是 Ubuntu Server 18.04 LTS (HVM)。接下来,选择实例类型。t2.micro 在我的情况下,因为它是免费轮胎资格。最后,您可以点击位于屏幕右下角的“R 查看并启动”,然后点击“启动”。
(图片由作者提供)
(图片由作者提供)
(图片由作者提供)
4 -现在将弹出一个窗口,让您选择是使用现有的密钥对还是创建一个新的密钥对。我将选择选项“创建一个新的密钥对”,给它命名,并最终下载密钥对。密钥对是在T3 中下载的。pem 文件格式。完成后,点击“启动实例”,最后点击“查看实例”。
(图片由作者提供)
(图片由作者提供)
5 -在创建实例的同时,我们下载了两个重要的应用程序 PuTTY 和 PuTTYgen。PuTTY 帮助您连接我们刚刚创建的 Ubuntu 服务器,PuTTYgen 帮助您从。我们在上一步中下载的 pem 文件。
6 -安装并打开 PuTTYgen,找到您的。pem 文件,并从 PuTTYgen " 里面加载"这个。pem 文件。接下来,点击“保存私钥”,然后点击“是”。给你的私钥起个名字“保存”它。
7 -接下来,下载另一个名为 WinSCP 的应用程序。这个软件很重要,因为它允许我们连接到 EC2 实例,然后将所需的 web 应用程序文件拖放到我们的 EC2 实例中。
8 -安装并打开 WinSCP。在登录提示中,我们需要首先输入主机名。可以通过选择新创建的实例并复制位于屏幕下半部分打开的 Details 选项卡中的公共 IPv4 DNS 来检索主机名。复制主机名并将其粘贴到登录提示符中。对于用户名,输入 ubuntu,然后点击“高级”。从左侧出现的菜单中选择“认证”。在“认证参数”中,上传您使用 PuTTYgen 生成的私钥文件,然后按“确定”。最后,点击“登录”,然后选择“是”。
**
(图片由作者提供)
9 -一旦你获得了 ubuntu 服务器的访问权,你就可以拖放部署 web 应用程序所需的文件。在我的例子中,我传输了 website.py、data_cleaning.py、config.py、tokenizer.pickle、toxcicity _ classifier.h5 和 requirements.txt 文件。
(图片由作者提供)
10 -一旦上述操作完成,安装并打开油灰。PuTTY 帮助我们与 ubuntu 服务器通信,并允许我们安装所有必需的库,以确保我们的 web 应用程序成功运行。要连接我们的 ubuntu 服务器,我们需要输入主机名(公共 IPv4 DNS)并给下面的会话命名。完成后,导航到侧边菜单中的" SSH" 选项,展开它并点击 "Auth ", " 浏览,然后上传您的私钥文件。使用侧面菜单导航回“会话”,并“保存”您的会话。最后,点击“打开”,你将能够访问你的 ubuntu 服务器的命令提示符。
**
(图片由作者提供)
*11 -输入用户名为 ubuntu,现在你可以编写命令在你的 ubuntu 服务器上执行操作。在我们继续安装必需的库之前,我们需要安装 *pip。在 PuTTY 提示符中键入下面提到的命令,并让它工作。
**sudo apt-get update && sudo apt-get install python-3 pip**
**
(图片由作者提供)
12 -还有一个关键的步骤,与您的 EC2 实例的配置相关。我们需要确保这个实例可以从任何地方访问。为此,从 EC2 管理控制台的侧面菜单导航到“网络&安全”,并点击“安全组”。接下来,点击“创建安全组”。给它一个名称和描述,然后点击“Add Rule”来添加一个新的入站规则。选择类型作为所有流量,选择源作为任何地方,最后点击“创建安全组”。现在,您可以导航回您的实例,选择我们创建的实例,右键单击并进入“安全”,选择选项“更改安全组”。搜索您刚刚创建的安全组,并点击“添加安全组”。不要忘记【保存】这些设置。
(图片由作者提供)
切换回 PuTTY,我现在已经安装了必要的 pip3 依赖项。现在运行下面的命令来安装所有必需的库。
**pip3 install -r requirements.txt**
14 -一旦安装了必需的库,在 PuTTY 中运行下面的命令,web 应用程序应该开始在 8080 端口上运行。
**python3 website.py**
现在获取 EC2 实例的公共 IPv4 DNS,将其复制到您的浏览器中,在公共 IPv4 DNS 的末尾添加:8080,然后点击 enter。web 应用程序现在将开始在您的浏览器上运行,这清楚地表明我们的应用程序已经成功部署在 AWS EC2 上。
警告:一旦您完成了对您部署的 web 应用程序的测试/试验,终止您的 EC2 实例总是最理想的。这防止了招致不必要的服务费的风险。为此,选择您的实例,右键单击它并从弹出的菜单中选择 Terminate Instance。
结论
使用云技术部署 LSTM 模型,对我来说是 AWS EC2,帮助我完成了一个端到端的深度学习项目。在这个过程中,我遇到了 Gradio,这是一个非常棒的库,可以帮助您为深度学习应用程序创建一个最小化的前端。本质上,我获得了成功地将应用程序部署到云服务器上并确保它运行时不会遇到任何错误或故障所需的关键步骤的知识。这个过程可能看起来很耗时或者很辛苦,但在我看来,在云上部署你的机器学习或深度学习模型并看到它给出期望的输出的满足感是无与伦比的。
完成这个端到端项目所需的所有项目文件都可以在我的 Github 个人资料中找到。我希望你喜欢看我的博客。
有毒评论分类使用 LSTM 和 LSTM。
原文:https://towardsdatascience.com/toxic-comment-classification-using-lstm-and-lstm-cnn-db945d6b7986?source=collection_archive---------7-----------------------
我第一次尝试用深度学习解决自然语言处理用例。
照片由丹缘在 Unsplash 拍摄
简介
在线论坛和社交媒体*台为个人提供了提出自己的想法和自由表达对各种问题和事件的意见的手段。在某些情况下,这些在线评论包含露骨的语言,可能会伤害读者。包含露骨语言的评论可以分为无数类别,如有毒、严重有毒、淫秽、威胁、侮辱和身份仇恨。虐待和骚扰的威胁意味着许多人停止表达自己,放弃寻求不同的意见。
为了保护用户免受在线论坛或社交媒体网站上攻击性语言的影响,公司已经开始标记评论并阻止那些被发现使用不愉快语言的用户。一些机器学习模型已经被开发和部署,以过滤掉难以控制的语言,并保护互联网用户免受在线骚扰和网络欺凌。
问题陈述
“到 建立一个多头模型,能够检测不同类型的毒性,如威胁、淫秽、侮辱和基于身份的仇恨。”
我之前曾经做过一个 NLP 用例(假新闻分类器,用来处理新冠肺炎的 dis-information”),我在这个项目中的目标是专注于数据预处理和特征工程,并确保我的深度学习模型将使用的数据尽可能干净。另外,我决定使用 fastText 的 预训练单词嵌入来驾驭迁移学习的力量。
工作流程
有毒评论分类器是一个由 Jigsaw/Conversation AI 组织的比赛,由 Kaggle 主办。用于建立分类模型的数据集是从比赛现场获得的,它包括训练集和测试集。以下工作流程中阐述的步骤将描述从数据预处理到模型测试的整个过程。
数据探索、数据预处理和特征工程
步骤 1:检查缺失值。
首先,在将训练和测试数据导入 pandas 数据框架后,我决定检查下载数据中是否有缺失值。对训练和测试数据使用“isnull”函数,我发现没有丢失记录,因此,我继续进行项目的下一步。
第二步:文本规范化。
因为我现在确信我的数据中没有缺失的记录,所以我决定从数据预处理开始。首先,我决定规范化文本数据,因为来自在线论坛的评论通常包含不一致的语言,使用特殊字符代替字母(例如@rgument),以及使用数字表示字母(例如 n0t)。为了解决数据中的这种不一致,我决定使用 Regex。 我执行的文本规范化步骤如下
- 删除文本之间的字符。
- 删除重复的字符。
- 将数据转换成小写。
- 删除标点符号。
- 删除单词之间不必要的空格。
- 正在删除“\n”。
- 删除非英语字符。
为了完成上面列出的步骤,我参考了以下 jupyter 笔记本[1] [2]。首先,我创建了一个字典,其中包含了在线论坛或社交媒体*台上常见的脏话。其次,我决定创建一个函数来执行上面列出的所有步骤,并给出干净的数据作为输出。这些步骤是在训练和测试数据上执行的。
第三步:词汇化。
既然数据现在是干净且一致的,那么是时候执行 术语化 了。词汇化是将一个词的不同屈折形式组合在一起的过程,这样它们就可以作为一个项目进行分析。例如,我们不希望机器学习算法将学习、研究和研究视为三个独立的词,因为事实上,它们不是。词汇化有助于将单词“学习”和“研究”简化为其词根形式,即学习。为了实现词汇化,我从“nltk”库中导入了“WordNetLemmatizer ”,创建了一个函数“lemma”来执行词汇化,并将其应用于我在步骤 2 中获得的干净数据。
步骤 4:停用字词的移除。
众所周知,对于涉及文本分类的用例,停用词去除是文本预处理中最关键的步骤之一。删除停用词可以确保更多的注意力放在那些定义文本含义的词上。
为了从我的数据中删除停用词,我借助了“spacy”库。Spacy 有一个常用停用词列表,即“停用词”,可以用来从任何文本数据中删除停用词。
二。虽然 spacy 的库提供的列表非常广泛,但我决定搜索可能对我的数据集唯一的附加停用词。
三。首先,我决定将单字母和双字母单词添加到停用词列表中。在阅读我的数据集中的随机评论时,我遇到了单个字母或两个字母的单词在没有任何上下文的情况下存在的例子,(例如:哇,这么可爱的枕头 w!!或者他真是个快乐的家伙 bb。)为了确保这种单字母或双字母单词的实例不会影响我的深度学习模型的性能,我将它们添加到了停用词列表中。尽管如此,我还是确保了像 me 、 am 、 a s 这样的单词,或者像 I 和 a 这样的字母不会被添加到停用词列表中。
四。一旦完成上述任务,我决定在我的数据集中搜索可能是停用词的单词,( 标准是它们在数据集中出现得非常频繁,其次,它们对分类任务 )没有显著贡献。为了完成这一步,我编写了下面给出的代码片段,它帮助我在数据集中找到停用词,这满足了上面强调的标准。最后,我将这些新获得的停用词添加到 spacy 的“停用词”列表中,从而创建了我的最终停用词列表。
动词 (verb 的缩写)现在我有了我想要的停用词列表,我使用它从我的训练数据和测试数据中删除停用词。一旦这一步完成,我就有了一个没有任何不一致的干净的数据集。
步骤 5:标记化、索引和索引表示。
众所周知,机器学习和深度学习模型对数值数据起作用,与用例无关。因此,要使用干净的文本数据训练深度学习模型,必须将数据转换为其等效的机器可读形式。实现这样的壮举。我们需要执行以下步骤[3]:
- 标记化——我们需要将句子分解成独特的单词。如“我爱猫爱狗”会变成[“我”、“爱”、“猫”、“和”、“狗”]。
- 索引—我们将单词放在一个类似字典的结构中,并给每个单词一个索引,例如{1:“我”,2:“爱”,3:“猫”,4:“和”,5:“狗”}。
- 索引表示——我们可以用索引的形式表示评论中的单词序列,并将这个索引链输入到我们的深度学习模型中。例如[1,2,3,4,2,5]。
使用“Keras”库中的“Tokenizer”类,可以很容易地执行上述步骤。该类允许对文本语料库进行矢量化,通过将每个文本转换为整数序列(每个整数是字典中某个标记的索引)或向量,其中每个标记的系数可以是二进制的,基于字数,基于 tf-idf 等[4]。下面的代码片段演示了文本数据到序列向量的转换。
第六步:填充。
在线论坛或社交媒体*台上的评论长短不一,一些是一个词的回复,而另一些则是大量阐述的想法。可变长度的句子被转换成可变长度的序列向量,我们不能将长度不一致的向量传递给我们的深度学习模型。为了避免这个问题,我们使用填充。在填充的帮助下,我们可以通过用零填充不足部分来使较短的句子与其他句子一样长,另一方面,我们可以将较长的句子修剪为与较短的句子一样长[3]。我使用了“Keras”库中的“pad_sequences”函数,我将句子长度固定为 200 个单词,并应用了postpadding(即对于较短的句子,0 将被添加到序列向量 的末尾)。一旦我们完成了序列向量的填充,我们就可以开始创建深度学习模型了。
模型创建和模型评估
步骤 1:将训练数据分为训练集和验证集。
由于我们已经完成了项目的数据预处理和特征工程部分,我们继续进行项目的模型创建和模型评估部分。在尝试对训练数据拟合深度学习模型之前,我将数据随机分为训练集和验证集。验证集占训练数据的 20%。
步骤 2:导入 fastText 的预训练单词嵌入。
如前所述,在 问题陈述*中,我想使用来自 fastTex t 的预训练单词嵌入来驾驭迁移学习的力量。为此,我将 fastText 单词嵌入加载到我自己的环境中,然后,通过为词汇表分配预先训练的单词嵌入来创建一个嵌入矩阵。*
第三步:模型创建(LSTM)。
现在是时候选择深度学习模型,并使用训练集和验证集来训练该模型。因为我们正在研究自然语言处理用例,所以使用长短期记忆模型(LSTM)是理想的。LSTM 网络类似于 rnn,一个主要区别是隐藏层更新由存储单元代替。这使得他们能够更好地发现和揭示数据中的长期依赖性,这对于句子结构来说是必不可少的[5]。
首先,我导入了" Talos " 库,因为它将帮助我们执行超参数调整以及模型评估。使用“扫描”功能,我执行了一个 GridSearchCV,并找到了能给我最高精度的最佳参数。
二。接下来,使用最佳超参数,我定义了 LSTM 模型所需的层数,编译了模型,最后使用训练集和验证集训练了模型。
第四步:模型创建(LSTM-CNN)。
在我项目的研究阶段,我遇到了使用混合模型( ,即 LSTM 和 CNN 一起工作的模型 )实现有毒评论分类的论文。对于深度学习模型来说,这样的架构引起了我的兴趣。LSTM 可以有效地保存长文本序列中历史信息的特征,而 CNN 可以提取文本的局部特征[6]。结合这两种传统的神经网络架构将有助于我们利用它们的综合能力。因此,我决定实现一个 LSTM-CNN 混合模型作为我项目的一部分。目标是比较两种深度学习架构的性能,并确定我的项目的最佳深度学习模型。
类似于步骤 3 中的过程,我使用“Talos”*发现了我的混合**模型的最佳超参数。操作完成后,我评估了结果,挑选出了精确度最高的超参数。最后,我使用训练集和验证集来训练我的混合模型。*
步骤 5:在训练阶段评估模型精度和模型损失。
由于我们已经完成了两个深度学习模型的训练,我们现在应该在整个训练过程中可视化它们的准确性和损失值。理想情况下,任何深度学习模型的损失值都应该随着时期数的增加而减少,另一方面,准确性应该随着时期数的增加而增加。这让我们对我们的深度学习模型的质量有了一个相当不错的想法,以及它是否经过了适当的训练。在下面的图像中可以看到每个历元的精度和损失值的趋势。
LSTM 模型在 2 个时期内的损失和精度值。(图片由作者提供)
LSTM-CNN 模型在 2 个时期内的损失和精度值。(图片由作者提供)
步骤 6:使用测试集计算模型准确性
基于准确性和损失值评估模型给了我有希望的结果。这让我有信心使用测试集评估我的深度学习模型的性能。正如本博客前面提到的,测试集是从 Kaggle 获得的,它通过了与训练数据相同的数据预处理和特征工程步骤。因为我现在已经有了经过处理的测试数据,所以我使用了“predict”函数来为测试数据中的输入生成输出。
我的两个深度学习模型的上述过程一完成,我就上传了各自的”。csv”输出文件到 Kaggle 竞赛,并提交它们以生成最终的准确度分数。我的两个深度学习模型的最大准确度分数可以在下图中看到。
传统 LSTM 模型和混合 LSTM-CNN 模型的精确度分数的比较。(图片由作者提供)
结论
在评估了我的项目在培训阶段获得的结果以及我从竞赛网站上获得的结果之后,我可以宣称传统的 LSTM 模式比混合的 LSTM-CNN 模式在表现得更好。混合模型略微输给了传统的深度学习模型,后者表明传统的 LSTM 模型是有毒评论分类用例的正确选择。
下一步是将 LSTM 模型作为后端部署到一个 web 应用程序,该应用程序确定用户作为输入提供的评论的毒性。在 AWS EC2 上部署 LSTM 模型所需的所有步骤的详细介绍可以在本博客的第二部分中找到。一定要看看那个。
项目的主要收获
这个项目让我能够使用两种不同的深度学习模型,此外,我还能够在自然语言处理用例上实现它们。项目中的各种数据预处理和特征工程步骤使我认识到可以用来清理文本数据的有效方法。我了解各种深度学习模型的工作方式,如 CNN、LSTM 和 LSTM-CNN 混合模型。我了解了单词嵌入的概念以及使用预训练单词嵌入的优点。最后,“Talos”库的发现帮助我为我的深度学习模型执行无缝的超参数调整,并帮助我实现最佳结果。
参考
[1]-https://www.kaggle.com/fizzbuzz/toxic-data-preprocessing
【2】-https://github . com/Susan Li 2016/NLP-with-Python/blob/master/Toxic % 20 comments % 20 lstm % 20g love . ipynb
【3】-https://www . ka ggle . com/sbongo/for-初学者-攻坚-用毒-keras
【4】-https://keras.io/api/preprocessing/text/
【5】
【6】——张,李,田,,李,“用于文本分类的 CNN 混合模型”,2018 IEEE 第三届高级信息技术、电子与自动化控制会议(IAEAC),重庆,2018,第 1675–1680 页,doi: 10.1109/IAEAC.2018.8577620
我为这个项目遵循的工作流程可以在我的Github页面找到。我希望你喜欢看我的博客。
计算机科学中有害的同行评议以及如何应对……
原文:https://towardsdatascience.com/toxic-peer-review-in-computer-science-and-what-to-do-about-it-562ed5608310?source=collection_archive---------19-----------------------
所有科学家都会在某个时候收到同行评议中的有毒评论。我们该如何处理这种情况?在 Unsplash 上由 Mikael Seegen 拍照
同行评议及其最重大的失误
科学同行评审影响着所有计算机科学研究人员和学者的日常生活。通常情况下,这个过程会导致严重的问题和错误的决策,这是我们不愿承认的。
同行评审示例
审核者 1:合格纸张— 接受
审核者 2:纸张合格— 弱接受
审核者 3:纸张不太好,修改后可能有用— 弱拒绝Meta Reviewer:
这篇论文莫名其妙的坏掉了——拒绝!
所有的科学家最终都会面临这种情况。他们每次都受伤。那么,这个系统坏了吗?我们为什么要玩这个游戏?!是时候看看同行评审的所有有趣的细节、它的弱点和一些真正有害的例子了!(警告:前方重磅触发!)
同行评审旨在向作者提供严谨的反馈。有时反馈可能非常直接。照片由蒂姆·莫斯霍尔德在 Unsplash 上拍摄
在这篇文章中,我想解释计算机科学中的科学同行评审系统及其缺陷。此外,我认为这是一个很好的机会来揭露这个系统是如何不断受到攻击,并报告我自己在这个系统中经历的一些科学不端行为。
难道我们不能找到比有毒评论更好的解决方案吗?照片由艾米丽·莫特在 Unsplash 上拍摄
为什么我们需要同行评审?
同行评审是一种发展了多年的机制,其目的是确保出版物的质量。所有的科学家都容易犯错误。让某人独立检查你的工作以防止你发表错误的研究,这是对你最有利的。想象一下你工作中的一个严重错误会产生怎样的反效果!一旦出版,每个人都会看到!所以有人会说,这是科学家的安全带。
由于这些原因,许多科学家只把同行评议的工作视为基于科学的观察。因此,同行评议是科学许多部分的一部分。我在这里特别考虑了三种不同的同行评审:
- 会议上的同行评审
- 期刊中的同行评议
- 论文工作的审查,例如博士论文
会议是科学交流的重要手段。产品学院在 Unsplash 上的照片
典型的会议同行评审是如何工作的?
同行评议最常见的形式是科学会议。这通常也是科学家职业生涯中第一次经历评审。根据领域的不同,会议可能从肤浅的反馈到复杂的竞争过程。在所有情况下,审查都是在固定期限的时间压力下进行的。由于所有的科学家都是大忙人,这种限制并非没有影响。在某些情况下,多达 30%的评论是在截止日期后提交的——通常是由所谓的紧急评论者在 24 小时内提交的。显然,这种审查比可能需要数周才能完成的全面审查更容易出错。因此,同行评审通常被认为是一种随机决策。
通常作者不知道该评论。这个过程叫做致盲。照片由 Ryoji Iwata 在 Unsplash 上拍摄
会议评论的类型
为了确保清晰和批判性的评论,大多数会议都采用盲法审查程序。在所谓的单盲审查中,审查者的身份被隐藏,这样负面反馈不会导致报复行为。尽管如此,一些作者试图通过使用的语言和术语来重新识别他们的审稿人。我只能建议不要这样做,因为这只会导致毫无根据的指控。
一些——通常是声誉很高的会议——试图进一步减少由于个人不喜欢而产生的潜在偏见。在这些情况下,会使用双盲评审。在这里,作者从论文中删除了他们的名字和所有可以识别他们的信息。因此,评论者也不知道他们实际上是在评价谁的作品,也不能偏爱某些个人喜欢的群体而不是其他作者。
同行评议并不总是公*的。由 Edge2Edge 媒体在 Unsplash 上拍摄
同行评审是一个随机的过程
审核者的决定存在一定程度的随机性。他们可能会被论文中的某些措辞所影响,或者对论文的大意提出质疑。所以单个审稿人被认为不靠谱。大多数会议选择两到四个评审者,并考虑他们对正在考虑的工作的多数投票。
在顶级会议中,即使这样也不被认为是值得信任的。这里,所谓的元评审者被引入到流程中。meta 的任务是仲裁评审者在第一轮评审中没有达成共识的情况。在这些情况下,元可以引导讨论,并帮助审稿人找到对论文的适当评价。不幸的是,就像本文开头的例子一样,一些 metas 认为自己是某种不会犯错的神,给予世界其他地方智慧。因此,通常所有的元决策都要受到更高层的控制,比如技术项目主席。然而,这种选择也有引入另一个随机因素的风险,例如,如果六个技术项目主席必须手动检查超过 1500 个书面决策。
为了进一步减少随机性,一些科学家建议使用更多的评审员——比如 30 到 50 人。在这些情况下,显然不可能进行全面的审查,但反馈只会是“赞成”或“反对”。显然,这将产生更好的决策,正如我们从助推理论中所知。然而,这从未在真正的会议上实施过,因为大量的决定很可能会导致这样的问题,即审查者将仅根据标题或摘要来判断论文,而不会阅读完整的提交内容。
尤其是会议评论很难*衡。廷杰伤害律师事务所在 Unsplash 上的照片
会议评论的利与弊
一般来说,会议只采用一步或两步流程。因此,没有机会与评审人员进行深入讨论。即使是最复杂的会议审查程序也会遇到这个问题。
因此,你不应该因为负面或苛刻的评论而失去动力。很多工作是由志愿者在时间压力下完成的。此外,审查人员容易出错。试着理解他们批评的原因,并用它来改进你的工作。
一些会议以高退稿率为目标,作为只发表“最好”论文的衡量标准。由于风险很高,审查往往会变得非常苛刻。此外,对顶级会议论文的期望也非常高。尽管同行评议——尤其是在会议上——是一个随机的过程,但更好的论文更有可能通过同行评议。
尽管如此,由于上面提到的随机因素,不合格不一定是工作质量差的标志。有许多好论文在第一次提交时被会议拒绝的例子(例如, nnU-Net 、深度行动学习、超级基准等等)。
科学期刊的评审周期比会议长得多。照片由 Wherda Arsianto 在 Unsplash 上拍摄
为什么我们仍然用科学期刊发表文章?
期刊出版物的一个显著缺点是同行评审通常需要更长的时间。一轮审查可能需要三到六个月的时间。尽管如此,向期刊投稿还是有很高的价值,因为同行评议过程更加精细,更加注重深入的论证。在很多期刊上,作者和审稿人之间的讨论要来回几次。因此,审稿人关注提交作品的细节。他们知道他们的评估将被提交给作者,他们有机会相应地调整他们的工作和论证。如果他们的论点不够详细,他们的批评将很容易反驳。因此,像“不够好”或“不够新颖”这样的论点没有被使用。取而代之的是,需要提供一个已经解决了这个问题并且没有被作者涵盖的先前工作的列表。
因为作者知道他们必须与评论者争论,一些作者倾向于讨论评论者的所有观察。然而,这不是同行评审的目的。每一轮都应该提高论文。因此,作者不应该陷入常见的错误,如将评论视为个人或认为评论者是愚蠢的。审稿人是你论文的代表性读者。其他看报纸的人也会有类似的想法。
因此,如果你必须向你的评审员提供额外的解释,你也要将它们添加到论文中。讨论区是这样做的合适地方,因为其他读者也会有类似的问题。如果你的论文像病毒一样传播,并被公众广泛误解,这样的部分也可以成为一个安全带。在这种情况下,你可以指向讨论部分,它应该已经反击可预见的批评和误解。还有,你要确保你的论证是正确的。任何错误都会被审稿人发现,你的论文可能会被拒绝。
期刊拒绝意味着你不能再次提交论文,除非你完全重做论文。(如果你的论文被拒绝了,你可能还是想这么做。)
我推荐去高排名的期刊和场馆试试你的机会。桌面拒绝最多需要两个星期,它会让你觉得你至少努力过。像《自然》这样的出版商甚至有提交前调查的工具,在一两周内只对摘要进行评估。
在精细化同行评议的时代,我们还需要博士论文吗?琼·夸姆博卡在 Unsplash 上的照片
我们还应该写博士论文吗?
我想在本文中包括的第三种评论是论文工作的评论,如博士论文。一些导师要求通过同行评审的出版物来顺利完成博士学位。许多大学甚至允许累积作品,即提交一组同行评审的文章,而不是论文。尽管如此,这一程序仍有不少问题。
由于论文与正式学位相关,累积作品必须提供证据证明提交的作品确实主要基于提交人的贡献。因此,作者经常被要求要求他们的合作者签署同意使用一篇论文作为论文的一部分。在大多数情况下,不存在滥用,这些表格有助于发现试图使用相同的论文为两个 不同的 人毕业的情况。
然而,问题可能会出现,一些实际上没有自己写作品的人可能会试图利用一长串的合著贡献来获得学位。因此,一些大学仍然要求正式论文的写作。支持和反对这一点的理由很多。有些人认为这是浪费资源。对其他人来说,这是展示真正学术能力的唯一途径。
在任何情况下,最终的论文都将接受独立评审员的评估。显然,他们会尽最大努力评估工作。根据我的经验,它有助于表明这项工作已经产生了高排名的同行评审工作,这可以通过地点的影响或引用因素或工作本身的引用数量来证明。因此,在博士项目期间追求同行评议的出版物是非常可取的。
在某些情况下,作者甚至没有意识到可疑的行为。图片由KnowYourMeme.com
同行评审中的陷阱
出于上述原因,在同行评审的场所发表文章的压力可能会很大。因此,经历过以前的拒绝的作者可能会寻找排名较低的地点,以便让他们的作品迅速被接受。虽然这种选择看起来是一种快速的解决方法,但这条路也可能会带来麻烦。
掠夺性期刊通过全面的同行评审为快速出版做广告。通常这甚至是通过参考作者以前的出版物来完成的。不幸的是,他们只是简单地发表任何未经同行审查的贡献,并收取出版费或会议费。在这样的期刊上接受一篇论文可能会对作者的名誉造成严重损害,即使提交论文的作者不知道该期刊的性质,或者如果在他或她不知情的情况下,一位合著者被添加到作者名单中。这种期刊的公开列表有助于避免这种虚假的同行评议。
适用于期刊的方法显然也可以应用于会议。掠夺性会议也很难被发现。它们通常位于受欢迎的旅游地点,因此提交和旅行变得更加有吸引力。识别这种会议的一种方法是寻找在同一日期和地点发生的类似事件。您可能会找到几个“关于[在此插入主题]”的世界会议,这些会议同时举行,甚至共用同一个主题发言人。为了避免此类骗局事件,您可能需要咨询您的同事或会议排名,如guide2research.com。
最*,视频期刊也出现了。虽然同行评审过程似乎很严格,但《华尔街日报》出版和制作这段视频可能相当昂贵。因此,作者最好在提交到任何地点之前研究出版的潜在成本。
有害行为可能会带来短期成功。从长远来看,它只是降低了科学的质量。照片由达尼洛·阿尔维斯在 Unsplash 上拍摄
同行评审中的有害行为
在同行评审中,简单的不当行为通常非常罕见。有毒行为更为常见。这里报道的例子从令人不快但常见的到极端的情况。请注意,我花了整个职业生涯来收集这些例子。科学造假极其罕见。然而,人们不能否认它的存在。
一个很常见的毒害行为就是对其他作品过度负面。即使在匿名的同行评议中,你也不会看到自己机构的作品。由于许多会议对接受分数设置了硬门槛,你创建的任何负面评论都会增加你自己小组的论文被接受的概率。此外,你可能会发现与你自己的作品相似的作品,你可能会故意推迟它的出版。因此,一些审稿人的常见策略是找到简单的理由拒绝论文。像“不新颖”、“不够清楚”这样的陈述,以及其他仅仅是粗略的理由,通常会出现在这样的拒绝中。因此,你要确保你了解所有相关的文献,并将其与你自己的作品进行比较——在最好的情况下——以反驳缺乏新颖性的说法。尽可能突出你的方法或研究的优点,这样就可以避免缺乏清晰度的说法。如果你从事机器学习,你会希望避免机器学习的七宗罪,因为它们很容易被快速拒绝。
另外一些评论者试图增加他们自己的引用统计数据。你会发现这样的评论给出了一个混合的评论,并要求引用几篇都是由同一组作者写的论文。虽然使用这种行为来增加自己的引用次数已经是有问题的,但这一程序有问题的另一个原因是:审稿人的身份很容易猜测,因此可能会妨碍同行评议过程的匿名性。因此,进行这样的审查是不可取的。
随着过去几年投稿数量的增加,同行评审的数量也在增加。所以,有些时间用完的评审自己不做评审。如果他们碰巧领导一个小组,他们有时会要求团队中的一名成员为他们执行评审。如果他们仍然检查评审的有效性,即使协助人员同意以保密的方式提供帮助,该过程仍然容易出错,因为保密的同行评审材料必须转移给第三方。因此,该程序在法律上是有问题的,特别是在没有明确法律条款的场所。幸运的是,这种趋势在几年前就已经被发现了,并且已经采取了一些应对措施,比如允许初级研究人员进行同行评议。这增加了可能的审阅者的数量,并减少了每个审阅者的工作量。
编辑和元审核者拥有很大的权力。谁会想到,权力越大,责任越大。把一个决定推向某个方向是很诱人的,因为你知道这是正确的。你是负责人,你的决定不可能改变。这将为作者、评审者和你自己节省大量时间,对吗?嗯,不。你可能会错过一个论点或一个重要的观察,这可能会影响你的决定。因此,过早地结束对一篇论文的有争议的评论有做出错误决定的风险,特别是如果你不得不推翻大多数的评论者,就像开始的例子一样。想象一下,作为一名作家,如果不能回应有争议的批评,你会有什么感受。
最后一个有问题的做法发生了当 元审稿人和编辑只分配论文给他们自己的学生。这使得能够形成集团,并增加了接收类似的依赖审查的可能性。因此,某篇论文的审稿人最好来自世界各地的不同机构。
有一条细线,但一旦越过,显然就是不当行为。图片由 Gerd Altmann 在 Pixabay 上拍摄
明显的不当行为
科学不端行为的案例很少,如果人们被抓住,可能会有严重的后果。尤其是抄袭其他作品很容易被发现,迟早会被发现。自从出现剽窃检查器以来,这个过程甚至可以自动执行,许多期刊和会议已经在使用它们,或者计划在不久的将来使用它们。因此从其他作品中复制&粘贴是不明智的。
为了增加自己的引用次数,一些作者从事所谓的造纸厂。通常,低等级期刊甚至掠夺性期刊被用于这些目的。此外,一些作者形成派系,从事大量的相互引用。虽然其中一些网络可能只是从某个领域的结构中出现,但也有明显的滥用情况。最*对一家造纸厂的调查发现超过 400 篇论文被剽窃,包括抄袭的数字。
研究中不时会出现伪造的结果。严重的病例甚至成为一般新闻的头条新闻。做出重大发现当然是一件令人兴奋的事。然而,成名的时间将会很短。因此,对自己的观察非常谨慎符合所有科学家的利益。科学发现的意愿可能是强烈的,但是一旦实验不能被其他人复制,捏造甚至仅仅是粗心的后果就会被发现。特别是对于机器学习研究来说,这可能很容易因为没有给予足够的关注而出现。这种篡改的结果很可能不会被同行评审过程发现,因此对任何研究人员都是一个重大威胁。
一些科学不端行为要么没有被报道,要么很少受到迫害。我们遗漏了多少这样的案例?图片由达尔文·拉甘松在 Pixabay 上拍摄
冰山一角之下
以上案例大概是所有科学家都熟知的。然而,我也遇到过其他不太为人所知的不当行为。以下报告的案例已经发生并已被报告。因此,我建议任何人都不要这样做。然而,你可能会发现其中一些事件令人震惊。请注意,我一直活跃在许多不同的科学界。因此,你将无法猜测事件发生在哪个社区,我也建议你不要尝试这样做。我也不会回答到底是谁卷入了这些事件。
同行评议具有随机性。从概率论中我们知道,我们尝试的次数越多,论文最终发表的几率就越高。然而,这一程序需要时间,因为不允许同时提交文件。尽管如此,我还是看到了一些团体的尝试,他们非常理解同行评审过程的本质。在一个特殊的案例中,作者更改了标题、摘要和关键词,并且提交了两次完全相同的论文。在这次特别的会议上,评审者的选择是基于关键词的。因此,用一组不连贯的关键字两次找到同一个评论者的可能性很小。有了两次提交,你的论文被接受的机会增加了一倍。如果两份申请都被接受,你只需撤回一份。然而,在这个特殊的案例中,项目主席查看了所有共享同一组作者的论文,从而发现了欺诈企图。这件事被升级到这个特定科学团体的董事会,并根据团体的标准进行处理。
有时一篇论文看起来有些熟悉,你甚至可能会无意中看到自己的论文或小组的论文。显然,此类事件必须报告给项目主席,他们会处理这个问题。还有,论文被接受后,作者有时会更换。通常情况下,论文会在提交截止日期的最后几个小时到几分钟内完成。因此,必须有机会纠正最后一分钟的错误。然而,不应该发生的是,在论文被接受后,一个评审者突然以合著者的身份出现。这一事件也已报告,并由相关的社区委员会进行了处理。
然而,我在同行评审中遇到的最令人震惊的事件是上述几种做法结合的结果,一系列非常不幸的事件。在这种情况下,一位年轻的研究人员提交了一篇论文给该领域一个非常受人尊敬的,双盲会议。T4 的论文以非常微弱的差距被否决。一些评论有助于论文的改进。六个月后,论文再次提交给了一个著名的单盲会议。然而这一次,论文因抄袭立即被拒绝。新的评审认为论文抄袭,并向会议主席报告了这一发现,会议主席开始对提交论文的作者进行调查。经过仔细考虑,调查发现匿名、双盲、第一版的论文是在该领域另一个非常知名的组的 公共文件服务器上发现的。显然,这篇论文是由第一次会议的匿名审稿人之一上传到文件服务器的。似乎一位高级研究员将审查委托给他的一位下属。他没有想到的是,该集团的文件服务器没有针对搜索引擎的保护措施。因此,Google 开始索引文件服务器的内容。结果二次会议审稿人在最前沿找相关研究时发现了论文**,他将论文认定为抄袭为 作者与文件服务器的所有者不同。调查结束后,提交论文的作者被判没有剽窃罪。此外,这一复杂的事件链并没有导致对将匿名论文上传到他们自己的公共文件服务器的组织采取任何措施。最终,提交作者离开了学术界,再也没有从他们的博士学位毕业**
同行评议不公*。适当的自卫可以避免这些问题。萨姆·穆卡达姆在 Unsplash 上拍摄的照片
我该如何应对这样的问题?
如果您发现重大中毒行为,您可以举报。会议和杂志为决定性的事件提供机密的评论。如果您怀疑某个审稿人越界,请将您的怀疑报告给副主编或元审稿人。在任何情况下,你都应该假定是无辜的,因为只引用某个小组的论文的建议可能仅仅与事实有关。永远审视自己的怀疑。
使用 ArXiv **!一旦你以你和你的合著者的名义发表了你的想法,这些想法就不会再在匿名的同行评议中丢失了。这是保护你的知识产权的好方法。现在,在 ArXiv 上发布预印本已经被所有主要的机器学习和模式识别会议所接受。**显然,你要确保你的所有合著者都同意这一点,并且已经提交了潜在的发明披露。还要确保你更新了 ArXiv 提交的最终出版物的参考文献,以便其他研究人员可以找到同行评审和发表的论文。
ArXiv 不是经过科学同行评审的来源。如果论文只是在 ArXiv 上,那很可能是前期工作。它可能仍然包含潜在的错误,并可能在最终出版前进行更新。此外,不要将 ArXiv 出版物作为相关的现有技术进行报告,尤其是如果论文在提交截止日期之后出现。
并非所有的应对措施都必须由你自己来采取。会议和期刊现在严重依赖剽窃检查。在许多会议和期刊中,评审员现在会收到论文和剽窃报告,以便对作品进行评估。此外,元审查和审查者分配由项目委员会手动检查。通常,评审者和 metas 会得到一个机密的分数来评估他们的信任度。
所有不当行为都是秘密处理的。我们这样做是为了不损害整个科学。科学家通常应该被认为是知识渊博和值得信赖的。记住:不当行为很少,错误更频繁。总是假定无罪。
不幸的是,没有一个通用而明确的“行为准则”来阐明哪种类型的不当行为与哪种处罚相关联。案件是根据个人情况处理的。因此,后果也可能因社区和国家的不同而有很大差异。了解适用于您的规则,遵守它们,并在同行评审中反对有害行为,例如通过提高您的同事对该主题的认识。不要在社交媒体上做出私刑和指控的行为!
如果你发现了不当行为,每个科学机构都有一个仲裁机构,会妥善处理这个问题。在一些社区,对不当行为的公开指控本身可能被认为是不当行为,因为它损害了科学作为一个整体的声誉,违反了假定无罪的原则。记住:同行评审过程很复杂,风险很高,某些行为很容易被误解。总是怀疑每个人都是出于好意但是要为最坏的情况做好准备。
最后一个提示:**不要去参加拒绝你作品的会议,自己分发你的论文。**如果你曾经遇到有人在会场前这样做,你会马上意识到为什么这是不可取的。
我们能做些什么来进一步改善同行评审?照片由 Clem Onojeghuo 在 Unsplash 上拍摄
带回家的信息
读了这篇文章,很明显同行评议有很多问题。然而,我们还不知道有哪种系统运行得更好。此外,我们已经看到没有单一版本的同行评审。每个科学界都在根据自己的需要建立自己的标准。此外,为了找到更好的解决方案,许多同行评审制度也在不断变化。这也防止了该领域中的玩家继续利用,这些玩家简单地很好地了解该过程。如果你负责调整一个同行评审过程,确保没有一个相关人员拥有过多的权力。一般来说,所有贡献者的目标都是在公*和负责任的基础上行事。然而,滥用权力可能很诱人,同时也很难被发现。
ArXiv 可能是对抗不公*同行评审的最佳对策之一,因为它承担了早期出版需求的压力。然而,如果在某个时候没有成功地通过同行评审,ArXiv 提交材料就不能被视为完整的科学作品。
同行评审中的有害行为通常只会降低同行评审结果的质量。其目的是获得对其他群体的不公*优势。此外,有毒的同行评议可能会在其他科学家身上引发更多的毒性。因此,一个人必须始终避免使用有毒的做法,即使你自己就是这种行为的受害者。
一些行为可能看起来是不当行为,但也可能只是一系列不幸的事件。因此,总是假定无罪。如果您怀疑有不当行为,请联系您的仲裁机构。不要马上公开身份这很可能会损害你自己的职业生涯!所以,你希望别人怎样对待你,你就要怎样对待别人。
如果你喜欢这篇文章,你可以在这里找到更多文章,在这里找到更多关于机器学习的教育材料,或者看看我的深度 学习 讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube、Twitter、脸书、LinkedIn 或 T21。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。
人工智能文本生成中的毒性
原文:https://towardsdatascience.com/toxicity-in-ai-text-generation-9e9d9646e68f?source=collection_archive---------13-----------------------
Julia Nikulski 创作的图形显示了聊天机器人在与用户对话时产生的有毒语言。由 Flaticon 的 Becris 和 Freepik 制作的图标。
公*和偏见
为什么语言模型会产生有害的输出,对此能做些什么
我最*实施了一个小型的 NLP 项目,在这个项目中,我问了两个开放域聊天机器人 36 个恋爱问题。最初作为消遣的东西,让我注意到了 AI 文本生成中的毒性问题。我最初问了语言模型(LM)GPT-2 36 个问题。但我被该模型产生的一些答案震惊了,这些答案包含仇恨和有问题的语言,我决定不公布它的答案。
除了一些关于 AI 出问题的轶事之外,我以前没有处理过文本生成的这个方面。然而,我意识到,意识到在面向用户的项目中应用语言模型所带来的潜在危害是至关重要的。所以我阅读了为什么语言模型倾向于创造出如此令人憎恶的语言,以及如何解决这个问题。
各种研究论文研究了自回归 LMs 固有的毒性和社会偏见——如 GPT-2【1】——以及双向编码器模型——如伯特【2】。本文概述了有毒语言的产生,并涵盖了其主要问题和解决方案。我讨论了文本生成中的毒性意味着什么,为什么会发生,以及目前是如何解决的。我还提出了一些与解毒语言模型相关的伦理考虑。
摇滚猴子在 Unsplash 上的照片
1.什么是毒性?
正如 Lilian Weng 在她的博客文章中提到的,关于 LMs 毒性的确切定义各不相同。 Jigsaw 和谷歌反滥用技术团队开发了 透视 API ,识别在线对话中的有毒语言。他们将毒性定义为
粗鲁、不尊重或不合理的评论可能会让你退出讨论。
Dhamala 等人【3】创建了一个数据集和度量标准来调查开放式文本生成中的社会偏见和毒性。他们将有毒语言定义为传达内容
不尊重、辱骂、不愉快和/或有害。
Pavlopoulos 等人【4】研究了潜在毒性评论的背景是否有助于提高毒性检测模型的性能。他们认为毒性是一个总括术语,包括几个亚型,如攻击性、辱骂性和仇恨性语言。基于这些定义,毒性不是一个明确定义的概念。这是一个宽泛的术语,涵盖了各种形式的攻击性、有问题的或有害的语言。
2.毒性检测与毒性产生
Julia Nikulski 制作的图形展示了有毒语言检测和有毒语言生成之间的区别。由 Smashicons 、dinosoftlab、 Becris 、 Freepik 和eucalype从 Flaticon 制作的图标。
在我为本文进行研究的过程中,我发现涉及 NLP 中毒性的学术论文可以大致分为两类,一类是涉及毒性语言检测的主题,另一类是毒性语言生成。虽然这篇博客文章的重点是有毒语言的生成,但是在寻找有毒语言模型的解决方案时,对有毒语言检测的一般理解是有帮助的。
各种研究专注于开发自动系统来检测人类书写的有毒语言,并在网上讨论中流行。虽然骂人的话似乎表明有毒,但没有这种话的语言仍然可能有毒。简单的“我一看就知道”——在构建数据集和模型来检测毒性时,这种方法是不够的。语境和语言中的细微差别很重要,决定什么导致冒犯通常是主观的【6】。Sheth 等人【7】对与定义和识别有毒物质相关的挑战进行了出色的概述。
在这一毒性检测领域,存在偏差检测模型的问题。用于检测毒性的自然语言理解(NLU)模型已被证明包括偏见——特别是对少数民族产生的文本和少数民族的身份提及【1】——这限制了模型正确标记有毒语言的能力【6】。通过将无毒内容标记为有毒来压制少数群体的声音也引发了伦理问题。
与种族、性别、宗教、民族、性取向和其他受保护身份相关的社会偏见也存在于为生成文本而设计的 LMs 中。它们体现在这些模型产生的有毒语言中。这些 LMs 还输出包含诅咒语、威胁和侮辱的语言。Gehman 等人【1】表明,五种不同的 LMs——包括 GPT、GPT-2 和 GPT-3——在 100 代中均产生至少一种毒性评论。即使相对无害的输入作为提示提供给这些模型,也会导致有毒文本的生成。此处显示了该研究的互动概述。
马库斯·温克勒在 Unsplash 上拍摄的照片
3.为什么会出现毒性?
最先进的(SOTA)语言模型——如 GPT-2 和 GPT-3——使用来自网络的大型文本语料库进行预训练。LMs 学习预测序列中的下一个单词(或句子中的单词)。如果模型被输入包含诅咒语或暴力语言的训练数据,它将在训练阶段学习预测这些单词,并在稍后生成包含它们的输出。在通过这些模型进行推断的过程中,也学习和复制了具有刻板印象、贬低或忽略受保护身份的有偏见的语言。
对 BookCorpus 的一项调查——一个经常用于预训练包含超过 11,000 本书的 LMs 的数据集——显示它包括与性别有关的有问题的内容,以及对流派、宗教和作者的歪曲表现。OpenWebTextCorpus——一个重现用于 GPT-2 的训练数据的数据集——包含 Reddit 上出站链接的内容。Gehman 等人【1】证明该数据集包含至少 50,000 个毒性句子,根据 Perspective API 测得的毒性分数(可解释为概率)为 0.51 或更高。
如前所述,在确定什么是有毒的时候,环境很重要。不幸的是,在特定语境中无毒的语言可以被语言模型重新“洗牌”,当给予暗示性提示【1】时,语言模型会产生有毒的输出。为了说明这一点,你可以想一想在客观描述犯罪时使用的词语。这些词然后被模型应用到一个句子中来表达威胁,清楚地显示出毒性。因此,控制预训练 LMs 的生成过程以及使用干净无毒的数据集进行预训练对于避免有毒输出非常重要【1】。
4.如何减少毒性的产生?
由 Julia Nikulski 创建的图形显示了语言模型的不同解毒策略。由 Flaticon 的 Smashicons 、dinosoftlab和 Freepik 制作的图标。
许多在复杂性和资源强度上不同的方法旨在减少语言模型产生的有害内容。我将简单介绍一些方法,并列出它们的优点和局限性。列出所有可用的方法超出了本文的范围。
根据 geh man et al .【1】,这些方法可以分为基于数据或基于解码的策略。基于数据的策略包括模型的额外预训练和改变模型参数,这使得这些方法在计算上很昂贵。基于解码的方法只是修改了 LM 的解码算法,模型参数保持不变【1】。因此,解码策略通常具有从业者更容易获得且成本更低的优势。
策略名称中的链接指向解释它们的博客文章(如果有的话)或介绍这些方法的原始学术论文。
领域自适应预训练(DAPT)
基于数据的策略:使用无毒数据集 [https://arxiv.org/pdf/2004.10964.pdf 1 , 9 , 10 对 LM 进行额外的预训练。优势:最有效的减毒策略之一【1】。局限性:计算量大【1】。需要用于训练的额外数据,当通过众包利用人类时,收集这些数据可能会很昂贵。
属性条件(基于 CTRL )
基于数据的策略:使用添加了“有毒”或“无毒”属性的训练样本进行进一步的 LM 预训练。在推断(文本生成)过程中,属性“无毒”可以添加到给予模型【1】的提示中。局限性:计算开销大。不如 DAPT、PPLM 和词汇转换【1】有效。
阻止列表(文字过滤)
基于解码的策略:在 LM 中,不需要的单词——如诅咒语、亵渎语和侮辱语——被分配零概率,以防止它们被生成(参见【1】和此处)。优点:易于实现。局限性:没有这些词的毒性仍然会发生。这些词可以被接受使用的上下文被忽略。
词汇转移
基于解码的策略:使用模型词汇中每个记号的毒性和非毒性的二维表示来提高生成非毒性记号的概率【1】。优势:显示出比阻断列表【1】更好地降低毒性。限制:实现起来比阻止列表更复杂。
照片由 Breanna Louise 在 Unsplash 上拍摄
即插即用语言模型(PPLM)
基于解码的策略:使用一个简单的模型(词袋或单层分类器)作为鉴别器(或属性模型),通过改变 LM 的隐藏表示来指导其语言生成[ 1 , 11 ]。优点:最有效的减毒策略之一【1】。限制:计算量非常大。
生成鉴别器(GeDi)
基于解码的策略:使用属性条件(或类别条件)LM 作为鉴别器,它使用贝叶斯规则为主 LM 可以生成的所有潜在的下一个令牌计算类别可能性(例如,有毒或无毒)。优势:计算效率比 PPLM 高。在解毒方面胜过 PPLM。局限性:仍然是比较复杂的策略之一。
自去偏置
基于解码的策略:通过在提供给 LM [ 13 ]的输入提示前添加一个简短的属性描述(如“以下文本包含毒性”),使用自去偏置算法来降低有毒单词产生的概率。优势:与 CTRL 策略相比,不需要额外的培训。 限制 :该策略目前仅使用 Perspective API 提供的毒性和偏差属性进行评估。它经常过滤掉无害的单词。它的解毒能力受限于模型对相关偏差和毒性的“意识”[ 13 ]。
在受控世代的保护伞下,还有各种其他降低毒性的策略[ 11 ] 文本风格转移 是一种将有毒句子翻译成无毒版本的相关方法。然而,它的主要应用一直与解决人类在社交媒体上产生的有毒文本有关,而不是消除语言模型的毒性。
Gehman 等人【1】在他们的调查中发现,网络文本语料库和神经语言生成都包含大量的有毒内容。他们的结果表明,没有一种解毒策略能清除所有的有毒语言。然而,这些策略降低了毒性分数和在 25 个文本生成中产生一次毒性评论的概率。总的来说,这显示了基于解码的方法的前景,同时也强调了为语言模型仔细选择预训练数据集的重要性。
5.解毒和语言模型的伦理考量
Julia Nikulski 创作的图表展示了偏见对语言解毒的影响。从 Flaticon 中 Vitaly Gorbachev 、 Smashicons 、dinosoftlab、 Becris 和 Freepik 制作的图标。
第 2 节简要地谈到了毒性检测中的偏见问题,这种偏见经常以少数人的言论被误认为有毒为代价。这种偏见也存在于解毒的语言模型中。如果少数民族身份提及和少数民族方言被解毒策略归类为有毒,那么少数民族和 NLP 系统之间的交流就会受阻。LMs 无法理解和响应用户提示可能被视为微侵犯[ 10 ]。
在无毒的环境中,有偏见的解毒也会导致回避某些话题,如宗教或性别。当用户与 NLP 系统交互时,这种回避可能会导致自我污名化,因为他们可能会觉得自己的身份和现实无关[ 10 ]。因此,开发语言模型的解毒技术以及以减少偏差的方式设计它们是至关重要的。
妇女和少数群体成员参与设计过程有助于提高认识,减少这些系统中的偏见。此外,如果仔细选择,用于语言模型和解毒策略的预训练的数据集可以减少毒性和偏差。由谁来决定对哪些数据语言模型进行训练是一个复杂的问题,没有简单的答案。但是,需要讨论。
另外,在创建数据集时需要考虑标注和10。注释偏差意味着负责创建标记数据集和确定句子毒性的人类可能会错误地将少数民族方言标记为有毒。抽样偏见增加了偏见解毒,因为有毒语言往往针对少数群体,在少数群体身份提及和有毒词语之间建立了关联。
照片由亚历山大拉·博古斯拉夫斯卡在 Unsplash 拍摄
最后的想法
语言模型中的毒性是一个比我预期的更加复杂和广泛的话题,无论是从技术实现还是伦理考虑。喷出仇恨和有毒语言、放大刻板印象和社会偏见的语言模型不利于公共话语、心理健康和民主制度。同时,有偏见的解毒策略会导致某些话题和无毒语言的污名化,压制少数群体的声音。因此,实现负责任、无毒且无偏见的 LMs 需要细微差别、偏见意识以及最终用户参与模型设计的所有步骤。
在写这篇文章的时候,我考虑了我处理 NLP 模型的责任。这项研究告诉我,让语言模型面向用户可能会有严重的影响,应该经过深思熟虑。我还决定不发表在我的 36 问题项目中产生的任何有害内容,因为我不希望未来通过抓取网络创建的任何数据集包含这些有问题的例子。
你想在媒体上阅读更多高质量的故事吗?考虑注册一个支持我和其他媒体作者的会员。
https://medium.com/@julia.nikulski/membership
您是否希望展示您的数据科学项目,但不确定如何展示?查看我的指南如何建立数据科学组合网站:
学术论文参考文献
[1]盖曼,s .,古鲁兰根,s .,萨普,m .,崔,y .,史密斯,N. A. (2020)。真实毒性提示:评估语言模型中的神经毒性退化。 计算语言学协会的发现:EMNLP 2020 ,3356–3369。
[2]梅,c .,王,a .,博迪亚,s .,鲍曼,S. R .,&鲁丁格,R. (2019)。在句子编码器中测量社会偏见。计算语言学协会北美分会 2019 年会议论文集:人类语言技术,第 1 卷(长短论文),622–628。
[3] Dhamala,j .,Sun,t .,Kumar,v .,Krishna,s .,Pruksachatkun,y .,Chang,K.-W .,& Gupta,R. (2021)。 BOLD:用于测量开放式语言生成偏差的数据集和指标。《2021 年美国计算机学会公*、问责和透明会议论文集,862–872 页。
[4] Pavlopoulos,j .,Sorensen,j .,Dixon,l .,Thain,n .,Androutsopoulos,I. (2020 年)。毒性检测:环境真的重要吗?ArXiv:2006.00998【Cs】。
[5]瓦伊迪亚,a .,麦,f .,&宁,Y. (2020)。多任务学习降低有毒评论检测中模型偏倚的实证分析。ArXiv:1909.09758【Cs】。
[6]周,x .,Sap,m .,Swayamdipta,s .,Smith,N. A .,,Choi,Y. (2021)。有毒语言检测自动化去偏的挑战。ArXiv:2102.00086【Cs】。
[7] Sheth,a .,Shalin,V. L .,& Kursuncu,U. (2021 年)。定义和检测社交媒体的毒性:背景和知识是关键。ArXiv:2104.10788【Cs】。
[8]t . Dias Oliva,d . m . Antonia lli 和 a . Gomes(2021 年)。战斗仇恨言论,消音变装女王?内容调节中的人工智能与 LGBTQ 在线之声的风险。 性&文化, 25 (2),700–732。
[9] Gururangan,s .,Marasovi,a .,Swayamdipta,s .,Lo,k .,Beltagy,I .,Downey,d .,和 Smith,N. A. (2020 年)。不要停止预训练:让语言模型适应领域和任务。ArXiv:2004.10964【Cs】。
[10]徐,a .,帕塔克,e .,华莱士,e .,古鲁兰根,s .,萨普,m .,&克莱因,D. (2021)。去除语言模型的毒性有边缘化少数群体声音的风险。ArXiv:2104.06390【Cs】。
[11] Dathathri,s .,Madotto,a .,Lan,j .,Hung,j .,Frank,e .,Molino,p .,Yosinski,j .,和 Liu,R. (2020 年)。即插即用语言模型:控制文本生成的简单方法。ArXiv:1912.02164【Cs】。
[12] Krause,b .,Gotmare,A. D .,McCann,b .,Keskar,N. S .,Joty,s .,Socher,r .,& Rajani,N. F. (2020 年)。 GeDi:生成鉴别器引导的序列生成。ArXiv:2009.06367【Cs】。
[13]茨韦塔纳·希克、乌杜帕和舒茨(2021 年)。自我诊断和自我去偏见:一个减少自然语言处理中基于语料库的偏见的建议。ArXiv:2103.00453【Cs】。
TPU 培训
原文:https://towardsdatascience.com/tpu-training-6eb84100d138?source=collection_archive---------16-----------------------
思想和理论
利用专用 DNN 训练芯片的力量
由费迪南·斯托尔在 Unsplash 上拍摄的照片
过去十年深度学习成功背后的驱动力之一是图形处理单元(GPU)提供的巨大计算能力。虽然最初是为将图像渲染到显示设备而设计的,但它们的高度并行结构使训练速度提高了几个数量级。随着时间的推移,GPU 得到了增强,以满足 DNN 培训不断增长的需求。今天,它们是训练大规模人工智能的主要方法。然而,在过去的几年中,潜在的挑战者已经以专门为训练 DNNs 设计的新芯片的形式出现。这些芯片(或 ASIC——专用集成电路——更恰当的称呼)可能会以很小的成本实现加速训练。虽然市场上已经有许多专门的人工智能 ASICs(例如,见这里的)和许多其他的正在形成中(例如,见这里的),但在撰写本文时,只有少数几个通过云服务提供给公众。这种情况有望在不久的将来发生改变,例如 Habana Gaudi 即将在 AWS 上发布以及备受期待的 AWS Trainium 。
对于现代机器学习开发团队来说,要保持竞争力,他们需要不断掌握新进展的脉搏。这包括在评估新的人工智能芯片及其在自己项目中的潜在应用时发展高水*的熟练程度。不幸的是,让你的训练工作量适应新的芯片有时会很有挑战性。这篇博文的目的是为如何应对这一挑战提供一点指导,同时也提供一些情感上的支持。这篇文章并不是要取代在线的官方文档和教程。
我要感谢 Allen Wang 和 Yitzhak Levi 对这篇文章的贡献。
序幕
在本帖中,我们建议将让你的模型适应新的人工智能芯片的挑战分解为四个步骤:
- 高级兼容性分析:对您的工作负载特性是否符合芯片规格进行早期评估。
- 调整你的模型在新的芯片上运行:你可能需要对你的模型做一些调整,比如替换专用 AI 芯片不支持的操作。
- 优化新芯片的运行时性能:有趣的事情开始了……为了充分利用芯片,您需要分析并最大限度地提高其利用率。
- (重新)调整模型以收敛:先前步骤中所需的更改(例如增加训练批量)可能需要调整模型超参数(例如学习率),以确保及时收敛。
显然,这种分类是一种简化。实际上,您可能会发现自己在迭代地和/或并行地执行这些步骤。例如,您可能决定将优化运行时的任务交给性能分析专家,而另一组数据科学家则致力于调整您的学习算法,以收敛于大批量训练(例如,在 GPU 上使用大批量模拟以最大限度地降低成本)。
在接下来的几节中,我们将通过将这四个步骤应用到谷歌云 TPU DNN 加速器来更详细地演示它们。更具体地说,我们将讨论当您尝试使用 TensorFlow 版转换您的模型以在云 TPU v3–8(包含 8 个 TPU 内核)上运行时可能面临的一些挑战。虽然我们是在特定的人工智能芯片和特定的训练框架上进行分区,但我们讨论的许多考虑因素也适用于其他人工智能芯片和其他训练框架。
你可以在计算引擎上启动云 TPU(如这里描述的)或者使用托管服务,如人工智能*台。对于本帖中描述的步骤,我们强烈建议在计算引擎上运行云 TPU。这将使调试和分析性能更加灵活。在撰写本文时,托管 API 不提供对 TPU 系统日志和 TPU 系统性能的相同可见性,不支持您捕获性能配置文件,也不支持使用 tf.data.service 卸载数据预处理。启动您的 TPU 时,请务必仔细按照说明进行操作,因为有一些细微之处是 TPU 设置所独有的(例如 TPU 专用服务账户)。
重要的是要记住,DNN 的发展前景仍然极具活力。当你读到这篇文章时,我们提出的一些观点可能已经过时了。请确保关注新版本和新工具的发布,并确保根据最新可用信息做出设计决策。
请原谅你可能遇到的任何不准确之处,或者更好的是,给我写信,告诉我你的更正。
步骤 1 —高级兼容性评估
自然,你想做的第一件事是尝试开发一个感兴趣的人工智能芯片是否与你的用例相关的早期评估。让你的模型适应新芯片的努力可能是巨大的,你越早排除某个死胡同越好。这种初始评估通常可以根据在线资源得出,包括系统规格和性能指标评测:
ASIC 描述
一个好的起点是专用硬件的公开描述。这通常包括训练芯片的功能:支持什么模型层和架构、使用什么浮点类型、需要什么软件堆栈、芯片如何与 CPU 和数据存储接口、计算核心是否以及如何互连、硬件扩展到多核训练的程度等。此描述可用于识别与您的模型的潜在不兼容性。您可能会发现可用内存不能满足您的模型大小的需要,或者不支持您的训练可扩展性需要。在这种情况下,不要再往前走了。
云 TPU 文档包含关于使用 TPU 的大量信息,包括 TPU 编程模型和最适合 TPU 的工作负载类型。从这些资源中,您可能会得出这样的结论:TPU 不适合您的模型,例如,因为它们依赖于自定义 ops、高精度算术或大量的元素操作。
当心基准
您可能想了解的另一个资源是在线性能基准比较。在各种常见架构(包括 ResNet、MaskRCNN、Bert 等)上,您不难找到 TPU 与 GPU 的性能对比。不幸的是,弄清楚如何将这些结果应用到您自己的用例中是非常困难的。
首先,不言而喻的是,芯片制造商提供的基准应该以合理的怀疑态度对待。但是,即使是你认为公正的分析也可能极难解读。在某种程度上,这可以说是任何学科中的基准比较,但在深度学习领域尤其如此,因为有大量因素可以对性能产生有意义的影响。首先是运行时环境 CPU 内核的数量及其类型、操作系统、驱动程序版本、操作系统、软件框架类型和版本——这些单独的元素中的每一个都可以单独影响性能几十个百分点。然后是模型:即使您自己的模型体系结构与基准测试中最相似的模型之间存在最微小的差异,无论是在图形体系结构、输入数据格式、预处理管道、损失函数还是优化器方面,都会对性能产生巨大的影响。质量基准比较将包括有关已进行评估的精确属性的详细信息。但是,它们不太可能涵盖影响性能的所有参数。
MLPerf : MLPerf 是一个经常被引用的人工智能训练和推理的基准套件,目前由 MLCommons 财团管理。本白皮书详细介绍了创建培训基准的理由以及参与规则。从对基准测试结果的粗略回顾中可以明显看出,该基准测试影响深远,涵盖了广泛的培训环境和模型架构。然而,如上所述,鉴于每个测试用例有许多不同的参数,您可能会发现很难推断出 AI 芯片之间的清晰比较,更不用说将这些结果应用到您自己的特定用例中了。我发现这些结果需要进行解释(例如参见这篇综述),尤其是考虑到 ASICs 之间的潜在价格差异时(这些差异不包括在原始比较结果中)。
例如,MLPerf 基准测试的所有迹象都让人相信 8 个 NVIDIA A100 GPU 核心将远远超过 TPU v3–8(包含 8 个 TPU 核心)。然而,最*我们在一个模型上工作,与评论中涉及的模型没有什么不同,在这个模型上,TPU 运行实际上匹配,甚至略优于我们最知名的 A100 GPU 运行配置。这个模型似乎完全符合 TPU 的规格。与此同时,对这个模型的小改动会极大地改变它的 TPU 兼容性,并大大增加步进时间。MLPerf 报告没有给出这两种极端结果的任何指示。
虽然我们认识到人工智能培训基准评估的重要性和价值,但我们认为承认它们在预测评估中包含的特定测试案例之外的性能方面的局限性也很重要。
系统架构规范
如果完整的系统规格可用,您还有一个选择,就是通过对您的模型在专用硬件上的运行方式进行离线模拟,来尝试规划您的培训步骤的运行时间。这种分析需要对系统架构和 DNN 模型有深入的了解。我认识许多人,他们通过创建基于参数矩阵大小、触发器数量、内存大小、L2 缓存延迟等精确性能预测的电子表格,过上了不错的生活。根据我的经验,这种预测往往是“命中或错过”,在复杂的机器学习工作负载的情况下,更多的时候是“错过”。
跳进深水区
当该说的都说了,该做的都做了,除了堕落和肮脏,真的别无选择。虽然我承认有些人可能厌倦了走在潜在的死胡同的道路上,但我相信,即使您最终没有在 TPU 上训练您当前的模型,随着您的项目的发展和更多 ASICs 的出现,您在这个过程中发展的专业知识几乎肯定会很好地服务于您和您的团队。
第二步——调整你的模型以在 TPU 上运行
为了在定制的 ASIC 上成功运行,您可能需要对您的 AI 应用程序进行更改。需要改变的程度将取决于许多因素,包括 ASIC 软件堆栈的成熟度和支持的操作范围。定制 ASICs 可能会对 AI SW 开发*台或版本施加严格限制,这可能需要进行重大调整。您应该始终努力使用最新的软件包,因为这些包可能包含最广泛和最佳的 API 支持。TPU 享有相对健康的软件堆栈和大型开发人员社区的优势(这两者通常是相互关联的)。然而,它们可能仍然需要适应您的数据输入管道和计算图。我们将在下面的小节中演示几个例子。首先,我们将指出定制 ASICs 调试中潜在的复杂性。
为 TPU 调试
GPU 培训的一个显著优势是,模型设计和调试的重要部分可以在 CPU 上执行。如果你能在 CPU 上编译你的模型,那么 100 次中有 99 次你的模型在 GPU 上是有效的(有足够的内存)。这是现代人工智能开发人员经常想当然的事情。定制 ASICs 不一定是这种情况。这样做的结果是,通常需要直接在定制 ASIC 上进行调试,这可能会影响成本和/或持续时间。或者,ASIC 制造商可能会提供一个模拟框架,用于识别和修复可能在 CPU 上运行的潜在问题。理想情况下,这种模拟框架还将提供如何最大化 ASIC 利用率的指导。不幸的是,在撰写本文时,官方的 TPU 模拟框架还不存在。虽然可用的文档和工具可能有助于构建一个 TPU 兼容的模型,但直到你在 TPU 上运行它,你才能确定。
您可能面临的另一个困难是理解 TPU 报告的错误消息。正如我们在过去的的中提到的,破译 TensorFlow 错误信息可能很难。TPU 上的错误消息,无论是那些报告给控制台的,还是那些通过云监控可访问的,往往都特别隐晦(截至本文撰写之时)。我们将在下面的章节中提供一些例子。
更新您的数据输入管道
尽管数据输入管道在 TPU 的主机 CPU 上运行,而不是在 TPU 本身上运行,TPU 系统架构对可以执行的操作施加了某些限制。启动 TPU 的标准方式依赖于通过 gRPC 与 TPU 主机通信的专用虚拟机。这种架构的后果之一是不允许任何自定义操作符或任何基于 python 的数据处理函数。这禁止使用 tf.py_function 和 tf.numpy_function ,它们通常用于绕过本机 TensorFlow API 施加的限制。它还禁止使用TF . data . dataset . from _ generatorAPI,该 API 通常用于增加输入数据集创建的灵活性。
不幸的是,在撰写本文时,如果您的输入管道图无效,您很可能会得到一个模糊的 gRPC 错误消息,就像下面的块中的消息一样,您将不得不自己寻找罪魁祸首。
W ./tensorflow/core/distributed_runtime/eager/destroy_tensor_handle_node.h:57] Ignoring an error encountered when deleting remote tensors handles: Invalid argument: Unable to find the relevant tensor remote_handle: Op ID: 22643, Output num: 7Additional GRPC error information from remote target /job:worker/replica:0/task:0::{"created":"@1632916556.697142899","description":"Error received from peer ipv4:10.11.250.138:8470","file":"external/com_github_grpc_grpc/src/core/lib/surface/call.cc","file_line":1056,"grpc_message":"Unable to find the relevant tensor remote_handle: Op ID: 22643, Output num: 7","grpc_status":3}
TPU 常见的另一种输入管道错误与数据输入的大小有关,它会导致同样不明确的消息。正如我们将在下面看到的,有效利用 TPU 可能需要比您以前习惯的更大的批量。如果没有在输入数据管道上正确处理,您可能会遇到 CPU 内存问题。例如,如果每个输入样本是 1 MB,而您的全局批处理大小是 4096,那么您的批处理大小将是 4 GB。解决这个问题的一个方法是修改您的数据管道以生成“本地”批处理而不是“全局”批处理;也就是说,创建每个内核批量大小的批。这可以使用TF . distribute . strategy . distribute _ datasets _ from _ functionAPI 来完成。在我们的示例中,批量大小是 0.5 GB,这是一个更容易管理的大小。
TPU-越南船民——救世在即:
今年 6 月,谷歌宣布一个新的云 TPU 架构,名为云 TPU 虚拟机。与最初的架构相反,被称为 TPU 节点、 TPU 虚拟机,允许对 TPU 主机的直接 SSH 访问,不需要中间虚拟机。其含义是深远的。这不仅消除了对数据输入管道创建的限制,还极大地提高了我们调试和分析输入管道性能的能力。此外,删除中间虚拟机可能会减少网络开销并提高性能。
新架构已经可以在“预览”模式下使用。根据我们的经验,它还没有完全成熟。但是未来看起来是光明的。
更新您的模型图
在 TPU 上训练您的模型可能还需要更改在 TPU 核心上运行的计算图。在这一节中,我们将演示为了符合 API 限制或 TPU 内存限制而可能实施的更改。
TensorFlow Op 限制:
ASIC 对支持的 Op 施加限制并不少见。这些限制可能来自硬件实施或支持软件堆栈的限制。TPU 文档包括一个支持(和不支持)TensorFlow 操作的列表。不幸的是,(在撰写本文时)这个列表自称是不完整的。 TensorBoard 的图形可视化工具包括一个 TPU 兼容性选项,如下图所示,但根据我们的经验,该测试并不完全可靠。只有当您尝试运行图表时,您才可能收到图表无效的第一个指示。
TPU 兼容性图(图片来自 GCP 在线文档
TPU 限制包括对使用自定义运算符和可能导致张量形状不确定的运算的限制:
定制操作— 在 GPU 上进行培训的优势之一是,它支持在软件堆栈的各个级别进行定制。你可以创建自己的基于 python 的操作(例如使用 tf.numpy_function )或者你可以在 CUDA 中创建自己的 GPU 内核。这种程度的灵活性在实现中非常有用:TensorFlow 本身不支持的操作,或者专门为您的用例优化的 GPU 内核。这些能力在 TPU 是缺乏的(在撰写本文时)。如果您的图包括这些类型的定制,您将需要用本地操作来替换它们。下面的块包含一段摘录,摘自您在图形包含一个 tf.numpy_function 调用的情况下可能会遇到的错误消息类型。
(0) Invalid argument: {{function_node __inference_train_function_117771}} Detected unsupported operations when trying to compile graph cluster_train_function_10723333522471149816[] on XLA_TPU_JIT: **PyFunc** (No registered '**PyFunc**' OpKernel for XLA_TPU_JIT devices compatible with node {{node model/segLoss/PyFunc}}){{node model/loss/PyFunc}}
导致形状不确定的张量的操作 —与 GPU 相反,TPU 不允许某些 API,因为它们使用非静态形状的张量。需要注意的是,最*的 TensorFlow 版本已经扩展了对此类操作的支持。然而,尽管受到支持,其中许多在 TPU 上表现很差,你应该尽量避免它们。
下面是一个在 TPU 失败的代码摘录的例子(摘自以前的博客文章):
shape = [None,1]
dtype = tf.float32
record_tensor = tf.Variable(
shape=shape,
*# initialize with batch size 1 since batch_size
# is unknown, and set validate_shape=False*
initial_value=tf.zeros(shape=[1]+shape[1:],
dtype=dtype),
validate_shape=False,
dtype=dtype,
trainable=False)
要为 TPU 修改它,我们需要修正 batch_size 并将 validate_shape 改为 True 。在这种情况下遇到的错误类似于:
tensorflow.python.framework.errors_impl.InvalidArgumentError: Dst node should be assigned to an allowed device.
导致未确定形状的张量的 API 的一个经典例子是 tf.boolean_mask 。假设我们正在处理一个分割模型,该模型将图像作为输入,并为每个像素生成一个标签。我们可能希望从我们的损失计算中屏蔽掉图像的某些区域(由于它们的模糊性或低水*的兴趣)。在 GPU 上,tf.boolean_mask 具有移除与这些区域上的损失计算相关联的所有操作的效果,并且可以显著提升性能。虽然 TensorFlow 最*增加了对 tf.boolean_mask 的 TPU 支持,但通过计算所有像素的损失并在被遮罩的区域将结果值清零,您可能会获得更好的性能,如下面的代码块所示:
# given input logits, lables, mask and loss_fnif tpu:
# zero out pixels according to mask
mask = tf.cast(mask, logits.dtype)
logits = logits * mask
labels = labels * mask
else:
# reduce number of loss_fn operations using tf.boolean_mask
logits = tf.boolean_mask(logits, mask)
labels = tf.boolean_mask(labels, mask)
sumLoss = tf.reduce_sum(loss_fn(logits, labels))
TPU 内存限制 :
当您将模型加载到 TPU 时,您可能会惊讶地发现,模型所需的内存量大大超过了 GPU 所需的内存量。出现这种情况的原因很可能是内存填充。我们将在下一节进一步讨论填充的主题。在下面的代码块中,我们演示了在内存需求超过可用 TPUv3 内存(每个内核 16 GB)的情况下预期的错误类型。我们选择了一个极端的例子,填充将内存利用率提高了大约 3 倍,从 6.4GB 提高到 19 GB 以上。
(0) Resource exhausted: {{function_node __inference_train_function_80576}} Ran out of memory in memory space hbm. **Used 19.46G of 15.48G hbm. Exceeded hbm capacity by 3.98G**.
Total hbm usage >= 19.98G:
reserved 530.00M
program 19.46G
arguments 0BOutput size 0B; shares 0B with arguments.Program hbm requirement 19.46G:
global 276.0K
scoped 173.0K
HLO temp 19.46G (33.1% utilization: **Unpadded (6.40G) Padded (19.32G)**, 0.7% fragmentation (147.91M)) **Largest program allocations in hbm**:
1\. Size: 14.00G
Operator: op_type="OneHot" op_name="model/loss/one_hot"
Shape: s32[29360128,10]{1,0:T(8,128)}
Unpadded size: 1.09G
Extra memory due to padding: 12.91G (12.8x expansion)
XLA label: %iota.2 = s32[29360128,10]{1,0:T(8,128)} iota(), iota_dimension=1, metadata={op_type="OneHot" op_name="model/loss/one_hot"}
Allocation type: HLO temp
========================== 2\. Size: 2.62G
Operator: op_name="model/layer_1/Conv2D"
Shape: f32[128,256,896,18]{0,3,2,1:T(8,128)}
Unpadded size: 1.97G
Extra memory due to padding: 672.00M (1.3x expansion)
XLA label: %fusion.9.remat.1.remat = f32[128,256,896,18]{0,3,2,1:T(8,128)} fusion(f32[1,1,8,18]{3,2,1,0:T(8,128)} %get-tuple-element.4316, f32[18]{0:T(256)} %get-tuple-element.4085, f32[128,256,896,8]{0,3,2,1:T(8,128)} %get-tuple-element.3899, f32[8]{0:T(256)} %rsqrt...
Allocation type: HLO temp
==========================
错误消息包括最大内存分配的列表。在这种情况下,我们看到单个操作导致了 12.91GB 的额外填充。
除了重新设计您的模型以适应内存需求之外,一个令人信服的选择是用混合精度编译您的模型,并将混合精度策略设置为 mixed_bfloat16 。默认情况下,所有变量都存储为 tf.float32,这是一种 32 位浮点表示形式。Bfloat16 是由 Google 创建的 16 位浮点表示。参见此处了解格式及其动态范围的详细信息。当您修改您的模型以使用混合精度时,激活和梯度存储为 tf.bfloat16,而权重保留在 tf.float32 中。这可以大大降低您的模型的内存需求,同时提高运行时性能。
根据 Google 的研究报告,大多数模型的收敛性不会受到 tf.bfloat 的影响。但是,如果您选择了这个选项,您应该意识到这种可能性。我们将在本文的第 4 步进一步讨论这个问题。
步骤 3-优化您的模型以在 TPU 上执行
此时,您应该能够在 TPU 上成功运行一个训练周期。接下来是性能分析和优化的关键步骤。一个人工智能加速器的好坏取决于它为性能分析提供的工具。如果你不能分析性能,你就不能充分利用人工智能芯片。
在之前的博客文章中,我们详述了性能分析的重要性,并演示了张量流分析器和张量板的使用。同样的技术也可用于分析 TPU 的性能。TPU 文档包括一个详细的指南,介绍如何在 TPU 获取个人资料并在 TensorBoard 中分析结果。该文档还包括一个指南,介绍如何设计您的模型以优化 TPU 利用率。在本节中,我们将根据自己的经验重点介绍一些性能技巧。要了解更多细节,你应该回头参考这两个重要的指南。
减少填充的开销
要了解 TPU 最重要的特性之一是张量在内存中的存储方式。未能根据 TPU 的内存*铺方案调整您的模型会导致大量的内存填充开销,这转化为未实现的潜力。在评估填充开销时,最重要的资源是 TensorBoard profile 页面上的 memory_viewer 选项卡。在下图中,我们展示了这个页面的一个例子。红色曲线显示未填充的内存利用率,蓝色曲线显示填充的内存利用率。在本例中,填充导致的内存占用大约是实际使用的内存大小的 4 倍。
摘自 TensorBoard(作者)
TPU 文档提供了关于如何最小化填充开销的指南。简化版是这样的:
- 使用 128 的倍数的(每个内核)批处理大小,并且
- 将每个图层的输出要素的维度设置为 8 的倍数。
当然,这可能并不适用于所有型号,在这种情况下,文档中会有更多的建议。不要忘记,正如我们在上面看到的,你可以选择启用混合精度,以增加将一批 128 大小的数据放入 TPU 存储器的可能性。
优化输入数据管道
可以用来测量训练系统与给定模型的兼容性的参数之一是主机将训练批次馈送到加速器中的能力(例如,通过每秒批次来测量)与加速器处理输入批次的能力之间的比率。io 带宽、输入管道中的数据处理操作量、CPU 内核的数量和类型以及加速器的速度都会影响这一比率。如果该比率小于 1,您可能会遇到输入管道瓶颈。在这种情况下,加速器在等待输入数据时将保持空闲,宝贵的计算周期将被浪费。这是一种不理想的情况,我们已经在之前的帖子中对此进行了阐述。
在 TPU 上训练时,由于其消耗数据的速度很快,您在数据准备管道上遇到瓶颈的可能性可能会增加。即使您的输入管道不包括繁重的处理,被解析、混洗和批处理的大量数据也很容易阻塞 CPU 资源。通过使用 tf.data.service 卸载到辅助 CPU 可能会减轻一些负担。(参见此示例,了解如何使用 TPU)。然而,它并不是在所有情况下都有帮助,您可能需要求助于更具创造性的解决方案,包括:调整分配给管道不同部分的进程数量,更改数据的格式和/或精度,或将计算转移到 TPU 上。
递增 steps_per_exec
最*,TensorFlow 在 tf.keras.Model.compile 输入参数中添加了 steps_per_exec 标志。此设置控制每次调用内部训练函数时运行的训练步骤数。增加该数字可以减少 TPU 和主机之间的通信开销,最终提高性能。不过要记住的一点是,这将影响你进入训练回调函数的时间间隔。例如,如果您的回调类跟踪训练期间输入的批次数量,那么每次调用 on_batch 函数时,该值应该增加 steps_per_exec 而不是 1 。更多细节参见文档。
你在一个定制的人工智能中发现的价值将在很大程度上取决于你在优化你的模型以有效使用它方面的成功。这种优化需要时间和精力,因此应该相应地进行规划。
第四步——调整你的模型,向 TPU 靠拢
如果你已经完成了这一步,那么你已经成功地在专用的 AI ASIC 上以你满意的速度运行了你的模型。为了达到这一步,您可能已经对您的模型进行了一些更改。您可能更换了一些操作员,重新格式化了您的数据,增加了您的批量,或者应用了混合精度。最后一步是验证你的模型成功收敛。这可能需要调整您的模型超参数,调整您的学习率,或者更换您的优化器。
即使您没有进行任何更改,这最后一步也是必需的。这是因为不同的硬件加速器以不同的方式实现,这可能会导致它们的行为存在数值差异。在一个 ASIC 上的收敛并不保证在另一个上的收敛。例如,TPUs 的高性能归功于它使用了较低精度的浮点类型 bfloat16(参见此处的)。您的模型可能对这种精度下降很敏感,在这种情况下,您需要重新调整它以收敛。
批量增加
为了充分利用 TPU,您可能需要将批量增加到超出您习惯的水*。您的模型可能对训练批次大小很敏感,对其进行调整以收敛(在相同数量的数据遍历上)可能会带来巨大的挑战。查看我们之前的博客文章了解更多关于这个话题的细节。
摘要
将你的模型转换为在定制的人工智能芯片上运行,可以节省大量的培训成本。然而,这可能需要相当大的努力。在这篇文章中,我们将重点放在 TPU 的训练上。在这一过程中,你可能会遇到各种各样的挑战。我们只讨论了几个例子。请务必参考丰富的在线文档以了解更多详细信息。
Tqdm、Pytorch 和 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨:通过智能手机查看培训
原文:https://towardsdatascience.com/tqdm-pytorch-and-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-check-training-from-your-smartphone-722566918ff6?source=collection_archive---------22-----------------------
让你的训练循环变得智能且易于使用
用电报机器人控制管道——图片由作者提供
无论你已经在深度学习领域工作了多年还是仅仅几个月,你无疑都会遇到一个典型的数据科学家的问题:监控你的模型的训练。
我开始直接在 Jupyter 笔记本里训练我的算法,间歇性地检查损失函数的趋势和准确性,希望观察谁知道趋势中的什么。我喜欢看训练曲线上下起伏。我会让你猜猜我在这上面浪费了多少时间,看着 Tensorboard 里面的曲线看得入迷。
然后我转向更结构化的方法,使用 python 和 bash 脚本,试图优化管道:但是主动监控训练的需求仍然存在。
监控长训练流水线的执行是节省时间和最大化性能的关键任务。
❌错误监控
- 浪费你的时间:我们不会中断无用的模拟,也不会注意到分歧
- 浪费你的金钱:运行模拟的电力或集群的成本
- 浪费你的精神健康:我们都想知道我们的算法表现如何
可以执行✅适当的监控
- 通过可以通过 CLI 定期检查的日志文件
- 通过张量板等功能接口
- 通过自定义界面
照片由威廉·胡克在 Unsplash 拍摄
因此,在这篇文章中,我们将看到如何将监控带在身边:使用一个著名的消息*台 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 的机器人,再加上 Tqdm 和 PyTorch 。
Tqdm 表示进度
Tqdm 在阿拉伯语中是“进步”的意思( taqadum ,تقدّم),在西班牙语中是“我如此爱你”的缩写( te quiero demasiado )。
对于监控 python 中的循环来说,这是一个非常方便的工具。你只需要传递一个 iterable 作为参数,就大功告成了!
tqdm 应用示例—作者图片
我发现这个工具非常方便,我已经开始在任何地方使用它,甚至在普通编程中,因为它允许你方便地监控任何迭代。
迪米特里·卡拉斯泰列夫在 Unsplash 拍摄的照片
在这个工具的各种功能中,与 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 的简单集成,“一个免费的、跨*台的、基于云的即时通讯服务”脱颖而出。我经常使用 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 进行常规信息传递、文件传输或应用程序提供的大量机器人和服务。这就是为什么我发现在这个*台上创建一个机器人来监控我的代码的可能性非常有趣。
电报用 Tqdm
使用 python 语言创建一个与之交互的机器人既简单又直观。遵循官方文件中的规定就足够了:
创建一个机器人
要创建这个机器人,你需要在 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 上搜索机器人父亲。
机器人父亲是统治他们所有人的机器人。使用它来创建新的机器人帐户和管理您现有的机器人。
使用下图所示的简单命令集,我们可以创建一个新机器人:只需指定名称和用户名(注意:它必须是唯一的)。然后我们会收到一个用于我们机器人的令牌,但是要小心!这个令牌是私有的,不应该被共享。它将用于集成到我们的 python API 中,以及修改机器人的名称、图像和各种属性。
父亲对话—作者图片
然后,我们在应用程序上通过名字搜索我们的机器人,并与他开始对话。用命令 /start 启动它。为了与机器人通信,我们需要我们刚刚创建的聊天的标识符。我们可以在“聊天 id”下找到它:
https://api.丨t丨e丨l丨e丨g丨r丨a丨m丨s丨.org/bot
[{token}](https://api.丨t丨e丨l丨e丨g丨r丨a丨m丨s丨.org/bot%7Btoken%7D/getUpdates)
/get updates
完成了!我们只需要使用通过这种方式获得的令牌和 chat_id 就可以在我们与机器人的聊天中直接接收。我们将像在正常对话中一样收到通知,在聊天中获得一个方便的进度条。
Tqdm 和电报集成—图片由作者提供
我测试了这个程序,用于训练一个用 PyTorch 构建的卷积神经网络进行图像分类。我发现 PyTorch 对于实现定制训练循环非常方便,因此特别适合于实现这种监控策略。同时,我们可以在一个自定义 Tensorflow 回调内使用这些调用。
使用 Pytorch、tqdm 和 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 定制训练循环—图片由作者提供
添加更多消息
之前创建的机器人允许我们向机器人发送任何文本消息。我们可以创建损失或准确性日志,或通知,以了解新模拟何时启动或何时完成。为此,我们使用 python 包 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-send ,可以通过以下方式安装:
pip 安装电报-发送
配置非常简单,类似于我们之前为 bot 所做的:在我们的 CLI 或笔记本中,我们启动配置:
电报-发送-配置
我们将被要求提供机器人的秘密 令牌,然后向机器人本身发送一条特定消息(5 个数字字符)以确认激活。一旦完成,将有可能自动生成任何文本消息。
用电报发送一条普通信息-发送-作者图片
总结
在本文中,我们看到了如何创建一个电报 机器人,它可以与 tqdm 接口,这是 Python 中一个很棒的可迭代管理包。我们看到了如何将其集成到 Pytorch 、 Tensorflow 、训练循环 …以及如何将文本、消息直接从代码发送到我们的智能手机。
苹果手表通知和机器人快照——图片由作者提供
📚在我的个人资料上阅读更多文章
📨成为电子邮件订阅者,了解最新动态
💻加入媒体没有阅读限制
✏️对疑点或新内容的评论
下次见,马可
使用 Amazon SageMaker 模型注册表更好地跟踪、管理、发现和重用人工智能模型
原文:https://towardsdatascience.com/track-manage-discover-and-reuse-ai-models-better-using-amazon-sagemaker-model-registry-a238ec73351c?source=collection_archive---------15-----------------------
提示和技巧
Model registry 是一个集中的存储库,用于存储我们的模型。为什么我们需要一个?为什么我们不能把它们存储在我们的笔记本电脑上呢?我们通过机器学习开发生命周期(MLDLC)来回答这些问题
图片来自 Unsplash
可搜索的集中式存储
MLDLC 包括两个阶段:实验和随后的产物电离。在实验过程中,数据科学家使用不同的数据集、算法和超参数构建许多模型,目标是找到最佳模型。在他们的 Jupyter 笔记本上,他们记录了每个模型的指标,并对他们了解到的情况进行了评论。如果需要,他们可以返回笔记本,回忆他们所做的工作,例如,使用什么超参数和数据集来构建特定模型。
如果你的组织只有一个记忆力极好的数据科学家,这个过程可能会奏效。他们可能还记得在哪个笔记本上记录了一个实验。然而,想象一下一个拥有 40 多名数据科学家、分属四个不同团队的组织。你将不得不面对数百个笔记本,打开并通读,以找到你需要的实验。
图片来自 Unsplash
这是一个低效的过程,即使这些笔记本电脑都集中存放。这是模型注册中心需要解决的第一个问题。它必须提供一个可搜索的集中存储,以记录与型号相关的信息。
一旦发现了最佳模型,它就进入了产品化阶段,包括构建一个培训和部署管道,以定期自动培训和部署模型。为什么我们需要定期训练?因为,例如,像欺诈检测这样的机器学习(ML)模型需要经常使用最*的网站活动数据进行训练,以跟上欺诈活动趋势。
部署事件和版本跟踪
在产品电离过程中,拥有每日培训时间表的管道将构建和部署比所有科学家在实验过程中所能提供的数据更多的模型版本。这里要强调的一个重要因素是,数据科学家创建的模型可能在数据集、超参数和算法方面有所不同。然而,由 AI 管道创建的模型通常仅在数据集上有所不同,因为所使用的算法和超参数是实验揭示的最佳版本。
此外,能够跟踪在特定日期哪个版本的模型正在生产中运行是非常重要的。想象一下这个欺诈检测模型场景:我们有一个包含每日训练计划的欺诈检测模型。一天,一个客户服务团队报告了上周发生的一起未被发现的欺诈活动。为了调查我们的模型故障,我们需要回顾上周在生产中运行的模型版本,以便我们可以提取相关的训练数据并进行实验(更改算法或超参数)来尝试构建更好的模型。这说明了我们需要模型注册中心的第二个原因。跟踪和查看部署事件的能力至关重要。
模型可发现性和可重用性
如果你的组织有不止一个团队在构建他们的人工智能模型,用不了多久,一个团队就会意识到,他们花了几天时间来构建另一个团队已经构建好的模型。如果所有的模型都有一个中央存储区,所有的团队都可以浏览和部署已经可用的模型,那么这个问题就可以避免。
图片来自 Unsplash
亚马逊 SageMaker 模型注册表
经过一些研究和实验后,我的心被 SageMaker 模型注册中心所吸引,它满足了前面提到的所有三个需求,甚至更多。我将带您了解 SageMaker 生态系统中的流程,并强调它如何解决上述问题。
亚马逊 SageMaker
为了演示 SageMaker 模型注册表,我将使用我的 Tensorflow MNIST 分类模型作为说明。注意,我不会深入模型架构和训练过程的细节,因为我想把重点放在模型注册上。
注册模型
我首先使用 SageMaker Python SDK 的 TensorFlow API 训练了一个图像分类模型,以插入这个定制的训练脚本:tf-train.py
from sagemaker.tensorflow import TensorFlowtf_estimator = TensorFlow(
entry_point=”tf-train.py”,
role=”AmazonSageMakerRole”,
instance_count=1,
instance_type=”ml.p2.xlarge”,
framework_version=”2.2",
output_path=f”{s3_folder}/output/”,
py_version=”py37")tf_estimator.fit({‘train’: f’s3://mybucket/dataset/train’,
‘eval’: f’s3://mybucket/dataset/eval’},
logs=”Training”)
为了在 SageMaker 模型注册中心注册这个模型,我必须首先创建模型组。一个模型组可以存储一个模型的多个版本。
sm_client = boto3.client('sagemaker')model_group_name = "MNIST-group-" + str(round(time.time()))
model_package_group_input_dict = {
"ModelPackageGroupName" : model_group_name,
"ModelPackageGroupDescription" : "MNIST digit classification"
}create_model_package_group_response = sm_client.create_model_package_group(**model_package_group_input_dict)
接下来,我必须在这个模型组中存储我之前训练的模型。你可以在这里添加一些元数据。描述有助于记录与该模型版本相关的任何重要信息,如超参数、精确度和纪元。您只需提及您想要强调的最重要的信息,因为您可以随时在与此模型注册相关的培训工作中查看完整的超参数和其他培训详细信息,稍后我将向您展示这些信息。还可以定义运行这个模型进行推理和转换所需的实例(机器)的类型,相当方便。例如,某些型号可能需要具有最低内存要求的 GPU。批准状态(批准或拒绝)用于模型审核,以便您可以让其他人知道哪个模型被批准用于生产。
model = tf_estimator.create_model(role="AmazonSageMakerRole")model.register(
model_package_group_name=model_group_name,
content_types=["application/json"],
response_types=["application/json"],
inference_instances=["ml.t2.medium", "ml.c5.xlarge"],
transform_instances=["ml.c5.xlarge"],
approval_status="Approved",
description="Trial 1 - Epoch 10, Learning rate 0.7 Accuracy 95%"
)
浏览注册表中的模型
您已经在模型注册中心构建并注册了一些模型。接下来,如何浏览这些模型?您可以通过代码浏览模型注册表中所有可用的模型,但是更好的方法是使用 Amazon SageMaker Studio GUI。Amazon SageMaker Studio 是一个完全集成的 IDE,专门为 ML 设计。把它想象成类固醇上的 Jupyter 笔记本。您不仅可以在不同的机器上同时打开和运行多个笔记本,还可以在 Studio GUI 中访问其他服务,如模型注册、功能存储、管道等。这种紧密的集成使得管理 ML 任务变得非常容易,而不需要在不同的工具之间切换。
正如您在下面看到的,我可以轻松地查看和搜索我之前创建的模型组。
模型注册组
单击模型会将我带到一个页面,在这个页面上我可以查看这个模型组下曾经部署过的所有模型版本,以及它们的批准状态、描述、作者和最后修改日期。模型注册中心自动分配一个增量版本号。
模型注册组中的模型版本
双击模型的第三个版本会将我带到 model version details 页面,该页面向我显示了重要的审计跟踪信息,例如该模型何时被批准或拒绝,谁在何时执行了该操作,以及该模型被部署到哪个端点。
查看部署事件
“metrics”选项卡将向您显示您选择在培训期间记录的指标,如准确性、损失或 r2。settings 选项卡将向您显示存储模型文件的 S3 存储区,最重要的是,模型版本 ARN,这是引用该模型版本所需的唯一标识符。您将需要这个模型版本 ARN 来从模型注册中心部署模型的特定版本。
查看模型版本详细信息
试用组件包含一个链接,该链接将带您进入正确的 SageMaker 培训工作,该工作描述了进一步的详细信息,例如生成该模型的培训集和评估指标。
查看培训工作详细信息
到目前为止,Amazon SageMaker 模型注册中心已经解决了可搜索的集中式模型记录、部署事件、版本跟踪和模型发现以及可重用性。现在让我们看看 SageMaker 模型注册中心如何满足我们最后的需求:可发现性和可重用性。
首先,让我们看看如何从模型注册中心部署模型的特定版本。
从注册表部署模型
在撰写本文时,还没有从 Amazon SageMaker Studio GUI 部署模型的机制。然而,从代码部署模型非常简单。您可以通过传递您想要部署的 ARN 模型版本来创建模型包。接下来,通过输入端点名称、初始实例数量和实例类型来调用 model.deploy。为什么需要多个实例计数?因为 SageMaker 具有内置的负载*衡功能,可以自动将流量分配给 x 个实例。
from sagemaker import ModelPackagemodel = ModelPackage(role="AmazonSageMakerRole",
model_package_arn=model_version_arn,
sagemaker_session=sm_session)timestamp = time.strftime("-%Y-%m-%d-%H-%M", time.gmtime())endpoint_name = f"NEW-DIGITS-{timestamp}"
model.deploy(1, "ml.c5.xlarge", endpoint_name=endpoint_name)
部署这个模型只需要几行代码,你可以在任何地方运行这些代码——在你的笔记本电脑上或者在云中运行的人工智能管道中..
将模型从模型注册中心部署到现有端点
SageMaker 端点非常类似于 REST API。您可以通过 api url 调用 REST API。要使用 SageMaker 端点进行推理调用,请使用 SageMaker Python SDK 或 boto3 库通过名称引用它。
predictor = Predictor(endpoint_name)
input = {'instances': [[0.5, 0.2, -5.2]]}
result = predictor.predict(input)
我们在前面学习了如何将模型从模型注册中心部署到新的端点。例如,您总是在每次部署新模型时创建一个新的端点名称,然后删除现有的端点。然而,这种方法有一个缺点。每当您部署新模型时,调用此端点的其他系统都需要知道新名称,如果您运行预定的 AI 管道训练,这可能是每天都要进行的。
用新模型简单地更新现有端点要容易得多,因为不需要通知其他消费者。下面的代码向您展示了这是如何做到的。
from sagemaker import Predictorsm_client = boto3.client('sagemaker')
timestamp = time.strftime("-%Y-%m-%d-%H-%M", time.gmtime())model_name = f'DEMO-modelregistry-model-{timestamp}'
container_list = [{'ModelPackageName': model_version_arn}]create_model_response = sm_client.create_model(
ModelName = model_name,
ExecutionRoleArn = 'arn:aws:iam::6253:role/SageMakerRole',
Containers = container_list
)predictor = Predictor(endpoint_name)
predictor.update_endpoint(model_name=model_name,
initial_instance_count=1, instance_type="ml.c5.xlarge")
首先,使用您想要部署的 model_version_arn 创建一个模型。然后,用刚刚创建的模型的名称调用“predictor.update_endpoint”。您需要再次输入 initial _ instance _ count 和 instance _ type’有点不方便,这迫使您从现有的端点配置中获取这些值。如果您所需要做的只是传入模型的名称,而保持其他一切不变,那就更简单了。
更新过程是无缝的,没有停机时间,即使在您更新时有请求到达您的端点,这令人印象深刻!
多账户支持
使用 SageMaker 模型注册中心,您可以指定一个 AWS 帐户作为您组织内所有模型的中央存储库。拥有不同 AWS 帐户的其他团队可以获得 IAM 角色访问权限,让他们在集中帐户的模型注册表中注册模型,浏览现有模型,甚至将模型部署到他们自己的 AWS 帐户中。每个团队还可以在自己的 AWS 帐户中拥有自己的模型注册中心,以管理只与他们的团队相关的模型。你可以在这里找到关于这个的更多细节。
拥有一个易于搜索的集中式模型库将显著提高模型的可发现性,这反过来将鼓励可重用性。谁愿意浪费精力去构建已经可用的东西呢?
图片来自 Unsplash
摘要
模型注册表是确保鼓励可发现性和可重用性的更有生产力和效率的 MLDLC 的关键组件。它的重要性随着你的 AI/ML 团队的规模而增加。Amazon SageMaker 模型注册中心在 Amazon SageMaker 生态系统中仍然是一个相当新的产品。然而,在其当前的形式中,它已经满足了注册管理机构模式的所有主要要求。我真的很期待这个令人敬畏的工具的进一步发展。
特别感谢 Romina Sharifpour 对本次实验的支持。
你可以在我的 github repo 中访问这个实验的 Jupyter 笔记本。
追踪来自太空的气溶胶污染
原文:https://towardsdatascience.com/tracking-aerosol-pollution-from-space-8ff53bb64d0f?source=collection_archive---------18-----------------------
利用 Google Earth 引擎提取某地区气溶胶污染的时间序列
照片由在 Unsplash 上叫我弗雷德
1.介绍
如今,在世界许多地方都能经常看到烟雾弥漫的天气。悬浮在空气中的细小固体颗粒通过吸收或散射阳光在造成烟雾条件中起着主要作用。这些粒子被称为气溶胶。气溶胶的来源包括来自工厂的污染、火灾产生的烟雾、风暴产生的灰尘、火山灰等(来源:NASA)。气溶胶可能对人类健康有害。它们还会干扰温度、云的形成和大气循环模式。因此,监测其水*并将其保持在限制范围内是很重要的。
NASA 的 Terra 卫星上的中分辨率成像光谱仪(MODIS)传感器每天跟踪气溶胶光学厚度(AOD)。它是一个无量纲数,与观测位置上方大气垂直柱中的气溶胶量有关。AOD 告诉我们,这些气溶胶粒子阻止了多少阳光直射到地面。值 0.01 对应于非常干净的大气,值 0.4 对应于雾蒙蒙的空气条件。AOD 值大于 1 代表严重污染时大气中气溶胶浓度高。一些自然现象如野火和沙尘暴会导致介于 1 和 3 之间的高 AOD 值。MODIS 传感器报告的最大 AOD 为 4。
在这篇博客中,我们将使用谷歌地球引擎(GEE)提取每日 AOD 数据(2000-2020 年),并找出德里市气溶胶污染的严重程度。
2.工作流程
工作流程可以分为三大部分
- 使用 GEE 收集 AOD 数据。
- 将数据作为 pandas dataframe 导入并绘图。
- 统计每年严重污染的天数。
3.使用 GEE 收集 AOD 数据
我们将从导入相关的库和认证 GEE 开始。
# Import relevant libraries
import ee# Authenticate GEE and initialize
try:
ee.Initialize()
except Exception as e:
ee.Authenticate()
ee.Initialize()
接下来,我们导入感兴趣区域(RoI)的矢量 shapefile 和 AOD 的光栅图像。每天的 AOD 值是从收集的不同图像中获得的,这些图像以卫星观察到该位置的日期进行标记。我们定义了一个函数reduce_del
,通过对 RoI 内包含的像素值进行*均,将它们减少到一个统计量。然后,该函数被映射到集合中的所有图像上,以导出该区域在所选持续时间内的*均 AOD。然后,生成的时间序列将作为 CSV 文件导出到 Google Drive。
# Import the boundaries of the region of interest
delhi = ee.FeatureCollection("FAO/GAUL/2015/level1") \
.filter(ee.Filter.eq('ADM1_NAME','Delhi'))# Import the raster data on aerosol concentration and apply regional filters.
# It vastly improves run time of the code by reducing the number of images in the collection.
asol = ee.ImageCollection("MODIS/006/MCD19A2_GRANULES")\
.filterBounds(delhi)\
.filterDate('2000-01-01', '2020-12-31');# Reduce the image data into a statistic for Delhi
def reduce_del(img):
stat = img.reduceRegion(reducer=ee.Reducer.mean(), geometry=delhi, scale=1000).get('Optical_Depth_047')
date = img.date().format()
mydict = {'date': date, 'stat': stat}
return ee.Feature(None).set(mydict)# Convert ImageCollection into FeatureCollection and filter the FeatureCollection keeping only notNull values
reduced_del = ee.FeatureCollection(asol.map(reduce_del)).filter(ee.Filter.notNull(['date','stat']))# Code for exporting Delhi AOD data to GDrive as a batch process.
task = ee.batch.Export.table.toDrive(
collection = reduced_del,
description = 'aod_stat_del',
folder = 'satellite',
fileFormat = 'CSV',
selectors = ['date','stat']
)task.start()
4.将数据作为时间序列导入并绘图
我们将数据从 Google Drive 下载到本地机器,并使用 Pandas 导入。AOD 值以 0.001 的比例报告。通过将所有值除以 1000,我们将这些值重新调整为 1。由于同一天有多个观察值,我们取它们的*均值来得出每天的单个值。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import matplotlib.pyplot as pltaerosoldf = pd.read_csv('C:\\Users\\ADMIN\\Desktop\\satellite\\geemap\\data\\aod_stat_del.csv')# Define a function to transform the dataframe into time series
# Rescale AOD values from 0.001 to 1 by dividing the numbers by 1000.
# Group the observations by day and take the average AOD value
def tseries(df):
df['date_formatted'] = pd.to_datetime(df['date']).dt.normalize()
df.stat = df.stat/1000
df = df.groupby('date_formatted').agg(mean_stat = pd.NamedAgg(column = 'stat', aggfunc = 'mean'))
return dfaerosoldf = tseries(aerosoldf)# we create a figure with pyplot and set the dimensions to 15 x 7
fig, ax = plt.subplots(figsize=(15,7))# we'll create the plot by setting our dataframe to the data argument
ax.plot(aerosoldf.index, aerosoldf.mean_stat)# we'll set the labels and title
ax.set_ylabel('aerosol optical depth',fontsize=20)
ax.set_xlabel('date',fontsize=20)
ax.set_title('Daily Aerosol Optical Depth Delhi (2000 - 2020)',fontsize=20);plt.show()
AOD 时间序列:作者图片
5.数据处理
每日时间序列图看起来很乱。我们绘制了大跨度的数据(20 年的每日数据),目的是验证气候变化的说法。值得注意的是,AOD 值超过 1 的次数在*期有所增加,这意味着严重污染事件的频率有所增加。让我们数一数每年 AOD 大于 1 的天数。
# Retrieve year information from date index
aerosoldf['year'] = aerosoldf.index.year
#Define AOD threshold as 1
aerosoldf['threshold'] = 1
#Create a binary column which takes value 1 when AOD exceeds threshold and 0 otherwise
aerosoldf['severe'] = np.where(aerosoldf['mean_stat'] > aerosoldf['threshold'], 1,0)#Group the observations and count the number of days having severe pollution in each year
aerosol = aerosoldf.groupby('year').agg(obs_days = pd.NamedAgg(column = 'severe', aggfunc = 'count'),
severe_days = pd.NamedAgg(column = 'severe', aggfunc = 'sum'))# As the number of observed days are not uniform across years, we calculate the percentage of severe days and multiply by 365 to make it comparable across yearsaerosol['severe_days_annual'] = aerosol['severe_days'] / aerosol['obs_days'] * 365
aerosol
显示每年严重天数的数据框架的前 10 行:作者图片
# Function to find slope and intercept of trendline
def trendline(df):
# get coeffs of linear fit
slope, intercept, r_value, p_value, std_err = stats.linregress(df.index,df['severe_days_annual'])
pct = intercept + slope * df.index
return(pct)#Plot
fig = plt.figure(figsize=(15,6))ax = fig.add_subplot(111)ax.plot(aerosol.index.astype(int), aerosol.severe_days_annual, linestyle="dashed", marker = 'o')ax.plot(aerosol.index.astype(int), trendline(aerosol), color = 'red', marker='o')ax.set_xticks(range(2000,2021))# we'll set the labels and title
ax.set_title('Number of days with severe aerosol concentration in Delhi',fontsize=20);
plt.grid()
plt.show()
图表显示严重污染事件的频率增加:图片由作者提供
6.结论
趋势图显示,一年中大约有 4 个月,德里空气受到高水*气溶胶的严重污染。一年中的严重天数从 2000 年的 70 天增加到 2020 年的 110 天。与二十年前相比,严重污染事件的发生频率增加了* 60%。那是惊人的!!这突出表明,由于污染的影响是跨国的,因此需要在国家和国际一级开展有意义的对话并制定行动计划。
免责声明:本博客表达的观点是个人观点。
参考
- https://earth data . NASA . gov/earth-observation-data/near-real-time/hazards-and-disasters/air-quality
- MCD 19 a 2.006:NASA 陆地过程分布式活动档案中心(LP DAAC)发布的 Terra & Aqua MAIAC 陆地气溶胶光学厚度每日 1 公里
- 吴(2020)。geemap:一个 Python 包,用于与 Google Earth 引擎进行交互式地图绘制。《开放源码软件杂志》,5(51),2305 页。【https://doi.org/10.21105/joss.02305
- Gorelick,m . Han cher,m . Dixon,m . Ilyushchenko,s .,Thau,d .,& Moore,R. (2017)。谷歌地球引擎:面向所有人的全球地理空间分析。环境遥感。
世界有多幸福?问问 Spotify 就知道了
原文:https://towardsdatascience.com/tracking-global-mood-with-spotify-847011228085?source=collection_archive---------29-----------------------
如何使用 Spotify 的 API 来跟踪全球情绪、研究幸福感、增加销售额等等
萨拉·库菲在 Unsplash 上拍摄的照片
我总是发现自己在窥探朋友们在 Spotify 上的收听反馈。这是一个很好的,自发的共鸣检查。当我看到格雷厄姆在听坎耶·韦斯特的音乐,或者尼克在听《指环王》的原声带时,我觉得我知道这意味着什么。我知道古典音乐意味着工作,凌晨两点的古典音乐意味着工作。我喜欢看到一个朋友和 ABBA 一起即兴演奏,当看到一个朋友在听 Billie Eilish 的时候感觉很糟糕。在我的想象中,上午 10 点的杰克·约翰森是一顿精力充沛的早餐,下午 2 点的 T-Pain 是一次健身房后的淋浴,而下午 5 点的杰克森·布朗是一次傍晚的烧烤。
Spotify 和我很像,但是更大,内存更大。Spotify 记录我们的收听历史,帮助他们改进宝贵的推荐算法。Spotify 已经创建了一个关于用户收听模式的数据宝库,并友好地通过一个直观的 API 提供给用户。这个数据库就像我自己的 Spotify 上的收听历史一样,可以告诉我们很多关于它背后的听众的信息。
在这篇文章中,我专注于一个项目,试图通过跟踪 Spotify 全球 200 强排行榜上歌曲的*均情绪来跟踪全球情绪波动。
背景研究
心理学家将听音乐分为情绪一致、情绪不一致或两者都不是,这取决于音乐是否符合情绪。研究已经证明,人类在倾听时会表现出情绪不一致和一致的*衡。一致是指我们听的歌曲与我们的感觉相似,而不一致是指我们试图用乐观的音乐来摆脱坏情绪的现象。Spotify 的数据与盖洛普和《华盛顿邮报》在最受欢迎月份的民意调查正相关,这表明情绪一致性主导了 Spotify 排行榜的收听习惯。在好的月份里,人们听好的音乐,在坏的月份里,他们听悲伤的音乐:
Spotify 数据与盖洛普调查数据正相关*,表明 Spotify 更符合情绪*
履行
我第一次发现前 200 名榜单是在 2 年前的 spotifycharts.com,每周递增一次。这些列表显示了当周在 Spotify 上获得最多流媒体播放的 200 首歌曲。
下载这些 CSV 文件后,我将它们作为数据帧导入到我的 RStudio 中。
*listofdfs <- list(
read_csv("~/Downloads/regional-global-weekly-2019-12-06--2019-12-13.csv", ...)*
接下来,我连接了 Spotify 的 API。你可以很容易地从 GitHub 下载 spotifyr web wrapper。
然后加载它:
*library(spotifyr)*
这个包装器提供了一组从 Spotify 服务器请求歌曲数据所需的函数。我感兴趣的数据是 Spotify 对歌曲的情绪评分。他们将速度、基调和音色等属性结合到一个名为价的度量标准中,该标准将歌曲的情绪从快乐 1 小时到悲伤 0 小时进行评级。
我创建了一个函数,将来自 spotifycharts.com的原始 CSV 转换成一个有序的价值列表。如果你想继续下去,自己尝试代码,我在下面解释这个程序。否则,请随意跳转到结果!
第一步:获得前 200 首歌曲的 URIs 奖
要使用 spotifyr 函数,我需要这些歌曲的 URIs。URI(不要与 url 混淆)是一首歌曲的 22 位条形码,幸运的是包含在前 200 名列表的 url 中。以下代码提取 url 的最后 22 位数字,并用这些值填充示例数据框。它需要一个名为“track_uri”的变量,spotifyr 预加载的函数才能工作。
*uris1 <- data.frame("track_uri" = 1:202, stringsAsFactors = FALSE)
for (i in 1:202) {
uris1[[1]][i] <- substr(chartdata[[5]][i], 32, 53)
}
uris1 <- na.omit(uris1)*
第二步:为每首歌曲添加价谱
现在,我可以使用 spotifyr 的便捷函数从 API 中请求每首歌曲的价数分数。由于我们在这一步中与 Spotify 服务器通信,因此需要互联网连接。
获得化合价分数很容易。我使用函数 get_track_audio_features。它获取一首歌曲 URI,并返回一个包含该歌曲所有音频特征的数据帧。这包括一个称为化合价的变量,所以要得到化合价,我只需过滤列化合价:
*get_track_audio_features(uris1)$valence*
步骤 3:按流%对化合价进行加权
为了更准确地了解人们在听什么,我想通过流计数来衡量情绪得分。这样,一首有 100 万条流的歌曲比一首有 10 万条流的歌曲对排行榜整体情绪的贡献更大。
来自 spotifycharts.com 的前 200 名 CSV 列出了流计数,所以我只需要跟踪这些。
*streams <- data.frame("streams" = 1:202, stringsAsFactors = FALSE)
for (i in 1:200) {
streams[[1]][i] <- chartdata[[4]][i]
}*
索引和数据类型有点混乱。
*streams <- na.omit(streams)
streams$streams <- as.double(streams$streams)for (i in 1:200) {
streams$streams[i] <- streams$streams[i+2]
}*
最后,我把它从原始数据流变成总数据流的一部分。这样,价*均值与总流数无关。
*streams$streams <- streams$streams / sum(streams$streams)*
第四步:组装
最后,我将流份额乘以化合价并取*均值。这将返回该周的*均情绪!
*return(mean(get_track_audio_features(uris1)$valence * streams$streams))*
结果
在我下载的所有 CSV 上使用 for 循环,我跟踪了过去两年 Spotify 全球 200 强播放列表的每周情绪。
这是 2020 年的:
快乐的圣诞音乐使 12 月下旬成为最快乐的一周,而 1 月初、2 月下旬和 7 月下旬的几个不同时期则是最悲伤的一周。
其余的变化很难解释。这是叠加在 2019 年之上的 2020 年:
我对化合价的长期正趋势进行了标准化。我猜,这种价格持续上涨的趋势可能是 Spotify 价格计算的一种特质,或者是整个音乐行业的一种模式。通过比较,我注意到以下几点:
- 2019 年和 2020 年在 10 月至 12 月的范围内几乎相同,表明西方假期对听力模式的稳定影响。
- 2019 年是一个更加乐观的夏天。我的猜测是,暑假的显著下降减少了感觉良好的夏季歌曲的流数,如 2019 top charter seorita(valence = 0.75)。
- 对于 Spotify 的听众来说,隔离的第一个月真是快乐的一个月。也许它变老了,因为情绪水*直到圣诞节周才会回到 4 月份的峰值。
- 在 2019 年这样的正常年份,情绪通常是季节性的,从 1 月份的年度低点开始,随着冬天转向春天而上升,在 6 月和 7 月达到顶峰,然后在寒冷的冬季假期再次下降。
这些数据似乎太嘈杂,无法进行更细致的观察。Spotify 对价值标准的记录有点不透明,也不像人们希望的那样准确。音乐和情绪并不总是联系在一起的。人们在悲伤的时候听快乐的音乐,在开心的时候听悲伤的音乐,在这两种情况下都可能根本不听音乐。另一个问题来自于只使用顶部图表。前 200 名榜单受到新专辑、广播电台、Spotify 的算法、音乐趋势以及歌曲是否是你有很多机会播放的歌曲类型的影响。
结论
摆弄这些数据很有趣,我在做这个项目时想到了一些应用/进一步的考虑。
- 幸福科学:通常很难衡量幸福和心情。最主要的方法是自我调查,但是这些通常不可靠,因为人们如何合理化他们的情绪。相反,你可以利用情绪一致性(和不一致性——任何相关性都可以利用)。跟踪干预对受试者的影响可能就像听他们的 Spotify 一样简单和准确。或者,你可以将 Spotify 的用户级数据整合到个人情绪跟踪器中。
- 更好的生意:音乐能对购物者产生惊人的影响。教科书上的例子是 1992 年关于葡萄酒购买的研究。研究发现,在市场上播放法国音乐导致法国葡萄酒的销量是德国葡萄酒的 5 倍;而演奏德国音乐使得德国葡萄酒的销量以 2:1 的比例超过了法国葡萄酒。其他研究发现,加快音乐节奏可以增加酒吧里的饮料购买量,快乐的音乐通常对购物者有利。希望利用音乐对购物者的影响的企业主可以利用 Spotify API 的指标来更准确地跟踪和了解他们商店中的音乐如何影响他们的客户。在效价、可跳舞性、能量、BPM、音调、声音、响度、活力和语速之间,有大量的指标可以测试销售。
- 隐私:Spotify 可以对我们的数据这样做,这也有点令人担忧。我可能喜欢偶尔看看我的朋友在听什么,但我也有自己的流对朋友隐藏。我认识到,我听的音乐可以透露很多关于我的信息,我不喜欢失去对这些数据的控制。也许在未来,Spotify 会将我的收听习惯与未来的负面健康结果联系起来,并将这些数据出售给我的医疗保健提供商,从而提高我的保费。也许我一直在听的舞曲都会被用来告诉一个未来的雇主,我不会努力。重视 Spotify 的数据意味着认识到我们正在与 Spotify 以及他们现在可能出售数据的任何人分享这一价值。
我计划稍后更深入地分析这个问题。如果你想继续收听,请跟我来!谢谢!
[1] C. Lee 等人,人际关系和审美体验中对情绪一致性的偏好 (2013),《芝加哥消费者研究杂志》。
[2] C. Ingraham,一年中最好和最差月份的权威排名 (2015 年),《华盛顿邮报》
[3]https://spotifycharts.com
https://github.com/charlie86/spotifyr
[5] B. Goldman,新冠肺炎时期的暑假有什么变化? (2020),ParkMobile
[6] M. Holder,衡量幸福:我们如何衡量幸福? (2017)《今日心理学》
[7] A.C. North 等人,店内音乐对葡萄酒选择的影响 (1999),《应用心理学杂志》
[8] K.M. Knoeferle 等人,乐观人群:快速店内音乐缓解高社交密度对顾客消费的负面影响 (2017),《零售杂志》
图像:
封面:照片由Sara kurfe在 Unsplash 上拍摄
用 Pytrends 跟踪谷歌搜索的关键词趋势
原文:https://towardsdatascience.com/tracking-keyword-trends-on-google-search-with-pytrends-cf97c43803f6?source=collection_archive---------18-----------------------
只用几行代码就能收集历史数据!
马库斯·温克勒开启解锁
Pytrends
是一个用于追踪谷歌搜索趋势的非官方 API,我们可以使用matplotlib
来可视化这些趋势随着时间的推移。你可以在这个项目的 GitHub 库这里阅读更多关于这个包的信息。
什么是谷歌搜索?
我们都知道谷歌搜索是什么。我们每天都要使用它几次,有时会不假思索地访问数以百万计的搜索结果。有趣的是,谷歌搜索工具栏最初是在 2000 年为 ie 5 发布的。
通过查看十年来谷歌搜索关键词的时间序列可视化,我们可以得出关于几乎任何主题的有价值的见解。让我们来看一个例子。让我们来看看关键词“数据科学”的趋势。
绘制数据科学搜索趋势
作者图片
下面是 2016 年到 2021 年关键词“数据科学”的趋势。我也将分享一个关于如何生成这种可视化的教程!超级简单。
对于任何包,我们从将安装到本地机器上开始。您可以用一行简单的代码来实现这一点。
! pip install pytrends
一旦pytrends
被安装,我们将从包中导入方法TrendReq
。
from pytrends.request import TrendReq
接下来,我们需要连接谷歌。我们可以使用TrendReq
并传递几个参数。对于这个例子,我们将使用hl
和tz
。
# connect to google
pytrends = TrendReq(hl='en-US', tz=360)
hl
参数指定用于访问 Google Trends 的主机语言。请注意,只有 https 代理可以工作,您需要在代理 ip 地址后添加端口号。tz
参数是时区偏移量。所以,比如美国 CST 是360
。
在 API 初始化之后,我们需要查询我们想要搜索的实际关键词。为此,我们使用方法build_payload
告诉 API 我们想要哪些关键字。如前所述,我们在这个例子中使用了“数据科学”。
# keywords to search for
pytrends.build_payload(kw_list=['data science'])
现在最困难的部分已经过去了!接下来,我们只需要创建一个 dataframe 来保存这个查询的时序数据。有一个 API 方法Interest over Time
,它返回历史索引数据,显示该关键字在 Google Trends 的 Interest Over Time 部分被搜索最多的时间。
# dataframe
time_df = pytrends.interest_over_time()
通过运行一个简单的time_df.head()
,看看该数据帧的前 5 行是什么样子。
一旦一切都设置好了,我们就可以使用matplotlib
来可视化这个数据框架!我不会解释这一部分,但这里是我在这个项目中使用的完整代码。如您所见,整个项目只用了大约 22 行代码就完成了。
你自己试试
这个小练习只是我们可以用pytrends
计划做的许多事情之一。例如,我们可以查看历史每小时兴趣、地区兴趣、相关主题、相关查询等等。
您可以随意安装 Pytrends 并自己使用它!有数不清的术语要搜索。
从太空追踪龙卷风
原文:https://towardsdatascience.com/tracking-tornados-from-space-ce4e525fd5b5?source=collection_archive---------26-----------------------
借助高分辨率哨兵-2 卫星数据对捷克境内龙卷风的评估
瑞歇尔·桑纳在 Unsplash 上拍摄的照片
6 月 24 日星期四下午 7:15 左右,一场大龙卷风袭击了捷克南部摩拉维亚地区,风速至少为 219 公里/小时(136 英里/小时)。在 T4 的藤田等级中,龙卷风被划分为 F4 级。
“简直是活地狱!”—南摩拉维亚州长扬·格罗里奇
六人死亡,至少 200 人受伤。当地人报告说冰雹有网球那么大。总的来说,六个不同的村庄(Hruš ky、Moravska Nova Ves、Mikulč ice、luice、Hodonína 和 Ratíkovic)遭到严重破坏。龙卷风的路径是通过空中任务评估的,如下图所示。红色区域表示对建筑物的损害,绿色区域表示对森林的损害,蓝色区域表示对农业的损害,黄色轮廓显示龙卷风的路径,大约 26 公里长,700 米宽。
根据空中任务评估龙卷风的破坏和路径——图片来自捷克气象局
从太空看得见吗?
在我看到电视上的视频和灾难性事件的报道后,我脑海中闪现的问题是— “龙卷风的影响能在卫星图像上看到吗?”因此,我决定查看 Sentinel-2 卫星星座的最新图像,该星座大约每 5 天(取决于位置)提供一次分辨率为 10m 的地球表面高分辨率图像。尽管有各种各样的工具可以用来访问数据,但我决定使用优秀的 Sentinelhub EO 浏览器,它使搜索和可视化最*的卫星数据变得非常容易。
来自龙卷风之前(顶部)和之后(底部)的 Sentinel-2 图像-由作者基于 Sentinelhub EO 浏览器提供的图像-包含修改后的 2021 年哥白尼 Sentinel 数据
上面的图像显示了哨兵-2 卫星拍摄的两个场景。上面的场景拍摄于 7 月 21 日,下面的场景描绘了 7 月 29 日龙卷风过后五天的同一地区。你可以清楚地看到在布雷克拉夫和霍多宁之间的底部场景的中心部分有一个亮点。这个斑点(光谱特性的变化)可以清楚地归因于龙卷风的影响。
评估损失
让我们把镜头拉*一点,看看我们刚刚确定的受龙卷风影响的地区:Moravska Nova Ves 村。如果你看下面的两幅卫星照片(再次显示前后对比),你可以看到村庄的北部和南部看起来没有受到影响,然而,中部再次显示了光谱特性的显著变化:你可以看到该区域以黄色突出显示的红色屋顶基本上都消失了,现在呈现出蓝色。这可能意味着该地区的屋顶或整个建筑被完全摧毁。在村庄周围(尤其是西边),你还可以看到龙卷风过后出现在橙色/褐色调中的农业区所遭受的大面积破坏。
Sentinel-2 在龙卷风袭击 Moravska Nova Ves 村之前(上图)和之后(下图)的图像——由作者基于 Sentinelhub EO 浏览器制作的图像——包含修改后的 2021 年哥白尼 Sentinel 数据
推导龙卷风的轨迹
在上面的第一幅图中,我们可以看到,通过对比龙卷风前后的卫星图像,我们可以确定对农业和建筑造成严重破坏的热点。但是有可能推导出龙卷风的轨迹吗?
为了找到答案,我对前后场景的光谱带进行了归一化,并计算了两个时间步长之间的光谱差异。结果是假色(8-4-3 ),如下图所示。如果你仔细观察,特别是从图像的中央部分向右上方,你可以清楚地看到一条路径,显示由于植被和基础设施的破坏而产生的光谱差异!
相关链接
[1] Synergise Sentinelhub 电子浏览器:【https://apps.sentinel-hub.com/eo-browser
[2]捷克气象局关于龙卷风的报告:https://www . chmi . cz/files/portal/docs/tisk ove _ zpravy/2021/Zprava _ k _ torna du _ 1 . pdf
用 Python 追踪你的焦点
原文:https://towardsdatascience.com/tracking-your-focus-with-python-bcd804f1f6f2?source=collection_archive---------22-----------------------
卢克·切瑟在 Unsplash 上拍摄的照片
一个简单的脚本,使用 Python 和 Streamlit 跟踪和可视化您的日常工作时间
注意力的价值
如今,注意力似乎成了一种商品。你访问的每个应用和网站都想吸引你的注意力,这几乎是一种货币。因此,尽可能多的控制自己的注意力是有意义的。
今天,我将向你展示如何使用 Python 和 Streamlit 追踪和可视化你专注的时间
跟踪和可视化
这些步骤将是:
- 设置跟踪脚本
- 设置可视化
- 将代码包装在一个 Streamlit 应用程序中
1.跟踪脚本
让我们开始写脚本来跟踪你的焦点:
让我们来看看这里发生了什么:
- 首先,我们编写一个名为
trackFocus()
的函数,它简单地跟踪由用户的简单输入分隔的时间间隔(比如按回车键) - 然后我们调用
calculatefocustime()
函数,该函数返回给定一天中跟踪的总时间 - 最后,我们调用
logFocus()
函数,它记录会话开始和结束的时间戳
现在我们有了追踪器,让我们写一个简单的可视化程序来看看我们每天集中的时间。
2.可视化聚焦时间
为了可视化聚焦时间,我们需要两个函数,一个用于创建数据帧以正确存储数据,另一个用于绘图。
绘制聚焦时间的脚本
输出:
聚焦时间 2021 年 2-6 月
该守则有两个主要部分:
- 使用
create_focus_df()
功能创建数据帧 - 使用
plotfocus()
功能中的plotly
库绘制焦点。
这件事很酷的一点是,它让你知道你实际上在活动上花了多少时间,以及这些时间是如何变化的。
对我来说,这些见解是有帮助的,因为它们让我对我的一致性和我在做有成效的工作所花费的时间方面的总体表现有了一个总体的了解。
3.将所有东西打包到一个 Streamlit 应用中
现在,作为结束,让我们用 Streamlit 制作一个简单的仪表板应用程序,只需从终端发出一个简单的命令,就可以随时可视化我们的数据。
现在,在终端中我们运行:
streamlit run app.py
你可以在这里找到源代码
追踪洞察力
我喜欢自我跟踪的想法,因为它给了我一些关于我的规律性和我每天实际关注多少时间的洞察力。有了这些信息,我可以为接下来的几周设定更现实的目标,并培养一种脚踏实地的进步意识。
如果你喜欢这篇文章,请在 Twitter 、 LinkedIn 、 Instagram 上联系我,并在 Medium 上关注我。谢谢,下次再见!:)
使用 MLMD 跟踪您的机器学习工作流
原文:https://towardsdatascience.com/tracking-your-machine-learning-workflows-with-mlmd-b289e37e020c?source=collection_archive---------29-----------------------
记录、分析和检索与您的 ML 开发项目相关的元数据
图片来自皮克斯拜
当我们想到机器学习(ML)项目时,我们会想到数据采集和处理。我们考虑模型开发、拟合、评估和部署。
构建和训练 ML 模型的过程一直是人们关注的焦点。有很多关于不同的神经网络架构实现前所未有的结果或新*台促进想法到生产的过渡的谈论。
但是,如果出了问题会怎么样呢?如果我们想回到过去,检查我们用来训练模型的数据集的版本,超参数的值是什么,以及生成模型的运行与其他运行相比如何,会发生什么情况。
2015 年,谷歌发表了一篇开创性的论文,名为《机器学习系统中的隐藏技术债务。如果你在 ML 工作超过六个月,你就已经看到下图了。
机器学习系统中隐藏的技术债务。
在这项工作中,作者试图警告说,只关注今天可用的强大的 ML 工具并认为它们是理所当然的是危险的;我引用:“使用技术债务的软件工程框架,我们发现在现实世界的 ML 系统中招致大量的持续维护成本是很常见的。”
今天,我们讨论一个图中没有的盒子。我们讨论的是一个在后台默默工作的组件,它收集信息并提供将所有东西结合在一起的粘合剂。在我看来,这是 ML 管道中最关键的元素:元数据存储。
学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!
ML 元数据
元数据存储是一个存储后端和 API,用于记录和检索与 ML 工作流相关的元数据。管道步骤的输入是什么?该步骤产生了哪些工件?他们住在哪里?他们是什么类型的?
这个故事讲述了一个具体的元数据存储实现:Google 的 ML 元数据(MLMD) 库,它是tensor flow Extended(TFX)的一个组成部分,但同时也是一个独立的应用程序。使用这个元数据存储实现将帮助我们更好地理解对这样一个组件的需求。
MLMD 图书馆
MLMD 帮助我们分析一个 ML 工作流程的所有部分和他们的相互联系,而不是看孤立的过程。它提供了发生的每一个事件的完整谱系,最重要的是,一个模型的完整历史。其中,MLML 可以帮助我们确定:
- 模型在哪个数据集上训练?
- 用于训练模型的超参数是什么?
- 模型的衡量标准是什么?
- 哪个运行创建了模型?
- 我们用这个数据集训练过其他模型吗?
- 不同的型号相比如何?
- 特定 ML 框架的哪个版本创建了这个模型?
MLMD 需要一个存储后端来记录它收集的信息。存储后端是可插拔的,可以扩展,但 MLMD 提供了现成的 SQLite 和 MySQL 的参考实现。MLMD 支持 SQLite 和 MySQL。但是,在大多数情况下,您不会关心底层运行的存储系统。
基本概念
要与 MLMD 合作,首先你需要定义三个Types
:
ContextType
ExecutionType
ArtifactType
想象这些是你想要追踪的实体的蓝图。使用这些Types
你可以创建符合相应ArtifactType
的Artifact
对象。然后,您还可以创建Execution
对象和Context
对象。
把一个Artifact
想象成一个由 and Execution
产生的具体对象。例如,模型是从训练步骤(即Execution
)产生的Artifact
。Context
可以是封装实验的整个运行。
每当一个步骤产生一个Artifact
时,我们可以说它发出一个Event
,这是将一个Artifact
和一个Execution
绑定在一起的另一种实体。最后,Attribution
用Context
连接Artifact
,用Association
连接Execution
和Context
。
因此,我们可以说,一个模型(即Artifact
)是由一个Execution
(即工作流步骤)产生的,并由一个Event
对象绑定在一起。然后,Execution
是实验的一部分(即Context
),它们通过Association
对象绑定在一起。最后,一个实验(即Context
)生成了一个模型(即Artifact
),它们被这个Attribution
对象绑定在一起。
MLMD 在行动
现在让我们走一遍典型的 ML 工作流程,并将 MLMD 集成到管道步骤中。最初,我们需要创建两个Artifacts
:一个代表数据集,一个代表模型。为此,我们应该先注册相关的ArtifactTypes
。
让我们看看代表数据集的ArtifactType
。在我们的声明中,我们指定每个数据集Artifact
应该有两个属性:一个day
和一个split
。同样的,型号Artifact
也有一个version
和一个name
。
除此之外,其他属性被直接传递给每个Artifact
。可以把它想象成面向对象编程中的继承属性。比如每个Artifact
都要有一个uri
指向物理对象。因此,让我们为数据集创建一个Artifact
。
接下来,让我们创建一个ExecutionType
和相应的Execution
对象来跟踪管道中的步骤。让我们创建一个 trainer execution
对象来表示训练步骤,并将其状态设置为 running。
现在,我们想要指定我们之前创建的数据集Artifact
是名为*“Trainer”的Execution
步骤的输入。*我们可以通过声明一个Event
实体来实现。
当训练步骤完成时,它产生一个模型。让我们定义一个模型Artifact
,并将其设置为Execution
步骤*“训练器”的输出*
最后,“培训师”步骤完成,我们可以将其状态设置为*“已完成”*
为了获得完整的图片,让我们将所有东西绑定在一起,并使用Attributions
和Assertions
实体记录我们的模型Artifact
的完整血统。
这 23 行代码为实验创建了一个Context
实体,并将*“Trainer”*链接为实验的Execution
步骤,并将模型链接为其输出。仅此而已;MLMD 负责剩下的事情,所以你将能够像我们在第一部分看到的那样跟踪一切。
结论
虽然训练代码是 ML 引擎的心脏,但连接一切的循环系统往往是缺失的。端到端 ML 系统中有许多组件,每个组件都扮演着重要的角色。
然而,今天我们讨论了一个在后台默默工作的组件,它提供了将所有东西绑定在一起的粘合剂——元数据存储。
我们看到了 MLMD 如何实现这个想法,它的核心概念,以及我们如何在一个简单的 ML 环境中使用它。要开始安装,请参见此处的安装说明。
但是,如果你把它安装在本地,你将看不到它的全部潜力。相反,最好在完整的云原生环境中使用。因此,我建议在一个 MiniKF 实例中工作,在那里一切都是预先配置好的。要开始,请参阅下面的故事:
关于作者
我叫 Dimitris Poulopoulos ,我是一名为 Arrikto 工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。
如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请在 Twitter 上关注我的 Medium 、 LinkedIn 或 @james2pl 。
所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。
人工智能系统中伦理、安全和包容性的权衡决定
原文:https://towardsdatascience.com/tradeoff-determination-for-ethics-safety-and-inclusivity-in-ai-systems-60f20a3d0d0c?source=collection_archive---------28-----------------------
由 Startaê Team 在 Unsplash 上拍摄的照片
人工智能系统的设计决策包括价值判断和优化选择。一些与技术考虑有关,如延迟和准确性,另一些与业务指标有关。但是每一个都需要仔细考虑,因为它们对系统的最终结果有影响。
需要明确的是,并不是所有的事情都需要权衡。通常会对问题进行巧妙的重新表述,这样您就可以满足用户和客户的需求,同时也满足内部业务考虑。
以早期 LinkedIn 的一个功能为例,该功能通过要求关系向目标用户推荐特定的职位发布,基于他们认为这些职位发布对目标用户的合适程度。它通过只将相关工作分享给用户的关系,同时帮助 LinkedIn 向用户提供更多相关的推荐,为推荐用户提供了目的感和善意。这是一个双赢的局面,相比之下,必须不断地深入调查用户,以获得更多的数据,为他们提供更有针对性的工作建议。
本文将基于在产品开发中设定目标以实现负责任的人工智能的重要性,为构建道德、安全和包容的人工智能系统增加另一个考虑维度。
为什么要权衡决定?
权衡决定的主要目的是突出项目各种目标之间的内在矛盾。
让我们考虑一个场景,其中业务指标是通过*台上的广告获得的收入。有助于此的一个设计决策是实现类似无限滚动的东西,通过不断提供更多穿插广告的相关内容,让用户尽可能长时间地停留在*台上。通过利用用户的个人数据,广告本身可以变得更有吸引力或与用户更相关,这可能会增加这些广告的点击率。
这里有很多顾虑。也许最明显的是侵犯隐私和扭曲用户同意如何使用他们的个人数据。另一个是对已知的黑暗设计模式的依赖,这种模式倾向于增加花费在*台上的时间,但不一定谈论这些时间的质量。
当你慢慢利用更复杂的模型时,你可能会遇到其他选择,比如偏差与方差的权衡,从可解释性的角度来看,你冒着使事情变得不透明的风险。如果你想证明你*台上的广告不是基于敏感属性的歧视,这可能很重要。更复杂的模型可能会提高性能,但代价是什么?
当在这里考虑权衡决定时,明确地强调这一点,即什么对用户有益,什么对商业有益,这是帮助有效解决问题的第一步。
如何有效地做权衡决定?
有 3 个初始步骤可以用来开始权衡决定。
1.明确列出权衡
正如上面的例子所强调的,当技术和设计决策的一阶效应清晰时,它们应该被明确地列出来。一旦做到这一点,采取一种系统思考的方法,考虑这些设计的二阶效应。
二阶效应很难追踪,而且可能以意想不到的方式表现出来。然而,他们通常要对很大一部分伤害负责,因为没有任何明确的保护措施来防止这些伤害。一个明确的列表也有助于让每个在系统上工作的人记住这些权衡。
2.对照你的目标检查这些决定
正如在产品开发中设定目标对实现负责任的人工智能的重要性中提到的,目标可以作为北极星,让我们对自己负责,就我们试图用系统实现的目标而言。随着您对项目细节的深入了解,很可能细节会偏离项目最初的愿景和目标。这是引入由使用该系统导致的不必要的伤害的候选。
当您做出技术和架构决策时,经常对照目标进行检查,并思考它会导致什么样的权衡,可以帮助您确定正确的方向。对于那些熟悉约翰·伯伊德的 OODA(观察、定位、决定、行动)的人来说,这构成了东方的关键一步,以确保接下来的事情朝着正确的方向发展。
3.互补性与输赢情景
并不是所有支持商业目标的决策都必须是对用户福利不利的方案。回到 LinkedIn 工作推荐的例子,我们可以看到一个用同行推荐取代大量数据收集的设计如何继续满足希望人们因为相关的工作发布而使用*台的商业目标,而不需要诉诸侵犯隐私和滥用个人数据。
这是一个获得创造力的机会,随着更多的从业者进入人工智能领域,你可以将此作为自己的差异化品质:在不牺牲业务需求的情况下实现道德一致性。
在人工智能的生命周期中,你能为权衡决定做些什么?
一旦你完成了上面的一些步骤,你需要在人工智能生命周期中做的一件关键的事情就是监控权衡。虽然在一开始就考虑它们并做出符合道德考虑的选择是很好的,但鉴于人工智能系统的动态性和复杂性,如果没有持续的监控,你就有可能遭受突发伤害,从而削弱你工作的影响。
为系统的可接受行为设置阈值是实现上述目标的具体方法。这可能包括用户在一个*台上连续花费的时间,以及是否有一个简短的通知弹出来,要求他们伸展一下身体,到外面走走,可以打破消极的模式。我们已经在健身追踪器和安卓手机的通话屏幕上看到了类似的东西。
最后,仅仅确定权衡决定是不够的。是的,承认有问题总是第一步,但我们需要超越。做到这一点的方法是将可行的补救措施与您列出的每一项权衡相关联。这有助于涉众打破惰性,并有意义地按照建议行动,以改善系统结果。
希望这种权衡决定的想法是你觉得自然的,并且已经可以看到在你的 AI 生命周期的设计和开发阶段你可以集成它们。请在下面留下您的评论,告诉我们您是如何在您的组织中实践这一理念的。
在这里注册接收更新 可操作的人工智能伦理书 !而你可以在这里 了解更多我的作品 !
您可以通过订阅 人工智能伦理简报 从 蒙特利尔人工智能伦理研究所 了解更多这样的见解!
阿亚龙路原始视频数据中的交通分析
原文:https://towardsdatascience.com/traffic-analysis-in-original-video-data-of-ayalon-road-158061b811ab?source=collection_archive---------23-----------------------
帖子中的所有图片均由作者创作,除非另有说明
https://github.com/ido90/AyalonRoad
摘要
这是 81 个 8 分钟长的视频的故事,记录了一个半月来阿亚龙路 的交通情况,这些视频是从我 2019 年住的公寓的窗户观察到的。我的任务物品包括一台笔记本电脑,一个智能手机摄像头和一个汽车真空支架。
分析交通需要检测视频帧中特定区域的车辆以及在连续帧中跟踪车辆。
由于视频中拥挤的小汽车未能被几个现成的检测器检测到,我在 15 帧内手动标记了车辆,并训练了一个专门设计的CNN(总体精神是更快的 RCNN ),由预训练的 Resnet34 层(根据所需的特征地图单元大小和感受域选择)、基于位置的网络(合并道路地图信息)和检测&位置头组成。
由于低帧速率不能保证相邻帧中相同车辆的包围盒之间的相交,我用通过卡尔曼滤波器实现的基于位置的概率模型代替了分类跟踪器的分配机制。
生成的交通数据从像素转换为米单位,并以空间和面向车辆的结构进行组织。提出了几个研究问题,例如速度/密度/流量之间的关系( 基本交通图 )、日常和时间模式以及车道转换的影响。
主要贡献
- 使用智能手机和个人笔记本电脑等简单工具进行实证交通研究的概念验证
- 主要道路交通的原始数据集
- 在噪声图像中检测小而拥挤的物体,可通过少量数据进行训练
- 对漏检具有鲁棒性的低帧率视频中快速运动对象的跟踪
- 验证基本交通图,检测流量最大化的临界速度(60km/h)并初步了解车道转换的影响
数据采集
数据是我住在特拉维夫 阿亚龙路 主要区间附*的一座塔里时收集的(在哈沙罗姆立交附*),使用 Galaxy S8+ Hyperlapse 模式,速度为 x8,分辨率为 FHD,其他为标准配置。我的同事兼朋友奥德·西蒙好心地提供了一个简单的磁铁支架,并把它放在公寓的玻璃墙上。事实证明,这样拍摄的 8 分钟视频(压缩为 1 分钟)需要大约 120MB 的存储空间。这不允许 24-7 记录道路,但允许在不同日期和时间合理覆盖道路。
在一个半月的时间里录制了 81 个视频(约 14 小时,总共 13gb)。
正在录音的智能手机
录制的视频覆盖小时和工作日(每个点代表一个视频)
车辆检测
在几个现成的工具失败后,我决定自己训练一个专用的 CNN 来检测视频帧中的车辆。我手动标记了 15 帧(共 190K 帧)的所有车辆以供借鉴。我遵循了常用对象检测解决方案(如 SSD、YOLO)中使用的锚盒框架,并将其简化为对应于我的二进制检测问题(而不是多类分类)。
我使用了标准 ResNet34 中的迁移学习,并在 15 层后对其进行了裁剪,以使特征图的分辨率与帧中车辆的密度相对应,感受域与所需的输入范围相对应。我还添加了锚定框的位置作为输入:当道路总是出现在你的视频中的相同位置时,位置过度拟合并不是一个诅咒:)
锚盒及其感受野样本
检测网络架构
我用亚当优化器来训练我的网络。由于大多数图像不包含车辆,我必须对正面锚盒(即有车辆的锚盒)进行上采样,以便网络不会简单地学习预测“没有车辆”。这个概念被称为硬负抽样,它对训练的成功至关重要。
经过训练的检测器的输出样本应用于具有显著窗户反射噪声的黑暗照片(检测器被训练为仅检测在经过哈沙勒姆立交后向北行驶的道路上的车辆)
跟踪
跟踪是在Objectdetecttrack包的框架下开发的。然而, SORT 追踪器——该框架所基于的——根据相应边界框的交集来关联相邻帧中相同对象的检测,隐含地假设高帧速率来保证这种交集。由于该假设不适用于本项目中的数据(汽车快速移动,在超延时相机模式下只有约 4 FPS),分配机制被替换为通过卡尔曼滤波器实现的基于位置的概率模型,该模型表达了车辆沿道路方向的位置的较大变化。该模型基本上询问“轨迹i
(给定道路方向和轨迹历史)在一帧内到达新检测j
的位置的可能性有多大?”。
在 3 个相邻帧中具有 3 个不相交边界框的车辆(#18):边界框之间的连接不能基于相交,但是可以从基于卡尔曼滤波器的概率模型中推导出,该概率模型的输出可能性由彩色点表示(红色表示低可能性,绿色表示高可能性)
跟踪主要应用于道路的连续可见区间(Moses 桥以北)。修改的跟踪算法允许在大部分道路区间上成功跟踪大部分车辆,即使在少数连续帧中存在遗漏检测。
对遗漏检测具有鲁棒性的跟踪:红点在各种帧上标记被跟踪对象(#4)的检测位置
最终的跟踪算法每秒可以处理 1.2 个完整帧或 3 个裁剪帧,这需要 10 分钟来处理 8 分钟的单个裁剪视频。
交通分析
分析输出的示例如下所示。更多信息,请访问该项目的回购协议。
几天和几个小时内的交通密度:工作日的高峰时间约为 16-17,星期五(安息日之前)为 12-13,星期六(安息日之后)为 19-20
基础交通图 和理论很像(要点来自数据,背景和笔记是 Hendrik Ammoser 出现在维基百科);流量-密度图显示了自由流动交通和拥挤之间的明显区别;最大通量速度(临界速度)约为 60 公里/小时
车辆车道转换通常伴随着车辆速度的显著且立即的增加
很高兴看到速度和密度之间关系的理论符合实际交通,或者得出最大化车辆流量的交通密度。车道转换的现象也很有意思,正如我们所料,它让车手们加快了速度。我也希望了解外部性(即车道转换对其他司机的影响),但不幸的是,我的数据噪音太大。
结论
在这个项目中,我获得了一些关于 Ayalon 路交通的见解,并开发了一些技术解决方案(如从少量和嘈杂的数据中检测小型和拥挤的对象,以及在低帧速率下跟踪快速目标)。然而,我相信从这个项目中得到的主要信息是,数据无处不在,通过注意到它们,我们可以用智能手机和笔记本电脑这样简单的工具做漂亮的事情。
使用 Pygame 的交通路口模拟,第 1 部分
原文:https://towardsdatascience.com/traffic-intersection-simulation-using-pygame-689d6bd7687a?source=collection_archive---------4-----------------------
实践教程
这一系列文章包含了使用 Pygame 从头开始开发交通路口模拟的分步指南。
我们在建造什么?
我们正在使用 Pygame 从头开始开发一个模拟程序,来模拟车辆穿过一个有计时器的交通灯的十字路口。它包括一个四向交通交叉口,交通信号控制着每个方向的交通流量。每个信号灯上方都有一个计时器,显示信号灯从绿色变为黄色、从黄色变为红色或从红色变为绿色的剩余时间。产生了汽车、自行车、公共汽车和卡车等交通工具,它们的运动根据信号和它们周围的交通工具来控制。这种模拟可以进一步用于数据分析或可视化 AI 或 ML 应用。下面的视频显示了我们将要构建的模拟的最终输出。
模拟的最终输出
获取图像
在开始编码并看到我们美丽的模拟变得栩栩如生之前,让我们先来看一些构建模拟所需的图片。这是我们需要的东西的清单:
- 四向交叉路口
intersection.png
- 交通信号:红色、黄色和绿色
red.png
yellow.png
green.png
- 汽车:
car.png
- 自行车:
bike.png
- 公共汽车
bus.png
- 卡车
truck.png
**请确保你根据上面图片的标题给你下载的图片重新命名。**接下来,我们需要根据四向交叉路口图像的大小来调整交通信号和车辆的图像。这是唯一需要反复试验的步骤,但是因为我们是从零开始构建模拟,所以这是必要的。
在应用程序中打开四向交叉点图像,如 Windows 的 Paint 或 Mac 的 Preview。选择一个区域,该区域等于您希望车辆在最终模拟中的外观。记下尺寸。
从路口图像中获取车辆尺寸和坐标
现在,在你选择的任何工具中打开你的车辆,把它们调整到这个尺寸。对交通信号图像也重复相同的过程。
在我们继续编码之前,还有最后一步。你可能已经注意到了,我们有车辆只朝右的图像。因此,旋转车辆的图像并保存它们,以获得面向所有方向的图像,如下图所示。
创建一个文件夹'交通路口模拟,并在其中创建一个文件夹'图片。在这里,我们将存储所有这些图像。文件夹结构如下所示,其中:
- 向下:包含面朝下的车辆图像
- 向上:包含车辆朝上的图像
- 左侧:包含面向左侧的车辆图像
- 右侧:包含面向右侧的车辆图像
- 信号:包含交通信号的图像
编码
现在让我们深入编码。
安装 Pygame
在安装 PyGame 之前,您需要在您的系统上安装 Python 3.1+。你可以从这里下载 Python。安装 Pygame 最简单的方法是使用 pip 。只需在 cmd/Terminal 中运行以下命令。
$ pip install pygame
导入所需的库
我们首先创建一个名为' simulation.py '的文件,并导入开发该模拟所需的库。
import randomimport timeimport threadingimport pygameimport sys
请注意,此时您的文件夹结构应该如下所示。
项目的文件夹结构
定义常数
接下来,我们定义一些常量,这些常量将用于模拟中车辆的移动以及交通信号计时器的控制。
# Default values of signal timers in secondsdefaultGreen = {0:20, 1:20, 2:20, 3:20}defaultRed = 150defaultYellow = 5signals = []noOfSignals = 4currentGreen = 0 # Indicates which signal is green currentlynextGreen = (currentGreen+1)%noOfSignals currentYellow = 0 # Indicates whether yellow signal is on or offspeeds = {'car':2.25, 'bus':1.8, 'truck':1.8, 'bike':2.5} # average speeds of vehicles
下面的坐标也是通过在 Paint/Preview 中打开 4 向交叉点图像并获取像素值来提取的。
# Coordinates of vehicles’ start
x = {‘right’:[0,0,0], ‘down’:[755,727,697], ‘left’:[1400,1400,1400], ‘up’:[602,627,657]}y = {‘right’:[348,370,398], ‘down’:[0,0,0], ‘left’:[498,466,436], ‘up’:[800,800,800]}vehicles = {‘right’: {0:[], 1:[], 2:[], ‘crossed’:0}, ‘down’: {0:[], 1:[], 2:[], ‘crossed’:0}, ‘left’: {0:[], 1:[], 2:[], ‘crossed’:0}, ‘up’: {0:[], 1:[], 2:[], ‘crossed’:0}}vehicleTypes = {0:’car’, 1:’bus’, 2:’truck’, 3:’bike’}directionNumbers = {0:’right’, 1:’down’, 2:’left’, 3:’up’}# Coordinates of signal image, timer, and vehicle countsignalCoods = [(530,230),(810,230),(810,570),(530,570)]signalTimerCoods = [(530,210),(810,210),(810,550),(530,550)]# Coordinates of stop linesstopLines = {‘right’: 590, ‘down’: 330, ‘left’: 800, ‘up’: 535}defaultStop = {‘right’: 580, ‘down’: 320, ‘left’: 810, ‘up’: 545}# Gap between vehiclesstoppingGap = 15 # stopping gapmovingGap = 15 # moving gap
正在初始化 Pygame
接下来,我们用下面的代码初始化 Pygame:
pygame.init()simulation = pygame.sprite.Group()
定义类别
现在让我们构建一些类,我们将在模拟中生成这些类的对象。我们需要定义两个类。
- 交通信号:我们需要为我们的模拟生成 4 个交通信号。因此,我们构建了一个具有以下属性的 TrafficSignal 类:
- 红色:红色信号定时器的值
- 黄色:黄色信号定时器的值
- 绿色:绿色信号定时器的值
- 信号文本:要显示的定时器值
class TrafficSignal:
def __init__(self, red, yellow, green):
self.red = red
self.yellow = yellow
self.green = green
self.signalText = ""
2.车辆:这是一个表示我们将在模拟中生成的车辆对象的类。Vehicle 类具有以下属性和方法:
- 车辆类别:表示车辆的类别,如轿车、公共汽车、卡车或自行车
- 速度:根据车辆的级别表示车辆的速度
- direction_number :表示方向——0 为右,1 为下,2 为左,3 为上
- 方向:表示文本格式的方向
- x :表示车辆当前的 x 坐标
- y :表示车辆当前的 y 坐标
- 已过:表示车辆是否已过信号灯
- 索引:表示本车在同方向同车道行驶的车辆中的相对位置
- 图像:表示要渲染的图像
- render():在屏幕上显示图像
- move():根据交通灯和前面的车辆控制车辆的移动
class Vehicle(pygame.sprite.Sprite):
def __init__(self, lane, vehicleClass, direction_number, direction):
pygame.sprite.Sprite.__init__(self)
self.lane = lane
self.vehicleClass = vehicleClass
self.speed = speeds[vehicleClass]
self.direction_number = direction_number
self.direction = direction
self.x = x[direction][lane]
self.y = y[direction][lane]
self.crossed = 0
vehicles[direction][lane].append(self)
self.index = len(vehicles[direction][lane]) - 1
path = "images/" + direction + "/" + vehicleClass + ".png"
self.image = pygame.image.load(path) if(len(vehicles[direction][lane])>1
and vehicles[direction][lane][self.index-1].crossed==0):
if(direction=='right'):
self.stop =
vehicles[direction][lane][self.index-1].stop
- vehicles[direction][lane][self.index-1].image.get_rect().width
- stoppingGap
elif(direction=='left'):
self.stop =
vehicles[direction][lane][self.index-1].stop
+ vehicles[direction][lane][self.index-1].image.get_rect().width
+ stoppingGap
elif(direction=='down'):
self.stop =
vehicles[direction][lane][self.index-1].stop
- vehicles[direction][lane][self.index-1].image.get_rect().height
- stoppingGap
elif(direction=='up'):
self.stop =
vehicles[direction][lane][self.index-1].stop
+ vehicles[direction][lane][self.index-1].image.get_rect().height
+ stoppingGap
else:
self.stop = defaultStop[direction]
if(direction=='right'):
temp = self.image.get_rect().width + stoppingGap
x[direction][lane] -= temp
elif(direction=='left'):
temp = self.image.get_rect().width + stoppingGap
x[direction][lane] += temp
elif(direction=='down'):
temp = self.image.get_rect().height + stoppingGap
y[direction][lane] -= temp
elif(direction=='up'):
temp = self.image.get_rect().height + stoppingGap
y[direction][lane] += temp
simulation.add(self) def render(self, screen):
screen.blit(self.image, (self.x, self.y))
让我们理解构造函数的后半部分。
在构造函数中,初始化所有变量后,我们检查是否有车辆已经出现在与当前车辆相同的方向和车道上。如果是,我们需要考虑'停止的值和前面车辆的宽度/高度,以及停止间隙,设置当前车辆的'停止的值。如果前方已经没有车辆,那么停止值被设置为等于默认停止。停止的这个值用于控制当信号为红色时车辆将停止的位置。一旦完成,我们就从车辆生成的地方更新坐标。这样做是为了避免新生成的车辆与现有车辆重叠,因为有很多车辆在红灯时停下来。
现在让我们谈谈 move()函数,它是我们模拟中最重要的代码之一。注意,这个函数也是上面定义的 Vehicle 类的一部分,需要相应地缩进。
def move(self):
if(self.direction=='right'):
if(self.crossed==0 and self.x+self.image.get_rect().width>stopLines[self.direction]):
self.crossed = 1
if((self.x+self.image.get_rect().width<=self.stop
or self.crossed == 1 or (currentGreen==0 and currentYellow==0))
and (self.index==0 or self.x+self.image.get_rect().width
<(vehicles[self.direction][self.lane][self.index-1].x - movingGap))):
self.x += self.speed
elif(self.direction=='down'):
if(self.crossed==0 and
self.y+self.image.get_rect().height>stopLines[self.direction]):
self.crossed = 1
if((self.y+self.image.get_rect().height<=self.stop
or self.crossed == 1 or (currentGreen==1 and currentYellow==0))
and (self.index==0 or self.y+self.image.get_rect().height
<(vehicles[self.direction][self.lane][self.index-1].y - movingGap))):
self.y += self.speed
elif(self.direction=='left'):
if(self.crossed==0 and
self.x<stopLines[self.direction]):
self.crossed = 1
if((self.x>=self.stop or self.crossed == 1
or (currentGreen==2 and currentYellow==0))
and (self.index==0 or self.x
>(vehicles[self.direction][self.lane][self.index-1].x
+ vehicles[self.direction][self.lane][self.index-1].image.get_rect().width
+ movingGap))):
self.x -= self.speed
elif(self.direction=='up'):
if(self.crossed==0 and
self.y<stopLines[self.direction]):
self.crossed = 1
if((self.y>=self.stop or self.crossed == 1
or (currentGreen==3 and currentYellow==0))
and (self.index==0 or self.y
>(vehicles[self.direction][self.lane][self.index-1].y
+ vehicles[self.direction][self.lane][self.index-1].image.get_rect().height
+ movingGap))):
self.y -= self.speed
对于每个方向,我们首先检查车辆是否已经穿过十字路口。这一点很重要,因为如果车辆已经过了马路,那么不管信号是绿灯还是红灯,它都可以继续行驶。所以当车辆穿越路口时,我们将穿越的值设置为 1。接下来,我们决定车辆何时移动,何时停止。车辆移动时有三种情况:
- 如果它在交叉路口之前没有到达它的停止点
- 如果它已经过了十字路口
- 如果控制车辆行驶方向的交通信号是绿色的
只有在这三种情况下,车辆的坐标才根据车辆的运动方向,通过增加/减少车辆的速度来更新。然而,我们需要考虑另一种可能性,即前方有一辆车在同一个方向和车道上行驶。在这种情况下,车辆只有在与前方车辆有足够的间隙时才能移动,这是通过考虑前方车辆的坐标和宽度/高度以及移动间隙来决定的。
创建 TrafficSignal 类的对象
接下来,我们初始化 4 个 TrafficSignal 对象,以顺时针方向从左上到左下,使用信号计时器的默认值。 ts2 的红色信号定时器设置为等于 ts1 的黄色和绿色信号定时器之和。
def initialize():
ts1 = TrafficSignal(0, defaultYellow, defaultGreen[0])
signals.append(ts1)
ts2 = TrafficSignal(ts1.yellow+ts1.green, defaultYellow, defaultGreen[1])
signals.append(ts2)
ts3 = TrafficSignal(defaultRed, defaultYellow, defaultGreen[2])
signals.append(ts3)
ts4 = TrafficSignal(defaultRed, defaultYellow, defaultGreen[3])
signals.append(ts4)
repeat()
重复()函数
在上面的 initialize()函数末尾调用的函数 repeat()是一个递归函数,它运行我们的整个模拟。这是我们模拟的驱动力。
def repeat():
global currentGreen, currentYellow, nextGreen
while(signals[currentGreen].green>0):
updateValues()
time.sleep(1)
currentYellow = 1
for i in range(0,3):
for vehicle in vehicles[directionNumbers[currentGreen]][i]:
vehicle.stop=defaultStop[directionNumbers[currentGreen]]
while(signals[currentGreen].yellow>0):
updateValues()
time.sleep(1)
currentYellow = 0
signals[currentGreen].green = defaultGreen[currentGreen]
signals[currentGreen].yellow = defaultYellow
signals[currentGreen].red = defaultRed
currentGreen = nextGreen
nextGreen = (currentGreen+1)%noOfSignals
signals[nextGreen].red = signals[currentGreen].yellow+signals[currentGreen].green
repeat()
repeat()函数首先每秒调用 updateValues()函数更新信号计时器,直到当前绿色信号的绿色计时器达到 0。然后,它将该信号设置为黄色,并重置所有在由当前绿色信号控制的方向上行驶的车辆的停止值。然后每秒再次调用 updateValues()函数,直到 currentGreen 信号的黄色计时器达到 0。current allow值现在设置为 0,因为该信号现在将变红。最后, currentGreen 信号的值被恢复为默认值, currentGreen 和 nextGreen 的值被更新以指向循环中的下一个信号,并且 nextGreen 信号的 red 定时器的值根据更新后的current green的 yellow 和 green 进行更新 repeat()函数随后调用自身,并使用更新后的 currentGreen 信号重复该过程。
updateValues()函数
函数 updateValues()每秒更新一次所有信号的计时器。
def updateValues():
for i in range(0, noOfSignals):
if(i==currentGreen):
if(currentYellow==0):
signals[i].green-=1
else:
signals[i].yellow-=1
else:
signals[i].red-=1
generateVehicles()函数
函数的作用是生成车辆。车辆的类型(轿车、公共汽车、卡车或自行车)、车道号(1 或 2)以及车辆行驶的方向由随机数决定。变量 dist 以百分比表示车辆的累积分布。因此,[25,50,75,100]的分布意味着所有 4 个方向的车辆分布相等(各 25%)。其他一些分布可以是[20,50,70,100],[10,20,30,100]等等。每 1 秒钟后,一辆新的车辆将添加到模拟中。
def generateVehicles():
while(True):
vehicle_type = random.randint(0,3)
lane_number = random.randint(1,2)
temp = random.randint(0,99)
direction_number = 0
dist= [25,50,75,100]
if(temp<dist[0]):
direction_number = 0
elif(temp<dist[1]):
direction_number = 1
elif(temp<dist[2]):
direction_number = 2
elif(temp<dist[3]):
direction_number = 3
Vehicle(lane_number, vehicleTypes[vehicle_type], direction_number, directionNumbers[direction_number])
time.sleep(1)
主类
我们已经到达了我们的最后一段代码,Main 类,之后我们可以看到我们的模拟在运行。
class Main:
thread1 = threading.Thread(name="initialization",target=initialize, args=())
thread1.daemon = True
thread1.start()
black = (0, 0, 0)
white = (255, 255, 255)
screenWidth = 1400
screenHeight = 800
screenSize = (screenWidth, screenHeight)
background = pygame.image.load('images/intersection.png')
screen = pygame.display.set_mode(screenSize)
pygame.display.set_caption("SIMULATION") redSignal = pygame.image.load('images/signals/red.png')
yellowSignal = pygame.image.load('images/signals/yellow.png')
greenSignal = pygame.image.load('images/signals/green.png')
font = pygame.font.Font(None, 30) thread2 = threading.Thread(name="generateVehicles",target=generateVehicles, args=())
thread2.daemon = True
thread2.start() while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit() screen.blit(background,(0,0))
for i in range(0,noOfSignals):
if(i==currentGreen):
if(currentYellow==1):
signals[i].signalText = signals[i].yellow
screen.blit(yellowSignal, signalCoods[i])
else:
signals[i].signalText = signals[i].green
screen.blit(greenSignal, signalCoods[i])
else:
if(signals[i].red<=10):
signals[i].signalText = signals[i].red
else:
signals[i].signalText = "---"
screen.blit(redSignal, signalCoods[i])
signalTexts = ["","","",""]
for i in range(0,noOfSignals):
signalTexts[i] = font.render(str(signals[i].signalText), True, white, black)
screen.blit(signalTexts[i],signalTimerCoods[i])
for vehicle in simulation:
screen.blit(vehicle.image, [vehicle.x, vehicle.y])
vehicle.move()
pygame.display.update()
让我们通过将 Main()函数分解成更小的部分来理解它。我们首先为 initialize()方法创建一个单独的线程,它实例化了 4 个 TrafficSignal 对象。然后我们定义两种颜色,白色和黑色,我们将在我们的显示中使用。接下来,我们定义屏幕宽度和屏幕大小,以及要在模拟窗口中显示的背景和标题。然后,我们加载 3 个信号的图像,即红色、黄色和绿色。现在我们为 generateVehicles()创建另一个线程。
接下来,我们运行一个无限循环,不断更新我们的模拟屏幕。在循环中,我们首先定义退出标准。在下一节中,我们将为 4 个交通信号中的每一个呈现适当的信号图像和信号计时器。最后,我们在屏幕上呈现车辆,并在每辆车上调用函数 move()。该功能使车辆在下一次更新时移动。
blit() 函数用于渲染屏幕上的对象。它需要两个参数,要渲染的图像和坐标。坐标指向图像的左上角。
快好了!现在我们只需要调用 Main()程序,我们的代码就完成了。
Main()
运行代码
是时候看看结果了。启动 cmd/终端并运行命令:
$ python simulation.py
最终模拟输出的快照
瞧啊。我们有一个从零开始构建的 4 向交叉路口的全功能模拟,从获取交叉路口、信号和车辆的图像,到编码信号切换和车辆移动的逻辑。
源代码:https://github . com/mihir-m-Gandhi/Basic-Traffic-cross-Simulation
这是系列文章的第一部分:
- 使用 Pygame 的交通路口模拟,第 1 部分
- 使用 Pygame 的交通路口模拟,第 2 部分
- 使用 Pygame 的交通路口模拟,第 3 部分
这种模拟是作为一个名为“使用人工智能的交通灯智能控制”的研究项目的一部分开发的。点击查看其演示视频。这项研究工作在 2020 年 IEEE 工程最新进展和创新国际会议(ICRAIE)上提出,并在 IEEE Xplore 上发表。在这里阅读论文。
感谢阅读!我希望这篇文章是有帮助的。如果您有任何疑问或需要进一步澄清,请随时联系我LinkedIn。
使用 Pygame 的交通路口模拟,第 2 部分
原文:https://towardsdatascience.com/traffic-intersection-simulation-using-pygame-part-2-9ce512fdb253?source=collection_archive---------21-----------------------
这一系列文章包含了使用 Pygame 从头开始开发交通路口模拟的分步指南。
我们增加了什么功能?
在本文中,我们将在我的上一篇文章中开发的模拟中添加更多的特性。这种更新的模拟将更接*真实生活场景,可以有效地用于数据分析任务或人工智能应用。首先,我们将为生成的车辆添加转向功能。因此,与之前所有车辆直行通过十字路口的模拟不同,在修改后的模拟中,一些车辆将左转,一些车辆将右转,一些车辆将直行。第二,我们将增加一个功能,让我们在汽车、公共汽车、卡车和自行车中选择我们想要的交通工具类型。第三,我们将添加一个随机绿色信号定时器功能,它将绿色信号时间设置为一个在给定范围内产生的随机数,并有助于建模任务。下面的视频显示了我们将要构建的模拟的最终输出。
模拟的最终输出
安装
我们从上一篇文章中停止的地方开始。按照文章中的步骤设置环境并构建一个基本的模拟,看起来有点像 this 。在本文中,我们将修改基本模拟,以包括前面提到的附加功能。或者,您可以在这里找到基本模拟的源代码以及设置说明。
编码
为了将额外的功能编码到我们现有的模拟中,我们需要添加一些新的变量,定义一些新的函数,并修改一些现有的函数。
定义变量
这里,我们增加了两个变量的值,停止间隙和移动间隙。这样做是为了防止车辆转弯时重叠。
# modify existing variables
stoppingGap = 25
movingGap = 25
接下来,我们定义一些实现我们期望的功能所需的新变量。
# add new variables
allowedVehicleTypes = {'car': True, 'bus': True, 'truck': True, 'bike': True}
allowedVehicleTypesList = []
vehiclesTurned = {'right': {1:[], 2:[]}, 'down': {1:[], 2:[]}, 'left': {1:[], 2:[]}, 'up': {1:[], 2:[]}}
vehiclesNotTurned = {'right': {1:[], 2:[]}, 'down': {1:[], 2:[]}, 'left': {1:[], 2:[]}, 'up': {1:[], 2:[]}}
rotationAngle = 3
mid = {'right': {'x':705, 'y':445}, 'down': {'x':695, 'y':450}, 'left': {'x':695, 'y':425}, 'up': {'x':695, 'y':400}}
randomGreenSignalTimer = True
randomGreenSignalTimerRange = [10,20]
allowedVehicleTypes 字典用于控制模拟中将生成哪些车型。 mid 字典表示十字路口图像中点的坐标,车辆将从这里右转穿过十字路口。 randomGreenSignalTimer 用于控制绿色信号定时器是随机设置还是等于默认值。如果 randomGreenSignalTimer 设置为真,则在randomgreensignaltimerrage指定的范围内的一个随机数被设置为绿色信号时间。
修改车辆类别
我们需要给 Vehicle 类添加一些新的属性,并更新 move()函数。车辆类别现在具有以下附加属性:
- willTurn :表示车辆在十字路口是否转弯
- 转向:表示车辆是否已经转向
- 旋转角度:表示每次调用 move()时车辆旋转的角度
- crossedIndex :表示车辆通过路口后,在同方向同车道行驶的车辆中的相对位置
- 指标:表示本车在同方向同车道行驶的车辆中的相对位置
- originalImage:表示车辆的原始图像
构造函数也需要修改以适应这些新的属性。改装车类看起来是这样的。
改装车辆类别
构造函数的后半部分和 render ()函数保持不变。
现在是我们代码中最重要也是最复杂的部分, move ()函数。让我们关注向右移动的车辆的代码,因为对于其他方向检查相同的条件,并且代码非常相似。
向右移动车辆的部分移动()功能
对于每个方向,我们首先检查车辆是否已经穿过十字路口。这一点很重要,因为如果车辆已经过了马路,那么不管信号是绿色还是红色,它都可以继续行驶,这仅仅取决于前面的车辆。所以当车辆穿越路口时,我们将穿越的值设置为 1。现在,如果车辆直行,即不转弯,那么我们将其添加到未转弯车辆列表中,并更新其交叉索引,这是其在未转弯车辆列表中的索引。这样做是因为车辆的顺序在交叉路口后会发生变化,有些会转弯,有些不会,并且之前定义的车辆列表对于防止它们重叠没有用。
接下来,如果车辆要转弯,它会直行直到十字路口中间的转弯点。这种移动可能发生在三种情况下:
- 如果它在交叉路口之前没有到达它的停止点
- 如果它已经过了十字路口
- 如果控制车辆行驶方向的交通信号是绿色的
与此同时,我们需要确保在车辆移动时不会与前方车辆重叠。这是通过考虑以下三个参数决定的:前方车辆的坐标、前方车辆的宽度/高度和移动间隙。此外,如果前面的车辆已经转向,那么我们不必担心重叠。只有当这三个条件中的任何一个都满足并且没有重叠时,车辆的坐标才根据其运动方向通过增加/减少车辆的速度来更新。
一旦车辆越过其转向点,如果转向值为 0,则车辆在旋转的同时沿 x 轴和 y 轴移动。一旦旋转角度为 90 度,则转动的变量被设置为 1,车辆被添加到车辆转动的列表中,并且其交叉索引被更新。否则,如果转向值为 1,车辆仅在与前方车辆有足够的间隙时移动,使用车辆转向列表。这是基于上述相同的三个参数来决定的。这种转向逻辑是为两个车道分别编码的,以便对模拟有更多的控制。
这是使用原始图像的地方。旋转图像被视为破坏性变换。这意味着每次执行该操作时,图像都会丢失像素数据。因此,重新变换原始图像比多次变换图像要好。因此,我们通过旋转角度来旋转原始图像,并通过修改后的图像来更新图像,同时保持原始图像不变。
最后,如果车辆不打算转弯,那么第一部分保持与转弯车辆相同,它们一直向前移动,直到穿过十字路口。然而,在穿过十字路口后,如果与前面的车辆有足够的距离,他们就移动,这是使用未转弯车辆列表发现的。同样,这是基于上述三个参数决定的。
下面给出了整个 move() 函数。注意,该功能也是上面定义的车辆类的一部分,需要相应地缩进。
完成 move()函数
创建 TrafficSignal 类的对象
我们需要修改 initialize ()函数,以便如果 randomGreenSignalTime 被设置为 True,则 4 个 TrafficSignal 对象被初始化为由randomgreensignaltimerrage指定的范围内的随机值。
def initialize():
minTime = randomGreenSignalTimerRange[0]
maxTime = randomGreenSignalTimerRange[1]
if(randomGreenSignalTimer):
ts1 = TrafficSignal(0, defaultYellow, random.randint(minTime,maxTime))
signals.append(ts1)
ts2 = TrafficSignal(ts1.yellow+ts1.green, defaultYellow, random.randint(minTime,maxTime))
signals.append(ts2)
ts3 = TrafficSignal(defaultRed, defaultYellow, random.randint(minTime,maxTime))
signals.append(ts3)
ts4 = TrafficSignal(defaultRed, defaultYellow, random.randint(minTime,maxTime))
signals.append(ts4)
else:
ts1 = TrafficSignal(0, defaultYellow, defaultGreen[0])
signals.append(ts1)
ts2 = TrafficSignal(ts1.yellow+ts1.green, defaultYellow, defaultGreen[1])
signals.append(ts2)
ts3 = TrafficSignal(defaultRed, defaultYellow, defaultGreen[2])
signals.append(ts3)
ts4 = TrafficSignal(defaultRed, defaultYellow, defaultGreen[3])
signals.append(ts4)
repeat()
重复()函数
这同样适用于重复()功能。唯一的变化是,如果 randomGreenSignalTimer 设置为 True,我们在randomgreensignaltimerrage【0】和randomgreensignaltimerrage【1】之间生成一个随机数,并将其设置为绿灯信号时间。
def repeat():
global currentGreen, currentYellow, nextGreen
while(signals[currentGreen].green>0):
updateValues()
time.sleep(1)
currentYellow = 1
for i in range(0,3):
for vehicle in vehicles[directionNumbers[currentGreen]][i]:
vehicle.stop=defaultStop[directionNumbers[currentGreen]]
while(signals[currentGreen].yellow>0):
updateValues()
time.sleep(1)
currentYellow = 0
minTime = randomGreenSignalTimerRange[0]
maxTime = randomGreenSignalTimerRange[1]
if(randomGreenSignalTimer):
signals[currentGreen].green=random.randint(minTime, maxTime)
else:
signals[currentGreen].green = defaultGreen[currentGreen]
signals[currentGreen].yellow = defaultYellow
signals[currentGreen].red = defaultRed
currentGreen = nextGreen
nextGreen = (currentGreen+1)%noOfSignals
signals[nextGreen].red = signals[currentGreen].yellow+signals[currentGreen].green
repeat()
generateVehicles()函数
generateVehicles ()函数修改如下。通过从allowedVehicleTypesList中生成一个随机数来设置车辆类型。该列表填充在下面的主类中。我们定义一个新的变量 will_turn ,初始设置为 0。 will_turn 然后用随机数设定为 1,有 40%的几率。最后,除了现有变量之外,在创建 Vehicle 类的对象时,这个 will_turn 变量也被传入构造函数。
def generateVehicles():
while(True):
vehicle_type = random.choice(allowedVehicleTypesList)
lane_number = random.randint(1,2)
will_turn = 0
if(lane_number == 1):
temp = random.randint(0,99)
if(temp<40):
will_turn = 1
elif(lane_number == 2):
temp = random.randint(0,99)
if(temp<40):
will_turn = 1
temp = random.randint(0,99)
direction_number = 0
dist = [25,50,75,100]
if(temp<dist[0]):
direction_number = 0
elif(temp<dist[1]):
direction_number = 1
elif(temp<dist[2]):
direction_number = 2
elif(temp<dist[3]):
direction_number = 3
Vehicle(lane_number, vehicleTypes[vehicle_type], direction_number, directionNumbers[direction_number], will_turn)
time.sleep(1)
主类
这里只有一个小补充。我们只需要根据 allowedVehicleTypes 字典填充allowed vehicle types list。为此,需要将下面的代码添加到主类的开头,如下所示。其余的主级保持不变。
class Main:
global allowedVehicleTypesList
i = 0
for vehicleType in allowedVehicleTypes:
if(allowedVehicleTypes[vehicleType]):
allowedVehicleTypesList.append(i)
i += 1
运行代码
是时候看看结果了。启动 cmd/终端并运行命令:
$ python simulation.py
显示车辆转向的最终模拟输出快照
显示模拟的快照:(I)仅汽车,(ii)仅重型车辆(公共汽车和卡车)
我们完了! 我们在模拟中增加了三个额外的功能——转弯功能、车辆类型控制器和随机绿灯定时器功能。这使得模拟更能代表现实生活中的场景,并给我们更多的控制来定制它,从而成为数据分析以及 AI 或 ML 应用程序的便捷工具。
源代码:https://github . com/mihir-m-Gandhi/Traffic-crossion-Simulation-with-Turns
这是系列文章的第二部分:
- 使用 Pygame 的交通路口模拟,第 1 部分
- 使用 Pygame 的交通路口模拟,第 2 部分
- 使用 Pygame 的交通路口模拟,第 3 部分
这种模拟是作为一个名为“使用人工智能的交通灯智能控制”的研究项目的一部分开发的。查看它的演示视频这里。这项研究工作在 2020 年 IEEE 工程最新进展和创新国际会议(ICRAIE)上提出,并在 IEEE Xplore 上发表。看这里的报纸。
感谢阅读!我希望这篇文章是有帮助的。如有疑问或需要进一步澄清,欢迎在LinkedIn联系我。
使用 Pygame 的交通路口模拟,第 3 部分
原文:https://towardsdatascience.com/traffic-intersection-simulation-using-pygame-part-3-98159178ef30?source=collection_archive---------19-----------------------
使用 Pygame 从头开始开发交通路口模拟的分步指南。
我们增加了什么功能?
在本文中,我们将在我的上一篇文章中开发的模拟中进一步添加更多的特性。更新后的模拟将显示每个方向穿过交叉路口的车辆的计数,显示自模拟开始后经过的时间**,启用设置模拟持续时间,每秒在终端上打印信号计时器以供分析,并打印一些统计数据,如方向车辆计数、车辆总数和模拟结束时的模拟时间。然后,这些统计数据和计时器可用于建模问题,如研究到达间隔时间、等待时间、&周转时间、交通数据分析&交通信号性能分析等数据分析任务,以及智能交通控制的自适应交通灯系统& V2V 通信等人工智能应用。下面的视频显示了我们将要构建的模拟的最终输出。**
模拟的最终输出
安装
我们从上一篇文章中停止的地方开始。按照文章中的步骤设置环境并构建模拟,看起来有点像 this 。在本文中,我们将修改模拟,以包括前面提到的附加功能。你可以在这里找到模拟的源代码以及设置说明。
编码
为了将额外的功能编码到我们现有的模拟中,我们需要添加一些新的变量,定义一些新的函数,并修改一些现有的函数。
导入所需的库
只需要导入一个额外的库,即“os”。
import os
定义变量
我们需要定义一些新的变量来实现我们想要的功能。
timeElapsed = 0
simulationTime = 300
timeElapsedCoods = (1100,50)
vehicleCountTexts = ["0", "0", "0", "0"]
vehicleCountCoods = [(480,210),(880,210),(880,550),(480,550)]
timeElapsed 变量存储自模拟开始以来经过的时间值,初始设置为 0。simulationTime 变量以秒为单位表示模拟持续时间,因此值 300 表示 300/60,即 5 分钟。vehicleCountTexts 表示以[右、下、左、上]方向穿过交叉口的车辆数量。timeElapsedCoods 和 vehicleCountCoods 表示 timeElapsed 和 vehicleCountTexts 将在屏幕上呈现的坐标。
交通信号和车辆类别没有变化。
printStatus()函数
该功能每秒钟在终端上打印所有 4 个信号的定时器值。此功能使我们能够检查模拟场景中的幕后情况,并仔细分析计时器值。
def printStatus():
for i in range(0, 4):
if(signals[i] != None):
if(i==currentGreen):
if(currentYellow==0):
print(" GREEN TS",i+1,"-> r:",signals[i].red," y:",signals[i].yellow," g:",signals[i].green)
else:
print("YELLOW TS",i+1,"-> r:",signals[i].red," y:",signals[i].yellow," g:",signals[i].green)
else:
print(" RED TS",i+1,"-> r:",signals[i].red," y:",signals[i].yellow," g:",signals[i].green)
print()
计时器打印在终端上,如下图所示。格式如下:
signal color SignalNumber→r:red timer y:yellow timer g:green timer,其中 signal number 从左上开始,顺时针移动到左下。
端子上印有信号计时器
重复()函数
因为我们希望每秒在终端上打印计时器,所以我们在 repeat 函数()的 while 循环中调用 printStatus()函数,如下所示。
def repeat():
global currentGreen, currentYellow, nextGreen
while(signals[currentGreen].green>0):
**printStatus()**
updateValues()
time.sleep(1)
currentYellow = 1
for i in range(0,3):
for vehicle in vehicles[directionNumbers[currentGreen]][i]:
vehicle.stop=defaultStop[directionNumbers[currentGreen]]
while(signals[currentGreen].yellow>0):
**printStatus()**
updateValues()
time.sleep(1)
currentYellow = 0
minTime = randomGreenSignalTimerRange[0]
maxTime = randomGreenSignalTimerRange[1]
if(randomGreenSignalTimer):
signals[currentGreen].green=random.randint(minTime, maxTime)
else:
signals[currentGreen].green = defaultGreen[currentGreen]
signals[currentGreen].yellow = defaultYellow
signals[currentGreen].red = defaultRed
currentGreen = nextGreen
nextGreen = (currentGreen+1)%noOfSignals
signals[nextGreen].red = signals[currentGreen].yellow+signals[currentGreen].green
repeat()
showStats()函数
当我们退出模拟或当 time elapsed 等于 simulationTime 时模拟自行终止时,此函数打印方向车辆计数以及累计统计数据,如从所有方向穿过交叉口的车辆总数以及模拟结束时经过的总时间。
def showStats():
totalVehicles = 0
print('Direction-wise Vehicle Counts')
for i in range(0,4):
if(signals[i]!=None):
print('Direction',i+1,':',vehicles[directionNumbers[i]]['crossed'])
totalVehicles += vehicles[directionNumbers[i]]['crossed']
print('Total vehicles passed:',totalVehicles)
print('Total time:',timeElapsed)
模拟结束时,统计数据打印在终端上
simTime()函数
该函数负责每秒更新 timeElapsed 变量,并在 timeElapsed 等于 simulationTime 时终止模拟。正如我们在下面看到的,showStats()在退出之前被调用。
def simTime():
global timeElapsed, simulationTime
while(True):
timeElapsed += 1
time.sleep(1)
if(timeElapsed==simulationTime):
showStats()
os._exit(1)
主类
我们需要对主类做一些补充。首先,我们需要为 simTime()函数创建一个新线程,它每秒更新一次 timeElapsed(第 23–25 行)。其次,我们需要在退出模拟之前调用 showStats()(第 32 行)。第三,我们需要添加代码以在模拟屏幕上显示车辆计数和经过的时间(第 55–63 行)。主类的其余部分保持不变。
更新的主类
运行代码
是时候看看结果了。启动 cmd/终端并运行命令:
$ python simulation.py
最终模拟输出的快照,在右上角显示每个信号旁边的车辆计数和经过的时间(图片由作者提供)
现在我们有了最后的模拟! 我们在模拟中增加了一些统计和分析功能——车辆计数、经过的时间、终端上打印的计时器、模拟结束时的累积统计数据,以及设置模拟结束时间的能力。这些统计数据、计时器和日志在建模问题、数据分析任务和 AI 应用程序中非常有用。在根据您的应用定制仿真时,它们也有助于有效的调试。
源代码:https://github . com/mihir-m-Gandhi/Traffic-crossion-Simulation-with-Stats
这是系列文章的第三部分:
- 使用 Pygame 的交通路口模拟,第 1 部分
- 使用 Pygame 的交通路口模拟,第 2 部分
- 使用 Pygame 的交通路口模拟,第 3 部分
这种模拟是作为一个名为“使用人工智能的交通灯智能控制”的研究项目的一部分开发的。点击查看其演示视频。这项研究工作在 2020 年 IEEE 工程最新进展和创新国际会议
(ICRAIE)上提出,并发表在 IEEE Xplore 上。在这里阅读论文。
特别感谢 达尔山 和 杰尼尔·沙阿 为本系列所有文章进行校对。
感谢阅读!我希望这篇文章是有帮助的。如有疑问或需要进一步澄清,欢迎联系我LinkedIn。
基于速度转移矩阵的道路交通状态聚类
原文:https://towardsdatascience.com/traffic-state-classification-using-the-speed-transition-matrices-36f7a03ca776?source=collection_archive---------20-----------------------
一种新的城市交通状态分类方法
阿尔瓦罗·雷耶斯在号航天飞机上拍摄的照片
速度转移矩阵(STM) 是一种用于交通状态估计、异常检测等各种交通相关分析的新型交通数据技术。本文将展示 STM 在处理 GPS 数据时如何应用于交通状态分类问题。整张纸可以在这里找到【1】。
介绍
聚类技术主要用于对未标记的数据集进行分组。处理流量数据时,目标是将数据群集到遵循相似流量模式的组中。这样,对大型流量数据集的分析就更简单,也更容易解释。在本文中,我们试图对数据进行分组,以表示不同的流量状态,如“拥塞”、“不稳定流量”等。 [2] 。
时间序列最常用于表示交通参数的变化,如速度、延误或交通量。大多数情况下,需要聚合大量数据来创建此类时间序列。在这一步中,会出现不同的问题,大多与较大的偏差有关。STM 就是为了解决这个问题而提出的,它提供了一种从交通数据中提取更多信息的方法。
如欲了解更多关于 STM 的信息,请参考以下文章:
https://medium.com/analytics-vidhya/speed-transition-matrix-novel-road-traffic-data-modeling-technique-d37bd82398d1
方法学
1。使用质心
第一步是只使用 2D 空间中的一个点来表示 STM。我们将通过估算每个观测 STM 的质心(COM)来完成:
每个 STM 的 COM 估计(图像作者:作者)
正如我们在图片中看到的,COM 是处理 STM 的一个重要特性。它显示了两个连续路段之间最可能的速度转换。当它被放置在右下角时,它表示正常的交通流量,因为车辆在起点和终点链接上的速度很快。另一方面,当放置在左上角时,它表示拥塞,因为起点和目的地链接的速度非常低。
当我们计算每个 STM 的 COMs 时,结果如下:
每个观测到的 STM 的 COM 计算结果(图片来源:作者[1])
2。聚类
现在,我们使用一些聚类方法来定义最佳的聚类数。每个聚类将代表一个交通状态。当应用分层凝聚聚类和拐点方法时,得到的聚类数为 3。图片在这里:
层次凝聚聚类和膝盖方法的结果(图片来源:作者[1])
这些类别的标签定义如下:
- “自由流”——车辆之间几乎没有相互作用的交通流。
- “稳定流”——有一些相互作用的交通流,没有严重的后果。
- “拥堵”——拥堵的交通流量导致交通堵塞。
3。领域知识验证
验证过程涉及到将得到的类与领域知识数据进行比较。众所周知的服务水*(LoS)的 HCM 值代表了用于交通状态估计过程的特定领域知识数据。HCM 根据驾驶速度值为路段定义了六个服务级别,从 A 到 F,其中 LoS A 代表最佳驾驶条件,LoS F 代表最差驾驶条件。首先,以如下方式将 LoS 值合并为三个类别:(I)由标记为 A 和 B 的 LoS 表示的自由流动交通状况,(ii)由标记为 C 和 D 的 LoS 表示的交通状况被标记为稳定,以及(iii)由 LoS 表示的拥堵交通状况被标记为 E 和 f。然后,标记的数据集被用作基础真值,并与聚集聚类结果进行比较。总准确率为 91%,混淆矩阵如下图所示:
困惑矩阵(图片作者:作者[1])
4.形象化
下图显示了所获得结果的可视化效果。结果显示为非高峰时间(左)和高峰时间间隔(右)。
三类可视化:拥堵(红色)、稳定流(黄色)和自由流(绿色)
结论
在这篇文章中,STM 被描述为一种新颖的交通数据建模技术,显示了巨大的交通数据表示和分析潜力。交通状态估计只是使用 STM 可以解决的许多问题之一。最*的论文【3】【4】展示了一些检测流量异常的有趣应用。
这是第一篇发表的论文,展示了应用 STMs 的可能性!如果您对这类研究感兴趣,请随时关注我的文章。这仍然是一项“进行中的工作”,所以如果你有任何问题或建议,请随时评论或联系我!
领英:【https://www.linkedin.com/in/leo-tisljaric-28a56b123/
参考
[1]l . tiljari,T. Cari,B. Abramovi 和 T. Fratrovi,使用速度转换矩阵对全市范围内的交通状态进行评估和分类(2020) ,可持续性,12,18:7278–7294
[2] J.C. Herrera,D.B. Work,R. Herring,X.J. Ban,Q. Jacobson,A.M. Bayen,通过支持 GPS 的移动电话获得的交通数据的评估:移动世纪现场实验(2010) , Transp。零件紧急情况。技术,18,1:568–583。
[3]l . tiljari,S. Fernandes,T. Cari,和 J. Gama,利用张量分解方法对城市道路网进行时空交通异常检测 (2020),载于发现科学。计算机科学讲义,A. Appice、G. Tsoumakas、Y. Manolopoulos 和 S. Matwin 编辑。湛:施普林格,12323,1:674–688。
[4]l . tiljari,Majstorovi、T. Erdeli 和 T. Cari,使用速度转换矩阵进行城市道路交通异常检测的措施(2020) ,载于国际信息和通信技术、电子和微电子会议记录,268–275。
训练自定义的 Tesseract OCR 模型,作为阅读儿童笔迹的 Google vision 的替代方案
原文:https://towardsdatascience.com/train-a-custom-tesseract-ocr-model-as-an-alternative-to-google-vision-ocr-for-reading-childrens-db8ba41571c8?source=collection_archive---------9-----------------------
一个故事小队项目
T 他是 Story Squad 的联合创始人,Graig Peterson 和 Darwin Johnson 开创了一个*台,让孩子们有机会发挥创造力,提高他们的阅读和写作能力,同时减少他们花在屏幕上的时间。故事班通过游戏化来保持这个过程的趣味性。
图片由故事小队提供
那么,这个游戏是如何让孩子们参与进来,而不是在他们的屏幕上呢?
下面是一个解释故事班的视频:
Graig Peterson(Story Squad 的联合创始人)的视频
什么是 OCR? 光学字符识别(OCR)是一种从扫描文档或图像文件的打印或手写文本中自动提取数据的解决方案。然后,文本被转换成可以通过数据处理进行操作的形式。OCR 有许多应用,例如,支票、护照、银行结单和收据等商业文件的数据输入、自动车牌识别和交通标志识别。
为什么这个项目需要 OCR?
我们需要转录孩子们上传的故事,并处理转录。在游戏中,每个孩子都需要与另一个写作水*相似的孩子配对,每个团队都应该与同一类别的另一个团队配对,这样游戏才会有竞争性和趣味性。这就是数据科学团队的用武之地。
- 使用 NLP 工具来找出写作的复杂程度,可以对参与者进行适当的分组。
- 我们需要 OCR 在家长仪表板上创建一个单词云,让家长看到他们的孩子写了什么。
- 我们需要监控孩子的进步(随着时间的推移,他们的复杂程度有所提高吗?他们*均写多少字?)
- 我们还想标记不恰当的词语。尽管每个故事都会被人看到,但我们会采取一切预防措施,通过添加自定义的脏话过滤器,让*台成为孩子们的安全空间。
tessera CT OCR Vs Google vision OCR Google vision 正在以大约 80–95%的准确率记录手写图像。我们现在面临的问题是这项服务是有价格标签的。利益相关者希望降低这些成本。
DS 团队的任务是训练一个宇宙魔方 OCR 模型,一个开源的 OCR,作为 Google vision 的替代方案。
宇宙魔方 OCR 模型训练周期
图片由作者提供
- 数据准备:数据清理和标记
Tesseract OCR 接收分段的手写图像及其相应的转录文本(基本事实)。这对需要有相同的名字
图片由作者提供
“塞利纳,”她会说,“当世界
如果存在文件命名不匹配,训练将会中断。您必须通过删除或重命名受影响的文件来纠正不匹配。repo(utils/check _ ground truth _ files _ pair . py)中有一个脚本可以检查是否存在不匹配。那些进行数据清理的人可以在将数据推送到回购之前纠正这些错误。此外,由于 COPPA ,GitHub 上不允许儿童写作的完整图像。有一个脚本检查数据中的完整图像(utils/essay check _ w _ image _ height . py)。
过去,数据准备有两种不同的方式。文件夹 32 和 52 中的图像经过预处理,将图像二值化,然后使用命令行上的脚本将它们分段。文件夹 31-和 51-(只有最后 5 个故事)被清理,并使用画图软件和另一个手动 python 脚本(不包括在 repo 中)手工标记。文件夹 31 在剪辑前没有二进制化。你可以在 ds repo/data/story-squad-ground-truth 中找到经过清理和标记的数据。
开发了一个数据管道来实现数据准备过程的半自动化。您可以在 data_management 文件夹中找到它。
2.宇宙魔方模型定型和调整
- GPU 箱将由讲师设置
- 下载 pem 键获得进入 EE2 机器的许可
- 在终端中,使用 pem 键将 cd 放入目录,并运行 ssh 命令以进入 EE2 机器
- git 克隆 ds repo(如果 repo 中有新数据,将其移动到tes strain \ \ data \ \ story squad-ground-truthdir)
- 在根目录下运行source training _ setup . sh命令
- cd 进入test strain并通过运行命令source ocr \ \ bin \ \ activate激活虚拟环境。如果有效,您应该切换到(OCR)环境
- 在 tesstrain dir 中运行该命令来训练模型 make trainingMODEL _ NAME = story squad START _ MODEL = eng Tess data =/home/Ubuntu/tesserac t/Tess data
- 上面的命令将使用默认的超参数来训练模型。要调整超参数,必须修改命令行以指示超参数,例如,如果您想将 PSM 设置为 7 而不是使用默认值,则必须修改命令行。
- 注意:这大约需要一个小时来运行。如果 ground_truth 和 snippet 之间有任何不匹配,将会出现一个错误。你需要进入 story-squad-ground-truth 目录,通过删除或上传相应的文件来解决问题。当问题解决后,只需再次运行训练命令,模型将从出错的地方开始。
- 一旦模型完成训练,新的模型将被存储在测试应变\ \数据中。现在默认的名字是 storysquad.traineddata 。如果新模型没有被移动到另一个目录或重命名,它们将覆盖旧模型。
由于 EC2 实例没有足够的空间让 tesseract 训练更多的数据,因此为将来的 tesseract 训练建立了一个 docker 文件* ds repo \ docker file _ tessera CT _ training
*。
3 & 4 数据预处理和转录
在使用新模型转录图像之前,进行数据预处理。每个图像需要不同的预处理方法。如果图像是打印文本,它几乎不需要预处理。有几个预处理方法是通用的,你总是想确保图像没有倾斜,并以一种或另一种形式二值化。印刷文本不需要太多的预处理。Tesseract OCR 可以准确地读取印刷文本和整洁书写的文字,但可能难以转录独特的字体和低质量的图像。
图片由作者提供
使用十个故事和它们相应的基本事实(人类转录的)来测试模型性能。我们还使用了一个整洁的手写图像作为对照(这个图像几乎不需要预处理)。
这个阶段包括使用 NLP 技术来提高转录文本的准确性。对于大多数 OCR 应用程序来说,这个阶段是必不可少的。然而,利益相关者希望保留儿童的话语。如果他们拼错了一个单词,自然语言处理技术可能会纠正它。
我们专注于使用准确度分数评估模型。我们遇到了准确性分数的问题。该模型对一些它根本无法转录的图像给出了很高的精确度。未来的群组可能会考虑使用其他评估指标,如余弦相似度、CER(字符错误率)和 WER(单词错误率)。
关键时刻
我们在整洁的手写图像(full_sample2.png)上使用模型取得了一些进展。准确率分数提高了 13%。不幸的是,该模型在儿童手写图像上表现不佳。我们的准确率在 0-20%之间。预处理图像将一些分数提高了大约 10%。
图片由作者提供
接下来是什么?
我们还有很长的路要走。DS 团队需要与经理和利益相关者讨论前进的方向。
以下是我们认为有助于继续我们工作的一些任务。
- 清除更多数据
- 构建一个 ML 基础设施,用于自动化关于模型结构、超参数和性能指标的重要信息
- 数据管道的优化
- 使用 Docker 容器进行 OCR 训练
- 构建预处理管道
参考文献
兰姆达学校涂鸦体育场 DS 回购:【https://github.com/Lambda-School-Labs/scribble-stadium-ds
儿童在线隐私保护规则(“COPPA”):https://www . FTC . gov/enforcement/rules/Rule making-regulatory-reform-proceedings/children-Online-Privacy-Protection-Rule
故事小队(Scribble stadium):https://www . story Squad . education/
训练一个用于检测超参数新闻内容的长模型
原文:https://towardsdatascience.com/train-a-longformer-for-detecting-hyperpartisan-news-content-7c141230784e?source=collection_archive---------39-----------------------
用数据做很酷的事情
资料来源:联合国人口与发展论坛—https://unsplash.com/photos/WYd_PkCa1BY
介绍
超党派新闻被描述为极度偏向一个政党的新闻。这可能是极左或极右。不幸的是,目前美国存在着严重的政治两极分化。人们只喜欢他们群体成员分享的政策和观点。最*美国国会大厦的骚乱暴露了自由派和保守派选民之间日益扩大的差距。随着时间的推移,这种政治分歧越来越大。查看皮尤研究中心关于 2020 年惊人发现的这篇文章。他们的研究表明,拜登和特朗普的选民在美国核心价值观等基本问题上存在根本分歧。80%的拜登支持者认为,特朗普的支持者不仅在政治方面有不同的优先考虑,而且有不同的核心价值观。同样比例的特朗普支持者对另一个阵营也有同样的想法。这是惊人的不信任!
在许多情况下,现有的新闻媒体通过让读者接触高度党派化的观点,加剧了这种两极分化。在这篇博客中,我想使用一个 Longformer 模型来检测超参数新闻。如果可以检测到超级名人新闻,那么这些新闻就会被自动标记,要么被删除,要么至少读者会被告知。这个模型的代码可以在我的 Colab 笔记本这里找到。我也上传到我的 GitHub 这里。
数据集和预处理
对于这个博客,我们使用超级新闻数据集。语义评估研讨会公开了这个数据集。我已经用 HuggingFace 数据集库下载了它。数据集库提供了一个简单的 API 来下载和访问数据集。
!pip install datasetsdataset = datasets.load_dataset('hyperpartisan_news_detection', 'bypublisher')
数据集在训练集中有 60 万篇新闻文章,在验证集中有 60 万篇。每篇文章都有一个“真/假”的标签,其中“真”意味着文章是超参数的。
标记为“超级艺术家”的文章示例如下:
As we prepare for oral arguments Friday before a federal appeals court in Washington, D.C. in our appeal of our lawsuit challenging ObamaCare, it\'s important to note that a growing number of Americans reject the pro-abortion, government-run, and costly health care law. In a new poll released by <a href="http://www.rasmussenreports.com/public_content/politics/current_events/healthcare/health_care_law">Rasmussen</a>, 56% of likely voters favor repeal of ObamaCare, while 52% say the health care law is bad for the country. A clear majority of voters have favored repeal of the law in every Rasmussen survey but one since the measure was passed by Congress in March of last year. As you may recall, our legal team is preparing for critical arguments before a three-judge panel of a federal appeals court in Washington on Friday. We\'re appealing a lower court decision dismissing our federal lawsuit which challenges the constitutionality of ObamaCare. We filed our lawsuit in federal
在文章被发送用于训练之前,我们对其进行一些基本的预处理。我已经用漂白剂库清理了文章中的 HTML 标签。我还随机抽取了 20K 个样本进行训练,5K 个样本进行验证。这是为了加快训练过程。
数据预处理中的一个关键步骤是确定文章的令牌长度。转换器将截断所有长于令牌长度的内容,并填充任何短于令牌长度的内容。使用 Longformer 模型的主要优点之一是,它可以使用多达 4096 个令牌的令牌长度进行训练。这里我们将令牌化到最大长度为 2048 个令牌。下面的代码片段进行了标记化。
encodings = tokenizer.encode_plus(text_, pad_to_max_length=True, max_length=2048,add_special_tokens=True,return_token_type_ids=False,return_attention_mask=True,padding='max_length', truncation=True)
典型的转换器模型可以接收 512 或 1024 个令牌,这可能不足以解决许多问题。Longformer 的主要优势之一是能够处理更长的序列。
龙前模特培训
long former—long document transformer 是艾伦人工智能研究所 2020 年发布的模型。基于转换器的模型不能处理长序列,因为它们使用的注意力机制是二次缩放的。因此,大多数 transformer 模型只能处理 512 或 1024 个令牌。Longformer 提出了一种与序列长度成线性比例的注意机制。这是通过使用局部窗口注意和特定任务的全局注意来实现的。Longformer 模型在长文档任务上优于 BERT/RoBERTa。
下图显示了不同的注意机制。在图 a 中,常规变压器使用完全二次注意,而 Longformer 使用基于窗口的局部注意+选择的全局注意,如在图 d 中所示。
来源:龙前论文
为了训练这个模型,我们使用了拥抱脸变形金刚 repo 。Longformer 模型初始化如下所示:
self.model = LongformerForSequenceClassification.from_pretrained("allenai/longformer-base-4096", return_dict=True, num_labels=2)self.tokenizer = LongformerTokenizer.from_pretrained('allenai/longformer-base-4096')
我创建了一个基于 PyTorch Lightning 的 LongformerFineTuner 类来执行训练和验证。该模型在 20K 篇新闻文章的训练集上被训练 2 个时期。定期执行验证,并输出准确度分数。
请在我的 colab 笔记本或 Github 这里找到完整代码。
我用 Colab Pro 训练过这个模型。整个培训大约花了 7 个小时。
模型评估
在验证集上评估训练的模型。模型的总体准确率为 93.4%。
该模型的精确度、召回率和 F1 值为:
precision recall f1-score support
Not HyperPartisan 0.95 0.92 0.93 7572
Hyper Partisan 0.92 0.95 0.93 7428accuracy 0.93 15000
macro avg 0.93 0.93 0.93 15000
weighted avg 0.93 0.93 0.93 15000
该模型正确地识别出下面的天气相关文章不是超参数的。
Input Text: <s>July 31 (UPI) — A tropical depression off the Gulf Coast of Florida was upgraded to a tropical storm on Monday, the National Hurricane Center said. The storm was designated Tropical Storm Emily on Monday morning — the fifth named storm of the 2017 Atlantic hurricane season. Emily is moving eastward with strong winds at about 8 mph, and is expected to bring very heavy rain to south and central Florida in the coming days. Monday, officials said 60 mph winds forced the closure of the Sunshine Skyway Bridge in St. Petersburg and caused some infrastructure damage. No serious injuries have yet been reported. A <a href="[http://www.sun-](http://www.sun-/) sentinel.com/news/weather/fl-reg-tropics-monday-20170731-story.html">tropical storm warning</a> was issued early Monday for the west coast of Florida, from Anclote River southward to Bonita Beach. The tropical storm made landfall at about 10:45 a.m., on Anna Maria Island, near Bradenton. Emily is expected to turn northeast as it passes over the state, indicating central Florida will receive much of the expected rain. The storm is expected to move offshore to the Atlantic Ocean by early Tuesday. Rain accumulations of two to four inches are predicted for the state’s west coast, the <a href="[http://www.nhc.noaa.gov/text/refresh/MIATCPAT1+shtml/311139.shtml](http://www.nhc.noaa.gov/text/refresh/MIATCPAT1+shtml/311139.shtml)">National Hurricane Center</a> said, with isolated amounts of up to eight inches possible
下面的这篇文章被正确地识别为一篇超级名人新闻。实际 1300+字的文章被 Longformer 不加删节的摄取!
'A combative President Trump launched an urgent, last-ditch bid Wednesday to revive an Obamacare repeal effort that had been left for dead just 24 hours earlier, imploring Republicans to stay in Washington until the job is done and warning that failure would decimate the party and its agenda.I'm ready to act, Mr. Trump said at the White House. For seven years you've promised the American people that you would repeal Obamacare. People are hurting. Inaction is not an option. The urgent public plea marked a confrontational shift in tone for Mr. Trump, who had been lobbying senators mainly behind the scenes, and a renewed commitment to the effort. One day earlier,Mr. Trump said Republicans should force Democrats to own Obamacare by letting it collapse under its unsustainable weight.SEE ALSO: Trump hosting GOP senators at White House on Obamacare repeal Mr. Trump got personal at times, leaning into Sen. Dean Heller, a Nevada Republican who faces a tough re-election battle next year and is wary of backing the repeal-and-replace effort....
我喜欢将自然语言处理应用于政治/新闻文章。我写过其他关于这个话题的有趣的博客。请查看这篇关于使用 GPT2 的语言生成能力生成唐纳德·川普风格的演讲的文章和这篇关于使用 T5 变压器检测假新闻的文章。
结论
这篇博客提出了一个解决超级名人新闻这一紧迫问题的方案。如果可以在社交媒体/博客上识别和标记极左/极右文章,那么它们可能有助于缩小两个政党之间日益扩大的差距。此外,本博客使用 Longformer 进行检测。我个人认为 Longformer 或处理更长序列的类似模型更实用,并将成为未来的趋势。我们能够处理 2048 个代币,并且仍然在合理的时间内训练。Longformer 可以扩展到其他任务,包括长文本问答或长文本摘要。如果你需要帮助,请直接联系我。
我希望您尝试一下代码,并训练自己的模型。请在下面的评论中分享你的经历。
在深度学习分析,我们非常热衷于使用机器学习来解决现实世界的问题。我们已经帮助许多企业部署了创新的基于人工智能的解决方案。如果您看到合作的机会,请通过我们的网站这里联系我们。
参考
- 龙前
- 拥抱脸变形金刚
- 政治上的两极分化
在一行 Python 代码中训练所有分类或回归模型
原文:https://towardsdatascience.com/train-all-classification-or-regression-models-in-one-line-of-python-code-4ccdcaf01f0c?source=collection_archive---------5-----------------------
使用 lazypredict 进行自动化模型训练
图片由穆罕默德·哈桑来自 Pixabay
自动化机器学习(Auto-ML)是指自动化数据科学模型开发管道的组件。AutoML 减少了数据科学家的工作量,加快了工作流程。AutoML 可用于自动化各种管道组件,包括数据理解、EDA、数据处理、模型训练、超参数调整等。
对于端到端的机器学习项目,每个流水线组件的复杂度取决于项目。有各种各样的 AutoML 开源库可以加速每个管道组件。阅读这篇文章了解 8 个这样的 AutoML 库,实现机器学习流水线的自动化。
在本文中,我们将讨论如何使用开源 Python 库 LazyPredict 来自动化模型训练过程。
什么是 LazyPredict?
LazyPredict 是一个开源的 Python 库,它自动化了模型训练管道,加快了工作流的速度。LazyPredict 为分类数据集训练大约 30 个分类模型,为回归数据集训练大约 40 个回归模型。
LazyPredict 返回经过训练的模型及其性能指标,而无需编写太多代码。人们可以比较每个模型的性能指标,并调整最佳模型以进一步提高性能。
安装:
LazyPredict 可以使用以下代码从 PyPl 库安装:
**pip install lazypredict**
安装后,可以导入库来执行分类和回归模型的自动训练。
**from lazypredict.Supervised import LazyRegressor, LazyClassifier**
用法:
LazyPredict 支持分类和回归问题,因此我将讨论这两项任务的演示
Boston Housing(回归)和 Titanic(分类)数据集用于 LazyPredict 库的演示。
分类任务:
LazyPredict 的用法非常直观,类似于 scikit-learn。首先,为分类任务创建一个估计器**LazyClassifier**
的实例。用户可以通过自定义指标进行评估,默认情况下,将对每个模型的准确性、ROC AUC 得分、F1 得分进行评估。
在进行 lazypredict 模型训练之前,必须读取数据集并对其进行处理,以使其适合训练。
(作者代码),Titanic 数据集处理
在特征工程和将数据分割成训练测试数据之后,我们可以使用 LazyPredict 继续进行模型训练。
# LazyClassifier Instance and fiting data **cls= LazyClassifier(ignore_warnings=False, custom_metric=None)
models, predictions = cls.fit(X_train, X_test, y_train, y_test)**
(图片由作者提供),泰坦尼克号数据集的 27 个分类模型的性能指标
回归任务:
与分类模型训练类似,LazyPredict 附带了针对回归数据集的自动化模型训练。实现类似于分类任务,只是实例**LazyRegressor**
有所变化。
(作者代码),波士顿住房数据集处理
**reg = LazyRegressor(ignore_warnings=False, custom_metric=None)
models, predictions = reg.fit(X_train, X_test, y_train, y_test)**
(图片由作者提供),波士顿住房数据集的 42 个回归模型的性能指标
观察上述性能指标,AdaBoost 分类器是分类任务的最佳性能模型,而 GradientBoostingRegressor 模型是回归任务的最佳性能模型。
结论:
在本文中,我们讨论了 LazyPredict 库的实现,它可以用几行 Python 代码训练大约 70 个分类和回归模型。这是一个非常方便的工具,因为它提供了模型性能的总体情况,并且可以比较每个模型的性能。
每个模型都使用其默认参数进行训练,因为它不执行超参数调整。在选择了性能最佳的模型之后,开发人员可以调整模型以进一步提高性能。
阅读下面提到的文章中的可以知道 8 个类似于 LazyPredict 的 AutoML 库。
https://medium.com/swlh/8-automl-libraries-to-automate-machine-learning-pipeline-3da0af08f636
参考资料:
[1] LazyPredict 文档:https://pypi.org/project/lazypredict/
感谢您的阅读
2021 年使用 Tensorflow 2 对象检测 API 训练一个手部检测器
原文:https://towardsdatascience.com/train-an-object-detector-using-tensorflow-2-object-detection-api-in-2021-a4fed450d1b9?source=collection_archive---------6-----------------------
作者图片
我们使用 Google Colab 在以自我为中心的手部图像数据集上训练我们的自定义对象检测器
我想开发一个计算机视觉应用程序,可以实时检测我的手。网上有很多文章都使用了 Tensorflow 对象检测 API 和 Google Colab,但我仍然努力让它真正工作起来。原因?库和代码的版本改变了!
这里有一个在虚拟特雷门琴中使用这个检测器的例子:
作者提供的视频
这篇文章应该会指导你现在(2021 年 3 月)什么是有效的。我假设你知道基本的 Python 技巧,并且有足够的知识从其他教程中查找你不知道的东西!😂
我们将使用的东西:
- Google Colab
- Tensorflow 对象检测 API 2
- Egohands 数据集:http://vision.soic.indiana.edu/projects/egohands/
步骤: 1 .设置环境
2。下载并安装 Tensorflow 2 物体检测 API
3。下载数据集,生成 tf_records
4。下载模型并编辑配置
5。训练模型并导出为 savedmodel 格式
鸣谢: 非常感谢 github 用户 molyswu 、 datitran 和 gilberttanner ,我从他们那里获取了一些代码并对其进行了轻微的修改。也请查看他们的教程。
1.设置环境
打开一个新的 Google Colab 笔记本,然后安装你的 Google drive 。你不需要这样做,但是如果你从你的会话中断开,或者只是想再次回到会话中,这是非常方便的。
from google.colab import drive
drive.mount('/content/drive')%cd /content/drive/MyDrive
我们现在在你的谷歌硬盘里。(您可能需要更改最后的%cd,以防您的驱动器装载到稍微不同的路径)。
Google Colab 将使用 Tensorflow 2,但为了以防万一,请明确地这样做:
%tensorflow_version 2.x
2.下载并安装 Tensorflow 2 对象检测 API
第一件事是下载并安装 Tensorflow 2 对象检测 API 最简单的方法是首先进入你的根目录,然后从 git 克隆:
%cd /content/drive/MyDrive
!git clone [https://github.com/tensorflow/models.gi](https://github.com/tensorflow/models.git)t
然后,编译原型——顺便说一下,没有输出。
( 协议应该可以正常工作,因为 Google Colab 已经安装了它):
%cd /content/drive/MyDrive/models/research
!protoc object_detection/protos/*.proto --python_out=.
现在安装实际的 API:
!cp object_detection/packages/tf2/setup.py .
!python -m pip install .
测试您的 tensorflow 对象检测 API 2 安装!一切都要*“OK”。*(有些测试自动跳过也没关系)。
#TEST IF YOU WANT
!python object_detection/builders/model_builder_tf2_test.py
作者图片
3.下载数据集,生成注释。csv 文件和张量流 tf_records
我将在这里描述你需要做什么,因为这部分和其他教程相比并没有太大的变化。总之,我们将下载 Egohands 数据集,但只使用其中许多图像的子集,因为我们正在进行迁移学习。
我们将它们拆分成一个训练目录和一个测试目录,并生成。每个图像的 xml 文件(包含每个图像的边界框注释)。
我已经创建了一个通用脚本:
- 下载整个 Egohands 数据集并提取它
- 仅保留少量(4 个)文件夹
- 将图像分割成训练集和测试集
- 创建注释。带边界框坐标的 csv 文件
首先我们需要确保你在你的根目录下,然后克隆我的 git repo。
%cd /content/drive/MyDrive
!git clone [https://github.com/aalpatya/detect_hands.git](https://github.com/aalpatya/detect_hands.git)
从我下载的 repo 中,将ego hands _ dataset _ to _ CSV . py文件复制到您的根目录并运行它。这将为您完成所有工作——默认情况下,它只会从实际的 Egohands 数据集中随机取出 4 个文件夹(即 400 张图像),将它们分成一个训练和测试集,然后生成。csv 文件。
!cp detect_hands/egohands_dataset_to_csv.py .
!python egohands_dataset_to_csv.py
向 https://github.com/molyswu/hand_detection 大声喊出来,我从他那里得到了最初的剧本。我刚刚整理了一下,做了一些调整。😁
生成 tf _ records
刚刚创建的 test_labels.csv 和 train_labels.csv 文件包含每个图像的边界框位置,但令人惊讶的是,Tensorflow 需要不同格式的信息,即 tf_record 。
我们将通过使用来自我的 git repo 的 generate_tfrecord.py 来创建所需的文件 train.record 和 test.record (这是我在 https://github.com/datitran/raccoon_dataset 的的精彩 datitran 教程中修改的)。
%cd /content/drive/MyDrive
!cp detect_hands/generate_tfrecord.py .# For the train dataset
!python generate_tfrecord.py --csv_input=images/train/train_labels.csv --output_path=train.record# For the test dataset
!python generate_tfrecord.py --csv_input=images/test/test_labels.csv --output_path=test.record
现在,您应该有一个如下所示的目录:
/content/drive/MyDrive (or whatever your root is called)
|__ egohands
|__ detect_hands
|__ images
|__ train
|__ <lots of images>
|__ train.csv
|__ test
|__ <lots of images>
|__ test.csv
|__ train.record
|__ test.record
4.下载迁移学习模型
下载您选择的 Tensorflow 2 模型
从https://github . com/tensor flow/models/blob/master/research/object _ detection/g3doc/tf2 _ detection _ zoo . MD
这里我用的是SSD Mobilenet V2 fpnlite 320 x320。我发现一些模型不能与 tensorflow 2 一起工作,所以如果你想确定的话,请使用这个模型。
%cd /content/drive/MyDrive!wget [http://download.tensorflow.org/models/object_detection/tf2/20200711/ssd_mobilenet_v2_fpnlite_320x320_coco17_tpu-8.tar.gz](http://download.tensorflow.org/models/object_detection/tf2/20200711/ssd_mobilenet_v2_fpnlite_320x320_coco17_tpu-8.tar.gz)# Unzip
!tar -xzvf ssd_mobilenet_v2_fpnlite_320x320_coco17_tpu-8.tar.gz
编辑训练参数
首先,创建一个名为 label_map.pbtxt 的文件,其中包含您的 hand 类。它应该是这样的:
item {
id: 1
name: 'hand'
}
或者,您可以记下已经在我的 git repo 中的路径,您应该已经有了:/content/drive/my drive/detect _ hands/model _ data/SSD _ mobilenet _ v2 _ fpn _ 320/label _ map . Pb txt
接下来我们将编辑下载的 tensorflow 模型附带的 pipeline.config 。它将位于您从 tensorflow 模型动物园下载的模型的模型目录中。例如:SSD _ mobilenet _ v2 _ fpnlite _ 320 x320 _ coco 17 _ TPU-8/pipeline . config
靠* pipeline.config 的开头:
- 将类别数更改为 1:
作者图片
朝向 pipeline.config 的中间/末端:
- 设置模型检查点的路径。我们只需要检查点名称的开头部分,直到数字。比如:“ckpt-0”,而不是“ckpt-0.index”。
- 将检查点类型设置为检测
- 您可能还想更改批量大小。一般来说,批量越小,模型损耗下降得越快,但是达到损耗值需要更长的时间。我选择批量大小为 4,因为我只是希望训练发生得更快,我并不是在这里寻找最先进的准确性。摆弄这个数字,看这篇文章。
作者图片
在 pipeline.config 的末尾:
- 将路径设置为 label_map.pbtxt (有两个地方可以这样做,一个用于测试,一个用于训练)
- 设置训练记录和测试记录文件的路径
作者图片
我们终于准备好开始训练了!
5.训练模型并将其导出为“savedmodel”格式
加载张量板
首先,我们将加载 tensorboard,这样一旦训练开始,我们就可以在漂亮的图表中可视化进度。
logdir 参数是您的训练过程将创建的日志目录的路径。在我们的例子中,这将被称为输出 _ 训练,日志自动存储在输出 _ 训练/训练中。
%load_ext tensorboard
%tensorboard --logdir=/content/drive/MyDrive/output_training/train
训练模型
现在开始训练,设置到我们的管道配置文件的正确路径,以及到 output_training 目录的路径(还没有创建)。
%cd /content/drive/MyDrive/models/research/object_detection/#train
!python model_main_tf2.py \
--pipeline_config_path=/content/drive/MyDrive/detect_hands/model_data/ssd_mobilenet_v2_fpn_320/pipeline.config \
--model_dir=/content/drive/MyDrive/output_training --alsologtostderr
这将开始训练的过程,你只要坐下来等待。要么你等很长时间,直到训练过程结束,或者只是在一段时间后取消这个过程(也许你在损失图上看到损失趋于*稳)。这样做是可以的,因为训练过程会不断保存模型检查点。
导出模型
现在,我们将把训练输出导出到一个 savedmodel 格式,这样我们就可以用它来进行推理。
%cd /content/drive/MyDrive/models/research/object_detection!python exporter_main_v2.py \
--trained_checkpoint_dir=/content/drive/MyDrive/output_training \
--pipeline_config_path=/content/drive/MyDrive/detect_hands/model_data/ssd_mobilenet_v2_fpn_320/pipeline.config \
--output_directory /content/drive/MyDrive/inference
整件事情的重要部分是推论文件夹。如果我们想进行推理,这是我们唯一需要的东西。
恭喜你!你训练了一个探手器!🎈🎉🎊
加载用于推理的模型
该模型可以加载 tensorflow 2 作为
detect_fn = tf.saved_model.load(PATH_TO_SAVED_MODEL)
从那里,您可以使用 detect_fn 函数并继续进行推理,但是我将把它留给另一个教程😉
使用多重处理将交叉验证时间优化三倍
原文:https://towardsdatascience.com/train-and-test-machine-learning-models-3x-faster-using-multithreading-d8cb0bf9eaf5?source=collection_archive---------29-----------------------
我实现了多重处理来优化我的机器学习代码
训练机器学习模型需要时间,一个很多的时间。使用支持向量机或朴素贝叶斯等传统机器学习算法的传统模型可能不需要那么长时间,但我们不会谈论这些算法。我们将讨论神经网络。
你看,在过去的几个月里,我和一个团队在做一个项目。我在做什么?我们正在开发一个实时运动评估系统,使用的是——你猜对了,人工神经网络。 LSTMs,确切的说是一些前馈神经网络。
我们的最终结果,图片由作者提供
我们想做的很简单:
- 首先,我们需要一个多姿态分类器,使用一个前馈神经网络根据我们运动的开始位置来分类运动的类型。
- 接下来,我们需要一个二元分类器来分类练习代表是否在起始位置。
- 在对开始位置进行分类后,我们需要评估练习的每个重复,确保计算找到了多少个正确的重复。
简单吧?这听起来很简单,但实际上,我们需要收集大量数据来训练我们的网络。此外,我们还需要培训不是一个,不是两个,而是九个模型。数学原理是这样的:我们想把运动分为四种类型。因此,我们需要八个模型,因为每个练习都有一个二元姿势分类器和一个练习姿势评估模型。我们还需要一个额外的模型作为多姿态分类器。
呀。
由于时间限制,我和我的团队担心我们不能及时完成这个项目。所以,最后,我们决定尝试一下多重处理。
等等,为什么是多重处理?
为什么我们脑海中的第一反应会是多重处理?让我解释一下,我们的项目是一个研究项目。我们需要找到神经网络的最佳架构。我们还需要找到符合我们需求的最佳超参数。我们使用了以前研究中的一些参考资料,但是很明显,我们没有完全照搬。之前的研究人员的神经网络架构并不完全符合我们的。
最后,我们不得不为多姿态分类器测试大约 24 个超参数组合,为每个二元姿态分类器测试 6 个组合,为每个运动姿态评估模型测试 54 个组合。如果我们想测试每个组合,我们必须让电脑开很长时间。但是如果我们可以同时训练一些组合呢?我们能把训练时间减少三倍吗?
答案是多重处理。
现在,像 Keras 和 Tensorflow 这样的机器学习框架确实在可用时使用多个 CPU 核心。但问题不在于我们的内核没有得到正确使用,而是我们如何从硬件中挖掘每一盎司的潜力来节省宝贵的时间。
你是如何实现多重处理的?
让我第一个说这个方法可能不是对每个人都有效,我将解释为什么。我们的模型即使有多种组合,也不需要太多的处理能力来训练。
你培养的是什么样的模特?
我们的二元姿态和多姿态分类器都使用前馈神经网络。我们使用名为 OpenPose 的预训练模型从图像中检索我们的数据点。
图像是从 rwcreations 中检索的。
然后,我们以数组的形式从每一帧中提取每个关键点的位置(我们使用了大约 14 个可用的关键点)。然后,我们将数据标准化,并将其传递给我们的前馈神经网络。你可以说我们的训练方法是— 直来直去。
由于训练这种规模的神经网络需要少量的计算能力,我们试图应用多处理作为我们的解决方案,使事情进行得更快。虽然我们没有像使用前馈神经网络那样在 LSTM 模型上广泛使用多重处理来进行运动姿势评估。
原因当然是 LSTMs 需要更多的计算能力来训练。想象我们提取的 14 个关键点,将它们乘以 24–48 帧,每个数据点成为一系列关键点。训练这种能力需要的不仅仅是多处理效率。
代码示例
为了实现多重处理,我们使用了 Python 中的多重处理模块。多重处理模块有一个非常干净的界面。实现多处理非常容易。
首先,安装模块。
pip3 install multiprocess
现在,假设我们要训练四种不同的模型类型,每种类型有六种超参数组合。
我们还有一个函数叫做train_model
。该函数包含四个参数:练习类型、隐藏层数、批量大小以及最终的训练数据。
所以,为了节省时间,我们想同时训练这六个组合。
代码实现
上面可以看到例子。看起来并不太复杂,读起来也很直白。
结果呢
当训练前馈神经网络时,我们的机器可以轻松处理六个过程。然而,LSTM 模型只能同时处理三个过程。当应用多重处理来训练机器学习模型时,另一个问题是 RAM。因为我们在六个不同的进程上加载数据集六次,所以我们把它全部保存在 RAM 中。我们来分解一下结果 。
设备规格
在展示结果之前,让我先描述一下我们的器件规格:
- CPU AMD 锐龙 5 2600 六核处理器
- 16 GB 内存
- GPU GeForce GTX 1070 TI
RAM 使用
在这个项目中,我和我的团队使用了一台内存大小适中的 PC,大约 16GB。我们以为这就够了,但是我们错了!你看,除了训练多个超参数来寻找最佳答案,我们还使用十倍交叉验证来测试我们的结果,以找到最佳结果。
即使在 Keras 中的每个 epoch 之后实现了手动垃圾收集,RAM 的使用也在稳步增加,除非我们停止所有进程。我们达到了内存使用的瓶颈。虽然,公*地说,单进程 RAM 的使用并没有远远落后于多进程 RAM 的使用,尽管多进程比单进程增加了 RAM 的使用。
训练开始时二元姿态单进程 RAM 的使用情况,图片由作者提供。
训练开始时二元姿态多重处理 RAM 的使用,图片由作者提供。
该图显示,训练开始时的 RAM 使用量彼此相差不大。前馈神经网络模型和 LSTM 模型的条件是相似的。
培训开始时 LSTM 模型单进程 RAM 的使用情况,图片由作者提供。
培训开始时 LSTM 模型多进程 RAM 的使用,图片由作者提供。
注意:最好知道二元姿态和多姿态模型的结果是相似的,因为两个模型使用相似的架构和相似的数据点
CPU 使用率
使用 AMD 锐龙 5,我们能够实现这一特技。我们的中央处理器没有任何问题。这可能是因为众所周知 AMD 处理器在多任务处理上表现更好。我相信 CPU 为我们的训练过程做出了很大贡献,特别是因为锐龙 5 有六个专用内核。
训练开始时的二元姿势单进程 CPU 使用率,图片由作者提供。
训练开始时的二元姿态多重处理 CPU 使用情况,图片由作者提供。
单进程保持相对较低的 CPU 使用率。超过一个 CPU 的使用率很少超过 40%。否则,多进程很少低于 60–70%的使用率,并且在每个进程停止后,每个 CPU 的使用率会慢慢下降到 9–15%左右。
培训开始时的 LSTM 模型单进程 CPU 使用情况,图片由作者提供。
培训开始时 LSTM 模型多处理 CPU 的使用情况,图片由作者提供。
LSTM 模型上的 CPU 使用率与二进制姿势 CPU 使用率的差别更大。正如我之前提到的,训练 LSTM 模型的任务消耗更多的计算能力。因此,它不能同时拥有三个以上的进程。
单进程 CPU 使用率表明了这两种型号的电源需求有多么不同。对于单个 CPU,二元姿态模型的 CPU 使用率很少超过 30%,更不用说多个 CPU 超过 40%。但是,单个进程的 CPU 使用率达到了 40%以上,而 CPU 的最低使用率为 35%。
令人惊讶的是,LSTM 模型的多处理器 CPU 使用率并没有超过二元姿态模型的使用率。当二元姿态模型有 6 个 CPU 时,LSTM 模型有 4 个 CPU,达到 70%的百分比。然而,可以得出结论,单个二元姿态模型比单个 LSTM 模型使用更少的 CPU,但是 6 个二元姿态模型比 3 个 LSTM 模型使用更多的 CPU 能力。
注意:同样,二元姿态和多姿态模型的结果是相似的,因为两个模型使用相似的架构和相似的数据点。
每个过程所需的总时间
这里最重要的指标是时间。因为这就是我们进行这个实验的全部原因。下面我有两个时间表,描述了单过程和多过程的训练结果。
每个表格有 6 种不同的组合,不同之处在于隐藏层和批量大小。多进程实验一次运行所有的组合,而单进程实验分别运行每个组合。
单进程前馈神经网络训练时间表。
这两个表之间的结果可以得出一个结论。多重处理并没有降低训练速度。每个组合的两个结果之间的差异不会太大。此外,如果我们将在单个过程中单独训练每个模型所需的时间加起来,我们大约需要 1212 秒。而在多重处理的例子中,我们最多只需要 372 秒。
多重处理前馈神经网络训练时间表。
使用多重处理,我们节省了 840 秒的训练时间。我们将训练速度提高了 3.25 倍
名单上的下一个。我们试图在更复杂的模型中实现这种技术。一个 LSTM。因为这两种型号所需的计算能力差别很大。我最终在三个过程中同时运行了 LSTM 模型。
每个表格有三种不同的组合,不同之处在于隐藏的图层。明确地说,每个 LSTM 模型有四层,每层有不同数量的隐藏层。多进程实验一次运行所有的组合,而单进程实验分别运行每个组合。
单流程 LSTM 培训时间表。
这两个表之间的结果可以看作是相似的。每种组合差别不大。奇特的结果是,单进程结果随着每一个隐藏层的增加而变得更快,而多进程结果则相反。
最终,多重处理训练时间最多只需要大约 6755 秒。而单个过程的训练时间加起来约为 15330 秒。
多重处理 LSTM 训练时间表。
在这种情况下,多重处理节省了 8575 秒的训练时间。因此训练时间加快了 2.26 倍
现在,这些结果似乎很有希望。请注意,与企业产品可能需要的模型相比,这里使用的模型仍然相对简单。使用的数据也有数千个,而企业人工智能通常有数百万个。
结论
最终,多处理解决方案将我们的训练时间在 LSTM 模型上提高了 2.26 倍,在前馈神经网络上提高了 3.25 倍。研究用途的潜力是无限的。计算机一年比一年强大。使用这种技术,超参数测试将轻而易举。
多重处理为我的团队节省了大量时间。我无法想象如果不实施的话,我们要等多久。尽管我不得不说多重处理并不是一颗银弹。它不能在任何情况下都提高每个模型的速度。我们很幸运,我们的情况完全符合条件。
特别感谢Kevin Janada和ferdinandz jap hne给予我使用我们项目数据的许可。
编辑说明:将文章从关于多线程更改为多处理。我把这两件事搞混了。抱歉给您带来不便。感谢, 米绍克拉斯捷夫 指出来。
用你自己的语言训练 BERT-Large
原文:https://towardsdatascience.com/train-bert-large-in-your-own-language-7685ee26b05b?source=collection_archive---------27-----------------------
此时训练自己的 BERT 模型最有效的解决方案
BERT-Large 是*年来自然语言处理领域真正的“游戏规则改变者”技术。通过迁移学习扩展基本模型,我们可以为问答、命名实体识别或文本摘要等任务提供最先进的解决方案。该模型目前存在于大约 10 种语言中,在本文中,我们将分享我们的培训经验,以便可以用您自己的语言相对容易和有效地培训新模型。
在培训方面,微软的 ONNX 运行时库和 DeepSpeed 优化提供了最快的(也是最便宜的!)训练模型的解决方案,所以我们在 Azure Machine Learning platform 的实验中使用了它(不过,您可以随意查看上面的 ONNX 运行时链接,了解本地/不同环境的运行情况)。请注意,在 4x Tesla V100 节点上,培训大约需要 200 小时才能完成。
该指南涵盖了培训流程,包括两个主要部分:
- 数据准备
- 培养
数据准备
原始的 BERT-Large 使用了 34 亿个单词的文本语料库,因此值得用这样大小的数据集进行训练。一个显而易见的解决方案可能是使用维基百科语料库,可以从这里下载目标语言。单独的 wikicorpus 很可能不会包含足够的数据,但它绝对值得添加到现有的语料库中,因为它是一个高质量的语料库,它提高了训练和使用的效率。数据预处理可能是计算密集型操作,根据训练文件的大小,可能需要大量 RAM。为此,我们在 AzureML 中使用了标准的 D14 V2(16 个内核,112 GB 内存,800 GB 磁盘)虚拟机。
OnnxRuntime 使用 NVIDIA 的 BERT-Large 解决方案。如果有必要,原始数据集首先需要清理,并且所需的格式必须满足两个标准:
- 每个句子都在单独的一行。
- 相关条目(文章、段落)由空行分隔。
对于 wiki 数据集,我创建了一个来自 NVIDIA BERT 数据准备脚本的定制解决方案,并上传到我自己的存储库。让我们来看看这个过程:
正在下载 WikiDump:
维基百科转储可在此链接获得。您甚至可以使用 wget 下载转储文件。下载的文件是. bz2 格式,可以在基于 Linux 的机器上用 bunzip2(或 bzip2 -d)命令提取。
提取的文件在。xml 格式。 WikiExtractor Python 包从输入的 wiki 文件中提取文章,为转储清理提供有用且必要的帮助。
当我们完成这些后,脚本创建了一个包含提取文本的文件夹结构。在这种情况下,我们需要采取以下步骤将数据集变成与训练脚本兼容的形式:
- 格式化
- 符号化
- 过滤
- 创建 vocab
- 分片
- 创建二进制文件
格式化(仅维基**)**
对于格式化,让我们使用以下脚本:
python3 formatting.py --input_folder=INPUT_FOLDER --output_file=OUTPUT_FILE
它将提取的文本分类到一个文件中,每行一篇文章。
符号化
此后,我们需要将我们的文章标记为每行一句(spl)格式,因为我们的训练脚本和进一步的操作(如过滤和分片)需要它。这是一个相当容易的工作,然而标记化的质量是绝对重要的,所以如果你不知道一个适合你的语言的好的句子标记器,现在是时候做一些研究工作了。在我们的标记化脚本中,我们将给出几个示例并实现几个方法:
- NLTK 是一个非常常见的库,它使用一个名为 punkt 的包来进行标记化。在此检查支持的语言。
- UDPipe (v1) 有很多支持语句标记化的语言。在这里检查它们。
- StanfordNLP 在这种情况下也是一个公共库。在此检查预训练(语言)模型。注意,这个库也有一个 spacy 包装器,如果你觉得这样更舒服的话。
- Spacy (最后但并非最不重要)是一个非常简单而强大的 NLP 库。可用的语言可以在这里找到。
请注意,在这一点上,我强烈建议对您的语言中可用的句子分词器做一些研究,因为这可能关系到您的模型性能。因此,如果您的文本不是 spl 格式,请测试一个正确的标记器,并在您的文本上使用它。确保文本的每一段都用空行隔开。
过滤
因为我们是芬兰 TurkuNLP 团队的忠实粉丝(他们已经用多种语言完成了 wikiBERT-base 模型),我们想分享一个来自他们管道的定制过滤方法。这种过滤方法具有基于 TurkuNLP 团队经验的默认参数值,但是可以根据您的数据集随意调整这些值(如果您愿意)。要运行(使用默认工作目录):
python filtering.py INPUT_SPL_FILE \
--word-chars abcdefghijklmnopqrstuvwxyz (replace with your alphabet) \
--language en (replace with your lang) \
--langdetect en (replace with your lang) \
> OUTPUT_FILE
在这一点上,确保你的文本是干净的,它没有不必要的或太多的重复行(更可能是在抓取的数据中),并且每一段都有它的意思,文本是连续的。对于预制字母,请参考 TurkuNLP 管道报告。
清理文本的另一种方法是转换成较小的字符集,如 Latin1(然后转换回 UTF-8),以删除不必要的符号。
创建词汇库
为了创建 vocab 文件,我们派生了 TurkuNLP group 的解决方案(它源自 Google)。
现在,您可以在整个数据集上运行词汇训练方法(注意,根据我们的设置,它将从大型语料库文件中随机抽取行)。根据您的经验和语言,随意增加您的 vocab 大小,但请注意,较大的 vocab 大小将需要更多的 VRAM,这意味着您必须使用较低的微批处理大小来训练您的模型,这可能会降低您的模型在 16GB 大小的 GPU 上的有效性。在 32 GB 的 GPU 上真的不算太多。
python3 spmtrain.py INPUT_FILE \
--model_prefix=bert \
--vocab_size=32000 \
--input_sentence_size=100000000 \
--shuffle_input_sentence=true \
--character_coverage=0.9999 \
--model_type=bpe
因此,在此之后,我们需要将我们的句子片段 vocab 转换为 BERT 兼容的单词片段 vocab,发出以下脚本:
python3 sent2wordpiece.py bert.vocab > vocab.txt
Tadaa!您已经基于您的文本语料库创建了一个 BERT 兼容的 vocab。
分片:
建议使用分片,因为在 512 seq len 二进制文件创建时,一个 500 兆字节的原始文本文件可能会占用高达 50GB 的 RAM,所以建议创建大小在 50-100 兆字节之间的分片。
python3 sharding.py \
--input_file=INPUT_FILE \
--num_shards=NUMBER_OF_SHARDS_TO_MAKE
创建二进制文件
对于二进制文件(. hdf5)的创建,我们需要一个与 BERT 兼容的词汇表文件。如果你有,那很好,如果你没有,那么请查看下面的文章来创建你自己的 vocab 文件。您可以并行处理这些文件,但是对于一个 100 兆字节的文件,它可能会占用高达 10GB 的 RAM。你可以在 128 seq len run 中尝试更多的碎片,因为它占用的内存更少。
要创建. hdf5 文件,请运行:
python3 create_hdf5_files.py --max_seq_length 128 --max_predictions_per_seq 20 --vocab_file=vocab.txt --n_processes=NUMBER_OF_PROCESSES
对于 128 序列长度训练,以及
python3 create_hdf5_files.py --max_seq_length 512 --max_predictions_per_seq 80 --vocab_file=vocab.txt --n_processes=NUMBER_OF_PROCESSES
用于 512 序列长度预处理。这两者都是训练过程所需要的,这将在后面解释。
完成. hdf5 创建后,您应该有两个文件夹,命名如下:
hdf5_lower_case_0_seq_len_128_max_pred_20_masked_lm_prob_0.15_random_seed_12345_dupe_factor_5/
和
hdf5_lower_case_0_seq_len_512_max_pred_80_masked_lm_prob_0.15_random_seed_12345_dupe_factor_5
移动到 BLOB
为了将转换后的文件用于训练,您需要将它们上传到 BLOB 容器中。我们推荐使用 Azure Storage Explorer 和 AzCopy 命令行工具。
在 Azure Storage Explorer 中,您可以轻松地创建 BLOB 容器(使用上面的指南),并且使用 AzCopy,您可以将转换后的文件复制到 BLOB 容器,格式如下:
azcopy.exe cp --recursive "src" "dest"
注意:您可以在您的 Azure 存储帐户下创建一个 BLOB(在资源管理器中的左侧),并且您可以使用“获取共享访问签名”选项导航到并右键单击您的. hdf5 文件夹来获取源代码。对于作为目标的 BLOB 容器也是如此。
培养
训练过程有两个部分:序列长度为 128 和 512 的阶段。这大大加快了训练,因为它首先需要大约。128 上的 7,000 步和 512 上的 1,500 步,这使得训练速度大大加快。这是基于这样一个事实,即 128 序列长度的训练要快得多,但是我们希望我们的模型能够处理 512 标记长度的文本。
对于训练,我们使用基于 ONNX 运行时的解决方案,它现在包含了 DeepSpeed 训练优化。这提供了目前最快,当然也是最便宜的解决方案(SOTA)。存储库在这里可用。ONNX 运行时团队还准备了一个 docker 映像用于使用必要的组件进行培训,如 openMPI、CUDA、cuDNN、NCCL 和所需的 Python 包。
如前所述,我们在 AzureML 中运行培训,因此指南也遵循这种方法。如果所需的资源(GPU)可用,这并不一定需要在 AzureML 中运行。上面的微软知识库也包括本地执行的方法。
让我们更深入地了解火车
首先,我们需要创建一个 compute 实例来从 GitHub 存储库中获取代码。这个实例(虚拟机)不一定是昂贵的,例如,我们使用标准 _D1_V2 (1 个内核,3.5 GB 内存,50 GB 磁盘)。要创建计算实例,请打开笔记本选项卡上的任何文件,然后单击+按钮:
现在打开一个终端,您可以在同一个选项卡上完成。
在 VM 的终端中,您需要使用以下命令(根据上面的 ONNX 运行时训练示例库)来获取训练代码。
要获得 ONNX 运行时代码,对于增强 BERT 训练:
git clone https://github.com/microsoft/onnxruntime-training-examples.git
cd onnxruntime-training-examples
要获得 NVIDIA 的 BERT 大型训练解决方案:
git clone --no-checkout https://github.com/NVIDIA/DeepLearningExamples.git
cd DeepLearningExamples/
git checkout 4733603577080dbd1bdcd51864f31e45d5196704
cd ..
让他们聚在一起:
mkdir -p workspace
mv DeepLearningExamples/PyTorch/LanguageModeling/BERT/ workspace
rm -rf DeepLearningExamples
cp -r ./nvidia-bert/ort_addon/* workspace/BERT
准备
在开始培训之前,您需要执行几个步骤:
- 将你的 vocab.txt 文件复制到 workspace/BERT/vocab 目录下
- 修改NVIDIA _ Bert/ort _ addon/ort _ supplement/ort _ supplement . py行中的 vocab 大小:55
- 下载并将 bert_config.json 复制到 workspace/BERT
- 修改workspace/BERT/BERT _ config . JSON中的 vocab 大小
现在,您可以访问*NVIDIA-Bert/azure ml-notebooks/*中的培训笔记本。打开它。
AzureML 工作区设置
首先你需要解决你的
- 工作区名称
- 订阅 ID
- 资源组
在笔记本里。
注册数据存储
接下来,必须授予访问 BLOB 容器的笔记本的权限,我们之前在那里上传了转换后的数据集。它包括
- 数据存储名称
- 帐户名
- 账号键
- 容器名称
参数。
创建 AzureML 计算群集
在下一步中,我们需要为培训创建一个计算目标。在培训过程中,我们使用了包含 4 个 Tesla V100 16GB GPU 的 Standard_NC24rs_v3 。此设置大约需要。200-220 小时的训练。
你想使用哪个虚拟机,这完全取决于你。你主要可以选择
- 标准 _ NC24rs _ v3(4 个特斯拉 V100 16GB)
- standard _ nd 40 RS _ v2(8x Tesla V100 32GB)
虚拟机的。
创建评估者
也许这是你训练中最激动人心的一步。在这里,您需要配置培训脚本,笔记本将启动该脚本作为 AzureML 实验。注意,我们将针对 128 和 512 次列车运行两次实验(和脚本)。
您需要设置以下基本参数:
- 每个节点的进程计数(2x)
- 节点计数
- 输入目录
- 输出目录
- 训练 _ 批量 _ 大小
- 梯度 _ 累积 _ 步数
- gpu _ 内存 _ 限制
process_count_per_node: 每个虚拟机的 GPU 数量(4/8)。
node_count: 您使用的虚拟机总数。
*输入 _ 方向:*斑点内 128 个预训练数据的位置。
output_dir: 检查点的任意目录。注意:512 次列车将使用此目录加载最后一个阶段 1 检查点。
*训练批次大小:*训练批次大小。根据笔记本中的上表进行设置。
*gradient _ accumulation _ steps:*根据笔记本上表设置这个。微批量将通过训练批量和该参数进行计算。
gpu_memory_limit: 根据您使用 16 或 32GB GPU 的情况设置此值。
最后,别忘了补充一点
'--deepspeed_zero_stage': ''
使用 DeepSpeed ZeRO 优化器加速训练的参数。
注意:在使用此参数进行预训练期间,您可能还希望禁用进度条:
'--disable_progress_bar': ''
注意,微量批次应通过批次大小和梯度累积步骤最大化。
提交。
因此,当您开始将 pretraining 作为 AzureML 实验时,您应该会在您的实验选项卡中找到类似这样的内容:
转换检查点
我还在我的 repo 中包含了一个名为 convert_checkpoint.py 的小脚本,以使您的检查点兼容 transformers 库的微调。
经过 128 次列车
在您的集群完成第 1 阶段后,您可以使用与上面相同的方法设置第 2 阶段脚本。使用相同的输出目录很重要,这样第二阶段运行将在该目录中找到第一阶段的检查点。
跑步将始终保持最后 3 个检查点,您可以设置检查点的训练步数。我们推荐大约 100 个步骤,因此您可以下载大约 100 个步骤的检查点,并使用微调脚本对它们进行基准测试。
512 次列车后
恭喜你,你有了一个用你自己的语言编写的 BERT-Large 模型!请在这里分享您的经验或通过电子邮件联系我,因为我们渴望听到您在匈牙利佩奇大学应用数据科学和人工智能小组的经历。
使用 Detectron2 分 4 步在自定义数据集上训练 MaskRCNN
原文:https://towardsdatascience.com/train-maskrcnn-on-custom-dataset-with-detectron2-in-4-steps-5887a6aa135d?source=collection_archive---------1-----------------------
对自定义数据集应用对象检测的最简单方法
照片作者
0 detector 2是 AI 脸书研究团队最新发布的用于物体检测的 Python 库。与火炬视觉相比,它的主要优势是你可以更快地训练。此外,我相信它更容易使用,因为他们已经提供了一个默认的训练器,其中包含了许多可配置的对象检测模型,如 FasterRCNN,MaskRCNN,Retinatet 等。在本教程中,我解释了使用 Detectron2 在自定义数据集上逐步训练 MaskRCNN,因此您可以在一分钟内看到它有多简单。
第一步:准备好注释
注释必须是下面的 COCO 格式,和这里介绍的 COCO 格式有点不同。对于每个图像,包括关于图像路径、宽度、高度、id 和注释的信息。
**注意:**如果已经有了 COCO 格式的数据集,可以跳过这一步,进入下一步。唯一的区别是,你应该用register_coco_instances()
而不是register()
来注册你的数据。
请记住,filename
应该是一个图像路径,并且image_id
在数据集的图像中必须是唯一的。segmentation
是一个有n
个点的多边形,(x_i, y_i)
。对于边界框,你有多种选择[x_0, y_1, x_1, y_1]
、[x_0, y_0, width, height]
或这里呈现的的任何其他表示。然而,bbox_mode
应该与bbox
表示一致。
例如,我将bbox_mode
设置为XYWH_ABS
,即[x_0, y_0, width, height]
。
Detectron2 数据集的模板
第二步:加载数据
假设您的数据集已经是上面的格式,并且在本地保存为.json
。为了加载数据,我们应该在 Detectron2 数据集目录中注册数据集,为此我们需要一个数据加载器函数:
加载数据集
第三步:定制配置
Detectron2 提供了一个默认配置,包括许多超参数。要定制默认配置,首先导入get_cfg
,这将返回一个超参数字典。
我们可以从detectron2.model_zoo
得到配置文件。此外,我们也可以通过从model_zoo
加载重量来使用预训练模型。此外,我们可以设置其他配置,就像我在下面对我的 desire 模型所做的那样。
- 默认情况下,遮罩是关闭的。要训练一个 MaskRCNN,打开它:
MODEL.MASK_ON = True
- 骨干网络默认为
build_resnet_backbone
,但预训练模型使用 ResnetFPN。我更喜欢保持默认,用resnet34
代替resnet101
,降低模型的复杂度;MODEL.BACKBONE.NAME = "build_resnet_backbone"
和cfg.MODEL.RESNETS.DEPTH = 34
。 - 我通过设置
cfg.INPUT.MIN_SIZE_TRAIN = (800,)
均等地缩小所有图像的尺寸 - 因为我知道每幅图像中只有很少的物体,所以我减少了区域提议网络中的预处理和后处理 NMS。
- 您还可以根据您的 GPU 设备
cfg.SOLVER.IMS_PER_BATCH = 4
设置每批图像的数量。 - 在本地设置数据集和输出目录。
自定义配置
最后一步:训练
现在,训练很简单。只需几行代码就可以完成。创建标签列表的是thing_classes
。在这里,我创建了三个标签:人、狗和猫。
使用检测器 2 训练 MaskRCNN
预测和可视化
可视化对于呈现对象检测结果是方便的,并且它也有助于评估。
最终的模型已经保存在输出目录中。我们可以从最终模型中加载权重,从测试集中逐个读取图像,运行预测器,并在本地保存带有遮罩和边界框的输出图像。
测试集应该包含图像路径的file_name
和image_id
。举个例子,
test_data = [{'file_name': '.../image_1.jpg',
'image_id': 10},
{'file_name': '.../image_2.jpg',
'image_id': 20}
]
visualization()
接受定制配置、元数据和测试集。它获取最终的模型,并将边界框和遮罩添加到图像中。最后,它在输出目录中创建一个目录,并将结果保存在那里。
可视化步骤
结论
Detectron2 使物体检测变得简单快捷。在本教程中,我解释了如何通过几个步骤运行 MaskRCNN。此外,Detectron2 在这里创建了一个对象检测的初学者教程。
参考
[1] Detectron2 Github 库
[2] 探测器 2 教程
https://sciencenotes.medium.com/membership
在一行 Python 代码中训练多个时间序列预测模型
原文:https://towardsdatascience.com/train-multiple-time-series-forecasting-models-in-one-line-of-python-code-615f2253b67a?source=collection_archive---------0-----------------------
使用 Auto-TS 库开发 ARIMA、SARIMAX、FB Prophet、VAR 和 ML 模型
图片由 Mediamodifier 来自 Pixabay
自动机器学习(AutoML)指的是将机器学习管道的一些组件自动化。AutoML 通过自动化一些模型开发过程来加速数据科学家的工作流程。自动化允许非专家在没有太多领域知识的情况下训练基本的机器学习模型。
有各种 Auto-ML 开源 Python 库包括 TPOT、MLBox、Auto-Sklearn 等,可以自动化一个分类或回归机器学习模型。为了自动化 NLP 问题,可以使用 AutoNLP 库。
在本文中,我们将讨论如何使用开源模型 Auto-TS 来自动化时间序列预测模型的实现。
什么是自动 TS:
(图片由作者提供)
Auto-TS 是一个带有时间序列预测实现的开源 Python 库。它可以在一行 Python 代码中训练多个时间序列预测模型,包括 ARIMA、SARIMAX、FB Prophet、VAR 等,然后从中选择最佳的一个进行预测。
Auto-TS 库的一些特性是:
- 利用遗传规划优化寻找最优时间序列预测模型。
- 利用所有可能的超参数配置和交叉验证,训练朴素模型、统计模型、机器学习模型和深度学习模型。
- 通过学习最佳 NaN 插补和异常值剔除,执行数据转换以处理杂乱数据。
- 模型选择的度量组合选择。
安装:
可以使用 PyPl 安装 Auto-TS,使用命令:
**pip install autots**
使用以下方式导入库:
**from auto_ts import auto_timeseries**
用法:
本案例研究中使用的数据集是从 Kaggle 下载的从 2006 年 1 月到 2017 年 12 月的亚马逊股价。
这个库只提供训练时间序列预测模型。数据集应该有一个时间或数据格式列。
- 使用时间/日期列加载时序数据集
**df = pd.read_csv("AMZN.csv", usecols=['Date', 'Close'])
df['Date'] = pd.to_datetime(df['Date'])
df = df.sort_values('Date')**
- 将整个数据分成训练和测试数据
**train_df = df.iloc[:2800]
test_df = df.iloc[2800:]**
- 可视化列车测试值以供参考
**train_df.Close.plot(figsize=(15,8), title= 'AMZN Stock Price', fontsize=14, label='Train')
test_df.Close.plot(figsize=(15,8), title= 'AMZN Stock Price', fontsize=14, label='Test')
plt.legend()
plt.grid()
plt.show()**
(图片由作者提供)、训练测试分割、AMZN 股价可视化
- 初始化 Auto-TS 模型对象,并拟合定型数据。
**model = auto_timeseries(forecast_period=219, score_type='rmse', time_interval='D', model_type='best')
model.fit(traindata= train_df, ts_column="Date", target="Close")**
- 比较不同型号的得分
**model.get_leaderboard()
model.plot_cv_scores()**
(图片由作者提供),不同车型的 RMSE 评分
- 预测测试数据
**future_predictions = model.predict(testdata=219)**
- 可视化测试数据值和预测。
(图片由作者提供),测试与预测,AMZN 股价可视化
结论:
在本文中,我们讨论了如何用一行 Python 代码实现时间序列建模。Auto-TS 对数据进行预处理,因为它通过学习最佳 NaN 插补从数据中移除异常值并处理杂乱数据。只需一行代码,通过初始化 Auto-TS 对象并拟合训练数据,您就可以训练多个时间序列模型,包括 ARIMA、SARIMAX、FB Prophet、VAR,并得出性能最佳的模型。
模型的结果看起来确实令人满意,但如果我们尝试增加数据集的大小,结果可能会有所改善。
除了为时序数据集训练模型的 Auto-TS 库之外,我们还有各种 AutoML 库,可以通过自动化模型开发管道来加快数据科学家的工作流程。阅读下面提到的文章中的,了解 8 个 AutoML 库。
https://medium.com/swlh/8-automl-libraries-to-automate-machine-learning-pipeline-3da0af08f636
参考资料:
[1] Auto-TS 文档:【https://pypi.org/project/AutoTS/
感谢您的阅读
用 Pytorch 在 50 行代码中训练一个用于语义分段的神经网络
原文:https://towardsdatascience.com/train-neural-net-for-semantic-segmentation-with-pytorch-in-50-lines-of-code-830c71a6544f?source=collection_archive---------0-----------------------
如何用不到 50 行代码(排除导入的话 40 行)训练一个语义切分的神经网络?这里的目标是给出如何使用内置的 Torchvision 神经网络(DeepLabV3)在 PyTorch 中训练语义分割神经网络的最快最简单的概述。
代码可用:https://github . com/sagie ppel/Train-Semantic-Segmentation-Net-with-py torch-In-50-Lines-Of-Code
语义分割的目标是获取图像并识别属于特定类别的区域。这是通过卷积神经网络处理图像来完成的,卷积神经网络输出每像素一类的映射。这些类别是以一组数字的形式给出的。例如,在这种情况下,我们将使用带有三个类的 LabPics V1 数据集(如下图所示):
图像,相应的分割掩模:黑色(0) =背景,灰色(1) =空容器,白色(2) =填充区域。图片由作者提供。
0 类:不是血管(黑色),
1 类:血管的空区域(灰色),
2 类:血管的填充区域(白色)。
网络的目标是接收一幅图像,并预测每个像素的三个类别之一。
第一步从这里下载 LabPics 数据集:https://zenodo.org/record/3697452/files/LabPicsV1.zip?下载=1
你还需要安装 Pytorch 和 OpenCV 来读取图像。
OpenCV 可以通过以下方式安装:
pip install opencv-python
首先,让我们导入包并定义主要的训练参数:
import os
import numpy as np
import cv2
import torchvision.models.segmentation
import torch
import torchvision.transforms as tfLearning_Rate=1e-5width=height=800 # image width and height
batchSize=3
Learning_Rate :训练时梯度下降的步长。
宽度和高度是用于训练的图像尺寸。训练过程中的所有图像都将调整到这个大小。
batchSize: i s 将用于每次训练迭代的图像数量。
批次大小宽度高度 t 将与训练的内存需求成比例。根据您的硬件,可能有必要使用较小的批处理大小来避免内存不足的问题。
请注意,由于我们只使用单一的图像大小进行训练,因此训练后的网络很可能仅限于使用这种大小的图像。在大多数情况下,你想做的是改变每个训练批次之间的大小。
接下来,我们创建数据集中所有图像的列表:
TrainFolder="LabPics/Simple/Train//"
ListImages=os.listdir(os.path.join(TrainFolder, "Image"))
Were TrainFolder 是 LabPics 数据集的 train 文件夹。
图片存储在 TrainFolder 的“image”子文件夹中。
接下来,我们定义一组将使用 TorchVision 变换模块在图像上执行的变换:
transformImg=tf.Compose([tf.ToPILImage(),tf.Resize((height,width)), tf.ToTensor(),tf.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))])transformAnn=tf.Compose([tf.ToPILImage(),tf.Resize((height,width)), tf.ToTensor()])
这定义了一组将应用于图像和注释映射的转换。这包括转换为 PIL 格式,这是转换的标准格式。调整大小并转换为 PyTorch 格式。对于图像,我们还通过减去*均值并除以像素强度的标准偏差来归一化图像中的像素强度。预先计算大量图像的*均值和偏差。
接下来,我们创建一个函数,该函数允许我们加载一个随机图像和相应的用于训练的注释图:
def ReadRandomImage(): idx=np.random.randint(0,len(ListImages)) # Pick random image Img=cv2.imread(os.path.join(TrainFolder, "Image",ListImages[idx])) Filled = cv2.imread(os.path.join(TrainFolder, "Semantic/16_Filled", ListImages[idx].replace("jpg","png")),0)
Vessel = cv2.imread(os.path.join(TrainFolder, "Semantic/1_Vessel", ListImages[idx].replace("jpg","png")),0) AnnMap = np.zeros(Img.shape[0:2],np.float32) # Segmentation map
if Vessel is not None: AnnMap[ Vessel == 1 ] = 1
if Filled is not None: AnnMap[ Filled == 1 ] = 2 Img=transformImg(Img)
AnnMap=transformAnn(AnnMap) return Img,AnnMap
在第一部分中,我们从图像列表中选择一个随机索引,并加载对应于该索引的图像。
idx = np.random.randint(0,len(ListImages)) # Pick random imageImg = cv2.imread(os.path.join(TrainFolder, "Image",ListImages[idx]))
接下来,我们要加载图像的注释遮罩:
Filled = cv2.imread(os.path.join(TrainFolder, "Semantic/16_Filled", ListImages[idx].replace("jpg","png")),0)
Vessel = cv2.imread(os.path.join(TrainFolder, "Semantic/1_Vessel", ListImages[idx].replace("jpg","png")),0)
这些注释被存储为覆盖属于特定类别(填充/脉管)的区域的图像/遮罩。每个类别掩码存储在单独的中。png 图像文件。其中属于该类的像素值为 1(灰色),其他像素值为 0(黑色)。
图像、填充和血管区域的遮罩以及统一的注释图(灰色=1,白色=2,黑色=0)。作者的形象。
为了训练网络,我们需要创建一个分割图,其中属于空血管区域的像素值为 1(灰色),属于填充区域的像素值为 2(白色),其余为 0(黑色)。
首先,我们创建一个在图像形状中充满零的分割图:
AnnMap = np.zeros(Img.shape[0:2],np.float32)
接下来,我们将在血管掩模中具有值 1 的所有像素设置为在分割掩模中具有值 1。并且在填充掩模中值为 1 的所有像素在分割掩模中具有值 2:
if Vessel is not None: AnnMap[ Vessel == 1 ] = 1
if Filled is not None: AnnMap[ Filled == 1 ] = 2
其中" AnnMap[ Filled == 1 ] = 2" 表示填充遮罩中值为 1 的每个位置在 AnnMap 中都将得到值 2。
如果没有血管和填充类的注释文件(如果图像中没有出现类,就会出现这种情况),cv2.imread 将返回 None,并且遮罩将被忽略。
最后,我们使用前面定义的转换将注释转换成 PyTorch 格式:
Img=transformImg(Img)
AnnMap=transformAnn(AnnMap)
为了训练,我们需要使用一批图像。这意味着几幅图像以 4D 矩阵的形式堆叠在一起。我们使用以下函数创建批处理:
def LoadBatch(): # Load batch of images
images = torch.zeros([batchSize,3,height,width])
ann = torch.zeros([batchSize, height, width])
for i in range(batchSize):
images[i],ann[i]=ReadRandomImage()
return images, ann
第一部分创建一个空的 4d 矩阵,它将存储具有维度的图像:[批次大小,通道,高度,宽度],其中通道是图像的层数;这对于 RGB 图像是 3,对于注释图是 1。
下一部分使用我们之前定义的 ReadRandomImage()将一组图像和注释加载到空矩阵中。
for i in range(batchSize):
images[i],ann[i]=ReadRandomImage()
现在我们可以加载数据了,是时候加载神经网络了:
device = torch.device(‘cuda’) if torch.cuda.is_available() else torch.device(‘cpu’)Net = torchvision.models.segmentation.deeplabv3_resnet50(pretrained=True)Net.classifier[4] = torch.nn.Conv2d(256, 3, kernel_size=(1, 1), stride=(1, 1)) # Change final layer to 3 classesNet=Net.to(device)optimizer=torch.optim.Adam(params=Net.parameters(),lr=Learning_Rate,weight_decay=Weight_Decay) # Create adam optimizer
第一部分是识别计算机是否有 GPU 或 CPU。如果有 Cuda GPU,培训将在 GPU 上进行:
device = torch.device(‘cuda’) if torch.cuda.is_available() else torch.device(‘cpu’)
对于任何实际的数据集,使用 CPU 进行训练都是极其缓慢的。
接下来,我们加载深度实验室网络语义分割:
Net = torchvision.models.segmentation.deeplabv3_resnet50(pretrained=True)
包含许多有用的语义分割模型,如 UNET 和 FCN。我们选择 Deeplabv3,因为它是最好的语义分割网络之一。通过设置 pretrained=True ,我们在 COCO 数据集上加载预训练的权重。当学习一个新问题时,从预先训练的模型开始总是更好,因为它允许网络使用以前的经验并更快地收敛。
我们可以通过编写以下内容来查看我们刚刚加载的网络的所有层:
打印(网)
….
(1): Conv2d(256,256,kernel_size=(3,3),stride=(1,1),padding=(1,1),bias = False)
(2):batch norm 2d(256,eps=1e-05,momentum=0.1,affine=True,track _ running _ stats = True)
(3):ReLU()
(4):conv 2d(256,21,kernel_size=(1,1),stride=(1,1))
这将按使用顺序打印层的网络。网络的最后一层是具有 256 层输入和 21 层输出的卷积层。21 代表输出类的数量。因为我们的数据集中只有 3 个类,所以我们想用一个具有 3 个输出的新卷积层来替换它:
Net.classifier[4] = torch.nn.Conv2d(256, 3, kernel_size=(1, 1), stride=(1, 1))
公*地说,这部分是可选的,因为具有 21 个输出类的网络可以简单地通过忽略剩余的 18 个类来预测 3 个类。但这样更优雅。
接下来,我们将网络加载到我们的 GPU 或 CPU 设备中:
Net=Net.to(device)
最后,我们加载一个优化器:
optimizer=torch.optim.Adam(params=Net.parameters(),lr=Learning_Rate) # Create adam optimizer
优化器将在训练的反向传播步骤中控制梯度率。亚当优化器是最快的优化器之一。
最后,我们开始训练循环:
for itr in range(20000): # Training loop
images,ann=LoadBatch()
images=torch.autograd.Variable(images,requires_grad=False)
.to(device)
ann = torch.autograd.Variable(ann,requires_grad=False).to(device)
Pred=Net(images)[‘out’] # make prediction
LoadBatch 是前面定义的,加载批量的图像和标注图。图像和 ann 将存储加载的图像和注释。
torch . autograded . variable:将数据转换成网络可以使用的梯度变量。我们设置 Requires_grad=False ,因为我们不想将渐变应用于图像,只应用于网络的层。 to(device) 将张量复制到与网络相同的设备(GPU/CPU)中。
最后,我们将图像输入网络,得到预测。
Pred=Net(images)[‘out’] # make prediction
一旦我们做出了预测,我们就可以将其与真实(地面实况)注释进行比较,并计算损失:
criterion = torch.nn.CrossEntropyLoss() # Set loss function
Loss=criterion(Pred,ann.long()) # Calculate cross entropy loss
Loss.backward() # Backpropogate loss
Optimizer.step() # Apply gradient descent change to weight
首先,我们定义损失函数。我们使用标准的交叉熵损失:
criterion = torch.nn.CrossEntropyLoss()
我们使用此函数来计算使用预测和真实注释的损失:
Loss=criterion(Pred,ann.long())
一旦我们计算出损失,我们就可以应用反向传播并改变净重。
Loss.backward() # Backpropogate loss
Optimizer.step() # Apply gradient descent change to weight
这涵盖了整个训练阶段,但是我们还需要保存训练好的模型。否则,一旦程序停止,它就会丢失。
保存非常耗时,所以我们希望每 1000 步保存一次:
if itr % 1000 == 0:
print(“Saving Model” +str(itr) + “.torch”)
torch.save(Net.state_dict(), str(itr) + “.torch”)
在运行这个脚本大约 3000 步之后,网络应该会给出不错的结果。
完整代码可在此处找到:
https://github.com/sagieppel/Train-Semantic-Segmentation-Net-with-Pytorch-In-50-Lines-Of-Code
总共 50 行代码,不包括空格,40 行代码,不包括导入:-)
最后,一旦网络被训练,我们想申请分割真实的图像,看看结果。我们使用一个单独的推理脚本来实现这一点,该脚本使用训练网络来分割图像:
import cv2
import torchvision.models.segmentation
import torch
import torchvision.transforms as tf
import matplotlib.pyplot as pltmodelPath = "3000.torch" # Path to trained model
imagePath = "test.jpg" # Test image
height=width=900transformImg = tf.Compose([tf.ToPILImage(), tf.Resize((height, width)), tf.ToTensor(),tf.Normalize((0.485, 0.456, 0.406),(0.229, 0.224, 0.225))])
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
Net = torchvision.models.segmentation.deeplabv3_resnet50(pretrained=True) Net.classifier[4] = torch.nn.Conv2d(256, 3, kernel_size=(1, 1), stride=(1, 1)) Net = Net.to(device) # Set net to GPU or CPUNet.load_state_dict(torch.load(modelPath)) # Load trained modelNet.eval() # Set to evaluation modeImg = cv2.imread(imagePath) # load test imageheight_orgin , widh_orgin ,d = Img.shape # Get image original size plt.imshow(Img[:,:,::-1]) # Show imageplt.show()
Img = transformImg(Img) # Transform to pytorchImg = torch.autograd.Variable(Img, requires_grad=False).to(device).unsqueeze(0)with torch.no_grad():
Prd = Net(Img)['out'] # Run net# resize to orginal size
Prd = tf.Resize((height_orgin,widh_orgin))(Prd[0])#Convert probability to class map
seg = torch.argmax(Prd, 0).cpu().detach().numpy() plt.imshow(seg) # display image
plt.show()
这里的大部分代码与训练脚本相同,只有几处不同:
Net.load_state_dict(torch.load(modelPath)) # Load trained model
从模型路径中的文件加载我们之前训练并保存的网络
Net.eval()
将网络从培训模式转换为评估模式。这主要意味着不会计算批量标准化统计数据。
with torch.no_grad():
这意味着网络运行时不收集梯度。梯度仅与训练相关,并且收集它们是资源密集型的。
请注意, Pred 中的输出将被映射为每幅图像 3 个通道,每个通道代表 3 个类别之一的非标准化概率。为了找到每个像素所属的类,我们使用 argmax 函数取具有 3 的最高值的通道(类):
seg = torch.argmax(Prd[0], 0)
我们对输出图中的每个像素都这样做,并为每个像素获得 3 个类中的一个。
结果是:
输入图像:
输出预测:
使用 PyTorch 在 40 行代码中训练神经网络来预测图像的连续属性。
原文:https://towardsdatascience.com/train-neural-net-to-predict-continuous-properties-from-an-image-in-40-lines-of-code-with-pytorch-c3a408a02b52?source=collection_archive---------6-----------------------
本教程的目标是如何使用 Pytorch 以最短的方式预测图像的连续属性,如颜色、填充级别。我们将学习加载现有的网络,修改它以预测特定的属性,并在不到 40 行代码(不包括空格)内训练它。
支持本教程的完整代码可以在这里找到:
https://github.com/sagieppel/Train-neural-net-to-predict-continuous-property-from-an-image-in-40-lines-of-code-with-PyTorch
标准神经网络通常专注于分类问题,如识别猫和狗。然而,这些网络可以很容易地修改,以预测图像的连续属性,如年龄,大小或价格。
首先,让我们导入包并定义主要的训练参数:
import numpy as np
import torchvision.models.segmentation
import torch
import torchvision.transforms as tfLearning_Rate=1e-5
width=height=900
batchSize=1
Learning_Rate :训练时梯度下降的步长。
宽度和高度是用于训练的图像尺寸。训练过程中的所有图像都将调整到这个大小。
batchSize: i s 将用于每次训练迭代的图像数量。
批次大小宽度高度将与训练的内存需求成比例。根据您的硬件,可能有必要使用较小的批处理大小来避免内存不足的问题。
请注意,由于我们只使用单一的图像大小进行训练,因此训练后的网络很可能仅限于使用这种大小的图像。
接下来,让我们创建我们的训练数据。我们想做一个简单的演示,所以我们将创建一个图像,用白色填充到一定高度。网络的目标是预测图像中被白色覆盖的部分。这可以很容易地用于从真实图像中预测更复杂的属性,正如在其他教程中演示的那样。
例如:
47%填充白色的图像。
76%填充白色的图像。
在上面的图像中,我们希望网络预测 0.47,因为图像的 47%填充为白色。在底部的图片中,我们希望网络预测 0.76,因为 76%的图像填充为白色。
在实际设置中,您可能会从文件中加载数据。在这里,我们将动态创建它:
def ReadRandomImage():
FillLevel=np.random.random() # Set random fill level
Img=np.zeros([900,900,3],np.uint8) # Create black image
Img[0:int(FillLevel*900),:]=255 # Fill the image
transformImg=tf.Compose([tf.ToPILImage(),
tf.Resize((height,width)),tf.ToTensor(),tf.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))]) # Set image transformation
Img=transformImg(Img) # Transform to pytorch
return Img,FillLevel
在第一部分,我们创建图像:
FillLevel=np.random.random() # Set random fill level
Img=np.zeros([900,900,3],np.uint8) # Create black image
Img[0:int(FillLevel*900),:]=255 # Fill the image
第一行选择 0-1 之间的一个随机数作为填充级别。
Img=np.zeros([900,900,3]) 创建一个大小为 900X900 的矩阵,用零填充该矩阵作为图像,这相当于一个高度和宽度为 900 的黑色图像。该图像有 3 个对应于 RGB 的通道。
接下来,我们用白色填充图像的顶部直到填充线。
Img[0:int(FillLevel*900),:]=255
现在我们已经创建了图像,我们对其进行处理并将其转换为 Pytorch 格式:
transformImg=tf.Compose([tf.ToPILImage(),
tf.Resize((height,width)),tf.ToTensor(),tf.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))]) # Set image transformation
这定义了一组将应用于图像的变换。这包括转换为 PIL 格式,这是转换的标准格式,以及调整大小和转换为 PyTorch 格式。对于图像,我们还通过减去*均值并除以像素强度的标准偏差来归一化图像中的像素强度。对于我们的简单图像,并不真正需要标准化和调整大小,但是这些转换对于真实图像是重要的。
接下来,我们将变换应用于图像:
Img=transformImg(Img)
为了训练,我们需要使用一批图像。这意味着几幅图像以 4D 矩阵的形式堆叠在一起。我们使用以下函数创建批处理:
def LoadBatch(): # Load batch of images
images = torch.zeros([batchSize,3,height,width])
FillLevel = torch.zeros([batchSize])
for i in range(batchSize):
images[i],FillLevel[i]=ReadRandomImage()
return images,FillLevel
第一行创建了一个空的 4d 矩阵,它将存储图像的维度:[batchSize,channels,height,width],其中 channels 是图像的层数;这是 RGB 图像的 3。下一行创建了一个数组,用来存储填充的级别。这将作为我们培训的目标(基本事实)。
下一部分使用我们之前定义的 ReadRandomImage()函数将一组图像和 FillLevels 加载到空矩阵中:
for i in range(batchSize):
images[i],FillLevel[i]=ReadRandomImage()
现在我们可以加载数据了,是时候加载神经网络了:
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')Net = torchvision.models.resnet18(pretrained=True) # Load netNet.fc = torch.nn.Linear(in_features=512, out_features=1, bias=True)Net = Net.to(device)optimizer = torch.optim.Adam(params=Net.parameters(),lr=Learning_Rate)
第一部分是识别计算机是否有 GPU 或 CPU。如果有 Cuda GPU,培训将在 GPU 上进行:
device = torch.device(‘cuda’) if torch.cuda.is_available() else torch.device(‘cpu’)
对于任何实际的数据集,使用 CPU 进行训练都是极其缓慢的。
接下来,我们加载网络进行图像分类:
Net = torchvision.models.resnet18(pretrained=True)
torchvision.models. 包含许多用于图像分类的有用模型reset 18是一个轻量级分类模型,适用于低资源训练或简单数据集。对于较难的问题,最好用 resenet50 (注意数字是指网的层数)。
通过设置 pretrained=True ,我们在 Imagenet 数据集上加载预训练权重的网络。当学习一个新问题时,从预先训练的模型开始总是更好,因为它允许网络使用以前的经验并更快地收敛。
我们可以看到我们刚刚加载的网络的所有结构和所有层,通过编写:
*print(Net)*
…
…
(avgpool):AdaptiveAvgPool2d(output _ size =(1,1))
(fc):Linear(in _ features = 512,out_features=1000,bias=True)
这将按使用顺序打印层的网络。网络的最后一层是具有 512 层输入和 1000 层输出的线性变换。1000 代表输出类别的数量(该网络在图像网络上训练,图像网络将图像分类为 1000 个类别中的一个)。因为我们只想预测一个值,所以我们想用一个具有一个输出的新线性图层来替换它:
Net.fc = torch.nn.Linear(in_features=512, out_features=1, bias=True)
公*地说,这部分是可选的,因为具有 1000 个输出通道的网络可以简单地通过忽略剩余的 999 个通道来预测一个值。但这样更优雅。
接下来,我们将网络加载到我们的 GPU 或 CPU 设备中:
Net=Net.to(device)
最后,我们加载一个优化器:
optimizer=torch.optim.Adam(params=Net.parameters(),lr=Learning_Rate) # Create adam optimizer
优化器将在训练的反向传播步骤中控制梯度率。亚当优化器是最快的优化器之一。
最后,我们通过加载数据开始训练循环,使用网络进行预测:
AverageLoss=np.zeros([50]) # Save average loss for display
for itr in range(2001): # Training loop
images,GTFillLevel=LoadBatch() # Load taining batch
images=torch.autograd.Variable(images,requires_grad=False).
to(device)
GTFillLevel = torch.autograd.Variable(GTFillLevel,
requires_grad=False).to(device)
PredLevel=Net(images) # make prediction
第一,我们想挽回我们训练时的*均损失;我们创建一个数组来存储最后 50 步的丢失。
AverageLoss=np.zeros([50])
这将允许我们跟踪网络学习的情况。
我们将训练 2000 步:
for itr in range(2000):
LoadBatch 是之前定义的,加载一批图像及其填充级别。
torch . autogradated . variable:将数据转换成网络可以使用的梯度变量。我们设置 Requires_grad=False ,因为我们不想将渐变只应用于网络的图层。 to(device) 将张量复制到与网络相同的设备(GPU/CPU)中。
最后,我们将图像输入网络,得到预测。
PredLevel=Net(images)
一旦我们做出预测,我们可以将其与真实(地面真实)填充水*进行比较,并计算损失。损失将仅仅是图像的预测和真实填充水*之间的绝对差(L1 ):
Loss=torch.abs(PredLevel-GTFillLevel).mean()
请注意,我们不是将损失应用于一个图像,而是应用于批中的几个图像,因此我们需要取*均值,将损失作为单个数字。
一旦我们计算出损失,我们就可以应用反向传播并改变净重。
Loss.backward() # Backpropogate loss
Optimizer.step() # Apply gradient descent change to wei
在训练过程中,我们想看看我们的*均损失是否减少,看看网络是否真正学到了什么。因此,我们将最后 50 个损失值存储在一个数组中,并显示每一步的*均值:
AverageLoss[itr%50]=Loss.data.cpu().numpy() # Save loss average
print(itr,") Loss=",Loss.data.cpu().numpy(),
'AverageLoss',AverageLoss.mean())
这涵盖了整个训练阶段,但是我们还需要保存训练好的模型。否则,一旦程序停止,它就会丢失。
存钱非常耗时,所以我们希望每 200 步只存一次:
if itr % 200 == 0:
print(“Saving Model” +str(itr) + “.torch”)
torch.save(Net.state_dict(), str(itr) + “.torch”)
在运行这个脚本大约 200 步之后,网络应该会给出好的结果。
总共 40 行代码,不包括空格。
完整代码可在此处找到:
https://github.com/sagieppel/Train-neural-net-to-predict-continuous-property-from-an-image-in-40-lines-of-code-with-PyTorch
在网络被训练和保存之后,它可以被加载用于进行预测:
https://github.com/sagieppel/Train-neural-net-to-predict-continuous-property-from-an-image-in-40-lines-of-code-with-PyTorch/blob/main/Infer.py
该脚本加载您之前训练和保存的网络,并使用它进行预测。
这里的大部分代码与训练脚本相同,只有几处不同:
Net.load_state_dict(torch.load(modelPath)) # Load trained model
从模型路径中的文件加载我们之前训练并保存的网络
#Net.eval()
将网络从培训模式转换为评估模式。这主要意味着不会计算批量标准化统计数据。虽然使用它通常是一个好主意,但在我们的情况下,它实际上降低了准确性,所以我们将使用没有它的网络。
with torch.no_grad():
这意味着网络运行时不收集梯度。梯度仅与训练相关,并且收集它们是资源密集型的。
这就是它如果你想知道如何将它应用到真实的图像和真实的属性,查看下一个教程:
https://medium . com/@ sagieppel/predict-material-properties-from-an-image-using-a-neural-net-in-50-line of-code-with-py torch-4d 60965 b58c 0
用一行代码在云上训练神经网络
原文:https://towardsdatascience.com/train-neural-network-on-cloud-with-one-line-of-code-8ae2e378bc98?source=collection_archive---------19-----------------------
你可能见过的最简单的无服务器模型训练工具
在自动气象站上训练张量流模型
大家好大家好,
我是 Aipaca 公司的 Yuki,是滑铁卢大学计算机工程专业的四年级学生。当我作为一名数据科学家实习时,我发现在云上设置基础设施和训练模型非常耗时。因此,我与 Cody、Xin、Lounan 和 Sam 合作开发了一个无服务器模型培训工具——**ai bro。**从上面的代码片段中可以观察到,Aibro 让云模型训练像一行 python 代码一样简单。这篇文章将带你一步一步地使用这个工具。
Colab 演示链接 & 我们的网站
注:目前 Aibro 版本仅支持基于 Tensorflow 的模型训练。我们将在不久的将来添加更多像 Pytorch 和 Sklearn 这样的框架。
关于 Aibro
Aibro 是一个将机器学习模型连接到任何云服务器的 MLOps API。它帮助数据科学家和机器学习研究人员轻松地在云*台上训练和部署模型,而无需担心基础设施的设置。
工作流程
步骤 1:准备模型和数据
例如,我们使用 MNIST 作为训练数据,然后将其处理成适合以下 CNN 的形状。
from tensorflow.keras.datasets import mnist
import tensorflow as tf#load data
TRAINING_SIZE = 10000
(train_X, train_Y), (test_X, test_Y) = mnist.load_data()validation_X = train_X[TRAINING_SIZE:(TRAINING_SIZE + 40)].reshape((40, 28, 28, 1))
validation_Y = train_Y[TRAINING_SIZE:(TRAINING_SIZE + 40)]#process data
train_X = train_X[:TRAINING_SIZE].reshape((TRAINING_SIZE, 28, 28, 1))
train_Y = train_Y[:TRAINING_SIZE]
train_Y = tf.keras.utils.to_categorical(train_Y, 10)validation_Y = tf.keras.utils.to_categorical(validation_Y, 10)
CNN 模型:
from tensorflow.keras import layers, modelsmodel = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation="relu", input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation="relu"))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation="relu"))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation="relu"))
model.add(layers.Dense(10, activation="softmax"))
model.compile(
optimizer="adam",
loss=tf.keras.losses.CategoricalCrossentropy(from_logits=False),
metrics=[tf.keras.metrics.CategoricalAccuracy()],
)
您可以尝试在 Colab 演示中即插即用任何基于 Tensorflow 的模型和数据。请记住,如果您的模型使用`度量=[" accuracy "]【T11 ]'进行编译,那么由于 Tensorflow 的模型保存和重新加载问题,度量可能会被错误地传输。为了避免这个问题,请在编译模型时指定您的指标,如演示中所示。
步骤 2:安装 Aibro 库
公共 Aibro 的版本是 1.1.0。您可以使用以下命令安装它。在调用它的方法时,我们可能需要您的电子邮件地址,这有助于我们回溯作业日志并改进未来的开发。
!pip install aibro
https://test.pypi.org/simple
第三步:选择一个云机器
在启动训练机之前,你需要选择一个云机来训练模型。目前,Aibro 仅支持 AWS 上的 spot 实例,因为它们比按需深度学习实例(如 Sagemaker)便宜 4 倍。
顺便说一下,不要担心 spot 实例的中断问题,Aibro 有一个专门的系统来自动重新连接中断的培训工作。
现在,让我们回到演示。通过调用 available_machines(),可以查看每台机器的租赁限额及其可用性。可用性被定义为成功启动指定的 spot 实例类型的概率(因为 spot 实例请求不能保证被 AWS 满足)。一般来说,更强大的实例不太可能可用。
from aibro.train import available_machinesavailable_machines()
样本输出:
Available Resources:
Machine Id: g4dn.4xlarge GPU Type: 1xT4 num_vCPU: 16 cost: $0.36/hr limit: 4 availability: 96.0%
Machine Id: g4dn.8xlarge GPU Type: 1xT4 num_vCPU: 32 cost: $0.67/hr limit: 2 availability: 84.0%
Machine Id: p2.8xlarge GPU Type: 8xK80 num_vCPU: 32 cost: $2.16/hr limit: 2 availability: 49.0%
Machine Id: p2.xlarge GPU Type: 1xK80 num_vCPU: 4 cost: $0.27/hr limit: 23 availability: 61.0%
Machine Id: p3.2xlarge GPU Type: 1xV100 num_vCPU: 8 cost: $0.92/hr limit: 11 availability: 24.0%
Machine Id: p3.8xlarge GPU Type: 4xV100 num_vCPU: 32 cost: $3.67/hr limit: 2 availability: 12.0%
好消息:由于我们想在更多的边缘情况下测试该工具,您产生的任何机器租赁费用将由我们支付。但是,请不要循环使用它!学生的口袋很脆弱😳。
步骤 4:启动培训工作
最上面的代码片段显示了培训作业是如何启动的。在设计方法时,我们试图保持通常适合张量流模型的相同风格。在 extra 中,你只需要通过 model ,cloud machine_id 来填充函数 args 并添加一个描述来帮助你识别工作。
from aibro import Trainingjob_id, trained_model, history = Training.online_fit(
model=model,
train_X=train_X,
train_Y=train_Y,
validation_data=(validation_X, validation_Y),
machine_id=machine_id,
description='Demo Run 0.0.41',
epochs=10
)
培训工作开始后有 7 个有序阶段:
- **【启动】:**向云*台发送打开实例的请求
- **【发送】:**向实例发送模型和数据
- **【镜像】:**将你本地的深度学习环境克隆到云端
- **【训练】:**模型开始训练
- 【**总结】:**返回培训工作的简要总结
- **【接收】:**将训练好的模型和其他结果返回给用户
- [ 关闭]: 销毁用户培训数据,终止实例
在**【训练】**阶段,会显示一个 tensorboard 地址供你实时跟踪进度。
培训作业完成后,将返回 job_id 、 trained_model 和 history 对象。
您还可以通过 list_trial() 查看您的历史作业,并通过使用get _ Tensorboard _ logs(job _ id)下载 tensor board 日志来检查相应的详细信息。
设计原则——通过打开和关闭来实现节能
图片由来自 Pexels 的 Luis Quintero 提供
云机器就像一个水龙头,当“水”运行时,你按秒计费,这是一种能源和金钱的浪费。Aibro 的设计不仅可以帮助数据科学家在云上训练模型,还可以最大限度地减少浪费。所以,每推出一个新的培训工作,Aibro 都会打开一个新的云服务器。一旦作业完成或取消,服务器将自动终止。代价是您可能需要 2-3 分钟的耐心来等待实例启动。
注意:我们正在添加多个功能以缩短发布时间;例如,在下一个版本中,我们将允许服务器在作业完成后保留一段时间,以便快速调试和修改模型。这样,如果在等待期间提交了新作业,该作业将直接跳过[启动]阶段。
什么即将到来
演示之后,我们正在为 Aibro 开发一个 alpha 版本,将于 10 月初推出。在下一版本中,您将看到以下更新:
- 用户注册:开放给用户注册和管理账户。
- 文档:解释更多关于库的细节。
- 保持期:在培训作业开始之前预打开服务器(预热期),在培训作业之后保持保持服务器(冷却期)。
- 离线 fit:启动一个培训任务,稍后通过 job_id 获取。
- 重新培训:从检查点恢复暂停的培训作业。
- 大数据:支持大数据传输和训练。
联系我们
如果你发现 Aibro 是有用的,请加入我们来自 aipaca.ai 的等候名单。我们将分享 Aibro 的最新更新。同时,我们欢迎您的任何反馈。您可以通过从 aipaca.ai 加入 AIpaca 社区、发送电子邮件至 hello@aipaca.ai 或使用*ai bro . comm . send _ message()*向我们发送直接消息来联系我们!
使用 Azure Machine Learning SDK for Python 在云 GPU 上进行培训
原文:https://towardsdatascience.com/train-on-cloud-gpus-with-azure-machine-learning-sdk-for-python-967c99418df1?source=collection_archive---------11-----------------------
在 Azure Machine Learning Studio cloud 中的 GPU 驱动的计算实例上运行机器学习模型的入门指南
在 Unsplash 上由 Daniel Páscoa 拍照
我最*在做一个项目,需要快速训练一组神经网络。这不能在我的笔记本电脑上完成,因为培训是连续的,没有足够的时间。另外,我不能忍受我的 3.1 GHz 2017 MacBook Pro 在用 tensorflow 训练模型时有多迟钝。
开始使用 Azure 机器学习有一个相当大的障碍。微软的文档很好,但没有提供上下文,所以拼凑必要的组件来运行这个项目最终有点痛苦。为了减轻你的痛苦,这里有一个在 Azure cloud 中使用 GPU 计算实例运行机器学习模型的入门指南。
数据
在本教程中,我将使用来自 Mindy Yang 和 Gary Thung 的论文垃圾可回收性分类中的数据可以从 google drive 文件夹下载原始尺寸和缩减采样尺寸的图像,或者从 kaggle 下载缩减采样尺寸的图像。
为了对数据有一个概念,这里有一些图片和它们的文件名。
图片由作者在麻省理工学院许可下使用 M. Yang 和 G. Thung 的组件制作
我将数据分为训练集和验证集。分割的代码与使用 Azure 没有直接关系,所以我没有在这里包括它;然而,用于创建这个项目的所有代码都可以在相关的 github 资源库中找到。
至此,是时候设置 Azure 环境了!
Azure 设置
请求 GPU 配额
如果你还没有 Azure 帐户,你可以注册一个,并获得 200 美元的免费点数(截至本文撰写之时)。但是,为了在支持 GPU 的实例上运行以下培训,您必须将您的帐户升级为“现收现付”,并请求增加 GPU 计算实例类型的配额。在您切换到“现收现付”后,您的点数将保持有效
GPU 将显著加快训练速度(例如,将我的笔记本电脑与我进行基准测试的模型上支持 GPU 的计算实例进行比较,每个时期从 18 分钟缩短到 40 秒),并且由于速度的提高还节省了资金。
要请求增加配额,请单击“?”(问号)并选择“新建支持请求”。"
- 对于
Issue type
,选择Service and Subscription Limits (quotas)
- 对于
Quota type
,选择Machine Learning services
在下面的屏幕上
- 选择
Enter Details
- 选择您首选的数据中心位置。请记住您选择的位置,以后会用到它。我在这个演示中使用了
East US
。 - 从 VM 系列下拉菜单中选择
NCPromo
。 - 为此计算类型选择您希望能够并发运行的 CPU 内核数量。在这种计算类型中,每个 GPU 有 6 个 CPU 内核,因此对于一个 GPU,您应该输入 6,对于两个 GPU,输入 12,依此类推。
- 点击
Save and continue
- 点击下一步:
Review + create >>
注意:该笔记本可以在配备了新帐户的标准 DSv2 虚拟机上运行,您的模型将需要相当长的时间来训练。
安装 AzureML python sdk。
尽管仍有可能安装 AzureML sdk,但当前推荐的最佳实践是仅将您需要的组件安装到您的环境中。
对于这个项目,我们只需要 azureml.core,它可以用 pip 安装,如下所示:
pip install azureml.core
设置 Azure 环境
在我们将模型传递给 Azure 进行训练之前,需要进行一些设置。它们是:
- 创建工作区
- 定义计算机目标
- 创建运行环境
- 将您的数据上传到数据存储(可选)
- 定义数据集
我将一步一步地介绍它们,并简要解释它们是什么以及它们如何适应整体架构。
创建工作区
Azure 上的机器学习工作区就像一个项目容器。它位于一个资源组中,包含您将在项目中使用的任何其他资源,如存储或计算。好消息是,可以使用 azureml python sdk 轻松地创建工作空间及其资源组。
像这个设置部分中的所有内容一样,工作区只需要创建一次。把[your-subscription-id]
换成,嗯……你能想出来。如果您愿意,您还可以将资源组名称和工作区名称更改为类似于test123
这样有创意的名称。
这将要求您进行身份验证,然后将您的连接信息存储在。azureml 子目录,这样你就不用再次认证了。
定义计算目标
计算目标定义了将运行您的培训脚本的虚拟机的类型。
compute_name
是用户定义的,可以是对你有意义的任何东西。这是您将来引用计算集群的方式。vm_size
是您想要在计算集群中使用的计算类型的 Azure 特定名称。我们正在使用Standard_NC6_Promo
,它对应于我们在上面请求配额的计算类型。它有 6 个 CPU 核心和一个特斯拉 K80 GPU。min_nodes
是即使没有要处理的内容也将保持活动状态的节点数。这可以减少培训的启动时间,但无论您是否使用这些节点,您都需要付费。我推荐 0 入门。max_nodes
是该计算目标中一次可以运行的最大节点数。max_nodes
必须小于您的 cpu 配额/每个节点的 CPU 数量,否则配置将失败。
创建运行环境
运行环境定义了脚本和要使用的基本 docker 映像的依赖关系。微软提供了几个策划环境,但是因为 ImageDataGenerator 需要Pillow,
而Pillow
不包含在策划环境中,所以我们必须创建自己的容器。
name
传递给Environment
的是用户为您的环境定义的名称。我们稍后将使用它来访问环境。CondaDependencies
为您的脚本定义 pip、conda 和 pip 包依赖关系。env.docker.base_image
定义 docker 容器用作基本图像。这可以来自于 AzureML-Containers repo 。(您也可以使用一个定制容器但是这超出了本文的范围)
将数据上传到数据存储
AzureML Studio 架构中需要理解的一个重要细节是数据存储和数据集之间的区别。一个 数据存储 是存储。它有多种类型,但是它存储你的数据。
数据集 是对存储在数据存储或任何可公开访问的 url 中的数据的引用。
每个工作区都有一个默认的 blob 数据存储,这就是我们将在本演示中使用的。
- 我们用
get_default_datastore()
获取对默认工作区数据存储的引用
然后我们通过调用数据存储对象上的upload
来上传文件,方法是:
src_dir
是上传的本地路径target_path
是您的数据将被上传到数据存储的路径
定义数据集
现在我们已经上传了数据,我们需要创建指向数据的数据集定义。
- 要创建数据集,调用
Dataset.File.from_files
并传入一个带有我们的datastore
对象和数据存储中数据的路径的元组。 - 然后我们注册数据存储区,这样我们就可以在以后访问它,而不必重新创建它。
这是一次性设置的结束。现在我们有了一个工作区,我们可以在ml.azure.com查看它,它包含一个compute_target
,以及一个注册的Environment
和Dataset
。
训练模特
此时,在 github 库中,我创建了一个新的 jupyter 笔记本。这是为了展示加载我们已经创建的所有资产是多么简单。看看这个:
定义一个实验名称
模型的每次运行都存在于一个实验中。实验就像你跑步的文件夹,让你保持跑步有条理。例如,您可以为 CNN 迭代创建一个实验,为 LSTM 迭代创建另一个实验。在这个演示中,我们将创建一个名为“回收”的实验你可以用任何对你有意义的方式对你的跑步进行分组。
创建控制脚本
控制脚本是一个独立的 python 文件(或多个文件),它被上传到 Azure,并在 AMLcompute 实例上运行以训练您的模型。您可以将参数作为命令行参数发送到您的脚本,我们将在下面看到。
这是我在这个演示中使用的控制脚本。它执行以下操作:
- 解析传递给脚本的参数
- 为数据创建 ImageDataGenerators
- 建立一个模型
- 符合模型
- 保存模型及其历史
发给 Azure!
现在我们将它发送到 Azure 以在云中运行!
一个重要的细节是控制脚本如何获得数据路径。我们将带有挂载类型的Dataset
对象传递给脚本。它将自动为您装载,并且装载路径将代替您的参数中的数据集。这是非常方便的,也没有解释在哪里(至少我找不到)。
参数按照您在命令行中编写的顺序传递。参数名和值分别传递,但作为一个列表按顺序传递。
第一次运行模型时,Azure 会构建它的计算容器。这可能需要相当长的时间,但 azure 会缓存容器,因此后续运行会更快。
检查培训情况
要查看培训并监控培训日志,您可以登录 Azure Machine Learning Studio。
- 前往https://portal.azure.com/并登录
- 搜索“机器学习”,选择“机器学习”
- 选择“azure_trash_demo”
- 选择“启动工作室”
- 从左侧菜单中选择
Experiments
- 选择
recycling
你的模型在云中运行。
此时,我们没有记录存储任何指标,因此您在这里看到的只是运行时间。在另一篇文章中,我将深入探讨如何使用这个仪表板实时监控你的跑步。
监控机器学习工作室中的日志
要在模型训练时实时查看日志,请单击运行 ID,然后单击输出+日志。
你可以通读所有的 tensorflow 控制台吐槽,看看我们确实是在 GPU 上训练。日志将定期更新,无需您的参与。
下载您的模型和日志
这个模型对我们没有太大的帮助。最后一步是将训练好的模型和模型历史放回我们的本地计算机,这样我们就可以用惊人的回收预测给我们的朋友留下深刻印象。
一旦模型训练完成,我们可以下载训练过程中生成的所有文件,包括日志,以及由我们的训练脚本保存到outputs/
路径的任何内容,代码如下。
加载模型
现在我们已经有了可以加载到模型中的文件和训练好的权重。
*Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, None, None, 32) 416
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, None, None, 32) 0
_________________________________________________________________
flatten (Flatten) (None, None) 0
_________________________________________________________________
dense (Dense) (None, 6) 3096774
=================================================================
Total params: 3,097,190
Trainable params: 3,097,190
Non-trainable params: 0
_________________________________________________________________*
绘制训练历史
我们可以绘制训练历史。
或者任何你想要的东西。
包装它
我希望这能让你在未来更快的训练!弄清楚这一切可能会很麻烦,但是希望这篇文章能加快你的速度。
你知道你可以不止一次为媒体上的文章鼓掌吗?来吧,试试看!给它一些掌声,就像你真的在鼓掌一样。我会听到它,并感谢掌声。
Github 回购
您可以查看完整的 github 资源库或者直接跳到下面的第一个笔记本:
**
现在去做好事吧。
基于 Java 的强化学习训练“不朽”的 Flappy Bird
原文:https://towardsdatascience.com/train-undying-flappy-bird-using-reinforcement-learning-on-java-98ff68eb28bf?source=collection_archive---------25-----------------------
拍打还是不拍打?让人工智能代理决定。
图片来自 Pixabay
Flappy Bird 是一款于 2013 年推出的手机游戏,因其简单的玩法(拍打/不拍打)而变得超受欢迎。随着深度学习(DL)和强化学习(RL)的发展,我们现在可以训练一个 AI 智能体来控制 Flappy Bird 的行动。今天,我们将看看使用 Java 创建人工智能代理的过程。对于游戏本身,我们使用了一个简单的使用 Java 的开源 Flappy Bird 游戏。对于训练,我们使用了深度 Java 库(DJL) ,一个基于 Java 的深度学习框架,来构建训练网络和 RL 算法。
在本文中,我们将从 RL 的基础开始,通过关键组件来构建培训架构。如果在任何时候你不能遵循我们的代码,并希望尝试游戏,你可以参考我们的 RL 报告。
作者图片
RL 架构
在本节中,我们将介绍一些主要的算法和网络,以帮助您更好地了解我们如何训练模型。这个项目使用了类似于 DeepLearningFlappyBird 的方法,这是一个 Python Flappy Bird RL 实现。主要的 RL 架构是 Q-Learning ,卷积神经网络(CNN)。在每个游戏动作阶段,我们存储鸟的当前状态、代理采取的动作以及鸟的下一个状态。这些被视为 CNN 的训练数据。
CNN 培训概述
用于训练的输入数据是连续的四帧图像。我们将这四幅图像叠加起来,形成对这只鸟的“观察”。这里的观察是指由一系列图像表示的时间序列数据。图像本身是灰度的,以减少训练负荷。图像的数组表示为(批量大小,4(帧),80(宽度),80(高度))。数组的每个元素代表每帧的像素值。这些数据被输入 CNN 并计算出一个输出(批量大小,2)。输出的第二维表示下一个动作(拍打,不拍打)的置信度。
我们使用记录的实际动作对照输出置信度来计算损失。之后,通过反向传播和参数优化来更新模型。代理会不断更新用于训练的数据,以获得更好的结果。
培训用数据
在行动阶段之后,我们创建预观察和当前观察。如前所述,这些只是代表一系列运动的图像。之后,我们只需将 preObservation、currentObservation、action、reward 和 terminal 放在一起,作为一个步骤存储到 replayBuffer 中。replayBuffer 是具有有限大小的训练数据集,并且用最新的动作动态更新。
public void step(NDList action, boolean training) {
if (action.singletonOrThrow().getInt(1) == 1) {
bird.birdFlap();
}
stepFrame();
NDList preObservation = currentObservation;
currentObservation = createObservation(currentImg);
FlappyBirdStep step = new FlappyBirdStep(manager.newSubManager(),
preObservation, currentObservation, action, currentReward, currentTerminal);
if (training) {
replayBuffer.addStep(step);
}
if (gameState == GAME_OVER) {
restartGame();
}
}
RL 的三个阶段
有三个不同阶段的 RL 用于生成更好的训练数据:
- 观察阶段:大多数动作是随机的,只有一小部分动作来自人工智能代理
- 探索阶段:随机行动和人工智能代理行动相结合
- 训练阶段:动作主要由人工智能代理产生
在探索阶段,我们将在随机行动和人工智能代理行动之间选择。在训练开始时,主要使用随机动作,因为人工智能代理生成的动作通常很差。在这之后,我们逐渐增加采取 AI 智能体行动的概率,直到它最终成为唯一的决策者。用于调整随机和人工智能代理动作之间的比率的参数称为ε。它会在训练过程中不断变化。
public NDList chooseAction(RlEnv env, boolean training) {
if (training && RandomUtils.random() < exploreRate.getNewValue(counter++)) {
return env.getActionSpace().randomAction();
} else return baseAgent.chooseAction(env, training);
}
训练逻辑
首先,我们对存储在 ReplayBuffer 中的步骤进行一些随机选择,以形成一个批处理。之后,预观测值被用于馈入 CNN 以获得预测回报(Q)。
NDList QReward = trainer.forward(preInput);
NDList Q = new NDList(QReward.singletonOrThrow()
.mul(actionInput.singletonOrThrow())
.sum(new int[]{1}));
然后后观察也被用来和 CNN 一起向前跑。遵循马尔可夫决策过程和贝尔曼方程(一个评估决策质量的过程),我们可以计算实际报酬(targetQ)作为期望输出。
NDList targetQReward = trainer.forward(postInput);
NDArray[] targetQValue = new NDArray[batchSteps.length];
for (int i = 0; i < batchSteps.length; i++) {
if (batchSteps[i].isTerminal()) {
// game over after the action
targetQValue[i] = batchSteps[i].getReward();
} else {
targetQValue[i] = targetQReward.singletonOrThrow().get(i)
.max()
.mul(rewardDiscount)
.add(rewardInput.singletonOrThrow().get(i));
}
}
NDList targetQBatch = new NDList();
Arrays.stream(targetQValue).forEach(value -> targetQBatch.addAll(new NDList(value)));
NDList targetQ = new NDList(NDArrays.stack(targetQBatch, 0));
在训练结束时,我们所做的就是从 Q 和 targetQ 计算损失值,进行反向传播并更新 CNN 中的权重。
CNN 架构
我们使用三个卷积层作为 ReLU 激活函数,两个全连接层形成神经网络。这里的架构被许多处理简单 CV 问题的 RL 应用所使用。
培训程序
DJL 提供了三个关键的 RL 组件:RlEnv、RlAgent 和 ReplayBuffer。
- 你可以实现 RlAgent 来构建一个可训练的 AI。
- 将 RlEnv 添加到现有的游戏环境中,作为数据馈送器。
- 构建一个 ReplayBuffer 来存储和动态更新训练数据
实现接口后,我们需要做的就是调用step
函数:
RlEnv.step(action, training);
它将输入一个由 RlAgent 决定的动作,并传递给环境以使其生效。为了运行它,RlEnv 还提供了一个叫做runEnvironment
的方法。当我们不断调用这个方法时,它会产生新的动作和状态。
public Step[] runEnvironment(RlAgent agent, boolean training) {
// run the game
NDList action = agent.chooseAction(this, training);
step(action, training);
if (training) {
batchSteps = this.getBatch();
}
return batchSteps;
}
对于 ReplayBuffer,我们将大小设置为 50k。在观察阶段,我们将从随机动作中存储 1000 个观察值到缓冲区。这将有助于人工智能代理从随机尝试中快速学习。
在探索和训练阶段,AI 智能体会随机形成一批,喂给模型进行训练。我们使用 Adam 优化器和 MSE 损失函数来改进 CNN。
预处理输入
首先,将原始图像的大小调整为 80x80,并更改为灰度。这将有助于在不丧失许多功能的情况下加快训练速度。
public static NDArray imgPreprocess(BufferedImage observation) {
return NDImageUtils.toTensor(
NDImageUtils.resize(
ImageFactory.getInstance().fromImage(observation)
.toNDArray(NDManager.newBaseManager(),
Image.Flag.GRAYSCALE) ,80,80));
}
然后,我们形成一个四图像输入。为了保持连续的图像序列,我们创建了一个全局图像队列来存储游戏线程中的图像。之后,四个图像将被堆叠到单个 NDArray 中。
public NDList createObservation(BufferedImage currentImg) {
NDArray observation = GameUtil.imgPreprocess(currentImg);
if (imgQueue.isEmpty()) {
for (int i = 0; i < 4; i++) {
imgQueue.offer(observation);
}
return new NDList(NDArrays.stack(new NDList(observation, observation, observation, observation), 1));
} else {
imgQueue.remove();
imgQueue.offer(observation);
NDArray[] buf = new NDArray[4];
int i = 0;
for (NDArray nd : imgQueue) {
buf[i++] = nd;
}
return new NDList(NDArrays.stack(new NDList(buf[0], buf[1], buf[2], buf[3]), 1));
}
}
一旦这一部分完成,我们就可以开始训练了。
培训优化
为了获得最佳的训练性能,我们关闭了 GUI 以加快样本生成速度。Java 多线程也被用来分离训练循环和样本生成循环。
List<Callable<Object>> callables = new ArrayList<>(numOfThreads);
callables.add(new GeneratorCallable(game, agent, training));
if(training) {
callables.add(new TrainerCallable(model, agent));
}
摘要
我们花了大约 4 个小时在亚马逊 EC2 g4dn.2xlarge 实例(英伟达 T4 GPU)上进行训练,每步 3 米。这只鸟最终可以在隧道间飞行。最终的模型也被上传到 repo 供你尝试和微调。
在我们 RL 旅程的开始,我们不知道我们是否真的可以用 Java 构建一切。经过几周的研究和测试,我们终于有了可以开始工作的东西。我们仍然记得那次我们让笔记本电脑日夜开着来训练这只鸟。经过大约 3,000,000 步的训练,人工智能代理可以通过 8000 多个管道而不会死亡!在未来,我们计划为 DJL 开发更多的 RL 应用,比如超级马里奥兄弟和一些有更多动作选择的游戏。
无需代码即可训练、可视化和检查计算机视觉模型
原文:https://towardsdatascience.com/train-visualize-and-inspect-computer-vision-models-on-a-no-code-mlops-platform-6e26ea9c6fef?source=collection_archive---------30-----------------------
计算机视觉
看看 Nexus 和 Portal,这是一个无代码的 MLOps *台,允许您训练、测试和部署最先进的 cv 模型
法尔汉·阿扎姆在 Unsplash 上拍摄的照片
A 你是一个对训练计算机视觉模型感兴趣的计算机视觉爱好者,但是本地机器的局限性或花费数小时编写大量代码阻止了你吗?
或者你是一个 ML 从业者,希望简化你的 ML 堆栈,而不是仅仅为了可视化和验证你的模型而与 cv2 或 matplotlib 代码争论?
这篇文章是给你的。
介绍由初创公司 Datature 打造的开源无代码 appNexus和 Portal ,一个无代码的 MLOps *台。
什么是 Nexus 和 Portal?
- Nexus 是构建计算机视觉应用的最快方法,无需代码(也不会牺牲准确性)
- 门户 ( 最*发布!)是一款针对视觉模型的开源视觉检测工具。
为了测试这两个应用程序,我决定使用 Kaggle 的人脸面具检测数据集,包含属于三个类别的 853 张图像——无面具、面具和面具佩戴不当,并训练一个简单的面具检测模型。
用 Nexus 训练掩模检测模型
上传图像
首先,我把图片上传到图片区;这一部分是不言自明的。
我取出了 10%的图像,并保存下来,以便在 Portal 中进行检查,从而验证我的模型。
上传注释
数据集带有 PASCAL VOC 格式的注释,因此将它们上传到 Nexus 只需要选择正确的格式。
上传注释
注释图像
如果你没有注释或者想要编辑和添加更多注释,Nexus 有一个圆滑而丰富的界面可供你使用。一个很酷的功能是,你可以实时地给它们贴标签。
完成图像和注释后,您会在主页上看到一个漂亮的小摘要。
标签的分布,图像和注释的良好统计。
创建工作流
构建工作流的可视化方式非常直观。基本的想法是:
数据集→扩充→选择模型架构
我的遮罩检测模型的简单工作流程
对于数据集,我使用默认值0.3
作为训练-测试分割比,您也可以选择一个特定的随机种子来实现可重复性。
我选择了一些基本的随机位置增强——中心裁剪、水*和垂直翻转。在色彩空间增强中还有许多其他选项,切换到高级模式可以让你选择这些增强的概率。
对于该模型,我选择了 FasterRCNN ResNet50 640x640,并使用每批 2 个图像和 1000 个训练时期的默认值,因此训练不会花费太多时间,因为这只是一个有趣的小项目。
还有一个预览增强功能,这是有用的测试选定的增强。
超参数调谐
在工作流启动之前,您将能够看到您选择的所有参数的预览,我发现这很有用,因为它可以作为神经网络初始化之前的最后一分钟检查。
训练前调整超参数
培训的实时监控
在 Nexus 上训练一个模型最酷的事情是,你可以看到你的模型在图表上的实时进度,如果你决定停止,你可以点击一个按钮。
NVIDIA k80 引擎上的模型训练只花了大约 30 分钟,但根据你训练的模型的大小和类型,有不同的 GPU 设置供你选择。
完成后,您会得到一个关于您的模型的所有重要指标的很好的摘要。
完成后,我前往工件部分生成我的 TensorFlow 模型并下载它。
准备好模型后,我前往门户网站开始可视化和检查它。
使用门户网站检查
加载训练好的模型和图像
加载模型非常容易。我所要做的就是选择 TensorFlow 选项,然后提供我下载的模型的路径。
然后,我将我的验证图像上传到门户网站。
准备好图像后,我可以开始测试我的模型了!
分析图像
分析图像只需点击一个按钮,如果您想一次性分析所有图像,只需点击Bulk Analysis
您可以为每个分析设置您想要的置信度阈值,甚至可以过滤您想要查看的标签。
在对我的验证图像进行批量分析时,我发现我的掩模检测模型出现了一些小问题。
以下是我的模型在相当高的置信阈值下的预测,这产生了错误的预测。
(右)模型应预测带面罩,(中)模型应预测不带面罩,(左)模型应预测面罩佩戴不正确
检查表明,该模型将一片单一颜色(帽子、太阳镜、衬衫)混淆为一个面罩,导致错误预测。
此外,检查显示该模型在头部转向左侧或右侧时表现不佳。
头部朝左或朝右时,模型表现不佳
该模型的另一个问题是,该模型没有像它应该的那样预测mask_worn_incorrectly
。下面的图片正好说明了这一点。
图像清楚地显示了没有正确佩戴的面具,因为鼻子暴露在外,但我们的模型只能在 5%的置信水*下预测正确的标签。
发生这种情况有两个可能的原因。首先,与其他两个标签相比,mask_weared_incorrectly
标签的样本量很小,另一个原因是该模型需要更多的训练或调整。
检查完成后,我现在可以继续调整我的注释,添加更多的数据,添加更多的扩充以捕获更多的信息,甚至使用不同的模型来改进我的掩码检测模型。
所以你走吧!我训练了一个更快的 R-CNN 模型,并使用 Nexus 和 Portal 在没有代码的情况下对其进行了检查。
关于连接和门户的思考
- 设计 —令人敬畏的设计和圆滑的界面。很明显他们在设计上下了很多功夫。
- 性能——对我来说,Nexus 和 Portal 都运行得很流畅,尽管 Nexus 有时在工作流部分滞后,我不得不刷新 web 应用程序。
- 易用性 —我惊讶于这些*台的易用性。我没有发现应用程序令人困惑的任何部分,每一步都很直观。
Portal 的最终目标是简化可视化和检查模型的过程,我认为它肯定实现了这一点,尤其是对于那些没有技术背景的人。
作为一个狂热的计算机视觉爱好者,我发现 Nexus 和 Portal 是两个非常直观的应用程序,可以旋转 cv 模型并测试模型。
我认为这两个无代码应用的革命性之处在于,它简化了整个计算机视觉管道,消除了对多个工具或*台的需求,更不用说无需编写任何代码,这肯定会占用大量时间。
Datature 的*台正在推动无代码人工智能革命,并无疑是计算机视觉行业的游戏规则改变者。
还有很多我没有在本文中介绍的特性,您可以使用 Portal 来完成,比如进行视频推理和通过 API 部署模型的能力(即将推出)。推荐你去他们网站自己试试!
构建您自己的模型@ Nexus →使用门户检查您的模型!
Datature 的 Nexus 和 Portal 视频教程
- 使用 Portal 检查计算机视觉模型
- 用#NoCode 训练一个自定义对象检测模型
- 用自定义数据集训练实例分割模型
欲了解更多关于数据的信息,请访问👉网站或联系他们!
我尽可能地撰写与数据科学和机器学习相关的文章,并经常在 bitgrit 数据科学出版物上发表文章。
订阅我的时事通讯以便在我发布时获得更新。
感谢阅读👋!
在 AWS SageMaker 中训练您的定制深度学习模型
原文:https://towardsdatascience.com/train-your-custom-deep-learning-model-in-aws-sagemaker-4e8674dd196e?source=collection_archive---------19-----------------------
使用 boto3 APIs 的可重复过程
概观
如果你像我一样,不想在家里设置服务器来训练你的深度学习模型,那么这篇文章就是为你准备的。很可能,基于云的机器学习基础设施是你的选择。我将在 AWS SageMaker 中一步一步介绍如何做到这一点。
图片由来自 Pixabay 的 chenspec 提供
为什么我们需要定制模型
亚马逊 SageMaker 附带了大量的预训练模型。这些模型是 AWS 中预先构建的 docker 映像。如果符合您的需求,您可以使用这些型号。这里有一个使用 SageMaker XGBoost 算法解决回归问题的例子。但是在很多情况下,您需要构建自己的定制模型。
有不同的 SageMaker SDKs 可用于此目的。在这个例子中,我将向您展示如何使用 sage makerboto3
API 来实现这一点。就我个人而言,我发现boto3
API 比其他 SageMaker SDKs 更全面、文档更完善、更容易理解。在互联网上,我看到 SageMaker 的例子缺乏一致性,因为他们使用了各种不同的方法。我希望这篇文章对那些正在寻找使用boto3
的一致例子的人有所帮助。
如何训练你的定制模型
SageMaker 使用 Docker [1] image 允许用户训练和部署自定义算法。Docker 使用一个名为Dockerfile
的文件来指定如何组装图像。
了解 AWS SageMaker 的 Docker 图像
因为您可以在培训和服务中运行相同的 docker 映像,SageMaker 使用参数train
或serve.
运行您的容器。您的容器如何处理该参数取决于容器。
- 您可以在
Dockerfile
中指定一个程序作为ENTRYPOINT
。该程序将在启动时运行,它的第一个参数将是train
或serve
。然后,程序可以查看该参数并决定要做什么。 - 在这个例子中,我们没有在
Dockerfile.
中定义一个ENTRYPOINT
,因此 Docker 在训练时间运行命令[train](https://docs.aws.amazon.com/sagemaker/latest/dg/your-algorithms-training-algo.html)
,在服务时间运行命令[serve](https://docs.aws.amazon.com/sagemaker/latest/dg/your-algorithms-inference-code.html)
。在这个例子中,我们将它们定义为可执行的 Python 脚本,但是它们可以是我们想要在那个环境中启动的任何程序。 - 如果您为培训和托管构建单独的容器(或者只为其中一个构建),您可以在
Dockerfile
中将程序定义为一个ENTRYPOINT
,并忽略(或验证)传入的第一个参数。
AWS SageMaker 的 Docker 图像布局
当 Amazon SageMaker 运行训练时,您的train
脚本将作为常规 Python 程序运行。在 Docker 映像中,在/opt/ml
目录[2]下有许多文件供您使用:
/opt/ml
|-- input
| |-- config
| | |-- hyperparameters.json
| | `-- resourceConfig.json
| `-- data
| `-- <channel_name>
| `-- <input data>
|-- model
| `-- <model files>
`-- output
`-- failure
输入
/opt/ml/input/config
包含控制程序如何运行的信息。hyperparameters.json
是一个 JSON 格式的超参数名称到值的字典。这些值总是字符串,所以您可能需要转换它们。resourceConfig.json
是一个 JSON 格式的文件,描述了用于分布式培训的网络布局。/opt/ml/input/data/<channel_name>/
(文件模式)包含该通道的输入数据。通道是基于对 CreateTrainingJob 的调用而创建的,但是通道与算法预期相匹配通常是很重要的。每个频道的文件都从 S3 复制到这个目录,保留了 S3 关键字结构指示的树形结构。/opt/ml/input/data/<channel_name>_<epoch_number>
(管道模式)是给定时期的管道。纪元从零开始,每读一次就加一。您可以运行的 epoch 数量没有限制,但是您必须在读取下一个 epoch 之前关闭每个管道。
输出
/opt/ml/model/
是您编写算法生成的模型的目录。您的模型可以是您想要的任何格式。它可以是单个文件,也可以是整个目录树。SageMaker 将这个目录中的所有文件打包成一个压缩的 tar 归档文件。该文件在DescribeTrainingJob
结果中返回的 S3 位置可用。/opt/ml/output
是一个目录,算法可以在其中写入一个描述作业失败原因的文件failure
。该文件的内容返回到DescribeTrainingJob
结果的FailureReason
字段中。对于成功的作业,没有理由写入该文件,因为它会被忽略。
建造一个容器
在这里参考 github 库并克隆它。您可以将它克隆到您的本地机器上(确保您安装了 AWS CLI 和 Docker ),或者在 SageMaker notebook 实例中获得这个 repo。在 SageMaker 中运行这些命令的好处是,它将比您的本地机器运行得快得多。
- 确保您已经登录到您的
ECR
。将目录切换到存储库中的docker
目录。然后创建一个ECR
存储库
$cd docker
$aws ecr create-repository --repository-name A-REPO-NAME
- 一旦运行了上面的命令,您应该会得到如下所示的 JSON 输出
{
"repository": {
"repositoryArn": "arn:aws:ecr:us-west-1:149363165341:repository/A-REPO-NAME",
"registryId": "149363165341",
"repositoryName": "nahid-sagemaker-tf-repo",
"repositoryUri": "149363165341.dkr.ecr.us-west-1.amazonaws.com/A-REPO-NAME",
"createdAt": 1619175745.0,
"imageTagMutability": "MUTABLE",
"imageScanningConfiguration": {
"scanOnPush": false
},
"encryptionConfiguration": {
"encryptionType": "AES256"
}
}
}
- 注意上面的
repositoryUri
。我们将在接下来的两步中使用那个repositoryUri
$docker build -t repositoryUri .
$docker push repositoryUri
训练你的模型
假设我们在上面的步骤中创建了一个定制的 docker 图像training-image
。让我们也给我们的培训工作起个名字job_name
。
现在您已经有了使用您的定制训练脚本的定制 docker 映像,我们可以使用它来训练 AWS SageMaker 中的模型。在开始训练之前,我们需要为训练我们的模型定义一组配置。下面是一个示例培训配置
training_config = {
"TrainingJobName": job_name,
"AlgorithmSpecification": {
"TrainingImage": training_image,
"TrainingInputMode": "File"
},
"RoleArn": role,
"OutputDataConfig": {"S3OutputPath": training_output_path,
"InputDataConfig": [
{
"ChannelName": "train",
"DataSource": {
"S3DataSource": {
"S3DataType": "S3Prefix",
"S3Uri": training_input_path,
"S3DataDistributionType": "FullyReplicated",
}
},
"ContentType": "text/csv"
}
],
"ResourceConfig": {
"InstanceType": "ml.m5.2xlarge",
"InstanceCount": 1,
"VolumeSizeInGB": 75,
},
"StoppingCondition": {
"MaxRuntimeInSeconds": 86400
}
}
以上training_config
中的几个要点
TrainingJobName
是 SageMakerTraining job
帮助你唯一识别你的培训工作亚马逊 SageMaker >培训工作TrainingImage
是您刚刚创建的自定义 docker 图像- 在
ResourceConfig
中,您正在指定您想要训练模型的机器的配置。因此,如果您有一个复杂的模型和更大的数据集,您将需要一台配置更高的机器。 - 在
OutputDataConfig
中,您指定了在训练完成后您将在哪里存储您的模型。 - 密切注意
InputDataConfig
键。注意,我们在里面有一个名为channelName
的键。这是指我们是为train
还是validation
指定数据集。在这个例子中,我们在不经过任何类型的验证数据集的情况下进行训练。因此,我们这里没有validation
通道。实际上,你很可能也有一个validation
数据集。在这种情况下,您也必须指定validation
通道。
关于training_config
的完整列表,你可以参考 boto3 文档这里
现在我们可以使用这个training_config
来创建一个培训工作
client = boto3.client("sagemaker", region_name=region)
client.create_training_job(**training_config)
检查培训状态
根据数据集的大小,训练作业可能需要一些时间。你可以通过查看亚马逊 SageMaker >培训工作来监控你的培训工作状态,如下图所示
一旦您进入Training jobs
,您将会看到到目前为止您运行的培训任务列表。您可以在此示例中单击正在运行的特定培训作业,并检查各种配置(输入/输出配置、超参数等。)和工作状态。如果作业由于任何原因失败,您可以转到Monitor
部分的View logs
,它将带您到Cloudwatch
查看详细日志。
您还可以通过编程方式监控培训作业状态
import time
status = client.describe_training_job(TrainingJobName=job_name)["TrainingJobStatus"]
print(status)
while status != "Completed" and status != "Failed":
time.sleep(60)
status = client.describe_training_job(TrainingJobName=job_name)["TrainingJobStatus"]
print(status)
主持模型
托管模型需要 3 个步骤
将模型导入宿主
我们需要使用存储在create_model
API 内s3
中的模型工件model.tar.gz
来使您的模型准备好托管。
%%time
import boto3
from time import gmtime, strftime
model_name = f"{job_name}-model"
info = client.describe_training_job(TrainingJobName=job_name)
model_data = info["ModelArtifacts"]["S3ModelArtifacts"]
primary_container = {"Image": container, "ModelDataUrl": model_data}
create_model_response = client.create_model(
ModelName=model_name, ExecutionRoleArn=role, PrimaryContainer=primary_container
)
print(create_model_response["ModelArn"])
定义端点配置
在 SageMaker 中,您可以为不同的目的创建模型托管端点——A/B 测试、开发与生产版本等。我们将在端点配置中指定这些,并使用create_endpoint_config
API 创建端点配置。
endpoint_config_name = f"my-custom-model-endpointconfig-{strftime('%Y-%m-%d-%H-%M-%S', gmtime())}"
create_endpoint_config_response = client.create_endpoint_config(
EndpointConfigName=endpoint_config_name,
ProductionVariants=[
{
"InstanceType": "ml.m5.xlarge",
"InitialVariantWeight": 1,
"InitialInstanceCount": 1,
"ModelName": model_name,
"VariantName": "AllTraffic",
}
],
)
print(f"Endpoint Config Arn: {create_endpoint_config_response['EndpointConfigArn']}")
创建端点
最后,我们使用create_endpoint
API 创建端点。根据您的数据集,此任务大约需要 5-10 分钟。因此,监视端点创建过程是一个好主意。
endpoint_name = f'my-custom-model-Endpoint-{strftime("%Y-%m-%d-%H-%M-%S", gmtime())}'
create_endpoint_response = client.create_endpoint(
EndpointName=endpoint_name, EndpointConfigName=endpoint_config_name
)
print(create_endpoint_response["EndpointArn"])
resp = client.describe_endpoint(EndpointName=endpoint_name)
status = resp["EndpointStatus"]
while status == "Creating":
print(f"Status: {status}")
time.sleep(60)
resp = client.describe_endpoint(EndpointName=endpoint_name)
status = resp["EndpointStatus"]
print(f"Arn: {resp['EndpointArn']}")
print(f"Status: {status}")
测试预测
最后,您可以测试您的模型端点并检验预测。
file_name = "test.csv"
with open(file_name, "r") as f:
payload = f.read().strip()
response = runtime_client.invoke_endpoint(
EndpointName=endpoint_name, ContentType="text/csv", Body=payload
)
result = response["Body"].read()
result = result.decode("utf-8")
result = result.split(",")
result = [math.ceil(float(i)) for i in result]
label = payload.strip(" ").split()[0]
print(f"Label: {label}\nPrediction: {result[0]}")
本文的完整源代码在这里。
参考:
[1].Docker入门。
[2].自带【Tensorflow 模型。
[3].亚马逊 SageMaker 概述这里。
[4].用亚马逊 SageMaker XGBoost 算法回归。
训练你自己的象棋人工智能
原文:https://towardsdatascience.com/train-your-own-chess-ai-66b9ca8d71e4?source=collection_archive---------0-----------------------
看着你的作品打败你
迈克尔在 Unsplash 上的照片
介绍
TLDR: Colab 链接
深度学习已经接管了计算机象棋世界。2017 年 AlphaZero ,AlphaGo 针对国际象棋的迭代,通过轻松击败 Stockfish 迷住了国际象棋迷。该领域的新发展,如 Leela Zero (一个开源的 AlphaZero 实现,碰巧使用了 my chess lib )和 Stockfish NNUE (可高效更新的反向神经网络)表明,在可预见的未来,神经网络将继续主导国际象棋。
作为一名国际象棋爱好者和人工智能实践者,我开始创造自己的国际象棋人工智能,但一个令人生畏的传言让我气馁: AlphaZero 花费 3500 万美元训练。AlphaZero 完全通过强化学习和自我游戏进行训练,以避免外部依赖。虽然明显有效,但从成本角度来看,自我游戏的效率低得令人难以置信。今天的引擎已经可以区分好位置和坏位置。这种先验知识可以用来引导学习过程,并使以非常有限的成本(或在 Colab 上免费)训练象棋 AI 成为可能。让我们试试吧!并使用来自现有引擎的数据集使用监督机器学习来训练神经网络。
定义模型
模型图,图片由作者提供
引擎如何决定一个位置好不好?给定一个位置,引擎返回从白色角度看这个位置有多好的分数。这个分数被称为评估,通常简称为 eval,eval 函数是国际象棋引擎的核心。eval 是一个以卒当量为单位的真实实力衡量标准。例如,如果白棋是一个棋子,评估将是+1。如果黑棋是骑士,评估将是-3。原材料不是决定评估的唯一因素,位置信息和未来的移动也会被考虑在内。
传统上,eval 功能是通过手工算法实现的,这些算法定量测量材料不*衡、工件移动性和国王安全等概念。这些直接测量,结合迭代加深单独产生超人的结果。神经网络可以取代这些手工算法,并直接返回评估结果,无需专门编码。总的来说,eval 函数接受一个位置并返回一个评估分数。我们如何把它变成一个模型?
输出 eval 可以由单个基于浮点的神经元来表示。代表棋盘位置的输入可以使用每种棋子类型的位棋盘 (64 位,棋盘上的每个方格一个)进行编码,剩余的几个位用于移动索引、要移动的颜色和路过的方格。这些输入数据一起形成了一个 808 位(1 和 0)的字符串,可以转换成浮点数并直接输入到模型中。
现在我们已经计划好了输入、输出和一般模型概念,让我们开始构建数据集。
建立数据集
我在Lichess.com上玩,因为它是免费的,开源的,由开发者运营。Lichess 拥有网站上所有游戏的每月下载片段。2021 年 7 月包含 9200 多万场比赛。在注释部分,它提到了一个非常重要的细节:“大约 6%的游戏包括 Stockfish 分析评估”,在这种情况下,这将是 550 多万个游戏。一般的国际象棋游戏持续大约 40 步,80 个位置(每一方每“步”得到一个回合),七月应该包含 441,600,000 个非唯一位置。这似乎足以创建我们的初始数据集。
Lichess 的每月碎片编码为. pgn.bz2 文件。文件扩展名. bz2 是一种压缩形式。pgn 是“可移植游戏符号”,这是一种基于文本的格式,用于将国际象棋游戏编码为代数符号中的一系列移动。以下是单个 PGN 文件记录的文本:
[Event "Rated Bullet tournament https://lichess.org/tournament/yc1WW2Ox"]
[Site "https://lichess.org/PpwPOZMq"]
[Date "2017.04.01"]
[Round "-"]
[White "Abbot"]
[Black "Costello"]
[Result "0-1"]
[UTCDate "2017.04.01"]
[UTCTime "11:32:01"]
[WhiteElo "2100"]
[BlackElo "2000"]
[WhiteRatingDiff "-4"]
[BlackRatingDiff "+1"]
[WhiteTitle "FM"]
[ECO "B30"]
[Opening "Sicilian Defense: Old Sicilian"]
[TimeControl "300+0"]
[Termination "Time forfeit"]
1\. e4 { [%eval 0.17] [%clk 0:00:30] } c5 { [%eval 0.19] [%clk 0:00:30] }
2\. Nf3 { [%eval 0.25] [%clk 0:00:29] } 2... Nc6 { [%eval 0.33] [%clk 0:00:30] }
3\. Bc4 { [%eval -0.13] [%clk 0:00:28] } 3... e6 { [%eval -0.04] [%clk 0:00:30] }
4\. c3 { [%eval -0.4] [%clk 0:00:27] } 4... b5? { [%eval 1.18] [%clk 0:00:30] }
5\. Bb3?! { [%eval 0.21] [%clk 0:00:26] } 5... c4 { [%eval 0.32] [%clk 0:00:29] }
6\. Bc2 { [%eval 0.2] [%clk 0:00:25] } 6... a5 { [%eval 0.6] [%clk 0:00:29] }
7\. d4 { [%eval 0.29] [%clk 0:00:23] } 7... cxd3 { [%eval 0.6] [%clk 0:00:27] }
8\. Qxd3 { [%eval 0.12] [%clk 0:00:22] } 8... Nf6 { [%eval 0.52] [%clk 0:00:26] }
9\. e5 { [%eval 0.39] [%clk 0:00:21] } 9... Nd5 { [%eval 0.45] [%clk 0:00:25] }
10\. Bg5?! { [%eval -0.44] [%clk 0:00:18] } 10... Qc7 { [%eval -0.12] [%clk 0:00:23] }
11\. Nbd2?? { [%eval -3.15] [%clk 0:00:14] } 11... h6 { [%eval -2.99] [%clk 0:00:23] }
12\. Bh4 { [%eval -3.0] [%clk 0:00:11] } 12... Ba6? { [%eval -0.12] [%clk 0:00:23] }
13\. b3?? { [%eval -4.14] [%clk 0:00:02] } 13... Nf4? { [%eval -2.73] [%clk 0:00:21] } 0-1
每次移动后,在注释部分,基于 Stockfish 的评估以定制的文本格式编写。
1\. e4 { [%eval 0.24] [%clk 0:05:00] }
这给了我们与位置配对的 eval(从一系列移动中计算)。2021 年 7 月的原始压缩月度碎片为 25.2 GB,因此单个 CSV 文件很可能是不可能的。带有适当索引的 SQLite 数据库似乎更合适。该架构包括 FEN(用于调试的位置的文本编码)、供模型直接使用的二进制以及对定型输出的评估:
> select * from evaluations limit 7;id|fen|binary|eval
1|rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq d3 0 1|0.0
2|rnbqkbnr/ppp1pppp/8/3p4/3P4/8/PPP1PPPP/RNBQKBNR w KQkq d6 0 2|0.27
3|rnbqkbnr/ppp1pppp/8/3p4/2PP4/8/PP2PPPP/RNBQKBNR b KQkq c3 0 2|0.0
4|rnbqkbnr/ppp2ppp/4p3/3p4/2PP4/8/PP2PPPP/RNBQKBNR w KQkq - 0 3|0.09
5|rnbqkbnr/ppp2ppp/4p3/3P4/3P4/8/PP2PPPP/RNBQKBNR b KQkq - 0 3|0.1
6|rnbqkbnr/ppp2ppp/8/3p4/3P4/8/PP2PPPP/RNBQKBNR w KQkq - 0 4|0.0
7|rnbqkbnr/ppp2ppp/8/3p4/3P4/2N5/PP2PPPP/R1BQKBNR b KQkq - 1 4|0.09
现在我们有了数据,让我们开始训练吧!
培养
对于这个项目,让我们使用 Pytorch Lightning ,它是 Pytorch 上面的一个便利层。为了训练,我们必须首先实现两个类:Dataset 和 LightningModule。由于数据集的规模很大(数据库最终有 37 毫米的位置),IterableDataset 最有意义,它将数据视为无限流。next 方法只需要返回随机的一行数据。因为我们不担心在数千万个位置上过度拟合,所以我们不需要将数据分成训练集、验证集和测试集。
Pytorch 数据集的实现,使用 https://carbon.now.sh 创建
EvaluationDataset 从 SQLite 表中随机提取一行,并通过提取原始字节中的二进制值对其进行预处理,使用 numpy 的 frombuffer 和 unpackbits 函数将这些字节转换为浮点型,并形成所需的 808 长度的浮点型数组作为输入。评估值 is 被提取并限制在-15 和 15 之间。边界保护防止极端赢的位置支配损失函数(例如+45 白)。+-15 是非常肯定的胜利,每一方,并评估过去,这是不必要的,我们的目的,将减缓训练收敛。
Pytorch 模型的实现,用 https://carbon.now.sh 创建
该模型由 808 个神经元的 N 层(初始设置为 4)组成,直到直接输出评估的 1 个神经元的最终输出层。使用 L1 损失,或标签和预测之间的绝对*均差异,因为输出是直观的。例如,如果 L1 损失是 2.0,那么*均而言,该模型与 stockfish 的评估相差 2 个卒。
Tensorboard 的训练损失,图片由作者提供
成功了,失败了!最终我们的模型的两个版本被训练。四层的一个达到 1.29 的损耗,六层的一个达到 1.06 的损耗。
测试
JESHOOTS.COM 在 Unsplash 上的照片
测试我们 AI 最好的方法就是玩!使用阿尔法贝塔搜索,换位表,和一些其他标准的国际象棋人工智能技术,我们可以创建一个完整的国际象棋引擎来对抗。AI 客户端在 Go ( 中实现,所以我可以使用我的象棋库),模型托管在一个基于 python 的 gRPC 服务器上,该服务器为我家里的 Nvidia 2080 加速 linux 服务器上的模型提供服务。
基于围棋的象棋引擎少于 300 LOC,这里是主要走法的代码。
Go 客户端的实现
这是服务于该模型的 pthon gRPC 服务器实现。它接受成批的编码位置并返回评估结果。
Python 服务器的实现
现在,我们已经连接了我们的机器人和我们的模型服务板评估,我们已经准备好玩了!这个机器人的对手(我自己)在快速、闪电战和子弹上只有可怜的 1200 左右的*均等级。这些游戏没有时间限制。我花了我需要的时间,a I 每一步花了大约 20 秒。在我与机器人的两场比赛中,我仁慈地给了自己白。
不幸的是,Medium 不允许嵌入,所以我在 Lichess 上放了一张整个游戏的 Gif 和一个完整游戏的链接,还有一个 Stockfish 分析。
第一场:洛根·斯皮尔斯(白)对切斯·博特·DNN-4 层-损失-1.29(黑)
洛根斯皮尔斯(白)诉国际象棋机器人 DNN-4 层-损失-1.29(黑)。画吧。完整游戏:https://lichess.org/rh7jL6rL
https://lichess.org/rh7jL6rL
我玩 E4(我总是玩 E4),人工智能选择了被称为“西西里防御”的 C5。黑棋的第一步很吸引人,因为人工智能没有打开的书,也没有玩游戏的经验,却为黑棋选择了一个最受欢迎的防御。开局相当*衡,没有一方获得明显的优势,直到我用我的黑暗广场主教换了移动中的黑骑士。事后看来,这揭开了布莱克的黑暗广场主教,暴露了 B2 广场上的弱点。然后我在移动 13 时与另一个骑士交易的主教复合了这个错误,他掉了一个兵,让黑方女王的攻击线通过。我蹲下身子,尽我最大的努力防守,通过移动 25 让比赛接**手。由于忽略了拿走我的兵,黑棋低估了 E8 的潜在升级,并在移动 26 时犯了个错误,让骑士去 B3,他认为如果骑士拿走了我可以强迫车交易,主教不能保护 A 的兵不被升级。不幸的是,我也没有看到这一点,我让我暂时的优势溜走了。游戏以一系列*淡无奇的举动结束,我同意和棋(斯托克菲什同意双方势均力敌)。
第二场:洛根·斯皮尔斯(白)对切斯·博特·DNN-6 层-损失-1.06(黑)
洛根斯皮尔斯(白)诉国际象棋机器人 DNN-6 层-损失-1.06(黑)。黑棋赢了。完整游戏:https://lichess.org/rh7jL6rL
https://lichess.org/K5OEAa3w
以法国开局,黑棋允许我通过移动 8 占据中心位置,导致白棋的 stockfish 评估为+1.1。有趣的是 Stockfish 想让我站在城堡女王一边,把我的优势推到中间。我有一个王侧易位的习惯,以更安全的方式玩,以避免不熟悉的游戏。在移动中 11 ,黑棋提供了一个女王交易,我接受了这个交易,把女王从棋盘上拿走,减少了可能有利于人工智能的战术机会。我做得很好,直到我在移动 16 时出错。我看不出黑棋可以用它的方形象串我的车并赢得交换。由于移动中的兵推 32 没有导致获胜的机会(即使*衡了车),黑棋逐渐吃掉我的兵,迫使我放弃。
虽然人工智能赢了,但我不知道是计算机变得更好了,还是我的失误让比较变得不公*。解决这个问题的最公*的方法是让人工智能版本互相比赛。
第三场:切斯博特 DNN-6 层-损失-1.06(白)对切斯博特 DNN-4 层-损失-1.29(黑)
象棋机器人 DNN-6 层-损失-1.06(白)对象棋机器人 DNN-4 层-损失-1.29(黑)。白棋赢了。完整游戏:https://lichess.org/es0pajXC
https://lichess.org/es0pajXC
最初我给了 4 层人工智能白色,但它以一个*淡无奇的画结束,所以我尊重颜色的分配。第二场比赛导致了一场令人难以置信的精彩比赛。快节奏的行动开始于第 12 步,主教拿走了 G7 的兵,并分别叉走了 H6 和 H8 的骑士和车。黑棋回应了一个狂野的牺牲,使用了黑方主教,然后是女王检定。白棋冷静地偏转,最终拿到了悬车。在移动中 16 黑棋牺牲了另一个棋子,这次是一个骑士,为了保住对白棋国王的攻击。在防守并掷出自己的皇后检查牌后,白棋自信地检查了黑王的移动 22 。这是非常危险的,因为如果给黑棋自由移动的话,它可以一步就将死!怀特发现了原力交配序列,在一场令人兴奋的将死中获胜,并证明了其较低的训练损失会导致更好的象棋。
分析
分析这些游戏最显著的方面是人工智能感觉有多“像人”。常见的开局,等待失误,以及用疯狂的牺牲来试图卷土重来是在线人类游戏中的标准公*。
我们的方法当然有改进的余地。许多众所周知的技术没有被使用,以保持这个项目的复杂性易于管理,并专注于人工智能部分:
- 移动排序优先搜索“感兴趣的”移动序列
- Endgame Tablebase 用于预先计算的获胜残局位置
- 预计算开口的开口书
- 只搜索 4 层的几十万个位置
- 许多其他人
我们过于简单的模型和训练程序也存在一些缺陷
- 移动计数以位的形式输入到模型中,而不是以浮点数的形式输入
- 模型架构是第一个没有优化的设计
- 学习率和批量大小调度器可以导致较低的总损失
- 象棋位置在数据库中是唯一的,因此更可能是唯一的较后位置在数据集中被过度表示
- 大多数游戏都是业余玩家玩的,高级游戏的搜索空间可能没有得到充分的体现
- 该模型可以被训练更长时间
总的来说,这很有趣!对现有发动机评估的监督训练是一种比自玩和蒙特卡罗树搜索(a la AlphaZero)更快和更经济的权重初始化方法,并且一个可玩的模型可以在几个 GPU 小时内生成。希望你喜欢这篇文章,我期待在评论中看到你的 AI 游戏的链接!
使用 AWS SageMaker 训练您自己的声音生成可变自动编码器
原文:https://towardsdatascience.com/train-your-own-variational-auto-encoder-for-sound-generation-with-aws-sagemaker-1ecb82918695?source=collection_archive---------34-----------------------
在脚本模式下使用 AWS SageMaker 训练您的定制 TensorFlow 模型的简单方法。
经过 10 个小时的训练,我进入了 150 个纪元中的第 22 个,我意识到 3000 wav 文件数据集对于我 5 岁的 MacBook Pro 来说有点难以接受。自由口述数字数据集包含来自 6 个说话者的录音,每个说话者 50 个 8kHz 的数字。wav 格式。当我在跟踪 Valerio Velardo 的关于神经网络 声音生成的优秀视频系列时,我发现自己陷入了一个无休止的训练阶段。目标是训练一个定制的可变自动编码器来生成声音数字。
Pawel Czerwinski 在 Unsplash 上拍摄的照片
FSDD wav 文件的预处理在本地进行,并在中生成 3000 个光谱图的训练数据集。npy 格式(我的 TensorFlow 模型的预期输入格式)。虽然 SageMaker 现在支持各种数据源,如亚马逊 FSx 和亚马逊 EFS ,但我将训练数据集上传到了位于美国东一区(N. Virginia)的 S3 的一个桶中。请注意这一点,因为 SageMaker 需要与您的铲斗在同一区域。
我的源代码由两个文件组成:
- autoencoder.py —自动编码器“ VAE ”类定义:具有镜像编码器/解码器和潜在空间的深度卷积自动编码器。包含所有 TensorFlow 库导入。
- train.py —训练初始化:访问训练数据,实例化模型,定义所有参数(输入形状、滤波器、核、步幅、潜在空间维度和各种超参数)。包含从 autoencoder.py 导入的 VAE 类
这两个文件在本地培训时在我的本地硬盘上协同工作,但是如何转移到云中呢?
与 SageMaker 一起训练
SageMaker 主要提供了 5 种训练模型的方法:
- 内置算法
- 脚本模式
- 码头集装箱
- 市场
- 笔记本实例
在我们的特殊情况下,脚本模式是可行的,因为我们提供了在 TensorFlow 兼容的容器(由 AWS 管理)中执行的源代码。
选择一个基本的 SageMaker 笔记本配置(一个 ml.t2.medium 就可以了),确保附加的 IAM-execution-role 允许访问您的 S3 bucket,并从管理控制台启动实例(与 bucket 在同一区域)。在脚本模式下,注意这个 SageMaker 笔记本实例只用于脚本启动,不用于培训。
我将我的源代码上传到 SageMaker 笔记本实例存储的工作目录中,在那里我还创建了自己的 script.ipynb 来编排培训过程。在这个脚本中,我包含了以下导入:
import sagemaker
from sagemaker.tensorflow import TensorFlow
import boto3
然后,我将所有有用的 SageMaker 变量定义如下:
bucket = 'mytrainingdatabucket'
role = sagemaker.get_execution_role()numpy_train_s3_prefix = f"**{**bucket**}**/spectrograms"
numpy_train_s3_uri = f"s3://**{**numpy_train_s3_prefix**}**"inputs = {'data' : numpy_train_s3_uri}
最重要的是,估算器处理所有端到端的 SageMaker 训练任务。以下是需要特别注意的参数:
- 入口点:你的训练代码的路径(在我的例子中是 train.py )
- source_dir :剩余源代码的路径(依赖、库等)。
- model_dir :指定你的代码将你的算法生成的模型写入容器的预期位置,通常为' opt/ml/model '。在训练结束时,SageMaker 获取它在' opt/ml/model '中找到的任何东西,并将其输出给 S3。
- 去找一个强大的,因为它只会用于训练。
- output_path :保存模型工件和输出文件的 S3 路径。
- script_mode : boolean,在这种情况下选择 True 。
下面是我如何为 AWS 管理的 TensorFlow 兼容容器初始化我的 estimator 实例:
estimator = TensorFlow(entry_point='train.py',
source_dir='.',
model_dir = "/opt/ml/model",
train_instance_type='ml.p2.xlarge',
output_path=f"s3://**{**bucket**}**/output",
train_instance_count=1,
role=sagemaker.get_execution_role(),
framework_version='2.0',
py_version='py3',
script_mode=**True**)
然后,将通过调用估计器上的 fit() 来启动训练,如下所示,但在此之前,我们需要定义下一段中描述的所有环境变量。
estimator.fit(inputs)
环境变量
我在我的 train.py 文件中实现了 parse_args() 函数来收集所有必要的 SageMaker 环境变量,比如路径和超参数:
def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('--epochs', type=int, default=150)
parser.add_argument('--batch_size', type=int, default=64)
parser.add_argument('--learning_rate', type=float, default=0.0005) # data directories
parser.add_argument('--data', type=str,
default=os.environ.get('SM_CHANNEL_DATA')) parser.add_argument('--output', type=str,
default=os.environ.get('SM_CHANNEL_OUTPUT')) parser.add_argument('--train', type=str,
default=os.environ.get('SM_CHANNEL_TRAIN')) parser.add_argument('--model_dir', type=str,
default=os.environ.get('SM_MODEL_DIR')) return parser.parse_known_args()
因此,我可以加载训练数据:
x_train = get_train_data(args.data)
然后我可以实例化 VAE 类,并相应地调用训练方法:
autoencoder = train(x_train, args.learning_rate, args.batch_size, args.epochs)
最后,一旦模型训练完毕,我就可以从 VAE 类中调用 save() 方法来将我的模型工件( parameters.pkl 和 weights.h5 )存储在' opt/ml/model '中。这一步是必不可少的,因为 SageMaker 不会自动保存你的模型,而是简单地获取容器文件夹中的内容。因此,请明确执行此操作:
autoencoder.save(args.model_dir)
就是这样!下面是我的 script.ipynb 的执行快照:
结论
如上所述,培训工作需要大约 2 个小时才能完成,费用大约为。根据我在自由层帐户上的 AWS 计费仪表板,3.20 美元(计算+存储)。
新生成的模型存储在我的“输出/ 文件夹的 S3 桶中,并以 8.4 MBmodel.tar.gz档案的形式出现。下载并解压后,我能够使用 VAE 类的 load() 方法,并成功地做出推理来生成声音。以下是我的模型生成的“零”声音数字的示例:
查看我的 GitHub 资源库这个项目,感谢阅读!
使用随机矩阵的可训练宏观交通建模
原文:https://towardsdatascience.com/trainable-macroscopic-traffic-modeling-using-stochastic-matrices-e5fc4dedf259?source=collection_archive---------24-----------------------
通过用真实世界的数据训练交通模型来获得真实的交通模拟。
图片由大卫·马克从皮克斯拜拍摄
在这篇文章中,我将讨论我如何定义一个交通网络,一个交通模型,以及我如何用我收集的流量数据来训练它。
交通网络可以表示为有向图,道路上的车辆负载可以表示为图边上的负载数值。微观交通模型阐述了单个车辆之间的相互作用,而宏观交通模型则考虑了交通流量。通过定义一个交通模型,将在图上形成一个动态系统,并且可以模拟交通行为。
收集和预处理好的真实世界交通流数据可用于训练交通模型。然后,可以使用该模型来研究交通网络的拓扑薄弱部分,以修改网络来改善较低的拥塞水*。
交通网络
让我们给出我们需要的初步定义。
特殊类型的矩阵可以用来保存图的属性信息。
图形是保存节点间关系信息的对象。图的线图直观地展示了图的边的关系。由于交通网络的动力学,如交通流,考虑了道路之间的关系,我们需要考虑交通网络的线图。
交通网络可以被认为是有向图 G,其中每个节点 r 是一条边,每个交叉点 j 可以被认为是一个节点。
为了获得真实的结果,我们需要关于道路类型和道路长度的信息。然后,我们可以根据这些值为每个图定义一个容量常数。设 H_r 为道路类型, l_r 为道路 r 的道路长度,定义一个函数 λ(H_r) 为道路类型 H_r. 的车道数然后定义 r 的通行能力为 C_r = λ(H_r)l_r 。
容量是一条道路所能承受的最大交通负荷。设每条道路持有一个荷载值 L_r(t)∈[0,C _ r】。此外,道路的拥挤程度被定义为 L_r(t)Cr。
使用 Python 的 osmnx 包,我们能够将真实世界的交通网络导入到网络 x 图中。该软件包从开放街道地图中收集真实的空间信息,并使用它生成一个网络。图书馆给了我们以下信息:名称、长度和道路类型。
对于这篇文章,我选择了伊斯坦布尔的交通网络 Kadikoy。
import osmnx as oxfrom networkx import *# Defining the map boundaries
#Kadikoy kordinatlarinorth, east, south, west = 40.9939, 29.0346, 40.9786, 29.0146# Downloading the map as a graph objectG = ox.graph_from_bbox(north, south, east, west, *network_type* = 'drive')draw(G, *linewidths*=1, *node_color*='w', *node_size*=15, *arrowsize*=5, *pos*=pos)ax = plt.gca() # to get the current axisax.collections[0].set_edgecolor("#000000")
现在,让我们创建这个网络的线图。
L = nx.line_graph(G)draw(L, *linewidths*=1, *node_color*='w', *node_size*=15, *arrowsize*=5, *pos*=pos2)ax = plt.gca() # to get the current axisax.collections[0].set_edgecolor("#000000")
通信模型
在前面的部分中,生成了一个交通网络。要模拟该网络中的流量,需要一个流量模型。我们需要定义一个模型,它可以获得每个节点持有的信息,并给我们结果。通常,流行的宏观模型,如 METANET,不考虑较小的市内道路,而只关注高速公路。
我们将要定义的模型将考虑网络中的每一条道路。这些模型是用随机过程和随机行走的思想来表述的。
设 P 是一个 n×n 概率转移矩阵,设 π(t) 是一个 n 维非负向量,它保存在时间 t 节点上的初始负载分布。那么下一个时间步的分布就是 π(t+ 1) =(π(t)T)P,*其中 *xT 定义 x 的转置。
我们有两个假设。第一个假设是,在每个时间步,每个交通灯是同步的,在每个路口,在每个时间步变绿一次。第二个假设是总负载不变。第二个假设是临时假设,稍后将引入基于时间的负载控制机制。
通常,最常见的随机游走是根据度数定义的。
设 G 为图,设 A 为邻接矩阵,设 D 为图的度矩阵。基于度的概率转移矩阵定义为 *P = D^(-1)A,*其中 P_(i,j)=A_(i,j)/deg(i)。
但是这个模型不考虑道路的通行能力,所以我们不能模拟交通的级联效应。
为了防止这种情况,并能够优化模型,稍后,公路关系矩阵 M 出现,其中 M(H_i,H_j)是从公路类型为 H _ I 的公路到公路类型为 H_j 的公路的流量常数。假设有一个从道路 r 到 p 的流量,如果λ(Hr)> λ(Hp)随着汽车的行驶,道路变得更窄,我们就面临一个瓶颈。瓶颈使汽车在不减速的情况下更难继续行驶,因为车道的数量减少了,汽车不得不变道,这导致了机动性的整体下降。随着道路类型的差异越来越大,流量变得越来越慢。所以,M(H _ r,H_p)应该很小。然而,如果λ(Hr)< λ(Hp),那么流量不会减慢,因为车道实际上是在增加的,汽车不必为了变道而减速。道路 r 上的载荷计算如下
概率转移矩阵是:
优化模型
我们希望模型以现实的方式行动。在建模阶段,模型被赋予一个道路型流量常数。在本节中,我们将使用这些参数优化模型。从这里,一家使用他们的 API 提供交通流量数据的导航公司,以 20 分钟的间隔收集 1080 步的真实世界交通数据。收集的数据用于优化模型。对未处理的数据进行处理,使其成为保持 Eminonu 地区主要道路拥堵程度的时间序列数据。之所以选择 Eminonu,而不是 Kadikoy,是因为它是这里最大的地区,有许多不同的道路类型。
设 D_i(t)表示时间 t 时道路 I 的真实世界拥堵水*,设所选成本函数为 MSE。设 N 是数据实例的数量,K 是道路的数量。因为 L(t)是递归函数,随着 t→ ∞,求导会越来越难。此外,考虑到现实世界的数据取决于实时性,这意味着在一天中的某些时候,流量水*会更高或更低。为了训练模型,在每个时间步 t+1,取 L_i(t)为 D_i(t),并对 L_i(t+ 1)进行优化,因此 L_i(t)被视为常数而不是函数,优化过程变得更容易。
假设时间序列数据为:
D(0),D(1),D(2),D(3),D(4),D(5),D(6)…
数据将被分组为(X,Y ),其中 X 是特征,Y 是预测值。将时间序列数据分组如下:
(D(0),D(1)),(D(1),D(2)),(D(2),D(3)),…
我们试图找到 8×8 M 矩阵,它给出了在总模拟时间τ上求和的成本函数的最小值。所以每 64 个变量都应该进行优化。对于时间 t+ 1,我们希望优化以下成本函数:
在哪里,
对于每个 M_,其中 a,b ∈[1,8],用梯度下降法进行优化。
现在,当我们求梯度时,我们需要计算每个时间步的最小值函数,并对最小值部分求导。因此我们有下面的梯度,
优化进行了 30 个时期。在每个时期,我们获取不同的矩阵 M。这 30 个不同的 M 矩阵用于预测下一个时间步中的流量负载值。
左图显示了前 10 代 M 矩阵的不同成本值,右图显示了后 10 代的成本值。对于这两个图,线形图是训练前的成本值,这些值是我直观给出的,所以理想的结果是成本值保持在线形图以下。可以观察到,在用 20 个数据对/数据实例训练模型 30 个时期之后,低于线图的成本值的数量增加了。
因此,我们可以看到,在预测下一次迭代中的负载分布时,经过训练的模型比未经训练的模型表现得更好。目前,正在以更短的时间间隔收集另一个真实世界的数据,以更高的精度训练模型。
训练 CNN 在没有任何人工注释图像的情况下检测停车标志
原文:https://towardsdatascience.com/training-a-cnn-to-detect-stop-signs-without-any-manually-annotated-images-715a91954006?source=collection_archive---------25-----------------------
实践教程
额外游戏:这篇文章中有一句话是故意错误的。你能找到它吗?
一个停车标志。图片由作者提供。
注释大型影像数据集是一项劳动密集型工作,因此成本高昂。在某些情况下,只有大公司才有资源来构建数据集,这将使他们的卷积神经网络(CNN)在给定的应用中具有优势。
解决这个问题的一个可能方法是图像合成。当 object 类如此简单,以至于我们可以以编程方式创建逼真的示例时,我们可以生成带有相应目标热图的图像。这些对将用作完全卷积神经网络(FCNN)的训练观测值,该网络将图像作为输入,并预测相应的热图。
当你看到一个红色的八角形时,必须停下来
作为一个简单的例子,我们将为停止标志的单色图像创建一个生成器,这是自动驾驶汽车必须处理的许多信号之一。忽略颜色信息会给训练带来额外的困难,但是如果我们成功了,得到的 FCNN 就不太可能被例如圆形的红斑所混淆。
你可以在这里找到本文中使用的代码。
发生器从随机背景图像开始。它将绘制一个内部带有“停止”字样的八边形。添加噪声、模糊和应用仿射变换将完成在随机背景上渲染合理逼真的停车标志图像的过程。在某些情况下,生成器会绘制一个额外的随机均匀八边形。这个八角形模拟了停车标志的背面,FCNN 人必须学会忽略它。生成器有时还会在八边形之外写“停止”这个词。通过仿射变换变形的八边形表面将成为 FCNN 需要学习生成的目标热图。
左图:随机背景图片。中心:合成图像。右图:对应的热图。图片由作者提供。
使用合成图像的主要优点之一是实际上无限的训练数据集。即使可用的背景图像的数量是有限的,各种变换、随机位置和绘制对象的比例也向我们保证了神经网络在训练期间将不会两次看到相同的图像。
训练图像是按需合成的,但是验证图像只生成一次并被保留,以提供从一个时期到另一个时期的损失的公*比较。
验证图像的样本。图片由作者提供。从 Picsum 中获得随机背景。
FCNN 建筑
我选择的架构(在令人尴尬的多次失败迭代之后)是三个卷积层的堆叠,后面是一系列三个转置卷积。
FCNN 建筑。图片由作者提供。
这个 FCNN 架构的实现接受一列输入张量,并返回每个张量输出的像素最大值作为其最终输出。这项功能的动机是观察到训练有素的 FCNN 倾向于对应用于输入图像的模糊水*非常敏感。在某些情况下,当输入图像没有模糊时,输出热图不会突出显示停车标志。当输入图像有点模糊时,热图会突出显示停车标志。在某些情况下,情况正好相反:当输入图像没有模糊时,停止标志会被检测到,但当输入图像模糊时,停止标志不会被检测到。这种观察导致提交越来越模糊的图像,并保留每个输出的像素最大值。这种机制被集成到神经网络的 forward()函数的定义中。
通过提供两个图像的列表来训练 FCNN:未模糊的图像和用 3×3 内核模糊的图像。
培养
使用二元交叉熵损失似乎对这类任务很有效。
作为时代函数的训练和验证损失。图片由作者提供。
真实场景图像的热图(编码在红色通道中)的演变,如 FCNN 正在训练。图片由作者提供。
测试训练有素的 FCNN
在使用合成图像进行训练之后,我们可以在真实场景图像上进行测试。这些图像中的一些包括停止标志,而另一些没有。一些场景以停止标志的背面为特色,这不应该激活热图。
神经网络的输出,用于真实场景图像(512 x 512)。红色通道对热图进行编码。图片由作者提供。
用于训练的合成图像的大小是 256 x 256,但是根据推断,当真实场景图像在被传递到 FCNN 之前被调整到 512 x 512 时,结果是最好的。
左图:调整为 256 x 256 后真实场景的热图(红色通道中)。右图:调整为 512 x 512 后同一图像的热图。热图被调整回原始图像的大小以便显示。图片由作者提供。
我们观察到,我们没有获得假阳性(即,当场景不包括停车标志时,热图不会显示高强度的区域),但发生了一些假阴性(即,错过了一些停车标志)。用合成图像观察不到这种现象。
经过训练的神经网络的输出,用于验证合成图像(256 x 256)。红色通道对热图进行编码。图片由作者提供。从 Picsum 中获得随机背景。
遗漏病例研究
对于神经网络,故障原因的识别通常是困难的。我们可以做的一件事是改变有问题的输入图像,并观察输出是否有所改善。
多重模糊
两个未能生成良好热图的案例被提交了多种模糊尺寸:1x1(即无模糊),高达 9x9:
模糊输入图像的效果,从 1x1(左上)到 9x9(右下)。当模糊度为 6x6(中间偏右)时,此特定图像会产生更好的效果。作者图片
模糊输入图像的效果,从 1x1(左上)到 9x9(右下)。当模糊度为 5x5(中间)或 6x6(中间偏右)时,此特定图像会产生更好的效果。图片由作者提供。
调整大小
使用全卷积神经网络可以将输入图像的大小调整为各种分辨率,因为它们的架构不包括输入和输出维度固定的全连接层。这种灵活性允许我们在通过 FCNN 之前选择应用于原始图像的调整尺寸。在通过神经网络之前,同样的有问题的图像被调整到不同的大小。
在通过 FCNN 之前,将图像调整到(128,128)(左)、(256,256)、(512,512)和(1024,1024)(右)的效果。在这种情况下,(256,256)给出了更好的结果。图片由作者提供。
在通过 FCNN 之前,将图像调整到(128,128)(左)、(256,256)、(512,512)和(1024,1024)(右)的效果。在这种情况下,这些尺寸都没有给出好的结果。图片由作者提供。
印刷文字的重要性
对于训练图像,单词“停止”出现在八边形的中心。我们可以测试这个词的出现是否是一个必要的特征。下图显示了提交不带任何文本的八边形合成图像的结果。
八边形内没有任何文本的合成图像的结果。图片由作者提供。
对于八角形表面的大部分,FCNN 没有激活。我们可以得出结论,文本的存在是必要的。
下图显示了打印文本是从牛津英语词典中随机选择的单词时的热图。
合成图像的结果,带有“停止”以外的单词。图片由作者提供。
结论
我们在随机背景上生成了停车标志的合成图像。这些图像用于训练一个完全卷积的神经网络,以生成停车标志八角形的热图。
最初观察到 FCNN 对输入图像中的模糊程度非常敏感,这一点通过对有问题的案例的分析得到了加强。虽然 FCNN 训练使用大小为 1 和 3 的模糊图像,但这对于一些真实场景输入来说是不够的。我会推荐模糊大小为[1,3,5,7]的训练。
左图:模糊尺寸为[1,3]时的结果。右图:模糊尺寸为[1,3,5,7]时的结果。图片由作者提供。
至于调整大小,在两个被研究的丢失物体的案例中,只有一个在特定维度上有所改善,而另一个没有改善。出于这个原因,我建议将调整大小保持为(512,512),这样总体来说效果不错。
最后,经过训练的 FCNN 似乎对写在八角形内部的单词不敏感,只要在深色背景上至少有一个浅色字母。虽然这个功能没有被明确地设计出来,但是它很有用,尤其是如果你像我一样,生活在一个停车标志可以显示“停止”、“arrêT”或“arrêT STOP”的地方。
这个项目既有挑战性又有趣!用简单的编程技巧就能弥补昂贵的手动注释图像数据集的不足,这是一种极大的满足感。让我知道你的想法!
[1]模糊是用相邻像素值的加权*均值替换图像中每个像素值的过程。在典型的场景中,邻域将是围绕中心像素的小正方形(例如:5×5),并且加权将是均匀的。在本文的剩余部分中,“N 的模糊大小”是指围绕中心像素的 N×N 个像素的邻域上的均匀*均值。
[2]通过利用从 https://picsum.photos 下载的随机背景图像来合成训练和验证图像。根据 Picsum 网站,这些图片是从https://unsplash.com/获得的
为意大利语培训上下文拼写检查器
原文:https://towardsdatascience.com/training-a-contextual-spell-checker-for-italian-language-66dda528e4bf?source=collection_archive---------11-----------------------
图片鸣谢:Unsplash。
介绍
在之前的帖子中,我们已经介绍了拼写检查,以及在生成更正时需要考虑上下文线索。我们还讨论了 Spark-NLP 库中用于拼写检查的预训练模型的可用性。虽然,预先训练的模型在许多情况下都很方便,但有时你需要针对特定的领域,如金融或特定的语言,如德语。在这篇文章中,我们将从头开始探索训练一个上下文拼写检查器。
我们将深入研究创建上下文拼写检查模型所涉及的训练过程和数据建模。我们将使用通用意大利语作为我们的目标语言,但是这些步骤可以应用于您感兴趣的任何其他领域或语言。
我们将使用PaisàCorpus作为我们的训练数据集,我们将添加自定义的单词类来处理像地点和名称这样的事情;最后,我们将看到如何使用 GPU 和 Spark-NLP 来加速训练。我们开始吧!。
本文的代码
您可以在下面的笔记本中找到本文的完整代码以及一些附加示例,
训练上下文拼写检查器——意大利语。
数据准备
您将从这个 URL 下载语料库文件。接下来,我们将应用一些清理原始文本,以消除一些噪音。
让我们从添加一些基本导入开始,
from sparknlp.annotator import *
from sparknlp.common import *
from sparknlp.base import *
import sparknlp
spark = sparknlp.start()
接下来让我们加载语料库数据。
from pyspark.sql.functions import *
paisaCorpusPath = “/path/to/paisa.raw.utf8”# do some brief DS exploration, and preparation to get clean text
df = spark.read.text(paisaCorpusPath)
df = df.filter(~col(‘value’).contains(‘</text’)).\
filter(~col(‘value’).contains(‘<text’)).\
filter(~col(‘value’).startswith(‘#’)).\
limit(10000)df.show(truncate=False)
这就是我们得到的,
+--------------------+
| value|
+--------------------+
|Davide Guglielmin...|
|Avete partecipato...|
|Otto mesi di rita...|
|Il prezzo dei big...|
|Dopo la “Shopping...|
|Il nome è tutto u...|
|Ovvero? Ovvero do...|
|Il patto ha lo sc...|
|La tre giorni org...|
|Quanto pagate per...|
|Per contro, nell’...|
|Non è poco, ovvia...|
|Dopo una lunga as...|
|La serata sarà un...|
|I primi 4 negozi ...|
|La Chaingang Rota...|
|La Chaingang Rota...|
|Tra le molte rami...|
|Un primo corollar...|
|E' proprio nel di...|
+--------------------+
only showing top 20 rows
我们有 7555997 个段落,每个段落包含几个句子,由于训练不需要带标签的数据,这就是我们所需要的。
基本管道设置
现在我们已经有了良好的数据,我们将设置一个基本的管道来进行处理。这是典型的 Spark-NLP 管道,数据在注释器中作为注释流动。
assembler = DocumentAssembler()\
.setInputCol(“value”)\
.setOutputCol(“document”)\tokenizer = RecursiveTokenizer()\
.setInputCols(“document”)\
.setOutputCol(“token”)\
.setPrefixes([“\””, ““”, “(“, “[“, “\n”, “.”, “l’”, “dell’”, “nell’”, “sull’”, “all’”, “d’”, “un’”])\
.setSuffixes([“\””, “””, “.”, “,”, “?”, “)”, “]”, “!”, “;”, “:”])spellChecker = ContextSpellCheckerApproach().\
setInputCols("token").\
setOutputCol("corrected").\
setLanguageModelClasses(1650).\
setWordMaxDistance(3).\
setEpochs(10).\
addVocabClass('_NAME_', names).\
updateRegexClass('_DATE_', date_regex)
我们从我们的 DocumentAssembler 开始,为它输入我们在上一步中准备好的数据。然后我们继续我们的 RecursiveTokenizer,其中我们设置了一些特殊的选项来处理意大利语的一些细节。
最后,我们有我们的拼写检查。前两个方法调用是管道中连接输入和输出的常用方法。然后,我们在拼写检查器 setLanguageModelClasses()中为语言模型设置了一个依赖于词汇大小的设置,模型将使用它来控制语言模型中的因子分解。
基本上,因式分解背后的思想是,我们不会孤立地对待单词,而是将它们分组,给每个单词分配一个特定的类,以及该类中的一个 id。这有助于加快训练和推理过程中的内部处理。
接下来是 setWordMaxDistance(3),它简单地告诉拼写检查器我们的错误最多在编辑距离 3 处。
历元数是您从神经网络中了解到的典型梯度下降参数,它将由拼写检查器中的神经语言模型使用。
最后但同样重要的是,我们增加了一个特殊的词类,在这个例子中是用来处理名字的。让我们进入更多的细节!。
添加特殊类别
这一节是可选的,它解释了我们在注释器设置代码末尾进行的 addVocabClass()和 addRegexClass()调用。如果您不想添加特殊的类或者您想稍后再来,只需注释掉这两行。
在这一点上,我们有一个相当大的语料库,足以让我们很好地接触到不同风味的意大利语。
尽管如此,除了我们在语料库中看到的,我们可能还想有另一种机制来构建我们的模型词汇表。这就是特殊类发挥作用的地方。
有了这个,我们就可以释放包含在特定数据集中的知识的力量,如名称词典或地名词典。
它们不仅允许我们教会拼写检查器保留一些单词,还可以提出更正建议,而且与主词汇表中的单词不同,一旦模型经过训练,您就可以更新它们。例如,如果在模型被训练之后,您仍然希望能够支持一个新名称,您可以通过更新 names 类来实现,而不需要从头开始重新训练。
当你像我们在这里做的那样从头开始训练拼写检查器时,你会得到两个预定义的特殊类:DATE,和 NUM,分别用于处理日期和数字。您可以覆盖它们,也可以添加更多的类。
按照我们关于名字的例子,我们将在 Spark-NLP 的上下文拼写检查器中添加意大利名字作为一个特殊的类,
import pandas as pd
import io
import requests# Get a list of common Italian names
url=”[https://gist.githubusercontent.com/pdesterlich/2562329/raw/7c09ac44d769539c61df15d5b3c441eaebb77660/nomi_italiani.txt](https://gist.githubusercontent.com/pdesterlich/2562329/raw/7c09ac44d769539c61df15d5b3c441eaebb77660/nomi_italiani.txt)"
s=requests.get(url).content# remove the first couple of lines (which are comments) & capitalize first letter
names = [name[0].upper() + name[1:] for name in s.decode(‘utf-8’).split(‘\n’)[7:]]# visualize
names
这是我们得到的结果(被截断),
['Abaco',
'Abbondanza',
'Abbondanzia',
'Abbondanzio',
'Abbondazio',
'Abbondia',
'Abbondina',
'Abbondio',
'Abdelkrim',
'Abdellah',
'Abdenago',
'Abdon',
'Abdone',
'Abela',
'Abelarda',
'Abelardo',
'Abele',
这就是我们在前面清单中注释器设置期间传递给拼写检查器的名称变量。
如果您关注了我们如何设置注释器,您可能还会注意到,我们使用 updateRegexClass()函数调用为数字配置了第二个特殊的类。
这与为修正候选项添加额外来源的目的是一样的,但是这次是针对日期,所以我们需要传递一个正则表达式来描述我们想要覆盖的日期。
这里我们将集中讨论一种特定的格式,但是您也可以添加自己的格式,
**格式:**日/月/年
正则表达式:
([0–2][0–9]|30|31)\/(01|02|03|04|05|06|07|08|09|10|11|12) \/(19|20)[0–9]{2}
理解我们刚刚创建的正则表达式的幕后发生的事情很重要。首先,我们创建的正则表达式是一个有限的正则表达式,也就是说,它匹配的词汇表或字符串集是有限的。这很重要,因为拼写检查器将枚举正则表达式,并用它创建一个 Levenshtein 自动机。
训练模型
现在我们已经准备好了管道,我们将调用 fit(),并传递我们的数据集。
pipeline = Pipeline(
stages = [
assembler,
tokenizer,
spellChecker
])
model = pipeline.fit(df)
使用 GPU
你会注意到训练过程不是很快。那是因为到目前为止我们只使用了 CPU。我们可以通过用 spark-nlp-gpu 替换 spark-nlp 库来显著加快训练速度。
您几乎不需要做任何更改就可以做到这一点,只需像这样将正确的标志传递给 Spark-NLP start()函数,
sparknlp.start(gpu=True)
玩模型
让我们看看这个模型能做什么!。
lp.annotate(“sonno Glorea ho lasciatth la paterte sul tavolo acanto allu fruttu”)[‘corrected’]['sono',
'Gloria',
'ho',
'lasciato',
'la',
'patente',
'sul',
'tavolo',
'accanto',
'alla',
'frutta']
我们可以看到,模型确实在生成考虑上下文的校正,例如,“allu”被校正为“alla ”,而其他选项如“alle”或“allo”也在离输入单词 1 的相同编辑距离处,然而模型做出了正确的选择。我们还可以看到名字的词汇化有助于模型理解和纠正专有名称“Gloria”。
总的来说,这就是我们从这个模型中所能期待的,当多个相似的、距离相等的候选对象都有可能时,采取正确的选择。该模型可以做出一些更冒险的决定,比如实际替换词汇表中存在的输入单词。
这更多的是语法检查的工作,例如,从语法上来看。尽管如此,如果您想探索您可以在多大程度上扩展这个模型来执行这些修正,在本文的配套笔记本中有更多的例子。
通过模型中心访问模型
虽然这个模型并不完美,但我已经把它上传到了模型中心,并在社区上公开,以防有人觉得有用。您可以通过以下方式访问它,
ContextSpellChecker.pretrained(“italian_spell”, “it”)
你也可以训练你自己的模型,并按照这些步骤与社区分享。
关于标记化的一句话
这一部分是可选的,但是推荐给那些试图为特定语言或领域微调模型的人。
在许多 NLP 任务中,标记化部分是至关重要的,拼写检查也不例外。您将从标记化中获得的单元将非常重要,因为这些单元将定义您的模型检测错误、生成更正以及利用上下文对不同的更正进行排序的级别。
这里,我们使用 RecursiveTokenizer,之所以这样叫是因为它将继续递归地应用它的标记化策略,也就是说,应用到前面的标记化步骤的结果,直到该策略不能再应用为止。
RecursiveTokenizer 中的默认标记化是在空白上分割。为了进一步标记化,您可以指定中缀模式、前缀模式和后缀模式。
中缀模式是可以在标记中间找到的字符,您希望在其上进行拆分。相应地,前缀模式和后缀模式是您想要拆分的字符,它们将分别出现在每个标记的开头和结尾。
您可以在文档中找到这个 RecursiveTokenizer 的更多选项。Spark-NLP 库中也有其他的记号赋予器。
结论
我们已经探索了如何训练我们自己的拼写检查器,如何准备我们的数据和管道,如何为特殊类提供规则,如何使用 GPU,以及如何调整标记化以更好地满足我们的特定需求。
Spark-NLP 库提供了一些合理的默认行为,但是也可以针对特定的领域和用例进行调整。
希望你可以开始训练和分享你自己的模型,在博卡阿尔卢波!!
用 Tez 和 PyTorch 训练多标签情感分类器
原文:https://towardsdatascience.com/training-a-multi-label-emotion-classifier-with-tez-and-pytorch-af04c899a63a?source=collection_archive---------19-----------------------
让您的培训脚本更上一层楼
作者图片
如果您厌倦了在 PyTorch 中重写相同的培训管道样板代码,我发现了一个非常简洁的解决方案,可以让您的生活更加轻松。别担心,这不是一个会改变你做事方式的沉重的库。
它是一个轻量级的包装器,将训练逻辑封装在一个类中。它是基于 PyTorch 之上构建的,虽然是最*才有的,但是我已经测试过了,我认为它确实做到了它所承诺的。
它叫做 Tez ,我们今天将看到它在一个有趣的多标签文本分类问题上的应用。以下是我们将要介绍的内容:
- 使用🤗数据集库,用于加载和操作数据
- 用 Tez 和变形金刚定义培训管道
- 针对多标签分类问题训练一个 SqueezeBert 轻量模型,并在验证和测试数据上达到+0.9 AUC
让我们直接跳进来吧!
***【PS *:***在继续本教程之前,我要向Abhishek tha kur致敬,他为构建 Tez 并使深度学习能够为更大的社区所用付出了努力和精力。
PS** :所有代码以及训练好的模型在我的 Githubrepo上都有。
在 GoEmotion 🧱上构建一个不寻常的情感分类器
您可能熟悉基于二进制(例如 IMDB 电影评论)或多类数据(例如亚马逊产品评论)构建情感分析模型。
我们今天仍将关注情绪分析,但我们会做一些稍微不同的事情。
在搜索 Huggingface 的网站寻找数据集时,我遇到了一个有趣的数据集,叫做 GoEmotions: 它包含了 58k 条精心策划的 Reddit 评论,分为 28 个类别,包括中性类别。
这些数据来自英语,旨在进行多标签分类,用有趣的类别描述社交网络上的人类行为。我不得不尝试这个数据集!
以下是 28 种不同的情绪:
[‘admiration’, ‘amusement’, ‘anger’, ‘annoyance’, ‘approval’, ‘caring’, ‘confusion’, ‘curiosity’, ‘desire’, ‘disappointment’, ‘disapproval’, ‘disgust’, ‘embarrassment’, ‘excitement’, ‘fear’, ‘gratitude’, ‘grief’, ‘joy’, ‘love’, ‘nervousness’, ‘optimism’, ‘pride’, ‘realization’, ‘relief’, ‘remorse’, ‘sadness’, ‘surprise’, ‘neutral’]
我发现这个数据集很有趣,因为它提供了详细情绪的标记数据,如好奇、感激或惊讶,这些情绪很难用典型的数据集来检测。
我也发现这样一个数据集的影响。部署将文本数据分类为这些情绪的模型可以有多种应用:
- 通过对客户评论的精细分析来评估客户行为
- 检测社交媒体上的有害评论或仇恨言论
- 建立一个代理来评估你的文章(电子邮件、报告、博客帖子)的语气
- 用元数据丰富数据集:例如,在通过模型进行分析之后,您可以使用这个模型用标签来补充电影概要
这样的例子不胜枚举。在评论区告诉我你还能想到哪些应用。
1 —设置您的环境💻
要重现本教程,您需要安装 python 3。我会选择 Anaconda ,但是你可以使用任何你想要的软件包管理器。
然后,您必须安装:
- PyTorch (最好是最新版本)
- 🤗transformers :一个库,提供了数千个预训练的模型来执行文本任务,如分类、翻译、100 多种语言的文本生成
- 🤗Datasets :一个轻量级库,为许多公共数据集(包括 GoEmotions)提供一行数据加载器和预处理
- Tez:py torch 的超简单轻量训练器
您还需要scikit-learn
和pandas
来进行通常的数据处理和操作。
你应该准备好了:让我们开始编码吧!
同样的老进口先:
2-从获取数据🤗数据集
数据可以很容易地从🤗数据集库,在训练中提取,验证和测试分割并转换为熊猫数据帧。
下面先来看一下数据:每个评论都有一个对应的 id 列表,这些 id 映射到 28 种情绪中的一种。
作者图片
将每个标签转换为原始值,我们可以获得更全面的视图。
为了将数据正确地输入到分类器中,我们需要将标签转换成一个热点向量。
作者图片
快速查看目标在训练、验证和测试之间的分布表明,它遵循相同的模式。(id 27 对应于中性情绪,该中性情绪恰好在 30%的数据中被标记)
作者图片
在训练一个模型之前,让我们先快速浏览一些根据他们的情绪取样的评论:
钦佩
Wow, your posting history is a real... interesting ride.
---
I've never heard the insult 'Galaxy-Brain' before, but it's a wonderful! I'm gonna have to use it more often.
---
That or spot up shooting. I like the confidence though, he’s not scared to expand his game.
---
Congratulations!! Colorado is an amazing place! I just moved away a year ago and miss it terribly :) Best of luck to you!
---
Your artwork is amazing.
---
游乐
A stork bite your baby?!?! *kidding*
---
I like how because it’s on topic you assume everyone involved is making it their entire being. Lmao.
---
It's funny cause you say socialists have an "ignorance of economics" while posting on an anarcho-capitalist sub :) I think you clearly fundamentally misunderstand socialism.
---
Oh hahaha, is it a reputable vendor?
---
This just made my day! Thanks for the laugh!!
---
愤怒
[NAME], don't f**king front the pass if your help defender is [NAME] he will not help you
---
I will kill you all
---
How aren’t you in f**king school
---
I hate betting unders.
---
How dare you disrespect [NAME].
---
关爱
Yes. One of her fingers is getting a sore on it and there’s concern it may push her into needing braces.
---
Most important!!! ALWAYS AIM THE HEAD! [NAME] arrows are pretty fat woodsticks, so keep aiming on the head on long distance. Thats it
---
special for you my dude :)
---
you did drug her though, and assault her by undressing her and taking her photo. you committed multiple crimes. you need professional help.
---
Sure, they can help nurse [NAME] back to health.
---
3-定义 PyTorch 数据集🗂
这不会改变:您仍然需要定义如何加载和预处理数据。
我们将在类的构造函数中定义记号赋予器。每次访问样本时都会调用标记器,将文本转换成标记 id 和注意掩码。
令牌 id 和注意力屏蔽稍后将被提供给模型以生成预测。
- 令牌 id 是令牌索引:它们只是构建将被模型用作输入的序列的令牌的数字表示。
- 注意掩码是一个可选参数,在将序列批处理在一起时使用。该参数向模型指示哪些令牌应该被关注,哪些不应该被关注。
请注意:
- 我们使用了一个 SqueezeBertTokenizer,因为我们将使用的模型是一个 SqueezeBert(更多细节见下文)
- 最大长度是 35,因为它对应于注释的最大长度
4——奇迹发生的地方:定义⚡️模式
使用 Tez 时,只需将代码定义为从 tez.Model 继承的类。
这个类实现了你必须重写的特殊方法。
填写每个方法都相当容易。让我们一个一个来做:
构造函数 init 将定义我们将使用的主干模型。在尝试了功能强大但非常大的型号,如Bert-base-unc cased和 roberta-base 后,我决定选择 SqueezeBERT ,它比 Bert-base-unc cased 快 4.3 倍,但性能相同。剩下的参数都很标准:dropout layer,带有类的数量和训练步骤的数量的输出层。
关于 fetch_optimizer 和 fetch_scheduler 方法,我使用了我在 repo 中找到的例子。如果这些设置对您不起作用,请随意尝试其他设置
损失:由于我们正在处理多标签分类,我们将在每个输出神经元使用二进制交叉熵。这对应于 PyTorch 中的 BCEWithLogitsLoss。
monitor_metrics :关于指标,我们可以分别计算每个目标的 F1 或 AUC 分数,但由于这会导致显示大量指标,所以我只选择了微 AUC。这里的技巧是在一维向量中展开目标和输出的批次,并计算它们之间的 AUC。由于目标是相互独立的,这非常有意义。
forward: 这是我们定义模型如何对输入数据执行正向传递的地方。这个方法应该返回一个由输出、损失和度量组成的元组。
5 —开始培训⏱
我们快到了!现在我们开始训练。如果您熟悉 Keras API,这看起来非常相似:训练模型是一行程序。
Tez 还提供了回调,允许您在模型训练时引入一些功能。我们将使用其中的两个:
- TensorBoardLogger 在 Tensorboard 中记录训练和验证指标
- 提前停止检查最佳模型并过早停止训练
嘭!在短短两个时期内,该模型达到了惊人的 0.922 AUC 分数或验证数据。
作者图片
在 8 个时期的训练后,模型在训练数据上达到 0.97 AUC,在验证数据上达到 0.95。
现在让我们看看模型在测试数据上的得分,并评估它在每个类中的表现。
作者图片
很神奇吧?该模型在除类别 21(对应于 pride )之外的所有类别上都有+0.8 的 AUC 分数。
在一些自由文本上测试模型
让我们在一些自由文本上测试这个模型。(你会在我的回购上找到 score_sentence 的实现)
**score_sentence("i miss my friends")** #sadness 0.863369
#disappointment 0.20503707
#neutral 0.05794677
#remorse 0.02818036
#annoyance 0.023128381 **score_sentence("i miss my friends")** #sadness 0.863369
#disappointment 0.20503707
#neutral 0.05794677
#remorse 0.02818036
#annoyance 0.023128381**score_sentence("you might have a point, but i strongly disagree with you")** #disapproval 0.77016926
#annoyance 0.11454596
#approval 0.08423975
#disappointment 0.04763091
#disgust 0.04497903**score_sentence("i'm feeling very confident about this situation") ** #optimism 0.456496
#approval 0.43606034
#admiration 0.1233574
#caring 0.096342765
#realization 0.07383881**score_sentence("try to be safe my friend")** #caring 0.73572147
#optimism 0.0856328
#neutral 0.071999945
#sadness 0.06158314
#approval 0.038069934
结论和未来工作🔜
本教程提供了一个机会,在一个多标签数据集上应用一个名为 SqueezeBert 的最先进的语言模型,该数据集包含 50K 条评论和 28 个类别。
使用 Tez 非常有效地组织了培训渠道,同时保留了很大程度的定制化。在几行代码之后,经过训练的模型在测试数据上达到了惊人的 0.95 AUC 分数。
但是旅程并没有到此为止:现在是时候将模型部署到互联网上,以便其他人可以通过 API 端点与之交互:如果您对这个主题感兴趣,可以看看我以前的文章中的一篇,在那里我使用 AWS Lambda 在无服务器架构上部署了一个生成模型。
感谢阅读!如果你有问题,请不要犹豫,尽管来找我。
如果你对代码感兴趣,你可以在我的回购上找到。
如果你喜欢 Tez 你可以查看一下这里!
训练蛇游戏人工智能:文献综述
原文:https://towardsdatascience.com/training-a-snake-game-ai-a-literature-review-1cdddcd1862f?source=collection_archive---------7-----------------------
方法综述,从非最大似然技术到遗传算法到深度强化学习
维多利亚博物馆在 Unsplash 拍摄的照片
0.介绍
你可能玩过,或者至少看过,蛇的游戏。玩家通过按箭头键控制一条蛇,蛇必须在屏幕上移动,吃苹果。每吃一个苹果,尾巴上的蛇就长一个单位。目标是在不碰到墙或蛇不断增长的尾巴的情况下吃尽可能多的苹果。
构建一个人工智能代理来玩 Snake 是一个经典的编程挑战,YouTube 上的许多视频显示了使用广泛技术的各种尝试。在本文中,我回顾了各种方法的优缺点,并提供了原始资料的链接。广义地说,人工智能蛇智能体的方法属于三类之一:非最大似然方法,遗传算法和强化学习。从这些主题中可以学到很多东西,所以让我们开始吧!
1.非 ML 技术
蛇的游戏实际上有一个微不足道的,无与伦比的解决方案。创建一个循环路径,该路径穿过棋盘上的每个方格,但不与自身交叉(这被称为哈密顿循环),然后继续沿着这个循环路径,直到蛇头与整个路径一样长。这样每次都会奏效,但是很无聊,也浪费了很多招式。在一个 NxN 网格中,大约需要 N 个苹果才能长出一条足够长的尾巴来填满棋盘。如果苹果随机出现,我们预计蛇将需要穿过一半当前开放的方块才能从当前位置到达苹果,或者在游戏开始时大约 N /2 步。由于这个数字随着蛇变长而减少,我们预计*均来说,蛇将需要~N⁴/4 移动来击败使用这种策略的游戏。对于 20x20 的棋盘来说,这大约是 40,000 步。
通过棋盘上所有点的哈密尔顿圈。如果蛇只是停留在这个循环上,那就保证赢。图片由作者基于谷歌 Snake 截图(合理使用)。
我在互联网上找到的几种方法本质上只是对这种幼稚的第一种方法的优化,找到聪明的方法来缩短周期而不困住蛇,这样就可以用更少的动作够到苹果。这包括动态地切割和重切哈密尔顿循环以快速到达苹果。有一种方法甚至在一部旧的诺基亚手机上实现了这一点!玩贪吃蛇还有其他非 ML 的技巧,比如使用 A*算法寻找食物的最短路径,但是不像哈密尔顿循环方法,这不能保证打败游戏。
优点:保证最终击败游戏。
**缺点:**不涉及机器学习——算法必须手工编码。需要对图论有所了解。对于大型游戏板可能会很慢。
下面的例子来自 YouTube 上的 AlphaPhoenix。
视频来源:AlphaPhoenix (YouTube)。
2.遗传算法
遗传算法是解决这类问题的另一种流行方法。这种方法是模仿生物进化和自然选择的。机器学习模型(例如,可以是神经网络,但不是必须的)将感知输入映射到动作输出。输入可以是蛇在四个主要方向(上、下、左、右)到障碍物的距离。输出将是类似左转或右转的动作。模型的每个实例对应于自然选择类比中的一个有机体,而模型的参数对应于有机体的基因。
首先,一组随机模型(例如,具有随机权重的神经网络)在环境中被初始化并被释放。一旦所有的蛇(即模型)死亡,一个适应度函数从给定的一代中选择最好的个体。在蛇的情况下,适应度函数将只挑选得分最高的蛇。然后,通过添加随机突变(例如,随机调整网络权重),从最佳个体中培育出新一代。这些突变有些会造成伤害,有些不会有任何影响,有些是有益的。随着时间的推移,进化的压力会选择越来越好的模型。要通过遗传算法来体验和可视化学习,请看 Keiwan 的这个工具。
**优点:**概念简单易懂。一旦模型被训练,预测下一步行动是很快的。
**缺点:**收敛慢,因为突变是随机的。性能取决于模型可用的输入。如果输入仅仅描述了在蛇的附*是否有障碍物,那么蛇不会意识到“大局”,并且容易被自己的尾巴困住。
下面的例子来自 Code Bullet,而 Greer Viau 的另一个例子也可以在 YouTube 上找到。
视频来源:代码子弹(YouTube)
3.强化学习
强化学习是人工智能的一个快速发展和令人兴奋的领域。在一个非常基础的层面上,强化学习包括一个代理、一个环境、代理可以采取的一组动作****,以及一个奖励函数,奖励代理的好动作或者惩罚代理的坏动作。当代理探索环境时,它更新它的参数以最大化它自己的期望回报。在蛇的情况下,代理人显然是蛇。环境是 NxN 板(根据食物和蛇的位置,该环境有许多可能的状态)。可能的行动是左转、右转和直行。
深度强化学习(DRL)将强化学习的上述思想与深度神经网络相结合。DRL 最*被用来建造超人的[国际象棋和围棋系统](http://Mastering Atari, Go, Chess and Shogi by Planning with aLearned Model),学习只用屏幕上的像素作为输入来玩雅达利游戏,以及控制机器人。
强化学习示意图。来源:维基百科(公共领域)。https://en . Wikipedia . org/wiki/reinforce _ learning #/media/File:Reinforcement _ learning _ diagram . SVG
深度 Q 学习是 DRL 的一种特殊类型。虽然一开始有点难以理解,但其背后的推理极其优雅。神经网络学习“Q 函数”,它将当前的环境状态作为输入,并输出一个包含每个可能行为的预期回报的向量。然后代理可以选择最大化 Q 函数的动作。基于该动作,游戏然后将环境更新到新的状态并分配奖励(例如,吃苹果+10,撞墙-10)。在训练开始时,Q 函数只是由一个随机初始化的神经网络来*似。现在,你可能会问:为了产生损失并更新权重,我们将输出与什么进行比较?
这就是**贝尔曼方程 的用武之地。该等式用于提供 Q 的*似值,以将神经网络引导到正确的方向。随着网络的改进,贝尔曼方程的输出也会改进。至关重要的是,在 Q 函数的定义中有递归(这是我在程序中使用的 Bellman 变体):**
Q(state, action) =
reward(state, action) + discount * max(Q(next_state, actions))
因此,Q 函数被递归定义为这步棋 *的奖励加上下一步棋的最佳可能 Q 函数* 。该项将扩展到下一个奖励加上下一个最佳行动的 Q 函数,以此类推。随着训练的进行,这个 Q 函数(有希望)接*给定移动的真实预期未来回报。(请注意折扣系数的存在,它给予即时回报比预期更大的权重,但不确定未来的回报)。
观看 Snake AI 使用深度 Q-Learning 训练自己的酷之处在于,你可以看到它的探索和利用的过程,现场发生。在一些游戏中,蛇走了 5 步就死了。这一开始可能会令人失望,但请记住,这将招致惩罚,网络将自我更新,以避免将来出现类似的举动。在一些游戏中,蛇会存活很长时间,并聚集一条长尾巴,获得大量奖励。无论哪种方式,这些动作都是积极或消极的强化来教会蛇如何在未来玩得更好。
为了了解更多关于 Q-learning 的知识,我强烈推荐计算机科学家在 YouTube 上的介绍视频。我还推荐 Lex Fridman 的麻省理工学院强化学习讲座,也可以在 YouTube 上看到。
优点:这是一个非常酷又优雅的概念。RL 也可以应用于许多其他任务,除了建立环境和奖励系统之外,不需要监督。根据我的经验,它比遗传算法收敛得更快,因为它可以利用梯度下降而不是随机变异。
****缺点:一开始有点挠头去理解。与遗传算法一样,模型的性能取决于网络可用的输入,输入越多意味着模型参数越多,这意味着训练时间越长。
下面的视频是 Python 工程师在 YouTube 上制作的惊人的** 4 部分教程的第 1 部分,我强烈推荐。相应的代码可以在 GitHub 上找到。**
视频来源:Python 工程师(YouTube)。
结论
最好的学习方法是边做边学。跟随上面链接的教程/解释并实现我自己的 Snake AI 教会了我更多关于手边主题的东西,这是任何数量的阅读或观看都无法做到的。我鼓励你自己尝试一下,并考虑将这些方法应用到不同的游戏中,例如 Pong、Asteroids 或 Breakout。感谢阅读!
参考
[1]哈密顿路径,https://en.wikipedia.org/wiki/Hamiltonian_path
[2]格里尔·维亚乌,神经网络学会玩蛇,https://www.youtube.com/watch?v=zIkBYwdkuTk
[3]贝尔曼方程,https://en.wikipedia.org/wiki/Bellman_equation
[4]进化论由基万著,https://keiwan.itch.io/evolution
[5] 通过学习模型规划掌握雅达利、围棋、国际象棋和日本象棋、https://arxiv.org/pdf/1911.08265.pdf
【Python 工程师,教 AI 打蛇,https://www.youtube.com/watch?v=PJl4iabBEz0&t = 3s
[7]代码子弹, AI 利用遗传算法和深度学习学习打蛇,https://www.youtube.com/watch?v=3bhP7zulFfY&t = 18s
机器人控制在人类环境中使用深度强化学习,https://ieeexplore.ieee.org/document/8961517
[9]莱克斯·弗里德曼,麻省理工学院 6。S091:深度强化学习介绍(Deep RL) ,https://www.youtube.com/watch?v=zR11FLZ-O9M&t = 3036s
在 Google Colab 中训练 AlphaZero
原文:https://towardsdatascience.com/training-alphazero-in-google-colab-cc2f1d6bd0ba?source=collection_archive---------25-----------------------
借助朱莉娅的力量在短短 5 小时内
训练如此之快,你甚至不会意识到它已经打败了你(图片:杰克·吉文斯, Unsplash
随着 Kaggle 对强化学习(RL)的推进,我一直在深入研究 RL 算法,同时研究哪些算法可以实际训练(我们并不都有一大群 GPU!).在这篇文章中,我讨论了如何使用 Google 的在线笔记本系统 Collaboratory,在不到 4 小时的时间内训练一个代理人玩人类级别的 connect four。
这篇文章是完全可复制的,你可以在这里找到笔记本,训练你自己的代理人,亲眼看看 AlphaZero + Colab + Julia 的力量是多么惊人!
AlphaZero 谷歌合作实验室笔记本链接
向 Alphazero.jl 的所有者以及那些努力让 Julia 起床并在 Google Colab 中运行的人们大声疾呼,这一切才成为可能。
背景
在深入研究之前,先了解一些关键组件的背景知识,如果您对此不感兴趣,请跳到下一部分。
阿尔法零
AlphaZero 是 Deepmind 在 2017 年首次分享的强化学习程序。它能够玩围棋、日本兵棋和国际象棋,这三种独特的复杂策略游戏。它完全通过自我游戏来学习如何做到这一点,当它发现和开发策略时,不断地与自己玩游戏。它是世界著名的 AlphaGo 的继任者,AlphaGo 作为第一个在围棋比赛中击败人类大师的系统而成为头条新闻。
该算法的一大卖点是它可以被训练的速度,Deepmind 报告说,在训练的一天内就达到了超人的水*。当然,这是在一台超级计算机上训练出来的,但是我们要用少得多的东西来管理。
谷歌合作实验室
本文使用的 Google Collaboratory 笔记本——眼熟吗?(作者创作)
想象一个 Jupyter 笔记本,现在想象你不需要设置任何东西,你不需要担心资源,你做的任何工作都可以在你的设备上和其他人即时共享——这就是 Google Collaboratory。这是一项基于云的服务,它复制了我们喜爱的 Jupyter 笔记本电脑,其工作方式与常规桌面安装相同。
这里的主要好处是,您不再受到您个人设置的计算资源的限制。您可以在云中运行这些笔记本电脑的多个实例,特别是对于我们的用例,您甚至可以使用 GPU 资源!
朱莉娅
Julia 是一种灵活的动态语言(易于使用),适用于科学和数值计算(不慢),其性能可与传统的静态类型语言相媲美( Julia Docs )。
茱莉亚于 2012 年推出,从那以后知名度慢慢增长。它在投资公司的时间序列分析和保险业的风险建模中得到了应用。最值得注意的是,纽约美联储银行使用 Julia 制作美国经济模型,并指出该语言使模型估计比之前的 MATLAB 实现“快大约 10 倍”(维基百科)。
由于其高性能的能力,它对 ML 项目特别有用,允许网络训练比在 Python 中本地运行快得多。
连接四个
Connect Four(也有许多其他名字,我最喜欢的名字是 Gravitrips )是一款双人游戏,玩家选择一种颜色,然后轮流将彩色圆盘投入 7x6 的格子中。碎片垂直下落,占据塔内最低的可用空间。游戏的目标是第一个形成自己的四个圆盘的水*线、垂直线或对角线。
Connect Four 实际上是在 1995 年解决的,这意味着我们知道如果第一个玩家采取正确的行动,他们总是能赢(完美的行动需要 41 步),但要在我们的大脑中存储所有可能的 5 万亿步并不容易,所以我们改为使用一些策略来解决游戏,导致有趣的游戏方式,使游戏在发布时受到欢迎。
连接四个游戏(维基共享)
现在,所有的部分都固定好了(看到我做了什么吗?),我们继续任务吧。
任务
概括一下,在本文中,我们将实现 AlphaZero 来玩简单的连接四个的游戏。我们将使用 Julia 作为基础语言,利用其惊人的速度,在云中这样做,使用 Colab 笔记本在云中训练。
提醒如果你想跟进: AlphaZero 谷歌合作实验室笔记本链接
第一步,设置环境。Google Colab 通常用于 Python,但实际上也可以在其中设置不同的环境。为了快速训练我们的神经网络,我们将安装 Julia 并默认启用 IJulia 运行时。在附带的笔记本中,这意味着运行第一个单元,然后使用启用的新环境进行刷新。
下一步是从 git 安装 Alphazero 的 Julia 实现。这可以通过运行下一部分来完成。笔记本将连接到 git 并获取该项目的文件。然后我们将把这个包加载到 Julia 中,并确保我们已经安装了所有需要的依赖项。
run(`git clone --branch v0.3.0 [https://github.com/jonathan-laurent/AlphaZero.jl.git`)](https://github.com/jonathan-laurent/AlphaZero.jl.git`))
cd("AlphaZero.jl")
run(`julia --project -e "import Pkg; Pkg.instantiate()"`)
安装好库后,我们就可以开始训练网络了。这可以用另一个简单的一行程序来执行,它启动了一个运行 Alphazero 核心算法的脚本。
run(`julia --project --color=yes scripts/alphazero.jl --game connect-four train`)
这将从列出网络的参数开始,用初始化的参数运行一个基准,然后进入第一轮自我游戏。每一轮自我游戏应该持续 30 分钟到 1 小时。这将取决于初始化的参数。
参数初始化(作者创建)
考虑到这需要多长时间,最好现在就离开这个会话,几个小时后再回来。在之前的测试中,我发现它会在 5-10 次迭代中表现良好,这取决于你初始化的运气。
当你准备好了,你可以停止运行单元,它会在最*一次迭代时切断训练。这样做的最佳时机是当您看到您的代理在所有基准代理中表现良好时(或者您已经没有耐心了)。注意:如果您决定继续提高代理的能力,也可以随时使用以下单元格重新开始培训。
一轮自我发挥(作者创作)
下一步是最有趣的——和你的经纪人比赛!希望现在你已经训练出了下一个世界排名前四的玩家,你已经做好了被打败的准备。理想情况下,运行下一个单元将加载您训练过的代理,然后启动一个交互环境,但是…我实际上很难让这部分工作起来。或者,您可以从您的培训工作中下载数据,并在您本地的 Julia 环境中运行(代理仍然是在云中培训的!).
您可以通过运行笔记本中的最后一个单元格来下载数据,这将压缩所有数据。或者,您可以导航到 sessions/connect-four 中的数据,其中包含已学习的网络参数以及用于训练的数据。
一旦你在本地完成设置,你就可以按照有用的维基上的说明进行操作。我和我的经纪人玩了很多游戏,但只有一两次能赢——你玩得怎么样?
接下来连接四颗星(来源
后续步骤
在本文中,我们看到了如何在几个小时内使用 AlphaZero 代理训练 connect four 代理。所使用的 AlphaZero 库可以访问其他游戏,你可能想用它们来进行训练实验。你也可以尝试实现不同的游戏,比如 Snake(这是我目前正在尝试的 Kaggle 比赛的一部分!).
希望这是明确的,任何问题或反馈都欢迎在评论中。
训练人工智能玩战锤 40k:第一部分
原文:https://towardsdatascience.com/training-an-ai-to-play-warhammer-40k-part-one-planning-78aa5dfa888a?source=collection_archive---------11-----------------------
实践教程
我们如何以一种人工智能友好的方式构建一个像战锤一样复杂的游戏?
https://www.instagram.com/p/CR7zpt2tHK-*图片*[*由大卫·梅耶授权给本·威廉姆斯*](https://www.instagram.com/p/CR7zpt2tHK-/)
你是否曾经想玩战锤,但发现设置游戏和与其他玩家一起玩太累了?你希望你可以一遍又一遍地与人工智能对抗,磨练你的技能并尝试其他策略吗?如果是这样,你来对地方了。在本文中,我,一个谦逊的软件工程师和战锤迷,开始了一个新项目,训练一个战锤 40k 第 9 版 AI。
为什么,你会问吗?为什么有人会训练人工智能在游戏中打人?可能是因为这很有趣,然后我就可以宣称自己比他们都好。等等,我的意思是为了人类的利益推进深度学习领域(总是把那些事情搞砸。)另外,谁不想和一些可恶的 AI 一起进入一个美好的 ole 技术黑暗时代呢?
我的意思是,我创造了人工智能,人工智能打败了他们,就好像是我做的一样,对吗?
强化学习——是什么?
视频游戏 AI 等控制任务最知名的训练方法是强化学习。强化学习,简称 RL,是一种深度学习技术,多智能体在竞争环境中执行任务。随着时间的推移,这些代理被奖励和加强以诱导期望的行为。有了足够的计算能力和一个结构良好的奖励方案,不可思议的行为就会出现。
必须训练才能有结果!在 Unsplash 上 Karsten Winegeart 拍照
这与监督学习有很大不同,在监督学习中,大量带标签的数据被输入到 ML 模型中,输出与基础事实进行比较。游戏人工智能代理在如此动态的环境中运行,几乎不可能生成和标记如此大量的数据,更不用说理解这些数据了。不断变化的输入会影响短期和长期规划,强化学习提供了完成工作的工具。
对于任何成功的强化学习项目,所有数据科学的通用原则都适用:
- 大量的好数据会产生更好的结果。
- 模拟的质量对于代理学习任何东西都是至关重要的
- 不惜一切代价避免偏差(人口过多或过少)
- 如果你知道一个信号对问题很重要,直接输入。当你可以加快速度的时候,不要等着人工智能去抓东西。
- 更新的神经网络拓扑、训练技术或其他方法会有所帮助,但最终好的、净化过的数据会得到更好的结果
那么,我们该怎么做呢?
我不是深度学习研究者。当谈到神经网络、训练方法或其他方面时,我不太了解任何事情的相对好处。幸运的是,我不需要!有一个很棒的项目就是为像我这样的人准备的——开放健身房。Gym 是一个 RL 框架——本质上是一组最流行的深度学习模型插入的公共 API。
它的明确目的是创建标准的虚拟环境,强化学习在其中进行。这方面的一些例子包括 Atari 游戏、*衡摆、国际象棋环境等等。
开放式健身环境范例——钢管舞。按作者分类的源视频
OpenAI 健身房挺简单的。在其核心,它是一个容易构建或消费标准环境的框架,因此我们可以测量不同的 ML 模型在同一任务上的表现如何(基准测试)。)我们程序的顶层将继承基本的环境类,在未来的某一天,它将被世界上每一个人工智能研究者所使用。
还有,需要朋友的 40k 玩家。
量化板卡状态
游戏的整个状态需要被存储,通过动作更新,然后再次反馈给我们的强化学习代理。在 OpenAI 健身房的世界中,这被称为观察—观察被反馈到模型中,以理解刚刚发生的事情。这意味着我需要模拟与游戏性相关的一切——棋盘的大小、地形的位置、模型底座的大小、剩余的伤口、模型是否是交通工具、它是否会爆炸等等。
人工智能模型输入和输出— ( 作者图片)
为了使数据能够被健身房代理理解,必须使用空格来组织数据。空格是框架可以理解的标准类型。它们本质上可以归结为:
- 离散值(枚举或整数)
- 盒子(N 维空间,连续或离散)
- 布尔运算
- 将上述类型组织成有意义的块的方法,比如字典和元组
按照我的说法,游戏状态是一种分层的、面向对象的模式,其中每个不同的项目都包含在一个对象中。我目前的计划是开发自己的 Warhammer 40k 引擎(目前正在开发中,将在后续文章中概述),并简单地维护一个翻译层,其中包含我自己的动态模式与 OpenAI Gym 使用的固定模式之间的任何差异。
步骤和动作类型
健身房环境最重要的作用就是步()。代理调用步骤()告诉程序消费它的动作,模拟结果,并更新观察。
step() 是单个时间步,动作之间的周期。这是战锤 40k 的实际游戏进行的地方,给出代理指定的动作。
OpenAI Gym step()函数—图片由作者提供
为了让我正确设计 step() ,我必须先知道什么是动作!在现实生活战锤,行动可以从选择一个目标射击的所有方式,以中断战斗使用战略。既然我们人类如此善于处理模糊性,我们就可以合理地凭直觉判断何时需要执行某个动作,以及如何理解它。对人工智能来说,事情变得更加棘手!
所有神经网络的输出层都是固定的。它们将永远是相同的维度。这使得将网络输出与战锤 40k 的动态动作联系起来变得棘手。游戏有很多来回的互动。策略是一个突出的痛苦的例子——一些可以在掷骰子之前或之后使用,甚至可以用来中断战斗解决的顺序。
即使在正常的回合顺序中,也有几个反复的决定——否定心灵力量,或者分配攻击给单位中的哪个模型,等等。掷骰子的结果通常会影响玩家随后做出的决定,这也可能随时发生。
让我们考虑下面的操作序列,如下所示:
40K AI 动作示例序列— 作者图片
在这种情况下,轮到蓝色玩家了。蓝色玩家选择向前移动两个单位,用远程武器射击第一个橙色敌人。他们选择用不同的敌人模式来攻击他们的第三个单位。橙色玩家选择向第三个蓝色单位发射警戒。
让我们探讨一下在这种情况下如何组织行动的不同可能性。
1。 小动作(真实动作)
对于我提议的小动作,一个动作正是游戏规则中定义的一个动作——这将是战锤规则到代码的最直译。任何时候一个玩家可以合法地对一种情况做出行动或反应,人工智能代理也将被允许这样做。这将意味着从移动命令,到宣布射击目标,到决定战斗顺序的任何事情都将是人工智能做出的独特动作。这为代理提供了最大限度的信息,以便在所有时间点做出最佳决策。这也是人工智能可以不受任何限制地玩 40K 的完整游戏的唯一方式(取决于那些讨厌的开发人员正确编码!)
动作序列示例—每个玩家交替动作和反应— 作者图片
以我自己不专业的观点来看,这样做最大的缺点是,这将变得难以置信地难以为人工智能建模。几乎所有的 OpenAI 健身房项目都倾向于只有一种类型的动作可以发出——他们在*台上*衡横梁(向左、向右、停止)或击败吃豆人(向上、向右、向下、向左或停止)。)通过的小动作,我们的模型现在必须了解它处于哪个阶段,它处于哪个环境中(瞄准、传球、移动、分配伤口等)。)甚至开始做出好的决定。本质上,它必须学习游戏规则,同时也要学习游戏中的最佳策略——也就是说,它很可能会有一大堆动作,当它们不相关时,它可以发出来。这意味着算法有很多模糊性——传统的学习算法可能无法很好地处理这一点。我们人类学习规则已经够辛苦了,我们还有参考文本要通读!
形成良好的输出图层模式在这里也很困难-我们要么为不同的操作重用相同的输出字段,要么创建一个大规模的输出表面来同时处理所有可能的操作。这可能会导致难以置信的漫长和困难的学习时间,因为学习过程会对大面积的不连续输出进行实验。
2。 大动作
有了大动作,一个动作就是战锤的一个完整回合——玩家回合的每一个集体动作、射击、冲锋命令都在一个巨大的输出中完成。对于我们上面概述的场景,所有蓝色命令(移动、射击和冲锋)在蓝色玩家的回合开始时同时输出。
样本大动作——所有蓝色订单同时提交——作者本人法师
这样做的最大好处是每个步骤()都是一样的——得到一组动作,然后玩完整个回合。这使得训练代理比小动作更容易一些,因为它不需要担心不同的“模式”或动作类型。只有一个动作的内容每个步骤()。这也使得开发变得容易——我们只需要大规模的动作输出,然后一举完成回合。
这种方法最大的缺点是代理人丢失了信息——它必须在任何决定执行之前做出决定,不像游戏的实际参与者。虽然我们人类玩家倾向于在每个回合开始时都有一个计划,但拙劣的射击或冲锋的结果会导致计划的改变。这可能发生得非常突然,如果可能的话,我不想妨碍人工智能这么做。随着大动作,人工智能无法利用我们都爱的战锤的动态来回方面。它还阻止了人工智能玩完整的游戏——无序的动作是规则的一部分。
3。 每型号或每单位动作
这是第三个概念,其中人工智能交替激活模型,在更像杀戮团队的模式下玩战锤,而不是完全成熟的桌面战争游戏。人工智能将被允许选择一个模型,并采取一系列行动,如站立和射击、 前进和射击、 冲锋、正常移动、等。这将防止大动作的一些问题——当激活一个模型时,AI 有更多的信息,随后将能够以*乎完美的信息玩游戏。
逐模式动作的主要缺点是 40k 不是这么玩的。很接*,但不是完全匹配。这可以通过缓存模型/单位的订单得到部分缓解,这样引擎就可以等到射击阶段再解决射击问题,直到充电阶段再充电,等等。它仍然有一个问题,即人工智能在对玩家的行为做出反应的方式上是有限的——它通常仍然只能使用标准的命令,而不是反动的策略。
以神经网络兼容的方式格式化 40k 的规则
如果我不小心,代理将有可能提交不合法的行动。没有真正的方法来告诉代理一个他们不能做的动作。我们有办法告诉他们不应该做这样的输出,但这不会阻止他们仍然不时地这样做。迫使代理人遵守 40k 规则的唯一真正方法是将行动空间限制在纯粹有效的移动范围内。
无效移动动作示例— 作者图片
例如,让我们使用上面的同一个示例图。我们的三个蓝队都在前进。我们给 AI 代理浮点 X 和 Y 位置输出来表示移动的目的地。如果我们想让一个警卫班几乎完全控制移动位置,它可以有几乎无限的非法移动:重叠基地,移动到无法通行的地形,离开单位一致性,移动到合格距离之外,或移动到交战范围内。
一种解决方案是净化代理的输出。如果代理人的行动会导致非法游戏状态,使用启发式后处理器来做出下一个允许的最佳决策。净化代理输出的缺点是,它只能达到我们的后处理器代码允许的程度。
如果我们想要一个具有卓越的微观和定位的代理,如果我们离开这种“训练轮”,我们并不总是能得到它——它们限制了代理的灵活性和控制力。
我想到的另一个解决方案是让代理人自由支配将模型放在无效的位置上,但是对这样做给予负面的奖励。这样,代理人就不愿意做非法的动作,而愿意做合法的动作。理论上,随着时间的推移,代理人会了解 40k 的规则,通常不会做出违反游戏规则的举动。这里的一个大风险是过度奖励移动的合法性,而低估我们试图训练的实际东西——40k 控制算法!
这可能会导致模型认为它做得很好,而执行愚蠢的动作,如在一条线上来回移动模型。这将导致我们只能成功地训练一个知道 40k 的规则但不知道策略的人工智能。
我们能想到的另一个简单的策略是,当无效的移动被指定时,不采取任何行动,或者将违规的模型移出游戏。这将作为一个有效的强制函数来惩罚 AI 的无效移动,而不必以某种方式计算奖励。这样做的主要风险是再次暴露了不是有效动作的动作空间——它似乎引入了各种各样的问题。
最后一个选项是我们提到的第一件事——将动作空间限制在纯粹有效的移动。虽然原则上很棒,但我对实现每一步可能的动作的巨大复杂性不感兴趣。
部署
渴望离开部署区的大虫子——图片由作者提供
部署是战锤 40k 战略的关键部分。然而,完成部署阶段与游戏的常规回合有很大不同。在我看来,训练一个机器学习模型以某种方式理解部署期间采取的行动和游戏流程中采取的行动之间的差异是相当困难的。
因此,我决定跳过第一次构建的部署阶段。相反,我计划使用一个基本的布局算法来开始。随着这个引擎的其他部分走到一起,我们可以开始考虑让 AI 也可以进行部署。
奖励代理
我想谈的最后一个话题是一个棘手的问题(我猜他们都是,不是吗。)OpenAI 健身房的模特在每走完步()后,都会从我们的环境中收到一个介于-无穷大和+无穷大之间的数字。这被称为奖励,为了从强化学习中获得好的结果,我们必须提供一个好的奖励指标。
一般来说,从一个小的奖励开始,随着时间的推移,随着模型的训练逐渐增加,这被认为是好的。通过这种方式,模型不会在训练开始时过度奖励自己的行为,因为它不太可能是正确的,并且随着训练的进行,开始更多地奖励自己,以磨练真正积极的行为。
对于我们所关心的,在每个步骤()之后返回一个奖励是很棘手的——在我之前提到的任何情况下,手写的算法都不可能知道模型采取的行动是好是坏!如果这是可能的,那么我们就不会使用深度学习来解决这个该死的问题了!我们可以尝试使用某些东西,比如:
- 这个动作是否导致敌方模型被移出桌面?
- 这一行动是否导致我的团队得分?
但这两者都有可能返回误报——在一天结束时,我们只关心人工智能是否赢得了比赛。正因为如此,我们应该只根据胜利和失败进行奖励。达到这一点的所有其他任务都是高度主观和视情况而定的。因此,在步骤()结束时(导致权重不变,中立),不会向 AI 提供奖励,直到确定游戏是否获胜(在集结束时)。)
插曲
一个情节是一系列相关的步骤。它们通常属于一个连续的序列,如战锤 40k 的单个游戏。一集结束后,我们可以决定要么结束训练,要么开始新的训练。
我的决策概述
经过深思熟虑,以下是我为本文中讨论的这个项目的第一个版本(称为 V0)所做的高层决策:
- 最后的可交付成果是一个开放式人工智能健身房环境。我将把这个环境插入到各种 RL 模型中,看看最终什么会做得好。
- 代理商将在每一集结束时根据胜负获得奖励
- 我将用 Python 编写这个环境,用 PyGame 中的可视化工具
- 我将动作定义为每个单元的动作,尽力模拟完整的规则集。
- 我将通过输入一个离散观察(enum)空间来处理动作变化,告诉代理我希望它执行哪个动作。
- 我省略了许多高级规则,如战略、部署、攻击分配和我的第一版引擎的精神阶段——这简直太多了。
- 除了移动之外,我通过不采取任何行动来处理非法输出——这比编写一大堆代码来试图辨别代理的意图要容易得多。对于移动,我将沿直线移动模型,尽可能靠*所需的位置。
下一步
嗯,说了很多,但没写多少代码。我敢肯定,你们都很兴奋地看到人工智能做什么的一些漂亮的可视化效果——在正义的荣耀中玩 40K。我们会到达那里,但是现在基本的决定已经决定了——为了我自己!
在张量处理器上训练 BERT 文本分类器
原文:https://towardsdatascience.com/training-bert-text-classifier-on-tensor-processing-unit-ce0adc8ae449?source=collection_archive---------37-----------------------
为突尼斯阿拉比齐社交媒体情感分析培训拥抱 TPU 最著名的模特
由作者设计|元素由 cookie-studio , rawpixel-com
介绍
说阿拉伯语的人通常在社交媒体上用当地方言表达自己,所以突尼斯人使用突尼斯阿拉伯语,它由以拉丁字母形式书写的阿拉伯语组成。**情感分析依靠文化知识和带上下文信息的词义。我们将使用阿拉伯方言和情感分析来解决这个项目中的问题。
比赛在津迪举行,由 AI4D 组织。在这场比赛中,我们获得了训练和测试数据集。训练数据集由阿拉伯文文本和该文本的情感组成。我们需要建立一个模型,并改进我们的指标,以便在竞争领先者排行榜中获得第一名。
数据集是从不同的社交媒体*台收集的,这个项目的目标是预测测试数据集的标签。标签将决定我们的句子是积极的、消极的还是中性的。
描述
在这个项目中,我们将使用 TPU 训练多语言 BERT 模型。
TPU
张量处理单元(TPU)是谷歌开发的人工智能加速器专用集成电路(ASIC),有助于减少深度学习模型的训练时间,尤其是谷歌自己的 TensorFlow 包张量处理单元。与 PyTorch 相比,在 TensorFlow python 库中在 TPU 上训练深度学习模型要简单得多。
张量处理单元| 维基百科
云 TPUs 资源最大限度地减少了计算线性代数问题的时间,并且使用大多数线性代数来开发机器学习应用。以前,用庞大的数据集训练一个复杂的深度学习模型需要几周时间,但使用 TPUs,训练时间减少到几个小时。谷歌云。
伯特
BERT(来自变形金刚的双向编码器表示)是 Google Research 的研究人员在 2018 年提出的 NLP(自然语言处理模型)。BERT 基本上是 transformer 架构的编码器栈 analyticsvidhya 。最初,当 BERT 发布它时,在许多 NLP 任务的准确性方面采用了其他模型,不久之后,其他研究人员开始使用 BERT 架构,并在不同语言中发布更新更好的模型版本。这就是我们基于 BERT 的多语言封装模型的由来,它在新的低资源语言上表现得相当好。我们的模型是使用最大的维基百科多语言数据语料库对前 104 种语言进行预训练的,要了解更多关于这个模型的信息,请阅读的论文。研究人员使用掩蔽语言建模(MLM)使其对多种语言有效。要了解更多关于该型号的信息,请查看型号卡Bert-base-多语言环境。
伯特多语模式| 拥抱脸
密码
我们将首先设置我们的模型在 TPU 上训练,然后我们将设置我们的超参数来提高性能。我们将加载和训练突尼斯阿拉伯语方言情感分析数据,然后在 ai4d.ai 提供的测试数据集上进行预测。
导入库
我们已经导入了所有必要的库,以便对 BERT 模型进行实验或预训练。
*import tensorflow as tf
import logging
from tensorflow.keras.layers import (
Dense,
Flatten,
Conv1D,
Dropout,
Input,
)
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import Model
from tensorflow.keras import regularizers
from transformers import BertTokenizer, TFBertModel
import os
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from tqdm import tqdm
tqdm.pandas()
import re
import random*
为 TPU 做准备
该代码尝试检查 TPU 集群,然后初始化 TPU,最后创建一个 TPU 策略,稍后我们将使用该策略在云上训练我们的模型。如果你没有 TPU,代码将根据你的机器转移到 GPU 或 CPU。
*try:
tpu = tf.distribute.cluster_resolver.TPUClusterResolver()
tf.config.experimental_connect_to_cluster(tpu)
tf.tpu.experimental.initialize_tpu_system(tpu)
strategy = tf.distribute.experimental.TPUStrategy(tpu)
except ValueError:
strategy = tf.distribute.get_strategy() # for CPU and single GPU
print('Number of replicas:', strategy.num_replicas_in_sync)*
设置超参数
这些超参数是用于实验的,以便我们可以做出改变并获得更好的结果。目前,这些参数产生了迄今为止最好的结果。
*max_length = 140
batch_size = 16
dev_size = 0.1
num_class = 4*
正在加载 BERT 标记器
使用变形金刚库从拥抱脸下载 BERT tokenizer。
*model_name = "bert-base-multilingual-cased"
tokenizer = BertTokenizer.from_pretrained(model_name)Downloading: 100% 996k/996k [00:00<00:00, 5.62MB/s]Downloading: 100% 29.0/29.0 [00:00<00:00, 950B/s]Downloading: 100% 1.96M/1.96M [00:00<00:00, 11.8MB/s]*
读取列车数据集
数据集可以在这里找到,并且是在麻省理工学院的许可下。
训练数据集包含 70,000 个样本,而我们的测试数据集包含 30,000 个样本。火车数据集有一个包含唯一标识符的 id 列、文本列,其中包含用阿拉伯语写的推文*、和标签**列,其中包含情感 {-1,0,1}。*
- ***读取数据:*使用熊猫读取 CSV 文件
- ***删除重复的推文:*这提高了模型的性能
- ***重新映射标签:*这使得编码和解码-1 情感变得容易,并最终提高了我们的性能指标。
- ***培训开发分割:*用于培训和评估。
*train_df = pd.read_csv('../input/aranizi-dailect-training-data/Arabizi-Dailect-Train.csv')
train_df.text = train_df.text.astype(str)
train_df.drop_duplicates(subset=['text'],inplace=True)
train_df.label=train_df.label.map({-1:0,1:2,0:1})
train, dev = train_test_split(train_df, test_size=dev_size, random_state=42)*
加载数据并进行处理
我们使用 transformers batch encode plus 来编码文本数据,并将最大长度限制为 150。我们使用 TensorFlow 函数将我们的标签转换为分类类型,并将其加载到 TensorFlow 数据集,该数据集为模型使用我们的数据做准备。我认为缓存有助于 TPU 存储数据,但你可以删除它或添加它,你的模型将在任何情况下工作。
*def bert_encode(data):
tokens = tokenizer.batch_encode_plus(
data, max_length=max_length, padding="max_length", truncation=True
)
return tf.constant(tokens["input_ids"])
train_encoded = bert_encode(train.text)
dev_encoded = bert_encode(dev.text)
train_labels = tf.keras.utils.to_categorical(train.label.values, num_classes=num_class)
dev_labels = tf.keras.utils.to_categorical(dev.label.values, num_classes=num_class)
train_dataset = (
tf.data.Dataset.from_tensor_slices((train_encoded, train_labels))
.shuffle(100)
.batch(batch_size)
).cache()
dev_dataset = (
tf.data.Dataset.from_tensor_slices((dev_encoded, dev_labels))
.shuffle(100)
.batch(batch_size)
).cache()*
模型
这个模型受到了卡格尔的笔记本的影响,他使用了 LSTM,而我只是使用了辍学的密集层。Kaggle 还提供 30 小时的免费 TPU,这使得任何人都可以更容易地免费使用云计算。
我们的模型非常简单,我们使用了相同的 BERT 架构,并添加了 3 个密集层,丢失率= 0.3 。我使用了前两层的 relu 激活,对于输出层,我们使用了在 TPU 上表现惊人的 soft plus。
我也试验过双向密集 LSTM 层和简单 LSTM,但这些模型表现不佳。
*def bert_tweets_model():
bert_encoder = TFBertModel.from_pretrained(model_name, output_attentions=True)
input_word_ids = Input(
shape=(max_length,), dtype=tf.int32, name="input_ids"
)
last_hidden_states = bert_encoder(input_word_ids)[0]
clf_output = Flatten()(last_hidden_states)
net = Dense(512, activation="relu")(clf_output)
net = Dropout(0.3)(net)
net = Dense(440, activation="relu")(net)
net = Dropout(0.3)(net)
output = Dense(num_class, activation="softplus")(net)
model = Model(inputs=input_word_ids, outputs=output)
return model*
编译模型
您需要添加 with strategy.scope():并运行我们的模型,该模型将从 Hugging Face 服务器下载模型并将其加载到模型变量中。您的模型、优化器和模型编译应该在 strategy.scope()下完成,以便在云 TPU 上进行训练。
*with strategy.scope():
model = bert_tweets_model()
adam_optimizer = Adam(learning_rate=1e-5)
model.compile(
loss="categorical_crossentropy", optimizer=adam_optimizer, metrics=["accuracy"]
)
model.summary()Downloading: 100% 625/625 [00:00<00:00, 19.9kB/s]Downloading: 100% 1.08G/1.08G [00:38<00:00, 29.6MB/s]*
模型结构
你可以看到我们用 Dropout 添加的模型结构和密集层。
*Model: "model_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_ids (InputLayer) [(None, 140)] 0
_________________________________________________________________
tf_bert_model_1 (TFBertModel TFBaseModelOutputWithPool 177853440
_________________________________________________________________
flatten_1 (Flatten) (None, 107520) 0
_________________________________________________________________
dense_3 (Dense) (None, 512) 55050752
_________________________________________________________________
dropout_76 (Dropout) (None, 512) 0
_________________________________________________________________
dense_4 (Dense) (None, 440) 225720
_________________________________________________________________
dropout_77 (Dropout) (None, 440) 0
_________________________________________________________________
dense_5 (Dense) (None, 4) 1764
=================================================================
Total params: 233,131,676
Trainable params: 233,131,676
Non-trainable params: 0
_________________________________________________________________*
培训模式
终于到了我们在 TPU 上训练模型的时候了。该模型在 TPU 上训练需要 17 分钟,在 GPU 上训练需要 45 分钟,在 CPU 上训练需要 2.5 小时。你可以清楚地看到性能差异。通过使用 model.fit ,我们在训练数据集上训练了我们的模型,并使用 dev_dataset 作为验证。我们训练精度随着每个时期以及我们的验证精度而提高。
*history = model.fit(
train_dataset,
batch_size=batch_size,
epochs=5,
validation_data=dev_dataset,
verbose=1,
)Epoch 1/5
4166/4166 [==============================] - 313s 60ms/step - loss: 0.7691 - accuracy: 0.6309 - val_loss: 0.4994 - val_accuracy: 0.7810
Epoch 2/5
4166/4166 [==============================] - 246s 59ms/step - loss: 0.5092 - accuracy: 0.7870 - val_loss: 0.4541 - val_accuracy: 0.8027
Epoch 3/5
4166/4166 [==============================] - 248s 59ms/step - loss: 0.4232 - accuracy: 0.8271 - val_loss: 0.4680 - val_accuracy: 0.8081
Epoch 4/5
4166/4166 [==============================] - 247s 59ms/step - loss: 0.3577 - accuracy: 0.8606 - val_loss: 0.4994 - val_accuracy: 0.8103
Epoch 5/5
4166/4166 [==============================] - 247s 59ms/step - loss: 0.2980 - accuracy: 0.8849 - val_loss: 0.6219 - val_accuracy: 0.8166*
节省重量
让我们保存或建模,以便我们可以再次使用它或将其部署为 streamlit web 应用程序。
*model.save_weights('weights.h5', overwrite=True)*
显示损失和准确性
我们可以在下面的线图中看到结果,每个时期我们的训练和验证准确性都有所提高。损失线情节中的故事是非常不同的,在纪元 3 之后损失开始增加。为了在测试数据集上获得更好的结果,我们应该将历元的数量保持在 3。
*import matplotlib.pyplot as plt
def plot_graphs(history, string):
plt.plot(history.history[string])
plt.plot(history.history["val_" + string])
plt.xlabel("Epochs")
plt.ylabel(string)
plt.legend([string, "val_" + string])
plt.show()
plot_graphs(history, "accuracy")
plot_graphs(history, "loss")*
**
预测测试数据集并保存提交
是时候使用我们的微调模型来预测测试数据集上的标签了。我们将重复用于训练数据集和预测标签的步骤。
- 读取测试数据
- 编码
- TF 数据集
- 批量预测
- 熊猫提交的数据框
- 重新映射标签
- 保存 CSV
*test = pd.read_csv("../input/arabizi-dialect/Test (1).csv")
test.text = test.text.astype(str)
test_encoded = bert_encode(test.text)##Loading Test Data
test_dataset = tf.data.Dataset.from_tensor_slices(test_encoded).batch(batch_size)## Prediction on test Datasets
predicted_tweets = model.predict(test_dataset, batch_size=batch_size)
predicted_tweets_binary = np.argmax(predicted_tweets, axis=-1)## Submisssion
my_submission = pd.DataFrame({"ID": test.ID, "label": predicted_tweets_binary})
my_submission.label = my_submission.label.map({1: -1, 3: 1, 2: 0})
my_submission.to_csv("/kaggle/working/my_submission.csv", index=False)*
检查课程和结果
我们的模型在测试数据集上表现得相当好,并且仅用很少的实验我们就得到最好的结果。你可以尝试嵌入和其他深度学习架构,以产生更好的结果。你也可以尝试集成多个模型来提高你的准确率。
图片作者| Zindi 测试分数
通过使用值计数,我们可以检查预测标签的分布。
*my_submission.label.value_counts() 1 15356
-1 14208
0 436*
我希望你喜欢我的工作,请♥并与你的朋友和同事分享它,如果你想阅读更多关于数据科学/机器学习的文章,请在 LinkedIn 和 Polywork 上关注我。
原载于 2021 年 8 月 4 日 https://www.analyticsvidhya.comhttps://www.analyticsvidhya.com/blog/2021/08/training-bert-text-classifier-on-tensor-processing-unit-tpu。
使用拥抱脸从头开始训练 BPE、单词块和单字标记器
原文:https://towardsdatascience.com/training-bpe-wordpiece-and-unigram-tokenizers-from-scratch-using-hugging-face-3dd174850713?source=collection_archive---------13-----------------------
使用 Hugging Face 的 tokenizers 包比较 SOTA 标记化算法生成的标记
作者图片
继续深入 NLP 的海洋,这篇文章是关于利用humping Face 的 tokenizers 包从头开始训练 tokenizers。
标记化通常被认为是 NLP 的一个子领域,但它有自己的进化故事,以及它是如何达到当前阶段的,它正在支撑最先进的 NLP 模型。
在我们开始训练和比较不同的记号赋予器的有趣部分之前,我想给你一个算法之间的关键区别的简要总结。
主要区别在于选择要合并的字符对和合并策略,这些算法中的每一个用来生成最终的令牌集。
BPE——基于频率的模型
- 字节对编码使用子字模式的频率将它们列入合并的候选名单。
- 使用频率作为驱动因素的缺点是,最终可能会产生模糊的最终编码,这对新的输入文本可能没有用。
- 在生成明确的令牌方面,它仍有改进的余地。
unigram——基于概率的模型
- Unigram 模型通过计算每个子词组合的可能性来解决合并问题,而不是选择最常见的模式。
- 它计算每个子词标记的概率,然后根据损失函数将其丢弃,该损失函数在本研究论文的中有所说明。
- 基于损失值的特定阈值,您可以触发模型丢弃底部 20–30%的子词标记。
- Unigram 是一种完全概率算法,它根据概率选择字符对,并最终决定在每次迭代中合并(或不合并)。
文字片
- 随着 2018 年 BERT 的发布,出现了一种新的子词标记化算法,称为 WordPiece,可以认为是 BPE 和 Unigram 算法的中介。
- WordPiece 也是一种贪婪算法,它利用似然性而不是计数频率来合并每次迭代中的最佳配对,但配对字符的选择是基于计数频率的。
- 因此,在选择要配对的字符方面,它类似于 BPE,在选择要合并的最佳字符对方面,它类似于 Unigram。
考虑到算法上的差异,我尝试实现这些算法中的每一个(不是从头开始),以比较它们各自生成的输出。
训练 BPE、Unigram 和 WordPiece 算法
现在,为了对输出进行无偏见的比较,我不想使用预先训练的算法,因为这会将数据集的大小、质量和内容带入图片中。
一种方法可能是使用研究论文从头开始编写这些算法,然后测试它们,这是一种很好的方法,以便真正理解每个算法的工作原理,但你可能会花费数周时间来完成这项工作。
相反,我使用了拥抱脸的记号赋予器包,它提供了所有当今最常用的记号赋予器的实现。它还允许我在我选择的数据集上从头开始训练这些模型,然后标记我们自己选择的输入字符串。
训练数据集
我选择了两个不同的数据集来训练这些模型,一个是来自古腾堡的免费书籍,作为一个小数据集,另一个是 wikitext-103 ,它是 516M 的文本。
在 Colab 中,您可以先下载数据集并解压缩(如果需要的话),
!wget [http://www.gutenberg.org/cache/epub/16457/pg16457.txt](http://www.gutenberg.org/cache/epub/16457/pg16457.txt)!wget [https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-103-raw-v1.zip](https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-103-raw-v1.zip)!unzip wikitext-103-raw-v1.zip
导入所需的模型和训练器
浏览文档,你会发现这个包的主要 API 是类Tokenizer.
然后,您可以用您选择的模型(BPE/ Unigram/ WordPiece)实例化任何记号化器。
在这里,我导入了主类,所有我想测试的模型,以及它们的训练器,因为我想从头开始训练这些模型。
## importing the tokenizer and subword BPE trainer
from tokenizers import Tokenizer
from tokenizers.models import BPE, Unigram, WordLevel, WordPiece
from tokenizers.trainers import BpeTrainer, WordLevelTrainer, \
WordPieceTrainer, UnigramTrainer## a pretokenizer to segment the text into words
from tokenizers.pre_tokenizers import Whitespace
自动化培训和令牌化的 3 步流程
因为我需要为三个不同的模型执行有些相似的过程,所以我将这些过程分成三个函数。我只需要为每个模型调用这些函数,我在这里的工作就完成了。
那么,这些函数是什么样子的呢?
步骤 1 —准备标记器
准备 tokenizer 需要我们用我们选择的模型实例化 tokenizer 类,但是因为我们有四个模型(还添加了一个简单的单词级算法)要测试,我们将编写 if/else 案例来用正确的模型实例化 Tokenizer。
为了在小型和大型数据集上训练实例化的记号赋予器,我们还需要实例化一个训练器,在我们的例子中,它们是[**BpeTrainer**](https://huggingface.co/docs/tokenizers/python/latest/api/reference.html#tokenizers.trainers.BpeTrainer)**, WordLevelTrainer, WordPieceTrainer, and UnigramTrainer.**
实例化和训练将需要我们指定一些特殊的令牌。这些是未知单词的标记和其他特殊标记,我们以后需要使用它们来增加我们的词汇。
您还可以在此指定其他训练参数的词汇大小或最小频率。
unk_token = "<UNK>" # token for unknown words
spl_tokens = ["<UNK>", "<SEP>", "<MASK>", "<CLS>"] # special tokensdef prepare_tokenizer_trainer(alg):
"""
Prepares the tokenizer and trainer with unknown & special tokens.
"""
if alg == 'BPE':
tokenizer = Tokenizer(BPE(unk_token = unk_token))
trainer = BpeTrainer(special_tokens = spl_tokens)
elif alg == 'UNI':
tokenizer = Tokenizer(Unigram())
trainer = UnigramTrainer(unk_token= unk_token, special_tokens = spl_tokens)
elif alg == 'WPC':
tokenizer = Tokenizer(WordPiece(unk_token = unk_token))
trainer = WordPieceTrainer(special_tokens = spl_tokens)
else:
tokenizer = Tokenizer(WordLevel(unk_token = unk_token))
trainer = WordLevelTrainer(special_tokens = spl_tokens)
tokenizer.pre_tokenizer = Whitespace()
return tokenizer, trainer
我们还需要添加一个预标记器来将我们的输入拆分成单词,因为没有预标记器,我们可能会得到重叠几个单词的标记:例如,我们可以得到一个**"there is"**
标记,因为这两个单词经常相邻出现。
使用预标记器将确保没有标记大于预标记器返回的单词。
该函数将返回 tokenizer 及其 trainer 对象,可用于在数据集上训练模型。
这里,我们对所有模型使用相同的预标记器(Whitespace
)。可以选择用其他来测试。
步骤 2 —培训分词器
准备好记号赋予者和训练者之后,我们就可以开始训练过程了。
这里有一个函数,它将获取我们打算用来训练我们的标记器的文件以及算法标识符。
‘WLV’
-词级算法‘WPC’
-计件算法‘BPE’
-字节对编码‘UNI’
-单字
def train_tokenizer(files, alg='WLV'):
"""
Takes the files and trains the tokenizer.
"""
tokenizer, trainer = prepare_tokenizer_trainer(alg)
tokenizer.train(files, trainer) # training the tokenzier
tokenizer.save("./tokenizer-trained.json")
tokenizer = Tokenizer.from_file("./tokenizer-trained.json")
return tokenizer
这是我们在训练分词器时需要调用的主要函数,它将首先准备分词器和训练器,然后用提供的文件开始训练分词器。
训练之后,它将模型保存在一个 JSON 文件中,从该文件中加载它,并返回经过训练的标记器,开始对新输入进行编码。
步骤 3 —对输入字符串进行标记
最后一步是开始对新的输入字符串进行编码,并比较每个算法生成的标记。
这里,我们将编写一个嵌套的 for 循环,首先在较小的数据集上训练每个模型,然后在较大的数据集上训练,并标记输入字符串。
输入字符串— “这是一个深度学习的记号化教程。标记化是深度学习 NLP 管道的第一步。我们将比较每个令牌化模型生成的令牌。很兴奋吗?!😍"
small_file = ['pg16457.txt']
large_files = [f"./wikitext-103-raw/wiki.{split}.raw" for split in ["test", "train", "valid"]]for files in [small_file, large_files]:
print(f"========Using vocabulary from {files}=======")
for alg in ['WLV', 'BPE', 'UNI', 'WPC']:
trained_tokenizer = train_tokenizer(files, alg)
input_string = "This is a deep learning tokenization tutorial. Tokenization is the first step in a deep learning NLP pipeline. We will be comparing the tokens generated by each tokenization model. Excited much?!😍"
output = tokenize(input_string, trained_tokenizer)
tokens_dict[alg] = output.tokens
print("----", alg, "----")
print(output.tokens, "->", len(output.tokens))
# #输出:
作者图片
输出分析:
查看输出,您将看到令牌生成方式的差异,这反过来导致生成不同数量的令牌。
- 一个简单的单词级算法创建了 35 个标记,不管它是在哪个数据集上被训练的。
- BPE 算法在较小数据集上训练时创建了 55 个令牌,在较大数据集上训练时创建了 47 个令牌。这表明,当在更大的数据集上训练时,它能够合并更多的字符对。
- Unigram 模型为两个数据集创建了数量相似(68 和 67)的令牌。但是您可以看到生成的令牌之间的差异:
作者图片
对于更大的数据集,合并更接*于生成更适合编码我们经常使用的真实世界英语语言的标记。
作者图片
- 在较小的数据集上训练时,WordPiece 创建了 52 个令牌,在较大的数据集上训练时,创建了 48 个令牌。生成的标记有两个##,表示标记用作前缀/后缀。
由作者制作的图像
- 当在更大的数据集上训练时,这三种算法都生成了更少和更好的子词标记。
比较令牌
为了比较标记,我将每个算法的输出存储在一个字典中,并将它转换成一个数据帧,以便更好地查看标记的差异。
由于每个模型生成的令牌数量不同,我添加了一个
import pandas as pdmax_len = max(len(tokens_dict['UNI']), len(tokens_dict['WPC']), len(tokens_dict['BPE']))
diff_bpe = max_len - len(tokens_dict['BPE'])
diff_wpc = max_len - len(tokens_dict['WPC'])tokens_dict['BPE'] = tokens_dict['BPE'] + ['<PAD>']*diff_bpe
tokens_dict['WPC'] = tokens_dict['WPC'] + ['<PAD>']*diff_wpcdel tokens_dict['WLV']df = pd.DataFrame(tokens_dict)
df.head(10)
# #输出:
作者图片
您还可以使用集合来查看标记的差异:
作者图片
作者图片作者图片
所有的代码都可以在这个 Colab 笔记本里找到。
结束想法和后续步骤!
根据生成的标记的种类,WPC 似乎确实生成了在英语中更常见的子词标记,但我并不认为这是一种观察结果。
这些算法彼此略有不同,但在开发一个像样的 NLP 模型方面做得有些类似。但是大部分性能取决于语言模型的用例、词汇量、速度和其他因素。
这些算法的进一步发展是 SentencePiece 算法,这是一种解决整个标记化问题的有益方法,但这个问题的大部分通过 HuggingFace 得以缓解,甚至更好的是,他们在单个 GitHub repo 中实现了所有算法。
这就结束了标记化算法,下一步是理解什么是嵌入,标记化如何在创建这些嵌入中发挥重要作用,以及它们如何影响模型的性能。
参考文献和注释
如果你不同意我的分析或我在这篇文章中的任何工作,我强烈建议你查看这些资源,以准确理解每个算法的工作原理:
- 子词正则化:改进神经网络翻译模型使用拥抱脸从头开始训练 BPE、单词块和单字标记器
- 具有子词单元的稀有词的神经机器翻译 —讨论基于 BPE 压缩算法的不同分割技术的研究论文。
- 拥抱脸的 tokenizer 包。
和我联系!
如果你想在数据科学或 ML 领域起步,请查看我的课程 数据科学基础& ML 。
如果你想看到更多这样的内容,并且你不是订阅者,可以考虑订阅我的简讯。
如有任何补充或建议,您可以通过以下方式联系我:
- YouTube
- 推特
- 领英
在您自己的数据集上训练 DETR
原文:https://towardsdatascience.com/training-detr-on-your-own-dataset-bcee0be05522?source=collection_archive---------8-----------------------
什么是 DETR?是什么让它在对象检测算法的世界中脱颖而出?而你是怎么用自己的数据训练它的?
照片由 note thanun 在 Unsplash 上拍摄
DETR——或检测变压器——是脸书基于深度学习的物体检测解决方案市场的最新成员。简单地说,它利用 transformer 架构来预测图像中的对象及其位置。
什么是 DETR?
来源:https://s content . fbll 1-1 . FNA . FBC dn . net/v/t 39.8562-6/101177000 _ 245125840263462 _ 1160672288488554496 _ n . pdf?_ NC _ cat = 104&CCB = 1-3&_ NC _ sid = ae5e 01&_ NC _ OHC = oki PD 6 ovnkkax 968 fln&_ NC _ ht = s content . fbll 1-1 . FNA&oh = ab 6 dcdc 2307471 a 56 fdbe 2 ebb 98 faf 6b&OE = 606 Abd 47
DETR 是一个联合卷积神经网络(CNN)和变压器,以前馈网络为头。这种架构允许网络使用由 CNN 提取的特征,使用 Transformer 架构中固有的强大多头注意力机制,可靠地推理图像中的对象关系。
来源:https://colab . research . Google . com/github/Facebook research/detr/blob/colab/notebooks/detr _ demo . ipynb
简单地说,网络能够估计图像中任何一点与图像其余部分的关系。给定一个样本点,自我注意地图显示周围区域与该点正相关的可能性。在上面的例子中,这意味着尽管有两只猫和两个遥控器,网络的注意力可以通过观察每个区域与其他区域的关系来区分不同的情况。
来源:https://colab . research . Google . com/github/Facebook research/detr/blob/colab/notebooks/detr _ attention . ipynb
上图显示了四个样本点和它们的自我关注地图。这些表示网络假定与每个点相关的区域。最终,每个注意力头可以被聚集在一个包含多个边界框和匹配概率分布的解决方案中。该解决方案基于大量的对象查询,或自动提供这些样本点的学习位置嵌入。每个输出嵌入通过一个共享的前馈网络,该网络估计上述检测(包围盒和分类概率)或*无对象。*流程结果如下所示:
来源:https://colab . research . Google . com/github/Facebook research/detr/blob/colab/notebooks/detr _ attention . ipynb
DETR 与其他物体探测器有何不同?
所有对象检测算法都有其优点和缺点;R-CNN (及其衍生)是一个两步算法,需要区域提议计算和检测计算。最*的进展,如 SSD (单次多盒检测器)和 YOLO (你只看一次)被称为单级物体检测器,因为它们在单次向前传递中计算它们的估计。他们如何实现这一点的细节各不相同,但这些网络的一个共同点是要求“先验知识”。
先验是锚盒、标度、网格大小、重复检测识别算法以及用于降低问题维度的类似技术。它们最终用于对输入进行下采样,或者在某些情况下,用于避免计算量大的区域提议步骤。通过应用这些技术,问题从计算问题转变为人类观察者的问题,因为他们必须在训练开始之前估计和提供这些先验。
相比之下,DETR 是对象检测问题的直接集合解决方案。基于上述学习到的位置嵌入,网络提供了许多估计的边界框和类得分。然而,DETR 并非没有先验信息。例如,在开始训练之前,需要手动设置置信度阈值之前的估计边界框的数量,并且应该“明显大于图像中对象的典型数量”。
我如何为自己训练 DETR?
DETR 通常需要非常密集的训练计划。在原始论文中,作者使用 16 个 Nvidia V100 GPUs 在 300 个时期内训练他们的模型,总共超过 3 天的训练时间(在 AWS 大约 4000 美元)。您可以自己尝试一下,但这不是本节的内容。我们对在个人数据集上微调预训练的 DETR 模型感兴趣,可能使用不同于 COCO 的类别数。
我们的 DETR 分叉(在这里找到:https://github.com/aivclab/detr)允许我们通过改变一些关键元素来做到这一点。首先,我们改变模型构建结构以支持任意数量的类。然后,我们将预训练模型的权重(没有类嵌入)提供给构建器。此外,我们将随机变换中图像的最大宽度改为 800 像素。这应该允许在大多数 GPU 上进行训练,但如果您的 GPU 可以处理它,建议改回原来的 1333。默认情况下,我们会将头部的学习速度和主干的学习速度分别降低到 1e-5 和 1e-6,但是您可以自行调整。
根据数据集中的样本数量,最好从头开始重新训练模型。原始 COCO 数据集有超过 200,000 个带注释的图像,超过 150 万个实例,分布在 90 多个类中,因此如果您的数据集具有可比性,它可能会改进您的培训计划,以便在笔记本中设置pretrained = False
。
笔记本在这里找到:https://github . com/aivclab/detr/blob/master/fine tune _ detr . ipynb
下面的示例参数显示了如何简单地为自己微调这样一个模型:
微调 DETR 很容易。来源:https://github . com/aivclab/detr/blob/master/fine tune _ detr . ipynb
结论
DETR 是物体探测领域令人激动的一步。它标志着先验知识的显著减少和简单、易于配置的网络架构。在大多数任务中,它的表现优于速度更快的 R-CNN,而不需要太多专门的额外工作,尽管它仍然比可比的单级对象检测器慢。其简单的结构使其易于根据研究人员提供的强大基线进行重建、实验和微调。
我在 Alexandra Institute 工作,这是一家丹麦非营利公司,专门研究最先进的 it 解决方案。在视觉计算实验室,我们专注于利用最新的计算机视觉和计算机图形研究。我们目前正在探索技术,以允许较小的公司和个人开始深度学习。我们永远欢迎合作!
脸书深度学习模型的训练效率
原文:https://towardsdatascience.com/training-efficiency-of-deep-learning-models-from-facebook-862816cd20da?source=collection_archive---------56-----------------------
影响深度学习推荐模型的关键因素
沙哈达特·拉赫曼在 Unsplash 上拍摄的照片
在脸书人工智能研究所发表的一项研究中,讨论了深度学习模型的训练效率,展示了与行业和学术界相关的模型架构和物理基础设施的数据。
深度学习模型效率的重要性
深度学习模型被科技巨头广泛使用。根据脸书人工智能研究公司的数据,以下公司利用深度学习推荐模型:谷歌、微软、网飞、阿里巴巴、脸书/Instagram。此外,像特斯拉汽车和 Waymo 团队这样的公司正在与 PyTorch 和 TensorFlow 一起做令人印象深刻的工作。从 Andrej Karpathy 关于特斯拉工作的视频中可以看到特斯拉的一瞥。该视频强调了用海量数据集训练深度学习模型的重要挑战。
从脸书人工智能研究看深度学习模型的效率
在论文“理解深度学习推荐模型在规模上的训练效率”中,脸书 AI Research 讨论了训练深度学习推荐模型的关键方面和挑战。我绝对鼓励读者深入研究那篇论文。然而,这篇文章似乎是强调那篇论文中发现的几个关键方面的最佳和合适的地方,这些方面可能对机器学习工程师和数据科学家有用。
首先,“并非所有的培训工作流都是相同的”,这直接来自论文,因为它们强调了培训持续时间的差异,这取决于输入模型的数据类型。下图描述了各种工作负载的培训持续时间和培训频率,即新闻馈送、搜索数据、语言翻译和人脸检测。
图片由作者提供,灵感来自脸书人工智能研究
可以看出,并非所有的训练工作流都是相同的,尽管这是一个相当直观的说法,但理解深度学习模型如何工作的特殊性是有用的。例如,语言翻译比搜索和新闻提要更难训练。
深度学习推荐模型的一个关键挑战是嵌入表格。脸书人工智能研究强调,嵌入表格有很大的内存需求,这激励了行业进一步开发他们的分布式训练系统。如果术语“嵌入表格”不清楚,我推荐读者查看这篇论文以获得进一步的解释(链接到期刊论文)。此外,谷歌机器学习速成班提供了一个关于嵌入的很好的教程(链接此处
另一个要考虑的重要特征是批量大小。根据 Goyal 等人(2018) 的说法,这是一个关键的超参数,直接影响训练表现和模型质量。总体而言,下图显示了批量大小如何影响脸书研究的深度学习推荐模型的准确性损失。
图片作者,灵感来自脸书人工智能研究
可以看出,批量越大,损失值越高。尽管 0.2%的损失看起来微不足道,但该期刊论文已经证明了 0.1-0.2%的损失对于推荐模型来说是不可容忍的(特别是在脸书的规模下)。
结束语
最后,我想鼓励读者通读这篇期刊论文,因为它有更多关于深度学习模型的其他挑战的数据,如硬件和系统配置。
总而言之,让我们记住批处理大小和嵌入表是需要记住的事情,至少对于大型数据集是如此。另外,请记住“并非所有的培训工作流程都是相同的”。
感谢您的阅读,感谢您对本文的任何反馈。你可以在我的 GitHub 页面上看到我在机器学习方面的公开工作,并随时关注我或通过 LinkedIn 联系我。
训练生成性对抗网络(提供代码)
原文:https://towardsdatascience.com/training-generative-adversarial-network-with-codes-2a6af80cf1f0?source=collection_archive---------23-----------------------
打造您的 GAN 系列——第 4 部分,共 4 部分
图片由com break来自 Pixabay
生成敌对网络(GANs)是强大的模型,它学习产生难以与现有真实对象区分的现实对象,如图像和音频(语音/音乐)。
在之前的教程中,我们已经看到了 GAN 中的两个组件——T4 发生器和鉴别器。
在本教程中,我们将合并生成器和鉴别器,并开始训练模型。
这是构建你的生成性敌对网络的第 4 部分:
第一部分:生成对抗网络背后的直觉
第二部分:甘鉴别器背后的直觉
第三部分:甘生成器背后的直觉
第四部分:训练生成对抗网络(本)
笔记本:训练甘生成手写数字
GitHub repo :包含本教程系列
鉴频器损耗
首先,我们给生成器输入一个随机噪声,生成器会产生一些假样本。这些生成的样本与来自数据集的真实样本一起被输入到鉴别器中。
鉴别器将试图区分样品是真的还是假的。这产生了将在二进制交叉熵损失函数中使用的概率,以与真实标签(真实或虚假)进行比较,并确定错误率和反向传播以更新鉴别器的参数。
发电机损耗
然后,我们来训练发电机。同样,我们将噪声向量输入生成器,它会生成一些假样本。这些假样本被送入鉴别器(这次没有真样本)。
鉴别器做出预测,产生这些样本有多假的概率。这些概率在二进制交叉熵损失函数中进行计算,以与真实标签进行比较,因为当鉴别器将这些生成的样本分类为真实时,生成器得分。根据错误率,我们将反向传播并更新生成器的参数。
训练循环
在训练过程中,我们交替进行训练,使得在任何时候只有一个网络被训练,在生成器和鉴别器之间交替。
我们的目标是确保两个网络具有相似的技能水*。因此,两个网络不能同时更新。否则,鉴别器的性能将优于生成器;因为鉴别器学习区分真假样本要比生成器学习生成样本容易得多。
两个网络都需要以相似的速度改进
为什么两个网络应该一起提高,并保持在相似的技能水*?如果鉴别器优于生成器,则所有生成的样本都被分类为 100%假的,因为“100%假”(概率1
假)损失函数对于网络学习是没有用的。因此没有学习的机会。
0.7
为假的概率对于网络在反向传播期间更新参数更有意义。(额外:在一个强化学习的情境中,任务是如此的困难,以至于无论代理做什么都失败了,才能给出任何奖励。)
同样,假设发生器优于鉴别器。在这种情况下,来自鉴别器的预测都是 100%真实的,鉴别器将没有机会学会区分真实和伪造的样本。
概括起来
鉴别器的目标是最小化真假样本之间的错误分类造成的损失。而生成器的目标是最大化鉴别者成为real
的概率。
在培训过程中,我们在生成器和鉴别器之间交替进行培训,以确保他们的技能水*相似。
笔记本:训练甘生成手写数字
GitHub repo :包含本教程系列
仅使用 JSON 训练 ML 模型
原文:https://towardsdatascience.com/training-ml-model-using-just-json-d69eb5d147c4?source=collection_archive---------20-----------------------
用尼龙创建自然语言表示的机器学习模型
阿瑟尼·托古列夫在 Unsplash 上的照片
机器学习建模是一项艰巨的任务,因为首先,我们需要准备数据,执行特征工程,为建模做好准备,然后创建不同的机器学习模型,以找出性能最佳的模型。但是,如果我告诉您,您可以使用 JSON 文件用几行代码完成所有这些工作,会怎么样呢?是的,你没看错。
我们只需要创建一个 JSON 文件,在其中定义目标变量和运行数据所需的模型列表。同样,我们也可以对数据进行预处理,在将数据传递给模型之前对其进行操作。在 JSON 文件中,我们只需要传递我们需要执行的操作的自然语言表示。
Nylon 是一个开源的 Python 库,它使用普通英语以 JSON 语法轻松构建机器学习模型。在这篇文章中,我们将探索尼龙及其功能。
让我们开始吧…
安装所需的库
我们将从使用 pip 安装尼龙开始。下面给出的命令可以做到这一点。
!pip install nylon
导入所需的库并创建尼龙对象
在这一步中,我们将导入创建 ML 模型所需的库。在执行任何操作之前,我们只需要初始化一个对象,并传递我们将要处理的数据的路径。在这里,我将向您展示如何创建一个对象并将数据传递给它。
from nylon import Polymer
nylon_object = Polymer('/content/diabetes.csv')
在这里,您可以看到我已经将数据集的路径作为参数传递给了对象。
创建 JSON 代码/文件
我们可以创建一个 JSON 文件或 JSON 风格的代码,用于建模。下面给出的代码创建了这个模型。模型的名称可以用作随机森林的“rf”,梯度下降的“sgd”,等等。
json_file = {
"data": {
"target": "Outcome"
},
"preprocessor": {
"fill": "ALL",
},
"modeling": {
"type": ["svms", "neighbors", "rf", "mlp","sgd"]
}
}
在这里,您可以看到我们已经传递了目标变量、预处理器和我们需要创建的所有模型。如果我们没有通过任何预处理程序,它会自动处理。通过运行这段代码,我们将能够创建 JSON 文件/代码,之后,我们可以通过传递 JSON 文件来运行 nylon 对象,这将运行模型。
nylon_object.run(json_file)
来源:作者
分析结果
在最后一步中,我们将分析我们创建的所有模型的结果,并查看哪个模型的性能最好。
nylon_object.results
结果(来源:作者)
在这里,我们可以分析所有模型的结果,并选择性能最佳的模型。尼龙非常容易使用,可以很容易地集成到机器学习工作流中。
继续尝试不同的数据集,并执行机器学习模型。如果您发现任何困难,请在回复部分告诉我。
本文是与 Piyush Ingale 合作完成的。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时联系我在 hmix13@gmail.com 或我的 LinkedIn 简介 。可以查看我的Github简介针对不同的数据科学项目和包教程。还有,随意探索 我的简介 ,阅读我写过的与数据科学相关的不同文章。
使用亚马逊 SageMaker 自动驾驶仪检测信用卡欺诈的训练模型
原文:https://towardsdatascience.com/training-models-to-detect-credit-card-frauds-with-amazon-sagemaker-autopilot-d49a6b667b2e?source=collection_archive---------14-----------------------
亚马逊 Sagemaker Autopilot 如何帮助你快速训练模型
米卡·鲍梅斯特在 Unsplash 上的照片
典型的数据科学项目生命周期经历许多阶段。第一阶段是理解业务和数据,随后是数据准备、模型训练、模型评估和生产部署。这些阶段并不简单。它们乏味、重复,并且仅限于少数有技能的个人,如研究人员、数据科学家和 ML 工程师。
实际上,数据科学家花大量时间做重复性的任务,比如清理、寻找和准备用于训练模型的数据。其中一些重复性的任务可以自动化。
对智能系统的需求持续增长,然而大多数组织缺乏资源来满足需求。许多企业都在争夺人工智能(AI)领域的稀缺人才,这一事实只会让情况变得更糟。
所有这些结合在一起使 AutoML 变得必不可少。AutoML 允许你将 ML 自动化并应用于商业问题。它为那些没有理论知识的人提供了 AI 开发的途径。
这篇文章将着眼于亚马逊的 AutoML 产品(亚马逊 SageMaker Autopilot ),并应用它来训练一个检测信用卡欺诈的模型。
如果你正在寻找这篇文章所用代码的 Jupyter 笔记本的链接,请点击这里。
亚马逊 SageMaker 自动驾驶仪
2019 年宣布, SageMaker Autopilot 是亚马逊的 AutoML 产品,允许你建立、训练端到端的 ML 模型。它通过浏览数据来简化您的任务,找到最适合您的数据的最佳算法,并为模型调整和训练准备数据。
自动驾驶仪为每次试验生成笔记本,因为它试图为你的数据选择最佳算法。这些笔记本显示了数据是如何争论的,以及模型选择过程的细节。这些笔记本还提供指导材料,教你关于训练过程和如何训练你自己的实验。
亚马逊 SageMaker 自动驾驶仪的一些好处
SageMaker Autopilot 的一些额外优势包括:
- ML 模型的自动训练
- 自动特征工程
- 提供培训过程的可见性
- 如何挑选候选人的逐步说明
- 如果需要,您可以灵活地手动调整您的模型
- 您可以从 UI 和 SDK 中使用它,从而为自动化留出空间。
虽然您可以使用 AutoML 来自动化机器学习(ML)过程以实现各种目的,如价格预测、流失预测、风险评估等。在本教程中,我们将使用亚马逊 SageMaker 自动驾驶仪来训练一个检测欺诈交易的模型。
亚马逊 SageMaker 自动驾驶仪的自动模型训练
欺诈交易有一些具体特征,可以通过学习将它们与合法交易区分开来。我不会在这篇文章中深入探讨这些特征。我们将使用托管在 Kaggle 上的现有公共数据集。该数据集包含 2013 年 9 月欧洲持卡人的信用卡交易。
对于本教程的其余部分,我们将遵循下列步骤:
- 在亚马逊 SageMaker 上创建一个笔记本
- 获取数据
- 检查数据
- 准备数据
- 创建一个亚马逊 SageMaker 自动驾驶作业
- 探索培训结果
在亚马逊 SageMaker 上创建新笔记本
登录 AWS 云,创建一个新的笔记本。如果您没有帐户,您可以在这里创建一个新帐户。
获取数据
要将数据集下载到您的笔记本,请按照以下说明授予您的笔记本对 Kaggle 的访问权限。
- 登录 Kaggle
- 单击您的个人资料图片,然后从下拉菜单中单击帐户。
- 向下滚动到 API 部分。
- 单击“创建新的 API 令牌”按钮,以 JSON 文件的形式下载一个新的令牌,该文件包含用户名和 API 密钥。
- 将 JSON 文件复制到~/。kaggle/该目录如下面的代码示例所示
!mkdir ~/.kaggle!echo '{"username":"your-user-name","key":"your-key"}' >> ~/.kaggle/kaggle.json !chmod 600 /home/ec2-user/.kaggle/kaggle.json
授予 Kaggle 笔记本访问权限
检查数据
用 panda 加载 CSV 数据并检查数据。
!kaggle datasets download -d "arockiaselciaa/creditcardcsv"dataset_path = './creditcard.csv'import pandas as pddf = pd.read_csv(dataset_path)
pd.set_option('display.max_columns', 500)
pd.set_option('display.max_rows', 10)
df
准备数据集
我们将做一些预处理。在此步骤中,我们将执行以下操作:
- 将数据分成训练和测试数据集
- 将拆分上传至 s3 时段
测试数据将用于稍后执行推理。
df = df.drop(['Amount', 'Time'], axis = 1)
train_data = df.sample(frac=0.8, random_state=200)
test_data = df.drop(train_data.index)test_data_no_y = test_data.drop(columns=['Class'])
test_data_no_y.head()
将训练数据集上传至 s3
train_file = 'train_data.csv'
train_data.to_csv(train_file, index=False, header=True)
train_path = session.upload_data(path=train_file, key_prefix=prefix + "/train")
print(f"Upload file to {train_path}")
我们将对测试数据集做同样的事情
test_file = 'test_data.csv'
test_data_no_y.to_csv(test_file, index=False, header=False)
test_path = session.upload_data(path=test_file, key_prefix=prefix + "/test")
print(f"Upload file to {test_path}")
创建亚马逊 SageMaker 自动驾驶作业
为了找到性能最佳的模型,我们首先需要配置自动驾驶仪的工作、输入数据和输出数据。
我们使用下面的代码片段配置自动驾驶仪的工作
auto_ml_job_config = {
'CompletionCriteria': {
'MaxCandidates': 5
}
}input_data_config = [{
'DataSource': {
'S3DataSource': {
'S3DataType': 'S3Prefix',
'S3Uri': 's3://{}/{}/train'.format(bucket, prefix)
}
},
'TargetAttributeName': 'Class'
}
]output_data_config = {
'S3OutputPath': 's3://{}/{}/output/'.format(bucket, prefix)
}from time import gmtime, strftime, sleep
timestamp_suffix = strftime('%d-%H-%M-%S', gmtime())auto_ml_job_name = f'automl-fraudcase-{timestamp_suffix}'
print(f"AutoMLJobName:{auto_ml_job_name}")
现在,我们创建实际的自动驾驶仪的工作
role = get_execution_role()
sm = boto3.Session().client(service_name='sagemaker',region_name=region)
sm.create_auto_ml_job(AutoMLJobName=auto_ml_job_name,
InputDataConfig=input_data_config,
OutputDataConfig=output_data_config,
AutoMLJobConfig=auto_ml_job_config,
RoleArn=role)
SageMaker Autopilot 分析数据集,以开发一个应在数据上尝试的 ML 管道列表。它还对数据执行要素工程,例如对每个数据集要素执行要素变换。最后,它执行模型调整,选择性能最好的管道。
您可以使用describe _ auto _ ml _ jobAPI将信息返回给 SageMaker 自动驾驶仪的作业。
我们将利用 describe_auto_ml_jon API 来监控正在运行的作业的进度,如下面的代码所示:
print('JobStatus Secondary Status')print('-------------------------------------')
describe_response = sm.describe_auto_ml_job(AutoMLJobName=auto_ml_job_name)
print(f"{describe_response['AutoMLJobStatus']} - {describe_response['AutoMLJobSecondaryStatus']}")job_run_status = describe_response['AutoMLJobStatus']
while job_run_status not in ('Failed', 'Completed', 'Stopped'):
describe_response = sm.describe_auto_ml_job(AutoMLJobName=auto_ml_job_name)
job_run_status = describe_response['AutoMLJobStatus']print(f"{describe_response['AutoMLJobStatus']} - {describe_response['AutoMLJobSecondaryStatus']}")
sleep(30)
使用最佳候选人进行批量推断
在训练了一些模型之后,这里,我们将使用 SageMaker 自动驾驶仪提供的最佳候选来执行批量推理工作。步骤如下:
- 从最佳候选中创建模型
- 使用 Amazon SageMaker 自动驾驶作业利用批量推理
您可以使用最佳候选项创建模型,如下所示:
model_name = 'automl-fraudcase-model-' + timestamp_suffixmodel = sm.create_model(Containers=best_candidate['InferenceContainers'],
ModelName=model_name,
ExecutionRoleArn=role)print('Model ARN corresponding to the best candidate is : {}'.format(model['ModelArn']))
创建一个匹配转换作业:
transform_job_name = 'automl-fraudcase-transform-' + timestamp_suffixtransform_input = {
'DataSource': {
'S3DataSource': {
'S3DataType': 'S3Prefix',
'S3Uri': test_path
}
},
'ContentType': 'text/csv',
'CompressionType': 'None',
'SplitType': 'Line'
}transform_output = {
'S3OutputPath': 's3://{}/{}/inference-results'.format(bucket, prefix),
}transform_resources = {
'InstanceType': 'ml.m5.4xlarge',
'InstanceCount': 1
}sm.create_transform_job(TransformJobName = transform_job_name,
ModelName = model_name,
TransformInput = transform_input,
TransformOutput = transform_output,
TransformResources = transform_resources
)
最后,您可以看到 Autopilot 试图为您的数据找到最佳算法时生成的模型列表,如下所示:
candidates = sm.list_candidates_for_auto_ml_job(AutoMLJobName=auto_ml_job_name, SortBy='FinalObjectiveMetricValue')['Candidates']
index = 1
for candidate in candidates:
print(f"{str(index)} {candidate['CandidateName']} {str(candidate['FinalAutoMLJobObjectiveMetric']['Value'])}")
index += 1
生成的笔记本
亚马逊 SageMaker Autopilot 生成笔记本,让你深入了解训练过程以及模型是如何选择的,如前所述。
你可以在这里找到生成的笔记本。
参考
信用卡欺诈数据集
亚马逊 SageMaker 示例
训练神经网络来预测排名
原文:https://towardsdatascience.com/training-neural-networks-to-predict-rankings-8a3308c472e6?source=collection_archive---------4-----------------------
根据人工智能模型对多标准决策分析排序数据的预测做出决策
您必须处理结构化数据并对您的“选项”进行排序的情况有多常见?更困难的是,如果你的数据不完整,你只能用你仅有的少量数据来预测排名,你会如何处理这个问题?
在这篇文章中,我将与你分享我对一个迭代过程的经验,这个过程导致了一个系统的和令人满意的方法来排列选项。在这里,我向您展示了一个应用于生物燃料相关问题和数据集的例子,但是该方法可以推广到其他类型的数据集。
由乔舒亚·戈德在 Unsplash 上拍摄的照片
介绍
人类在本世纪面临的挑战之一是从化石燃料能源转向可再生能源。生物燃料是解决油价持续上涨、温室气体减排和石油储备枯竭的少数几种方法之一。为了生产出质量合格的生物燃料,并确保其生产的可持续性,我们面临着一个挑战,即在给定的地点找到合适的原料。
如今,科学家已经报道了几种植物物种在生物燃料生产中的潜在用途。然而,到目前为止,还没有人对这些原料的所有需要测试的特性进行评估,包括燃料特性、发动机性能、排放特性、生产潜力等。用于评估生物柴油质量的参数由澳大利亚的燃料质量标准(生物柴油)测定 2019 和欧洲的欧洲标准 EN 14214 建立。十六烷值、每公顷作物产量或闪点是这些重要参数的三个例子。其他重要参数是生产效率,如油转化为生物柴油的转化率、含油量或产量。然而,这些参数在很大程度上取决于原料位置,因此,一个地区的完美解决方案可能与另一个地区的不同。
https://www.sciencedirect.com/science/article/abs/pii/S0196890419307721
总的来说,我们最终得到了一个涵盖数百个不同选项的 20 多个参数的数据集,但是我们如何为这些选项创建决策排序呢?
方法
本文将探索一种新颖的方法来对所谓的原料数据进行排序。使用 Scopus 和其他来源进行数据挖掘,收集的数据将被馈送到[深度神经网络](https://en.wikipedia.org/wiki/Deep_learning#:~:text=A%20deep%20neural%20network%20(DNN,weights%2C%20biases%2C%20and%20functions.) (DNN)系统,以预测原料的排名。
这是怎么回事?
这个想法是选择原料属性(信息最丰富的属性),并使用选择的原料设计一个多标准决策分析 (MCDA)排序方法来对我们的选项进行排序。该步骤的输出是数据集中代表每种原料等级的附加列。在此过程中,超过 20 个生物燃料参数(例如含油量、油特性、生物柴油特性,包括十六烷值等。)用于 106 种原料。我们使用等级数据来训练 DNN 系统,该系统可用于基于全套属性对新的(看不见的)原料集合进行分级。
如前所述,原料特性非常依赖于位置,因为它们受农业气候特征(如降雨量、温度、光照强度等)的影响很大。然后,通过替换 DNN 算法中的农业气候参数,可以将提议的方法/模型部署到其他位置,从而根据位置变化模拟产生预测。
MCDA 进程用于设置不同属性之间的优先级,它基于三个原则:
- 模型的结构
- 数据的比较判断
- 优先事项综合
三种技术用于创建排名,即加权求和模型(WSM)加权乘积模型 (WPM)和 TOPSIS 。
通过使用合适的深度学习方法来预测排名输出,并且随机选择数据用于训练和测试。使用了几种递增的详细技术,包括多变量回归 (MVR)、深度神经网络(DNN)和(前馈)多层感知器 (MLP),最后选择最佳执行模型。
MCDA+神经网络模型可用于对未知/看不见的原料进行排序,以测试它们在给定位置对生物燃料生产的适用性。
MCDA +神经网络系统
多标准决策分析(MCDA)
到这一点,如果你还和我在一起(lol),你可能会对问题和建议的方法有清晰的认识。
现在,最有趣的是,我们可以深入了解解决方案。
要开始,需要进行一些数据清理和格式化…
数据预处理后,我们可以看到大部分 NaN 单元格(左图灰色单元格)被填充…
数据预处理
一旦对数据进行了清理和预处理,就需要选择将哪些标准包含在 MCDA 中进行排名。
换句话说,我们必须决定哪些标准会影响我们的决策。
根据我们的数据完整性和行业标准,我们选择了 8 个相关标准来创建原料等级,并为每个标准分配了一个最小值或最大值标志,以确定是最小化还是最大化每个标准。
显示所选标准分布的小提琴图
所选择的标准属于不同的类别,即生物柴油特性、发动机性能和发动机排放。为了决定如何对我们的数据进行排序,必须根据上述标准分配权重。
然而,权重可能取决于您选择用来对决策进行排序的方法。例如,基于环境友好性的分级决策可能不一定与优化发动机性能的决策相同,或者类似地,优化经济性的决策分级可能不提供发动机性能的最佳解决方案,等等。
为了考虑这些方面,需要根据我们的决策类别建立一组不同的权重。
选择三组权重,即'发动机'、环境'和'经济。每组优先考虑一个特定的方面,按照这种方式,排名系统是根据优先考虑发动机、环境还是经济来指定的。在下面的例子中,我们选择权重=weights_eco 。
此后,包括所选标准的新的“决策数据框架被创建。使用 WSM、WPM 和 TOPSIS 计算决策等级,最后将它们连接到我们的“决策数据框架中。
通过在数据变量中使用不同的权重重复上述过程,获得以下等级表示。
决策等级
正如所料,它们之间有一些相似之处,但是权重的选择对决策排序有影响。生成一个决策等级数据集,它将用作训练神经网络的基础事实。
神经网络
首先,通过再次选择相关标准进行一些数据准备,然后初始化精度矩阵,并在训练神经网络时填充该矩阵…
1。多变量回归(MVR)
在直接进入“更深”的网络之前,尝试使用一种 MVR 方法,更具体地说是一种 最小绝对收缩和选择算子 ,在文献中称为 LASSO。决策标准被设置为因变量(X ),等级被设置为目标变量(Y)。进行几次迭代来调整套索参数,然后训练一个模型。R2 评分、MSQE 和 MAE 的准确性数据记录在准确性矩阵中。
MVR 的工作流程
2.自定义深度神经网络(DNN)
结果并不真正令人满意。为了改进我们的结果,我们对数据进行了简单的统计分析,以去除异常值。
然后,使用排除了异常值的新集合再次确定 X 和 Y 变量。数据在被送入 7 层 DNN 模型之前进行缩放,其架构如下所示。与 MVR 类似,模型的准确性根据 R2 评分、MSQE 和 MAE 进行评估,结果存储在准确性矩阵中。
DNN 模式总结
3.多层感知器(MLP)
尽管事实上 DNN 的实验是成功的,因为它显示出比 MVR 更好的性能,我试图拟合 MLP 回归到数据集。使用穷举网格搜索调谐(或交叉验证)超参数,以找到用于训练 MLP 的“最佳参数】。
MLP 工作流程
结果
在实现和训练之后,通过对训练集和测试集的预测来评估上述三个模型的性能。来自 MVR、DNN 和 MLP 的预测条形图报告如下。接着,还报告了精度矩阵。
总的来说,所获得的结果是令人满意的,并且在该方法的发展中注意到了明显的改进。
测试集上的预测
准确度矩阵
如果你对复制我的相同结果感兴趣,你可以在我的个人 GitHub 的回购中找到完整的脚本。
给回购打个星:)
经验教训
通常很难找到现成的 git-ready 解决方案来满足您特定的决策科学问题。我们回顾了从结构化数据预测排名的 MCDA+神经网络方法的框架和结果。该方法可推广到任何类型的结构化数据。然而,这种方法需要对问题的解释和理解来为你的决策建立权重。我相信这是一个 pro ,因为它允许用户根据自己的喜好定制决策等级,但它也是一个 con ,因为它需要手动调整权重。
你怎么想呢?
如果你在数据科学和/或人工智能项目上需要任何帮助,请随时通过 Linkedin 或 midasanalytics.ai 联系我
在反事实文本上训练自然语言处理模型
原文:https://towardsdatascience.com/training-nlp-models-on-counterfactual-text-ff1b2a4fffbc?source=collection_archive---------32-----------------------
西班牙语和阿拉伯语的再反射实验
今年年初,我上传了一个 seq2seq 模型来生成西班牙语的性别反事实(El professor viejo<->la profesora vieja)。从那以后,我调试了一些问题,做了一个通用库,并为阿拉伯语创建了一个初始的 seq2seq 模型。
目标是看看通过流程传递数据是否会创建更一般化的训练数据(数据扩充),从而提高准确性和公*性。
这篇文章和笔记本在 2021 年 7 月更新了一个新的、固定的 **random_state**
和一个更精确的 SimpleTransformers 版本。
训练阿拉伯语 seq2seq 模型
当我提出这个项目的阿拉伯语版本时, Wissam Antoun 推荐了一篇论文“自动性别识别和阿拉伯语再输入”。阿布扎比 NYU 大学的作者发布了他们改编自 OpenSubtitles 的*行性别语料库。这是少数几篇 NLP 和语言学论文中的一篇,这些论文称这种反事实构建实践为“再反射”。
对数据集的两大警告是:
- 它只有第一人称陈述,这意味着没有翻转一些名词和代词的训练数据(“你见过我的朋友吗?”)和有限的兴趣去翻动其他的词,比如‘母亲’或者‘经理’。
- 阿拉伯语电视和电影通常是埃及阿拉伯语,但其中一些字幕是志愿者翻译的。我没有用方言分类器测试数据集。
我基于最*的阿拉伯模型训练了几个 seq2seq 模型:来自 UBC NLP(温哥华)的 MARBERT 和来自 AUB MindLab(贝鲁特)的 AraBERT。我测试了一个方向的准确性(男性-女性或女性-男性句子翻转),然后是双向任务。我包括了一组有限的第三人称训练示例,但是没有进一步扩展它和编辑其他训练数据,没有一个模型能很好地处理这些。
最终,我在 HuggingFace 上发布了一个基于 MARBERT 模型的解码器和编码器。
数据扩充和基准
西班牙语
在西班牙语笔记本中,我过滤了一个现有的亚马逊评论数据集。我发现 BETO(一个单语西班牙模型)在预测评论的星级数方面优于 mBERT。
我有两个策略来使用这些性别再反应模型来增加和消除我的训练数据(数据扩充)。对我来说,哪种策略更好并不明显:
- 将翻转的示例添加到训练数据中——顺序稍后将被随机化,因此它们将与原始数据混合在一起
- 用反事实替换训练数据中的例子
对于 mBERT 来说,当作为一个分类器时,附加数据对问题的改善微不足道;替换数据取得了微小但更可衡量的改进(54.8%比 56.2%)。
重新思考我的方法
我对这个实验最大的担心是花费数小时通过 seq2seq 运行数千个例子。该库没有使用 GPU 来转换这些示例,因此您可以提前在本地运行它,但它对实验进行了甚至很小的调整和更改,这令人沮丧。
当我对阿拉伯语 seq2seq 模型和笔记本感到困惑时,我离开了这个问题,回来时没有理解我自己的代码。我决定写一个脚本( GitHub link )让这两种方法的实验变得更容易,并阅读我的阿拉伯语笔记本。
append_sequenced(
"monsoon-nlp/es-seq2seq-gender-encoder",
"monsoon-nlp/es-seq2seq-gender-decoder",
[[txt1, label1], ...],
seq_length=512, # cap length of input for model
random_state=404, # random state for scikit-learn
frequency=0.5, # fraction of examples to edit
always_append=False # append example even if unchanged by flip
)
replace_sequenced(
"monsoon-nlp/es-seq2seq-gender-encoder",
"monsoon-nlp/es-seq2seq-gender-decoder",
[[txt1, label1], ...],
seq_length=512,
random_state=404,
frequency=0.5
)
阿拉伯实验
我尝试的第一个数据集( ajgt_twitter_ar ,Jordanian Tweets)相当小,但所有分类器都得分很高,不可能显示数据增强的效果。
我最终使用的数据集( HARD ,Hotel Arabic-Reviews 数据集)包含评论和评级(0–3)。
将此视为一个回归问题,当附加示例时,新模型具有明显更小的误差(RMSE = 0.2442 至 0.1977)。
在替换时,误差介于前两次运行之间(0.2285)。
我在 Koc 大学(伊斯坦布尔)的 bert-base-arabic 模型上重新运行了这些测试。用一个模型及其嵌入生成示例,并将它们覆盖到另一个模型的嵌入上,可能会有好处[除非 seq2seq 模型基于每个模型会有相同的输出?].
未编辑时,追加时误差为 0.2694
,替换时误差略微降低至 0.2643
,误差也降低至 0.2523
此 seq2seq 步骤的用途
替换方法对西班牙分类模型的整体准确性有一个小的积极影响,而附加方法对阿拉伯回归模型总是有一个小的积极影响。当我们考虑整体准确性时,选择特定的模型或随机种子可能是一个更重要的选择。不幸的是,我在 2020 年测试中看到的积极结果很可能是错误的。
阿拉伯模型仍有很大的空间,可以通过更多的例子进行训练,并在翻转方面更加全面。
数据集的适用性
评论以第一人称编写,这有助于阿拉伯语 seq2seq 模型在第一人称对话文本上训练。因为评论是关于产品和地点的,所以评论文本可能较少提及性别和其他人。
当涉及到数据来源(员工评论、个人经历、艺术描述)时,更好的是有更多的多样性,或者更好的是,一个专门围绕这些语言的公*性或健壮性的数据集。
对于较小的少数群体来说,一个微小的准确度变化,甚至是对多数群体的负变化,都可能隐藏了显著的准确度变化,我们希望更好地打包和标记数据,以便我们可以衡量和了解如何为每个人提供最佳选择。
未来是菲利克斯
展望未来,我会对谷歌的新 FELIX 架构感兴趣:
与 seq2seq 方法相比,速度提高了 90 倍,同时在四个单语生成任务上取得了令人印象深刻的结果
更新?
这篇文章发表于 2021 年 5 月。有关任何更新,请参见GitHub 自述文件。
训练可证明鲁棒的神经网络
原文:https://towardsdatascience.com/training-provably-robust-neural-networks-1e15f2d80be2?source=collection_archive---------14-----------------------
思想和理论
用 GloRo 网防御对抗的例子
由恩里克·费雷拉在 Unsplash 上拍摄的照片
在过去的几年中,深度网络已经被广泛地证明容易受到攻击者的攻击,攻击者可以简单地通过向网络提供恶意扰乱的输入来导致网络犯下令人困惑的错误。显然,这为部署在野外的神经网络提出了具体的安全问题,特别是在安全关键的设置中,例如在自动车辆中。反过来,这激发了大量关于实际防御的工作,从攻击检测策略到旨在产生难以(或不可能)攻击的网络的修改后的训练例程。在这篇文章中,我们将看看我和我在 CMU 的同事们设计的优雅而有效的防御(出现在 ICML 2021 中),它修改了神经网络的架构,以自然地提供可证明的针对某些类别攻击的鲁棒性保证——在测试期间没有额外的成本。
我们将受我们的方法保护的神经网络家族称为“GloRo 网”(用于“ gl 全球- ro 半身像网络”)。对于那些对本文提出的想法感兴趣的人来说,一个用于构建和训练 GloRo 网的库在这里是公开可用的。
动机:对立的例子
尽管深度神经网络由于其令人印象深刻的理解大量高维数据并归纳出看不见的数据点的能力而迅速成为机器学习的代表,但早在 2014 年,研究人员就开始注意到,深度网络很容易通过对其输入进行难以察觉的修改而被愚弄。这些成功导致错误行为的干扰输入被称为对抗示例。下面是一个典型的对抗性例子。
一个典型的对抗性例子,改编自 Goodfellow 等人【2】,其中一幅熊猫的图像被不知不觉地操纵,以欺骗神经网络预测“长臂猿”。
一般来说,对于被认为是敌对示例的输入,它应该类似于一个类别(例如,“熊猫”),而被网络分类为另一个类别(例如,“长臂猿”)。这表明对输入的扰动应该是语义上无意义的*。这个要求相当模糊,并且与人类的感知有着内在的联系;这可能意味着变化对人眼来说是察觉不到的,或者仅仅是在给定的上下文中它们是不明显的。因此,我们经常考虑更明确定义的对立例子的规范;最常见的是,小规范对抗性例子。*
一个相反的例子是小范数*,如果它与原始输入的距离(根据某种度量,例如欧几里德距离)低于某个小阈值,通常用ε表示。从几何角度来看,这意味着原始点位于模型中的决策边界附*,如下图所示。就感知而言,当ε足够小时,与原始输入ε接*的任何点都将在感知上与原始输入无法区分,这意味着小范数对立示例符合我们对对立示例的更广泛要求。*
小范数对立例子的几何解释。图片作者。
虽然对立例子存在背后的确切原因不是本文的重点,但一些高层次的直觉可能会给出为什么这种现象在深层网络中如此普遍的一点想法。本质上,我们可以考虑网络的决策面*,它将网络的输出映射为其输入的函数。如果决策面在某个方向上很陡,当输入在那个方向上稍有改变时,网络会迅速改变它分配给输入的标签。由于深度网络通常在非常高维的空间(通常是数千维)中运行,因此存在许多不同的方向,在这些方向上,决策面可能是陡峭的,这使得任何点都有可能接*意外的“悬崖”。*
防御敌人
已经提出了许多防御措施来处理对抗性例子的威胁——尤其是小规范对抗性例子。虽然这些方法中有许多本质上是启发式的——也就是说,它们不保证告诉我们模型的预测何时或是否不能被操纵——但在最安全的应用中,这可能还不够好。出于我们的目的,我们对可证明的防御感兴趣。
第一个问题是,我们到底想证明什么?在小范数对抗例子的情况下,我们所追求的性质就是所谓的局部鲁棒性*。一个点上的局部鲁棒性, x 规定距离 x 为ε的所有点被赋予与 x 相同的标号。从几何学上讲,这意味着围绕 x 的半径为ε的球保证没有任何决策边界,如下图所示。根据这种直觉,应该清楚的是,局部鲁棒性排除了从 x 导出对立示例的可能性。*
局部鲁棒点的几何解释(以蓝色显示)。图片作者。
顾名思义,局部鲁棒性是局部的意思,它适用于单个点的邻域 x 。但是,对于整个网络来说,这意味着什么呢?通过检查,我们看到任何有趣的网络不可能在所有地方都是局部鲁棒的:如果所有点都远离决策边界,将没有地方放置边界,因此网络将不得不在所有地方进行相同的预测——这不是一个非常有趣的网络。
这表明,我们可能需要接受网络在某些地方不够健壮;只要网络在我们关心的地方——数据覆盖的区域——是健壮的,这就不是问题。因此,我们将认为一个模型是健壮的,只要在边界上有一个宽度至少为ε的边缘,将输入空间中被赋予不同标签的区域分开。
下图显示了健壮模型的一个示例。边缘(以黑色显示)本质上是一个“无人区”,模型通过用一个特殊的标签⊥(“底部”,一个有时用来表示空值的数学符号)来标记这些点,从而表明这些点不是而不是局部鲁棒的。理想情况下,没有“真实的”数据点(例如,训练点、验证点等。)躺在这无人区。
稳健模型决策面的可视化。这些类由宽度为ε的边距(标记为⊥)分隔开。图片作者。
构建全局鲁棒网络
GloRo Nets 背后的关键思想是,我们希望以这样一种方式构建网络,即自动在边界上强加一个边界。**
神经网络分类器的输出通常是所谓的 logit 向量,每个可能的输出类包含一个维度(即一个 logit 值)。网络通过选择对应于最高 logit 值的类来进行预测。
当我们跨越决策边界时,一个 logit 值将超过之前的最高 logit 值。因此,决策边界对应于最高 logit 输出出现*局的点。为了沿着边界创建边距,我们本质上想要加厚边界。每当两个最高的对数太接*时,我们可以通过声明*局来做到这一点;也就是说,除非一个 logit 超过其他 logit 至少δ,否则我们将认为该决定是*局。
我们可以让*局的情况对应于⊥类。这将创建一个无人区,根据需要将其他职业分开。但仍需确保该区域的宽度始终至少为ε(在输入空间中)。为此,我们将利用网络的李普希兹常数。
利用 Lipschitz 常数
一个函数的李普希兹常数告诉我们当它的输入改变时,函数的输出可以改变多少。直观上,我们可以认为它是函数的最大斜率或变化率。
因此,如果一个函数的 Lipschitz 常数是 K ,那么该函数的输出最多可以改变,如果其输入总共改变了ε,则ε K 。我们将利用这一事实在我们的网络决策面上强加一个正确宽度的余量。
由于神经网络实际上只是一个高维函数,所以我们也可以考虑神经网络的 Lipschitz 常数。为了简单起见,我们将每个 logit 值视为具有其自己的 Lipschitz 常数的不同函数(这将足以解释 GloRo 网络如何工作,但是该分析可以通过对整个网络的 Lipschitz 常数进行稍微更复杂的计算来加强;我们论文的附录提供了这些技术细节)。
我们现在回到我们之前的直觉,通过一个例子来演示如何构建 GloRo 网。
假设我们有一个在四个类之间进行预测的网络,它产生如下所示的逻辑。如果类别 1 和类别 2 的 logits 之间的差异足够大,则类别 2 将无法超过类别 1(类似地,类别 3 和类别 4 也是如此)。
图片作者。
如前所述,Lipschitz 常数告诉我们,当输入在半径ε内受到扰动时,每个 logit 可以移动多少。通过考虑等级 1 可以减少的量,以及每个其他等级可以增加的量,我们可以计算每个等级在预测等级(等级 1)上可以增加的量。然后,我们插入一个新的 logit 值,对应于⊥类,在考虑了每个类可以移动多少后,基于最具竞争力的类将其值取为类 1。
因此,我们有以下重要的性质:如果⊥ logit 在给定点是而不是最大 logit,那么我们保证该模型在该点是局部稳健的。另一方面,如果⊥ logit 是最大 logit,网络将根据需要预测⊥,指示该点位于类之间的边缘。
GloRo 网是如何构建的插图。红色箭头表示 1 级在ε半径内可以减少的最大量。橙色箭头表示类别 2、3 和 4(分别)在ε半径内可以增加的最大量。红色和橙色条结合起来给出了量δ,第 1 类必须超过其他类,以确保输入空间中的ε-余量。图片作者。
*似 Lipschitz 常数
虽然计算神经网络的精确 Lipschitz 常数在计算上是一个非常困难的问题,但是我们可以通过分解计算一次考虑一层来相当容易和有效地获得 Lipschitz 常数的上界。本质上,我们可以将每个单独层的 Lipschitz 常数相乘,以获得整个网络的界限。下图直观地说明了这种方法的工作原理。**
如何推导网络 Lipschitz 常数的逐层上界的图示。图片作者。
有趣的是,虽然这个界限在典型的网络上通常会非常松散——也就是说,它会极大地高估 Lipschitz 常数——因为界限计算被合并到学习目标中(下文对此有更多描述),但即使这个天真的逐层界限在 GloRo 网络上也相当紧密,GloRo 网络不是“典型”网络。这意味着使用 Lipschitz 常数的简单计算实际上是一种有效的方法,可以在类别之间施加足够的余量,以获得可证明的鲁棒性。
此外,在训练之后,Lipschitz 常数将保持固定。这意味着测试时认证不需要任何额外的计算来计算 Lipschitz 界限,使得认证实质上是免费的。与其他鲁棒性认证方法相比,这是一个主要优势,其他方法通常需要昂贵的计算来获得鲁棒性保证。
自然地捕捉一个强健的目标
方便的是,我们将⊥区域编码为一个额外的类的方式允许我们训练 GloRo 网来非常容易地优化可证明的鲁棒性。这一事实的关键在于,在 GloRo 网络中,鲁棒性是由精度来捕捉的。本质上,由于⊥在我们的标记数据上从来不是正确的类,通过训练网络变得准确(正如我们通常所做的),它避免了选择⊥,这反过来意味着它避免了不稳健。
带有代码的说明性示例
我们现在来看一个 GloRo Nets 的例子(要互动地跟随,请查看这个笔记本)。TensorFlow/Keras 中实现 GloRo Nets 的库在这里可用;它也可以与 pip 一起安装:
*pip install gloro*
使用gloro
库,我们会看到 GloRo 网构造和训练都很简单;它们为可认证的健壮模型实现了最先进的性能[1]。
我们将使用手写数字的 MNIST 数据集作为例子。这个数据集可以通过tensorflow-datasets
轻松获得。
*import tensorflow as tf
import tensorflow_datasets as tfds# Load the data.
(train, test), metadata = tfds.load(
'mnist',
split=['train', 'test'],
with_info=True,
shuffle_files=True,
as_supervised=True)# Set up the train and test pipelines.
train = (train
.map(lambda x,y: (tf.cast(x, 'float32') / 255., y))
.cache()
.batch(512)) test = (test
.map(lambda x,y: (tf.cast(x, 'float32') / 255., y))
.cache()
.batch(512))*
我们首先定义一个简单的卷积网络。用gloro
库构建 GloRo 网络看起来和在 Keras 中完全一样;唯一的区别是我们用GloroNet
类(而不是默认的 Keras Model
类)实例化它,这需要我们指定一个鲁棒性半径epsilon
。虽然GloroNet
模型类开箱即用地兼容任何 1-Lipschitz 激活函数(包括 ReLU),但我们发现对相邻神经元进行排序的MinMax
激活效果最好(原因超出了本文的范围)。
*from gloro import GloroNet
from gloro.layers import MinMax
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Inputx = Input((28, 28, 1))z = Conv2D(
16, 4,
strides=2,
padding='same',
kernel_initializer='orthogonal')(x)
z = MinMax()(z)z = Conv2D(
32, 4,
strides=2,
padding='same',
kernel_initializer='orthogonal')(z)
z = MinMax()(z)z = Flatten()(z)
z = Dense(100, kernel_initializer='orthogonal')(z)
z = MinMax()(z)y = Dense(10, kernel_initializer='orthogonal')(z)g = GloroNet(x, y, epsilon=0.3)*
然后我们可以编译这个模型。GloRo-Net 兼容的损失函数有几个选择,包括标准分类交叉熵,但我们通常发现Trades
损失(在gloro.training.losses
中找到)效果最好(不同损失函数的细节不在本文范围内)。
我们还发现clean_acc
和vra
度量对于跟踪进度很有用。净精度是忽略余量时模型达到的精度(即,如果我们不关心鲁棒性)。 VRA 或验证稳健精度是被正确分类并被证明为局部稳健的点的分数;这是健壮模型的典型成功标准。
*# Use TRADES loss with crossentropy and a TRADES
# parameter of 1.2.
g.compile(
loss='sparse_trades_ce.1.2',
optimizer='adam',
metrics=['clean_acc', 'vra'])*
最后,我们准备好让我们的模型适合我们的数据。gloro
库包含许多有用的回调函数,用于定义各种超参数的时间表;这些有助于在训练中获得最佳表现。例如,我们发现在训练过程中缓慢提高鲁棒性半径会产生更好的结果。
*from gloro.training.callbacks import EpsilonScheduler
from gloro.training.callbacks import LrSchedulerg.fit(
train,
epochs=50,
validation_data=test,
callbacks=[
# Scale epsilon from 10% of our target value
# (0.03) to 100% of our target value (0.3)
# half-way through training.
EpsilonScheduler('[0.1]-log-[50%:1.0]'),
# Decay the learning rate linearly to 0 half-
# way through training.
LrScheduler('[1.0]-[50%:1.0]-[0.0]'),
])*
就是这样!这导致了以下干净的精度和 VRA:
*test clean_acc: 99.1%
test vra: 95.8%*
摘要
GloRo 网通过在网络的构造中自动引入ε-margin,提供了一种优雅而有效的方式来防范小范数对抗示例。因为鲁棒性认证被自然地结合到网络的输出中,GloRo 网络可以很容易地被优化以获得验证的鲁棒性精度,并且可以在测试时执行本质上免费的认证。此外,因为用于证明网络的 Lipschitz 界限也被合并到网络中,GloRo 网可以使用简单、有效计算的 lip schitz 常数上限来实现最先进的 VRA。
参考
- 整体强健的神经网络。ICML 2021。 ArXiv
- 解释和利用对立的例子。ICLR 2015。 ArXiv
从合成数据训练问答模型(研究论文摘要)
原文:https://towardsdatascience.com/training-question-answering-models-from-synthetic-data-research-paper-summary-2220186703f?source=collection_archive---------37-----------------------
一个用合成数据训练的问答模型能打败 SOTA 吗??
图片来自来源
在这篇博客中,我尝试根据我的理解,从合成数据 中总结出论文 训练问答模型。请随时评论你的想法!
问题陈述
这项研究的重点是在处理有限的人工标注数据时,通过生成合成问题和答案来改进问答模型。与来自训练集的人工注释问题相比,作者在仅使用合成数据的 SQUAD1.1 问题回答任务上实现了更好的性能。
提议的方法
作者提出了由非条件答案抽取、问题生成和问题过滤组成的三步流水线。他们用于训练管道中所有三个组件的数据是 SQUAD 训练分割的一部分,并使用另一半从训练的组件中生成合成数据。一旦生成合成数据,他们就训练 Q/A 模型,并在 SQUAD 的开发集上测试其性能。下图显示了整个管道—
合成质量保证模型管道流|图片来自来源
答案生成— a' ~ p(a|c)
在这一步,他们提出了一个 BERT 模型,该模型学习在给定的上下文中提取答案跨度。他们只通过观察上下文而不是问题标记来训练这个模型*(这与典型的问答模型的训练方式有点不同)。通过这种方式,他们了解了数据集中答案的先验分布。如上所述,他们使用来自班的训练分割的(上下文和答案)对来训练该模型。*
他们通过联合学习开始和结束标记来对答案提取头进行建模,因为他们发现联合建模比单独对开始和结束标记进行建模的单个提取头执行得更好。数学上可以表示为—
答案生成模型
这里,a=(s,e)和 s,e,c 分别是开始标记、结束标记和上下文标记。首先,我们通过 BERT 模型传递上下文,并在输出端获取开始和结束令牌嵌入。然后,这两种嵌入表示被连接起来,并被传递到一个多层感知器模型,随后是 softmax,跨越可能的开始和结束跨度。目标是使这个软最大概率对于实际地面真实跨度更倾向于 1,而对于所有其他跨度减小到 0。所以,偏斜度越好,模型越好。
问题生成— q' ~ p(q|a ',c)
作为下一步的一部分,他们使用预训练的 GPT-2 语言模型来训练问题生成模型。它们将上下文标记、答案标记和问题标记连接成一个大的单个序列,由序列标记的结尾分隔。他们还在问题附*预先考虑并附加 :问题: 标记作为问题标记。此外,为了确保模型知道不同的输入段,他们定义了三种类型的段嵌入,每种数据类型一种。此外,他们还将答案片段嵌入到上下文嵌入中,帮助模型在上下文中定位答案跨度。如下图所示—
问题生成培训|图片来自来源
在推理过程中,它们提供上下文和答案标记,后跟 :question: 作为触发词,并采样直到下一次出现相同的触发词。
往返问题过滤—a’?a* ~ p(a|c,q ')
往返过滤的思想建立在过度生成然后过滤事物的动机上,其中,目标是从候选集中验证和选择最终问题。为此,我们首先在来自 SQUAD 的标记数据上训练一个问题回答模型 p(a|c,q ),这里 a、c、q 分别是答案、上下文和问题。然后在推理过程中,我们传递生成的问题和上下文来生成候选答案。并且基于候选答案是否匹配生成的答案*(步骤-1),选择或拒绝问题*。
推理流程
训练阶段完成后,我们继续进行推理阶段,其中,假设我们现在有了一个新的上下文,我们首先通过答案生成模型来生成答案。我们使用生成的答案和预定义的上下文,并将其传递给问题生成模型。一旦我们有了候选问题和答案,我们使用上下文和生成的问题来获得可能的候选答案。如果我们在此步骤中生成的答案与生成的答案*(步骤 1 的一部分)*匹配,我们认为生成的问题有效,而所有其他问题都被拒绝。下图显示了整个推理流程—
推理流程|作者图片
我的想法
我发现这是一个非常有趣的阅读,我觉得在合成数据上训练 Q/A 模型的想法不仅是在数据较少的情况下采取的一个好步骤,而且也可以用作特定领域 Q/A 微调之后的预训练步骤的一部分。此外,为问题生成系统尝试编码器-解码器模型(如 T5 等)而不是仅使用解码器模型将是一个很好的实验。
如果你愿意你也可以 查看我写的其他研究论文摘要 。
好了,这篇博客到此为止。如果你喜欢看视频而不是文字(就像我一样的:D),一定要去看看—
多看看这样的视频
请随意阅读整篇论文,并向作者问好,感谢他们的贡献。
论文标题: 从合成数据中训练问答模型
论文链接: 访问论文
作者: 劳尔·普里、瑞安·斯普林、莫斯托法·帕特瓦雷、穆罕默德·舒伊比、布莱恩·卡坦扎罗
另外,如果你喜欢读这篇文章,你可以选择 给我买一杯【柴】【https://www.buymeacoffee.com/TechvizCoffee】https://www.buymeacoffee.com/TechvizCoffee——因为我实际上不喝咖啡:)非常感谢!完全是可选的,自愿的:)
马科斯蒙特里的张量流训练速度
原文:https://towardsdatascience.com/training-speed-of-tensorflow-in-macos-monterey-3b8020569be1?source=collection_archive---------8-----------------------
M1 SoC 中的 GPU 训练与 Quadro RTX6000 中的结果以及 M1 Max SoC 中的评估进行比较
作者图片
[更新]2021 年 10 月 30 日
我上传了一组用于训练基准的 Python 代码和图片数据到我的 GitHub 。更多细节见本文底部。
背景
新的 OS,macOS Monterey,来了!我等这个新操作系统等了很久,因为 TensorFlow/Keras 模型的 GPU 训练(=更快的计算)将得到官方支持。这意味着我存储在 Windows 工作站中的深度学习代码将是活的,实际上在 macOS 机器中也是活的。
但是我现在不打算把我的生态系统完全转移到 Mac 上。我知道我的 MacBook Air M1(我用它来工作、学习、娱乐和处理私人事务)不够坚固,无法胜任如此繁重的任务。当然,作为一款日常使用的入门级笔记本电脑,我当然对它适当的功率和效率感到满意。此外,正如我过去的文章“M1 SoC 中的苹果神经引擎在预测方面表现出令人难以置信的性能”所述,M1 在我的研究所需的图像分割任务中表现出令人难以置信的预测(推理)速度。令人印象深刻的是,M1 足球在某些情况下击败了英伟达巨头 RTX。
然而,除了预测,训练任务复杂而繁重。的确,有时需要几天(不是几分钟或几小时!)用于在 Windows 工作站中使用十万幅图像进行培训。
在本文中,我将展示我的试验,在苹果的 M1 SoC 上对 TensorFlow/Keras 模型的 GPU 训练。我将速度与 Quadro RTX6000 和 M1 Max SoC 中的估计进行了比较。
现在,TensorFlow for macOS 支持蒙特雷的 GPU 训练!
方法
在 M1 SoC 的 CPU 和 GPU 上完成了图像分割的训练任务。我按照官方的步骤安装了 TensorFlow for macOS Monterey 。我在装有 nVidia 高端 GPU 之一 Quadro RTX6000 的 Windows 工作站上使用了相同的代码进行比较。此外,我还估算了 M1 Max SoC 的速度。我的估算很简单,将 M1 的计算时间除以 4,因为 M1 有 8 核 GPU,M1 有 32 核 GPU。
表 1。作者的特征和条件/图像
表 1 显示了测试条件,下面的屏幕电影是在 macOS Monterey 上的训练场景。
TensorFlow 2.6 在 macOS Monterey 上的 GPU 训练/图片由作者提供
结果
不出所料,M1 的 GPU 培训比 CPU 培训快两倍。对于尺寸为 512×512 像素的灰度图像,训练速度为 328 毫秒。这导致了十万张图片的 9 小时 6 分钟。屏幕电影显示 M1 正在使用其 GPU 的全部能力。
另一方面,RTX6000 显示了它在这个领域的力量,计算机图形学、CAD、数值模拟和深度学习领域。特别是 AMP(自动混合精度),这种计算技术同时使用 32 位和 16 位浮点数来实现比单一 32 位精度更高的速度和更低的内存消耗,显示出有效的增益。M1 足球必须接受十到二十倍落后(我从来没有说它慢)。
在 M1 Max 的后面估计通过它的 32 核 GPU 提高两到六倍(这是我的梦想估计)。
下表分别显示了 M1 SoC 的实际结果和我对 M1 Max 的估计。
表二。前两个时期的训练速度/图片由作者提供
表 3。作者对 M1 Max SoC / Image 中 32 核 GPU 训练速度的估算
讨论
我对这个结果感到欣慰。M1 足球“仅”落后十到二十倍。这个苹果的入门硅消耗 10 或 15W 的电力,而 RTX6000 对最大功率 295W 有很大的胃口!
在这种背景下,这种比较可能毫无意义。
然而,在 M1·马克斯看来,这是有意义的。事实上,结果(再次这是估计!)作为笔记本电脑芯片似乎不错,但苹果表示,新的 SoC 是为专业用途而设计的。“专业用途”一词意味着 M1 Max/Pro 和其他高端芯片应该在专业场合用于相同或至少相似的目的和/或目标。机器永远不可能在工作负荷的任何时刻说“这对我来说太重了”。即使是笔记本电脑,这样的用户也会期望相同的性能。
在这种情况下,M1 Max 可能不是我满意的选择。
用于 Windows 和 Linux 机器的 TensorFlow 已经开发了多年。nVidia GPUs 和 CUDA 库为性能提供了强有力的支持。我认为为苹果芯片实现的 TensorFlow 还不够优化。事实上,Core ML 和 Metal APIs,苹果公司用于高性能计算的纯 API,似乎将所有的 CPU,GPU 和 ANE(苹果神经引擎)用于其繁重的计算。上面的电影明显揭示了 Mac 上的 TensorFlow 只用 GPU。我认为,各种内核的综合使用是苹果 SoC 的具体优势。会留下很大的优化空间。
结论
- 我可以使用我的 smiley MacBook Air 在 M1 SoC 的 GPU 上训练我的 TensorFlow/Keras 模型。训练速度比在它的 CPU 上快两倍。
- 然而,与庞然大物 RTX6000 相比,SoC 并没有神奇的力量,而是取决于它的功耗。
- M1 Max SoC 的估算结果看起来和笔记本电脑一样好,但不足以满足我的使用=十万张图片的深度学习。
- 根据 TensorFlow for macOS 内核间任务分配的优化情况,这种情况在未来可能会有所改变。
不管怎样,不管结果如何,老实说,我想要一台新的 M1 Max MacBook Pro!:>
[更新]2021 年 10 月 30 日
我上传了一组 Python 代码和图像数据到我的 GitHub 。
注意:GitHub 中的文件与上面文章中使用的原始代码不同,因为原始代码包含研究信息。
下面的表 2+显示了从该释放组获得的结果。
表 2+。前两个时期的训练速度/图片由作者提供
用于释义生成的训练 T5
原文:https://towardsdatascience.com/training-t5-for-paraphrase-generation-ab3b5be151a2?source=collection_archive---------14-----------------------
使用 Imgflip 生成的图像
在我之前的博客中谈到了 TextGenie ,我提到了我在从零开始收集文本数据和使用 T5(文本到文本转换转换器)生成的释义作为扩充文本数据的方法之一时所面临的问题。看过模型的运行后,让我们来体验一下培训过程😉
如果您希望全程跟随我,您可以在我的 Github repo 上的这里找到培训笔记本。
**提示:**如果你没有 GPU,我建议使用 Google Colaboratory 来训练模型。
安装依赖项
在继续之前,让我们准备好所有需要的包,使用:
pip install simpletransformers datasets tqdm pandas
资料组
我们将使用 TaPaCo 数据集来完成我们的任务。该数据集由 73 种语言的总共 190 万个句子组成,我们将从中提取English
语言的句子。
预处理数据集(可选)
在将数据集输入模型之前,需要将其转换成成对的输入句子和目标句子。预处理的代码可以在这里以及笔记本中找到。
下载已经预处理的数据集
如果您不想对数据进行预处理,我已经为您完成了任务。你可以直接从这里下载数据集的预处理版本。
加载数据集
完成后,您可以按以下方式加载数据集:
import pandas as pddataset_df = pd.read_csv("tapaco_paraphrases_dataset.csv",sep="\t")
加载后,需要重命名数据的列。另外,我们需要给每个句子加一个前缀。这里,前缀可以是作为列添加的任何文本,每行具有相同的值。
# Renaming the columns
dataset_df.columns = ["input_text","target_text"]# Adding a prefix. Here we shall keep "paraphrase" as a prefix.
dataset_df["prefix"] = "paraphrase"
分割数据集
我们将以 90%-10%的比例分割数据集
from sklearn.model_selection import train_test_splittrain_data,test_data = train_test_split(dataset_df,test_size=0.1)
训练模型
该模型需要调整某些参数,如下所示:
从simpletransformers
初始化T5Model
类对象:
from simpletransformers.t5 import T5Model
import sklearnmodel = T5Model("t5","t5-small", args=args)
我们现在将采用t5-small
模式。让我们继续培训:
model.train_model(train_data, eval_data=test_data, use_cuda=True,acc=sklearn.metrics.accuracy_score)
使用训练好的模型进行加载和预测
模型训练可能需要几个小时。一旦培训完成,您可能会在outputs
目录中找到最终的模型。它可以加载为:
加载已训练的模型
from simpletransformers.t5 import T5Model
import osroot_dir = os.getcwd()
trained_model_path = os.path.join(root_dir,"outputs")args = {
"overwrite_output_dir": True,
"max_seq_length": 256,
"max_length": 50,
"top_k": 50,
"top_p": 0.95,
"num_return_sequences": 5
}trained_model = T5Model("t5",trained_model_path,args=args)
使用所训练的模型生成释义
让我们看看模型在我们的自定义输入下表现如何:
prefix = "paraphrase"
pred = trained_model.predict([f"{prefix}: The house will be cleaned by me every Saturday."])print(pred)#Output:[['My home will be cleaned on Saturdays.',
'I will clean the house every Saturday.',
'The house is going to be clean every Saturday.',
"I'll clean the house every Saturday.",
'I will clean the house every Saturday.']]
而且很管用!!耶!
T5 车型培训到此为止。我已经开源了预训练模型和预处理数据集,以便在我的 Github repo 上解释,如果你想探索它们的话。
感谢您的阅读😄
PyTorch 中训练时间序列预测模型
原文:https://towardsdatascience.com/training-time-series-forecasting-models-in-pytorch-81ef9a66bd3a?source=collection_archive---------29-----------------------
从培训许多不同领域的数百个 PyTorch 时间序列预测模型中获得的经验和技巧
来自 Unsplash 的照片
在过去的一年里,我使用流量预测在各种数据集(河流流量、新冠肺炎、太阳能/风能和股票价格)上训练了数百个 PyTorch 时间序列预测模型。经常有新手来找我寻求他们应该首先做什么的信息。本文是一些基本技巧的简要分类,您可以在训练时间序列预测模型时使用这些技巧。
框出你的问题
我经常看到很多关于时间序列 ML 技术的不同术语。在这里,我将试图澄清它们:
- 异常检测:这是一种检测时间序列数据中异常值的通用技术。究竟什么是异常本身是一个争论的主题,然而异常通常形成数据集的很小一部分,并且与其他数据点有本质的不同。最后,异常检测可以被视为二元分类的特定极端形式,尽管它通常被视为一个独立的领域。大多数异常检测方法都是无人监管的,因为我们通常不太可能在异常发生之前识别出异常。更多信息见本文。
- **时间序列分类:**类似于其他形式的分类,这是我们取一个时间序列,并想把它分成许多类别的地方。与异常检测不同,我们通常对每一类都有一个更*衡的样本数量(尽管它可能仍然有 10%,80%,10%的偏差)。
- **时间序列预测:**在预测中,我们通常希望预测时序数据序列中的下一个值或下(n)个值。这是本文将要关注的内容。
- **时间序列预测:**我不喜欢使用这个术语,因为它含糊不清,可能意味着很多事情。虽然我发现大多数人在这种情况下通常用它来指预测或分类。
- **时间序列分析:**一个可以包含以上所有内容的总称。然而,在我看来,我通常更多地将它与查看时间序列数据和比较不同的时间结构联系起来,而不是固有地设计预测模型。例如,如果您开发了一个时间序列预测模型,它可能会告诉您更多关于时间序列中的偶然因素,并支持更多的时间序列分析。
也就是说,在开始之前,你应该确定你的问题实际上是否是一个预测问题,因为这将指导你应该如何进行。有时,将预测问题转化为分类问题可能更好。例如,如果预测的确切数字不那么重要,您可以将其分成不同的范围,然后使用分类模型。此外,您应该对部署和最终产品有所了解。如果你的股票交易需要毫秒级的延迟,那么无论你的测试 MAE 是什么,一个有 20 个编码器层的巨大的 transformer 模型可能都不会起作用。
数据质量/预处理
- **始终缩放或规范化数据:**在 99%的用例中,缩放或规范化数据可以提高性能。除非你的值很小,否则这是你应该采取的步骤。F 低预测内置了易于使用的定标器和规格化器。未能缩放您的数据通常会导致损失激增,尤其是在训练一些变压器时。
- **仔细检查空值、编码不正确或缺失的值:**由于数据质量问题,我已经失去了很多时间和理智。有时缺失值以一种奇怪的方式编码。例如,一些气象站将缺失的 precip 值编码为-9999。这可能会导致很多问题,因为常规的 NA 检查不会发现这一点。流量预测确实提供了一个模块,用于插值缺失值和警告可能输入的数据不正确。
- **从更少的功能开始:**一般来说,从更少的功能开始,然后根据性能增加更多的功能会更容易。例如,当我预测 COVID 时,我从移动数据+新案例开始。随着时间的推移,我熟悉了工作的一般超参数,我添加了天气数据。
模型选择和超参数选择
- 可视化时间滞后以确定 forecast_history: 在时间序列预测中,无论模型如何,我们都有希望传递到模型中的历史时间步长数。这将因架构而有所不同,因为一些模型能够更好地了解长期依赖关系。然而,找到一个初始范围是有用的。在某些情况下,真正的长期依赖可能根本没有用。
- 从 达-RNN : 我发现达-RNN 模型创建了一个非常强大的时间序列基线。使用变压器可以超越它,但它们通常需要更多数据和更仔细的超参数调整。流量预测提供了一个易于使用的 DA-RNN 实施方案。
- **确定要预测的长度:**这是一个棘手的超参数,用于确定要搜索的值。首先澄清这是你的模型一次预测的时间步数。您仍然可以生成更长的预测,但这是通过追加以前的预测来实现的。一方面,如果你的目标是预测一个长范围的时间步长,那么你可能希望将它们直接计入损失函数。另一方面,同时拥有两个以上的时间步长会使模型混乱。在我的大多数超参数扫描中,我发现较短的预测长度效果很好。
- **从低学习率开始:**对于大多数时间序列预测模型,我建议选择低学习。
- **Adam 并不总是最好的:**我发现其他优化程序可以做得更好。例如,BertAdam 适合变压器类型的模型,而 DA-RNN 香草可以工作得很好。
稳健性
- 模拟运行不同场景的逐场分析。流量预测可以很容易地模拟不同条件下的模型性能。例如,如果您正在预测河流流量,您可能会尝试输入非常大的降水量值,并观察模型如何响应。或者如果你在预测
- **仔细检查热图和其他可解释性指标:**我看过几次模型,认为它们表现不错。然后,我检查了热图,发现模型没有使用预测中的重要功能。当我做进一步的测试时,很明显这个模型只是在学习记忆,而不是特征的实际偶然影响。
结论
时间序列预测是一个很难掌握的领域,尤其是使用 DL 模型。我希望这些提示对你如何提高性能有用。一如既往,随时留下问题和评论。
培训 vs 测试 vs 验证集
原文:https://towardsdatascience.com/training-vs-testing-vs-validation-sets-a44bed52a0e1?source=collection_archive---------0-----------------------
在机器学习的背景下讨论训练、测试和验证数据之间的差异
约翰尼斯·格罗尔在 Unsplash 上的照片
介绍
在机器学习项目中,我们通常需要考虑多个模型,然后选择最终用于对现实世界数据进行预测的最终模型。
在这个过程中,我们通常在原始数据集的子集上训练模型,原始数据集是模型用来从数据中学习的数据集。因此,我们需要以某种方式评估哪个候选模型基于特定的度量表现得更好,这些度量是基于项目的性质和我们要解决的问题在开始时确定的。最后,一旦选择了最终模型,我们还需要评估它是否能很好地推广到新的、看不见的数据。
为了能够训练模型、执行模型选择并最终评估最终模型以检查它是否能够很好地泛化,我们通常将原始数据集分成训练集、测试集和验证集。在下面几节中,我们将讨论它们在监督学习环境中的用途。
训练集
就规模而言,训练集通常是从原始数据集创建的最大的集,用于确定模型。换句话说,训练集中包含的数据点用于学习感兴趣的模型的参数。
在监督学习的背景下,所有的训练示例应该包括预测变量(即特征)以及相应的输出变量(即标签)。在训练阶段,您可以使用正确的标签来获得训练精度,然后与测试精度(见下文)进行比较,以评估模型是否过度拟合。
验证集
现在,在进行超参数调整和模型选择时,验证数据集非常有用。该组中包含的验证示例将用于找到所考虑模型的超参数的最佳值。
使用机器学习模型时,您通常需要使用不同的超参数值测试多个模型,以便找到能够提供最佳性能的最佳值。因此,为了客观地选择“最佳”模型,您需要对每个模型进行评估。
例如,在深度学习中,我们使用验证集来找到最佳的网络层大小、隐藏单元的数量和正则化项。
测试设备
现在,您已经通过执行超参数优化调整了模型,您应该最终得到最终模型。测试集用于评估该模型的性能,并确保它可以很好地推广到新的、看不见的数据点。
此时,您还应该将测试精度与训练精度进行比较,以确保模型不会过度拟合。这是两个精度“足够接*”的情况。当训练精度明显超过测试精度时,就很有可能发生过度拟合。
为什么我们需要验证集和测试集?
如果没有多个模型可供选择,那么验证集可能是多余的。在这种情况下,您只需要一个训练集和一个分割比为 75:25 的测试集。
但是,如果您需要执行模型选择,但忽略了验证集,最终模型的测试误差将小于实际(或真实)误差。因此,对最终模型的评估将会误导您的模型归纳为新数据点的能力。
当涉及超参数优化时,评估模型的另一种方法是使用 K 倍交叉验证。
同样重要的是要提到,一旦您在测试集上评估了模型,您就不应该对最终模型执行任何进一步的调整。如果这是你需要做的事情,那么你也必须再次重复前面的步骤。
最后的想法
在今天的文章中,我们讨论了在监督学习的背景下开发和评估机器学习模型时,使用数据集的独立子集的重要性。
总之,训练集通常是从用于模型拟合的原始数据集创建的最大子集。然后,验证集用于评估模型,以便执行模型选择。另一方面,测试集用于评估最终模型(在上一步中选择的)是否能够很好地概括新的、看不见的数据。理想情况下,训练集、验证集和测试集应该包含互斥的数据点。请注意,训练集、验证集和测试集之间的典型分割比约为 50:25:25。
如果您对如何在 Python 中将数据集分割成训练和测试子集感兴趣,请务必阅读下面的文章。
您可能感兴趣的其他文章:
使用谷歌人工智能*台和定制环境容器训练你的 ML 模型
原文:https://towardsdatascience.com/training-your-ml-model-using-google-ai-platform-and-custom-environment-containers-1531888cac3d?source=collection_archive---------17-----------------------
使用 Tensorflow、气流调度程序和 Docker 的完整指南
由 Setyaki Irham 在 Unsplash 拍摄的照片
G oogle AI *台允许使用各种环境进行高级模型训练。因此,训练您的模型非常简单,只需一个命令,如下所示:
gcloud ai-platform jobs submit training ${JOB_NAME} \
--region $REGION \
--scale-tier=CUSTOM \
--job-dir ${BUCKET}/jobs/${JOB_NAME} \
--module-name trainer.task \
--package-path trainer \
--config trainer/config/config_train.json \
--master-machine-type complex_model_m_gpu \
--**runtime-version 1.15**
然而,Google 运行时环境不时地被否决,你可能想要使用你自己的自定义运行时环境。本教程讲解如何在 AI *台训练上用自定义容器设置一个并训练一个 Tensorflow 推荐模型。
我的资源库可以在这里找到:
https://github . com/mshakhomirov/recommendation-trainer-customendocker/
概观
本教程将解释如何使用 WALS 算法训练一个user-items-ratings
推荐模型。
- 这是一个非常常见的例子,当用户对一些内容或产品进行评级,你需要向他们推荐类似的产品。
- 这是一个产品级代码示例,可以处理任意大小的用户评分矩阵。
本指南包含以下步骤:
- 本地环境设置
- 编写 Dockerfile 文件并创建自定义容器
- 本地运行 docker 映像
- 将图像推送到 GCP 集装箱登记处
- 提交自定义容器培训作业
- 用气流安排模型训练
先决条件:
- GCP 开发者帐户
- 已安装码头
- Python 2
- 云 SDK 安装完毕。
- 启用 AI *台培训&预测、计算引擎和容器注册 API。
创建上述资源将产生大约 0.20 美元的成本。完成后不要忘记清理。
训练数据集
我们用于培训的数据( repo )将如下所示:
作者图片
它非常类似于 MovieLens 评级数据集,但出于开发目的进行了简化。您可以将该模式应用于任何东西,包括 Google Analytics 页面视图或任何其他与产品/内容相关的用户活动。
第一步。安装 docker 后,您需要对其进行认证。使用
gcloud
作为 Docker 的凭证助手:
gcloud auth configure-docker
**第二步。**创建您的云存储空间,并设置您的本地环境变量:
export BUCKET_NAME="your_bucket_name"
export REGION=us-central1
gsutil mb -l $REGION gs://$BUCKET_NAME
提示:试着在同一个地区做一个项目中的所有事情。
**第三步。**克隆回购。
cd Documnets/code/
git clone [git@github.com](mailto:git@github.com):mshakhomirov/recommendation-trainer-customEnvDocker.git
cd recommendation-trainer/wals_ml_engine
**第四步。**写一个 dockerfile 文件
Docker 文件已经存在于此 repo 中:
这一点非常重要,否则您的实例将无法将模型保存到云存储中:
# Make sure gsutil will use the default service account
RUN echo ‘[GoogleCompute]\nservice_account = default’ > /etc/boto.cfg
使用这个 docker 文件,您将使用这些自定义环境依赖项构建一个映像:
tensorflow==1.15
numpy==1.16.6
pandas==0.20.3
scipy==0.19.1
sh
这些依赖版本是我使用定制容器的主要原因。
谷歌人工智能*台的运行时版本 1.15 有 Tensorflow 1.15 ,但不同的 Pandas 版本对于我的用例场景是不可接受的,Pandas 版本必须是 0.20.3。
第五步。建立你的码头工人形象。
export PROJECT_ID=$(gcloud config list project --format "value(core.project)")
export IMAGE_REPO_NAME=recommendation_bespoke_container
export IMAGE_TAG=tf_rec
export IMAGE_URI=gcr.io/$PROJECT_ID/$IMAGE_REPO_NAME:$IMAGE_TAGdocker build -f Dockerfile -t $IMAGE_URI ./
本地测试:
docker run $IMAGE_URI
输出将是:
task.py: error: argument --job-dir is required
这是正常的,因为这个图像将被用作我们的自定义环境,入口点是
“trainer/task.py”
例如,在推送我们的映像后,我们将能够在本地运行此命令:
gcloud ai-platform jobs submit training ${JOB_NAME} \
--region $REGION \
--scale-tier=CUSTOM \
--job-dir ${BUCKET}/jobs/${JOB_NAME} \
**--master-image-uri $IMAGE_URI \**
--config trainer/config/config_train.json \
--master-machine-type complex_model_m_gpu \
-- \
${ARGS}
并且 master-image-uri 参数将替换**运行时环境。**查看回购中的 mltrain.sh 了解更多详情。
**第六步。**将图像推送到 docker repo
docker push $IMAGE_URI
输出应该是:
The push refers to repository [gcr.io/<your-project>/recommendation_bespoke_container]
第七步。提交培训工作
运行 repo 中包含的脚本:
./mltrain.sh train_custom gs://$BUCKET_NAME data/ratings_small.csv — data-type user_ratings
输出:
这意味着您的培训工作已使用自定义环境成功提交。现在,如果你去谷歌人工智能*台控制台,你应该可以看到你的训练运行:
作者图片
使用 Cloud composer(气流)运行模型训练。
现在,让我们部署一个 Cloud Composer 环境来编排模型培训更新。
**步骤 8。**在您的项目中创建 Cloud Composer 环境:
export CC_ENV=composer-recserve
gcloud composer environments create $CC_ENV --location europe-west2
步骤九。
获取 Cloud Composer 为您创建的云存储空间的名称:
gcloud composer environments describe $CC_ENV \
--location europe-west2 --format="csv[no-heading](config.dagGcsPrefix)" | sed 's/.\{5\}$//'
在输出中,您可以看到云存储空间的位置,如下所示:
gs://[region-environment_name-random_id-bucket]
我的情况是:
gs://europe-west2-composer-recse-156e7e30-bucket
我们将在这里上传插件。
**第十步。**设置一个包含输出路径的外壳变量:
export AIRFLOW_BUCKET="gs://europe-west2-composer-recse-156e7e30-bucket"
第十一步。上传气流插件
在气流/插件文件夹中有两个文件。这些插件将作为助手模块来运行我们的 DAG 并提交培训作业。
gcloud composer environments storage plugins import \
--location europe-west2 --environment composer-recserve --source airflow/plugins/
第十二步。检查云作曲家权限
现在转到 GCP Cloud Composer Web UI,确保 Composer 的服务帐户拥有启动作业所需的所有权限,即 Cloud ML、BigQuery 等。您可以在 IAM 控制台中找到它。
另外,确保您的 Composer 环境安装了这些 PyPi 包:
作者图片
第十三步。上传你的 DAG 文件
将 DAG model_training.py
文件复制到 Cloud Composer bucket 中的dags
文件夹:
gsutil cp airflow/dags/model_training.py ${AIRFLOW_BUCKET}/dags
完成了。现在,我们可以转到 Airflow web 控制台并检查我们的作业。
访问 Airflow web 控制台
Airflow web 控制台允许您管理 DAG 的配置和执行。例如,使用控制台,您可以:
- 检查并更改 DAG 执行的计划。
- 在 DAG 中手动执行任务。
- 检查任务日志。
**第 14 步。**运行此命令获取气流控制台 uri:
gcloud composer environments describe $CC_ENV \
--location europe-west2 --format="csv[no-heading](config.airflow_uri)"
您会看到控制台网站的 URL,如下所示:
[https://za4fg484711dd1p-tp.appspot.com](https://z9d39afb484711dd1p-tp.appspot.com)
要访问 Cloud Composer 实例的 Airflow 控制台,请转到输出中显示的 URL。您将使用您的 DAG:
达格。作者图片
单击建议 _ 模型 _ 训练 DAG 并检查日志。如果一切正常,你会看到一些成功的活动。此外,您会注意到您的定制环境培训作业正在进行**。**
假设我们从 BigQuery 中提取训练数据,这将是 ML 管道的第一步。转到 model_training.py DAG 并取消对此的注释:
...
...
# t1 = BigQueryToCloudStorageOperator(
# task_id='bq_export_op',
# source_project_dataset_table='%s.recommendation_training' % DATASET,
# destination_cloud_storage_uris=[training_file],
# export_format='CSV',
# dag=dag
# )
...
...
...
*# t3.set_upstream(t1)*
这将允许从 BigQuery 表中提取和保存:
**<your-project>.staging.recommendation_training**
DAG 现在看起来像这样:
达格。作者图片
就是这样!我们已经建立了 ML 管道编排。
结论
我们刚刚使用 Airflow 设置了 ML pipeline 流程编排,在定制环境中使用 Docker image 进行培训。这一点非常重要,因为现在你不再依赖可能会被否决的 Google 运行时环境,并且你能够满足你的数据科学团队设定的任何定制运行时版本要求。此外,使用版本控制设置可靠的 CI/CD ML 管道要容易得多。
Apache Airflow 是一个优秀的管道编排管理器,其中每一步都依赖于前一步的成功完成。在本教程中,我们部署了一个 Google Cloud Composer 环境,其中我们的 ML 管道以有向无环图(DAG)表示,以执行模型数据提取和训练步骤。
推荐阅读
*[1]:https://cloud . Google . com/ai-platform/training/docs/custom-containers-training
*[2]:https://cloud . Google . com/ai-platform/training/docs/using-containers
*[3]:https://cloud . Google . com/SDK/g cloud/reference/ai-platform/jobs/submit/training #-master-image-uri
*[4]:https://github . com/Google cloud platform/cloud ml-samples/tree/master/tensor flow/containers/unsupported _ runtime
*[5]:https://cloud . Google . com/ai-platform/training/docs/reference/rest/v1/projects . jobs # replica config
*[6]:https://airflow.readthedocs.io/_/downloads/en/1.10.2/pdf/
使用深度学习训练您自己的消息建议模型
原文:https://towardsdatascience.com/training-your-own-message-suggestions-model-using-deep-learning-3609c0057ba8?source=collection_archive---------4-----------------------
照片由希望之家出版社-皮革日记工作室在 Unsplash
解释业务问题
随着*几年智能设备的出现,电子邮件和聊天已经成为我们今天生活的一个重要部分。每天,笔记本电脑和手机用户都会回复数百条信息,不仅仅是在工作场所,在个人生活中也是如此。这些回答中的大部分倾向于特定领域或需要上下文,但有很大一部分是通用的,由常见的词语组成,如“好的”、“哇”或“早上好”等。因此,我们的设备有一些额外的功能来帮助我们在这样的日常情况下响应收到的消息是有意义的。
谷歌已经有了这样一个机制,叫做智能回复,可以在 Gmail 中看到。智能回复通过对用户当前正在查看的消息提供 3 种可能的响应来工作。响应的长度通常少于 10 个标记,并且通常具有不同的语义意图。
在本文中,我们试图训练一个类似的深度学习模型,该模型将接受用户输入,并基于这些输入,输出 3 种可能的相关响应。
目录
- 数据来源
- 现有工作
- 初始方法
- 训练 LSTM 模型来预测响应标签
- 未来的工作
数据来源
互联网上充斥着可以用来训练我们模型的数据集。一个很好的选择是开放字幕数据集,可以从以下链接下载-
https://github . com/PolyAI-LDN/conversatile-datasets/tree/master/open subtitle
开放字幕数据集由 62 种语言的数千部电影的字幕组成。该数据集对于文本翻译任务的训练模型非常有帮助。
Opus 主页截图
这个数据集有一个小缺点,因为这个数据集中的句子是电影对白,所以它包含了大量的俚语文本,这是不可取的,因为我们需要我们的模型输出坚持一些质量标准。
Ubuntu 对话语料库是另一个很好的候选,它包括从 Ubuntu 的技术支持聊天系统中提取的大约 100 万个 2 人对话。这个数据集可以在下面的链接中找到。
https://github.com/rkadlec/ubuntu-ranking-dataset-creator
但是由于这个数据集中的信息倾向于过多地围绕 Ubuntu 技术支持,它由许多命令和 Ubuntu 相关的术语组成,因此我们的模型最终可能会稍微倾向于使用技术术语,而不是通用的、非技术的日常词汇。
最后,我们有话题聊天数据集,可以在下面的链接中找到
https://github.com/alexa/Topical-Chat
该数据集中的消息基于随机的主题,但是由于主题彼此之间有很大的不同,并且随着每次对话而变化,所以它不应该使我们的模型偏向任何单一的主题,因此该数据集对于训练我们的模型似乎是理想的。(尽管后来发现,早期的试验模型之一最终确实偏向于用与美国情景喜剧“The Simpsons”相关的文本进行响应,因为数据集中的一些对话主题与 Simpsons 有关。例如,当被问到“你好吗”时,模型会回答“我很好”。你喜欢看《辛普森一家》吗
在 Kaggle 上,同样的数据集也有一个稍微改动过的版本,链接如下
https://www . ka ggle . com/arnavsharmas/chatbot-dataset-topic-chat
正如页面上提到的,该数据集包含“基于人类知识的开放领域对话”,由 8000 多个对话和 184,000 多条消息组成。每条消息都分配有一个对话 ID,这很有用,因为它有助于只训练与输入文本相关的响应。
数据集中的一个对话样本(显然,话题与猫有关)如下—
- “猫呢,你喜欢猫吗?我自己就是狗迷。”
- “猫被称为家猫和野猫。他们让我们的世界变得非常干净,没有老鼠!”
- “是啊,猫可能很酷,但它们肯定会花很多时间睡觉。”
- "猫听到的声音太微弱或频率太高,人耳听不到."
- “我也听说了。嗯,和你聊天很愉快。祝你愉快。”
如上例所示,数据集中的一些响应可能过于具体,因此不能用作对更广泛的用户输入的响应。因此,我们还必须确保响应是通用的和非特定的,以便每个集合都提供最大的效用。
我们将使用来自 Kaggle 链接的数据集,因为大部分培训将在 Kaggle 上进行。Kaggle 在其笔记本中提供了 TPU 访问,从而将培训时间从几个小时大幅减少到了几分钟。
这个数据集在 Kaggle 上被命名为“聊天机器人数据集主题聊天”,是 CSV 格式,有 3 列-
- 对话 id
- 消息
- 感情
Kaggle 上数据集页面截图
列“ conversation_id ”是一个整数,表示消息所属的会话。“消息”列包含实际的句子,该句子或者是对话的开始,或者是对对话中先前消息的回复。“情绪栏表示 7 种情绪之一— 愤怒、好奇、伪装、恐惧、快乐、悲伤和惊讶。
为了训练我们的模型,我们将只使用数据集中的前两列,即 conversation_id 和 message。
现有工作
正如谷歌的智能回复文件中提到的,建立一个自动建议回复电子邮件的系统并不是一个积极研究的领域。为电子邮件提出自动回复建议并不完全是一个标准的机器学习问题,因此在这个方向上几乎没有任何工作。
初始方法
预处理和数据集准备
我们首先使用 Pandas 将所有消息加载到一个数据帧中。
加载数据框后,所有重复项都将被删除。
进行基本的预处理以去除所有标点符号。
然后,数据帧中的所有消息按照会话 ID 进行拆分和分组。我们创建了两个名为“input_texts”和“target_texts”的列表,并将会话组中的每条消息(少于 50 个单词)添加到“input_texts”中,将其后的消息(少于 10 个单词)添加到“target_texts”中。之所以只考虑 10 个单词或更少的消息作为目标文本,是因为我们希望捕获广泛和一般的语句,这些语句可以作为对各种用户输入的查询的响应。简短的目标文本,如“好的”、“哇”、“很高兴与你聊天”、“你也一样”,可以作为各种查询的合适响应。另一方面,像下面这样的长而具体的句子很少被用作回应
“来自这样一位才华横溢的歌手和舞者真是太棒了。我做梦也跳不出那样的舞。”
输入文本最多允许有 50 个单词,因为我们假设任何更长的句子都需要更详细的响应,需要上下文,在某些情况下还需要领域知识,因此不适合从我们的模型中获取响应文本。
过滤输入和目标文本
一旦输入和目标文本数组被填充,我们就标记和填充两个数组的每一项。标记化是自然语言处理中非常常见的任务,它将数组中的每个句子转换成更小的单元,并为该单元分配唯一的整数值。每个单元既可以是一个单独的单词,也可以是单词中的一个字符。每个单元被称为一个标记,因此这个过程被称为标记化。考虑一下“我爱咖啡”这句话。这句话可以用以下两种方式来标记—
字符标记—
i = 1,(空格)= 2,l = 3,o = 4,v = 5,e = 6,c = 7,o = 4,f = 8,e = 6
工作代币—
我= 1,爱= 2,咖啡= 3
在字符级标记化中,我们最终得到 8 个唯一的标记,而在单词级标记化中,我们得到 3 个标记。
为了训练我们的模型,我们使用了单词标记。
由于每个句子中的单词数量不同,因此数据集中每个项目的输入大小也不同。这是因为,很明显,数据集中有些句子较长,有些较短。现在,如果我们在训练期间一次只向我们的模型提供一个数组项目(即批量= 1 ),这是可以的。但是这将显著增加训练时间,因此不是优选的。
在填充中,单个标记化的句子以零作为前缀或后缀,以保持输入大小固定。这允许我们在训练中使用更高的批量值。
在下面的代码片段中,我们声明了一个标记化器,然后将它“安装”在目标文本数组上。这将为目标文本数组中的每个唯一单词生成一个令牌。一旦生成了标记,就通过将目标文本数组传递给“texts_to_sequences”函数,将其转换为标记数组。完成标记化后,使用函数“generate_padded_sequences”填充新创建的“target_sequences”数组。
在对输入和目标文本进行标记化和填充之后,我们训练我们的第一个模型,这是一个单词级 Seq2Seq 模型。
训练单词级 Seq2Seq 模型并使用波束搜索进行预测
Seq2Seq 模型是一个编码器-解码器框架,它接收一个输入序列(可以是字符或单词)并输出另一个序列。例如,输入可以是英语单词序列,输出可以是完全不同的语言(如法语或印地语)的单词序列。在我们的例子中,输入是用户的查询,输出是对用户查询的响应。
Seq2Seq 的工作原理是首先将输入序列输入编码器,然后将其转换为状态向量。
词级 Seq2Seq 模型
一旦状态向量准备就绪,解码器就将状态向量与第一个目标序列一起输入,该目标序列映射到任何指示序列开始的标记,例如—
训练后,可以“贪婪地”或通过使用波束搜索来进行文本预测。在贪婪方法中,来自较早时间步骤的具有最高概率的令牌(连同状态向量)被简单地馈送给模型,以获得当前时间步骤的输出。重复这个过程,直到从模型接收到作为输出的语句结束标记。
贪婪文本预测
另一方面,在波束搜索中,考虑前 K 个可能的记号(和它们相应的状态向量),而不是仅仅一个。然后,前 K 个表征和状态向量在下一个时间步骤中被馈送到模型,每个表征生成下一个前 K 个表征,从而导致 KK 个可能的输出。计算所有输出的组合概率得分(对于跨所有时间步长的令牌)。这个 KK 个输出的数组根据它们的分数排序(以降序方式),除了最上面的 K 个,所有其他输出都被排除。重复这个过程,直到模型为 K 个“束”中的每一个输出语句结束标记或最大输出句子长度限制。
Seq2Seq 是一个基于文本生成的模型,它为输入文本生成文本输出。文本生成模型的一个问题是,有时模型可能会给出太不正式或不适合电子邮件的响应(例如,“好啊”,“非常感谢兄弟”)。在某些情况下,输出也可能是令人不快的(例如,“迷路”)。这是基于文本生成的模型的主要缺点之一。
除此之外,我们还能如何开发 LSTMs 的巨大潜力,同时确保在模型响应时始终保持特定的质量标准?
一种方法是根据预定的响应集训练我们的模型,该响应集只包含满足所有质量响应的响应。对于使用来说被认为太不合适或太不正式的回答可以从数据集中移除,从而确保满足所有标准。一旦排除了所有不需要的响应,剩余的集合可以被分配标签,然后可以被用作训练模型的目标,输入是用户输入的文本。如果在生产环境中使用这种模型来提供某种服务(例如,为银行应用程序提供聊天机器人支持),这种方法可以帮助我们确保所有响应都限制在所提供的服务范围内。这种方法的另一个优点是这些标签中的一些可以被映射到一些功能上,从而代替文本输出,执行一个任务。例如,继续我们前面的例子,在银行环境中,一个标签可以被映射到获取客户的银行账户余额。因此,当用户输入诸如“我的银行账户余额是多少”之类的任何文本时,(假设)客户的实时银行余额被获取并显示给他或她。
然而,这种方法的挑战是生成只包含适当响应的理想“响应集”。另一个挑战是将这样的响应集标签映射到训练数据集中的各个输入文本。
以下几节解释了我们可以在某种程度上克服上述挑战的方法之一。
训练基于响应集的 LSTM 模型
如上所述,响应集是语义相*的句子的集合,这些句子优选地具有 10 个或更少的标记(在我们的情况下),并且是通用的、非特定的句子,可以作为对各种用户输入的输入的有效响应。由于我们拥有的唯一数据是数据集中的消息,我们面临的任务是过滤出特定的响应,然后将所有语义相*的消息分组到单独的集群中。
实现这一点的一个方法是—
- ****将目标句子转换成向量(即句子嵌入)——应用某种算法将目标信息转换成它们的 N 维表示。
- 对向量进行聚类 —使用聚类算法将 N 维空间中的邻*点分组在一起,以创建一组聚类或响应集。一旦点(即句子的向量表示)被聚类,每个聚类可以被分配一个标签。
- 将聚类标签映射到输入文本 —将每个目标句子映射到一个聚类的标签现在可以用于将相应的输入文本映射到这些聚类。一旦映射完成,我们就可以用这个新的数据集训练一个 LSTM 模型,在给定一个输入文本的情况下预测一个聚类标签。
关于这种方法的更多细节可以在下面的章节中找到。
将目标句子转换成向量
我们的输入和目标文本数组中的句子可以通过使用以下任何一个库转换成向量
- ****sent 2 vec—https://github.com/pdrm83/sent2vec
Sent2Vec 可以看作是广泛使用的 word2vec 库的扩展。Word2vec 将单词转换为固定长度的向量,这样语义相似的单词,如“美丽的”和“有吸引力的”或“愤怒的”和“狂怒的”在向量空间中更接*。我们可以使用 word2vec 通过使用单词袋等技术来表示句子,但是这种方法不考虑句子的顺序和整体含义。因此,需要一种更复杂的方法来将所有消息转换成向量。这就是 sent2vec 的用武之地。
句去矢
Sent2vec 将句子编码成有意义的格式,这种格式考虑了单词的顺序和句子的整体语义。
因此,Sent2vec 是一个不错的编码器,可用于对数据集中的消息进行编码。然而,当试图在 16GB 的机器上编码 21,000+数据集句子时,sent2vec 在编码时不断耗尽内存,最终导致笔记本崩溃。经过多次试验,发现 sent2vec 最多只能编码大约 5000 个句子。由于 5000 个句子不足以训练我们的模型,因此需要另一个可以编码 21,000+个句子的库。
****2。惹恼—https://github.com/spotify/annoy/
Yeah 上的骚扰或*似最*邻居是 Spotify 开发和使用的一个库,用于提供音乐推荐。ANNOY 能够在几分钟内成功地对所有 21,000+点进行编码。
这个库使用欧几里德距离、曼哈顿距离、余弦距离、汉明距离或点(内)积距离来解决 N 维空间中最*邻搜索的问题。给定一个查询点,库搜索接*这个点的点,并且使用非常少的内存。
以下代码片段返回数据集中所有消息的 N 维向量—
" inputanoyindex . build(100)"构建一个由 100 棵树组成的森林。一旦构建完成,inputAnnoyIndex 就可以用于查找与给定点最*的 k 个点。
下面我们随机向库输入一个查询点索引,它会返回几个相似的句子。
当然罗,你看过《功夫》吗?是的,我也是。你看过《功夫》吗?你看过功夫吗
使用同样的方法,我们为输入文本和目标文本生成一个简单的相似性矩阵。
在下一步中,我们使用这个相似性矩阵将数据集中所有相似的句子聚集在一起,并为每个聚类分配标签。
聚类语义相似的句子
聚类语义相似的句子是至关重要的一步,因为它让我们生成响应集。为了生成响应集,语义上彼此接*的句子被分组到单个簇中(或者换句话说,一个响应集)。以这种方式,数据集中的所有目标句子被分组到多个响应集合中,并被分配唯一的标签。
聚类语义相似的句子
一旦分配了标签,我们就根据目标文本的标签在输入文本上训练模型。
在前面的步骤中生成的句子相似性矩阵的预览如下所示
为了将所有相似的句子聚类在一起,我们使用 DBSCAN(带噪声的基于密度的应用空间聚类)算法,这是最广泛使用的聚类算法之一。使用 DBSCAN 算法而不是其他聚类算法(如 K-Means)的原因之一是,给定某个空间中的一组点,DBSCAN 将密集邻域中的邻*点组合在一起,并自行得出聚类数。这很方便,因为我们不知道我们的目标文本数组包含多少“响应集”或相似句子集。我们将使用 scikit-learn 的 DBSCAN 算法实现来满足集群需求。更多细节可以在下面的链接中找到——
【T2https://sci kit-learn . org/stable/modules/generated/sk learn . cluster . DBS can . html****
然而,在我们开始 DBSCAN 之前,参数“eps”必须是固定的,它是两个点之间的最大距离,以便被认为是彼此的邻域。这很重要,因为如果 eps 值太小,将不会发生聚类,所有点都将被标记为噪声。另一方面,如果 eps 选择得太大,它会导致所有点合并成一个大簇。因此,必须将 eps 的最佳值传递给 DBSCAN 算法,使得只有语义接*的句子被分组,而将其他不相关的句子作为噪声排除在外。
为了做到这一点,我们首先尝试通过使用熊猫的“n 最小”函数来估计每个点的第 10 个邻居的距离分布。
一旦我们对所有点的第 10 个邻居的距离的分布有了一个公*的想法,我们通过尝试多个 eps 值并捕获每个 eps 值的聚类和噪声点的数量来更深入地挖掘。
我们绘制了 Y 轴上的聚类数/噪声与 X 轴上的 eps 值的关系图。
聚类数/噪声与 EPS 的关系
基于观察,我们认为 0.006 是运行 DBSCAN 算法的 eps 的合适值,该算法最终给出 881 个语义相似句子的聚类。
有关 881 集群的更多详细信息,请点击下面的链接。
https://www . ka ggle . com/great rxt/smart-reply-clustering-asury-output
训练模型
这是最关键的步骤,其中我们训练单层 LSTM 模型来接受输入文本并预测目标聚类标签。
模型预测工作流程
模型架构非常简单,第一层是一个嵌入层,它接受一个整数(代表数据集词汇表中的一个单词),并将其转换为该单词的 512 维密集矢量表示。下一层是 LSTM 层,后面是辍学率为 20%的辍学层。最后一层是具有 sigmoid 激活的致密层。一旦输入文本,密集层输出每个标签的概率。
该模型被训练 25 个时期。在配备 16 GB RAM 和第六代 I7 处理器的标准笔记本电脑上,每个纪元需要大约 50-60 分钟才能完成。因此,25 个纪元的训练需要一整天。如果我们的模型需要微调,因此需要一次又一次地训练,这会使训练变得有些乏味。因此,使用 TPU 加速器,在 Kaggle 笔记本上完成了 25 个时期的全部训练。一旦笔记本中的加速器选项切换到“TPU”,我们使用以下代码片段来启用 TensorFlow Keras 中的 TPU 培训。
我们实例化一个 TPUStrategy,然后在这个 TPUStrategy 的范围内实例化我们的模型。
一旦模型被训练,我们保存它以便以后使用。
模型损失与历元数的关系
左边的图显示了模型损失与模型被训练的时期数的关系。
我们使用下面给出的函数“get_response”来获得文本输入的输出。该函数从用户处获取输入文本,并将其提供给模型。该模型进而预测每个分类标签的概率。然后以降序方式对概率进行排序,并且仅考虑具有前 5 个概率分数的标签(predictions . arg sort()[0][::-1][:n])。
一旦我们有了具有前 5 个概率分数的聚类标签,我们就遍历每个聚类,并从每个聚类中随机选取任何句子,并将其作为可能的响应显示给用户。
最终输出
我们模型的一些样本输出(以及每个响应的概率分数)如下所示
请注意,在生产设置中,得分为 0 的回答将被忽略。
****
未来工作
对输入文本和目标文本进行词干/词尾排序
词干化是一种文本标准化技术,它通过删除常见的后缀或前缀来切断单词的结尾或开头,而词汇化则在将单词简化为其根单词之前考虑单词的形态分析。使用这样的技术,输入文本可以被标准化,然后输入到模型中,有望得到更好的预测。类似地,目标文本也可以被规范化,以便聚集相似的聚类并增加每个聚类的点数。
剔除点数较少的聚类
一些聚类具有非常少的点(只有 2、3 个点),因此不足以训练模型。通过将 DBSCAN 中的“min_samples”设置为更高的值(大约 50),可以删除这些点。但是这将减少响应集的数量。这个问题可以通过向我们的数据集添加更多的点来解决,如下所述。
使用附加数据集进行训练
合并额外的数据集可以帮助我们在每个聚类中获得更多的点。看起来 21,000+个点足以训练我们的模型,但是这些点分布在 880 个集群中。因此,一些聚类只有很少的训练点,这使得数据集非常不*衡。
通过合并更多的数据集来增加更多的点可能会解决这个问题。
结论
有人可能会说,使用响应集而不是传统的基于文本生成的方法来训练深度神经网络限制了它们的巨大潜力。这是真的,因为使用响应集训练的网络将只有有限数量的响应,无论模型架构有多好或训练有素。另一方面,与我们当前的模型相比,一个训练有素的具有良好架构的模型可以给出更好、更多样的建议。
但是,正如已经解释过的,即使是最好的模型有时也会偏离轨道,并给出不适当的响应,这在生产设置中可能是不期望的。因此,在深度神经网络变得足够好以准确处理人类给出的任何类型的输入文本之前,我们可能不得不退回到这样的替代方法,以保证在现实世界的场景中遵守所需的标准。
GitHub 链接
完整的代码可以在 GitHub 上找到,链接如下
**【https://github.com/greatrxt/deep-suggestions **
作者的 LinkedIn 个人资料
https://www.linkedin.com/in/rakshitpujari/
参考文献
https://www.appliedaicourse.com/
https://towardsdatascience . com/lemma tization-in-natural-language-processing-NLP-and-machine-learning-a 4416 f 69 a7b 6
https://blog . bitext . com/what-is-difference-thanking-and-lemma tization/
https://sun Jackson . github . io/2018/06/19/a3f 95 a 167 B4 a 350 a 82 CB 523478 e 89 b 16/
https://blog . keras . io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras . html
https://keras.io/examples/nlp/lstm_seq2seq/
https://www.aclweb.org/anthology/W15-4640.pdf
谷歌的聪明回复—https://www.kdd.org/kdd2016/papers/files/Paper_1069.pdf
https://Lena-voita . github . io/NLP _ course/seq 2 seq _ and _ attention . html # main _ content
https://machinelementmastery . com/beam-search-decoder-natural-language-processing/
https://en.wikipedia.org/wiki/Beam_search
用 Wav2Vec2 抄写诗歌和演讲
原文:https://towardsdatascience.com/transcribing-poetry-and-speeches-with-wav2vec2-2658c6510f06?source=collection_archive---------30-----------------------
迄今为止,音频文件的有效转录一直是现代 NLP 中主要的“缺失环节”之一。进入拥抱脸的脸书 Wav2Vec2 模型的实现,它产生了令人印象深刻的开箱即用的结果。
2021 年 1 月 20 日,诗人阿曼达·戈尔曼发表就职诗。通过 PBS NewsHour 的 YouTube 剪辑截屏。
AI 自己写不出伟大的诗歌(还不行?).但是它现在可以很好地转录诗歌朗诵,如果从 Wav2Vec2 变压器模型得到的结果是什么的话。
我使用长度从 62 秒到 12.5 分钟不等的音频剪辑进行了测试,包括青年诗人阿曼达·戈尔曼的令人回味的就职诗,结果令人印象深刻。
高效的音频到文本转录是现代自然语言处理(NLP)工具包中“缺失的环节”之一。现在看来不再是了,这要归功于拥抱脸对脸书的 Wav2Vec2 模型的实现。
令人兴奋的是,它开辟了从音频文件到文本情感分析甚至翻译的“链式链接”NLP 任务的新可能性。这里需要注意的是,长音频剪辑以这种方式处理时确实是内存密集型的,对于没有超级电脑的人(比如我)来说需要额外的工作。
这篇文章概述了我最*试验的结果,并包括一个 repo 的链接,里面有笔记本和样本文件来运行你自己的试验。你可以在这里查看两个长片段的输出结果。
回购、要求和参考
我的 repo 包含 3 个笔记本(2 个 Jupyter,1 个 Colab)和 3 套音频文件。要运行它们,您需要:
- 变压器≥ 4.3
- Librosa (管理音频文件)
repo 中的音频文件已被拆分并向下采样至 16kHz。如果您希望使用自己的音频剪辑,请确保它们以 16kHz 采样,因为这是 Wav2Vec2 基本模型预先训练和微调的频率。
每个音频剪辑应该有多长?这将取决于你所能处理的计算量。Wav2Vec2 转录过程非常占用内存。试图转录超过 90 秒的音频文件都崩溃了,即使是在 Colab Pro 上。
因此,我将音频剪辑保持在最大 60 秒左右。要处理较长的音频片段,你必须将它们分成相等的部分,每部分一分钟(或者你的机器可以处理的任何东西)。我们稍后再讨论这个。
在我的试验中,我使用了 Audacity 来分割音频文件。它是免费的,对于手头的任务来说绰绰有余。
在这篇文章中,我不会深入讨论技术细节。但是关于 Wav2Vec2 的文档和论文值得一读:
- 关于拥抱脸的文档
- 关于 wav2vec 2.0 的论文:语音表示的自我监督学习框架
- 托管推理拥抱面上的 API
在 Hugging Face 的 model hub 上有几个版本的 Wav2Vec2 模型。对于这个练习,我坚持使用 wav2vec2-base-960h 基本型号。
尝试 1:“问问你能为你的国家做些什么”
1961 年 1 月 20 日,美国前总统约翰·肯尼迪发表就职演说。通过 JFK 总统图书馆和博物馆网站上的视频截图。
试用 Wav2Vec2 的最简单方法是使用一个小的音频剪辑,该剪辑对于模型来说可以相对快速地一次性转录。我从已故美国总统约翰·肯尼迪 1961 年著名的就职演说(第 13 分钟开始)中挑选了一个 62 秒的片段,这是 Wav2Vec2 的文字记录:
在漫长的世界历史中,只有少数几代人被赋予在自由面临最大危险时捍卫自由的职责。我不会逃避这一职责,我欢迎这一职责。我不相信我们中的任何人会与任何其他民族或任何其他一代人交换位置。王锷为此付出的精力、信念和奉献精神将会使我们的国家和整个世卫组织为之服务 那团火发出的光芒和真的像世界,所以我的美国同胞不要问你的国家能为你做什么,问你能为你的国家做什么****
Wav2Vec2 抄本中的粗体部分是有问题的部分。总的来说,在我看来,结果令人印象深刻。但是,在一个更长的音频剪辑中,如果说话的口音和节奏发生变化,该模型将如何表现呢?
试验 2:“我们攀登的山”
2021 年 1 月 20 日,诗人阿曼达·戈尔曼发表就职诗。通过 PBS NewsHour 的 YouTube 剪辑截屏。
为了与第一次审判形成鲜明对比的第二次审判,我提前 40 年跳到另一个美国总统就职典礼,并挑选了一个 5 分 34 秒的阿曼达·戈尔曼在美国国会大厦的台阶上发表一首美丽而令人回味的诗的片段。
然而,试图一次转录 334s 片段被证明是徒劳的,内存不足的问题反复破坏了我的笔记本。我最终找到了一个简单但笨拙的解决办法,将原始剪辑分成更小的 35 个剪辑,一次转录一个。见本笔记本。
这是来自 Wav2Vec2 的文字记录:
MISTER PRESIDENT DOCTER **BYDEN** MADAM VICE PRESIDENT MISTER MHOFF AMERICANS AND THE WORLD WHEN DAY COMES WE ASK OURSELVES WHERE CAN WE FIND LIGHT IN THIS NEVER ENDING SHADE THE LOSS WE CARRY A SEA WE MUST WADE WE BRAVE THE BELLY OF THE BEAST WE'VE LEARNED THAT QUIET ISN'T ALWAYS PEACE IN THE NORMS IN NOTIONS OF WHAT JUST
IS ISN'T ALWAYS JUST IS AND YET THE DAWN IS HOURS BEFORE WE KNEW IT SOMEHOW WE DO IT SOMEHOW WE'VE WEATHERED AND WITNESSED A NATION THAT ISN'T BROKEN BUT SIMPLY UNFINISHED WE THE SUCCESSORS OF A COUNTRY AND A TIME WERE A SKINNY BLACK GIRL DESCENDED FROM SLAVES AND RAISED BY A SINGLE MOTHER CAN DREAM OF BECOMING PRESIDENT ONLY TO FIND HERSELF RECITING
FOR ONE AND YES WE ARE FAR FROM POLISHED FAR FROM **PESTIM** BUT THAT DOESN'T MEAN WE ARE STRIVING TO FORM A UNION THAT IS PERFECT WE **OR** STRIVING TO FORGE OR UNION WITH PURPOSE TO COMPOSE A COUNTRY COMMITTED TO ALL CULTURES COLORS CHARACTERS AND CONDITIONS OF MAN AND SO WE LIFT OUR GAZES NOT TO WHAT STANDS BETWEEN US BUT WHAT STANDS BEFORE US WE CLOSE THE DIVIDE BECAUSE WE **KNOT A
PUT OUR FUTSURE** FIRST WE MUST FIRST PUT OUR DIFFERENCES ASIDE WE LAY DOWN OUR ARMS TIL WE CAN REACH OUT OUR ARMS TO ONE ANOTHER WE SEEK HARM TO NONE AND HARMONY FOR ALL LET THE GLOBE IF NOTHING ELSE SAY THIS IS TRUE THAT EVEN AS WE GRIEVED WE **GREWE** THAT EVEN AS WE HURT WE HOPED THAT EVEN AS WE TIRED WE **TRIE** THAT WILL FOREVER BE TIED TOGETHER VICTORIOUS NOT BECAUSE WE WILL NEVER AGAIN **KNO** DEFEAT BUT BECAUSE WE WILL N
EVER AGAIN **SO** DIVISION SKIPSER TELLS US TO **INVISION** THAT EVERYONE SHALL SIT UNDER THE OWN VINE AND FIG TREE AND NO ONE SHALL MAKE THEM AFRAID IF WE'RE TO LIVE UP TO OUR OWN TIME **THAN** VICTORY WON'T LIE IN THE BLADE BUT IN ALL THE BRIDGES WE'VE MADE THAT IS THE PROMISE TO GLADE THE HILL WE **CLIME** IF ONLY WE DARE IT BECAUSE BEING AMERICAN IS MORE THAN A PRIDE WE INHERIT IT'S THE PAST WE STEP INTO AND HOW WE **RE
HAR** IT WE'VE SEEN A FOREST THAT WOULD SHATTER OR NATION RATHER THAN SHARE IT **WELD** DESTROY OUR COUNTRY IF IT MEANT DELAYING DEMOCRACY AND THIS EFFORT VERY NEARLY SUCCEEDED BUT WHILE DEMOCRACY CAN BE PERIODICALLY DELAYED IT CAN NEVER BE PERMANENTLY DEFEATED IN THIS TRUTH IN THIS FAITH WE TRUST FOR WHILE WE HAVE OUR EYES ON THE FUTURE OR HISTORY HAS ITS EYES ON US THIS IS THE ERA OF JUST REDEMPTION WE FEARED **A
CEPTION** WE DID NOT FEEL PREPARED TO BE THE **EIRS** OF SUCH A TERRIFYING HOUR BUT WITHIN IT WE FOUND THE POWER TO AUTHOR A NEW CHAPTER TO OFFER HOPE AND LAUGHTER TO OURSELVES SO WHILE ONCE WE ASKED HOW COULD WE POSSIBLY PREVAIL OVER CATASTROPHE NOW WE ASSERT HOW COULD CATASTROPHE POSSIBLY PREVAIL OVER US WE WILL NOT MARCH BACK TO WHAT WAS BUT MOVE TO WHAT SHALL BE A COUNTRY THAT IS BRUISED BUT WHOLE **BE
VOLENCE** BUT BOLD FIERCE AND FREE WE WILL NOT BE TURNED AROUND OR INTERRUPTED BY INTIMIDATION BECAUSE WE KNOW OUR INACTION AND INERTIA WILL BE THE INHERITANCE OF THE NEXT GENERATION OUR BLENDERS BECOME THEIR BURDENS BUT ONE THING IS CERTAIN IF WE MERGE MERCY WITH MIGHT AND MIGHT WITH **MIGHT** THEN LOVE BECOMES OUR LEGACY **IN** CHANGE OUR CHILDREN'S BIRTHRIGHT SO LET US LEAVE BEHIND A COUNTRY
BETTER THAN ONE WE WERE LEFT WITH EVERY BREATH FROM OUR BRONZE POUNDED CHEST WE WILL RAISE THIS WOUNDED WORLD INTO A WONDROUS ONE WE WILL RISE FROM THE **GOLDLIMD** HILLS OF THE WEST WE WILL RISE FROM THE WIND SWEPT NORTHEAST WHERE OUR FORFATHER'S FIRST REALISE REVOLUTION WE WILL RISE FROM THE LAKE **RIMD** CITIES OF THE MIDWESTERN STATES WE WILL RISE FROM THE SUNBAKED SOUTH WE WILL REBUILD RECONCILE AND **BECOVER** AND EVERY KNOWN NOOK OF OUR NATION IN EVERY CORNER CALLED OUR COUNTRY OUR PEOPLE DIVERSE AND BEAUTIFUL WILL **EMMERGE** BATTERED
AND BEAUTIFUL WHEN DAY COMES WE STEP OUT OF THE SHADE AFLAME AND UNAFRAID THE NEW DAWN BALLOONS AS WE FREE IT FOR THERE WAS ALWAYS LIGHT IF ONLY WERE BRAVE ENOUGH TO SEE IT IF ONLY **WERE** BRAVE ENOUGH TO BE IT
同样,粗体部分是模型没有正确处理的有问题的部分。但是我认为这些都是很小的问题,很容易解决。随着 Wav2Vec2 模型变得更加复杂,我非常肯定结果会更好。
试验三:新加坡和 WEF
通过新加坡总理办公室的 YouTube 频道截屏。
在第三次试验中,我想在一个超过 10 分钟的剪辑上评估这个模型,这个剪辑的特点是一个说话者带有亚洲口音。我选定了 2021 年 1 月 29 日新加坡总理李显龙在世界经济论坛达沃斯议程周的演讲。
这一次,我把 12 分钟 30 秒的演讲分成了 13 个部分(12 个 60 秒的片段和 1 个 30 秒的片段),并在 Colab Pro 上运行。《T2》的剧本花了 2 分钟 4 秒制作完成:
IAM VERY **HONOR** TO SPEAK AT **DISCLOSING** ADDRESS AND I LIKE TO CONGRATULATE PROFESSOR **SCHOEB** YOURSELF AND THE WHOLE **BLW F** TEAM FOR PUTTING TOGETHER A SUCCESSFUL PROGRAMM IT 'S BEEN A YEAR SINCE WE WERE ALL PHYSICALLY GATHERED IN **DAVORCE** FOR THE FIFTIETH ANNUAL MEETING **OFER THE DBU F** AT THAT TIME WE WERE JUST STARTING TO HEAR ABOUT THIS NEW VIRUS AND TRYING TO UNDERSTAND WHAT WAS HAPPENING NONE OF US ANTICIPATED HOW QUICKLY A FULL SCALE **PANDAMIC** WOULD BLOW UP AND DRAMATICALLY CHANGE OUR WORLD THE **DESRUPTION** TO LIVES AND LIVELIHOODS HAS BEEN MASSIVE AND UNPRECEDENTED THE **VIRAS** IS STILL RAGING IN MANY COUNTRIES IN THE DEVELOPED WORLD IN THE US AN EUROPE AND ALSO IN THE DEVELOPING WORLD IN AFRICA SOUTH AMERICA AND SOUTH ASIA THANKFULLY WITH **BAXINES** BECOMING AVAILABLE THERE IS SOME LIGHT AT THE END OF THE TUNNEL IT IS NOW
CRITICAL THAT **VAXINES** ARE **RULED** OUT QUICKLY ACROSS THE WORLD BUT EVEN WITH **VAXINES** THE **PANDAMIC** IS FAR FROM BEING QUELLED THE NEW VARIANCE DISCOVERED **AND** THE U K IN SOUTH AFRICA AND BRASIL ARE **WARRYING** AND FURTHER MUTATIONS WILL SURELY EMERGE UNTIL A LARGE PART OF THE WORLD'S POPULATION IS VACCINATED WE STILL **NEEDS** STRONG PUBLIC HEALTH MEASURES EVERYWHERE TO SUPPRESS THE SPREAD OF THE **VIOLUS** AND KEEP POPULATION SAFE WHAT WILL THE **POSTCOVE NINETEEN WOLL** LOOK LIKE WILL COUNTRIES EMERGE MORE **RESOLVE** TO BUILD A MORE **RESILIANT** BUT STILL GLOBALIZED **WELL** OR ARE WE HEADED TOWARDS A LESS INTEGRATED GLOBAL ECONOMY A LESS STABLE INTERNATIONAL ORDER THE ANSWER DEPENDS ON THE DECISIONS THAT COUNTRIES TAKE NOW EVEN BEFORE **COVER NINETEEN** GLOBILIZATION WAS ALREADY UNDER PRESSURE CONFIDENCE AND **MALTILACERAL** INSTITUTIONS AND RULES AND **NORMES** WAS ERODING POPULOUS POLITICS NATIVISM NATIONALISM PROTECTIONISM WERE ON THE RISE **COUNTRYS** INITIAL REACTIONS TO THE **PENDEMIC** SEEMED TO **HERL GRUBILIZATIONS DEMIES** BORDERS WERE CLOSE SUPPLY CHANGE WERE BADLY DISRUPTED EACH COUNTRY SCRAMBLE TO SECURE ITS OWN SUPPLIES OF ESSENTIAL GOODS ESPECIALLY IN MEDICINES FACE MASKS AND VENTILATORS IT WAS EACH MAN FOR HIMSELF BUT AS THEIR SITUATION UNFOLDED WE WERE FORCEFULLY REMINDED THAT OUR FATES WERE INTERTWINED AND THAT WE HAD TO WORK TOGETHER AND SO WE DID IN MANY AREAS WE RESTORED SUPPLY CHANGE WE **REPATRATED** EACH OTHER'S CITIZENS STUCK **OVER SEAS** WE SHARED TESTS AND MEDICAL SUPPLIES WE SUPPORTED **VAXYNG MALTILATERALISM** INITIATIVES LIKE THE KOVACS
SO THAT ALL COUNTRIES **AV SPECIALLY** THE LEAST DEVELOP ONES WOULD HAVE ACCESS TO **VACSCENES** AND AS WE GRADUALLY REBUILT CONFIDENCE IN ONE ANOTHER WE OPENED UP CONTROL CORRIDORS FOR TRAVEL AND TRADE BETWEEN COUNTRIES CRUCIALLY INTERNATIONAL SCIENTIFIC CO OPERATION IN THE FIGHT AGAINST **COVERNINETEEN** CONTINUE DOCTORS AND SCIENTISTS SHARED INFORMATION ABOUT THE DISEASE AND THE VIRUS STUDYING THEM DEVELOPING TREATMENTS AND TESTING **VAKSCENES** THIS ENABLE US TO IMPROVE PATIENT CARE AND TO PRODUCE EFFECTIVE **ACTENES** IN RECORD TIME SOME USING NEW **ECKNOWLEDGIES** SUCH INTERNATIONAL CO OPERATION AND **MALTILATERAL** EFFORTS REMAIN ESSENTIAL TO TACKLE THE GLOBAL PANDEMIC COHERENTLY WITH BORDER CLOSURES AND LOCK DOWNS ECONOMIES HAVE ALL TAKEN A DEEP PLUNGE THE **LIBLIHOODS** OF MILLIONS CAME UNDER **IN
NORMOUS** STRESS ONLY UNPRECEDENTED LEVELS OF EMERGENCY SPENDING AND **MAGETARY** STIMULUS HAVE KEPT US **AFLOAD** PROVIDING A LIFE LINE TO COMPANIES WORKERS AND FAMILIES CENTRAL BANKS HAVE PLAYED THEIR PART TO PREVENT FINANCIAL SYSTEMS AND GLOBAL CAPITAL MARKETS FROM SEIZING UP **UNLIKEN** PREVIOUS CRISES THESE EXTRAORDINARY MEASURES CANNOT BE SUSTAINED INDEFINITELY IN FACT SPENDING PACKAGES ARE ALREADY TAPERING OFF BUT HOPEFULLY AS **FASCINATION** BECOMES MORE WIDESPREAD AND WE MAKE HEADWAYS SUPPRESSING THE **VIOLUS COVET NINETEEN** RESTRICTIONS CAN BE PROGRESSIVELY EASE AND ECONOMIES WILL **REBOUN** THE WORLD BANK AND **I MY** FORECAST GLOBAL GROWTH TO RECOVER THIS YEAR IT WILL NOT RESTORE OUTPUT TO **PRICOVENINETEEN** LEVELS BUT **TI** SOMETHING STILL TO BE THANKFUL FOR NOW WE ARE ENTERING A NEW PHASE
THE PANDEMIC HAS EXPOSED BUSINESSES AND JOBS WHICH ARE NOT GOING TO REMAIN VIABLE THEY HAVE TO BE LET GO TO ALLOW NEW GROWTH AND BETTER JOBS TO BE CREATED IN THEIR PLACE HARD DECISIONS HAVE TO BE MADE AND THIS WILL **EXASCEBATE** EXISTING STRESSES GOVERNMENTS WILL COME UNDER MORE PRESSURE TO ADOPT PROTECTIONISTS AND **NATIVEST** POSITIONS TO RESUME GROWTH WE MUST LOOK BEYOND RETURNING TO THE **STATEST QUA** ANTI WE MUST LOOK AHEAD WILEN COUNTRIES GOVERNMENTS AND BUSINESSES MUST COLLABORATE TO TACT NEW MARKETS AND DEVELOP NOVELT ACKNOWLEDGES EXTERNALLY COUNTRIES NEED TO STRENGTHEN THE FRAMEWORK FOR INTERNATIONAL CO OPERATION AS AN IMMEDIATE TASK COUNTRIES SHOULD COLLABORATE TO DEVELOP A STANDARDIZE ROBUST SYSTEM TO VERIFY THE AUTHENTICITY OF TESTS AND VACCINATIONS THIS IS ESSENTIAL TO REOPEN B
ORDERS AND RESUME INTERNATIONAL TRAVEL IN THE LONGER TERM COUNTRIES SHOULD WORK TOGETHER TO UPDATE AND **STRENGTHENINTS TERNATIONAL** INSTITUTIONS LIKE THE **W TEOL** AND CREATE NEW RULES TO GOVERN AND FOSTER NOVEL FORMS OF ECONOMIC ACTIVITY FOR EXAMPLE TO SUSTAIN THE GROWTH OF THE DIGITAL ECONOMY AND FACILITATE SAFE SECURE AND EFFICIENT CROSS BORDER E PAYMENTS AND DATA FLOWS WE HAVE TO DEVELOP NEW E TRADE REGULATIONS **SINGAPOLE** HAS CONCLUDED DIGITAL ECONOMY AGREEMENTS WITH LIKE MINDED COUNTRIES LIKE AUSTRALIA CHILLE AND NEW **ZEALAN** WE HOPE THAT THIS IS ONLY THE BEGINNING WE ENCOURAGE ALL COUNTRIES TO COME TOGETHER TO SHAPE AND GROW THE DIGITAL ECONOMY GLOBLY **THUSSIGNING** OF THE **REGINAL** COMPREHENSIVE ECONOMIC PARTNERSHIP OR THE **ARLC E P LAST
TIA** BY FIFTEEN COUNTRIES IN ASIA WAS ALSO A MAJOR COLLECTIVE COMMITMENT TO TRADE **AN** ECONOMIC INTEGRATION AMIDST THE PANDEMIC THE **ARC P** WILL BROADEN **TRAN OPEN AT** MARKETS IN EAST AND SOUTH **EASTATIA** AND AUSTRALASIA AND HOPEFULLY PREVENT THE PUSH FOR **RASILIANTS** AND SELF RELIANCE FROM GOING TOO FAR WHILE DEALING WITH THE AFTERMATH OF **COVET NINETEEN** WE MUST NOT LOSE SIGHT OF OTHER LONG TERM CHALLENGES THAT AFFECT ALL OF US ONE MAJOR PROBLEM IS CLIMATE CHANGE TWENTY TWENTY WAS THE WORLD'S **HOTTESEER** ON RECORD EXTREME WEATHER EVENTS HAVE BECOME MUCH MORE FREQUENT LAST **YIAR** CARBON EMISSIONS WENT DOWN BUT ONLY BECAUSE OF **COVET NINETEEN** OTHERWISE THE TREN HAS BEEN INEXORABLY UPWARDS CLIMATE CHANGE IS CLEARLY **EX
CELERATING** DANGEROUSLY AND IT IS LATE IN THE DAY BUT IF COUNTRIES ACT NOW AND IN CONCERT HUMAN KIND CAN STILL HOPE TO AVERT A CATASTROPHE WE ALL KNOW WHAT WE NEED TO DO WITHIN INDIVIDUAL COUNTRIES TO MUSTER SUPPORT FOR POLICIES AND MEASURES THAT WILL SLOW THE CHANGES AND LIMIT GLOBLE WARNING COLLECTIVELY TO SET HIGHER COMMON STANDARDS AND HOLD ONE ANOTHER TO OUR MUTUAL COMMITMENTS WHETHER IT'S TIGHTENING EMISSION RULES **FASING** OUT **FOSSILFIELD** SUBSIDIES OR PROMOTING RENEWABLE ENERGY WE CAN TAKE SOME COMFORT THAT COUNTRIES ARE NOW TAKING CLIMATE CHANGE MORE SERIOUSLY THE US HAS REJOINED THE PARIS AGREEMENT CHINA HAS ANNOUNCED A ZERO EMISSIONS TARGET BY TWENTY **SIXLY** BUT MUCH MORE STILL NEEDS TO BE DONE GOING BEYOND OUR PARIS COMMITMENTS OTHERWISE
WE RISK GRAVE CONSEQUENCES IN THE NOT TOO DISTANT FUTURE EVEN WITHIN OUR OWN LIFETIMES TO TACKLE THESE CHALLENGES COVET NINETEEN ECONOMIC RECOVERY AND CLIMATE CHANGE GLOBA CO OPERATION IS ESSENTIAL BUT GETTING COUNTRIES TO WORK TOGETHER IS NOT SIMPLY A MATTER OF NURTURING AND SHOWING GOODWILL THE INTERNATIONAL ORDER MUST BE UNDERPINNED BY STABLE GREAT POWER RELATIONS BIG COUNTRIES NATURALLY JOSTLE AND COMPETE WITH ONE ANOTHER FOR INFLUENCE AND POWER BUT THEY ALSO NEED TO WORK WITH ONE ANOTHER THROUGH ESTABLISH AN ACCEPTED RULES AND NORMS ON ISSUES WHICH AFFECT US ALL BE IT **PANDAMICS** ECONOMIC CO OPERATION OR CLIMATE CHANGE RECENT YEARS HAVE WITNESSED GROWING FRICTION AND DISTRUST RATHER THAN CO OPERATION AND CONFIDENCE BUILDING AMONG MAJOR POWERS THE MOST WORRYING TREND I
S THE **W S CHINA** RELATIONS THIS REMAINS THE MOST IMPORTANT **BYLATURAL** RELATIONSHIP FOR THE WORLD IN THE YEARS AHEAD OVER THE LAST FOUR YEARS TENSIONS BETWEEN THE U S AND CHINA HAVE INTENSIFIED SHARPLY BOTH POWERS HAVE ADOPTED MORE **SERTIVE** AND UNCOMPROMISING POSTURES THE U S NOW SEES CHINAS AS STRATEGIC RIVAL AND CHALLENGER TO ITS PRE EMINENT POSITION AND CHINA IS VIGOROUSLY ASSERTING WHAT IT CONSIDERS ITS RIGHTFUL PLACE IN THE WORLD ON BOTH SIDES DOMESTIC PRESSURES TO HARDEN THEIR EXTERNAL POSITIONS ARE CONSIDERABLE AND MODERATE VOICES HAVE BEEN MARGINALIZE GIVEN THE ENORMOUS STAKES DIFFICULT AS IT WILL BE IT CANNOT POSSIBLY BE TOO LATE FOR THE U S AND CHINA TO RESET THE TONE OF THEIR INTERACTIONS AND AVERT A CLASH
BETWEEN THEM WHICH WILL BECOME A GENERATIONAL TWILIGHT STRUGGLE THE NEW US ADMINISTRATION IS AN OPPORTUNITY TO STEER THE RELATIONSHIP TOWARDS SAFER WATERS AMID PRESIDENT **BIDONS** MANY URGENT PREOCCUPATIONS THE U S CHINA RELATIONSHIP SHOULD BECOME A KEY STRATEGIC **PRORITY** TO **BILD** A STABLE INTERNATIONAL ORDER REGULAR CONSTRUCTIVE DIALOGUE IS CRITICAL IAM THUS HAPPY TO SEE MANY DISTINGUISHED PARTICIPANTS TAKING PART IN THE **DAVOSA** **GENDER** WEEK THE WORLD ECONOMIC FORUM PLAYS AN IMPORTANT RULE PROMOTING DIALOGUE BRINGING TOGETHER LEADERS IN GOVERNMENT INDUSTRY AND CIVIL SOCIETY IT'S A FORUM WHERE LEADERS FROM COUNTRIES LARGE AND SMALLER LIKE CAN SPEAK AND BE HEARD AND THIS IS WHY WHEN PROFESSOR **SHROB** ASK ME WHETHER **SINGO POET HOSTESS** SPECIAL ANNUAL MEETING OF THE W E F I AGREED IT WAS NOT
A DECISION LIGHTLY TAKEN BUT WE ARE HAPPY TO MAKE A MODEST CONTRIBUTION TO THE GLOBAL DISCUSSION AS THE HOST COUNTRY WE WILL WORK WITH A W E F TO ENSURE THE HEALTH AND SAFETY OF ALL I WELCOME ALL OF YOU TO **SING A POR** IN MAY SO THAT WE CAN TAKE THESE DISCUSSIONS FORWARD AND FORGE A NEW **PARTH** AHEAD TOGETHER THANK YOU
按照前两次试验,粗体部分表示有问题的地方。演讲中有很多技术术语,很明显是模型出错了,就像总理对一些单词的发音一样。
这次需要做更多的清理工作。但是这花了 2 分钟 4 秒。想一想手动抄写演讲稿可以节省多少时间。
Wav2Vec2 的转录本无论如何都不是完美的。对于某些用例来说,缺少标点符号可能是一个问题,音频剪辑的管理需要额外的资源。
但是考虑到所有的事情,我会说 Wav2Vec2 模型在 NLP 中开辟了令人兴奋的新的可能性,不仅仅是快速和准确的转录。我对通过其他 transformer 模型将抄本用作翻译、情感分析或摘要的输入的前景感到特别兴奋。
这会变得非常有趣。
和往常一样,如果你在这篇文章或我之前的文章中发现了错误,请联系我:
- 推特:蔡振鸿
- 领英:www.linkedin.com/in/chuachinhon
这篇文章的回购,包含图表的数据和笔记本,可以在这里找到。
使用 Twilio API 和 AssemblyAI 转录 Twilio 录音
原文:https://towardsdatascience.com/transcribing-twilio-recordings-using-the-twilio-api-and-assemblyai-4daf25fa32f0?source=collection_archive---------36-----------------------
我们将使用 Twilio API 和 AssemblyAI API
照片由奎诺·阿尔在 Unsplash 上拍摄
在本教程中,我们将使用 AssemblyAI 的 API 用 Twilio 转录一段通话记录。我们将使用 Python 来编写脚本。我们将讨论以下内容
- 我们将使用的库/API
- 设置环境和文件结构
- 使用 twilio API
- 使用 AssemblyAI API
- 转录录音
要求
- Python 的基础知识
- 虽然不是必需的,但是熟悉请求库将会有所帮助
GitHub 回购链接
你可以在这里找到完整的源代码
我们将使用的库/API
特维利奥
Twilio 是一项让你使用 API 拨打/接听电话和短信的服务。Twilio 还为他们的 API 提供了一个官方的包装器。包装器使得与他们的 API 通信更加容易。在本教程中,我们将使用它们的包装器。Jovan Hernandez撰写的这篇文章讲述了如何使用 Twilio 和 Python。
AssemblyAI
AssemblyAI 可以将音频转换成文本。它提供了一个任何现代编程语言都可以使用的 REST API。例如:Python,JavaScript,PHP 等。
要求
我们将使用请求库向 AssemblyAI 的 REST API 发出请求。阅读亚当·斯奈德的文章来学习更多关于在 Python 中使用请求的知识。
Python-dotenv
为了遵循最佳实践,我们将在一个. env 文件中存储我们的凭据和电话号码。Python-dotenv 库帮助我们从。环境文件
设置环境和文件结构
创建必要的文件
使用命令行创建新的文件夹/目录
mkdir twilio_assemblyai
将目录更改为新创建的文件夹
cd twilio_assemblyai
为了保证机密凭证的安全,最好将凭证存储在. env 文件中。然后我们可以使用 Python-dotenv 库从。环境文件。让我们继续创建。env 文件,以及我们将一起构建的 3 个 python 文件。
如果使用 Windows:
New-Item main.py, transcribe.py, call.py ,.env
如果使用 macOS 或 Linux:
touch main.py; touch transcribe.py; touch call.py ;touch .env
以下是我们刚刚创建的文件的概述:
- call.py —该文件包含使用 twilio 发出呼叫并创建该呼叫记录的脚本
- transcripte . py—该文件包含与 AssemblyAI 的 API 交互所需的函数
- main.py —这个文件集合了我们在 transcribe.py 和 call.py 中的函数,所以我们有一个打电话的脚本,然后用 AssemblyAI 转录那个电话的录音
- 。env —这个文件将包含我们的秘密凭证,比如我们的 API 凭证、电话号码和我们发出的呼叫的 ID
创建和激活虚拟环境
如果这是您第一次使用虚拟环境,您必须使用以下命令安装 virtualenv :
如果使用 Windows:
python -m pip install --user virtualenv
如果使用 macOS 或 Linux:
python3 -m pip install --user virtualenv
确保你在我们在教程开始时创建的目录中。如果不是,只需使用 cd 命令来更改目录。
cd twilio_assemblyai
首先,我们需要通过在命令行上输入以下代码来创建一个虚拟环境:
如果使用 Windows:
python -m venv venv
如果使用 macOS 或 Linux:
python3 -m venv venv
然后,我们需要使用以下命令激活本地虚拟环境:
如果使用 Windows:
venv/Scripts/activate
如果使用 macOS 或 Linux:
source venv/bin/activate
关于如何建立虚拟环境以及它们如何工作的更多细节,你可以参考官方 Python 文档..
文件结构截图
安装所需的库
我们需要安装我们在“我们将使用的库/API”一节中讨论过的以下库
- python-dotenv
- 要求
- 特维利奥
如果使用 Windows:
pip install twilio, requests, python-dotenv
如果使用 macOS 或 Linux:
pip3 install twilio, requests, python-dotenv
使用 twilio API
获取 API 凭据
- 在这里创建一个 twilio 账户。你会得到一个免费的 twilio 电话号码。
Twilio 网站
- 使用提供的免费电话号码,您只能向经过验证的号码拨打电话。在注册过程中,添加您的个人号码并进行验证。我们将拨打经过验证的号码。您可以在此添加多个验证号码
- 转到您的账户仪表板
- 在项目信息部分,您应该看到您的账户 SID 和认证令牌。这些是您使用 twilio API 的凭证。我们将它们存储在。我们之前创建的 env 文件。
- 在项目信息部分,你还应该看到你的 twilio 电话号码。我们会将此电话号码与经过验证的电话号码一起保存在。环境文件。
Twilio 仪表板
account_sid = "YOUR TWILIO ACCOUNT SID"
auth_token = "YOUR TWILIO AUTH TOKEN"from_phone_number = "YOUR TWILIO PHONE NUMBER"
to_phone_number = "YOUR VERIFIED NUMBER"
用于拨打和记录呼出电话的功能
我们将使用 twilio 库来打电话。本节中的所有代码都应该在 call.py 文件中。首先,让我们导入所需的库
import os
from dotenv import load_dotenv
from twilio.rest import Client
import requests
from requests.auth import HTTPBasicAuth
客户端让我们创建一个 twilio 包装器的实例。我们将使用这个实例的方法进行调用。在创建实例之前,让我们定义一个函数。
def make_phone_call(client,from_phone_number,to_phone_number):
return None
上述函数将接受一个 twilio 客户端实例、我们的 twilio 电话号码和我们验证过的电话号码作为参数。现在,让它保持空白。我们稍后将回到这个问题。
现在,让我们从. env 加载我们的凭证和电话号码。创建一个 twilio client 实例将需要这些凭证。
if __name__ == '__main__':
load_dotenv()
account_sid = os.environ.get('account_sid')
auth_token = os.environ.get('auth_token')
from_phone_number = os.environ.get('from_phone_number')
to_phone_number = os.environ.get('to_phone_number') client = Client(account_sid, auth_token)
call_sid = make_phone_call(client, from_phone_number, to_phone_number) print(f'Call sid is {call_sid}')
上面的代码片段创建了一个 twilio 客户端实例。调用 make_phone_call ,并将 twilio client 实例和电话号码作为参数传递。
现在,让我们编写 make_phone_call 函数,该函数将向我们验证过的电话号码发出呼叫并进行录音。该函数将返回呼出呼叫的 ID。这个 ID 需要存储在。env 文件,我们之前创建的。
def make_phone_call(client_,from_phone_number_,to_phone_number_):
'''
Parameter:
client: A twillio client instance
Return:
call.sid: The sid of the outgoing call
'''
phone_call = '''<Response>
<Say>What are you working on?</Say>
<Pause length="5"/>
</Response>''' call = client_.calls.create(
record = True,
twiml=phone_call,
from_=from_phone_number_,
to = to_phone_number_
)
return call.sid
变量 phone_call 是我们拨出电话时将被读取/播放的脚本。它必须用类似于 HTML/XML 的 TwiML 来编写。出于本教程的目的,我们只需要关注以下 TwiML 元素:
- Say —这个标签之间的内容只是在传出时朗读
- 暂停 —暂停并让被呼叫者讲话。它有一个属性 length ,表示呼叫暂停的持续时间。
- 响应——它类似于 html 标签。基本上,整个脚本必须在响应标记之间
所以把这些片段放在一起,这就是变量 phone_call 中的脚本所做的
- 询问被叫者他们正在做什么
- 等待 5 秒钟,等待被呼叫者说话
客户端实例的 calls.create 方法发出一个电话呼叫。它接受以下参数
- 记录 —一个布尔值,告诉 twilio 记录电话
- twiml —通话过程中要播放的脚本
- from_ —拨打电话的号码。在我们的例子中,它是 twilio 数
- 到 —我们要呼叫的号码。如前所述,如果你使用的是免费帐户,它必须是一个经过验证的号码。
一旦你运行一个脚本,你应该会收到一个电话对你的验证号码。键入以下命令运行脚本
Twilio 电话号码呼叫
如果使用 Windows:
python call.py
如果使用 macOS 或 Linux:
python3 call.py
下面是 make_phone_call 函数的输出
终端输出
记下 make_phone_call 函数返回的调用 sid。接下来,将您的呼叫 sid 存储在。环境文件。
call_sid = ‘YOUR CALL SID’
如果您遇到任何错误,您可以检查可编程语音仪表板。
Twilio 为调试错误信息提供了有用的消息。一个常见的错误是脚本的格式。确保脚本中没有多余的空格或新行。下面是仪表板中的一个错误示例
Twilio 错误日志
函数来获取录制 ID
Twilio 提供了以下 API 端点来获取特定调用的记录 id。需要注意的是,一个呼叫可以有多个相关的录音,但是在我们的例子中,整个呼叫只有一个录音。例如:特定时间范围的记录。我们的通话有一段录音,是整个通话的录音。
https://api.twilio.com/2010-04-01/Accounts/{account_sid}
/Calls/{call_sid_}/Recordings.json
Twilio 使用 HTTPBasicAuth 来认证对其 API 端点的请求。下面,我们将编写一个函数来获取我们的呼叫记录的 ID,我们需要它来下载该记录。
def get_recording_sid(account_sid_,auth_token_,call_sid_):
'''
Parameter:
account_sid: Twilio Account SID,
auth_token: Twilio API Key/Auth Token
call_sid_: Call Sid
Return:
recording.sid: The sid of the recording
'''
url = f"https://api.twilio.com/2010-04-01/Accounts/{account_sid_}"\
+ f'/Calls/{call_sid_}/Recordings.json'
result = requests.get(url , auth = HTTPBasicAuth(account_sid_, auth_token_))
recordings = result.json()
# Since our call has a single recording, we just need to access the first
# element in the list of recordings. If a call has multiple recordings
# associated with it, this list will contain the SIDs of all the
# recordings.
recording_sid = recordings['recordings'][0]['sid']
return recording_sid
一旦有了 twilio 调用 id,就可以调用 get_recording_sid 函数来获得一个录音 ID。下面是调用该函数的方式
recording_sid = get_recording_sid(account_sid, auth_token, call_sid)
print(f"Recording Sid: {recording_sid}")
参数 account_sid 和 auth_token 是您的 twilio API 凭证。
下面是一个输出示例
Recording Sid: REe5c2f483b17755f76492f516e7c7df5a
我们将调用 main.py 中的get _ recording _ sid
您的录音的 URL
我们可以通过以下网址访问我们录音的 mp3 文件
[https://api.twilio.com/2010-04-01/Accounts/{account_sid}/Recordings/{recording_sid}.mp3'](https://api.twilio.com/2010-04-01/Accounts/{account_sid}/Recordings/{recording_sid}.mp3')
您只需将替换为您的 twilio 帐户 id,将替换为我们从上述函数中检索到的您的录音 ID。
使用 AssemblyAI API
本节中的函数将在transcripte . py中编写
获取 API 凭据
- 转到https://www.assemblyai.com/
- 注册一个账户
AssemblyAI 网站
- 转到https://app.assemblyai.com/dashboard/
- 复制 API 键下的字符串
AssemblyAI 网站
- 将令牌存储在。环境文件
assemblyai_token = “Your AssemblyAI API Key”
在编写函数之前,我们需要导入请求库
import requests
将文件排队并获取转录 ID 的函数
我们将使用记录 URL 并向端点发出请求,这将启动转录状态。
最初,当我们请求音频文件的转录时,它具有“排队”的状态。我们将在后面的章节中更多地讨论文件如何从“排队”到“完成”。现在,我们只需要向转录端点以及文件的 URL 发出请求。我们需要向以下 AssemblyAI API 端点发出请求:
[https://api.assemblyai.com/v2/transcript](https://api.assemblyai.com/v2/transcript)
该端点接受新的转录作业。下面是一个接受 AssemblyAI API 令牌和音频文件 URL 作为参数的函数。
def get_transcribe_id(token,url):
'''
Parameter:
token: The AssemblyAI API key
url : Url to uploaded file
Return Value:
id : The transcribe id of the file
'''
endpoint = "https://api.assemblyai.com/v2/transcript"
json = {
"audio_url": url
}
headers = {
"authorization": token,
"content-type": "application/json"
}
response = requests.post(endpoint, json=json, headers=headers)
id_ = response.json()['id']
print("Made request and file is currently queued")
return id_
该函数接受两个参数:AssemblyAI API 令牌和一个音频文件 URL。
我们可以使用 get_recording_sid 函数来获取记录 id,并创建包含 twilio 呼叫记录的端点。下面的代码应该写在 main.py 中。但是,为了测试我们的上述函数,我们可以将它包含在 regulate . py 中。环境文件。请参阅“拨打和记录呼出电话的函数”一节,从。环境文件。
recording_sid = get_recording_sid(account_sid, auth_token, call_sid)
print(f"Recording Sid: {recording_sid}")
recording_endpoint = 'https://api.twilio.com/2010-04-01/Accounts/' \
+ f'{account_sid}/Recordings/{recording_sid}.mp3'
我们将使用get _ transcripte _ id函数,并将这个记录端点作为参数传递。
transcribe_id = get_transcribe_id(assemblyai_token,recording_endpoint)
print(f”Transcription ID is {transcribe_id}”)
下面是 get _ transcribe _ id 函数的示例输出
Transcription ID is uyzt6qhog-15d8–4af4-a87f-bdc66a2a56f2
转录 ID 有助于我们检查转录的状态。我们需要将这个 ID 作为参数传递给一个单独的端点(将在下面讨论),并继续请求获得转录的状态。我们将继续请求,直到转录完成。
检查转录状态的功能
一旦我们有了音频文件的转录 ID,我们就可以向下面的 AssemblyAI API 端点发出 GET 请求来检查转录的状态
[https://api.assemblyai.com/v2/transcript/{transcribe_id}](https://api.assemblyai.com/v2/transcript/{transcribe_id})
只要没有遇到错误,转录的状态就从“排队”变为“处理中”再变为“完成”,如果遇到错误,则变为“错误”。如果当前没有进行音频文件转录,则立即处理新文件。如果有正在进行的转录,则新的音频文件将排队,直到前一个作业完成。如果您希望能够同时运行多个作业,您将需要升级到高级计划
我们将需要轮询这个端点,直到我们得到一个状态为“completed”或“error”的响应对象。基本上,继续向这个端点发出请求并检查状态。
def get_text(token,transcribe_id):
'''
Parameter:
token: The AssemblyAI API key
transcribe_id: The ID of the file which is being
Return Value:
result : The response object
'''
endpoint = f"https://api.assemblyai.com/v2/transcript/{transcribe_id}"
headers = {
"authorization": token
}
result = requests.get(endpoint, headers=headers).json()
return result
上面的函数只是接受 AssemblyAI API 令牌和转录 ID 作为参数,并返回包含转录状态的结果。下面是一个 while 循环,它不断向端点发出请求。
我们可以利用一个 while 循环来连续调用上述函数并向端点发出请求。在循环的每次迭代中,我们将检查转录的状态。循环将继续运行,直到状态为“完成”。发出请求并等待状态完成的过程称为轮询。
result = {}
print("AssemblyAI is processing the file")
while result.get("status") != 'completed' and result.get("status") != 'error':
time.sleep(2)
result = get_text(assemblyai_token,transcribe_id)print("Transcription Complete - The result is below")
print(result['text'])
为了限制请求的数量,我们将在请求之间添加一个睡眠功能。下面是输出的样子
终端输出
使用 while 循环的轮询应该在 main.py 文件中完成。我们将在下面讨论 main.py 文件。
转录录音
我们将使用来自 transcription.py 和 Twilio recording ID 的函数来转录呼出呼叫。这段代码要用 main.py 写。
首先,让我们导入必要的库和方法
import os
from dotenv import load_dotenv
from transcribe import get_transcribe_id, get_text
from call import get_recording_sid
接下来,我们将从。环境文件
# Reading Data from .env file
load_dotenv()
account_sid = os.environ.get('account_sid')
call_sid = os.environ.get('call_sid')
auth_token = os.environ.get('auth_token')
assemblyai_token = os.environ.get('assemblyai_token')
我们将使用 get_recording_sid 函数来获取录制 id
recording_sid = get_recording_sid(account_sid, auth_token, call_sid)
print(f”Recording Sid: {recording_sid}”)
现在,我们将使用录音 ID 并创建录音的 URL
recording_endpoint = ‘https://api.twilio.com/2010-04-01/Accounts/' \
+ f’{account_sid}/Recordings/{recording_sid}.mp3'
我们将使用get _ transcripte _ id函数,并将这个记录端点作为参数传递。
transcribe_id = get_transcribe_id(assemblyai_token,recording_endpoint)
print(f”Transcription ID is {transcribe_id}”)
一旦我们获得转录 ID,我们将轮询转录端点以获得转录的状态。
result = {}
print("AssemblyAI is processing the file")
while result.get("status") != 'completed':
result = get_text(assemblyai_token,transcribe_id)
print("Transcription Complete - The result is below")
print(result['text'])
要运行 main.py 文件:
如果使用 Windows:
python main.py
如果使用 macOS 或 Linux:
python3 main.py
下面是输出
终端输出
结论
恭喜你!👏你已经成功地写了一个可以转录音频的脚本。如果您想在此基础上进行构建,您可以尝试在电话记录中添加转录作为注释。
深度迁移学习
原文:https://towardsdatascience.com/transfer-learning-3e9bb53549f6?source=collection_archive---------23-----------------------
重用他人训练的模型的艺术
(图片由作者提供)
介绍
好的机器学习模型需要海量的数据和许多GPU或TPU来训练。而且大多数时候他们只能执行一个特定的任务。
大学和大公司有时会发布他们的模型。但是很可能你想开发一个机器学习应用程序,但是没有适合你的任务的模型。
但是不要担心,你不必收集大量的数据和花费大量的现金来开发自己的模型。可以用迁移学习来代替。这减少了训练时间,您可以用更少的数据获得良好的性能。
什么是迁移学习?
在迁移学习中,我们使用模型在特定任务的训练中收集的知识来解决不同但相关的任务。该模型可以从以前的任务中学到的东西中获益,以便更快地学习新的任务。
这里打个比方,说你要检测图像上的狗。在网上你可以找到一个可以检测猫的模型。因为这是一个足够相似的任务,你拍几张你的狗的照片,然后重新训练这个模型来探测狗。也许它会有偏见,只认出你的宠物,但我想你明白了😉。
也许模型已经学会了通过他们的皮毛或者他们有眼睛的事实来识别猫,这对于识别狗也是非常有帮助的。
迁移学习其实有两种,特征提取和微调。
一般来说,这两种方法遵循相同的程序:
- 初始化预训练的模型(我们想要学习的模型)
- 重塑最终图层,使其输出数量与新数据集中的类数量相同
- 定义我们想要更新的图层
- 在新数据集上训练
特征抽出
让我们考虑一个卷积神经网络架构,它具有滤波器、密集层和一个输出神经元。
(图片由作者提供)
网络被训练来预测图像上有猫的概率。我们需要一个大数据集(有猫和没有猫的图像)训练时间长。这一步叫做“前期训练”。
(图片由作者提供)
接下来是有趣的部分。我们再次训练网络,但是这一次使用包含狗的小图像数据集。在训练期间,除了输出层之外的所有层都被“冻结”。这意味着我们不会在培训期间更新它们。训练之后,网络输出狗在图像上可见的概率。与之前的预培训相比,该培训程序将花费更少的时间。
(图片由作者提供)
或者,我们也可以“解冻”最后两个图层,即输出图层和密集图层。这取决于我们拥有的数据量。如果数据较少,我们可以考虑只训练最后一层。
微调
在微调中,我们从预先训练的模型开始,但是我们更新所有的权重。
(图片由作者提供)
pytorch 中的迁移学习示例
我将使用来自 kaggle 的数据集猫对狗。数据集可以在这里找到。你总是可以使用不同的数据集。
这里的任务与我上面的例子有点不同。用于识别哪些图像上有狗,哪些图像上有猫的模型。为使代码正常工作,您必须按以下结构组织数据:
(图片由作者提供)
你可以在这里找到关于猫和狗的更详细的介绍。
设置
我们从导入所需的库开始。
(作者代码)
我们检查一个 CUDA 兼容的 CPU,否则我们将使用 CPU。
(作者代码)
然后我们加载 torchvision 的预训练 ResNet50。
(作者代码)
数据扩充是通过对图像应用不同的变换来完成的,从而防止过拟合。
(作者代码)
我们创建数据加载器,它将从内存中加载图像。
(作者代码)
创建学习率计划程序,它将在培训过程中修改学习率。或者,您可以使用 ADAM 优化器,它可以自动调整学习速率,并且不需要调度程序。
(作者代码)
特征提取优化器
这里将只为最后一层计算梯度,因此只训练最后一层。
用于微调的优化器
在这里,所有的层将被训练。
培养
我们来定义一下训练循环。
(作者代码)
最后,我们可以训练我们的模型。
要么使用特征提取:
(作者代码)
或者使用微调:
(作者代码)
不要太骄傲地使用迁移学习
当我向人们推荐他们可以在他们的 ML 项目中使用迁移学习时,他们有时会拒绝,宁愿自己训练一个模型,而不是使用迁移学习。但是没有人应该为使用迁移学习而感到羞耻,因为:
- 训练神经网络使用能量,因此增加了全球碳排放量。转移学习通过减少训练时间来拯救我们的星球。
- 当训练数据不足时,迁移学习可能是您的模型表现良好的唯一选择。在计算机视觉中,通常缺乏训练数据。
结论
对于现代数据科学家来说,迁移学习是一个方便的工具。您可以使用其他人预先训练的模型,并对其执行迁移学习,以节省时间、计算机资源并减少训练所需的数据量。
数据集
猫和狗的数据集
数据集可以在下找到。
【https://www.tensorflow.org/datasets/catalog/cats_vs_dogs
并根据知识共享署名 4.0 许可进行许可。
来源
什么是深度迁移学习,为什么它变得如此流行?
吴恩达转移学习
Lambda 实验室,揭开 gpt 3 的神秘面纱
深度学习的碳排放
DALL E:从文本创建图像
想联系支持我?
LinkedIn
https://www.linkedin.com/in/vincent-m%C3%BCller-6b3542214/
脸书
https://www.facebook.com/profile.php?id=100072095823739
Twitter
https://twitter.com/Vincent02770108
Medium
https://medium.com/@Vincent.Mueller
成为 Medium 会员并支持我(你的部分会费直接交给我)
https://medium.com/@Vincent.Mueller/membership
应用于辛普森图像数据集的迁移学习和数据扩充
原文:https://towardsdatascience.com/transfer-learning-and-data-augmentation-applied-to-the-simpsons-image-dataset-e292716fbd43?source=collection_archive---------12-----------------------
理解大数据
使用 Tensorflow 和 Keras 的深度学习应用
1.介绍
在机器学习(ML)的理想场景中,有大量带标签的训练实例,它们与测试数据【1】共享相同的分布。但是,在某些情况下,收集这些数据可能需要大量资源,或者不切实际。因此,迁移学习成为一种有用的方法。它包括通过从不同但相关的领域转移信息来增加模型的学习能力。换句话说,它放松了训练和测试数据独立同分布的假设【2】。只有当要学习的特征对两个任务都通用时,这种方法才有效。另一种处理有限数据的方法是使用数据扩充(DA)。它包括应用一套变换来膨胀数据集。传统的 ML 算法非常依赖于特征工程,而深度学习(DL)专注于通过无监督或半监督的特征学习方法和分层特征提取来学习数据。DL 通常需要大量的数据来进行有效的训练,这使得它成为 TL 和 DA 的强有力的候选对象。
我们的任务是对一系列带标签的图像进行分类。由于数据集较小,我们面临两个问题:有效学习数据中的模式的挑战和过度拟合的高概率。我们从零开始实现一个卷积神经网络(CNN)模型作为基准模型。接下来,遵循 TL 的原理,我们在 ImageNet 数据集上使用一个预先训练好的卷积神经网络(【3】,【4】)。我们移除了它的顶层,以包含我们自己的适合我们的问题规范的深层结构。因此,预训练的 CNN 在整个新模型中充当特征提取层。通过这种方法,我们解决了这两个问题:我们大大减少了对大量训练数据的需求,同时也减少了过度拟合。我们还进行了第二个实验,通过应用一套增强图像大小和质量的技术来增加我们的训练数据。这种方法被定义为数据扩充(DA ),它是一种正则化技术。虽然它保留了标签,但它也使用转换来增加数据集,以添加更多不变的示例【5】。
在本文中,我们使用辛普森一家的角色数据集【6】。我们对数据集进行了过滤,仅包含包含 100 张以上图像的类(字符)。在训练、验证和测试数据集之间进行拆分后,数据集的最终大小如下:12411 幅图像用于训练,3091 幅图像用于验证,950 幅图像用于测试。
和往常一样,代码可以在我的 GitHub 上获得。
本文属于使用 TensorFlow 进行深度学习的系列文章:
- 迁移学习和数据增强应用于辛普森图像数据集
- 基于 F. Pessoa 的工作用递归神经网络生成文本
- 使用 Seq2Seq 架构和注意力的神经机器翻译(ENG to POR)
- 残差网络从无到有应用于计算机视觉
2.数据预处理
尽管数据集的大小很小,CNN 可以有效地学习,但它足够大,我们在加载和转换它时会有内存问题。我们使用数据生成器向不同的模型提供实时数据。生成器函数是一种特殊类型的函数,它返回一个惰性迭代器,也就是说,它们不将内容存储在内存中。在创建生成器时,我们应用一个转换来规范化我们的数据,在训练和验证数据集之间分割它们,并定义一个 32 的批处理大小。
import tensorflow as tf
from tensorflow.keras.models import Sequential, Model
import numpy as np
import os
import pandas as pd
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
from tensorflow.keras import Input, layers
from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D
import tensorflow_hub as hub
from tensorflow.keras.layers import Dropout, BatchNormalization
from sklearn.model_selection import train_test_split
from tensorflow.keras.preprocessing.image import ImageDataGeneratordirectory_train = "./data/simpsons_data_split/train/"
directory_test = "./data/simpsons_data_split/test/"def get_ImageDataGenerator(validation_split=None):
image_generator = ImageDataGenerator(rescale=(1/255.),
validation_split=validation_split)
return image_generatorimage_gen_train = get_ImageDataGenerator(validation_split=0.2)def get_generator(image_data_generator, directory, train_valid=None, seed=None):
train_generator = image_data_generator.flow_from_directory(directory, batch_size=32, class_mode='categorical', target_size=(299,299), subset=train_valid, seed=seed)
return train_generatortrain_generator = get_generator(image_gen_train, directory_train, train_valid='training', seed=1)
validation_generator = get_generator(image_gen_train, directory_train, train_valid='validation')Found 12411 images belonging to 19 classes.
Found 3091 images belonging to 19 classes.image_gen_test = get_ImageDataGenerator(validation_split=None)
test_generator = get_generator(image_gen_test, directory_test)Found 950 images belonging to 19 classes.
我们可以遍历生成器来获得一组图像,其大小等于上面定义的批处理大小。
target_labels = next(os.walk(directory_train))[1]
target_labels.sort()
batch = next(train_generator)
batch_images = np.array(batch[0])
batch_labels = np.array(batch[1])
target_labels = np.asarray(target_labels)
plt.figure(figsize=(15,10))
for n, i in enumerate(np.arange(10)):
ax = plt.subplot(3,5,n+1)
plt.imshow(batch_images[i])
plt.title(target_labels[np.where(batch_labels[i]==1)[0][0]])
plt.axis('off')
图 1:由训练生成器生成的一组图像。
3.基准模型
我们定义一个简单的 CNN 作为基准模型。它结合使用 2D 卷积层(对图像执行空间卷积)和最大池操作。接下来是具有 128 个单元和 ReLU 激活功能的密集层和速率为 0.5 的下降层。最后,最后一层产生我们的网络的输出,其单元数量等于目标标签的数量,并使用 softmax 激活函数。该模型是用 Adam 优化器编译的,具有默认设置和分类交叉熵损失。
def get_benchmark_model(input_shape):
x = Input(shape=input_shape)
h = Conv2D(32, padding='same', kernel_size=(3,3), activation='relu')(x)
h = Conv2D(32, padding='same', kernel_size=(3,3), activation='relu')(x)
h = MaxPooling2D(pool_size=(2,2))(h)
h = Conv2D(64, padding='same', kernel_size=(3,3), activation='relu')(h)
h = Conv2D(64, padding='same', kernel_size=(3,3), activation='relu')(h)
h = MaxPooling2D(pool_size=(2,2))(h)
h = Conv2D(128, kernel_size=(3,3), activation='relu')(h)
h = Conv2D(128, kernel_size=(3,3), activation='relu')(h)
h = MaxPooling2D(pool_size=(2,2))(h)
h = Flatten()(h)
h = Dense(128, activation='relu')(h)
h = Dropout(.5)(h)
output = Dense(target_labels.shape[0], activation='softmax')(h)
model = tf.keras.Model(inputs=x, outputs=output)
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
return model
下面,你可以找到我们的模型的概要,详细列出了定义的层和每层的训练参数数量。
benchmark_model = get_benchmark_model((299, 299, 3))
benchmark_model.summary()Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 299, 299, 3)] 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 299, 299, 32) 896
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 149, 149, 32) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 149, 149, 64) 18496
_________________________________________________________________
conv2d_3 (Conv2D) (None, 149, 149, 64) 36928
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 74, 74, 64) 0
_________________________________________________________________
conv2d_4 (Conv2D) (None, 72, 72, 128) 73856
_________________________________________________________________
conv2d_5 (Conv2D) (None, 70, 70, 128) 147584
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 35, 35, 128) 0
_________________________________________________________________
flatten (Flatten) (None, 156800) 0
_________________________________________________________________
dense (Dense) (None, 128) 20070528
_________________________________________________________________
dropout (Dropout) (None, 128) 0
_________________________________________________________________
dense_1 (Dense) (None, 19) 2451
=================================================================
Total params: 20,350,739
Trainable params: 20,350,739
Non-trainable params: 0
_________________________________________________________________
我们使用回调来训练基准 CNN 模型,以在验证准确性在 10 个时期内没有提高的情况下更早地停止训练过程。这个数字应该更小,但它用于显示模型很快开始过度拟合数据。
def train_model(model, train_gen, valid_gen, epochs):
train_steps_per_epoch = train_gen.n // train_gen.batch_size
val_steps = valid_gen.n // valid_gen.batch_size
earlystopping = tf.keras.callbacks.EarlyStopping(patience=10)
history = model.fit(train_gen,
steps_per_epoch = train_steps_per_epoch,
epochs=epochs,
validation_data=valid_gen,
callbacks=[earlystopping])
return history
每次我们使用一个生成器,都需要在馈给一个模型之前进行重置;否则,我们将丢失大量数据。
train_generator = get_generator(image_gen_train, directory_train, train_valid='training')
validation_generator = get_generator(image_gen_train, directory_train, train_valid='validation')Found 12411 images belonging to 19 classes.
Found 3091 images belonging to 19 classes.history_benchmark = train_model(benchmark_model, train_generator, validation_generator, 50)Epoch 1/50
387/387 [==============================] - 747s 2s/step - loss: 2.8358 - accuracy: 0.1274 - val_loss: 2.4024 - val_accuracy: 0.2436
Epoch 2/50
387/387 [==============================] - 728s 2s/step - loss: 2.3316 - accuracy: 0.2758 - val_loss: 1.9895 - val_accuracy: 0.4170
[...]
Epoch 14/50
387/387 [==============================] - 719s 2s/step - loss: 0.3846 - accuracy: 0.8612 - val_loss: 2.4831 - val_accuracy: 0.5962
Epoch 15/50
387/387 [==============================] - 719s 2s/step - loss: 0.3290 - accuracy: 0.8806 - val_loss: 2.5545 - val_accuracy: 0.5930
下图显示了训练和验证数据集的准确性和损失随时间(时期)的演变。显然,我们的模型过度拟合了数据,因为训练的准确性接* 90%,并且验证数据集的损失实际上在过去的时期中不断增加。这也是训练中纪元数量减少的原因。
plt.figure(figsize=(15,5))
plt.subplot(121)
plt.plot(history_benchmark.history['accuracy'])
plt.plot(history_benchmark.history['val_accuracy'])
plt.title('Accuracy vs. epochs')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Training', 'Validation'], loc='lower right')
plt.subplot(122)
plt.plot(history_benchmark.history['loss'])
plt.plot(history_benchmark.history['val_loss'])
plt.title('Loss vs. epochs')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Training', 'Validation'], loc='upper right')
plt.show()
图 2:基准模型在几个时期内的准确性和损失演变。
我们可以通过使基准模型适合我们的测试数据集来评估它。结果如下所示。
test_steps = test_generator.n // test_generator.batch_size
benchmark_test_loss, benchmark_test_acc = benchmark_model.evaluate(test_generator, steps=test_steps)
print('\nTest dataset:')
print("Loss: {}".format(benchmark_test_loss))
print("Accuracy: {}".format(benchmark_test_acc))29/29 [==============================] - 9s 304ms/step - loss: 2.5011 - accuracy: 0.6272
Test dataset:
Loss: 2.5011332035064697
Accuracy: 0.6271551847457886
4.预先训练的 CNN
对于预训练的模型,我们使用 Xception 架构(【3】,【4】),在keras.applications
模块中实现的深度 CNN。我们已经加载了预训练的参数(在 ImageNet 数据集上学习的)。我们使用预训练的 CNN 作为大的特征提取层,我们用针对我们的多类分类任务的一组未训练的层来扩展它。这就是翻译原则被有效应用的地方。
feature_extractor = tf.keras.applications.Xception(weights="imagenet")feature_extractor.summary()Model: "xception"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_2 (InputLayer) [(None, 299, 299, 3) 0
__________________________________________________________________________________________________
[...]
avg_pool (GlobalAveragePooling2 (None, 2048) 0 block14_sepconv2_act[0][0]
__________________________________________________________________________________________________
predictions (Dense) (None, 1000) 2049000 avg_pool[0][0]
==================================================================================================
Total params: 22,910,480
Trainable params: 22,855,952
Non-trainable params: 54,528
_________________________________________________________________________________________________def remove_head(feature_extractor_model):
model_input = feature_extractor_model.input
output = feature_extractor_model.get_layer(name='avg_pool').output
model = tf.keras.Model(inputs=model_input, outputs=output)
return modelfeature_extractor = remove_head(feature_extractor)
feature_extractor.summary()Model: "model_1"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_2 (InputLayer) [(None, 299, 299, 3) 0
__________________________________________________________________________________________________
[...]
avg_pool (GlobalAveragePooling2 (None, 2048) 0 block14_sepconv2_act[0][0]
==================================================================================================
Total params: 20,861,480
Trainable params: 20,806,952
Non-trainable params: 54,528
__________________________________________________________________________________________________def add_new_classifier_head(feature_extractor_model):
model = Sequential([
feature_extractor_model,
Dense(128, activation='relu'),
Dropout(.5),
Dense(target_labels.shape[0], activation='softmax')
])
return model
下面,我们可以看到添加到我们的模型头部的层。
new_model = add_new_classifier_head(feature_extractor)
new_model.summary()Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
model_1 (Functional) (None, 2048) 20861480
_________________________________________________________________
dense_2 (Dense) (None, 128) 262272
_________________________________________________________________
dropout_1 (Dropout) (None, 128) 0
_________________________________________________________________
dense_3 (Dense) (None, 19) 2451
=================================================================
Total params: 21,126,203
Trainable params: 21,071,675
Non-trainable params: 54,528
_________________________________________________________________def freeze_pretrained_weights(model):
model.get_layer(name='model_1').trainable=False
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
return model
我们将预先训练的 CNN 参数冻结为不可训练的——我们可以看到在我们的新模型中有超过 2000 万个不可训练的参数。与基准模型相比,这也导致每个时期的训练时间更短。
frozen_new_model = freeze_pretrained_weights(new_model)
frozen_new_model.summary()Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
model_1 (Functional) (None, 2048) 20861480
_________________________________________________________________
dense_2 (Dense) (None, 128) 262272
_________________________________________________________________
dropout_1 (Dropout) (None, 128) 0
_________________________________________________________________
dense_3 (Dense) (None, 19) 2451
=================================================================
Total params: 21,126,203
Trainable params: 264,723
Non-trainable params: 20,861,480
_________________________________________________________________def train_model(model, train_gen, valid_gen, epochs):
train_steps_per_epoch = train_gen.n // train_gen.batch_size
val_steps = valid_gen.n // valid_gen.batch_size
history = model.fit(train_gen,
steps_per_epoch = train_steps_per_epoch,
epochs=epochs,
validation_data=valid_gen)
return historyhistory_frozen_new_model = train_model(frozen_new_model, train_generator, validation_generator, 50)Epoch 1/50
387/387 [==============================] - 564s 1s/step - loss: 2.6074 - accuracy: 0.1943 - val_loss: 2.0344 - val_accuracy: 0.4232
Epoch 2/50
387/387 [==============================] - 561s 1s/step - loss: 2.0173 - accuracy: 0.3909 - val_loss: 1.7743 - val_accuracy: 0.5118
[...]
Epoch 49/50
387/387 [==============================] - 547s 1s/step - loss: 0.4772 - accuracy: 0.8368 - val_loss: 1.7771 - val_accuracy: 0.6137
Epoch 50/50
387/387 [==============================] - 547s 1s/step - loss: 0.4748 - accuracy: 0.8342 - val_loss: 1.7402 - val_accuracy: 0.6215
我们在没有使用回调的情况下运行了更长时间的模型。我们没有看到同样的过度拟合模式,因为超过 90%的砝码被冻结。事实上,我们可以运行少量的时期,因为在 10 个时期后我们看不到真正的改进。
plt.figure(figsize=(15,5))
plt.subplot(121)
plt.plot(history_frozen_new_model.history['accuracy'])
plt.plot(history_frozen_new_model.history['val_accuracy'])
plt.title('Accuracy vs. epochs')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Training', 'Validation'], loc='lower right')
plt.subplot(122)
plt.plot(history_frozen_new_model.history['loss'])
plt.plot(history_frozen_new_model.history['val_loss'])
plt.title('Loss vs. epochs')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Training', 'Validation'], loc='upper right')
plt.show()
图 3:TL 模型在几个时期内的准确性和损失演变。
将我们的新模型与测试数据集进行拟合,结果是精度略有提高(略高于 1%)。
test_generator = get_generator(image_gen_test, directory_test)
new_model_test_loss, new_model_test_acc = frozen_new_model.evaluate(test_generator, steps=test_steps)
print('\nTest dataset')
print("Loss: {}".format(new_model_test_loss))
print("Accuracy: {}".format(new_model_test_acc))Found 950 images belonging to 19 classes.
29/29 [==============================] - 33s 1s/step - loss: 1.6086 - accuracy: 0.6390
Test dataset
Loss: 1.6085671186447144
Accuracy: 0.639008641242981
5.数据扩充
正如我们在上面看到的,DA 是一组用于膨胀数据集同时减少过度拟合的方法。我们关注由几何和光度变换组成的通用 DA(参见【5】了解更多关于这些和其他方法的信息)。几何变换改变了图像的几何形状,使得 CNN 不会因位置和方向的改变而改变。另一方面,光度变换通过调整图像的颜色通道,使 CNN 不受颜色和光照变化的影响。
def get_ImageDataGenerator_augmented(validation_split=None):
image_generator = ImageDataGenerator(rescale=(1/255.),
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.1,
brightness_range=[0.8,1.2],
horizontal_flip=True,
validation_split=validation_split)
return image_generatorimage_gen_train_aug = get_ImageDataGenerator_augmented(validation_split=0.2)train_generator_aug = get_generator(image_gen_train_aug, directory_train, train_valid='training', seed=1)
validation_generator_aug = get_generator(image_gen_train_aug, directory_train, train_valid='validation')Found 12411 images belonging to 19 classes.
Found 3091 images belonging to 19 classes.train_generator = get_generator(image_gen_train, directory_train, train_valid='training', seed=1)Found 12411 images belonging to 19 classes.
我们可以显示原始图像和增强图像进行比较。请注意图像的几何变化,如翻转、垂直和水*方向的*移或缩放,以及光度测定,在一些图像的亮度变化中可见。
batch = next(train_generator)
batch_images = np.array(batch[0])
batch_labels = np.array(batch[1])
aug_batch = next(train_generator_aug)
aug_batch_images = np.array(aug_batch[0])
aug_batch_labels = np.array(aug_batch[1])
plt.figure(figsize=(16,5))
plt.suptitle("original images", fontsize=16)
for n, i in enumerate(np.arange(10)):
ax = plt.subplot(2, 5, n+1)
plt.imshow(batch_images[i])
plt.title(target_labels[np.where(batch_labels[i]==1)[0][0]])
plt.axis('off')
plt.figure(figsize=(16,5))
plt.suptitle("Augmented images", fontsize=16)
for n, i in enumerate(np.arange(10)):
ax = plt.subplot(2, 5, n+1)
plt.imshow(aug_batch_images[i])
plt.title(target_labels[np.where(batch_labels[i]==1)[0][0]])
plt.axis('off')
图 4:一组没有任何变换的图像和相应的增强图像之间的比较。
train_generator_aug = get_generator(image_gen_train_aug, directory_train, train_valid='training')Found 12411 images belonging to 19 classes.
扩充的数据集现在被提供给我们上面定义的定制模型(不使用预先训练的权重)。
benchmark_model_aug = benchmark_model
benchmark_model_aug.summary()Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 299, 299, 3)] 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 299, 299, 32) 896
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 149, 149, 32) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 149, 149, 64) 18496
_________________________________________________________________
conv2d_3 (Conv2D) (None, 149, 149, 64) 36928
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 74, 74, 64) 0
_________________________________________________________________
conv2d_4 (Conv2D) (None, 72, 72, 128) 73856
_________________________________________________________________
conv2d_5 (Conv2D) (None, 70, 70, 128) 147584
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 35, 35, 128) 0
_________________________________________________________________
flatten (Flatten) (None, 156800) 0
_________________________________________________________________
dense (Dense) (None, 128) 20070528
_________________________________________________________________
dropout (Dropout) (None, 128) 0
_________________________________________________________________
dense_1 (Dense) (None, 19) 2451
=================================================================
Total params: 20,350,739
Trainable params: 20,350,739
Non-trainable params: 0
_________________________________________________________________history_augmented = train_model(benchmark_model_aug, train_generator_aug, validation_generator_aug, epochs=150)Epoch 1/150
387/387 [==============================] - 748s 2s/step - loss: 2.1520 - accuracy: 0.3649 - val_loss: 1.8956 - val_accuracy: 0.4426
Epoch 2/150
387/387 [==============================] - 749s 2s/step - loss: 1.8233 - accuracy: 0.4599 - val_loss: 1.6556 - val_accuracy: 0.5273
[...]
Epoch 149/150
387/387 [==============================] - 753s 2s/step - loss: 0.2859 - accuracy: 0.9270 - val_loss: 0.6202 - val_accuracy: 0.8609
Epoch 150/150
387/387 [==============================] - 753s 2s/step - loss: 0.2830 - accuracy: 0.9259 - val_loss: 0.6289 - val_accuracy: 0.8622
过度拟合显然不再是一个问题。训练可以运行更长的时期,因为它显示了度量的一致改进。不过,我们可以在大约第 70 个纪元时停止学习过程,但是我们扩展了这个过程,以表明 DA 实际上可以减少过度拟合的可能性。此外,请注意,我们增加了模型识别属于每个字符的数据中的特征的能力,因为验证集的准确性显著提高(超过 86%)。
plt.figure(figsize=(15,5))
plt.subplot(121)
plt.plot(history_augmented.history['accuracy'])
plt.plot(history_augmented.history['val_accuracy'])
plt.title('Accuracy vs. epochs')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Training', 'Validation'], loc='lower right')
plt.subplot(122)
plt.plot(history_augmented.history['loss'])
plt.plot(history_augmented.history['val_loss'])
plt.title('Loss vs. epochs')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Training', 'Validation'], loc='upper right')
plt.show()
图 5:使用 DA 的定制模型在几个时期内的精度和损耗变化。
在我们的测试集上用增强的数据拟合我们的定制模型导致了超过 91%的显著增加的准确性。
test_generator = get_generator(image_gen_test, directory_test)
augmented_model_test_loss, augmented_model_test_acc = benchmark_model_aug.evaluate(test_generator, steps=test_steps)
print('\nTest dataset')
print("Loss: {}".format(augmented_model_test_loss))
print("Accuracy: {}".format(augmented_model_test_acc))Found 950 images belonging to 19 classes.
29/29 [==============================] - 9s 307ms/step - loss: 0.4446 - accuracy: 0.9106
Test dataset
Loss: 0.44464701414108276
Accuracy: 0.9105603694915771
6.结果
最后,我们可以比较基准模型、使用 TL 原则定义的预训练模型和带有扩充数据的定制模型之间的训练、验证和测试指标。结果表明,TL 方法仅略微优于基准模型。这可能是由于模型最初被训练的数据(域)的性质以及它如何转移到 Simpsons 字符域。另一方面,使用扩充数据的方法能够更有效地捕捉数据中的模式,将测试集中的准确率提高到 91%以上。
benchmark_train_loss = history_benchmark.history['loss'][-1]
benchmark_valid_loss = history_benchmark.history['val_loss'][-1]
benchmark_train_acc = history_benchmark.history['accuracy'][-1]
benchmark_valid_acc = history_benchmark.history['val_accuracy'][-1]
new_model_train_loss = history_frozen_new_model.history['loss'][-1]
new_model_valid_loss = history_frozen_new_model.history['val_loss'][-1]
new_model_train_acc = history_frozen_new_model.history['accuracy'][-1]
new_model_valid_acc = history_frozen_new_model.history['val_accuracy'][-1]
augmented_model_train_loss = history_augmented.history['loss'][-1]
augmented_model_valid_loss = history_augmented.history['val_loss'][-1]
augmented_model_train_acc = history_augmented.history['accuracy'][-1]
augmented_model_valid_acc = history_augmented.history['val_accuracy'][-1]comparison = pd.DataFrame([['Training loss', benchmark_train_loss, new_model_train_loss, augmented_model_train_loss],
['Training accuracy', benchmark_train_acc, new_model_train_acc, augmented_model_train_acc],
['Validation loss', benchmark_valid_loss, new_model_valid_loss, augmented_model_valid_loss],
['Validation accuracy', benchmark_valid_acc, new_model_valid_acc, augmented_model_valid_acc],
['Test loss', benchmark_test_loss, new_model_test_loss, augmented_model_test_loss],
['Test accuracy', benchmark_test_acc, new_model_test_acc, augmented_model_test_acc]],
columns=['Metric', 'Benchmark CNN', 'Transfer Learning CNN', 'Custom CNN w/ Data Augmentation'])
comparison.index=['']*6
comparison
表 1:测试的 3 个模型的比较结果。带有 DA 的定制 CNN 产生了最好的结果——测试准确率超过 91%。
为了说明使用 DA 的自定义 CNN 输出,我们绘制了测试集中随机图像预测的分类分布。
test_generator = get_generator(image_gen_test, directory_test, seed=123)
predictions = benchmark_model_aug.predict(test_generator)Found 950 images belonging to 19 classes.test_generator = get_generator(image_gen_test, directory_test, seed=123)
batches = []
for i in range(1):
batches.append(next(test_generator))
batch_images = np.vstack([b[0] for b in batches])
batch_labels = np.concatenate([b[1].astype(np.int32) for b in batches])Found 950 images belonging to 19 classes.fig, axes = plt.subplots(3, 2, figsize=(16, 17))
fig.subplots_adjust(hspace = 0.4, wspace=0.8)
axes = axes.ravel()
for i in range(3):
inx = np.random.choice(batch_images.shape[0], 1, replace=False)[0]
axes[0+i*2].imshow(batch_images[inx])
axes[0+i*2].get_xaxis().set_visible(False)
axes[0+i*2].get_yaxis().set_visible(False)
axes[0+i*2].text(60., -8, target_labels[np.where(batch_labels[inx]==1)[0][0]],
horizontalalignment='center')
axes[1+i*2].barh(np.arange(len(predictions[inx])),predictions[inx])
axes[1+i*2].set_yticks(np.arange(len(predictions[inx])))
axes[1+i*2].set_yticklabels(target_labels)
axes[1+i*2].set_title(f"Categorical distribution. Model prediction: {target_labels[np.argmax(predictions[inx])]}")
plt.show()
图 6:随机图像(在左边)和由定制 CNN 产生的预测的相应分类分布,带有 DA ( 在右边)
7.结论
我们使用两种不同的方法解决了小数据集和高过拟合可能性的问题。首先,我们加载了一个预先训练好的模型,从中我们删除了顶层,并添加了我们的任务所需的一组特定的层。第二种方法测试了使用 DA 技术来扩充我们的数据集。我们的结果表明,第二种方法能够克服有限的数据和过拟合问题,产生非常有趣的指标。
可以通过在不同类型的数据集中测试更多的架构或预先训练的网络来进一步研究 TL 原则。在这种情况下,面部识别任务的预训练模型可能会产生有趣的结果。关于 DA 方法,它可以通过应用更复杂的变换来扩展。
保持联系: LinkedIn
8.参考
【1】——【庄等,2020】庄,f,齐,z,段,k,,d,朱,y,朱,h,熊,h,何,Q. (2020)。迁移学习综述。
【2】——【谭等,2018】谭,孙,孔,张,杨,刘(2018)。深度迁移学习综述。
【3】——【乔莱,2017】乔莱,F. (2017)。例外:具有深度可分卷积的深度学习。
【4】——https://keras.io/api/applications/xception/
【5】——https://arxiv.org/pdf/1708.06020.pdf
【6】——https://www . ka ggle . com/Alex attia/the-Simpsons-characters-dataset
迁移学习和 RNN——CoreNLP 系列
原文:https://towardsdatascience.com/transfer-learning-and-rnn-the-corenlp-series-pt-iii-2944f42a19a0?source=collection_archive---------33-----------------------
这篇文章旨在测试 CoreNLP 预训练的 RNN 在不同领域做出预测的能力。
大家好,欢迎来到第三个*(可能也是最后一个?我还没决定…* 🙄 ) 本 coreNLP 系列的一部分!在本系列的前几篇文章中,我已经介绍了 coreNLP 库和研究了他们为情感分析计算句子嵌入方式背后的理论。
这将是一篇更加实用的文章,在这篇文章中,我将解决 RNN 的一个最大限制:很难(几乎不可能)重新训练模型。在这篇文章中,我将解释迁移学习的概念,作为这个培训问题的解决方案。我还将在两个数据集上测试 RNN ,这两个数据集在二元情感分类任务的训练中没有出现过。
梁杰森在 Unsplash 上的照片
RNN 模式的培训局限性
从我使用 coreNLP 的体验来看,Socher 的递归模型最讨厌的地方(除了运行的时间)就是基本不可能重新训练。
CoreNLP 实际上使你用一个简单的命令重新训练模型变得非常容易。然而,问题是你需要一个非常特殊的训练数据集。
如前所述,为了综合学习句子的情感,在 RNN 解析树的每个节点处构建了一个 softmax 分类器。这意味着,为了训练这个 RNN,基本上在树的每个节点都需要真实标签(情感分数范围从 0-4)!让我们更深入地了解一下这意味着什么…
- 斯坦福情感树库。
为了进行这种特殊的训练,创建了一个标记了已解析树的语料库:斯坦福情感树库 。这个语料库由 11,855 个单句组成,这些单句是从电影评论中提取的,更具体地说是从由庞和李(2005)介绍的烂番茄数据集中提取的。原始文本数据被解析,获得 215,154 个唯一短语。这些短语由三位人类评委根据他们的情感手动标注**。因此,情感树库包括数千个句子中每个可能短语的情感标签,允许 RNTN 被训练预测句子每个节点的情感。**********
这个语料库对于训练和测试 RNN 非常有效,但是它的复杂性使得它很难复制。想象一下……人们需要手动标注语料库中的每个单词、短语、短语和句子!!这是一个很大的限制,因为它使得在电影评论之外的一些语料库上重新训练和测试模型变得非常困难。
迁移学习
由于上述限制,我们无法重新培训 RNN。然而,在本帖中,我们感兴趣的是使用 RNN 在其他数据集上进行预测,而不一定是来自烂番茄的电影评论。我们如何面对训练和测试数据不同的问题?
机器学习的整个研究领域都试图在不同的数据集(或领域)上重用在一个数据集(或领域)中训练的分类器。这被称为迁移学习或领域适应。这是一个旨在将在源域上训练的分类器推广到目标域的领域。
有许多原因**为什么人们想要重用在一个领域(例如电影评论)上训练的分类器来对另一个领域(例如餐馆评论)进行预测。可以说,最主要的问题是我们在这篇文章中面临的问题:有时收集训练数据是一项困难而昂贵的任务。
这个问题在现实世界中经常出现,因此已经开发了非常复杂的迁移学习技术来解决它。我不打算深入探讨它们。在这篇文章中,我的主要目的是简单地了解一下在电影评论领域训练有素的 RNN 如何能够推广到其他领域**。**
任务
在这篇文章中,我们将测试预训练的 RNN 在句子级别的二元情感分类任务。RNN 是在电影评论这个来源领域接受训练的。测试将在两个不同的目标领域上进行:餐馆评论和电子评论。****
在性能方面,Socher 等人(2013)报告说,RNN 可以在句子级别上对二元情感分类实现 85.4%的准确率。****
****的目标将是比较 RNN 在源域和目标域上的性能。通过这种方式,我们将能够得出一些结论,即 Socher 的模型能够如何将其学习成果转移到训练期间未见过的其他数据集进行预测。
目标领域:餐馆和电子产品
为了测试 RNN 的领域适应能力,我选择了两个数据集作为目标领域**。他们都是基于评论,以确保写作风格保持不变。不同之处在于评论的主题:电子产品和餐馆T21。******
****
数据集 1 包含来自亚马逊网站上分类为“手机和配件”、的评论的句子,是麦考利和莱斯科维奇收集的更大数据集的一部分。数据集 2 的实例从 Yelp 挑战数据集获得,该数据集是在 Yelp *台上发布的餐厅评论的更大数据集。
两个数据集的大小相同:每个都有 1000 个句子。根据他们的情感,句子被二进制标记为否定(0 类)或肯定(1 类)。为了强化数据集的极性,不考虑具有中性评级的综述。类是*衡的,每种情绪 500 个实例。评论的长度及其在两个数据集上的分布非常相似**。**
方法学
该过程分为三个步骤。所有的代码都可以在我的 GitHub 上找到,但是我现在将浏览一些主要部分!
- 数据探索和格式化
第一个脚本formatting_and_eda.py
获取上面的统计数据并生成直方图。它还在目录test_data
中生成.txt
文件。文件X_amazon.txt
和X_yelp.txt
是 RNN 将要进行预测的评论。文件Y_amazon.txt
和Y_yelp.txt
是真正的标签,我们将使用它们进行评估。
2。RNN 预测
第二个脚本coreNLP_pipeline4.py
运行 coreNLP 管道。这个 coreNLP 管道是为了预测单个句子的情感得分而构建的。预测得分以五个不同类别标签(1-5)的分布形式输出。
我们的结果将被打印到predictions_amazon.txt
和predictions_yelp.txt.
上,它们将以数据帧的形式组织,包含以下各列:
review_id, sent_id, sentence, score, very_neg, neg, neu, pos, very_pos
其中very_neg, neg, neu, pos, very_pos
是 RNN 预测的句子非常否定、否定、中性、肯定和非常肯定的概率。
该文件必须带有两个参数:输入文件和数据集的名称。例如:
java -cp “*” coreNLP_pipeline4.java test_data/X_amazon.txt amazon
我在stanford-corenlp-4.1.0
文件夹中运行了两次:一次用于 amazon 数据,另一次用于 yelp 数据。
3。结果评估
一旦我们有了预测器的结果,剩下的唯一事情就是评估它们相对于 y 的真实值有多好。这就是evaluation.py
所做的。
然而,Y_true 的值是二进制的:0 或 1,Y_pred 的值是分布在五个值上的概率:非常正、正、中性、负和非常负。因此,为了对结果进行评估,我们必须首先对它们进行二值化。
为了将它们转换成 1 和 0,我们去掉中性列,将正负概率相加,得到正负总得分。如果一个句子的总正面得分大于总负面得分,那么它的目标值将是 1,反之亦然。
为了评估,我们将计算准确度**、精度、召回和一个混淆矩阵。**
结果
Socher 等人(2013)报告称,RNTN 在句子级别上对二元情感分类可以达到 85.4% 的准确率。从下表中可以看出,目标领域的分类准确度较低:电子领域的准确度为 79%,餐馆领域的准确度为 80%。****
然而,尽管表现不佳,我们仍然可以自信地说 Socher 的递归模型 能够对电子产品和餐馆的目标域进行跨域分类达到良好的标准。
令人感兴趣的是,在执行该评估时获得的其他度量可以提供递归分类器的行为。对于两个目标领域,该模型在分类类别 1(肯定句)方面似乎比类别 0(否定句)表现得更好。这两个目标域之间的性能似乎也没有太大差异。
结论
这都是为了现在!我希望你喜欢它,并希望你有动力在不同的领域使用这个超级酷的模型,相信性能会相对较好。下次见!✌🏻
文献学
Socher,r .,Perelygin,a .,Wu,j .,Chuang,j .,Manning,C.D .,ng,a .,Potts,c .,2013 年 10 月。情感树库语义合成的递归深度模型。在2013 年自然语言处理经验方法会议论文集(第 1631-1642 页)。可在:https://www.aclweb.org/anthology/D13-1170
斯坦福科伦普。(未注明)。斯坦福 CoreNLP——自然语言软件。可在:https://stanfordnlp.github.io/CoreNLP/
使用来自 MATLAB 的 Alexnet 预训练网络对 Unsplash 数据应用迁移学习
原文:https://towardsdatascience.com/transfer-learning-applied-on-the-unsplash-data-using-alexnet-pretrained-network-2fc6aa70d43a?source=collection_archive---------35-----------------------
使用 MATLAB 预先训练的深度学习网络进行迁移学习可以很容易地实现,以获得快速和令人印象深刻的结果
我从 Unsplash 获得了图像数据。我下载了 42 幅猫的图像、46 幅狗的图像和 35 幅马的图像,输入到 MATLAB 中预先训练好的 Alexnet 模型中。有关 MATLAB 中 Alexnet 网络的详细信息,请参见其文档。
照片由 JJ 英在 Unsplash 上拍摄
Alexnet
AlexNet 是一个 8 层深度的卷积神经网络。MATLAB 有一个预先训练好的网络版本,对来自 ImageNet 数据库的 100 多万张图像进行训练。预训练的网络可以将图像分类为 1000 个预定义的对象类别。
针对一百万幅图像上的 1000 个对象类别的训练使得该网络学习了广泛图像的丰富特征表示。
https://www.earthinversion.com/machinelearning/transfer-learning-applied-on-unsplash-data-using-alexnet/
装置
您可以通过键入以下命令来检查 alexnet 的安装
alexnet
在命令行中。如果没有安装,它会在附加资源管理器中提示指向所需支持包的链接。简单来说,跟着链接走。
为什么要转学?
迁移学习因其速度快、易于实现而成为深度学习应用中的热门。人们可以使用预先训练好的网络,并将其作为学习新任务的起点。这使用较少数量的训练图像将学习的特征快速转移到新的任务。
数据
我从 Unsplash 网站上获得了这三类图片。Unsplash 提供了数百万张高质量的免费图片。我获得了猫、狗和马的图像。使用这些类别没有特定的原因,但使用猫和狗已经成为测试任何模型的标准,因为它提供了足够的鲁棒性。
我将数据保存到三个子文件夹中,分别标有cats
、dogs
和horses
,在文件夹unsplashData
下。我将压缩数据保存在包含脚本的文件夹中。
准备数据
我们做的第一件事是使用unzip
命令解压数据。然后,我们根据文件夹名称自动标记图像,并将数据存储为一个ImageDatastore
对象。
clear; close; clc;
%% Unzip and load the new images as an image datastore
filename = 'unsplashData';
unzip(strcat(filename,'.zip'));
% imageDatastore automatically labels the images based on folder names and stores the data as an ImageDatastore object
imds = imageDatastore(filename, ...
'IncludeSubfolders',true, ...
'LabelSource','foldernames');
将数据分为训练数据集和验证数据集
我们使用随机选择的图像的 70%用于训练,30%用于验证。
[imdsTrain,imdsValidation] = splitEachLabel(imds,0.7,'randomized');
可视化加载的图像
我们绘制了 16 个随机选择的数据。
visualize = 1;
if visualize==1
numTrainImages = numel(imdsTrain.Labels);
idx = randperm(numTrainImages,16);
fig1 = figure;
for i = 1:16
subplot(4,4,i)
I = readimage(imdsTrain,idx(i));
imshow(I)
end
print(fig1,strcat(filename,'input-data-selected'),'-djpeg')
end
作者图片
负载预训练网络
net = alexnet;
inputSize = net.Layers(1).InputSize
来分析 alexnet 网络的层次。
inspect_network=0;
if inspect_network==1
analyzeNetwork(net)
end
作者图片
替换最后三层
我们从预训练的网络中提取所有层,除了最后三层。可以增加完全连接层的 WeightLearnRateFactor 和 BiasLearnRateFactor 值,以便在新层中比在转移层中学习得更快
layersTransfer = net.Layers(1:end-3);
numClasses = numel(categories(imdsTrain.Labels)) %the number of classes in the new data
layers = [
layersTransfer
fullyConnectedLayer(numClasses,'WeightLearnRateFactor',20,'BiasLearnRateFactor',20)
softmaxLayer
classificationLayer];
使用增强的图像数据库来自动调整训练图像的大小
alexnet 网络设计用于处理固定尺寸(227 x 227 x 3)的图像。我们遵循标准操作来扩充训练图像——沿着垂直轴随机翻转训练图像,将它们随机水*和垂直*移 30 个像素。数据扩充对于防止网络过度拟合和记忆训练图像的精确细节是必要的。
pixelRange = [-30 30];
imageAugmenter = imageDataAugmenter( ...
'RandXReflection',true, ... %randomly flip the training images along the vertical axis
'RandXTranslation',pixelRange, ... %randomly translate them up to 30 pixels horizontally and vertically
'RandYTranslation',pixelRange);
augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain, ...
'DataAugmentation',imageAugmenter);
% automatically resize the validation images without performing further data augmentation
augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);
微调培训选项
应用迁移学习的目标是保持预训练网络早期层的特征(迁移的层权重)。
options = trainingOptions('sgdm', ...
'MiniBatchSize',10, ... %when performing transfer learning, you do not need to train for as many epochs
'MaxEpochs',6, ...
'InitialLearnRate',1e-4, ... %slow down learning in the transferred layers ( fast learning only in the new layers and slower learning in the other layers)
'Shuffle','every-epoch', ...
'ValidationData',augimdsValidation, ...
'ValidationFrequency',3, ...
'Verbose',false, ...
'Plots','training-progress', ...
'ExecutionEnvironment','auto'); %Hardware resource for training network - auto, cpu, gpu, multi-gpu, parallel
训练网络
我们训练由转移层和新层组成的网络。
netTransfer = trainNetwork(augimdsTrain,layers,options); %By default, trainNetwork uses a GPU if one is available
分类验证图像
[YPred,scores] = classify(netTransfer,augimdsValidation); %classify using the fine-tuned network
我们显示了四个样本验证图像及其预测标签。
classify_visualize = 1;
if classify_visualize==1
idx = randperm(numel(imdsValidation.Files),4);
fig = figure;
for i = 1:4
subplot(2,2,i)
I = readimage(imdsValidation,idx(i));
imshow(I)
label = YPred(idx(i));
title(string(label));
end
print(fig,strcat(filename,'classification-result'),'-djpeg')
end
作者图片
分类准确度
分类准确度给出了网络正确预测的标签的比例。
YValidation = imdsValidation.Labels;
accuracy = mean(YPred == YValidation)% accuracy = 0.9189
结论
我使用 MATLAB 中预先训练的 Alexnet 网络,用 Unsplash 数据对其进行微调。但是,它有可能导致图像数据的任何分类问题。我们还应该探索 MATLAB 提供的其他几个预训练网络,如 squeezenet、resnet18、googlenet 等,以实现更好的准确性。准确性在很大程度上取决于数据数量、质量和模型参数,如层数。
原载于 2021 年 4 月 25 日【https://www.earthinversion.com】。
迁移学习:来自胸部 x 光分类器的新冠肺炎
原文:https://towardsdatascience.com/transfer-learning-covid-19-from-chest-x-rays-classifier-66d6c483fb03?source=collection_archive---------11-----------------------
照片由泰在 Unsplash 上抓拍
关于如何进行迁移学习的详细概述以及每一步背后的一些理论。
简介
冠状病毒病(新冠肺炎)是一种由新发现的冠状病毒引起的传染病。大多数感染新冠肺炎病毒的人会经历轻度至中度的呼吸道疾病,无需特殊治疗即可康复。老年人以及那些患有心血管疾病、糖尿病、慢性呼吸系统疾病和癌症等潜在疾病的人更有可能患上严重疾病。(世卫组织,2020 年)。虽然大多数新冠肺炎患者康复并恢复正常健康,但一些患者在急性疾病康复后可能会出现持续数周甚至数月的症状。即使是没有住院的人和病情较轻的人也可能出现持续或晚期症状。(美国疾病预防控制中心,2020 年)。
正在进行多年的研究以进一步调查,并且目前进行这些实验的一种方式是通过分析以前的新冠肺炎患者根据时间肺部和胸腔其他方面的变化。这需要时间和大量资源。然而,机器学习技术不仅可以用于测试目的,还可以用于对延迟效应的长期研究。因此,这个项目的目的是建立一个二元分类器来确定 X 射线图像中新冠肺炎的存在。
本文中使用的数据集可以在这里找到,这是一个由 441 个正面和 505 个正常图像组成的开源存储库。然而,来自卡塔尔多哈的卡塔尔大学和孟加拉国达卡大学的一组研究人员与他们来自巴基斯坦和马来西亚的合作者一起,与医生合作,为新冠肺炎阳性病例和正常图像创建了一个胸部 X 射线图像数据库,可在 Kaggle 上以“新冠肺炎射线照相数据库的名称获得。在当前版本中,有 1143 个新冠肺炎阳性图像和 1341 个正常图像。类似于这里介绍的方法也可以应用于后一个数据集,这似乎比本例中使用的方法更加健壮和可靠。
一些 ML 伦理
本文的主要目的是在一个有趣的话题中展示迁移学习的方法。这种方法不应该被认为是对病人的诊断,因为它是在这里提出的。为了让它服务于大规模的预测,必须进行额外的研究和改进。这篇文章的发现和方法并不意味着鼓励读者自我诊断或诊断其他人对新冠肺炎的看法。如果你有任何症状,或者与被诊断患有新冠肺炎的人有过接触,请遵循你所在国家制定的方案,并从你所在地区更准确的检测方法中寻求安慰。最重要的是,请保持安全。
数据预处理
这个项目利用深度学习来建立胸部 x 光图像的二元分类器,并预测新冠肺炎的存在。这些图像经过预处理并调整到 150528 尺寸(224,224,3),这意味着它们从 BGR 转换为 RGB 颜色格式。这在使用 OpenCV 库的 imread()方法时尤其必要,因为它的颜色顺序是 BGR,不同于 Pillow 假定颜色顺序为 RGB。图像被转换成像素矩阵,然后归一化到 0 和 1 之间的区间。在预处理之后,根据它们的原始目录给每个图像分配标签。下面可以看到这些图像的概述。
**图片 1(作者):**根据数据集,显示了使用和不使用新冠肺炎的胸部 x 光图像。标签是根据从公共数据集下载的原始目录分配的。假设图像被适当地分类,因为我缺乏医疗保健科学方面的专业知识,不允许我对图像是否被正确标记做出准确的推断。
在预处理之后,大约 20%的数据集被留出用于测试,剩下 80%的图像用于训练。下面可以看到这两个数据集的一瞥。请注意,有些图像似乎来自核磁共振成像研究,而不是胸部 x 光片。此外,一些 x 光片似乎是侧面图像和 CT 扫描。这是该模型的一个缺点,因为几乎不可能有一个完美的公共数据集。然而,在训练之前,可以采取额外的预处理步骤来分割每种类型的扫描。鉴于该数据集中可用的图像数量有限,这种预处理步骤将被取消,但可能会在该实验的未来迭代中重新考虑。
**图 2(作者):**数据集被分割用于训练和测试后的一瞥。
型号
具有 imagenet 权重的 VGG19 卷积神经网络 (CNN)被用作我们的模型的核心。 Keras 应用程序类允许我们导入 CNN,有一个 2D 最大池输出层的形状(7,7,512)并且没有参数。因此,转移学习用于使输出层适应二元分类器,因为我们只有两个分类类,Covid19 和 No-Covid19。输出从最后一层提取,并作为参数添加到展*层。这一层将数据转换成一维数组作为单个长特征向量,用于将其输入到下一层作为完全连接的层。在我们的示例中,由于该层位于 shape (7,7,512)的 2D 最大池输出层之后,因此展*数组的维数为 77512 = 25088。这通常在 CNN 的最后阶段完成,因为矩形或立方体形状不能直接输入。
接下来,增加一个脱落层主要作为一种有效的正则化方法来减少过拟合和改善泛化误差。由于我们的目标是建立一个二元分类器,层的输出被丢弃的概率被设置为 0.5,这实际上是一个常见的值。这是在假设相对较小的数据集上的大型神经网络通常会过度拟合训练数据,从而降低我们的验证准确性的情况下完成的。当模型过度拟合时,模型会学习训练数据中的统计噪声,导致在新数据(主要是我们的验证数据集)上评估模型时性能不佳。
然后,添加两个单位(用于分类两个不同的对象)的密集层作为输出层,并使用 softmax 函数作为激活函数。Softmax 通常用于预测多项式概率分布的神经网络模型的输出层。换句话说,它可以用于多类分类。然而,它仍然适用于两个单元密集层中的二元分类器。
最后,使用分类交叉熵损失函数(因为模型的输出是分类的)和亚当优化器来编译模型。交叉熵损失允许训练 CNN,使得它输出每个图像的类的概率,这有助于从概率上区分一个图像和另一个图像。作为随机梯度下降的扩展,Adam 优化器应用 Adam 优化算法来基于训练数据迭代地更新网络权重。它保持每个参数的学习率,该学习率提高了在具有稀疏梯度的问题上的性能,并且基于权重的梯度的最*幅度的*均值(例如,它变化得有多快)进行调整。这意味着这个优化器在有噪声的问题上表现很好,考虑到我们之前提到的数据集的缺点,这一点很重要。有关模型的摘要,请参见下面的输出。
Model: "model" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) [(None, 224, 224, 3)] 0 _________________________________________________________________ block1_conv1 (Conv2D) (None, 224, 224, 64) 1792 _________________________________________________________________ block1_conv2 (Conv2D) (None, 224, 224, 64) 36928 _________________________________________________________________ block1_pool (MaxPooling2D) (None, 112, 112, 64) 0 _________________________________________________________________ block2_conv1 (Conv2D) (None, 112, 112, 128) 73856 _________________________________________________________________ block2_conv2 (Conv2D) (None, 112, 112, 128) 147584 _________________________________________________________________ block2_pool (MaxPooling2D) (None, 56, 56, 128) 0 _________________________________________________________________ block3_conv1 (Conv2D) (None, 56, 56, 256) 295168 _________________________________________________________________ block3_conv2 (Conv2D) (None, 56, 56, 256) 590080 _________________________________________________________________ block3_conv3 (Conv2D) (None, 56, 56, 256) 590080 _________________________________________________________________ block3_conv4 (Conv2D) (None, 56, 56, 256) 590080 _________________________________________________________________ block3_pool (MaxPooling2D) (None, 28, 28, 256) 0 _________________________________________________________________ block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160 _________________________________________________________________ block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808 _________________________________________________________________ block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808 _________________________________________________________________ block4_conv4 (Conv2D) (None, 28, 28, 512) 2359808 _________________________________________________________________ block4_pool (MaxPooling2D) (None, 14, 14, 512) 0 _________________________________________________________________ block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808 _________________________________________________________________ block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808 _________________________________________________________________ block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808 _________________________________________________________________ block5_conv4 (Conv2D) (None, 14, 14, 512) 2359808 _________________________________________________________________ block5_pool (MaxPooling2D) (None, 7, 7, 512) 0 _________________________________________________________________ flatten (Flatten) (None, 25088) 0 _________________________________________________________________ dropout (Dropout) (None, 25088) 0 _________________________________________________________________ dense (Dense) (None, 2) 50178 ================================================================= Total params: 20,074,562 Trainable params: 50,178 Non-trainable params: 20,024,384 _________________________________________________________________
测试和分析
在我们的 VGG19 CNN 上进行迁移学习后,该模型使用 250 个时期的 32 个批次大小进行训练。基于 F-1 分数,其准确度为 0.88,并且能够在第一个 50 个时期后达到类似的验证和训练准确度,这可以从下图的模型准确度图中看出。之所以选择这一精确度指标,是因为它也被称为精确度和召回率的调和*均值。它是根据测试的精确度和召回率计算的,其中精确度是正确识别的阳性结果的数量除以所有阳性结果的数量,包括那些没有正确识别的阳性结果,而召回率是正确识别的阳性结果的数量除以本应被识别为阳性的所有样本的数量。
**图 1(作者):**我们的二元分类器相对于历元数的训练和验证(测试)精度。
还绘制了受试者操作特征曲线(ROC 曲线),其说明了当其辨别阈值变化时我们的二元分类器的诊断能力。ROC 曲线是通过在各种阈值设置下绘制真阳性率(TPR)对假阳性率(FPR)来创建的。真阳性率也称为回忆灵敏度,而假阳性率也称为虚警概率,可以计算为(1 特异性)。因此,ROC 曲线是灵敏度或回忆作为脱落的函数。因此,一个好的分类器能够具有高召回率和低假阳性率。如图 2 所示,我们的模型在假阳性率低于 0.1 时达到了高于 0.8 的真阳性率,表明性能良好。
**图 2(作者):**我们模型的 ROC 曲线。请注意如何在低假阳性率的情况下达到高召回率(真阳性率)。
最后,还绘制了归一化混淆矩阵来评估我们的模型的性能。注意大多数图像是如何被正确分类为真阳性和真阴性的。此外,假阴性率低于假阳性率,这对于新冠肺炎的环境是合乎需要的。换句话说,更保守的做法是出现假阳性,要求患者隔离,而不是错误地将阳性病例归类为阴性,允许患者外出聚会,同时传播病毒。
**图 3(作者):**预测图像的归一化混淆矩阵。
优化
请注意图 1 中的验证准确度有时会高于训练准确度。在这种情况下,假设模型不会过度拟合,但是,可能是丢弃层导致了一些奇怪的现象,其中验证精度高于某些时期的训练精度。验证集可能由比训练集“更容易”的例子组成。然而,我们需要一个非常大的差异才能产生这样的差异。交叉验证是帮助解决这一问题的好方法,因为它会尝试不同的训练和验证数据集组合。
VGG19 是图像分类的一个很好的架构选择。例如,VGGNet 是首批获得错误率低于 10%的深度学习模型之一,更具体地说,是在困难的 ILSVRC 2014 期间。尽管这种方法是有效的并且提供了良好的结果,但是它具有某些缺点,这些缺点可以通过其他方法更好地解决。虽然这里没有探讨,但是类似的方法可以展示支持向量分类器(SVC),特别是当使用径向基函数核(RBF)时,如何能够以更低的计算开销实现与 VGG16 CNN 二元分类器类似的结果。另外,一些改进甚至可能包括一些降维技术,如 PCA。此外,其他神经网络体系结构可能具有以较低的计算和存储开销实现类似结果的潜力。这方面的例子有 ResNet-50,它在 2015 年以 3.6%的错误率赢得了 ImageNet 大规模视觉识别挑战赛(ILSVRC),被认为比人类感知或 Inception-V3 更好,被认为比 VGG19 更有效。可以进行额外的研究来测试不同架构在同一数据集中进行二进制分类的性能。
该模型还可能受益于附加的预处理步骤,这些步骤倾向于增加验证结果的准确性。其中一些方法可能包括数据扩充和渐进调整大小。这些可能会在这个项目的未来迭代中被探索。
链接
Github:https://Github . com/alfonsonatcruz/covid 19-chest-x-ray-detector
参考文献
- j . brown lee(2019 年 08 月 06 日)。正则化深度神经网络的退出的温和介绍。检索于 2020 年 12 月 18 日,来自https://machine learning mastery . com/dropout-for-regulating-deep-neural-networks/
- j . brown lee(2019 年 08 月 06 日)。深度学习神经网络如何避免过拟合?检索于 2020 年 12 月 18 日,来自https://machine learning mastery . com/introduction-to-regulation-to-reduce-over fitting-and-improve-generalization-error/
- 布朗利,J. (2020 年 8 月 20 日)。深度学习的 Adam 优化算法简介。检索于 2020 年 12 月 18 日,来自https://machine learning mastery . com/Adam-optimization-algorithm-for-deep-learning/
- 冠状病毒。(未注明)。检索于 2020 年 12 月 18 日,发自 https://www.who.int/health-topics/coronavirus
- “使用 ROC 曲线进行检测器性能分析— MATLAB 和 Simulink 示例”。【www.mathworks.com】T4。检索于 2016 年 8 月 11 日。
- Jeong,J. (2019,7 月 17 日)。CNN 最直观最简单的指南。2020 年 12 月 18 日,从 https://towards data science . com/the-most-intuitive-and-easy-guide-for-convolutionary-neural-network-3607 be 47480 中检索
- 帕特尔,K. (2020,08 年 3 月)。AlexNet,VGGNet,ResNet,Inception,DenseNet 的架构比较。2020 年 12 月 18 日检索,来自https://towardsdatascience . com/architecture-comparison-of-Alex net-vggnet-resnet-inception-dense net-beb8b 116866d
- SACHAN,A. (2017 年 12 月 14 日)。使用 Keras Tensorflow 根据自己的数据微调卷积神经网络。检索于 2020 年 12 月 18 日,来自https://cv-tricks.com/keras/fine-tuning-tensorflow/
- Simonyan 和 a . zisser man(2014 年)。用于大规模图像识别的非常深的卷积网络。arXiv 预印本 arXiv:1409.1556。
- 塔库尔河(2020 年 11 月 24 日)。使用 Keras 从零开始转移学习。2020 年 12 月 18 日检索,来自https://medium . com/@ 1297 rohit/transfer-learning-from-scratch-using-keras-339834 b 153 b 9
鲁棒图像分类的迁移学习
原文:https://towardsdatascience.com/transfer-learning-data-augmentation-for-robust-image-classification-643ca88b3175?source=collection_archive---------12-----------------------
亨特·哈里特在 Unsplash 上的照片
了解如何将 Google Colab 与 VScode 结合使用,并将您的解决方案提交给 Kaggle
众所周知,Google Colab 是一个非常有用的工具,可以使用 Google 提供的硬件来开发机器学习项目。的确,在 Colab 上使用单个页面构建项目有时很复杂,而使用像 VScode 这样的 IDE 来管理一切会容易得多。嗯,有解决的办法!
打开一个新的 Colab 笔记本,输入以下命令
现在在已经启动的网页编辑器中选择并打开内容文件夹。
作者图片
你已经正式在 Google Colab 上使用 VScode 了!
资料组
我们将使用 dogs vs cats 数据集(它有一个免费的许可证),您可以在下面的链接中找到:https://www . ka ggle . com/c/dogs-vs-cats-redux-kernels-edition/overview。我将向您展示如何创建一个模型来解决这个二元分类任务,并提交您的解决方案。
为了下载该数据集,首先要做的是使用您的凭证访问 Kaggle,然后下载 kaggle.json 文件,您可以通过单击创建新的 API 令牌按钮来获得该文件。
作者图片
您现在必须将我们下载的 kaggle.json 文件加载到您的内容工作目录中。那我们来创建下面的*。这个项目需要的 py* 文件
作者图片
实用工具
让我们从 utils.py 文件开始。我们首先定义一个函数来下载包含图像的压缩文件夹,并适当地提取它们。
您现在应该会看到这样的目录结构
作者图片
您将在培训文件夹中找到的所有图像必须被分割并放入子文件夹 train 和 val 中,它们分别包含我们的培训和验证集的图像。基于 sklearn 库,我们编写了一个执行这种分割的函数。
在同一个文件中,我们还需要两个函数。第一个是 get_avg_size ,它将迭代训练集的所有图像,以计算所有图像的*均高度和宽度。这是需要的,因为我们应该指定卷积网络的输入大小,因为每个图像的输入是不同的,取*均值似乎是一个很好的妥协。
现在,我们已经清理了文件系统 e,知道了图片的*均大小,我们可以使用我们的数据来实际创建训练、验证和测试集,以提供给我们的网络。TensorFlow 为我们提供了 ImageDataGenerator 类以非常简单的方式编写基本的数据处理。
以下代码中的训练和验证预处理程序将对输入图像像素执行缩放,将它们除以 255。
ImageDataGenerator 的后续输入参数允许我们通过添加现有数据的稍微修改的副本来修改和增加数据量(数据增加)。例如, rotation_range 将图像旋转 0 到 360 度之间的任意角度。
您可以通过阅读 Tensorflow 文档了解用于数据扩充的所有参数:https://www . tensor flow . org/API _ docs/python/TF/keras/preprocessing/image/image Data generator
请注意,验证数据的预处理器没有数据扩充特性,因为我们希望保持不变,以便更好地验证我们的模型。
对于测试装置发生器自然也应该做同样的事情。
深度学习模型
我们现在继续在 deeplearning _ models . py文件中创建我们的模型。
在解决大多数 Kaggle 任务时,你不会从头开始编写一个网络,而是使用一个名为 base_model 的预训练模型,并使其适应手头的任务。把 base_model 想象成一个已经学会识别图像中重要特征的模型。我们想做的是通过添加一个由其他密集层组成的头来适应它。在我们的例子中,最后的密集层将由单个神经元组成,该神经元将使用 sigmoid 激活函数,以便我们将具有为 0 或 1(猫或狗)的输出概率。
作者图片
我们必须小心不要训练之前已经训练过的基础模型。
我们要导入的 base_model 是 MobileNetV2 非常常用于图像分类任务的任务。(https://www . tensor flow . org/API _ docs/python/TF/keras/applications/mobilenet _ v2/mobilenet v2)
训练模型
现在让我们来处理 model_training.py 文件。
在训练步骤中,我们将使用回调模型检查点,它允许我们不时地保存在每个时期找到的最佳模型(根据验证损失进行评估)。如果在耐心=x 次之后没有改善,则提前停止回调用于中断训练阶段。我们照常编译和拟合模型。记得包括两个回调。
现在让我们处理一下 model_training.py 文件。
在训练步骤中,我们将使用回调模型检查点,它允许我们不时地保存在每个时期找到的最佳模型(根据验证损失进行评估)。如果在耐心=x 次后没有改善,则提前停止回调用于中断训练阶段。所以让我们像往常一样编译和拟合模型。记得包括两个回调。
预言
让我们在 predictions.py 中编写我们的预测过程。
预测完测试图像后,下载生成的 submission.csv 文件,上传到 Kaggle,才能完成挑战!
你在排行榜上排到了什么位置?
结束了
马赛洛·波利蒂
Linkedin , Twitter , CV
吉他效果的迁移学习
原文:https://towardsdatascience.com/transfer-learning-for-guitar-effects-4af50609dce1?source=collection_archive---------13-----------------------
挡泥板布鲁斯 Jr .放大器中的真空管(图片由作者提供)
实践教程
如果每一件新事物都要从头学起,生活会有多艰难?如果你曾经学过“狗”这个词,你必须再次学习字母是有声音的符号,你可以把它们放在一起组成单词,而“c-a-t”是一种不同的有尾巴的四条腿的动物?
谢天谢地,我们的大脑非常擅长识别模式。如果你已经知道“狗”这个词表示一种动物,那么不难理解“猫”这个词代表一种不同的动物。使用我们已经知道的东西来解决类似的问题是人工神经网络中的转移学习背后的概念。
迁移学习是机器学习中的一种技术,其中从解决一个问题中获得的信息被应用到类似但不同的问题中。实际上,当训练神经网络时,这种技术可用于获得更快的收敛或更低的损失。当缺少特定问题的训练数据时,也可以使用它。
本文介绍了使用迁移学习来模拟吉他效果和放大器的几个实验的结果。(关于使用神经网络模拟模拟吉他效果和放大器的介绍,请从这里的开始。)
实验设置
这些测试有几个假设。首先,原始模型和“迁移学习增强”模型使用完全相同的层和层大小(LSTM 大小为 20,接着是密集层)。迁移学习的一个棘手部分是考虑模型架构的差异,并保持相关信息的完整性。使用相同的模型可以大大简化事情。
注:有关该特定神经网络实现的更多信息,请在此处阅读。
第二,每个迁移学习测试只使用相似声音(失真水*)的设备。测试了一个失真踏板对另一个失真踏板和一个放大器对另一个放大器的相似超速传动水*。每个目标设备首先从头开始训练(基线)。接下来,使用预先训练的模型作为起点(迁移学习增强)。
每个设备对进行两次运行:完整数据集运行(3 分钟以上的音频)和有限数据集运行(30 秒的音频)。对于数据不足的模型,使用大约相同长度的验证数据(~30 秒)来提供与完整数据集模型的合理损失比较。每 2 个时期进行一次验证,并使用 Matplotlib 绘制验证损失。
选择的失真踏板是依班娜 TS9 电子管扬声器踏板和 Boss MT-2 失真踏板。TS9 用作起始模型,MT-2 用作迁移学习模型。
TS9 模型用作 MT2 模型的起点(图片由作者提供)
选择的放大器是 Fender Blues Jr 和 Blackstar HT40。蓝调 Jr .作为起步机型,HT40 作为转移学习机型。
小布鲁斯模型被用作 HT40 模型的起点(图片由作者提供)
注意:开始的模型都是在完整的 3-4 分钟数据集上训练的(TS9 和 Blues Jr)。
使用的训练代码是 Github 上的Automated-guitar amp modeling项目,具体是同一项目的 GuitarML fork 中包含的 Colab 脚本。允许训练运行至完成,每次运行的周期数根据“验证耐心”设置 25 而变化,这意味着在 25 个周期没有改善后,训练自动停止。应当注意,在该代码中还实现了自适应学习率。
失真踏板测试
Boss MT-2 全数据集
进行的第一次测试是从 TS9 型号开始的 Boss MT-2。即使这些是相似的踏板,它们的失真质量在音乐上是不同的。MT-2 驱动器被拨回,以更紧密地匹配 TS9 的较轻失真,这是在全驱动设置。验证损失比较如下所示。
图 1: Boss MT2 与来自 TS9 的 Boss MT2,完整数据集(作者提供的图)
最显著的差异是起始损失,这是在前两个时期之后测量的。迁移学习模型能够从 0.37 快速下降到 0.06。总体趋势显示,转移模型的损失略低,持续到运行结束。0.004 的整体损失改善(对我的耳朵来说)不是听觉上的更好。在这种情况下,最佳点似乎就在第 50 时段之前,此时损耗差约为 0.02。
Boss MT-2 精简数据集
第二个测试使用 30 秒的相同 MT-2 数据进行训练,而不是完整的 150 秒。30 秒的音频仍然用于验证,因为较短长度的验证数据可能导致看似较低的损失值。
图 2:来自 TS9 的 Boss MT2 与 Boss MT2,有限的训练数据集(30 秒)(图由作者提供)
由于训练数据集更小,训练时间减少了一半,如果使用更小的验证集,时间会更短。(同样,为了更准确的比较,验证集保持与完整数据训练中相同的长度,大约 30 秒)。
开始的损失要低得多,在迁移学习模型持续改进的 60 年代前后,趋势相似。迁移学习模型也继续在更多的时期有非常小的改进,直到在时期 263 停止。与完整数据集测试相比,从头开始模型和迁移学习模型之间的损失差异在 60 代左右开始更显著。0.023 的总损耗差足以让受过训练的耳朵(和高质量扬声器)识别更精确的模型。
放大器测试
接下来进行组合放大器的迁移学习测试。小布鲁斯驱动器被设置为最大与“脂肪”推进按钮接合。HT40 的驱动旋钮从最大值减少到大约 25%,以接*相同的嘎吱声水*。两个放大器都具有全电子管前置放大器和功率放大器电路,但 HT-40 也有一个带有电子管扬声器风格声音的过驱动限幅电路。两个样本都是使用位于扬声器锥体中部的 SM57 动圈麦克风录制的。一般来说,使用带麦克风的放大器进行训练比使用带直接输出功能的放大器更困难。扬声器和麦克风增加了信号的力度,听起来悦耳,但对于训练来说更复杂。
HT40 完整数据集(带声音样本)
第一个 amp 测试使用了全套数据,这次使用了 4 分钟的音频(3' 20 "用于训练,40 秒用于验证)。
图 3:来自 Blues Jr .的 HT40 与 HT40 的比较,完整数据集(图由作者提供)
HT40 放大器在整个训练过程中的损耗差异比 MT-2 失真踏板更加极端。从零开始的 HT40 在损失开始减少之前需要大约 60 个时期。然而,迁移学习增强模型的起点低得多,并在整个运行过程中不断取得小的改进。
注意:HT40 从零开始的训练在纪元 340 附*被中断,但是看起来它自己接*完成。
完整数据集 HT40 放大器测试的声音样本在此分享,以供比较。目标是听起来尽可能接*目标音频。这是目标音频,即从 SM57 麦克风录制的 25%增益的 HT40 放大器(过驱动通道):
这是从零开始训练的模型(无迁移学习,损失值 0.078):
这是以 Blues Jr. amp 为起点的模型(迁移学习增强,损失值为 0.036):
即使没有录音室显示器或昂贵的耳机,迁移学习模式也明显更接*目标。使用迁移学习的损失改善约为 0.04。
HT40 精简数据集
接下来,使用有限的数据集;40 秒用于培训,40 秒用于验证。
图 4:来自 Blues Jr 的 HT40 与 HT40 对比,有限训练数据集(40 秒)(作者图)
这项测试显示了使用迁移学习最显著的好处。从头开始训练 HT-40 的有限数据集未收敛,验证损失未低于 0.74。在达到耐心极限和训练自动停止之前,跑步持续了 68 个时期。然而,当从小布鲁斯模型开始时,损失立即开始减少,并在整个过程中继续改善。
下表 1 中比较了所有测试的损失和培训时间。当在 Colab 上训练时,减少的训练集的每个时期的时间大约减少了一半。由于达到了 Colab 限制,HT40 的完整数据集必须在本地 GPU 上进行训练,因此 HT40 的训练时间不应与缩减后的数据集进行比较。转移学习模型的最终损失值较小,在放大器测试与失真踏板的情况下,差异更明显。在 HT-40 放大器缩减数据集的情况下,需要使用转移学习来对模型进行训练。除了 HT40 缩减数据集之外,转移模型的最佳损失大约减半。
表 1:所有运行比较(作者图片)
结论和未来工作
这些初始测试表明,使用迁移学习可以减少训练时间,因为达到可接受的准确度需要更少的训练数据。当训练过驱的麦克风放大器等困难信号时,这也是有益的。在数据有限的情况下,可能需要迁移学习才能使模型收敛,就像 HT40 有限的数据集一样。使用转移学习来训练一个"容易的"信号,如直接输出轻度失真踏板似乎对最终模型的影响最小。需要进行更多测试,以确定这些结论是否适用于其他效应和放大器。
在上述测试中,确定什么构成了类似的发声装置是基于简单地听它,这是主观的。有可能使用人工智能(或其他 DSP 技术)来首先分析来自目标设备的音频,然后从预训练模型库中确定哪个最接*,以获得最佳结果。
所有测试都是在特定设置(增益水*、均衡器、音量)下对每个设备的“快照”进行的。可以使用每个设置的训练数据来调节给定参数或参数集的模型。例如,您可以训练增益或驱动旋钮全范围的单个模型。但是,使用模型调节会增加所需的数据量和训练时间。迁移学习可能是减少条件模型训练所需的训练时间和数据量的好方法。
我希望你喜欢阅读这篇文章!关于问题和反馈,你可以发电子邮件到 smartguitarml@gmail.com 给我。
基于张量流的图像分类迁移学习
原文:https://towardsdatascience.com/transfer-learning-for-image-classification-using-tensorflow-71c359b56673?source=collection_archive---------8-----------------------
案例研究:图像分类预测它是否是一种食物
尼克·萨莫伊洛夫在 Unsplash 上的照片
介绍
图像分类是一项任务,其中计算机将预测图像属于哪一类。在深度学习开始蓬勃发展之前,像图像分类这样的任务无法达到人类水*的性能。这是因为机器学习模型无法学习图像的邻居信息。该模型仅获得像素级信息。
得益于深度学习的力量,使用一种称为卷积神经网络(CNN)的模型,图像分类任务可以达到人类水*的性能。
CNN 是一种深度学习模型,从图像中学习表示。这种模型可以在没有人类参与的情况下从低级到高级特征进行学习。
该模型不仅学习像素级的信息。该模型还通过一种称为卷积的机制从图像中学习邻居信息。卷积通过将一个区域中的像素集合相乘并将它们相加为一个值来聚合邻域信息。这些特征将用于将图像分类成一类。
深度学习虽然可以达到人类水*的性能,但是需要大量的数据。如果我们没有他们呢?我们可以用一个叫做迁移学习的概念。
迁移学习是一种方法,在这种方法中,我们将使用针对我们的问题在大规模数据上训练过的模型。所以我们只通过微调模型来训练他们。我们将得到的好处是模型将在短时间内训练。
本文将向您介绍如何使用 TensorFlow 使用迁移学习进行图像分类。因为预处理步骤是必不可少的过程,所以我也将向您展示如何为我们的深度学习模型准备数据。没有进一步,让我们开始吧!
实施
导入库
我们需要做的第一步是导入库。我们需要 TensorFlow,NumPy,os,还有熊猫。如果您还没有安装软件包,您可以使用 pip 命令来安装这些库。
请注意,我将使用的 TensorFlow 是版本 2.4.1,所以请确保安装该版本。
还有,如果你想用 GPU 来训练深度学习模型,请安装 11.0 版本的 CUDA,因为那个版本支持 2.4.1 版本的 TensorFlow。你可以在这里下载 CUDA 软件T5。
下面是安装和加载库的代码。
准备数据
加载库之后,下一步是准备数据集。在这种情况下,我们将使用一个名为 Food-5K 的数据集。
该数据集由 5000 幅图像组成,分为食物和非食物两类。此外,数据已经分为训练、验证和测试数据集。我们数据集的文件夹结构看起来像这样,
**\---Food-5K
+---evaluation
| 0_0.jpg
| 1_0.jpg
|
+---training
| 0_0.jpg
| 1_1.jpg
|
\---validation
| 0_0.jpg
| 1_0.jpg**
正如您在上面看到的,每个文件夹都由图像组成,其中每个图像文件名都包含它的类和标识符。标识符由下划线分隔。
对于该文件夹结构,我们需要生成包含图像文件名和标签列的数据帧。准备数据集的代码如下所示,
这是数据帧的预览,
下一步是准备一个对象,将图像放入模型中。我们将首先使用 tf.keras.preprocessing.image 库中的 ImageDataGenerator 对象。
使用该对象,我们将生成图像批。此外,我们可以扩大我们的图像,以增加数据集的数量。因为我们也放大那些图像,所以我们也为图像放大方法设置参数。
此外,因为我们使用数据帧作为关于数据集的信息,所以我们将使用 flow_from_dataframe 方法来生成批处理并扩充图像。
下面是代码的样子,
训练模型
生成批次后,现在我们可以用迁移学习方法训练模型。因为我们使用那种方法,我们不需要从头实现 CNN 架构。相反,我们将使用现有的和已经过预训练的架构。
我们将使用 ResNet-50 作为我们新模型的主干。我们将创建输入,并根据类的数量用新的线性图层更改 ResNet-50 的最终线性图层。
下面是构建模型的代码,
现在我们来训练模型。我们将使用 fit 方法来训练它。下面是代码的样子,
测试模型
在我们训练模型之后,现在让我们在测试数据上测试模型。此外,我们需要添加 pillow 库来加载和调整图像的大小,并添加 scikit-learn 来计算模型性能。
我们将使用 scikit-learn 库中的 classification_report 来生成一个关于模型性能的报告。此外,我们将从中可视化混淆矩阵。下面是预测测试数据集及其结果的代码,
从上面可以看出,该模型的性能已经达到了 95%以上。因此,我们可以在构建图像分类器 API 的情况下使用该模型。
保存模型
如果您希望将模型用于以后的使用或部署,您可以使用 save 方法保存模型,如下所示,
如果要加载加载模型,可以像这样使用 load_model 函数,
结束语
干得好!现在你知道如何使用 TensorFlow 实现迁移学习了。希望这篇文章对你有所帮助,尤其是想用有限的数据训练一个深度学习模型的人。
如果你对这篇文章感兴趣,可以关注我的媒。另外,如果你想与我交谈,你可以在 LinkedIn 上与我联系。
谢谢你看我的文章!
迁移学习:你能学到的最有效的深度学习技能
原文:https://towardsdatascience.com/transfer-learning-in-deep-learning-641089950f5d?source=collection_archive---------23-----------------------
当你开始一个新的深度学习项目时,迁移学习将大大减少培训时间和成本
你可以使用狗分类器深度学习模型来训练和识别使用转移学习的猫——图片来自 Pixabay 的 huoadg5888
训练深度学习模型可能需要几天、几周甚至几个月的时间。
迁移学习可以解决这个问题。这是一种机器学习方法,训练好的模型被重新用作新任务的起点。这加快了培训速度,并提高了相关问题的绩效。
这是深度学习中最受欢迎的方法之一,因为它 通过重用与你自己的任务结构相似的其他任务中预先训练的模型 来节省时间和金钱。在这篇文章中,你将了解迁移学习是如何工作的,以及如何使用它来加速你的深度学习训练过程!
什么是迁移学习?
迁移学习是一种机器学习技术,其中在特定任务上训练的模型被重用为另一个不同任务的训练过程的一部分。
这里有一个简单的类比来帮助你理解迁移学习是如何工作的:想象一个人已经学会了关于狗的所有知识。相比之下,另一个人对猫了如指掌。如果两个人都被问到,“什么动物有四条腿,一条尾巴,会叫?”对狗了如指掌的人会回答“狗”,而对猫了如指掌的人会说“猫”
因为两个人都已经知道了解决手头问题所需的一半信息,所以每个人只需在正确回答之前填写他们缺少的信息。这就是迁移学习在机器学习中的工作方式。将一个模型了解到的某些特性的信息与另一个模型了解的其他特性的信息结合起来,可以产生一个新的任务。
如何利用迁移学习?
既然你知道迁移学习是如何工作的,你可能想知道如何让它为你自己的机器学习模型工作。有两种不同的方法可以做到这一点:特征提取和微调。
迁移学习中的特征提取和微调—图片作者作者
**特征提取:**如果你想将知识从一个机器学习模型转移到另一个模型,但不想在你的数据集上重新训练第二个更大的模型,那么特征提取是最好的方法。这是可能的,因为你可以从一个模型中学习特征,并训练另一个更小的模型。结合微调使用,此过程可以在短时间内为您提供出色的结果。
**微调:**如果你已经在训练自己的深度学习模型,或者想为你的数据集微调现有模型的输出,这种方法可能很适合你。通过使用较小的模型向较大的模型学习,您可以从较大的模型已经完成的任何工作中受益,而不必经历自己训练它的所有麻烦。因此,这种方法比单独的特征提取更快更有效。
将学习从预训练模型转移到新模型的步骤。
迁移学习程序包括这五个步骤。如果你使用 Keras 来建立你的深层网络,这里有一些步骤和方法。
从预先训练的模型中提取层。 这些层包含实现任务的一般设置信息。通常情况下,他们会接受大量数据集的预训练。在 Keras 中,您可以通过在加载预训练模型时指定include_top=False
来轻松消除它。
冻结图层。
这确保了来自先前模型的信息在将来的训练中不会被破坏。在 Keras 中,可以使用“可训练”选项在冻结和解除冻结模式之间切换层。
通过添加可训练层来扩展冻结模型。
这些新层将学习根据您的具体问题调整预训练模型。下面是向 Keras 模型添加新层的一种方法。
在数据集上训练新图层。
在预训练模型上使用新数据集时,指定一个小的学习率。小的比率确保模型不会严重偏离原始模型。慢慢的,新的模式会适应新的问题。
微调(可选):解冻整个模型,并在新数据集上重新训练它。 使用model.trainable=False
将整个模型设置为自由学习。现在按照前面的步骤用小的学习率进行训练。
正迁移和负迁移学习
迁移学习有两种类型:负迁移和正迁移。在一个任务上训练的模型所获得的所有知识都会应用到一个新的任务上,但并不是所有的知识都会有益地迁移,这种差异就是负迁移和正迁移的来源。
深度学习模型的正负迁移学习。—图片由作者提供
当在一项任务(例如,使用深度神经网络的数字分类)上训练的模型未能完成另一项任务(例如,图像分类任务)时,就会发生负迁移,因为从先前训练中获得的知识会渗透到新任务的执行中。这种类型的干扰表现在新任务中模型性能的退化。
当一些学到的知识有助于提高新任务的结果时,就会发生正迁移。它通过利用以前在相关任务中的学习经验来学习如何更快地执行它。这是有益的,因为你不必花太多时间在第二个新任务上。
流行深度学习模型中的迁移学习
用作迁移学习一部分的不同类型的模型如下:
**卷积神经网络:**当输入数据是一组图像时,使用这些模型。卷积神经网络的输入是表示像素的二维数组。模型每一层的输出可以被认为代表了图像的不同部分。这是因为这些类型的网络将输入映射到一组不同的输出,每一个都负责表示图像的特定部分。
示例:参见 VGG16 和 VGG19 。这里有一篇由杰森·布朗利撰写的详细博客文章
**递归神经网络:**当输入数据具有时间性质时,如文本或时间序列数据,使用这些模型。在这些情况下,通常来自先前点的信息会影响在未来时间点学习到的信息。这使得递归神经网络非常适合这种类型的数据,因为它们基于环路,允许网络具有记忆并从以前的信息中学习。
例如: Timenet,一个经过训练从时间序列数据中提取特征的 RNN
**生成对抗网络:**这些模型通过获取关于生成一组图像的知识并将其应用于另一组图像,来使用迁移学习。例如,GANs 可以被训练生成与以前看到的手写数字相似的新样本。然而,这只是这个模型如何用于迁移学习的一个例子。
例子: DCGAN-TensorFlow,深度卷积生成对抗网络
**自动编码器:**自动编码器是一种特殊类型的模型,用于压缩和解压缩信息。有两种类型的自动编码器:一种将原始数据编码成压缩表示(编码自动编码器),另一种试图从这种压缩表示中重建原始图像(重建自动编码器)。这些模型可以非常有效地找到输入数据的压缩表示,然后可以用作迁移学习的一部分。
例子:这里有一个由 Sreenivas Bhattiprolu 制作的 Youtube 视频。
总而言之,
迁移学习是一种加速深度学习训练的惊人方法。它有助于用已有的知识解决复杂的问题。迁移学习的核心是使用针对一个问题训练的深度学习模型作为解决另一个问题的起点。
本文涵盖了使用迁移学习的基础和好处。如果使用迁移学习,数据科学家可以在更短的时间内训练新模型,而不会消耗大量预算。此外,当针对新问题的训练样本较少时,迁移学习是一个救星。
在大多数情况下,您可以用简单的模型解决组织问题。如果你有兴趣了解它们,可以看看这些文章。
朋友,谢谢你的阅读。看来你和我有许多共同的兴趣。 跟我打招呼 上 领英推特中 。我会为你打破僵局。**
还不是中等会员?请使用此链接 成为会员 因为我为你免费推荐赚取佣金。
用手套词向量进行迁移学习
原文:https://towardsdatascience.com/transfer-learning-with-glove-word-vectors-7652456ae269?source=collection_archive---------18-----------------------
这是一个向量,好吗??塔曼娜·茹米在 Unsplash 拍摄的照片
过去,我在为我的一个项目训练单词向量,但是我一直碰壁。我在研究哲学史上的文本,试图找到可以揭示作者如何使用一个词的向量。但是我一直得到这样的结果:
我是说,我确实喜欢斯宾诺莎…
如果你非常努力地眯着眼睛,那么这可能是有意义的。毕竟,爱情的确与完美有关,而且很刺激……对吗?
但是相似性分数很小,我们不想为了让结果有意义而眯着眼睛看。他们应该给我们带来启发——我们不应该给他们带来启发。
为了解决这个问题,我尝试调整太阳下的超参数,但是尽管感觉像是一个字面上的工作时代,结果从来没有比这更好。
但后来我灵机一动。我不会单独在我的数据集上训练数据,而是使用 GloVe 预先训练的单词向量作为基线。这意味着我的机器基本上已经知道基本的英语,然后只需进行微调,以更准确地匹配我的数据。
这个过程比我想象的要困难一些,而且我也没有找到任何完整的指南,所以我想我应该为你写一份。这个过程基本上有三个步骤,我将按顺序逐一介绍。如果你想得到一个可以完成所有工作的功能,可以直接跳到最后或者看看这个笔记本。
本教程需要 Gensim Word2Vec 库。
步骤 1:加载手套向量
为了训练手套嵌入,你需要(大惊喜)加载嵌入到你的系统。你可以在这里下载它们。
一旦有了文件,就可以使用下面的代码来加载它。
这实际上需要。txt 文件,并将其以适当的格式加载到 Gensim Word2Vec 库中。在这一点上,你可以做通常的相似性搜索,以测试是否一切都正确加载。
爱情真的是一场梦,❤
如你所见,手套的嵌入比我们之前得到的更有意义。
第二步:建立一个玩具模型来更新
在这一步中,您实际上是在没有使用 GloVe 的情况下根据您的数据构建了一个 Word2Vec 模型。该模型使您能够捕获新单词并构建包含特定数据集的词汇,如果您处理的文本不仅仅是普通英语,这将非常有用。
很好,现在你有了一个蹩脚的模型可以作为基础。现在来了很酷的东西。
第三步:增加手套重量并重新训练
在这里,您将使用现有模型,添加手套词汇和起始重量,并在数据集上对其进行重新训练。
结果将是一组新的单词向量,使用 GloVe 的原始权重,但现在也调整为包含您自己的数据。下面是一个结果示例:
请注意,这是在理性主义哲学学派上训练出来的
你可能不太了解理性主义哲学,但是相信我,这非常有道理。他们的主要焦点之一是上帝,我们可以看到,几乎所有这些在讨论上帝之爱的背景下都是有意义的——上帝爱我们,因为他是好的,他的恩典是这种爱的表现,他给我们自由,因为他爱我们,等等。事实上,仅仅是“爱”的用法围绕着上帝的概念这一事实就表明,这种用法效果很好,而且相似性得分要高得多。
另一个更好的测试你的结果的方法是通过运行.most_similar
一个你知道在你的特定数据集中有不同含义的词来检查你的新向量和原始的手套向量。这是我得到的结果的一个例子:
哲学家和口语如何使用“哲学”
你可以看到,在哲学文集里,‘哲学’是与科学和形而上学联系在一起的,而在基手套文集里,却没有这样的联系。
这很有道理。玄学在口语中有着非常不同的含义(在口语中,它与占星术和超自然现象联系在一起),而在哲学中,它是一个主要的分支。所以当哲学家谈论哲学的时候,形而上学总是在讨论之中,但是正常人谈论哲学的时候,几乎不会把它和形而上学联系在一起。哲学家也认为自己是科学的,或者在与自然科学的对话中,公众通常看不到哲学和科学之间的紧密联系。
额外的一步:把所有的都集中在一起
嗯,太好了!此时,您现在有了一个漂亮的单词嵌入,它可以独立使用来生成对您的语料库的见解,或者可以用于深度学习或其他应用程序。
剩下的工作就是将所有这些整合到一个功能中:
如果你想看到实际的结果,你可以查看哲学数据项目的单词使用分析页面。对于包含此工作和其他 NLP 工作的回购,请在此处查看。
感谢您的宝贵时间,如果您遇到任何问题,请随时联系我们:)
使用 VGG16 和 Keras 进行迁移学习
原文:https://towardsdatascience.com/transfer-learning-with-vgg16-and-keras-50ea161580b4?source=collection_archive---------0-----------------------
如何使用最先进的训练神经网络来解决你的图像分类问题
本文的主要目标是用代码和例子演示如何使用一个已经训练好的 CNN(卷积神经网络)来解决你的具体问题。
卷积网络对于图像问题非常有用,但是,如果你使用一个大的架构,并且没有 GPU,那么卷积网络的计算成本会很高。为此,我们有两种解决方案:
绘图处理器
GPU 对训练神经网络更有效,但它们在普通计算机上并不常见。所以这就是**Google colab来拯救我们的地方。他们提供 GPU 高达 16 GB 内存的虚拟机,最棒的是:它是免费的。**
但是,即使有了这些升级的规格,你仍然可以在训练一个全新的 CNN 时挣扎。这就是迁移学习可以帮助你用更少的计算获得更好的结果的地方。
迁移学习
那么什么是迁移学习呢?
为了更好地解释这一点,我们必须首先了解 CNN 的基本架构。
作者图片
CNN 可以分为两个主要部分:特征学习和分类。
特征学习
在这一部分中,神经网络的主要目标是在图像的像素中找到可用于识别分类目标的模式。这发生在网络的卷积层,专门处理手头问题的那些模式。
我不会深入探究这背后的工作原理,但如果你想更深入地挖掘,我强烈推荐这篇文章 和这个令人惊叹的视频 。**
分类
现在,我们想使用这些模式将我们的图像分类到正确的标签。网络的这一部分正是做这项工作的,它使用来自前几层的输入,在新图像中找到与你的匹配模式最匹配的类别。
定义
因此,现在我们可以在我们的上下文中定义迁移学习,即利用经过训练的 CNN 的特征学习层来分类一个不同于它为之创建的问题。
换句话说,我们使用神经网络发现对给定问题的图像分类有用的模式来分类完全不同的问题,而无需重新训练网络的这一部分。
现在,我将演示如何使用 Keras 实现这一点,并证明在很多情况下,这比训练一个新的网络效果更好。
使用 Keras 进行迁移学习
在这个演示中,我将使用一个著名的神经网络 VGG16。这是它的架构:
作者图片
该网络在 ImageNet 数据集上进行训练,该数据集包含属于 1000 个不同标签的超过 1400 万个高分辨率图像。
如果你想更深入地研究这个特定的模型,你可以研究一下 这篇论文。
资料组
在这个演示中,我将使用 tf_flowers 数据集。只是提醒一下:VGG16 网络没有被训练来对不同种类的花进行分类。
数据看起来是这样的:
作者图片
最后…
代码
首先,我们必须从 TensorFlow 加载数据集:
现在我们可以加载 VGG16 模型了。
我们使用Include _ top =False移除在 ImageNet 数据集上训练的分类层,并将模型设置为不可训练。此外,我们使用 VGG16 中的 preprocess_input 函数来规范化输入数据。
我们可以运行这段代码来检查模型摘要。
*base_model.summary()*
作者图片
两个要点:该模型有超过 1400 万个训练参数,并以 maxpooling 层结束,该层属于网络的特征学习部分。
现在我们为我们的具体问题添加最后几层。
并编译和拟合模型。
在测试集上评估这个模型,我们得到了 96%的准确率!
就是这样!
就是这么简单。很漂亮,对吧?
我们如何在世界上找到一些模式,可以用来识别完全不同的事物。
如果你想查看完整的代码和一个 jupyter 笔记本,这里有 GitHubrepo:
***https://github.com/gabrielcassimiro17/object-detection ***
额外:与手工制作的模型相比
为了确保这种方法在计算资源和精度上都更好,我为这个问题创建了一个手工制作的简单模型。
这是代码:
我使用相同的最终层和拟合参数来比较卷积的影响。
手工模型的准确率为 83%。比我们从 VGG16 型号获得的 96%要差得多。
使用 XGBoost 和 PyTorch 进行迁移学习:破解 Alexnet for MNIST 数据集
原文:https://towardsdatascience.com/transfer-learning-with-xgboost-and-pytorch-hack-alexnet-for-mnist-dataset-51c823ed11cd?source=collection_archive---------12-----------------------
马修·施瓦茨在 Unsplash 上的照片
更新:发现我关于渐变提升的新书实用渐变提升。这是用 python 中的许多例子对渐变增强的深入探究。
https://www.amazon.com/dp/B0BJ82S916
在处理深度学习时,训练一个模型总是很复杂:不仅是一项耗时且成本高昂的任务,还需要非常大的数据集。微调模型架构也相当繁琐,使用超参数调整/ AutoML 仍然是一个开放的计算耗时的主题。
希望有另一种选择:迁移学习。这种技术允许在新用例中重用预先训练好的模型,避免昂贵的培训。
在本文中,我们将展示如何将 XGBoost 和 PyTorch 结合起来,将 Alexnet 获得的知识转移到一个新的应用程序中。
最初,Alexnet 在 1000 个类别的子集上接受了 ImageNet 大规模视觉识别挑战(ILSVRC)的培训。给定一幅图像,这个网络能够将其分类到 1000 个类别中的一个。这些课程的完整列表可以在这里找到。
原文值得一读,可以在这里找到。
使用 Alexnet
在转移 Alexenet 深度神经网络训练获得的知识之前,我们要提醒自己如何使用它。
让我们回忆一下,Alexenet 是一个深度卷积网络,有 5 个卷积层和 3 个用于功能部分的池层。该分类使用 3 个密集层。Alex Krizhevsky 带来的创新是为了证明网络的深度对表演至关重要。这是通过设计一种新的算法在 GPU 上运行训练来实现的。
我们将把这种预先训练好的架构应用到以下照片中,这些照片是在 Unsplash 上随机挑选的:
https://unsplash.com/photos/Sg3XwuEpybU
多亏了 pytorch ,这可以用几行 python 代码完成:
这几行代码加载图像并使用 Alexnet 对其进行分类。作者代码。
多亏了 Pytorch,我们只需一行代码就可以访问预先训练好的模型。多方便啊!
Alexnet 的输出是一个 1000 维的概率数组,即类的数量。该列表将前 5 名列为最佳标签。
正如你在这段代码的最后一行看到的,深度神经网络识别图像,并使用狗的名字正确地标记它。注意变换函数,用于缩放输入图像并将其转换为 PyTorch 张量。
转移 Alexnet 学习
迁移学习的思想是将在深度神经网络(或任何其他类型的模型)的训练期间获得的知识应用于试图解决给定问题的另一个问题。
在 Alexnet 的情况下,该网络已经学会对 ImageNet 大规模视觉识别挑战(ILSVRC)的图像进行分类。如上所述,网络输出是 1000 个类别中每一个的概率数组。
为了执行这种分类,Alexnet 使用与 3 个池层交织的 5 个卷积层来计算特征。该层堆栈的输出被送入 3 个密集层,以执行分类并生成最终的 1000 个概率。
我们在这里想要做的是访问特征部分的输出,并从它的知识中获益。
我们在本文中想要验证的假设是,为分类器训练的深度卷积神经网络足够通用,可以应用于另一个问题。
此外,出于兴趣和利益,我们将使用 XGBoost 替换密集神经网络分类器。
入侵 Alexnet 来识别数字
为了验证我们的假设, MNIST 数据集是一个非常好的候选者。这是 Yann Lecunn 广泛用于建立分类器以识别手写数字的数据库之一。再一次, PyTorch 简化了我们的工作,因为它提供了对 MNIST 数据集的便捷访问。
该数据集包含 60 000 个数字,它们的标签在训练集中,另外 10 000 个标记的数字用于测试集。每个数字存储为灰度 28x28 图像。因此,我们不能将它们直接输入 Alexnet。这将是必要的重新调整他们,并将其转换为 RGB。
在这一步,现在可以使用非常方便的 extract_features 方法将图像输入 Alexnet 并获取特征。
最后,由于我们计划使用 XGBoost 作为分类器,我们需要将输出存储为 CSV 文件,该文件可以作为 Pandas Dataframe 轻松加载。
所有这些转换都由下面的 python 清单处理:
这个脚本对图像进行预处理,并将它们传送到 Alexnet,这样我们就可以得到图像的特征。作者代码。
运行这个脚本会生成一个 csv 文件,其中每一行都包含给定数字的所有特征及其标签。我们所要做的就是用这些数据装配一个 xgb 分类器。预处理测试数据需要一个类似的脚本。
因为有大量的样本和特征,所以可以根据这些数据的子集进行训练,比如说 10 000 个样本。下面是如何做到这一点:
从预处理数据中编写脚本训练 XGBClassifier。作者代码。
最后几行远远没有给出该模型的完整评估,而是倾向于表明将来自深度神经网络和 XGB 分类器的预先学习的知识相结合是可行的。
注意,由于训练可能需要一些时间,我们使用 joblib 将模型存储为 pkl。因此,在进行评估时,我们可以轻松地重新加载它。
下面几行更准确地评估了这个模型:
评估模型性能。作者代码
如混淆矩阵和分类报告所示,分类确实不错。
我们也许可以做得更好,在 XGB 分类器上使用超参数调整,但它已经相当不错了。
结论
重用预先训练好的模型是构建新模型的一种非常有效的方式,而没有执行完整训练的负担:收集数据、调整模型、训练模型、评估模型等等。所有这些步骤都可以通过迁移学习来避免。
我们还展示了结合不同类型的模型,利用它们各自的优势是可能的。这里,例如 XGBoost 是一种非常好的基于深度神经网络输出执行分类的方法。PyTorch 非常适合操纵神经网络部分。
为了进一步说明这个例子,最好从卷积网络的第一层提取特征,看看学习如何从这些中间层转移。
使用 Python 将发票转换成表格数据
原文:https://towardsdatascience.com/transform-invoices-into-tabular-data-using-python-cd30b31d1a8f?source=collection_archive---------8-----------------------
PDF 水管工和正则表达式使它更容易
作者图片(Canva 上制作)
99%的文本数据以非结构化形式存在。当我们谈到难以解释和管理的非结构化数据时,发票是非结构化数据的一个例子。
当我们在分析和数据科学领域工作时,我们通常需要表格形式的数据来分析它们。我的意思是,通过分析,我们可以绘制洞察图、监控、预测未来的洞察、管理未来的需求,等等。
根据 quora 上的信息,一家大型企业一个月可以产生 33000 张发票,根据商业杂志的一份报告,有 16000 多家大公司,这意味着一天内会产生数百万张发票,这是非结构化数据要多得多。
发票的好处是——大多数都遵循相同的模式。也就是说,如果我们能够匹配单一发票的模式,我们就可以处理任何行业的所有发票。
时至今日,一些行业已经采用了自动化发票处理方法,其中大多数仍在手动处理,少数仍在进行相同的自动化流程,以节省时间和资金。
让我们看看如何使用 python 编程来自动化这个过程。我们的最终产品将是一个功能,将采取 pdf 文件的列表作为输入,并生成一个 excel 表,其中一行将表示一个结构化的发票文件。
必需的库
我们将需要一些库来读取 pdf 文件,并对我们的文本数据应用正则表达式。
- pdf lumber—读取 pdf 文件
- re-应用正则表达式
- 熊猫——来创建和操作我们的数据集
导入所需的库
import pdfplumber
import re
import itertools
import pandas as pd
示范发票
演示发票截图
这里,我们有三个部分。最上面的第一部分给出了日期和时间、用户名、程序名和菜单代码的详细信息。
第二个中间部分告诉我们该发票可用的菜单选项。最后,倒数第三个部分告诉我们每个菜单选项下的授权码。
方法
我们的第一个目标是制作一个能够区分每个部分的 python 脚本。
with **pdfplumber.open("Menu_Authorizations.pdf") as pdf**:
next_page_continue=False
for pcount in range(len(pdf.pages)):
page=pdf.pages[pcount]
text=page.extract_text()
上面的代码帮助我们打开 pdf 文件。这里,我们只有一个包含 300 个菜单的 pdf 文件。有些菜单需要两页纸,因为它们有更多的菜单选项。我们需要根据正则表达式的结果来处理这种情况。
我们可以使用 extract_text()函数从 pdf 中提取数据。因为我们使用了一个循环,所以一次只能接受一张发票。
当我们迭代提取的文本时,我们的循环逐行迭代文本。这意味着——我们必须根据循环正在执行的行来定义正则表达式。
让我们首先定义每个条件的正则表达式。
抓取菜单代码
菜单编号出现在以“Menu”开头的行中。这里,我们需要一个正则表达式来检测时间。
menu_re= re.compile(r'^MENU:')
作者截图
这一行 python 代码可以为我们完成这项任务。
抓取所有菜单选项
根据菜单格式——就在菜单代码下面,我们可以找到菜单选项列表。这里,我们需要确保我们的行对于菜单选项表有各自的标题。
menu_func_re=re.compile(r'^\s*\d+\s{2}[A-Za-z\s\d\W]+$')
如果我们的行以空格、数字开头,后面跟两个空格,上面的正则表达式可以帮助我们。这样,我们就可以检测到这条线。
作者截图
抓取每个菜单的授权码
这是我们需要提取的最后一部分。我们需要检查该行是否以数字开头,后跟代码“APM”。
APM_re=re.compile(r'\s*\d+\s+APM')
APM_re_internal=re.compile(r"^AUTHORIZED:")
以上两行可以为我们完成任务。
将这些点连接起来
一旦正则表达式部分完成,我们就可以用必要的条件连接所有的代码部分。
最终输出
通过运行代码,我们可以获得表示文档及其相关信息的列表列表。
最终结果—导出前
现在,我们可以使用 pandas 将列表转换为数据框,然后将该数据框导出到 excel 表中。
结论
这篇内容丰富的文章就到这里。我们已经介绍了将 PDF 发票转换成 excel 表格的一步一步的方法。这一次,我们还讨论了这个用例的重要性。
我希望你喜欢这篇文章。敬请关注即将到来的文章。
谢谢你的阅读!
以下是我的一些最佳选择:
</7-amazing-python-one-liners-you-must-know-413ae021470f> https://betterprogramming.pub/10-python-tricks-that-will-wow-you-de450921d96a </5-data-science-projects-that-you-can-complete-over-the-weekend-34445b14707d> [## 你可以在周末完成的 5 个数据科学项目
towardsdatascience.com](/5-data-science-projects-that-you-can-complete-over-the-weekend-34445b14707d)
在你走之前……
如果你喜欢这篇文章,并希望继续关注更多关于 Python &数据科学的精彩文章——请点击这里https://pranjalai.medium.com/membership考虑成为一名中级会员。
请考虑使用我的推荐链接注册。通过这种方式,会员费的一部分归我,这激励我写更多关于 Python 和数据科学的令人兴奋的东西。
还有,可以随时订阅我的免费简讯: Pranjal 的简讯 。
简单电影数据集到功能推荐系统的转换
原文:https://towardsdatascience.com/transformation-of-a-simple-movie-dataset-into-a-functional-recommender-system-89c2a5a668c?source=collection_archive---------39-----------------------
从创建模型到使用 Python 部署 web 应用程序的所有步骤
(左最新 ratings.csv 电影数据集的小版本由 MovieLens | ( 右 ) 推荐系统 web 应用 I 在本地实现和部署,电影海报图片来自 IMDb
为什么是推荐系统?
你们当中有谁没有花过几分钟甚至几个小时去选择一部电影,是独自看还是和家人一起看,可惜没有成功?承认在这种时候你希望有人替你做决定,这正是推荐系统的作用。这是巨头网飞和亚马逊目前成功的主要原因之一。我设计这篇文章是为了向您展示任何在数据科学和编程方面有一点创造力和经验的人都可以通过遵循我将要描述的几个步骤来实现他们自己的推荐系统。我在德国电信(DEUTSCHE TELEKOM AG)创新中心(IHUB) 数据科学部门实习的 8 个月期间,意识到了这个项目。这个想法也是着眼于实用方面,而不是理论和数学方面,你可以在互联网上到处找到科学文献。
系统概述和架构
电影推荐系统架构,架构由作者
本文中介绍的推荐系统是在 4 主要步骤中实现的:
- 步骤 1 : 计算每部电影的加权*均分数以便向最终用户建议该电影院的 100 部最受欢迎的电影的目录
- 步骤 2 : 使用机器学习算法建立对 5 部“受欢迎”电影的推荐:k-最*邻居(kNN) 用 Scikit-learn
- 步骤 3 : 设置推荐 5 部“鲜为人知”的电影由深度学习算法推荐:深度*神经矩阵分解**【DNMF】*使用 Tensorflow 和 Keras
- 步骤 4 : 部署最终系统使用 Flask、Python web 开发上的先例模型的预计算结果
但首先,让我们简单解释一下为什么我们特别使用了一个数据集,在这个数据集里用户对他们看过的电影进行了评分。
协同过滤方法
协同过滤方法,图像由艾玛·马尔迪上走向数据科学
这种方法可以根据一个用户过去的行为和其他用户做出的类似决定建立一个模型。事实上,它是基于在数据集中选择的电影和给予这些电影的数字评级。然后,该模型用于预测用户可能感兴趣的电影,通过这些电影的预测评级。
MovieLens 的 ratings.csv 数据集
MovieLens' ratings.csv 文件,来源此处
该数据集中突出显示的一行内容如下:4 号用户观看了 21 号电影,并给了它 3.0/5.0 的评分。
关于此数据集的所有信息都直接从以下链接的“README.html”页面的“摘要”部分中检索到:https://grouplens.org/datasets/movielens/latest/
我引用道:“这个数据集[1】(ml-latest-small)描述了来自电影推荐服务 MovieLens 的五星评级和自由文本标记活动。它包含 100836 个评级和跨越 9742 部电影的 3683 个标签应用。这些数据是由 610 个用户在 1996 年 3 月 29 日到 2018 年 9 月 24 日之间创建的。这个数据集是 2018 年 9 月 26 日生成的。
随机选择用户进行纳入。所有被选中的用户都对至少 20 部电影进行了评级。不包括人口统计信息。每个用户用一个 id 表示,不提供其他信息。”
还请注意,对于本文中介绍的推荐系统,只使用了电影的评级,而没有使用标签应用。
第一步:计算每部电影的加权*均得分
第一步的目标是为我们推荐系统的最终用户提供一个流行电影的目录,他们可以从中选择他们最喜欢的。
最受欢迎电影加权*均得分,排行榜由作者
代码本身是不言自明的,唯一值得注意的是使用了 PySpark 来执行这个计算。事实上,这个库允许使用 SQL 语言固有的" mean" 和" col "函数,从而促进了代码的组织和可读性。然而,同样的计算在 Pandas 库中也是完全可行的,Pandas 库在数据科学初学者中更受欢迎。
代码我国电影推荐系统实现的第一步
步骤 2:使用k-最*邻(kNN) 设置 5 部“流行”电影的推荐
第二步的目标是向最终用户推荐一系列可以被描述为**【流行】的电影。
首先,这有助于让用户放心,因为他会认出至少一部推荐的电影。的确,如果他不认可任何推荐的电影,他可能会拒绝我们系统的有用性。这个因素,心理的和人为的,不幸的是无法量化**。它还证明,如果不考虑文化因素,最好的数学和统计模型可能不适合某些用户。
其次,使用 kNN 算法推荐的电影都“受欢迎”的事实是在训练机器学习模型之前对数据进行预先过滤的直接结果。事实上,我们数据集中的评估频率遵循“长尾”分布**。这意味着大多数电影的评分很少,而一个“压倒性少数”的评分比其他电影的评分总和还要多得多(更多细节请见本文 精彩文章 作者 凯文廖 )。因此,这个过滤器只允许最受欢迎的电影被用来训练 kNN 算法,所以产生的推荐也只能是受欢迎的电影。**
这个算法也有相当容易理解的优点,也相当容易解释。对于非技术人员来说尤其如此,例如您公司的销售团队或您的朋友和家人,他们不一定在数据科学领域。正如 Kevin Liao 在他的文章中解释的那样:“当 KNN 对一部电影做出推论时,KNN 会计算目标电影与其数据库中所有其他电影之间的**‘距离’,然后对其距离进行排序,并返回前 K 部最*邻电影作为最相似的**电影推荐”。
图解 KNN 如何对新样本进行分类,凯文廖关于走向数据科学的图式
与《钢铁侠(2008)》最*的 10 部电影根据我的推荐系统中使用的 kNN 算法,由作者得出的结果
在这个例子中可以看到,与“钢铁侠(2008) ”最接*的邻居电影是“黑暗骑士(2008) ”,其余弦相似度(或简称为**“距离”)约为 0.33。从主观和个人的角度来看,这个结果似乎非常连贯,因为它们是两部超级英雄电影。我们还可以注意到“《阿凡达》(2009) ”和“《盗梦空间》(2010) ”的存在,这也是两部科幻电影。我感谢有必要注意到这个机器学习算法的魔力,因为,正如我提醒你的那样,只有在 1.0 到 5.0 范围内给出的评分被使用过**。事实上,这些电影的类型并没有被用来提供这些推荐。下面是与代码相关的片段,向您展示如何使用 Scikit-Learn 库实现该算法,并根据选择的电影标题获得推荐:****
我们的电影推荐系统实现中第二步的 kNN 算法片段
第三步:使用深度神经矩阵分解(DNMF)推荐 5 部“不太出名”的电影
这个第三步的目的和这个算法的选择是向终端用户推荐一系列倾向于**【不太为人所知】的电影。不要进入太多的细节,只要记住不需要事先过滤**,一部电影可以被用作训练数据而不管它的受欢迎程度。事实上,这种算法在数学上非常复杂,结合了数据科学中经常使用的两种模型。第一种模型是矩阵分解,例如交替最小二乘(ALS) 算法。另一个模型是一个深度神经网络的例子,比如多层感知器(MLP) 。那么就有必要写一整篇文章来正确地解释它,但是正如我先前已经宣布的,我们的目标不是要做一个统计学课程。所以我让你看这两个已经很好的解释了这些概念的资源:2018 年底 Kevin Liao 写的文章《 逐步原型化一个推荐系统第二部分:协同过滤 中的交替最小二乘(ALS)矩阵分解》和Eijaz Alli bhai【t3t 现在假设您至少对上述两个模型有基本的了解,那么在第三步中使用的深度神经矩阵分解算法(DNMF) 具有以下架构:
深度神经矩阵分解架构,架构由作者
该算法的原理是与经典矩阵分解相同的**。我的意思是,使用这个模型,我们试图预测某个用户对某部电影的评价。我指定评级**,因为该算法填充了当前存在于' ratings.csv '数据集中的空白值。让我解释一下:即使是一个超级影迷也可能没有看过或评价过我们所掌握的数据集中的 9742 部电影。他的想法是给那些他自己还没有评价的电影打分,以决定他是否喜欢这些电影。这正是我们算法的矩阵分解部分所做的。神经网络的加入使得进一步增加模型的预测性能成为可能,从而减少预测和实际评级之间的误差。这里有一个代码片段向您展示如何使用 Tensorflow 和 Keras 库实现这样一个模型。我们将使用它来预测与不存在的*(userId,movieId)* 对相关联的评级**。******
电影推荐系统实现中第三步的 DNMF 算法片段
我们现在可以遵循相同的逻辑来预测在我们的'ratings . CSV'数据集中还不存在的所有*(userId,movieId)* 【对的关联分数。让我们以用户 n 401 为例,由 DNMF 算法计算的他的电影评级的前 10 名如下:
根据我的推荐系统中使用的 DNMF 算法,用户 n 401 的前 10 个电影评级预测,由作者得出的结果
我们现在可以将使用该模型生成的 2 个表的结果保存在 2 个不同的 csv 文件中:为每部电影推荐的前 10 名用户和为每个用户推荐的前 10 部电影。
pdUserRecs.to_csv(os.path.join(trained_datapath, 'DNMF_MovieRecommendationsForAllUsers.csv'), index=False)pdMovieRecs.to_csv(os.path.join(trained_datapath, 'DNMF_UserRecommendationsForAllMovies.csv'), index=False)
步骤 4:使用 Flask 上先前模型的预计算结果部署最终系统
我们终于到了最后一步**,这一次需要一些关于网络开发的知识。适当地部署该系统作为真正的应用会很有用。在这个 web 应用程序中,我们将链接本文前面的步骤中完成的所有工作。事实上,用户将从 100 部最受欢迎电影的目录中选择 3 部电影开始,这是根据它们在步骤 1 中的加权*均分数计算的。这 3 部电影将作为我们 2 模型的输入数据**,以获得 10 部电影的最终推荐,其中 5 部来自 kNN 和 5 部来自 DNMF 。此外,为了给最终用户提供快速和流畅的体验,DNMF** 车型将给出的预测已经预计算。这具体是什么意思?这意味着对于选择的 3 部电影中的每一部,系统将根据预测得分在“DNMF _ 用户推荐所有电影. csv 表中搜索与最匹配的 5 个用户**:****
****电影 n 6726 的前 10 个用户匹配预测根据我的推荐系统中使用的 DNMF 算法,产生由作者创作的图像
然后,系统将使用与最匹配的用户的列表来重复与之前相同的过程。换句话说,会在另一个列表中添加每个用户最喜欢的 5 部电影,其中 5 会随机保留在最后,使用另一个保存的表**。这使得我们能够根据相似的用户简档向我们 web 应用程序的最终用户提供电影推荐。另一个非常重要的点是,这些推荐已经被快速地给出和准确地****,而不必等待几个小时等待模型被重新训练,因此主要的兴趣在于已经预先计算了DNMF 结果**。
在我们的电影推荐系统实现的最后一步中,make _ recommendations()函数的代码和
正如你所注意到的,当用户选择了他的 3 部电影并按下按钮获得他的推荐时,一个 POST 请求被发送到服务器。当这个请求被处理时,呈现的函数返回几个与 " 模板 " 相关联的变量。下面是如何在我们部署的 web 应用程序的“index.html”文件中使用它们:
在我们的电影推荐系统实现的最后一步中,index.html 文件的片段
因此,最终用户将能够受益于好看的电影推荐以及在功能性网络应用中的海报**。下面是最终结果的样子:**
部署系统最终推荐,图片由作者
而就是这样**!读完这篇文章后,你现在可以喝一杯好咖啡,然后试着实现你自己版本的这个系统。**
摘要
在这篇文章中,我们一起看到了如何使用 Python 编程语言将一个简单的数据集转化为一个真正的功能性电影推荐系统**,以及如何将它部署为一个 web 应用。我们还了解到,推荐系统通常基于不同的互连算法。这对于为每种类型的产品提供**建议非常有用,无论它是“受欢迎的”还是“不太知名的”。我尽最大努力用一种比理论更实际的方式来呈现这个话题,所以任何人都可以理解我在说什么,希望你会喜欢。源代码在我的GitHubMovie _ Recommender _ System-Pythonrepo中有。****
参考
[1] F .麦克斯韦·哈珀和约瑟夫·康斯坦。movie lens 数据集:历史和背景 (2015),美国计算机学会交互式智能系统汇刊(TiiS) 5,4:19:1–19:19。
请随时访问我的 GitHub,关注我的数据科学项目。您也可以直接在 LinkedIn 上联系我,如果您有任何问题,我很乐意帮助您!我还要感谢我的上司。Aykan Aydin,第 AI 章&数据科学,感谢他在这个项目实现过程中提供的宝贵提示和建议。
基于变压器的三维计算机视觉合成
原文:https://towardsdatascience.com/transformer-based-3d-computer-vision-synthesis-eaa9677d931f?source=collection_archive---------13-----------------------
用数据做很酷的事情
图 1:西蒙·李在 Unsplash 上的照片
介绍
3D 计算机视觉是一种迷人的现场教学模型,可以像我们一样理解世界。*年来,2D 计算机视觉在目标检测、分割、关键点估计等方面取得了巨大的进展。3D 计算机视觉涉及理解几何形状和深度,并在许多领域中有应用,包括机器人、自动驾驶、3D 跟踪、3D 场景重建和 AR/VR。
传统方法仍然非常受 3D 计算机视觉的欢迎,但深度学习已经取得了令人印象深刻的进展。在这篇博客中,我们将讨论表现 3D 物体和场景的不同方式。然后,我们将使用 Transformer 模型进行 3D 特征生成的实践代码。代码分享在 Github 这里。
3D 信息的表示
从摄像机捕获的图像本质上是 2D 的,并且在过去,多个摄像机被用于理解场景的几何形状。
然而,使用多个相机和激光雷达来生成 3D 信息是一项昂贵的任务,也是 3D 计算机视觉更广泛使用的一个障碍。因此,焦点已经转移到深度学习方法上,这些方法可以从单个单目相机中提取关于场景的 3D 信息。
让我们来看看 3D 信息的不同表现方式。常见的代表包括:
- 深度图
- 体素表示
- 点云
- 网格表示
深度图
深度图允许我们提取深度,并将其显示为一个额外的维度。返回的深度可以是绝对深度,也可以是相对深度。深度可以标准化为 0 到 255 的黑白色标,并如下图 2 所示进行可视化。这里,靠*相机的点用红橙色标度,远离相机的点用蓝色标度。
图 2:使用 DLT 模型的深度估计。从本博客中的代码生成。作者照片
有几个公共数据集包含图像和相应的深度信息。NYU 深度 v2 就是这样一个数据集。通常,这些数据集的深度信息是使用 Kinect 等传感器计算的。
使用 DLT 的深度估计
DLT 模型将视觉转换器扩展到密集预测任务。我是变形金刚模型的忠实粉丝,Vision Transformer 是第一个流行的用于视觉任务的变形金刚实现。然而,Vision Transformer 是一种仅支持编码器的型号,通常与分类头一起用于分类任务。
DLT 的论文用解码器/融合器扩展了视觉变换器,该解码器/融合器在不同的头部对视觉变换器的输出进行采样,并融合这些表示以获得与输入图像具有相同形状的输出表示。该模型在深度估计和语义分割任务上进行训练,并在这两个方面显示了最先进的结果。
DLT 模型的模型架构如下图 3 所示。左侧显示了整体 DLT 架构,包括视觉转换器编码器模块,然后重组+融合为解码器模块。中间的面板展开了重新组装块,右边的面板解释了融合块。
图 3:他们论文中的 DLT 模型。来源:链接
我已经使用 PyTorch hub 的 DLT 的实现来从单目图像生成深度估计。我写了一个 colab 笔记本,用于加载 DLT 模型,并使用样本图像对其进行推理。该代码也可以在 Github 这里获得。
运行 DLT 模型的管道如下:
图 4:来自 Colab 笔记本的 DLT 模型代码。作者照片
深度图很容易计算并且相当精确,但是深度本身并不能提供场景的完整 3D 表示,因为深度不能从被遮挡的对象中计算出来。例如,上面图 1 中蒲团珠后面的床被遮挡,因此我们没有对它的深度估计。
其他表示能够提供物体的完整 3D 模型。
图 5:点云(左)、体素(中)和网格(右)的 3D 表示。来源:链接
3D 对象的三种最常见的表示是体素、网格和点云。我真的很喜欢下面的图 5,它将一幅 2D 图像转换成了各种 3D 图像。
点云表示
点云表示涉及将 3D 空间表示为点的集合,每个点具有 3D 位置。
point_cloud = [(x1, y1, z1), (x2, y2, z2),..., (xn, yn, zn)]
物体的点云表示非常流行。它比深度估计更好地保留了输入形状。如果物体的 RGBD 信息是可用的,那么如果相机参数是已知的,它可以用于估计物体的点云。相机参数通常使用称为相机校准的过程来估计。
在我们关于 Colab 和 Github 的代码中,我们使用 Kornia 使用来自 DLT 的 RGBD 信息计算 3D 点云。
图 6:从深度图中提取三维点云的代码。作者照片
我们使用 depth_to_3d 函数将深度图转换为点云。对于尺寸为 416x416 的图像,点云是形状为 416x416x3 的 NumPy 数组。
然后,我们可以使用 Open3D 库将 3D 点云转换为 ply 格式文件,并可视化生成的点云。 colab 笔记本有运行这个可视化的代码,但是,colab 不能打开交互式可视化器。我能够在我的本地机器上运行 jupyter 笔记本的可视化。
图 7:来自 Open3D 的 3D 点云甲龙。从本博客中的代码生成。作者照片
从我们的深度图生成的椅子点云如下所示。请使用 open3d 库可视化椅子点云
图 8:来自 Open3D 的椅子的 3D 点云。从本博客中的代码生成。作者照片
体素表示
体素表示将对象表示为许多 3D 像素或立方体的组合。体素表示非常类似于真实世界的表示,在真实世界中,物体由微小的部分——原子/分子——组成。如果增加体素网格的分辨率,你会越来越接*真实世界的物体,如下图 6 所示。
图 9:椅子的体素表示。来源
基于体素的方法的主要缺点是在高分辨率体素上渲染和运行深度学习模型所需的计算。
网格表示
另一种常见的 3D 表示是网格表示。如图 6 所示,该网格表示将对象显示为连接在一起的面和顶点。
来自 DeepMind 的 Polygen model 使用变形器来生成代表 3D 对象的网格和面。它使用 2D 图像或体素作为条件输入,为 3D 对象生成一组可信的顶点。然后,它通过合理的方式连接顶点来生成面。
顶点和面模型都是自回归解码器,其中下一个顶点/面是基于在该点之前预测的所有其他东西来预测的。
图 10:解释的多边形模型。来源:宝丽金论文
回购协议的作者已经发布了预先训练的模型和相同的 Colab 代码是在这里。我测试了代码,为两个常见的对象生成网格——桌子和鸟舍。
图 11。多边形模型生成的表格网格样本。来源:本博客中的代码。作者照片
结论
这个博客展示了变形金刚模型是如何被用来生成我们世界的 3D 表现的。我们研究了如何使用变形金刚来生成室内场景的深度图。然后,我们将深度图转换为 3D 点云,并使用 Open3D 可视化这些点云。我们还查看了来自 Deep Mind 的多边形模型,以生成常见对象的网格。
我希望您尝试一下代码,并生成自己的常见场景的 3D 可视化。请在下面的评论中分享你的经历。
在深度学习分析,我们非常热衷于使用机器学习来解决现实世界的问题。我们已经帮助许多企业部署了创新的基于人工智能的解决方案。通过我们的网站这里联系我们,或者如果你看到合作的机会,给我发电子邮件到 priya@deeplearninganalytics.org。
参考
- Polygen 模型解释
- 用于密集预测的视觉转换器
- 关于立体几何的细节
- Kornia3D 点云估算库
Scribd 上基于变压器的实时推荐
原文:https://towardsdatascience.com/transformer-based-real-time-recommendation-at-scribd-5fa05f000c47?source=collection_archive---------12-----------------------
我们如何在 Scribd 使用 transformer 模型生成实时推荐的详细信息、我们面临的挑战及其解决方案。
顺序深度学习模型已经在推荐行业中证明了其优势,可以根据用户过去的操作顺序生成更相关和动态的推荐。在 Scribd 时,我们还使用顺序深度学习模型来生成个性化建议,从而显著提升了我们的业务指标。我们使用 transformer 模型架构来实现顺序深度学习模型,以生成实时建议。在这里,我将描述我们如何端到端地使用 transformer 模型。
本文介绍了变形金刚模型:注意力是你所需要的全部,然后应用于各种成功的项目中,如 BERT:深度双向变形金刚的前期培训。在自然语言处理领域,它被证明比 LSTM 的[和 GRU 的](https://arxiv.org/abs/1909.09586\)更好更快。基于转换器的模型架构也可以应用于推荐应用,但是推荐问题比 NLP 领域更复杂一些,因此需要根据业务需求进行调整。因此,在 Scribd,我们不是基于过去的单词序列来预测下一个单词,而是基于多种类型的文档和多种类型的交互的丰富用户交互历史来预测用户接下来想要阅读什么,其中序列中的位置&相对时间都是重要的因素。
我们缩小了范围,首次实施时最多只支持 300 万用户和 500 万个项目。但对于这种规模,我们还必须对特征收集和模型训练过程进行大量优化,以将训练时间减少到 12 小时以内。在这里,我包括我们执行的整体设计和优化。
如果你不熟悉基于 transformer 的架构,那么我推荐你阅读这篇文章:图示的 Transformer
模型架构
我们只使用了 transformer 架构的编码器,它使用自我关注来组合来自用户过去交互的信号。自我关注是一种非常有效的机制,可以捕捉用户兴趣的任何*期变化,同时还能保持长期的上下文。但我们的模型仍然存在受欢迎程度偏差,我们通过对训练数据进行分层来减少这种偏差。
经许可,图片由 Scribd 提供
输入嵌入和池层 : -
这一层对来自交互、用户和项目数据的各种特征进行整形,并将它们加在一起以创建最终的输入向量,该向量将被输入到 transformer 的编码器层。
- 分类特征被映射到相应的嵌入,并且它们作为训练过程被学习。
- 所有数字特征被连接并通过前馈网络,以将矢量大小调整为变压器层输入的预期矢量大小。
- 所有这些向量被加权并相加,以产生每次交互的最终向量,该向量将被馈入 transformer 的编码器层。
变压器的编码器层 :-
编码器层使用自关注结合所有交互序列,随后是前馈网络和标准化。我们发现,在超参数调整期间,2 个编码器和 1 个头就足够了。
潜在输出向量将在每个序列的 2 个编码器的末端生成,但是只有最后一个序列的潜在输出向量用于预测下一个项目。我们称这个最后的潜在输出向量为用户嵌入。
优化功能:-
Scribd 的用户可以以不同的方式进行互动,如阅读书籍,听有声读物或播客,书签,下载或评价书籍,导航,搜索等。在仔细分析业务影响后,我们决定仅对几个重要的参与度指标进行模型优化,如具有特定阅读阈值的阅读、书签、下载等。为了简化多任务学习问题,我们假设所有这些指标的权重相等。它把 MTL 问题归结为第一阶段的分类问题。在后期阶段,我们将微调多种交互类型的权重。
最初,我们使用三元组和 BPR 损失,它学习对给定用户的正面目标进行比负面目标更高的排序,但是交叉熵分类损失在实践中对我们的训练数据表现得更好。
使用用户和项目嵌入服务 : -
如上所述,来自编码器的最后一个潜在输出向量被称为用户嵌入。然后这些用户嵌入通过前馈网络来计算所有项目的预测分数。因此,这些最后的预测前向网络的权重被称为项目嵌入。因此,用户嵌入和项目嵌入之间的点积将给出实际的推荐分数。因此,可以使用任何支持最*邻搜索的数据库来提供实时推荐。我们决定使用弹性搜索,这样在进行最*邻搜索之前,我们可以根据地理、语言和其他数百种业务限制进行预过滤。
每当用户的交互发生变化时,我们可以使用推理阶段(每小时 X 次)计算用户嵌入,并且只为该用户计算变化指数。因此,它还可能支持*乎实时的更新。
注意,前馈网络也具有偏差项,因此需要通过添加最后填充维度来调整用户嵌入的维度。
训练数据和特点
经许可,图片由 Scribd 提供
用户的交互阅读序列被分成子序列,以创建更多的训练数据,如下图所示。这对于捕捉用户早期的消费模式非常有用,有助于对交互历史较少的用户进行预测。
特征 :-对于用户交互序列中的每个交互,我们基本上有 3 种类型的特征:交互特征、用户特征和物品特征。
交互特征有阅读时间、下载与否、书签与否等。用户特征是用户的人口统计信息,项目特征是类别/分类、项目 id、语言等。
挑战和解决方案:—
这些是我们在实施过程中面临的一些挑战,并找到了解决方案。如果您有与我们相似的用例,这可能会对您有所帮助。
可变序列长度的相互作用 :-
尽管 transformer 模型足够灵活,可以采用可变的序列长度,但许多从业者通常使用固定长度的交互序列,因此可以批量运行不同序列的不同交互,以加快训练速度。分批运行非常有效,但是需要填充较小的序列。因此,如果我们保持最大序列太高,我们将有太多的序列与很多 paddings,这在训练期间浪费资源。
所以我们在 spark 中开发了自定义特征管道,将长度相*的序列批量分组,并以预批量格式保存在 TFRecords 文件中。这大大减少了较小序列的填充。此外,我们确保了序列批次将不会按序列长度排序,从而允许从不同长度的序列批次中快速学习。
使用类似于位置嵌入的相对时间:-
所有基于变压器的模型都使用位置嵌入来捕获序列相关信号,但在我们的情况下,相对时间比位置本身更重要。例如,用户可能在 2 个月左右后访问网站,那么最后一次交互可能不是那么新鲜。
当超参数调整时,我们发现相对时间的基于正弦的编码比使用以天为单位的绝对相对时间作为特征执行得更好。
处理电力用户超负荷:-
由于训练数据具有来自高级用户的大量样本,因此模型仅关注高级用户细分的过度优化。但与此同时,超级用户更有可能与不太受欢迎的项目进行交互,因此截断用户历史可能会损害低尾项目的性能。最初,我们试图为超级用户减轻体重,但这也损害了低尾物品的性能。因此,后来我们发现了一种*衡的折衷方案,首先用几个时期的原始训练数据来训练模型,然后用另外几个时期的截断训练数据来训练模型,以便在所有用户群之间进行微调。
多 GPU &优化函数:——
多 GPU 大大加快了训练时间,所以我们使用 8 个 GPU 的 AWS 机器进行训练和预测。使用多 GPU 是直截了当的,除了模型训练的优化步骤。这个特别的 tensorflow 文档在这里帮助了。我们目前使用TF . keras . losses . sparsecategoricalcrossentropyloss,因为我们的文档不到 500 万个。
排名管道
在推荐行业,排名管道通常由候选生成和排名管道组成。尽管我们有多达 500 万个文档,但我们使用弹性搜索,在没有候选生成步骤的情况下,成功地直接进行了实时排名。更多细节在这篇博客中有所描述。
经许可,图片由 Scribd 提供
- 模特每周都要重新训练。
- 用户和项目嵌入每小时生成 X 次。
- 在预过滤和排序步骤之后,生成前 N 个 rec。
结果
使用 Scribd 的内部 A/B 测试*台,我们进行了一项实验,将现有的推荐服务与新的个性化模型进行比较,以生成订户的主页。测试进行了大约一个月,超过 100 万 Scribd 用户(试用者或订户)被指定为参与者。在对结果进行仔细分析后,我们发现,与所有用户群的控制体验相比,个性化变体在统计上有以下显著改善(p<0.01):
- 点击推荐项目的用户数量增加
- 每个用户*均点击次数的增加
- 阅读时间至少为 10 分钟的用户数量增加(在三天的时间内)
这些增长代表了对关键性能指标的重大业务影响。
后续步骤
正如预期的那样,个性化模型在具有丰富历史的用户上表现得更好,但仍需要对早期用户进行改进。因此,我们正在努力使用强化学习来改善早期用户的用户体验。另一方面,我们正致力于通过为项目添加丰富的分类功能来提高长尾项目的推荐质量。
感谢您的阅读!我们希望这篇文章对你有所帮助。
参考资料:-
以下是我为本文参考的一些论文:
- 注意力是你所需要的一切
- 伯特:深度双向变压器预训练
- 自我关注顺序推荐
- BERT4Rec:来自变压器的双向编码器表示的顺序推荐
- 环境感知顺序推荐
- 带有亚马逊产品嵌入的大规模协同过滤
- 阿里巴巴电子商务推荐行为序列转换器
变压器网络:为什么缩放点积会导致更稳定的梯度的数学解释
原文:https://towardsdatascience.com/transformer-networks-a-mathematical-explanation-why-scaling-the-dot-products-leads-to-more-stable-414f87391500?source=collection_archive---------9-----------------------
一个小细节如何能产生巨大的影响
在变压器网络中使用的自注意机制的主要目的是生成考虑了周围单词的上下文的单词嵌入。自我注意机制通过将句子中的每个单词与句子中的每个其他单词进行比较,并随后将上下文相关的单词组合在一起来完成这项任务。
计算第一个单词的自我关注分数(图片由作者提供)
自我注意机制首先为句子中的每个单词计算三个向量(查询、键和值)。为了找到所选单词的上下文相关单词,我们将查询向量与句子中其他单词的关键向量进行点积,见上图。点积产生负无穷大和正无穷大之间的任何值,因此应用 softmax 将这些值映射到[0,1],并确保它们在整个序列中的总和为 1。如此获得的自我注意分数对于与所选单词无关的单词来说是很小的。
上图未示:自我关注分数随后用于构建所谓的价值向量的 凸组合 。关于变压器网络如何工作的更多细节,见这篇 帖子 。
但为什么点积在馈入 softmax 函数之前要用√64 进行缩放?在大多数关于变形金刚的教程中,我们听到一些关于点积在数量级上变大的事情,从而将 softmax 函数推到梯度极小的区域。
在这篇文章中,我们想从数学上理解为什么这句话成立。为此,我们将首先探讨 softmax 函数对于大幅度输入的行为。然后,我们将分析大幅度对 softmax 函数导数的影响。
Softmax 函数
在变压器网络中,softmax 函数的主要目的是获取一系列任意实数(正数和负数),并将它们转换为正数,其总和为 1:
(图片由作者提供)
上面公式中的指数函数确保获得的值是非负的。由于分母中的归一化项,获得的值总和为 1。
但是,softmax 函数不是比例不变的,如以下动画所示:
(图片由作者提供)
我们对输入的比例越大,最大的输入就越能控制输出。随着比例的增加,softmax 函数会将接* 1 的值分配给最大输入值,将 0 分配给所有其他值。这是由指数函数的性质造成的,指数函数增长越快,其输入越大。另一方面,如果我们降低输入的比例,softmax 输出会变得非常相似。
雅可比矩阵
在我们继续之前,我们必须澄清一件事:softmax 在形式上是一个所谓的向量函数,它以一个向量作为输入,并产生一个向量作为输出:
所以,我们在讲 softmax 函数的导数时,实际上讲的是它的雅可比矩阵(而不是梯度),它是所有一阶偏导数的矩阵:
在哪里
在之前的帖子中,我们已经推导出了雅可比矩阵元素的封闭表达式:
看,在上面的公式中,𝑠的偏导数是如何用𝑠本身来表示的。为了看到雅可比矩阵的完整结构,让我们把𝑛 = 4 写在纸上:
我们看到对角线元素不同于非对角线元素。此外,我们看到 softmax 的雅可比矩阵是对称的。
接下来让我们寻找一种情况,其中雅可比矩阵的所有元素都变为零。很容易看出,当任何一个𝑠取值为 0 或 1 时,对角线元素变为零。当非对角线元素的一个或两个因子为零时,非对角线元素变为零。因此,雅可比矩阵在以下四种情况下成为零矩阵:
我们在上一节中已经看到,对于较大的输入,softmax 函数产生的输出与上述输出非常相似。
通过 Softmax 层反向传播
这个难题的最后一部分是展示,为什么 softmax 的大输入值会导致梯度在反向传播过程中消失。
假设使用反向传播,我们已经计算了 softmax 函数输出端的梯度,如下图所示:
(图片由作者提供)
接下来,我们希望通过 softmax 函数反向传播,并获得输入端的梯度。请记住,softmax 函数的每个输出都依赖于它的所有输入。使用我们为𝑗-th 输入获得的链式法则:
右手边的行向量可以被识别为雅可比矩阵的𝑗-th 列。因此,通过 softmax 层反向传播相当于乘以其雅可比矩阵:
我们已经看到,当输入大幅增加时,softmax 函数的雅可比矩阵收敛为零矩阵。在这种情况下,梯度流(误差传播)因此被 softmax 层扼杀,并且在 softmax 层之前的所有元素减慢学习或者甚至完全停止学习。
在变压器网络中,softmax 函数的输入由关键向量和查询向量之间的点积组成。关键向量和查询向量的维度𝑑越大,点积就越大。在原始论文中,关键向量的维数是 64。作者在原始论文中应用的补救措施是用查询和键的维度的*方根来划分点积。这样,不管键和查询向量的维数是多少,学习都会进行得很好。
参考
注意你所需要的一切
从零开始绘制变压器网络
从零开始绘制变压器
soft max 的雅可比矩阵
变形金刚、时间形成者和注意力
原文:https://towardsdatascience.com/transformers-an-exciting-revolution-from-text-to-videos-dc70a15e617b?source=collection_archive---------6-----------------------
从文本到视频的激动人心的革命
转换器是一种非常强大的深度学习模型,已经能够成为许多自然语言处理任务的标准,并有望彻底改变计算机视觉领域。
这一切都始于 2017 年,当时谷歌大脑发表了一篇注定改变一切的论文,注意力是你所需要的一切[4]。研究人员将这种新的架构应用于几个自然语言处理问题,很快就可以看出这在多大程度上能够克服困扰 rnn 的一些限制,rnn 传统上用于诸如从一种语言翻译到另一种语言的任务。
这些年来,变形金刚已经成为自然语言处理领域的一个机构,谷歌大脑在 2020 年问道,它们在图像上也会一样有效吗?答案是肯定的,视觉变形金刚诞生了,通过对图像的一些初步修改,他们设法利用了变形金刚的经典架构,并很快在该领域的许多问题上达到了最先进的水*。
兴奋是巨大的,几个月后,在 2021 年初,脸书的研究人员发布了新版本的变形金刚,然而,这一次,专门针对视频,时间形成者。显然,即使在这种情况下,通过一些微小的结构变化,这种架构很快就成为视频的赢家,脸书在 2021 年 2 月宣布,它将把它与社交视频结合使用,以创建用于各种目的的新模型。
为什么我们需要变形金刚?
B 但是让我们后退一步,探索驱使谷歌研究人员寻找一种新的替代架构来解决自然语言处理任务的动机。
传统上,诸如翻译之类的任务是使用递归神经网络来执行的,已知递归神经网络存在许多问题。主要问题之一是它的顺序操作。例如,要将一个句子从英语翻译成意大利语,使用这种类型的网络,要翻译的句子的第一个单词与初始状态一起被传递到编码器,然后下一个状态与句子的第二个单词一起被传递到第二个编码器,依此类推,直到最后一个单词。来自最后一个编码器的结果状态然后被传递到解码器,该解码器返回第一个翻译的单词和随后的状态作为输出,该状态被传递到另一个解码器,依此类推。
这里的问题相当明显,要完成下一步,我必须有上一步的结果。这是一个很大的缺陷,因为您没有利用现代 GPU 的并行化能力,因此在性能方面会有所损失。还有梯度爆炸、无法检测同一个句子中距离较远的词之间的依存关系等等其他问题。
你需要的只是关注?
于是问题出现了,有没有一种机制可以让我们以并行的方式计算,让我们从句子中提取我们需要的信息?答案是肯定的,这个机制就是注意力。
如果我们要定义注意力暂时忘记任何技术和实现方面,我们将如何去做?
让我们以一个例句为例,问我们自己,把注意力集中在单词“gave”上,我应该把注意力放在句子中的哪些其他单词上来增加这个单词的含义?我可能会问自己一系列问题,比如,谁给的?在这种情况下,我会把注意力集中在“我”这个词上,然后我可能会问是谁给的?把我的注意力放在查理这个词上,最后,我可能会问,是什么给出了?最后关注食物这个词。
通过问自己这些问题,也许对句子中的每个单词都这样做,我也许能够理解句子的意思和层面。此时的问题是,我如何在实践中实现这个概念?
为了理解注意力的计算,我们可以将注意力与数据库世界相比较。当我们在数据库中进行搜索时,我们提交一个查询(Q ),并在可用数据中搜索满足该查询的一个或多个关键字。输出是与查询最相关的键的相关值。
注意力计算的情况极其相似。
我们首先将计算注意力的句子视为一组向量。通过单词嵌入机制,每个单词被编码成一个向量。我们认为这些向量是搜索的关键,对于我们正在搜索的查询,它可能是来自同一个句子(自我关注)或来自另一个句子的单词。此时,我们需要计算查询和每个可用键之间的相似性,通过缩放的点积进行数学计算。该过程将返回一系列真实值,这些值可能彼此非常不同,但是由于我们希望获得 0 到 1 之间的权重,并且其总和等于 1,因此我们对结果应用 SoftMax。一旦获得了权重,我们必须将每个单词的权重,以及它与查询的相关性,乘以代表它的向量。我们最终返回这些产品的组合作为注意力向量。
为了建立这种机制,我们使用线性层,从输入向量开始,通过矩阵乘法生成关键字、查询和值。关键字和查询的组合将允许在这两个集合之间获得最正确的匹配,然后将它们的结果与值组合,以便获得最相关的组合。
但是如果我们想把注意力集中在一个单词上,这个机制就足够了,但是如果我们想从几个角度看这个句子,然后并行地计算几次注意力呢?我们使用所谓的多头注意力,具有类似的结构,其结果在最后被简单地组合以返回所有计算的注意力的单个汇总向量。
既然我们已经了解了使用哪种机制并确定了其并行性,那么让我们分析一下嵌入多头注意力的结构以及构成转换器的结构。
考虑到总是翻译任务,让我们首先关注图像的左边部分,即编码部分,它把要从英语翻译成意大利语的整个句子作为输入。在这里,我们已经看到,与 RNN 方法相比,这是一个巨大的革命,因为它不是逐字处理句子,而是完全提交。在进行注意力计算之前,表示单词的向量与基于正弦和余弦的位置编码机制相结合,该位置编码机制在向量中嵌入关于单词在句子中的位置的信息。这一点非常重要,因为我们知道,在任何语言中,单词在句子中的位置都不仅仅是相关的,如果我们想要做出正确的评估,这是我们绝对不能丢失的信息。所有这些信息传递到多头注意力机制,其结果被标准化并传递到前馈。编码可以进行 N 次,以获得更有意义的信息。
但是要翻译的句子并不是转换器的唯一输入,我们还有第二个模块,解码器,它接收转换器先前执行的输出。例如,如果我们假设我们已经翻译了前两个单词,我们想预测意大利语句子的第三个单词,我们将把前两个翻译的单词传入解码器。将对这些字进行位置编码和多头关注,并将结果与编码器结果相结合。对该组合重新计算注意力,并且借助于线性层和 softmax,结果将是成为新翻译单词的潜在候选单词的向量,具有与它们中的每一个相关联的概率。在下一次迭代中,除了前面的单词之外,解码器还将接收这个单词。
因此,这种结构被证明是非常有效的,这是因为它完整地处理句子,而不是一个单词一个单词地处理,保留了关于单词在句子中的位置的信息,并利用了注意力,这是一种能够有效表达句子内容的机制。
经过这么好的解释,你可能会认为变形金刚是完美的,没有任何缺陷。显然,事实并非如此,它的优势之一也是它的弱点,注意力的计算!
为了计算每个单词相对于所有其他单词的注意力,我必须执行 N 次计算,即使是部分并行的,也仍然非常昂贵。有了这样的复杂性,让我们想象一下,在一个数百个单词的段落上多次计算关注度意味着什么。
从图形上看,你可以想象一个矩阵,其中必须填充每个单词相对于其他任何单词的注意力值,这显然有相关的成本。重要的是要指出,可选地并且通常在解码器上,可以计算掩蔽注意力,其中避免计算查询词和所有后续词之间的注意力
有些人可能会说,但是如果变形金刚带来的许多好处都与注意力机制有关,我们真的需要上面看到的所有结构吗?但 2017 年的第一篇谷歌大脑论文不是说“注意力是你所需要的一切”吗?[4]这当然是合理的,但在 2021 年 3 月,谷歌的研究人员再次发表了一篇题为“注意力不是你所需要的全部”的论文[6]。那是什么意思?研究人员进行了实验,分析了在没有变压器任何其他组件的情况下进行的自我关注机制的行为,并发现它以双指数速率收敛到秩 1 矩阵。这意味着这种机制本身实际上是无用的。那么为什么变形金刚这么厉害呢?这是由于倾向于降低矩阵等级的自我关注机制与变形金刚的另外两个组成部分——跳过连接和 MLP——之间的拉锯战。
第一种方法允许路径分布多样化,避免获得所有相同的路径,这大大降低了矩阵降阶为 1 的可能性。相反,由于其非线性,MLP 设法增加所得矩阵的秩。相反,已经证明正常化在避免自我注意机制的这种行为中不起作用。因此,注意力并不是你所需要的全部,但是 transformer 架构成功地利用了注意力来达到令人印象深刻的效果。
视觉变形金刚
A 生活在 2020 年的这个时候,谷歌的研究人员再次想知道,“但是如果变形金刚被发现在自然语言处理领域如此有效,它们将如何处理图像?”。有点像 NLP,我们从注意力的概念开始,但这次应用于图像。我们试着通过一个例子来理解一下。
图片来自“一张图片相当于 16x16 个单词”(Dosovitskiy 等人)
如果我们考虑一幅站在墙前的狗的图片,我们中的任何人都会说这是一幅“狗的图片”而不是一幅“墙的图片”,这是因为我们将注意力集中在图像的主导和辨别主体上,这正是应用于图像的注意力机制所做的。
既然我们知道注意力的概念也可以扩展到图像,我们只需要找到一种方法将图像输入到一个经典的转换器中。
我们知道转换器将单词作为输入向量,那么我们如何将图像转换成向量呢?当然,第一个解决方案是使用图像的所有像素,并将它们“内联”以获得一个矢量。但是让我们停一会儿,看看如果我们选择这个选项会发生什么。
我们之前说过,注意力的计算复杂度等于 O(N)。这意味着,如果我们必须计算每个像素相对于所有其他像素的复杂度,在像 256x256 像素这样的低分辨率图像中,我们将需要进行大量的计算,并且使用当今的资源绝对无法完成。所以这种方法肯定是不可行的。
解决方案非常简单,在论文“一幅图像相当于 16x16 个字”[2]中,提出将图像分成小块,然后使用线性投影将每个小块转换成矢量,该线性投影将小块映射到矢量空间中。
现在我们只需要去看看视觉转换器的架构。
然后,图像被分成小块,这些小块通过线性投影获得向量,向量与关于小块在图像中的位置的信息耦合,并被提交给经典变换器。添加关于图像内补片的原始位置的信息是基本的,因为在线性投影期间,该信息将会丢失,即使这对于完全理解图像的内容是非常重要的。插入另一个向量,该向量独立于被分析的图像,并且用于获得关于整个图像的全局信息,并且实际上,对应于该小块的输出是唯一被考虑并被传递到将返回预测类的 MLP 中的输出。
但是,在这个过程中有一个点会丢失大量信息。事实上,在从面片到矢量的转换过程中,任何有关面片中像素位置的信息都会丢失。这肯定是一件严肃的事情,Transformer in Transformer(TnT)[3]的作者指出,因为要分析的一部分图像中的像素排列是我们不希望为了进行质量预测而丢失的某些信息。
TnT 的作者然后问他们自己,有没有可能找到一种更好的方法让向量提交给转换器?然后,他们的建议是获取图像的每个单独的小块(pxp ),这些小块本身是 3 个 RGB 通道上的图像,并将其转换为 c 通道张量。然后这个张量被分成 p '个部分,p' < p,在这个例子中 p'=4。这产生了 c 维中的 p '矢量。这些向量现在包含了关于片内像素排列的信息。
然后,将它们连接起来并进行线性投影,以便使它们与从原始面片的线性投影中获得的矢量大小相同,并与该矢量组合。
通过这样做,变换器的输入向量也将受到片内像素排列的影响,并且通过这样做,作者已经设法进一步提高了各种计算机视觉任务的性能。
时间形成者
鉴于变形金刚首先在自然语言处理领域取得了巨大成功,然后在图像领域取得了巨大成功,2021 年,脸书的研究人员试图将这种架构应用到视频领域。
直觉上,很明显这是可能的,因为我们都知道视频只不过是一个接一个的一组帧,而帧只不过是图像。
只有一个小细节使它们不同于视觉变形金刚,你不仅要考虑空间,还要考虑时间。事实上,在这种情况下,当我们计算注意力时,我们不能将帧视为孤立的图像,而是应该找到某种形式的注意力,将连续帧之间发生的变化考虑在内,因为它是视频评估的核心。
为了试图解决这个问题,作者提出了几种新的注意力机制,从专门关注空间(主要用作参考点)的机制,到在空间和时间之间轴向、分散或联合计算注意力的机制。
图片来自“一张图片相当于 16x16 个单词”(Dosovitskiy 等人)
然而,取得最佳效果的方法是时空分离注意力。在给定时刻 t 的帧和作为查询的它的一个片的情况下,它包括计算整个帧上的空间注意力,然后计算查询的相同片但在前一帧和下一帧中的时间注意力。
但是为什么这种方法如此有效呢?原因是它比其他方法学习更多的独立特征,因此能够更好地理解不同类别的视频。我们可以在下面的可视化中看到这一点,其中每个视频由空间中的一个点表示,其颜色代表其所属的类别。
图片来自“一张图片相当于 16x16 个单词”(Dosovitskiy 等人)
作者还质疑了视频分辨率和其中帧数的相关性,并发现分辨率越高,模型的准确性就越高,在一定程度上。至于帧数,同样随着帧数的增加,精度也增加。有趣的是,不可能用比图中所示更高的帧数进行测试,因此精度仍有可能提高,我们还没有找到这种提高的上限。
众所周知,在视觉变形器中,较大的训练数据集通常会产生更好的准确性。作者在 TimeSformers 上也检查了这一点,同样,随着考虑的训练视频数量的增加,准确性也增加了。
结论
现在还剩下什么要做?变形金刚刚刚进入计算机视觉的世界,似乎决心要取代传统的卷积网络,或者至少在这一领域为自己开拓出一个重要的角色。因此,科学界正处于混乱之中,试图进一步改进变压器,将它们与各种技术结合起来,并应用于实际问题,最终能够做一些直到最*才成为可能的事情。像脸书和谷歌这样的大巨头正在积极开发和应用变形金刚,我们可能只是触及了表面。
关键词:变形金刚,视觉变形金刚,时间变形金刚,注意力
你喜欢这篇文章吗? 加入我的领英 !
如果你对变形金刚感兴趣,请阅读我关于恐龙的文章!
参考文献和见解
[1]“格达斯·伯塔修斯、王恒、洛伦佐·托雷萨尼”。"视频理解只需要时空注意力吗?”。
[2]“阿列克谢·多索维茨基等人”。一幅图像相当于 16x16 个字:用于图像识别的变形金刚。
[3]《韩凯等人》。变压器中的变压器。
[4]“阿希什·瓦斯瓦尼等人”。注意力是你所需要的一切。
[5]《启哲谢等》。"与吵闹的学生一起进行自我训练提高了 ImageNet 分类"。
[6]"董一禾等人","注意力不是你所需要的全部:纯粹的注意力随着深度成倍地失去排名"
[7]“Nicola Messina 等”,用于图文匹配检索的变压器推理网络
[8]“Nicola Messina 等人”,“使用转换器编码器进行跨模态检索的细粒度可视文本对齐”
[9]“大卫·科科米尼”,“训练码为的视频分类时间转换器”
[10]《大卫·柯考米尼》。视觉变压器还是卷积神经网络?都是!”
[11]《大卫·柯考米尼》。"注意力是你在《变形金刚》中真正需要的吗?
[12]《大卫·柯考米尼》。在迪诺上,无标签自蒸馏
变形金刚,你能评价阅读段落的复杂程度吗?
原文:https://towardsdatascience.com/transformers-can-you-rate-the-complexity-of-reading-passages-17c76da3403?source=collection_archive---------15-----------------------
实践教程
用 PyTorch 微调 RoBERTa 以预测文本摘录的阅读难易程度
照片由 Jeffery Ho 在 Unsplash 上拍摄
变压器,它们到底是什么?它们不是用于电能动力传输的装置,也不是虚构的活生生的自主机器人擎天柱或大黄蜂可以变形为车辆等其他物体。在我们的上下文中,Transformers 指的是 BERT、ALBERT、RoBERTa 等,它们在数据科学领域中用于解决各种自然语言处理任务,如机器翻译、文本摘要、语音识别、情感分析等。它们是用于自然语言处理的最先进的语言模型,并且在过去的几年中获得了极大的欢迎。
这篇文章将展示 Transformer 模型的微调,特别是 RoBERTa 在我们感兴趣的数据集上的微调。对下游任务进行微调,以预测 3-12 年级课堂使用的文学作品摘录的阅读难易程度。
这项工作是由非营利教育技术组织 CommonLit 发起的。它赞助了在 Kaggle 上举办的一场比赛(你可以在这里阅读更多信息),旨在使用机器学习来寻求对现有可读性评级方法的改进。这将有助于读写课程的开发者以及教育者为学生选择合适的阅读文章。呈现具有适当复杂程度和阅读挑战的引人入胜的段落将极大地有利于学生发展基本的阅读技能。
目录
1。 关于数据集
2。 拆分数据
3。 创建数据集类
4。 罗伯塔-基为我们的型号
5。 变压器有哪些典型的原始输出?
6。 定义模型类
∘ 使用 pooler_output
∘ 构建自己的变压器自定义头
∘ (A)注意头
∘ (B)串接隐藏层
7。 模型训练
∘ 评价度量和损失函数
∘ 训练函数
∘ 验证函数
∘ 运行训练
总结
参考文献
1.关于数据集
我们将要使用的数据集可以在这个 Kaggle 页面上找到。这个数据集包含大约 2800 条记录。我们将使用的两个重要字段是excerpt
和target
。
查看数据,excerpt
是预测阅读难易程度的文本,target
是可以包含正值或负值的数值字段。如该数据集中所示,它是一个连续变量,最小值为-3.676268,最大值为 1.711390。因此,给定一个特定的excerpt
,我们需要预测target
的值。
给大家一点背景知识,竞赛主持人 Scott Crossley 曾在这个讨论中提到“目标值是一个Bradley-Terry分析超过 111,000 个两两比较摘录的结果。跨越 3-12 年级的教师,大多数在 6-10 年级教学,担任这些比较的评分者。
较高的target
值对应于“更易阅读”,较低的值对应于“更难阅读”。例如,假设我们有三个摘录 A、B 和 C,它们对应的target
值是 1.599999、-1.333333 和-2.888888。这将意味着 A 比 B 更容易阅读,B 比 c 更容易阅读。
为了说明,下面是两个样本摘录。
**Excerpt with target value of 1.541672:**More people came to the bus stop just before 9am. Half an hour later they are all still waiting. Sam is worried. "Maybe the bus broke down," he thinks. "Maybe we won't go to town today. Maybe I won't get my new school uniform." At 9:45am some people give up and go home. Sam starts to cry. "We will wait a bit longer," says his mother. Suddenly, they hear a noise. The bus is coming! The bus arrives at the stop at 10 o'clock. "Get in! Get in!" calls the driver. "We are very late today!" People get on the bus and sit down. The bus leaves the stop at 10:10am. "What time is the return bus this afternoon?" asks Sam's mother. "The blue bus leaves town at 2:30pm," replies the driver. Sam thinks, "We will get to town at 11 o'clock." "How much time will we have in town before the return bus?" wonders Sam.**Excerpt with target value of -3.642892:**The iron cylinder weighs 23 kilogrammes; but, when the current has an intensity of 43 amperes and traverses 15 sections, the stress developed may reach 70 kilogrammes; that is to say, three times the weight of the hammer. So this latter obeys with absolute docility the motions of the operator's hands, as those who were present at the lecture were enabled to see. I will incidentally add that this power hammer was placed on a circuit derived from one that served likewise to supply three Hefner-Alteneck machines (Siemens D5 model) and a Gramme machine (Breguet model P.L.). Each of these machines was making 1,500 revolutions per minute and developing 25 kilogrammeters per second, measured by means of a Carpentier brake. All these apparatuses were operating with absolute independence, and had for generators the double excitation machine that figured at the Exhibition of Electricity. In an experiment made since then, I have succeeded in developing in each of these four machines 50 kilogrammeters per second, whatever was the number of those that were running; and I found it possible to add the hammer on a derived circuit without notably affecting the operation of the receivers.
显然,在这两篇摘录中,前者比后者更容易阅读。
2.拆分数据
由于我们的数据集相当小,我们将使用交叉验证来更准确地衡量我们模型的性能。因此,我们将使用分层 k-fold 将数据分为训练集和验证集。使用分层 k-fold,通过保留每个类别的样本百分比来进行折叠。当我们有一个倾斜的数据集时,或者当target
的分布不*衡时,这种方法是有用的。然而,因为我们的target
是一个连续变量而不是类,所以我们需要某种变通方法。这就是宁滨target
前来救援的地方。bin 类似于类,这对于 scikit-learn 的[StratifiedKFold](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedKFold.html)
来说再好不过了。
代码相当简单。在计算对target
进行分类所需的分类数之前,我们随机化数据行并重置行索引。一种方法是使用斯特奇法则来确定要使用的箱数。接下来,我们使用 scikit-learn 的StratifiedKFold
类,根据我们拥有的 bin 将数据分成 5 份。最后,生成的折叠编号(范围从 0 到 4)将被分配给一个名为skfold
的新列。过程结束时,不再需要垃圾箱,如果您愿意,可以将其丢弃。
用StratifiedKFold
创作褶皱,改编自 Abhishek Thakur 的笔记本这里。
供您参考,完整数据集的*均值target
为-0.96(四舍五入到小数点后两位)。拆分成 5 个褶皱后,我们可以看到target
在每个褶皱上的分布形状都被保留了下来。看下面的图,每个折叠的*均值target
几乎是一致的,它们确实非常接*-0.96。
图 1:每个折叠的目标变量的分布形状。作者图片
3.创建数据集类
我们现在将创建MyDataset
的子类torch.utils.data.Dataset
。摘录将作为texts
传入,同时传入的还有用于标记texts
的tokenizer
。在这个过程中,记号赋予器产生记号的 id(称为输入 id)以及输入到我们的模型中所必需的注意屏蔽。图 2 显示了一个输入文本为“你好吗?”。如果你感兴趣,可以在这里找到关于记号赋予器、注意力屏蔽、填充和截断的更多细节。
4.roberta-base
作为我们的模型
RoBERTa 代表RobustublyOoptimizedBERTPre-trainingAapproach,由华盛顿大学和脸书大学的研究人员于 2019 年提出。它是在 2018 年发布的 BERT:面向语言理解的深度双向变换器预训练的基础上改进的预训练程序。在整个演示过程中,我们将使用 RoBERTa 和 PyTorch,但是如果您愿意,您也可以修改和使用其他的 Transformer 模型。请务必查看您所使用的变压器模型的相关文档,以确认它们支持代码所使用的输入和输出。
上有一些 RoBERTa 类的变体🤗拥抱脸。其中一个是RobertaModel
,这里的引用为*“裸露的罗伯塔模型变压器输出原始的隐藏状态,顶部没有任何特定的头。”*换句话说,bare RobertaModel
的原始输出是输入序列中每个 token 对应的预定义隐藏大小的隐藏状态向量。使用裸露的RobertaModel
类,我们将添加我们自己的定制回归头来预测target
。
对于我们的变压器微调任务,我们将使用来自🤗拥抱脸作为我们的模特。正如那里所描述的,“RoBERTa 是一个以自我监督的方式在一个大的英语语料库上预先训练的变形金刚模型”。 roberta-base
隐藏尺寸为 768,由一个嵌入层后跟 12 个隐藏层组成。
图 2:用max_length=10
和padding=“max_length”
设置 tokenizer 参数的例子。添加特殊标记后,任何短于 10 的输入序列都将被填充<pad>
标记。作者图片
5.变压器的典型原始输出是什么?
在我们开始创建和定义模型类之前,我们需要理解 Transformer 的原始输出是什么。这是因为我们将使用原始输出来填充自定义回归头。
以下是 BERT、ALBERT 和 RoBERTa 等变压器模型通常返回的常见原始输出。它们取自文档这里,这里这里,这里这里。
- last_hidden_state :这是模型最后一层输出的隐藏状态序列。它是一个形状张量
(batch_size, sequence_length, hidden_size)
- pooler_output :这是由线性层和 Tanh 激活函数进一步处理的序列的第一个令牌(分类令牌)的最后一层隐藏状态。它是一个形状为
(batch_size, hidden_size)
的张量。请注意,pooler_output
可能不适用于某些型号的变压器。 - 隐藏状态:可选,当
output_hidden_states = True
通过时返回。它是形状(batch_size, sequence_length, hidden_size)
的张量元组(一个用于嵌入的输出+一个用于每层的输出)。
那么,什么是batch_size
、sequence_length
、hidden_size
?
通常,模型按批次处理记录。因此batch_size
是模型在一次向前/向后传递中更新其内部参数之前处理的记录数。sequence_length
是我们为标记器的max_length
参数设置的值,而hidden_size
是处于隐藏状态的特征(或元素)的数量。至于张量,你可以把它形象化为一个 n 维数组,可以用于任意数值计算。
图 3: last_hidden_state
,即最后一层的模型输出。它是一个形状张量(batch_size, sequence_length, hidden_size)
。作者图片
6.定义模型类
这里我们将创建MyModel
和子类[nn.Module](https://pytorch.org/docs/stable/generated/torch.nn.Module.html)
。
An nn.Module
是所有神经网络模块的基类,它包含多个层和一个方法forward
,该方法接受输入并返回输出。除此之外,它还包含状态和参数,并可以通过它们进行权重更新或将其梯度归零。从nn.Module
的__call__
函数中调用forward
方法。因此,当我们运行MyModel(inputs)
时,就会调用forward
方法。
使用pooler_output
对于任何回归或分类任务,最简单的实现是直接采用pooler_output
并附加一个额外的回归器或分类器输出层。
特别是在我们的例子中,我们可以在__init__
方法中定义一个带有一个[nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html)
层的regressor
作为我们网络的一部分。然后在forward
方法中,我们将把pooler_output
输入到regressor
中,为target
产生预测值。
构建您自己的变压器定制头
除了简单地使用pooler_output
之外,还有许多不同的方法可以定义和组成你自己的层和自定义头。我们将演示的一个例子是注意力头,它是从这里的改编而来的。
🅰️ 注意头像
在forward
方法中,来自last_hidden_state
的原始输出被输入到另一个类AttentionHead
的实例中(我们将在下一段中讨论AttentionHead
)。来自AttentionHead
的输出然后被传递到我们之前看到的regressor
中。
那么,AttentionHead
里面是什么?AttentionHead
中有两个线性层。AttentionHead
将last_hidden_state
带入第一个线性图层,在进入第二个线性图层之前,经过一个tanh(双曲线正切)激活函数。这就导出了注意力得分。然后将 softmax 函数应用于这些注意力分数,重新缩放它们,以使张量的元素位于范围[0,1]内,总和为 1(嗯,试着将其视为概率分布)。然后将这些权重与last_hidden_state
相乘,并对跨越sequence_length
维度的张量求和,最终产生形状(batch_size, hidden_size)
的结果。
🅱️ 连接隐藏层
我们想分享的另一个技术是隐藏层的连接。这个想法来自于 BERT:用于语言理解的深度双向转换器的预训练 ,其中作者提到,使用基于特征的方法,连接最后四个隐藏层在他们的案例研究中给出了最佳性能。
“最佳执行方法是连接预训练转换器的前四个隐藏层的标记表示”
您可以在下面的代码中观察到,在调用我们的模型时,我们需要如何指定output_hidden_states = True
。这是因为我们现在想要接收和使用来自其他隐藏层的输出,而不仅仅是last_hidden_state
。
在forward
方法中,来自hidden_states
的原始输出被叠加,给我们一个(layers, batch_size, sequence_length, hidden_size)
的张量形状。由于roberta-base
总共有 13 层,这简单地转化为(13, batch_size, sequence_length, 768)
的张量形状。接下来,我们在hidden_size
维度上连接最后四层,这给我们留下了一个张量形状(batch_size, sequence_length, 768*4)
。连接之后,我们使用序列中第一个标记的表示。我们现在有了一个张量形状(batch_size, 768*4)
,这最终被输入到regressor
。
图 4:4 个隐藏层的连接。作者图片
如果你有兴趣继续阅读更多的例子,请看一下这个笔记本。
7.模特培训
好了,让我们继续为一个基本的模型训练过程编写训练代码。
因为在这篇文章中我们不会涉及训练变形金刚的高级技术,我们将只创建简单的函数。现在,我们需要创建一个损失函数,一个训练函数,一个验证函数,最后是运行训练的主函数。
由于我们使用的是预训练模型(而不是从头开始训练),这里的模型训练也通常被称为变压器微调过程。
▶️评价度量和损失函数📉
为了衡量我们模型的性能,我们将使用 RMSE (均方根误差)作为评估指标。
等等,损失函数是什么?它是用来做什么的?损失函数是用来测量预测输出和提供的target
值之间的误差,以优化我们的模型。事实上,这是优化器试图最小化的函数。
有时评估度量和损失函数可以不同,特别是对于分类任务。但是在我们的例子中,由于这是一个回归任务,我们将使用 RMSE 来完成这两个任务。
因此,我们将损失函数定义如下:
def loss_fn(predictions, targets):
return torch.sqrt(nn.MSELoss()(predictions, targets))
▶️训练函数
我们正在创建的train_fn
将使用训练数据集来训练我们的模型。在我们运行训练时的主训练循环中,每个历元都会调用这个函数。
该功能将首先在训练模式下设置模型。本质上,它将在数据加载器中循环所有批次的训练数据,获得批次的预测,反向传播误差,基于当前梯度更新参数,并基于调度器更新学习率。
需要注意的一点是,在开始反向传播之前,我们需要将梯度设置为零。这是因为 PyTorch 会在后续反向过程中累积梯度。
最后,该函数将返回它在批次中收集的培训损失和学习率。
▶️验证函数
validate_fn
用于对我们的验证数据集进行评估。它基本上会评估我们的模型在每个时期的训练过程中表现如何。它与我们上面写的train_fn
非常相似,除了梯度计算被禁用。因此没有误差的反向传播,也没有参数和学习率的更新。
该功能首先将模型设置为评估模式。它将在数据加载器中循环所有批次的认证数据,对认证数据(即训练期间未看到的数据)的批次运行预测,并收集将在最后返回的认证损失。
笔记摘自 PyTorch 文档 此处 和 此处 :
建议我们在训练时总是使用
model.train()
,在评估我们的模型(验证/测试)时总是使用model.eval()
,因为我们正在使用的模块可能会被更新以在训练和评估模式下表现不同。当我们确定不会调用
[.backward()](https://pytorch.org/docs/stable/generated/torch.Tensor.backward.html#torch.Tensor.backward)
进行反向传播时,禁用梯度计算对推断(或验证/测试)很有用。这将减少原本需要梯度计算的计算的内存消耗。
▶️跑步训练
现在我们已经创建了train_fn
和validate_fn
,让我们继续创建运行培训的主函数。
该功能的顶部将为模型训练做必要的准备。对于每个折叠,它将初始化标记化器,获取并创建训练和验证数据集和数据加载器,加载模型并将其发送到设备,并获取优化器和学习率调度器。
一旦这些都完成了,它就准备好进入训练循环了。训练循环将调用train_fn
进行训练,然后再调用validate_fn
对每个时期进行模型评估。一般来说,训练损失和验证损失应该随着时间逐渐减少。每当验证损失有所改善时(记住,它越低越好),模型检查点就会被保存。否则,循环将继续,直到最后一个时期,或者当达到早期停止阈值时。基本上,当经过 n 次迭代后确认损失仍无改善时,触发提前停止,其中 n 为预设阈值。
该函数还将绘制训练和验证损失,以及每个折叠结束时的学习率时间表。
图 5:每个折叠的训练和验证损失的样本图。作者图片
摘要
最后,我们即将结束这篇冗长的文章。总结一下:
☑️:我们学习了如何使用 scikit-learn 的StratifiedKFold
执行分层 k-fold,将数据分成训练集和验证集。特别是在我们的案例中,我们使用了垃圾箱。
☑️:我们从变压器中得到典型的原始输出的要点。
☑️:我们创建并定义了数据集和模型类。
☑️我们探索了一些自定义回归头的例子,我们可以建立我们的模型。
☑️:我们经历了模型训练过程的基础,并为它创建了必要的功能。
这还不是全部。请关注我的下一篇文章,关于如何应用高级培训技术来微调变压器模型。
如果你喜欢我的帖子,别忘了点击 关注 和 订阅 以获得邮件通知。
可选地,你也可以 注册 成为媒体会员,以获得媒体上每个故事的全部访问权限。
📑访问这个GitHub repo获取我在帖子中分享的所有代码和笔记本。
2021 保留所有权利。
参考
[1] A. Thakur,(几乎)接*任何机器学习问题 (2020)
[2] C .孙,x .邱,y .徐,x .黄,如何微调用于文本分类的 BERT? (2020)
[3] Y. Liu,M. Ott,N. Goyal,J. Du,M. Joshi,D. Chen,O. Levy,M. Lewis,L. Zettlemoyer 和 V. Stoyanov, RoBERTa:稳健优化的 BERT 预训练方法 (2019)
[4] J. Devlin,M. Chang,K. Lee 和 K. Toutanova, BERT:用于语言理解的深度双向转换器的预训练 (2018)
[5] A .瓦斯瓦尼、n .沙泽尔、n .帕尔马、j .乌兹科雷特、l .琼斯、A .戈麦斯、l .凯泽和 I .波洛苏欣,注意力是你所需要的全部 (2017)
变形金刚,解释:理解 GPT 3,伯特和 T5 背后的模型
原文:https://towardsdatascience.com/transformers-explained-understand-the-model-behind-gpt-3-bert-and-t5-cdbf3fc8a40a?source=collection_archive---------1-----------------------
戴尔·马科维茨原创图片
实践教程
你知道那句话吗,当你有一把锤子时,一切看起来都像钉子?嗯,在机器学习中,似乎我们真的发现了一把神奇的锤子,事实上,对它来说一切都是钉子,它们被称为变形金刚。变形金刚是可以被设计成翻译文本,写诗和专栏,甚至生成计算机代码的模型。事实上,我写的许多关于 daleonai.com 的惊人研究都是建立在变形金刚之上的,比如从基因序列预测蛋白质结构的模型 AlphaFold 2 ,以及强大的自然语言处理(NLP)模型,比如 GPT-3 ,BERT,T5,Switch,Meena 等等。你可能会说他们不仅仅是满足了…唉,算了吧。
如果你想在机器学习,特别是 NLP 方面保持领先,你至少要知道一点关于变形金刚的知识。所以在这篇文章中,我们将谈论它们是什么,它们是如何工作的,以及为什么它们如此有影响力。
转换器是一种神经网络体系结构。概括地说,神经网络是一种非常有效的模型,用于分析复杂的数据类型,如图像、视频、音频和文本。但是有不同类型的神经网络针对不同类型的数据进行了优化。例如,为了分析图像,我们通常会使用卷积神经网络或“CNN”隐约地,它们模仿了人类大脑处理视觉信息的方式。
卷积神经网络,图片来自 Wikicommons 的 Renanar2。
大约从 2012 年开始,我们已经相当成功地用 CNN 解决了视觉问题,比如识别照片中的物体、识别人脸和阅读手写数字。但是在很长一段时间里,对于语言任务(翻译、文本摘要、文本生成、命名实体识别等)来说,没有什么可以与之相比的。这很不幸,因为语言是我们人类交流的主要方式。
在 2017 年推出变形金刚之前,我们使用深度学习来理解文本的方式是一种叫做递归神经网络或 RNN 的模型,看起来像这样:
来自维基媒体 fdeloche 的一张 RNN 图片。
假设你想把一个句子从英语翻译成法语。RNN 会把一个英语句子作为输入,一次处理一个单词,然后依次吐出它们的法语对应物。这里的关键词是“顺序”在语言中,单词的顺序很重要,你不能把它们混在一起。句子:
"简自找麻烦。"
意思和这句话很不一样:
“荷生去找简了”
因此,任何理解语言的模型都必须捕捉词序,递归神经网络通过按顺序一次处理一个词来做到这一点。
但是 RNNs 有问题。首先,他们很难处理大型文本序列,比如长段落或短文。当一个段落结束时,他们会忘记开头发生的事情。例如,一个基于 RNN 的翻译模型可能很难记住一个长段落主题的性别。
更糟糕的是,注册护士很难训练。众所周知,他们容易受到所谓的消失/爆炸梯度问题(有时你只需重新开始训练并交叉手指)。更有问题的是,因为它们顺序处理单词,rnn 很难并行化。这意味着你不能仅仅通过向它们扔更多的 GPU 来加速训练,这反过来意味着你不能在那么多数据上训练它们。
输入变压器
这就是变形金刚改变一切的地方。它们是由谷歌和多伦多大学的研究人员在 2017 年开发的,最初旨在做翻译。但与递归神经网络不同,变压器可以非常有效地并行化。这意味着,有了合适的硬件,你可以训练一些真正的大模型。
多大?
非常大。
GPT-3 是一个特别令人印象深刻的文本生成模型,它写得几乎和人类一样好,它是在一些 45 TB 的文本数据上训练出来的,包括几乎所有的公共网络。
因此,如果你还记得关于变形金刚的任何事情,就让它这样吧:将一个可扩展的模型与一个巨大的数据集结合起来,结果可能会让你大吃一惊。
变形金刚是怎么工作的?
变压器图来自原图:https://arxiv.org/abs/1706.03762
虽然来自原始论文的图表有点吓人,但变形金刚背后的创新可以归结为三个主要概念:
- 位置编码
- 注意力
- 自我关注
位置编码
让我们从第一个开始,位置编码。假设我们试图将文本从英语翻译成法语。请记住,RNNs,旧的翻译方法,通过顺序处理单词来理解单词顺序。但这也是它们难以并行化的原因。
变形金刚通过一种叫做位置编码的创新技术绕过了这个障碍。这个想法是获取输入序列中的所有单词——在这个例子中是一个英语句子——并给每个单词附加一个它的顺序号。所以,你给你的网络输入一个序列:
[("Dale", 1), ("says", 2), ("hello", 3), ("world", 4)]
从概念上讲,你可以把理解词序的负担从神经网络的结构转移到数据本身。
首先,在转换器接受任何数据训练之前,它不知道如何解释这些位置编码。但随着模型看到越来越多的句子及其编码的例子,它学会了如何有效地使用它们。
我在这里做了一点过度简化——最初的作者使用正弦函数来提出位置编码,而不是简单的整数 1、2、3、4——但要点是相同的。将词序存储为数据,而不是结构,你的神经网络变得更容易训练。
注意力
变形金刚的下一个重要部分叫做注意力。
呵。
注意力是一种神经网络结构,这些天你会在机器学习中到处听到。事实上,2017 年介绍变形金刚的论文标题并不叫*我们向你呈现变形金刚。*取而代之的是叫做注意力是你所需要的全部。
关注是在两年前的 2015 年,在翻译的语境下引入的。要理解它,请参考原文中的例句:
欧洲经济区协议于 1992 年 8 月签署。
现在想象一下,试着把这句话翻译成法语的对等物:
《欧洲经济区协定》于 1992 年 8 月签署。
尝试翻译这句话的一个糟糕的方法是仔细阅读英语句子中的每个单词,并尝试一次一个单词地吐出它的法语对应词。出于几个原因,这不会很好地工作,但其中一个原因是,法语翻译中的一些单词被颠倒了:在英语中是“欧洲经济区”,但在法语中是“欧洲经济区”。此外,法语是一种带有性别词汇的语言。形容词“économique”和“européenne”必须是阴性形式,以匹配阴性宾语“la zone”
注意力是一种机制,它允许文本模型在决定如何翻译输出句子中的单词时“查看”原始句子中的每个单词。这是来自最初的关注文件的一个很好的可视化:
图自论文《联合学习对齐和翻译的神经机器翻译(2015)》,【https://arxiv.org/abs/1409.0473】T2
这是一种热图,显示了当模型输出法语句子中的每个单词时,它“注意”了哪里。正如您所料,当模型输出单词“européenne”时,它会同时关注输入单词“European”和“Economic”
模型如何知道在每个时间点应该“注意”哪些单词?这是从训练数据中学到的东西。通过查看数千个法语和英语句子的例子,该模型了解了哪些类型的单词是相互依赖的。它学习如何尊重性别、多元化和其他语法规则。
自 2015 年被发现以来,注意力机制一直是自然语言处理的一个非常有用的工具,但在其最初的形式中,它是与递归神经网络一起使用的。因此,2017 年《变形金刚》论文的创新部分是完全抛弃了 RNNs。这就是为什么 2017 年的论文被称为“注意力是你所需要的全部”
自我关注
《变形金刚》的最后一部分(可能也是最有影响力的部分)是注意力的扭曲,叫做“自我关注”
我们刚刚谈到的“香草”注意力有助于在英语和法语句子中对齐单词,这对翻译很重要。但是,如果你不是试图翻译单词,而是建立一个理解语言潜在意义和模式的模型——一种可以用来完成任何数量的语言任务的模型——会怎么样呢?
总的来说,使神经网络强大、令人兴奋和酷的是,它们经常自动建立对它们接受训练的数据的有意义的内部表示。例如,当你检查视觉神经网络的层时,你会发现一组神经元“识别”边缘、形状,甚至像眼睛和嘴这样的高级结构。根据文本数据训练的模型可能会自动学习词性、语法规则以及单词是否同义。
神经网络学习的语言的内部表示越好,它在任何语言任务中就越好。事实证明,如果注意力被输入的文本本身所吸引,它会是一种非常有效的方式。
例如,以这两句话为例:
"服务员,能给我结账吗?"
“看来我刚刚让服务器崩溃了。”
服务器这个词在这里意味着两个非常不同的东西,我们人类可以通过查看周围的单词来轻松消除歧义。自我注意允许神经网络在周围单词的上下文中理解一个单词。
因此,当一个模型处理第一句话中的单词“服务器”时,它可能会“注意”单词“检查”,这有助于区分人工服务器和金属服务器。
在第二句话中,模型可能会注意到单词“崩溃”来确定这个“服务器”指的是一台机器。
自我关注帮助神经网络消除单词歧义,进行词性标注,实体解析,学习语义角色和等等。
所以,我们到了。:变压器,在 10,000 英尺的高度解释,归结为:
如果你想要更深入的技术解释,我强烈推荐看看杰伊·阿拉玛的博客文章《变形金刚》。
变形金刚能做什么?
最流行的基于变压器的模型之一被称为 BERT,是“来自变压器的双向编码器表示”的缩写它是在我 2018 年加入谷歌时由谷歌的研究人员推出的,很快就进入了几乎所有的 NLP 项目——包括谷歌搜索。
BERT 指的不仅仅是模型架构,而是经过训练的模型本身,你可以在这里免费下载和使用。它由谷歌研究人员在大规模文本语料库上训练,已经成为 NLP 的通用小刀。它可以扩展解决一系列不同的任务,例如:
-文本摘要
-回答问题
-分类
-命名实体解析
-文本相似性
-攻击性信息/亵渎检测
-了解用户查询
-多得多
BERT 证明了你可以在未标记的数据上建立非常好的语言模型,比如从维基百科和 Reddit 上搜集的文本,然后这些大型“基础”模型可以根据特定领域的数据进行调整,以适应许多不同的用例。
最*,由 OpenAI 创建的模型 GPT-3 以其生成逼真文本的能力震撼了人们的心灵。 Meena ,由 Google Research 去年推出,是一个基于 Transformer 的聊天机器人(akhem,“对话代理”),它可以就几乎任何话题进行引人注目的对话(作者曾经花了 20 分钟与 Meena 争论对人类来说意味着什么)。
变形金刚也在自然语言处理之外兴风作浪,通过作曲,从文本描述生成图像,以及预测蛋白质结构。
如何使用变形金刚?
既然你已经被变压器的力量所吸引,你可能想知道如何在你自己的应用中使用它们。没问题。
你可以从 TensorFlow Hub 下载常见的基于变压器的模型,比如 BERT。关于代码教程,请查看我写的这篇关于构建语义语言驱动的应用的文章。
但是如果你想真正时髦并且你写 Python,我强烈推荐由 HuggingFace 公司维护的流行的“变形金刚”库。这个*台允许你以一种对开发者非常友好的方式训练和使用大多数当今流行的 NLP 模型,比如 BERT,Roberta,T5,GPT-2。
暂时就这样吧!
特别感谢路易斯/古斯·古斯塔沃、卡尔·魏因梅斯特和亚历克斯·Ku 审阅了本文的初稿!
原载于 2021 年 5 月 6 日 https://daleonai.com**T21。
变形金刚形象地解释了——不仅仅是如何解释,还解释了它们为什么如此好用
原文:https://towardsdatascience.com/transformers-explained-visually-not-just-how-but-why-they-work-so-well-d840bd61a9d3?source=collection_archive---------1-----------------------
实践教程,直观变形金刚系列 NLP
一个温和的指南,用简单的英语介绍注意力得分计算如何捕捉一个序列中单词之间的关系。
奥拉夫·阿伦斯·罗特内在 Unsplash 上的照片
在过去的几年里,变形金刚席卷了 NLP 的世界。现在,它们在 NLP 以外的应用中也获得了成功。
变压器因为注意力模块而获得能量。这是因为它捕捉到了序列中每个单词与其他单词之间的关系。
但是最重要的问题是它到底是如何做到的?
在本文中,我们将尝试回答这个问题,并理解为什么会执行它所做的计算。
我的变形金刚系列还有几篇文章。在那些文章中,我们学习了 Transformer 架构,并在训练和推理过程中一步一步地完成了它们的操作。我们还探索了引擎盖下,并确切了解他们如何工作的细节。
我们的目标是不仅要理解事物是如何工作的,还要理解它为什么会这样工作。
- 功能概述 ( 变压器如何使用,为什么比 rnn 好。架构的组件,以及训练和推理期间的行为
- 工作原理 ( 端到端内部操作。数据如何流动以及执行何种计算,包括矩阵表示
- 多头关注 ( 整个变压器关注模块的内部工作方式)
如果您对一般的 NLP 应用程序感兴趣,我还有一些您可能会喜欢的文章。
- 波束搜索
- Bleu 评分 ( Bleu 评分和单词错误率是 NLP 模型的两个基本指标)
为了理解是什么让变压器滴答作响,我们必须集中注意力。让我们从输入它的信息开始,然后看看它是如何处理这些信息的。
输入序列如何到达注意模块
注意模块存在于编码器堆栈中的每个编码器以及解码器堆栈中的每个解码器中。我们先放大编码器的注意力。
注意编码器(图片由作者提供)
例如,假设我们正在处理一个英语到西班牙语的翻译问题,其中一个样本源序列是“球是蓝色的”。目标序列是“La bola es azul”。
源序列首先通过嵌入和位置编码层,该层为序列中的每个单词生成嵌入向量。嵌入被传递到编码器,在那里它首先到达注意模块。
在 Attention 中,嵌入的序列通过三个线性层传递,这三个层产生三个独立的矩阵,即查询、键和值。这是用于计算注意力得分的三个矩阵。
要记住的重要一点是,这些矩阵的每一行对应于源序列中的一个单词。
源序列的流程(图片由作者提供)
每个输入行都是序列中的一个单词
我们理解注意力是怎么回事的方法是从源序列中的单个单词开始,然后沿着它们的路径通过转换器。特别是,我们想要关注注意力模块内部发生的事情。
这将帮助我们清楚地看到源和目标序列中的每个单词是如何与源和目标序列中的其他单词相互作用的。
因此,当我们仔细阅读这个解释时,要集中精力在每个单词上执行什么操作,以及每个向量如何映射到原始输入单词。我们不需要担心许多其他细节,如矩阵形状、算术计算的细节、多重注意力等等,如果它们与每个单词的走向没有直接关系的话。
因此,为了简化解释和可视化,让我们忽略嵌入维度,只跟踪每个单词的行。
源序列中每个单词的流向(图片由作者提供)
每个单词都经历了一系列可学习的变化
每个这样的行都是通过一系列转换(嵌入、位置编码和线性层)从其对应的源单词生成的。
所有这些转变都是可训练的操作。这意味着这些操作中使用的权重不是预先确定的,而是由模型以产生所需输出预测的方式学习的。
学习线性和嵌入权重(图片由作者提供)
关键问题是,转换器如何计算出哪组权重会给它最好的结果?请记住这一点,因为我们稍后会谈到这一点。
注意力得分—查询和关键词之间的点积
注意力执行几个步骤,但是在这里,我们将只关注线性层和注意力分数。
多头关注(图片由作者提供)
关注度评分计算(图片由作者提供)
从公式中我们可以看出,注意力的第一步是做矩阵乘法(即点积)在查询(Q)矩阵和关键(K)矩阵的转置之间。观察每个单词的变化。
我们产生一个中间矩阵(姑且称之为‘因子’矩阵),其中每个单元是两个字之间的矩阵乘法。
查询和关键矩阵之间的点积(图片由作者提供)
例如,第四行中的每一列对应于第四个查询词与每个关键词之间的点积。
查询和关键矩阵之间的点积(图片由作者提供)
注意力得分—查询关键词和值词之间的点积
下一步是这个中间“因子”矩阵和值(V)矩阵之间的矩阵乘法,以产生由注意力模块输出的注意力分数。这里我们可以看到,第四行对应于第四个查询词矩阵乘以所有其他关键字和值词。
查询键和值矩阵之间的点积(图片由作者提供)
这产生由注意力模块输出的注意力得分向量(Z)。
考虑输出分数的方式是,对于每个单词,它是来自“值”矩阵的每个单词的编码值,由“因子”矩阵加权。因子矩阵是特定单词的查询值与所有单词的键值的点积。
注意力得分是单词值(作者图片)的加权和
查询、关键字和值字的作用是什么?
查询词可以被解释为我们正在计算关注度的词*。关键词和值词是我们关注的词*即。该单词与查询单词的相关程度如何。**
单词“blue”的注意力分数关注其他所有单词(图片由作者提供)
例如,对于句子“球是蓝色的”,单词“蓝色”的行将包含“蓝色”和其他每个单词的注意力得分。这里“蓝色”是查询词,其他词是“键/值”。
还有其他正在执行的操作,如除法和 softmax,但在本文中我们可以忽略它们。它们只是改变矩阵中的数值,但不影响矩阵中每个字行的位置。它们也不涉及任何单词间的相互作用。
点积告诉我们单词之间的相似性
我们已经看到,注意力得分是通过做点积,然后将它们相加,来捕捉特定单词和句子中其他单词之间的一些相互作用。但是矩阵乘法如何帮助变换器确定两个单词之间的相关性呢?
要理解这一点,请记住查询、键和值行实际上是具有嵌入维度的向量。让我们放大一下这些向量之间的矩阵乘法是如何计算的。
每个单元格是两个单词向量之间的点积(图片由作者提供)
当我们在两个向量之间做点积时,我们将数对相乘,然后求和。
- 如果两个成对的数字(如上面的‘a’和‘d ’)都是正的或者都是负的,那么乘积将是正的。乘积将增加最终总和。
- 如果一个数字是正的,另一个是负的,那么乘积将是负的。乘积将减少最终总和。
- 如果乘积为正,两个数字越大,它们对最终总和的贡献就越大。
这意味着,如果两个向量中相应数字的符号对齐,最终的和将会更大。
变形金刚是如何学习单词之间的关联性的?
点积的概念也适用于注意力得分。如果两个单词的向量更加一致,注意力得分将会更高。
那么我们希望变压器的行为是什么呢?
我们希望句子中彼此相关的两个单词的注意力得分高。我们希望两个互不相关的单词得分较低。
比如,对于“黑猫喝了牛奶”这句话,“牛奶”这个词与“喝了”非常相关,可能与“猫”的相关性略低,与“黑”无关。我们希望“牛奶”和“喝了”产生一个高的注意力分数,“牛奶”和“猫”产生一个稍低的分数,而“牛奶”和“黑色”产生一个可以忽略的分数。
这是我们希望模型学习产生的输出。
要做到这一点,表示“牛奶”和“饮用”的单词向量必须对齐。“牛奶”和“猫”的向量会有些不同。而他们对于“奶”和“黑”会有很大的不同。
让我们回到我们一直在思考的问题——转换器是如何计算出哪组权重会给它带来最好的结果的?
基于单词嵌入和线性层的权重来生成单词向量。因此,转换器可以学习这些嵌入、线性权重等等,以产生如上所要求的单词向量。
换句话说,它将学习这些嵌入和权重,如果一个句子中的两个单词彼此相关,那么它们的单词向量将被对齐。并因此产生更高的注意力分数。对于彼此不相关的单词,单词向量将不会对齐,并且将产生较低的注意力分数。
因此,“牛奶”和“喝过的”的嵌入将非常一致,并产生高的注意力分数。对于“牛奶”和“猫”来说,它们会有些不同,从而产生稍低的分数,而对于“牛奶”和“黑色”来说,它们会有很大的不同,从而产生较低的分数。
这就是注意力模块背后的原理。
总结一下——是什么让变压器运转起来?
查询和关键字之间的点积计算每对单词之间的相关性。这种相关性然后被用作“因子”来计算所有值词的加权和。该加权和作为注意力分数输出。
转换器学习嵌入等,以这种方式,彼此相关的单词更加对齐。
这是引入三个线性层并为查询、键和值制作三个版本的输入序列的一个原因。这给了注意力模块更多的参数,它能够学习来调整单词向量的创建。
变压器中的编码器自关注
注意力被用在变压器的三个地方:
- 编码器中的自我关注—源序列关注自身
- 解码器中的自我关注—目标序列关注自身
- 编码器-解码器-注意解码器-目标序列注意源序列
变形金刚中的注意力(图片由作者提供)
在编码器自我关注中,我们计算源句子中的每个单词与源句子中的每个其他单词的相关性。堆栈中的所有编码器都会发生这种情况。
变压器中的解码器自关注
我们刚刚在编码器中看到的大部分自我注意也适用于解码器中的注意,有一些小但重要的区别。
解码器中的注意力(图片由作者提供)
在解码器自我关注中,我们计算目标句子中的每个单词与目标句子中的每个其他单词的相关性。
解码器自我关注(图片由作者提供)
变压器中的编码器-解码器注意
在编码-解码注意中,从目标句子中获得查询,从源句子中获得键/值。因此,它计算目标句子中每个单词与源句子中每个单词的相关性。
编解码注意(图片由作者提供)
结论
希望这能让你对变压器设计的优雅有一个很好的认识。也请阅读我的系列中的其他 Transformer 文章,以深入了解为什么 Transformer 现在已经成为这么多深度学习应用程序的首选架构。
最后,如果你喜欢这篇文章,你可能也会喜欢我关于音频深度学习、地理定位机器学习和批处理规范的其他系列。
让我们继续学习吧!
变形金刚直观解释(第 2 部分):如何工作,一步一步
原文:https://towardsdatascience.com/transformers-explained-visually-part-2-how-it-works-step-by-step-b49fa4a64f34?source=collection_archive---------0-----------------------
直观变形金刚系列 NLP
引擎盖下的变压器及其端到端操作的温和指南。
约书亚·索蒂诺在 Unsplash 上拍摄的照片
这是我的变形金刚系列的第二篇文章。在的第一篇文章中,我们了解了变压器的功能、使用方法、高级架构以及优势。
在这篇文章中,我们现在可以看看引擎盖下,并研究他们如何工作的细节。我们将看到数据如何通过实际的矩阵表示和形状在系统中流动,并理解每个阶段执行的计算。
这里是对本系列之前和之后文章的一个快速总结。我的目标是不仅要理解事物是如何工作的,还要理解它为什么会这样工作。
- 功能概述 (变压器是怎么用的,为什么比 RNNs 好。架构的组件,以及训练和推理期间的行为)
- 工作原理—本文 (端到端内部操作。数据如何流动和执行什么计算,包括矩阵表示)
- 多头警示 (整个变压器警示模块的内部工作方式)
- 为什么注意力能提高表现 (不仅仅是注意力能做什么,还有为什么它如此有效。注意力是如何捕捉句子中单词之间的关系的)
如果您对一般的 NLP 应用程序感兴趣,我还有一些您可能会喜欢的文章。
- 波束搜索
- Bleu 评分 ( Bleu 评分和单词错误率是 NLP 模型的两个基本指标)
架构概述
正如我们在第 1 部分中看到的,该架构的主要组件包括:
(图片由作者提供)
编码器和解码器的数据输入,包括:
- 嵌入层
- 位置编码层
编码器堆栈包含许多编码器。每个编码器包含:
- 多头注意力层
- 前馈层
解码器堆栈包含多个解码器。每个解码器包含:
- 两个多头注意力层
- 前馈层
输出(右上)—生成最终输出,包含:
- 线性层
- Softmax 层。
为了理解每个组件的作用,让我们在训练转换器解决翻译问题时,先来看看它的工作过程。我们将使用一个训练数据样本,该样本由一个输入序列(英语为“You ' welcome”)和一个目标序列(西班牙语为“De nada”)组成。
嵌入和位置编码
像任何 NLP 模型一样,Transformer 需要关于每个单词的两件事情——单词的含义及其在序列中的位置。
- 嵌入层对单词的含义进行编码。
- 位置编码层表示单词的位置。
转换器通过添加这两种编码来组合它们。
把...嵌入
变压器有两个嵌入层。输入序列被馈送到第一嵌入层,称为输入嵌入。
(图片由作者提供)
在将目标右移一个位置并在第一位置插入开始标记之后,将目标序列馈送到第二嵌入层。注意,在推理过程中,我们没有目标序列,我们将输出序列循环输入到第二层,正如我们在第一部分中所学的。这就是为什么它被称为输出嵌入。
使用我们的词汇表将文本序列映射到数字单词 id。然后,嵌入层将每个输入单词映射到一个嵌入向量中,这是该单词含义的更丰富的表示。
(图片由作者提供)
位置编码
因为 RNN 实现了一个循环,其中每个单词都是顺序输入的,所以它隐式地知道每个单词的位置。
然而,变压器不使用 RNNs,序列中的所有单词都是并行输入的。这是其优于 RNN 架构的主要优势,但这意味着位置信息丢失,并且必须单独添加回去。
就像两个嵌入层一样,有两个位置编码层。位置编码的计算独立于输入序列。这些是固定值,仅取决于序列的最大长度。举个例子,
- 第一项是指示第一个位置的常量代码
- 第二项是指示第二位置的常数代码,
- 诸如此类。
这些常数使用下面的公式计算,其中
- pos 是单词在序列中的位置
- d_model 是编码向量的长度(与嵌入向量相同),并且
- i 是这个向量的索引值。
(图片由作者提供)
换句话说,它交错了正弦曲线和余弦曲线,所有偶数索引的正弦值和所有奇数索引的余弦值。例如,如果我们对一个 40 个单词的序列进行编码,我们可以在下面看到一些(单词位置,encoding_index)组合的编码值。
(图片由作者提供)
蓝色曲线表示所有 40 个字位置的第 0 个索引的编码,橙色曲线表示所有 40 个字位置的第 1 个索引的编码。对于剩余的指数值将有类似的曲线。
矩阵维度
我们知道,深度学习模型一次处理一批训练样本。嵌入和位置编码层对表示一批序列样本的矩阵进行操作。嵌入采用(样本,序列长度)形状的单词 id 矩阵。它将每个单词 ID 编码成一个单词向量,其长度为嵌入大小,从而产生一个(样本、序列长度、嵌入大小)形状的输出矩阵。位置编码使用的编码大小等于嵌入大小。所以它产生一个形状相似的矩阵,可以添加到嵌入矩阵中。
(图片由作者提供)
由嵌入和位置编码层产生的(样本、序列长度、嵌入大小)形状在整个变换器中保持不变,因为数据流经编码器和解码器堆栈,直到它被最终输出层整形。
这给出了变压器中 3D 矩阵尺寸的感觉。然而,为了简化可视化,从这里开始,我们将放弃第一维(对于样本),并使用单个样本的 2D 表示。
(图片由作者提供)
输入嵌入将其输出发送到编码器。类似地,输出嵌入馈入解码器。
编码器
编码器和解码器堆栈分别由几个(通常是六个)编码器和解码器组成,按顺序连接。
(图片由作者提供)
堆栈中的第一个编码器从嵌入和位置编码接收其输入。堆栈中的其他编码器接收来自前一个编码器的输入。
编码器将其输入传递到多头自关注层。自我关注输出被传递到前馈层,然后前馈层将其输出向上发送到下一个编码器。
(图片由作者提供)
自我注意和前馈子层都具有围绕它们的剩余跳跃连接,随后是层标准化。
最后一个编码器的输出被馈送到解码器堆栈中的每个解码器,如下所述。
解码器
解码器的结构与编码器非常相似,但也有一些不同。
像编码器一样,堆栈中的第一个解码器从输出嵌入和位置编码接收其输入。堆栈中的其他解码器接收来自前一个解码器的输入。
解码器将其输入传递到多头自关注层。这与编码器中的操作方式略有不同。它只允许处理序列中较早的位置。这是通过掩盖未来头寸来实现的,我们稍后会谈到这一点。
(图片由作者提供)
与编码器不同,解码器有第二个多头关注层,称为编码器-解码器关注层。编码器-解码器关注层的工作方式类似于自我关注,只是它结合了两个输入源——其下的自我关注层以及编码器堆栈的输出。
自我关注输出被传递到前馈层,然后前馈层将其输出向上发送到下一个解码器。
这些子层中的每一层,自关注、编码器-解码器关注和前馈,都有一个围绕它们的剩余跳跃连接,随后是层标准化。
注意力
在第一部分中,我们讨论了为什么注意力在处理序列时如此重要。在《变形金刚》中,注意力用在三个地方:
- 编码器中的自我关注—输入序列关注自身
- 解码器中的自我关注—目标序列关注自身
- 编码器-解码器-注意解码器-目标序列注意输入序列
关注层以三个参数的形式接受输入,即查询、键和值。
- 在编码器的自我关注中,编码器的输入被传递给所有三个参数,查询、键和值。
(图片由作者提供)
- 在解码器的自我关注中,解码器的输入被传递给所有三个参数,查询、键和值。
- 在解码器的编码器-解码器中,堆栈中最后一个编码器的输出被传递给 Value 和 Key 参数。它下面的自我关注(和层范数)模块的输出被传递给查询参数。
(图片由作者提供)
多头注意力
转换器将每个注意力处理器称为注意力头,并并行重复几次。这就是众所周知的多头注意力。通过结合几个相似的注意力计算,它给予它的注意力更大的辨别能力。
(图片由作者提供)
查询、键和值分别通过单独的线性层,每个层都有自己的权重,产生三个结果,分别称为 Q、K 和 V。然后使用如下所示的关注度公式将它们结合在一起,以产生关注度分数。
(图片由作者提供)
这里要认识到的重要事情是,Q、K 和 V 值携带序列中每个单词的编码表示。注意力计算然后将每个单词与序列中的每个其他单词相结合,使得注意力分数对序列中每个单词的分数进行编码。
不久前讨论解码器时,我们简要提到了掩蔽。面具也显示在上面的注意图中。让我们看看它是如何工作的。
注意面具
在计算注意力分数时,注意力模块实现屏蔽步骤。掩蔽有两个目的:
**在编码器自我注意和编码器-解码器-注意中:**掩蔽用于在输入句子中有填充的地方使注意力输出为零,以确保填充不会对自我注意有所贡献。(注意:由于输入序列可能有不同的长度,所以像在大多数 NLP 应用程序中一样,用填充标记来扩展它们,以便可以将固定长度的向量输入到转换器中。)
(图片由作者提供)
类似地,对于编码器-解码器的注意。
(图片由作者提供)
**在解码器自我关注:**掩蔽用来防止解码器在预测下一个单词时提前“偷看”目标句子的其余部分。
解码器处理源序列中的单词,并使用它们来预测目标序列中的单词。在训练过程中,这是通过教师强制完成的,其中完整的目标序列作为解码器输入。因此,在预测某个位置的单词时,解码器可以获得该单词之前的目标单词以及该单词之后的目标单词。这允许解码器通过使用来自未来“时间步”的目标字来“欺骗”。
例如,当预测'单词 3' 时,解码器应该只参考来自目标的前 3 个输入单词,而不参考第四个单词'可探'。
(图片由作者提供)
因此,解码器会屏蔽序列中稍后出现的输入单词。
(图片由作者提供)
在计算注意力得分时(参考前面显示计算的图片),掩蔽应用于 Softmax 之前的分子。被屏蔽的元素(白色正方形)被设置为负无穷大,因此 Softmax 将这些值变为零。
生成输出
堆栈中的最后一个解码器将其输出传递给输出组件,输出组件将其转换为最终的输出语句。
线性层将解码器向量投影到单词得分中,在句子中的每个位置,目标词汇表中的每个唯一单词都有一个得分值。例如,如果我们的最终输出句子有 7 个单词,而目标西班牙语词汇有 10000 个独特的单词,我们为这 7 个单词中的每一个生成 10000 个分值。得分值指示词汇表中的每个单词在句子的那个位置出现的可能性。
然后,Softmax 层将这些分数转化为概率(总计为 1.0)。在每个位置,我们找到概率最高的单词的索引,然后将该索引映射到词汇表中相应的单词。这些字构成了变压器的输出序列。
(图片由作者提供)
训练和损失函数
在训练期间,我们使用诸如交叉熵损失的损失函数来将生成的输出概率分布与目标序列进行比较。概率分布给出了每个单词在该位置出现的概率。
(图片由作者提供)
让我们假设我们的目标词汇表只包含四个单词。我们的目标是产生一个与我们预期的目标序列“De nada END”相匹配的概率分布。
这意味着第一个单词位置的概率分布对于“De”应该具有概率 1,而对于词汇表中所有其他单词的概率是 0。类似地,“nada”和“END”分别对于第二和第三个字位置应该具有概率 1。
通常,损耗用于计算梯度,以通过反向传播来训练变压器。
结论
希望这能让你在训练中对变压器内部的情况有所了解。正如我们在上一篇文章中所讨论的,它在推理过程中循环运行,但是大部分处理保持不变。
多头注意力模块为变形金刚提供了动力。在下一篇文章中,我们将继续我们的旅程,更深入地去真正理解注意力是如何计算的细节。
最后,如果你喜欢这篇文章,你可能也会喜欢我关于音频深度学习、地理位置机器学习和图像字幕架构的其他系列。
让我们继续学习吧!
变形金刚直观讲解(第三部分):多头关注,深度潜水
原文:https://towardsdatascience.com/transformers-explained-visually-part-3-multi-head-attention-deep-dive-1c1ff1024853?source=collection_archive---------0-----------------------
直观变形金刚系列 NLP
一个温和的自我注意,编码解码器注意,注意分数和掩蔽的内部工作指南,用简单的英语。
斯科特·托宾在 Unsplash 上的照片
这是我的变形金刚系列的第三篇文章。我们以自顶向下的方式覆盖它的功能。在前面的文章中,我们学习了什么是转换器,它的架构,以及它是如何工作的。
在本文中,我们将更进一步,深入探讨多头注意力,这是变形金刚的大脑。
这里是对本系列之前和之后文章的一个快速总结。我的目标是不仅要理解事物是如何工作的,还要理解它为什么会这样工作。
- 功能概述 (变压器是怎么用的,为什么比 RNNs 好。架构的组成部分,以及训练和推理期间的行为)
- 工作原理 (内部端到端操作。数据如何流动以及执行何种计算,包括矩阵表示)
- 多头关注——本文 (关注模块在整个变压器内部的工作方式)
- 为什么注意力能提高表现 (不仅仅是注意力能做什么,还有为什么它如此有效。注意力如何捕捉句子中单词之间的关系)
如果您对一般的 NLP 应用程序感兴趣,我还有一些您可能会喜欢的文章。
- 波束搜索
- Bleu 评分 ( Bleu 评分和单词错误率是 NLP 模型的两个基本指标)
注意力是如何在变压器中使用的
正如我们在第 2 部分中所讨论的,注意力用在了变压器的三个地方:
- 编码器中的自我关注—输入序列关注自身
- 解码器中的自我关注—目标序列关注自身
- 编码器-解码器-注意解码器-目标序列注意输入序列
(图片由作者提供)
注意输入参数—查询、键和值
关注层以三个参数的形式接受输入,即查询、键和值。
这三个参数在结构上是相似的,序列中的每个单词都由一个向量表示。
编码器自关注
输入序列被馈送到输入嵌入和位置编码,该编码为输入序列中的每个单词产生编码表示,该编码表示捕获每个单词的含义和位置。这被馈送到第一编码器中的自关注中的所有三个参数,查询、关键字和值,然后第一编码器还为输入序列中的每个单词产生编码表示,其现在也合并了每个单词的关注分数。当它通过堆栈中的所有编码器时,每个自我注意模块也将其自己的注意分数添加到每个单词的表示中。
(图片由作者提供)
解码器自我关注
到了解码器堆栈,目标序列被馈送到输出嵌入和位置编码,该输出嵌入和位置编码为目标序列中的每个单词产生编码表示,该编码表示捕获每个单词的含义和位置。这被馈送到第一解码器中的自关注中的所有三个参数,查询、关键字和值,第一解码器然后还为目标序列中的每个单词产生编码表示,其现在也合并了每个单词的关注分数。
在通过层规范之后,这被馈送到第一解码器中的编码器-解码器注意中的查询参数
编解码器注意
与此同时,堆栈中最后一个编码器的输出被传递给编码器-解码器关注的值和关键参数。
因此,编码器-解码器的注意力同时获得目标序列的表示(来自解码器自身的注意力)和输入序列的表示(来自编码器堆栈)。因此,它为每个目标序列单词产生一个具有注意力分数的表示,该表示也捕获了来自输入序列的注意力分数的影响。
当这通过堆栈中的所有解码器时,每个自我注意和每个编码器-解码器注意也将它们自己的注意分数添加到每个单词的表示中。
多个注意力头
在转换器中,注意力模块并行多次重复其计算。每一个都被称为注意力头。注意模块将其查询、键和值参数分成 N 个部分,并通过单独的头独立地传递每个部分。所有这些相似的注意力计算然后被组合在一起以产生最终的注意力分数。这被称为多头注意力,它赋予了转换者更大的能力来编码每个单词的多种关系和细微差别。
(图片由作者提供)
为了准确理解数据在内部是如何处理的,让我们在训练 Transformer 解决翻译问题的同时,来看看注意力模块的工作。我们将使用一个训练数据样本,该样本由一个输入序列(英语为‘You ' welcome)和一个目标序列(西班牙语为‘De nada’)组成。
注意力超参数
有三个超参数决定数据维度:
- 嵌入大小—嵌入向量的宽度(在我们的示例中,我们使用宽度 6)。该尺寸贯穿于整个变压器模型,因此有时被称为“模型尺寸”等其他名称。
- 查询大小(等于键和值大小)-三个线性图层分别用于生成查询、键和值矩阵的权重大小(在我们的示例中,我们使用的查询大小为 3)
- 注意力头的数量(在我们的例子中使用 2 个头)
此外,我们还有批量大小,这为我们提供了样本数量的一个维度。
输入层
输入嵌入和位置编码层产生一个形状矩阵(样本数、序列长度、嵌入大小),该矩阵被提供给堆栈中第一个编码器的查询、关键字和值。
(图片由作者提供)
为了使可视化变得简单,我们将在图片中删除 Batch 维度,并将重点放在其余维度上。
(图片由作者提供)
线性图层
查询、键和值有三个独立的线性层。每个线性图层都有自己的权重。输入通过这些线性层产生 Q、K 和 V 矩阵。
(图片由作者提供)
在注意力集中拆分数据
现在,数据被分散到多个注意力头上,这样每个注意力头都可以独立处理数据。
然而,需要理解的重要一点是,这只是一个逻辑分割。查询、键和值没有被物理地分割成单独的矩阵,一个矩阵对应一个注意头。单个数据矩阵分别用于查询、键和值,矩阵的逻辑上独立的部分用于每个注意力标题。类似地,没有单独的线性层,每个注意力头部一个。所有的注意力头共享相同的线性层,但只是在数据矩阵的“自己的”逻辑部分上操作。
线性层权重按人头进行逻辑分区
这种逻辑分割是通过将输入数据以及线性层权重均匀地划分到注意力头上来完成的。我们可以通过如下选择查询大小来实现这一点:
查询大小=嵌入大小/头数
(图片由作者提供)
在我们的示例中,这就是查询大小= 6/2 = 3 的原因。即使层权重(和输入数据)是一个单一的矩阵,我们也可以认为它是每个头部的单独层权重的“叠加”。
(图片由作者提供)
因此,所有磁头的计算可以通过单个矩阵运算来实现,而不需要 N 次单独的运算。这使得计算更有效,并保持模型简单,因为需要更少的线性层,同时仍然实现独立注意头的能力。
重塑 Q、K 和 V 矩阵
由线性层输出的 Q、K 和 V 矩阵被重新整形以包括显式的头部尺寸。现在,每个“切片”对应于每个头部的一个矩阵。
通过交换头部和序列维度,该矩阵被再次整形。虽然没有画出批量维度,但是现在 Q 的维度是(批量、头、序列、查询大小)。
Q 矩阵被整形以包括头部维度,然后通过交换头部和序列维度再次被整形。(图片由作者提供)
在下图中,我们可以看到分裂我们的例子 Q 矩阵的完整过程,从线性层出来后。
最后一个阶段仅用于可视化——尽管 Q 矩阵是单个矩阵,但我们可以将其视为每个人头逻辑上独立的 Q 矩阵。
注意力头部的 q 矩阵分裂(图片由作者提供)
我们准备计算注意力得分。
计算每个头部的注意力得分
我们现在有三个矩阵,Q,K 和 V,分布在头部。这些用于计算注意力得分。
我们将只使用最后两个维度(序列和查询大小)来显示单个头的计算,并跳过前两个维度(批处理和头)。本质上,我们可以想象,我们所看到的计算对于批次中的每个头和每个样品都是“重复”的(尽管,很明显,它们是作为单个矩阵操作而不是循环进行的)。
第一步是做 Q 和 k 之间的矩阵乘法。
(图片由作者提供)
现在结果中添加了一个掩码值。在编码器自我关注中,掩码用于屏蔽填充值,以便它们不参与关注分数。
在解码器自关注和解码器编码器关注中应用了不同的掩码,我们稍后将在流程中进行讨论。
(图片由作者提供)
现在,通过除以查询大小的*方根来缩放结果,然后对其应用 Softmax。
(图片由作者提供)
在 Softmax 的输出和 V 矩阵之间执行另一个矩阵乘法。
(图片由作者提供)
编码器自我关注中完整的关注分数计算如下:
(图片由作者提供)
将每个头部的注意力分数合并在一起
我们现在对每个头部都有单独的注意力分数,这些分数需要合并成一个单一的分数。这种合并操作本质上是拆分操作的逆操作。
这是通过简单地改变结果矩阵的形状以消除头部维度来实现的。这些步骤是:
- 通过交换头部和序列维度来重塑注意力得分矩阵。换句话说,矩阵形状从(批、头、序列、查询大小)到(批、序列、头、查询大小)。
- 通过将形状调整为(批处理、序列、标题*查询大小)来折叠标题维。这有效地将每个头部的注意力得分向量连接成单个合并的注意力得分。
由于嵌入大小=头*查询大小,所以合并后的分数为(批次,序列,嵌入大小)。在下图中,我们可以看到示例得分矩阵合并的完整过程。
(图片由作者提供)
端到端多头关注
综合起来,这就是多头关注的端到端流程。
(图片由作者提供)
多头分割捕捉更丰富的诠释
嵌入向量捕捉单词的意思。在多头注意力的情况下,正如我们已经看到的,输入(和目标)序列的嵌入向量在逻辑上被分割成多个头。这有什么意义?
(图片由作者提供)
这意味着嵌入的不同部分可以了解每个单词含义的不同方面,因为它与序列中的其他单词相关。这允许转换器捕获序列的更丰富的解释。
这可能不是一个现实的例子,但它可能有助于建立直觉。例如,一个部分可能捕获名词的“性别”(男性、女性、中性),而另一个部分可能捕获名词的“基数”(单数对复数)。这在翻译过程中可能很重要,因为在许多语言中,需要使用的动词取决于这些因素。
解码器自我关注和掩蔽
解码器自我关注的工作方式与编码器自我关注类似,只是它对目标序列的每个字都起作用。
(图片由作者提供)
类似地,屏蔽会屏蔽掉目标序列中的填充字。
解码器编码器-解码器注意和掩蔽
编码器-解码器的注意力来自两个来源。因此,与计算每个输入单词与其他输入单词之间的交互的编码器自关注和计算每个目标单词与其他目标单词之间的交互的解码器自关注不同,编码器-解码器关注计算每个目标单词与每个输入单词之间的交互。
(图片由作者提供)
因此,得到的注意力分数中的每个单元格对应于一个 Q(即目标序列字)与所有其他 K(即输入序列)单词和所有 V(即输入序列)字。
类似地,屏蔽屏蔽了目标输出中后面的单词,这在本系列的第二篇文章中有详细解释。
结论
希望这能让你很好地理解 Transformer 中的注意力模块是做什么的。当把我们在第二篇文章中讨论的转换器的端到端流程放在一起时,我们现在已经涵盖了整个转换器架构的详细操作。
我们现在确切地理解了变压器是做什么的。但是我们还没有完全回答为什么变压器的注意力执行它所做的计算这个问题。为什么它使用查询、键和值的概念,为什么它执行我们刚刚看到的矩阵乘法?
我们有一个模糊的直觉想法,认为它“抓住了每个单词与其他单词之间的关系”,但这到底是什么意思呢?这是如何让变形人的注意力有能力理解序列中每个单词的细微差别的呢?
这是一个有趣的问题,也是本系列最后一篇文章的主题。一旦我们了解了这一点,我们将真正理解变压器架构的优雅。
最后,如果你喜欢这篇文章,你可能也会喜欢我关于音频深度学习、地理位置机器学习和图像字幕架构的其他系列。
让我们继续学习吧!
如何构建一个 Transformer 标记器
原文:https://towardsdatascience.com/transformers-from-scratch-creating-a-tokenizer-7d7418adb403?source=collection_archive---------8-----------------------
你所需要的就是使用高频变压器创建一个定制的记号赋予器
作者图片
一个几乎每个自然语言处理(NLP)项目都是这样开始的:
当然,总会有一些复杂的情况。也许数据具有您(或其他任何人)以前从未见过的奇怪属性,并且使数据成为预处理的噩梦——但是对于模型设置,我们通常可以使用现有的预训练模型。
这很好,但是如果没有符合我们特定要求的预训练模型呢?
也许我们希望我们的模型能够理解一种不太常见的语言,例如,有多少 transformer 模型已经接受了皮埃蒙特语或纳瓦特尔语的训练?
零点
在这种情况下,我们需要做一些不同的事情。我们需要从头开始构建自己的模型。
现在,构建新的 transformer 模型背后的很大一部分工作是创建新的模型标记器。
记号赋予器是我们从人类可读文本到转换器可读记号的翻译器。在本文中,我们将学习如何构建我们自己的 transformer tokenizer。
获取数据
像往常一样,我们从数据开始。关于 transformer 的最大好处之一是我们的选择太多了——我们构建我们的标记器和预训练 transformer 模型所需要的只是非结构化的文本数据。
多语言数据的 HuggingFace 数据集的视频漫游
最大的非结构化文本数据集之一是 OSCAR,碰巧这是一个巨大的多语言数据集。现在,我们可以通过 HF datasets
包直接访问这个数据集,让我们来看看。
现在,我们只能通过 Python 列出数据集的名称——这不是很多信息。为了获得更多细节,我们可以前往 HF 数据集查看器。
左侧窗口允许我们使用过滤器和/或通过指定确切的数据集进行搜索。
选择 oscar 后,我们将看到另一个下拉选项— 子集 —它列出了 oscar 中所有可用的不同子集(如语言)。
我们可以通过选择unshuffled _ duplicated _ PMS子集来预览 OSCAR Piemontese 数据。
奥斯卡皮埃蒙特子集预览。
我们将继续使用datasets.load_dataset(*'dataset'*, *'subset'*)
用 Python 下载这个数据集。
从这里我们可以看到拉丁子集包含 18.8K 个样本,其中每个样本都是一个字典,包含一个 id 和文本。
在训练我们的标记器时,我们需要从文件中读取数据——我们将在纯文本文件中存储所有样本,用换行符分隔每个样本。
我们将把每个文本文件分成 5K 个样本的块(尽管对于这种大小的数据集来说没有必要,但对于大型数据集来说是必需的),并将它们保存到一个新的 oscar_la 目录中。
训练分词器
现在我们的数据已经准备好了,我们可以开始训练标记器了。我们将使用字节级字节对编码(BPE)记号赋予器。
标记化器构建的视频演练
字节级编码意味着我们将从字节字母表中构建我们的记号化器词汇表。由于这个原因,所有的单词都可以分解成记号——甚至是新单词——所以我们不需要特殊的未知记号。
我们需要一个文件列表来输入我们的分词器的训练过程,我们将列出所有的*。我们的 oscar_la 目录中的 txt* 文件。
现在我们初始化并训练我们的记号赋予器。我们将使用 roBERTa 特殊标记,一个词汇大小为30522
的标记,以及一个最小频率(一个标记在数据中出现的次数,以引起我们的注意)2
。
我们现在已经构建了我们的拉丁文 roBERTa tokenizer。让我们给它起一个听起来像拉丁语的名字——Bert ius——并保存到文件中。
记号化器文件
保存我们的记号赋予器创建了两个文件,一个merges.txt
和vocab.json
。
两个标记器文件— merges.txt 和 vocab.json 。
当我们的记号赋予器编码文本时,它将首先使用merges.txt
将文本映射到记号,然后使用vocab.json
将记号映射到记号 id。
使用分词器
我们已经构建并保存了我们的标记器——但是我们如何使用它呢?嗯,我们可以像加载其他标记器一样加载我们的标记器——使用from_pretrained
。
现在让我们试着编码每个人最喜欢的拉丁短语:
这里可以看到我们的两个张量,input_ids
和attention_mask
。在input_ids
中,我们可以看到由 0 表示的序列令牌s>T21,由 2 表示的序列令牌s >结束,以及由 1 表示的填充令牌 < pad > 。
太好了!我们在巨大的 OSCAR 数据集的拉丁子集上组装了一个定制的标记器。本文到此为止!
我希望你喜欢这篇文章!如果你有任何问题,请通过 Twitter 或在下面的评论中告诉我。如果你想要更多这样的内容,我也会在 YouTube 上发布。
感谢阅读!
🤖《变形金刚》NLP 课程 70%的折扣
*除另有说明外,所有图片均出自作者之手
变形金刚:用 3 行代码实现 NLP 模型
原文:https://towardsdatascience.com/transformers-implementing-nlp-models-in-3-lines-of-code-475639c3611d?source=collection_archive---------16-----------------------
transformers 库简介,用于实现不同 NLP 任务的最新模型
图一。变形金刚|作者图片
使用最先进的自然语言处理模型从未如此简单。拥抱脸[ 1 ]已经开发了一个名为transformers
的强大库,它允许我们以一种非常简单的方式实现和利用各种各样最先进的 NLP 模型。在这篇博客中,我们将了解如何安装和使用 transformers 库来完成不同的任务,例如:
- 文本分类
- 问答
- 屏蔽语言建模
- 文字生成
- 命名实体识别
- 文本摘要
- 翻译
所以在我们开始回顾不同任务的每个实现之前,让我们安装transformers
库。在我的情况下,我在 macOS 上工作,当试图用pip
直接安装时,我得到了一个错误,我通过之前安装的Rust
编译器解决了这个错误,如下所示:
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
之后我用pip
直接安装了transformers
,如下所示:
$ pip install transformers
太好了,通过前面的两个步骤,库应该已经被正确安装了。因此,让我们从不同的实现开始,让我们开始吧!
文本分类
文本分类任务包括将给定的文本分配到给定的一组类中的特定类。情感分析是文本分类问题中最常解决的问题。
要通过transformers
库使用文本分类模型,我们只需要两个参数task
和model
,它们分别指定要处理的问题类型和要使用的模型。考虑到拥抱脸存储库中托管的模型的多样性,我们可以开始使用其中的一些。在这里你可以找到文本分类任务的模型集合。
在图 2 中,我们可以看到用于情感分析的bert-base-multilingual-uncasced-sentiment
模型的实现。
图二。文本分类|按作者分类的图片
输出是:
Result: [{'label': 'NEG', 'score': 0.9566874504089355}]
根据您选择实现的模型,这将是要获得的结果。考虑阅读每个模型的文档以了解它们在什么数据集上被训练以及它们执行什么类型的分类是很重要的。transformers
的另一个巨大优势是,如果你有自己的模型托管在拥抱脸存储库中,你也可以通过这个库使用它。
问题回答
抽取式问题回答的任务是试图在给定的上下文中找到给定问题的答案。这个任务最有代表性的数据集之一是斯坦福问答数据集。
完成这项任务。变压器pipeline
需要context
和question
。在下面的例子中,context
是由爱丽丝漫游奇境记中的一段确定的,这个问题指的是该段中描述的一个事件。在下图中,您可以看到实现方式:
图二。问答|作者图片
输出是:
Answer: 'her sister'
对于这个任务,我们选择模型robert-base-squad-v1
,然而,在拥抱脸库中,我们可以为这个任务找到不同的替代模型,值得看看其中的一些。
掩蔽语言建模
屏蔽语言建模任务是用屏蔽标记屏蔽给定文本句子的标记,其中要求模型用适当的标记填充每个屏蔽。
对于这种类型的任务,transformers pipeline
只需要任务的名称(在本例中为fill-mask
),然后是指定要屏蔽的令牌的文本序列,在下图中我们可以看到实现:
图 3。蒙版语言建模|作者图片
输出是:
[{'sequence': ' Horror movies are often very scary to people',
'score': 0.12314373254776001,
'token': 28719,
'token_str': ' Horror'},
{'sequence': ' horror movies are often very scary to people',
'score': 0.052469268441200256,
'token': 8444,
'token_str': ' horror'},
{'sequence': 'Ghost movies are often very scary to people',
'score': 0.05243474990129471,
'token': 38856,
'token_str': 'Ghost'},
{'sequence': 'War movies are often very scary to people',
'score': 0.03345327079296112,
'token': 20096,
'token_str': 'War'},
{'sequence': 'Action movies are often very scary to people',
'score': 0.029487883672118187,
'token': 36082,
'token_str': 'Action'}]
结果显示为令牌及其各自属性的列表。在这种情况下,得分最高的令牌是Horror
,最后一个令牌是Action
。
文本生成
文本生成任务指的是相对于确定的上下文创建语法和语义正确的文本部分。在这种情况下,pipeline
初始化需要使用task
的类型和model
,就像前面的任务一样。最后,pipeline
实例需要两个参数,即context
(或种子)和要生成的序列的长度max_length
。要生成的序列数是一个可选参数。
下图显示了生成 5 个文本序列的GPT-2
模型的实现:
图 4。文本生成|作者图片
输出是:
[{'generated_text': 'My name is Fernando, I am from Mexico and live for a reason. I am a musician and the best producer, you might call me a poet'}, {'generated_text': 'My name is Fernando, I am from Mexico and I make an app with a lot of friends to keep us safe!" said Fernando.\n\nThe'}, {'generated_text': 'My name is Fernando, I am from Mexico and I am an atheist. I am living in a town called Tanta and I am living in the'}, {'generated_text': 'My name is Fernando, I am from Mexico and I have been doing this gig since the age of 21 and I am the first person to record this'}, {'generated_text': 'My name is Fernando, I am from Mexico and I am in Mexico", he said.\n\nHis name may be a reference to his birthplace and'}]
有点好笑的是GPT-2
生成的序列是基于一个住在墨西哥的人,他的名字叫费尔南多。
命名实体识别
命名实体识别任务是指给给定文本序列的每个标记分配一个类。对于该任务的执行,只需要将任务标识符ner
分配给pipeline
初始化。随后,对象只接收一个文本流。在下图中,我们可以看到实施过程:
图 5。命名实体识别|作者图片
输出是:
('Fernando', 'I-PER')
('Mexico', 'I-LOC')
('Learning', 'I-ORG')
('Engineer', 'I-MISC')
('Hit', 'I-ORG')
('##ch', 'I-ORG')
对于本例,这些类是:
- I-MISC ,杂项实体
- 根据,人名
- I-ORG ,组织
- I-LOC ,位置
有趣的是,公司作为一个组织被正确地分配。
文本摘要
文本摘要任务是指在给定一个确定文本的情况下提取一个摘要。为了初始化pipeline
,需要task
的定义以及summarization
标识符。随后,对于任务的执行,仅需要text
和要生成的最大和最小序列长度作为自变量。在下图中我们可以看到这个任务的实现:
图 6。摘要|作者图片
输出是:
[{'summary_text': ' Machine learning is an important component of the growing field of data science . Machine learning, deep learning, and neural networks are all sub-fields of artificial intelligence . As big data continues to grow, the market demand for data scientists will increase, requiring them to assist in the identification of the most relevant business questions .'}]
正如我们所看到的,由模型生成的摘要相对于输入文本是正确的。与前面的任务一样,我们可以使用各种模型进行文本摘要,如BART
、DistilBart
、Pegasus
[ 4 。
翻译
翻译任务是指将一种给定语言的文本转换成另一种语言。transformers
库允许以非常简单的方式使用最先进的模型进行翻译,例如T5
。流水线用要解决的任务的标识符初始化,该标识符指的是原始语言和要翻译的语言,例如从英语翻译成法语,标识符是:translation_en_to_fr
。最后,生成的对象接收要翻译的文本作为参数。在下图中我们可以看到一个从英语到法语的文本翻译器的实现:
图 7。翻译|作者图片
输出是:
L'apprentissage automatique est une branche de l'intelligence artificielle (AI) et de la science informatique qui se concentre sur l'utilisation de données et d'algorithmes pour imiter la façon dont les humains apprennent, en améliorant progressivement sa précision.
结论
在这篇教程博客中,我们看到了如何使用transformers
库以一种非常简单的方式实现最先进的 NLP 模型。
在这篇博客中,我们看到了如何实现一些最常见的任务,然而重要的是要提到,这篇博客中显示的例子仅仅是为了推断,然而transformers
库的一个伟大的属性是,它提供了能够基于那些已经训练好的模型微调我们自己的模型的方法。这将是下一篇博客的好主题。
参考文献
【1】抱紧脸
【2】小队 : 斯坦福问答数据集
【3】爱丽丝梦游仙境
[4] 文本摘要模型
NLP 中的变压器
原文:https://towardsdatascience.com/transformers-in-nlp-7c164291326d?source=collection_archive---------28-----------------------
伯特、罗伯塔和 GPT-3
https://unsplash.com/photos/iy_MT2ifklc
介绍
与计算机视觉不同,在自然语言处理(NLP)中,预训练模型最*才变得广泛可用。部分由于文本数据集的稀缺,NLP 的进展缓慢,直到 2018 年变压器(BERT)双向编码器表示的发布[1]。
BERT 由 Jacob Devlin 和他的同事在 Google AI Language 发表[1]。
BERT 有两种预训练模型:基本模型和大型模型。虽然两者使用相同的架构,但前者包含 1.1 亿个参数,而后者包含 3.45 亿个参数。能够使用预先训练的模型并对其进行微调以适应不同的任务意味着即使在缺乏足够的数据来训练具有数百万个参数的模型的情况下,也可以避免模型过度拟合。较大的模型通常具有更好的性能[2]。
在微调 BERT 时,有三种可能性[2]:
- 训练所有架构
- 训练一些层,冷冻其他层
- 冻结整个网络并将额外的层附加到模型上
第三种方法用于下面的案例研究(食谱->烹饪)。
与其他神经网络架构一样,提供的训练数据量越大,它的性能就越好。因此,一个重要的收获是,运行更多代的 BERT 将导致更高的准确性,并有足够的数据。作为一个参考值,包含 128 000 字批量的任务可能需要 500K 到 1M 的训练步骤才能收敛。就所需的计算能力而言,它相当于使用多个最先进的 GPU 进行几天的训练[3]。
BERT 的另一个特点是它的双向方法。与以前的从左到右或者结合从左到右和从右到左训练来查看文本序列的努力相反[3]。
与递归神经网络和长短期记忆神经网络相比,BERT 的一个优点是它可以并行化。这意味着它可以通过在多个 GPU 中训练来加速。在输入数据是文本序列的情况下,这意味着它可以一次接受多个标记作为输入[3]。
变压器的两种后实现是鲁棒优化的伯特预训练方法(罗伯塔)和生成预训练变压器 3 (GPT-3)。罗伯塔于 2019 年由脸书研究中心发布,在广泛使用的基准-通用语言理解评估上取得了最先进的结果。后来,在 2020 年,OpenAI 发布了 GPT-3。它的完整版本拥有 1750 亿个机器学习参数的容量。由于其非凡的成果,微软于 2020 年 9 月 22 日宣布授权 GPT-3 独家使用。使得它只能通过开放的 API 提供给公众。
案例研究(食谱->烹饪)
使用 BERT 变换器,训练了一个从给定的配料列表中预测菜肴的模型。
包含大约 100,00 0 个配方的 Kaggle 和 Nature 数据集用于训练转换器。每个食谱包括一个配料列表(图 1),以及相应的菜肴。一份按字母顺序排列的配料清单给了模型。数据集的 80%用于训练,10%用于验证,10%用于测试。
在训练模型之前,标记化步骤使用 BERT 标记化器将每个配方分成 50 个标记。初始变压器的所有参数都被冻结。
图 1 编号。每份食谱的配料数量。食谱
训练时使用了实现权重衰减为 1e-3 的 Adam 算法的优化器。负对数似然被用作损失函数。并且模型收敛需要 40 个时期。训练在来自 Google Colab 的 P100 GPU 中进行。
模型的性能是用每种菜肴的精确度、召回率和 f1 分数来评估的。此外,所有菜系的 f1 总分。以及精确度、召回率和 f1 分数的宏观和加权*均值(图 2)。
图 2 料理预测器模型性能。0-非洲、1-东亚、2-东欧、3-拉丁美洲、4-中东、5-北美、6-北欧、7-南亚、8-东南亚、9-南欧&10-西欧
对于北美、南欧、拉丁美洲和东亚菜系,检测准确率达到 65%以上。
参考
[1]https://en . Wikipedia . org/wiki/BERT _(language _ model)【2021 年 7 月 21 日访问】
[2]https://www . analyticsvidhya . com/blog/2020/07/transfer-learning-for-NLP-fine-tuning-Bert-for-text-class ification/【2021 年 7 月 21 日访问】
[3]https://towards data science . com/Bert-explained-state-of-art-language-model-for-NLP-F8 b 21 a9b 6270【2021 年 7 月 21 日获取】
[4]https://ai . Facebook . com/blog/Roberta-an-optimized-method-for-pre training-self-supervised-NLP-systems/【2021 年 7 月 21 日访问】
[5]https://openai.com/blog/gpt-3-apps/【2021 年 7 月 21 日访问】
变形金刚满足主动学习:更少的数据,更好的性能
原文:https://towardsdatascience.com/transformers-meet-active-learning-less-data-better-performance-4cf931517ff6?source=collection_archive---------16-----------------------
关于如何对 Transformer 模型使用主动学习的实践教程
丹·伯顿在 Unsplash 上拍摄的照片
最*,大型语言模型(LLM)推动了许多自然语言处理(NLP)任务的发展。通常,这些 LLM 遵循两步框架:预训练步骤,随后是微调步骤。预训练使用大量未标记的数据来创建预训练的权重。然后,微调步骤加载这些权重,并根据来自下游任务的标记数据进行训练。LLMs 可以用少量的标记数据获得良好的结果,从而缩短训练时间。然而,在现实世界中,即使注释一个很小的数据集也是很昂贵的。这不仅是一项漫长的人工工作,而且是一项复杂的任务(即,用 30 个类别或一个复杂的领域进行分类),标记也不是微不足道的。例如,学习任务领域可能具有挑战性(医疗、财务)或者处理多个注释者之间的差异。因此,减少注释的数量是非常有益的,这也是主动学习(al)可以发挥作用的地方。
这篇文章将向你展示如何将 AL 与 Transformer 模型一起使用,以更少的标记数据获得相似或更好的结果。然而,这篇文章中的技术适用于任何概率分类器。另外,如果你对在多任务学习环境中使用人工智能感兴趣,可以看看我在 ICLR21 上发表的论文。
主动学习:高层次的概述
在我们进入教程之前,我将概述一些高层次的概念,它们将帮助你更好地理解这篇文章的剩余部分。然而,如果你正在寻找更多关于 AL 的细节,我推荐这个文献调查。
AL 背后的核心思想是,如果算法可以选择标记样本,那么它可以使用更少的标记样本来实现更好的性能,从而减少标注工作和训练时间。此外,在标记数据昂贵或难以收集而未标记数据大量可用的情况下,人工智能是有益的。后者是大多数真实世界应用的情况,如产品评论、对话数据等。
在机器学习(ML)文献中有三种主要的人工智能方法:
- 成员查询学习
- 基于池的采样
- 基于流的选择性采样
出于本教程的考虑,我将只概述基于池的抽样,但是如果您想深入了解其他技术的细节,我邀请您查看上面链接的调查。
基于池的采样
基于池的采样假设我们有一个用于训练初始分类器的小的初始标记数据集和一个大的未标记数据集。初始分类器使用信息量度量*从未标记集合中选择样本。*选定的样本随后由 oracle(自动化流程或人工)标记,并添加到标记的数据中。最后,使用新的标记集学习新的模型。重复该过程,直到达到期望的性能。
图片由 Amine Elhattami 拍摄,灵感来自 https://minds.wisconsin.edu/handle/1793/60660
信息含量指标
也被称为查询策略,信息量度量是一种试图帮助选择值得标记的样本的度量。有多种查询策略。选择正确的将取决于您的数据和任务。在这篇文章中,我们将使用不确定性抽样。
不确定抽样
不确定性采样是一种启发式方法,用于概率分类器,以帮助选择最不确定的样本。核心直觉是,高度的不确定性预示着一个决策边界。澄清这个界限将导致学习更好的分类器。
有多种方法可以应用不确定性采样。在这里,我将介绍熵采样,在本教程中使用的。
熵采样选择使用下面的等式计算的具有最高香农熵[2]的未标记样本,其中 qc 是样本属于类别 c 的概率
香农熵方程
例如,在二进制分类中,熵采样将选择类概率接* 0.5 的实例,其中熵最大,如下图所示。直观上,如果该分类器预测类 1 的概率为 0.99,类 2 的概率为 0.01,则该模型是合理可信的。因此,注释这个特殊的样本可能对模型没有好处。相反,如果两个类别的类别概率都是 0.5,则分类器是非常不确定的。因此,注释这个样本将是非常有益的(定义决策边界)。
基于 Amine Elhattami 的二元分类熵
实践教程
在本教程中,我们将在微软研究院释义语料库 (MRPC)任务[4]中使用带有 cased BERT [3]基础模型的 al。我选择了一个小模型和一个小任务,让每个人都能在几个小时左右的时间内**复制这个教程。**BERT base 可以安装在几乎任何 GPU 上,包括免费提供的 GPU(如 Google colab)。至于任务,MRPC 数据集并不庞大,三个历元的训练最多需要 30 分钟。
对于 BERT 实现和数据集管理,我使用了流行的 huggingface 库。此外,我在这个 git 资源库中共享了全部源代码,并创建了一个公共 Google colab 笔记本。
数据集
MRPC 数据集由从在线新闻中提取的 5801 个句子对组成。这项任务的目标是预测一对句子在语义上是否等价。
句子对示例:
第一句话:“纳斯达克综合指数小幅上涨 1.28 点,涨幅 0.1%,至 1766.60 点,此前一周上涨 3.7%。”
第二句话:科技股纳斯达克综合指数。IXIC 下跌 24.44 点,或 1.39%,至 1,739.87 点。
MRPC 任务使用两个指标。准确性和 F1 分数。本教程将比较评估数据集中两个分数的组合(*均值),如 GLUE 排行榜所示,因为测试集标签不公开。
基线
在我们开始实现和试验人工智能之前,我们需要使用整个训练数据集创建一个基线分数,以比较后来的结果。因为我们的目标是尝试 al,所以我没有做任何超参数搜索。我使用了 huggingface run glue 示例中的默认值。因此,这个基线分数绝不是我们使用所选模型所能达到的最好成绩。以下是所有实验中使用的超参数:
per_device_train_batch_size: 32
per_device_eval_batch_size: 32
learning_rate: 2e-5
num_train_epochs: 3
seed: 12
random_seed: 123
下图显示了模型在所有训练样本上训练后的评估结果。最大综合得分是 85.7,这是一个相当不错的分数,因为使用一个大得多的模型,当前的最先进水*是 92.85(在写这篇文章的时候)。
Amine Elhattami 使用所有训练数据集的评估结果
主动学习设置
现在我们有了基线,让我们看看主动学习是否可以使用更少的标记样本获得类似或更好的结果。概括一下,我们将使用基于池的采样和 Shanon 熵。
首先,我们将原始训练数据集分成两部分:一个小的初始训练数据集和一个较大的“未标记”数据集。由于我们的数据集已经被标记,我们将只从训练集中移除样本。在这个例子中,我选择初始训练数据集为原始数据集的 30%。
第二步是使用我们之前创建的初始训练集来训练初始模型。然后,在评估集上记录分数,并在未标记的数据集上进行预测。
接下来,我们计算未标记数据集预测的熵,并选择具有最高 Shanon 熵的 topk 样本。query_samples_count
是我们想要选择的样本数量。理想情况下,这个数字应该是批量的倍数。这里我选了 64。
一旦选择了样本,我们就请求 oracle(或注释器)提供标签(在我们的例子中,我们已经有了标签),扩展训练数据集,并从未标记的集合中删除这些样本。
在现实世界的应用程序中,从 oracle 请求标签可能需要将未标记的数据发送到您的标记*台,并保持该过程,直到数据被标记。
最后,从第二步开始重复,直到当前分数超过目标分数,或者未标记数据集为空。后一种情况,意味着你没有足够的数据来达到想要的分数,或者你可能需要做一些超参数搜索。
整个代码将如下所示:
结果呢
下图显示了 AL 实验的结果。AL 结果中的每个点(蓝色)是使用训练数据集百分比(x 轴)的不同运行。橙色中的基线分数(使用 100%的训练样本)用作参考。
Amine Elhattami 将所有结果与基线进行比较
如您所见,所有结果都超过了使用少 21%训练样本的基线结果。知道训练数据集包含 3668 个样本,AL 避免了我们标记 776 个样本。如果我们假设一个注释者*均在每个样本上花费 3 分钟,那么就节省了 38.8 个工作小时(T4)。当然,这个时间将取决于任务的复杂性和注释者的知识。
结论
在这篇文章中,我们看到了如何使用 transformer 模型进行主动学习,以更少的标记数据获得更好的结果。
这里展示的用例很简单,它可能需要您为自己的应用程序做更多的调整。然而,这篇文章旨在向您展示,这很容易做到,而且值得努力,因为从长远来看,它可以节省大量时间,尤其是在数据域封闭的应用程序中。例如,当使用会话数据时,您不需要注释所有可能的打招呼方式
同样,我已经在这个 git 仓库中分享了全部源代码,并创建了一个公共 Google colab 笔记本供你尝试代码和不同的参数。
在你走之前
在 Twitter 上关注我,我经常在 Twitter 上发布关于软件开发和机器学习的消息。
参考
[1]毛刺解决。主动学习文献调查。计算机科学技术报告 1648,威斯康星大学麦迪逊分校。2009.
[2] C. E. Shannon,“通信的数学理论”,《贝尔系统技术杂志》,第 27 卷,第 3 期,第 379-423 页,1948 年 7 月,会议名称:《贝尔系统技术杂志》。
[3] Jacob Devlin、张明蔚、Kenton Lee 和 Kristina Toutanova。BERT:用于语言理解的深度双向转换器的预训练。 CoRR ,abs/1810.04805,2018。网址http://arxiv.org/abs/1810.04805.
[4]威廉·多兰和克里斯·布罗克特。自动构建句子释义语料库。《第三届国际释义研讨会论文集》(IWP2005) ,2005 年。网址https://www.aclweb.org/anthology/I05-5002.
变形金刚——你只需要关注
原文:https://towardsdatascience.com/transformers-you-just-need-attention-f3775734c0da?source=collection_archive---------20-----------------------
保罗·斯科鲁普斯卡斯在 Unsplash 上的照片
自然语言处理或 NLP 是处理文本分析的机器学习的子集。它与人类语言和计算机的相互作用有关。有不同的 NLP 技术,最新的是最先进的变压器。
这将是第一个关于变形金刚架构的博客系列。事实证明,变形金刚在自然语言处理(NLP)领域是革命性的。自发明以来,它已经取代了所有其他自然语言处理(NLP)架构,如递归神经网络(RNN)、卷积神经网络(CNN)和长短期记忆(LSTM)。变压器有一个编码器-解码器的结构和一定的注意机制,使国家的艺术成果在许多任务。
在这篇文章中我们会学到什么?
- 这篇博文主要关注编码器部分,它的所有组件都将被详细讨论。在本帖中,将从理论和实践两个方面讨论编码器的内部细节(包括代码笔记本)。
- 编码器结构
- 编码器的关键部件或者说编码器中的数据流
- 输入-转换为嵌入。
- 位置编码
- 多头关注层(自我关注机制)
- 剩余网络
- 添加和定额层
- 前馈层。
架构概述
根据流程,变压器的不同部分
这篇博文将集中在上面这张图片的左边部分。
- 输入预处理
- 编码器
1.输入预处理
让我们放大输入预处理图像,如下所示。
位置编码器
举个例子:- 《我回家了》。如果这个句子作为输入被传递到编码器,让我们看看流程。
步骤 1:-单词嵌入
电脑看不懂英文字母,需要转换成数字版本。因此,句子中的每个单词都被转换成一个相应的恒定大小(维数)的随机数向量。这些向量被称为**嵌入向量。新矩阵将是【句子长度,尺寸】**形状。
词的嵌入表征
在上面的例子中,我们有 3 个单词,每个单词都有一个长度为 4 的嵌入向量。于是,Shape=(3,4) 【句子 _ 长度,维度】。在自然语言处理中,单词嵌入中的每个数字都具有与单词的语言特征相关的信息。如果我们把两个单词的单词嵌入在一起,比如说**【灰色】****【白色】既然这些都是颜色,那么它们在 n 维空间中就会彼此靠*。这些单词嵌入最初是随机数,并且在训练过程中它们得到更新并且看起来彼此更接*或相似,因为它们属于颜色**的类别。
步骤 2:-位置编码
在 LSTM RNN,单词是按顺序输入的,因此它能理解单词的顺序。但是在 transformer 中,所有的单词都是并行传递的。随着刑期的增加,在 LSTM 复发将需要大量手术。为了记住单词的顺序,引入了位置编码的概念。这是一种表示单词位置的编码。简而言之,将位置编码添加到我们的现有字嵌入中,这就给出了最终的预处理嵌入以用于编码器部分。位置编码的概念很重要,我会写一篇关于它的单独的博客文章并链接到这里。
注意:位置嵌入的大小应该和我们的现有的字嵌入一样,就是这么加起来的。
2.编码器堆栈:-
编码器堆栈
可以有 N 个编码器,但它们的内部结构是相同的。我们之前讨论的嵌入将通过 4 个单元:-
- 多头注意力
- 添加和规范层
- 前馈层
- 添加和规范
1.多头注意力
注意机制是一种为每个单词创建表示的方式,其中句子中的每个单词理解与同一句子中所有其他单词(包括其自身)的语义相似性。这是通过点积运算实现的。文中 8 个注意力头并行运行,所以多头注意力。它实际上有助于获得句子中所有单词之间的语义相似关系。输出嵌入将由上下文信息组成,并将显示每个单词如何与句子中的其他单词相关。它可以处理歧义,如下所示。这里的“ it ”与“**大象”**的关联度大于“香蕉”。
自我注意机制中的词汇表征
多头注意力机制将在更详细的https://machinelearningmarvel.in/intuitive-maths-and-code-behind-self-attention-mechanism-of-transformers-for-dummies/中讨论。我会写一篇关于它的独立博文,并把它链接到这里。
2.添加和规范层
编码器的输出嵌入通过残差网络被添加到原始输入嵌入。残差的目的是确保原始重要信息在通过编码器的过程中不会丢失。然后这被归一化。
3.前馈层
然后,归一化的嵌入通过完全连接的层。
4.添加和规范层
前馈层的输出通过残差网络被添加到编码器的输出嵌入中。残差网络的目的是确保原始重要信息在通过编码器的过程中不会丢失。然后这被归一化。
以上四个步骤是编码器的一部分,并且重复多次( Nx 如图所示),这给了我们纯粹的上下文嵌入。
赞成的意见
它在大多数 NLP 任务中提供了最先进的结果。即使是基本的预训练模型也能给出很好的结果。
骗局
建筑太大了。它有几百万个参数需要训练,并且需要大量的计算能力来训练。下一篇文章将展示解码器部分。直到那时
用集体推理转变协作决策
原文:https://towardsdatascience.com/transforming-organizational-decision-making-with-collective-reasoning-c859c1a9d991?source=collection_archive---------17-----------------------
创建一致性和可操作的结果
组织转型的障碍
决策的信心、准确性和速度是组织变革的圣杯。尽管所有的工作都发生在决策科学、人工智能和数据科学中,但我们仍然发现自己对冗长的会议感到厌倦,这些会议寻求集体信心,以知道我们正在做出正确的决定。疫情使情况变得更糟。
我最*与一家顶级捐赠基金的首席投资官进行了交谈。在他的职位上,他监管投资委员会,每个委员会通过合作决策分配数十亿美元的资金。他知道,改善他们的投资决策过程可以对回报产生重大的积极影响,他确信提高决策准确性的途径必须是通过技术进步。具体来说,他希望捕捉尽可能多的不同观点,使讨论更加透明,并记录决策过程以对照结果进行回溯测试,以便他们可以学习如何改进。
传统上,在所有这些领域,合作决策都很棘手,而且往往会无意中偏向高层领导,或者“房间里最响亮的声音”。此外,协作决策很难大规模管理,当参与者来自多个地点或不同文化时,这更具挑战性。大多数决策都是在行政否决的情况下做出的,这并非偶然,任何试图在一个大型群体中达成共识的人无疑都可以证明这一点。“回音室”效应导致全球投资界每年损失数十亿美元的机会。幸运的是,集体智能、人工智能和自然语言处理的最新发展使得解决高效、准确决策的诸多挑战成为可能。本文阐述了一种通过利用这些技术进步的集体力量来增加组织决策的信心、速度和准确性的方法。通过将人的洞察力和推理技能与人工智能的优化和精炼清晰度结合起来,我们可以开始改善商业中最人性化和最容易出错的方面之一,即信息灵通和准确决策的“艺术”。
在我们开始之前,了解一些我们需要解决的关键挑战是有帮助的。这些是功能障碍的“三大”来源,代表着有效决策机会的丧失:
- 对决策原因的集体协调 : 不协调往往会导致僵局、会议令人沮丧的结束,或者领导想要推翻原本开放的流程。在关键决策上寻求集体一致的过程往往会引发组织政治,这往往会导致参与者长期不满、脱离、跟进和执行不力,以及对领导层信心的长期侵蚀。
- 系统性偏见 : 无意识的系统性偏见让组织墨守成规。创新常常被植根于多年“经验”的决策和组织结构的规范模式所阻碍。当根深蒂固的模式和响亮的声音统治着一天的时候,有价值的不同的想法落到了地板上。与教育背景、文化、年龄、性别和资历相关的隐性偏见,共同扼杀了潜在的令人信服的创新想法。
- 基于证据的准确性跟踪: 对支撑决策的原因和影响的记录不足,为修正主义历史创造了机会,在修正主义历史中,评论浮出水面,如“我认为做出决策时我正在休假”,或总是有用的“我一直有疑问”。健康的组织学会将重点从个人责任转移到直接从证据的审计线索中获得的集体组织学习。
集体智能和人工智能的进步为克服这三个障碍提供了一个突破性的机会,并为做出充分知情和预测准确的组织决策提供了一种变革性的新方法。
集体推理:学习和评估群体对决策或预测的理由或信念的过程
创建与集体推理的一致性
这三个障碍的解决方案以及自信、快速和准确决策的途径是快速了解支持决策的证据的共同信念和优先级,同时努力消除偏见。在没有技术的情况下,这通常是在与专注于创建共享优先级和一致性的客观主持人的会议中完成的。这种手动流程不能很好地跨地点和时区扩展,也不适用于疫情这样的危机时刻。此外,由于“房间里最大的声音”、在组织中的地位、激情或说服的力量支配了证据、逻辑和不同的观点,会议过程经常失败。显然,这是一个协作技术解决方案的巨大机会。
集体智慧的研究表明,我们集体更聪明。从多个角度进行决策是众所周知的最佳实践。随着我们进入一个合作的新时代,一代人将参与视为就业的一个基本方面,我们可以在一系列关于集体智慧力量的优秀书籍中找到灵感。斯科特·佩奇(Scott Page)的《差异》(Difference)展示了思维多样性的力量,以提高预测的准确性。菲利普·泰特洛克和丹·加德纳记录并分析了无数案例,证明了集体智慧在“超级预测”中的力量。最后,司各特·佩奇和汤姆·马龙分别在他们广受欢迎的著作《模范思想者》和《超级智者》中贡献了他们丰富的专业知识。总之,这些书展示了集体智慧科学承诺的思考预测和决策准确性的新方法的各种方式。
集体智慧总结:多视角、多元背景增加预测准确率,减少系统偏差。
集体推理比集体智慧更进了一步。在集体智慧中,预测是完全独立完成的。一个多元化的小组被赋予一项任务,以做出一个预测的结果,每个人独立工作,并对结果进行分析。独立分析决策的不同观点背后的“为什么”的原因。
在集体推理中,我们将决策的预测或评级从评级的原因中分离出来。集体推理抓住了在伟大的头脑风暴会议中经常观察到的动态潜力,在头脑风暴会议中,我们从彼此的思维中学习;它共同创造了新的决策方法。集体推理捕捉到了协作思维不可思议的力量,超越了简单聚合一系列独立思想的数学演算,捕捉到了集体思维在创造力、解决问题和一致性方面的力量。
一个说明性的例子
让我们用一个简单的例子来说明这一点,那就是决定投资或不投资一家早期公司——一家初创公司。在押注一家可能有下一个大创意的初创公司时,我们都需要自信、速度和准确性。
想象一下,你被邀请成为一群人中的一员,来评估是否投资一家新的秘密创业公司。总的来说,你的任务是预测公司能否成功吸引主要投资者。你可以接触到公司的所有资料,你可以参加创始团队的问答活动。你已经有了做出深思熟虑的决定和预测所需的所有材料。你正在评估的公司有高度技术性的业务。虽然你不知道他们的身份,但你知道还有其他人有很强的技术背景,适合这项任务。
您需要根据以下属性,用 1 到 10 分对公司进行评分:
- 引人注目的商业机会,考虑市场、竞争等因素。
- 团队——这是在目标市场领导公司的合适团队吗?
- 早期顾问和投资者的网络效应——他们能帮助推动公司吗?
- 投资信念——这是你会进行或推荐的投资吗?
在审查材料后,你提供你的输入分数以及导致你给出你给出的分数的原因。一旦你提交了你的想法,你就会看到其他人的理由和他们得分的原因。您看不到其他贡献者的分数。注意,你看不出谁是幕后推手。你被要求优先考虑与你的想法一致的原因。这一过程增加了对驱动决策观点的证据的关注,并减少了组织立场或团队政治的偏见。一旦你提交了优先考虑的理由列表,阅读它们可能会让你回头重新考虑你的评分或你对决定的其他想法。这种重新考虑是团队走向一致点过程的重要组成部分。
图 1
以科学的准确性学习相关性
我们冻结了这个例子,以指出集体推理的技术和科学解决方案的机会。事实上,学习群体偏好的根源可以追溯到* 100 年前 L.L. Thurstone 在 1927 年首次提出的比较判断法则。 学习‘预测性’偏好的唯一方法是 A/B 测试,一种经济权衡 *。*我们很多人都经历过在验光师办公室回答“A 还是 B?”…“B 还是 A?”一遍又一遍。营销人员非常熟悉 A/B 测试,这是了解产品偏好的标准方法。但是,在动态发现环境中,要比较的项目数量可能需要大量的 A/B 测试,这种方法对大规模的组有效吗?人工智能技术提供了一个解决方案。
每当上述评估团队中的个人对一系列原因进行排名时,我们就可以创建一个谁优先考虑谁的原因的“网络”。下面显示的是我们上面列出的一个会议的网页。节点是独立的贡献者,链接是通过对彼此的想法进行优先排序而生成的:
群体互动的网络表现
通过使用隐马尔可夫过程来学习相关性。图 1 右侧面板中显示的示例列表是基于之前的评级事件动态生成的列表。马尔可夫过程的“隐藏”部分是一种功能,它逐渐从“发现模式”转变为“优先模式”,前者获取新想法的输入,后者试图估计最能代表群体排序原因的原因列表。请注意,样本列表的上下文是由所考虑的“特征”决定的。团队评估是整体模型的一个示例“特征”。下图显示了算法的学习曲线。请注意,其收敛速度由评级事件的数量决定,但对于评级最高的项目(靠*图的原点),其收敛速度相当快。
学习相关性
从连接网络中,我们学习各种成员影响力排名,且我们使用自然语言处理技术来学习表示与商业机会、团队等的评估相关联的集体推理的原因和主题。学习相关性与情感提供了一个有意义的信号,表明哪些项目是高度相关的。下图是一个具体投资分析的例子。
相关性与情感
在这种特殊情况下,评估小组认为收入非常重要,但情绪表明关于收入的讨论是混合的。关于为什么这是真的细节是通过研究分配给这个主题的相关原因来了解的。
这是集体推理系统的本质。它自动获取应用于手头决策的知识。
整合人类和人工智能
今天,我们面临着前所未有的挑战,涉及投资者和企业如何配置资本,以及如何成功规划企业转型和增长的道路。对人工智能的大量投资影响了某些业务流程的自动化,但在规划、战略思维、投资决策和企业转型方面,人工智能的承诺却没有兑现。对统计学习的短视关注及其对历史数据的严重依赖,限制了人工智能在催化创新解决方案以应对我们最大挑战方面的愿景。创造性集体行动的需要超越了公司战略。需要明确的集体规划和行动,这延伸到应对气候变化和公共政策。在这篇文章中,我介绍了一个使用集体人类智能和人工智能的*台,该*台经过多年的发展,有望催化和授权集体创造性的预测和行动。
第二代人工智能(statistical learning AI)的限制在朱迪亚·珀尔(Judea Pearl)的新书《为什么之书》(The Book of Why)中有明确阐述。他指出:
“如果我可以用一句简洁的话来总结这本书的主旨,那就是:你比你的数据更聪明。数据不懂因果;人类有。”
他继续解释道:
“虽然概率编码了我们对静态世界的信念,但因果关系告诉我们,当世界发生变化时,无论是通过干预还是通过想象,概率是否以及如何变化。”
在《麻省理工科技评论》的一次采访中,深度学习的创始人之一 Yoshua Bengio 说:
“我认为我们需要考虑人工智能的硬挑战,不要满足于短期的增量进步。我不是说我要忘记深度学习。相反,我想在此基础上更进一步。但我们需要能够扩展它来做推理、学习因果关系和探索世界等事情,以便学习和获取信息。”
有强有力的论据表明,人类和机器智能的集成是下一代人工智能系统的基础。人类在从极小的数据集学习以及富有想象力的发现和预测方面仍然处于优势。信任和透明对于金融投资和企业转型决策等领域的人工智能应用至关重要。人类授权的人工智能和集体智慧提出了指导人工智能未来进程的方法。
集体推理:从数据获取到认知模型
如果您想使用目前可用的工具集获得决策输入,您通常会求助于调查工具、投票或通过电子邮件和消息工具的开放式输入。今天的工具适合于收集个人对某个主题或决策的观点。例如,假设你有一组人,你想从他们那里得到投资决策的反馈,你只想得到我们上面提出的三个问题的意见——业务、团队、网络效应。每位参与者被要求从 1 到 10 (10 为最高)对问题进行评分,并给出他们的理由或对其答案的思考。该图以图形方式显示了信息收集工作的模式:
无相关性排名的个人评论
蓝点代表输入他们观点的人(23 名参与者)。粉色圆点代表他们的分数和理由(提交分数的 113 个理由)。有些人比其他人更详细地阐述了他们的理由,但他们都为每个问题提供了分数。此图显示了使用上述任何方法(调查、投票或电子邮件)获得的结果。计算一个小组的*均分数很容易,调查工具会自动为你计算。总结这 113 个理由或思考是很难的,除非你使用人类的大脑并阅读每一个理由。即使一个人阅读了每一篇文章,他们也不能把它们都保存在工作记忆中。最多,他们可能会挑出五六个有共鸣的。即使这样,除非他们把评估小组召集到一起,否则他们永远也不会知道代表小组对投资决策的想法的前三或四个原因。学习优先相关性是一个难题。情绪分析只是轻度预测。严重缺失的是提问的能力:
团队如何围绕这一投资决策的理由保持一致?
假设我们引入一种机制,允许他们从上面提到的一个样本中对彼此的理由进行排序。使用相关性学习算法,我们可以过滤掉与该组相关性较低的原因,从而从根本上简化分析过程。注意,我们看到了这个群体如何一起推理的早期阶段。这是 集体推理的第一步,通过人工智能增强的同行评审过程过滤相关性 :
同行评审的相关意见
请注意,左下方的人有许多与她/他的同事不太相关的原因。你是否曾经觉得自己就是会议中的那个人?)如果只看相关性高的原因(比如分数> 50%),就要把问题的复杂程度降低一点。注意,如果我们想更深入地了解团队的想法,我们现在必须阅读大约 50 个理由。
使用一些最新的 NLP 技术,因为我们正在动态地学习原因的相关性。我们还可以了解对决策至关重要的主题(绿色)。像“好的市场”或“差的上市”这样的主题更容易总结小组的推理。请注意,由于主题或主题只是原因的集合,它们将具有主题相关性分数,因此现在可以根据小组的集体判断,将小组正在思考的主题按优先顺序排列。在这种特殊情况下,结果是有五个关键主题,每个主题都有积极、消极和中性的情绪,从而进一步简化了结果。由于原因与量化分数相关联,我们可以将该分数与情绪分析相结合,以获得更具预测性和更精确的读数,从而了解该人对决策的真实想法。
按主题组织的评论
但是,请记住,这一练习的最初目的是按照小组对这一投资决策的建议去做。通过使用如图 1 所示的结构化过程,我们可以将所有的集体推理链接成一个预测。绿色显示的主题和粉色显示的相关原因最终会影响功能的评分,从而影响预测得分。在这种情况下,小组给这项投资打了 79%的分。这种评分方法可以使用地面真实数据进行训练,整合人类和集体智慧,为组织集体决策的全新方法提供框架。
具有相关原因和主题的预测模型
每一个决策过程都会产生一个决策的集体推理模型:一个集体认知模型,这个模型是关于群体认为什么是决策的结果,比如投资或通过的决策。该模型允许从不同的角度进行检查。比如我们可以从预测结果入手,问“为什么”。决定的理由是什么?下图显示了决策的业务质量方面的观点。
分数和预测背后的原因和主题
与业务质量相关的特征得到了 8 分的*均分数。
然而,正如你所看到的,存在着不同的意见。一些人认为有一个好的商业模式,而另一些人认为没有。集体推理允许探索意见的多样性;这里有一点非常重要。集体推理不是关于“从众心理”,而是探索由不同个体推理的不同意见的分支,以及它如何融入集体预测或决策。
评级分布
集体推理利用了集体智慧的发现,特别是多样性预测定理:
集体群体误差=群体误差—多样性得分
对于这里描述的集体推理系统,我们计算数量多样性得分和语言多样性得分。后者是通过使用最新的嵌入技术将语言转化为几何图形而成为可能的。每个原因都是语言空间中的一个点,与其他原因有一个可计算的距离。我们已经证明:
团队的认知多样性越大,预测准确度越大
通过将原因(原因)与分数联系起来,我们就在推理和分数之间建立了因果关系。最终结果是,我们现在有了一个用于预测的因果网络或一个用于决策的因果认知模型。随着时间的推移,这可以被一般化,这样我们就有了一个基础,来构建跨越广泛决策领域的集体推理和个人团队智能的计算模型。
总之,所描述的集体推理系统有可能从根本上改变捕捉和提高组织中决策者智力的方式。
对于那些对人工智能感兴趣的人来说,你会将结果识别为贝叶斯信念网络或因果网络。实际上,我们已经自动化了从组织中的一组专家或团队成员那里获取知识的过程。
在这篇短文中,我介绍了创建更快、更准确的组织决策的解决方案。每一个协作过程都由一个决策“记分卡”驱动,该“记分卡”记录了您做出决策时需要考虑的因素。每一个过程都会产生一个分数和一个完整的知识和思考记录。该模型可以存档,并用作组织学习的独立资源。该模型模拟了群体的思维,因此是一个因果模型,一个知识模型,一个导致决策的专业知识和思维的迷你智能。
如果你有一个做决定时需要考虑的因素的“记分卡”,考虑使用如上所述的集体推理来自动化和简化你的决策过程。它可以异步地、远程地完成,你不必去开会。你们一旦结盟就能见面,这将是一次愉快得多的经历。你将有一个永久的记录,记录你的团队在做决定时所经历的完整的推理过程。一旦你们达成一致,你们就可以见面,思考这个过程产生的信息,并做出最终决定。请记住,这是一个决策支持过程,其他因素,如资金的流入或减少,宏观经济的突然转变,甚至疫情可能与决策密切相关,但没有包括在分析中。
最后,也许从长远来看是最重要的,我所描述的过程产生了个人和组织作为一个整体的推理过程的永久记录。随着这一永久记录的展开,可以在现实的强光下对其进行评估。该组织是否考虑了适当的理由?它们的重量合适吗?将过程与结果联系起来有助于学习,因为分析师可以根据未来的发展来评估过去的推理。
如果你没有一个“记分卡”来记录你的决策,那就创建一个。这又引出了另一篇文章,请稍后继续,或者通过 tom@crowdsmart.ai 联系我。
- 丹尼尔·卡内曼等人即将出版一本名为《噪音,人类判断的缺陷》的书。艾尔。人类判断中的噪音问题及其对准确性的影响。虽然我们的方法可以通过相关性排名和集体输入来隐含地处理噪声,但是它没有明确地处理或模拟噪声问题,并且是未来工作的主题。
R 中空间数据到表格数据的转换
原文:https://towardsdatascience.com/transforming-spatial-data-to-tabular-data-in-r-4dab139f311f?source=collection_archive---------21-----------------------
关于原始格式的空间数据和将其转换成表格数据的技术问题的评论
转型的需要
您可能会问的第一个问题是,为什么还要转换空间数据。在我的案例中,在一个闪亮的数据可视化应用程序上处理空间数据时,转换的需求是必然的。
但是,(地理)空间数据是与映射到地图上的地理位置的数据一致地构造的,由特定的经度和纬度值控制。我们从这些数据中提出的问题要求我们对其进行子集划分/过滤/查询,并最终对其进行处理,以呈现我们希望展示给目标受众的信息。
R 中有几个函数可用于以其原生格式绘制空间数据,例如 plot()、image()和 filled.contour()函数。
library(raster)rainfall <- raster("2007.daily_rain.nc")
image(rainfall,plot.title = title(main = "Isarithmic(Contour) plot of total rainfall(in mm) in Australia in 2017"))
plot(rainfall, plot.title = title(main = "Isarithmic(Contour) plot of rainfall(in mm) in Australia in 2017"))
作者图片
但是,在某些情况下,您需要不断地处理空间数据来过滤/子集化坐标或与坐标相关联的信息(例如,x-y 坐标位置或 z 坐标位置的降雨量,通常是时间),以显示受约束区域或时间的数据。
尽管这可以通过使用某些库来实现,比如 tidync (如下所示)
library(tidync)nc_2007 <- tidync(“2007.daily_rain.nc”)# Filtering based on longitude,lattitude or time(available variables)nc_2007 %>% hyper_filter(lon = lon < 120)
nc_2007 %>% hyper_filter(time = time <= 5 & time >= 2) # 2nd Jan to 5th Jan 2007 data
nc_2007 %>% hyper_filter(lat = lat <120,time = between(time,1,10))
使用 dplyr 软件包进行数据操作的简便性是无与伦比的。
为此,我们需要将空间数据转换成表格数据(最好是 dataframe 格式)。
但首先,让我们看看空间数据及其常见格式的一些基础知识。
空间数据及其常见类型和格式
什么是空间数据?
项目与地图上的地理位置相关联的数据。比如澳大利亚各个城市的降雨量。
常见的空间数据类型
- 基于光栅或像素的数据
Arial 照片、卫星图像和高程数据通常存储为栅格数据。
最常用的格式:
- ADRG
- 二进制文件
- Esri 网格
- netCDF 网格
- GeoTIFF
- JPEG2000
2.矢量数据
地理形状存储为矢量数据。
- 点用于存储 0 维特征的位置,如山峰
- 线/折线用于存储道路或河流等一维特征的位置
- 多边形用于存储湖泊或国家等二维特征的位置和形状
最常用的格式:
- 锁眼标记语言(KML)
- 地理标记语言(GML)
- Esri shapefile
- 杰奥森
- 挽救(saving 的简写)
在本文中,我将重点介绍转换最常用的栅格数据格式之一:netCDF grid。
将栅格数据转换为数据帧
这里使用的栅格数据是从 SILO 收集的,SILO 是一个从 1889 年到现在的澳大利亚气候数据的数据库,由昆士兰环境和科学部(DES)托管。我们在这里关注的数据是 2017 年澳大利亚不同经度和纬度的月降雨量数据。
这些数据可以通过下面的超链接访问。
https://www.longpaddock.qld.gov.au/silo/gridded-data/
网格数据主要由三个坐标和每个 x-y-z 的相应属性组成,以月降雨量表示:
X —经度
Y —纬度
Z —一年中的某月
步骤 1:从 netCDF 网格格式创建一个 RasterBrick 对象
library(raster)r_2017 <- brick("2017.monthly_rain.nc")
r_2017
对象的尺寸和属性—按作者分类的图像
使用栅格库的 brick()函数部分,将 netCDF grid 数据转换为 RasterBrick 对象,允许我们使用 plot()、image()函数作为栅格库的一部分直接绘制该对象。
步骤 2:将 RasterBrick 对象转换为 SpatialPointsDataFrame 对象,最后转换为 DataFrame
r_2017_df <- as.data.frame(rasterToPoints(r_2017,spatial = TRUE))
head(r_2017_df)
按作者显示数据框的前几行图像
rasterToPoints() 将 RasterBrick 对象转换为 Points 对象,这是一种矢量数据,如果您还记得上一节的话。
设置空间参数= TRUE 将其转换为 空间点数据帧 对象。
最后,通过使用转换函数 as.data.frame() ,我们可以很容易地将其从spatialpointsdata frame对象转换为 dataframe 。
步骤 3:重命名列名以提高可读性
library(dplyr)r_2017_df <- dplyr::rename(r_2017_df,January = 'X2017.01.16')
r_2017_df <- dplyr::rename(r_2017_df,February = 'X2017.02.15')
r_2017_df <- dplyr::rename(r_2017_df,March = 'X2017.03.16')
r_2017_df <- dplyr::rename(r_2017_df,April = 'X2017.04.16')
r_2017_df <- dplyr::rename(r_2017_df,May = 'X2017.05.16')
r_2017_df <- dplyr::rename(r_2017_df,June = 'X2017.06.16')
r_2017_df <- dplyr::rename(r_2017_df,July = 'X2017.07.16')
r_2017_df <- dplyr::rename(r_2017_df,August = 'X2017.08.16')
r_2017_df <- dplyr::rename(r_2017_df,September = 'X2017.09.16')
r_2017_df <- dplyr::rename(r_2017_df,October = 'X2017.10.16')
r_2017_df <- dplyr::rename(r_2017_df,November = 'X2017.11.16')
r_2017_df <- dplyr::rename(r_2017_df,December = 'X2017.12.16')
r_2017_df <- dplyr::rename(r_2017_df,Longitude = 'x')
r_2017_df <- dplyr::rename(r_2017_df,Latitude = 'y')
对数据框架进行最终更新,以重命名列名—图片由作者提供
最后,我们可以使用 dplyr 包中的 重命名 函数,将列名重命名为更有意义的名称。
现在,我们可以轻松地操纵我们的数据框架来绘制美丽的可视化图形,从数据中找到有趣的见解,如下所述。
library(ggplot2)ggplot(r_2017_df,aes(x=Longitude,y=Latitude,z=.data[["January"]])) + theme_void() + geom_contour_filled_interactive(aes(fill = stat(level),data_id = stat(level),tooltip = paste("Rainfall Range", stat(level))), bins = 9) + labs(fill = "Rainfall Range(in mm)") + scale_fill_brewer(palette = "Blues")
2017 年 1 月澳大利亚降雨量的空间分布-图片由作者提供
总之,通过采用这种将空间数据转换为表格数据的方法,我们可以更好地控制数据,让我们能够更轻松地操作数据,从而帮助我们更自由地从数据中提出问题。
使用弹性堆栈将您的电子表格转换为数据分析视图!
原文:https://towardsdatascience.com/transforming-your-business-spreadsheets-into-data-analytics-view-using-kibana-and-logstash-efbc2d598f51?source=collection_archive---------33-----------------------
商业电子表格如何具有重要的洞察力…
由 安德烈拉斐尔
照片由米卡·鲍梅斯特在 Unsplash 上拍摄
为什么将 excel 电子表格导出到 Elasticsearch 会很有用?如果你在一家拥有大量遗留系统和僵化的 IT 组织结构的大公司工作,你很可能已经看到人们传递 Excel 电子表格,并将其作为存储数据的一种方式(一种数据库)。分析师浪费大量时间将这种临时系统转换为对业务有用的信息,手动将数据传输到数据库或 Tableau、Qlik 或 Power BI 实例。在本文中,我们将尝试通过使用 ELK 堆栈来解决这个问题,以便自动化这种过程,并生成更好的、可操作的见解。
但是这是如何工作的呢?
为了演示从基于存储库的数据管理中自动收集简单数据的过程,我将使用 ka ggle "meal delivery company"数据集,从头开始介绍这个过程。
我们将从在微软 Azure 上提供 Ubuntu Server 18.04 开始(它可以是你熟悉的任何云服务和操作系统)。
在这个例子中,我将我的服务器命名为“elastic ”,在部署服务器之后,我添加了一个 SSD 磁盘(挂载点/数据),对于我们的目的,Elasticsearch 在 SSD 上工作得最好
[图片由作者提供]
然后,我们将 elasticsearch、kibana 和 log stash 7 . 9 . 2 版安装在这个文件系统“数据”中,按产品进行分类,如下所示。
*Installations commands:**apt-get install elasticsearch, apt-get install kibana, apt-get install logstash**Important: Change permission and owner for folder where you installed for example (in my case):*
[图片由作者提供]
为了组织日志和数据路径,以便 Elasticsearch 可以与它们同步,我们将编辑 elasticsearch.yml 文件。在我们的例子中,我们将使用 root 访问权限,但在真实的生产环境中,我们可以实现一个控制用户或用户组,对 elasticsearch 过程和配置文件拥有足够的权限。
启动麋鹿栈!
在没有错误地启动 elasticsearch 和 Kibana 之后,下一步是使用' curl '命令来识别 elasticsearch 是否可以摄取任何数据。
service elasticsearch start
service kibana start
curl localhost:9200
我用用户和密码保护了我的环境(弹性安全),如果到目前为止所有的程序都是正确的,你会看到消息“你知道,搜索”。
[图片由作者提供]
摄取数据!
我们将使用的数据集包含关于中心、餐饮、地区和许多其他变量的信息。它分为四个数据集。
在实际情况中,我们很可能需要安排一个下载命令在我们知道文件可用的特定时间运行(比如说,每天晚上 8:00)。在我们的例子中,我们使用 bash wget 命令并将数据存储在/data/arquivos 目录中。
[图片由作者提供]
现在,我们需要配置我们的 logstash.yml 管道设置,并在配置文件中描述正确的路径。我创建了一个示例配置(/etc/log stash/conf . d/spread sheet . conf)来读取。csv 文件。
#structure of sample
input{} - path of files
filter{} - ajust columns, lines, values, strings etc
output{} - send data to elasticsearch
这个文件结构对于创建输入来读取所有 <电子表格名称>很重要。csv 文件,并为每个文件定义过滤器。您不需要为每个电子表格创建单独的输入或过滤器。也可以使用相同的方法。conf 并依次输入您的“输入/过滤器”。下面我展示了一个 train.csv 文件的输入的例子。
我们还可以使用 Logstash 作为 ETL 工具,并修复不一致的地方,如空值、字符串形式的日期以及其他可能出现的问题。将数字字段转换成正确的数据类型非常重要,这样我们以后就可以使用 Elasticsearch 和 Kibana 来探索数字聚合和可视化。
配置完数据字段后,就该输入信息并使用客户机经常需要的所有数据构建一个 kibana 索引了。有了这些数据,就可以执行分析并创建优化的视图。
运行您的 logstash 代理,可以检查是否一切正常…
/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/**spreadsheet.conf**Or create daemon process and run as a service:
service logstash start
启动 logstash 代理后,我们的示例的输出应该是:
{
"week" => 145,
"center_id" => 61,
"meal_id" => 2490,
"[@timestamp](http://twitter.com/timestamp)" => 2021-01-18T01:47:13.253Z,
"path" => "/data/arquivos/train.csv",
"type" => "train",
"base_price" => 290.03,
"[@version](http://twitter.com/version)" => "1",
"num_orders" => 162,
"id" => 1361984,
"emailer_for_promotion" => 0,
"homepage_featured" => 0,
"host" => "elastic",
"checkout_price" => 292.03
}
检查数据!
首先,检查创建的索引,查看所有数据值和字符串是否正确(管理>数据>索引管理):
[图片由作者提供]
在 Kibana 中创建新的索引模式(管理> Kibana >索引模式)。为每个电子表格创建正确的索引是这个过程的一个重要部分。csv)并关联数据以构建分析视图。
[图片由作者提供]
可视化数据!
一旦熟悉了获取的数据,现在就可以分析信息并创建可视化,从而为我们的业务提供可操作的见解,以及该视图如何帮助做出更好的决策。
在这个例子中,我创建了 4 个不同的视图:
1 —按订单频率分组的前 10 大销售类别。有了这个观点,就有可能分析哪些是最消耗的物品。
[图片由作者提供]
2 —按中心分组并按餐细分的销售额。该视图允许中心销售最多的物品的可视化。
[图片由作者提供]
3-按促销分组并按订单细分的销售,允许分析促销是否确实吸引了客户以及销售最多的产品是什么。
[图片由作者提供]
4-按周分组的订单可以直观显示哪一周的订单最多。
[图片由作者提供]
另一件有趣的事情是可以很容易地创建一个仪表板,提供你的业务或客户的动态视图,如下图所示;)
[图片由作者提供]
感谢阅读!
结论
电子表格可能包含大量有价值的信息,这些信息可能会丢失或损坏。处理此类文件的良好数据收集系统对于保证信息的完整性和高效检索至关重要。在这里,我们研究了一种实现这种数据收集过程的方法,使用 ELK 堆栈来接收和探索我们的数据。通过这种方式,我们可以使拥有许多遗留系统和电子表格的企业仍然能够发布正确的信息,但以一种更加动态的方式发布。
参考文献
[1] Elastic, Logstash. *Published online at elastic.co.* Retrieved from (2020):
'[https://www.elastic.co/guide/en/logstash/current/logstash-7-9-2.html](https://www.elastic.co/guide/en/logstash/current/logstash-7-9-2.html)'[2] Saptarshi Ghosh, "Meal delivery company", Analytics Vidhya Genpact Hackathon. *Published online at Kaggle (2018).* Retrieved from:
'[https://www.kaggle.com/ghoshsaptarshi/av-genpact-hack-dec2018](https://www.kaggle.com/ghoshsaptarshi/av-genpact-hack-dec2018)'